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) const16std::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)23sk_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) const33void 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) const39SkShaderBase::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) const54SkImage* 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) const65bool 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) const76sk_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