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 "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 kConstA_GrBlendCoeff, //<! constant color alpha 66 kIConstA_GrBlendCoeff, //<! one minus constant color alpha 67 kS2C_GrBlendCoeff, 68 kIS2C_GrBlendCoeff, 69 kS2A_GrBlendCoeff, 70 kIS2A_GrBlendCoeff, 71 72 kIllegal_GrBlendCoeff, 73 74 kLast_GrBlendCoeff = kIllegal_GrBlendCoeff, 75 }; 76 77 static const int kGrBlendCoeffCnt = kLast_GrBlendCoeff + 1; 78 79 static constexpr bool GrBlendCoeffRefsSrc(const GrBlendCoeff coeff) { 80 return kSC_GrBlendCoeff == coeff || kISC_GrBlendCoeff == coeff || kSA_GrBlendCoeff == coeff || 81 kISA_GrBlendCoeff == coeff; 82 } 83 84 static constexpr bool GrBlendCoeffRefsDst(const GrBlendCoeff coeff) { 85 return kDC_GrBlendCoeff == coeff || kIDC_GrBlendCoeff == coeff || kDA_GrBlendCoeff == coeff || 86 kIDA_GrBlendCoeff == coeff; 87 } 88 89 static constexpr bool GrBlendCoeffRefsSrc2(const GrBlendCoeff coeff) { 90 return kS2C_GrBlendCoeff == coeff || kIS2C_GrBlendCoeff == coeff || 91 kS2A_GrBlendCoeff == coeff || kIS2A_GrBlendCoeff == coeff; 92 } 93 94 static constexpr bool GrBlendCoeffsUseSrcColor(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 95 return kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff); 96 } 97 98 static constexpr bool GrBlendCoeffsUseDstColor(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 99 return GrBlendCoeffRefsDst(srcCoeff) || kZero_GrBlendCoeff != dstCoeff; 100 } 101 102 static constexpr bool GrBlendEquationIsAdvanced(GrBlendEquation equation) { 103 return equation >= kFirstAdvancedGrBlendEquation 104 && equation != kIllegal_GrBlendEquation; 105 } 106 107 static constexpr bool GrBlendModifiesDst(GrBlendEquation equation, GrBlendCoeff srcCoeff, 108 GrBlendCoeff dstCoeff) { 109 return (kAdd_GrBlendEquation != equation && kReverseSubtract_GrBlendEquation != equation) || 110 kZero_GrBlendCoeff != srcCoeff || kOne_GrBlendCoeff != dstCoeff; 111 } 112 113 /** 114 * Advanced blend equations can always tweak alpha for coverage. (See GrCustomXfermode.cpp) 115 * 116 * For "add" and "reverse subtract" the blend equation with f=coverage is: 117 * 118 * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D 119 * = f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) 120 * 121 * (Let srcCoeff be negative for reverse subtract.) We can tweak alpha for coverage when the 122 * following relationship holds: 123 * 124 * (f*S) * srcCoeff' + D * dstCoeff' == f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) 125 * 126 * (Where srcCoeff' and dstCoeff' have any reference to S pre-multiplied by f.) 127 * 128 * It's easy to see this works for the src term as long as srcCoeff' == srcCoeff (meaning srcCoeff 129 * does not reference S). For the dst term, this will work as long as the following is true: 130 *| 131 * dstCoeff' == f * dstCoeff + (1 - f) 132 * dstCoeff' == 1 - f * (1 - dstCoeff) 133 * 134 * By inspection we can see this will work as long as dstCoeff has a 1, and any other term in 135 * dstCoeff references S. 136 * 137 * Moreover, if the blend doesn't modify the dst at all then it is ok to arbitrarily modify the src 138 * color so folding in coverage is allowed. 139 */ 140 static constexpr bool GrBlendAllowsCoverageAsAlpha(GrBlendEquation equation, 141 GrBlendCoeff srcCoeff, 142 GrBlendCoeff dstCoeff) { 143 return GrBlendEquationIsAdvanced(equation) || 144 !GrBlendModifiesDst(equation, srcCoeff, dstCoeff) || 145 ((kAdd_GrBlendEquation == equation || kReverseSubtract_GrBlendEquation == equation) && 146 !GrBlendCoeffRefsSrc(srcCoeff) && 147 (kOne_GrBlendCoeff == dstCoeff || kISC_GrBlendCoeff == dstCoeff || 148 kISA_GrBlendCoeff == dstCoeff)); 149 } 150 151 #endif 152