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