1 | |
2 | /* |
3 | * Copyright 2013 Google Inc. |
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 | #ifndef GrBlend_DEFINED |
10 | #define GrBlend_DEFINED |
11 | |
12 | #include "include/core/SkTypes.h" |
13 | |
14 | /** |
15 | * Equations for alpha-blending. |
16 | */ |
17 | enum GrBlendEquation { |
18 | // Basic blend equations. |
19 | kAdd_GrBlendEquation, //<! Cs*S + Cd*D |
20 | kSubtract_GrBlendEquation, //<! Cs*S - Cd*D |
21 | kReverseSubtract_GrBlendEquation, //<! Cd*D - Cs*S |
22 | |
23 | // Advanced blend equations. These are described in the SVG and PDF specs. |
24 | kScreen_GrBlendEquation, |
25 | kOverlay_GrBlendEquation, |
26 | kDarken_GrBlendEquation, |
27 | kLighten_GrBlendEquation, |
28 | kColorDodge_GrBlendEquation, |
29 | kColorBurn_GrBlendEquation, |
30 | kHardLight_GrBlendEquation, |
31 | kSoftLight_GrBlendEquation, |
32 | kDifference_GrBlendEquation, |
33 | kExclusion_GrBlendEquation, |
34 | kMultiply_GrBlendEquation, |
35 | kHSLHue_GrBlendEquation, |
36 | kHSLSaturation_GrBlendEquation, |
37 | kHSLColor_GrBlendEquation, |
38 | kHSLLuminosity_GrBlendEquation, |
39 | |
40 | kIllegal_GrBlendEquation, |
41 | |
42 | kFirstAdvancedGrBlendEquation = kScreen_GrBlendEquation, |
43 | kLast_GrBlendEquation = kIllegal_GrBlendEquation, |
44 | }; |
45 | |
46 | static const int kGrBlendEquationCnt = kLast_GrBlendEquation + 1; |
47 | |
48 | |
49 | /** |
50 | * Coefficients for alpha-blending. |
51 | */ |
52 | enum GrBlendCoeff { |
53 | kZero_GrBlendCoeff, //<! 0 |
54 | kOne_GrBlendCoeff, //<! 1 |
55 | kSC_GrBlendCoeff, //<! src color |
56 | kISC_GrBlendCoeff, //<! one minus src color |
57 | kDC_GrBlendCoeff, //<! dst color |
58 | kIDC_GrBlendCoeff, //<! one minus dst color |
59 | kSA_GrBlendCoeff, //<! src alpha |
60 | kISA_GrBlendCoeff, //<! one minus src alpha |
61 | kDA_GrBlendCoeff, //<! dst alpha |
62 | kIDA_GrBlendCoeff, //<! one minus dst alpha |
63 | kConstC_GrBlendCoeff, //<! constant color |
64 | kIConstC_GrBlendCoeff, //<! one minus constant color |
65 | kS2C_GrBlendCoeff, |
66 | kIS2C_GrBlendCoeff, |
67 | kS2A_GrBlendCoeff, |
68 | kIS2A_GrBlendCoeff, |
69 | |
70 | kIllegal_GrBlendCoeff, |
71 | |
72 | kLast_GrBlendCoeff = kIllegal_GrBlendCoeff, |
73 | }; |
74 | |
75 | static const int kGrBlendCoeffCnt = kLast_GrBlendCoeff + 1; |
76 | |
77 | static constexpr bool GrBlendCoeffRefsSrc(const GrBlendCoeff coeff) { |
78 | return kSC_GrBlendCoeff == coeff || kISC_GrBlendCoeff == coeff || kSA_GrBlendCoeff == coeff || |
79 | kISA_GrBlendCoeff == coeff; |
80 | } |
81 | |
82 | static constexpr bool GrBlendCoeffRefsDst(const GrBlendCoeff coeff) { |
83 | return kDC_GrBlendCoeff == coeff || kIDC_GrBlendCoeff == coeff || kDA_GrBlendCoeff == coeff || |
84 | kIDA_GrBlendCoeff == coeff; |
85 | } |
86 | |
87 | static constexpr bool GrBlendCoeffRefsSrc2(const GrBlendCoeff coeff) { |
88 | return kS2C_GrBlendCoeff == coeff || kIS2C_GrBlendCoeff == coeff || |
89 | kS2A_GrBlendCoeff == coeff || kIS2A_GrBlendCoeff == coeff; |
90 | } |
91 | |
92 | static constexpr bool GrBlendCoeffsUseSrcColor(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { |
93 | return kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff); |
94 | } |
95 | |
96 | static constexpr bool GrBlendCoeffsUseDstColor(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { |
97 | return GrBlendCoeffRefsDst(srcCoeff) || kZero_GrBlendCoeff != dstCoeff; |
98 | } |
99 | |
100 | static constexpr bool GrBlendEquationIsAdvanced(GrBlendEquation equation) { |
101 | return equation >= kFirstAdvancedGrBlendEquation |
102 | && equation != kIllegal_GrBlendEquation; |
103 | } |
104 | |
105 | static constexpr bool GrBlendModifiesDst(GrBlendEquation equation, GrBlendCoeff srcCoeff, |
106 | GrBlendCoeff dstCoeff) { |
107 | return (kAdd_GrBlendEquation != equation && kReverseSubtract_GrBlendEquation != equation) || |
108 | kZero_GrBlendCoeff != srcCoeff || kOne_GrBlendCoeff != dstCoeff; |
109 | } |
110 | |
111 | static constexpr bool GrBlendCoeffRefsConstant(const GrBlendCoeff coeff) { |
112 | return coeff == kConstC_GrBlendCoeff || coeff == kIConstC_GrBlendCoeff; |
113 | } |
114 | |
115 | static constexpr bool GrBlendShouldDisable(GrBlendEquation equation, GrBlendCoeff srcCoeff, |
116 | GrBlendCoeff dstCoeff) { |
117 | return (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) && |
118 | kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff; |
119 | } |
120 | |
121 | /** |
122 | * Advanced blend equations can always tweak alpha for coverage. (See GrCustomXfermode.cpp) |
123 | * |
124 | * For "add" and "reverse subtract" the blend equation with f=coverage is: |
125 | * |
126 | * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D |
127 | * = f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) |
128 | * |
129 | * (Let srcCoeff be negative for reverse subtract.) We can tweak alpha for coverage when the |
130 | * following relationship holds: |
131 | * |
132 | * (f*S) * srcCoeff' + D * dstCoeff' == f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) |
133 | * |
134 | * (Where srcCoeff' and dstCoeff' have any reference to S pre-multiplied by f.) |
135 | * |
136 | * It's easy to see this works for the src term as long as srcCoeff' == srcCoeff (meaning srcCoeff |
137 | * does not reference S). For the dst term, this will work as long as the following is true: |
138 | *| |
139 | * dstCoeff' == f * dstCoeff + (1 - f) |
140 | * dstCoeff' == 1 - f * (1 - dstCoeff) |
141 | * |
142 | * By inspection we can see this will work as long as dstCoeff has a 1, and any other term in |
143 | * dstCoeff references S. |
144 | * |
145 | * Moreover, if the blend doesn't modify the dst at all then it is ok to arbitrarily modify the src |
146 | * color so folding in coverage is allowed. |
147 | */ |
148 | static constexpr bool GrBlendAllowsCoverageAsAlpha(GrBlendEquation equation, |
149 | GrBlendCoeff srcCoeff, |
150 | GrBlendCoeff dstCoeff) { |
151 | return GrBlendEquationIsAdvanced(equation) || |
152 | !GrBlendModifiesDst(equation, srcCoeff, dstCoeff) || |
153 | ((kAdd_GrBlendEquation == equation || kReverseSubtract_GrBlendEquation == equation) && |
154 | !GrBlendCoeffRefsSrc(srcCoeff) && |
155 | (kOne_GrBlendCoeff == dstCoeff || kISC_GrBlendCoeff == dstCoeff || |
156 | kISA_GrBlendCoeff == dstCoeff)); |
157 | } |
158 | |
159 | #endif |
160 | |