| Index: third_party/WebKit/Source/core/svg/SVGLength.cpp
|
| diff --git a/third_party/WebKit/Source/core/svg/SVGLength.cpp b/third_party/WebKit/Source/core/svg/SVGLength.cpp
|
| index decc141174f4362309d65185a707f37e147b7b38..63ca653b78cf394d726146138760df55620f56e0 100644
|
| --- a/third_party/WebKit/Source/core/svg/SVGLength.cpp
|
| +++ b/third_party/WebKit/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::UnitType::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::UnitType::Number);
|
| }
|
|
|
| return length.release();
|
| @@ -168,116 +81,100 @@ 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;
|
| + return m_unitMode == other.m_unitMode && 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->typeWithCalcResolved());
|
| }
|
|
|
| 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->typeWithCalcResolved()),
|
| + m_value->typeWithCalcResolved());
|
| }
|
|
|
| -void SVGLength::setUnitType(SVGLengthType type)
|
| +void SVGLength::setUnitType(CSSPrimitiveValue::UnitType type)
|
| {
|
| - ASSERT(type != LengthTypeUnknown && type <= LengthTypeCHS);
|
| - m_unitType = type;
|
| + ASSERT(type != CSSPrimitiveValue::UnitType::Unknown
|
| + && (type <= CSSPrimitiveValue::UnitType::UserCoordinates
|
| + || type == CSSPrimitiveValue::UnitType::Chs
|
| + || type == CSSPrimitiveValue::UnitType::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->typeWithCalcResolved() == CSSPrimitiveValue::UnitType::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->typeWithCalcResolved() == CSSPrimitiveValue::UnitType::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->typeWithCalcResolved() == CSSPrimitiveValue::UnitType::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::UnitType::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::UnitType::Unknown
|
| + && (type <= CSSPrimitiveValue::UnitType::UserCoordinates
|
| + || type == CSSPrimitiveValue::UnitType::Chs
|
| + || type == CSSPrimitiveValue::UnitType::Rems));
|
|
|
| float valueInUserUnits = value(context);
|
| - m_unitType = type;
|
| - setValue(valueInUserUnits, context);
|
| + m_value = CSSPrimitiveValue::create(
|
| + context.convertValueFromUserUnits(valueInUserUnits, unitMode(), type),
|
| + type);
|
| }
|
|
|
| SVGLengthMode SVGLength::lengthModeForAnimatedLengthAttribute(const QualifiedName& attrName)
|
| @@ -323,7 +220,13 @@ void SVGLength::add(PassRefPtrWillBeRawPtr<SVGPropertyBase> other, SVGElement* c
|
| setValue(value(lengthContext) + toSVGLength(other)->value(lengthContext), lengthContext);
|
| }
|
|
|
| -void SVGLength::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, PassRefPtrWillBeRawPtr<SVGPropertyBase> fromValue, PassRefPtrWillBeRawPtr<SVGPropertyBase> toValue, PassRefPtrWillBeRawPtr<SVGPropertyBase> toAtEndOfDurationValue, SVGElement* contextElement)
|
| +void SVGLength::calculateAnimatedValue(SVGAnimationElement* animationElement,
|
| + float percentage,
|
| + unsigned repeatCount,
|
| + PassRefPtrWillBeRawPtr<SVGPropertyBase> fromValue,
|
| + PassRefPtrWillBeRawPtr<SVGPropertyBase> toValue,
|
| + PassRefPtrWillBeRawPtr<SVGPropertyBase> toAtEndOfDurationValue,
|
| + SVGElement* contextElement)
|
| {
|
| RefPtrWillBeRawPtr<SVGLength> fromLength = toSVGLength(fromValue);
|
| RefPtrWillBeRawPtr<SVGLength> toLength = toSVGLength(toValue);
|
| @@ -331,11 +234,14 @@ void SVGLength::calculateAnimatedValue(SVGAnimationElement* animationElement, fl
|
|
|
| SVGLengthContext lengthContext(contextElement);
|
| float animatedNumber = value(lengthContext);
|
| - animationElement->animateAdditiveNumber(percentage, repeatCount, fromLength->value(lengthContext), toLength->value(lengthContext), toAtEndOfDurationLength->value(lengthContext), animatedNumber);
|
| + 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->typeWithCalcResolved() : toLength->typeWithCalcResolved();
|
| + animatedNumber = lengthContext.convertValueFromUserUnits(animatedNumber, unitMode(), newUnit);
|
| + m_value = CSSPrimitiveValue::create(animatedNumber, newUnit);
|
| }
|
|
|
| float SVGLength::calculateDistance(PassRefPtrWillBeRawPtr<SVGPropertyBase> toValue, SVGElement* contextElement)
|
|
|