nsCSSRendering.h (41126B)
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 /* utility functions for drawing borders and backgrounds */ 8 9 #ifndef nsCSSRendering_h___ 10 #define nsCSSRendering_h___ 11 12 #include "gfxBlur.h" 13 #include "gfxContext.h" 14 #include "gfxTextRun.h" 15 #include "mozilla/TypedEnumBits.h" 16 #include "mozilla/gfx/PathHelpers.h" 17 #include "mozilla/gfx/Rect.h" 18 #include "nsCSSRenderingBorders.h" 19 #include "nsIFrame.h" 20 #include "nsImageRenderer.h" 21 #include "nsStyleStruct.h" 22 23 class gfxContext; 24 class nsPresContext; 25 26 namespace mozilla { 27 28 class ComputedStyle; 29 30 namespace gfx { 31 struct sRGBColor; 32 class DrawTarget; 33 } // namespace gfx 34 35 namespace layers { 36 class ImageContainer; 37 class StackingContextHelper; 38 class WebRenderParentCommand; 39 class WebRenderLayerManager; 40 class RenderRootStateManager; 41 } // namespace layers 42 43 namespace wr { 44 class DisplayListBuilder; 45 } // namespace wr 46 47 enum class PaintBorderFlags : uint8_t { SyncDecodeImages = 1 << 0 }; 48 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(PaintBorderFlags) 49 50 } // namespace mozilla 51 52 /** 53 * A struct representing all the information needed to paint a background 54 * image to some target, taking into account all CSS background-* properties. 55 * See PrepareImageLayer. 56 */ 57 struct nsBackgroundLayerState { 58 typedef mozilla::gfx::CompositionOp CompositionOp; 59 typedef mozilla::nsImageRenderer nsImageRenderer; 60 61 /** 62 * @param aFlags some combination of nsCSSRendering::PAINTBG_* flags 63 */ 64 nsBackgroundLayerState(nsIFrame* aForFrame, const mozilla::StyleImage* aImage, 65 uint32_t aFlags) 66 : mImageRenderer(aForFrame, aImage, aFlags) {} 67 68 /** 69 * The nsImageRenderer that will be used to draw the background. 70 */ 71 nsImageRenderer mImageRenderer; 72 /** 73 * A rectangle that one copy of the image tile is mapped onto. Same 74 * coordinate system as aBorderArea/aBGClipRect passed into 75 * PrepareImageLayer. 76 */ 77 nsRect mDestArea; 78 /** 79 * The actual rectangle that should be filled with (complete or partial) 80 * image tiles. Same coordinate system as aBorderArea/aBGClipRect passed into 81 * PrepareImageLayer. 82 */ 83 nsRect mFillArea; 84 /** 85 * The anchor point that should be snapped to a pixel corner. Same 86 * coordinate system as aBorderArea/aBGClipRect passed into 87 * PrepareImageLayer. 88 */ 89 nsPoint mAnchor; 90 /** 91 * The background-repeat property space keyword computes the 92 * repeat size which is image size plus spacing. 93 */ 94 nsSize mRepeatSize; 95 }; 96 97 struct nsCSSRendering { 98 typedef mozilla::gfx::sRGBColor sRGBColor; 99 typedef mozilla::gfx::CompositionOp CompositionOp; 100 typedef mozilla::gfx::DrawTarget DrawTarget; 101 typedef mozilla::gfx::Float Float; 102 typedef mozilla::gfx::Point Point; 103 typedef mozilla::gfx::Rect Rect; 104 typedef mozilla::gfx::Size Size; 105 typedef mozilla::gfx::RectCornerRadii RectCornerRadii; 106 typedef mozilla::layers::WebRenderLayerManager WebRenderLayerManager; 107 typedef mozilla::image::ImgDrawResult ImgDrawResult; 108 typedef nsIFrame::Sides Sides; 109 110 /** 111 * Initialize any static variables used by nsCSSRendering. 112 */ 113 static void Init(); 114 115 /** 116 * Clean up any static variables used by nsCSSRendering. 117 */ 118 static void Shutdown(); 119 120 static bool IsBoxDecorationSlice(const nsStyleBorder& aStyleBorder); 121 static nsRect BoxDecorationRectForBorder( 122 nsIFrame* aFrame, const nsRect& aBorderArea, Sides aSkipSides, 123 const nsStyleBorder* aStyleBorder = nullptr); 124 static nsRect BoxDecorationRectForBackground( 125 nsIFrame* aFrame, const nsRect& aBorderArea, Sides aSkipSides, 126 const nsStyleBorder* aStyleBorder = nullptr); 127 128 static bool GetShadowInnerRadii(nsIFrame* aFrame, const nsRect& aFrameArea, 129 RectCornerRadii& aOutInnerRadii); 130 static nsRect GetBoxShadowInnerPaddingRect(nsIFrame* aFrame, 131 const nsRect& aFrameArea); 132 static bool ShouldPaintBoxShadowInner(nsIFrame* aFrame); 133 static void PaintBoxShadowInner(nsPresContext* aPresContext, 134 gfxContext& aRenderingContext, 135 nsIFrame* aForFrame, 136 const nsRect& aFrameArea); 137 138 static bool GetBorderRadii(const nsRect& aFrameRect, 139 const nsRect& aBorderRect, nsIFrame* aFrame, 140 RectCornerRadii& aOutRadii); 141 static nsRect GetShadowRect(const nsRect& aFrameArea, bool aNativeTheme, 142 nsIFrame* aForFrame); 143 static mozilla::gfx::sRGBColor GetShadowColor( 144 const mozilla::StyleSimpleShadow&, nsIFrame* aFrame, float aOpacity); 145 // Returns if the frame has a themed frame. 146 // aMaybeHasBorderRadius will return false if we can early detect 147 // that we don't have a border radius. 148 static bool HasBoxShadowNativeTheme(nsIFrame* aFrame, 149 bool& aMaybeHasBorderRadius); 150 static void PaintBoxShadowOuter(nsPresContext* aPresContext, 151 gfxContext& aRenderingContext, 152 nsIFrame* aForFrame, const nsRect& aFrameArea, 153 const nsRect& aDirtyRect, 154 float aOpacity = 1.0); 155 156 static void ComputePixelRadii(const nsRectCornerRadii& aRadii, 157 nscoord aAppUnitsPerPixel, 158 RectCornerRadii* oBorderRadii); 159 160 /** 161 * Render the border for an element using css rendering rules 162 * for borders. aSkipSides says which sides to skip 163 * when rendering, the default is to skip none. 164 */ 165 static ImgDrawResult PaintBorder( 166 nsPresContext* aPresContext, gfxContext& aRenderingContext, 167 nsIFrame* aForFrame, const nsRect& aDirtyRect, const nsRect& aBorderArea, 168 mozilla::ComputedStyle* aStyle, mozilla::PaintBorderFlags aFlags, 169 Sides aSkipSides = Sides()); 170 171 /** 172 * Like PaintBorder, but taking an nsStyleBorder argument instead of 173 * getting it from aStyle. aSkipSides says which sides to skip 174 * when rendering, the default is to skip none. 175 */ 176 static ImgDrawResult PaintBorderWithStyleBorder( 177 nsPresContext* aPresContext, gfxContext& aRenderingContext, 178 nsIFrame* aForFrame, const nsRect& aDirtyRect, const nsRect& aBorderArea, 179 const nsStyleBorder& aBorderStyle, mozilla::ComputedStyle* aStyle, 180 mozilla::PaintBorderFlags aFlags, Sides aSkipSides = Sides()); 181 182 static mozilla::Maybe<nsCSSBorderRenderer> CreateBorderRenderer( 183 nsPresContext* aPresContext, DrawTarget* aDrawTarget, nsIFrame* aForFrame, 184 const nsRect& aDirtyRect, const nsRect& aBorderArea, 185 mozilla::ComputedStyle* aStyle, bool* aOutBorderIsEmpty, 186 Sides aSkipSides = Sides()); 187 188 static mozilla::Maybe<nsCSSBorderRenderer> 189 CreateBorderRendererWithStyleBorder( 190 nsPresContext* aPresContext, DrawTarget* aDrawTarget, nsIFrame* aForFrame, 191 const nsRect& aDirtyRect, const nsRect& aBorderArea, 192 const nsStyleBorder& aBorderStyle, mozilla::ComputedStyle* aStyle, 193 bool* aOutBorderIsEmpty, Sides aSkipSides = Sides()); 194 195 static mozilla::Maybe<nsCSSBorderRenderer> 196 CreateNullBorderRendererWithStyleBorder( 197 nsPresContext* aPresContext, DrawTarget* aDrawTarget, nsIFrame* aForFrame, 198 const nsRect& aDirtyRect, const nsRect& aBorderArea, 199 const nsStyleBorder& aBorderStyle, mozilla::ComputedStyle* aStyle, 200 bool* aOutBorderIsEmpty, Sides aSkipSides = Sides()); 201 202 static mozilla::Maybe<nsCSSBorderRenderer> 203 CreateBorderRendererForNonThemedOutline(nsPresContext* aPresContext, 204 DrawTarget* aDrawTarget, 205 nsIFrame* aForFrame, 206 const nsRect& aDirtyRect, 207 const nsRect& aInnerRect, 208 mozilla::ComputedStyle* aStyle); 209 210 static ImgDrawResult CreateWebRenderCommandsForBorder( 211 mozilla::nsDisplayItem* aItem, nsIFrame* aForFrame, 212 const nsRect& aBorderArea, mozilla::wr::DisplayListBuilder& aBuilder, 213 mozilla::wr::IpcResourceUpdateQueue& aResources, 214 const mozilla::layers::StackingContextHelper& aSc, 215 mozilla::layers::RenderRootStateManager* aManager, 216 mozilla::nsDisplayListBuilder* aDisplayListBuilder); 217 218 static void CreateWebRenderCommandsForNullBorder( 219 mozilla::nsDisplayItem* aItem, nsIFrame* aForFrame, 220 const nsRect& aBorderArea, mozilla::wr::DisplayListBuilder& aBuilder, 221 mozilla::wr::IpcResourceUpdateQueue& aResources, 222 const mozilla::layers::StackingContextHelper& aSc, 223 const nsStyleBorder& aStyleBorder); 224 225 static ImgDrawResult CreateWebRenderCommandsForBorderWithStyleBorder( 226 mozilla::nsDisplayItem* aItem, nsIFrame* aForFrame, 227 const nsRect& aBorderArea, mozilla::wr::DisplayListBuilder& aBuilder, 228 mozilla::wr::IpcResourceUpdateQueue& aResources, 229 const mozilla::layers::StackingContextHelper& aSc, 230 mozilla::layers::RenderRootStateManager* aManager, 231 mozilla::nsDisplayListBuilder* aDisplayListBuilder, 232 const nsStyleBorder& aStyleBorder); 233 234 /** 235 * Render the outline for an element using css rendering rules for borders. 236 */ 237 static void PaintNonThemedOutline(nsPresContext* aPresContext, 238 gfxContext& aRenderingContext, 239 nsIFrame* aForFrame, 240 const nsRect& aDirtyRect, 241 const nsRect& aInnerRect, 242 mozilla::ComputedStyle* aStyle); 243 244 /** 245 * Render keyboard focus on an element. 246 * |aFocusRect| is the outer rectangle of the focused element. 247 * Uses a fixed style equivalent to "1px dotted |aColor|". 248 * Not used for controls, because the native theme may differ. 249 */ 250 static nsCSSBorderRenderer GetBorderRendererForFocus(nsIFrame*, DrawTarget*, 251 const nsRect& aFocusRect, 252 nscolor aColor); 253 254 /** 255 * Render a gradient for an element. 256 * aDest is the rect for a single tile of the gradient on the destination. 257 * aFill is the rect on the destination to be covered by repeated tiling of 258 * the gradient. 259 * aSrc is the part of the gradient to be rendered into a tile (aDest), if 260 * aSrc and aDest are different sizes, the image will be scaled to map aSrc 261 * onto aDest. 262 * aIntrinsicSize is the size of the source gradient. 263 */ 264 static void PaintGradient(nsPresContext* aPresContext, gfxContext& aContext, 265 const mozilla::StyleGradient& aGradient, 266 const nsRect& aDirtyRect, const nsRect& aDest, 267 const nsRect& aFill, const nsSize& aRepeatSize, 268 const mozilla::CSSIntRect& aSrc, 269 const nsSize& aIntrinsiceSize, 270 float aOpacity = 1.0); 271 272 /** 273 * Find the frame whose background style should be used to draw the 274 * canvas background. aForFrame must be the frame for the root element 275 * whose background style should be used. This function will return 276 * aForFrame unless the <body> background should be propagated, in 277 * which case we return the frame associated with the <body>'s background. 278 */ 279 static nsIFrame* FindBackgroundStyleFrame(nsIFrame* aForFrame); 280 281 /** 282 * Returns the ComputedStyle to be used to paint the background for the given 283 * frame, if its element has a meaningful background. This applies the rules 284 * for propagating backgrounds between BODY, the root element, and the 285 * canvas. 286 * 287 * @return the ComputedStyle (if any) to be used for painting aForFrame's 288 * background. 289 */ 290 static mozilla::ComputedStyle* FindBackground(const nsIFrame* aForFrame); 291 static nsIFrame* FindBackgroundFrame(const nsIFrame* aForFrame); 292 293 /** 294 * As FindBackground, but the passed-in frame is known to be a root frame 295 * (returned from nsCSSFrameConstructor::GetRootElementStyleFrame()) 296 * and there is always some meaningful background returned. 297 */ 298 static mozilla::ComputedStyle* FindRootFrameBackground(nsIFrame* aForFrame); 299 300 /** 301 * Find a non-transparent background color on an ancestor, for various 302 * contrast checks. Note that this only accounts for background-color and 303 * might stop at themed frames (depending on the argument), so it might not be 304 * what you want. Note that if we stop at themed frames we might, in fact, end 305 * up returning a transparent color (but then mIsThemed will be set to true). 306 * 307 * For semi-transparent colors, right now we blend with the default 308 * background-color rather than with all ancestor backgrounds. 309 * 310 * If aPreferBodyToCanvas is true, we prefer the background color of the 311 * <body> frame, even though we found a canvas background, because the body 312 * background color is most likely what will be visible as the background 313 * color of the page, even if the html element has a different background 314 * color which prevents that of the body frame to propagate to the viewport. 315 */ 316 struct EffectiveBackgroundColor { 317 nscolor mColor = 0; 318 bool mIsThemed = false; 319 }; 320 static EffectiveBackgroundColor FindEffectiveBackgroundColor( 321 nsIFrame* aFrame, bool aStopAtThemed = true, 322 bool aPreferBodyToCanvas = false); 323 324 /** 325 * Determine the background color to draw taking into account print settings. 326 */ 327 static nscolor DetermineBackgroundColor(nsPresContext* aPresContext, 328 const mozilla::ComputedStyle* aStyle, 329 nsIFrame* aFrame, 330 bool& aDrawBackgroundImage, 331 bool& aDrawBackgroundColor); 332 333 static nsRect ComputeImageLayerPositioningArea( 334 nsPresContext* aPresContext, nsIFrame* aForFrame, 335 const nsRect& aBorderArea, const nsStyleImageLayers::Layer& aLayer, 336 nsIFrame** aAttachedToFrame, bool* aOutTransformedFixed); 337 338 // Implementation of the formula for computation of background-repeat round 339 // See http://dev.w3.org/csswg/css3-background/#the-background-size 340 // This function returns the adjusted size of the background image. 341 static nscoord ComputeRoundedSize(nscoord aCurrentSize, 342 nscoord aPositioningSize); 343 344 /* ComputeBorderSpacedRepeatSize 345 * aImageDimension: the image width/height 346 * aAvailableSpace: the background positioning area width/height 347 * aSpace: the space between each image 348 * Returns the image size plus gap size of app units for use as spacing 349 */ 350 static nscoord ComputeBorderSpacedRepeatSize(nscoord aImageDimension, 351 nscoord aAvailableSpace, 352 nscoord& aSpace); 353 354 static nsBackgroundLayerState PrepareImageLayer( 355 nsPresContext* aPresContext, nsIFrame* aForFrame, uint32_t aFlags, 356 const nsRect& aBorderArea, const nsRect& aBGClipRect, 357 const nsStyleImageLayers::Layer& aLayer, 358 bool* aOutIsTransformedFixed = nullptr); 359 360 struct ImageLayerClipState { 361 nsRect mBGClipArea; // Affected by mClippedRadii 362 nsRect mAdditionalBGClipArea; // Not affected by mClippedRadii 363 nsRect mDirtyRectInAppUnits; 364 gfxRect mDirtyRectInDevPx; 365 366 nsRectCornerRadii mRadii; 367 RectCornerRadii mClippedRadii; 368 bool mHasRoundedCorners; 369 bool mHasAdditionalBGClipArea; 370 371 // Whether we are being asked to draw with a caller provided background 372 // clipping area. If this is true we also disable rounded corners. 373 bool mCustomClip; 374 375 ImageLayerClipState() 376 : mHasRoundedCorners(false), 377 mHasAdditionalBGClipArea(false), 378 mCustomClip(false) {} 379 380 bool IsValid() const; 381 }; 382 383 static void GetImageLayerClip(const nsStyleImageLayers::Layer& aLayer, 384 nsIFrame* aForFrame, 385 const nsStyleBorder& aBorder, 386 const nsRect& aBorderArea, 387 const nsRect& aCallerDirtyRect, 388 bool aWillPaintBorder, 389 nscoord aAppUnitsPerPixel, 390 /* out */ ImageLayerClipState* aClipState); 391 392 /** 393 * Render the background for an element using css rendering rules 394 * for backgrounds or mask. 395 */ 396 enum { 397 /** 398 * When this flag is passed, the element's nsDisplayBorder will be 399 * painted immediately on top of this background. 400 */ 401 PAINTBG_WILL_PAINT_BORDER = 0x01, 402 /** 403 * When this flag is passed, images are synchronously decoded. 404 */ 405 PAINTBG_SYNC_DECODE_IMAGES = 0x02, 406 /** 407 * When this flag is passed, painting will go to the screen so we can 408 * take advantage of the fact that it will be clipped to the viewport. 409 */ 410 PAINTBG_TO_WINDOW = 0x04, 411 /** 412 * When this flag is passed, painting will read properties of mask-image 413 * style, instead of background-image. 414 */ 415 PAINTBG_MASK_IMAGE = 0x08, 416 /** 417 * When this flag is passed, images are downscaled during decode. This 418 * is also implied by PAINTBG_TO_WINDOW. 419 */ 420 PAINTBG_HIGH_QUALITY_SCALING = 0x10, 421 }; 422 423 struct PaintBGParams { 424 nsPresContext& presCtx; 425 nsRect dirtyRect; 426 nsRect borderArea; 427 nsIFrame* frame; 428 uint32_t paintFlags; 429 nsRect* bgClipRect = nullptr; 430 int32_t layer; // -1 means painting all layers; other 431 // value means painting one specific 432 // layer only. 433 CompositionOp compositionOp; 434 float opacity; 435 436 static PaintBGParams ForAllLayers(nsPresContext& aPresCtx, 437 const nsRect& aDirtyRect, 438 const nsRect& aBorderArea, 439 nsIFrame* aFrame, uint32_t aPaintFlags, 440 float aOpacity = 1.0); 441 static PaintBGParams ForSingleLayer( 442 nsPresContext& aPresCtx, const nsRect& aDirtyRect, 443 const nsRect& aBorderArea, nsIFrame* aFrame, uint32_t aPaintFlags, 444 int32_t aLayer, CompositionOp aCompositionOp = CompositionOp::OP_OVER, 445 float aOpacity = 1.0); 446 447 private: 448 PaintBGParams(nsPresContext& aPresCtx, const nsRect& aDirtyRect, 449 const nsRect& aBorderArea, nsIFrame* aFrame, 450 uint32_t aPaintFlags, int32_t aLayer, 451 CompositionOp aCompositionOp, float aOpacity) 452 : presCtx(aPresCtx), 453 dirtyRect(aDirtyRect), 454 borderArea(aBorderArea), 455 frame(aFrame), 456 paintFlags(aPaintFlags), 457 layer(aLayer), 458 compositionOp(aCompositionOp), 459 opacity(aOpacity) {} 460 }; 461 462 static ImgDrawResult PaintStyleImageLayer(const PaintBGParams& aParams, 463 gfxContext& aRenderingCtx); 464 465 /** 466 * Same as |PaintStyleImageLayer|, except using the provided style structs. 467 * This short-circuits the code that ensures that the root element's 468 * {background|mask} is drawn on the canvas. 469 * The aLayer parameter allows you to paint a single layer of the 470 * {background|mask}. 471 * The default value for aLayer, -1, means that all layers will be painted. 472 * The background color will only be painted if the back-most layer is also 473 * being painted and (aParams.paintFlags & PAINTBG_MASK_IMAGE) is false. 474 * aCompositionOp is only respected if a single layer is specified (aLayer != 475 * -1). If all layers are painted, the image layer's blend mode (or the mask 476 * layer's composition mode) will be used. 477 */ 478 static ImgDrawResult PaintStyleImageLayerWithSC( 479 const PaintBGParams& aParams, gfxContext& aRenderingCtx, 480 const mozilla::ComputedStyle* aBackgroundSC, 481 const nsStyleBorder& aBorder); 482 483 static bool CanBuildWebRenderDisplayItemsForStyleImageLayer( 484 WebRenderLayerManager* aManager, nsPresContext& aPresCtx, 485 nsIFrame* aFrame, const nsStyleBackground* aBackgroundStyle, 486 int32_t aLayer, uint32_t aPaintFlags); 487 static ImgDrawResult BuildWebRenderDisplayItemsForStyleImageLayer( 488 const PaintBGParams& aParams, mozilla::wr::DisplayListBuilder& aBuilder, 489 mozilla::wr::IpcResourceUpdateQueue& aResources, 490 const mozilla::layers::StackingContextHelper& aSc, 491 mozilla::layers::RenderRootStateManager* aManager, 492 mozilla::nsDisplayItem* aItem); 493 494 static ImgDrawResult BuildWebRenderDisplayItemsForStyleImageLayerWithSC( 495 const PaintBGParams& aParams, mozilla::wr::DisplayListBuilder& aBuilder, 496 mozilla::wr::IpcResourceUpdateQueue& aResources, 497 const mozilla::layers::StackingContextHelper& aSc, 498 mozilla::layers::RenderRootStateManager* aManager, 499 mozilla::nsDisplayItem* aItem, mozilla::ComputedStyle* mBackgroundSC, 500 const nsStyleBorder& aBorder); 501 502 /** 503 * Returns the rectangle covered by the given background layer image, taking 504 * into account background positioning, sizing, and repetition, but not 505 * clipping. 506 */ 507 static nsRect GetBackgroundLayerRect(nsPresContext* aPresContext, 508 nsIFrame* aForFrame, 509 const nsRect& aBorderArea, 510 const nsRect& aClipRect, 511 const nsStyleImageLayers::Layer& aLayer, 512 uint32_t aFlags); 513 514 /** 515 * Called when we start creating a display list. The frame tree will not 516 * change until a matching EndFrameTreeLocked is called. 517 */ 518 static void BeginFrameTreesLocked(); 519 /** 520 * Called when we've finished using a display list. When all 521 * BeginFrameTreeLocked calls have been balanced by an EndFrameTreeLocked, 522 * the frame tree may start changing again. 523 */ 524 static void EndFrameTreesLocked(); 525 526 // Draw a border segment in the table collapsing border model with beveling 527 // corners. 528 static void DrawTableBorderSegment( 529 DrawTarget& aDrawTarget, mozilla::StyleBorderStyle aBorderStyle, 530 nscolor aBorderColor, const nsRect& aBorderRect, 531 int32_t aAppUnitsPerDevPixel, mozilla::Side aStartBevelSide, 532 nscoord aStartBevelOffset, mozilla::Side aEndBevelSide, 533 nscoord aEndBevelOffset); 534 535 // A single border bevel. 536 struct Bevel { 537 mozilla::Side mSide; 538 nscoord mOffset; 539 }; 540 541 // A single solid beveled border segment. 542 struct SolidBeveledBorderSegment { 543 nsRect mRect; 544 nscolor mColor; 545 Bevel mStartBevel; 546 Bevel mEndBevel; 547 }; 548 549 // Collect the table border segments with beveling. Can't be called with 550 // dashed / dotted borders, since we don't support beveling those. 551 static void GetTableBorderSolidSegments( 552 nsTArray<SolidBeveledBorderSegment>& aSegments, 553 mozilla::StyleBorderStyle aBorderStyle, nscolor aBorderColor, 554 const nsRect& aBorderRect, int32_t aAppUnitsPerDevPixel, 555 mozilla::Side aStartBevelSide, nscoord aStartBevelOffset, 556 mozilla::Side aEndBevelSide, nscoord aEndBevelOffset); 557 558 // NOTE: pt, dirtyRect, lineSize, ascent, offset, insetLeft, and insetRight in 559 // the following structs are non-rounded device pixels, not app units. 560 struct DecorationRectParams { 561 // Checks if either start or end inset value is negative. 562 // In that situation, text decoration will extend past the edges of the 563 // text. 564 bool HasNegativeInset() const { 565 return insetLeft < 0.0 || insetRight < 0.0; 566 } 567 568 // The width [length] and the height [thickness] of the decoration 569 // line. This is a "logical" size in textRun orientation, so that 570 // for a vertical textrun, width will actually be a physical height; 571 // and conversely, height will be a physical width. 572 Size lineSize; 573 // The default height [thickness] of the line given by the font metrics. 574 // This is used for obtaining the correct offset for the decoration line 575 // when CSS specifies a unique thickness for a text-decoration, 576 // since the offset given by the font is derived from the font metric's 577 // assumed line height 578 Float defaultLineThickness = 0.0f; 579 // The ascent of the text. 580 Float ascent = 0.0f; 581 // The offset of the decoration line from the baseline of the text 582 // (if the value is positive, the line is lifted up). 583 Float offset = 0.0f; 584 // If descentLimit is zero or larger and the underline overflows 585 // from the descent space, the underline should be lifted up as far 586 // as possible. Note that this does not mean the underline never 587 // overflows from this limitation, because if the underline is 588 // positioned to the baseline or upper, it causes unreadability. 589 // Note that if this is zero or larger, the underline rect may be 590 // shrunken if it's possible. Therefore, this value is used for 591 // strikeout line and overline too. 592 Float descentLimit = -1.0f; 593 // Which line will be painted. The value can be 594 // UNDERLINE or OVERLINE or LINE_THROUGH. 595 mozilla::StyleTextDecorationLine decoration = 596 mozilla::StyleTextDecorationLine::UNDERLINE; 597 // The style of the decoration line 598 mozilla::StyleTextDecorationStyle style = 599 mozilla::StyleTextDecorationStyle::None; 600 // Decoration-line start/end inset values for this decoration. 601 // The caller must ensure that the start/end values are translated to 602 // left/right in the line-relative direction. 603 Float insetLeft = 0.0f; 604 Float insetRight = 0.0f; 605 bool vertical = false; 606 bool sidewaysLeft = false; 607 gfxTextRun::Range glyphRange; 608 gfxTextRun::PropertyProvider* provider = nullptr; 609 }; 610 611 struct PaintDecorationLineParams : DecorationRectParams { 612 // No need to paint outside this rect. 613 Rect dirtyRect; 614 // The top/left edge of the text. 615 Point pt; 616 // The color of the decoration line. 617 nscolor color = NS_RGBA(0, 0, 0, 0); 618 // The distance between the left edge of the given frame and the 619 // position of the text as positioned without offset of the shadow. 620 Float icoordInFrame = 0.0f; 621 // Baseline offset being applied to this text (block-direction adjustment 622 // applied to glyph positions when computing skip-ink intercepts). 623 Float baselineOffset = 0.0f; 624 // Whether text-decoration-skip-ink behavior is to be supported. 625 bool allowInkSkipping = true; 626 627 mozilla::StyleTextDecorationSkipInk skipInk = 628 mozilla::StyleTextDecorationSkipInk::None; 629 }; 630 631 /** 632 * Function for painting the clipped decoration lines for the text. 633 * Takes into account the rect clipping that occurs when 634 * text-decoration-skip-ink is being used for underlines or overlines 635 * 636 * input: 637 * @param aFrame the frame which needs the decoration line 638 * @param aDrawTarget the target/backend being drawn to 639 * @param aParams the parameters for the decoration line 640 * being drawn 641 * @param aRect the rect representing the decoration line 642 */ 643 static void PaintDecorationLineInternal( 644 nsIFrame* aFrame, DrawTarget& aDrawTarget, 645 const PaintDecorationLineParams& aParams, Rect aRect); 646 647 /** 648 * Function for painting the decoration lines for the text. 649 * 650 * input: 651 * @param aFrame the frame which needs the decoration line 652 * @param aDrawTarget the target/backend being drawn to 653 * @param aParams the parameters for the decoration line 654 * being drawn 655 */ 656 static void PaintDecorationLine(nsIFrame* aFrame, DrawTarget& aDrawTarget, 657 const PaintDecorationLineParams& aParams); 658 659 /** 660 * Returns a Rect corresponding to the outline of the decoration line for the 661 * given text metrics. Arguments have the same meaning as for 662 * PaintDecorationLine. Currently this only works for solid 663 * decorations; for other decoration styles the returned Rect will be empty. 664 */ 665 static Rect DecorationLineToPath(const PaintDecorationLineParams& aParams); 666 667 /** 668 * Function for getting the decoration line rect for the text. 669 * NOTE: aLineSize, aAscent and aOffset are non-rounded device pixels, 670 * not app units. 671 * input: 672 * @param aPresContext 673 * output: 674 * @return the decoration line rect for the input, 675 * the each values are app units. 676 */ 677 static nsRect GetTextDecorationRect(nsPresContext* aPresContext, 678 const DecorationRectParams& aParams); 679 680 static CompositionOp GetGFXBlendMode(mozilla::StyleBlend aBlendMode) { 681 switch (aBlendMode) { 682 case mozilla::StyleBlend::Normal: 683 return CompositionOp::OP_OVER; 684 case mozilla::StyleBlend::Multiply: 685 return CompositionOp::OP_MULTIPLY; 686 case mozilla::StyleBlend::Screen: 687 return CompositionOp::OP_SCREEN; 688 case mozilla::StyleBlend::Overlay: 689 return CompositionOp::OP_OVERLAY; 690 case mozilla::StyleBlend::Darken: 691 return CompositionOp::OP_DARKEN; 692 case mozilla::StyleBlend::Lighten: 693 return CompositionOp::OP_LIGHTEN; 694 case mozilla::StyleBlend::ColorDodge: 695 return CompositionOp::OP_COLOR_DODGE; 696 case mozilla::StyleBlend::ColorBurn: 697 return CompositionOp::OP_COLOR_BURN; 698 case mozilla::StyleBlend::HardLight: 699 return CompositionOp::OP_HARD_LIGHT; 700 case mozilla::StyleBlend::SoftLight: 701 return CompositionOp::OP_SOFT_LIGHT; 702 case mozilla::StyleBlend::Difference: 703 return CompositionOp::OP_DIFFERENCE; 704 case mozilla::StyleBlend::Exclusion: 705 return CompositionOp::OP_EXCLUSION; 706 case mozilla::StyleBlend::Hue: 707 return CompositionOp::OP_HUE; 708 case mozilla::StyleBlend::Saturation: 709 return CompositionOp::OP_SATURATION; 710 case mozilla::StyleBlend::Color: 711 return CompositionOp::OP_COLOR; 712 case mozilla::StyleBlend::Luminosity: 713 return CompositionOp::OP_LUMINOSITY; 714 case mozilla::StyleBlend::PlusLighter: 715 return CompositionOp::OP_ADD; 716 default: 717 MOZ_ASSERT(false); 718 return CompositionOp::OP_OVER; 719 } 720 } 721 722 static CompositionOp GetGFXCompositeMode( 723 mozilla::StyleMaskComposite aCompositeMode) { 724 switch (aCompositeMode) { 725 case mozilla::StyleMaskComposite::Add: 726 return CompositionOp::OP_OVER; 727 case mozilla::StyleMaskComposite::Subtract: 728 return CompositionOp::OP_OUT; 729 case mozilla::StyleMaskComposite::Intersect: 730 return CompositionOp::OP_IN; 731 case mozilla::StyleMaskComposite::Exclude: 732 return CompositionOp::OP_XOR; 733 default: 734 MOZ_ASSERT(false); 735 return CompositionOp::OP_OVER; 736 } 737 } 738 739 protected: 740 static gfxRect GetTextDecorationRectInternal( 741 const Point& aPt, const DecorationRectParams& aParams); 742 743 /** 744 * Returns inflated rect for painting a decoration line. 745 * Complex style decoration lines should be painted from leftmost of nearest 746 * ancestor block box because that makes better look of connection of lines 747 * for different nodes. ExpandPaintingRectForDecorationLine() returns 748 * a rect for actual painting rect for the clipped rect. 749 * 750 * input: 751 * @param aFrame the frame which needs the decoration line. 752 * @param aStyle the style of the complex decoration line 753 * @param aClippedRect the clipped rect for the decoration line. 754 * in other words, visible area of the line. 755 * @param aICoordInFrame the distance between inline-start edge of aFrame 756 * and aClippedRect.pos. 757 * @param aCycleLength the width of one cycle of the line style. 758 */ 759 static Rect ExpandPaintingRectForDecorationLine( 760 nsIFrame* aFrame, const mozilla::StyleTextDecorationStyle aStyle, 761 const Rect& aClippedRect, const Float aICoordInFrame, 762 const Float aCycleLength, bool aVertical); 763 }; 764 765 /* 766 * nsContextBoxBlur 767 * Creates an 8-bit alpha channel context for callers to draw in, blurs the 768 * contents of that context and applies it as a 1-color mask on a 769 * different existing context. Uses gfxGaussianBlur as its back end. 770 * 771 * You must call Init() first to create a suitable temporary surface to draw 772 * on. You must then draw any desired content onto the given context, then 773 * call DoPaint() to apply the blurred content as a single-color mask. You 774 * can only call Init() once, so objects cannot be reused. 775 * 776 * This is very useful for creating drop shadows or silhouettes. 777 */ 778 class nsContextBoxBlur { 779 typedef mozilla::gfx::sRGBColor sRGBColor; 780 typedef mozilla::gfx::DrawTarget DrawTarget; 781 typedef mozilla::gfx::RectCornerRadii RectCornerRadii; 782 783 public: 784 enum { FORCE_MASK = 0x01 }; 785 /** 786 * Prepares a gfxContext to draw on. Do not call this twice; if you want 787 * to get the gfxContext again use GetContext(). 788 * 789 * @param aRect The coordinates of the surface to create. 790 * All coordinates must be in app units. 791 * This must not include the blur radius, pass 792 * it as the second parameter and everything 793 * is taken care of. 794 * 795 * @param aBlurRadius The blur radius in app units. 796 * 797 * @param aAppUnitsPerDevPixel The number of app units in a device pixel, 798 * for conversion. Most of the time you'll 799 * pass this from the current PresContext if 800 * available. 801 * 802 * @param aDestinationCtx The graphics context to apply the blurred 803 * mask to when you call DoPaint(). Make sure 804 * it is not destroyed before you call 805 * DoPaint(). To set the color of the 806 * resulting blurred graphic mask, you must 807 * set the color on this context before 808 * calling Init(). 809 * 810 * @param aDirtyRect The absolute dirty rect in app units. Used to 811 * optimize the temporary surface size and speed 812 * up blur. 813 * 814 * @param aSkipRect An area in device pixels (NOT app units!) to 815 * avoid blurring over, to prevent unnecessary work. 816 * 817 * @param aFlags FORCE_MASK to ensure that the content drawn to 818 * the returned gfxContext is used as a mask, and not drawn directly to 819 * aDestinationCtx. 820 * 821 * @return A blank 8-bit alpha-channel-only graphics context to 822 * draw on, or null on error. Must not be freed. The 823 * context has a device offset applied to it given by 824 * aRect. This means you can use coordinates as if it 825 * were at the desired position at aRect and you don't 826 * need to worry about translating any coordinates to 827 * draw on this temporary surface. 828 * 829 * If aBlurRadius is 0, the returned context is aDestinationCtx and 830 * DoPaint() does nothing, because no blurring is required. Therefore, you 831 * should prepare the destination context as if you were going to draw 832 * directly on it instead of any temporary surface created in this class. 833 */ 834 gfxContext* Init(const nsRect& aRect, nscoord aSpreadRadius, 835 nscoord aBlurRadius, int32_t aAppUnitsPerDevPixel, 836 gfxContext* aDestinationCtx, const nsRect& aDirtyRect, 837 const gfxRect* aSkipRect, uint32_t aFlags = 0); 838 839 /** 840 * Does the actual blurring and mask applying. Users of this object *must* 841 * have called Init() first, then have drawn whatever they want to be 842 * blurred onto the internal gfxContext before calling this. 843 */ 844 void DoPaint(); 845 846 /** 847 * Gets the internal gfxContext at any time. Must not be freed. Avoid 848 * calling this before calling Init() since the context would not be 849 * constructed at that point. 850 */ 851 gfxContext* GetContext(); 852 853 /** 854 * Get the margin associated with the given blur radius, i.e., the 855 * additional area that might be painted as a result of it. (The 856 * margin for a spread radius is itself, on all sides.) 857 */ 858 static nsMargin GetBlurRadiusMargin(nscoord aBlurRadius, 859 int32_t aAppUnitsPerDevPixel); 860 861 /** 862 * Blurs a coloured rectangle onto aDestinationCtx. This is equivalent 863 * to calling Init(), drawing a rectangle onto the returned surface 864 * and then calling DoPaint, but may let us optimize better in the 865 * backend. 866 * 867 * @param aDestinationCtx The destination to blur to. 868 * @param aRect The rectangle to blur in app units. 869 * @param aAppUnitsPerDevPixel The number of app units in a device pixel, 870 * for conversion. Most of the time you'll 871 * pass this from the current PresContext if 872 * available. 873 * @param aCornerRadii Corner radii for aRect, if it is a rounded 874 * rectangle. 875 * @param aBlurRadius The blur radius in app units. 876 * @param aShadowColor The color to draw the blurred shadow. 877 * @param aDirtyRect The absolute dirty rect in app units. Used to 878 * optimize the temporary surface size and speed 879 * up blur. 880 * @param aSkipRect An area in device pixels (NOT app units!) to 881 * avoid blurring over, to prevent unnecessary work. 882 */ 883 static void BlurRectangle(gfxContext* aDestinationCtx, const nsRect& aRect, 884 int32_t aAppUnitsPerDevPixel, 885 RectCornerRadii* aCornerRadii, nscoord aBlurRadius, 886 const sRGBColor& aShadowColor, 887 const nsRect& aDirtyRect, const gfxRect& aSkipRect); 888 889 /** 890 * Draws a blurred inset box shadow shape onto the destination surface. 891 * Like BlurRectangle, this is equivalent to calling Init(), 892 * drawing a rectangle onto the returned surface 893 * and then calling DoPaint, but may let us optimize better in the 894 * backend. 895 * 896 * @param aDestinationCtx The destination to blur to. 897 * @param aDestinationRect The rectangle to blur in app units. 898 * @param aShadowClipRect The inside clip rect that creates the path. 899 * @param aShadowColor The color of the blur 900 * @param aBlurRadiusAppUnits The blur radius in app units 901 * @param aSpreadRadiusAppUnits The spread radius in app units. 902 * @param aAppUnitsPerDevPixel The number of app units in a device pixel, 903 * for conversion. Most of the time you'll 904 * pass this from the current PresContext if 905 * available. 906 * @param aHasBorderRadius If this inset box blur has a border radius 907 * @param aInnerClipRectRadii The clip rect radii used for the inside rect's 908 * path. 909 * @param aSkipRect An area in device pixels (NOT app units!) to 910 * avoid blurring over, to prevent unnecessary work. 911 */ 912 bool InsetBoxBlur(gfxContext* aDestinationCtx, 913 mozilla::gfx::Rect aDestinationRect, 914 mozilla::gfx::Rect aShadowClipRect, 915 mozilla::gfx::sRGBColor& aShadowColor, 916 nscoord aBlurRadiusAppUnits, nscoord aSpreadRadiusAppUnits, 917 int32_t aAppUnitsPerDevPixel, bool aHasBorderRadius, 918 RectCornerRadii& aInnerClipRectRadii, 919 mozilla::gfx::Rect aSkipRect, 920 mozilla::gfx::Point aShadowOffset); 921 922 protected: 923 static void GetBlurAndSpreadRadius(DrawTarget* aDestDrawTarget, 924 int32_t aAppUnitsPerDevPixel, 925 nscoord aBlurRadius, nscoord aSpreadRadius, 926 mozilla::gfx::IntSize& aOutBlurRadius, 927 mozilla::gfx::IntSize& aOutSpreadRadius, 928 bool aConstrainSpreadRadius = true); 929 930 gfxGaussianBlur mGaussianBlur; 931 mozilla::UniquePtr<gfxContext> mOwnedContext; 932 gfxContext* mContext; // may be either mOwnedContext or mDestinationContext 933 gfxContext* mDestinationCtx; 934 935 /* This is true if the blur already has it's content transformed 936 * by mDestinationCtx's transform */ 937 bool mPreTransformed; 938 }; 939 940 #endif /* nsCSSRendering_h___ */