• 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 "include/core/SkString.h"
9 #include "include/private/SkColorData.h"
10 #include "include/private/SkOnce.h"
11 #include "src/core/SkBlendModePriv.h"
12 #include "src/core/SkMathPriv.h"
13 #include "src/core/SkOpts.h"
14 #include "src/core/SkRasterPipeline.h"
15 #include "src/core/SkReadBuffer.h"
16 #include "src/core/SkWriteBuffer.h"
17 #include "src/core/SkXfermodePriv.h"
18 
19 #if SK_SUPPORT_GPU
20 #include "src/gpu/GrFragmentProcessor.h"
21 #include "src/gpu/effects/GrCustomXfermode.h"
22 #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
23 #endif
24 
25 ///////////////////////////////////////////////////////////////////////////////////////////////////
26 
27 class SkProcCoeffXfermode : public SkXfermode {
28 public:
SkProcCoeffXfermode(SkBlendMode mode)29     SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {}
30 
xfer32(SkPMColor dst[],const SkPMColor src[],int count,const SkAlpha aa[]) const31     void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
32                 const SkAlpha aa[]) const override {
33         SkASSERT(dst && src && count >= 0);
34 
35         SkRasterPipeline_<256> p;
36 
37         SkRasterPipeline_MemoryCtx dst_ctx = { (void*)dst, 0 },
38                                    src_ctx = { (void*)src, 0 },
39                                     aa_ctx = { (void*)aa,  0 };
40 
41         p.append_load    (kN32_SkColorType, &src_ctx);
42         p.append_load_dst(kN32_SkColorType, &dst_ctx);
43 
44         if (SkBlendMode_ShouldPreScaleCoverage(fMode, /*rgb_coverage=*/false)) {
45             if (aa) {
46                 p.append(SkRasterPipeline::scale_u8, &aa_ctx);
47             }
48             SkBlendMode_AppendStages(fMode, &p);
49         } else {
50             SkBlendMode_AppendStages(fMode, &p);
51             if (aa) {
52                 p.append(SkRasterPipeline::lerp_u8, &aa_ctx);
53             }
54         }
55 
56         p.append_store(kN32_SkColorType, &dst_ctx);
57         p.run(0, 0, count,1);
58     }
59 
60 private:
61     const SkBlendMode fMode;
62 
63     using INHERITED = SkXfermode;
64 };
65 
SkBlendMode_Name(SkBlendMode bm)66 const char* SkBlendMode_Name(SkBlendMode bm) {
67     switch (bm) {
68         case SkBlendMode::kClear:      return "Clear";
69         case SkBlendMode::kSrc:        return "Src";
70         case SkBlendMode::kDst:        return "Dst";
71         case SkBlendMode::kSrcOver:    return "SrcOver";
72         case SkBlendMode::kDstOver:    return "DstOver";
73         case SkBlendMode::kSrcIn:      return "SrcIn";
74         case SkBlendMode::kDstIn:      return "DstIn";
75         case SkBlendMode::kSrcOut:     return "SrcOut";
76         case SkBlendMode::kDstOut:     return "DstOut";
77         case SkBlendMode::kSrcATop:    return "SrcATop";
78         case SkBlendMode::kDstATop:    return "DstATop";
79         case SkBlendMode::kXor:        return "Xor";
80         case SkBlendMode::kPlus:       return "Plus";
81         case SkBlendMode::kModulate:   return "Modulate";
82         case SkBlendMode::kScreen:     return "Screen";
83 
84         case SkBlendMode::kOverlay:    return "Overlay";
85         case SkBlendMode::kDarken:     return "Darken";
86         case SkBlendMode::kLighten:    return "Lighten";
87         case SkBlendMode::kColorDodge: return "ColorDodge";
88         case SkBlendMode::kColorBurn:  return "ColorBurn";
89         case SkBlendMode::kHardLight:  return "HardLight";
90         case SkBlendMode::kSoftLight:  return "SoftLight";
91         case SkBlendMode::kDifference: return "Difference";
92         case SkBlendMode::kExclusion:  return "Exclusion";
93         case SkBlendMode::kMultiply:   return "Multiply";
94 
95         case SkBlendMode::kHue:        return "Hue";
96         case SkBlendMode::kSaturation: return "Saturation";
97         case SkBlendMode::kColor:      return "Color";
98         case SkBlendMode::kLuminosity: return "Luminosity";
99     }
100     SkUNREACHABLE;
101 }
102 
Make(SkBlendMode mode)103 sk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) {
104     if ((unsigned)mode > (unsigned)SkBlendMode::kLastMode) {
105         // report error
106         return nullptr;
107     }
108 
109     // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
110     // so we can just return nullptr from the factory.
111     if (SkBlendMode::kSrcOver == mode) {
112         return nullptr;
113     }
114 
115     const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1;
116 
117     static SkOnce        once[COUNT_BLENDMODES];
118     static SkXfermode* cached[COUNT_BLENDMODES];
119 
120     once[(int)mode]([mode] {
121         if (auto xfermode = SkOpts::create_xfermode(mode)) {
122             cached[(int)mode] = xfermode;
123         } else {
124             cached[(int)mode] = new SkProcCoeffXfermode(mode);
125         }
126     });
127     return sk_ref_sp(cached[(int)mode]);
128 }
129 
130 ///////////////////////////////////////////////////////////////////////////////////////////////////
131 
IsOpaque(SkBlendMode mode,SrcColorOpacity opacityType)132 bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {
133     SkBlendModeCoeff src, dst;
134     if (!SkBlendMode_AsCoeff(mode, &src, &dst)) {
135         return false;
136     }
137 
138     switch (src) {
139         case SkBlendModeCoeff::kDA:
140         case SkBlendModeCoeff::kDC:
141         case SkBlendModeCoeff::kIDA:
142         case SkBlendModeCoeff::kIDC:
143             return false;
144         default:
145             break;
146     }
147 
148     switch (dst) {
149         case SkBlendModeCoeff::kZero:
150             return true;
151         case SkBlendModeCoeff::kISA:
152             return kOpaque_SrcColorOpacity == opacityType;
153         case SkBlendModeCoeff::kSA:
154             return kTransparentBlack_SrcColorOpacity == opacityType ||
155             kTransparentAlpha_SrcColorOpacity == opacityType;
156         case SkBlendModeCoeff::kSC:
157             return kTransparentBlack_SrcColorOpacity == opacityType;
158         default:
159             return false;
160     }
161     return false;
162 }
163 
164 #if SK_SUPPORT_GPU
SkBlendMode_AsXPFactory(SkBlendMode mode)165 const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) {
166     if (SkBlendMode_AsCoeff(mode, nullptr, nullptr)) {
167         const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode);
168         SkASSERT(result);
169         return result;
170     }
171 
172     SkASSERT(GrCustomXfermode::IsSupportedMode(mode));
173     return GrCustomXfermode::Get(mode);
174 }
175 #endif
176