• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "SkPM4f.h"
18 
19 //////////////////////////////////////////////////////////////////////////////////////////////////
20 
21 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const22 void SkModeColorFilter::toString(SkString* str) const {
23     str->append("SkModeColorFilter: color: 0x");
24     str->appendHex(fColor);
25     str->append(" mode: ");
26     str->append(SkXfermode::ModeName(fMode));
27 }
28 #endif
29 
asColorMode(SkColor * color,SkXfermode::Mode * mode) const30 bool SkModeColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
31     if (color) {
32         *color = fColor;
33     }
34     if (mode) {
35         *mode = fMode;
36     }
37     return true;
38 }
39 
getFlags() const40 uint32_t SkModeColorFilter::getFlags() const {
41     uint32_t flags = 0;
42     switch (fMode) {
43         case SkXfermode::kDst_Mode:      //!< [Da, Dc]
44         case SkXfermode::kSrcATop_Mode:  //!< [Da, Sc * Da + (1 - Sa) * Dc]
45             flags |= kAlphaUnchanged_Flag;
46         default:
47             break;
48     }
49     return flags;
50 }
51 
filterSpan(const SkPMColor shader[],int count,SkPMColor result[]) const52 void SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const {
53     SkPMColor       color = fPMColor;
54     SkXfermodeProc  proc = fProc;
55 
56     for (int i = 0; i < count; i++) {
57         result[i] = proc(color, shader[i]);
58     }
59 }
60 
filterSpan4f(const SkPM4f shader[],int count,SkPM4f result[]) const61 void SkModeColorFilter::filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const {
62     SkPM4f            color = SkPM4f::FromPMColor(fPMColor);
63     SkXfermodeProc4f  proc = SkXfermode::GetProc4f(fMode);
64 
65     for (int i = 0; i < count; i++) {
66         result[i] = proc(color, shader[i]);
67     }
68 }
69 
flatten(SkWriteBuffer & buffer) const70 void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
71     buffer.writeColor(fColor);
72     buffer.writeUInt(fMode);
73 }
74 
updateCache()75 void SkModeColorFilter::updateCache() {
76     fPMColor = SkPreMultiplyColor(fColor);
77     fProc = SkXfermode::GetProc(fMode);
78 }
79 
CreateProc(SkReadBuffer & buffer)80 SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
81     SkColor color = buffer.readColor();
82     SkXfermode::Mode mode = (SkXfermode::Mode)buffer.readUInt();
83     return SkColorFilter::CreateModeFilter(color, mode);
84 }
85 
86 ///////////////////////////////////////////////////////////////////////////////
87 #if SK_SUPPORT_GPU
88 #include "GrBlend.h"
89 #include "GrInvariantOutput.h"
90 #include "effects/GrXfermodeFragmentProcessor.h"
91 #include "effects/GrConstColorProcessor.h"
92 #include "SkGr.h"
93 
asFragmentProcessor(GrContext *) const94 const GrFragmentProcessor* SkModeColorFilter::asFragmentProcessor(GrContext*) const {
95     if (SkXfermode::kDst_Mode == fMode) {
96         return nullptr;
97     }
98 
99     SkAutoTUnref<const GrFragmentProcessor> constFP(
100         GrConstColorProcessor::Create(SkColorToPremulGrColor(fColor),
101                                         GrConstColorProcessor::kIgnore_InputMode));
102     const GrFragmentProcessor* fp =
103         GrXfermodeFragmentProcessor::CreateFromSrcProcessor(constFP, fMode);
104     if (!fp) {
105         return nullptr;
106     }
107 #ifdef SK_DEBUG
108     // With a solid color input this should always be able to compute the blended color
109     // (at least for coeff modes)
110     if (fMode <= SkXfermode::kLastCoeffMode) {
111         static SkRandom gRand;
112         GrInvariantOutput io(GrPremulColor(gRand.nextU()), kRGBA_GrColorComponentFlags,
113                                 false);
114         fp->computeInvariantOutput(&io);
115         SkASSERT(io.validFlags() == kRGBA_GrColorComponentFlags);
116     }
117 #endif
118     return fp;
119 }
120 
121 #endif
122 
123 ///////////////////////////////////////////////////////////////////////////////
124 
125 class Src_SkModeColorFilter final : public SkModeColorFilter {
126 public:
Src_SkModeColorFilter(SkColor color)127     Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
128 
filterSpan(const SkPMColor shader[],int count,SkPMColor result[]) const129     void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
130         sk_memset32(result, this->getPMColor(), count);
131     }
132 
133 private:
134     typedef SkModeColorFilter INHERITED;
135 };
136 
137 class SrcOver_SkModeColorFilter final : public SkModeColorFilter {
138 public:
SrcOver_SkModeColorFilter(SkColor color)139     SrcOver_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrcOver_Mode) { }
140 
filterSpan(const SkPMColor shader[],int count,SkPMColor result[]) const141     void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
142         SkBlitRow::Color32(result, shader, count, this->getPMColor());
143     }
144 
145 private:
146     typedef SkModeColorFilter INHERITED;
147 };
148 
149 ///////////////////////////////////////////////////////////////////////////////
150 
CreateModeFilter(SkColor color,SkXfermode::Mode mode)151 SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color, SkXfermode::Mode mode) {
152     if (!SkIsValidMode(mode)) {
153         return nullptr;
154     }
155 
156     unsigned alpha = SkColorGetA(color);
157 
158     // first collaps some modes if possible
159 
160     if (SkXfermode::kClear_Mode == mode) {
161         color = 0;
162         mode = SkXfermode::kSrc_Mode;
163     } else if (SkXfermode::kSrcOver_Mode == mode) {
164         if (0 == alpha) {
165             mode = SkXfermode::kDst_Mode;
166         } else if (255 == alpha) {
167             mode = SkXfermode::kSrc_Mode;
168         }
169         // else just stay srcover
170     }
171 
172     // weed out combinations that are noops, and just return null
173     if (SkXfermode::kDst_Mode == mode ||
174         (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
175                         SkXfermode::kDstOver_Mode == mode ||
176                         SkXfermode::kDstOut_Mode == mode ||
177                         SkXfermode::kSrcATop_Mode == mode ||
178                         SkXfermode::kXor_Mode == mode ||
179                         SkXfermode::kDarken_Mode == mode)) ||
180             (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
181         return nullptr;
182     }
183 
184     switch (mode) {
185         case SkXfermode::kSrc_Mode:
186             return new Src_SkModeColorFilter(color);
187         case SkXfermode::kSrcOver_Mode:
188             return new SrcOver_SkModeColorFilter(color);
189         default:
190             return SkModeColorFilter::Create(color, mode);
191     }
192 }
193