[svg] Add feTurbulence filter (incomplete)
This was the simplest one to start with. I need to add support for the
"filter effect subregion" in order to handle tile stitching property,
so this isn't quite complete. But I believe this is enough for the
basic filters-turb-01-f test to pass, which gives us a baseline for
further filter work.
Summary of changes:
- Added attribute type and parsing for SVG integer datatype
- Added new node class for feTurbulence
- Added several new properties and parsing for feTurbulence
Bug: skia:10841
Change-Id: I8c877a5e1a837bfd527782253062eeb58febdde6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/330621
Commit-Queue: Tyler Denniston <tdenniston@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/modules/svg/src/SkSVGFeTurbulence.cpp b/modules/svg/src/SkSVGFeTurbulence.cpp
new file mode 100644
index 0000000..3adb554
--- /dev/null
+++ b/modules/svg/src/SkSVGFeTurbulence.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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/effects/SkImageFilters.h"
+#include "include/effects/SkPerlinNoiseShader.h"
+#include "modules/svg/include/SkSVGFeTurbulence.h"
+#include "modules/svg/include/SkSVGFilterContext.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
+
+void SkSVGFeTurbulence::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
+ switch (attr) {
+ case SkSVGAttribute::kFeTurbulenceBaseFrequency:
+ if (const auto* f = v.as<SkSVGFeTurbulenceBaseFrequencyValue>()) {
+ this->setBaseFrequency(*f);
+ }
+ break;
+ case SkSVGAttribute::kFeTurbulenceNumOctaves:
+ if (const auto* n = v.as<SkSVGIntegerValue>()) {
+ this->setNumOctaves(*n);
+ }
+ break;
+ case SkSVGAttribute::kFeTurbulenceSeed:
+ if (const auto* s = v.as<SkSVGNumberValue>()) {
+ this->setSeed(*s);
+ }
+ break;
+ case SkSVGAttribute::kFeTurbulenceType:
+ if (const auto* t = v.as<SkSVGFeTurbulenceTypeValue>()) {
+ this->setTurbulenceType(*t);
+ }
+ break;
+ default:
+ this->INHERITED::onSetAttribute(attr, v);
+ }
+}
+
+sk_sp<SkImageFilter> SkSVGFeTurbulence::onMakeImageFilter(const SkSVGRenderContext& ctx,
+ const SkSVGFilterContext& fctx) const {
+ const SkISize* tileSize = nullptr; // TODO: needs filter element subregion properties
+
+ sk_sp<SkShader> shader;
+ switch (fTurbulenceType.fType) {
+ case SkSVGFeTurbulenceType::Type::kTurbulence:
+ shader = SkPerlinNoiseShader::MakeTurbulence(
+ fBaseFrequency.freqX(), fBaseFrequency.freqY(), fNumOctaves, fSeed, tileSize);
+ break;
+ case SkSVGFeTurbulenceType::Type::kFractalNoise:
+ shader = SkPerlinNoiseShader::MakeFractalNoise(
+ fBaseFrequency.freqX(), fBaseFrequency.freqY(), fNumOctaves, fSeed, tileSize);
+ break;
+ }
+
+ return SkImageFilters::Shader(shader, fctx.filterEffectsRegion());
+}