Reviewed by Eric. Rubber stamped by Oliver.
[WebKit-https.git] / WebCore / ksvg2 / svg / SVGMarkerElement.cpp
1 /*
2     Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3                   2004, 2005, 2006 Rob Buis <buis@kde.org>
4
5     This file is part of the KDE project
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., 59 Temple Place - Suite 330,
20     Boston, MA 02111-1307, USA.
21 */
22
23 #include "config.h"
24
25 #ifdef SVG_SUPPORT
26 #include "SVGMarkerElement.h"
27
28 #include "PlatformString.h"
29 #include "RenderSVGContainer.h"
30 #include "SVGAngle.h"
31 #include "SVGFitToViewBox.h"
32 #include "SVGHelper.h"
33 #include "SVGLength.h"
34 #include "SVGMatrix.h"
35 #include "SVGNames.h"
36 #include "SVGPreserveAspectRatio.h"
37 #include "SVGSVGElement.h"
38
39 namespace WebCore {
40
41 SVGMarkerElement::SVGMarkerElement(const QualifiedName& tagName, Document* doc)
42     : SVGStyledElement(tagName, doc)
43     , SVGLangSpace()
44     , SVGExternalResourcesRequired()
45     , SVGFitToViewBox()
46     , m_refX(new SVGLength(this, LM_WIDTH, viewportElement()))
47     , m_refY(new SVGLength(this, LM_HEIGHT, viewportElement()))
48     , m_markerWidth(new SVGLength(this, LM_WIDTH, viewportElement()))
49     , m_markerHeight(new SVGLength(this, LM_HEIGHT, viewportElement()))
50     , m_markerUnits(SVG_MARKERUNITS_STROKEWIDTH)
51     , m_orientType(0)
52     , m_orientAngle(new SVGAngle(this))
53 {
54 }
55
56 SVGMarkerElement::~SVGMarkerElement()
57 {
58 }
59
60 void SVGMarkerElement::parseMappedAttribute(MappedAttribute* attr)
61 {
62     const AtomicString& value = attr->value();
63     if (attr->name() == SVGNames::markerUnitsAttr) {
64         if (value == "userSpaceOnUse")
65             setMarkerUnitsBaseValue(SVG_MARKERUNITS_USERSPACEONUSE);
66     } else if (attr->name() == SVGNames::refXAttr)
67         refXBaseValue()->setValueAsString(value);
68     else if (attr->name() == SVGNames::refYAttr)
69         refYBaseValue()->setValueAsString(value);
70     else if (attr->name() == SVGNames::markerWidthAttr)
71         markerWidthBaseValue()->setValueAsString(value);
72     else if (attr->name() == SVGNames::markerHeightAttr)
73         markerHeightBaseValue()->setValueAsString(value);
74     else if (attr->name() == SVGNames::orientAttr) {
75         if (value == "auto")
76             setOrientToAuto();
77         else {
78             SVGAngle* angle = new SVGAngle(0);
79             angle->setValueAsString(value);
80             setOrientToAngle(angle);
81         }
82     } else {
83         if (SVGLangSpace::parseMappedAttribute(attr))
84             return;
85         if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
86             return;
87         if (SVGFitToViewBox::parseMappedAttribute(attr))
88             return;
89
90         SVGStyledElement::parseMappedAttribute(attr);
91     }
92 }
93
94 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, SVGLength*, Length, length, RefX, refX, SVGNames::refXAttr.localName(), m_refX.get())
95 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, SVGLength*, Length, length, RefY, refY, SVGNames::refYAttr.localName(), m_refY.get())
96 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, int, Enumeration, enumeration, MarkerUnits, markerUnits, SVGNames::markerUnitsAttr.localName(), m_markerUnits)
97 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, SVGLength*, Length, length, MarkerWidth, markerWidth, SVGNames::markerWidthAttr.localName(), m_markerWidth.get())
98 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, SVGLength*, Length, length, MarkerHeight, markerHeight, SVGNames::markerHeightAttr.localName(), m_markerHeight.get())
99 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, int, Enumeration, enumeration, OrientType, orientType, "orientType", m_orientType)
100 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, SVGAngle*, Angle, angle, OrientAngle, orientAngle, "orientAngle", m_orientAngle.get())
101
102 void SVGMarkerElement::setOrientToAuto()
103 {
104     setOrientTypeBaseValue(SVG_MARKER_ORIENT_AUTO);
105 }
106
107 void SVGMarkerElement::setOrientToAngle(SVGAngle* angle)
108 {
109     setOrientTypeBaseValue(SVG_MARKER_ORIENT_ANGLE);
110     setOrientAngleBaseValue(angle);
111 }
112
113 SVGResource* SVGMarkerElement::canvasResource()
114 {
115     if (!m_marker)
116         m_marker = new SVGResourceMarker();
117     
118     m_marker->setMarker(static_cast<RenderSVGContainer*>(renderer()));
119
120     // Spec: If the attribute is not specified, the effect is as if a
121     // value of "0" were specified.
122     if (!m_orientType)
123         setOrientToAngle(SVGSVGElement::createSVGAngle());
124     
125     if (orientType() == SVG_MARKER_ORIENT_ANGLE)
126         m_marker->setAngle(orientAngle()->value());
127     else
128         m_marker->setAutoAngle();
129
130     m_marker->setRef(refX()->value(), refY()->value());
131     m_marker->setUseStrokeWidth(markerUnits() == SVG_MARKERUNITS_STROKEWIDTH);
132     
133     return m_marker.get();
134 }
135
136 RenderObject* SVGMarkerElement::createRenderer(RenderArena* arena, RenderStyle* style)
137 {
138     RenderSVGContainer* markerContainer = new (arena) RenderSVGContainer(this);
139     markerContainer->setViewBox(viewBox());
140     markerContainer->setAlign(KCAlign(preserveAspectRatio()->align() - 1));
141     markerContainer->setSlice(preserveAspectRatio()->meetOrSlice() == SVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE);
142     markerContainer->setDrawsContents(false); // Marker contents will be explicitly drawn.
143     return markerContainer;
144 }
145
146 }
147
148 // vim:ts=4:noet
149 #endif // SVG_SUPPORT
150