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