blob: 0221a57e027d1d12a57f6e429a48c49209d6bd31 [file] [log] [blame]
/*
* Copyright 2020 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/SkColorFilter.h"
#include "include/effects/SkImageFilters.h"
#include "include/private/SkColorData.h"
#include "modules/svg/include/SkSVGAttributeParser.h"
#include "modules/svg/include/SkSVGFeColorMatrix.h"
#include "modules/svg/include/SkSVGFilterContext.h"
#include "modules/svg/include/SkSVGRenderContext.h"
#include "modules/svg/include/SkSVGValue.h"
bool SkSVGFeColorMatrix::parseAndSetAttribute(const char* name, const char* value) {
return INHERITED::parseAndSetAttribute(name, value) ||
this->setType(
SkSVGAttributeParser::parse<SkSVGFeColorMatrixType>("type", name, value)) ||
this->setValues(
SkSVGAttributeParser::parse<SkSVGFeColorMatrixValues>("values", name, value));
}
SkColorMatrix SkSVGFeColorMatrix::makeMatrixForType() const {
if (fValues.empty() && fType != SkSVGFeColorMatrixType::kLuminanceToAlpha) {
return SkColorMatrix();
}
switch (fType) {
case SkSVGFeColorMatrixType::kMatrix: {
if (fValues.size() < 20) {
return SkColorMatrix();
}
SkColorMatrix m;
m.setRowMajor(this->fValues.begin());
return m;
}
case SkSVGFeColorMatrixType::kSaturate:
return MakeSaturate(!fValues.empty() ? fValues[0] : 1);
case SkSVGFeColorMatrixType::kHueRotate:
return MakeHueRotate(!fValues.empty() ? fValues[0] : 0);
case SkSVGFeColorMatrixType::kLuminanceToAlpha:
return MakeLuminanceToAlpha();
}
SkUNREACHABLE;
}
SkColorMatrix SkSVGFeColorMatrix::MakeSaturate(SkSVGNumberType s) {
SkColorMatrix m;
m.setSaturation(s);
return m;
}
SkColorMatrix SkSVGFeColorMatrix::MakeHueRotate(SkSVGNumberType degrees) {
const SkScalar theta = SkDegreesToRadians(degrees);
const SkSVGNumberType c = SkScalarCos(theta);
const SkSVGNumberType s = SkScalarSin(theta);
return SkColorMatrix(
0.213f + c* 0.787f + s*-0.213f,
0.715f + c*-0.715f + s*-0.715f,
0.072f + c*-0.072f + s* 0.928f,
0,
0,
0.213f + c*-0.213f + s* 0.143f,
0.715f + c* 0.285f + s* 0.140f,
0.072f + c*-0.072f + s*-0.283f,
0,
0,
0.213f + c*-0.213f + s*-0.787f,
0.715f + c*-0.715f + s* 0.715f,
0.072f + c* 0.928f + s* 0.072f,
0,
0,
0,0,0,1,0
);
}
SkColorMatrix SkSVGFeColorMatrix::MakeLuminanceToAlpha() {
return SkColorMatrix(
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B, 0, 0
);
}
sk_sp<SkImageFilter> SkSVGFeColorMatrix::onMakeImageFilter(const SkSVGRenderContext& ctx,
const SkSVGFilterContext& fctx) const {
return SkImageFilters::ColorFilter(
SkColorFilters::Matrix(makeMatrixForType()),
fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)),
this->resolveFilterSubregion(ctx, fctx));
}
template <> bool SkSVGAttributeParser::parse(SkSVGFeColorMatrixValues* values) {
SkSVGNumberType value;
if (!this->parse(&value)) {
return false;
}
values->push_back(value);
while (true) {
if (!this->parse(&value) || values->size() >= 20) {
break;
}
values->push_back(value);
}
return this->parseEOSToken();
}
template <> bool SkSVGAttributeParser::parse(SkSVGFeColorMatrixType* type) {
static constexpr std::tuple<const char*, SkSVGFeColorMatrixType> gTypeMap[] = {
{"matrix", SkSVGFeColorMatrixType::kMatrix},
{"saturate", SkSVGFeColorMatrixType::kSaturate},
{"hueRotate", SkSVGFeColorMatrixType::kHueRotate},
{"luminanceToAlpha", SkSVGFeColorMatrixType::kLuminanceToAlpha},
};
return this->parseEnumMap(gTypeMap, type) && this->parseEOSToken();
}