Bug 1941128 - Turn off network.dns.native_https_query on Mac again
[gecko.git] / dom / svg / SVGContentUtils.h
blobe4d8d6defe9c0d4c5b09259213370bc9b0c14dae
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 DOM_SVG_SVGCONTENTUTILS_H_
8 #define DOM_SVG_SVGCONTENTUTILS_H_
10 // include math.h to pick up definition of M_ maths defines e.g. M_PI
11 #include <math.h>
13 #include "mozilla/gfx/2D.h" // for StrokeOptions
14 #include "mozilla/gfx/Matrix.h"
15 #include "nsError.h"
16 #include "nsStringFwd.h"
17 #include "nsTArray.h"
18 #include "gfx2DGlue.h"
19 #include "nsDependentSubstring.h"
21 class nsIContent;
23 class nsIFrame;
24 class nsPresContext;
26 namespace mozilla {
27 class ComputedStyle;
28 class SVGAnimatedTransformList;
29 class SVGAnimatedPreserveAspectRatio;
30 class SVGContextPaint;
31 class SVGPreserveAspectRatio;
32 union StyleLengthPercentageUnion;
33 namespace dom {
34 class Document;
35 class Element;
36 class SVGElement;
37 class SVGSVGElement;
38 class SVGViewportElement;
39 } // namespace dom
41 #define SVG_ZERO_LENGTH_PATH_FIX_FACTOR 512
43 /**
44 * Functions generally used by SVG Content classes. Functions here
45 * should not generally depend on layout methods/classes e.g. SVGUtils
47 class SVGContentUtils {
48 public:
49 using Float = gfx::Float;
50 using Matrix = gfx::Matrix;
51 using Rect = gfx::Rect;
52 using StrokeOptions = gfx::StrokeOptions;
55 * Get the outer SVG element of an nsIContent
57 static dom::SVGSVGElement* GetOuterSVGElement(dom::SVGElement* aSVGElement);
59 /**
60 * Moz2D's StrokeOptions requires someone else to own its mDashPattern
61 * buffer, which is a pain when you want to initialize a StrokeOptions object
62 * in a helper function and pass it out. This sub-class owns the mDashPattern
63 * buffer so that consumers of such a helper function don't need to worry
64 * about creating it, passing it in, or deleting it. (An added benefit is
65 * that in the typical case when stroke-dasharray is short it will avoid
66 * allocating.)
68 struct AutoStrokeOptions : public StrokeOptions {
69 AutoStrokeOptions() {
70 MOZ_ASSERT(mDashLength == 0, "InitDashPattern() depends on this");
72 ~AutoStrokeOptions() {
73 if (mDashPattern && mDashPattern != mSmallArray) {
74 delete[] mDashPattern;
77 /**
78 * Creates the buffer to store the stroke-dasharray, assuming out-of-memory
79 * does not occur. The buffer's address is assigned to mDashPattern and
80 * returned to the caller as a non-const pointer (so that the caller can
81 * initialize the values in the buffer, since mDashPattern is const).
83 Float* InitDashPattern(size_t aDashCount) {
84 if (aDashCount <= std::size(mSmallArray)) {
85 mDashPattern = mSmallArray;
86 return mSmallArray;
88 Float* nonConstArray = new (fallible) Float[aDashCount];
89 mDashPattern = nonConstArray;
90 return nonConstArray;
92 void DiscardDashPattern() {
93 if (mDashPattern && mDashPattern != mSmallArray) {
94 delete[] mDashPattern;
96 mDashLength = 0;
97 mDashPattern = nullptr;
100 private:
101 // Most dasharrays will fit in this and save us allocating
102 Float mSmallArray[16];
105 enum StrokeOptionFlags { eAllStrokeOptions, eIgnoreStrokeDashing };
107 * Note: the linecap style returned in aStrokeOptions is not valid when
108 * ShapeTypeHasNoCorners(aElement) == true && aFlags == eIgnoreStrokeDashing,
109 * since when aElement has no corners the rendered linecap style depends on
110 * whether or not the stroke is dashed.
112 static void GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
113 dom::SVGElement* aElement,
114 const ComputedStyle* aComputedStyle,
115 const SVGContextPaint* aContextPaint,
116 StrokeOptionFlags aFlags = eAllStrokeOptions);
119 * Returns the current computed value of the CSS property 'stroke-width' for
120 * the given element. aComputedStyle may be provided as an optimization.
121 * aContextPaint is also optional.
123 * Note that this function does NOT take account of the value of the 'stroke'
124 * and 'stroke-opacity' properties to, say, return zero if they are "none" or
125 * "0", respectively.
127 static Float GetStrokeWidth(const dom::SVGElement* aElement,
128 const ComputedStyle* aComputedStyle,
129 const SVGContextPaint* aContextPaint);
132 * Get the number of CSS px (user units) per em (i.e. the em-height in user
133 * units) for an nsIContent
135 * XXX document the conditions under which these may fail, and what they
136 * return in those cases.
138 static float GetFontSize(const dom::Element* aElement);
139 static float GetFontSize(const nsIFrame* aFrame);
140 static float GetFontSize(const ComputedStyle*, nsPresContext*);
142 * Get the number of CSS px (user units) per ex (i.e. the x-height in user
143 * units) for an nsIContent
145 * XXX document the conditions under which these may fail, and what they
146 * return in those cases.
148 static float GetFontXHeight(const dom::Element* aElement);
149 static float GetFontXHeight(const nsIFrame* aFrame);
150 static float GetFontXHeight(const ComputedStyle*, nsPresContext*);
153 * Get the number of CSS px (user units) per lh (i.e. the line-height in
154 * user units) for an nsIContent.
156 * Requires the element be styled - if not, a default value assuming
157 * the font-size of 16px and line-height of 1.2 is returned.
159 static float GetLineHeight(const dom::Element* aElement);
162 * Report a localized error message to the error console.
164 static nsresult ReportToConsole(const dom::Document* doc,
165 const char* aWarning,
166 const nsTArray<nsString>& aParams);
168 static Matrix GetCTM(dom::SVGElement* aElement);
170 static Matrix GetNonScalingStrokeCTM(dom::SVGElement* aElement);
172 static Matrix GetScreenCTM(dom::SVGElement* aElement);
175 * Gets the tight bounds-space stroke bounds of the non-scaling-stroked rect
176 * aRect.
177 * @param aToBoundsSpace transforms from source space to the space aBounds
178 * should be computed in. Must be rectilinear.
179 * @param aToNonScalingStrokeSpace transforms from source
180 * space to the space in which non-scaling stroke should be applied.
181 * Must be rectilinear.
183 static void RectilinearGetStrokeBounds(const Rect& aRect,
184 const Matrix& aToBoundsSpace,
185 const Matrix& aToNonScalingStrokeSpace,
186 float aStrokeWidth, Rect* aBounds);
189 * Check if this is one of the SVG elements that SVG 1.1 Full says
190 * establishes a viewport: svg, symbol, image or foreignObject.
192 static bool EstablishesViewport(const nsIContent* aContent);
194 static dom::SVGViewportElement* GetNearestViewportElement(
195 const nsIContent* aContent);
197 /* enum for specifying coordinate direction for ObjectSpace/UserSpace */
198 enum ctxDirection { X, Y, XY };
201 * Computes sqrt((aWidth^2 + aHeight^2)/2);
203 static double ComputeNormalizedHypotenuse(double aWidth, double aHeight);
205 /* Returns the angle halfway between the two specified angles */
206 static float AngleBisect(float a1, float a2);
208 /* Generate a viewbox to viewport transformation matrix */
210 static Matrix GetViewBoxTransform(
211 float aViewportWidth, float aViewportHeight, float aViewboxX,
212 float aViewboxY, float aViewboxWidth, float aViewboxHeight,
213 const SVGAnimatedPreserveAspectRatio& aPreserveAspectRatio);
215 static Matrix GetViewBoxTransform(
216 float aViewportWidth, float aViewportHeight, float aViewboxX,
217 float aViewboxY, float aViewboxWidth, float aViewboxHeight,
218 const SVGPreserveAspectRatio& aPreserveAspectRatio);
221 * Parses the sign (+ or -) of a number and moves aIter to the next
222 * character if a sign is found.
223 * @param aSignMultiplier [outparam] -1 if the sign is negative otherwise 1
224 * @return false if we hit the end of the string (i.e. if aIter is initially
225 * at aEnd, or if we reach aEnd right after the sign character).
227 static inline bool ParseOptionalSign(nsAString::const_iterator& aIter,
228 const nsAString::const_iterator& aEnd,
229 int32_t& aSignMultiplier) {
230 if (aIter == aEnd) {
231 return false;
233 aSignMultiplier = *aIter == '-' ? -1 : 1;
235 nsAString::const_iterator iter(aIter);
237 if (*iter == '-' || *iter == '+') {
238 ++iter;
239 if (iter == aEnd) {
240 return false;
243 aIter = iter;
244 return true;
248 * Parse a number of the form:
249 * number ::= integer ([Ee] integer)? | [+-]? [0-9]* "." [0-9]+ ([Ee]
250 * integer)? Parsing fails if the number cannot be represented by a floatType.
251 * If parsing succeeds, aIter is updated so that it points to the character
252 * after the end of the number, otherwise it is left unchanged
254 template <class floatType>
255 static bool ParseNumber(nsAString::const_iterator& aIter,
256 const nsAString::const_iterator& aEnd,
257 floatType& aValue);
260 * Parse a number of the form:
261 * number ::= integer ([Ee] integer)? | [+-]? [0-9]* "." [0-9]+ ([Ee]
262 * integer)? Parsing fails if there is anything left over after the number, or
263 * the number cannot be represented by a floatType.
265 template <class floatType>
266 static bool ParseNumber(const nsAString& aString, floatType& aValue);
269 * Parse an integer of the form:
270 * integer ::= [+-]? [0-9]+
271 * The returned number is clamped to an int32_t if outside that range.
272 * If parsing succeeds, aIter is updated so that it points to the character
273 * after the end of the number, otherwise it is left unchanged
275 static bool ParseInteger(nsAString::const_iterator& aIter,
276 const nsAString::const_iterator& aEnd,
277 int32_t& aValue);
280 * Parse an integer of the form:
281 * integer ::= [+-]? [0-9]+
282 * The returned number is clamped to an int32_t if outside that range.
283 * Parsing fails if there is anything left over after the number.
285 static bool ParseInteger(const nsAString& aString, int32_t& aValue);
287 // XXX This should rather use LengthPercentage instead of
288 // StyleLengthPercentageUnion, but that's a type alias defined in
289 // ServoStyleConsts.h, and we don't want to avoid including that large header
290 // with all its dependencies. If a forwarding header were generated by
291 // cbindgen, we could include that.
292 // https://github.com/eqrion/cbindgen/issues/617 addresses this.
294 * Converts a LengthPercentage into a userspace value, resolving percentage
295 * values relative to aContent's SVG viewport.
297 static float CoordToFloat(const dom::SVGElement* aContent,
298 const StyleLengthPercentageUnion&,
299 uint8_t aCtxType = SVGContentUtils::XY);
301 * Parse the SVG path string
302 * Returns a path
303 * string formatted as an SVG path
305 static already_AddRefed<gfx::Path> GetPath(const nsACString& aPathString);
308 * Returns true if aContent is one of the elements whose stroke is guaranteed
309 * to have no corners: circle or ellipse
311 static bool ShapeTypeHasNoCorners(const nsIContent* aContent);
314 * Return one token in aString, aString may have leading and trailing
315 * whitespace; aSuccess will be set to false if there is no token or more than
316 * one token, otherwise it's set to true.
318 static nsDependentSubstring GetAndEnsureOneToken(const nsAString& aString,
319 bool& aSuccess);
322 } // namespace mozilla
324 #endif // DOM_SVG_SVGCONTENTUTILS_H_