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