blob: a5ba12ec2fd53c94556787a223085e96462d3bb3 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
8#ifndef SkShader_DEFINED
9#define SkShader_DEFINED
10
Mike Reed75ae4212018-01-23 11:24:08 -050011#include "SkBlendMode.h"
Mike Reede602f392018-02-06 10:17:08 -050012#include "SkColor.h"
Mike Klein987de5b2016-11-17 10:47:39 -050013#include "SkFilterQuality.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014#include "SkFlattenable.h"
fmalitad0c4e092016-02-22 17:19:04 -080015#include "SkImageInfo.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000016#include "SkMatrix.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017
Herb Derby83e939b2017-02-07 14:25:11 -050018class SkArenaAlloc;
Mike Reed75ae4212018-01-23 11:24:08 -050019class SkBitmap;
reed3061af42016-01-07 15:47:29 -080020class SkColorFilter;
reed0ccc62d2016-05-04 13:09:39 -070021class SkColorSpace;
Matt Sarett6cc6ae752017-04-18 18:29:12 -040022class SkColorSpaceXformer;
reedf1ac1822016-08-01 11:24:14 -070023class SkImage;
reed@android.com8a1c16f2008-12-17 15:59:43 +000024class SkPath;
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +000025class SkPicture;
Mike Kleinb0d10e02016-11-12 10:29:26 -050026class SkRasterPipeline;
rileya@google.com03c1c352012-07-20 20:02:43 +000027class GrContext;
joshualittb0a8a372014-09-23 09:50:21 -070028class GrFragmentProcessor;
reed@android.com8a1c16f2008-12-17 15:59:43 +000029
30/** \class SkShader
reed@google.comad917992011-04-11 19:01:12 +000031 *
reed@google.com880dc472012-05-11 14:47:03 +000032 * Shaders specify the source color(s) for what is being drawn. If a paint
33 * has no shader, then the paint's color is used. If the paint has a
34 * shader, then the shader's color(s) are use instead, but they are
35 * modulated by the paint's alpha. This makes it easy to create a shader
36 * once (e.g. bitmap tiling or gradient) and then change its transparency
37 * w/o having to modify the original shader... only the paint's alpha needs
38 * to be modified.
reed@google.comad917992011-04-11 19:01:12 +000039 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000040class SK_API SkShader : public SkFlattenable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000041public:
reed@android.com8a1c16f2008-12-17 15:59:43 +000042 enum TileMode {
reed@google.com0beaba52012-03-16 14:38:06 +000043 /** replicate the edge color if the shader draws outside of its
44 * original bounds
45 */
46 kClamp_TileMode,
47
48 /** repeat the shader's image horizontally and vertically */
49 kRepeat_TileMode,
50
51 /** repeat the shader's image horizontally and vertically, alternating
52 * mirror images so that adjacent images always seam
53 */
54 kMirror_TileMode,
55
56#if 0
57 /** only draw within the original domain, return 0 everywhere else */
58 kDecal_TileMode,
59#endif
reed19c25f12015-03-15 14:01:21 -070060 };
reed@android.com8a1c16f2008-12-17 15:59:43 +000061
reed19c25f12015-03-15 14:01:21 -070062 enum {
63 kTileModeCount = kMirror_TileMode + 1
reed@android.com8a1c16f2008-12-17 15:59:43 +000064 };
65
Florin Malita4aed1382017-05-25 10:38:07 -040066 /**
67 * Returns the local matrix.
68 *
69 * FIXME: This can be incorrect for a Shader with its own local matrix
70 * that is also wrapped via CreateLocalMatrixShader.
71 */
72 const SkMatrix& getLocalMatrix() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +000073
reed@google.comad917992011-04-11 19:01:12 +000074 /**
junov@chromium.orgb6e16192011-12-09 15:48:03 +000075 * Returns true if the shader is guaranteed to produce only opaque
76 * colors, subject to the SkPaint using the shader to apply an opaque
77 * alpha value. Subclasses should override this to allow some
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000078 * optimizations.
junov@chromium.orgb6e16192011-12-09 15:48:03 +000079 */
80 virtual bool isOpaque() const { return false; }
81
Mike Reed627778d2016-09-28 17:13:38 -040082#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
reed@google.comad917992011-04-11 19:01:12 +000083 /**
reed0f0af232015-09-08 11:02:04 -070084 * Returns true if this shader is just a bitmap, and if not null, returns the bitmap,
85 * localMatrix, and tilemodes. If this is not a bitmap, returns false and ignores the
86 * out-parameters.
reed@android.comf2b98d62010-12-20 18:26:13 +000087 */
Florin Malita4aed1382017-05-25 10:38:07 -040088 bool isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const;
reed0f0af232015-09-08 11:02:04 -070089
reedf5822822015-08-19 11:46:38 -070090 bool isABitmap() const {
91 return this->isABitmap(nullptr, nullptr, nullptr);
92 }
Mike Reed627778d2016-09-28 17:13:38 -040093#endif
reedf5822822015-08-19 11:46:38 -070094
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +000095 /**
reedf1ac1822016-08-01 11:24:14 -070096 * Iff this shader is backed by a single SkImage, return its ptr (the caller must ref this
97 * if they want to keep it longer than the lifetime of the shader). If not, return nullptr.
98 */
Florin Malita4aed1382017-05-25 10:38:07 -040099 SkImage* isAImage(SkMatrix* localMatrix, TileMode xy[2]) const;
reedf1ac1822016-08-01 11:24:14 -0700100
101 bool isAImage() const {
102 return this->isAImage(nullptr, nullptr) != nullptr;
103 }
104
105 /**
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000106 * If the shader subclass can be represented as a gradient, asAGradient
107 * returns the matching GradientType enum (or kNone_GradientType if it
108 * cannot). Also, if info is not null, asAGradient populates info with
109 * the relevant (see below) parameters for the gradient. fColorCount
110 * is both an input and output parameter. On input, it indicates how
111 * many entries in fColors and fColorOffsets can be used, if they are
112 * non-NULL. After asAGradient has run, fColorCount indicates how
113 * many color-offset pairs there are in the gradient. If there is
114 * insufficient space to store all of the color-offset pairs, fColors
115 * and fColorOffsets will not be altered. fColorOffsets specifies
116 * where on the range of 0 to 1 to transition to the given color.
117 * The meaning of fPoint and fRadius is dependant on the type of gradient.
118 *
119 * None:
120 * info is ignored.
121 * Color:
122 * fColorOffsets[0] is meaningless.
123 * Linear:
124 * fPoint[0] and fPoint[1] are the end-points of the gradient
125 * Radial:
126 * fPoint[0] and fRadius[0] are the center and radius
reed71a6cbf2015-05-04 08:32:51 -0700127 * Conical:
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000128 * fPoint[0] and fRadius[0] are the center and radius of the 1st circle
129 * fPoint[1] and fRadius[1] are the center and radius of the 2nd circle
130 * Sweep:
131 * fPoint[0] is the center of the sweep.
132 */
133
134 enum GradientType {
135 kNone_GradientType,
136 kColor_GradientType,
137 kLinear_GradientType,
138 kRadial_GradientType,
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000139 kSweep_GradientType,
reed@google.com83226972012-06-07 20:26:47 +0000140 kConical_GradientType,
141 kLast_GradientType = kConical_GradientType
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000142 };
143
144 struct GradientInfo {
145 int fColorCount; //!< In-out parameter, specifies passed size
146 // of fColors/fColorOffsets on input, and
147 // actual number of colors/offsets on
148 // output.
149 SkColor* fColors; //!< The colors in the gradient.
150 SkScalar* fColorOffsets; //!< The unit offset for color transitions.
151 SkPoint fPoint[2]; //!< Type specific, see above.
152 SkScalar fRadius[2]; //!< Type specific, see above.
153 TileMode fTileMode; //!< The tile mode used.
reed@google.com3d3a8602013-05-24 14:58:44 +0000154 uint32_t fGradientFlags; //!< see SkGradientShader::Flags
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000155 };
156
157 virtual GradientType asAGradient(GradientInfo* info) const;
158
Mike Reeda6aaa302017-06-09 10:29:40 -0400159#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
Florin Malitad93e11c2017-05-24 21:15:46 +0000160 struct ComposeRec {
161 const SkShader* fShaderA;
162 const SkShader* fShaderB;
163 SkBlendMode fBlendMode;
164 };
Florin Malitad93e11c2017-05-24 21:15:46 +0000165 virtual bool asACompose(ComposeRec*) const { return false; }
Mike Reeda6aaa302017-06-09 10:29:40 -0400166#endif
Florin Malitad93e11c2017-05-24 21:15:46 +0000167
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168 //////////////////////////////////////////////////////////////////////////
reedf880e452015-12-30 13:39:41 -0800169 // Methods to create combinations or variants of shaders
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +0000171 /**
reedf880e452015-12-30 13:39:41 -0800172 * Return a shader that will apply the specified localMatrix to this shader.
173 * The specified matrix will be applied before any matrix associated with this shader.
174 */
reed150835e2016-03-10 06:36:49 -0800175 sk_sp<SkShader> makeWithLocalMatrix(const SkMatrix&) const;
reed3061af42016-01-07 15:47:29 -0800176
177 /**
178 * Create a new shader that produces the same colors as invoking this shader and then applying
179 * the colorfilter.
180 */
reedd053ce92016-03-22 10:17:23 -0700181 sk_sp<SkShader> makeWithColorFilter(sk_sp<SkColorFilter>) const;
reeda2b340f2016-02-10 08:53:15 -0800182
reedf880e452015-12-30 13:39:41 -0800183 //////////////////////////////////////////////////////////////////////////
184 // Factory methods for stock shaders
Mike Kleinb0d10e02016-11-12 10:29:26 -0500185
reedf880e452015-12-30 13:39:41 -0800186 /**
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +0000187 * Call this to create a new "empty" shader, that will not draw anything.
188 */
reed8a21c9f2016-03-08 18:50:00 -0800189 static sk_sp<SkShader> MakeEmptyShader();
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +0000190
reed8367b8c2014-08-22 08:30:20 -0700191 /**
192 * Call this to create a new shader that just draws the specified color. This should always
193 * draw the same as a paint with this color (and no shader).
194 */
reed8a21c9f2016-03-08 18:50:00 -0800195 static sk_sp<SkShader> MakeColorShader(SkColor);
reed8367b8c2014-08-22 08:30:20 -0700196
reed0ccc62d2016-05-04 13:09:39 -0700197 /**
198 * Create a shader that draws the specified color (in the specified colorspace).
199 *
200 * This works around the limitation that SkPaint::setColor() only takes byte values, and does
201 * not support specific colorspaces.
202 */
203 static sk_sp<SkShader> MakeColorShader(const SkColor4f&, sk_sp<SkColorSpace>);
204
Mike Reed01b2b832017-06-09 10:51:52 -0400205 /**
206 * Compose two shaders together, using two operators: mode and lerp. The resulting colors
207 * are computed by first combining the src and dst shaders using mode, and then linearly
208 * interpolating between the dst and result colors using lerp.
209 *
210 * result = dst * (1 - lerp) + (src (mode) dst) * lerp
211 *
212 * If either shader is nullptr, then this returns nullptr.
213 * If lerp is NaN then this returns nullptr, otherwise lerp is clamped to [0..1].
214 */
215 static sk_sp<SkShader> MakeCompose(sk_sp<SkShader> dst, sk_sp<SkShader> src,
216 SkBlendMode mode, float lerp = 1);
217
218 /*
219 * DEPRECATED: call MakeCompose.
220 */
221 static sk_sp<SkShader> MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
222 SkBlendMode mode) {
223 return MakeCompose(std::move(dst), std::move(src), mode, 1);
224 }
225
226 /**
227 * Compose two shaders together using a weighted average.
228 *
229 * result = dst * (1 - lerp) + src * lerp
230 *
231 * If either shader is nullptr, then this returns nullptr.
232 * If lerp is NaN then this returns nullptr, otherwise lerp is clamped to [0..1].
233 */
234 static sk_sp<SkShader> MakeMixer(sk_sp<SkShader> dst, sk_sp<SkShader> src, float lerp) {
235 return MakeCompose(std::move(dst), std::move(src), SkBlendMode::kSrc, lerp);
236 }
Mike Reed7d954ad2016-10-28 15:42:34 -0400237
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238 /** Call this to create a new shader that will draw with the specified bitmap.
reed@google.com99c114e2012-05-03 20:14:26 +0000239 *
240 * If the bitmap cannot be used (e.g. has no pixels, or its dimensions
241 * exceed implementation limits (currently at 64K - 1)) then SkEmptyShader
242 * may be returned.
243 *
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000244 * If the src is kA8_Config then that mask will be colorized using the color on
245 * the paint.
246 *
reed@google.com99c114e2012-05-03 20:14:26 +0000247 * @param src The bitmap to use inside the shader
248 * @param tmx The tiling mode to use when sampling the bitmap in the x-direction.
249 * @param tmy The tiling mode to use when sampling the bitmap in the y-direction.
250 * @return Returns a new shader object. Note: this function never returns null.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251 */
reed8a21c9f2016-03-08 18:50:00 -0800252 static sk_sp<SkShader> MakeBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
253 const SkMatrix* localMatrix = nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000254
halcanarya5f46e12015-09-08 07:12:25 -0700255 // NOTE: You can create an SkImage Shader with SkImage::newShader().
256
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000257 /** Call this to create a new shader that will draw with the specified picture.
258 *
259 * @param src The picture to use inside the shader (if not NULL, its ref count
commit-bot@chromium.org855e88e2014-04-21 19:33:12 +0000260 * is incremented). The SkPicture must not be changed after
261 * successfully creating a picture shader.
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000262 * @param tmx The tiling mode to use when sampling the bitmap in the x-direction.
263 * @param tmy The tiling mode to use when sampling the bitmap in the y-direction.
fmalitab5f78262014-08-06 13:07:15 -0700264 * @param tile The tile rectangle in picture coordinates: this represents the subset
265 * (or superset) of the picture used when building a tile. It is not
266 * affected by localMatrix and does not imply scaling (only translation
267 * and cropping). If null, the tile rect is considered equal to the picture
268 * bounds.
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000269 * @return Returns a new shader object. Note: this function never returns null.
270 */
reed7fb4f8b2016-03-11 04:33:52 -0800271 static sk_sp<SkShader> MakePictureShader(sk_sp<SkPicture> src, TileMode tmx, TileMode tmy,
reed8a21c9f2016-03-08 18:50:00 -0800272 const SkMatrix* localMatrix, const SkRect* tile);
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000273
Florin Malitad93e11c2017-05-24 21:15:46 +0000274 /**
275 * If this shader can be represented by another shader + a localMatrix, return that shader and
276 * the localMatrix. If not, return nullptr and ignore the localMatrix parameter.
277 */
Florin Malita4aed1382017-05-25 10:38:07 -0400278 // TODO: clean up clients, move to SkShaderBase.
Florin Malitad93e11c2017-05-24 21:15:46 +0000279 virtual sk_sp<SkShader> makeAsALocalMatrixShader(SkMatrix* localMatrix) const;
280
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +0000281private:
Florin Malitaf7beee72017-05-26 12:54:32 -0400282 SkShader() = default;
283 friend class SkShaderBase;
284
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285 typedef SkFlattenable INHERITED;
286};
287
288#endif