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