SkXfermode.h revision 30da745bbf67a0ee0f305ca7bbdb685cc8a9e686
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    SK_DECLARE_INST_COUNT(SkXfermode)
27
28    SkXfermode() {}
29
30    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
31                        const SkAlpha aa[]) const;
32    virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
33                        const SkAlpha aa[]) const;
34    virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count,
35                          const SkAlpha aa[]) const;
36    virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
37                        const SkAlpha aa[]) const;
38
39    /** Enum of possible coefficients to describe some xfermodes
40     */
41    enum Coeff {
42        kZero_Coeff,    /** 0 */
43        kOne_Coeff,     /** 1 */
44        kSC_Coeff,      /** src color */
45        kISC_Coeff,     /** inverse src color (i.e. 1 - sc) */
46        kDC_Coeff,      /** dst color */
47        kIDC_Coeff,     /** inverse dst color (i.e. 1 - dc) */
48        kSA_Coeff,      /** src alpha */
49        kISA_Coeff,     /** inverse src alpha (i.e. 1 - sa) */
50        kDA_Coeff,      /** dst alpha */
51        kIDA_Coeff,     /** inverse dst alpha (i.e. 1 - da) */
52
53        kCoeffCount
54    };
55
56    /** If the xfermode can be expressed as an equation using the coefficients
57        in Coeff, then asCoeff() returns true, and sets (if not null) src and
58        dst accordingly.
59
60            result = src_coeff * src_color + dst_coeff * dst_color;
61
62        As examples, here are some of the porterduff coefficients
63
64        MODE        SRC_COEFF       DST_COEFF
65        clear       zero            zero
66        src         one             zero
67        dst         zero            one
68        srcover     one             isa
69        dstover     ida             one
70     */
71    virtual bool asCoeff(Coeff* src, Coeff* dst) const;
72
73    /**
74     *  The same as calling xfermode->asCoeff(..), except that this also checks
75     *  if the xfermode is NULL, and if so, treats its as kSrcOver_Mode.
76     */
77    static bool AsCoeff(const SkXfermode*, Coeff* src, Coeff* dst);
78
79    /** List of predefined xfermodes.
80        The algebra for the modes uses the following symbols:
81        Sa, Sc  - source alpha and color
82        Da, Dc - destination alpha and color (before compositing)
83        [a, c] - Resulting (alpha, color) values
84        For these equations, the colors are in premultiplied state.
85        If no xfermode is specified, kSrcOver is assumed.
86     */
87    enum Mode {
88        kClear_Mode,    //!< [0, 0]
89        kSrc_Mode,      //!< [Sa, Sc]
90        kDst_Mode,      //!< [Da, Dc]
91        kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc]
92        kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc]
93        kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
94        kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
95        kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
96        kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
97        kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
98        kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
99        kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
100
101        // all remaining modes are defined in the SVG Compositing standard
102        // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/
103        kPlus_Mode,
104        kMultiply_Mode,
105
106        // all above modes can be expressed as pair of src/dst Coeffs
107        kCoeffModesCnt,
108
109        kScreen_Mode = kCoeffModesCnt,
110        kOverlay_Mode,
111        kDarken_Mode,
112        kLighten_Mode,
113        kColorDodge_Mode,
114        kColorBurn_Mode,
115        kHardLight_Mode,
116        kSoftLight_Mode,
117        kDifference_Mode,
118        kExclusion_Mode,
119
120        kLastMode = kExclusion_Mode
121    };
122
123    /**
124     *  If the xfermode is one of the modes in the Mode enum, then asMode()
125     *  returns true and sets (if not null) mode accordingly. Otherwise it
126     *  returns false and ignores the mode parameter.
127     */
128    virtual bool asMode(Mode* mode) const;
129
130    /**
131     *  The same as calling xfermode->asMode(mode), except that this also checks
132     *  if the xfermode is NULL, and if so, treats its as kSrcOver_Mode.
133     */
134    static bool AsMode(const SkXfermode*, Mode* mode);
135
136    /**
137     *  Returns true if the xfermode claims to be the specified Mode. This works
138     *  correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
139     *  you can say this without checking for a null...
140     *
141     *  If (SkXfermode::IsMode(paint.getXfermode(),
142     *                         SkXfermode::kDstOver_Mode)) {
143     *      ...
144     *  }
145     */
146    static bool IsMode(const SkXfermode* xfer, Mode mode);
147
148    /** Return an SkXfermode object for the specified mode.
149     */
150    static SkXfermode* Create(Mode mode);
151
152    /** Return a function pointer to a routine that applies the specified
153        porter-duff transfer mode.
154     */
155    static SkXfermodeProc GetProc(Mode mode);
156
157    /** Return a function pointer to a routine that applies the specified
158        porter-duff transfer mode and srcColor to a 16bit device color. Note,
159        if the mode+srcColor might return a non-opaque color, then there is not
160        16bit proc, and this will return NULL.
161      */
162    static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor);
163
164    /**
165     *  If the specified mode can be represented by a pair of Coeff, then return
166     *  true and set (if not NULL) the corresponding coeffs. If the mode is
167     *  not representable as a pair of Coeffs, return false and ignore the
168     *  src and dst parameters.
169     */
170    static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
171
172    // DEPRECATED: call AsMode(...)
173    static bool IsMode(const SkXfermode* xfer, Mode* mode) {
174        return AsMode(xfer, mode);
175    }
176
177    SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
178protected:
179    SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}
180
181    /** The default implementation of xfer32/xfer16/xferA8 in turn call this
182        method, 1 color at a time (upscaled to a SkPMColor). The default
183        implmentation of this method just returns dst. If performance is
184        important, your subclass should override xfer32/xfer16/xferA8 directly.
185
186        This method will not be called directly by the client, so it need not
187        be implemented if your subclass has overridden xfer32/xfer16/xferA8
188    */
189    virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
190
191private:
192    enum {
193        kModeCount = kLastMode + 1
194    };
195    typedef SkFlattenable INHERITED;
196};
197
198///////////////////////////////////////////////////////////////////////////////
199
200/** \class SkProcXfermode
201
202    SkProcXfermode is a xfermode that applies the specified proc to its colors.
203    This class is not exported to java.
204*/
205class SkProcXfermode : public SkXfermode {
206public:
207    SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {}
208
209    // overrides from SkXfermode
210    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
211                        const SkAlpha aa[]) const SK_OVERRIDE;
212    virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
213                        const SkAlpha aa[]) const SK_OVERRIDE;
214    virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count,
215                          const SkAlpha aa[]) const SK_OVERRIDE;
216    virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
217                        const SkAlpha aa[]) const SK_OVERRIDE;
218
219    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcXfermode)
220
221protected:
222    SkProcXfermode(SkFlattenableReadBuffer&);
223    virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
224
225    // allow subclasses to update this after we unflatten
226    void setProc(SkXfermodeProc proc) {
227        fProc = proc;
228    }
229
230private:
231    SkXfermodeProc  fProc;
232
233    typedef SkXfermode INHERITED;
234};
235
236#endif
237