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 : #ifndef mozilla_dom_SVGGeometryElement_h
8 : #define mozilla_dom_SVGGeometryElement_h
9 :
10 : #include "mozilla/gfx/2D.h"
11 : #include "SVGGraphicsElement.h"
12 : #include "nsISVGPoint.h"
13 : #include "nsSVGNumber2.h"
14 :
15 : struct nsSVGMark {
16 : enum Type {
17 : eStart,
18 : eMid,
19 : eEnd,
20 :
21 : eTypeCount
22 : };
23 :
24 : float x, y, angle;
25 : Type type;
26 0 : nsSVGMark(float aX, float aY, float aAngle, Type aType) :
27 0 : x(aX), y(aY), angle(aAngle), type(aType) {}
28 : };
29 :
30 : namespace mozilla {
31 : namespace dom {
32 :
33 : class SVGAnimatedNumber;
34 :
35 : typedef mozilla::dom::SVGGraphicsElement SVGGeometryElementBase;
36 :
37 0 : class SVGGeometryElement : public SVGGeometryElementBase
38 : {
39 : protected:
40 : typedef mozilla::gfx::CapStyle CapStyle;
41 : typedef mozilla::gfx::DrawTarget DrawTarget;
42 : typedef mozilla::gfx::FillRule FillRule;
43 : typedef mozilla::gfx::Float Float;
44 : typedef mozilla::gfx::Matrix Matrix;
45 : typedef mozilla::gfx::Path Path;
46 : typedef mozilla::gfx::Point Point;
47 : typedef mozilla::gfx::PathBuilder PathBuilder;
48 : typedef mozilla::gfx::Rect Rect;
49 : typedef mozilla::gfx::StrokeOptions StrokeOptions;
50 :
51 : public:
52 : explicit SVGGeometryElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
53 :
54 : virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
55 : const nsAttrValue* aValue,
56 : const nsAttrValue* aOldValue,
57 : bool aNotify) override;
58 :
59 : /**
60 : * Causes this element to discard any Path object that GetOrBuildPath may
61 : * have cached.
62 : */
63 0 : virtual void ClearAnyCachedPath() override final {
64 0 : mCachedPath = nullptr;
65 0 : }
66 :
67 : virtual bool AttributeDefinesGeometry(const nsIAtom *aName);
68 :
69 : /**
70 : * Returns true if this element's geometry depends on the width or height of its
71 : * coordinate context (typically the viewport established by its nearest <svg>
72 : * ancestor). In other words, returns true if one of the attributes for which
73 : * AttributeDefinesGeometry returns true has a percentage value.
74 : *
75 : * This could be moved up to a more general class so it can be used for non-leaf
76 : * elements, but that would require care and for now there's no need.
77 : */
78 : bool GeometryDependsOnCoordCtx();
79 :
80 : virtual bool IsMarkable();
81 : virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks);
82 :
83 : /**
84 : * A method that can be faster than using a Moz2D Path and calling GetBounds/
85 : * GetStrokedBounds on it. It also helps us avoid rounding error for simple
86 : * shapes and simple transforms where the Moz2D Path backends can fail to
87 : * produce the clean integer bounds that content authors expect in some cases.
88 : *
89 : * If |aToNonScalingStrokeSpace| is non-null then |aBounds|, which is computed
90 : * in bounds space, has the property that it's the smallest (axis-aligned)
91 : * rectangular bound containing the image of this shape as stroked in
92 : * non-scaling-stroke space. (When all transforms involved are rectilinear
93 : * the bounds of the image of |aBounds| in non-scaling-stroke space will be
94 : * tight, but if there are non-rectilinear transforms involved then that may
95 : * be impossible and this method will return false).
96 : *
97 : * If |aToNonScalingStrokeSpace| is non-null then |*aToNonScalingStrokeSpace|
98 : * must be non-singular.
99 : */
100 40 : virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
101 : const Matrix& aToBoundsSpace,
102 : const Matrix* aToNonScalingStrokeSpace = nullptr) {
103 40 : return false;
104 : }
105 :
106 : /**
107 : * For use with GetAsSimplePath.
108 : */
109 : class SimplePath
110 : {
111 : public:
112 34 : SimplePath()
113 34 : : mType(NONE)
114 34 : {}
115 34 : bool IsPath() const {
116 34 : return mType != NONE;
117 : }
118 4 : void SetRect(Float x, Float y, Float width, Float height) {
119 4 : mX = x;
120 4 : mY = y;
121 4 : mWidthOrX2 = width;
122 4 : mHeightOrY2 = height;
123 4 : mType = RECT;
124 4 : }
125 4 : Rect AsRect() const {
126 4 : MOZ_ASSERT(mType == RECT);
127 4 : return Rect(mX, mY, mWidthOrX2, mHeightOrY2);
128 : }
129 34 : bool IsRect() const {
130 34 : return mType == RECT;
131 : }
132 0 : void SetLine(Float x1, Float y1, Float x2, Float y2) {
133 0 : mX = x1;
134 0 : mY = y1;
135 0 : mWidthOrX2 = x2;
136 0 : mHeightOrY2 = y2;
137 0 : mType = LINE;
138 0 : }
139 0 : Point Point1() const {
140 0 : MOZ_ASSERT(mType == LINE);
141 0 : return Point(mX, mY);
142 : }
143 0 : Point Point2() const {
144 0 : MOZ_ASSERT(mType == LINE);
145 0 : return Point(mWidthOrX2, mHeightOrY2);
146 : }
147 2 : bool IsLine() const {
148 2 : return mType == LINE;
149 : }
150 30 : void Reset() {
151 30 : mType = NONE;
152 30 : }
153 : private:
154 : enum Type {
155 : NONE, RECT, LINE
156 : };
157 : Float mX, mY, mWidthOrX2, mHeightOrY2;
158 : Type mType;
159 : };
160 :
161 : /**
162 : * For some platforms there is significant overhead to creating and painting
163 : * a Moz2D Path object. For Rects and lines it is better to get the path data
164 : * using this method and then use the optimized DrawTarget methods for
165 : * filling/stroking rects and lines.
166 : */
167 26 : virtual void GetAsSimplePath(SimplePath* aSimplePath) {
168 26 : aSimplePath->Reset();
169 26 : }
170 :
171 : /**
172 : * Returns a Path that can be used to paint, hit-test or calculate bounds for
173 : * this element. May return nullptr if there is no [valid] path. The path
174 : * that is created may be cached and returned on subsequent calls.
175 : */
176 : virtual already_AddRefed<Path> GetOrBuildPath(const DrawTarget& aDrawTarget,
177 : FillRule fillRule);
178 :
179 : /**
180 : * The same as GetOrBuildPath, but bypasses the cache (neither returns any
181 : * previously cached Path, nor caches the Path that in does return).
182 : * this element. May return nullptr if there is no [valid] path.
183 : */
184 : virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) = 0;
185 :
186 : /**
187 : * Returns a Path that can be used to measure the length of this elements
188 : * path, or to find the position at a given distance along it.
189 : *
190 : * This is currently equivalent to calling GetOrBuildPath, but it may not be
191 : * in the future. The reason for this function to be separate from
192 : * GetOrBuildPath is because SVGPathData::BuildPath inserts small lines into
193 : * the path if zero length subpaths are encountered, in order to implement
194 : * the SVG specifications requirements that zero length subpaths should
195 : * render circles/squares if stroke-linecap is round/square, respectively.
196 : * In principle these inserted lines could interfere with path measurement,
197 : * so we keep callers that are looking to do measurement separate in case we
198 : * run into problems with the inserted lines negatively affecting measuring
199 : * for content.
200 : */
201 : virtual already_AddRefed<Path> GetOrBuildPathForMeasuring();
202 :
203 : /**
204 : * Returns the current computed value of the CSS property 'fill-rule' for
205 : * this element.
206 : */
207 : FillRule GetFillRule();
208 :
209 : // WebIDL
210 : already_AddRefed<SVGAnimatedNumber> PathLength();
211 : float GetTotalLength();
212 : already_AddRefed<nsISVGPoint>
213 : GetPointAtLength(float distance, ErrorResult& rv);
214 :
215 : protected:
216 : // nsSVGElement method
217 : virtual NumberAttributesInfo GetNumberInfo() override;
218 :
219 : nsSVGNumber2 mPathLength;
220 : static NumberInfo sNumberInfo;
221 : mutable RefPtr<Path> mCachedPath;
222 : };
223 :
224 : } // namespace dom
225 : } // namespace mozilla
226 :
227 : #endif // mozilla_dom_SVGGeometryElement_h
|