1 /* 2 * Copyright 2015 Google Inc. 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 #include "GrBlend.h" 9 10 /** 11 * MaskedColor is used to evaluate the color and valid color component flags through the 12 * blending equation. Could possibly extend this to be used more broadly. 13 */ 14 class MaskedColor { 15 public: 16 MaskedColor(GrColor color, GrColorComponentFlags flags) 17 : fColor(color) 18 , fFlags(flags) {} 19 20 MaskedColor() {} 21 22 void set(GrColor color, GrColorComponentFlags flags) { 23 fColor = color; 24 fFlags = flags; 25 } 26 27 static MaskedColor Invert(const MaskedColor& in) { 28 return MaskedColor(GrInvertColor(in.fColor), in.fFlags); 29 } 30 31 static MaskedColor ExtractAlpha(const MaskedColor& in) { 32 GrColorComponentFlags flags = (in.fFlags & kA_GrColorComponentFlag) ? 33 kRGBA_GrColorComponentFlags : kNone_GrColorComponentFlags; 34 return MaskedColor(GrColorPackA4(GrColorUnpackA(in.fColor)), flags); 35 } 36 37 static MaskedColor ExtractInverseAlpha(const MaskedColor& in) { 38 GrColorComponentFlags flags = (in.fFlags & kA_GrColorComponentFlag) ? 39 kRGBA_GrColorComponentFlags : kNone_GrColorComponentFlags; 40 return MaskedColor(GrColorPackA4(0xFF - GrColorUnpackA(in.fColor)), flags); 41 } 42 43 static MaskedColor Mul(const MaskedColor& a, const MaskedColor& b) { 44 GrColorComponentFlags outFlags = (a.fFlags & b.fFlags) | a.componentsWithValue(0) | 45 b.componentsWithValue(0); 46 return MaskedColor(GrColorMul(a.fColor, b.fColor), outFlags); 47 } 48 49 static MaskedColor SatAdd(const MaskedColor& a, const MaskedColor& b) { 50 GrColorComponentFlags outFlags = (a.fFlags & b.fFlags) | a.componentsWithValue(0xFF) | 51 b.componentsWithValue(0xFF); 52 return MaskedColor(GrColorSatAdd(a.fColor, b.fColor), outFlags); 53 } 54 55 GrColor color() const { return fColor; } 56 57 GrColorComponentFlags validFlags () const { return fFlags; } 58 59 private: 60 GrColorComponentFlags componentsWithValue(unsigned value) const { 61 GrColorComponentFlags flags = kNone_GrColorComponentFlags; 62 if ((kR_GrColorComponentFlag & fFlags) && value == GrColorUnpackR(fColor)) { 63 flags |= kR_GrColorComponentFlag; 64 } 65 if ((kG_GrColorComponentFlag & fFlags) && value == GrColorUnpackG(fColor)) { 66 flags |= kG_GrColorComponentFlag; 67 } 68 if ((kB_GrColorComponentFlag & fFlags) && value == GrColorUnpackB(fColor)) { 69 flags |= kB_GrColorComponentFlag; 70 } 71 if ((kA_GrColorComponentFlag & fFlags) && value == GrColorUnpackA(fColor)) { 72 flags |= kA_GrColorComponentFlag; 73 } 74 return flags; 75 } 76 77 GrColor fColor; 78 GrColorComponentFlags fFlags; 79 }; 80 81 static MaskedColor get_term(GrBlendCoeff coeff, const MaskedColor& src, const MaskedColor& dst, 82 const MaskedColor& value) { 83 switch (coeff) { 84 case kZero_GrBlendCoeff: 85 return MaskedColor(0, kRGBA_GrColorComponentFlags); 86 case kOne_GrBlendCoeff: 87 return value; 88 case kDC_GrBlendCoeff: 89 return MaskedColor::Mul(dst, value); 90 case kIDC_GrBlendCoeff: 91 return MaskedColor::Mul(MaskedColor::Invert(dst), value); 92 case kDA_GrBlendCoeff: 93 return MaskedColor::Mul(MaskedColor::ExtractAlpha(dst), value); 94 case kIDA_GrBlendCoeff: 95 return MaskedColor::Mul(MaskedColor::ExtractInverseAlpha(dst), value); 96 case kSC_GrBlendCoeff: 97 return MaskedColor::Mul(src, value); 98 case kISC_GrBlendCoeff: 99 return MaskedColor::Mul(MaskedColor::Invert(src), value); 100 case kSA_GrBlendCoeff: 101 return MaskedColor::Mul(MaskedColor::ExtractAlpha(src), value); 102 case kISA_GrBlendCoeff: 103 return MaskedColor::Mul(MaskedColor::ExtractInverseAlpha(src), value); 104 default: 105 SK_ABORT("Illegal coefficient"); 106 return MaskedColor(); 107 } 108 } 109 110 void GrGetCoeffBlendKnownComponents(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff, 111 GrColor srcColor, GrColorComponentFlags srcColorFlags, 112 GrColor dstColor, GrColorComponentFlags dstColorFlags, 113 GrColor* outColor, 114 GrColorComponentFlags* outFlags) { 115 MaskedColor src(srcColor, srcColorFlags); 116 MaskedColor dst(dstColor, dstColorFlags); 117 118 MaskedColor srcTerm = get_term(srcCoeff, src, dst, src); 119 MaskedColor dstTerm = get_term(dstCoeff, src, dst, dst); 120 121 MaskedColor output = MaskedColor::SatAdd(srcTerm, dstTerm); 122 *outColor = output.color(); 123 *outFlags = output.validFlags(); 124 } 125