Bug 1858915 [wpt PR 42525] - Use taskcluster-run in infra tests, a=testonly
[gecko.git] / layout / painting / nsCSSRenderingBorders.h
blob881708320853f1fff930a9457d4db6d4c573d5ba
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 "gfxRect.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/gfx/2D.h"
13 #include "mozilla/gfx/BezierUtils.h"
14 #include "mozilla/gfx/PathHelpers.h"
15 #include "mozilla/RefPtr.h"
16 #include "nsColor.h"
17 #include "nsCOMPtr.h"
18 #include "nsIFrame.h"
19 #include "nsImageRenderer.h"
20 #include "gfxUtils.h"
22 struct nsBorderColors;
24 namespace mozilla {
25 class nsDisplayItem;
26 class nsDisplayList;
27 class nsDisplayListBuilder;
29 class nsDisplayBorder;
30 class nsDisplayButtonBorder;
31 class nsDisplayButtonForeground;
32 class nsDisplayOutline;
34 enum class StyleBorderStyle : uint8_t;
35 enum class StyleBorderImageRepeat : uint8_t;
37 namespace gfx {
38 class GradientStops;
39 } // namespace gfx
40 namespace layers {
41 class StackingContextHelper;
42 } // namespace layers
43 } // namespace mozilla
45 // define this to enable a bunch of debug dump info
46 #undef DEBUG_NEW_BORDERS
49 * Helper class that handles border rendering.
51 * aDrawTarget -- the DrawTarget to which the border should be rendered
52 * outsideRect -- the rectangle on the outer edge of the border
54 * For any parameter where an array of side values is passed in,
55 * they are in top, right, bottom, left order.
57 * borderStyles -- one border style enum per side
58 * borderWidths -- one border width per side
59 * borderRadii -- a RectCornerRadii struct describing the w/h for each rounded
60 * corner. If the corner doesn't have a border radius, 0,0 should be given for
61 * it. borderColors -- one nscolor per side
63 * skipSides -- a bit mask specifying which sides, if any, to skip
64 * backgroundColor -- the background color of the element.
65 * Used in calculating colors for 2-tone borders, such as inset and outset
66 * gapRect - a rectangle that should be clipped out to leave a gap in a border,
67 * or nullptr if none.
70 typedef enum {
71 BorderColorStyleNone,
72 BorderColorStyleSolid,
73 BorderColorStyleLight,
74 BorderColorStyleDark
75 } BorderColorStyle;
77 class nsPresContext;
79 class nsCSSBorderRenderer final {
80 typedef mozilla::gfx::Bezier Bezier;
81 typedef mozilla::gfx::ColorPattern ColorPattern;
82 typedef mozilla::gfx::DrawTarget DrawTarget;
83 typedef mozilla::gfx::Float Float;
84 typedef mozilla::gfx::Path Path;
85 typedef mozilla::gfx::Point Point;
86 typedef mozilla::gfx::Rect Rect;
87 typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
88 typedef mozilla::gfx::StrokeOptions StrokeOptions;
90 friend class mozilla::nsDisplayOutline;
91 friend class mozilla::nsDisplayButtonBorder;
92 friend class mozilla::nsDisplayButtonForeground;
94 public:
95 nsCSSBorderRenderer(nsPresContext* aPresContext, DrawTarget* aDrawTarget,
96 const Rect& aDirtyRect, Rect& aOuterRect,
97 const mozilla::StyleBorderStyle* aBorderStyles,
98 const Float* aBorderWidths, RectCornerRadii& aBorderRadii,
99 const nscolor* aBorderColors, bool aBackfaceIsVisible,
100 const mozilla::Maybe<Rect>& aClipRect);
102 // draw the entire border
103 void DrawBorders();
105 void CreateWebRenderCommands(
106 mozilla::nsDisplayItem* aItem, mozilla::wr::DisplayListBuilder& aBuilder,
107 mozilla::wr::IpcResourceUpdateQueue& aResources,
108 const mozilla::layers::StackingContextHelper& aSc);
110 // utility function used for background painting as well as borders
111 static void ComputeInnerRadii(const RectCornerRadii& aRadii,
112 const Float* aBorderSizes,
113 RectCornerRadii* aInnerRadiiRet);
115 // Given aRadii as the border radii for a rectangle, compute the
116 // appropriate radii for another rectangle *outside* that rectangle
117 // by increasing the radii, except keeping sharp corners sharp.
118 // Used for spread box-shadows
119 static void ComputeOuterRadii(const RectCornerRadii& aRadii,
120 const Float* aBorderSizes,
121 RectCornerRadii* aOuterRadiiRet);
123 static bool AllCornersZeroSize(const RectCornerRadii& corners);
125 private:
126 RectCornerRadii mBorderCornerDimensions;
128 nsPresContext* mPresContext;
130 // destination DrawTarget and dirty rect
131 DrawTarget* mDrawTarget;
132 Rect mDirtyRect;
134 // the rectangle of the outside and the inside of the border
135 Rect mOuterRect;
136 Rect mInnerRect;
138 // the style and size of the border
139 mozilla::StyleBorderStyle mBorderStyles[4];
140 Float mBorderWidths[4];
141 RectCornerRadii mBorderRadii;
143 // the colors for 'border-top-color' et. al.
144 nscolor mBorderColors[4];
146 // calculated values
147 bool mAllBordersSameStyle;
148 bool mAllBordersSameWidth;
149 bool mOneUnitBorder;
150 bool mNoBorderRadius;
151 bool mAvoidStroke;
152 bool mBackfaceIsVisible;
153 mozilla::Maybe<Rect> mLocalClip;
155 // For all the sides in the bitmask, would they be rendered
156 // in an identical color and style?
157 bool AreBorderSideFinalStylesSame(mozilla::SideBits aSides);
159 // For the given style, is the given corner a solid color?
160 bool IsSolidCornerStyle(mozilla::StyleBorderStyle aStyle,
161 mozilla::Corner aCorner);
163 // For the given corner, is the given corner mergeable into one dot?
164 bool IsCornerMergeable(mozilla::Corner aCorner);
166 // For the given solid corner, what color style should be used?
167 BorderColorStyle BorderColorStyleForSolidCorner(
168 mozilla::StyleBorderStyle aStyle, mozilla::Corner aCorner);
171 // Path generation functions
174 // Get the Rect for drawing the given corner
175 Rect GetCornerRect(mozilla::Corner aCorner);
176 // add the path for drawing the given side without any adjacent corners to the
177 // context
178 Rect GetSideClipWithoutCornersRect(mozilla::Side aSide);
180 // Create a clip path for the wedge that this side of
181 // the border should take up. This is only called
182 // when we're drawing separate border sides, so we know
183 // that ADD compositing is taking place.
185 // This code needs to make sure that the individual pieces
186 // don't ever (mathematically) overlap; the pixel overlap
187 // is taken care of by the ADD compositing.
188 already_AddRefed<Path> GetSideClipSubPath(mozilla::Side aSide);
190 // Return start or end point for dashed/dotted side
191 Point GetStraightBorderPoint(mozilla::Side aSide, mozilla::Corner aCorner,
192 bool* aIsUnfilled, Float aDotOffset = 0.0f);
194 // Return bezier control points for the outer and the inner curve for given
195 // corner
196 void GetOuterAndInnerBezier(Bezier* aOuterBezier, Bezier* aInnerBezier,
197 mozilla::Corner aCorner);
199 // Given a set of sides to fill and a color, do so in the fastest way.
201 // Stroke tends to be faster for smaller borders because it doesn't go
202 // through the tessellator, which has initialization overhead. If
203 // we're rendering all sides, we can use stroke at any thickness; we
204 // also do TL/BR pairs at 1px thickness using stroke.
206 // If we can't stroke, then if it's a TL/BR pair, we use the specific
207 // TL/BR paths. Otherwise, we do the full path and fill.
209 // Calling code is expected to only set up a clip as necessary; no
210 // clip is needed if we can render the entire border in 1 or 2 passes.
211 void FillSolidBorder(const Rect& aOuterRect, const Rect& aInnerRect,
212 const RectCornerRadii& aBorderRadii,
213 const Float* aBorderSizes, mozilla::SideBits aSides,
214 const ColorPattern& aColor);
217 // core rendering
220 // draw the border for the given sides, using the style of the first side
221 // present in the bitmask
222 void DrawBorderSides(mozilla::SideBits aSides);
224 // Setup the stroke options for the given dashed/dotted side
225 void SetupDashedOptions(StrokeOptions* aStrokeOptions, Float aDash[2],
226 mozilla::Side aSide, Float aBorderLength,
227 bool isCorner);
229 // Draw the given dashed/dotte side
230 void DrawDashedOrDottedSide(mozilla::Side aSide);
232 // Draw the given dotted side, each dot separately
233 void DrawDottedSideSlow(mozilla::Side aSide);
235 // Draw the given dashed/dotted corner
236 void DrawDashedOrDottedCorner(mozilla::Side aSide, mozilla::Corner aCorner);
238 // Draw the given dotted corner, each segment separately
239 void DrawDottedCornerSlow(mozilla::Side aSide, mozilla::Corner aCorner);
241 // Draw the given dashed corner, each dot separately
242 void DrawDashedCornerSlow(mozilla::Side aSide, mozilla::Corner aCorner);
244 // Draw the given dashed/dotted corner with solid style
245 void DrawFallbackSolidCorner(mozilla::Side aSide, mozilla::Corner aCorner);
247 // Analyze if all border sides have the same width.
248 bool AllBordersSameWidth();
250 // Analyze if all borders are 'solid' this also considers hidden or 'none'
251 // borders because they can be considered 'solid' borders of 0 width and
252 // with no color effect.
253 bool AllBordersSolid();
255 // Draw a solid color border that is uniformly the same width.
256 void DrawSingleWidthSolidBorder();
258 // Draw any border which is solid on all sides.
259 void DrawSolidBorder();
262 class nsCSSBorderImageRenderer final {
263 typedef mozilla::nsImageRenderer nsImageRenderer;
265 public:
266 static mozilla::Maybe<nsCSSBorderImageRenderer> CreateBorderImageRenderer(
267 nsPresContext* aPresContext, nsIFrame* aForFrame,
268 const nsRect& aBorderArea, const nsStyleBorder& aStyleBorder,
269 const nsRect& aDirtyRect, nsIFrame::Sides aSkipSides, uint32_t aFlags,
270 mozilla::image::ImgDrawResult* aDrawResult);
272 mozilla::image::ImgDrawResult DrawBorderImage(nsPresContext* aPresContext,
273 gfxContext& aRenderingContext,
274 nsIFrame* aForFrame,
275 const nsRect& aDirtyRect);
276 mozilla::image::ImgDrawResult CreateWebRenderCommands(
277 mozilla::nsDisplayItem* aItem, nsIFrame* aForFrame,
278 mozilla::wr::DisplayListBuilder& aBuilder,
279 mozilla::wr::IpcResourceUpdateQueue& aResources,
280 const mozilla::layers::StackingContextHelper& aSc,
281 mozilla::layers::RenderRootStateManager* aManager,
282 mozilla::nsDisplayListBuilder* aDisplayListBuilder);
284 nsCSSBorderImageRenderer(const nsCSSBorderImageRenderer& aRhs);
285 nsCSSBorderImageRenderer& operator=(const nsCSSBorderImageRenderer& aRhs);
287 private:
288 nsCSSBorderImageRenderer(nsIFrame* aForFrame, const nsRect& aBorderArea,
289 const nsStyleBorder& aStyleBorder,
290 nsIFrame::Sides aSkipSides,
291 const nsImageRenderer& aImageRenderer);
293 nsImageRenderer mImageRenderer;
294 nsSize mImageSize;
295 nsMargin mSlice;
296 nsMargin mWidths;
297 nsMargin mImageOutset;
298 nsRect mArea;
299 nsRect mClip;
300 mozilla::StyleBorderImageRepeat mRepeatModeHorizontal;
301 mozilla::StyleBorderImageRepeat mRepeatModeVertical;
302 bool mFill;
304 friend class mozilla::nsDisplayBorder;
305 friend struct nsCSSRendering;
308 namespace mozilla {
309 #ifdef DEBUG_NEW_BORDERS
310 # include <stdarg.h>
312 static inline void PrintAsString(const mozilla::gfx::Point& p) {
313 fprintf(stderr, "[%f,%f]", p.x, p.y);
316 static inline void PrintAsString(const mozilla::gfx::Size& s) {
317 fprintf(stderr, "[%f %f]", s.width, s.height);
320 static inline void PrintAsString(const mozilla::gfx::Rect& r) {
321 fprintf(stderr, "[%f %f %f %f]", r.X(), r.Y(), r.Width(), r.Height());
324 static inline void PrintAsString(const mozilla::gfx::Float f) {
325 fprintf(stderr, "%f", f);
328 static inline void PrintAsString(const char* s) { fprintf(stderr, "%s", s); }
330 static inline void PrintAsStringNewline(const char* s = nullptr) {
331 if (s) fprintf(stderr, "%s", s);
332 fprintf(stderr, "\n");
333 fflush(stderr);
336 static inline MOZ_FORMAT_PRINTF(1, 2) void PrintAsFormatString(const char* fmt,
337 ...) {
338 va_list vl;
339 va_start(vl, fmt);
340 vfprintf(stderr, fmt, vl);
341 va_end(vl);
344 #else
345 static inline void PrintAsString(const mozilla::gfx::Point& p) {}
346 static inline void PrintAsString(const mozilla::gfx::Size& s) {}
347 static inline void PrintAsString(const mozilla::gfx::Rect& r) {}
348 static inline void PrintAsString(const mozilla::gfx::Float f) {}
349 static inline void PrintAsString(const char* s) {}
350 static inline void PrintAsStringNewline(const char* s = nullptr) {}
351 static inline MOZ_FORMAT_PRINTF(1, 2) void PrintAsFormatString(const char* fmt,
352 ...) {}
353 #endif
355 } // namespace mozilla
357 #endif /* NS_CSS_RENDERING_BORDERS_H */