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