|
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 |
|
9 #ifndef SkShader_DEFINED |
|
10 #define SkShader_DEFINED |
|
11 |
|
12 #include "SkBitmap.h" |
|
13 #include "SkFlattenable.h" |
|
14 #include "SkMask.h" |
|
15 #include "SkMatrix.h" |
|
16 #include "SkPaint.h" |
|
17 |
|
18 class SkPath; |
|
19 class GrContext; |
|
20 class GrEffectRef; |
|
21 |
|
22 /** \class SkShader |
|
23 * |
|
24 * Shaders specify the source color(s) for what is being drawn. If a paint |
|
25 * has no shader, then the paint's color is used. If the paint has a |
|
26 * shader, then the shader's color(s) are use instead, but they are |
|
27 * modulated by the paint's alpha. This makes it easy to create a shader |
|
28 * once (e.g. bitmap tiling or gradient) and then change its transparency |
|
29 * w/o having to modify the original shader... only the paint's alpha needs |
|
30 * to be modified. |
|
31 */ |
|
32 class SK_API SkShader : public SkFlattenable { |
|
33 public: |
|
34 SK_DECLARE_INST_COUNT(SkShader) |
|
35 |
|
36 SkShader(); |
|
37 virtual ~SkShader(); |
|
38 |
|
39 /** |
|
40 * Returns true if the local matrix is not an identity matrix. |
|
41 */ |
|
42 bool hasLocalMatrix() const { return !fLocalMatrix.isIdentity(); } |
|
43 |
|
44 /** |
|
45 * Returns the local matrix. |
|
46 */ |
|
47 const SkMatrix& getLocalMatrix() const { return fLocalMatrix; } |
|
48 |
|
49 /** |
|
50 * Set the shader's local matrix. |
|
51 * @param localM The shader's new local matrix. |
|
52 */ |
|
53 void setLocalMatrix(const SkMatrix& localM) { fLocalMatrix = localM; } |
|
54 |
|
55 /** |
|
56 * Reset the shader's local matrix to identity. |
|
57 */ |
|
58 void resetLocalMatrix() { fLocalMatrix.reset(); } |
|
59 |
|
60 enum TileMode { |
|
61 /** replicate the edge color if the shader draws outside of its |
|
62 * original bounds |
|
63 */ |
|
64 kClamp_TileMode, |
|
65 |
|
66 /** repeat the shader's image horizontally and vertically */ |
|
67 kRepeat_TileMode, |
|
68 |
|
69 /** repeat the shader's image horizontally and vertically, alternating |
|
70 * mirror images so that adjacent images always seam |
|
71 */ |
|
72 kMirror_TileMode, |
|
73 |
|
74 #if 0 |
|
75 /** only draw within the original domain, return 0 everywhere else */ |
|
76 kDecal_TileMode, |
|
77 #endif |
|
78 |
|
79 kTileModeCount |
|
80 }; |
|
81 |
|
82 // override these in your subclass |
|
83 |
|
84 enum Flags { |
|
85 //!< set if all of the colors will be opaque |
|
86 kOpaqueAlpha_Flag = 0x01, |
|
87 |
|
88 //! set if this shader's shadeSpan16() method can be called |
|
89 kHasSpan16_Flag = 0x02, |
|
90 |
|
91 /** Set this bit if the shader's native data type is instrinsically 16 |
|
92 bit, meaning that calling the 32bit shadeSpan() entry point will |
|
93 mean the the impl has to up-sample 16bit data into 32bit. Used as a |
|
94 a means of clearing a dither request if the it will have no effect |
|
95 */ |
|
96 kIntrinsicly16_Flag = 0x04, |
|
97 |
|
98 /** set (after setContext) if the spans only vary in X (const in Y). |
|
99 e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient |
|
100 that varies from left-to-right. This flag specifies this for |
|
101 shadeSpan(). |
|
102 */ |
|
103 kConstInY32_Flag = 0x08, |
|
104 |
|
105 /** same as kConstInY32_Flag, but is set if this is true for shadeSpan16 |
|
106 which may not always be the case, since shadeSpan16 may be |
|
107 predithered, which would mean it was not const in Y, even though |
|
108 the 32bit shadeSpan() would be const. |
|
109 */ |
|
110 kConstInY16_Flag = 0x10 |
|
111 }; |
|
112 |
|
113 /** |
|
114 * Called sometimes before drawing with this shader. Return the type of |
|
115 * alpha your shader will return. The default implementation returns 0. |
|
116 * Your subclass should override if it can (even sometimes) report a |
|
117 * non-zero value, since that will enable various blitters to perform |
|
118 * faster. |
|
119 */ |
|
120 virtual uint32_t getFlags() { return 0; } |
|
121 |
|
122 /** |
|
123 * Returns true if the shader is guaranteed to produce only opaque |
|
124 * colors, subject to the SkPaint using the shader to apply an opaque |
|
125 * alpha value. Subclasses should override this to allow some |
|
126 * optimizations. isOpaque() can be called at any time, unlike getFlags, |
|
127 * which only works properly when the context is set. |
|
128 */ |
|
129 virtual bool isOpaque() const { return false; } |
|
130 |
|
131 /** |
|
132 * Return the alpha associated with the data returned by shadeSpan16(). If |
|
133 * kHasSpan16_Flag is not set, this value is meaningless. |
|
134 */ |
|
135 virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; } |
|
136 |
|
137 /** |
|
138 * Called once before drawing, with the current paint and device matrix. |
|
139 * Return true if your shader supports these parameters, or false if not. |
|
140 * If false is returned, nothing will be drawn. If true is returned, then |
|
141 * a balancing call to endContext() will be made before the next call to |
|
142 * setContext. |
|
143 * |
|
144 * Subclasses should be sure to call their INHERITED::setContext() if they |
|
145 * override this method. |
|
146 */ |
|
147 virtual bool setContext(const SkBitmap& device, const SkPaint& paint, |
|
148 const SkMatrix& matrix); |
|
149 |
|
150 /** |
|
151 * Assuming setContext returned true, endContext() will be called when |
|
152 * the draw using the shader has completed. It is an error for setContext |
|
153 * to be called twice w/o an intervening call to endContext(). |
|
154 * |
|
155 * Subclasses should be sure to call their INHERITED::endContext() if they |
|
156 * override this method. |
|
157 */ |
|
158 virtual void endContext(); |
|
159 |
|
160 SkDEBUGCODE(bool setContextHasBeenCalled() const { return SkToBool(fInSetContext); }) |
|
161 |
|
162 /** |
|
163 * Called for each span of the object being drawn. Your subclass should |
|
164 * set the appropriate colors (with premultiplied alpha) that correspond |
|
165 * to the specified device coordinates. |
|
166 */ |
|
167 virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0; |
|
168 |
|
169 typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count); |
|
170 virtual ShadeProc asAShadeProc(void** ctx); |
|
171 |
|
172 /** |
|
173 * Called only for 16bit devices when getFlags() returns |
|
174 * kOpaqueAlphaFlag | kHasSpan16_Flag |
|
175 */ |
|
176 virtual void shadeSpan16(int x, int y, uint16_t[], int count); |
|
177 |
|
178 /** |
|
179 * Similar to shadeSpan, but only returns the alpha-channel for a span. |
|
180 * The default implementation calls shadeSpan() and then extracts the alpha |
|
181 * values from the returned colors. |
|
182 */ |
|
183 virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count); |
|
184 |
|
185 /** |
|
186 * Helper function that returns true if this shader's shadeSpan16() method |
|
187 * can be called. |
|
188 */ |
|
189 bool canCallShadeSpan16() { |
|
190 return SkShader::CanCallShadeSpan16(this->getFlags()); |
|
191 } |
|
192 |
|
193 /** |
|
194 * Helper to check the flags to know if it is legal to call shadeSpan16() |
|
195 */ |
|
196 static bool CanCallShadeSpan16(uint32_t flags) { |
|
197 return (flags & kHasSpan16_Flag) != 0; |
|
198 } |
|
199 |
|
200 /** |
|
201 Gives method bitmap should be read to implement a shader. |
|
202 Also determines number and interpretation of "extra" parameters returned |
|
203 by asABitmap |
|
204 */ |
|
205 enum BitmapType { |
|
206 kNone_BitmapType, //<! Shader is not represented as a bitmap |
|
207 kDefault_BitmapType,//<! Access bitmap using local coords transformed |
|
208 // by matrix. No extras |
|
209 kRadial_BitmapType, //<! Access bitmap by transforming local coordinates |
|
210 // by the matrix and taking the distance of result |
|
211 // from (0,0) as bitmap column. Bitmap is 1 pixel |
|
212 // tall. No extras |
|
213 kSweep_BitmapType, //<! Access bitmap by transforming local coordinates |
|
214 // by the matrix and taking the angle of result |
|
215 // to (0,0) as bitmap x coord, where angle = 0 is |
|
216 // bitmap left edge of bitmap = 2pi is the |
|
217 // right edge. Bitmap is 1 pixel tall. No extras |
|
218 kTwoPointRadial_BitmapType, |
|
219 //<! Matrix transforms to space where (0,0) is |
|
220 // the center of the starting circle. The second |
|
221 // circle will be centered (x, 0) where x may be |
|
222 // 0. The post-matrix space is normalized such |
|
223 // that 1 is the second radius - first radius. |
|
224 // Three extra parameters are returned: |
|
225 // 0: x-offset of second circle center |
|
226 // to first. |
|
227 // 1: radius of first circle in post-matrix |
|
228 // space |
|
229 // 2: the second radius minus the first radius |
|
230 // in pre-transformed space. |
|
231 kTwoPointConical_BitmapType, |
|
232 //<! Matrix transforms to space where (0,0) is |
|
233 // the center of the starting circle. The second |
|
234 // circle will be centered (x, 0) where x may be |
|
235 // 0. |
|
236 // Three extra parameters are returned: |
|
237 // 0: x-offset of second circle center |
|
238 // to first. |
|
239 // 1: radius of first circle |
|
240 // 2: the second radius minus the first radius |
|
241 kLinear_BitmapType, //<! Access bitmap using local coords transformed |
|
242 // by matrix. No extras |
|
243 |
|
244 kLast_BitmapType = kLinear_BitmapType |
|
245 }; |
|
246 /** Optional methods for shaders that can pretend to be a bitmap/texture |
|
247 to play along with opengl. Default just returns kNone_BitmapType and |
|
248 ignores the out parameters. |
|
249 |
|
250 @param outTexture if non-NULL will be the bitmap representing the shader |
|
251 after return. |
|
252 @param outMatrix if non-NULL will be the matrix to apply to vertices |
|
253 to access the bitmap after return. |
|
254 @param xy if non-NULL will be the tile modes that should be |
|
255 used to access the bitmap after return. |
|
256 @param twoPointRadialParams Two extra return values needed for two point |
|
257 radial bitmaps. The first is the x-offset of |
|
258 the second point and the second is the radius |
|
259 about the first point. |
|
260 */ |
|
261 virtual BitmapType asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, |
|
262 TileMode xy[2]) const; |
|
263 |
|
264 /** |
|
265 * If the shader subclass can be represented as a gradient, asAGradient |
|
266 * returns the matching GradientType enum (or kNone_GradientType if it |
|
267 * cannot). Also, if info is not null, asAGradient populates info with |
|
268 * the relevant (see below) parameters for the gradient. fColorCount |
|
269 * is both an input and output parameter. On input, it indicates how |
|
270 * many entries in fColors and fColorOffsets can be used, if they are |
|
271 * non-NULL. After asAGradient has run, fColorCount indicates how |
|
272 * many color-offset pairs there are in the gradient. If there is |
|
273 * insufficient space to store all of the color-offset pairs, fColors |
|
274 * and fColorOffsets will not be altered. fColorOffsets specifies |
|
275 * where on the range of 0 to 1 to transition to the given color. |
|
276 * The meaning of fPoint and fRadius is dependant on the type of gradient. |
|
277 * |
|
278 * None: |
|
279 * info is ignored. |
|
280 * Color: |
|
281 * fColorOffsets[0] is meaningless. |
|
282 * Linear: |
|
283 * fPoint[0] and fPoint[1] are the end-points of the gradient |
|
284 * Radial: |
|
285 * fPoint[0] and fRadius[0] are the center and radius |
|
286 * Radial2: |
|
287 * fPoint[0] and fRadius[0] are the center and radius of the 1st circle |
|
288 * fPoint[1] and fRadius[1] are the center and radius of the 2nd circle |
|
289 * Sweep: |
|
290 * fPoint[0] is the center of the sweep. |
|
291 */ |
|
292 |
|
293 enum GradientType { |
|
294 kNone_GradientType, |
|
295 kColor_GradientType, |
|
296 kLinear_GradientType, |
|
297 kRadial_GradientType, |
|
298 kRadial2_GradientType, |
|
299 kSweep_GradientType, |
|
300 kConical_GradientType, |
|
301 kLast_GradientType = kConical_GradientType |
|
302 }; |
|
303 |
|
304 struct GradientInfo { |
|
305 int fColorCount; //!< In-out parameter, specifies passed size |
|
306 // of fColors/fColorOffsets on input, and |
|
307 // actual number of colors/offsets on |
|
308 // output. |
|
309 SkColor* fColors; //!< The colors in the gradient. |
|
310 SkScalar* fColorOffsets; //!< The unit offset for color transitions. |
|
311 SkPoint fPoint[2]; //!< Type specific, see above. |
|
312 SkScalar fRadius[2]; //!< Type specific, see above. |
|
313 TileMode fTileMode; //!< The tile mode used. |
|
314 uint32_t fGradientFlags; //!< see SkGradientShader::Flags |
|
315 }; |
|
316 |
|
317 virtual GradientType asAGradient(GradientInfo* info) const; |
|
318 |
|
319 /** |
|
320 * If the shader subclass has a GrEffect implementation, this resturns the effect to install. |
|
321 * The incoming color to the effect has r=g=b=a all extracted from the SkPaint's alpha. |
|
322 * The output color should be the computed SkShader premul color modulated by the incoming |
|
323 * color. The GrContext may be used by the effect to create textures. The GPU device does not |
|
324 * call setContext. Instead we pass the SkPaint here in case the shader needs paint info. |
|
325 */ |
|
326 virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const; |
|
327 |
|
328 ////////////////////////////////////////////////////////////////////////// |
|
329 // Factory methods for stock shaders |
|
330 |
|
331 /** Call this to create a new shader that will draw with the specified bitmap. |
|
332 * |
|
333 * If the bitmap cannot be used (e.g. has no pixels, or its dimensions |
|
334 * exceed implementation limits (currently at 64K - 1)) then SkEmptyShader |
|
335 * may be returned. |
|
336 * |
|
337 * If the src is kA8_Config then that mask will be colorized using the color on |
|
338 * the paint. |
|
339 * |
|
340 * @param src The bitmap to use inside the shader |
|
341 * @param tmx The tiling mode to use when sampling the bitmap in the x-direction. |
|
342 * @param tmy The tiling mode to use when sampling the bitmap in the y-direction. |
|
343 * @return Returns a new shader object. Note: this function never returns null. |
|
344 */ |
|
345 static SkShader* CreateBitmapShader(const SkBitmap& src, |
|
346 TileMode tmx, TileMode tmy); |
|
347 |
|
348 SK_TO_STRING_VIRT() |
|
349 SK_DEFINE_FLATTENABLE_TYPE(SkShader) |
|
350 |
|
351 protected: |
|
352 enum MatrixClass { |
|
353 kLinear_MatrixClass, // no perspective |
|
354 kFixedStepInX_MatrixClass, // fast perspective, need to call fixedStepInX() each scanline |
|
355 kPerspective_MatrixClass // slow perspective, need to mappoints each pixel |
|
356 }; |
|
357 static MatrixClass ComputeMatrixClass(const SkMatrix&); |
|
358 |
|
359 // These can be called by your subclass after setContext() has been called |
|
360 uint8_t getPaintAlpha() const { return fPaintAlpha; } |
|
361 const SkMatrix& getTotalInverse() const { return fTotalInverse; } |
|
362 MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; } |
|
363 |
|
364 SkShader(SkReadBuffer& ); |
|
365 virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; |
|
366 private: |
|
367 SkMatrix fLocalMatrix; |
|
368 SkMatrix fTotalInverse; |
|
369 uint8_t fPaintAlpha; |
|
370 uint8_t fTotalInverseClass; |
|
371 SkDEBUGCODE(SkBool8 fInSetContext;) |
|
372 |
|
373 typedef SkFlattenable INHERITED; |
|
374 }; |
|
375 |
|
376 #endif |