1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/base/nsCSSRenderingBorders.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,295 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +// vim:cindent:ts=2:et:sw=2: 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef NS_CSS_RENDERING_BORDERS_H 1.11 +#define NS_CSS_RENDERING_BORDERS_H 1.12 + 1.13 +#include "nsColor.h" 1.14 + 1.15 +class gfxContext; 1.16 +class gfxPattern; 1.17 +struct gfxRGBA; 1.18 + 1.19 +namespace mozilla { 1.20 +namespace gfx { 1.21 +class GradientStops; 1.22 +} 1.23 +} 1.24 + 1.25 +// define this to enable a bunch of debug dump info 1.26 +#undef DEBUG_NEW_BORDERS 1.27 + 1.28 +//thickness of dashed line relative to dotted line 1.29 +#define DOT_LENGTH 1 //square 1.30 +#define DASH_LENGTH 3 //3 times longer than dot 1.31 + 1.32 +//some shorthand for side bits 1.33 +#define SIDE_BIT_TOP (1 << NS_SIDE_TOP) 1.34 +#define SIDE_BIT_RIGHT (1 << NS_SIDE_RIGHT) 1.35 +#define SIDE_BIT_BOTTOM (1 << NS_SIDE_BOTTOM) 1.36 +#define SIDE_BIT_LEFT (1 << NS_SIDE_LEFT) 1.37 +#define SIDE_BITS_ALL (SIDE_BIT_TOP|SIDE_BIT_RIGHT|SIDE_BIT_BOTTOM|SIDE_BIT_LEFT) 1.38 + 1.39 +#define C_TL NS_CORNER_TOP_LEFT 1.40 +#define C_TR NS_CORNER_TOP_RIGHT 1.41 +#define C_BR NS_CORNER_BOTTOM_RIGHT 1.42 +#define C_BL NS_CORNER_BOTTOM_LEFT 1.43 + 1.44 +/* 1.45 + * Helper class that handles border rendering. 1.46 + * 1.47 + * appUnitsPerPixel -- current value of AUPP 1.48 + * destContext -- the gfxContext to which the border should be rendered 1.49 + * outsideRect -- the rectangle on the outer edge of the border 1.50 + * 1.51 + * For any parameter where an array of side values is passed in, 1.52 + * they are in top, right, bottom, left order. 1.53 + * 1.54 + * borderStyles -- one border style enum per side 1.55 + * borderWidths -- one border width per side 1.56 + * borderRadii -- a gfxCornerSizes struct describing the w/h for each rounded corner. 1.57 + * If the corner doesn't have a border radius, 0,0 should be given for it. 1.58 + * borderColors -- one nscolor per side 1.59 + * compositeColors -- a pointer to an array of composite color structs, or 1.60 + * nullptr if none. 1.61 + * 1.62 + * skipSides -- a bit mask specifying which sides, if any, to skip 1.63 + * backgroundColor -- the background color of the element. 1.64 + * Used in calculating colors for 2-tone borders, such as inset and outset 1.65 + * gapRect - a rectangle that should be clipped out to leave a gap in a border, 1.66 + * or nullptr if none. 1.67 + */ 1.68 + 1.69 +typedef enum { 1.70 + BorderColorStyleNone, 1.71 + BorderColorStyleSolid, 1.72 + BorderColorStyleLight, 1.73 + BorderColorStyleDark 1.74 +} BorderColorStyle; 1.75 + 1.76 +struct nsCSSBorderRenderer { 1.77 + nsCSSBorderRenderer(int32_t aAppUnitsPerPixel, 1.78 + gfxContext* aDestContext, 1.79 + gfxRect& aOuterRect, 1.80 + const uint8_t* aBorderStyles, 1.81 + const gfxFloat* aBorderWidths, 1.82 + gfxCornerSizes& aBorderRadii, 1.83 + const nscolor* aBorderColors, 1.84 + nsBorderColors* const* aCompositeColors, 1.85 + int aSkipSides, 1.86 + nscolor aBackgroundColor); 1.87 + 1.88 + gfxCornerSizes mBorderCornerDimensions; 1.89 + 1.90 + // destination context 1.91 + gfxContext* mContext; 1.92 + 1.93 + // the rectangle of the outside and the inside of the border 1.94 + gfxRect mOuterRect; 1.95 + gfxRect mInnerRect; 1.96 + 1.97 + // the style and size of the border 1.98 + const uint8_t* mBorderStyles; 1.99 + const gfxFloat* mBorderWidths; 1.100 + uint8_t* mSanitizedStyles; 1.101 + gfxFloat* mSanitizedWidths; 1.102 + gfxCornerSizes mBorderRadii; 1.103 + 1.104 + // colors 1.105 + const nscolor* mBorderColors; 1.106 + nsBorderColors* const* mCompositeColors; 1.107 + 1.108 + // core app units per pixel 1.109 + int32_t mAUPP; 1.110 + 1.111 + // misc -- which sides to skip, the background color 1.112 + int mSkipSides; 1.113 + nscolor mBackgroundColor; 1.114 + 1.115 + // calculated values 1.116 + bool mOneUnitBorder; 1.117 + bool mNoBorderRadius; 1.118 + bool mAvoidStroke; 1.119 + 1.120 + // For all the sides in the bitmask, would they be rendered 1.121 + // in an identical color and style? 1.122 + bool AreBorderSideFinalStylesSame(uint8_t aSides); 1.123 + 1.124 + // For the given style, is the given corner a solid color? 1.125 + bool IsSolidCornerStyle(uint8_t aStyle, mozilla::css::Corner aCorner); 1.126 + 1.127 + // For the given solid corner, what color style should be used? 1.128 + BorderColorStyle BorderColorStyleForSolidCorner(uint8_t aStyle, mozilla::css::Corner aCorner); 1.129 + 1.130 + // 1.131 + // Path generation functions 1.132 + // 1.133 + 1.134 + // add the path for drawing the given corner to the context 1.135 + void DoCornerSubPath(mozilla::css::Corner aCorner); 1.136 + // add the path for drawing the given side without any adjacent corners to the context 1.137 + void DoSideClipWithoutCornersSubPath(mozilla::css::Side aSide); 1.138 + 1.139 + // Create a clip path for the wedge that this side of 1.140 + // the border should take up. This is only called 1.141 + // when we're drawing separate border sides, so we know 1.142 + // that ADD compositing is taking place. 1.143 + // 1.144 + // This code needs to make sure that the individual pieces 1.145 + // don't ever (mathematically) overlap; the pixel overlap 1.146 + // is taken care of by the ADD compositing. 1.147 + void DoSideClipSubPath(mozilla::css::Side aSide); 1.148 + 1.149 + // Given a set of sides to fill and a color, do so in the fastest way. 1.150 + // 1.151 + // Stroke tends to be faster for smaller borders because it doesn't go 1.152 + // through the tessellator, which has initialization overhead. If 1.153 + // we're rendering all sides, we can use stroke at any thickness; we 1.154 + // also do TL/BR pairs at 1px thickness using stroke. 1.155 + // 1.156 + // If we can't stroke, then if it's a TL/BR pair, we use the specific 1.157 + // TL/BR paths. Otherwise, we do the full path and fill. 1.158 + // 1.159 + // Calling code is expected to only set up a clip as necessary; no 1.160 + // clip is needed if we can render the entire border in 1 or 2 passes. 1.161 + void FillSolidBorder(const gfxRect& aOuterRect, 1.162 + const gfxRect& aInnerRect, 1.163 + const gfxCornerSizes& aBorderRadii, 1.164 + const gfxFloat *aBorderSizes, 1.165 + int aSides, 1.166 + const gfxRGBA& aColor); 1.167 + 1.168 + // 1.169 + // core rendering 1.170 + // 1.171 + 1.172 + // draw the border for the given sides, using the style of the first side 1.173 + // present in the bitmask 1.174 + void DrawBorderSides (int aSides); 1.175 + 1.176 + // function used by the above to handle -moz-border-colors 1.177 + void DrawBorderSidesCompositeColors(int aSides, const nsBorderColors *compositeColors); 1.178 + 1.179 + // draw the given dashed side 1.180 + void DrawDashedSide (mozilla::css::Side aSide); 1.181 + 1.182 + // Setup the stroke style for a given side 1.183 + void SetupStrokeStyle(mozilla::css::Side aSize); 1.184 + 1.185 + // Analyze if all border sides have the same width. 1.186 + bool AllBordersSameWidth(); 1.187 + 1.188 + // Analyze if all borders are 'solid' this also considers hidden or 'none' 1.189 + // borders because they can be considered 'solid' borders of 0 width and 1.190 + // with no color effect. 1.191 + bool AllBordersSolid(bool *aHasCompositeColors); 1.192 + 1.193 + // Create a gradient pattern that will handle the color transition for a 1.194 + // corner. 1.195 + already_AddRefed<gfxPattern> CreateCornerGradient(mozilla::css::Corner aCorner, 1.196 + const gfxRGBA &aFirstColor, 1.197 + const gfxRGBA &aSecondColor); 1.198 + 1.199 + // Azure variant of CreateCornerGradient. 1.200 + mozilla::TemporaryRef<mozilla::gfx::GradientStops> 1.201 + CreateCornerGradient(mozilla::css::Corner aCorner, const gfxRGBA &aFirstColor, 1.202 + const gfxRGBA &aSecondColor, mozilla::gfx::DrawTarget *aDT, 1.203 + mozilla::gfx::Point &aPoint1, mozilla::gfx::Point &aPoint2); 1.204 + 1.205 + // Draw a solid color border that is uniformly the same width. 1.206 + void DrawSingleWidthSolidBorder(); 1.207 + 1.208 + // Draw any border which is solid on all sides and does not use 1.209 + // CompositeColors. 1.210 + void DrawNoCompositeColorSolidBorder(); 1.211 + // Draw any border which is solid on all sides and does not use 1.212 + // CompositeColors. Using Azure. 1.213 + void DrawNoCompositeColorSolidBorderAzure(); 1.214 + 1.215 + // Draw a solid border that has no border radius (i.e. is rectangular) and 1.216 + // uses CompositeColors. 1.217 + void DrawRectangularCompositeColors(); 1.218 + 1.219 + // draw the entire border 1.220 + void DrawBorders (); 1.221 + 1.222 + // utility function used for background painting as well as borders 1.223 + static void ComputeInnerRadii(const gfxCornerSizes& aRadii, 1.224 + const gfxFloat *aBorderSizes, 1.225 + gfxCornerSizes *aInnerRadiiRet); 1.226 + 1.227 + // Given aRadii as the border radii for a rectangle, compute the 1.228 + // appropriate radii for another rectangle *outside* that rectangle 1.229 + // by increasing the radii, except keeping sharp corners sharp. 1.230 + // Used for spread box-shadows 1.231 + static void ComputeOuterRadii(const gfxCornerSizes& aRadii, 1.232 + const gfxFloat *aBorderSizes, 1.233 + gfxCornerSizes *aOuterRadiiRet); 1.234 +}; 1.235 + 1.236 +namespace mozilla { 1.237 + 1.238 +#ifdef DEBUG_NEW_BORDERS 1.239 +#include <stdarg.h> 1.240 + 1.241 +static inline void S(const gfxPoint& p) { 1.242 + fprintf (stderr, "[%f,%f]", p.x, p.y); 1.243 +} 1.244 + 1.245 +static inline void S(const gfxSize& s) { 1.246 + fprintf (stderr, "[%f %f]", s.width, s.height); 1.247 +} 1.248 + 1.249 +static inline void S(const gfxRect& r) { 1.250 + fprintf (stderr, "[%f %f %f %f]", r.pos.x, r.pos.y, r.size.width, r.size.height); 1.251 +} 1.252 + 1.253 +static inline void S(const gfxFloat f) { 1.254 + fprintf (stderr, "%f", f); 1.255 +} 1.256 + 1.257 +static inline void S(const char *s) { 1.258 + fprintf (stderr, "%s", s); 1.259 +} 1.260 + 1.261 +static inline void SN(const char *s = nullptr) { 1.262 + if (s) 1.263 + fprintf (stderr, "%s", s); 1.264 + fprintf (stderr, "\n"); 1.265 + fflush (stderr); 1.266 +} 1.267 + 1.268 +static inline void SF(const char *fmt, ...) { 1.269 + va_list vl; 1.270 + va_start(vl, fmt); 1.271 + vfprintf (stderr, fmt, vl); 1.272 + va_end(vl); 1.273 +} 1.274 + 1.275 +static inline void SX(gfxContext *ctx) { 1.276 + gfxPoint p = ctx->CurrentPoint(); 1.277 + fprintf (stderr, "p: %f %f\n", p.x, p.y); 1.278 + return; 1.279 + ctx->MoveTo(p + gfxPoint(-2, -2)); ctx->LineTo(p + gfxPoint(2, 2)); 1.280 + ctx->MoveTo(p + gfxPoint(-2, 2)); ctx->LineTo(p + gfxPoint(2, -2)); 1.281 + ctx->MoveTo(p); 1.282 +} 1.283 + 1.284 + 1.285 +#else 1.286 +static inline void S(const gfxPoint& p) {} 1.287 +static inline void S(const gfxSize& s) {} 1.288 +static inline void S(const gfxRect& r) {} 1.289 +static inline void S(const gfxFloat f) {} 1.290 +static inline void S(const char *s) {} 1.291 +static inline void SN(const char *s = nullptr) {} 1.292 +static inline void SF(const char *fmt, ...) {} 1.293 +static inline void SX(gfxContext *ctx) {} 1.294 +#endif 1.295 + 1.296 +} 1.297 + 1.298 +#endif /* NS_CSS_RENDERING_BORDERS_H */