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:
MaskedColor(GrColor color,GrColorComponentFlags flags)16     MaskedColor(GrColor color, GrColorComponentFlags flags)
17         : fColor(color)
18         , fFlags(flags) {}
19 
MaskedColor()20     MaskedColor() {}
21 
set(GrColor color,GrColorComponentFlags flags)22     void set(GrColor color, GrColorComponentFlags flags) {
23         fColor = color;
24         fFlags = flags;
25     }
26 
Invert(const MaskedColor & in)27     static MaskedColor Invert(const MaskedColor& in) {
28         return MaskedColor(GrInvertColor(in.fColor), in.fFlags);
29     }
30 
ExtractAlpha(const MaskedColor & in)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 
ExtractInverseAlpha(const MaskedColor & in)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 
Mul(const MaskedColor & a,const MaskedColor & b)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 
SatAdd(const MaskedColor & a,const MaskedColor & b)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 
color() const55     GrColor color() const { return fColor; }
56 
validFlags() const57     GrColorComponentFlags validFlags () const { return fFlags; }
58 
59 private:
componentsWithValue(unsigned value) const60     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 
get_term(GrBlendCoeff coeff,const MaskedColor & src,const MaskedColor & dst,const MaskedColor & value)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             SkFAIL("Illegal coefficient");
106             return MaskedColor();
107     }
108 }
109 
GrGetCoeffBlendKnownComponents(GrBlendCoeff srcCoeff,GrBlendCoeff dstCoeff,GrColor srcColor,GrColorComponentFlags srcColorFlags,GrColor dstColor,GrColorComponentFlags dstColorFlags,GrColor * outColor,GrColorComponentFlags * outFlags)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