Chromium Code Reviews| Index: Source/core/svg/SVGLength.cpp |
| diff --git a/Source/core/svg/SVGLength.cpp b/Source/core/svg/SVGLength.cpp |
| index b503868a82efe1f95daa9e6be16deb7c26e651f7..365e87249f89652ffe0cd2b40e43f6d93df6a007 100644 |
| --- a/Source/core/svg/SVGLength.cpp |
| +++ b/Source/core/svg/SVGLength.cpp |
| @@ -26,6 +26,8 @@ |
| #include "bindings/core/v8/ExceptionState.h" |
| #include "core/SVGNames.h" |
| #include "core/css/CSSPrimitiveValue.h" |
| +#include "core/css/CSSValue.h" |
| +#include "core/css/parser/CSSParser.h" |
| #include "core/dom/ExceptionCode.h" |
| #include "core/svg/SVGAnimationElement.h" |
| #include "core/svg/SVGParserUtilities.h" |
| @@ -35,112 +37,18 @@ |
| 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(CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER)) |
|
fs
2015/05/29 08:09:42
I wonder if we could have this initially value sta
|
| , 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) |
| { |
| } |
| @@ -154,13 +62,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 +75,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 = CSSPrimitiveValue::create(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 +212,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->getCSSPrimitiveValue()->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 +270,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->getCSSPrimitiveValue()->primitiveType() : toLength->getCSSPrimitiveValue()->primitiveType(); |
| + animatedNumber = lengthContext.convertValueFromUserUnits(animatedNumber, unitMode(), newUnit); |
| + m_value = CSSPrimitiveValue::create(animatedNumber, newUnit); |
| } |
| float SVGLength::calculateDistance(PassRefPtrWillBeRawPtr<SVGPropertyBase> toValue, SVGElement* contextElement) |