blob: 65e0f0d41f180eeb749de12b449797f03c65674e [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
16/** \class SkXfermode
17
18 SkXfermode is the base class for objects that are called to implement custom
19 "transfer-modes" in the drawing pipeline. The static function Create(Modes)
20 can be called to return an instance of any of the predefined subclasses as
21 specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
22 then objects drawn with that paint have the xfermode applied.
23*/
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000024class SK_API SkXfermode : public SkFlattenable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000025public:
26 SkXfermode() {}
27
28 virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
29 const SkAlpha aa[]);
30 virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
31 const SkAlpha aa[]);
32 virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count,
33 const SkAlpha aa[]);
34 virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
35 const SkAlpha aa[]);
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000036
reed@android.comd252db02009-04-01 18:31:44 +000037 /** Enum of possible coefficients to describe some xfermodes
38 */
reed@android.com8a1c16f2008-12-17 15:59:43 +000039 enum Coeff {
reed@android.comd252db02009-04-01 18:31:44 +000040 kZero_Coeff, /** 0 */
41 kOne_Coeff, /** 1 */
42 kSC_Coeff, /** src color */
43 kISC_Coeff, /** inverse src color (i.e. 1 - sc) */
44 kDC_Coeff, /** dst color */
45 kIDC_Coeff, /** inverse dst color (i.e. 1 - dc) */
46 kSA_Coeff, /** src alpha */
47 kISA_Coeff, /** inverse src alpha (i.e. 1 - sa) */
48 kDA_Coeff, /** dst alpha */
49 kIDA_Coeff, /** inverse dst alpha (i.e. 1 - da) */
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000050
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 kCoeffCount
52 };
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000053
reed@android.comd252db02009-04-01 18:31:44 +000054 /** If the xfermode can be expressed as an equation using the coefficients
55 in Coeff, then asCoeff() returns true, and sets (if not null) src and
56 dst accordingly.
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000057
reed@android.comd252db02009-04-01 18:31:44 +000058 result = src_coeff * src_color + dst_coeff * dst_color;
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000059
reed@android.comd252db02009-04-01 18:31:44 +000060 As examples, here are some of the porterduff coefficients
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000061
reed@android.comd252db02009-04-01 18:31:44 +000062 MODE SRC_COEFF DST_COEFF
63 clear zero zero
64 src one zero
65 dst zero one
66 srcover one isa
67 dstover ida one
68 */
reed@android.com8a1c16f2008-12-17 15:59:43 +000069 virtual bool asCoeff(Coeff* src, Coeff* dst);
70
reed@google.com43c50c82011-04-14 15:50:52 +000071 /**
72 * The same as calling xfermode->asCoeff(..), except that this also checks
73 * if the xfermode is NULL, and if so, treats its as kSrcOver_Mode.
74 */
75 static bool AsCoeff(SkXfermode*, Coeff* src, Coeff* dst);
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000076
reed@android.coma0f5d152009-06-22 17:38:10 +000077 /** List of predefined xfermodes.
78 The algebra for the modes uses the following symbols:
79 Sa, Sc - source alpha and color
80 Da, Dc - destination alpha and color (before compositing)
81 [a, c] - Resulting (alpha, color) values
82 For these equations, the colors are in premultiplied state.
83 If no xfermode is specified, kSrcOver is assumed.
84 */
85 enum Mode {
86 kClear_Mode, //!< [0, 0]
87 kSrc_Mode, //!< [Sa, Sc]
88 kDst_Mode, //!< [Da, Dc]
89 kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc]
90 kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc]
91 kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
92 kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
93 kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
94 kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
95 kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
96 kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
97 kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
98
bsalomon@google.comf2d91552011-05-16 20:56:06 +000099 // all remaining modes are defined in the SVG Compositing standard
reed@android.coma0f5d152009-06-22 17:38:10 +0000100 // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/
101 kPlus_Mode,
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000102 kMultiply_Mode,
103
104 // all above modes can be expressed as pair of src/dst Coeffs
105 kCoeffModesCnt,
106
107 kScreen_Mode = kCoeffModesCnt,
reed@android.coma0f5d152009-06-22 17:38:10 +0000108 kOverlay_Mode,
109 kDarken_Mode,
110 kLighten_Mode,
111 kColorDodge_Mode,
112 kColorBurn_Mode,
113 kHardLight_Mode,
114 kSoftLight_Mode,
115 kDifference_Mode,
116 kExclusion_Mode,
117
118 kLastMode = kExclusion_Mode
119 };
120
reed@google.comc0d4aa22011-04-13 21:12:04 +0000121 /**
122 * If the xfermode is one of the modes in the Mode enum, then asMode()
123 * returns true and sets (if not null) mode accordingly. Otherwise it
124 * returns false and ignores the mode parameter.
vandebo@chromium.org48543272011-02-08 19:28:07 +0000125 */
126 virtual bool asMode(Mode* mode);
127
reed@google.com43c50c82011-04-14 15:50:52 +0000128 /**
129 * The same as calling xfermode->asMode(mode), except that this also checks
130 * if the xfermode is NULL, and if so, treats its as kSrcOver_Mode.
131 */
132 static bool AsMode(SkXfermode*, Mode* mode);
133
mike@reedtribe.orge303fcf2011-11-17 02:16:43 +0000134 /**
135 * Returns true if the xfermode claims to be the specified Mode. This works
136 * correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
137 * you can say this without checking for a null...
138 *
139 * If (SkXfermode::IsMode(paint.getXfermode(),
140 * SkXfermode::kDstOver_Mode)) {
141 * ...
142 * }
143 */
144 static bool IsMode(SkXfermode* xfer, Mode mode);
145
reed@android.coma0f5d152009-06-22 17:38:10 +0000146 /** Return an SkXfermode object for the specified mode.
147 */
148 static SkXfermode* Create(Mode mode);
149
150 /** Return a function pointer to a routine that applies the specified
151 porter-duff transfer mode.
152 */
153 static SkXfermodeProc GetProc(Mode mode);
154
155 /** Return a function pointer to a routine that applies the specified
156 porter-duff transfer mode and srcColor to a 16bit device color. Note,
157 if the mode+srcColor might return a non-opaque color, then there is not
158 16bit proc, and this will return NULL.
159 */
160 static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor);
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000161
reed@google.comc0d4aa22011-04-13 21:12:04 +0000162 /**
reed@google.com43c50c82011-04-14 15:50:52 +0000163 * If the specified mode can be represented by a pair of Coeff, then return
164 * true and set (if not NULL) the corresponding coeffs. If the mode is
165 * not representable as a pair of Coeffs, return false and ignore the
166 * src and dst parameters.
reed@android.coma0f5d152009-06-22 17:38:10 +0000167 */
reed@google.com43c50c82011-04-14 15:50:52 +0000168 static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
reed@android.coma0f5d152009-06-22 17:38:10 +0000169
reed@google.com43c50c82011-04-14 15:50:52 +0000170 // DEPRECATED: call AsMode(...)
171 static bool IsMode(SkXfermode* xfer, Mode* mode) {
172 return AsMode(xfer, mode);
173 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000174
djsollen@google.coma2ca41e2012-03-23 19:00:34 +0000175 SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
reed@android.com8a1c16f2008-12-17 15:59:43 +0000176protected:
177 SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000178
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179 /** The default implementation of xfer32/xfer16/xferA8 in turn call this
180 method, 1 color at a time (upscaled to a SkPMColor). The default
181 implmentation of this method just returns dst. If performance is
182 important, your subclass should override xfer32/xfer16/xferA8 directly.
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000183
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184 This method will not be called directly by the client, so it need not
185 be implemented if your subclass has overridden xfer32/xfer16/xferA8
186 */
187 virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst);
188
189private:
reed@android.coma0f5d152009-06-22 17:38:10 +0000190 enum {
191 kModeCount = kLastMode + 1
192 };
reed@android.com8a1c16f2008-12-17 15:59:43 +0000193 typedef SkFlattenable INHERITED;
194};
195
196///////////////////////////////////////////////////////////////////////////////
197
198/** \class SkProcXfermode
199
200 SkProcXfermode is a xfermode that applies the specified proc to its colors.
201 This class is not exported to java.
202*/
203class SkProcXfermode : public SkXfermode {
204public:
205 SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {}
206
207 // overrides from SkXfermode
208 virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
tomhudson@google.com13413042011-10-03 16:01:10 +0000209 const SkAlpha aa[]) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210 virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
tomhudson@google.com13413042011-10-03 16:01:10 +0000211 const SkAlpha aa[]) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212 virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count,
tomhudson@google.com13413042011-10-03 16:01:10 +0000213 const SkAlpha aa[]) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000214 virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
tomhudson@google.com13413042011-10-03 16:01:10 +0000215 const SkAlpha aa[]) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216
217 // overrides from SkFlattenable
tomhudson@google.com13413042011-10-03 16:01:10 +0000218 virtual void flatten(SkFlattenableWriteBuffer&) SK_OVERRIDE;
djsollen@google.comba28d032012-03-26 17:57:35 +0000219 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcXfermode)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220
221protected:
222 SkProcXfermode(SkFlattenableReadBuffer&);
223
reed@google.comc34d7cf2011-08-09 22:42:10 +0000224 // allow subclasses to update this after we unflatten
225 void setProc(SkXfermodeProc proc) {
226 fProc = proc;
227 }
228
reed@android.com8a1c16f2008-12-17 15:59:43 +0000229private:
230 SkXfermodeProc fProc;
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000231
reed@android.com8a1c16f2008-12-17 15:59:43 +0000232 typedef SkXfermode INHERITED;
233};
234
235#endif