LCOV - code coverage report
Current view: top level - dom/svg - nsSVGViewBox.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 42 175 24.0 %
Date: 2017-07-14 16:53:18 Functions: 6 40 15.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsSVGViewBox.h"
       8             : 
       9             : #include "mozilla/Move.h"
      10             : #include "nsCharSeparatedTokenizer.h"
      11             : #include "nsSMILValue.h"
      12             : #include "nsTextFormatter.h"
      13             : #include "SVGContentUtils.h"
      14             : #include "SVGViewBoxSMILType.h"
      15             : 
      16             : #define NUM_VIEWBOX_COMPONENTS 4
      17             : using namespace mozilla;
      18             : 
      19             : /* Implementation of nsSVGViewBoxRect methods */
      20             : 
      21             : bool
      22           0 : nsSVGViewBoxRect::operator==(const nsSVGViewBoxRect& aOther) const
      23             : {
      24           0 :   if (&aOther == this)
      25           0 :     return true;
      26             : 
      27           0 :   return (none && aOther.none) ||
      28           0 :     (!none && !aOther.none &&
      29           0 :      x == aOther.x &&
      30           0 :      y == aOther.y &&
      31           0 :      width == aOther.width &&
      32           0 :      height == aOther.height);
      33             : }
      34             : 
      35             : /* static */ nsresult
      36          16 : nsSVGViewBoxRect::FromString(const nsAString& aStr, nsSVGViewBoxRect *aViewBox)
      37             : {
      38          16 :   if (aStr.EqualsLiteral("none")) {
      39           0 :     aViewBox->none = true;
      40           0 :     return NS_OK;
      41             :   }
      42             : 
      43             :   nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
      44             :   tokenizer(aStr, ',',
      45          16 :             nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
      46             :   float vals[NUM_VIEWBOX_COMPONENTS];
      47             :   uint32_t i;
      48          80 :   for (i = 0; i < NUM_VIEWBOX_COMPONENTS && tokenizer.hasMoreTokens(); ++i) {
      49          64 :     if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), vals[i])) {
      50           0 :       return NS_ERROR_DOM_SYNTAX_ERR;
      51             :     }
      52             :   }
      53             : 
      54          32 :   if (i != NUM_VIEWBOX_COMPONENTS ||              // Too few values.
      55          32 :       tokenizer.hasMoreTokens() ||                // Too many values.
      56          16 :       tokenizer.separatorAfterCurrentToken()) {   // Trailing comma.
      57           0 :     return NS_ERROR_DOM_SYNTAX_ERR;
      58             :   }
      59             : 
      60          16 :   aViewBox->x = vals[0];
      61          16 :   aViewBox->y = vals[1];
      62          16 :   aViewBox->width = vals[2];
      63          16 :   aViewBox->height = vals[3];
      64          16 :   aViewBox->none = false;
      65             : 
      66          16 :   return NS_OK;
      67             : }
      68             : 
      69             : 
      70             : /* Cycle collection macros for nsSVGViewBox */
      71             : 
      72           0 : NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(nsSVGViewBox::DOMBaseVal, mSVGElement)
      73           0 : NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(nsSVGViewBox::DOMAnimVal, mSVGElement)
      74             : 
      75           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGViewBox::DOMBaseVal)
      76           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGViewBox::DOMBaseVal)
      77             : 
      78           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGViewBox::DOMAnimVal)
      79           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGViewBox::DOMAnimVal)
      80             : 
      81           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGViewBox::DOMBaseVal)
      82           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      83           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      84           0 : NS_INTERFACE_MAP_END
      85             : 
      86           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGViewBox::DOMAnimVal)
      87           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      88           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      89           0 : NS_INTERFACE_MAP_END
      90             : 
      91             : static nsSVGAttrTearoffTable<nsSVGViewBox, nsSVGViewBox::DOMBaseVal>
      92           3 :   sBaseSVGViewBoxTearoffTable;
      93             : static nsSVGAttrTearoffTable<nsSVGViewBox, nsSVGViewBox::DOMAnimVal>
      94           3 :   sAnimSVGViewBoxTearoffTable;
      95             : nsSVGAttrTearoffTable<nsSVGViewBox, dom::SVGAnimatedRect>
      96           3 :   nsSVGViewBox::sSVGAnimatedRectTearoffTable;
      97             : 
      98             : 
      99             : /* Implementation of nsSVGViewBox methods */
     100             : 
     101             : void
     102          22 : nsSVGViewBox::Init()
     103             : {
     104          22 :   mHasBaseVal = false;
     105             :   // We shouldn't use mBaseVal for rendering (its usages should be guarded with
     106             :   // "mHasBaseVal" checks), but just in case we do by accident, this will
     107             :   // ensure that we treat it as "none" and ignore its numeric values:
     108          22 :   mBaseVal.none = true;
     109             : 
     110          22 :   mAnimVal = nullptr;
     111          22 : }
     112             : 
     113             : bool
     114        1510 : nsSVGViewBox::HasRect() const
     115             : {
     116             :   // Check mAnimVal if we have one; otherwise, check mBaseVal if we have one;
     117             :   // otherwise, just return false (we clearly do not have a rect).
     118        1510 :   const nsSVGViewBoxRect* rect = mAnimVal;
     119        1510 :   if (!rect) {
     120        1510 :     if (!mHasBaseVal) {
     121             :       // no anim val, no base val --> no viewbox rect
     122         529 :       return false;
     123             :     }
     124         981 :     rect = &mBaseVal;
     125             :   }
     126             : 
     127         981 :   return !rect->none && rect->width >= 0 && rect->height >= 0;
     128             : }
     129             : 
     130             : void
     131           0 : nsSVGViewBox::SetAnimValue(const nsSVGViewBoxRect& aRect,
     132             :                            nsSVGElement *aSVGElement)
     133             : {
     134           0 :   if (!mAnimVal) {
     135             :     // it's okay if allocation fails - and no point in reporting that
     136           0 :     mAnimVal = new nsSVGViewBoxRect(aRect);
     137             :   } else {
     138           0 :     if (aRect == *mAnimVal) {
     139           0 :       return;
     140             :     }
     141           0 :     *mAnimVal = aRect;
     142             :   }
     143           0 :   aSVGElement->DidAnimateViewBox();
     144             : }
     145             : 
     146             : void
     147           0 : nsSVGViewBox::SetBaseValue(const nsSVGViewBoxRect& aRect,
     148             :                            nsSVGElement *aSVGElement)
     149             : {
     150           0 :   if (!mHasBaseVal || mBaseVal == aRect) {
     151             :     // This method is used to set a single x, y, width
     152             :     // or height value. It can't create a base value
     153             :     // as the other components may be undefined. We record
     154             :     // the new value though, so as not to lose data.
     155           0 :     mBaseVal = aRect;
     156           0 :     return;
     157             :   }
     158             : 
     159           0 :   nsAttrValue emptyOrOldValue = aSVGElement->WillChangeViewBox();
     160             : 
     161           0 :   mBaseVal = aRect;
     162           0 :   mHasBaseVal = true;
     163             : 
     164           0 :   aSVGElement->DidChangeViewBox(emptyOrOldValue);
     165           0 :   if (mAnimVal) {
     166           0 :     aSVGElement->AnimationNeedsResample();
     167             :   }
     168             : }
     169             : 
     170             : nsresult
     171          16 : nsSVGViewBox::SetBaseValueString(const nsAString& aValue,
     172             :                                  nsSVGElement *aSVGElement,
     173             :                                  bool aDoSetAttr)
     174             : {
     175          16 :   nsSVGViewBoxRect viewBox;
     176             : 
     177          16 :   nsresult rv = nsSVGViewBoxRect::FromString(aValue, &viewBox);
     178          16 :   if (NS_FAILED(rv)) {
     179           0 :     return rv;
     180             :   }
     181             :   // Comparison against mBaseVal is only valid if we currently have a base val.
     182          16 :   if (mHasBaseVal && viewBox == mBaseVal) {
     183           0 :     return NS_OK;
     184             :   }
     185             : 
     186          32 :   nsAttrValue emptyOrOldValue;
     187          16 :   if (aDoSetAttr) {
     188           0 :     emptyOrOldValue = aSVGElement->WillChangeViewBox();
     189             :   }
     190          16 :   mHasBaseVal = true;
     191          16 :   mBaseVal = viewBox;
     192             : 
     193          16 :   if (aDoSetAttr) {
     194           0 :     aSVGElement->DidChangeViewBox(emptyOrOldValue);
     195             :   }
     196          16 :   if (mAnimVal) {
     197           0 :     aSVGElement->AnimationNeedsResample();
     198             :   }
     199          16 :   return NS_OK;
     200             : }
     201             : 
     202             : void
     203           0 : nsSVGViewBox::GetBaseValueString(nsAString& aValue) const
     204             : {
     205           0 :   if (mBaseVal.none) {
     206           0 :     aValue.AssignLiteral("none");
     207           0 :     return;
     208             :   }
     209             :   char16_t buf[200];
     210           0 :   nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
     211             :                             u"%g %g %g %g",
     212           0 :                             (double)mBaseVal.x, (double)mBaseVal.y,
     213           0 :                             (double)mBaseVal.width, (double)mBaseVal.height);
     214           0 :   aValue.Assign(buf);
     215             : }
     216             : 
     217             : 
     218             : already_AddRefed<dom::SVGAnimatedRect>
     219           0 : nsSVGViewBox::ToSVGAnimatedRect(nsSVGElement* aSVGElement)
     220             : {
     221             :   RefPtr<dom::SVGAnimatedRect> domAnimatedRect =
     222           0 :     sSVGAnimatedRectTearoffTable.GetTearoff(this);
     223           0 :   if (!domAnimatedRect) {
     224           0 :     domAnimatedRect = new dom::SVGAnimatedRect(this, aSVGElement);
     225           0 :     sSVGAnimatedRectTearoffTable.AddTearoff(this, domAnimatedRect);
     226             :   }
     227             : 
     228           0 :   return domAnimatedRect.forget();
     229             : }
     230             : 
     231             : already_AddRefed<dom::SVGIRect>
     232           0 : nsSVGViewBox::ToDOMBaseVal(nsSVGElement *aSVGElement)
     233             : {
     234           0 :   if (!mHasBaseVal || mBaseVal.none) {
     235           0 :     return nullptr;
     236             :   }
     237             : 
     238             :   RefPtr<DOMBaseVal> domBaseVal =
     239           0 :     sBaseSVGViewBoxTearoffTable.GetTearoff(this);
     240           0 :   if (!domBaseVal) {
     241           0 :     domBaseVal = new DOMBaseVal(this, aSVGElement);
     242           0 :     sBaseSVGViewBoxTearoffTable.AddTearoff(this, domBaseVal);
     243             :   }
     244             : 
     245           0 :  return domBaseVal.forget();
     246             : }
     247             : 
     248           0 : nsSVGViewBox::DOMBaseVal::~DOMBaseVal()
     249             : {
     250           0 :   sBaseSVGViewBoxTearoffTable.RemoveTearoff(mVal);
     251           0 : }
     252             : 
     253             : already_AddRefed<dom::SVGIRect>
     254           0 : nsSVGViewBox::ToDOMAnimVal(nsSVGElement *aSVGElement)
     255             : {
     256           0 :   if ((mAnimVal && mAnimVal->none) ||
     257           0 :       (!mAnimVal && (!mHasBaseVal || mBaseVal.none))) {
     258           0 :     return nullptr;
     259             :   }
     260             : 
     261             :   RefPtr<DOMAnimVal> domAnimVal =
     262           0 :     sAnimSVGViewBoxTearoffTable.GetTearoff(this);
     263           0 :   if (!domAnimVal) {
     264           0 :     domAnimVal = new DOMAnimVal(this, aSVGElement);
     265           0 :     sAnimSVGViewBoxTearoffTable.AddTearoff(this, domAnimVal);
     266             :   }
     267             : 
     268           0 :   return domAnimVal.forget();
     269             : }
     270             : 
     271           0 : nsSVGViewBox::DOMAnimVal::~DOMAnimVal()
     272             : {
     273           0 :   sAnimSVGViewBoxTearoffTable.RemoveTearoff(mVal);
     274           0 : }
     275             : 
     276             : void
     277           0 : nsSVGViewBox::DOMBaseVal::SetX(float aX, ErrorResult& aRv)
     278             : {
     279           0 :   nsSVGViewBoxRect rect = mVal->GetBaseValue();
     280           0 :   rect.x = aX;
     281           0 :   mVal->SetBaseValue(rect, mSVGElement);
     282           0 : }
     283             : 
     284             : void
     285           0 : nsSVGViewBox::DOMBaseVal::SetY(float aY, ErrorResult& aRv)
     286             : {
     287           0 :   nsSVGViewBoxRect rect = mVal->GetBaseValue();
     288           0 :   rect.y = aY;
     289           0 :   mVal->SetBaseValue(rect, mSVGElement);
     290           0 : }
     291             : 
     292             : void
     293           0 : nsSVGViewBox::DOMBaseVal::SetWidth(float aWidth, ErrorResult& aRv)
     294             : {
     295           0 :   nsSVGViewBoxRect rect = mVal->GetBaseValue();
     296           0 :   rect.width = aWidth;
     297           0 :   mVal->SetBaseValue(rect, mSVGElement);
     298           0 : }
     299             : 
     300             : void
     301           0 : nsSVGViewBox::DOMBaseVal::SetHeight(float aHeight, ErrorResult& aRv)
     302             : {
     303           0 :   nsSVGViewBoxRect rect = mVal->GetBaseValue();
     304           0 :   rect.height = aHeight;
     305           0 :   mVal->SetBaseValue(rect, mSVGElement);
     306           0 : }
     307             : 
     308             : UniquePtr<nsISMILAttr>
     309           0 : nsSVGViewBox::ToSMILAttr(nsSVGElement *aSVGElement)
     310             : {
     311           0 :   return MakeUnique<SMILViewBox>(this, aSVGElement);
     312             : }
     313             : 
     314             : nsresult
     315           0 : nsSVGViewBox::SMILViewBox
     316             :             ::ValueFromString(const nsAString& aStr,
     317             :                               const dom::SVGAnimationElement* /*aSrcElement*/,
     318             :                               nsSMILValue& aValue,
     319             :                               bool& aPreventCachingOfSandwich) const
     320             : {
     321           0 :   nsSVGViewBoxRect viewBox;
     322           0 :   nsresult res = nsSVGViewBoxRect::FromString(aStr, &viewBox);
     323           0 :   if (NS_FAILED(res)) {
     324           0 :     return res;
     325             :   }
     326           0 :   nsSMILValue val(&SVGViewBoxSMILType::sSingleton);
     327           0 :   *static_cast<nsSVGViewBoxRect*>(val.mU.mPtr) = viewBox;
     328           0 :   aValue = Move(val);
     329           0 :   aPreventCachingOfSandwich = false;
     330             : 
     331           0 :   return NS_OK;
     332             : }
     333             : 
     334             : nsSMILValue
     335           0 : nsSVGViewBox::SMILViewBox::GetBaseValue() const
     336             : {
     337           0 :   nsSMILValue val(&SVGViewBoxSMILType::sSingleton);
     338           0 :   *static_cast<nsSVGViewBoxRect*>(val.mU.mPtr) = mVal->mBaseVal;
     339           0 :   return val;
     340             : }
     341             : 
     342             : void
     343           0 : nsSVGViewBox::SMILViewBox::ClearAnimValue()
     344             : {
     345           0 :   if (mVal->mAnimVal) {
     346           0 :     mVal->mAnimVal = nullptr;
     347           0 :     mSVGElement->DidAnimateViewBox();
     348             :   }
     349           0 : }
     350             : 
     351             : nsresult
     352           0 : nsSVGViewBox::SMILViewBox::SetAnimValue(const nsSMILValue& aValue)
     353             : {
     354           0 :   NS_ASSERTION(aValue.mType == &SVGViewBoxSMILType::sSingleton,
     355             :                "Unexpected type to assign animated value");
     356           0 :   if (aValue.mType == &SVGViewBoxSMILType::sSingleton) {
     357           0 :     nsSVGViewBoxRect &vb = *static_cast<nsSVGViewBoxRect*>(aValue.mU.mPtr);
     358           0 :     mVal->SetAnimValue(vb, mSVGElement);
     359             :   }
     360           0 :   return NS_OK;
     361           9 : }

Generated by: LCOV version 1.13