diff options
Diffstat (limited to 'Source/WebCore/svg/SVGAngle.cpp')
-rw-r--r-- | Source/WebCore/svg/SVGAngle.cpp | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/Source/WebCore/svg/SVGAngle.cpp b/Source/WebCore/svg/SVGAngle.cpp new file mode 100644 index 0000000..37cb73a --- /dev/null +++ b/Source/WebCore/svg/SVGAngle.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(SVG) +#include "SVGAngle.h" + +#include "SVGParserUtilities.h" +#include <wtf/MathExtras.h> +#include <wtf/text/StringConcatenate.h> + +namespace WebCore { + +SVGAngle::SVGAngle() + : m_unitType(SVG_ANGLETYPE_UNSPECIFIED) + , m_valueInSpecifiedUnits(0) +{ +} + +float SVGAngle::value() const +{ + switch (m_unitType) { + case SVG_ANGLETYPE_GRAD: + return grad2deg(m_valueInSpecifiedUnits); + case SVG_ANGLETYPE_RAD: + return rad2deg(m_valueInSpecifiedUnits); + case SVG_ANGLETYPE_UNSPECIFIED: + case SVG_ANGLETYPE_UNKNOWN: + case SVG_ANGLETYPE_DEG: + return m_valueInSpecifiedUnits; + } + + ASSERT_NOT_REACHED(); + return 0; +} + +void SVGAngle::setValue(float value) +{ + switch (m_unitType) { + case SVG_ANGLETYPE_GRAD: + m_valueInSpecifiedUnits = deg2grad(value); + break; + case SVG_ANGLETYPE_RAD: + m_valueInSpecifiedUnits = deg2rad(value); + break; + case SVG_ANGLETYPE_UNSPECIFIED: + case SVG_ANGLETYPE_UNKNOWN: + case SVG_ANGLETYPE_DEG: + m_valueInSpecifiedUnits = value; + break; + } +} + +inline SVGAngle::SVGAngleType stringToAngleType(const UChar*& ptr, const UChar* end) +{ + // If there's no unit given, the angle type is unspecified. + if (ptr == end) + return SVGAngle::SVG_ANGLETYPE_UNSPECIFIED; + + const UChar firstChar = *ptr; + + // If the unit contains only one character, the angle type is unknown. + ++ptr; + if (ptr == end) + return SVGAngle::SVG_ANGLETYPE_UNKNOWN; + + const UChar secondChar = *ptr; + + // If the unit contains only two characters, the angle type is unknown. + ++ptr; + if (ptr == end) + return SVGAngle::SVG_ANGLETYPE_UNKNOWN; + + const UChar thirdChar = *ptr; + if (firstChar == 'd' && secondChar == 'e' && thirdChar == 'g') + return SVGAngle::SVG_ANGLETYPE_DEG; + if (firstChar == 'r' && secondChar == 'a' && thirdChar == 'd') + return SVGAngle::SVG_ANGLETYPE_RAD; + + // If the unit contains three characters, but is not deg or rad, then it's unknown. + ++ptr; + if (ptr == end) + return SVGAngle::SVG_ANGLETYPE_UNKNOWN; + + const UChar fourthChar = *ptr; + + if (firstChar == 'g' && secondChar == 'r' && thirdChar == 'a' && fourthChar == 'd') + return SVGAngle::SVG_ANGLETYPE_GRAD; + + return SVGAngle::SVG_ANGLETYPE_UNKNOWN; +} + +String SVGAngle::valueAsString() const +{ + switch (m_unitType) { + case SVG_ANGLETYPE_DEG: + return makeString(String::number(m_valueInSpecifiedUnits), "deg"); + case SVG_ANGLETYPE_RAD: + return makeString(String::number(m_valueInSpecifiedUnits), "rad"); + case SVG_ANGLETYPE_GRAD: + return makeString(String::number(m_valueInSpecifiedUnits), "grad"); + case SVG_ANGLETYPE_UNSPECIFIED: + case SVG_ANGLETYPE_UNKNOWN: + return makeString(String::number(m_valueInSpecifiedUnits)); + } + + ASSERT_NOT_REACHED(); + return String(); +} + +void SVGAngle::setValueAsString(const String& value, ExceptionCode& ec) +{ + if (value.isEmpty()) { + m_unitType = SVG_ANGLETYPE_UNSPECIFIED; + return; + } + + float valueInSpecifiedUnits = 0; + const UChar* ptr = value.characters(); + const UChar* end = ptr + value.length(); + + if (!parseNumber(ptr, end, valueInSpecifiedUnits, false)) { + ec = SYNTAX_ERR; + return; + } + + SVGAngleType unitType = stringToAngleType(ptr, end); + if (unitType == SVG_ANGLETYPE_UNKNOWN) { + ec = SYNTAX_ERR; + return; + } + + m_unitType = unitType; + m_valueInSpecifiedUnits = valueInSpecifiedUnits; +} + +void SVGAngle::newValueSpecifiedUnits(unsigned short unitType, float valueInSpecifiedUnits, ExceptionCode& ec) +{ + if (unitType == SVG_ANGLETYPE_UNKNOWN || unitType > SVG_ANGLETYPE_GRAD) { + ec = NOT_SUPPORTED_ERR; + return; + } + + if (unitType != m_unitType) + m_unitType = static_cast<SVGAngleType>(unitType); + + m_valueInSpecifiedUnits = valueInSpecifiedUnits; +} + +void SVGAngle::convertToSpecifiedUnits(unsigned short unitType, ExceptionCode& ec) +{ + if (unitType == SVG_ANGLETYPE_UNKNOWN || m_unitType == SVG_ANGLETYPE_UNKNOWN || unitType > SVG_ANGLETYPE_GRAD) { + ec = NOT_SUPPORTED_ERR; + return; + } + + if (unitType == m_unitType) + return; + + switch (m_unitType) { + case SVG_ANGLETYPE_RAD: + switch (unitType) { + case SVG_ANGLETYPE_GRAD: + m_valueInSpecifiedUnits = rad2grad(m_valueInSpecifiedUnits); + break; + case SVG_ANGLETYPE_UNSPECIFIED: + case SVG_ANGLETYPE_DEG: + m_valueInSpecifiedUnits = rad2deg(m_valueInSpecifiedUnits); + break; + case SVG_ANGLETYPE_RAD: + case SVG_ANGLETYPE_UNKNOWN: + ASSERT_NOT_REACHED(); + break; + } + break; + case SVG_ANGLETYPE_GRAD: + switch (unitType) { + case SVG_ANGLETYPE_RAD: + m_valueInSpecifiedUnits = grad2rad(m_valueInSpecifiedUnits); + break; + case SVG_ANGLETYPE_UNSPECIFIED: + case SVG_ANGLETYPE_DEG: + m_valueInSpecifiedUnits = grad2deg(m_valueInSpecifiedUnits); + break; + case SVG_ANGLETYPE_GRAD: + case SVG_ANGLETYPE_UNKNOWN: + ASSERT_NOT_REACHED(); + break; + } + break; + case SVG_ANGLETYPE_UNSPECIFIED: + // Spec: For angles, a unitless value is treated the same as if degrees were specified. + case SVG_ANGLETYPE_DEG: + switch (unitType) { + case SVG_ANGLETYPE_RAD: + m_valueInSpecifiedUnits = deg2rad(m_valueInSpecifiedUnits); + break; + case SVG_ANGLETYPE_GRAD: + m_valueInSpecifiedUnits = deg2grad(m_valueInSpecifiedUnits); + break; + case SVG_ANGLETYPE_UNSPECIFIED: + break; + case SVG_ANGLETYPE_DEG: + case SVG_ANGLETYPE_UNKNOWN: + ASSERT_NOT_REACHED(); + break; + } + break; + case SVG_ANGLETYPE_UNKNOWN: + ASSERT_NOT_REACHED(); + break; + } + + m_unitType = static_cast<SVGAngleType>(unitType); +} + +} + +#endif // ENABLE(SVG) |