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 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 : */
24 0 : class SK_API SkXfermode : public SkFlattenable {
25 : public:
26 0 : 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[]);
36 :
37 : /** Enum of possible coefficients to describe some xfermodes
38 : */
39 : enum Coeff {
40 : 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) */
50 :
51 : kCoeffCount
52 : };
53 :
54 : /** 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.
57 :
58 : result = src_coeff * src_color + dst_coeff * dst_color;
59 :
60 : As examples, here are some of the porterduff coefficients
61 :
62 : 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 : */
69 : virtual bool asCoeff(Coeff* src, Coeff* dst);
70 :
71 : /**
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);
76 :
77 : /** 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 :
99 : // all remaining modes are defined in the SVG Compositing standard
100 : // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/
101 : kPlus_Mode,
102 : kMultiply_Mode,
103 :
104 : // all above modes can be expressed as pair of src/dst Coeffs
105 : kCoeffModesCnt,
106 :
107 : kScreen_Mode = kCoeffModesCnt,
108 : 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 :
121 : /**
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.
125 : */
126 : virtual bool asMode(Mode* mode);
127 :
128 : /**
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 :
134 : /**
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 :
146 : /** 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);
161 :
162 : /**
163 : * 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.
167 : */
168 : static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
169 :
170 : // DEPRECATED: call AsMode(...)
171 : static bool IsMode(SkXfermode* xfer, Mode* mode) {
172 : return AsMode(xfer, mode);
173 : }
174 :
175 : SK_DECLARE_FLATTENABLE_REGISTRAR()
176 : protected:
177 0 : SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}
178 :
179 : /** 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.
183 :
184 : 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 :
189 : private:
190 : enum {
191 : kModeCount = kLastMode + 1
192 : };
193 : 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 : */
203 0 : class SkProcXfermode : public SkXfermode {
204 : public:
205 0 : SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {}
206 :
207 : // overrides from SkXfermode
208 : virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
209 : const SkAlpha aa[]) SK_OVERRIDE;
210 : virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
211 : const SkAlpha aa[]) SK_OVERRIDE;
212 : virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count,
213 : const SkAlpha aa[]) SK_OVERRIDE;
214 : virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
215 : const SkAlpha aa[]) SK_OVERRIDE;
216 :
217 : // overrides from SkFlattenable
218 0 : virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
219 : virtual void flatten(SkFlattenableWriteBuffer&) SK_OVERRIDE;
220 :
221 : protected:
222 : SkProcXfermode(SkFlattenableReadBuffer&);
223 :
224 : // allow subclasses to update this after we unflatten
225 0 : void setProc(SkXfermodeProc proc) {
226 0 : fProc = proc;
227 0 : }
228 :
229 : private:
230 : SkXfermodeProc fProc;
231 :
232 0 : static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
233 0 : return SkNEW_ARGS(SkProcXfermode, (buffer)); }
234 :
235 : typedef SkXfermode INHERITED;
236 : };
237 :
238 : #endif
|