• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 #include "include/core/SkShader.h"
12 
13 /** \class SkGradientShader
14 
15     SkGradientShader hosts factories for creating subclasses of SkShader that
16     render linear and radial gradients. In general, degenerate cases should not
17     produce surprising results, but there are several types of degeneracies:
18 
19      * A linear gradient made from the same two points.
20      * A radial gradient with a radius of zero.
21      * A sweep gradient where the start and end angle are the same.
22      * A two point conical gradient where the two centers and the two radii are
23        the same.
24 
25     For any degenerate gradient with a decal tile mode, it will draw empty since the interpolating
26     region is zero area and the outer region is discarded by the decal mode.
27 
28     For any degenerate gradient with a repeat or mirror tile mode, it will draw a solid color that
29     is the average gradient color, since infinitely many repetitions of the gradients will fill the
30     shape.
31 
32     For a clamped gradient, every type is well-defined at the limit except for linear gradients. The
33     radial gradient with zero radius becomes the last color. The sweep gradient draws the sector
34     from 0 to the provided angle with the first color, with a hardstop switching to the last color.
35     When the provided angle is 0, this is just the solid last color again. Similarly, the two point
36     conical gradient becomes a circle filled with the first color, sized to the provided radius,
37     with a hardstop switching to the last color. When the two radii are both zero, this is just the
38     solid last color.
39 
40     As a linear gradient approaches the degenerate case, its shader will approach the appearance of
41     two half planes, each filled by the first and last colors of the gradient. The planes will be
42     oriented perpendicular to the vector between the two defining points of the gradient. However,
43     once they become the same point, Skia cannot reconstruct what that expected orientation is. To
44     provide a stable and predictable color in this case, Skia just uses the last color as a solid
45     fill to be similar to many of the other degenerate gradients' behaviors in clamp mode.
46 */
47 class SK_API SkGradientShader {
48 public:
49     enum Flags {
50         /** By default gradients will interpolate their colors in unpremul space
51          *  and then premultiply each of the results. By setting this flag, the
52          *  gradients will premultiply their colors first, and then interpolate
53          *  between them.
54          *  example: https://fiddle.skia.org/c/@GradientShader_MakeLinear
55          */
56         kInterpolateColorsInPremul_Flag = 1 << 0,
57     };
58 
59     /** Returns a shader that generates a linear gradient between the two specified points.
60         <p />
61         @param  pts     The start and end points for the gradient.
62         @param  colors  The array[count] of colors, to be distributed between the two points
63         @param  pos     May be NULL. array[count] of SkScalars, or NULL, of the relative position of
64                         each corresponding color in the colors array. If this is NULL,
65                         the the colors are distributed evenly between the start and end point.
66                         If this is not null, the values must begin with 0, end with 1.0, and
67                         intermediate values must be strictly increasing.
68         @param  count   Must be >=2. The number of colors (and pos if not NULL) entries.
69         @param  mode    The tiling mode
70 
71         example: https://fiddle.skia.org/c/@GradientShader_MakeLinear
72     */
73     static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],
74                                       const SkColor colors[], const SkScalar pos[], int count,
75                                       SkTileMode mode,
76                                       uint32_t flags, const SkMatrix* localMatrix);
MakeLinear(const SkPoint pts[2],const SkColor colors[],const SkScalar pos[],int count,SkTileMode mode)77     static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],
78                                       const SkColor colors[], const SkScalar pos[], int count,
79                                       SkTileMode mode) {
80         return MakeLinear(pts, colors, pos, count, mode, 0, nullptr);
81     }
82 
83     /** Returns a shader that generates a linear gradient between the two specified points.
84         <p />
85         @param  pts     The start and end points for the gradient.
86         @param  colors  The array[count] of colors, to be distributed between the two points
87         @param  pos     May be NULL. array[count] of SkScalars, or NULL, of the relative position of
88                         each corresponding color in the colors array. If this is NULL,
89                         the the colors are distributed evenly between the start and end point.
90                         If this is not null, the values must begin with 0, end with 1.0, and
91                         intermediate values must be strictly increasing.
92         @param  count   Must be >=2. The number of colors (and pos if not NULL) entries.
93         @param  mode    The tiling mode
94 
95         example: https://fiddle.skia.org/c/@GradientShader_MakeLinear
96     */
97     static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],
98                                       const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
99                                       const SkScalar pos[], int count, SkTileMode mode,
100                                       uint32_t flags, const SkMatrix* localMatrix);
MakeLinear(const SkPoint pts[2],const SkColor4f colors[],sk_sp<SkColorSpace> colorSpace,const SkScalar pos[],int count,SkTileMode mode)101     static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],
102                                       const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
103                                       const SkScalar pos[], int count, SkTileMode mode) {
104         return MakeLinear(pts, colors, std::move(colorSpace), pos, count, mode, 0, nullptr);
105     }
106 
107     /** Returns a shader that generates a radial gradient given the center and radius.
108         <p />
109         @param  center  The center of the circle for this gradient
110         @param  radius  Must be positive. The radius of the circle for this gradient
111         @param  colors  The array[count] of colors, to be distributed between the center and edge of the circle
112         @param  pos     May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
113                         each corresponding color in the colors array. If this is NULL,
114                         the the colors are distributed evenly between the center and edge of the circle.
115                         If this is not null, the values must begin with 0, end with 1.0, and
116                         intermediate values must be strictly increasing.
117         @param  count   Must be >= 2. The number of colors (and pos if not NULL) entries
118         @param  mode    The tiling mode
119     */
120     static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,
121                                       const SkColor colors[], const SkScalar pos[], int count,
122                                       SkTileMode mode,
123                                       uint32_t flags, const SkMatrix* localMatrix);
MakeRadial(const SkPoint & center,SkScalar radius,const SkColor colors[],const SkScalar pos[],int count,SkTileMode mode)124     static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,
125                                       const SkColor colors[], const SkScalar pos[], int count,
126                                       SkTileMode mode) {
127         return MakeRadial(center, radius, colors, pos, count, mode, 0, nullptr);
128     }
129 
130     /** Returns a shader that generates a radial gradient given the center and radius.
131         <p />
132         @param  center  The center of the circle for this gradient
133         @param  radius  Must be positive. The radius of the circle for this gradient
134         @param  colors  The array[count] of colors, to be distributed between the center and edge of the circle
135         @param  pos     May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
136                         each corresponding color in the colors array. If this is NULL,
137                         the the colors are distributed evenly between the center and edge of the circle.
138                         If this is not null, the values must begin with 0, end with 1.0, and
139                         intermediate values must be strictly increasing.
140         @param  count   Must be >= 2. The number of colors (and pos if not NULL) entries
141         @param  mode    The tiling mode
142     */
143     static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,
144                                       const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
145                                       const SkScalar pos[], int count, SkTileMode mode,
146                                       uint32_t flags, const SkMatrix* localMatrix);
MakeRadial(const SkPoint & center,SkScalar radius,const SkColor4f colors[],sk_sp<SkColorSpace> colorSpace,const SkScalar pos[],int count,SkTileMode mode)147     static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,
148                                       const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
149                                       const SkScalar pos[], int count, SkTileMode mode) {
150         return MakeRadial(center, radius, colors, std::move(colorSpace), pos, count, mode,
151                           0, nullptr);
152     }
153 
154     /**
155      *  Returns a shader that generates a conical gradient given two circles, or
156      *  returns NULL if the inputs are invalid. The gradient interprets the
157      *  two circles according to the following HTML spec.
158      *  http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient
159      */
160     static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,
161                                                const SkPoint& end, SkScalar endRadius,
162                                                const SkColor colors[], const SkScalar pos[],
163                                                int count, SkTileMode mode,
164                                                uint32_t flags, const SkMatrix* localMatrix);
MakeTwoPointConical(const SkPoint & start,SkScalar startRadius,const SkPoint & end,SkScalar endRadius,const SkColor colors[],const SkScalar pos[],int count,SkTileMode mode)165     static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,
166                                                const SkPoint& end, SkScalar endRadius,
167                                                const SkColor colors[], const SkScalar pos[],
168                                                int count, SkTileMode mode) {
169         return MakeTwoPointConical(start, startRadius, end, endRadius, colors, pos, count, mode,
170                                    0, nullptr);
171     }
172 
173     /**
174      *  Returns a shader that generates a conical gradient given two circles, or
175      *  returns NULL if the inputs are invalid. The gradient interprets the
176      *  two circles according to the following HTML spec.
177      *  http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient
178      */
179     static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,
180                                                const SkPoint& end, SkScalar endRadius,
181                                                const SkColor4f colors[],
182                                                sk_sp<SkColorSpace> colorSpace, const SkScalar pos[],
183                                                int count, SkTileMode mode,
184                                                uint32_t flags, const SkMatrix* localMatrix);
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)185     static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,
186                                                const SkPoint& end, SkScalar endRadius,
187                                                const SkColor4f colors[],
188                                                sk_sp<SkColorSpace> colorSpace, const SkScalar pos[],
189                                                int count, SkTileMode mode) {
190         return MakeTwoPointConical(start, startRadius, end, endRadius, colors,
191                                    std::move(colorSpace), pos, count, mode, 0, nullptr);
192     }
193 
194     /** Returns a shader that generates a sweep gradient given a center.
195         <p />
196         @param  cx         The X coordinate of the center of the sweep
197         @param  cx         The Y coordinate of the center of the sweep
198         @param  colors     The array[count] of colors, to be distributed around the center, within
199                            the gradient angle range.
200         @param  pos        May be NULL. The array[count] of SkScalars, or NULL, of the relative
201                            position of each corresponding color in the colors array. If this is
202                            NULL, then the colors are distributed evenly within the angular range.
203                            If this is not null, the values must begin with 0, end with 1.0, and
204                            intermediate values must be strictly increasing.
205         @param  count      Must be >= 2. The number of colors (and pos if not NULL) entries
206         @param  mode       Tiling mode: controls drawing outside of the gradient angular range.
207         @param  startAngle Start of the angular range, corresponding to pos == 0.
208         @param  endAngle   End of the angular range, corresponding to pos == 1.
209     */
210     static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
211                                      const SkColor colors[], const SkScalar pos[], int count,
212                                      SkTileMode mode,
213                                      SkScalar startAngle, SkScalar endAngle,
214                                      uint32_t flags, const SkMatrix* localMatrix);
MakeSweep(SkScalar cx,SkScalar cy,const SkColor colors[],const SkScalar pos[],int count,uint32_t flags,const SkMatrix * localMatrix)215     static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
216                                      const SkColor colors[], const SkScalar pos[], int count,
217                                      uint32_t flags, const SkMatrix* localMatrix) {
218         return MakeSweep(cx, cy, colors, pos, count, SkTileMode::kClamp, 0, 360, flags,
219                          localMatrix);
220     }
MakeSweep(SkScalar cx,SkScalar cy,const SkColor colors[],const SkScalar pos[],int count)221     static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
222                                      const SkColor colors[], const SkScalar pos[], int count) {
223         return MakeSweep(cx, cy, colors, pos, count, 0, nullptr);
224     }
225 
226     /** Returns a shader that generates a sweep gradient given a center.
227         <p />
228         @param  cx         The X coordinate of the center of the sweep
229         @param  cx         The Y coordinate of the center of the sweep
230         @param  colors     The array[count] of colors, to be distributed around the center, within
231                            the gradient angle range.
232         @param  pos        May be NULL. The array[count] of SkScalars, or NULL, of the relative
233                            position of each corresponding color in the colors array. If this is
234                            NULL, then the colors are distributed evenly within the angular range.
235                            If this is not null, the values must begin with 0, end with 1.0, and
236                            intermediate values must be strictly increasing.
237         @param  count      Must be >= 2. The number of colors (and pos if not NULL) entries
238         @param  mode       Tiling mode: controls drawing outside of the gradient angular range.
239         @param  startAngle Start of the angular range, corresponding to pos == 0.
240         @param  endAngle   End of the angular range, corresponding to pos == 1.
241     */
242     static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
243                                      const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
244                                      const SkScalar pos[], int count,
245                                      SkTileMode mode,
246                                      SkScalar startAngle, SkScalar endAngle,
247                                      uint32_t flags, const SkMatrix* localMatrix);
MakeSweep(SkScalar cx,SkScalar cy,const SkColor4f colors[],sk_sp<SkColorSpace> colorSpace,const SkScalar pos[],int count,uint32_t flags,const SkMatrix * localMatrix)248     static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
249                                      const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
250                                      const SkScalar pos[], int count,
251                                      uint32_t flags, const SkMatrix* localMatrix) {
252         return MakeSweep(cx, cy, colors, std::move(colorSpace), pos, count,
253                          SkTileMode::kClamp, 0, 360, flags, localMatrix);
254     }
MakeSweep(SkScalar cx,SkScalar cy,const SkColor4f colors[],sk_sp<SkColorSpace> colorSpace,const SkScalar pos[],int count)255     static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
256                                      const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
257                                      const SkScalar pos[], int count) {
258         return MakeSweep(cx, cy, colors, std::move(colorSpace), pos, count, 0, nullptr);
259     }
260 
261     static void RegisterFlattenables();
262 };
263 
264 #endif
265