• 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 "SkArenaAlloc.h"
9 #include "SkBlendModePriv.h"
10 #include "SkBlitRow.h"
11 #include "SkColorFilter.h"
12 #include "SkColorPriv.h"
13 #include "SkColorSpaceXformer.h"
14 #include "SkModeColorFilter.h"
15 #include "SkPM4f.h"
16 #include "SkPM4fPriv.h"
17 #include "SkRandom.h"
18 #include "SkRasterPipeline.h"
19 #include "SkReadBuffer.h"
20 #include "SkString.h"
21 #include "SkUtils.h"
22 #include "SkValidationUtils.h"
23 #include "SkWriteBuffer.h"
24 
25 //////////////////////////////////////////////////////////////////////////////////////////////////
26 
SkModeColorFilter(SkColor color,SkBlendMode mode)27 SkModeColorFilter::SkModeColorFilter(SkColor color, SkBlendMode mode) {
28     fColor = color;
29     fMode = mode;
30     // cache
31     fPMColor = SkPreMultiplyColor(fColor);
32 }
33 
34 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const35 void SkModeColorFilter::toString(SkString* str) const {
36     str->append("SkModeColorFilter: color: 0x");
37     str->appendHex(fColor);
38     str->append(" mode: ");
39     str->append(SkBlendMode_Name(fMode));
40 }
41 #endif
42 
asColorMode(SkColor * color,SkBlendMode * mode) const43 bool SkModeColorFilter::asColorMode(SkColor* color, SkBlendMode* mode) const {
44     if (color) {
45         *color = fColor;
46     }
47     if (mode) {
48         *mode = fMode;
49     }
50     return true;
51 }
52 
getFlags() const53 uint32_t SkModeColorFilter::getFlags() const {
54     uint32_t flags = 0;
55     switch (fMode) {
56         case SkBlendMode::kDst:      //!< [Da, Dc]
57         case SkBlendMode::kSrcATop:  //!< [Da, Sc * Da + (1 - Sa) * Dc]
58             flags |= kAlphaUnchanged_Flag;
59         default:
60             break;
61     }
62     return flags;
63 }
64 
flatten(SkWriteBuffer & buffer) const65 void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
66     buffer.writeColor(fColor);
67     buffer.writeUInt((int)fMode);
68 }
69 
CreateProc(SkReadBuffer & buffer)70 sk_sp<SkFlattenable> SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
71     SkColor color = buffer.readColor();
72     SkBlendMode mode = (SkBlendMode)buffer.readUInt();
73     return SkColorFilter::MakeModeFilter(color, mode);
74 }
75 
onAppendStages(SkRasterPipeline * p,SkColorSpace * dst,SkArenaAlloc * scratch,bool shaderIsOpaque) const76 void SkModeColorFilter::onAppendStages(SkRasterPipeline* p,
77                                        SkColorSpace* dst,
78                                        SkArenaAlloc* scratch,
79                                        bool shaderIsOpaque) const {
80     p->append(SkRasterPipeline::move_src_dst);
81     p->append_uniform_color(scratch, SkPM4f_from_SkColor(fColor, dst));
82     SkBlendMode_AppendStages(fMode, p);
83 }
84 
onMakeColorSpace(SkColorSpaceXformer * xformer) const85 sk_sp<SkColorFilter> SkModeColorFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
86     SkColor color = xformer->apply(fColor);
87     if (color != fColor) {
88         return SkColorFilter::MakeModeFilter(color, fMode);
89     }
90     return this->INHERITED::onMakeColorSpace(xformer);
91 }
92 
93 ///////////////////////////////////////////////////////////////////////////////
94 #if SK_SUPPORT_GPU
95 #include "GrBlend.h"
96 #include "effects/GrXfermodeFragmentProcessor.h"
97 #include "effects/GrConstColorProcessor.h"
98 #include "SkGr.h"
99 
asFragmentProcessor(GrContext *,SkColorSpace * dstColorSpace) const100 sk_sp<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor(
101                                                     GrContext*, SkColorSpace* dstColorSpace) const {
102     if (SkBlendMode::kDst == fMode) {
103         return nullptr;
104     }
105 
106     sk_sp<GrFragmentProcessor> constFP(
107         GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpace),
108                                     GrConstColorProcessor::kIgnore_InputMode));
109     sk_sp<GrFragmentProcessor> fp(
110         GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode));
111     if (!fp) {
112         return nullptr;
113     }
114 #ifdef SK_DEBUG
115     // With a solid color input this should always be able to compute the blended color
116     // (at least for coeff modes)
117     if ((unsigned)fMode <= (unsigned)SkBlendMode::kLastCoeffMode) {
118         SkASSERT(fp->hasConstantOutputForConstantInput());
119     }
120 #endif
121     return fp;
122 }
123 
124 #endif
125 
126 ///////////////////////////////////////////////////////////////////////////////
127 
MakeModeFilter(SkColor color,SkBlendMode mode)128 sk_sp<SkColorFilter> SkColorFilter::MakeModeFilter(SkColor color, SkBlendMode mode) {
129     if (!SkIsValidMode(mode)) {
130         return nullptr;
131     }
132 
133     unsigned alpha = SkColorGetA(color);
134 
135     // first collaps some modes if possible
136 
137     if (SkBlendMode::kClear == mode) {
138         color = 0;
139         mode = SkBlendMode::kSrc;
140     } else if (SkBlendMode::kSrcOver == mode) {
141         if (0 == alpha) {
142             mode = SkBlendMode::kDst;
143         } else if (255 == alpha) {
144             mode = SkBlendMode::kSrc;
145         }
146         // else just stay srcover
147     }
148 
149     // weed out combinations that are noops, and just return null
150     if (SkBlendMode::kDst == mode ||
151         (0 == alpha && (SkBlendMode::kSrcOver == mode ||
152                         SkBlendMode::kDstOver == mode ||
153                         SkBlendMode::kDstOut == mode ||
154                         SkBlendMode::kSrcATop == mode ||
155                         SkBlendMode::kXor == mode ||
156                         SkBlendMode::kDarken == mode)) ||
157             (0xFF == alpha && SkBlendMode::kDstIn == mode)) {
158         return nullptr;
159     }
160 
161     return SkModeColorFilter::Make(color, mode);
162 }
163