Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 // vim:cindent:ts=2:et:sw=2:
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/. */
7 #ifndef NS_CSS_RENDERING_BORDERS_H
8 #define NS_CSS_RENDERING_BORDERS_H
10 #include "nsColor.h"
12 class gfxContext;
13 class gfxPattern;
14 struct gfxRGBA;
16 namespace mozilla {
17 namespace gfx {
18 class GradientStops;
19 }
20 }
22 // define this to enable a bunch of debug dump info
23 #undef DEBUG_NEW_BORDERS
25 //thickness of dashed line relative to dotted line
26 #define DOT_LENGTH 1 //square
27 #define DASH_LENGTH 3 //3 times longer than dot
29 //some shorthand for side bits
30 #define SIDE_BIT_TOP (1 << NS_SIDE_TOP)
31 #define SIDE_BIT_RIGHT (1 << NS_SIDE_RIGHT)
32 #define SIDE_BIT_BOTTOM (1 << NS_SIDE_BOTTOM)
33 #define SIDE_BIT_LEFT (1 << NS_SIDE_LEFT)
34 #define SIDE_BITS_ALL (SIDE_BIT_TOP|SIDE_BIT_RIGHT|SIDE_BIT_BOTTOM|SIDE_BIT_LEFT)
36 #define C_TL NS_CORNER_TOP_LEFT
37 #define C_TR NS_CORNER_TOP_RIGHT
38 #define C_BR NS_CORNER_BOTTOM_RIGHT
39 #define C_BL NS_CORNER_BOTTOM_LEFT
41 /*
42 * Helper class that handles border rendering.
43 *
44 * appUnitsPerPixel -- current value of AUPP
45 * destContext -- the gfxContext to which the border should be rendered
46 * outsideRect -- the rectangle on the outer edge of the border
47 *
48 * For any parameter where an array of side values is passed in,
49 * they are in top, right, bottom, left order.
50 *
51 * borderStyles -- one border style enum per side
52 * borderWidths -- one border width per side
53 * borderRadii -- a gfxCornerSizes struct describing the w/h for each rounded corner.
54 * If the corner doesn't have a border radius, 0,0 should be given for it.
55 * borderColors -- one nscolor per side
56 * compositeColors -- a pointer to an array of composite color structs, or
57 * nullptr if none.
58 *
59 * skipSides -- a bit mask specifying which sides, if any, to skip
60 * backgroundColor -- the background color of the element.
61 * Used in calculating colors for 2-tone borders, such as inset and outset
62 * gapRect - a rectangle that should be clipped out to leave a gap in a border,
63 * or nullptr if none.
64 */
66 typedef enum {
67 BorderColorStyleNone,
68 BorderColorStyleSolid,
69 BorderColorStyleLight,
70 BorderColorStyleDark
71 } BorderColorStyle;
73 struct nsCSSBorderRenderer {
74 nsCSSBorderRenderer(int32_t aAppUnitsPerPixel,
75 gfxContext* aDestContext,
76 gfxRect& aOuterRect,
77 const uint8_t* aBorderStyles,
78 const gfxFloat* aBorderWidths,
79 gfxCornerSizes& aBorderRadii,
80 const nscolor* aBorderColors,
81 nsBorderColors* const* aCompositeColors,
82 int aSkipSides,
83 nscolor aBackgroundColor);
85 gfxCornerSizes mBorderCornerDimensions;
87 // destination context
88 gfxContext* mContext;
90 // the rectangle of the outside and the inside of the border
91 gfxRect mOuterRect;
92 gfxRect mInnerRect;
94 // the style and size of the border
95 const uint8_t* mBorderStyles;
96 const gfxFloat* mBorderWidths;
97 uint8_t* mSanitizedStyles;
98 gfxFloat* mSanitizedWidths;
99 gfxCornerSizes mBorderRadii;
101 // colors
102 const nscolor* mBorderColors;
103 nsBorderColors* const* mCompositeColors;
105 // core app units per pixel
106 int32_t mAUPP;
108 // misc -- which sides to skip, the background color
109 int mSkipSides;
110 nscolor mBackgroundColor;
112 // calculated values
113 bool mOneUnitBorder;
114 bool mNoBorderRadius;
115 bool mAvoidStroke;
117 // For all the sides in the bitmask, would they be rendered
118 // in an identical color and style?
119 bool AreBorderSideFinalStylesSame(uint8_t aSides);
121 // For the given style, is the given corner a solid color?
122 bool IsSolidCornerStyle(uint8_t aStyle, mozilla::css::Corner aCorner);
124 // For the given solid corner, what color style should be used?
125 BorderColorStyle BorderColorStyleForSolidCorner(uint8_t aStyle, mozilla::css::Corner aCorner);
127 //
128 // Path generation functions
129 //
131 // add the path for drawing the given corner to the context
132 void DoCornerSubPath(mozilla::css::Corner aCorner);
133 // add the path for drawing the given side without any adjacent corners to the context
134 void DoSideClipWithoutCornersSubPath(mozilla::css::Side aSide);
136 // Create a clip path for the wedge that this side of
137 // the border should take up. This is only called
138 // when we're drawing separate border sides, so we know
139 // that ADD compositing is taking place.
140 //
141 // This code needs to make sure that the individual pieces
142 // don't ever (mathematically) overlap; the pixel overlap
143 // is taken care of by the ADD compositing.
144 void DoSideClipSubPath(mozilla::css::Side aSide);
146 // Given a set of sides to fill and a color, do so in the fastest way.
147 //
148 // Stroke tends to be faster for smaller borders because it doesn't go
149 // through the tessellator, which has initialization overhead. If
150 // we're rendering all sides, we can use stroke at any thickness; we
151 // also do TL/BR pairs at 1px thickness using stroke.
152 //
153 // If we can't stroke, then if it's a TL/BR pair, we use the specific
154 // TL/BR paths. Otherwise, we do the full path and fill.
155 //
156 // Calling code is expected to only set up a clip as necessary; no
157 // clip is needed if we can render the entire border in 1 or 2 passes.
158 void FillSolidBorder(const gfxRect& aOuterRect,
159 const gfxRect& aInnerRect,
160 const gfxCornerSizes& aBorderRadii,
161 const gfxFloat *aBorderSizes,
162 int aSides,
163 const gfxRGBA& aColor);
165 //
166 // core rendering
167 //
169 // draw the border for the given sides, using the style of the first side
170 // present in the bitmask
171 void DrawBorderSides (int aSides);
173 // function used by the above to handle -moz-border-colors
174 void DrawBorderSidesCompositeColors(int aSides, const nsBorderColors *compositeColors);
176 // draw the given dashed side
177 void DrawDashedSide (mozilla::css::Side aSide);
179 // Setup the stroke style for a given side
180 void SetupStrokeStyle(mozilla::css::Side aSize);
182 // Analyze if all border sides have the same width.
183 bool AllBordersSameWidth();
185 // Analyze if all borders are 'solid' this also considers hidden or 'none'
186 // borders because they can be considered 'solid' borders of 0 width and
187 // with no color effect.
188 bool AllBordersSolid(bool *aHasCompositeColors);
190 // Create a gradient pattern that will handle the color transition for a
191 // corner.
192 already_AddRefed<gfxPattern> CreateCornerGradient(mozilla::css::Corner aCorner,
193 const gfxRGBA &aFirstColor,
194 const gfxRGBA &aSecondColor);
196 // Azure variant of CreateCornerGradient.
197 mozilla::TemporaryRef<mozilla::gfx::GradientStops>
198 CreateCornerGradient(mozilla::css::Corner aCorner, const gfxRGBA &aFirstColor,
199 const gfxRGBA &aSecondColor, mozilla::gfx::DrawTarget *aDT,
200 mozilla::gfx::Point &aPoint1, mozilla::gfx::Point &aPoint2);
202 // Draw a solid color border that is uniformly the same width.
203 void DrawSingleWidthSolidBorder();
205 // Draw any border which is solid on all sides and does not use
206 // CompositeColors.
207 void DrawNoCompositeColorSolidBorder();
208 // Draw any border which is solid on all sides and does not use
209 // CompositeColors. Using Azure.
210 void DrawNoCompositeColorSolidBorderAzure();
212 // Draw a solid border that has no border radius (i.e. is rectangular) and
213 // uses CompositeColors.
214 void DrawRectangularCompositeColors();
216 // draw the entire border
217 void DrawBorders ();
219 // utility function used for background painting as well as borders
220 static void ComputeInnerRadii(const gfxCornerSizes& aRadii,
221 const gfxFloat *aBorderSizes,
222 gfxCornerSizes *aInnerRadiiRet);
224 // Given aRadii as the border radii for a rectangle, compute the
225 // appropriate radii for another rectangle *outside* that rectangle
226 // by increasing the radii, except keeping sharp corners sharp.
227 // Used for spread box-shadows
228 static void ComputeOuterRadii(const gfxCornerSizes& aRadii,
229 const gfxFloat *aBorderSizes,
230 gfxCornerSizes *aOuterRadiiRet);
231 };
233 namespace mozilla {
235 #ifdef DEBUG_NEW_BORDERS
236 #include <stdarg.h>
238 static inline void S(const gfxPoint& p) {
239 fprintf (stderr, "[%f,%f]", p.x, p.y);
240 }
242 static inline void S(const gfxSize& s) {
243 fprintf (stderr, "[%f %f]", s.width, s.height);
244 }
246 static inline void S(const gfxRect& r) {
247 fprintf (stderr, "[%f %f %f %f]", r.pos.x, r.pos.y, r.size.width, r.size.height);
248 }
250 static inline void S(const gfxFloat f) {
251 fprintf (stderr, "%f", f);
252 }
254 static inline void S(const char *s) {
255 fprintf (stderr, "%s", s);
256 }
258 static inline void SN(const char *s = nullptr) {
259 if (s)
260 fprintf (stderr, "%s", s);
261 fprintf (stderr, "\n");
262 fflush (stderr);
263 }
265 static inline void SF(const char *fmt, ...) {
266 va_list vl;
267 va_start(vl, fmt);
268 vfprintf (stderr, fmt, vl);
269 va_end(vl);
270 }
272 static inline void SX(gfxContext *ctx) {
273 gfxPoint p = ctx->CurrentPoint();
274 fprintf (stderr, "p: %f %f\n", p.x, p.y);
275 return;
276 ctx->MoveTo(p + gfxPoint(-2, -2)); ctx->LineTo(p + gfxPoint(2, 2));
277 ctx->MoveTo(p + gfxPoint(-2, 2)); ctx->LineTo(p + gfxPoint(2, -2));
278 ctx->MoveTo(p);
279 }
282 #else
283 static inline void S(const gfxPoint& p) {}
284 static inline void S(const gfxSize& s) {}
285 static inline void S(const gfxRect& r) {}
286 static inline void S(const gfxFloat f) {}
287 static inline void S(const char *s) {}
288 static inline void SN(const char *s = nullptr) {}
289 static inline void SF(const char *fmt, ...) {}
290 static inline void SX(gfxContext *ctx) {}
291 #endif
293 }
295 #endif /* NS_CSS_RENDERING_BORDERS_H */