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