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