/* * Copyright 2014 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkLocalMatrixShader.h" #if SK_SUPPORT_GPU #include "GrFragmentProcessor.h" #endif #if SK_SUPPORT_GPU std::unique_ptr SkLocalMatrixShader::asFragmentProcessor( const GrFPArgs& args) const { SkMatrix tmp = this->getLocalMatrix(); if (args.fLocalMatrix) { tmp.preConcat(*args.fLocalMatrix); } return as_SB(fProxyShader) ->asFragmentProcessor(GrFPArgs(args.fContext, args.fViewMatrix, &tmp, args.fFilterQuality, args.fDstColorSpaceInfo)); } #endif sk_sp SkLocalMatrixShader::CreateProc(SkReadBuffer& buffer) { SkMatrix lm; buffer.readMatrix(&lm); auto baseShader(buffer.readShader()); if (!baseShader) { return nullptr; } return baseShader->makeWithLocalMatrix(lm); } void SkLocalMatrixShader::flatten(SkWriteBuffer& buffer) const { buffer.writeMatrix(this->getLocalMatrix()); buffer.writeFlattenable(fProxyShader.get()); } SkShaderBase::Context* SkLocalMatrixShader::onMakeContext( const ContextRec& rec, SkArenaAlloc* alloc) const { ContextRec newRec(rec); SkMatrix tmp; if (rec.fLocalMatrix) { tmp.setConcat(*rec.fLocalMatrix, this->getLocalMatrix()); newRec.fLocalMatrix = &tmp; } else { newRec.fLocalMatrix = &this->getLocalMatrix(); } return as_SB(fProxyShader)->makeContext(newRec, alloc); } SkImage* SkLocalMatrixShader::onIsAImage(SkMatrix* outMatrix, enum TileMode* mode) const { SkMatrix imageMatrix; SkImage* image = fProxyShader->isAImage(&imageMatrix, mode); if (image && outMatrix) { // Local matrix must be applied first so it is on the right side of the concat. *outMatrix = SkMatrix::Concat(imageMatrix, this->getLocalMatrix()); } return image; } bool SkLocalMatrixShader::onAppendStages(const StageRec& rec) const { SkMatrix tmp; if (rec.fLocalM) { tmp.setConcat(*rec.fLocalM, this->getLocalMatrix()); } StageRec newRec = rec; newRec.fLocalM = rec.fLocalM ? &tmp : &this->getLocalMatrix(); return as_SB(fProxyShader)->appendStages(newRec); } #ifndef SK_IGNORE_TO_STRING void SkLocalMatrixShader::toString(SkString* str) const { str->append("SkLocalMatrixShader: ("); as_SB(fProxyShader)->toString(str); this->INHERITED::toString(str); str->append(")"); } #endif sk_sp SkShader::makeWithLocalMatrix(const SkMatrix& localMatrix) const { if (localMatrix.isIdentity()) { return sk_ref_sp(const_cast(this)); } const SkMatrix* lm = &localMatrix; sk_sp baseShader; SkMatrix otherLocalMatrix; sk_sp proxy(as_SB(this)->makeAsALocalMatrixShader(&otherLocalMatrix)); if (proxy) { otherLocalMatrix.preConcat(localMatrix); lm = &otherLocalMatrix; baseShader = proxy; } else { baseShader = sk_ref_sp(const_cast(this)); } return sk_make_sp(std::move(baseShader), *lm); }