/work/obj-fuzz/dist/include/nsSVGUtils.h
Line | Count | Source (jump to first uncovered line) |
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 NS_SVGUTILS_H |
8 | | #define NS_SVGUTILS_H |
9 | | |
10 | | // include math.h to pick up definition of M_ maths defines e.g. M_PI |
11 | | #include <math.h> |
12 | | |
13 | | #include "DrawMode.h" |
14 | | #include "ImgDrawResult.h" |
15 | | #include "gfx2DGlue.h" |
16 | | #include "gfxMatrix.h" |
17 | | #include "gfxPoint.h" |
18 | | #include "gfxRect.h" |
19 | | #include "mozilla/gfx/Rect.h" |
20 | | #include "nsAlgorithm.h" |
21 | | #include "nsChangeHint.h" |
22 | | #include "nsColor.h" |
23 | | #include "nsCOMPtr.h" |
24 | | #include "nsID.h" |
25 | | #include "nsIFrame.h" |
26 | | #include "nsISupportsBase.h" |
27 | | #include "nsMathUtils.h" |
28 | | #include "nsStyleStruct.h" |
29 | | #include <algorithm> |
30 | | |
31 | | class gfxContext; |
32 | | class nsFrameList; |
33 | | class nsIContent; |
34 | | class nsIDocument; |
35 | | class nsIFrame; |
36 | | class nsPresContext; |
37 | | class nsStyleSVGPaint; |
38 | | class nsSVGDisplayContainerFrame; |
39 | | class nsSVGElement; |
40 | | class nsSVGEnum; |
41 | | class nsSVGLength2; |
42 | | class nsSVGOuterSVGFrame; |
43 | | class nsTextFrame; |
44 | | |
45 | | struct nsStyleSVG; |
46 | | struct nsRect; |
47 | | |
48 | | namespace mozilla { |
49 | | class SVGContextPaint; |
50 | | struct SVGContextPaintImpl; |
51 | | class SVGGeometryFrame; |
52 | | namespace dom { |
53 | | class Element; |
54 | | class UserSpaceMetrics; |
55 | | } // namespace dom |
56 | | namespace gfx { |
57 | | class DrawTarget; |
58 | | class GeneralPattern; |
59 | | } // namespace gfx |
60 | | } // namespace mozilla |
61 | | |
62 | | // maximum dimension of an offscreen surface - choose so that |
63 | | // the surface size doesn't overflow a 32-bit signed int using |
64 | | // 4 bytes per pixel; in line with Factory::CheckSurfaceSize |
65 | | // In fact Macs can't even manage that |
66 | | #define NS_SVG_OFFSCREEN_MAX_DIMENSION 4096 |
67 | | |
68 | | #define SVG_HIT_TEST_FILL 0x01 |
69 | | #define SVG_HIT_TEST_STROKE 0x02 |
70 | | #define SVG_HIT_TEST_CHECK_MRECT 0x04 |
71 | | |
72 | | |
73 | | bool NS_SVGDisplayListHitTestingEnabled(); |
74 | | bool NS_SVGDisplayListPaintingEnabled(); |
75 | | bool NS_SVGNewGetBBoxEnabled(); |
76 | | |
77 | | /** |
78 | | * Sometimes we need to distinguish between an empty box and a box |
79 | | * that contains an element that has no size e.g. a point at the origin. |
80 | | */ |
81 | | class SVGBBox { |
82 | | typedef mozilla::gfx::Rect Rect; |
83 | | |
84 | | public: |
85 | | SVGBBox() |
86 | | : mIsEmpty(true) {} |
87 | | |
88 | | MOZ_IMPLICIT SVGBBox(const Rect& aRect) |
89 | | : mBBox(aRect), mIsEmpty(false) {} |
90 | | |
91 | | MOZ_IMPLICIT SVGBBox(const gfxRect& aRect) |
92 | | : mBBox(ToRect(aRect)), mIsEmpty(false) {} |
93 | | |
94 | | operator const Rect& () { |
95 | | return mBBox; |
96 | | } |
97 | | |
98 | | gfxRect ToThebesRect() const { |
99 | | return ThebesRect(mBBox); |
100 | | } |
101 | | |
102 | | bool IsEmpty() const { |
103 | | return mIsEmpty; |
104 | | } |
105 | | |
106 | 0 | bool IsFinite() const { |
107 | 0 | return mBBox.IsFinite(); |
108 | 0 | } |
109 | | |
110 | | void Scale(float aScale) { |
111 | | mBBox.Scale(aScale); |
112 | | } |
113 | | |
114 | | void UnionEdges(const SVGBBox& aSVGBBox) { |
115 | | if (aSVGBBox.mIsEmpty) { |
116 | | return; |
117 | | } |
118 | | mBBox = mIsEmpty ? aSVGBBox.mBBox : mBBox.UnionEdges(aSVGBBox.mBBox); |
119 | | mIsEmpty = false; |
120 | | } |
121 | | |
122 | | void Intersect(const SVGBBox& aSVGBBox) { |
123 | | if (!mIsEmpty && !aSVGBBox.mIsEmpty) { |
124 | | mBBox = mBBox.Intersect(aSVGBBox.mBBox); |
125 | | if (mBBox.IsEmpty()) { |
126 | | mIsEmpty = true; |
127 | | mBBox = Rect(0, 0, 0, 0); |
128 | | } |
129 | | } else { |
130 | | mIsEmpty = true; |
131 | | mBBox = Rect(0, 0, 0, 0); |
132 | | } |
133 | | } |
134 | | |
135 | | private: |
136 | | Rect mBBox; |
137 | | bool mIsEmpty; |
138 | | }; |
139 | | |
140 | | // GRRR WINDOWS HATE HATE HATE |
141 | | #undef CLIP_MASK |
142 | | |
143 | | class MOZ_RAII SVGAutoRenderState |
144 | | { |
145 | | typedef mozilla::gfx::DrawTarget DrawTarget; |
146 | | |
147 | | public: |
148 | | explicit SVGAutoRenderState(DrawTarget* aDrawTarget |
149 | | MOZ_GUARD_OBJECT_NOTIFIER_PARAM); |
150 | | ~SVGAutoRenderState(); |
151 | | |
152 | | void SetPaintingToWindow(bool aPaintingToWindow); |
153 | | |
154 | | static bool IsPaintingToWindow(DrawTarget* aDrawTarget); |
155 | | |
156 | | private: |
157 | | DrawTarget* mDrawTarget; |
158 | | void* mOriginalRenderState; |
159 | | bool mPaintingToWindow; |
160 | | MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
161 | | }; |
162 | | |
163 | | |
164 | | /** |
165 | | * General functions used by all of SVG layout and possibly content code. |
166 | | * If a method is used by content and depends only on other content methods |
167 | | * it should go in SVGContentUtils instead. |
168 | | */ |
169 | | class nsSVGUtils |
170 | | { |
171 | | public: |
172 | | typedef mozilla::dom::Element Element; |
173 | | typedef mozilla::gfx::AntialiasMode AntialiasMode; |
174 | | typedef mozilla::gfx::DrawTarget DrawTarget; |
175 | | typedef mozilla::gfx::FillRule FillRule; |
176 | | typedef mozilla::gfx::GeneralPattern GeneralPattern; |
177 | | typedef mozilla::gfx::Size Size; |
178 | | typedef mozilla::SVGContextPaint SVGContextPaint; |
179 | | typedef mozilla::SVGContextPaintImpl SVGContextPaintImpl; |
180 | | typedef mozilla::SVGGeometryFrame SVGGeometryFrame; |
181 | | typedef mozilla::image::imgDrawingParams imgDrawingParams; |
182 | | |
183 | | static void Init(); |
184 | | |
185 | | NS_DECLARE_FRAME_PROPERTY_DELETABLE(ObjectBoundingBoxProperty, gfxRect) |
186 | | |
187 | | /** |
188 | | * Returns the frame's post-filter visual overflow rect when passed the |
189 | | * frame's pre-filter visual overflow rect. If the frame is not currently |
190 | | * being filtered, this function simply returns aUnfilteredRect. |
191 | | */ |
192 | | static nsRect GetPostFilterVisualOverflowRect(nsIFrame *aFrame, |
193 | | const nsRect &aUnfilteredRect); |
194 | | |
195 | | /** |
196 | | * Schedules an update of the frame's bounds (which will in turn invalidate |
197 | | * the new area that the frame should paint to). |
198 | | * |
199 | | * This does nothing when passed an NS_FRAME_IS_NONDISPLAY frame. |
200 | | * In future we may want to allow ReflowSVG to be called on such frames, |
201 | | * but that would be better implemented as a ForceReflowSVG function to |
202 | | * be called synchronously while painting them without marking or paying |
203 | | * attention to dirty bits like this function. |
204 | | * |
205 | | * This is very similar to PresShell::FrameNeedsReflow. The main reason that |
206 | | * we have this function instead of using FrameNeedsReflow is because we need |
207 | | * to be able to call it under nsSVGOuterSVGFrame::NotifyViewportChange when |
208 | | * that function is called by nsSVGOuterSVGFrame::Reflow. FrameNeedsReflow |
209 | | * is not suitable for calling during reflow though, and it asserts as much. |
210 | | * The reason that we want to be callable under NotifyViewportChange is |
211 | | * because we want to synchronously notify and dirty the nsSVGOuterSVGFrame's |
212 | | * children so that when nsSVGOuterSVGFrame::DidReflow is called its children |
213 | | * will be updated for the new size as appropriate. Otherwise we'd have to |
214 | | * post an event to the event loop to mark dirty flags and request an update. |
215 | | * |
216 | | * Another reason that we don't currently want to call |
217 | | * PresShell::FrameNeedsReflow is because passing eRestyle to it to get it to |
218 | | * mark descendants dirty would cause it to descend through |
219 | | * nsSVGForeignObjectFrame frames to mark their children dirty, but we want to |
220 | | * handle nsSVGForeignObjectFrame specially. It would also do unnecessary work |
221 | | * descending into NS_FRAME_IS_NONDISPLAY frames. |
222 | | */ |
223 | | static void ScheduleReflowSVG(nsIFrame *aFrame); |
224 | | |
225 | | /** |
226 | | * Returns true if the frame or any of its children need ReflowSVG |
227 | | * to be called on them. |
228 | | */ |
229 | | static bool NeedsReflowSVG(nsIFrame *aFrame); |
230 | | |
231 | | /* |
232 | | * Update the filter invalidation region for ancestor frames, if relevant. |
233 | | */ |
234 | | static void NotifyAncestorsOfFilterRegionChange(nsIFrame *aFrame); |
235 | | |
236 | | /** |
237 | | * Percentage lengths in SVG are resolved against the width/height of the |
238 | | * nearest viewport (or its viewBox, if set). This helper returns the size |
239 | | * of this "context" for the given frame so that percentage values can be |
240 | | * resolved. |
241 | | */ |
242 | | static Size GetContextSize(const nsIFrame* aFrame); |
243 | | |
244 | | /* Computes the input length in terms of object space coordinates. |
245 | | Input: rect - bounding box |
246 | | length - length to be converted |
247 | | */ |
248 | | static float ObjectSpace(const gfxRect &aRect, const nsSVGLength2 *aLength); |
249 | | |
250 | | /* Computes the input length in terms of user space coordinates. |
251 | | Input: content - object to be used for determining user space |
252 | | Input: length - length to be converted |
253 | | */ |
254 | | static float UserSpace(nsSVGElement *aSVGElement, |
255 | | const nsSVGLength2 *aLength); |
256 | | static float UserSpace(nsIFrame *aFrame, const nsSVGLength2 *aLength); |
257 | | static float UserSpace(const mozilla::dom::UserSpaceMetrics& aMetrics, |
258 | | const nsSVGLength2 *aLength); |
259 | | |
260 | | /* Find the outermost SVG frame of the passed frame */ |
261 | | static nsSVGOuterSVGFrame* GetOuterSVGFrame(nsIFrame *aFrame); |
262 | | |
263 | | /** |
264 | | * Get the covered region for a frame. Return null if it's not an SVG frame. |
265 | | * @param aRect gets a rectangle in app units |
266 | | * @return the outer SVG frame which aRect is relative to |
267 | | */ |
268 | | static nsIFrame* GetOuterSVGFrameAndCoveredRegion(nsIFrame* aFrame, |
269 | | nsRect* aRect); |
270 | | |
271 | | /* Paint SVG frame with SVG effects - aDirtyRect is the area being |
272 | | * redrawn, in device pixel coordinates relative to the outer svg */ |
273 | | static void PaintFrameWithEffects(nsIFrame *aFrame, |
274 | | gfxContext& aContext, |
275 | | const gfxMatrix& aTransform, |
276 | | imgDrawingParams& aImgParams, |
277 | | const nsIntRect *aDirtyRect = nullptr); |
278 | | |
279 | | /* Hit testing - check if point hits the clipPath of indicated |
280 | | * frame. Returns true if no clipPath set. */ |
281 | | static bool HitTestClip(nsIFrame *aFrame, const gfxPoint &aPoint); |
282 | | |
283 | | /** |
284 | | * Hit testing - check if point hits any children of aFrame. aPoint is |
285 | | * expected to be in the coordinate space established by aFrame for its |
286 | | * children (e.g. the space established by the 'viewBox' attribute on <svg>). |
287 | | */ |
288 | | static nsIFrame* HitTestChildren(nsSVGDisplayContainerFrame *aFrame, |
289 | | const gfxPoint &aPoint); |
290 | | |
291 | | /* |
292 | | * Returns the CanvasTM of the indicated frame, whether it's a |
293 | | * child SVG frame, container SVG frame, or a regular frame. |
294 | | * For regular frames, we just return an identity matrix. |
295 | | */ |
296 | | static gfxMatrix GetCanvasTM(nsIFrame* aFrame); |
297 | | |
298 | | /** |
299 | | * Returns the transform from aFrame's user space to canvas space. Only call |
300 | | * with SVG frames. This is like GetCanvasTM, except that it only includes |
301 | | * the transforms from aFrame's user space (i.e. the coordinate context |
302 | | * established by its 'transform' attribute, or else the coordinate context |
303 | | * that its _parent_ establishes for its children) to outer-<svg> device |
304 | | * space. Specifically, it does not include any other transforms introduced |
305 | | * by the frame such as x/y offsets and viewBox attributes. |
306 | | */ |
307 | | static gfxMatrix GetUserToCanvasTM(nsIFrame* aFrame); |
308 | | |
309 | | /** |
310 | | * Notify the descendants of aFrame of a change to one of their ancestors |
311 | | * that might affect them. |
312 | | */ |
313 | | static void NotifyChildrenOfSVGChange(nsIFrame *aFrame, uint32_t aFlags); |
314 | | |
315 | | static nsRect TransformFrameRectToOuterSVG(const nsRect& aRect, |
316 | | const gfxMatrix& aMatrix, |
317 | | nsPresContext* aPresContext); |
318 | | |
319 | | /* |
320 | | * Convert a surface size to an integer for use by thebes |
321 | | * possibly making it smaller in the process so the surface does not |
322 | | * use excessive memory. |
323 | | * |
324 | | * @param aSize the desired surface size |
325 | | * @param aResultOverflows true if the desired surface size is too big |
326 | | * @return the surface size to use |
327 | | */ |
328 | | static mozilla::gfx::IntSize ConvertToSurfaceSize(const gfxSize& aSize, |
329 | | bool *aResultOverflows); |
330 | | |
331 | | /* |
332 | | * Hit test a given rectangle/matrix. |
333 | | */ |
334 | | static bool HitTestRect(const mozilla::gfx::Matrix &aMatrix, |
335 | | float aRX, float aRY, float aRWidth, float aRHeight, |
336 | | float aX, float aY); |
337 | | |
338 | | |
339 | | /** |
340 | | * Get the clip rect for the given frame, taking into account the CSS 'clip' |
341 | | * property. See: |
342 | | * http://www.w3.org/TR/SVG11/masking.html#OverflowAndClipProperties |
343 | | * The arguments for aX, aY, aWidth and aHeight should be the dimensions of |
344 | | * the viewport established by aFrame. |
345 | | */ |
346 | | static gfxRect GetClipRectForFrame(nsIFrame *aFrame, |
347 | | float aX, float aY, float aWidth, |
348 | | float aHeight); |
349 | | |
350 | | static void SetClipRect(gfxContext *aContext, |
351 | | const gfxMatrix &aCTM, |
352 | | const gfxRect &aRect); |
353 | | |
354 | | /* Using group opacity instead of fill or stroke opacity on a |
355 | | * geometry object seems to be a common authoring mistake. If we're |
356 | | * not applying filters and not both stroking and filling, we can |
357 | | * generate the same result without going through the overhead of a |
358 | | * push/pop group. */ |
359 | | static bool CanOptimizeOpacity(nsIFrame *aFrame); |
360 | | |
361 | | /** |
362 | | * Take the CTM to userspace for an element, and adjust it to a CTM to its |
363 | | * object bounding box space if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX. |
364 | | * (I.e. so that [0,0] is at the top left of its bbox, and [1,1] is at the |
365 | | * bottom right of its bbox). |
366 | | * |
367 | | * If the bbox is empty, this will return a singular matrix. |
368 | | * |
369 | | * @param aFlags One or more of the BBoxFlags values defined below. |
370 | | */ |
371 | | static gfxMatrix AdjustMatrixForUnits(const gfxMatrix &aMatrix, |
372 | | nsSVGEnum *aUnits, |
373 | | nsIFrame *aFrame, |
374 | | uint32_t aFlags); |
375 | | |
376 | | enum BBoxFlags { |
377 | | eBBoxIncludeFill = 1 << 0, |
378 | | // Include the geometry of the fill even when the fill does not |
379 | | // actually render (e.g. when fill="none" or fill-opacity="0") |
380 | | eBBoxIncludeFillGeometry = 1 << 1, |
381 | | eBBoxIncludeStroke = 1 << 2, |
382 | | // Include the geometry of the stroke even when the stroke does not |
383 | | // actually render (e.g. when stroke="none" or stroke-opacity="0") |
384 | | eBBoxIncludeStrokeGeometry = 1 << 3, |
385 | | eBBoxIncludeMarkers = 1 << 4, |
386 | | eBBoxIncludeClipped = 1 << 5, |
387 | | // Normally a getBBox call on outer-<svg> should only return the |
388 | | // bounds of the elements children. This flag will cause the |
389 | | // element's bounds to be returned instead. |
390 | | eUseFrameBoundsForOuterSVG = 1 << 6, |
391 | | // https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect |
392 | | eForGetClientRects = 1 << 7, |
393 | | // If the given frame is an HTML element, only include the region of the |
394 | | // given frame, instead of all continuations of it, while computing bbox if |
395 | | // this flag is set. |
396 | | eIncludeOnlyCurrentFrameForNonSVGElement = 1 << 8, |
397 | | // This flag is only has an effect when the target is a <use> element. |
398 | | // getBBox returns the bounds of the elements children in user space if |
399 | | // this flag is set; Otherwise, getBBox returns the union bounds in |
400 | | // the coordinate system formed by the <use> element. |
401 | | eUseUserSpaceOfUseElement = 1 << 9, |
402 | | // For a frame with a clip-path, if this flag is set then the result |
403 | | // will not be clipped to the bbox of the content inside the clip-path. |
404 | | eDoNotClipToBBoxOfContentInsideClipPath = 1 << 10, |
405 | | }; |
406 | | /** |
407 | | * This function in primarily for implementing the SVG DOM function getBBox() |
408 | | * and the SVG attribute value 'objectBoundingBox'. However, it has been |
409 | | * extended with various extra parameters in order to become more of a |
410 | | * general purpose getter of all sorts of bounds that we might need to obtain |
411 | | * for SVG elements, or even for other elements that have SVG effects applied |
412 | | * to them. |
413 | | * |
414 | | * @param aFrame The frame of the element for which the bounds are to be |
415 | | * obtained. |
416 | | * @param aFlags One or more of the BBoxFlags values defined above. |
417 | | * @param aToBoundsSpace If not specified the returned rect is in aFrame's |
418 | | * element's "user space". A matrix can optionally be pass to specify a |
419 | | * transform from aFrame's user space to the bounds space of interest |
420 | | * (typically this will be the ancestor nsSVGOuterSVGFrame, but it could be |
421 | | * to any other coordinate space). |
422 | | */ |
423 | | static gfxRect GetBBox(nsIFrame *aFrame, |
424 | | // If the default arg changes, update the handling for |
425 | | // ObjectBoundingBoxProperty() in the implementation. |
426 | | uint32_t aFlags = eBBoxIncludeFillGeometry, |
427 | | const gfxMatrix* aToBoundsSpace = nullptr); |
428 | | |
429 | | /* |
430 | | * "User space" is the space that the frame's BBox (as calculated by |
431 | | * nsSVGUtils::GetBBox) is in. "Frame space" is the space that has its origin |
432 | | * at the top left of the union of the frame's border-box rects over all |
433 | | * continuations. |
434 | | * This function returns the offset one needs to add to something in frame |
435 | | * space in order to get its coordinates in user space. |
436 | | */ |
437 | | static gfxPoint FrameSpaceInCSSPxToUserSpaceOffset(nsIFrame *aFrame); |
438 | | |
439 | | /** |
440 | | * Convert a userSpaceOnUse/objectBoundingBoxUnits rectangle that's specified |
441 | | * using four nsSVGLength2 values into a user unit rectangle in user space. |
442 | | * |
443 | | * @param aXYWH pointer to 4 consecutive nsSVGLength2 objects containing |
444 | | * the x, y, width and height values in that order |
445 | | * @param aBBox the bounding box of the object the rect is relative to; |
446 | | * may be null if aUnits is not SVG_UNIT_TYPE_OBJECTBOUNDINGBOX |
447 | | * @param aFrame the object in which to interpret user-space units; |
448 | | * may be null if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX |
449 | | */ |
450 | | static gfxRect GetRelativeRect(uint16_t aUnits, const nsSVGLength2 *aXYWH, |
451 | | const gfxRect& aBBox, nsIFrame *aFrame); |
452 | | |
453 | | static gfxRect GetRelativeRect(uint16_t aUnits, const nsSVGLength2 *aXYWH, |
454 | | const gfxRect& aBBox, |
455 | | const mozilla::dom::UserSpaceMetrics& aMetrics); |
456 | | |
457 | | /** |
458 | | * Find the first frame, starting with aStartFrame and going up its |
459 | | * parent chain, that is not an svgAFrame. |
460 | | */ |
461 | | static nsIFrame* GetFirstNonAAncestorFrame(nsIFrame* aStartFrame); |
462 | | |
463 | | static bool OuterSVGIsCallingReflowSVG(nsIFrame *aFrame); |
464 | | static bool AnyOuterSVGIsCallingReflowSVG(nsIFrame *aFrame); |
465 | | |
466 | | /** |
467 | | * See https://svgwg.org/svg2-draft/painting.html#NonScalingStroke |
468 | | * |
469 | | * If the computed value of the 'vector-effect' property on aFrame is |
470 | | * 'non-scaling-stroke', then this function will set aUserToOuterSVG to the |
471 | | * transform from aFrame's SVG user space to the initial coordinate system |
472 | | * established by the viewport of aFrame's outer-<svg>'s (the coordinate |
473 | | * system in which the stroke is fixed). If aUserToOuterSVG is set to a |
474 | | * non-identity matrix this function returns true, else it returns false. |
475 | | */ |
476 | | static bool GetNonScalingStrokeTransform(nsIFrame *aFrame, |
477 | | gfxMatrix* aUserToOuterSVG); |
478 | | |
479 | | /** |
480 | | * Compute the maximum possible device space stroke extents of a path given |
481 | | * the path's device space path extents, its stroke style and its ctm. |
482 | | * |
483 | | * This is a workaround for the lack of suitable cairo API for getting the |
484 | | * tight device space stroke extents of a path. This basically gives us the |
485 | | * tightest extents that we can guarantee fully enclose the inked stroke |
486 | | * without doing the calculations for the actual tight extents. We exploit |
487 | | * the fact that cairo does have an API for getting the tight device space |
488 | | * fill/path extents. |
489 | | * |
490 | | * This should die once bug 478152 is fixed. |
491 | | */ |
492 | | static gfxRect PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents, |
493 | | nsTextFrame* aFrame, |
494 | | const gfxMatrix& aMatrix); |
495 | | static gfxRect PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents, |
496 | | SVGGeometryFrame* aFrame, |
497 | | const gfxMatrix& aMatrix); |
498 | | |
499 | | /** |
500 | | * Convert a floating-point value to a 32-bit integer value, clamping to |
501 | | * the range of valid integers. |
502 | | */ |
503 | | static int32_t ClampToInt(double aVal) |
504 | | { |
505 | | return NS_lround(std::max(double(INT32_MIN), |
506 | | std::min(double(INT32_MAX), aVal))); |
507 | | } |
508 | | |
509 | | static nscolor GetFallbackOrPaintColor(mozilla::ComputedStyle *aComputedStyle, |
510 | | nsStyleSVGPaint nsStyleSVG::*aFillOrStroke); |
511 | | |
512 | | static void |
513 | | MakeFillPatternFor(nsIFrame *aFrame, |
514 | | gfxContext* aContext, |
515 | | GeneralPattern* aOutPattern, |
516 | | imgDrawingParams& aImgParams, |
517 | | SVGContextPaint* aContextPaint = nullptr); |
518 | | |
519 | | static void |
520 | | MakeStrokePatternFor(nsIFrame* aFrame, |
521 | | gfxContext* aContext, |
522 | | GeneralPattern* aOutPattern, |
523 | | imgDrawingParams& aImgParams, |
524 | | SVGContextPaint* aContextPaint = nullptr); |
525 | | |
526 | | static float GetOpacity(nsStyleSVGOpacitySource aOpacityType, |
527 | | const float& aOpacity, |
528 | | SVGContextPaint* aContextPaint); |
529 | | |
530 | | /* |
531 | | * @return false if there is no stroke |
532 | | */ |
533 | | static bool HasStroke(nsIFrame* aFrame, |
534 | | SVGContextPaint* aContextPaint = nullptr); |
535 | | |
536 | | static float GetStrokeWidth(nsIFrame* aFrame, |
537 | | SVGContextPaint* aContextPaint = nullptr); |
538 | | |
539 | | /* |
540 | | * Set up a context for a stroked path (including any dashing that applies). |
541 | | */ |
542 | | static void SetupStrokeGeometry(nsIFrame* aFrame, gfxContext *aContext, |
543 | | SVGContextPaint* aContextPaint = nullptr); |
544 | | |
545 | | /** |
546 | | * This function returns a set of bit flags indicating which parts of the |
547 | | * element (fill, stroke, bounds) should intercept pointer events. It takes |
548 | | * into account the type of element and the value of the 'pointer-events' |
549 | | * property on the element. |
550 | | */ |
551 | | static uint16_t GetGeometryHitTestFlags(nsIFrame* aFrame); |
552 | | |
553 | | static FillRule ToFillRule(mozilla::StyleFillRule aFillRule) { |
554 | | return aFillRule == mozilla::StyleFillRule::Evenodd ? |
555 | | FillRule::FILL_EVEN_ODD : FillRule::FILL_WINDING; |
556 | | } |
557 | | |
558 | | static AntialiasMode ToAntialiasMode(uint8_t aTextRendering) { |
559 | | return aTextRendering == NS_STYLE_TEXT_RENDERING_OPTIMIZESPEED ? |
560 | | AntialiasMode::NONE : AntialiasMode::SUBPIXEL; |
561 | | } |
562 | | |
563 | | /** |
564 | | * Render a SVG glyph. |
565 | | * @param aElement the SVG glyph element to render |
566 | | * @param aContext the thebes aContext to draw to |
567 | | * @return true if rendering succeeded |
568 | | */ |
569 | | static void PaintSVGGlyph(Element* aElement, gfxContext* aContext); |
570 | | |
571 | | /** |
572 | | * Get the extents of a SVG glyph. |
573 | | * @param aElement the SVG glyph element |
574 | | * @param aSVGToAppSpace the matrix mapping the SVG glyph space to the |
575 | | * target context space |
576 | | * @param aResult the result (valid when true is returned) |
577 | | * @return true if calculating the extents succeeded |
578 | | */ |
579 | | static bool GetSVGGlyphExtents(Element* aElement, |
580 | | const gfxMatrix& aSVGToAppSpace, |
581 | | gfxRect* aResult); |
582 | | |
583 | | /** |
584 | | * Returns the app unit canvas bounds of a userspace rect. |
585 | | * |
586 | | * @param aToCanvas Transform from userspace to canvas device space. |
587 | | */ |
588 | | static nsRect ToCanvasBounds(const gfxRect &aUserspaceRect, |
589 | | const gfxMatrix &aToCanvas, |
590 | | const nsPresContext *presContext); |
591 | | |
592 | | struct MaskUsage { |
593 | | bool shouldGenerateMaskLayer; |
594 | | bool shouldGenerateClipMaskLayer; |
595 | | bool shouldApplyClipPath; |
596 | | bool shouldApplyBasicShapeOrPath; |
597 | | float opacity; |
598 | | |
599 | | MaskUsage() |
600 | | : shouldGenerateMaskLayer(false) |
601 | | , shouldGenerateClipMaskLayer(false) |
602 | | , shouldApplyClipPath(false) |
603 | | , shouldApplyBasicShapeOrPath(false) |
604 | | , opacity(0.0) |
605 | | { } |
606 | | |
607 | | bool shouldDoSomething() { |
608 | | return shouldGenerateMaskLayer |
609 | | || shouldGenerateClipMaskLayer |
610 | | || shouldApplyClipPath |
611 | | || shouldApplyBasicShapeOrPath |
612 | | || opacity != 1.0; |
613 | | } |
614 | | }; |
615 | | |
616 | | static void DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity, |
617 | | MaskUsage& aUsage); |
618 | | |
619 | | static float ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity); |
620 | | |
621 | | /** |
622 | | * SVG frames expect to paint in SVG user units, which are equal to CSS px |
623 | | * units. This method provides a transform matrix to multiply onto a |
624 | | * gfxContext's current transform to convert the context's current units from |
625 | | * its usual dev pixels to SVG user units/CSS px to keep the SVG code happy. |
626 | | */ |
627 | | static gfxMatrix GetCSSPxToDevPxMatrix(nsIFrame* aNonSVGFrame); |
628 | | |
629 | 0 | static bool IsInSVGTextSubtree(const nsIFrame* aFrame) { |
630 | 0 | // Returns true if the frame is an SVGTextFrame or one of its descendants. |
631 | 0 | return aFrame->GetStateBits() & NS_FRAME_IS_SVG_TEXT; |
632 | 0 | } |
633 | | }; |
634 | | |
635 | | #endif |