|
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 "nsLayoutUtils.h" |
|
14 #include "nsStyleStruct.h" |
|
15 #include "nsIFrame.h" |
|
16 |
|
17 class nsStyleContext; |
|
18 class nsPresContext; |
|
19 class nsRenderingContext; |
|
20 |
|
21 namespace mozilla { |
|
22 |
|
23 namespace layers { |
|
24 class ImageContainer; |
|
25 } |
|
26 |
|
27 // A CSSSizeOrRatio represents a (possibly partially specified) size for use |
|
28 // in computing image sizes. Either or both of the width and height might be |
|
29 // given. A ratio of width to height may also be given. If we at least two |
|
30 // of these then we can compute a concrete size, that is a width and height. |
|
31 struct CSSSizeOrRatio |
|
32 { |
|
33 CSSSizeOrRatio() |
|
34 : mRatio(0, 0) |
|
35 , mHasWidth(false) |
|
36 , mHasHeight(false) {} |
|
37 |
|
38 bool CanComputeConcreteSize() const |
|
39 { |
|
40 return mHasWidth + mHasHeight + HasRatio() >= 2; |
|
41 } |
|
42 bool IsConcrete() const { return mHasWidth && mHasHeight; } |
|
43 bool HasRatio() const { return mRatio.width > 0 && mRatio.height > 0; } |
|
44 bool IsEmpty() const |
|
45 { |
|
46 return (mHasWidth && mWidth <= 0) || |
|
47 (mHasHeight && mHeight <= 0) || |
|
48 mRatio.width <= 0 || mRatio.height <= 0; |
|
49 } |
|
50 |
|
51 // CanComputeConcreteSize must return true when ComputeConcreteSize is |
|
52 // called. |
|
53 nsSize ComputeConcreteSize() const; |
|
54 |
|
55 void SetWidth(nscoord aWidth) |
|
56 { |
|
57 mWidth = aWidth; |
|
58 mHasWidth = true; |
|
59 if (mHasHeight) { |
|
60 mRatio = nsSize(mWidth, mHeight); |
|
61 } |
|
62 } |
|
63 void SetHeight(nscoord aHeight) |
|
64 { |
|
65 mHeight = aHeight; |
|
66 mHasHeight = true; |
|
67 if (mHasWidth) { |
|
68 mRatio = nsSize(mWidth, mHeight); |
|
69 } |
|
70 } |
|
71 void SetSize(const nsSize& aSize) |
|
72 { |
|
73 mWidth = aSize.width; |
|
74 mHeight = aSize.height; |
|
75 mHasWidth = true; |
|
76 mHasHeight = true; |
|
77 mRatio = aSize; |
|
78 } |
|
79 void SetRatio(const nsSize& aRatio) |
|
80 { |
|
81 MOZ_ASSERT(!mHasWidth || !mHasHeight, |
|
82 "Probably shouldn't be setting a ratio if we have a concrete size"); |
|
83 mRatio = aRatio; |
|
84 } |
|
85 |
|
86 nsSize mRatio; |
|
87 nscoord mWidth; |
|
88 nscoord mHeight; |
|
89 bool mHasWidth; |
|
90 bool mHasHeight; |
|
91 }; |
|
92 |
|
93 } |
|
94 |
|
95 /** |
|
96 * This is a small wrapper class to encapsulate image drawing that can draw an |
|
97 * nsStyleImage image, which may internally be a real image, a sub image, or a |
|
98 * CSS gradient. |
|
99 * |
|
100 * @note Always call the member functions in the order of PrepareImage(), |
|
101 * SetSize(), and Draw*(). |
|
102 */ |
|
103 class nsImageRenderer { |
|
104 public: |
|
105 typedef mozilla::layers::LayerManager LayerManager; |
|
106 typedef mozilla::layers::ImageContainer ImageContainer; |
|
107 |
|
108 enum { |
|
109 FLAG_SYNC_DECODE_IMAGES = 0x01, |
|
110 FLAG_PAINTING_TO_WINDOW = 0x02 |
|
111 }; |
|
112 enum FitType |
|
113 { |
|
114 CONTAIN, |
|
115 COVER |
|
116 }; |
|
117 |
|
118 nsImageRenderer(nsIFrame* aForFrame, const nsStyleImage* aImage, uint32_t aFlags); |
|
119 ~nsImageRenderer(); |
|
120 /** |
|
121 * Populates member variables to get ready for rendering. |
|
122 * @return true iff the image is ready, and there is at least a pixel to |
|
123 * draw. |
|
124 */ |
|
125 bool PrepareImage(); |
|
126 |
|
127 /** |
|
128 * The three Compute*Size functions correspond to the sizing algorthms and |
|
129 * definitions from the CSS Image Values and Replaced Content spec. See |
|
130 * http://dev.w3.org/csswg/css-images-3/#sizing . |
|
131 */ |
|
132 |
|
133 /** |
|
134 * Compute the intrinsic size of the image as defined in the CSS Image Values |
|
135 * spec. The intrinsic size is the unscaled size which the image would ideally |
|
136 * like to be in app units. |
|
137 */ |
|
138 mozilla::CSSSizeOrRatio ComputeIntrinsicSize(); |
|
139 |
|
140 /** |
|
141 * Compute the size of the rendered image using either the 'cover' or |
|
142 * 'contain' constraints (aFitType). |
|
143 * aIntrinsicRatio may be an invalid ratio, that is one or both of its |
|
144 * dimensions can be less than or equal to zero. |
|
145 */ |
|
146 static nsSize ComputeConstrainedSize(const nsSize& aConstrainingSize, |
|
147 const nsSize& aIntrinsicRatio, |
|
148 FitType aFitType); |
|
149 /** |
|
150 * Compute the size of the rendered image (the concrete size) where no cover/ |
|
151 * contain constraints are given. The 'default algorithm' from the CSS Image |
|
152 * Values spec. |
|
153 */ |
|
154 static nsSize ComputeConcreteSize(const mozilla::CSSSizeOrRatio& aSpecifiedSize, |
|
155 const mozilla::CSSSizeOrRatio& aIntrinsicSize, |
|
156 const nsSize& aDefaultSize); |
|
157 |
|
158 /** |
|
159 * Set this image's preferred size. This will be its intrinsic size where |
|
160 * specified and the default size where it is not. Used as the unscaled size |
|
161 * when rendering the image. |
|
162 */ |
|
163 void SetPreferredSize(const mozilla::CSSSizeOrRatio& aIntrinsicSize, |
|
164 const nsSize& aDefaultSize); |
|
165 |
|
166 /** |
|
167 * Draws the image to the target rendering context. |
|
168 * aSrc is a rect on the source image which will be mapped to aDest. |
|
169 * @see nsLayoutUtils::DrawImage() for other parameters. |
|
170 */ |
|
171 void Draw(nsPresContext* aPresContext, |
|
172 nsRenderingContext& aRenderingContext, |
|
173 const nsRect& aDirtyRect, |
|
174 const nsRect& aFill, |
|
175 const nsRect& aDest, |
|
176 const mozilla::CSSIntRect& aSrc); |
|
177 /** |
|
178 * Draws the image to the target rendering context using background-specific |
|
179 * arguments. |
|
180 * @see nsLayoutUtils::DrawImage() for parameters. |
|
181 */ |
|
182 void DrawBackground(nsPresContext* aPresContext, |
|
183 nsRenderingContext& aRenderingContext, |
|
184 const nsRect& aDest, |
|
185 const nsRect& aFill, |
|
186 const nsPoint& aAnchor, |
|
187 const nsRect& aDirty); |
|
188 |
|
189 /** |
|
190 * Draw the image to a single component of a border-image style rendering. |
|
191 * aFill The destination rect to be drawn into |
|
192 * aSrc is the part of the image to be rendered into a tile (aUnitSize in |
|
193 * aFill), if aSrc and the dest tile are different sizes, the image will be |
|
194 * scaled to map aSrc onto the dest tile. |
|
195 * aHFill and aVFill are the repeat patterns for the component - |
|
196 * NS_STYLE_BORDER_IMAGE_REPEAT_* |
|
197 * aUnitSize The scaled size of a single source rect (in destination coords) |
|
198 * aIndex identifies the component: 0 1 2 |
|
199 * 3 4 5 |
|
200 * 6 7 8 |
|
201 */ |
|
202 void |
|
203 DrawBorderImageComponent(nsPresContext* aPresContext, |
|
204 nsRenderingContext& aRenderingContext, |
|
205 const nsRect& aDirtyRect, |
|
206 const nsRect& aFill, |
|
207 const mozilla::CSSIntRect& aSrc, |
|
208 uint8_t aHFill, |
|
209 uint8_t aVFill, |
|
210 const nsSize& aUnitSize, |
|
211 uint8_t aIndex); |
|
212 |
|
213 bool IsRasterImage(); |
|
214 bool IsAnimatedImage(); |
|
215 already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager); |
|
216 |
|
217 bool IsReady() { return mIsReady; } |
|
218 |
|
219 private: |
|
220 /** |
|
221 * Helper method for creating a gfxDrawable from mPaintServerFrame or |
|
222 * mImageElementSurface. |
|
223 * Requires mType is eStyleImageType_Element. |
|
224 * Returns null if we cannot create the drawable. |
|
225 */ |
|
226 already_AddRefed<gfxDrawable> DrawableForElement(const nsRect& aImageRect, |
|
227 nsRenderingContext& aRenderingContext); |
|
228 |
|
229 nsIFrame* mForFrame; |
|
230 const nsStyleImage* mImage; |
|
231 nsStyleImageType mType; |
|
232 nsCOMPtr<imgIContainer> mImageContainer; |
|
233 nsRefPtr<nsStyleGradient> mGradientData; |
|
234 nsIFrame* mPaintServerFrame; |
|
235 nsLayoutUtils::SurfaceFromElementResult mImageElementSurface; |
|
236 bool mIsReady; |
|
237 nsSize mSize; // unscaled size of the image, in app units |
|
238 uint32_t mFlags; |
|
239 }; |
|
240 |
|
241 /** |
|
242 * A struct representing all the information needed to paint a background |
|
243 * image to some target, taking into account all CSS background-* properties. |
|
244 * See PrepareBackgroundLayer. |
|
245 */ |
|
246 struct nsBackgroundLayerState { |
|
247 /** |
|
248 * @param aFlags some combination of nsCSSRendering::PAINTBG_* flags |
|
249 */ |
|
250 nsBackgroundLayerState(nsIFrame* aForFrame, const nsStyleImage* aImage, uint32_t aFlags) |
|
251 : mImageRenderer(aForFrame, aImage, aFlags), mCompositingOp(gfxContext::OPERATOR_OVER) {} |
|
252 |
|
253 /** |
|
254 * The nsImageRenderer that will be used to draw the background. |
|
255 */ |
|
256 nsImageRenderer mImageRenderer; |
|
257 /** |
|
258 * A rectangle that one copy of the image tile is mapped onto. Same |
|
259 * coordinate system as aBorderArea/aBGClipRect passed into |
|
260 * PrepareBackgroundLayer. |
|
261 */ |
|
262 nsRect mDestArea; |
|
263 /** |
|
264 * The actual rectangle that should be filled with (complete or partial) |
|
265 * image tiles. Same coordinate system as aBorderArea/aBGClipRect passed into |
|
266 * PrepareBackgroundLayer. |
|
267 */ |
|
268 nsRect mFillArea; |
|
269 /** |
|
270 * The anchor point that should be snapped to a pixel corner. Same |
|
271 * coordinate system as aBorderArea/aBGClipRect passed into |
|
272 * PrepareBackgroundLayer. |
|
273 */ |
|
274 nsPoint mAnchor; |
|
275 /** |
|
276 * The compositing operation that the image should use |
|
277 */ |
|
278 gfxContext::GraphicsOperator mCompositingOp; |
|
279 }; |
|
280 |
|
281 struct nsCSSRendering { |
|
282 /** |
|
283 * Initialize any static variables used by nsCSSRendering. |
|
284 */ |
|
285 static void Init(); |
|
286 |
|
287 /** |
|
288 * Clean up any static variables used by nsCSSRendering. |
|
289 */ |
|
290 static void Shutdown(); |
|
291 |
|
292 static void PaintBoxShadowInner(nsPresContext* aPresContext, |
|
293 nsRenderingContext& aRenderingContext, |
|
294 nsIFrame* aForFrame, |
|
295 const nsRect& aFrameArea, |
|
296 const nsRect& aDirtyRect); |
|
297 |
|
298 static void PaintBoxShadowOuter(nsPresContext* aPresContext, |
|
299 nsRenderingContext& aRenderingContext, |
|
300 nsIFrame* aForFrame, |
|
301 const nsRect& aFrameArea, |
|
302 const nsRect& aDirtyRect, |
|
303 float aOpacity = 1.0); |
|
304 |
|
305 static void ComputePixelRadii(const nscoord *aAppUnitsRadii, |
|
306 nscoord aAppUnitsPerPixel, |
|
307 gfxCornerSizes *oBorderRadii); |
|
308 |
|
309 /** |
|
310 * Render the border for an element using css rendering rules |
|
311 * for borders. aSkipSides is a bitmask of the sides to skip |
|
312 * when rendering. If 0 then no sides are skipped. |
|
313 */ |
|
314 static void PaintBorder(nsPresContext* aPresContext, |
|
315 nsRenderingContext& aRenderingContext, |
|
316 nsIFrame* aForFrame, |
|
317 const nsRect& aDirtyRect, |
|
318 const nsRect& aBorderArea, |
|
319 nsStyleContext* aStyleContext, |
|
320 int aSkipSides = 0); |
|
321 |
|
322 /** |
|
323 * Like PaintBorder, but taking an nsStyleBorder argument instead of |
|
324 * getting it from aStyleContext. |
|
325 */ |
|
326 static void PaintBorderWithStyleBorder(nsPresContext* aPresContext, |
|
327 nsRenderingContext& aRenderingContext, |
|
328 nsIFrame* aForFrame, |
|
329 const nsRect& aDirtyRect, |
|
330 const nsRect& aBorderArea, |
|
331 const nsStyleBorder& aBorderStyle, |
|
332 nsStyleContext* aStyleContext, |
|
333 int aSkipSides = 0); |
|
334 |
|
335 |
|
336 /** |
|
337 * Render the outline for an element using css rendering rules |
|
338 * for borders. aSkipSides is a bitmask of the sides to skip |
|
339 * when rendering. If 0 then no sides are skipped. |
|
340 */ |
|
341 static void PaintOutline(nsPresContext* aPresContext, |
|
342 nsRenderingContext& aRenderingContext, |
|
343 nsIFrame* aForFrame, |
|
344 const nsRect& aDirtyRect, |
|
345 const nsRect& aBorderArea, |
|
346 nsStyleContext* aStyleContext); |
|
347 |
|
348 /** |
|
349 * Render keyboard focus on an element. |
|
350 * |aFocusRect| is the outer rectangle of the focused element. |
|
351 * Uses a fixed style equivalent to "1px dotted |aColor|". |
|
352 * Not used for controls, because the native theme may differ. |
|
353 */ |
|
354 static void PaintFocus(nsPresContext* aPresContext, |
|
355 nsRenderingContext& aRenderingContext, |
|
356 const nsRect& aFocusRect, |
|
357 nscolor aColor); |
|
358 |
|
359 /** |
|
360 * Render a gradient for an element. |
|
361 * aDest is the rect for a single tile of the gradient on the destination. |
|
362 * aFill is the rect on the destination to be covered by repeated tiling of |
|
363 * the gradient. |
|
364 * aSrc is the part of the gradient to be rendered into a tile (aDest), if |
|
365 * aSrc and aDest are different sizes, the image will be scaled to map aSrc |
|
366 * onto aDest. |
|
367 * aIntrinsicSize is the size of the source gradient. |
|
368 */ |
|
369 static void PaintGradient(nsPresContext* aPresContext, |
|
370 nsRenderingContext& aRenderingContext, |
|
371 nsStyleGradient* aGradient, |
|
372 const nsRect& aDirtyRect, |
|
373 const nsRect& aDest, |
|
374 const nsRect& aFill, |
|
375 const mozilla::CSSIntRect& aSrc, |
|
376 const nsSize& aIntrinsiceSize); |
|
377 |
|
378 /** |
|
379 * Find the frame whose background style should be used to draw the |
|
380 * canvas background. aForFrame must be the frame for the root element |
|
381 * whose background style should be used. This function will return |
|
382 * aForFrame unless the <body> background should be propagated, in |
|
383 * which case we return the frame associated with the <body>'s background. |
|
384 */ |
|
385 static nsIFrame* FindBackgroundStyleFrame(nsIFrame* aForFrame); |
|
386 |
|
387 /** |
|
388 * @return true if |aFrame| is a canvas frame, in the CSS sense. |
|
389 */ |
|
390 static bool IsCanvasFrame(nsIFrame* aFrame); |
|
391 |
|
392 /** |
|
393 * Fill in an aBackgroundSC to be used to paint the background |
|
394 * for an element. This applies the rules for propagating |
|
395 * backgrounds between BODY, the root element, and the canvas. |
|
396 * @return true if there is some meaningful background. |
|
397 */ |
|
398 static bool FindBackground(nsIFrame* aForFrame, |
|
399 nsStyleContext** aBackgroundSC); |
|
400 |
|
401 /** |
|
402 * As FindBackground, but the passed-in frame is known to be a root frame |
|
403 * (returned from nsCSSFrameConstructor::GetRootElementStyleFrame()) |
|
404 * and there is always some meaningful background returned. |
|
405 */ |
|
406 static nsStyleContext* FindRootFrameBackground(nsIFrame* aForFrame); |
|
407 |
|
408 /** |
|
409 * Returns background style information for the canvas. |
|
410 * |
|
411 * @param aForFrame |
|
412 * the frame used to represent the canvas, in the CSS sense (i.e. |
|
413 * nsCSSRendering::IsCanvasFrame(aForFrame) must be true) |
|
414 * @param aRootElementFrame |
|
415 * the frame representing the root element of the document |
|
416 * @param aBackground |
|
417 * contains background style information for the canvas on return |
|
418 */ |
|
419 static nsStyleContext* |
|
420 FindCanvasBackground(nsIFrame* aForFrame, nsIFrame* aRootElementFrame) |
|
421 { |
|
422 NS_ABORT_IF_FALSE(IsCanvasFrame(aForFrame), "not a canvas frame"); |
|
423 if (aRootElementFrame) |
|
424 return FindRootFrameBackground(aRootElementFrame); |
|
425 |
|
426 // This should always give transparent, so we'll fill it in with the |
|
427 // default color if needed. This seems to happen a bit while a page is |
|
428 // being loaded. |
|
429 return aForFrame->StyleContext(); |
|
430 } |
|
431 |
|
432 /** |
|
433 * Find a frame which draws a non-transparent background, |
|
434 * for various table-related and HR-related backwards-compatibility hacks. |
|
435 * This function will also stop if it finds themed frame which might draw |
|
436 * background. |
|
437 * |
|
438 * Be very hesitant if you're considering calling this function -- it's |
|
439 * usually not what you want. |
|
440 */ |
|
441 static nsIFrame* |
|
442 FindNonTransparentBackgroundFrame(nsIFrame* aFrame, |
|
443 bool aStartAtParent = false); |
|
444 |
|
445 /** |
|
446 * Determine the background color to draw taking into account print settings. |
|
447 */ |
|
448 static nscolor |
|
449 DetermineBackgroundColor(nsPresContext* aPresContext, |
|
450 nsStyleContext* aStyleContext, |
|
451 nsIFrame* aFrame, |
|
452 bool& aDrawBackgroundImage, |
|
453 bool& aDrawBackgroundColor); |
|
454 |
|
455 static nsRect |
|
456 ComputeBackgroundPositioningArea(nsPresContext* aPresContext, |
|
457 nsIFrame* aForFrame, |
|
458 const nsRect& aBorderArea, |
|
459 const nsStyleBackground& aBackground, |
|
460 const nsStyleBackground::Layer& aLayer, |
|
461 nsIFrame** aAttachedToFrame); |
|
462 |
|
463 static nsBackgroundLayerState |
|
464 PrepareBackgroundLayer(nsPresContext* aPresContext, |
|
465 nsIFrame* aForFrame, |
|
466 uint32_t aFlags, |
|
467 const nsRect& aBorderArea, |
|
468 const nsRect& aBGClipRect, |
|
469 const nsStyleBackground& aBackground, |
|
470 const nsStyleBackground::Layer& aLayer); |
|
471 |
|
472 /** |
|
473 * Render the background for an element using css rendering rules |
|
474 * for backgrounds. |
|
475 */ |
|
476 enum { |
|
477 /** |
|
478 * When this flag is passed, the element's nsDisplayBorder will be |
|
479 * painted immediately on top of this background. |
|
480 */ |
|
481 PAINTBG_WILL_PAINT_BORDER = 0x01, |
|
482 /** |
|
483 * When this flag is passed, images are synchronously decoded. |
|
484 */ |
|
485 PAINTBG_SYNC_DECODE_IMAGES = 0x02, |
|
486 /** |
|
487 * When this flag is passed, painting will go to the screen so we can |
|
488 * take advantage of the fact that it will be clipped to the viewport. |
|
489 */ |
|
490 PAINTBG_TO_WINDOW = 0x04 |
|
491 }; |
|
492 static void PaintBackground(nsPresContext* aPresContext, |
|
493 nsRenderingContext& aRenderingContext, |
|
494 nsIFrame* aForFrame, |
|
495 const nsRect& aDirtyRect, |
|
496 const nsRect& aBorderArea, |
|
497 uint32_t aFlags, |
|
498 nsRect* aBGClipRect = nullptr, |
|
499 int32_t aLayer = -1); |
|
500 |
|
501 static void PaintBackgroundColor(nsPresContext* aPresContext, |
|
502 nsRenderingContext& aRenderingContext, |
|
503 nsIFrame* aForFrame, |
|
504 const nsRect& aDirtyRect, |
|
505 const nsRect& aBorderArea, |
|
506 uint32_t aFlags); |
|
507 |
|
508 /** |
|
509 * Same as |PaintBackground|, except using the provided style structs. |
|
510 * This short-circuits the code that ensures that the root element's |
|
511 * background is drawn on the canvas. |
|
512 * The aLayer parameter allows you to paint a single layer of the background. |
|
513 * The default value for aLayer, -1, means that all layers will be painted. |
|
514 * The background color will only be painted if the back-most layer is also |
|
515 * being painted. |
|
516 */ |
|
517 static void PaintBackgroundWithSC(nsPresContext* aPresContext, |
|
518 nsRenderingContext& aRenderingContext, |
|
519 nsIFrame* aForFrame, |
|
520 const nsRect& aDirtyRect, |
|
521 const nsRect& aBorderArea, |
|
522 nsStyleContext *aStyleContext, |
|
523 const nsStyleBorder& aBorder, |
|
524 uint32_t aFlags, |
|
525 nsRect* aBGClipRect = nullptr, |
|
526 int32_t aLayer = -1); |
|
527 |
|
528 static void PaintBackgroundColorWithSC(nsPresContext* aPresContext, |
|
529 nsRenderingContext& aRenderingContext, |
|
530 nsIFrame* aForFrame, |
|
531 const nsRect& aDirtyRect, |
|
532 const nsRect& aBorderArea, |
|
533 nsStyleContext *aStyleContext, |
|
534 const nsStyleBorder& aBorder, |
|
535 uint32_t aFlags); |
|
536 /** |
|
537 * Returns the rectangle covered by the given background layer image, taking |
|
538 * into account background positioning, sizing, and repetition, but not |
|
539 * clipping. |
|
540 */ |
|
541 static nsRect GetBackgroundLayerRect(nsPresContext* aPresContext, |
|
542 nsIFrame* aForFrame, |
|
543 const nsRect& aBorderArea, |
|
544 const nsRect& aClipRect, |
|
545 const nsStyleBackground& aBackground, |
|
546 const nsStyleBackground::Layer& aLayer, |
|
547 uint32_t aFlags); |
|
548 |
|
549 /** |
|
550 * Checks if image in layer aLayer of aBackground is currently decoded. |
|
551 */ |
|
552 static bool IsBackgroundImageDecodedForStyleContextAndLayer( |
|
553 const nsStyleBackground *aBackground, uint32_t aLayer); |
|
554 |
|
555 /** |
|
556 * Checks if all images that are part of the background for aFrame are |
|
557 * currently decoded. |
|
558 */ |
|
559 static bool AreAllBackgroundImagesDecodedForFrame(nsIFrame* aFrame); |
|
560 |
|
561 /** |
|
562 * Called when we start creating a display list. The frame tree will not |
|
563 * change until a matching EndFrameTreeLocked is called. |
|
564 */ |
|
565 static void BeginFrameTreesLocked(); |
|
566 /** |
|
567 * Called when we've finished using a display list. When all |
|
568 * BeginFrameTreeLocked calls have been balanced by an EndFrameTreeLocked, |
|
569 * the frame tree may start changing again. |
|
570 */ |
|
571 static void EndFrameTreesLocked(); |
|
572 |
|
573 // Draw a border segment in the table collapsing border model without |
|
574 // beveling corners |
|
575 static void DrawTableBorderSegment(nsRenderingContext& aContext, |
|
576 uint8_t aBorderStyle, |
|
577 nscolor aBorderColor, |
|
578 const nsStyleBackground* aBGColor, |
|
579 const nsRect& aBorderRect, |
|
580 int32_t aAppUnitsPerCSSPixel, |
|
581 uint8_t aStartBevelSide = 0, |
|
582 nscoord aStartBevelOffset = 0, |
|
583 uint8_t aEndBevelSide = 0, |
|
584 nscoord aEndBevelOffset = 0); |
|
585 |
|
586 /** |
|
587 * Function for painting the decoration lines for the text. |
|
588 * NOTE: aPt, aLineSize, aAscent and aOffset are non-rounded device pixels, |
|
589 * not app units. |
|
590 * input: |
|
591 * @param aFrame the frame which needs the decoration line |
|
592 * @param aGfxContext |
|
593 * @param aDirtyRect no need to paint outside this rect |
|
594 * @param aColor the color of the decoration line |
|
595 * @param aPt the top/left edge of the text |
|
596 * @param aXInFrame the distance between aPt.x and left edge of |
|
597 * aFrame. If the decoration line is for shadow, |
|
598 * set the distance between the left edge of |
|
599 * the aFrame and the position of the text as |
|
600 * positioned without offset of the shadow. |
|
601 * @param aLineSize the width and the height of the decoration |
|
602 * line |
|
603 * @param aAscent the ascent of the text |
|
604 * @param aOffset the offset of the decoration line from |
|
605 * the baseline of the text (if the value is |
|
606 * positive, the line is lifted up) |
|
607 * @param aDecoration which line will be painted. The value can be |
|
608 * NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or |
|
609 * NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or |
|
610 * NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH. |
|
611 * @param aStyle the style of the decoration line such as |
|
612 * NS_STYLE_TEXT_DECORATION_STYLE_*. |
|
613 * @param aDescentLimit If aDescentLimit is zero or larger and the |
|
614 * underline overflows from the descent space, |
|
615 * the underline should be lifted up as far as |
|
616 * possible. Note that this does not mean the |
|
617 * underline never overflows from this |
|
618 * limitation. Because if the underline is |
|
619 * positioned to the baseline or upper, it causes |
|
620 * unreadability. Note that if this is zero |
|
621 * or larger, the underline rect may be shrunken |
|
622 * if it's possible. Therefore, this value is |
|
623 * used for strikeout line and overline too. |
|
624 */ |
|
625 static void PaintDecorationLine(nsIFrame* aFrame, |
|
626 gfxContext* aGfxContext, |
|
627 const gfxRect& aDirtyRect, |
|
628 const nscolor aColor, |
|
629 const gfxPoint& aPt, |
|
630 const gfxFloat aXInFrame, |
|
631 const gfxSize& aLineSize, |
|
632 const gfxFloat aAscent, |
|
633 const gfxFloat aOffset, |
|
634 const uint8_t aDecoration, |
|
635 const uint8_t aStyle, |
|
636 const gfxFloat aDescentLimit = -1.0); |
|
637 |
|
638 /** |
|
639 * Adds a path corresponding to the outline of the decoration line to |
|
640 * the specified context. Arguments have the same meaning as for |
|
641 * PaintDecorationLine. Currently this only works for solid |
|
642 * decorations; for other decoration styles, an empty path is added |
|
643 * to the context. |
|
644 */ |
|
645 static void DecorationLineToPath(nsIFrame* aFrame, |
|
646 gfxContext* aGfxContext, |
|
647 const gfxRect& aDirtyRect, |
|
648 const nscolor aColor, |
|
649 const gfxPoint& aPt, |
|
650 const gfxFloat aXInFrame, |
|
651 const gfxSize& aLineSize, |
|
652 const gfxFloat aAscent, |
|
653 const gfxFloat aOffset, |
|
654 const uint8_t aDecoration, |
|
655 const uint8_t aStyle, |
|
656 const gfxFloat aDescentLimit = -1.0); |
|
657 |
|
658 /** |
|
659 * Function for getting the decoration line rect for the text. |
|
660 * NOTE: aLineSize, aAscent and aOffset are non-rounded device pixels, |
|
661 * not app units. |
|
662 * input: |
|
663 * @param aPresContext |
|
664 * @param aLineSize the width and the height of the decoration |
|
665 * line |
|
666 * @param aAscent the ascent of the text |
|
667 * @param aOffset the offset of the decoration line from |
|
668 * the baseline of the text (if the value is |
|
669 * positive, the line is lifted up) |
|
670 * @param aDecoration which line will be painted. The value can be |
|
671 * NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or |
|
672 * NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or |
|
673 * NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH. |
|
674 * @param aStyle the style of the decoration line such as |
|
675 * NS_STYLE_TEXT_DECORATION_STYLE_*. |
|
676 * @param aDescentLimit If aDescentLimit is zero or larger and the |
|
677 * underline overflows from the descent space, |
|
678 * the underline should be lifted up as far as |
|
679 * possible. Note that this does not mean the |
|
680 * underline never overflows from this |
|
681 * limitation. Because if the underline is |
|
682 * positioned to the baseline or upper, it causes |
|
683 * unreadability. Note that if this is zero |
|
684 * or larger, the underline rect may be shrunken |
|
685 * if it's possible. Therefore, this value is |
|
686 * used for strikeout line and overline too. |
|
687 * output: |
|
688 * @return the decoration line rect for the input, |
|
689 * the each values are app units. |
|
690 */ |
|
691 static nsRect GetTextDecorationRect(nsPresContext* aPresContext, |
|
692 const gfxSize& aLineSize, |
|
693 const gfxFloat aAscent, |
|
694 const gfxFloat aOffset, |
|
695 const uint8_t aDecoration, |
|
696 const uint8_t aStyle, |
|
697 const gfxFloat aDescentLimit = -1.0); |
|
698 |
|
699 static gfxContext::GraphicsOperator GetGFXBlendMode(uint8_t mBlendMode) { |
|
700 switch (mBlendMode) { |
|
701 case NS_STYLE_BLEND_NORMAL: return gfxContext::OPERATOR_OVER; |
|
702 case NS_STYLE_BLEND_MULTIPLY: return gfxContext::OPERATOR_MULTIPLY; |
|
703 case NS_STYLE_BLEND_SCREEN: return gfxContext::OPERATOR_SCREEN; |
|
704 case NS_STYLE_BLEND_OVERLAY: return gfxContext::OPERATOR_OVERLAY; |
|
705 case NS_STYLE_BLEND_DARKEN: return gfxContext::OPERATOR_DARKEN; |
|
706 case NS_STYLE_BLEND_LIGHTEN: return gfxContext::OPERATOR_LIGHTEN; |
|
707 case NS_STYLE_BLEND_COLOR_DODGE: return gfxContext::OPERATOR_COLOR_DODGE; |
|
708 case NS_STYLE_BLEND_COLOR_BURN: return gfxContext::OPERATOR_COLOR_BURN; |
|
709 case NS_STYLE_BLEND_HARD_LIGHT: return gfxContext::OPERATOR_HARD_LIGHT; |
|
710 case NS_STYLE_BLEND_SOFT_LIGHT: return gfxContext::OPERATOR_SOFT_LIGHT; |
|
711 case NS_STYLE_BLEND_DIFFERENCE: return gfxContext::OPERATOR_DIFFERENCE; |
|
712 case NS_STYLE_BLEND_EXCLUSION: return gfxContext::OPERATOR_EXCLUSION; |
|
713 case NS_STYLE_BLEND_HUE: return gfxContext::OPERATOR_HUE; |
|
714 case NS_STYLE_BLEND_SATURATION: return gfxContext::OPERATOR_SATURATION; |
|
715 case NS_STYLE_BLEND_COLOR: return gfxContext::OPERATOR_COLOR; |
|
716 case NS_STYLE_BLEND_LUMINOSITY: return gfxContext::OPERATOR_LUMINOSITY; |
|
717 default: MOZ_ASSERT(false); return gfxContext::OPERATOR_OVER; |
|
718 } |
|
719 |
|
720 return gfxContext::OPERATOR_OVER; |
|
721 } |
|
722 |
|
723 protected: |
|
724 static gfxRect GetTextDecorationRectInternal(const gfxPoint& aPt, |
|
725 const gfxSize& aLineSize, |
|
726 const gfxFloat aAscent, |
|
727 const gfxFloat aOffset, |
|
728 const uint8_t aDecoration, |
|
729 const uint8_t aStyle, |
|
730 const gfxFloat aDscentLimit); |
|
731 |
|
732 /** |
|
733 * Returns inflated rect for painting a decoration line. |
|
734 * Complex style decoration lines should be painted from leftmost of nearest |
|
735 * ancestor block box because that makes better look of connection of lines |
|
736 * for different nodes. ExpandPaintingRectForDecorationLine() returns |
|
737 * a rect for actual painting rect for the clipped rect. |
|
738 * |
|
739 * input: |
|
740 * @param aFrame the frame which needs the decoration line. |
|
741 * @param aStyle the style of the complex decoration line |
|
742 * NS_STYLE_TEXT_DECORATION_STYLE_DOTTED or |
|
743 * NS_STYLE_TEXT_DECORATION_STYLE_DASHED or |
|
744 * NS_STYLE_TEXT_DECORATION_STYLE_WAVY. |
|
745 * @param aClippedRect the clipped rect for the decoration line. |
|
746 * in other words, visible area of the line. |
|
747 * @param aXInFrame the distance between left edge of aFrame and |
|
748 * aClippedRect.pos.x. |
|
749 * @param aCycleLength the width of one cycle of the line style. |
|
750 */ |
|
751 static gfxRect ExpandPaintingRectForDecorationLine( |
|
752 nsIFrame* aFrame, |
|
753 const uint8_t aStyle, |
|
754 const gfxRect &aClippedRect, |
|
755 const gfxFloat aXInFrame, |
|
756 const gfxFloat aCycleLength); |
|
757 }; |
|
758 |
|
759 /* |
|
760 * nsContextBoxBlur |
|
761 * Creates an 8-bit alpha channel context for callers to draw in, blurs the |
|
762 * contents of that context and applies it as a 1-color mask on a |
|
763 * different existing context. Uses gfxAlphaBoxBlur as its back end. |
|
764 * |
|
765 * You must call Init() first to create a suitable temporary surface to draw |
|
766 * on. You must then draw any desired content onto the given context, then |
|
767 * call DoPaint() to apply the blurred content as a single-color mask. You |
|
768 * can only call Init() once, so objects cannot be reused. |
|
769 * |
|
770 * This is very useful for creating drop shadows or silhouettes. |
|
771 */ |
|
772 class nsContextBoxBlur { |
|
773 public: |
|
774 enum { |
|
775 FORCE_MASK = 0x01 |
|
776 }; |
|
777 /** |
|
778 * Prepares a gfxContext to draw on. Do not call this twice; if you want |
|
779 * to get the gfxContext again use GetContext(). |
|
780 * |
|
781 * @param aRect The coordinates of the surface to create. |
|
782 * All coordinates must be in app units. |
|
783 * This must not include the blur radius, pass |
|
784 * it as the second parameter and everything |
|
785 * is taken care of. |
|
786 * |
|
787 * @param aBlurRadius The blur radius in app units. |
|
788 * |
|
789 * @param aAppUnitsPerDevPixel The number of app units in a device pixel, |
|
790 * for conversion. Most of the time you'll |
|
791 * pass this from the current PresContext if |
|
792 * available. |
|
793 * |
|
794 * @param aDestinationCtx The graphics context to apply the blurred |
|
795 * mask to when you call DoPaint(). Make sure |
|
796 * it is not destroyed before you call |
|
797 * DoPaint(). To set the color of the |
|
798 * resulting blurred graphic mask, you must |
|
799 * set the color on this context before |
|
800 * calling Init(). |
|
801 * |
|
802 * @param aDirtyRect The absolute dirty rect in app units. Used to |
|
803 * optimize the temporary surface size and speed up blur. |
|
804 * |
|
805 * @param aSkipRect An area in device pixels (NOT app units!) to avoid |
|
806 * blurring over, to prevent unnecessary work. |
|
807 * |
|
808 * @param aFlags FORCE_MASK to ensure that the content drawn to the |
|
809 * returned gfxContext is used as a mask, and not |
|
810 * drawn directly to aDestinationCtx. |
|
811 * |
|
812 * @return A blank 8-bit alpha-channel-only graphics context to |
|
813 * draw on, or null on error. Must not be freed. The |
|
814 * context has a device offset applied to it given by |
|
815 * aRect. This means you can use coordinates as if it |
|
816 * were at the desired position at aRect and you don't |
|
817 * need to worry about translating any coordinates to |
|
818 * draw on this temporary surface. |
|
819 * |
|
820 * If aBlurRadius is 0, the returned context is aDestinationCtx and |
|
821 * DoPaint() does nothing, because no blurring is required. Therefore, you |
|
822 * should prepare the destination context as if you were going to draw |
|
823 * directly on it instead of any temporary surface created in this class. |
|
824 */ |
|
825 gfxContext* Init(const nsRect& aRect, nscoord aSpreadRadius, |
|
826 nscoord aBlurRadius, |
|
827 int32_t aAppUnitsPerDevPixel, gfxContext* aDestinationCtx, |
|
828 const nsRect& aDirtyRect, const gfxRect* aSkipRect, |
|
829 uint32_t aFlags = 0); |
|
830 |
|
831 /** |
|
832 * Does the actual blurring and mask applying. Users of this object *must* |
|
833 * have called Init() first, then have drawn whatever they want to be |
|
834 * blurred onto the internal gfxContext before calling this. |
|
835 */ |
|
836 void DoPaint(); |
|
837 |
|
838 /** |
|
839 * Gets the internal gfxContext at any time. Must not be freed. Avoid |
|
840 * calling this before calling Init() since the context would not be |
|
841 * constructed at that point. |
|
842 */ |
|
843 gfxContext* GetContext(); |
|
844 |
|
845 |
|
846 /** |
|
847 * Get the margin associated with the given blur radius, i.e., the |
|
848 * additional area that might be painted as a result of it. (The |
|
849 * margin for a spread radius is itself, on all sides.) |
|
850 */ |
|
851 static nsMargin GetBlurRadiusMargin(nscoord aBlurRadius, |
|
852 int32_t aAppUnitsPerDevPixel); |
|
853 |
|
854 /** |
|
855 * Blurs a coloured rectangle onto aDestinationCtx. This is equivalent |
|
856 * to calling Init(), drawing a rectangle onto the returned surface |
|
857 * and then calling DoPaint, but may let us optimize better in the |
|
858 * backend. |
|
859 * |
|
860 * @param aDestinationCtx The destination to blur to. |
|
861 * @param aRect The rectangle to blur in app units. |
|
862 * @param aAppUnitsPerDevPixel The number of app units in a device pixel, |
|
863 * for conversion. Most of the time you'll |
|
864 * pass this from the current PresContext if |
|
865 * available. |
|
866 * @param aCornerRadii Corner radii for aRect, if it is a rounded |
|
867 * rectangle. |
|
868 * @param aBlurRadius The blur radius in app units. |
|
869 * @param aShadowColor The color to draw the blurred shadow. |
|
870 * @param aDirtyRect The absolute dirty rect in app units. Used to |
|
871 * optimize the temporary surface size and speed up blur. |
|
872 * @param aSkipRect An area in device pixels (NOT app units!) to avoid |
|
873 * blurring over, to prevent unnecessary work. |
|
874 */ |
|
875 static void BlurRectangle(gfxContext* aDestinationCtx, |
|
876 const nsRect& aRect, |
|
877 int32_t aAppUnitsPerDevPixel, |
|
878 gfxCornerSizes* aCornerRadii, |
|
879 nscoord aBlurRadius, |
|
880 const gfxRGBA& aShadowColor, |
|
881 const nsRect& aDirtyRect, |
|
882 const gfxRect& aSkipRect); |
|
883 |
|
884 protected: |
|
885 gfxAlphaBoxBlur blur; |
|
886 nsRefPtr<gfxContext> mContext; |
|
887 gfxContext* mDestinationCtx; |
|
888 |
|
889 /* This is true if the blur already has it's content transformed |
|
890 * by mDestinationCtx's transform */ |
|
891 bool mPreTransformed; |
|
892 |
|
893 }; |
|
894 |
|
895 #endif /* nsCSSRendering_h___ */ |