Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkGradientShader.h
Go to the documentation of this file.
1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkGradientShader_DEFINED
9#define SkGradientShader_DEFINED
10
16#include "include/core/SkShader.h" // IWYU pragma: keep
19
20#include <cstdint>
21#include <utility>
22
23class SkMatrix;
24
25/** \class SkGradientShader
26
27 SkGradientShader hosts factories for creating subclasses of SkShader that
28 render linear and radial gradients. In general, degenerate cases should not
29 produce surprising results, but there are several types of degeneracies:
30
31 * A linear gradient made from the same two points.
32 * A radial gradient with a radius of zero.
33 * A sweep gradient where the start and end angle are the same.
34 * A two point conical gradient where the two centers and the two radii are
35 the same.
36
37 For any degenerate gradient with a decal tile mode, it will draw empty since the interpolating
38 region is zero area and the outer region is discarded by the decal mode.
39
40 For any degenerate gradient with a repeat or mirror tile mode, it will draw a solid color that
41 is the average gradient color, since infinitely many repetitions of the gradients will fill the
42 shape.
43
44 For a clamped gradient, every type is well-defined at the limit except for linear gradients. The
45 radial gradient with zero radius becomes the last color. The sweep gradient draws the sector
46 from 0 to the provided angle with the first color, with a hardstop switching to the last color.
47 When the provided angle is 0, this is just the solid last color again. Similarly, the two point
48 conical gradient becomes a circle filled with the first color, sized to the provided radius,
49 with a hardstop switching to the last color. When the two radii are both zero, this is just the
50 solid last color.
51
52 As a linear gradient approaches the degenerate case, its shader will approach the appearance of
53 two half planes, each filled by the first and last colors of the gradient. The planes will be
54 oriented perpendicular to the vector between the two defining points of the gradient. However,
55 once they become the same point, Skia cannot reconstruct what that expected orientation is. To
56 provide a stable and predictable color in this case, Skia just uses the last color as a solid
57 fill to be similar to many of the other degenerate gradients' behaviors in clamp mode.
58*/
60public:
61 enum Flags {
62 /** By default gradients will interpolate their colors in unpremul space
63 * and then premultiply each of the results. By setting this flag, the
64 * gradients will premultiply their colors first, and then interpolate
65 * between them.
66 * example: https://fiddle.skia.org/c/@GradientShader_MakeLinear
67 */
68 kInterpolateColorsInPremul_Flag = 1 << 0,
69 };
70
72 enum class InPremul : bool { kNo = false, kYes = true };
73
74 enum class ColorSpace : uint8_t {
75 // Default Skia behavior: interpolate in the color space of the destination surface
76 kDestination,
77
78 // https://www.w3.org/TR/css-color-4/#interpolation-space
79 kSRGBLinear,
80 kLab,
81 kOKLab,
82 // This is the same as kOKLab, except it has a simplified version of the CSS gamut
83 // mapping algorithm (https://www.w3.org/TR/css-color-4/#css-gamut-mapping)
84 // into Rec2020 space applied to it.
85 // Warning: This space is experimental and should not be used in production.
86 kOKLabGamutMap,
87 kLCH,
88 kOKLCH,
89 // This is the same as kOKLCH, except it has the same gamut mapping applied to it
90 // as kOKLabGamutMap does.
91 // Warning: This space is experimental and should not be used in production.
92 kOKLCHGamutMap,
93 kSRGB,
94 kHSL,
95 kHWB,
96
97 kLastColorSpace = kHWB,
98 };
99 static constexpr int kColorSpaceCount = static_cast<int>(ColorSpace::kLastColorSpace) + 1;
100
101 enum class HueMethod : uint8_t {
102 // https://www.w3.org/TR/css-color-4/#hue-interpolation
103 kShorter,
104 kLonger,
105 kIncreasing,
106 kDecreasing,
107
108 kLastHueMethod = kDecreasing,
109 };
110 static constexpr int kHueMethodCount = static_cast<int>(HueMethod::kLastHueMethod) + 1;
111
112 InPremul fInPremul = InPremul::kNo;
113 ColorSpace fColorSpace = ColorSpace::kDestination;
114 HueMethod fHueMethod = HueMethod::kShorter; // Only relevant for LCH, OKLCH, HSL, or HWB
115
116 static Interpolation FromFlags(uint32_t flags) {
117 return {flags & kInterpolateColorsInPremul_Flag ? InPremul::kYes : InPremul::kNo,
118 ColorSpace::kDestination,
119 HueMethod::kShorter};
120 }
121 };
122
123 /** Returns a shader that generates a linear gradient between the two specified points.
124 <p />
125 @param pts The start and end points for the gradient.
126 @param colors The array[count] of colors, to be distributed between the two points
127 @param pos May be NULL. array[count] of SkScalars, or NULL, of the relative position of
128 each corresponding color in the colors array. If this is NULL,
129 the the colors are distributed evenly between the start and end point.
130 If this is not null, the values must lie between 0.0 and 1.0, and be
131 strictly increasing. If the first value is not 0.0, then an additional
132 color stop is added at position 0.0, with the same color as colors[0].
133 If the the last value is not 1.0, then an additional color stop is added
134 at position 1.0, with the same color as colors[count - 1].
135 @param count Must be >=2. The number of colors (and pos if not NULL) entries.
136 @param mode The tiling mode
137
138 example: https://fiddle.skia.org/c/@GradientShader_MakeLinear
139 */
140 static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],
141 const SkColor colors[], const SkScalar pos[], int count,
142 SkTileMode mode,
143 uint32_t flags = 0, const SkMatrix* localMatrix = nullptr);
144
145 /** Returns a shader that generates a linear gradient between the two specified points.
146 <p />
147 @param pts The start and end points for the gradient.
148 @param colors The array[count] of colors, to be distributed between the two points
149 @param pos May be NULL. array[count] of SkScalars, or NULL, of the relative position of
150 each corresponding color in the colors array. If this is NULL,
151 the the colors are distributed evenly between the start and end point.
152 If this is not null, the values must lie between 0.0 and 1.0, and be
153 strictly increasing. If the first value is not 0.0, then an additional
154 color stop is added at position 0.0, with the same color as colors[0].
155 If the the last value is not 1.0, then an additional color stop is added
156 at position 1.0, with the same color as colors[count - 1].
157 @param count Must be >=2. The number of colors (and pos if not NULL) entries.
158 @param mode The tiling mode
159
160 example: https://fiddle.skia.org/c/@GradientShader_MakeLinear
161 */
162 static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],
163 const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
164 const SkScalar pos[], int count, SkTileMode mode,
165 const Interpolation& interpolation,
166 const SkMatrix* localMatrix);
167 static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],
168 const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
169 const SkScalar pos[], int count, SkTileMode mode,
170 uint32_t flags = 0, const SkMatrix* localMatrix = nullptr) {
171 return MakeLinear(pts, colors, std::move(colorSpace), pos, count, mode,
172 Interpolation::FromFlags(flags), localMatrix);
173 }
174
175 /** Returns a shader that generates a radial gradient given the center and radius.
176 <p />
177 @param center The center of the circle for this gradient
178 @param radius Must be positive. The radius of the circle for this gradient
179 @param colors The array[count] of colors, to be distributed between the center and edge of the circle
180 @param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
181 each corresponding color in the colors array. If this is NULL,
182 the the colors are distributed evenly between the center and edge of the circle.
183 If this is not null, the values must lie between 0.0 and 1.0, and be
184 strictly increasing. If the first value is not 0.0, then an additional
185 color stop is added at position 0.0, with the same color as colors[0].
186 If the the last value is not 1.0, then an additional color stop is added
187 at position 1.0, with the same color as colors[count - 1].
188 @param count Must be >= 2. The number of colors (and pos if not NULL) entries
189 @param mode The tiling mode
190 */
191 static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,
192 const SkColor colors[], const SkScalar pos[], int count,
193 SkTileMode mode,
194 uint32_t flags = 0, const SkMatrix* localMatrix = nullptr);
195
196 /** Returns a shader that generates a radial gradient given the center and radius.
197 <p />
198 @param center The center of the circle for this gradient
199 @param radius Must be positive. The radius of the circle for this gradient
200 @param colors The array[count] of colors, to be distributed between the center and edge of the circle
201 @param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
202 each corresponding color in the colors array. If this is NULL,
203 the the colors are distributed evenly between the center and edge of the circle.
204 If this is not null, the values must lie between 0.0 and 1.0, and be
205 strictly increasing. If the first value is not 0.0, then an additional
206 color stop is added at position 0.0, with the same color as colors[0].
207 If the the last value is not 1.0, then an additional color stop is added
208 at position 1.0, with the same color as colors[count - 1].
209 @param count Must be >= 2. The number of colors (and pos if not NULL) entries
210 @param mode The tiling mode
211 */
212 static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,
213 const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
214 const SkScalar pos[], int count, SkTileMode mode,
215 const Interpolation& interpolation,
216 const SkMatrix* localMatrix);
218 const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
219 const SkScalar pos[], int count, SkTileMode mode,
220 uint32_t flags = 0, const SkMatrix* localMatrix = nullptr) {
221 return MakeRadial(center, radius, colors, std::move(colorSpace), pos, count, mode,
222 Interpolation::FromFlags(flags), localMatrix);
223 }
224
225 /**
226 * Returns a shader that generates a conical gradient given two circles, or
227 * returns NULL if the inputs are invalid. The gradient interprets the
228 * two circles according to the following HTML spec.
229 * http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient
230 */
231 static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,
232 const SkPoint& end, SkScalar endRadius,
233 const SkColor colors[], const SkScalar pos[],
234 int count, SkTileMode mode,
235 uint32_t flags = 0,
236 const SkMatrix* localMatrix = nullptr);
237
238 /**
239 * Returns a shader that generates a conical gradient given two circles, or
240 * returns NULL if the inputs are invalid. The gradient interprets the
241 * two circles according to the following HTML spec.
242 * http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient
243 */
244 static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,
245 const SkPoint& end, SkScalar endRadius,
246 const SkColor4f colors[],
247 sk_sp<SkColorSpace> colorSpace, const SkScalar pos[],
248 int count, SkTileMode mode,
249 const Interpolation& interpolation,
250 const SkMatrix* localMatrix);
252 const SkPoint& end, SkScalar endRadius,
253 const SkColor4f colors[],
254 sk_sp<SkColorSpace> colorSpace, const SkScalar pos[],
255 int count, SkTileMode mode,
256 uint32_t flags = 0,
257 const SkMatrix* localMatrix = nullptr) {
258 return MakeTwoPointConical(start, startRadius, end, endRadius, colors,
259 std::move(colorSpace), pos, count, mode,
260 Interpolation::FromFlags(flags), localMatrix);
261 }
262
263 /** Returns a shader that generates a sweep gradient given a center.
264
265 The shader accepts negative angles and angles larger than 360, draws
266 between 0 and 360 degrees, similar to the CSS conic-gradient
267 semantics. 0 degrees means horizontal positive x axis. The start angle
268 must be less than the end angle, otherwise a null pointer is
269 returned. If color stops do not contain 0 and 1 but are within this
270 range, the respective outer color stop is repeated for 0 and 1. Color
271 stops less than 0 are clamped to 0, and greater than 1 are clamped to 1.
272 <p />
273 @param cx The X coordinate of the center of the sweep
274 @param cx The Y coordinate of the center of the sweep
275 @param colors The array[count] of colors, to be distributed around the center, within
276 the gradient angle range.
277 @param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative
278 position of each corresponding color in the colors array. If this is
279 NULL, then the colors are distributed evenly within the angular range.
280 If this is not null, the values must lie between 0.0 and 1.0, and be
281 strictly increasing. If the first value is not 0.0, then an additional
282 color stop is added at position 0.0, with the same color as colors[0].
283 If the the last value is not 1.0, then an additional color stop is added
284 at position 1.0, with the same color as colors[count - 1].
285 @param count Must be >= 2. The number of colors (and pos if not NULL) entries
286 @param mode Tiling mode: controls drawing outside of the gradient angular range.
287 @param startAngle Start of the angular range, corresponding to pos == 0.
288 @param endAngle End of the angular range, corresponding to pos == 1.
289 */
291 const SkColor colors[], const SkScalar pos[], int count,
292 SkTileMode mode,
293 SkScalar startAngle, SkScalar endAngle,
294 uint32_t flags, const SkMatrix* localMatrix);
296 const SkColor colors[], const SkScalar pos[], int count,
297 uint32_t flags = 0, const SkMatrix* localMatrix = nullptr) {
298 return MakeSweep(cx, cy, colors, pos, count, SkTileMode::kClamp, 0, 360, flags,
299 localMatrix);
300 }
301
302 /** Returns a shader that generates a sweep gradient given a center.
303
304 The shader accepts negative angles and angles larger than 360, draws
305 between 0 and 360 degrees, similar to the CSS conic-gradient
306 semantics. 0 degrees means horizontal positive x axis. The start angle
307 must be less than the end angle, otherwise a null pointer is
308 returned. If color stops do not contain 0 and 1 but are within this
309 range, the respective outer color stop is repeated for 0 and 1. Color
310 stops less than 0 are clamped to 0, and greater than 1 are clamped to 1.
311 <p />
312 @param cx The X coordinate of the center of the sweep
313 @param cx The Y coordinate of the center of the sweep
314 @param colors The array[count] of colors, to be distributed around the center, within
315 the gradient angle range.
316 @param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative
317 position of each corresponding color in the colors array. If this is
318 NULL, then the colors are distributed evenly within the angular range.
319 If this is not null, the values must lie between 0.0 and 1.0, and be
320 strictly increasing. If the first value is not 0.0, then an additional
321 color stop is added at position 0.0, with the same color as colors[0].
322 If the the last value is not 1.0, then an additional color stop is added
323 at position 1.0, with the same color as colors[count - 1].
324 @param count Must be >= 2. The number of colors (and pos if not NULL) entries
325 @param mode Tiling mode: controls drawing outside of the gradient angular range.
326 @param startAngle Start of the angular range, corresponding to pos == 0.
327 @param endAngle End of the angular range, corresponding to pos == 1.
328 */
330 const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
331 const SkScalar pos[], int count,
332 SkTileMode mode,
333 SkScalar startAngle, SkScalar endAngle,
334 const Interpolation& interpolation,
335 const SkMatrix* localMatrix);
337 const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
338 const SkScalar pos[], int count,
339 SkTileMode mode,
340 SkScalar startAngle, SkScalar endAngle,
341 uint32_t flags, const SkMatrix* localMatrix) {
342 return MakeSweep(cx, cy, colors, std::move(colorSpace), pos, count, mode, startAngle,
343 endAngle, Interpolation::FromFlags(flags), localMatrix);
344 }
346 const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
347 const SkScalar pos[], int count,
348 uint32_t flags = 0, const SkMatrix* localMatrix = nullptr) {
349 return MakeSweep(cx, cy, colors, std::move(colorSpace), pos, count, SkTileMode::kClamp,
350 0, 360, flags, localMatrix);
351 }
352};
353
354#endif
int count
static sk_sp< SkShader > MakeSweep(const SkPoint pts[2], const GradData &data, SkTileMode tm, float scale)
Ignores scale.
SkPoint pos
#define SK_API
Definition SkAPI.h:35
uint32_t SkColor
Definition SkColor.h:37
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
@ kNo
Don't pre-clip the geometry before applying the (perspective) matrix.
SkTileMode
Definition SkTileMode.h:13
static SkScalar center(float pos0, float pos1)
static sk_sp< SkShader > MakeRadial()
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor4f colors[], sk_sp< SkColorSpace > colorSpace, const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkShader > MakeSweep(SkScalar cx, SkScalar cy, const SkColor colors[], const SkScalar pos[], int count, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkShader > MakeTwoPointConical(const SkPoint &start, SkScalar startRadius, const SkPoint &end, SkScalar endRadius, const SkColor4f colors[], sk_sp< SkColorSpace > colorSpace, const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkShader > MakeSweep(SkScalar cx, SkScalar cy, const SkColor4f colors[], sk_sp< SkColorSpace > colorSpace, const SkScalar pos[], int count, SkTileMode mode, SkScalar startAngle, SkScalar endAngle, uint32_t flags, const SkMatrix *localMatrix)
static sk_sp< SkShader > MakeSweep(SkScalar cx, SkScalar cy, const SkColor4f colors[], sk_sp< SkColorSpace > colorSpace, const SkScalar pos[], int count, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkShader > MakeRadial(const SkPoint &center, SkScalar radius, const SkColor4f colors[], sk_sp< SkColorSpace > colorSpace, const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkShader > MakeLinear()
float SkScalar
Definition extension.cpp:12
FlutterSemanticsFlag flags
glong glong end
static Interpolation FromFlags(uint32_t flags)