• 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 
10 #if SK_SUPPORT_GPU
11 #include "GrFragmentProcessor.h"
12 #endif
13 
14 #if SK_SUPPORT_GPU
asFragmentProcessor(const AsFPArgs & args) const15 sk_sp<GrFragmentProcessor> SkLocalMatrixShader::asFragmentProcessor(const AsFPArgs& args) const {
16     SkMatrix tmp = this->getLocalMatrix();
17     if (args.fLocalMatrix) {
18         tmp.preConcat(*args.fLocalMatrix);
19     }
20     return fProxyShader->asFragmentProcessor(AsFPArgs(
21         args.fContext, args.fViewMatrix, &tmp, args.fFilterQuality, args.fDstColorSpace));
22 }
23 #endif
24 
CreateProc(SkReadBuffer & buffer)25 sk_sp<SkFlattenable> SkLocalMatrixShader::CreateProc(SkReadBuffer& buffer) {
26     SkMatrix lm;
27     buffer.readMatrix(&lm);
28     auto baseShader(buffer.readShader());
29     if (!baseShader) {
30         return nullptr;
31     }
32     return baseShader->makeWithLocalMatrix(lm);
33 }
34 
flatten(SkWriteBuffer & buffer) const35 void SkLocalMatrixShader::flatten(SkWriteBuffer& buffer) const {
36     buffer.writeMatrix(this->getLocalMatrix());
37     buffer.writeFlattenable(fProxyShader.get());
38 }
39 
onMakeContext(const ContextRec & rec,SkArenaAlloc * alloc) const40 SkShader::Context* SkLocalMatrixShader::onMakeContext(
41     const ContextRec& rec, SkArenaAlloc* alloc) const
42 {
43     ContextRec newRec(rec);
44     SkMatrix tmp;
45     if (rec.fLocalMatrix) {
46         tmp.setConcat(*rec.fLocalMatrix, this->getLocalMatrix());
47         newRec.fLocalMatrix = &tmp;
48     } else {
49         newRec.fLocalMatrix = &this->getLocalMatrix();
50     }
51     return fProxyShader->makeContext(newRec, alloc);
52 }
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(SkRasterPipeline * p,SkColorSpace * dst,SkArenaAlloc * scratch,const SkMatrix & ctm,const SkPaint & paint,const SkMatrix * localM) const65 bool SkLocalMatrixShader::onAppendStages(SkRasterPipeline* p,
66                                          SkColorSpace* dst,
67                                          SkArenaAlloc* scratch,
68                                          const SkMatrix& ctm,
69                                          const SkPaint& paint,
70                                          const SkMatrix* localM) const {
71     SkMatrix tmp;
72     if (localM) {
73         tmp.setConcat(*localM, this->getLocalMatrix());
74     }
75 
76     return fProxyShader->onAppendStages(p, dst, scratch, ctm, paint,
77                                         localM ? &tmp : &this->getLocalMatrix());
78 }
79 
80 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const81 void SkLocalMatrixShader::toString(SkString* str) const {
82     str->append("SkLocalMatrixShader: (");
83 
84     fProxyShader->toString(str);
85 
86     this->INHERITED::toString(str);
87 
88     str->append(")");
89 }
90 #endif
91 
makeWithLocalMatrix(const SkMatrix & localMatrix) const92 sk_sp<SkShader> SkShader::makeWithLocalMatrix(const SkMatrix& localMatrix) const {
93     if (localMatrix.isIdentity()) {
94         return sk_ref_sp(const_cast<SkShader*>(this));
95     }
96 
97     const SkMatrix* lm = &localMatrix;
98 
99     sk_sp<SkShader> baseShader;
100     SkMatrix otherLocalMatrix;
101     sk_sp<SkShader> proxy(this->makeAsALocalMatrixShader(&otherLocalMatrix));
102     if (proxy) {
103         otherLocalMatrix.preConcat(localMatrix);
104         lm = &otherLocalMatrix;
105         baseShader = proxy;
106     } else {
107         baseShader = sk_ref_sp(const_cast<SkShader*>(this));
108     }
109 
110     return sk_make_sp<SkLocalMatrixShader>(std::move(baseShader), *lm);
111 }
112