Coverage Report

Created: 2018-09-25 14:53

/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