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