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