| Index: Source/core/svg/SVGLength.cpp
|
| diff --git a/Source/core/svg/SVGLength.cpp b/Source/core/svg/SVGLength.cpp
|
| index b503868a82efe1f95daa9e6be16deb7c26e651f7..fab52d2d262b9e3eb96fa5162e4a3d596446c9b3 100644
|
| --- a/Source/core/svg/SVGLength.cpp
|
| +++ b/Source/core/svg/SVGLength.cpp
|
| @@ -26,6 +26,9 @@
|
| #include "bindings/core/v8/ExceptionState.h"
|
| #include "core/SVGNames.h"
|
| #include "core/css/CSSPrimitiveValue.h"
|
| +#include "core/css/CSSValue.h"
|
| +#include "core/css/CSSValuePool.h"
|
| +#include "core/css/parser/CSSParser.h"
|
| #include "core/dom/ExceptionCode.h"
|
| #include "core/svg/SVGAnimationElement.h"
|
| #include "core/svg/SVGParserUtilities.h"
|
| @@ -35,115 +38,27 @@
|
|
|
| namespace blink {
|
|
|
| -namespace {
|
| -
|
| -inline const char* lengthTypeToString(SVGLengthType type)
|
| -{
|
| - switch (type) {
|
| - case LengthTypeUnknown:
|
| - case LengthTypeNumber:
|
| - return "";
|
| - case LengthTypePercentage:
|
| - return "%";
|
| - case LengthTypeEMS:
|
| - return "em";
|
| - case LengthTypeEXS:
|
| - return "ex";
|
| - case LengthTypePX:
|
| - return "px";
|
| - case LengthTypeCM:
|
| - return "cm";
|
| - case LengthTypeMM:
|
| - return "mm";
|
| - case LengthTypeIN:
|
| - return "in";
|
| - case LengthTypePT:
|
| - return "pt";
|
| - case LengthTypePC:
|
| - return "pc";
|
| - case LengthTypeREMS:
|
| - return "rem";
|
| - case LengthTypeCHS:
|
| - return "ch";
|
| - }
|
| -
|
| - ASSERT_NOT_REACHED();
|
| - return "";
|
| -}
|
| -
|
| -template<typename CharType>
|
| -SVGLengthType stringToLengthType(const CharType*& ptr, const CharType* end)
|
| -{
|
| - if (ptr == end)
|
| - return LengthTypeNumber;
|
| -
|
| - SVGLengthType type = LengthTypeUnknown;
|
| - const CharType firstChar = *ptr++;
|
| -
|
| - if (firstChar == '%') {
|
| - type = LengthTypePercentage;
|
| - } else if (isHTMLSpace<CharType>(firstChar)) {
|
| - type = LengthTypeNumber;
|
| - } else if (ptr < end) {
|
| - const CharType secondChar = *ptr++;
|
| -
|
| - if (firstChar == 'p') {
|
| - if (secondChar == 'x')
|
| - type = LengthTypePX;
|
| - if (secondChar == 't')
|
| - type = LengthTypePT;
|
| - if (secondChar == 'c')
|
| - type = LengthTypePC;
|
| - } else if (firstChar == 'e') {
|
| - if (secondChar == 'm')
|
| - type = LengthTypeEMS;
|
| - if (secondChar == 'x')
|
| - type = LengthTypeEXS;
|
| - } else if (firstChar == 'r') {
|
| - if (secondChar == 'e' && ptr < end) {
|
| - const CharType thirdChar = *ptr++;
|
| - if (thirdChar == 'm')
|
| - type = LengthTypeREMS;
|
| - }
|
| - } else if (firstChar == 'c') {
|
| - if (secondChar == 'h')
|
| - type = LengthTypeCHS;
|
| - if (secondChar == 'm')
|
| - type = LengthTypeCM;
|
| - } else if (firstChar == 'm' && secondChar == 'm') {
|
| - type = LengthTypeMM;
|
| - } else if (firstChar == 'i' && secondChar == 'n') {
|
| - type = LengthTypeIN;
|
| - } else if (isHTMLSpace<CharType>(firstChar) && isHTMLSpace<CharType>(secondChar)) {
|
| - type = LengthTypeNumber;
|
| - }
|
| - }
|
| -
|
| - if (!skipOptionalSVGSpaces(ptr, end))
|
| - return type;
|
| -
|
| - return LengthTypeUnknown;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| SVGLength::SVGLength(SVGLengthMode mode)
|
| : SVGPropertyBase(classType())
|
| - , m_valueInSpecifiedUnits(0)
|
| + , m_value(cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER))
|
| , m_unitMode(static_cast<unsigned>(mode))
|
| - , m_unitType(LengthTypeNumber)
|
| {
|
| ASSERT(unitMode() == mode);
|
| }
|
|
|
| SVGLength::SVGLength(const SVGLength& o)
|
| : SVGPropertyBase(classType())
|
| - , m_valueInSpecifiedUnits(o.m_valueInSpecifiedUnits)
|
| + , m_value(o.m_value)
|
| , m_unitMode(o.m_unitMode)
|
| - , m_unitType(o.m_unitType)
|
| {
|
| }
|
|
|
| +DEFINE_TRACE(SVGLength)
|
| +{
|
| + visitor->trace(m_value);
|
| + SVGPropertyBase::trace(visitor);
|
| +}
|
| +
|
| PassRefPtrWillBeRawPtr<SVGLength> SVGLength::clone() const
|
| {
|
| return adoptRefWillBeNoop(new SVGLength(*this));
|
| @@ -154,13 +69,11 @@ PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGLength::cloneForAnimation(const Strin
|
| RefPtrWillBeRawPtr<SVGLength> length = create();
|
|
|
| length->m_unitMode = m_unitMode;
|
| - length->m_unitType = m_unitType;
|
|
|
| TrackExceptionState exceptionState;
|
| length->setValueAsString(value, exceptionState);
|
| if (exceptionState.hadException()) {
|
| - length->m_unitType = LengthTypeNumber;
|
| - length->m_valueInSpecifiedUnits = 0;
|
| + length->m_value = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER);
|
| }
|
|
|
| return length.release();
|
| @@ -169,216 +82,102 @@ PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGLength::cloneForAnimation(const Strin
|
| bool SVGLength::operator==(const SVGLength& other) const
|
| {
|
| return m_unitMode == other.m_unitMode
|
| - && m_unitType == other.m_unitType
|
| - && m_valueInSpecifiedUnits == other.m_valueInSpecifiedUnits;
|
| + && m_value == other.m_value;
|
| }
|
|
|
| float SVGLength::value(const SVGLengthContext& context) const
|
| {
|
| - return context.convertValueToUserUnits(m_valueInSpecifiedUnits, unitMode(), unitType());
|
| + return context.convertValueToUserUnits(m_value->getFloatValue(), unitMode(), m_value->primitiveType());
|
| }
|
|
|
| void SVGLength::setValue(float value, const SVGLengthContext& context)
|
| {
|
| - m_valueInSpecifiedUnits = context.convertValueFromUserUnits(value, unitMode(), unitType());
|
| + m_value = CSSPrimitiveValue::create(
|
| + context.convertValueFromUserUnits(value, unitMode(), m_value->primitiveType()),
|
| + m_value->primitiveType());
|
| }
|
|
|
| -void SVGLength::setUnitType(SVGLengthType type)
|
| +void SVGLength::setUnitType(CSSPrimitiveValue::UnitType type)
|
| {
|
| - ASSERT(type != LengthTypeUnknown && type <= LengthTypeCHS);
|
| - m_unitType = type;
|
| + ASSERT(type != CSSPrimitiveValue::CSS_UNKNOWN && (type <= CSSPrimitiveValue::CSS_PC || type == CSSPrimitiveValue::CSS_CHS || type == CSSPrimitiveValue::CSS_REMS));
|
| + m_value = CSSPrimitiveValue::create(m_value->getFloatValue(), type);
|
| }
|
|
|
| float SVGLength::valueAsPercentage() const
|
| {
|
| // LengthTypePercentage is represented with 100% = 100.0. Good for accuracy but could eventually be changed.
|
| - if (m_unitType == LengthTypePercentage) {
|
| + if (m_value->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) {
|
| // Note: This division is a source of floating point inaccuracy.
|
| - return m_valueInSpecifiedUnits / 100;
|
| + return m_value->getFloatValue() / 100;
|
| }
|
|
|
| - return m_valueInSpecifiedUnits;
|
| + return m_value->getFloatValue();
|
| }
|
|
|
| float SVGLength::valueAsPercentage100() const
|
| {
|
| // LengthTypePercentage is represented with 100% = 100.0. Good for accuracy but could eventually be changed.
|
| - if (m_unitType == LengthTypePercentage)
|
| - return m_valueInSpecifiedUnits;
|
| + if (m_value->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
|
| + return m_value->getFloatValue();
|
|
|
| - return m_valueInSpecifiedUnits * 100;
|
| + return m_value->getFloatValue() * 100;
|
| }
|
|
|
| float SVGLength::scaleByPercentage(float input) const
|
| {
|
| - float result = input * m_valueInSpecifiedUnits;
|
| - if (m_unitType == LengthTypePercentage) {
|
| + float result = input * m_value->getFloatValue();
|
| + if (m_value->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) {
|
| // Delaying division by 100 as long as possible since it introduces floating point errors.
|
| result = result / 100;
|
| }
|
| return result;
|
| }
|
|
|
| -template<typename CharType>
|
| -static bool parseValueInternal(const String& string, float& convertedNumber, SVGLengthType& type)
|
| -{
|
| - const CharType* ptr = string.getCharacters<CharType>();
|
| - const CharType* end = ptr + string.length();
|
| -
|
| - if (!parseNumber(ptr, end, convertedNumber, AllowLeadingWhitespace))
|
| - return false;
|
| -
|
| - type = stringToLengthType(ptr, end);
|
| - ASSERT(ptr <= end);
|
| - if (type == LengthTypeUnknown)
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| void SVGLength::setValueAsString(const String& string, ExceptionState& exceptionState)
|
| {
|
| if (string.isEmpty()) {
|
| - m_unitType = LengthTypeNumber;
|
| - m_valueInSpecifiedUnits = 0;
|
| + m_value = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER);
|
| return;
|
| }
|
|
|
| - float convertedNumber = 0;
|
| - SVGLengthType type = LengthTypeUnknown;
|
| -
|
| - bool success = string.is8Bit() ?
|
| - parseValueInternal<LChar>(string, convertedNumber, type) :
|
| - parseValueInternal<UChar>(string, convertedNumber, type);
|
| -
|
| - if (!success) {
|
| + CSSParserContext svgParserContext(SVGAttributeMode, 0);
|
| + RefPtrWillBeRawPtr<CSSValue> parsed = CSSParser::parseSingleValue(CSSPropertyX, string, svgParserContext);
|
| + if (!parsed || !parsed->isPrimitiveValue()) {
|
| exceptionState.throwDOMException(SyntaxError, "The value provided ('" + string + "') is invalid.");
|
| return;
|
| }
|
|
|
| - m_unitType = type;
|
| - m_valueInSpecifiedUnits = convertedNumber;
|
| + ASSERT(parsed->isPrimitiveValue());
|
| + m_value = toCSSPrimitiveValue(parsed.get());
|
| }
|
|
|
| String SVGLength::valueAsString() const
|
| {
|
| - return String::number(m_valueInSpecifiedUnits) + lengthTypeToString(unitType());
|
| + return m_value->customCSSText();
|
| }
|
|
|
| -void SVGLength::newValueSpecifiedUnits(SVGLengthType type, float value)
|
| +void SVGLength::newValueSpecifiedUnits(CSSPrimitiveValue::UnitType type, float value)
|
| {
|
| - setUnitType(type);
|
| - m_valueInSpecifiedUnits = value;
|
| + m_value = CSSPrimitiveValue::create(value, type);
|
| }
|
|
|
| -void SVGLength::convertToSpecifiedUnits(SVGLengthType type, const SVGLengthContext& context)
|
| +void SVGLength::convertToSpecifiedUnits(CSSPrimitiveValue::UnitType type, const SVGLengthContext& context)
|
| {
|
| - ASSERT(type != LengthTypeUnknown && type <= LengthTypeCHS);
|
| -
|
| + ASSERT(type != CSSPrimitiveValue::CSS_UNKNOWN && (type <= CSSPrimitiveValue::CSS_PC || type == CSSPrimitiveValue::CSS_CHS || type == CSSPrimitiveValue::CSS_REMS));
|
| float valueInUserUnits = value(context);
|
| - m_unitType = type;
|
| - setValue(valueInUserUnits, context);
|
| + m_value = CSSPrimitiveValue::create(
|
| + context.convertValueFromUserUnits(valueInUserUnits, unitMode(), type),
|
| + type);
|
| }
|
|
|
| PassRefPtrWillBeRawPtr<SVGLength> SVGLength::fromCSSPrimitiveValue(CSSPrimitiveValue* value)
|
| {
|
| ASSERT(value);
|
| -
|
| - SVGLengthType svgType;
|
| - switch (value->primitiveType()) {
|
| - case CSSPrimitiveValue::CSS_NUMBER:
|
| - svgType = LengthTypeNumber;
|
| - break;
|
| - case CSSPrimitiveValue::CSS_PERCENTAGE:
|
| - svgType = LengthTypePercentage;
|
| - break;
|
| - case CSSPrimitiveValue::CSS_EMS:
|
| - svgType = LengthTypeEMS;
|
| - break;
|
| - case CSSPrimitiveValue::CSS_EXS:
|
| - svgType = LengthTypeEXS;
|
| - break;
|
| - case CSSPrimitiveValue::CSS_PX:
|
| - svgType = LengthTypePX;
|
| - break;
|
| - case CSSPrimitiveValue::CSS_CM:
|
| - svgType = LengthTypeCM;
|
| - break;
|
| - case CSSPrimitiveValue::CSS_MM:
|
| - svgType = LengthTypeMM;
|
| - break;
|
| - case CSSPrimitiveValue::CSS_IN:
|
| - svgType = LengthTypeIN;
|
| - break;
|
| - case CSSPrimitiveValue::CSS_PT:
|
| - svgType = LengthTypePT;
|
| - break;
|
| - case CSSPrimitiveValue::CSS_REMS:
|
| - svgType = LengthTypeREMS;
|
| - break;
|
| - case CSSPrimitiveValue::CSS_CHS:
|
| - svgType = LengthTypeCHS;
|
| - break;
|
| - default:
|
| - ASSERT(value->primitiveType() == CSSPrimitiveValue::CSS_PC);
|
| - svgType = LengthTypePC;
|
| - break;
|
| - };
|
| -
|
| RefPtrWillBeRawPtr<SVGLength> length = SVGLength::create();
|
| - length->newValueSpecifiedUnits(svgType, value->getFloatValue());
|
| + length->m_value = value;
|
| return length.release();
|
| }
|
|
|
| -PassRefPtrWillBeRawPtr<CSSPrimitiveValue> SVGLength::toCSSPrimitiveValue(PassRefPtrWillBeRawPtr<SVGLength> passLength)
|
| -{
|
| - RefPtrWillBeRawPtr<SVGLength> length = passLength;
|
| -
|
| - CSSPrimitiveValue::UnitType cssType = CSSPrimitiveValue::CSS_UNKNOWN;
|
| - switch (length->unitType()) {
|
| - case LengthTypeUnknown:
|
| - break;
|
| - case LengthTypeNumber:
|
| - cssType = CSSPrimitiveValue::CSS_NUMBER;
|
| - break;
|
| - case LengthTypePercentage:
|
| - cssType = CSSPrimitiveValue::CSS_PERCENTAGE;
|
| - break;
|
| - case LengthTypeEMS:
|
| - cssType = CSSPrimitiveValue::CSS_EMS;
|
| - break;
|
| - case LengthTypeEXS:
|
| - cssType = CSSPrimitiveValue::CSS_EXS;
|
| - break;
|
| - case LengthTypePX:
|
| - cssType = CSSPrimitiveValue::CSS_PX;
|
| - break;
|
| - case LengthTypeCM:
|
| - cssType = CSSPrimitiveValue::CSS_CM;
|
| - break;
|
| - case LengthTypeMM:
|
| - cssType = CSSPrimitiveValue::CSS_MM;
|
| - break;
|
| - case LengthTypeIN:
|
| - cssType = CSSPrimitiveValue::CSS_IN;
|
| - break;
|
| - case LengthTypePT:
|
| - cssType = CSSPrimitiveValue::CSS_PT;
|
| - break;
|
| - case LengthTypePC:
|
| - cssType = CSSPrimitiveValue::CSS_PC;
|
| - break;
|
| - case LengthTypeREMS:
|
| - cssType = CSSPrimitiveValue::CSS_REMS;
|
| - break;
|
| - case LengthTypeCHS:
|
| - cssType = CSSPrimitiveValue::CSS_CHS;
|
| - break;
|
| - };
|
| -
|
| - return CSSPrimitiveValue::create(length->valueInSpecifiedUnits(), cssType);
|
| -}
|
| -
|
| SVGLengthMode SVGLength::lengthModeForAnimatedLengthAttribute(const QualifiedName& attrName)
|
| {
|
| typedef HashMap<QualifiedName, SVGLengthMode> LengthModeForLengthAttributeMap;
|
| @@ -420,26 +219,26 @@ PassRefPtrWillBeRawPtr<SVGLength> SVGLength::blend(PassRefPtrWillBeRawPtr<SVGLen
|
| {
|
| RefPtrWillBeRawPtr<SVGLength> from = passFrom;
|
|
|
| - SVGLengthType toType = unitType();
|
| - SVGLengthType fromType = from->unitType();
|
| + CSSPrimitiveValue::UnitType toType = m_value->primitiveType();
|
| + CSSPrimitiveValue::UnitType fromType = from->primitiveType();
|
| if ((from->isZero() && isZero())
|
| - || fromType == LengthTypeUnknown
|
| - || toType == LengthTypeUnknown
|
| - || (!from->isZero() && fromType != LengthTypePercentage && toType == LengthTypePercentage)
|
| - || (!isZero() && fromType == LengthTypePercentage && toType != LengthTypePercentage)
|
| - || (!from->isZero() && !isZero() && (fromType == LengthTypeEMS || fromType == LengthTypeEXS || fromType == LengthTypeREMS || fromType == LengthTypeCHS) && fromType != toType))
|
| + || fromType == CSSPrimitiveValue::CSS_UNKNOWN
|
| + || toType == CSSPrimitiveValue::CSS_UNKNOWN
|
| + || (!from->isZero() && fromType != CSSPrimitiveValue::CSS_PERCENTAGE && toType == CSSPrimitiveValue::CSS_PERCENTAGE)
|
| + || (!isZero() && fromType == CSSPrimitiveValue::CSS_PERCENTAGE && toType != CSSPrimitiveValue::CSS_PERCENTAGE)
|
| + || (!from->isZero() && !isZero() && (fromType == CSSPrimitiveValue::CSS_EMS || fromType == CSSPrimitiveValue::CSS_EXS || fromType == CSSPrimitiveValue::CSS_REMS || fromType == CSSPrimitiveValue::CSS_CHS) && fromType != toType))
|
| return clone();
|
|
|
| RefPtrWillBeRawPtr<SVGLength> length = create();
|
|
|
| - if (fromType == LengthTypePercentage || toType == LengthTypePercentage) {
|
| + if (fromType == CSSPrimitiveValue::CSS_PERCENTAGE || toType == CSSPrimitiveValue::CSS_PERCENTAGE) {
|
| float fromPercent = from->valueAsPercentage100();
|
| float toPercent = valueAsPercentage100();
|
| - length->newValueSpecifiedUnits(LengthTypePercentage, blink::blend(fromPercent, toPercent, progress));
|
| + length->newValueSpecifiedUnits(CSSPrimitiveValue::CSS_PERCENTAGE, blink::blend(fromPercent, toPercent, progress));
|
| return length;
|
| }
|
|
|
| - if (fromType == toType || from->isZero() || isZero() || fromType == LengthTypeEMS || fromType == LengthTypeEXS || fromType == LengthTypeREMS || fromType == LengthTypeCHS) {
|
| + if (fromType == toType || from->isZero() || isZero() || fromType == CSSPrimitiveValue::CSS_EMS || fromType == CSSPrimitiveValue::CSS_EXS || fromType == CSSPrimitiveValue::CSS_REMS || fromType == CSSPrimitiveValue::CSS_CHS) {
|
| float fromValue = from->valueInSpecifiedUnits();
|
| float toValue = valueInSpecifiedUnits();
|
| if (isZero())
|
| @@ -478,8 +277,10 @@ void SVGLength::calculateAnimatedValue(SVGAnimationElement* animationElement, fl
|
| animationElement->animateAdditiveNumber(percentage, repeatCount, fromLength->value(lengthContext), toLength->value(lengthContext), toAtEndOfDurationLength->value(lengthContext), animatedNumber);
|
|
|
| ASSERT(unitMode() == lengthModeForAnimatedLengthAttribute(animationElement->attributeName()));
|
| - m_unitType = percentage < 0.5 ? fromLength->unitType() : toLength->unitType();
|
| - setValue(animatedNumber, lengthContext);
|
| +
|
| + CSSPrimitiveValue::UnitType newUnit = percentage < 0.5 ? fromLength->primitiveType() : toLength->primitiveType();
|
| + animatedNumber = lengthContext.convertValueFromUserUnits(animatedNumber, unitMode(), newUnit);
|
| + m_value = CSSPrimitiveValue::create(animatedNumber, newUnit);
|
| }
|
|
|
| float SVGLength::calculateDistance(PassRefPtrWillBeRawPtr<SVGPropertyBase> toValue, SVGElement* contextElement)
|
|
|