#include "config.h"
#include "SVGAngleValue.h"
#include "ExceptionCode.h"
#include "SVGParserUtilities.h"
#include <wtf/MathExtras.h>
#include <wtf/text/StringView.h>
namespace WebCore {
float SVGAngleValue::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 SVGAngleValue::setValue(float value)
{
switch (m_unitType) {
case SVG_ANGLETYPE_GRAD:
m_valueInSpecifiedUnits = deg2grad(value);
return;
case SVG_ANGLETYPE_RAD:
m_valueInSpecifiedUnits = deg2rad(value);
return;
case SVG_ANGLETYPE_UNSPECIFIED:
case SVG_ANGLETYPE_UNKNOWN:
case SVG_ANGLETYPE_DEG:
m_valueInSpecifiedUnits = value;
return;
}
ASSERT_NOT_REACHED();
}
String SVGAngleValue::valueAsString() const
{
switch (m_unitType) {
case SVG_ANGLETYPE_DEG:
return String::number(m_valueInSpecifiedUnits) + "deg";
case SVG_ANGLETYPE_RAD:
return String::number(m_valueInSpecifiedUnits) + "rad";
case SVG_ANGLETYPE_GRAD:
return String::number(m_valueInSpecifiedUnits) + "grad";
case SVG_ANGLETYPE_UNSPECIFIED:
case SVG_ANGLETYPE_UNKNOWN:
return String::number(m_valueInSpecifiedUnits);
}
ASSERT_NOT_REACHED();
return String();
}
static inline SVGAngleValue::Type parseAngleType(const UChar* ptr, const UChar* end)
{
switch (end - ptr) {
case 0:
return SVGAngleValue::SVG_ANGLETYPE_UNSPECIFIED;
case 3:
if (ptr[0] == 'd' && ptr[1] == 'e' && ptr[2] == 'g')
return SVGAngleValue::SVG_ANGLETYPE_DEG;
if (ptr[0] == 'r' && ptr[1] == 'a' && ptr[2] == 'd')
return SVGAngleValue::SVG_ANGLETYPE_RAD;
break;
case 4:
if (ptr[0] == 'g' && ptr[1] == 'r' && ptr[2] == 'a' && ptr[3] == 'd')
return SVGAngleValue::SVG_ANGLETYPE_GRAD;
break;
}
return SVGAngleValue::SVG_ANGLETYPE_UNKNOWN;
}
ExceptionOr<void> SVGAngleValue::setValueAsString(const String& value)
{
if (value.isEmpty()) {
m_unitType = SVG_ANGLETYPE_UNSPECIFIED;
return { };
}
auto upconvertedCharacters = StringView(value).upconvertedCharacters();
const UChar* ptr = upconvertedCharacters;
const UChar* end = ptr + value.length();
float valueInSpecifiedUnits = 0;
if (!parseNumber(ptr, end, valueInSpecifiedUnits, false))
return Exception { SYNTAX_ERR };
auto unitType = parseAngleType(ptr, end);
if (unitType == SVG_ANGLETYPE_UNKNOWN)
return Exception { SYNTAX_ERR };
m_unitType = unitType;
m_valueInSpecifiedUnits = valueInSpecifiedUnits;
return { };
}
ExceptionOr<void> SVGAngleValue::newValueSpecifiedUnits(unsigned short unitType, float valueInSpecifiedUnits)
{
if (unitType == SVG_ANGLETYPE_UNKNOWN || unitType > SVG_ANGLETYPE_GRAD)
return Exception { NOT_SUPPORTED_ERR };
m_unitType = static_cast<Type>(unitType);
m_valueInSpecifiedUnits = valueInSpecifiedUnits;
return { };
}
ExceptionOr<void> SVGAngleValue::convertToSpecifiedUnits(unsigned short unitType)
{
if (unitType == SVG_ANGLETYPE_UNKNOWN || m_unitType == SVG_ANGLETYPE_UNKNOWN || unitType > SVG_ANGLETYPE_GRAD)
return Exception { NOT_SUPPORTED_ERR };
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:
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:
case SVG_ANGLETYPE_DEG:
break;
case SVG_ANGLETYPE_UNKNOWN:
ASSERT_NOT_REACHED();
break;
}
break;
case SVG_ANGLETYPE_UNKNOWN:
ASSERT_NOT_REACHED();
break;
}
m_unitType = static_cast<Type>(unitType);
return { };
}
}