blob: 1cdbf17cf6351cb8a1f18200c8440917d5c78c67 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkShader_DEFINED
18#define SkShader_DEFINED
19
20#include "SkBitmap.h"
21#include "SkFlattenable.h"
22#include "SkMask.h"
23#include "SkMatrix.h"
24#include "SkPaint.h"
25
26class SkPath;
27
28/** \class SkShader
29
30 SkShader is the based class for objects that return horizontal spans of colors during drawing.
31 A subclass of SkShader is installed in a SkPaint calling paint.setShader(shader). After that
32 any object (other than a bitmap) that is drawn with that paint will get its color(s) from the
33 shader.
34*/
35class SkShader : public SkFlattenable {
36public:
37 SkShader();
38 virtual ~SkShader();
39
40 /** Return true if the shader has a non-identity local matrix.
41 @param localM Optional: If not null, return the shader's local matrix
42 @return true if the shader has a non-identity local matrix.
43 */
44 bool getLocalMatrix(SkMatrix* localM) const;
45 /** Set the shader's local matrix.
46 @param localM The shader's new local matrix.
47 */
48 void setLocalMatrix(const SkMatrix& localM);
49 /** Reset the shader's local matrix to identity.
50 */
51 void resetLocalMatrix();
52
53 enum TileMode {
54 kClamp_TileMode, //!< replicate the edge color if the shader draws outside of its original bounds
55 kRepeat_TileMode, //!< repeat the shader's image horizontally and vertically
56 kMirror_TileMode, //!< repeat the shader's image horizontally and vertically, alternating mirror images so that adjacent images always seam
57
58 kTileModeCount
59 };
60
61 // override these in your subclass
62
63 enum Flags {
64 //!< set if all of the colors will be opaque
reed@android.com3c9b2a42009-08-27 19:28:37 +000065 kOpaqueAlpha_Flag = 0x01,
reed@android.com5119bdb2009-06-12 21:27:03 +000066
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 //! set if this shader's shadeSpan16() method can be called
reed@android.com3c9b2a42009-08-27 19:28:37 +000068 kHasSpan16_Flag = 0x02,
reed@android.com5119bdb2009-06-12 21:27:03 +000069
reed@android.com8a1c16f2008-12-17 15:59:43 +000070 /** Set this bit if the shader's native data type is instrinsically 16
71 bit, meaning that calling the 32bit shadeSpan() entry point will
72 mean the the impl has to up-sample 16bit data into 32bit. Used as a
73 a means of clearing a dither request if the it will have no effect
74 */
reed@android.com5119bdb2009-06-12 21:27:03 +000075 kIntrinsicly16_Flag = 0x04,
76
77 /** set (after setContext) if the spans only vary in X (const in Y).
78 e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
reed@android.com3c9b2a42009-08-27 19:28:37 +000079 that varies from left-to-right. This flag specifies this for
80 shadeSpan().
reed@android.com5119bdb2009-06-12 21:27:03 +000081 */
reed@android.com3c9b2a42009-08-27 19:28:37 +000082 kConstInY32_Flag = 0x08,
83
84 /** same as kConstInY32_Flag, but is set if this is true for shadeSpan16
85 which may not always be the case, since shadeSpan16 may be
86 predithered, which would mean it was not const in Y, even though
87 the 32bit shadeSpan() would be const.
88 */
89 kConstInY16_Flag = 0x10
reed@android.com8a1c16f2008-12-17 15:59:43 +000090 };
91
92 /** Called sometimes before drawing with this shader.
93 Return the type of alpha your shader will return.
94 The default implementation returns 0. Your subclass should override if it can
95 (even sometimes) report a non-zero value, since that will enable various blitters
96 to perform faster.
97 */
98 virtual uint32_t getFlags() { return 0; }
99
100 /** Return the alpha associated with the data returned by shadeSpan16(). If
101 kHasSpan16_Flag is not set, this value is meaningless.
102 */
103 virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }
104
105 /** Called once before drawing, with the current paint and
106 device matrix. Return true if your shader supports these
107 parameters, or false if not. If false is returned, nothing
108 will be drawn.
109 */
reed@android.com3c9b2a42009-08-27 19:28:37 +0000110 virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
111 const SkMatrix& matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112
113 /** Called for each span of the object being drawn. Your subclass
114 should set the appropriate colors (with premultiplied alpha) that
115 correspond to the specified device coordinates.
116 */
reed@android.com3c9b2a42009-08-27 19:28:37 +0000117 virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
118 /** Called only for 16bit devices when getFlags() returns
119 kOpaqueAlphaFlag | kHasSpan16_Flag
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120 */
reed@android.com3c9b2a42009-08-27 19:28:37 +0000121 virtual void shadeSpan16(int x, int y, uint16_t[], int count);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122 /** Similar to shadeSpan, but only returns the alpha-channel for a span.
123 The default implementation calls shadeSpan() and then extracts the alpha
124 values from the returned colors.
125 */
reed@android.com3c9b2a42009-08-27 19:28:37 +0000126 virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127
128 /** Helper function that returns true if this shader's shadeSpan16() method can
129 be called.
130 */
reed@android.com3c9b2a42009-08-27 19:28:37 +0000131 bool canCallShadeSpan16() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132 return SkShader::CanCallShadeSpan16(this->getFlags());
133 }
134
135 /** Helper to check the flags to know if it is legal to call shadeSpan16()
136 */
137 static bool CanCallShadeSpan16(uint32_t flags) {
138 return (flags & kHasSpan16_Flag) != 0;
139 }
140
141 /** Called before a session using the shader begins. Some shaders override
142 this to defer some of their work (like calling bitmap.lockPixels()).
143 Must be balanced by a call to endSession.
144 */
145 virtual void beginSession();
146 virtual void endSession();
147
reed@android.comf2b98d62010-12-20 18:26:13 +0000148 /**
149 Gives method bitmap should be read to implement a shader.
150 Also determines number and interpretation of "extra" parameters returned
151 by asABitmap
152 */
153 enum BitmapType {
154 kNone_BitmapType, //<! Shader is not represented as a bitmap
155 kDefault_BitmapType,//<! Access bitmap using local coords transformed
156 // by matrix. No extras
157 kRadial_BitmapType, //<! Access bitmap by transforming local coordinates
158 // by the matrix and taking the distance of result
159 // from (0,0) as bitmap column. Bitmap is 1 pixel
160 // tall. No extras
161 kSweep_BitmapType, //<! Access bitmap by transforming local coordinates
162 // by the matrix and taking the angle of result
163 // to (0,0) as bitmap x coord, where angle = 0 is
164 // bitmap left edge of bitmap = 2pi is the
165 // right edge. Bitmap is 1 pixel tall. No extras
166 kTwoPointRadial_BitmapType
167 //<! Matrix transforms to space where (0,0) is
168 // the center of the starting circle. The second
169 // circle will be centered (x, 0) where x may be
170 // 0. The post-matrix space is normalized such
171 // that 1 is the second radius - first radius.
172 // Three extra parameters are returned:
173 // 0: x-offset of second circle center
174 // to first.
175 // 1: radius of first circle in post-matrix
176 // space
177 // 2: the second radius minus the first radius
178 // in pre-transformed space.
179
180 };
reed@android.com8a1c16f2008-12-17 15:59:43 +0000181 /** Optional methods for shaders that can pretend to be a bitmap/texture
reed@android.comf2b98d62010-12-20 18:26:13 +0000182 to play along with opengl. Default just returns kNone_BitmapType and
183 ignores the out parameters.
184
185 @param outTexture if non-NULL will be the bitmap representing the shader
186 after return.
187 @param outMatrix if non-NULL will be the matrix to apply to vertices
188 to access the bitmap after return.
189 @param xy if non-NULL will be the tile modes that should be
190 used to access the bitmap after return.
191 @param twoPointRadialParams Two extra return values needed for two point
192 radial bitmaps. The first is the x-offset of
193 the second point and the second is the radius
194 about the first point.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000195 */
reed@android.comf2b98d62010-12-20 18:26:13 +0000196 virtual BitmapType asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
197 TileMode xy[2], SkScalar* twoPointRadialParams);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198
199 //////////////////////////////////////////////////////////////////////////
200 // Factory methods for stock shaders
201
202 /** Call this to create a new shader that will draw with the specified bitmap.
203 @param src The bitmap to use inside the shader
204 @param tmx The tiling mode to use when sampling the bitmap in the x-direction.
205 @param tmy The tiling mode to use when sampling the bitmap in the y-direction.
206 @return Returns a new shader object. Note: this function never returns null.
207 */
208 static SkShader* CreateBitmapShader(const SkBitmap& src,
209 TileMode tmx, TileMode tmy);
210
211 virtual void flatten(SkFlattenableWriteBuffer& );
212protected:
213 enum MatrixClass {
214 kLinear_MatrixClass, // no perspective
215 kFixedStepInX_MatrixClass, // fast perspective, need to call fixedStepInX() each scanline
216 kPerspective_MatrixClass // slow perspective, need to mappoints each pixel
217 };
218 static MatrixClass ComputeMatrixClass(const SkMatrix&);
219
220 // These can be called by your subclass after setContext() has been called
221 uint8_t getPaintAlpha() const { return fPaintAlpha; }
222 SkBitmap::Config getDeviceConfig() const { return (SkBitmap::Config)fDeviceConfig; }
223 const SkMatrix& getTotalInverse() const { return fTotalInverse; }
224 MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
225
226 SkShader(SkFlattenableReadBuffer& );
227private:
228 SkMatrix* fLocalMatrix;
229 SkMatrix fTotalInverse;
230 uint8_t fPaintAlpha;
231 uint8_t fDeviceConfig;
232 uint8_t fTotalInverseClass;
233 SkDEBUGCODE(SkBool8 fInSession;)
234
235 static SkShader* CreateBitmapShader(const SkBitmap& src,
236 TileMode, TileMode,
237 void* storage, size_t storageSize);
238 friend class SkAutoBitmapShaderInstall;
239 typedef SkFlattenable INHERITED;
240};
241
242#endif
243