| 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 |  | 
|---|