15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved.
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)
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGPatternElement.h"
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/XLinkNames.h"
2709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/dom/ElementTraversal.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGResourcePattern.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/PatternAttributes.h"
301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/transforms/AffineTransform.h"
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)inline SVGPatternElement::SVGPatternElement(Document& document)
3551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    : SVGElement(SVGNames::patternTag, document)
3609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , SVGURIReference(this)
3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , SVGTests(this)
3809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , SVGFitToViewBox(this)
3907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
4007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
4107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth), ForbidNegativeLengths))
4207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight), ForbidNegativeLengths))
43d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_patternTransform(SVGAnimatedTransformList::create(this, SVGNames::patternTransformAttr, SVGTransformList::create()))
44d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_patternUnits(SVGAnimatedEnumeration<SVGUnitTypes::SVGUnitType>::create(this, SVGNames::patternUnitsAttr, SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX))
45d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_patternContentUnits(SVGAnimatedEnumeration<SVGUnitTypes::SVGUnitType>::create(this, SVGNames::patternContentUnitsAttr, SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE))
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ScriptWrappable::init(this);
4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    addToPropertyMap(m_x);
5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    addToPropertyMap(m_y);
5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    addToPropertyMap(m_width);
5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    addToPropertyMap(m_height);
53d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    addToPropertyMap(m_patternTransform);
54d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    addToPropertyMap(m_patternUnits);
55d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    addToPropertyMap(m_patternContentUnits);
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
585d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)DEFINE_NODE_FACTORY(SVGPatternElement)
595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGPatternElement::isSupportedAttribute(const QualifiedName& attrName)
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (supportedAttributes.isEmpty()) {
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGURIReference::addSupportedAttributes(supportedAttributes);
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGTests::addSupportedAttributes(supportedAttributes);
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGFitToViewBox::addSupportedAttributes(supportedAttributes);
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::patternUnitsAttr);
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::patternContentUnitsAttr);
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::patternTransformAttr);
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::xAttr);
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::yAttr);
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::widthAttr);
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::heightAttr);
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
75591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGPatternElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGParsingError parseError = NoError;
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!isSupportedAttribute(name)) {
83f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        SVGElement::parseAttribute(name, value);
8409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (name == SVGNames::patternUnitsAttr) {
85d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_patternUnits->setBaseValueAsString(value, parseError);
86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (name == SVGNames::patternContentUnitsAttr) {
87d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_patternContentUnits->setBaseValueAsString(value, parseError);
88926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (name == SVGNames::patternTransformAttr) {
89d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_patternTransform->setBaseValueAsString(value, parseError);
9009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (name == SVGNames::xAttr) {
9107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_x->setBaseValueAsString(value, parseError);
9209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (name == SVGNames::yAttr) {
9307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_y->setBaseValueAsString(value, parseError);
9409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (name == SVGNames::widthAttr) {
9507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_width->setBaseValueAsString(value, parseError);
9609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (name == SVGNames::heightAttr) {
9707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_height->setBaseValueAsString(value, parseError);
9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (SVGURIReference::parseAttribute(name, value, parseError)) {
9909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (SVGTests::parseAttribute(name, value)) {
10009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (SVGFitToViewBox::parseAttribute(name, value, document(), parseError)) {
10109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else {
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    reportAttributeParsingError(parseError, name, value);
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPatternElement::svgAttributeChanged(const QualifiedName& attrName)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isSupportedAttribute(attrName)) {
111f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        SVGElement::svgAttributeChanged(attrName);
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
115323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    SVGElement::InvalidationGuard invalidationGuard(this);
11602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (attrName == SVGNames::xAttr
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || attrName == SVGNames::yAttr
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || attrName == SVGNames::widthAttr
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || attrName == SVGNames::heightAttr)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateRelativeLengthsInformation();
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
123f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
124f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    if (renderer)
125f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        renderer->invalidateCacheAndMarkForLayout();
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPatternElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
130f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (changedByParser)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (RenderObject* object = renderer())
1365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        object->setNeedsLayoutAndFullPaintInvalidation();
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
139591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochRenderObject* SVGPatternElement::createRenderer(RenderStyle*)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
141f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return new RenderSVGResourcePattern(this);
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static void setPatternAttributes(const SVGPatternElement* element, PatternAttributes& attributes)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!attributes.hasX() && element->x()->isSpecified())
14709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        attributes.setX(element->x()->currentValue());
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!attributes.hasY() && element->y()->isSpecified())
15009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        attributes.setY(element->y()->currentValue());
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!attributes.hasWidth() && element->width()->isSpecified())
15309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        attributes.setWidth(element->width()->currentValue());
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!attributes.hasHeight() && element->height()->isSpecified())
15609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        attributes.setHeight(element->height()->currentValue());
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!attributes.hasViewBox() && element->viewBox()->isSpecified() && element->viewBox()->currentValue()->isValid())
15909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        attributes.setViewBox(element->viewBox()->currentValue()->value());
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!attributes.hasPreserveAspectRatio() && element->preserveAspectRatio()->isSpecified())
16209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        attributes.setPreserveAspectRatio(element->preserveAspectRatio()->currentValue());
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
164d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!attributes.hasPatternUnits() && element->patternUnits()->isSpecified())
165d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        attributes.setPatternUnits(element->patternUnits()->currentValue()->enumValue());
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
167d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!attributes.hasPatternContentUnits() && element->patternContentUnits()->isSpecified())
168d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        attributes.setPatternContentUnits(element->patternContentUnits()->currentValue()->enumValue());
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
170d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!attributes.hasPatternTransform() && element->patternTransform()->isSpecified()) {
17109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        AffineTransform transform;
172d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        element->patternTransform()->currentValue()->concatenate(transform);
17309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        attributes.setPatternTransform(transform);
17409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!attributes.hasPatternContentElement() && ElementTraversal::firstWithin(*element))
17709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        attributes.setPatternContentElement(element);
17809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGPatternElement::collectPatternAttributes(PatternAttributes& attributes) const
18109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
18209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    HashSet<const SVGPatternElement*> processedPatterns;
18309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const SVGPatternElement* current = this;
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    while (true) {
18609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        setPatternAttributes(current, attributes);
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        processedPatterns.add(current);
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Respect xlink:href, take attributes from referenced element
19010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        Node* refNode = SVGURIReference::targetElementFromIRIString(current->hrefString(), treeScope());
191d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (isSVGPatternElement(refNode)) {
192d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            current = toSVGPatternElement(refNode);
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Cycle detection
19509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            if (processedPatterns.contains(current))
19609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                return;
19709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        } else {
19809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return;
19909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
20209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT_NOT_REACHED();
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)AffineTransform SVGPatternElement::localCoordinateSpaceTransform(SVGElement::CTMScope) const
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform matrix;
208d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_patternTransform->currentValue()->concatenate(matrix);
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return matrix;
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGPatternElement::selfHasRelativeLengths() const
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
21409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return m_x->currentValue()->isRelative()
21509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        || m_y->currentValue()->isRelative()
21609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        || m_width->currentValue()->isRelative()
21709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        || m_height->currentValue()->isRelative();
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
221