• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 class SK_API SkXfermode : public SkFlattenable {
25 public:
SkXfermode()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[]);
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(...)
IsMode(SkXfermode * xfer,Mode * mode)171     static bool IsMode(SkXfermode* xfer, Mode* mode) {
172         return AsMode(xfer, mode);
173     }
174 
SK_DECLARE_FLATTENABLE_REGISTRAR()175     SK_DECLARE_FLATTENABLE_REGISTRAR()
176 protected:
177     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 class SkProcXfermode : public SkXfermode {
204 public:
SkProcXfermode(SkXfermodeProc proc)205     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
getFactory()218     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
setProc(SkXfermodeProc proc)225     void setProc(SkXfermodeProc proc) {
226         fProc = proc;
227     }
228 
229 private:
230     SkXfermodeProc  fProc;
231 
CreateProc(SkFlattenableReadBuffer & buffer)232     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
233         return SkNEW_ARGS(SkProcXfermode, (buffer)); }
234 
235     typedef SkXfermode INHERITED;
236 };
237 
238 #endif
239