LCOV - code coverage report
Current view: top level - dom/svg - SVGRectElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 49 88 55.7 %
Date: 2017-07-14 16:53:18 Functions: 8 15 53.3 %
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 "mozilla/dom/SVGRectElement.h"
       8             : #include "nsGkAtoms.h"
       9             : #include "mozilla/dom/SVGRectElementBinding.h"
      10             : #include "mozilla/gfx/2D.h"
      11             : #include "mozilla/gfx/Matrix.h"
      12             : #include "mozilla/gfx/Rect.h"
      13             : #include "mozilla/gfx/PathHelpers.h"
      14             : #include <algorithm>
      15             : 
      16          18 : NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Rect)
      17             : 
      18             : using namespace mozilla::gfx;
      19             : 
      20             : namespace mozilla {
      21             : namespace dom {
      22             : 
      23             : class SVGAnimatedLength;
      24             : 
      25             : JSObject*
      26           0 : SVGRectElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
      27             : {
      28           0 :   return SVGRectElementBinding::Wrap(aCx, this, aGivenProto);
      29             : }
      30             : 
      31             : nsSVGElement::LengthInfo SVGRectElement::sLengthInfo[6] =
      32             : {
      33             :   { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
      34             :   { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
      35             :   { &nsGkAtoms::width, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
      36             :   { &nsGkAtoms::height, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
      37             :   { &nsGkAtoms::rx, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
      38             :   { &nsGkAtoms::ry, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }
      39             : };
      40             : 
      41             : //----------------------------------------------------------------------
      42             : // Implementation
      43             : 
      44          11 : SVGRectElement::SVGRectElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
      45          11 :   : SVGRectElementBase(aNodeInfo)
      46             : {
      47          11 : }
      48             : 
      49             : //----------------------------------------------------------------------
      50             : // nsIDOMNode methods
      51             : 
      52           4 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGRectElement)
      53             : 
      54             : //----------------------------------------------------------------------
      55             : 
      56             : already_AddRefed<SVGAnimatedLength>
      57           0 : SVGRectElement::X()
      58             : {
      59           0 :   return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this);
      60             : }
      61             : 
      62             : already_AddRefed<SVGAnimatedLength>
      63           0 : SVGRectElement::Y()
      64             : {
      65           0 :   return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this);
      66             : }
      67             : 
      68             : already_AddRefed<SVGAnimatedLength>
      69           0 : SVGRectElement::Width()
      70             : {
      71           0 :   return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this);
      72             : }
      73             : 
      74             : already_AddRefed<SVGAnimatedLength>
      75           0 : SVGRectElement::Height()
      76             : {
      77           0 :   return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this);
      78             : }
      79             : 
      80             : already_AddRefed<SVGAnimatedLength>
      81           0 : SVGRectElement::Rx()
      82             : {
      83           0 :   return mLengthAttributes[ATTR_RX].ToDOMAnimatedLength(this);
      84             : }
      85             : 
      86             : already_AddRefed<SVGAnimatedLength>
      87           0 : SVGRectElement::Ry()
      88             : {
      89           0 :   return mLengthAttributes[ATTR_RY].ToDOMAnimatedLength(this);
      90             : }
      91             : 
      92             : //----------------------------------------------------------------------
      93             : // nsSVGElement methods
      94             : 
      95             : /* virtual */ bool
      96           8 : SVGRectElement::HasValidDimensions() const
      97             : {
      98          16 :   return mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() &&
      99          16 :          mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0 &&
     100          24 :          mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() &&
     101          16 :          mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0;
     102             : }
     103             : 
     104             : nsSVGElement::LengthAttributesInfo
     105          97 : SVGRectElement::GetLengthInfo()
     106             : {
     107             :   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
     108          97 :                               ArrayLength(sLengthInfo));
     109             : }
     110             : 
     111             : //----------------------------------------------------------------------
     112             : // SVGGeometryElement methods
     113             : 
     114             : bool
     115          16 : SVGRectElement::GetGeometryBounds(Rect* aBounds,
     116             :                                   const StrokeOptions& aStrokeOptions,
     117             :                                   const Matrix& aToBoundsSpace,
     118             :                                   const Matrix* aToNonScalingStrokeSpace)
     119             : {
     120          16 :   Rect rect;
     121             :   Float rx, ry;
     122          16 :   GetAnimatedLengthValues(&rect.x, &rect.y, &rect.width,
     123          16 :                           &rect.height, &rx, &ry, nullptr);
     124             : 
     125          16 :   if (rect.IsEmpty()) {
     126             :     // Rendering of the element disabled
     127           0 :     rect.SetEmpty(); // Make sure width/height are zero and not negative
     128             :     // We still want the x/y position from 'rect'
     129           0 :     *aBounds = aToBoundsSpace.TransformBounds(rect);
     130           0 :     return true;
     131             :   }
     132             : 
     133          16 :   if (!aToBoundsSpace.IsRectilinear()) {
     134             :     // We can't ignore the radii in this case if we want tight bounds
     135           0 :     rx = std::max(rx, 0.0f);
     136           0 :     ry = std::max(ry, 0.0f);
     137             : 
     138           0 :     if (rx != 0 || ry != 0) {
     139           0 :       return false;
     140             :     }
     141             :   }
     142             : 
     143          16 :   if (aStrokeOptions.mLineWidth > 0.f) {
     144           4 :     if (aToNonScalingStrokeSpace) {
     145           0 :       if (aToNonScalingStrokeSpace->IsRectilinear()) {
     146           0 :         MOZ_ASSERT(!aToNonScalingStrokeSpace->IsSingular());
     147           0 :         rect = aToNonScalingStrokeSpace->TransformBounds(rect);
     148             :         // Note that, in principle, an author could cause the corners of the
     149             :         // rect to be beveled by specifying stroke-linejoin or setting
     150             :         // stroke-miterlimit to be less than sqrt(2). In that very unlikely
     151             :         // event the bounds that we calculate here may be too big if
     152             :         // aToBoundsSpace is non-rectilinear. This is likely to be so rare it's
     153             :         // not worth handling though.
     154           0 :         rect.Inflate(aStrokeOptions.mLineWidth / 2.f);
     155             :         Matrix nonScalingToBounds =
     156           0 :           aToNonScalingStrokeSpace->Inverse() * aToBoundsSpace;
     157           0 :         *aBounds = nonScalingToBounds.TransformBounds(rect);
     158           0 :         return true;
     159             :       }
     160           0 :       return false;
     161             :     }
     162             :     // The "beveled" comment above applies here too
     163           4 :     rect.Inflate(aStrokeOptions.mLineWidth / 2.f);
     164             :   }
     165             : 
     166          16 :   *aBounds = aToBoundsSpace.TransformBounds(rect);
     167          16 :   return true;
     168             : }
     169             : 
     170             : void
     171           8 : SVGRectElement::GetAsSimplePath(SimplePath* aSimplePath)
     172             : {
     173             :   float x, y, width, height, rx, ry;
     174           8 :   GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nullptr);
     175             : 
     176           8 :   if (width <= 0 || height <= 0) {
     177           0 :     aSimplePath->Reset();
     178           0 :     return;
     179             :   }
     180             : 
     181           8 :   rx = std::max(rx, 0.0f);
     182           8 :   ry = std::max(ry, 0.0f);
     183             : 
     184           8 :   if (rx != 0 || ry != 0) {
     185           4 :     aSimplePath->Reset();
     186           4 :     return;
     187             :   }
     188             : 
     189           4 :   aSimplePath->SetRect(x, y, width, height);
     190             : }
     191             : 
     192             : already_AddRefed<Path>
     193           4 : SVGRectElement::BuildPath(PathBuilder* aBuilder)
     194             : {
     195             :   float x, y, width, height, rx, ry;
     196           4 :   GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nullptr);
     197             : 
     198           4 :   if (width <= 0 || height <= 0) {
     199           0 :     return nullptr;
     200             :   }
     201             : 
     202           4 :   rx = std::max(rx, 0.0f);
     203           4 :   ry = std::max(ry, 0.0f);
     204             : 
     205           4 :   if (rx == 0 && ry == 0) {
     206             :     // Optimization for the no rounded corners case.
     207           0 :     Rect r(x, y, width, height);
     208           0 :     aBuilder->MoveTo(r.TopLeft());
     209           0 :     aBuilder->LineTo(r.TopRight());
     210           0 :     aBuilder->LineTo(r.BottomRight());
     211           0 :     aBuilder->LineTo(r.BottomLeft());
     212           0 :     aBuilder->Close();
     213             :   } else {
     214             :     // If either the 'rx' or the 'ry' attribute isn't set, then we have to
     215             :     // set it to the value of the other:
     216           4 :     bool hasRx = mLengthAttributes[ATTR_RX].IsExplicitlySet();
     217           4 :     bool hasRy = mLengthAttributes[ATTR_RY].IsExplicitlySet();
     218           4 :     MOZ_ASSERT(hasRx || hasRy);
     219             : 
     220           4 :     if (hasRx && !hasRy) {
     221           2 :       ry = rx;
     222           2 :     } else if (hasRy && !hasRx) {
     223           0 :       rx = ry;
     224             :     }
     225             : 
     226             :     // Clamp rx and ry to half the rect's width and height respectively:
     227           4 :     rx = std::min(rx, width / 2);
     228           4 :     ry = std::min(ry, height / 2);
     229             : 
     230           4 :     RectCornerRadii radii(rx, ry);
     231           4 :     AppendRoundedRectToPath(aBuilder, Rect(x, y, width, height), radii);
     232             :   }
     233             : 
     234           4 :   return aBuilder->Finish();
     235             : }
     236             : 
     237             : } // namespace dom
     238             : } // namespace mozilla

Generated by: LCOV version 1.13