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