reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 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 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 8 | #include "include/core/SkColorSpace.h" |
Ben Wagner | 729a23f | 2019-05-17 16:29:34 -0400 | [diff] [blame] | 9 | #include "src/core/SkArenaAlloc.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 10 | #include "src/core/SkColorSpacePriv.h" |
| 11 | #include "src/core/SkColorSpaceXformSteps.h" |
| 12 | #include "src/core/SkRasterPipeline.h" |
| 13 | #include "src/core/SkReadBuffer.h" |
| 14 | #include "src/core/SkUtils.h" |
| 15 | #include "src/shaders/SkColorShader.h" |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 16 | |
| 17 | SkColorShader::SkColorShader(SkColor c) : fColor(c) {} |
| 18 | |
| 19 | bool SkColorShader::isOpaque() const { |
| 20 | return SkColorGetA(fColor) == 255; |
| 21 | } |
| 22 | |
| 23 | sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) { |
| 24 | return sk_make_sp<SkColorShader>(buffer.readColor()); |
| 25 | } |
| 26 | |
| 27 | void SkColorShader::flatten(SkWriteBuffer& buffer) const { |
| 28 | buffer.writeColor(fColor); |
| 29 | } |
| 30 | |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 31 | SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { |
| 32 | if (info) { |
| 33 | if (info->fColors && info->fColorCount >= 1) { |
| 34 | info->fColors[0] = fColor; |
| 35 | } |
| 36 | info->fColorCount = 1; |
Mike Reed | fae8fce | 2019-04-03 10:27:45 -0400 | [diff] [blame] | 37 | info->fTileMode = SkTileMode::kRepeat; |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 38 | } |
| 39 | return kColor_GradientType; |
| 40 | } |
| 41 | |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 42 | SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space) |
| 43 | : fColorSpace(std::move(space)) |
Mike Klein | a4eb936 | 2018-10-30 13:36:24 -0400 | [diff] [blame] | 44 | , fColor(color) |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 45 | {} |
| 46 | |
| 47 | sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) { |
| 48 | SkColor4f color; |
Brian Osman | 97d0970 | 2018-08-03 15:56:55 -0400 | [diff] [blame] | 49 | sk_sp<SkColorSpace> colorSpace; |
brianosman | 97bbf82 | 2016-09-25 13:15:58 -0700 | [diff] [blame] | 50 | buffer.readColor4f(&color); |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 51 | if (buffer.readBool()) { |
Brian Osman | 97d0970 | 2018-08-03 15:56:55 -0400 | [diff] [blame] | 52 | sk_sp<SkData> data = buffer.readByteArrayAsData(); |
| 53 | colorSpace = data ? SkColorSpace::Deserialize(data->data(), data->size()) : nullptr; |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 54 | } |
Mike Reed | c8bea7d | 2019-04-09 13:55:36 -0400 | [diff] [blame] | 55 | return SkShaders::Color(color, std::move(colorSpace)); |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 56 | } |
| 57 | |
| 58 | void SkColor4Shader::flatten(SkWriteBuffer& buffer) const { |
Mike Klein | a4eb936 | 2018-10-30 13:36:24 -0400 | [diff] [blame] | 59 | buffer.writeColor4f(fColor); |
Brian Osman | 97d0970 | 2018-08-03 15:56:55 -0400 | [diff] [blame] | 60 | sk_sp<SkData> colorSpaceData = fColorSpace ? fColorSpace->serialize() : nullptr; |
| 61 | if (colorSpaceData) { |
| 62 | buffer.writeBool(true); |
| 63 | buffer.writeDataAsByteArray(colorSpaceData.get()); |
| 64 | } else { |
| 65 | buffer.writeBool(false); |
| 66 | } |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 67 | } |
| 68 | |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 69 | |
Mike Reed | c8bea7d | 2019-04-09 13:55:36 -0400 | [diff] [blame] | 70 | sk_sp<SkShader> SkShaders::Color(const SkColor4f& color, sk_sp<SkColorSpace> space) { |
reed | 0ccc62d | 2016-05-04 13:09:39 -0700 | [diff] [blame] | 71 | if (!SkScalarsAreFinite(color.vec(), 4)) { |
| 72 | return nullptr; |
| 73 | } |
| 74 | return sk_make_sp<SkColor4Shader>(color, std::move(space)); |
| 75 | } |
| 76 | |
Mike Reed | 1386b2d | 2019-03-13 21:15:05 -0400 | [diff] [blame] | 77 | bool SkColorShader::onAppendStages(const SkStageRec& rec) const { |
Brian Osman | 5d7b5a3 | 2018-10-26 13:05:07 -0400 | [diff] [blame] | 78 | SkColor4f color = SkColor4f::FromColor(fColor); |
| 79 | SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType, |
| 80 | rec.fDstCS, kUnpremul_SkAlphaType).apply(color.vec()); |
| 81 | rec.fPipeline->append_constant_color(rec.fAlloc, color.premul().vec()); |
Matt Sarett | 8734566 | 2017-03-08 13:13:58 -0500 | [diff] [blame] | 82 | return true; |
Mike Klein | b0d10e0 | 2016-11-12 10:29:26 -0500 | [diff] [blame] | 83 | } |
| 84 | |
Mike Reed | 1386b2d | 2019-03-13 21:15:05 -0400 | [diff] [blame] | 85 | bool SkColor4Shader::onAppendStages(const SkStageRec& rec) const { |
Mike Klein | a4eb936 | 2018-10-30 13:36:24 -0400 | [diff] [blame] | 86 | SkColor4f color = fColor; |
Brian Osman | 5d7b5a3 | 2018-10-26 13:05:07 -0400 | [diff] [blame] | 87 | SkColorSpaceXformSteps(fColorSpace.get(), kUnpremul_SkAlphaType, |
| 88 | rec.fDstCS, kUnpremul_SkAlphaType).apply(color.vec()); |
| 89 | rec.fPipeline->append_constant_color(rec.fAlloc, color.premul().vec()); |
Matt Sarett | 8734566 | 2017-03-08 13:13:58 -0500 | [diff] [blame] | 90 | return true; |
Mike Klein | b0d10e0 | 2016-11-12 10:29:26 -0500 | [diff] [blame] | 91 | } |
Mike Klein | a4eb936 | 2018-10-30 13:36:24 -0400 | [diff] [blame] | 92 | |
Mike Klein | 9d0c67a | 2019-10-31 15:41:58 -0500 | [diff] [blame] | 93 | static bool common_program(SkColor4f color, SkColorSpace* cs, |
| 94 | skvm::Builder* p, |
| 95 | SkColorSpace* dstCS, |
Mike Klein | 1cc6067 | 2019-11-05 14:19:58 -0600 | [diff] [blame] | 96 | skvm::Uniforms* uniforms, |
Mike Klein | b9f2088 | 2019-11-08 12:14:15 -0600 | [diff] [blame] | 97 | skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) { |
Mike Klein | 9d0c67a | 2019-10-31 15:41:58 -0500 | [diff] [blame] | 98 | SkColorSpaceXformSteps( cs, kUnpremul_SkAlphaType, |
Mike Klein | b9f2088 | 2019-11-08 12:14:15 -0600 | [diff] [blame] | 99 | dstCS, kPremul_SkAlphaType).apply(color.vec()); |
Mike Klein | e4522dc | 2019-10-29 12:10:34 -0500 | [diff] [blame] | 100 | |
Mike Klein | b9f2088 | 2019-11-08 12:14:15 -0600 | [diff] [blame] | 101 | *r = p->uniformF(uniforms->pushF(color.fR)); |
| 102 | *g = p->uniformF(uniforms->pushF(color.fG)); |
| 103 | *b = p->uniformF(uniforms->pushF(color.fB)); |
| 104 | *a = p->uniformF(uniforms->pushF(color.fA)); |
| 105 | return true; |
Mike Klein | e4522dc | 2019-10-29 12:10:34 -0500 | [diff] [blame] | 106 | } |
Mike Klein | e4522dc | 2019-10-29 12:10:34 -0500 | [diff] [blame] | 107 | |
Mike Klein | 0393505 | 2019-11-01 11:36:55 -0500 | [diff] [blame] | 108 | bool SkColorShader::onProgram(skvm::Builder* p, |
Mike Klein | 9d0c67a | 2019-10-31 15:41:58 -0500 | [diff] [blame] | 109 | SkColorSpace* dstCS, |
Mike Klein | 1cc6067 | 2019-11-05 14:19:58 -0600 | [diff] [blame] | 110 | skvm::Uniforms* uniforms, |
Mike Klein | f3d4109 | 2019-11-04 13:22:02 -0600 | [diff] [blame] | 111 | skvm::F32 /*x*/, skvm::F32 /*y*/, |
Mike Klein | b9f2088 | 2019-11-08 12:14:15 -0600 | [diff] [blame] | 112 | skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const { |
Mike Klein | 0393505 | 2019-11-01 11:36:55 -0500 | [diff] [blame] | 113 | return common_program(SkColor4f::FromColor(fColor), sk_srgb_singleton(), |
Mike Klein | 1cc6067 | 2019-11-05 14:19:58 -0600 | [diff] [blame] | 114 | p, dstCS, uniforms, r,g,b,a); |
Mike Klein | 0393505 | 2019-11-01 11:36:55 -0500 | [diff] [blame] | 115 | } |
| 116 | bool SkColor4Shader::onProgram(skvm::Builder* p, |
| 117 | SkColorSpace* dstCS, |
Mike Klein | 1cc6067 | 2019-11-05 14:19:58 -0600 | [diff] [blame] | 118 | skvm::Uniforms* uniforms, |
Mike Klein | f3d4109 | 2019-11-04 13:22:02 -0600 | [diff] [blame] | 119 | skvm::F32 /*x*/, skvm::F32 /*y*/, |
Mike Klein | b9f2088 | 2019-11-08 12:14:15 -0600 | [diff] [blame] | 120 | skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const { |
Mike Klein | 9d0c67a | 2019-10-31 15:41:58 -0500 | [diff] [blame] | 121 | return common_program(fColor, fColorSpace.get(), |
Mike Klein | 1cc6067 | 2019-11-05 14:19:58 -0600 | [diff] [blame] | 122 | p, dstCS, uniforms, r,g,b,a); |
Mike Klein | 9d0c67a | 2019-10-31 15:41:58 -0500 | [diff] [blame] | 123 | } |
Mike Klein | e4522dc | 2019-10-29 12:10:34 -0500 | [diff] [blame] | 124 | |
Mike Klein | a4eb936 | 2018-10-30 13:36:24 -0400 | [diff] [blame] | 125 | #if SK_SUPPORT_GPU |
| 126 | |
Brian Salomon | 4bc0c1f | 2019-09-30 15:12:27 -0400 | [diff] [blame] | 127 | #include "src/gpu/GrColorInfo.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 128 | #include "src/gpu/GrColorSpaceXform.h" |
| 129 | #include "src/gpu/SkGr.h" |
| 130 | #include "src/gpu/effects/generated/GrConstColorProcessor.h" |
Mike Klein | a4eb936 | 2018-10-30 13:36:24 -0400 | [diff] [blame] | 131 | |
| 132 | std::unique_ptr<GrFragmentProcessor> SkColorShader::asFragmentProcessor( |
| 133 | const GrFPArgs& args) const { |
Brian Salomon | 4bc0c1f | 2019-09-30 15:12:27 -0400 | [diff] [blame] | 134 | SkPMColor4f color = SkColorToPMColor4f(fColor, *args.fDstColorInfo); |
Mike Klein | a4eb936 | 2018-10-30 13:36:24 -0400 | [diff] [blame] | 135 | return GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kModulateA); |
| 136 | } |
| 137 | |
| 138 | std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor( |
| 139 | const GrFPArgs& args) const { |
Brian Salomon | 4bc0c1f | 2019-09-30 15:12:27 -0400 | [diff] [blame] | 140 | SkColorSpaceXformSteps steps{ fColorSpace.get(), kUnpremul_SkAlphaType, |
| 141 | args.fDstColorInfo->colorSpace(), kUnpremul_SkAlphaType }; |
Mike Klein | a4eb936 | 2018-10-30 13:36:24 -0400 | [diff] [blame] | 142 | SkColor4f color = fColor; |
| 143 | steps.apply(color.vec()); |
| 144 | return GrConstColorProcessor::Make(color.premul(), |
| 145 | GrConstColorProcessor::InputMode::kModulateA); |
| 146 | } |
| 147 | |
| 148 | #endif |