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
18SkColorShader::SkColorShader(SkColor c) : fColor(c) {}
19
20bool SkColorShader::isOpaque() const {
21 return SkColorGetA(fColor) == 255;
22}
23
24sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) {
25 return sk_make_sp<SkColorShader>(buffer.readColor());
26}
27
28void SkColorShader::flatten(SkWriteBuffer& buffer) const {
29 buffer.writeColor(fColor);
30}
31
32SkShader::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
43SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space)
44 : fColorSpace(std::move(space))
45 , fColor(color)
46{}
47
48sk_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
59void 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
71sk_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
78bool 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
86bool 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
94skvm::Color SkColorShader::onProgram(skvm::Builder* p,
95 skvm::F32 /*x*/, skvm::F32 /*y*/, skvm::Color /*paint*/,
96 const SkMatrix& /*ctm*/, const SkMatrix* /*localM*/,
97 SkFilterQuality /*quality*/, const SkColorInfo& dst,
98 skvm::Uniforms* uniforms, SkArenaAlloc*) const {
99 return p->uniformPremul(SkColor4f::FromColor(fColor), sk_srgb_singleton(),
100 uniforms, dst.colorSpace());
101}
102skvm::Color SkColor4Shader::onProgram(skvm::Builder* p,
103 skvm::F32 /*x*/, skvm::F32 /*y*/, skvm::Color /*paint*/,
104 const SkMatrix& /*ctm*/, const SkMatrix* /*localM*/,
105 SkFilterQuality /*quality*/, const SkColorInfo& dst,
106 skvm::Uniforms* uniforms, SkArenaAlloc*) const {
107 return p->uniformPremul(fColor, fColorSpace.get(),
108 uniforms, dst.colorSpace());
109}
110
111#if SK_SUPPORT_GPU
112
113#include "src/gpu/GrColorInfo.h"
114#include "src/gpu/GrColorSpaceXform.h"
115#include "src/gpu/SkGr.h"
116#include "src/gpu/effects/generated/GrConstColorProcessor.h"
117
118std::unique_ptr<GrFragmentProcessor> SkColorShader::asFragmentProcessor(
119 const GrFPArgs& args) const {
120 SkPMColor4f color = SkColorToPMColor4f(fColor, *args.fDstColorInfo);
121 return GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kModulateA);
122}
123
124std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(
125 const GrFPArgs& args) const {
126 SkColorSpaceXformSteps steps{ fColorSpace.get(), kUnpremul_SkAlphaType,
127 args.fDstColorInfo->colorSpace(), kUnpremul_SkAlphaType };
128 SkColor4f color = fColor;
129 steps.apply(color.vec());
130 return GrConstColorProcessor::Make(color.premul(),
131 GrConstColorProcessor::InputMode::kModulateA);
132}
133
134#endif
135