1 /* 2 * Copyright 2016 Google Inc. 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 "SkColorShader.h" 10 #include "SkColorSpace.h" 11 #include "SkPM4fPriv.h" 12 #include "SkRasterPipeline.h" 13 #include "SkReadBuffer.h" 14 #include "SkUtils.h" 15 16 SkColorShader::SkColorShader(SkColor c) : fColor(c) {} 17 18 bool SkColorShader::isOpaque() const { 19 return SkColorGetA(fColor) == 255; 20 } 21 22 sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) { 23 return sk_make_sp<SkColorShader>(buffer.readColor()); 24 } 25 26 void SkColorShader::flatten(SkWriteBuffer& buffer) const { 27 buffer.writeColor(fColor); 28 } 29 30 uint32_t SkColorShader::ColorShaderContext::getFlags() const { 31 return fFlags; 32 } 33 34 SkShader::Context* SkColorShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const { 35 return alloc->make<ColorShaderContext>(*this, rec); 36 } 37 38 SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, 39 const ContextRec& rec) 40 : INHERITED(shader, rec) 41 { 42 SkColor color = shader.fColor; 43 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); 44 45 unsigned r = SkColorGetR(color); 46 unsigned g = SkColorGetG(color); 47 unsigned b = SkColorGetB(color); 48 49 if (a != 255) { 50 r = SkMulDiv255Round(r, a); 51 g = SkMulDiv255Round(g, a); 52 b = SkMulDiv255Round(b, a); 53 } 54 fPMColor = SkPackARGB32(a, r, g, b); 55 56 SkColor4f c4 = SkColor4f::FromColor(shader.fColor); 57 c4.fA *= rec.fPaint->getAlpha() / 255.0f; 58 fPM4f = c4.premul(); 59 60 fFlags = kConstInY32_Flag; 61 if (255 == a) { 62 fFlags |= kOpaqueAlpha_Flag; 63 } 64 } 65 66 void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) { 67 sk_memset32(span, fPMColor, count); 68 } 69 70 void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 71 memset(alpha, SkGetPackedA32(fPMColor), count); 72 } 73 74 void SkColorShader::ColorShaderContext::shadeSpan4f(int x, int y, SkPM4f span[], int count) { 75 for (int i = 0; i < count; ++i) { 76 span[i] = fPM4f; 77 } 78 } 79 80 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { 81 if (info) { 82 if (info->fColors && info->fColorCount >= 1) { 83 info->fColors[0] = fColor; 84 } 85 info->fColorCount = 1; 86 info->fTileMode = SkShader::kRepeat_TileMode; 87 } 88 return kColor_GradientType; 89 } 90 91 #if SK_SUPPORT_GPU 92 93 #include "SkGr.h" 94 #include "effects/GrConstColorProcessor.h" 95 sk_sp<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const AsFPArgs& args) const { 96 GrColor4f color = SkColorToPremulGrColor4f(fColor, args.fDstColorSpace); 97 return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode); 98 } 99 100 #endif 101 102 #ifndef SK_IGNORE_TO_STRING 103 void SkColorShader::toString(SkString* str) const { 104 str->append("SkColorShader: ("); 105 106 str->append("Color: "); 107 str->appendHex(fColor); 108 109 this->INHERITED::toString(str); 110 111 str->append(")"); 112 } 113 #endif 114 115 /////////////////////////////////////////////////////////////////////////////////////////////////// 116 /////////////////////////////////////////////////////////////////////////////////////////////////// 117 118 static unsigned unit_to_byte(float unit) { 119 SkASSERT(unit >= 0 && unit <= 1); 120 return (unsigned)(unit * 255 + 0.5); 121 } 122 123 static SkColor unit_to_skcolor(const SkColor4f& unit, SkColorSpace* cs) { 124 return SkColorSetARGB(unit_to_byte(unit.fA), unit_to_byte(unit.fR), 125 unit_to_byte(unit.fG), unit_to_byte(unit.fB)); 126 } 127 128 SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space) 129 : fColorSpace(std::move(space)) 130 , fColor4(color) 131 , fCachedByteColor(unit_to_skcolor(color.pin(), space.get())) 132 {} 133 134 sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) { 135 SkColor4f color; 136 buffer.readColor4f(&color); 137 if (buffer.readBool()) { 138 // TODO how do we unflatten colorspaces 139 } 140 return SkShader::MakeColorShader(color, nullptr); 141 } 142 143 void SkColor4Shader::flatten(SkWriteBuffer& buffer) const { 144 buffer.writeColor4f(fColor4); 145 buffer.writeBool(false); // TODO how do we flatten colorspaces? 146 } 147 148 uint32_t SkColor4Shader::Color4Context::getFlags() const { 149 return fFlags; 150 } 151 152 SkShader::Context* SkColor4Shader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const { 153 return alloc->make<Color4Context>(*this, rec); 154 } 155 156 SkColor4Shader::Color4Context::Color4Context(const SkColor4Shader& shader, 157 const ContextRec& rec) 158 : INHERITED(shader, rec) 159 { 160 SkColor color = shader.fCachedByteColor; 161 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); 162 163 unsigned r = SkColorGetR(color); 164 unsigned g = SkColorGetG(color); 165 unsigned b = SkColorGetB(color); 166 167 if (a != 255) { 168 r = SkMulDiv255Round(r, a); 169 g = SkMulDiv255Round(g, a); 170 b = SkMulDiv255Round(b, a); 171 } 172 fPMColor = SkPackARGB32(a, r, g, b); 173 174 SkColor4f c4 = shader.fColor4; 175 c4.fA *= rec.fPaint->getAlpha() * (1 / 255.0f); 176 fPM4f = c4.premul(); 177 178 fFlags = kConstInY32_Flag; 179 if (255 == a) { 180 fFlags |= kOpaqueAlpha_Flag; 181 } 182 } 183 184 void SkColor4Shader::Color4Context::shadeSpan(int x, int y, SkPMColor span[], int count) { 185 sk_memset32(span, fPMColor, count); 186 } 187 188 void SkColor4Shader::Color4Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 189 memset(alpha, SkGetPackedA32(fPMColor), count); 190 } 191 192 void SkColor4Shader::Color4Context::shadeSpan4f(int x, int y, SkPM4f span[], int count) { 193 for (int i = 0; i < count; ++i) { 194 span[i] = fPM4f; 195 } 196 } 197 198 // TODO: do we need an updated version of this method for color4+colorspace? 199 SkShader::GradientType SkColor4Shader::asAGradient(GradientInfo* info) const { 200 if (info) { 201 if (info->fColors && info->fColorCount >= 1) { 202 info->fColors[0] = fCachedByteColor; 203 } 204 info->fColorCount = 1; 205 info->fTileMode = SkShader::kRepeat_TileMode; 206 } 207 return kColor_GradientType; 208 } 209 210 #if SK_SUPPORT_GPU 211 212 #include "SkGr.h" 213 #include "effects/GrConstColorProcessor.h" 214 #include "GrColorSpaceXform.h" 215 sk_sp<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const AsFPArgs& args) const { 216 sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(), 217 args.fDstColorSpace); 218 GrColor4f color = GrColor4f::FromSkColor4f(fColor4); 219 if (colorSpaceXform) { 220 color = colorSpaceXform->apply(color); 221 } 222 return GrConstColorProcessor::Make(color.premul(), GrConstColorProcessor::kModulateA_InputMode); 223 } 224 225 #endif 226 227 #ifndef SK_IGNORE_TO_STRING 228 void SkColor4Shader::toString(SkString* str) const { 229 str->append("SkColor4Shader: ("); 230 231 str->append("RGBA:"); 232 for (int i = 0; i < 4; ++i) { 233 str->appendf(" %g", fColor4.vec()[i]); 234 } 235 str->append(" )"); 236 } 237 #endif 238 239 sk_sp<SkShader> SkShader::MakeColorShader(const SkColor4f& color, sk_sp<SkColorSpace> space) { 240 if (!SkScalarsAreFinite(color.vec(), 4)) { 241 return nullptr; 242 } 243 return sk_make_sp<SkColor4Shader>(color, std::move(space)); 244 } 245 246 /////////////////////////////////////////////////////////////////////////////////////////////////// 247 /////////////////////////////////////////////////////////////////////////////////////////////////// 248 249 static void D32_BlitBW(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst, 250 int count) { 251 SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0]; 252 const SkPM4f* src = (const SkPM4f*)state->fStorage[1]; 253 proc(state->fMode, dst.writable_addr32(x, y), src, count, nullptr); 254 } 255 256 static void D32_BlitAA(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst, 257 int count, const SkAlpha aa[]) { 258 SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0]; 259 const SkPM4f* src = (const SkPM4f*)state->fStorage[1]; 260 proc(state->fMode, dst.writable_addr32(x, y), src, count, aa); 261 } 262 263 static void F16_BlitBW(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst, 264 int count) { 265 SkXfermode::F16Proc proc = (SkXfermode::F16Proc)state->fStorage[0]; 266 const SkPM4f* src = (const SkPM4f*)state->fStorage[1]; 267 proc(state->fMode, dst.writable_addr64(x, y), src, count, nullptr); 268 } 269 270 static void F16_BlitAA(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst, 271 int count, const SkAlpha aa[]) { 272 SkXfermode::F16Proc proc = (SkXfermode::F16Proc)state->fStorage[0]; 273 const SkPM4f* src = (const SkPM4f*)state->fStorage[1]; 274 proc(state->fMode, dst.writable_addr64(x, y), src, count, aa); 275 } 276 277 static bool choose_blitprocs(const SkPM4f* pm4, const SkImageInfo& info, 278 SkShader::Context::BlitState* state) { 279 uint32_t flags = SkXfermode::kSrcIsSingle_D32Flag; 280 if (pm4->a() == 1) { 281 flags |= SkXfermode::kSrcIsOpaque_D32Flag; 282 } 283 switch (info.colorType()) { 284 case kN32_SkColorType: 285 if (info.gammaCloseToSRGB()) { 286 flags |= SkXfermode::kDstIsSRGB_D32Flag; 287 } 288 state->fStorage[0] = (void*)SkXfermode::GetD32Proc(state->fMode, flags); 289 state->fStorage[1] = (void*)pm4; 290 state->fBlitBW = D32_BlitBW; 291 state->fBlitAA = D32_BlitAA; 292 return true; 293 case kRGBA_F16_SkColorType: 294 state->fStorage[0] = (void*)SkXfermode::GetF16Proc(state->fMode, flags); 295 state->fStorage[1] = (void*)pm4; 296 state->fBlitBW = F16_BlitBW; 297 state->fBlitAA = F16_BlitAA; 298 return true; 299 default: 300 return false; 301 } 302 } 303 304 bool SkColorShader::ColorShaderContext::onChooseBlitProcs(const SkImageInfo& info, 305 BlitState* state) { 306 return choose_blitprocs(&fPM4f, info, state); 307 } 308 309 bool SkColor4Shader::Color4Context::onChooseBlitProcs(const SkImageInfo& info, BlitState* state) { 310 return choose_blitprocs(&fPM4f, info, state); 311 } 312 313 bool SkColorShader::onAppendStages(SkRasterPipeline* p, 314 SkColorSpace* dst, 315 SkArenaAlloc* scratch, 316 const SkMatrix&, 317 const SkPaint&, 318 const SkMatrix*) const { 319 auto color = scratch->make<SkPM4f>(SkPM4f_from_SkColor(fColor, dst)); 320 p->append(SkRasterPipeline::constant_color, color); 321 return append_gamut_transform(p, scratch, 322 SkColorSpace::MakeSRGB().get(), dst); 323 } 324 325 bool SkColor4Shader::onAppendStages(SkRasterPipeline* p, 326 SkColorSpace* dst, 327 SkArenaAlloc* scratch, 328 const SkMatrix&, 329 const SkPaint&, 330 const SkMatrix*) const { 331 auto color = scratch->make<SkPM4f>(fColor4.premul()); 332 p->append(SkRasterPipeline::constant_color, color); 333 return append_gamut_transform(p, scratch, fColorSpace.get(), dst); 334 } 335