OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2006 The Android Open Source Project | |
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 "SkBlitRow.h" | |
9 #include "SkColorFilter.h" | |
10 #include "SkColorPriv.h" | |
11 #include "SkModeColorFilter.h" | |
12 #include "SkReadBuffer.h" | |
13 #include "SkWriteBuffer.h" | |
14 #include "SkUtils.h" | |
15 #include "SkString.h" | |
16 #include "SkValidationUtils.h" | |
17 | |
18 bool SkModeColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) cons
t { | |
19 if (color) { | |
20 *color = fColor; | |
21 } | |
22 if (mode) { | |
23 *mode = fMode; | |
24 } | |
25 return true; | |
26 } | |
27 | |
28 uint32_t SkModeColorFilter::getFlags() const { | |
29 switch (fMode) { | |
30 case SkXfermode::kDst_Mode: //!< [Da, Dc] | |
31 case SkXfermode::kSrcATop_Mode: //!< [Da, Sc * Da + (1 - Sa) * Dc] | |
32 return kAlphaUnchanged_Flag; | |
33 default: | |
34 break; | |
35 } | |
36 return 0; | |
37 } | |
38 | |
39 void SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColo
r result[]) const { | |
40 SkPMColor color = fPMColor; | |
41 SkXfermodeProc proc = fProc; | |
42 | |
43 for (int i = 0; i < count; i++) { | |
44 result[i] = proc(color, shader[i]); | |
45 } | |
46 } | |
47 | |
48 void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const { | |
49 buffer.writeColor(fColor); | |
50 buffer.writeUInt(fMode); | |
51 } | |
52 | |
53 void SkModeColorFilter::updateCache() { | |
54 fPMColor = SkPreMultiplyColor(fColor); | |
55 fProc = SkXfermode::GetProc(fMode); | |
56 } | |
57 | |
58 SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) { | |
59 SkColor color = buffer.readColor(); | |
60 SkXfermode::Mode mode = (SkXfermode::Mode)buffer.readUInt(); | |
61 return SkColorFilter::CreateModeFilter(color, mode); | |
62 } | |
63 | |
64 /////////////////////////////////////////////////////////////////////////////// | |
65 #if SK_SUPPORT_GPU | |
66 #include "GrBlend.h" | |
67 #include "GrInvariantOutput.h" | |
68 #include "effects/GrXfermodeFragmentProcessor.h" | |
69 #include "effects/GrConstColorProcessor.h" | |
70 #include "SkGr.h" | |
71 | |
72 const GrFragmentProcessor* SkModeColorFilter::asFragmentProcessor(GrContext*) co
nst { | |
73 if (SkXfermode::kDst_Mode == fMode) { | |
74 return nullptr; | |
75 } | |
76 | |
77 SkAutoTUnref<const GrFragmentProcessor> constFP( | |
78 GrConstColorProcessor::Create(SkColorToPremulGrColor(fColor), | |
79 GrConstColorProcessor::kIgnore_InputMode
)); | |
80 const GrFragmentProcessor* fp = | |
81 GrXfermodeFragmentProcessor::CreateFromSrcProcessor(constFP, fMode); | |
82 if (!fp) { | |
83 return nullptr; | |
84 } | |
85 #ifdef SK_DEBUG | |
86 // With a solid color input this should always be able to compute the blende
d color | |
87 // (at least for coeff modes) | |
88 if (fMode <= SkXfermode::kLastCoeffMode) { | |
89 static SkRandom gRand; | |
90 GrInvariantOutput io(GrPremulColor(gRand.nextU()), kRGBA_GrColorComponen
tFlags, | |
91 false); | |
92 fp->computeInvariantOutput(&io); | |
93 SkASSERT(io.validFlags() == kRGBA_GrColorComponentFlags); | |
94 } | |
95 #endif | |
96 return fp; | |
97 } | |
98 | |
99 #endif | |
100 | |
101 /////////////////////////////////////////////////////////////////////////////// | |
102 | |
103 class Src_SkModeColorFilter : public SkModeColorFilter { | |
104 public: | |
105 Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mod
e) {} | |
106 | |
107 void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) con
st override { | |
108 sk_memset32(result, this->getPMColor(), count); | |
109 } | |
110 | |
111 private: | |
112 typedef SkModeColorFilter INHERITED; | |
113 }; | |
114 | |
115 class SrcOver_SkModeColorFilter : public SkModeColorFilter { | |
116 public: | |
117 SrcOver_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc
Over_Mode) { } | |
118 | |
119 void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) con
st override { | |
120 SkBlitRow::Color32(result, shader, count, this->getPMColor()); | |
121 } | |
122 | |
123 private: | |
124 typedef SkModeColorFilter INHERITED; | |
125 }; | |
126 | |
127 /////////////////////////////////////////////////////////////////////////////// | |
128 | |
129 SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color, SkXfermode::Mode m
ode) { | |
130 if (!SkIsValidMode(mode)) { | |
131 return nullptr; | |
132 } | |
133 | |
134 unsigned alpha = SkColorGetA(color); | |
135 | |
136 // first collaps some modes if possible | |
137 | |
138 if (SkXfermode::kClear_Mode == mode) { | |
139 color = 0; | |
140 mode = SkXfermode::kSrc_Mode; | |
141 } else if (SkXfermode::kSrcOver_Mode == mode) { | |
142 if (0 == alpha) { | |
143 mode = SkXfermode::kDst_Mode; | |
144 } else if (255 == alpha) { | |
145 mode = SkXfermode::kSrc_Mode; | |
146 } | |
147 // else just stay srcover | |
148 } | |
149 | |
150 // weed out combinations that are noops, and just return null | |
151 if (SkXfermode::kDst_Mode == mode || | |
152 (0 == alpha && (SkXfermode::kSrcOver_Mode == mode || | |
153 SkXfermode::kDstOver_Mode == mode || | |
154 SkXfermode::kDstOut_Mode == mode || | |
155 SkXfermode::kSrcATop_Mode == mode || | |
156 SkXfermode::kXor_Mode == mode || | |
157 SkXfermode::kDarken_Mode == mode)) || | |
158 (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) { | |
159 return nullptr; | |
160 } | |
161 | |
162 switch (mode) { | |
163 case SkXfermode::kSrc_Mode: | |
164 return new Src_SkModeColorFilter(color); | |
165 case SkXfermode::kSrcOver_Mode: | |
166 return new SrcOver_SkModeColorFilter(color); | |
167 default: | |
168 return SkModeColorFilter::Create(color, mode); | |
169 } | |
170 } | |
OLD | NEW |