no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / layout / painting / nsCSSRenderingGradients.h
blob549cd8c4b6ed0c74490cf7adc901dfb1ccb9b2f5
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 nsCSSRenderingGradients_h__
8 #define nsCSSRenderingGradients_h__
10 #include "gfxRect.h"
11 #include "gfxUtils.h"
12 #include "nsStyleStruct.h"
13 #include "Units.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/gfx/2D.h"
16 #include "mozilla/webrender/webrender_ffi.h"
18 class gfxPattern;
20 namespace mozilla {
22 namespace layers {
23 class StackingContextHelper;
24 } // namespace layers
26 namespace wr {
27 class DisplayListBuilder;
28 } // namespace wr
30 // A resolved color stop, with a specific position along the gradient line and
31 // a color.
32 struct ColorStop {
33 ColorStop() : mPosition(0), mIsMidpoint(false) {}
34 ColorStop(double aPosition, bool aIsMidPoint,
35 const StyleAbsoluteColor& aColor)
36 : mPosition(aPosition), mIsMidpoint(aIsMidPoint), mColor(aColor) {}
37 double mPosition; // along the gradient line; 0=start, 1=end
38 bool mIsMidpoint;
39 StyleAbsoluteColor mColor;
42 template <class T>
43 class MOZ_STACK_CLASS ColorStopInterpolator {
44 public:
45 ColorStopInterpolator(
46 const nsTArray<ColorStop>& aStops,
47 const StyleColorInterpolationMethod& aStyleColorInterpolationMethod)
48 : mStyleColorInterpolationMethod(aStyleColorInterpolationMethod),
49 mStops(aStops) {}
51 void CreateStops() {
52 for (uint32_t i = 0; i < mStops.Length() - 1; i++) {
53 const auto& start = mStops[i];
54 const auto& end = mStops[i + 1];
55 uint32_t extraStops =
56 (uint32_t)(floor(end.mPosition * kFullRangeExtraStops) -
57 floor(start.mPosition * kFullRangeExtraStops));
58 extraStops = clamped(extraStops, 1U, kFullRangeExtraStops);
59 float step = 1.0f / (float)extraStops;
60 for (uint32_t extraStop = 0; extraStop <= extraStops; extraStop++) {
61 auto progress = (float)extraStop * step;
62 auto position =
63 start.mPosition + progress * (end.mPosition - start.mPosition);
64 StyleAbsoluteColor color =
65 Servo_InterpolateColor(mStyleColorInterpolationMethod, &end.mColor,
66 &start.mColor, progress);
67 static_cast<T*>(this)->CreateStop(float(position),
68 gfx::ToDeviceColor(color));
73 protected:
74 StyleColorInterpolationMethod mStyleColorInterpolationMethod;
75 const nsTArray<ColorStop>& mStops;
77 // this could be made tunable, but at 1.0/128 the error is largely
78 // irrelevant, as WebRender re-encodes it to 128 pairs of stops.
80 // note that we don't attempt to place the positions of these stops
81 // precisely at intervals, we just add this many extra stops across the
82 // range where it is convenient.
83 inline static const uint32_t kFullRangeExtraStops = 128;
86 class nsCSSGradientRenderer final {
87 public:
88 /**
89 * Prepare a nsCSSGradientRenderer for a gradient for an element.
90 * aIntrinsicSize - the size of the source gradient.
92 static nsCSSGradientRenderer Create(nsPresContext* aPresContext,
93 ComputedStyle* aComputedStyle,
94 const StyleGradient& aGradient,
95 const nsSize& aIntrinsiceSize);
97 /**
98 * Draw the gradient to aContext
99 * aDest - where the first tile of gradient is
100 * aFill - the area to be filled with tiles of aDest
101 * aSrc - the area of the gradient that will fill aDest
102 * aRepeatSize - the distance from the origin of a tile
103 * to the next origin of a tile
104 * aDirtyRect - pixels outside of this area may be skipped
106 void Paint(gfxContext& aContext, const nsRect& aDest, const nsRect& aFill,
107 const nsSize& aRepeatSize, const mozilla::CSSIntRect& aSrc,
108 const nsRect& aDirtyRect, float aOpacity = 1.0);
111 * Collect the gradient parameters
113 void BuildWebRenderParameters(float aOpacity, wr::ExtendMode& aMode,
114 nsTArray<wr::GradientStop>& aStops,
115 LayoutDevicePoint& aLineStart,
116 LayoutDevicePoint& aLineEnd,
117 LayoutDeviceSize& aGradientRadius,
118 LayoutDevicePoint& aGradientCenter,
119 float& aGradientAngle);
122 * Build display items for the gradient
123 * aLayer - the layer to make this display item relative to
124 * aDest - where the first tile of gradient is
125 * aFill - the area to be filled with tiles of aDest
126 * aRepeatSize - the distance from the origin of a tile
127 * to the next origin of a tile
128 * aSrc - the area of the gradient that will fill aDest
130 void BuildWebRenderDisplayItems(wr::DisplayListBuilder& aBuilder,
131 const layers::StackingContextHelper& aSc,
132 const nsRect& aDest, const nsRect& aFill,
133 const nsSize& aRepeatSize,
134 const mozilla::CSSIntRect& aSrc,
135 bool aIsBackfaceVisible,
136 float aOpacity = 1.0);
138 private:
139 nsCSSGradientRenderer()
140 : mPresContext(nullptr),
141 mGradient(nullptr),
142 mRadiusX(0.0),
143 mRadiusY(0.0),
144 mAngle(0.0) {}
147 * Attempts to paint the tiles for a gradient by painting it once to an
148 * offscreen surface and then painting that offscreen surface with
149 * ExtendMode::Repeat to cover all tiles.
151 * Returns false if the optimization wasn't able to be used, in which case
152 * a fallback should be used.
154 bool TryPaintTilesWithExtendMode(
155 gfxContext& aContext, gfxPattern* aGradientPattern, nscoord aXStart,
156 nscoord aYStart, const gfxRect& aDirtyAreaToFill, const nsRect& aDest,
157 const nsSize& aRepeatSize, bool aForceRepeatToCoverTiles);
159 nsPresContext* mPresContext;
160 const StyleGradient* mGradient;
161 nsTArray<ColorStop> mStops;
162 gfxPoint mLineStart, mLineEnd; // only for linear/radial gradients
163 double mRadiusX, mRadiusY; // only for radial gradients
164 gfxPoint mCenter; // only for conic gradients
165 float mAngle; // only for conic gradients
168 } // namespace mozilla
170 #endif /* nsCSSRenderingGradients_h__ */