Add WTF::move()
[WebKit-https.git] / Source / WebCore / rendering / svg / RenderSVGViewportContainer.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@kde.org>
4  * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
5  * Copyright (C) 2009 Google, Inc.
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 "RenderSVGViewportContainer.h"
25
26 #include "GraphicsContext.h"
27 #include "RenderView.h"
28 #include "SVGElementInstance.h"
29 #include "SVGNames.h"
30 #include "SVGSVGElement.h"
31 #include "SVGUseElement.h"
32
33 namespace WebCore {
34
35 RenderSVGViewportContainer::RenderSVGViewportContainer(SVGSVGElement& element, PassRef<RenderStyle> style)
36     : RenderSVGContainer(element, WTF::move(style))
37     , m_didTransformToRootUpdate(false)
38     , m_isLayoutSizeChanged(false)
39     , m_needsTransformUpdate(true)
40 {
41 }
42
43 SVGSVGElement& RenderSVGViewportContainer::svgSVGElement() const
44 {
45     return toSVGSVGElement(RenderSVGContainer::element());
46 }
47
48 void RenderSVGViewportContainer::determineIfLayoutSizeChanged()
49 {
50     m_isLayoutSizeChanged = svgSVGElement().hasRelativeLengths() && selfNeedsLayout();
51 }
52
53 void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo)
54 {
55     if (SVGRenderSupport::isOverflowHidden(*this))
56         paintInfo.context->clip(m_viewport);
57 }
58
59 void RenderSVGViewportContainer::calcViewport()
60 {
61     SVGSVGElement& svg = svgSVGElement();
62     FloatRect oldViewport = m_viewport;
63
64     SVGLengthContext lengthContext(&svg);
65     m_viewport = FloatRect(svg.x().value(lengthContext), svg.y().value(lengthContext), svg.width().value(lengthContext), svg.height().value(lengthContext));
66
67     SVGElement* correspondingElement = svg.correspondingElement();
68     if (correspondingElement && svg.isInShadowTree()) {
69         const HashSet<SVGElementInstance*>& instances = correspondingElement->instancesForElement();
70         ASSERT(!instances.isEmpty());
71
72         SVGUseElement* useElement = 0;
73         const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
74         for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
75             const SVGElementInstance* instance = (*it);
76             ASSERT(instance->correspondingElement()->hasTagName(SVGNames::svgTag) || instance->correspondingElement()->hasTagName(SVGNames::symbolTag));
77             if (instance->shadowTreeElement() == &svg) {
78                 ASSERT(correspondingElement == instance->correspondingElement());
79                 useElement = instance->directUseElement();
80                 if (!useElement)
81                     useElement = instance->correspondingUseElement();
82                 break;
83             }
84         }
85
86         ASSERT(useElement);
87         bool isSymbolElement = correspondingElement->hasTagName(SVGNames::symbolTag);
88
89         // Spec (<use> on <symbol>): This generated 'svg' will always have explicit values for attributes width and height.
90         // If attributes width and/or height are provided on the 'use' element, then these attributes
91         // will be transferred to the generated 'svg'. If attributes width and/or height are not specified,
92         // the generated 'svg' element will use values of 100% for these attributes.
93
94         // Spec (<use> on <svg>): If attributes width and/or height are provided on the 'use' element, then these
95         // values will override the corresponding attributes on the 'svg' in the generated tree.
96
97         SVGLengthContext lengthContext(&svg);
98         if (useElement->hasAttribute(SVGNames::widthAttr))
99             m_viewport.setWidth(useElement->width().value(lengthContext));
100         else if (isSymbolElement && svg.hasAttribute(SVGNames::widthAttr)) {
101             SVGLength containerWidth(LengthModeWidth, "100%");
102             m_viewport.setWidth(containerWidth.value(lengthContext));
103         }
104
105         if (useElement->hasAttribute(SVGNames::heightAttr))
106             m_viewport.setHeight(useElement->height().value(lengthContext));
107         else if (isSymbolElement && svg.hasAttribute(SVGNames::heightAttr)) {
108             SVGLength containerHeight(LengthModeHeight, "100%");
109             m_viewport.setHeight(containerHeight.value(lengthContext));
110         }
111     }
112
113     if (oldViewport != m_viewport) {
114         setNeedsBoundariesUpdate();
115         setNeedsTransformUpdate();
116     }
117 }
118
119 bool RenderSVGViewportContainer::calculateLocalTransform() 
120 {
121     m_didTransformToRootUpdate = m_needsTransformUpdate || SVGRenderSupport::transformToRootChanged(parent());
122     if (!m_needsTransformUpdate)
123         return false;
124     
125     m_localToParentTransform = AffineTransform::translation(m_viewport.x(), m_viewport.y()) * viewportTransform();
126     m_needsTransformUpdate = false;
127     return true;
128 }
129
130 AffineTransform RenderSVGViewportContainer::viewportTransform() const
131 {
132     return svgSVGElement().viewBoxToViewTransform(m_viewport.width(), m_viewport.height());
133 }
134
135 bool RenderSVGViewportContainer::pointIsInsideViewportClip(const FloatPoint& pointInParent)
136 {
137     // Respect the viewport clip (which is in parent coords)
138     if (!SVGRenderSupport::isOverflowHidden(*this))
139         return true;
140     
141     return m_viewport.contains(pointInParent);
142 }
143
144 void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
145 {
146     // An empty viewBox disables rendering.
147     if (svgSVGElement().hasEmptyViewBox())
148         return;
149
150     RenderSVGContainer::paint(paintInfo, paintOffset);
151 }
152
153 }