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