Bug 1610775 [wpt PR 21336] - Update urllib3 to 1.25.8, a=testonly
[gecko.git] / dom / svg / SVGPathSegUtils.h
blob53d05b04441f329b7771381a260b1e5fa0638ce8
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 #ifndef MOZILLA_SVGPATHSEGUTILS_H__
8 #define MOZILLA_SVGPATHSEGUTILS_H__
10 #include "mozilla/ArrayUtils.h"
11 #include "mozilla/dom/SVGPathSegBinding.h"
12 #include "mozilla/gfx/Point.h"
13 #include "nsDebug.h"
15 namespace mozilla {
17 #define NS_SVG_PATH_SEG_MAX_ARGS 7
18 #define NS_SVG_PATH_SEG_FIRST_VALID_TYPE \
19 dom::SVGPathSeg_Binding::PATHSEG_CLOSEPATH
20 #define NS_SVG_PATH_SEG_LAST_VALID_TYPE \
21 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
22 #define NS_SVG_PATH_SEG_TYPE_COUNT (NS_SVG_PATH_SEG_LAST_VALID_TYPE + 1)
24 /**
25 * Code that works with path segments can use an instance of this class to
26 * store/provide information about the start of the current subpath and the
27 * last path segment (if any).
29 struct SVGPathTraversalState {
30 typedef gfx::Point Point;
32 enum TraversalMode { eUpdateAll, eUpdateOnlyStartAndCurrentPos };
34 SVGPathTraversalState()
35 : start(0.0, 0.0),
36 pos(0.0, 0.0),
37 cp1(0.0, 0.0),
38 cp2(0.0, 0.0),
39 length(0.0),
40 mode(eUpdateAll) {}
42 bool ShouldUpdateLengthAndControlPoints() { return mode == eUpdateAll; }
44 Point start; // start point of current sub path (reset each moveto)
46 Point pos; // current position (end point of previous segment)
48 Point cp1; // quadratic control point - if the previous segment was a
49 // quadratic bezier curve then this is set to the absolute
50 // position of its control point, otherwise its set to pos
52 Point cp2; // cubic control point - if the previous segment was a cubic
53 // bezier curve then this is set to the absolute position of
54 // its second control point, otherwise it's set to pos
56 float length; // accumulated path length
58 TraversalMode mode; // indicates what to track while traversing a path
61 /**
62 * This class is just a collection of static methods - it doesn't have any data
63 * members, and it's not possible to create instances of this class. This class
64 * exists purely as a convenient place to gather together a bunch of methods
65 * related to manipulating and answering questions about path segments.
66 * Internally we represent path segments purely as an array of floats. See the
67 * comment documenting SVGPathData for more info on that.
69 * The DOM wrapper classes for encoded path segments (data contained in
70 * instances of SVGPathData) is DOMSVGPathSeg and its sub-classes. Note that
71 * there are multiple different DOM classes for path segs - one for each of the
72 * 19 SVG 1.1 segment types.
74 class SVGPathSegUtils {
75 private:
76 SVGPathSegUtils() = default; // private to prevent instances
78 public:
79 static void GetValueAsString(const float* aSeg, nsAString& aValue);
81 /**
82 * Encode a segment type enum to a float.
84 * At some point in the future we will likely want to encode other
85 * information into the float, such as whether the command was explicit or
86 * not. For now all this method does is save on int to float runtime
87 * conversion by requiring uint32_t and float to be of the same size so we
88 * can simply do a bitwise uint32_t<->float copy.
90 static float EncodeType(uint32_t aType) {
91 static_assert(sizeof(uint32_t) == sizeof(float),
92 "sizeof uint32_t and float must be the same");
93 MOZ_ASSERT(IsValidType(aType), "Seg type not recognized");
94 return *(reinterpret_cast<float*>(&aType));
97 static uint32_t DecodeType(float aType) {
98 static_assert(sizeof(uint32_t) == sizeof(float),
99 "sizeof uint32_t and float must be the same");
100 uint32_t type = *(reinterpret_cast<uint32_t*>(&aType));
101 MOZ_ASSERT(IsValidType(type), "Seg type not recognized");
102 return type;
105 static char16_t GetPathSegTypeAsLetter(uint32_t aType) {
106 MOZ_ASSERT(IsValidType(aType), "Seg type not recognized");
108 static const char16_t table[] = {
109 char16_t('x'), // 0 == PATHSEG_UNKNOWN
110 char16_t('z'), // 1 == PATHSEG_CLOSEPATH
111 char16_t('M'), // 2 == PATHSEG_MOVETO_ABS
112 char16_t('m'), // 3 == PATHSEG_MOVETO_REL
113 char16_t('L'), // 4 == PATHSEG_LINETO_ABS
114 char16_t('l'), // 5 == PATHSEG_LINETO_REL
115 char16_t('C'), // 6 == PATHSEG_CURVETO_CUBIC_ABS
116 char16_t('c'), // 7 == PATHSEG_CURVETO_CUBIC_REL
117 char16_t('Q'), // 8 == PATHSEG_CURVETO_QUADRATIC_ABS
118 char16_t('q'), // 9 == PATHSEG_CURVETO_QUADRATIC_REL
119 char16_t('A'), // 10 == PATHSEG_ARC_ABS
120 char16_t('a'), // 11 == PATHSEG_ARC_REL
121 char16_t('H'), // 12 == PATHSEG_LINETO_HORIZONTAL_ABS
122 char16_t('h'), // 13 == PATHSEG_LINETO_HORIZONTAL_REL
123 char16_t('V'), // 14 == PATHSEG_LINETO_VERTICAL_ABS
124 char16_t('v'), // 15 == PATHSEG_LINETO_VERTICAL_REL
125 char16_t('S'), // 16 == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
126 char16_t('s'), // 17 == PATHSEG_CURVETO_CUBIC_SMOOTH_REL
127 char16_t('T'), // 18 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
128 char16_t('t') // 19 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
130 static_assert(MOZ_ARRAY_LENGTH(table) == NS_SVG_PATH_SEG_TYPE_COUNT,
131 "Unexpected table size");
133 return table[aType];
136 static uint32_t ArgCountForType(uint32_t aType) {
137 MOZ_ASSERT(IsValidType(aType), "Seg type not recognized");
139 static const uint8_t table[] = {
140 0, // 0 == PATHSEG_UNKNOWN
141 0, // 1 == PATHSEG_CLOSEPATH
142 2, // 2 == PATHSEG_MOVETO_ABS
143 2, // 3 == PATHSEG_MOVETO_REL
144 2, // 4 == PATHSEG_LINETO_ABS
145 2, // 5 == PATHSEG_LINETO_REL
146 6, // 6 == PATHSEG_CURVETO_CUBIC_ABS
147 6, // 7 == PATHSEG_CURVETO_CUBIC_REL
148 4, // 8 == PATHSEG_CURVETO_QUADRATIC_ABS
149 4, // 9 == PATHSEG_CURVETO_QUADRATIC_REL
150 7, // 10 == PATHSEG_ARC_ABS
151 7, // 11 == PATHSEG_ARC_REL
152 1, // 12 == PATHSEG_LINETO_HORIZONTAL_ABS
153 1, // 13 == PATHSEG_LINETO_HORIZONTAL_REL
154 1, // 14 == PATHSEG_LINETO_VERTICAL_ABS
155 1, // 15 == PATHSEG_LINETO_VERTICAL_REL
156 4, // 16 == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
157 4, // 17 == PATHSEG_CURVETO_CUBIC_SMOOTH_REL
158 2, // 18 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
159 2 // 19 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
161 static_assert(MOZ_ARRAY_LENGTH(table) == NS_SVG_PATH_SEG_TYPE_COUNT,
162 "Unexpected table size");
164 return table[aType];
168 * Convenience so that callers can pass a float containing an encoded type
169 * and have it decoded implicitly.
171 static uint32_t ArgCountForType(float aType) {
172 return ArgCountForType(DecodeType(aType));
175 static bool IsValidType(uint32_t aType) {
176 return aType >= NS_SVG_PATH_SEG_FIRST_VALID_TYPE &&
177 aType <= NS_SVG_PATH_SEG_LAST_VALID_TYPE;
180 static bool IsCubicType(uint32_t aType) {
181 return aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_REL ||
182 aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_ABS ||
183 aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_REL ||
184 aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
187 static bool IsQuadraticType(uint32_t aType) {
188 return aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_REL ||
189 aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_ABS ||
190 aType ==
191 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL ||
192 aType ==
193 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
196 static bool IsArcType(uint32_t aType) {
197 return aType == dom::SVGPathSeg_Binding::PATHSEG_ARC_ABS ||
198 aType == dom::SVGPathSeg_Binding::PATHSEG_ARC_REL;
201 static bool IsRelativeOrAbsoluteType(uint32_t aType) {
202 MOZ_ASSERT(IsValidType(aType), "Seg type not recognized");
204 // When adding a new path segment type, ensure that the returned condition
205 // below is still correct.
206 static_assert(
207 NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
208 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
209 "Unexpected type");
211 return aType >= dom::SVGPathSeg_Binding::PATHSEG_MOVETO_ABS;
214 static bool IsRelativeType(uint32_t aType) {
215 MOZ_ASSERT(IsRelativeOrAbsoluteType(aType),
216 "IsRelativeType called with segment type that does not come in "
217 "relative and absolute forms");
219 // When adding a new path segment type, ensure that the returned condition
220 // below is still correct.
221 static_assert(
222 NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
223 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
224 "Unexpected type");
226 return aType & 1;
229 static uint32_t RelativeVersionOfType(uint32_t aType) {
230 MOZ_ASSERT(IsRelativeOrAbsoluteType(aType),
231 "RelativeVersionOfType called with segment type that does not "
232 "come in relative and absolute forms");
234 // When adding a new path segment type, ensure that the returned condition
235 // below is still correct.
236 static_assert(
237 NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
238 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
239 "Unexpected type");
241 return aType | 1;
244 static uint32_t SameTypeModuloRelativeness(uint32_t aType1, uint32_t aType2) {
245 if (!IsRelativeOrAbsoluteType(aType1)) {
246 return aType1 == aType2;
249 return RelativeVersionOfType(aType1) == RelativeVersionOfType(aType2);
253 * Traverse the given path segment and update the SVGPathTraversalState
254 * object.
256 static void TraversePathSegment(const float* aData,
257 SVGPathTraversalState& aState);
260 } // namespace mozilla
262 #endif // MOZILLA_SVGPATHSEGUTILS_H__