1/*
2 * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB.  If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include "config.h"
22
23#if ENABLE(SVG)
24#include "SVGGElement.h"
25
26#include "RenderSVGHiddenContainer.h"
27#include "RenderSVGResource.h"
28#include "RenderSVGTransformableContainer.h"
29#include "SVGElementInstance.h"
30#include "SVGNames.h"
31
32namespace WebCore {
33
34// Animated property definitions
35DEFINE_ANIMATED_BOOLEAN(SVGGElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
36
37BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGGElement)
38    REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
39    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGStyledTransformableElement)
40    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTests)
41END_REGISTER_ANIMATED_PROPERTIES
42
43SVGGElement::SVGGElement(const QualifiedName& tagName, Document* document, ConstructionType constructionType)
44    : SVGStyledTransformableElement(tagName, document, constructionType)
45{
46    ASSERT(hasTagName(SVGNames::gTag));
47    registerAnimatedPropertiesForSVGGElement();
48}
49
50PassRefPtr<SVGGElement> SVGGElement::create(const QualifiedName& tagName, Document* document)
51{
52    return adoptRef(new SVGGElement(tagName, document));
53}
54
55bool SVGGElement::isSupportedAttribute(const QualifiedName& attrName)
56{
57    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
58    if (supportedAttributes.isEmpty()) {
59        SVGTests::addSupportedAttributes(supportedAttributes);
60        SVGLangSpace::addSupportedAttributes(supportedAttributes);
61        SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
62    }
63    return supportedAttributes.contains<QualifiedName, SVGAttributeHashTranslator>(attrName);
64}
65
66void SVGGElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
67{
68    if (!isSupportedAttribute(name)) {
69        SVGStyledTransformableElement::parseAttribute(name, value);
70        return;
71    }
72
73    if (SVGTests::parseAttribute(name, value))
74        return;
75    if (SVGLangSpace::parseAttribute(name, value))
76        return;
77    if (SVGExternalResourcesRequired::parseAttribute(name, value))
78        return;
79
80    ASSERT_NOT_REACHED();
81}
82
83void SVGGElement::svgAttributeChanged(const QualifiedName& attrName)
84{
85    if (!isSupportedAttribute(attrName)) {
86        SVGStyledTransformableElement::svgAttributeChanged(attrName);
87        return;
88    }
89
90    SVGElementInstance::InvalidationGuard invalidationGuard(this);
91
92    if (SVGTests::handleAttributeChange(this, attrName))
93        return;
94
95    if (RenderObject* renderer = this->renderer())
96        RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
97}
98
99RenderObject* SVGGElement::createRenderer(RenderArena* arena, RenderStyle* style)
100{
101    // SVG 1.1 testsuite explicitely uses constructs like <g display="none"><linearGradient>
102    // We still have to create renderers for the <g> & <linearGradient> element, though the
103    // subtree may be hidden - we only want the resource renderers to exist so they can be
104    // referenced from somewhere else.
105    if (style->display() == NONE)
106        return new (arena) RenderSVGHiddenContainer(this);
107
108    return new (arena) RenderSVGTransformableContainer(this);
109}
110
111bool SVGGElement::rendererIsNeeded(const NodeRenderingContext&)
112{
113    // Unlike SVGStyledElement::rendererIsNeeded(), we still create renderers, even if
114    // display is set to 'none' - which is special to SVG <g> container elements.
115    return parentOrShadowHostElement() && parentOrShadowHostElement()->isSVGElement();
116}
117
118}
119
120#endif // ENABLE(SVG)
121