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*/
24class SK_API SkXfermode : public SkFlattenable {
25public:
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(...)
171    static bool IsMode(SkXfermode* xfer, Mode* mode) {
172        return AsMode(xfer, mode);
173    }
174
175    SK_DECLARE_FLATTENABLE_REGISTRAR()
176protected:
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
189private:
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*/
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,
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    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
219    virtual void    flatten(SkFlattenableWriteBuffer&) SK_OVERRIDE;
220
221protected:
222    SkProcXfermode(SkFlattenableReadBuffer&);
223
224    // allow subclasses to update this after we unflatten
225    void setProc(SkXfermodeProc proc) {
226        fProc = proc;
227    }
228
229private:
230    SkXfermodeProc  fProc;
231
232    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
233        return SkNEW_ARGS(SkProcXfermode, (buffer)); }
234
235    typedef SkXfermode INHERITED;
236};
237
238#endif
239