blob: 86c08dd6b7bb43d86731b85def691248a7d515b8 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com8a1c16f2008-12-17 15:59:43 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#ifndef SkXfermode_DEFINED
11#define SkXfermode_DEFINED
12
13#include "SkFlattenable.h"
14#include "SkColor.h"
15
bsalomon@google.comf51c0132013-03-27 18:31:15 +000016class GrEffectRef;
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000017class GrTexture;
robertphillips@google.comb83b6b42013-01-22 14:32:09 +000018class SkString;
19
reed@android.com8a1c16f2008-12-17 15:59:43 +000020/** \class SkXfermode
reed@google.comfb6deed2013-10-10 17:35:58 +000021 *
22 * SkXfermode is the base class for objects that are called to implement custom
23 * "transfer-modes" in the drawing pipeline. The static function Create(Modes)
24 * can be called to return an instance of any of the predefined subclasses as
25 * specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
26 * then objects drawn with that paint have the xfermode applied.
27 *
28 * All subclasses are required to be reentrant-safe : it must be legal to share
29 * the same instance between several threads.
30 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000031class SK_API SkXfermode : public SkFlattenable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000032public:
robertphillips@google.com0456e0b2012-06-27 14:03:26 +000033 SK_DECLARE_INST_COUNT(SkXfermode)
34
reed@android.com8a1c16f2008-12-17 15:59:43 +000035 virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
reed@google.com30da7452012-12-17 19:55:24 +000036 const SkAlpha aa[]) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +000037 virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
reed@google.com30da7452012-12-17 19:55:24 +000038 const SkAlpha aa[]) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +000039 virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
reed@google.com30da7452012-12-17 19:55:24 +000040 const SkAlpha aa[]) const;
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000041
reed@android.comd252db02009-04-01 18:31:44 +000042 /** Enum of possible coefficients to describe some xfermodes
43 */
reed@android.com8a1c16f2008-12-17 15:59:43 +000044 enum Coeff {
reed@android.comd252db02009-04-01 18:31:44 +000045 kZero_Coeff, /** 0 */
46 kOne_Coeff, /** 1 */
47 kSC_Coeff, /** src color */
48 kISC_Coeff, /** inverse src color (i.e. 1 - sc) */
49 kDC_Coeff, /** dst color */
50 kIDC_Coeff, /** inverse dst color (i.e. 1 - dc) */
51 kSA_Coeff, /** src alpha */
52 kISA_Coeff, /** inverse src alpha (i.e. 1 - sa) */
53 kDA_Coeff, /** dst alpha */
54 kIDA_Coeff, /** inverse dst alpha (i.e. 1 - da) */
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000055
reed@android.com8a1c16f2008-12-17 15:59:43 +000056 kCoeffCount
57 };
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000058
reed@android.comd252db02009-04-01 18:31:44 +000059 /** If the xfermode can be expressed as an equation using the coefficients
60 in Coeff, then asCoeff() returns true, and sets (if not null) src and
61 dst accordingly.
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000062
reed@android.comd252db02009-04-01 18:31:44 +000063 result = src_coeff * src_color + dst_coeff * dst_color;
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000064
reed@android.comd252db02009-04-01 18:31:44 +000065 As examples, here are some of the porterduff coefficients
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000066
reed@android.comd252db02009-04-01 18:31:44 +000067 MODE SRC_COEFF DST_COEFF
68 clear zero zero
69 src one zero
70 dst zero one
71 srcover one isa
72 dstover ida one
73 */
reed@google.com30da7452012-12-17 19:55:24 +000074 virtual bool asCoeff(Coeff* src, Coeff* dst) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +000075
reed@google.com43c50c82011-04-14 15:50:52 +000076 /**
77 * The same as calling xfermode->asCoeff(..), except that this also checks
bsalomon@google.comf51c0132013-03-27 18:31:15 +000078 * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
reed@google.com43c50c82011-04-14 15:50:52 +000079 */
reed@google.com30da7452012-12-17 19:55:24 +000080 static bool AsCoeff(const SkXfermode*, Coeff* src, Coeff* dst);
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000081
reed@android.coma0f5d152009-06-22 17:38:10 +000082 /** List of predefined xfermodes.
83 The algebra for the modes uses the following symbols:
84 Sa, Sc - source alpha and color
85 Da, Dc - destination alpha and color (before compositing)
86 [a, c] - Resulting (alpha, color) values
87 For these equations, the colors are in premultiplied state.
88 If no xfermode is specified, kSrcOver is assumed.
bsalomon@google.com8da9bc72013-04-19 15:03:21 +000089 The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those
90 that aren't Coeffs but have separable r,g,b computations, and finally
91 those that are not separable.
reed@android.coma0f5d152009-06-22 17:38:10 +000092 */
93 enum Mode {
94 kClear_Mode, //!< [0, 0]
95 kSrc_Mode, //!< [Sa, Sc]
96 kDst_Mode, //!< [Da, Dc]
97 kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc]
98 kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc]
99 kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
100 kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
101 kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
102 kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
103 kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
104 kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
105 kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
commit-bot@chromium.orgb24f8932013-03-05 16:23:59 +0000106 kPlus_Mode, //!< [Sa + Da, Sc + Dc]
reed@google.com8d3cd7a2013-01-30 21:36:11 +0000107 kModulate_Mode, // multiplies all components (= alpha and color)
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000108
skia.committer@gmail.com64334352013-03-06 07:01:46 +0000109 // Following blend modes are defined in the CSS Compositing standard:
commit-bot@chromium.orgb24f8932013-03-05 16:23:59 +0000110 // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
bsalomon@google.comb0091b82013-04-15 15:16:47 +0000111 kScreen_Mode,
bsalomon@google.com8da9bc72013-04-19 15:03:21 +0000112 kLastCoeffMode = kScreen_Mode,
113
114 kOverlay_Mode,
reed@android.coma0f5d152009-06-22 17:38:10 +0000115 kDarken_Mode,
116 kLighten_Mode,
117 kColorDodge_Mode,
118 kColorBurn_Mode,
119 kHardLight_Mode,
120 kSoftLight_Mode,
121 kDifference_Mode,
122 kExclusion_Mode,
reed@google.com25cfa692013-02-04 20:06:00 +0000123 kMultiply_Mode,
bsalomon@google.com8da9bc72013-04-19 15:03:21 +0000124 kLastSeparableMode = kMultiply_Mode,
reed@android.coma0f5d152009-06-22 17:38:10 +0000125
commit-bot@chromium.orgb24f8932013-03-05 16:23:59 +0000126 kHue_Mode,
127 kSaturation_Mode,
128 kColor_Mode,
129 kLuminosity_Mode,
commit-bot@chromium.orgb24f8932013-03-05 16:23:59 +0000130 kLastMode = kLuminosity_Mode
reed@android.coma0f5d152009-06-22 17:38:10 +0000131 };
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000132
commit-bot@chromium.orgd7aaf602013-04-01 12:51:34 +0000133 /**
134 * Gets the name of the Mode as a string.
135 */
136 static const char* ModeName(Mode);
reed@android.coma0f5d152009-06-22 17:38:10 +0000137
reed@google.comc0d4aa22011-04-13 21:12:04 +0000138 /**
139 * If the xfermode is one of the modes in the Mode enum, then asMode()
140 * returns true and sets (if not null) mode accordingly. Otherwise it
141 * returns false and ignores the mode parameter.
vandebo@chromium.org48543272011-02-08 19:28:07 +0000142 */
reed@google.com30da7452012-12-17 19:55:24 +0000143 virtual bool asMode(Mode* mode) const;
vandebo@chromium.org48543272011-02-08 19:28:07 +0000144
reed@google.com43c50c82011-04-14 15:50:52 +0000145 /**
146 * The same as calling xfermode->asMode(mode), except that this also checks
bsalomon@google.comf51c0132013-03-27 18:31:15 +0000147 * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
reed@google.com43c50c82011-04-14 15:50:52 +0000148 */
reed@google.com30da7452012-12-17 19:55:24 +0000149 static bool AsMode(const SkXfermode*, Mode* mode);
reed@google.com43c50c82011-04-14 15:50:52 +0000150
mike@reedtribe.orge303fcf2011-11-17 02:16:43 +0000151 /**
152 * Returns true if the xfermode claims to be the specified Mode. This works
153 * correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
154 * you can say this without checking for a null...
155 *
156 * If (SkXfermode::IsMode(paint.getXfermode(),
157 * SkXfermode::kDstOver_Mode)) {
158 * ...
159 * }
160 */
reed@google.com30da7452012-12-17 19:55:24 +0000161 static bool IsMode(const SkXfermode* xfer, Mode mode);
mike@reedtribe.orge303fcf2011-11-17 02:16:43 +0000162
reed@android.coma0f5d152009-06-22 17:38:10 +0000163 /** Return an SkXfermode object for the specified mode.
164 */
165 static SkXfermode* Create(Mode mode);
166
167 /** Return a function pointer to a routine that applies the specified
168 porter-duff transfer mode.
169 */
170 static SkXfermodeProc GetProc(Mode mode);
171
172 /** Return a function pointer to a routine that applies the specified
173 porter-duff transfer mode and srcColor to a 16bit device color. Note,
174 if the mode+srcColor might return a non-opaque color, then there is not
175 16bit proc, and this will return NULL.
176 */
177 static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor);
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000178
reed@google.comc0d4aa22011-04-13 21:12:04 +0000179 /**
reed@google.com43c50c82011-04-14 15:50:52 +0000180 * If the specified mode can be represented by a pair of Coeff, then return
181 * true and set (if not NULL) the corresponding coeffs. If the mode is
182 * not representable as a pair of Coeffs, return false and ignore the
183 * src and dst parameters.
reed@android.coma0f5d152009-06-22 17:38:10 +0000184 */
reed@google.com43c50c82011-04-14 15:50:52 +0000185 static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
reed@android.coma0f5d152009-06-22 17:38:10 +0000186
reed@google.com44699382013-10-31 17:28:30 +0000187 SK_ATTR_DEPRECATED("use AsMode(...)")
reed@google.com30da7452012-12-17 19:55:24 +0000188 static bool IsMode(const SkXfermode* xfer, Mode* mode) {
reed@google.com43c50c82011-04-14 15:50:52 +0000189 return AsMode(xfer, mode);
190 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000191
bsalomon@google.comf51c0132013-03-27 18:31:15 +0000192 /** A subclass may implement this factory function to work with the GPU backend. It is legal
senorblanco@chromium.org1a6382f2013-10-23 18:41:36 +0000193 to call this with all params NULL to simply test the return value. If effect is non-NULL
194 then the xfermode may optionally allocate an effect to return and the caller as *effect.
195 The caller will install it and own a ref to it. Since the xfermode may or may not assign
196 *effect, the caller should set *effect to NULL beforehand. background specifies the
197 texture to use as the background for compositing, and should be accessed in the effect's
198 fragment shader. If NULL, the effect should request access to destination color
199 (setWillReadDstColor()), and use that in the fragment shader (builder->dstColor()).
bsalomon@google.comf51c0132013-03-27 18:31:15 +0000200 */
senorblanco@chromium.org1a6382f2013-10-23 18:41:36 +0000201 virtual bool asNewEffect(GrEffectRef** effect, GrTexture* background = NULL) const;
bsalomon@google.comf51c0132013-03-27 18:31:15 +0000202
senorblanco@chromium.org1a6382f2013-10-23 18:41:36 +0000203 /** Returns true if the xfermode can be expressed as coeffs (src, dst), or as an effect
204 (effect). This helper calls the asCoeff() and asNewEffect() virtuals. If the xfermode is
205 NULL, it is treated as kSrcOver_Mode. It is legal to call this with all params NULL to
206 simply test the return value. effect, src, and dst must all be NULL or all non-NULL.
bsalomon@google.comf51c0132013-03-27 18:31:15 +0000207 */
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000208 static bool AsNewEffectOrCoeff(SkXfermode*,
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000209 GrEffectRef** effect,
210 Coeff* src,
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000211 Coeff* dst,
212 GrTexture* background = NULL);
bsalomon@google.comf51c0132013-03-27 18:31:15 +0000213
robertphillips@google.comb83b6b42013-01-22 14:32:09 +0000214 SkDEVCODE(virtual void toString(SkString* str) const = 0;)
djsollen@google.coma2ca41e2012-03-23 19:00:34 +0000215 SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000216 SK_DEFINE_FLATTENABLE_TYPE(SkXfermode)
217
reed@android.com8a1c16f2008-12-17 15:59:43 +0000218protected:
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000219 SkXfermode(SkReadBuffer& rb) : SkFlattenable(rb) {}
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000220
reed@android.com8a1c16f2008-12-17 15:59:43 +0000221 /** The default implementation of xfer32/xfer16/xferA8 in turn call this
222 method, 1 color at a time (upscaled to a SkPMColor). The default
223 implmentation of this method just returns dst. If performance is
224 important, your subclass should override xfer32/xfer16/xferA8 directly.
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000225
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226 This method will not be called directly by the client, so it need not
227 be implemented if your subclass has overridden xfer32/xfer16/xferA8
228 */
reed@google.com30da7452012-12-17 19:55:24 +0000229 virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000230
commit-bot@chromium.org0a2bf902014-02-20 20:40:19 +0000231#ifdef SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS
232public:
233#endif
234 SkXfermode() {}
235
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236private:
reed@android.coma0f5d152009-06-22 17:38:10 +0000237 enum {
238 kModeCount = kLastMode + 1
239 };
commit-bot@chromium.org86490572013-10-04 16:52:55 +0000240
241 friend class SkGraphics;
242 static void Term();
243
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244 typedef SkFlattenable INHERITED;
245};
246
247///////////////////////////////////////////////////////////////////////////////
248
249/** \class SkProcXfermode
250
251 SkProcXfermode is a xfermode that applies the specified proc to its colors.
252 This class is not exported to java.
253*/
254class SkProcXfermode : public SkXfermode {
255public:
commit-bot@chromium.org0a2bf902014-02-20 20:40:19 +0000256 static SkProcXfermode* Create(SkXfermodeProc proc) {
257 return SkNEW_ARGS(SkProcXfermode, (proc));
258 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259
260 // overrides from SkXfermode
261 virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
reed@google.com30da7452012-12-17 19:55:24 +0000262 const SkAlpha aa[]) const SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000263 virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
reed@google.com30da7452012-12-17 19:55:24 +0000264 const SkAlpha aa[]) const SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000265 virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
reed@google.com30da7452012-12-17 19:55:24 +0000266 const SkAlpha aa[]) const SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000267
robertphillips@google.comb83b6b42013-01-22 14:32:09 +0000268 SK_DEVELOPER_TO_STRING()
djsollen@google.comba28d032012-03-26 17:57:35 +0000269 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcXfermode)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270
271protected:
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000272 SkProcXfermode(SkReadBuffer&);
273 virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000274
reed@google.comc34d7cf2011-08-09 22:42:10 +0000275 // allow subclasses to update this after we unflatten
276 void setProc(SkXfermodeProc proc) {
277 fProc = proc;
278 }
279
commit-bot@chromium.orgdf187c72013-10-09 14:39:46 +0000280 SkXfermodeProc getProc() const {
281 return fProc;
282 }
283
commit-bot@chromium.org0a2bf902014-02-20 20:40:19 +0000284#ifdef SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS
285public:
286#endif
287 SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {}
288
reed@android.com8a1c16f2008-12-17 15:59:43 +0000289private:
290 SkXfermodeProc fProc;
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000291
reed@android.com8a1c16f2008-12-17 15:59:43 +0000292 typedef SkXfermode INHERITED;
293};
294
295#endif