• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 "SkLocalMatrixShader.h"
9 #include "SkTLazy.h"
10 
11 #if SK_SUPPORT_GPU
12 #include "GrFragmentProcessor.h"
13 #endif
14 
15 #if SK_SUPPORT_GPU
asFragmentProcessor(const GrFPArgs & args) const16 std::unique_ptr<GrFragmentProcessor> SkLocalMatrixShader::asFragmentProcessor(
17         const GrFPArgs& args) const {
18     return as_SB(fProxyShader)->asFragmentProcessor(
19         GrFPArgs::WithPreLocalMatrix(args, this->getLocalMatrix()));
20 }
21 #endif
22 
CreateProc(SkReadBuffer & buffer)23 sk_sp<SkFlattenable> SkLocalMatrixShader::CreateProc(SkReadBuffer& buffer) {
24     SkMatrix lm;
25     buffer.readMatrix(&lm);
26     auto baseShader(buffer.readShader());
27     if (!baseShader) {
28         return nullptr;
29     }
30     return baseShader->makeWithLocalMatrix(lm);
31 }
32 
flatten(SkWriteBuffer & buffer) const33 void SkLocalMatrixShader::flatten(SkWriteBuffer& buffer) const {
34     buffer.writeMatrix(this->getLocalMatrix());
35     buffer.writeFlattenable(fProxyShader.get());
36 }
37 
38 #ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
onMakeContext(const ContextRec & rec,SkArenaAlloc * alloc) const39 SkShaderBase::Context* SkLocalMatrixShader::onMakeContext(
40     const ContextRec& rec, SkArenaAlloc* alloc) const
41 {
42     SkTCopyOnFirstWrite<SkMatrix> lm(this->getLocalMatrix());
43     if (rec.fLocalMatrix) {
44         lm.writable()->preConcat(*rec.fLocalMatrix);
45     }
46 
47     ContextRec newRec(rec);
48     newRec.fLocalMatrix = lm;
49 
50     return as_SB(fProxyShader)->makeContext(newRec, alloc);
51 }
52 #endif
53 
onIsAImage(SkMatrix * outMatrix,enum TileMode * mode) const54 SkImage* SkLocalMatrixShader::onIsAImage(SkMatrix* outMatrix, enum TileMode* mode) const {
55     SkMatrix imageMatrix;
56     SkImage* image = fProxyShader->isAImage(&imageMatrix, mode);
57     if (image && outMatrix) {
58         // Local matrix must be applied first so it is on the right side of the concat.
59         *outMatrix = SkMatrix::Concat(imageMatrix, this->getLocalMatrix());
60     }
61 
62     return image;
63 }
64 
onAppendStages(const StageRec & rec) const65 bool SkLocalMatrixShader::onAppendStages(const StageRec& rec) const {
66     SkTCopyOnFirstWrite<SkMatrix> lm(this->getLocalMatrix());
67     if (rec.fLocalM) {
68         lm.writable()->preConcat(*rec.fLocalM);
69     }
70 
71     StageRec newRec = rec;
72     newRec.fLocalM = lm;
73     return as_SB(fProxyShader)->appendStages(newRec);
74 }
75 
makeWithLocalMatrix(const SkMatrix & localMatrix) const76 sk_sp<SkShader> SkShader::makeWithLocalMatrix(const SkMatrix& localMatrix) const {
77     if (localMatrix.isIdentity()) {
78         return sk_ref_sp(const_cast<SkShader*>(this));
79     }
80 
81     const SkMatrix* lm = &localMatrix;
82 
83     sk_sp<SkShader> baseShader;
84     SkMatrix otherLocalMatrix;
85     sk_sp<SkShader> proxy(as_SB(this)->makeAsALocalMatrixShader(&otherLocalMatrix));
86     if (proxy) {
87         otherLocalMatrix.preConcat(localMatrix);
88         lm = &otherLocalMatrix;
89         baseShader = proxy;
90     } else {
91         baseShader = sk_ref_sp(const_cast<SkShader*>(this));
92     }
93 
94     return sk_make_sp<SkLocalMatrixShader>(std::move(baseShader), *lm);
95 }
96