1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2012 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/shaders/gradients/SkLinearGradient.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h"
11cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h"
12cb93a386Sopenharmony_ci#include "src/shaders/gradients/Sk4fLinearGradient.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_cistatic SkMatrix pts_to_unit_matrix(const SkPoint pts[2]) {
15cb93a386Sopenharmony_ci    SkVector    vec = pts[1] - pts[0];
16cb93a386Sopenharmony_ci    SkScalar    mag = vec.length();
17cb93a386Sopenharmony_ci    SkScalar    inv = mag ? SkScalarInvert(mag) : 0;
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci    vec.scale(inv);
20cb93a386Sopenharmony_ci    SkMatrix matrix;
21cb93a386Sopenharmony_ci    matrix.setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
22cb93a386Sopenharmony_ci    matrix.postTranslate(-pts[0].fX, -pts[0].fY);
23cb93a386Sopenharmony_ci    matrix.postScale(inv, inv);
24cb93a386Sopenharmony_ci    return matrix;
25cb93a386Sopenharmony_ci}
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ciSkLinearGradient::SkLinearGradient(const SkPoint pts[2], const Descriptor& desc)
30cb93a386Sopenharmony_ci    : SkGradientShaderBase(desc, pts_to_unit_matrix(pts))
31cb93a386Sopenharmony_ci    , fStart(pts[0])
32cb93a386Sopenharmony_ci    , fEnd(pts[1]) {
33cb93a386Sopenharmony_ci}
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_cisk_sp<SkFlattenable> SkLinearGradient::CreateProc(SkReadBuffer& buffer) {
36cb93a386Sopenharmony_ci    DescriptorScope desc;
37cb93a386Sopenharmony_ci    if (!desc.unflatten(buffer)) {
38cb93a386Sopenharmony_ci        return nullptr;
39cb93a386Sopenharmony_ci    }
40cb93a386Sopenharmony_ci    SkPoint pts[2];
41cb93a386Sopenharmony_ci    pts[0] = buffer.readPoint();
42cb93a386Sopenharmony_ci    pts[1] = buffer.readPoint();
43cb93a386Sopenharmony_ci    return SkGradientShader::MakeLinear(pts, desc.fColors, std::move(desc.fColorSpace), desc.fPos,
44cb93a386Sopenharmony_ci                                        desc.fCount, desc.fTileMode, desc.fGradFlags,
45cb93a386Sopenharmony_ci                                        desc.fLocalMatrix);
46cb93a386Sopenharmony_ci}
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_civoid SkLinearGradient::flatten(SkWriteBuffer& buffer) const {
49cb93a386Sopenharmony_ci    this->INHERITED::flatten(buffer);
50cb93a386Sopenharmony_ci    buffer.writePoint(fStart);
51cb93a386Sopenharmony_ci    buffer.writePoint(fEnd);
52cb93a386Sopenharmony_ci}
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ci#ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
55cb93a386Sopenharmony_ciSkShaderBase::Context* SkLinearGradient::onMakeContext(
56cb93a386Sopenharmony_ci    const ContextRec& rec, SkArenaAlloc* alloc) const
57cb93a386Sopenharmony_ci{
58cb93a386Sopenharmony_ci    // make sure our colorspaces are compatible with legacy blits
59cb93a386Sopenharmony_ci    if (!rec.isLegacyCompatible(fColorSpace.get())) {
60cb93a386Sopenharmony_ci        return nullptr;
61cb93a386Sopenharmony_ci    }
62cb93a386Sopenharmony_ci    // Can't use legacy blit if we can't represent our colors as SkColors
63cb93a386Sopenharmony_ci    if (!this->colorsCanConvertToSkColor()) {
64cb93a386Sopenharmony_ci        return nullptr;
65cb93a386Sopenharmony_ci    }
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci    return fTileMode != SkTileMode::kDecal
68cb93a386Sopenharmony_ci        ? CheckedMakeContext<LinearGradient4fContext>(alloc, *this, rec)
69cb93a386Sopenharmony_ci        : nullptr;
70cb93a386Sopenharmony_ci}
71cb93a386Sopenharmony_ci#endif
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_civoid SkLinearGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline*,
74cb93a386Sopenharmony_ci                                            SkRasterPipeline*) const {
75cb93a386Sopenharmony_ci    // No extra stage needed for linear gradients.
76cb93a386Sopenharmony_ci}
77cb93a386Sopenharmony_ci
78cb93a386Sopenharmony_ciskvm::F32 SkLinearGradient::transformT(skvm::Builder* p, skvm::Uniforms*,
79cb93a386Sopenharmony_ci                                       skvm::Coord coord, skvm::I32* mask) const {
80cb93a386Sopenharmony_ci    // We've baked getting t in x into the matrix, so this is pretty trivial.
81cb93a386Sopenharmony_ci    return coord.x;
82cb93a386Sopenharmony_ci}
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_ciSkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const {
85cb93a386Sopenharmony_ci    if (info) {
86cb93a386Sopenharmony_ci        commonAsAGradient(info);
87cb93a386Sopenharmony_ci        info->fPoint[0] = fStart;
88cb93a386Sopenharmony_ci        info->fPoint[1] = fEnd;
89cb93a386Sopenharmony_ci    }
90cb93a386Sopenharmony_ci    return kLinear_GradientType;
91cb93a386Sopenharmony_ci}
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci#if SK_SUPPORT_GPU
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ci#include "src/gpu/gradients/GrGradientShader.h"
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> SkLinearGradient::asFragmentProcessor(
100cb93a386Sopenharmony_ci        const GrFPArgs& args) const {
101cb93a386Sopenharmony_ci    return GrGradientShader::MakeLinear(*this, args);
102cb93a386Sopenharmony_ci}
103cb93a386Sopenharmony_ci
104cb93a386Sopenharmony_ci#endif
105