LCOV - code coverage report
Current view: top level - dom/svg - SVGLineElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 9 111 8.1 %
Date: 2017-07-14 16:53:18 Functions: 4 15 26.7 %
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/SVGLineElement.h"
       8             : #include "mozilla/dom/SVGLineElementBinding.h"
       9             : #include "mozilla/gfx/2D.h"
      10             : 
      11           4 : NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Line)
      12             : 
      13             : using namespace mozilla::gfx;
      14             : 
      15             : namespace mozilla {
      16             : namespace dom {
      17             : 
      18             : JSObject*
      19           0 : SVGLineElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
      20             : {
      21           0 :   return SVGLineElementBinding::Wrap(aCx, this, aGivenProto);
      22             : }
      23             : 
      24             : nsSVGElement::LengthInfo SVGLineElement::sLengthInfo[4] =
      25             : {
      26             :   { &nsGkAtoms::x1, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
      27             :   { &nsGkAtoms::y1, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
      28             :   { &nsGkAtoms::x2, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
      29             :   { &nsGkAtoms::y2, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
      30             : };
      31             : 
      32             : //----------------------------------------------------------------------
      33             : // Implementation
      34             : 
      35           2 : SVGLineElement::SVGLineElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
      36           2 :   : SVGLineElementBase(aNodeInfo)
      37             : {
      38           2 : }
      39             : 
      40             : void
      41           0 : SVGLineElement::MaybeAdjustForZeroLength(float aX1, float aY1,
      42             :                                          float& aX2, float aY2)
      43             : {
      44           0 :   if (aX1 == aX2 && aY1 == aY2) {
      45           0 :     SVGContentUtils::AutoStrokeOptions strokeOptions;
      46           0 :     SVGContentUtils::GetStrokeOptions(&strokeOptions, this, nullptr, nullptr,
      47           0 :                                       SVGContentUtils::eIgnoreStrokeDashing);
      48             : 
      49           0 :     if (strokeOptions.mLineCap != CapStyle::BUTT) {
      50             :       float tinyLength =
      51           0 :         strokeOptions.mLineWidth / SVG_ZERO_LENGTH_PATH_FIX_FACTOR;
      52           0 :       aX2 += tinyLength;
      53             :     }
      54             :   }
      55           0 : }
      56             : 
      57             : //----------------------------------------------------------------------
      58             : // nsIDOMNode methods
      59             : 
      60           0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGLineElement)
      61             : 
      62             : //----------------------------------------------------------------------
      63             : 
      64             : already_AddRefed<SVGAnimatedLength>
      65           0 : SVGLineElement::X1()
      66             : {
      67           0 :   return mLengthAttributes[ATTR_X1].ToDOMAnimatedLength(this);
      68             : }
      69             : 
      70             : already_AddRefed<SVGAnimatedLength>
      71           0 : SVGLineElement::Y1()
      72             : {
      73           0 :   return mLengthAttributes[ATTR_Y1].ToDOMAnimatedLength(this);
      74             : }
      75             : 
      76             : already_AddRefed<SVGAnimatedLength>
      77           0 : SVGLineElement::X2()
      78             : {
      79           0 :   return mLengthAttributes[ATTR_X2].ToDOMAnimatedLength(this);
      80             : }
      81             : 
      82             : already_AddRefed<SVGAnimatedLength>
      83           0 : SVGLineElement::Y2()
      84             : {
      85           0 :   return mLengthAttributes[ATTR_Y2].ToDOMAnimatedLength(this);
      86             : }
      87             : 
      88             : //----------------------------------------------------------------------
      89             : // nsIContent methods
      90             : 
      91             : NS_IMETHODIMP_(bool)
      92          39 : SVGLineElement::IsAttributeMapped(const nsIAtom* name) const
      93             : {
      94             :   static const MappedAttributeEntry* const map[] = {
      95             :     sMarkersMap
      96             :   };
      97             : 
      98          78 :   return FindAttributeDependence(name, map) ||
      99          78 :     SVGLineElementBase::IsAttributeMapped(name);
     100             : }
     101             : 
     102             : //----------------------------------------------------------------------
     103             : // nsSVGElement methods
     104             : 
     105             : nsSVGElement::LengthAttributesInfo
     106          15 : SVGLineElement::GetLengthInfo()
     107             : {
     108             :   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
     109          15 :                               ArrayLength(sLengthInfo));
     110             : }
     111             : 
     112             : //----------------------------------------------------------------------
     113             : // SVGGeometryElement methods
     114             : 
     115             : void
     116           0 : SVGLineElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks) {
     117             :   float x1, y1, x2, y2;
     118             : 
     119           0 :   GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
     120             : 
     121           0 :   float angle = atan2(y2 - y1, x2 - x1);
     122             : 
     123           0 :   aMarks->AppendElement(nsSVGMark(x1, y1, angle, nsSVGMark::eStart));
     124           0 :   aMarks->AppendElement(nsSVGMark(x2, y2, angle, nsSVGMark::eEnd));
     125           0 : }
     126             : 
     127             : void
     128           0 : SVGLineElement::GetAsSimplePath(SimplePath* aSimplePath)
     129             : {
     130             :   float x1, y1, x2, y2;
     131           0 :   GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
     132             : 
     133           0 :   MaybeAdjustForZeroLength(x1, y1, x2, y2);
     134           0 :   aSimplePath->SetLine(x1, y1, x2, y2);
     135           0 : }
     136             : 
     137             : already_AddRefed<Path>
     138           0 : SVGLineElement::BuildPath(PathBuilder* aBuilder)
     139             : {
     140             :   float x1, y1, x2, y2;
     141           0 :   GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
     142             : 
     143           0 :   MaybeAdjustForZeroLength(x1, y1, x2, y2);
     144           0 :   aBuilder->MoveTo(Point(x1, y1));
     145           0 :   aBuilder->LineTo(Point(x2, y2));
     146             : 
     147           0 :   return aBuilder->Finish();
     148             : }
     149             : 
     150             : bool
     151           0 : SVGLineElement::GetGeometryBounds(Rect* aBounds,
     152             :                                   const StrokeOptions& aStrokeOptions,
     153             :                                   const Matrix& aToBoundsSpace,
     154             :                                   const Matrix* aToNonScalingStrokeSpace)
     155             : {
     156             :   float x1, y1, x2, y2;
     157           0 :   GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
     158             : 
     159           0 :   if (aStrokeOptions.mLineWidth <= 0) {
     160           0 :     *aBounds = Rect(aToBoundsSpace.TransformPoint(Point(x1, y1)), Size());
     161           0 :     aBounds->ExpandToEnclose(aToBoundsSpace.TransformPoint(Point(x2, y2)));
     162           0 :     return true;
     163             :   }
     164             : 
     165             :   // transform from non-scaling-stroke space to the space in which we compute
     166             :   // bounds
     167           0 :   Matrix nonScalingToBounds;
     168           0 :   if (aToNonScalingStrokeSpace) {
     169           0 :     MOZ_ASSERT(!aToNonScalingStrokeSpace->IsSingular());
     170           0 :     Matrix nonScalingToUser = aToNonScalingStrokeSpace->Inverse();
     171           0 :     nonScalingToBounds = nonScalingToUser * aToBoundsSpace;
     172             :   }
     173             : 
     174           0 :   if (aStrokeOptions.mLineCap == CapStyle::ROUND) {
     175           0 :     if (!aToBoundsSpace.IsRectilinear() ||
     176           0 :         (aToNonScalingStrokeSpace &&
     177           0 :          !aToNonScalingStrokeSpace->IsRectilinear())) {
     178             :       // TODO: handle this case.
     179           0 :       return false;
     180             :     }
     181           0 :     Rect bounds(Point(x1, y1), Size());
     182           0 :     bounds.ExpandToEnclose(Point(x2, y2));
     183           0 :     if (aToNonScalingStrokeSpace) {
     184           0 :       bounds = aToNonScalingStrokeSpace->TransformBounds(bounds);
     185           0 :       bounds.Inflate(aStrokeOptions.mLineWidth / 2.f);
     186           0 :       *aBounds = nonScalingToBounds.TransformBounds(bounds);
     187             :     } else {
     188           0 :       bounds.Inflate(aStrokeOptions.mLineWidth / 2.f);
     189           0 :       *aBounds = aToBoundsSpace.TransformBounds(bounds);
     190             :     }
     191           0 :     return true;
     192             :   }
     193             : 
     194             :   // Handle butt and square linecap, normal and non-scaling stroke cases
     195             :   // together: start with endpoints (x1, y1), (x2, y2) in the stroke space,
     196             :   // compute the four corners of the stroked line, transform the corners to
     197             :   // bounds space, and compute bounds there.
     198             : 
     199           0 :   if (aToNonScalingStrokeSpace) {
     200           0 :     Point nonScalingSpaceP1, nonScalingSpaceP2;
     201           0 :     nonScalingSpaceP1 = aToNonScalingStrokeSpace->TransformPoint(Point(x1, y1));
     202           0 :     nonScalingSpaceP2 = aToNonScalingStrokeSpace->TransformPoint(Point(x2, y2));
     203           0 :     x1 = nonScalingSpaceP1.x;
     204           0 :     y1 = nonScalingSpaceP1.y;
     205           0 :     x2 = nonScalingSpaceP2.x;
     206           0 :     y2 = nonScalingSpaceP2.y;
     207             :   }
     208             : 
     209           0 :   Float length = Float(NS_hypot(x2 - x1, y2 - y1));
     210             :   Float xDelta;
     211             :   Float yDelta;
     212           0 :   Point points[4];
     213             : 
     214           0 :   if (aStrokeOptions.mLineCap == CapStyle::BUTT) {
     215           0 :     if (length == 0.f) {
     216           0 :       xDelta = yDelta = 0.f;
     217             :     } else {
     218           0 :       Float ratio = aStrokeOptions.mLineWidth / 2.f / length;
     219           0 :       xDelta = ratio * (y2 - y1);
     220           0 :       yDelta = ratio * (x2 - x1);
     221             :     }
     222           0 :     points[0] = Point(x1 - xDelta, y1 + yDelta);
     223           0 :     points[1] = Point(x1 + xDelta, y1 - yDelta);
     224           0 :     points[2] = Point(x2 + xDelta, y2 - yDelta);
     225           0 :     points[3] = Point(x2 - xDelta, y2 + yDelta);
     226             :   } else {
     227           0 :     MOZ_ASSERT(aStrokeOptions.mLineCap == CapStyle::SQUARE);
     228           0 :     if (length == 0.f) {
     229           0 :       xDelta = yDelta = aStrokeOptions.mLineWidth / 2.f;
     230           0 :       points[0] = Point(x1 - xDelta, y1 + yDelta);
     231           0 :       points[1] = Point(x1 - xDelta, y1 - yDelta);
     232           0 :       points[2] = Point(x1 + xDelta, y1 - yDelta);
     233           0 :       points[3] = Point(x1 + xDelta, y1 + yDelta);
     234             :     } else {
     235           0 :       Float ratio = aStrokeOptions.mLineWidth / 2.f / length;
     236           0 :       yDelta = ratio * (x2 - x1);
     237           0 :       xDelta = ratio * (y2 - y1);
     238           0 :       points[0] = Point(x1 - yDelta - xDelta, y1 - xDelta + yDelta);
     239           0 :       points[1] = Point(x1 - yDelta + xDelta, y1 - xDelta - yDelta);
     240           0 :       points[2] = Point(x2 + yDelta + xDelta, y2 + xDelta - yDelta);
     241           0 :       points[3] = Point(x2 + yDelta - xDelta, y2 + xDelta + yDelta);
     242             :     }
     243             :   }
     244             : 
     245           0 :   const Matrix& toBoundsSpace = aToNonScalingStrokeSpace ?
     246           0 :     nonScalingToBounds : aToBoundsSpace;
     247             : 
     248           0 :   *aBounds = Rect(toBoundsSpace.TransformPoint(points[0]), Size());
     249           0 :   for (uint32_t i = 1; i < 4; ++i) {
     250           0 :     aBounds->ExpandToEnclose(toBoundsSpace.TransformPoint(points[i]));
     251             :   }
     252             : 
     253           0 :   return true;
     254             : }
     255             : 
     256             : } // namespace dom
     257             : } // namespace mozilla

Generated by: LCOV version 1.13