2006-09-25 Anders Carlsson <acarlsson@apple.com>
[WebKit-https.git] / WebCore / ksvg2 / svg / SVGAngle.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 <math.h>
26
27 #include <ksvg2/ksvg.h>
28
29 #include "DeprecatedString.h"
30 #include "SVGAngle.h"
31 #include "SVGHelper.h"
32
33 using namespace WebCore;
34
35 const double deg2rad = 0.017453292519943295769; // pi/180
36 const double deg2grad = 400.0 / 360.0;
37
38 #define rad2grad deg2grad / deg2rad
39
40 SVGAngle::SVGAngle(const SVGStyledElement* context)
41     : Shared<SVGAngle>()
42     , m_unitType(SVG_ANGLETYPE_UNKNOWN)
43     , m_value(0)
44     , m_valueInSpecifiedUnits(0)
45     , m_context(context)
46 {
47 }
48
49 SVGAngle::~SVGAngle()
50 {
51 }
52
53 SVGAngle::SVGAngleType SVGAngle::unitType() const
54 {
55     return m_unitType;
56 }
57
58 void SVGAngle::setValue(float value)
59 {
60     m_value = value;
61 }
62
63 float SVGAngle::value() const
64 {
65     return m_value;
66 }
67
68 // calc m_value
69 void SVGAngle::calculate()
70 {
71     if (m_unitType == SVG_ANGLETYPE_GRAD)
72         m_value = m_valueInSpecifiedUnits / deg2grad;
73     else if (m_unitType == SVG_ANGLETYPE_RAD)
74         m_value = m_valueInSpecifiedUnits / deg2rad;
75     else if (m_unitType == SVG_ANGLETYPE_UNSPECIFIED || m_unitType == SVG_ANGLETYPE_DEG)
76         m_value = m_valueInSpecifiedUnits;
77 }
78
79 void SVGAngle::setValueInSpecifiedUnits(float valueInSpecifiedUnits)
80 {
81     m_valueInSpecifiedUnits = valueInSpecifiedUnits;
82     calculate();
83 }
84
85 float SVGAngle::valueInSpecifiedUnits() const
86 {
87     return m_valueInSpecifiedUnits;
88 }
89
90 void SVGAngle::setValueAsString(const String& s)
91 {
92     m_valueAsString = s;
93
94     bool bOK;
95     m_valueInSpecifiedUnits = m_valueAsString.deprecatedString().toDouble(&bOK);
96     m_unitType = SVG_ANGLETYPE_UNSPECIFIED;
97
98     if (!bOK) {
99         if (m_valueAsString.endsWith("deg"))
100             m_unitType = SVG_ANGLETYPE_DEG;
101         else if (m_valueAsString.endsWith("grad"))
102             m_unitType = SVG_ANGLETYPE_GRAD;
103         else if (m_valueAsString.endsWith("rad"))
104             m_unitType = SVG_ANGLETYPE_RAD;
105     }
106     
107     calculate();
108 }
109
110 String SVGAngle::valueAsString() const
111 {
112     m_valueAsString = String::number(m_valueInSpecifiedUnits);
113
114     switch(m_unitType) {
115         case SVG_ANGLETYPE_UNSPECIFIED:
116         case SVG_ANGLETYPE_DEG:
117             m_valueAsString += "deg";
118             break;
119         case SVG_ANGLETYPE_RAD:
120             m_valueAsString += "rad";
121             break;
122         case SVG_ANGLETYPE_GRAD:
123             m_valueAsString += "grad";
124             break;
125         case SVG_ANGLETYPE_UNKNOWN:
126             break;
127     }
128     
129     return m_valueAsString;
130 }
131
132 void SVGAngle::newValueSpecifiedUnits(unsigned short unitType, float valueInSpecifiedUnits)
133 {
134     m_unitType = (SVGAngleType)unitType;
135     m_valueInSpecifiedUnits = valueInSpecifiedUnits;
136     calculate();
137 }
138
139 void SVGAngle::convertToSpecifiedUnits(unsigned short unitType)
140 {
141     if (m_unitType == unitType)
142         return;
143
144     if (m_unitType == SVG_ANGLETYPE_DEG && unitType == SVG_ANGLETYPE_RAD)
145         m_valueInSpecifiedUnits *= deg2rad;
146     else if (m_unitType == SVG_ANGLETYPE_GRAD && unitType == SVG_ANGLETYPE_RAD)
147         m_valueInSpecifiedUnits /= rad2grad;
148     else if (m_unitType == SVG_ANGLETYPE_DEG && unitType == SVG_ANGLETYPE_GRAD)
149         m_valueInSpecifiedUnits *= deg2grad;
150     else if (m_unitType == SVG_ANGLETYPE_RAD && unitType == SVG_ANGLETYPE_GRAD)
151         m_valueInSpecifiedUnits *= rad2grad;
152     else if (m_unitType == SVG_ANGLETYPE_RAD && unitType == SVG_ANGLETYPE_DEG)
153         m_valueInSpecifiedUnits /= deg2rad;
154     else if (m_unitType == SVG_ANGLETYPE_GRAD && unitType == SVG_ANGLETYPE_DEG)
155         m_valueInSpecifiedUnits /= deg2grad;
156
157     m_unitType = (SVGAngleType)unitType;
158 }
159
160 // Helpers
161 double SVGAngle::todeg(double rad)
162 {
163     return rad / deg2rad;
164 }
165
166 double SVGAngle::torad(double deg)
167 {
168     return deg * deg2rad;
169 }
170
171 double SVGAngle::shortestArcBisector(double angle1, double angle2)
172 {
173     double bisector = (angle1 + angle2) / 2;
174
175     if (fabs(angle1 - angle2) > 180)
176         bisector += 180;
177
178     return bisector;
179 }
180
181 const SVGStyledElement *SVGAngle::context() const
182 {
183     return m_context;
184 }
185
186 void SVGAngle::setContext(const SVGStyledElement *context)
187 {
188     m_context = context;
189 }
190
191
192 // vim:ts=4:noet
193 #endif // SVG_SUPPORT
194