15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * Copyright (C) 2014 Google, Inc.
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
24591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/svg/SVGGraphicsElement.h"
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/SVGNames.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGPath.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGResource.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGPathData.h"
301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/transforms/AffineTransform.h"
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
348abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)SVGGraphicsElement::SVGGraphicsElement(const QualifiedName& tagName, Document& document, ConstructionType constructionType)
35f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    : SVGElement(tagName, document, constructionType)
3609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , SVGTests(this)
37d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_transform(SVGAnimatedTransformList::create(this, SVGNames::transformAttr, SVGTransformList::create()))
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
39d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    addToPropertyMap(m_transform);
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochSVGGraphicsElement::~SVGGraphicsElement()
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
46d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)PassRefPtr<SVGMatrixTearOff> SVGGraphicsElement::getTransformToElement(SVGElement* target, ExceptionState& exceptionState)
4751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
4851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    AffineTransform ctm = getCTM(AllowStyleUpdate);
4951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
5051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (target && target->isSVGGraphicsElement()) {
5151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        AffineTransform targetCTM = toSVGGraphicsElement(target)->getCTM(AllowStyleUpdate);
5251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (!targetCTM.isInvertible()) {
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            exceptionState.throwDOMException(InvalidStateError, "The target transformation is not invertable.");
54d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
5551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
5651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ctm = targetCTM.inverse() * ctm;
5751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
5851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
59d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return SVGMatrixTearOff::create(ctm);
60d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
61d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
62d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static bool isViewportElement(const Element& element)
63d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
64d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return (isSVGSVGElement(element)
65d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGSymbolElement(element)
66d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGForeignObjectElement(element)
67d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGImageElement(element));
6851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
6951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
70d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)AffineTransform SVGGraphicsElement::computeCTM(SVGElement::CTMScope mode,
71d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    SVGGraphicsElement::StyleUpdateStrategy styleUpdateStrategy, const SVGGraphicsElement* ancestor) const
7251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
73d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (styleUpdateStrategy == AllowStyleUpdate)
74d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        document().updateLayoutIgnorePendingStylesheets();
7551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
7651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    AffineTransform ctm;
77d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    bool done = false;
7851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
79d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    for (const Element* currentElement = this; currentElement && !done;
80d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        currentElement = currentElement->parentOrShadowHostElement()) {
8151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (!currentElement->isSVGElement())
8251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            break;
8351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
8451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ctm = toSVGElement(currentElement)->localCoordinateSpaceTransform(mode).multiply(ctm);
8551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
86d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        switch (mode) {
87d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        case NearestViewportScope:
88d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            // Stop at the nearest viewport ancestor.
89d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            done = currentElement != this && isViewportElement(*currentElement);
9051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            break;
91d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        case AncestorScope:
92d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            // Stop at the designated ancestor.
93d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            done = currentElement == ancestor;
94d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            break;
95d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        default:
96d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            ASSERT(mode == ScreenScope);
97d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            break;
98d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
9951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
10051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
10151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return ctm;
10251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
10351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
104591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochAffineTransform SVGGraphicsElement::getCTM(StyleUpdateStrategy styleUpdateStrategy)
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
106d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return computeCTM(NearestViewportScope, styleUpdateStrategy);
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
109591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochAffineTransform SVGGraphicsElement::getScreenCTM(StyleUpdateStrategy styleUpdateStrategy)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
111d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return computeCTM(ScreenScope, styleUpdateStrategy);
112d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
113d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
114d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)PassRefPtr<SVGMatrixTearOff> SVGGraphicsElement::getCTMFromJavascript()
115d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
116d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return SVGMatrixTearOff::create(getCTM());
117d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
118d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
119d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)PassRefPtr<SVGMatrixTearOff> SVGGraphicsElement::getScreenCTMFromJavascript()
120d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
121d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return SVGMatrixTearOff::create(getScreenCTM());
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
124591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochAffineTransform SVGGraphicsElement::animatedLocalTransform() const
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform matrix;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderStyle* style = renderer() ? renderer()->style() : 0;
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If CSS property was set, use that, otherwise fallback to attribute (if set).
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (style && style->hasTransform()) {
131d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        TransformationMatrix transform;
132d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        float zoom = style->effectiveZoom();
133d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
134d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // CSS transforms operate with pre-scaled lengths. To make this work with SVG
135d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // (which applies the zoom factor globally, at the root level) we
136d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        //
137d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        //   * pre-scale the bounding box (to bring it into the same space as the other CSS values)
138d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        //   * invert the zoom factor (to effectively compute the CSS transform under a 1.0 zoom)
139d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        //
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Note: objectBoundingBox is an emptyRect for elements like pattern or clipPath.
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // See the "Object bounding box units" section of http://dev.w3.org/csswg/css3-transforms/
142d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (zoom != 1) {
143d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            FloatRect scaledBBox = renderer()->objectBoundingBox();
144d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            scaledBBox.scale(zoom);
145d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            transform.scale(1 / zoom);
146d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            style->applyTransform(transform, scaledBBox);
147d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            transform.scale(zoom);
148d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        } else {
149d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            style->applyTransform(transform, renderer()->objectBoundingBox());
150d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        }
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Flatten any 3D transform.
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        matrix = transform.toAffineTransform();
154591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } else {
155d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_transform->currentValue()->concatenate(matrix);
156591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_supplementalTransform)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return *m_supplementalTransform * matrix;
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return matrix;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
163591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochAffineTransform* SVGGraphicsElement::supplementalTransform()
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_supplementalTransform)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_supplementalTransform = adoptPtr(new AffineTransform);
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_supplementalTransform.get();
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
170591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochbool SVGGraphicsElement::isSupportedAttribute(const QualifiedName& attrName)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
173591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (supportedAttributes.isEmpty()) {
174591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        SVGTests::addSupportedAttributes(supportedAttributes);
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::transformAttr);
176591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
177591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
180591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid SVGGraphicsElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
182c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    parseAttributeNew(name, value);
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
185591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid SVGGraphicsElement::svgAttributeChanged(const QualifiedName& attrName)
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isSupportedAttribute(attrName)) {
188f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        SVGElement::svgAttributeChanged(attrName);
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
192323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    SVGElement::InvalidationGuard invalidationGuard(this);
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
194f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    // Reattach so the isValid() check will be run again during renderer creation.
195f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    if (SVGTests::isKnownAttribute(attrName)) {
196f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        lazyReattachIfAttached();
197591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return;
198f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    }
199591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* object = renderer();
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!object)
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (attrName == SVGNames::transformAttr) {
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        object->setNeedsTransformUpdate();
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderSVGResource::markForLayoutAndParentResourceInvalidation(object);
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
213591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochSVGElement* SVGGraphicsElement::nearestViewportElement() const
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
21551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    for (Element* current = parentOrShadowHostElement(); current; current = current->parentOrShadowHostElement()) {
216d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (isViewportElement(*current))
21751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return toSVGElement(current);
21851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
21951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
22051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return 0;
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
223591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochSVGElement* SVGGraphicsElement::farthestViewportElement() const
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
22551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    SVGElement* farthest = 0;
22651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    for (Element* current = parentOrShadowHostElement(); current; current = current->parentOrShadowHostElement()) {
227d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (isViewportElement(*current))
22851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            farthest = toSVGElement(current);
22951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
23051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return farthest;
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)FloatRect SVGGraphicsElement::getBBox()
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
235f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    document().updateLayoutIgnorePendingStylesheets();
236f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
237f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    // FIXME: Eventually we should support getBBox for detached elements.
238f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    if (!renderer())
23909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return FloatRect();
240f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
241f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    return renderer()->objectBoundingBox();
242f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)}
243f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
24409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)PassRefPtr<SVGRectTearOff> SVGGraphicsElement::getBBoxFromJavascript()
245f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){
24609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return SVGRectTearOff::create(SVGRect::create(getBBox()), 0, PropertyIsNotAnimVal);
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
249591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochRenderObject* SVGGraphicsElement::createRenderer(RenderStyle*)
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // By default, any subclass is expected to do path-based drawing
252f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return new RenderSVGPath(this);
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid SVGGraphicsElement::toClipPath(Path& path)
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updatePathFromGraphicsElement(this, path);
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: How do we know the element has done a layout?
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    path.transform(animatedLocalTransform());
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
263