ef1cae155d910b642c792cdbd81dd4e6d0691e66
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / svg / SVGForeignObjectElement.cpp
1 /*
2  * Copyright (C) 2006 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@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 #include "core/svg/SVGForeignObjectElement.h"
23
24 #include "core/XLinkNames.h"
25 #include "core/frame/UseCounter.h"
26 #include "core/rendering/svg/RenderSVGForeignObject.h"
27 #include "core/svg/SVGLength.h"
28 #include "wtf/Assertions.h"
29
30 namespace blink {
31
32 inline SVGForeignObjectElement::SVGForeignObjectElement(Document& document)
33     : SVGGraphicsElement(SVGNames::foreignObjectTag, document)
34     , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
35     , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
36     , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth), ForbidNegativeLengths))
37     , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight), ForbidNegativeLengths))
38 {
39     addToPropertyMap(m_x);
40     addToPropertyMap(m_y);
41     addToPropertyMap(m_width);
42     addToPropertyMap(m_height);
43
44     UseCounter::count(document, UseCounter::SVGForeignObjectElement);
45 }
46
47 DEFINE_NODE_FACTORY(SVGForeignObjectElement)
48
49 bool SVGForeignObjectElement::isSupportedAttribute(const QualifiedName& attrName)
50 {
51     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
52     if (supportedAttributes.isEmpty()) {
53         supportedAttributes.add(SVGNames::xAttr);
54         supportedAttributes.add(SVGNames::yAttr);
55         supportedAttributes.add(SVGNames::widthAttr);
56         supportedAttributes.add(SVGNames::heightAttr);
57     }
58     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
59 }
60
61 void SVGForeignObjectElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
62 {
63     parseAttributeNew(name, value);
64 }
65
66 bool SVGForeignObjectElement::isPresentationAttribute(const QualifiedName& name) const
67 {
68     if (name == SVGNames::widthAttr || name == SVGNames::heightAttr)
69         return true;
70     return SVGGraphicsElement::isPresentationAttribute(name);
71 }
72
73 void SVGForeignObjectElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
74 {
75     if (name == SVGNames::widthAttr || name == SVGNames::heightAttr) {
76         RefPtr<SVGLength> length = SVGLength::create(LengthModeOther);
77         TrackExceptionState exceptionState;
78         length->setValueAsString(value, exceptionState);
79         if (!exceptionState.hadException()) {
80             if (name == SVGNames::widthAttr)
81                 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, value);
82             else if (name == SVGNames::heightAttr)
83                 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight, value);
84         }
85     } else {
86         SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, style);
87     }
88 }
89
90 void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName)
91 {
92     if (!isSupportedAttribute(attrName)) {
93         SVGGraphicsElement::svgAttributeChanged(attrName);
94         return;
95     }
96
97     if (attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) {
98         invalidateSVGPresentationAttributeStyle();
99         setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::SVGContainerSizeChange));
100     }
101
102     SVGElement::InvalidationGuard invalidationGuard(this);
103
104     bool isLengthAttribute = attrName == SVGNames::xAttr
105                           || attrName == SVGNames::yAttr
106                           || attrName == SVGNames::widthAttr
107                           || attrName == SVGNames::heightAttr;
108
109     if (isLengthAttribute) {
110         updateRelativeLengthsInformation();
111         if (RenderObject* renderer = this->renderer())
112             markForLayoutAndParentResourceInvalidation(renderer);
113     }
114 }
115
116 RenderObject* SVGForeignObjectElement::createRenderer(RenderStyle*)
117 {
118     return new RenderSVGForeignObject(this);
119 }
120
121 bool SVGForeignObjectElement::rendererIsNeeded(const RenderStyle& style)
122 {
123     // Suppress foreignObject renderers in SVG hidden containers.
124     // (https://bugs.webkit.org/show_bug.cgi?id=87297)
125     // Note that we currently do not support foreignObject instantiation via <use>, hence it is safe
126     // to use parentElement() here. If that changes, this method should be updated to use
127     // parentOrShadowHostElement() instead.
128     Element* ancestor = parentElement();
129     while (ancestor && ancestor->isSVGElement()) {
130         if (ancestor->renderer() && ancestor->renderer()->isSVGHiddenContainer())
131             return false;
132
133         ancestor = ancestor->parentElement();
134     }
135
136     return SVGGraphicsElement::rendererIsNeeded(style);
137 }
138
139 bool SVGForeignObjectElement::selfHasRelativeLengths() const
140 {
141     return m_x->currentValue()->isRelative()
142         || m_y->currentValue()->isRelative()
143         || m_width->currentValue()->isRelative()
144         || m_height->currentValue()->isRelative();
145 }
146
147 } // namespace blink