Bug 1691109 [wpt PR 27513] - Increase timeout duration for wpt/fetch/api/basic/keepal...
[gecko.git] / dom / svg / SVGPathElement.cpp
blobec90ffcf4961b5359da018b0e5b5834c1305d3db
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/. */
7 #include "mozilla/dom/SVGPathElement.h"
9 #include <algorithm>
11 #include "DOMSVGPathSeg.h"
12 #include "DOMSVGPathSegList.h"
13 #include "SVGGeometryProperty.h"
14 #include "gfx2DGlue.h"
15 #include "gfxPlatform.h"
16 #include "nsGkAtoms.h"
17 #include "nsIFrame.h"
18 #include "nsStyleConsts.h"
19 #include "nsStyleStruct.h"
20 #include "nsWindowSizes.h"
21 #include "mozilla/dom/SVGPathElementBinding.h"
22 #include "mozilla/gfx/2D.h"
23 #include "mozilla/RefPtr.h"
24 #include "mozilla/SVGContentUtils.h"
26 NS_IMPL_NS_NEW_SVG_ELEMENT(Path)
28 using namespace mozilla::gfx;
30 namespace mozilla {
31 namespace dom {
33 JSObject* SVGPathElement::WrapNode(JSContext* aCx,
34 JS::Handle<JSObject*> aGivenProto) {
35 return SVGPathElement_Binding::Wrap(aCx, this, aGivenProto);
38 //----------------------------------------------------------------------
39 // Implementation
41 SVGPathElement::SVGPathElement(
42 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
43 : SVGPathElementBase(std::move(aNodeInfo)) {}
45 //----------------------------------------------------------------------
46 // memory reporting methods
48 void SVGPathElement::AddSizeOfExcludingThis(nsWindowSizes& aSizes,
49 size_t* aNodeSize) const {
50 SVGPathElementBase::AddSizeOfExcludingThis(aSizes, aNodeSize);
51 *aNodeSize += mD.SizeOfExcludingThis(aSizes.mState.mMallocSizeOf);
54 //----------------------------------------------------------------------
55 // nsINode methods
57 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGPathElement)
59 uint32_t SVGPathElement::GetPathSegAtLength(float distance) {
60 return mD.GetAnimValue().GetPathSegAtLength(distance);
63 already_AddRefed<DOMSVGPathSegClosePath>
64 SVGPathElement::CreateSVGPathSegClosePath() {
65 RefPtr<DOMSVGPathSegClosePath> pathSeg = new DOMSVGPathSegClosePath();
66 return pathSeg.forget();
69 already_AddRefed<DOMSVGPathSegMovetoAbs>
70 SVGPathElement::CreateSVGPathSegMovetoAbs(float x, float y) {
71 RefPtr<DOMSVGPathSegMovetoAbs> pathSeg = new DOMSVGPathSegMovetoAbs(x, y);
72 return pathSeg.forget();
75 already_AddRefed<DOMSVGPathSegMovetoRel>
76 SVGPathElement::CreateSVGPathSegMovetoRel(float x, float y) {
77 RefPtr<DOMSVGPathSegMovetoRel> pathSeg = new DOMSVGPathSegMovetoRel(x, y);
78 return pathSeg.forget();
81 already_AddRefed<DOMSVGPathSegLinetoAbs>
82 SVGPathElement::CreateSVGPathSegLinetoAbs(float x, float y) {
83 RefPtr<DOMSVGPathSegLinetoAbs> pathSeg = new DOMSVGPathSegLinetoAbs(x, y);
84 return pathSeg.forget();
87 already_AddRefed<DOMSVGPathSegLinetoRel>
88 SVGPathElement::CreateSVGPathSegLinetoRel(float x, float y) {
89 RefPtr<DOMSVGPathSegLinetoRel> pathSeg = new DOMSVGPathSegLinetoRel(x, y);
90 return pathSeg.forget();
93 already_AddRefed<DOMSVGPathSegCurvetoCubicAbs>
94 SVGPathElement::CreateSVGPathSegCurvetoCubicAbs(float x, float y, float x1,
95 float y1, float x2, float y2) {
96 // Note that we swap from DOM API argument order to the argument order used
97 // in the <path> element's 'd' attribute (i.e. we put the arguments for the
98 // end point of the segment last instead of first).
99 RefPtr<DOMSVGPathSegCurvetoCubicAbs> pathSeg =
100 new DOMSVGPathSegCurvetoCubicAbs(x1, y1, x2, y2, x, y);
101 return pathSeg.forget();
104 already_AddRefed<DOMSVGPathSegCurvetoCubicRel>
105 SVGPathElement::CreateSVGPathSegCurvetoCubicRel(float x, float y, float x1,
106 float y1, float x2, float y2) {
107 // See comment in CreateSVGPathSegCurvetoCubicAbs
108 RefPtr<DOMSVGPathSegCurvetoCubicRel> pathSeg =
109 new DOMSVGPathSegCurvetoCubicRel(x1, y1, x2, y2, x, y);
110 return pathSeg.forget();
113 already_AddRefed<DOMSVGPathSegCurvetoQuadraticAbs>
114 SVGPathElement::CreateSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1,
115 float y1) {
116 // See comment in CreateSVGPathSegCurvetoCubicAbs
117 RefPtr<DOMSVGPathSegCurvetoQuadraticAbs> pathSeg =
118 new DOMSVGPathSegCurvetoQuadraticAbs(x1, y1, x, y);
119 return pathSeg.forget();
122 already_AddRefed<DOMSVGPathSegCurvetoQuadraticRel>
123 SVGPathElement::CreateSVGPathSegCurvetoQuadraticRel(float x, float y, float x1,
124 float y1) {
125 // See comment in CreateSVGPathSegCurvetoCubicAbs
126 RefPtr<DOMSVGPathSegCurvetoQuadraticRel> pathSeg =
127 new DOMSVGPathSegCurvetoQuadraticRel(x1, y1, x, y);
128 return pathSeg.forget();
131 already_AddRefed<DOMSVGPathSegArcAbs> SVGPathElement::CreateSVGPathSegArcAbs(
132 float x, float y, float r1, float r2, float angle, bool largeArcFlag,
133 bool sweepFlag) {
134 // See comment in CreateSVGPathSegCurvetoCubicAbs
135 RefPtr<DOMSVGPathSegArcAbs> pathSeg =
136 new DOMSVGPathSegArcAbs(r1, r2, angle, largeArcFlag, sweepFlag, x, y);
137 return pathSeg.forget();
140 already_AddRefed<DOMSVGPathSegArcRel> SVGPathElement::CreateSVGPathSegArcRel(
141 float x, float y, float r1, float r2, float angle, bool largeArcFlag,
142 bool sweepFlag) {
143 // See comment in CreateSVGPathSegCurvetoCubicAbs
144 RefPtr<DOMSVGPathSegArcRel> pathSeg =
145 new DOMSVGPathSegArcRel(r1, r2, angle, largeArcFlag, sweepFlag, x, y);
146 return pathSeg.forget();
149 already_AddRefed<DOMSVGPathSegLinetoHorizontalAbs>
150 SVGPathElement::CreateSVGPathSegLinetoHorizontalAbs(float x) {
151 RefPtr<DOMSVGPathSegLinetoHorizontalAbs> pathSeg =
152 new DOMSVGPathSegLinetoHorizontalAbs(x);
153 return pathSeg.forget();
156 already_AddRefed<DOMSVGPathSegLinetoHorizontalRel>
157 SVGPathElement::CreateSVGPathSegLinetoHorizontalRel(float x) {
158 RefPtr<DOMSVGPathSegLinetoHorizontalRel> pathSeg =
159 new DOMSVGPathSegLinetoHorizontalRel(x);
160 return pathSeg.forget();
163 already_AddRefed<DOMSVGPathSegLinetoVerticalAbs>
164 SVGPathElement::CreateSVGPathSegLinetoVerticalAbs(float y) {
165 RefPtr<DOMSVGPathSegLinetoVerticalAbs> pathSeg =
166 new DOMSVGPathSegLinetoVerticalAbs(y);
167 return pathSeg.forget();
170 already_AddRefed<DOMSVGPathSegLinetoVerticalRel>
171 SVGPathElement::CreateSVGPathSegLinetoVerticalRel(float y) {
172 RefPtr<DOMSVGPathSegLinetoVerticalRel> pathSeg =
173 new DOMSVGPathSegLinetoVerticalRel(y);
174 return pathSeg.forget();
177 already_AddRefed<DOMSVGPathSegCurvetoCubicSmoothAbs>
178 SVGPathElement::CreateSVGPathSegCurvetoCubicSmoothAbs(float x, float y,
179 float x2, float y2) {
180 // See comment in CreateSVGPathSegCurvetoCubicAbs
181 RefPtr<DOMSVGPathSegCurvetoCubicSmoothAbs> pathSeg =
182 new DOMSVGPathSegCurvetoCubicSmoothAbs(x2, y2, x, y);
183 return pathSeg.forget();
186 already_AddRefed<DOMSVGPathSegCurvetoCubicSmoothRel>
187 SVGPathElement::CreateSVGPathSegCurvetoCubicSmoothRel(float x, float y,
188 float x2, float y2) {
189 // See comment in CreateSVGPathSegCurvetoCubicAbs
190 RefPtr<DOMSVGPathSegCurvetoCubicSmoothRel> pathSeg =
191 new DOMSVGPathSegCurvetoCubicSmoothRel(x2, y2, x, y);
192 return pathSeg.forget();
195 already_AddRefed<DOMSVGPathSegCurvetoQuadraticSmoothAbs>
196 SVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y) {
197 RefPtr<DOMSVGPathSegCurvetoQuadraticSmoothAbs> pathSeg =
198 new DOMSVGPathSegCurvetoQuadraticSmoothAbs(x, y);
199 return pathSeg.forget();
202 already_AddRefed<DOMSVGPathSegCurvetoQuadraticSmoothRel>
203 SVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothRel(float x, float y) {
204 RefPtr<DOMSVGPathSegCurvetoQuadraticSmoothRel> pathSeg =
205 new DOMSVGPathSegCurvetoQuadraticSmoothRel(x, y);
206 return pathSeg.forget();
209 already_AddRefed<DOMSVGPathSegList> SVGPathElement::PathSegList() {
210 return DOMSVGPathSegList::GetDOMWrapper(mD.GetBaseValKey(), this, false);
213 already_AddRefed<DOMSVGPathSegList> SVGPathElement::AnimatedPathSegList() {
214 return DOMSVGPathSegList::GetDOMWrapper(mD.GetAnimValKey(), this, true);
217 //----------------------------------------------------------------------
218 // SVGElement methods
220 /* virtual */
221 bool SVGPathElement::HasValidDimensions() const {
222 return !mD.GetAnimValue().IsEmpty();
225 //----------------------------------------------------------------------
226 // nsIContent methods
228 NS_IMETHODIMP_(bool)
229 SVGPathElement::IsAttributeMapped(const nsAtom* name) const {
230 static const MappedAttributeEntry* const map[] = {sMarkersMap};
232 return FindAttributeDependence(name, map) ||
233 SVGPathElementBase::IsAttributeMapped(name);
236 already_AddRefed<Path> SVGPathElement::GetOrBuildPathForMeasuring() {
237 return mD.GetAnimValue().BuildPathForMeasuring();
240 //----------------------------------------------------------------------
241 // SVGGeometryElement methods
243 bool SVGPathElement::AttributeDefinesGeometry(const nsAtom* aName) {
244 return aName == nsGkAtoms::d || aName == nsGkAtoms::pathLength;
247 bool SVGPathElement::IsMarkable() { return true; }
249 void SVGPathElement::GetMarkPoints(nsTArray<SVGMark>* aMarks) {
250 mD.GetAnimValue().GetMarkerPositioningData(aMarks);
253 already_AddRefed<Path> SVGPathElement::BuildPath(PathBuilder* aBuilder) {
254 // The Moz2D PathBuilder that our SVGPathData will be using only cares about
255 // the fill rule. However, in order to fulfill the requirements of the SVG
256 // spec regarding zero length sub-paths when square line caps are in use,
257 // SVGPathData needs to know our stroke-linecap style and, if "square", then
258 // also our stroke width. See the comment for
259 // ApproximateZeroLengthSubpathSquareCaps for more info.
261 auto strokeLineCap = StyleStrokeLinecap::Butt;
262 Float strokeWidth = 0;
264 SVGGeometryProperty::DoForComputedStyle(this, [&](const ComputedStyle* s) {
265 const nsStyleSVG* style = s->StyleSVG();
266 // Note: the path that we return may be used for hit-testing, and SVG
267 // exposes hit-testing of strokes that are not actually painted. For that
268 // reason we do not check for eStyleSVGPaintType_None or check the stroke
269 // opacity here.
270 if (style->mStrokeLinecap != StyleStrokeLinecap::Butt) {
271 strokeLineCap = style->mStrokeLinecap;
272 strokeWidth = SVGContentUtils::GetStrokeWidth(this, s, nullptr);
276 return mD.GetAnimValue().BuildPath(aBuilder, strokeLineCap, strokeWidth);
279 } // namespace dom
280 } // namespace mozilla