mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibWeb+LibGfx: Implement SVGFEMorphologyElement
This filter primitive is used to erode or dilate an image.
This commit is contained in:
parent
837d5fb7ea
commit
36c6079dbc
Notes:
github-actions[bot]
2025-11-15 15:09:46 +00:00
Author: https://github.com/tcl3
Commit: 36c6079dbc
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6831
17 changed files with 235 additions and 0 deletions
|
|
@ -277,6 +277,18 @@ Filter Filter::merge(Vector<Optional<Filter>> const& inputs)
|
||||||
return Filter(Impl::create(SkImageFilters::Merge(skia_filters.data(), skia_filters.size())));
|
return Filter(Impl::create(SkImageFilters::Merge(skia_filters.data(), skia_filters.size())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Filter Filter::erode(float radius_x, float radius_y, Optional<Filter> const& input)
|
||||||
|
{
|
||||||
|
sk_sp<SkImageFilter> input_skia = input.has_value() ? input->m_impl->filter : nullptr;
|
||||||
|
return Filter(Impl::create(SkImageFilters::Erode(radius_x, radius_y, input_skia)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Filter Filter::dilate(float radius_x, float radius_y, Optional<Filter> const& input)
|
||||||
|
{
|
||||||
|
sk_sp<SkImageFilter> input_skia = input.has_value() ? input->m_impl->filter : nullptr;
|
||||||
|
return Filter(Impl::create(SkImageFilters::Dilate(radius_x, radius_y, input_skia)));
|
||||||
|
}
|
||||||
|
|
||||||
Filter Filter::offset(float dx, float dy, Optional<Filter const&> input)
|
Filter Filter::offset(float dx, float dy, Optional<Filter const&> input)
|
||||||
{
|
{
|
||||||
sk_sp<SkImageFilter> input_skia = input.has_value() ? input->m_impl->filter : nullptr;
|
sk_sp<SkImageFilter> input_skia = input.has_value() ? input->m_impl->filter : nullptr;
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ public:
|
||||||
static Filter image(Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::IntRect const& dest_rect, Gfx::ScalingMode scaling_mode);
|
static Filter image(Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::IntRect const& dest_rect, Gfx::ScalingMode scaling_mode);
|
||||||
static Filter merge(Vector<Optional<Filter>> const&);
|
static Filter merge(Vector<Optional<Filter>> const&);
|
||||||
static Filter offset(float dx, float dy, Optional<Filter const&> input = {});
|
static Filter offset(float dx, float dy, Optional<Filter const&> input = {});
|
||||||
|
static Filter erode(float radius_x, float radius_y, Optional<Filter> const& input = {});
|
||||||
|
static Filter dilate(float radius_x, float radius_y, Optional<Filter> const& input = {});
|
||||||
|
|
||||||
FilterImpl const& impl() const;
|
FilterImpl const& impl() const;
|
||||||
|
|
||||||
|
|
|
||||||
17
Libraries/LibGfx/MorphologyOperator.h
Normal file
17
Libraries/LibGfx/MorphologyOperator.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Gfx {
|
||||||
|
|
||||||
|
enum class MorphologyOperator {
|
||||||
|
Unknown,
|
||||||
|
Erode,
|
||||||
|
Dilate,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -927,6 +927,7 @@ set(SOURCES
|
||||||
SVG/SVGFEImageElement.cpp
|
SVG/SVGFEImageElement.cpp
|
||||||
SVG/SVGFEMergeElement.cpp
|
SVG/SVGFEMergeElement.cpp
|
||||||
SVG/SVGFEMergeNodeElement.cpp
|
SVG/SVGFEMergeNodeElement.cpp
|
||||||
|
SVG/SVGFEMorphologyElement.cpp
|
||||||
SVG/SVGFEOffsetElement.cpp
|
SVG/SVGFEOffsetElement.cpp
|
||||||
SVG/SVGFilterElement.cpp
|
SVG/SVGFilterElement.cpp
|
||||||
SVG/SVGFilterPrimitiveStandardAttributes.cpp
|
SVG/SVGFilterPrimitiveStandardAttributes.cpp
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@
|
||||||
#include <LibWeb/SVG/SVGFEImageElement.h>
|
#include <LibWeb/SVG/SVGFEImageElement.h>
|
||||||
#include <LibWeb/SVG/SVGFEMergeElement.h>
|
#include <LibWeb/SVG/SVGFEMergeElement.h>
|
||||||
#include <LibWeb/SVG/SVGFEMergeNodeElement.h>
|
#include <LibWeb/SVG/SVGFEMergeNodeElement.h>
|
||||||
|
#include <LibWeb/SVG/SVGFEMorphologyElement.h>
|
||||||
#include <LibWeb/SVG/SVGFEOffsetElement.h>
|
#include <LibWeb/SVG/SVGFEOffsetElement.h>
|
||||||
#include <LibWeb/SVG/SVGFilterElement.h>
|
#include <LibWeb/SVG/SVGFilterElement.h>
|
||||||
#include <LibWeb/SVG/SVGForeignObjectElement.h>
|
#include <LibWeb/SVG/SVGForeignObjectElement.h>
|
||||||
|
|
@ -504,6 +505,8 @@ static GC::Ref<SVG::SVGElement> create_svg_element(JS::Realm& realm, Document& d
|
||||||
return realm.create<SVG::SVGFEMergeElement>(document, move(qualified_name));
|
return realm.create<SVG::SVGFEMergeElement>(document, move(qualified_name));
|
||||||
if (local_name == SVG::TagNames::feMergeNode)
|
if (local_name == SVG::TagNames::feMergeNode)
|
||||||
return realm.create<SVG::SVGFEMergeNodeElement>(document, move(qualified_name));
|
return realm.create<SVG::SVGFEMergeNodeElement>(document, move(qualified_name));
|
||||||
|
if (local_name == SVG::TagNames::feMorphology)
|
||||||
|
return realm.create<SVG::SVGFEMorphologyElement>(document, move(qualified_name));
|
||||||
if (local_name == SVG::TagNames::feOffset)
|
if (local_name == SVG::TagNames::feOffset)
|
||||||
return realm.create<SVG::SVGFEOffsetElement>(document, move(qualified_name));
|
return realm.create<SVG::SVGFEOffsetElement>(document, move(qualified_name));
|
||||||
if (local_name == SVG::TagNames::filter)
|
if (local_name == SVG::TagNames::filter)
|
||||||
|
|
|
||||||
|
|
@ -1116,6 +1116,7 @@ class SVGFEFuncGElement;
|
||||||
class SVGFEFuncRElement;
|
class SVGFEFuncRElement;
|
||||||
class SVGFEGaussianBlurElement;
|
class SVGFEGaussianBlurElement;
|
||||||
class SVGFEImageElement;
|
class SVGFEImageElement;
|
||||||
|
class SVGFEMorphologyElement;
|
||||||
class SVGFilterElement;
|
class SVGFilterElement;
|
||||||
class SVGFitToViewBox;
|
class SVGFitToViewBox;
|
||||||
class SVGForeignObjectElement;
|
class SVGForeignObjectElement;
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ namespace Web::SVG::AttributeNames {
|
||||||
__ENUMERATE_SVG_ATTRIBUTE(preserveAspectRatio, "preserveAspectRatio") \
|
__ENUMERATE_SVG_ATTRIBUTE(preserveAspectRatio, "preserveAspectRatio") \
|
||||||
__ENUMERATE_SVG_ATTRIBUTE(primitiveUnits, "primitiveUnits") \
|
__ENUMERATE_SVG_ATTRIBUTE(primitiveUnits, "primitiveUnits") \
|
||||||
__ENUMERATE_SVG_ATTRIBUTE(r, "r") \
|
__ENUMERATE_SVG_ATTRIBUTE(r, "r") \
|
||||||
|
__ENUMERATE_SVG_ATTRIBUTE(radius, "radius") \
|
||||||
__ENUMERATE_SVG_ATTRIBUTE(refX, "refX") \
|
__ENUMERATE_SVG_ATTRIBUTE(refX, "refX") \
|
||||||
__ENUMERATE_SVG_ATTRIBUTE(refY, "refY") \
|
__ENUMERATE_SVG_ATTRIBUTE(refY, "refY") \
|
||||||
__ENUMERATE_SVG_ATTRIBUTE(repeatCount, "repeatCount") \
|
__ENUMERATE_SVG_ATTRIBUTE(repeatCount, "repeatCount") \
|
||||||
|
|
|
||||||
85
Libraries/LibWeb/SVG/SVGFEMorphologyElement.cpp
Normal file
85
Libraries/LibWeb/SVG/SVGFEMorphologyElement.cpp
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibWeb/Bindings/SVGFEMorphologyElementPrototype.h>
|
||||||
|
#include <LibWeb/SVG/AttributeNames.h>
|
||||||
|
#include <LibWeb/SVG/SVGFEMorphologyElement.h>
|
||||||
|
|
||||||
|
namespace Web::SVG {
|
||||||
|
|
||||||
|
GC_DEFINE_ALLOCATOR(SVGFEMorphologyElement);
|
||||||
|
|
||||||
|
SVGFEMorphologyElement::SVGFEMorphologyElement(DOM::Document& document, DOM::QualifiedName qualified_name)
|
||||||
|
: SVGElement(document, qualified_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SVGFEMorphologyElement::initialize(JS::Realm& realm)
|
||||||
|
{
|
||||||
|
WEB_SET_PROTOTYPE_FOR_INTERFACE(SVGFEMorphologyElement);
|
||||||
|
Base::initialize(realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SVGFEMorphologyElement::visit_edges(Cell::Visitor& visitor)
|
||||||
|
{
|
||||||
|
Base::visit_edges(visitor);
|
||||||
|
SVGFilterPrimitiveStandardAttributes::visit_edges(visitor);
|
||||||
|
visitor.visit(m_in1);
|
||||||
|
visitor.visit(m_radius_x);
|
||||||
|
visitor.visit(m_radius_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SVGFEMorphologyElement::attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& new_value, Optional<FlyString> const& namespace_)
|
||||||
|
{
|
||||||
|
Base::attribute_changed(name, old_value, new_value, namespace_);
|
||||||
|
|
||||||
|
if (name == SVG::AttributeNames::operator_) {
|
||||||
|
if (!new_value.has_value()) {
|
||||||
|
m_morphology_operator = Gfx::MorphologyOperator::Dilate;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (new_value->equals_ignoring_ascii_case("erode"sv)) {
|
||||||
|
m_morphology_operator = Gfx::MorphologyOperator::Erode;
|
||||||
|
} else if (new_value->equals_ignoring_ascii_case("dilate"sv)) {
|
||||||
|
m_morphology_operator = Gfx::MorphologyOperator::Dilate;
|
||||||
|
} else {
|
||||||
|
m_morphology_operator = Gfx::MorphologyOperator::Dilate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GC::Ref<SVGAnimatedString> SVGFEMorphologyElement::in1()
|
||||||
|
{
|
||||||
|
if (!m_in1)
|
||||||
|
m_in1 = SVGAnimatedString::create(realm(), *this, DOM::QualifiedName { AttributeNames::in, OptionalNone {}, OptionalNone {} });
|
||||||
|
|
||||||
|
return *m_in1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GC::Ref<SVGAnimatedEnumeration> SVGFEMorphologyElement::operator_for_bindings()
|
||||||
|
{
|
||||||
|
return SVGAnimatedEnumeration::create(realm(), to_underlying(m_morphology_operator));
|
||||||
|
}
|
||||||
|
|
||||||
|
GC::Ref<SVGAnimatedNumber> SVGFEMorphologyElement::radius_x()
|
||||||
|
{
|
||||||
|
if (!m_radius_x)
|
||||||
|
m_radius_x = SVGAnimatedNumber::create(realm(), *this, DOM::QualifiedName { SVG::AttributeNames::radius, OptionalNone {}, OptionalNone {} }, 0.0,
|
||||||
|
SVGAnimatedNumber::SupportsSecondValue::Yes, SVGAnimatedNumber::ValueRepresented::First);
|
||||||
|
|
||||||
|
return *m_radius_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
GC::Ref<SVGAnimatedNumber> SVGFEMorphologyElement::radius_y()
|
||||||
|
{
|
||||||
|
if (!m_radius_y)
|
||||||
|
m_radius_y = SVGAnimatedNumber::create(realm(), *this, DOM::QualifiedName { SVG::AttributeNames::radius, OptionalNone {}, OptionalNone {} }, 0.0,
|
||||||
|
SVGAnimatedNumber::SupportsSecondValue::Yes, SVGAnimatedNumber::ValueRepresented::Second);
|
||||||
|
|
||||||
|
return *m_radius_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
50
Libraries/LibWeb/SVG/SVGFEMorphologyElement.h
Normal file
50
Libraries/LibWeb/SVG/SVGFEMorphologyElement.h
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibGfx/MorphologyOperator.h>
|
||||||
|
#include <LibWeb/SVG/SVGAnimatedEnumeration.h>
|
||||||
|
#include <LibWeb/SVG/SVGAnimatedNumber.h>
|
||||||
|
#include <LibWeb/SVG/SVGAnimatedString.h>
|
||||||
|
#include <LibWeb/SVG/SVGElement.h>
|
||||||
|
#include <LibWeb/SVG/SVGFilterPrimitiveStandardAttributes.h>
|
||||||
|
|
||||||
|
namespace Web::SVG {
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/filter-effects-1/#svgfemorphologyelement
|
||||||
|
class SVGFEMorphologyElement final
|
||||||
|
: public SVGElement
|
||||||
|
, public SVGFilterPrimitiveStandardAttributes<SVGFEMorphologyElement> {
|
||||||
|
WEB_PLATFORM_OBJECT(SVGFEMorphologyElement, SVGElement);
|
||||||
|
GC_DECLARE_ALLOCATOR(SVGFEMorphologyElement);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~SVGFEMorphologyElement() override = default;
|
||||||
|
|
||||||
|
GC::Ref<SVGAnimatedString> in1();
|
||||||
|
|
||||||
|
GC::Ref<SVGAnimatedEnumeration> operator_for_bindings();
|
||||||
|
Gfx::MorphologyOperator morphology_operator() { return m_morphology_operator; }
|
||||||
|
|
||||||
|
GC::Ref<SVGAnimatedNumber> radius_x();
|
||||||
|
GC::Ref<SVGAnimatedNumber> radius_y();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SVGFEMorphologyElement(DOM::Document&, DOM::QualifiedName);
|
||||||
|
|
||||||
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
|
||||||
|
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& new_value, Optional<FlyString> const& namespace_) override;
|
||||||
|
|
||||||
|
GC::Ptr<SVGAnimatedString> m_in1;
|
||||||
|
Gfx::MorphologyOperator m_morphology_operator { Gfx::MorphologyOperator::Erode };
|
||||||
|
GC::Ptr<SVGAnimatedNumber> m_radius_x;
|
||||||
|
GC::Ptr<SVGAnimatedNumber> m_radius_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
22
Libraries/LibWeb/SVG/SVGFEMorphologyElement.idl
Normal file
22
Libraries/LibWeb/SVG/SVGFEMorphologyElement.idl
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#import <SVG/SVGAnimatedEnumeration.idl>
|
||||||
|
#import <SVG/SVGAnimatedNumber.idl>
|
||||||
|
#import <SVG/SVGAnimatedString.idl>
|
||||||
|
#import <SVG/SVGElement.idl>
|
||||||
|
#import <SVG/SVGFilterPrimitiveStandardAttributes.idl>
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
|
||||||
|
[Exposed=Window]
|
||||||
|
interface SVGFEMorphologyElement : SVGElement {
|
||||||
|
|
||||||
|
// Morphology Operators
|
||||||
|
const unsigned short SVG_MORPHOLOGY_OPERATOR_UNKNOWN = 0;
|
||||||
|
const unsigned short SVG_MORPHOLOGY_OPERATOR_ERODE = 1;
|
||||||
|
const unsigned short SVG_MORPHOLOGY_OPERATOR_DILATE = 2;
|
||||||
|
|
||||||
|
readonly attribute SVGAnimatedString in1;
|
||||||
|
[ImplementedAs=operator_for_bindings] readonly attribute SVGAnimatedEnumeration operator;
|
||||||
|
readonly attribute SVGAnimatedNumber radiusX;
|
||||||
|
readonly attribute SVGAnimatedNumber radiusY;
|
||||||
|
};
|
||||||
|
|
||||||
|
SVGFEMorphologyElement includes SVGFilterPrimitiveStandardAttributes;
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include <LibWeb/SVG/SVGFEImageElement.h>
|
#include <LibWeb/SVG/SVGFEImageElement.h>
|
||||||
#include <LibWeb/SVG/SVGFEMergeElement.h>
|
#include <LibWeb/SVG/SVGFEMergeElement.h>
|
||||||
#include <LibWeb/SVG/SVGFEMergeNodeElement.h>
|
#include <LibWeb/SVG/SVGFEMergeNodeElement.h>
|
||||||
|
#include <LibWeb/SVG/SVGFEMorphologyElement.h>
|
||||||
#include <LibWeb/SVG/SVGFEOffsetElement.h>
|
#include <LibWeb/SVG/SVGFEOffsetElement.h>
|
||||||
#include <LibWeb/SVG/SVGFilterElement.h>
|
#include <LibWeb/SVG/SVGFilterElement.h>
|
||||||
|
|
||||||
|
|
@ -284,6 +285,24 @@ Optional<Gfx::Filter> SVGFilterElement::gfx_filter(Layout::NodeWithStyle const&
|
||||||
|
|
||||||
root_filter = Gfx::Filter::merge(merge_inputs);
|
root_filter = Gfx::Filter::merge(merge_inputs);
|
||||||
update_result_map(*merge_primitive);
|
update_result_map(*merge_primitive);
|
||||||
|
} else if (auto* morphology_primitive = as_if<SVGFEMorphologyElement>(node)) {
|
||||||
|
auto input = resolve_input_filter(morphology_primitive->in1()->base_val());
|
||||||
|
|
||||||
|
auto radius_x = morphology_primitive->radius_x()->base_val();
|
||||||
|
auto radius_y = morphology_primitive->radius_y()->base_val();
|
||||||
|
auto morphology_operator = morphology_primitive->morphology_operator();
|
||||||
|
switch (morphology_operator) {
|
||||||
|
case Gfx::MorphologyOperator::Erode:
|
||||||
|
root_filter = Gfx::Filter::erode(radius_x, radius_y, input);
|
||||||
|
break;
|
||||||
|
case Gfx::MorphologyOperator::Dilate:
|
||||||
|
root_filter = Gfx::Filter::dilate(radius_x, radius_y, input);
|
||||||
|
break;
|
||||||
|
case Gfx::MorphologyOperator::Unknown:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
update_result_map(*morphology_primitive);
|
||||||
} else if (auto* offset_primitive = as_if<SVGFEOffsetElement>(node)) {
|
} else if (auto* offset_primitive = as_if<SVGFEOffsetElement>(node)) {
|
||||||
auto input = resolve_input_filter(offset_primitive->in1()->base_val());
|
auto input = resolve_input_filter(offset_primitive->in1()->base_val());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include <LibWeb/SVG/SVGFEGaussianBlurElement.h>
|
#include <LibWeb/SVG/SVGFEGaussianBlurElement.h>
|
||||||
#include <LibWeb/SVG/SVGFEImageElement.h>
|
#include <LibWeb/SVG/SVGFEImageElement.h>
|
||||||
#include <LibWeb/SVG/SVGFEMergeElement.h>
|
#include <LibWeb/SVG/SVGFEMergeElement.h>
|
||||||
|
#include <LibWeb/SVG/SVGFEMorphologyElement.h>
|
||||||
#include <LibWeb/SVG/SVGFEOffsetElement.h>
|
#include <LibWeb/SVG/SVGFEOffsetElement.h>
|
||||||
|
|
||||||
namespace Web::SVG {
|
namespace Web::SVG {
|
||||||
|
|
@ -60,6 +61,7 @@ template class SVGFilterPrimitiveStandardAttributes<SVGFEFloodElement>;
|
||||||
template class SVGFilterPrimitiveStandardAttributes<SVGFEGaussianBlurElement>;
|
template class SVGFilterPrimitiveStandardAttributes<SVGFEGaussianBlurElement>;
|
||||||
template class SVGFilterPrimitiveStandardAttributes<SVGFEImageElement>;
|
template class SVGFilterPrimitiveStandardAttributes<SVGFEImageElement>;
|
||||||
template class SVGFilterPrimitiveStandardAttributes<SVGFEMergeElement>;
|
template class SVGFilterPrimitiveStandardAttributes<SVGFEMergeElement>;
|
||||||
|
template class SVGFilterPrimitiveStandardAttributes<SVGFEMorphologyElement>;
|
||||||
template class SVGFilterPrimitiveStandardAttributes<SVGFEOffsetElement>;
|
template class SVGFilterPrimitiveStandardAttributes<SVGFEOffsetElement>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ namespace Web::SVG::TagNames {
|
||||||
__ENUMERATE_SVG_TAG(feImage) \
|
__ENUMERATE_SVG_TAG(feImage) \
|
||||||
__ENUMERATE_SVG_TAG(feMerge) \
|
__ENUMERATE_SVG_TAG(feMerge) \
|
||||||
__ENUMERATE_SVG_TAG(feMergeNode) \
|
__ENUMERATE_SVG_TAG(feMergeNode) \
|
||||||
|
__ENUMERATE_SVG_TAG(feMorphology) \
|
||||||
__ENUMERATE_SVG_TAG(feOffset) \
|
__ENUMERATE_SVG_TAG(feOffset) \
|
||||||
__ENUMERATE_SVG_TAG(filter) \
|
__ENUMERATE_SVG_TAG(filter) \
|
||||||
__ENUMERATE_SVG_TAG(foreignObject) \
|
__ENUMERATE_SVG_TAG(foreignObject) \
|
||||||
|
|
|
||||||
|
|
@ -402,6 +402,7 @@ libweb_js_bindings(SVG/SVGFEGaussianBlurElement)
|
||||||
libweb_js_bindings(SVG/SVGFEImageElement)
|
libweb_js_bindings(SVG/SVGFEImageElement)
|
||||||
libweb_js_bindings(SVG/SVGFEMergeElement)
|
libweb_js_bindings(SVG/SVGFEMergeElement)
|
||||||
libweb_js_bindings(SVG/SVGFEMergeNodeElement)
|
libweb_js_bindings(SVG/SVGFEMergeNodeElement)
|
||||||
|
libweb_js_bindings(SVG/SVGFEMorphologyElement)
|
||||||
libweb_js_bindings(SVG/SVGFEOffsetElement)
|
libweb_js_bindings(SVG/SVGFEOffsetElement)
|
||||||
libweb_js_bindings(SVG/SVGFilterElement)
|
libweb_js_bindings(SVG/SVGFilterElement)
|
||||||
libweb_js_bindings(SVG/SVGForeignObjectElement)
|
libweb_js_bindings(SVG/SVGForeignObjectElement)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<div style="width: 100px; height: 100px; background-color: green"></div>
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>feMorphology filter on mirrored content</title>
|
||||||
|
<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#feMorphologyElement">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/filter-effects/reference/green-100x100.html">
|
||||||
|
<svg>
|
||||||
|
<filter id="dilate" filterUnits="userSpaceOnUse"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feMorphology operator="dilate" radius="10"/>
|
||||||
|
</filter>
|
||||||
|
<rect width="100" height="100" fill="red"/>
|
||||||
|
<rect x="10" y="10" width="80" height="30" fill="green" filter="url(#dilate)"
|
||||||
|
transform="translate(0, 50) scale(1, -1)"/>
|
||||||
|
<rect x="10" y="60" width="80" height="30" fill="green" filter="url(#dilate)"
|
||||||
|
transform="translate(100, 0) scale(-1, 1)"/>
|
||||||
|
</svg>
|
||||||
|
|
@ -390,6 +390,7 @@ SVGFEGaussianBlurElement
|
||||||
SVGFEImageElement
|
SVGFEImageElement
|
||||||
SVGFEMergeElement
|
SVGFEMergeElement
|
||||||
SVGFEMergeNodeElement
|
SVGFEMergeNodeElement
|
||||||
|
SVGFEMorphologyElement
|
||||||
SVGFEOffsetElement
|
SVGFEOffsetElement
|
||||||
SVGFilterElement
|
SVGFilterElement
|
||||||
SVGForeignObjectElement
|
SVGForeignObjectElement
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue