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 "include/core/SkColorSpace.h"
9 #include "src/core/SkArenaAlloc.h"
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/core/SkVM.h"
16 #include "src/shaders/SkColorShader.h"
17
SkColorShader(SkColor c)18 SkColorShader::SkColorShader(SkColor c) : fColor(c) {}
19
isOpaque() const20 bool SkColorShader::isOpaque() const {
21 return SkColorGetA(fColor) == 255;
22 }
23
CreateProc(SkReadBuffer & buffer)24 sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) {
25 return sk_make_sp<SkColorShader>(buffer.readColor());
26 }
27
flatten(SkWriteBuffer & buffer) const28 void SkColorShader::flatten(SkWriteBuffer& buffer) const {
29 buffer.writeColor(fColor);
30 }
31
asAGradient(GradientInfo * info) const32 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
33 if (info) {
34 if (info->fColors && info->fColorCount >= 1) {
35 info->fColors[0] = fColor;
36 }
37 info->fColorCount = 1;
38 info->fTileMode = SkTileMode::kRepeat;
39 }
40 return kColor_GradientType;
41 }
42
SkColor4Shader(const SkColor4f & color,sk_sp<SkColorSpace> space)43 SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space)
44 : fColorSpace(std::move(space))
45 , fColor({color.fR, color.fG, color.fB, SkTPin(color.fA, 0.0f, 1.0f)})
46 {}
47
CreateProc(SkReadBuffer & buffer)48 sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) {
49 SkColor4f color;
50 sk_sp<SkColorSpace> colorSpace;
51 buffer.readColor4f(&color);
52 if (buffer.readBool()) {
53 sk_sp<SkData> data = buffer.readByteArrayAsData();
54 colorSpace = data ? SkColorSpace::Deserialize(data->data(), data->size()) : nullptr;
55 }
56 return SkShaders::Color(color, std::move(colorSpace));
57 }
58
flatten(SkWriteBuffer & buffer) const59 void SkColor4Shader::flatten(SkWriteBuffer& buffer) const {
60 buffer.writeColor4f(fColor);
61 sk_sp<SkData> colorSpaceData = fColorSpace ? fColorSpace->serialize() : nullptr;
62 if (colorSpaceData) {
63 buffer.writeBool(true);
64 buffer.writeDataAsByteArray(colorSpaceData.get());
65 } else {
66 buffer.writeBool(false);
67 }
68 }
69
70
Color(const SkColor4f & color,sk_sp<SkColorSpace> space)71 sk_sp<SkShader> SkShaders::Color(const SkColor4f& color, sk_sp<SkColorSpace> space) {
72 if (!SkScalarsAreFinite(color.vec(), 4)) {
73 return nullptr;
74 }
75 return sk_make_sp<SkColor4Shader>(color, std::move(space));
76 }
77
onAppendStages(const SkStageRec & rec) const78 bool SkColorShader::onAppendStages(const SkStageRec& rec) const {
79 SkColor4f color = SkColor4f::FromColor(fColor);
80 SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
81 rec.fDstCS, kUnpremul_SkAlphaType).apply(color.vec());
82 rec.fPipeline->append_constant_color(rec.fAlloc, color.premul().vec());
83 return true;
84 }
85
onAppendStages(const SkStageRec & rec) const86 bool SkColor4Shader::onAppendStages(const SkStageRec& rec) const {
87 SkColor4f color = fColor;
88 SkColorSpaceXformSteps(fColorSpace.get(), kUnpremul_SkAlphaType,
89 rec.fDstCS, kUnpremul_SkAlphaType).apply(color.vec());
90 rec.fPipeline->append_constant_color(rec.fAlloc, color.premul().vec());
91 return true;
92 }
93
onProgram(skvm::Builder * p,skvm::Coord,skvm::Coord,skvm::Color,const SkMatrixProvider &,const SkMatrix *,const SkColorInfo & dst,skvm::Uniforms * uniforms,SkArenaAlloc *) const94 skvm::Color SkColorShader::onProgram(skvm::Builder* p,
95 skvm::Coord /*device*/, skvm::Coord /*local*/,
96 skvm::Color /*paint*/, const SkMatrixProvider&,
97 const SkMatrix* /*localM*/, const SkColorInfo& dst,
98 skvm::Uniforms* uniforms, SkArenaAlloc*) const {
99 SkColor4f color = SkColor4f::FromColor(fColor);
100 SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
101 dst.colorSpace(), kPremul_SkAlphaType).apply(color.vec());
102 return p->uniformColor(color, uniforms);
103 }
onProgram(skvm::Builder * p,skvm::Coord,skvm::Coord,skvm::Color,const SkMatrixProvider &,const SkMatrix *,const SkColorInfo & dst,skvm::Uniforms * uniforms,SkArenaAlloc *) const104 skvm::Color SkColor4Shader::onProgram(skvm::Builder* p,
105 skvm::Coord /*device*/, skvm::Coord /*local*/,
106 skvm::Color /*paint*/, const SkMatrixProvider&,
107 const SkMatrix* /*localM*/, const SkColorInfo& dst,
108 skvm::Uniforms* uniforms, SkArenaAlloc*) const {
109 SkColor4f color = fColor;
110 SkColorSpaceXformSteps(fColorSpace.get(), kUnpremul_SkAlphaType,
111 dst.colorSpace(), kPremul_SkAlphaType).apply(color.vec());
112 return p->uniformColor(color, uniforms);
113 }
114
115 #if SK_SUPPORT_GPU
116
117 #include "src/gpu/GrColorInfo.h"
118 #include "src/gpu/GrColorSpaceXform.h"
119 #include "src/gpu/GrFragmentProcessor.h"
120 #include "src/gpu/SkGr.h"
121
asFragmentProcessor(const GrFPArgs & args) const122 std::unique_ptr<GrFragmentProcessor> SkColorShader::asFragmentProcessor(
123 const GrFPArgs& args) const {
124 return GrFragmentProcessor::MakeColor(SkColorToPMColor4f(fColor, *args.fDstColorInfo));
125 }
126
asFragmentProcessor(const GrFPArgs & args) const127 std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(
128 const GrFPArgs& args) const {
129 SkColorSpaceXformSteps steps{ fColorSpace.get(), kUnpremul_SkAlphaType,
130 args.fDstColorInfo->colorSpace(), kUnpremul_SkAlphaType };
131 SkColor4f color = fColor;
132 steps.apply(color.vec());
133 return GrFragmentProcessor::MakeColor(color.premul());
134 }
135
136 #endif
137