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: |
29 | SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {} |
30 | |
31 | 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 | typedef SkXfermode INHERITED; |
64 | }; |
65 | |
66 | const char* SkBlendMode_Name(SkBlendMode mode) { |
67 | SkASSERT((unsigned) mode <= (unsigned)SkBlendMode::kLastMode); |
68 | const char* gModeStrings[] = { |
69 | "Clear" , "Src" , "Dst" , "SrcOver" , "DstOver" , "SrcIn" , "DstIn" , |
70 | "SrcOut" , "DstOut" , "SrcATop" , "DstATop" , "Xor" , "Plus" , |
71 | "Modulate" , "Screen" , "Overlay" , "Darken" , "Lighten" , "ColorDodge" , |
72 | "ColorBurn" , "HardLight" , "SoftLight" , "Difference" , "Exclusion" , |
73 | "Multiply" , "Hue" , "Saturation" , "Color" , "Luminosity" |
74 | }; |
75 | return gModeStrings[(int)mode]; |
76 | static_assert(SK_ARRAY_COUNT(gModeStrings) == (size_t)SkBlendMode::kLastMode + 1, "mode_count" ); |
77 | } |
78 | |
79 | sk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) { |
80 | if ((unsigned)mode > (unsigned)SkBlendMode::kLastMode) { |
81 | // report error |
82 | return nullptr; |
83 | } |
84 | |
85 | // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover |
86 | // so we can just return nullptr from the factory. |
87 | if (SkBlendMode::kSrcOver == mode) { |
88 | return nullptr; |
89 | } |
90 | |
91 | const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1; |
92 | |
93 | static SkOnce once[COUNT_BLENDMODES]; |
94 | static SkXfermode* cached[COUNT_BLENDMODES]; |
95 | |
96 | once[(int)mode]([mode] { |
97 | if (auto xfermode = SkOpts::create_xfermode(mode)) { |
98 | cached[(int)mode] = xfermode; |
99 | } else { |
100 | cached[(int)mode] = new SkProcCoeffXfermode(mode); |
101 | } |
102 | }); |
103 | return sk_ref_sp(cached[(int)mode]); |
104 | } |
105 | |
106 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
107 | |
108 | bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) { |
109 | SkBlendModeCoeff src, dst; |
110 | if (!SkBlendMode_AsCoeff(mode, &src, &dst)) { |
111 | return false; |
112 | } |
113 | |
114 | switch (src) { |
115 | case SkBlendModeCoeff::kDA: |
116 | case SkBlendModeCoeff::kDC: |
117 | case SkBlendModeCoeff::kIDA: |
118 | case SkBlendModeCoeff::kIDC: |
119 | return false; |
120 | default: |
121 | break; |
122 | } |
123 | |
124 | switch (dst) { |
125 | case SkBlendModeCoeff::kZero: |
126 | return true; |
127 | case SkBlendModeCoeff::kISA: |
128 | return kOpaque_SrcColorOpacity == opacityType; |
129 | case SkBlendModeCoeff::kSA: |
130 | return kTransparentBlack_SrcColorOpacity == opacityType || |
131 | kTransparentAlpha_SrcColorOpacity == opacityType; |
132 | case SkBlendModeCoeff::kSC: |
133 | return kTransparentBlack_SrcColorOpacity == opacityType; |
134 | default: |
135 | return false; |
136 | } |
137 | return false; |
138 | } |
139 | |
140 | #if SK_SUPPORT_GPU |
141 | const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) { |
142 | if (SkBlendMode_AsCoeff(mode, nullptr, nullptr)) { |
143 | const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode); |
144 | SkASSERT(result); |
145 | return result; |
146 | } |
147 | |
148 | SkASSERT(GrCustomXfermode::IsSupportedMode(mode)); |
149 | return GrCustomXfermode::Get(mode); |
150 | } |
151 | #endif |
152 | |
153 | |