blob: c5e06799efc419a685cc2cb28c7946863b49d8c7 [file] [log] [blame]
/*
* 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<SkFlattenable> 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<GrFragmentProcessor> SkColorFilter_Matrix::asFragmentProcessor(
GrRecordingContext*, const GrColorSpaceInfo&) const {
return GrColorMatrixFragmentProcessor::Make(fMatrix,
/* premulInput = */ true,
/* clampRGBOutput = */ true,
/* premulOutput = */ true);
}
#endif
///////////////////////////////////////////////////////////////////////////////
sk_sp<SkColorFilter> SkColorFilters::Matrix(const float array[20]) {
if (!sk_floats_are_finite(array, 20)) {
return nullptr;
}
return sk_sp<SkColorFilter>(new SkColorFilter_Matrix(array));
}
sk_sp<SkColorFilter> 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<SkFlattenable> {
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;
});
}