1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /* utility functions for drawing borders and backgrounds */
39 :
40 : #ifndef nsCSSRendering_h___
41 : #define nsCSSRendering_h___
42 :
43 : #include "nsStyleConsts.h"
44 : #include "gfxBlur.h"
45 : #include "gfxContext.h"
46 : #include "gfxImageSurface.h"
47 :
48 : struct nsPoint;
49 : class nsStyleContext;
50 : class nsPresContext;
51 : class nsRenderingContext;
52 :
53 : struct nsCSSRendering {
54 : /**
55 : * Initialize any static variables used by nsCSSRendering.
56 : */
57 : static void Init();
58 :
59 : /**
60 : * Clean up any static variables used by nsCSSRendering.
61 : */
62 : static void Shutdown();
63 :
64 : static void PaintBoxShadowInner(nsPresContext* aPresContext,
65 : nsRenderingContext& aRenderingContext,
66 : nsIFrame* aForFrame,
67 : const nsRect& aFrameArea,
68 : const nsRect& aDirtyRect);
69 :
70 : static void PaintBoxShadowOuter(nsPresContext* aPresContext,
71 : nsRenderingContext& aRenderingContext,
72 : nsIFrame* aForFrame,
73 : const nsRect& aFrameArea,
74 : const nsRect& aDirtyRect);
75 :
76 : static void ComputePixelRadii(const nscoord *aAppUnitsRadii,
77 : nscoord aAppUnitsPerPixel,
78 : gfxCornerSizes *oBorderRadii);
79 :
80 : /**
81 : * Render the border for an element using css rendering rules
82 : * for borders. aSkipSides is a bitmask of the sides to skip
83 : * when rendering. If 0 then no sides are skipped.
84 : */
85 : static void PaintBorder(nsPresContext* aPresContext,
86 : nsRenderingContext& aRenderingContext,
87 : nsIFrame* aForFrame,
88 : const nsRect& aDirtyRect,
89 : const nsRect& aBorderArea,
90 : nsStyleContext* aStyleContext,
91 : PRIntn aSkipSides = 0);
92 :
93 : /**
94 : * Like PaintBorder, but taking an nsStyleBorder argument instead of
95 : * getting it from aStyleContext.
96 : */
97 : static void PaintBorderWithStyleBorder(nsPresContext* aPresContext,
98 : nsRenderingContext& aRenderingContext,
99 : nsIFrame* aForFrame,
100 : const nsRect& aDirtyRect,
101 : const nsRect& aBorderArea,
102 : const nsStyleBorder& aBorderStyle,
103 : nsStyleContext* aStyleContext,
104 : PRIntn aSkipSides = 0);
105 :
106 :
107 : /**
108 : * Render the outline for an element using css rendering rules
109 : * for borders. aSkipSides is a bitmask of the sides to skip
110 : * when rendering. If 0 then no sides are skipped.
111 : */
112 : static void PaintOutline(nsPresContext* aPresContext,
113 : nsRenderingContext& aRenderingContext,
114 : nsIFrame* aForFrame,
115 : const nsRect& aDirtyRect,
116 : const nsRect& aBorderArea,
117 : nsStyleContext* aStyleContext);
118 :
119 : /**
120 : * Render keyboard focus on an element.
121 : * |aFocusRect| is the outer rectangle of the focused element.
122 : * Uses a fixed style equivalent to "1px dotted |aColor|".
123 : * Not used for controls, because the native theme may differ.
124 : */
125 : static void PaintFocus(nsPresContext* aPresContext,
126 : nsRenderingContext& aRenderingContext,
127 : const nsRect& aFocusRect,
128 : nscolor aColor);
129 :
130 : /**
131 : * Render a gradient for an element.
132 : */
133 : static void PaintGradient(nsPresContext* aPresContext,
134 : nsRenderingContext& aRenderingContext,
135 : nsStyleGradient* aGradient,
136 : const nsRect& aDirtyRect,
137 : const nsRect& aOneCellArea,
138 : const nsRect& aFillArea);
139 :
140 : /**
141 : * Find the frame whose background style should be used to draw the
142 : * canvas background. aForFrame must be the frame for the root element
143 : * whose background style should be used. This function will return
144 : * aForFrame unless the <body> background should be propagated, in
145 : * which case we return the frame associated with the <body>'s background.
146 : */
147 : static nsIFrame* FindBackgroundStyleFrame(nsIFrame* aForFrame);
148 :
149 : /**
150 : * @return true if |aFrame| is a canvas frame, in the CSS sense.
151 : */
152 : static bool IsCanvasFrame(nsIFrame* aFrame);
153 :
154 : /**
155 : * Fill in an aBackgroundSC to be used to paint the background
156 : * for an element. This applies the rules for propagating
157 : * backgrounds between BODY, the root element, and the canvas.
158 : * @return true if there is some meaningful background.
159 : */
160 : static bool FindBackground(nsPresContext* aPresContext,
161 : nsIFrame* aForFrame,
162 : nsStyleContext** aBackgroundSC);
163 :
164 : /**
165 : * As FindBackground, but the passed-in frame is known to be a root frame
166 : * (returned from nsCSSFrameConstructor::GetRootElementStyleFrame())
167 : * and there is always some meaningful background returned.
168 : */
169 : static nsStyleContext* FindRootFrameBackground(nsIFrame* aForFrame);
170 :
171 : /**
172 : * Returns background style information for the canvas.
173 : *
174 : * @param aForFrame
175 : * the frame used to represent the canvas, in the CSS sense (i.e.
176 : * nsCSSRendering::IsCanvasFrame(aForFrame) must be true)
177 : * @param aRootElementFrame
178 : * the frame representing the root element of the document
179 : * @param aBackground
180 : * contains background style information for the canvas on return
181 : */
182 : static nsStyleContext*
183 0 : FindCanvasBackground(nsIFrame* aForFrame, nsIFrame* aRootElementFrame)
184 : {
185 0 : NS_ABORT_IF_FALSE(IsCanvasFrame(aForFrame), "not a canvas frame");
186 0 : if (aRootElementFrame)
187 0 : return FindRootFrameBackground(aRootElementFrame);
188 :
189 : // This should always give transparent, so we'll fill it in with the
190 : // default color if needed. This seems to happen a bit while a page is
191 : // being loaded.
192 0 : return aForFrame->GetStyleContext();
193 : }
194 :
195 : /**
196 : * Find a frame which draws a non-transparent background,
197 : * for various table-related and HR-related backwards-compatibility hacks.
198 : * This function will also stop if it finds themed frame which might draw
199 : * background.
200 : *
201 : * Be very hesitant if you're considering calling this function -- it's
202 : * usually not what you want.
203 : */
204 : static nsIFrame*
205 : FindNonTransparentBackgroundFrame(nsIFrame* aFrame,
206 : bool aStartAtParent = false);
207 :
208 : /**
209 : * Determine the background color to draw taking into account print settings.
210 : */
211 : static nscolor
212 : DetermineBackgroundColor(nsPresContext* aPresContext,
213 : nsStyleContext* aStyleContext,
214 : nsIFrame* aFrame);
215 :
216 : /**
217 : * Render the background for an element using css rendering rules
218 : * for backgrounds.
219 : */
220 : enum {
221 : /**
222 : * When this flag is passed, the element's nsDisplayBorder will be
223 : * painted immediately on top of this background.
224 : */
225 : PAINTBG_WILL_PAINT_BORDER = 0x01,
226 : /**
227 : * When this flag is passed, images are synchronously decoded.
228 : */
229 : PAINTBG_SYNC_DECODE_IMAGES = 0x02,
230 : /**
231 : * When this flag is passed, painting will go to the screen so we can
232 : * take advantage of the fact that it will be clipped to the viewport.
233 : */
234 : PAINTBG_TO_WINDOW = 0x04
235 : };
236 : static void PaintBackground(nsPresContext* aPresContext,
237 : nsRenderingContext& aRenderingContext,
238 : nsIFrame* aForFrame,
239 : const nsRect& aDirtyRect,
240 : const nsRect& aBorderArea,
241 : PRUint32 aFlags,
242 : nsRect* aBGClipRect = nsnull);
243 :
244 : /**
245 : * Same as |PaintBackground|, except using the provided style structs.
246 : * This short-circuits the code that ensures that the root element's
247 : * background is drawn on the canvas.
248 : */
249 : static void PaintBackgroundWithSC(nsPresContext* aPresContext,
250 : nsRenderingContext& aRenderingContext,
251 : nsIFrame* aForFrame,
252 : const nsRect& aDirtyRect,
253 : const nsRect& aBorderArea,
254 : nsStyleContext *aStyleContext,
255 : const nsStyleBorder& aBorder,
256 : PRUint32 aFlags,
257 : nsRect* aBGClipRect = nsnull);
258 :
259 : /**
260 : * Returns the rectangle covered by the given background layer image, taking
261 : * into account background positioning, sizing, and repetition, but not
262 : * clipping.
263 : */
264 : static nsRect GetBackgroundLayerRect(nsPresContext* aPresContext,
265 : nsIFrame* aForFrame,
266 : const nsRect& aBorderArea,
267 : const nsStyleBackground& aBackground,
268 : const nsStyleBackground::Layer& aLayer);
269 :
270 : /**
271 : * Called by the presShell when painting is finished, so we can clear our
272 : * inline background data cache.
273 : */
274 : static void DidPaint();
275 :
276 : // Draw a border segment in the table collapsing border model without
277 : // beveling corners
278 : static void DrawTableBorderSegment(nsRenderingContext& aContext,
279 : PRUint8 aBorderStyle,
280 : nscolor aBorderColor,
281 : const nsStyleBackground* aBGColor,
282 : const nsRect& aBorderRect,
283 : PRInt32 aAppUnitsPerCSSPixel,
284 : PRUint8 aStartBevelSide = 0,
285 : nscoord aStartBevelOffset = 0,
286 : PRUint8 aEndBevelSide = 0,
287 : nscoord aEndBevelOffset = 0);
288 :
289 : /**
290 : * Function for painting the decoration lines for the text.
291 : * NOTE: aPt, aLineSize, aAscent and aOffset are non-rounded device pixels,
292 : * not app units.
293 : * input:
294 : * @param aGfxContext
295 : * @param aDirtyRect no need to paint outside this rect
296 : * @param aColor the color of the decoration line
297 : * @param aPt the top/left edge of the text
298 : * @param aLineSize the width and the height of the decoration
299 : * line
300 : * @param aAscent the ascent of the text
301 : * @param aOffset the offset of the decoration line from
302 : * the baseline of the text (if the value is
303 : * positive, the line is lifted up)
304 : * @param aDecoration which line will be painted. The value can be
305 : * NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
306 : * NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
307 : * NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
308 : * @param aStyle the style of the decoration line such as
309 : * NS_STYLE_TEXT_DECORATION_STYLE_*.
310 : * @param aDescentLimit If aDescentLimit is zero or larger and the
311 : * underline overflows from the descent space,
312 : * the underline should be lifted up as far as
313 : * possible. Note that this does not mean the
314 : * underline never overflows from this
315 : * limitation. Because if the underline is
316 : * positioned to the baseline or upper, it causes
317 : * unreadability. Note that if this is zero
318 : * or larger, the underline rect may be shrunken
319 : * if it's possible. Therefore, this value is
320 : * used for strikeout line and overline too.
321 : */
322 : static void PaintDecorationLine(gfxContext* aGfxContext,
323 : const gfxRect& aDirtyRect,
324 : const nscolor aColor,
325 : const gfxPoint& aPt,
326 : const gfxSize& aLineSize,
327 : const gfxFloat aAscent,
328 : const gfxFloat aOffset,
329 : const PRUint8 aDecoration,
330 : const PRUint8 aStyle,
331 : const gfxFloat aDescentLimit = -1.0);
332 :
333 : /**
334 : * Function for getting the decoration line rect for the text.
335 : * NOTE: aLineSize, aAscent and aOffset are non-rounded device pixels,
336 : * not app units.
337 : * input:
338 : * @param aPresContext
339 : * @param aLineSize the width and the height of the decoration
340 : * line
341 : * @param aAscent the ascent of the text
342 : * @param aOffset the offset of the decoration line from
343 : * the baseline of the text (if the value is
344 : * positive, the line is lifted up)
345 : * @param aDecoration which line will be painted. The value can be
346 : * NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
347 : * NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
348 : * NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
349 : * @param aStyle the style of the decoration line such as
350 : * NS_STYLE_TEXT_DECORATION_STYLE_*.
351 : * @param aDescentLimit If aDescentLimit is zero or larger and the
352 : * underline overflows from the descent space,
353 : * the underline should be lifted up as far as
354 : * possible. Note that this does not mean the
355 : * underline never overflows from this
356 : * limitation. Because if the underline is
357 : * positioned to the baseline or upper, it causes
358 : * unreadability. Note that if this is zero
359 : * or larger, the underline rect may be shrunken
360 : * if it's possible. Therefore, this value is
361 : * used for strikeout line and overline too.
362 : * output:
363 : * @return the decoration line rect for the input,
364 : * the each values are app units.
365 : */
366 : static nsRect GetTextDecorationRect(nsPresContext* aPresContext,
367 : const gfxSize& aLineSize,
368 : const gfxFloat aAscent,
369 : const gfxFloat aOffset,
370 : const PRUint8 aDecoration,
371 : const PRUint8 aStyle,
372 : const gfxFloat aDescentLimit = -1.0);
373 :
374 : protected:
375 : static gfxRect GetTextDecorationRectInternal(const gfxPoint& aPt,
376 : const gfxSize& aLineSize,
377 : const gfxFloat aAscent,
378 : const gfxFloat aOffset,
379 : const PRUint8 aDecoration,
380 : const PRUint8 aStyle,
381 : const gfxFloat aDscentLimit);
382 : };
383 :
384 : /*
385 : * nsContextBoxBlur
386 : * Creates an 8-bit alpha channel context for callers to draw in, blurs the
387 : * contents of that context and applies it as a 1-color mask on a
388 : * different existing context. Uses gfxAlphaBoxBlur as its back end.
389 : *
390 : * You must call Init() first to create a suitable temporary surface to draw
391 : * on. You must then draw any desired content onto the given context, then
392 : * call DoPaint() to apply the blurred content as a single-color mask. You
393 : * can only call Init() once, so objects cannot be reused.
394 : *
395 : * This is very useful for creating drop shadows or silhouettes.
396 : */
397 0 : class nsContextBoxBlur {
398 : public:
399 : enum {
400 : FORCE_MASK = 0x01
401 : };
402 : /**
403 : * Prepares a gfxContext to draw on. Do not call this twice; if you want
404 : * to get the gfxContext again use GetContext().
405 : *
406 : * @param aRect The coordinates of the surface to create.
407 : * All coordinates must be in app units.
408 : * This must not include the blur radius, pass
409 : * it as the second parameter and everything
410 : * is taken care of.
411 : *
412 : * @param aBlurRadius The blur radius in app units.
413 : *
414 : * @param aAppUnitsPerDevPixel The number of app units in a device pixel,
415 : * for conversion. Most of the time you'll
416 : * pass this from the current PresContext if
417 : * available.
418 : *
419 : * @param aDestinationCtx The graphics context to apply the blurred
420 : * mask to when you call DoPaint(). Make sure
421 : * it is not destroyed before you call
422 : * DoPaint(). To set the color of the
423 : * resulting blurred graphic mask, you must
424 : * set the color on this context before
425 : * calling Init().
426 : *
427 : * @param aDirtyRect The absolute dirty rect in app units. Used to
428 : * optimize the temporary surface size and speed up blur.
429 : *
430 : * @param aSkipRect An area in device pixels (NOT app units!) to avoid
431 : * blurring over, to prevent unnecessary work.
432 : *
433 : * @param aFlags FORCE_MASK to ensure that the content drawn to the
434 : * returned gfxContext is used as a mask, and not
435 : * drawn directly to aDestinationCtx.
436 : *
437 : * @return A blank 8-bit alpha-channel-only graphics context to
438 : * draw on, or null on error. Must not be freed. The
439 : * context has a device offset applied to it given by
440 : * aRect. This means you can use coordinates as if it
441 : * were at the desired position at aRect and you don't
442 : * need to worry about translating any coordinates to
443 : * draw on this temporary surface.
444 : *
445 : * If aBlurRadius is 0, the returned context is aDestinationCtx and
446 : * DoPaint() does nothing, because no blurring is required. Therefore, you
447 : * should prepare the destination context as if you were going to draw
448 : * directly on it instead of any temporary surface created in this class.
449 : */
450 : gfxContext* Init(const nsRect& aRect, nscoord aSpreadRadius,
451 : nscoord aBlurRadius,
452 : PRInt32 aAppUnitsPerDevPixel, gfxContext* aDestinationCtx,
453 : const nsRect& aDirtyRect, const gfxRect* aSkipRect,
454 : PRUint32 aFlags = 0);
455 :
456 : /**
457 : * Does the actual blurring/spreading. Users of this object *must*
458 : * have called Init() first, then have drawn whatever they want to be
459 : * blurred onto the internal gfxContext before calling this.
460 : */
461 : void DoEffects();
462 :
463 : /**
464 : * Does the actual blurring and mask applying. Users of this object *must*
465 : * have called Init() first, then have drawn whatever they want to be
466 : * blurred onto the internal gfxContext before calling this.
467 : */
468 : void DoPaint();
469 :
470 : /**
471 : * Gets the internal gfxContext at any time. Must not be freed. Avoid
472 : * calling this before calling Init() since the context would not be
473 : * constructed at that point.
474 : */
475 : gfxContext* GetContext();
476 :
477 :
478 : /**
479 : * Get the margin associated with the given blur radius, i.e., the
480 : * additional area that might be painted as a result of it. (The
481 : * margin for a spread radius is itself, on all sides.)
482 : */
483 : static nsMargin GetBlurRadiusMargin(nscoord aBlurRadius,
484 : PRInt32 aAppUnitsPerDevPixel);
485 :
486 : protected:
487 : gfxAlphaBoxBlur blur;
488 : nsRefPtr<gfxContext> mContext;
489 : gfxContext* mDestinationCtx;
490 :
491 : };
492 :
493 : #endif /* nsCSSRendering_h___ */
|