1/*
2    Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3                  2004, 2005, 2006, 2008 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 "SVGTextElement.h"
25
26#include "AffineTransform.h"
27#include "FloatRect.h"
28#include "MappedAttribute.h"
29#include "RenderSVGText.h"
30#include "SVGLengthList.h"
31#include "SVGRenderStyle.h"
32#include "SVGTSpanElement.h"
33#include "SVGTransformList.h"
34
35namespace WebCore {
36
37SVGTextElement::SVGTextElement(const QualifiedName& tagName, Document* doc)
38    : SVGTextPositioningElement(tagName, doc)
39    , SVGTransformable()
40    , m_transform(SVGTransformList::create(SVGNames::transformAttr))
41{
42}
43
44SVGTextElement::~SVGTextElement()
45{
46}
47
48void SVGTextElement::parseMappedAttribute(MappedAttribute* attr)
49{
50    if (SVGTransformable::isKnownAttribute(attr->name())) {
51        SVGTransformList* localTransforms = transformBaseValue();
52        if (!SVGTransformable::parseTransformAttribute(localTransforms, attr->value())) {
53            ExceptionCode ec = 0;
54            localTransforms->clear(ec);
55        }
56    } else
57        SVGTextPositioningElement::parseMappedAttribute(attr);
58}
59
60SVGElement* SVGTextElement::nearestViewportElement() const
61{
62    return SVGTransformable::nearestViewportElement(this);
63}
64
65SVGElement* SVGTextElement::farthestViewportElement() const
66{
67    return SVGTransformable::farthestViewportElement(this);
68}
69
70FloatRect SVGTextElement::getBBox() const
71{
72    return SVGTransformable::getBBox(this);
73}
74
75AffineTransform SVGTextElement::getScreenCTM() const
76{
77    return SVGTransformable::getScreenCTM(this);
78}
79
80AffineTransform SVGTextElement::getCTM() const
81{
82    return SVGTransformable::getCTM(this);
83}
84
85AffineTransform SVGTextElement::animatedLocalTransform() const
86{
87    return m_supplementalTransform ? transform()->concatenate().matrix() * *m_supplementalTransform : transform()->concatenate().matrix();
88}
89
90AffineTransform* SVGTextElement::supplementalTransform()
91{
92    if (!m_supplementalTransform)
93        m_supplementalTransform.set(new AffineTransform());
94    return m_supplementalTransform.get();
95}
96
97RenderObject* SVGTextElement::createRenderer(RenderArena* arena, RenderStyle*)
98{
99    return new (arena) RenderSVGText(this);
100}
101
102bool SVGTextElement::childShouldCreateRenderer(Node* child) const
103{
104    if (child->isTextNode()
105#if ENABLE(SVG_FONTS)
106        || child->hasTagName(SVGNames::altGlyphTag)
107#endif
108        || child->hasTagName(SVGNames::tspanTag) || child->hasTagName(SVGNames::trefTag) || child->hasTagName(SVGNames::aTag) || child->hasTagName(SVGNames::textPathTag))
109        return true;
110    return false;
111}
112
113void SVGTextElement::svgAttributeChanged(const QualifiedName& attrName)
114{
115    SVGTextPositioningElement::svgAttributeChanged(attrName);
116
117    if (!renderer())
118        return;
119
120    if (SVGTransformable::isKnownAttribute(attrName))
121        renderer()->setNeedsLayout(true);
122}
123
124void SVGTextElement::synchronizeProperty(const QualifiedName& attrName)
125{
126    SVGTextPositioningElement::synchronizeProperty(attrName);
127
128    if (attrName == anyQName() || SVGTransformable::isKnownAttribute(attrName))
129        synchronizeTransform();
130}
131
132void SVGTextElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
133{
134    SVGTextPositioningElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
135
136    if (!renderer())
137        return;
138
139    renderer()->setNeedsLayout(true);
140}
141
142}
143
144#endif // ENABLE(SVG)
145