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