/* * Copyright 2013 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkColorFilterShader.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" #include "SkShader.h" #include "SkString.h" #if SK_SUPPORT_GPU #include "GrFragmentProcessor.h" #endif SkColorFilterShader::SkColorFilterShader(sk_sp shader, sk_sp filter) : fShader(std::move(shader)) , fFilter(std::move(filter)) { SkASSERT(fShader); SkASSERT(fFilter); } sk_sp SkColorFilterShader::CreateProc(SkReadBuffer& buffer) { auto shader = buffer.readShader(); auto filter = buffer.readColorFilter(); if (!shader || !filter) { return nullptr; } return sk_make_sp(shader, filter); } void SkColorFilterShader::flatten(SkWriteBuffer& buffer) const { buffer.writeFlattenable(fShader.get()); buffer.writeFlattenable(fFilter.get()); } uint32_t SkColorFilterShader::FilterShaderContext::getFlags() const { const SkColorFilterShader& filterShader = static_cast(fShader); uint32_t shaderF = fShaderContext->getFlags(); uint32_t filterF = filterShader.fFilter->getFlags(); // If the filter does not support a given feature, but sure to clear the corresponding flag // in the shader flags. // if (!(filterF & SkColorFilter::kAlphaUnchanged_Flag)) { shaderF &= ~SkShader::kOpaqueAlpha_Flag; } return shaderF; } SkShader::Context* SkColorFilterShader::onCreateContext(const ContextRec& rec, void* storage) const { char* shaderContextStorage = (char*)storage + sizeof(FilterShaderContext); SkShader::Context* shaderContext = fShader->createContext(rec, shaderContextStorage); if (nullptr == shaderContext) { return nullptr; } return new (storage) FilterShaderContext(*this, shaderContext, rec); } size_t SkColorFilterShader::onContextSize(const ContextRec& rec) const { return sizeof(FilterShaderContext) + fShader->contextSize(rec); } SkColorFilterShader::FilterShaderContext::FilterShaderContext( const SkColorFilterShader& filterShader, SkShader::Context* shaderContext, const ContextRec& rec) : INHERITED(filterShader, rec) , fShaderContext(shaderContext) {} SkColorFilterShader::FilterShaderContext::~FilterShaderContext() { fShaderContext->~Context(); } void SkColorFilterShader::FilterShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) { const SkColorFilterShader& filterShader = static_cast(fShader); fShaderContext->shadeSpan(x, y, result, count); filterShader.fFilter->filterSpan(result, count, result); } void SkColorFilterShader::FilterShaderContext::shadeSpan4f(int x, int y, SkPM4f result[], int count) { const SkColorFilterShader& filterShader = static_cast(fShader); fShaderContext->shadeSpan4f(x, y, result, count); filterShader.fFilter->filterSpan4f(result, count, result); } #if SK_SUPPORT_GPU ///////////////////////////////////////////////////////////////////// sk_sp SkColorFilterShader::asFragmentProcessor(const AsFPArgs& args) const { sk_sp fp1(fShader->asFragmentProcessor(args)); if (!fp1) { return nullptr; } sk_sp fp2(fFilter->asFragmentProcessor(args.fContext, args.fDstColorSpace)); if (!fp2) { return fp1; } sk_sp fpSeries[] = { std::move(fp1), std::move(fp2) }; return GrFragmentProcessor::RunInSeries(fpSeries, 2); } #endif #ifndef SK_IGNORE_TO_STRING void SkColorFilterShader::toString(SkString* str) const { str->append("SkColorFilterShader: ("); str->append("Shader: "); fShader->toString(str); str->append(" Filter: "); // TODO: add "fFilter->toString(str);" once SkColorFilter::toString is added this->INHERITED::toString(str); str->append(")"); } #endif /////////////////////////////////////////////////////////////////////////////////////////////////// sk_sp SkShader::makeWithColorFilter(sk_sp filter) const { SkShader* base = const_cast(this); if (!filter) { return sk_ref_sp(base); } return sk_make_sp(sk_ref_sp(base), filter); }