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 GrFragmentProcessor;
17class GrTexture;
18class GrXPFactory;
19class SkString;
20
21struct SkPM4f;
22typedef SkPM4f (*SkXfermodeProc4f)(const SkPM4f& src, const SkPM4f& dst);
23
24/** \class SkXfermode
25 *
26 *  SkXfermode is the base class for objects that are called to implement custom
27 *  "transfer-modes" in the drawing pipeline. The static function Create(Modes)
28 *  can be called to return an instance of any of the predefined subclasses as
29 *  specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
30 *  then objects drawn with that paint have the xfermode applied.
31 *
32 *  All subclasses are required to be reentrant-safe : it must be legal to share
33 *  the same instance between several threads.
34 */
35class SK_API SkXfermode : public SkFlattenable {
36public:
37    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
38                        const SkAlpha aa[]) const;
39    virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
40                        const SkAlpha aa[]) const;
41    virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
42                        const SkAlpha aa[]) const;
43
44    /** Enum of possible coefficients to describe some xfermodes
45     */
46    enum Coeff {
47        kZero_Coeff,    /** 0 */
48        kOne_Coeff,     /** 1 */
49        kSC_Coeff,      /** src color */
50        kISC_Coeff,     /** inverse src color (i.e. 1 - sc) */
51        kDC_Coeff,      /** dst color */
52        kIDC_Coeff,     /** inverse dst color (i.e. 1 - dc) */
53        kSA_Coeff,      /** src alpha */
54        kISA_Coeff,     /** inverse src alpha (i.e. 1 - sa) */
55        kDA_Coeff,      /** dst alpha */
56        kIDA_Coeff,     /** inverse dst alpha (i.e. 1 - da) */
57
58        kCoeffCount
59    };
60
61    /** List of predefined xfermodes.
62        The algebra for the modes uses the following symbols:
63        Sa, Sc  - source alpha and color
64        Da, Dc - destination alpha and color (before compositing)
65        [a, c] - Resulting (alpha, color) values
66        For these equations, the colors are in premultiplied state.
67        If no xfermode is specified, kSrcOver is assumed.
68        The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those
69        that aren't Coeffs but have separable r,g,b computations, and finally
70        those that are not separable.
71     */
72    enum Mode {
73        kClear_Mode,    //!< [0, 0]
74        kSrc_Mode,      //!< [Sa, Sc]
75        kDst_Mode,      //!< [Da, Dc]
76        kSrcOver_Mode,  //!< [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)]
77        kDstOver_Mode,  //!< [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)]
78        kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
79        kDstIn_Mode,    //!< [Da * Sa, Dc * Sa]
80        kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
81        kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
82        kSrcATop_Mode,  //!< [Da, Sc * Da + Dc * (1 - Sa)]
83        kDstATop_Mode,  //!< [Sa, Dc * Sa + Sc * (1 - Da)]
84        kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]
85        kPlus_Mode,     //!< [Sa + Da, Sc + Dc]
86        kModulate_Mode, // multiplies all components (= alpha and color)
87
88        // Following blend modes are defined in the CSS Compositing standard:
89        // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
90        kScreen_Mode,
91        kLastCoeffMode = kScreen_Mode,
92
93        kOverlay_Mode,
94        kDarken_Mode,
95        kLighten_Mode,
96        kColorDodge_Mode,
97        kColorBurn_Mode,
98        kHardLight_Mode,
99        kSoftLight_Mode,
100        kDifference_Mode,
101        kExclusion_Mode,
102        kMultiply_Mode,
103        kLastSeparableMode = kMultiply_Mode,
104
105        kHue_Mode,
106        kSaturation_Mode,
107        kColor_Mode,
108        kLuminosity_Mode,
109        kLastMode = kLuminosity_Mode
110    };
111
112    /**
113     * Gets the name of the Mode as a string.
114     */
115    static const char* ModeName(Mode);
116
117    /**
118     *  If the xfermode is one of the modes in the Mode enum, then asMode()
119     *  returns true and sets (if not null) mode accordingly. Otherwise it
120     *  returns false and ignores the mode parameter.
121     */
122    virtual bool asMode(Mode* mode) const;
123
124    /**
125     *  The same as calling xfermode->asMode(mode), except that this also checks
126     *  if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
127     */
128    static bool AsMode(const SkXfermode*, Mode* mode);
129
130    /**
131     *  Returns true if the xfermode claims to be the specified Mode. This works
132     *  correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
133     *  you can say this without checking for a null...
134     *
135     *  If (SkXfermode::IsMode(paint.getXfermode(),
136     *                         SkXfermode::kDstOver_Mode)) {
137     *      ...
138     *  }
139     */
140    static bool IsMode(const SkXfermode* xfer, Mode mode);
141
142    /** Return an SkXfermode object for the specified mode.
143     */
144    static SkXfermode* Create(Mode mode);
145
146    /** Return a function pointer to a routine that applies the specified
147        porter-duff transfer mode.
148     */
149    static SkXfermodeProc GetProc(Mode mode);
150    static SkXfermodeProc4f GetProc4f(Mode);
151
152    virtual SkXfermodeProc4f getProc4f() const;
153
154    /**
155     *  If the specified mode can be represented by a pair of Coeff, then return
156     *  true and set (if not NULL) the corresponding coeffs. If the mode is
157     *  not representable as a pair of Coeffs, return false and ignore the
158     *  src and dst parameters.
159     */
160    static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
161
162    SK_ATTR_DEPRECATED("use AsMode(...)")
163    static bool IsMode(const SkXfermode* xfer, Mode* mode) {
164        return AsMode(xfer, mode);
165    }
166
167    /**
168     * Returns whether or not the xfer mode can support treating coverage as alpha
169     */
170    virtual bool supportsCoverageAsAlpha() const;
171
172    /**
173     *  The same as calling xfermode->supportsCoverageAsAlpha(), except that this also checks if
174     *  the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
175     */
176    static bool SupportsCoverageAsAlpha(const SkXfermode* xfer);
177
178    enum SrcColorOpacity {
179        // The src color is known to be opaque (alpha == 255)
180        kOpaque_SrcColorOpacity = 0,
181        // The src color is known to be fully transparent (color == 0)
182        kTransparentBlack_SrcColorOpacity = 1,
183        // The src alpha is known to be fully transparent (alpha == 0)
184        kTransparentAlpha_SrcColorOpacity = 2,
185        // The src color opacity is unknown
186        kUnknown_SrcColorOpacity = 3
187    };
188
189    /**
190     * Returns whether or not the result of the draw with the xfer mode will be opaque or not. The
191     * input to this call is an enum describing known information about the opacity of the src color
192     * that will be given to the xfer mode.
193     */
194    virtual bool isOpaque(SrcColorOpacity opacityType) const;
195
196    /**
197     *  The same as calling xfermode->isOpaque(...), except that this also checks if
198     *  the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
199     */
200    static bool IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType);
201
202#if SK_SUPPORT_GPU
203    /** Used by the SkXfermodeImageFilter to blend two colors via a GrFragmentProcessor.
204        The input to the returned FP is the src color. The dst color is
205        provided by the dst param which becomes a child FP of the returned FP.
206        It is legal for the function to return a null output. This indicates that
207        the output of the blend is simply the src color.
208     */
209    virtual const GrFragmentProcessor* getFragmentProcessorForImageFilter(
210                                                            const GrFragmentProcessor* dst) const;
211
212    /** A subclass must implement this factory function to work with the GPU backend.
213        The xfermode will return a factory for which the caller will get a ref. It is up
214        to the caller to install it. XferProcessors cannot use a background texture.
215      */
216    virtual GrXPFactory* asXPFactory() const;
217#endif
218
219    SK_TO_STRING_PUREVIRT()
220    SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
221    SK_DEFINE_FLATTENABLE_TYPE(SkXfermode)
222
223    enum D32Flags {
224        kSrcIsOpaque_D32Flag  = 1 << 0,
225        kSrcIsSingle_D32Flag  = 1 << 1,
226        kDstIsSRGB_D32Flag    = 1 << 2,
227    };
228    typedef void (*D32Proc)(const SkXfermode*, uint32_t dst[], const SkPM4f src[],
229                            int count, const SkAlpha coverage[]);
230    static D32Proc GetD32Proc(SkXfermode*, uint32_t flags);
231
232    enum D64Flags {
233        kSrcIsOpaque_D64Flag  = 1 << 0,
234        kSrcIsSingle_D64Flag  = 1 << 1,
235        kDstIsFloat16_D64Flag = 1 << 2, // else U16 bit components
236    };
237    typedef void (*D64Proc)(const SkXfermode*, uint64_t dst[], const SkPM4f src[], int count,
238                            const SkAlpha coverage[]);
239    static D64Proc GetD64Proc(SkXfermode*, uint32_t flags);
240
241    enum LCDFlags {
242        kSrcIsOpaque_LCDFlag    = 1 << 0,   // else src(s) may have alpha < 1
243        kSrcIsSingle_LCDFlag    = 1 << 1,   // else src[count]
244        kDstIsLinearInt_LCDFlag = 1 << 2,   // else srgb/half-float
245    };
246    typedef void (*LCD32Proc)(uint32_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
247    typedef void (*LCD64Proc)(uint64_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
248    static LCD32Proc GetLCD32Proc(uint32_t flags);
249    static LCD64Proc GetLCD64Proc(uint32_t) { return nullptr; }
250
251protected:
252    SkXfermode() {}
253    /** The default implementation of xfer32/xfer16/xferA8 in turn call this
254        method, 1 color at a time (upscaled to a SkPMColor). The default
255        implementation of this method just returns dst. If performance is
256        important, your subclass should override xfer32/xfer16/xferA8 directly.
257
258        This method will not be called directly by the client, so it need not
259        be implemented if your subclass has overridden xfer32/xfer16/xferA8
260    */
261    virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
262
263    virtual D32Proc onGetD32Proc(uint32_t flags) const;
264    virtual D64Proc onGetD64Proc(uint32_t flags) const;
265
266private:
267    enum {
268        kModeCount = kLastMode + 1
269    };
270
271    typedef SkFlattenable INHERITED;
272};
273
274#endif
275