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