• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 GrFragmentProcessor;
17 class GrTexture;
18 class GrXPFactory;
19 class SkString;
20 
21 struct SkPM4f;
22 typedef 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  */
35 class SK_API SkXfermode : public SkFlattenable {
36 public:
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(...)")
IsMode(const SkXfermode * xfer,Mode * mode)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);
GetLCD64Proc(uint32_t)249     static LCD64Proc GetLCD64Proc(uint32_t) { return nullptr; }
250 
251 protected:
SkXfermode()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 
266 private:
267     enum {
268         kModeCount = kLastMode + 1
269     };
270 
271     typedef SkFlattenable INHERITED;
272 };
273 
274 #endif
275