• 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  #include "src/gpu/effects/GrXfermodeFragmentProcessor.h"
24  #endif
25  
26  ///////////////////////////////////////////////////////////////////////////////////////////////////
27  
28  class SkProcCoeffXfermode : public SkXfermode {
29  public:
SkProcCoeffXfermode(SkBlendMode mode)30      SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {}
31  
xfer32(SkPMColor dst[],const SkPMColor src[],int count,const SkAlpha aa[]) const32      void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
33                  const SkAlpha aa[]) const override {
34          SkASSERT(dst && src && count >= 0);
35  
36          SkRasterPipeline_<256> p;
37  
38          SkRasterPipeline_MemoryCtx dst_ctx = { (void*)dst, 0 },
39                                     src_ctx = { (void*)src, 0 },
40                                      aa_ctx = { (void*)aa,  0 };
41  
42          p.append_load    (kN32_SkColorType, &src_ctx);
43          p.append_load_dst(kN32_SkColorType, &dst_ctx);
44  
45          if (SkBlendMode_ShouldPreScaleCoverage(fMode, /*rgb_coverage=*/false)) {
46              if (aa) {
47                  p.append(SkRasterPipeline::scale_u8, &aa_ctx);
48              }
49              SkBlendMode_AppendStages(fMode, &p);
50          } else {
51              SkBlendMode_AppendStages(fMode, &p);
52              if (aa) {
53                  p.append(SkRasterPipeline::lerp_u8, &aa_ctx);
54              }
55          }
56  
57          p.append_store(kN32_SkColorType, &dst_ctx);
58          p.run(0, 0, count,1);
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