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 "SkArenaAlloc.h" 9 #include "SkBlendModePriv.h" 10 #include "SkBlitRow.h" 11 #include "SkColorFilter.h" 12 #include "SkColorPriv.h" 13 #include "SkColorSpaceXformer.h" 14 #include "SkModeColorFilter.h" 15 #include "SkPM4f.h" 16 #include "SkPM4fPriv.h" 17 #include "SkRandom.h" 18 #include "SkRasterPipeline.h" 19 #include "SkReadBuffer.h" 20 #include "SkString.h" 21 #include "SkUtils.h" 22 #include "SkValidationUtils.h" 23 #include "SkWriteBuffer.h" 24 25 ////////////////////////////////////////////////////////////////////////////////////////////////// 26 27 SkModeColorFilter::SkModeColorFilter(SkColor color, SkBlendMode mode) { 28 fColor = color; 29 fMode = mode; 30 // cache 31 fPMColor = SkPreMultiplyColor(fColor); 32 } 33 34 #ifndef SK_IGNORE_TO_STRING 35 void SkModeColorFilter::toString(SkString* str) const { 36 str->append("SkModeColorFilter: color: 0x"); 37 str->appendHex(fColor); 38 str->append(" mode: "); 39 str->append(SkBlendMode_Name(fMode)); 40 } 41 #endif 42 43 bool SkModeColorFilter::asColorMode(SkColor* color, SkBlendMode* mode) const { 44 if (color) { 45 *color = fColor; 46 } 47 if (mode) { 48 *mode = fMode; 49 } 50 return true; 51 } 52 53 uint32_t SkModeColorFilter::getFlags() const { 54 uint32_t flags = 0; 55 switch (fMode) { 56 case SkBlendMode::kDst: //!< [Da, Dc] 57 case SkBlendMode::kSrcATop: //!< [Da, Sc * Da + (1 - Sa) * Dc] 58 flags |= kAlphaUnchanged_Flag; 59 default: 60 break; 61 } 62 return flags; 63 } 64 65 void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const { 66 buffer.writeColor(fColor); 67 buffer.writeUInt((int)fMode); 68 } 69 70 sk_sp<SkFlattenable> SkModeColorFilter::CreateProc(SkReadBuffer& buffer) { 71 SkColor color = buffer.readColor(); 72 SkBlendMode mode = (SkBlendMode)buffer.readUInt(); 73 return SkColorFilter::MakeModeFilter(color, mode); 74 } 75 76 void SkModeColorFilter::onAppendStages(SkRasterPipeline* p, 77 SkColorSpace* dst, 78 SkArenaAlloc* scratch, 79 bool shaderIsOpaque) const { 80 p->append(SkRasterPipeline::move_src_dst); 81 p->append_uniform_color(scratch, SkPM4f_from_SkColor(fColor, dst)); 82 SkBlendMode_AppendStages(fMode, p); 83 } 84 85 sk_sp<SkColorFilter> SkModeColorFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const { 86 SkColor color = xformer->apply(fColor); 87 if (color != fColor) { 88 return SkColorFilter::MakeModeFilter(color, fMode); 89 } 90 return this->INHERITED::onMakeColorSpace(xformer); 91 } 92 93 /////////////////////////////////////////////////////////////////////////////// 94 #if SK_SUPPORT_GPU 95 #include "GrBlend.h" 96 #include "effects/GrXfermodeFragmentProcessor.h" 97 #include "effects/GrConstColorProcessor.h" 98 #include "SkGr.h" 99 100 sk_sp<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor( 101 GrContext*, SkColorSpace* dstColorSpace) const { 102 if (SkBlendMode::kDst == fMode) { 103 return nullptr; 104 } 105 106 sk_sp<GrFragmentProcessor> constFP( 107 GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpace), 108 GrConstColorProcessor::kIgnore_InputMode)); 109 sk_sp<GrFragmentProcessor> fp( 110 GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode)); 111 if (!fp) { 112 return nullptr; 113 } 114 #ifdef SK_DEBUG 115 // With a solid color input this should always be able to compute the blended color 116 // (at least for coeff modes) 117 if ((unsigned)fMode <= (unsigned)SkBlendMode::kLastCoeffMode) { 118 SkASSERT(fp->hasConstantOutputForConstantInput()); 119 } 120 #endif 121 return fp; 122 } 123 124 #endif 125 126 /////////////////////////////////////////////////////////////////////////////// 127 128 sk_sp<SkColorFilter> SkColorFilter::MakeModeFilter(SkColor color, SkBlendMode mode) { 129 if (!SkIsValidMode(mode)) { 130 return nullptr; 131 } 132 133 unsigned alpha = SkColorGetA(color); 134 135 // first collaps some modes if possible 136 137 if (SkBlendMode::kClear == mode) { 138 color = 0; 139 mode = SkBlendMode::kSrc; 140 } else if (SkBlendMode::kSrcOver == mode) { 141 if (0 == alpha) { 142 mode = SkBlendMode::kDst; 143 } else if (255 == alpha) { 144 mode = SkBlendMode::kSrc; 145 } 146 // else just stay srcover 147 } 148 149 // weed out combinations that are noops, and just return null 150 if (SkBlendMode::kDst == mode || 151 (0 == alpha && (SkBlendMode::kSrcOver == mode || 152 SkBlendMode::kDstOver == mode || 153 SkBlendMode::kDstOut == mode || 154 SkBlendMode::kSrcATop == mode || 155 SkBlendMode::kXor == mode || 156 SkBlendMode::kDarken == mode)) || 157 (0xFF == alpha && SkBlendMode::kDstIn == mode)) { 158 return nullptr; 159 } 160 161 return SkModeColorFilter::Make(color, mode); 162 } 163