Line data Source code
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 :
15 : class GrFragmentProcessor;
16 : class GrTexture;
17 : class GrXPFactory;
18 : class SkRasterPipeline;
19 : class SkString;
20 :
21 : struct SkArithmeticParams;
22 :
23 : struct SkPM4f;
24 : typedef 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 : */
37 0 : class SK_API SkXfermode : public SkFlattenable {
38 : public:
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 0 : static const char* ModeName(SkBlendMode mode) {
119 0 : 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 0 : 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 166 : static SkXfermode* Peek(SkBlendMode mode) {
164 332 : sk_sp<SkXfermode> xfer = Make(mode);
165 166 : if (!xfer) {
166 166 : SkASSERT(SkBlendMode::kSrcOver == mode);
167 166 : return nullptr;
168 : }
169 0 : SkASSERT(!xfer->unique());
170 0 : return xfer.get();
171 : }
172 :
173 0 : SkBlendMode blend() const {
174 : Mode mode;
175 0 : SkAssertResult(this->asMode(&mode));
176 0 : 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 0 : static bool ModeAsCoeff(SkBlendMode mode, Coeff* src, Coeff* dst) {
190 0 : 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 0 : 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 0 : static LCDF16Proc GetLCDF16Proc(uint32_t) { return nullptr; }
282 :
283 0 : virtual bool isArithmetic(SkArithmeticParams*) const { return false; }
284 :
285 : protected:
286 0 : 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 :
297 : private:
298 : enum {
299 : kModeCount = kLastMode + 1
300 : };
301 :
302 : typedef SkFlattenable INHERITED;
303 : };
304 :
305 : #endif
|