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 15 std::unique_ptr<GrFragmentProcessor> SkLocalMatrixShader::asFragmentProcessor( 16 const GrFPArgs& args) const { 17 SkMatrix tmp = this->getLocalMatrix(); 18 if (args.fLocalMatrix) { 19 tmp.preConcat(*args.fLocalMatrix); 20 } 21 return as_SB(fProxyShader) 22 ->asFragmentProcessor(GrFPArgs(args.fContext, args.fViewMatrix, &tmp, 23 args.fFilterQuality, args.fDstColorSpaceInfo)); 24 } 25 #endif 26 27 sk_sp<SkFlattenable> SkLocalMatrixShader::CreateProc(SkReadBuffer& buffer) { 28 SkMatrix lm; 29 buffer.readMatrix(&lm); 30 auto baseShader(buffer.readShader()); 31 if (!baseShader) { 32 return nullptr; 33 } 34 return baseShader->makeWithLocalMatrix(lm); 35 } 36 37 void SkLocalMatrixShader::flatten(SkWriteBuffer& buffer) const { 38 buffer.writeMatrix(this->getLocalMatrix()); 39 buffer.writeFlattenable(fProxyShader.get()); 40 } 41 42 SkShaderBase::Context* SkLocalMatrixShader::onMakeContext( 43 const ContextRec& rec, SkArenaAlloc* alloc) const 44 { 45 ContextRec newRec(rec); 46 SkMatrix tmp; 47 if (rec.fLocalMatrix) { 48 tmp.setConcat(*rec.fLocalMatrix, this->getLocalMatrix()); 49 newRec.fLocalMatrix = &tmp; 50 } else { 51 newRec.fLocalMatrix = &this->getLocalMatrix(); 52 } 53 return as_SB(fProxyShader)->makeContext(newRec, alloc); 54 } 55 56 SkImage* SkLocalMatrixShader::onIsAImage(SkMatrix* outMatrix, enum TileMode* mode) const { 57 SkMatrix imageMatrix; 58 SkImage* image = fProxyShader->isAImage(&imageMatrix, mode); 59 if (image && outMatrix) { 60 // Local matrix must be applied first so it is on the right side of the concat. 61 *outMatrix = SkMatrix::Concat(imageMatrix, this->getLocalMatrix()); 62 } 63 64 return image; 65 } 66 67 bool SkLocalMatrixShader::onAppendStages(const StageRec& rec) const { 68 SkMatrix tmp; 69 if (rec.fLocalM) { 70 tmp.setConcat(*rec.fLocalM, this->getLocalMatrix()); 71 } 72 StageRec newRec = rec; 73 newRec.fLocalM = rec.fLocalM ? &tmp : &this->getLocalMatrix(); 74 return as_SB(fProxyShader)->appendStages(newRec); 75 } 76 77 #ifndef SK_IGNORE_TO_STRING 78 void SkLocalMatrixShader::toString(SkString* str) const { 79 str->append("SkLocalMatrixShader: ("); 80 81 as_SB(fProxyShader)->toString(str); 82 83 this->INHERITED::toString(str); 84 85 str->append(")"); 86 } 87 #endif 88 89 sk_sp<SkShader> SkShader::makeWithLocalMatrix(const SkMatrix& localMatrix) const { 90 if (localMatrix.isIdentity()) { 91 return sk_ref_sp(const_cast<SkShader*>(this)); 92 } 93 94 const SkMatrix* lm = &localMatrix; 95 96 sk_sp<SkShader> baseShader; 97 SkMatrix otherLocalMatrix; 98 sk_sp<SkShader> proxy(as_SB(this)->makeAsALocalMatrixShader(&otherLocalMatrix)); 99 if (proxy) { 100 otherLocalMatrix.preConcat(localMatrix); 101 lm = &otherLocalMatrix; 102 baseShader = proxy; 103 } else { 104 baseShader = sk_ref_sp(const_cast<SkShader*>(this)); 105 } 106 107 return sk_make_sp<SkLocalMatrixShader>(std::move(baseShader), *lm); 108 } 109