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) |