• 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 "SkBlendModePriv.h"
9 #include "SkColorPriv.h"
10 #include "SkMathPriv.h"
11 #include "SkOnce.h"
12 #include "SkOpts.h"
13 #include "SkPM4f.h"
14 #include "SkRasterPipeline.h"
15 #include "SkReadBuffer.h"
16 #include "SkString.h"
17 #include "SkWriteBuffer.h"
18 #include "SkXfermodePriv.h"
19 
20 #if SK_SUPPORT_GPU
21 #include "GrFragmentProcessor.h"
22 #include "effects/GrCustomXfermode.h"
23 #include "effects/GrPorterDuffXferProcessor.h"
24 #include "effects/GrXfermodeFragmentProcessor.h"
25 #endif
26 
27 ///////////////////////////////////////////////////////////////////////////////////////////////////
28 
29 class SkProcCoeffXfermode : public SkXfermode {
30 public:
SkProcCoeffXfermode(SkBlendMode mode)31     SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {}
32 
xfer32(SkPMColor dst[],const SkPMColor src[],int count,const SkAlpha aa[]) const33     void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
34                 const SkAlpha aa[]) const override {
35         SkASSERT(dst && src && count >= 0);
36 
37         SkRasterPipeline_<256> p;
38 
39         if (kN32_SkColorType == kBGRA_8888_SkColorType) {
40             p.append(SkRasterPipeline::load_bgra_dst, &dst);
41             p.append(SkRasterPipeline::load_bgra    , &src);
42         } else {
43             p.append(SkRasterPipeline::load_8888_dst, &dst);
44             p.append(SkRasterPipeline::load_8888,     &src);
45         }
46 
47         SkBlendMode_AppendStagesNoClamp(fMode, &p);
48         if (aa) {
49             p.append(SkRasterPipeline::lerp_u8, &aa);
50         }
51         SkBlendMode_AppendClampIfNeeded(fMode, &p);
52 
53         if (kN32_SkColorType == kBGRA_8888_SkColorType) {
54             p.append(SkRasterPipeline::store_bgra, &dst);
55         } else {
56             p.append(SkRasterPipeline::store_8888, &dst);
57         }
58         p.run(0, 0, count);
59     }
60 
61 private:
62     const SkBlendMode fMode;
63 
64     typedef SkXfermode INHERITED;
65 };
66 
SkBlendMode_Name(SkBlendMode mode)67 const char* SkBlendMode_Name(SkBlendMode mode) {
68     SkASSERT((unsigned) mode <= (unsigned)SkBlendMode::kLastMode);
69     const char* gModeStrings[] = {
70         "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
71         "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
72         "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
73         "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
74         "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
75     };
76     return gModeStrings[(int)mode];
77     static_assert(SK_ARRAY_COUNT(gModeStrings) == (size_t)SkBlendMode::kLastMode + 1, "mode_count");
78 }
79 
Make(SkBlendMode mode)80 sk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) {
81     if ((unsigned)mode > (unsigned)SkBlendMode::kLastMode) {
82         // report error
83         return nullptr;
84     }
85 
86     // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
87     // so we can just return nullptr from the factory.
88     if (SkBlendMode::kSrcOver == mode) {
89         return nullptr;
90     }
91 
92     const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1;
93 
94     static SkOnce        once[COUNT_BLENDMODES];
95     static SkXfermode* cached[COUNT_BLENDMODES];
96 
97     once[(int)mode]([mode] {
98         if (auto xfermode = SkOpts::create_xfermode(mode)) {
99             cached[(int)mode] = xfermode;
100         } else {
101             cached[(int)mode] = new SkProcCoeffXfermode(mode);
102         }
103     });
104     return sk_ref_sp(cached[(int)mode]);
105 }
106 
107 ///////////////////////////////////////////////////////////////////////////////////////////////////
108 
IsOpaque(SkBlendMode mode,SrcColorOpacity opacityType)109 bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {
110     SkBlendModeCoeff src, dst;
111     if (!SkBlendMode_AsCoeff(mode, &src, &dst)) {
112         return false;
113     }
114 
115     switch (src) {
116         case SkBlendModeCoeff::kDA:
117         case SkBlendModeCoeff::kDC:
118         case SkBlendModeCoeff::kIDA:
119         case SkBlendModeCoeff::kIDC:
120             return false;
121         default:
122             break;
123     }
124 
125     switch (dst) {
126         case SkBlendModeCoeff::kZero:
127             return true;
128         case SkBlendModeCoeff::kISA:
129             return kOpaque_SrcColorOpacity == opacityType;
130         case SkBlendModeCoeff::kSA:
131             return kTransparentBlack_SrcColorOpacity == opacityType ||
132             kTransparentAlpha_SrcColorOpacity == opacityType;
133         case SkBlendModeCoeff::kSC:
134             return kTransparentBlack_SrcColorOpacity == opacityType;
135         default:
136             return false;
137     }
138     return false;
139 }
140 
141 #if SK_SUPPORT_GPU
SkBlendMode_AsXPFactory(SkBlendMode mode)142 const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) {
143     if (SkBlendMode_AsCoeff(mode, nullptr, nullptr)) {
144         const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode);
145         SkASSERT(result);
146         return result;
147     }
148 
149     SkASSERT(GrCustomXfermode::IsSupportedMode(mode));
150     return GrCustomXfermode::Get(mode);
151 }
152 #endif
153 
154