/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "include/core/SkRefCnt.h" #include "include/core/SkString.h" #include "include/core/SkUnPreMultiply.h" #include "include/effects/SkColorMatrix.h" #include "include/private/SkColorData.h" #include "include/private/SkNx.h" #include "src/core/SkColorFilter_Matrix.h" #include "src/core/SkRasterPipeline.h" #include "src/core/SkReadBuffer.h" #include "src/core/SkWriteBuffer.h" void SkColorFilter_Matrix::initState() { const float* srcA = fMatrix + 15; fFlags = (srcA[0] == 0 && srcA[1] == 0 && srcA[2] == 0 && srcA[3] == 1 && srcA[4] == 0) ? kAlphaUnchanged_Flag : 0; } SkColorFilter_Matrix::SkColorFilter_Matrix(const float array[20]) { memcpy(fMatrix, array, 20 * sizeof(float)); this->initState(); } uint32_t SkColorFilter_Matrix::getFlags() const { return this->INHERITED::getFlags() | fFlags; } void SkColorFilter_Matrix::flatten(SkWriteBuffer& buffer) const { SkASSERT(sizeof(fMatrix)/sizeof(float) == 20); buffer.writeScalarArray(fMatrix, 20); } sk_sp SkColorFilter_Matrix::CreateProc(SkReadBuffer& buffer) { float matrix[20]; if (buffer.readScalarArray(matrix, 20)) { return SkColorFilters::Matrix(matrix); } return nullptr; } bool SkColorFilter_Matrix::onAsAColorMatrix(float matrix[20]) const { if (matrix) { memcpy(matrix, fMatrix, 20 * sizeof(float)); } return true; } bool SkColorFilter_Matrix::onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const { const bool willStayOpaque = shaderIsOpaque && (fFlags & kAlphaUnchanged_Flag); SkRasterPipeline* p = rec.fPipeline; if (!shaderIsOpaque) { p->append(SkRasterPipeline::unpremul); } if ( true) { p->append(SkRasterPipeline::matrix_4x5, fMatrix); } if ( true) { p->append(SkRasterPipeline::clamp_0); } if ( true) { p->append(SkRasterPipeline::clamp_1); } if (!willStayOpaque) { p->append(SkRasterPipeline::premul); } return true; } #if SK_SUPPORT_GPU #include "src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h" std::unique_ptr SkColorFilter_Matrix::asFragmentProcessor( GrRecordingContext*, const GrColorSpaceInfo&) const { return GrColorMatrixFragmentProcessor::Make(fMatrix, /* premulInput = */ true, /* clampRGBOutput = */ true, /* premulOutput = */ true); } #endif /////////////////////////////////////////////////////////////////////////////// sk_sp SkColorFilters::Matrix(const float array[20]) { if (!sk_floats_are_finite(array, 20)) { return nullptr; } return sk_sp(new SkColorFilter_Matrix(array)); } sk_sp SkColorFilters::Matrix(const SkColorMatrix& cm) { return Matrix(cm.fMat); } void SkColorFilter_Matrix::RegisterFlattenables() { SK_REGISTER_FLATTENABLE(SkColorFilter_Matrix); // This subclass was removed 4/2019 SkFlattenable::Register("SkColorMatrixFilterRowMajor255", [](SkReadBuffer& buffer) -> sk_sp { float matrix[20]; if (buffer.readScalarArray(matrix, 20)) { matrix[ 4] *= (1.0f/255); matrix[ 9] *= (1.0f/255); matrix[14] *= (1.0f/255); matrix[19] *= (1.0f/255); return SkColorFilters::Matrix(matrix); } return nullptr; }); }