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