1 /* 2 * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis (at) kde.org> 4 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22 #include "config.h" 23 24 #if ENABLE(SVG) 25 #include "SVGAngle.h" 26 27 #include "SVGParserUtilities.h" 28 #include <wtf/MathExtras.h> 29 #include <wtf/text/StringConcatenate.h> 30 31 namespace WebCore { 32 33 SVGAngle::SVGAngle() 34 : m_unitType(SVG_ANGLETYPE_UNSPECIFIED) 35 , m_valueInSpecifiedUnits(0) 36 { 37 } 38 39 float SVGAngle::value() const 40 { 41 switch (m_unitType) { 42 case SVG_ANGLETYPE_GRAD: 43 return grad2deg(m_valueInSpecifiedUnits); 44 case SVG_ANGLETYPE_RAD: 45 return rad2deg(m_valueInSpecifiedUnits); 46 case SVG_ANGLETYPE_UNSPECIFIED: 47 case SVG_ANGLETYPE_UNKNOWN: 48 case SVG_ANGLETYPE_DEG: 49 return m_valueInSpecifiedUnits; 50 } 51 52 ASSERT_NOT_REACHED(); 53 return 0; 54 } 55 56 void SVGAngle::setValue(float value) 57 { 58 switch (m_unitType) { 59 case SVG_ANGLETYPE_GRAD: 60 m_valueInSpecifiedUnits = deg2grad(value); 61 break; 62 case SVG_ANGLETYPE_RAD: 63 m_valueInSpecifiedUnits = deg2rad(value); 64 break; 65 case SVG_ANGLETYPE_UNSPECIFIED: 66 case SVG_ANGLETYPE_UNKNOWN: 67 case SVG_ANGLETYPE_DEG: 68 m_valueInSpecifiedUnits = value; 69 break; 70 } 71 } 72 73 inline SVGAngle::SVGAngleType stringToAngleType(const UChar*& ptr, const UChar* end) 74 { 75 // If there's no unit given, the angle type is unspecified. 76 if (ptr == end) 77 return SVGAngle::SVG_ANGLETYPE_UNSPECIFIED; 78 79 const UChar firstChar = *ptr; 80 81 // If the unit contains only one character, the angle type is unknown. 82 ++ptr; 83 if (ptr == end) 84 return SVGAngle::SVG_ANGLETYPE_UNKNOWN; 85 86 const UChar secondChar = *ptr; 87 88 // If the unit contains only two characters, the angle type is unknown. 89 ++ptr; 90 if (ptr == end) 91 return SVGAngle::SVG_ANGLETYPE_UNKNOWN; 92 93 const UChar thirdChar = *ptr; 94 if (firstChar == 'd' && secondChar == 'e' && thirdChar == 'g') 95 return SVGAngle::SVG_ANGLETYPE_DEG; 96 if (firstChar == 'r' && secondChar == 'a' && thirdChar == 'd') 97 return SVGAngle::SVG_ANGLETYPE_RAD; 98 99 // If the unit contains three characters, but is not deg or rad, then it's unknown. 100 ++ptr; 101 if (ptr == end) 102 return SVGAngle::SVG_ANGLETYPE_UNKNOWN; 103 104 const UChar fourthChar = *ptr; 105 106 if (firstChar == 'g' && secondChar == 'r' && thirdChar == 'a' && fourthChar == 'd') 107 return SVGAngle::SVG_ANGLETYPE_GRAD; 108 109 return SVGAngle::SVG_ANGLETYPE_UNKNOWN; 110 } 111 112 String SVGAngle::valueAsString() const 113 { 114 switch (m_unitType) { 115 case SVG_ANGLETYPE_DEG: 116 return makeString(String::number(m_valueInSpecifiedUnits), "deg"); 117 case SVG_ANGLETYPE_RAD: 118 return makeString(String::number(m_valueInSpecifiedUnits), "rad"); 119 case SVG_ANGLETYPE_GRAD: 120 return makeString(String::number(m_valueInSpecifiedUnits), "grad"); 121 case SVG_ANGLETYPE_UNSPECIFIED: 122 case SVG_ANGLETYPE_UNKNOWN: 123 return makeString(String::number(m_valueInSpecifiedUnits)); 124 } 125 126 ASSERT_NOT_REACHED(); 127 return String(); 128 } 129 130 void SVGAngle::setValueAsString(const String& value, ExceptionCode& ec) 131 { 132 if (value.isEmpty()) { 133 m_unitType = SVG_ANGLETYPE_UNSPECIFIED; 134 return; 135 } 136 137 float valueInSpecifiedUnits = 0; 138 const UChar* ptr = value.characters(); 139 const UChar* end = ptr + value.length(); 140 141 if (!parseNumber(ptr, end, valueInSpecifiedUnits, false)) { 142 ec = SYNTAX_ERR; 143 return; 144 } 145 146 SVGAngleType unitType = stringToAngleType(ptr, end); 147 if (unitType == SVG_ANGLETYPE_UNKNOWN) { 148 ec = SYNTAX_ERR; 149 return; 150 } 151 152 m_unitType = unitType; 153 m_valueInSpecifiedUnits = valueInSpecifiedUnits; 154 } 155 156 void SVGAngle::newValueSpecifiedUnits(unsigned short unitType, float valueInSpecifiedUnits, ExceptionCode& ec) 157 { 158 if (unitType == SVG_ANGLETYPE_UNKNOWN || unitType > SVG_ANGLETYPE_GRAD) { 159 ec = NOT_SUPPORTED_ERR; 160 return; 161 } 162 163 if (unitType != m_unitType) 164 m_unitType = static_cast<SVGAngleType>(unitType); 165 166 m_valueInSpecifiedUnits = valueInSpecifiedUnits; 167 } 168 169 void SVGAngle::convertToSpecifiedUnits(unsigned short unitType, ExceptionCode& ec) 170 { 171 if (unitType == SVG_ANGLETYPE_UNKNOWN || m_unitType == SVG_ANGLETYPE_UNKNOWN || unitType > SVG_ANGLETYPE_GRAD) { 172 ec = NOT_SUPPORTED_ERR; 173 return; 174 } 175 176 if (unitType == m_unitType) 177 return; 178 179 switch (m_unitType) { 180 case SVG_ANGLETYPE_RAD: 181 switch (unitType) { 182 case SVG_ANGLETYPE_GRAD: 183 m_valueInSpecifiedUnits = rad2grad(m_valueInSpecifiedUnits); 184 break; 185 case SVG_ANGLETYPE_UNSPECIFIED: 186 case SVG_ANGLETYPE_DEG: 187 m_valueInSpecifiedUnits = rad2deg(m_valueInSpecifiedUnits); 188 break; 189 case SVG_ANGLETYPE_RAD: 190 case SVG_ANGLETYPE_UNKNOWN: 191 ASSERT_NOT_REACHED(); 192 break; 193 } 194 break; 195 case SVG_ANGLETYPE_GRAD: 196 switch (unitType) { 197 case SVG_ANGLETYPE_RAD: 198 m_valueInSpecifiedUnits = grad2rad(m_valueInSpecifiedUnits); 199 break; 200 case SVG_ANGLETYPE_UNSPECIFIED: 201 case SVG_ANGLETYPE_DEG: 202 m_valueInSpecifiedUnits = grad2deg(m_valueInSpecifiedUnits); 203 break; 204 case SVG_ANGLETYPE_GRAD: 205 case SVG_ANGLETYPE_UNKNOWN: 206 ASSERT_NOT_REACHED(); 207 break; 208 } 209 break; 210 case SVG_ANGLETYPE_UNSPECIFIED: 211 // Spec: For angles, a unitless value is treated the same as if degrees were specified. 212 case SVG_ANGLETYPE_DEG: 213 switch (unitType) { 214 case SVG_ANGLETYPE_RAD: 215 m_valueInSpecifiedUnits = deg2rad(m_valueInSpecifiedUnits); 216 break; 217 case SVG_ANGLETYPE_GRAD: 218 m_valueInSpecifiedUnits = deg2grad(m_valueInSpecifiedUnits); 219 break; 220 case SVG_ANGLETYPE_UNSPECIFIED: 221 break; 222 case SVG_ANGLETYPE_DEG: 223 case SVG_ANGLETYPE_UNKNOWN: 224 ASSERT_NOT_REACHED(); 225 break; 226 } 227 break; 228 case SVG_ANGLETYPE_UNKNOWN: 229 ASSERT_NOT_REACHED(); 230 break; 231 } 232 233 m_unitType = static_cast<SVGAngleType>(unitType); 234 } 235 236 } 237 238 #endif // ENABLE(SVG) 239