1/*
2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
5 * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23#include "config.h"
24#include "SVGFilterPrimitiveStandardAttributes.h"
25
26#include "FilterEffect.h"
27#include "RenderSVGResourceFilterPrimitive.h"
28#include "SVGFilterBuilder.h"
29#include <wtf/IsoMallocInlines.h>
30#include <wtf/NeverDestroyed.h>
31
32namespace WebCore {
33
34WTF_MAKE_ISO_ALLOCATED_IMPL(SVGFilterPrimitiveStandardAttributes);
35
36SVGFilterPrimitiveStandardAttributes::SVGFilterPrimitiveStandardAttributes(const QualifiedName& tagName, Document& document)
37 : SVGElement(tagName, document)
38{
39 static std::once_flag onceFlag;
40 std::call_once(onceFlag, [] {
41 PropertyRegistry::registerProperty<SVGNames::xAttr, &SVGFilterPrimitiveStandardAttributes::m_x>();
42 PropertyRegistry::registerProperty<SVGNames::yAttr, &SVGFilterPrimitiveStandardAttributes::m_y>();
43 PropertyRegistry::registerProperty<SVGNames::widthAttr, &SVGFilterPrimitiveStandardAttributes::m_width>();
44 PropertyRegistry::registerProperty<SVGNames::heightAttr, &SVGFilterPrimitiveStandardAttributes::m_height>();
45 PropertyRegistry::registerProperty<SVGNames::resultAttr, &SVGFilterPrimitiveStandardAttributes::m_result>();
46 });
47}
48
49void SVGFilterPrimitiveStandardAttributes::parseAttribute(const QualifiedName& name, const AtomicString& value)
50{
51 SVGParsingError parseError = NoError;
52
53 if (name == SVGNames::xAttr)
54 m_x->setBaseValInternal(SVGLengthValue::construct(LengthModeWidth, value, parseError));
55 else if (name == SVGNames::yAttr)
56 m_y->setBaseValInternal(SVGLengthValue::construct(LengthModeHeight, value, parseError));
57 else if (name == SVGNames::widthAttr)
58 m_width->setBaseValInternal(SVGLengthValue::construct(LengthModeWidth, value, parseError));
59 else if (name == SVGNames::heightAttr)
60 m_height->setBaseValInternal(SVGLengthValue::construct(LengthModeHeight, value, parseError));
61 else if (name == SVGNames::resultAttr)
62 m_result->setBaseValInternal(value);
63
64 reportAttributeParsingError(parseError, name, value);
65
66 SVGElement::parseAttribute(name, value);
67}
68
69bool SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(FilterEffect*, const QualifiedName&)
70{
71 // When all filters support this method, it will be changed to a pure virtual method.
72 ASSERT_NOT_REACHED();
73 return false;
74}
75
76void SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(const QualifiedName& attrName)
77{
78 if (isKnownAttribute(attrName)) {
79 InstanceInvalidationGuard guard(*this);
80 invalidate();
81 return;
82 }
83
84 SVGElement::svgAttributeChanged(attrName);
85}
86
87void SVGFilterPrimitiveStandardAttributes::childrenChanged(const ChildChange& change)
88{
89 SVGElement::childrenChanged(change);
90
91 if (change.source == ChildChangeSource::Parser)
92 return;
93 invalidate();
94}
95
96void SVGFilterPrimitiveStandardAttributes::setStandardAttributes(FilterEffect* filterEffect) const
97{
98 ASSERT(filterEffect);
99 if (!filterEffect)
100 return;
101
102 if (hasAttribute(SVGNames::xAttr))
103 filterEffect->setHasX(true);
104 if (hasAttribute(SVGNames::yAttr))
105 filterEffect->setHasY(true);
106 if (hasAttribute(SVGNames::widthAttr))
107 filterEffect->setHasWidth(true);
108 if (hasAttribute(SVGNames::heightAttr))
109 filterEffect->setHasHeight(true);
110}
111
112RenderPtr<RenderElement> SVGFilterPrimitiveStandardAttributes::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
113{
114 return createRenderer<RenderSVGResourceFilterPrimitive>(*this, WTFMove(style));
115}
116
117bool SVGFilterPrimitiveStandardAttributes::rendererIsNeeded(const RenderStyle& style)
118{
119 if (parentNode() && (parentNode()->hasTagName(SVGNames::filterTag)))
120 return SVGElement::rendererIsNeeded(style);
121
122 return false;
123}
124
125void invalidateFilterPrimitiveParent(SVGElement* element)
126{
127 if (!element)
128 return;
129
130 auto parent = makeRefPtr(element->parentNode());
131
132 if (!parent)
133 return;
134
135 RenderElement* renderer = parent->renderer();
136 if (!renderer || !renderer->isSVGResourceFilterPrimitive())
137 return;
138
139 RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer, false);
140}
141
142}
143