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