summaryrefslogtreecommitdiffstats
path: root/WebCore/css/CSSPrimitiveValue.cpp
diff options
context:
space:
mode:
authorRussell Brenner <russellbrenner@google.com>2010-11-18 17:33:13 -0800
committerRussell Brenner <russellbrenner@google.com>2010-12-02 13:47:21 -0800
commit6b70adc33054f8aee8c54d0f460458a9df11b8a5 (patch)
tree103a13998c33944d6ab3b8318c509a037e639460 /WebCore/css/CSSPrimitiveValue.cpp
parentbdf4ebc8e70b2d221b6ee7a65660918ecb1d33aa (diff)
downloadexternal_webkit-6b70adc33054f8aee8c54d0f460458a9df11b8a5.zip
external_webkit-6b70adc33054f8aee8c54d0f460458a9df11b8a5.tar.gz
external_webkit-6b70adc33054f8aee8c54d0f460458a9df11b8a5.tar.bz2
Merge WebKit at r72274: Initial merge by git.
Change-Id: Ie51f0b4a16da82942bd516dce59cfb79ebbe25fb
Diffstat (limited to 'WebCore/css/CSSPrimitiveValue.cpp')
-rw-r--r--WebCore/css/CSSPrimitiveValue.cpp201
1 files changed, 135 insertions, 66 deletions
diff --git a/WebCore/css/CSSPrimitiveValue.cpp b/WebCore/css/CSSPrimitiveValue.cpp
index 065c244..ce1b87b 100644
--- a/WebCore/css/CSSPrimitiveValue.cpp
+++ b/WebCore/css/CSSPrimitiveValue.cpp
@@ -36,6 +36,7 @@
#include "RenderStyle.h"
#include <wtf/ASCIICType.h>
#include <wtf/DecimalNumber.h>
+#include <wtf/MathExtras.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringBuffer.h>
@@ -47,6 +48,38 @@ using namespace WTF;
namespace WebCore {
+static CSSPrimitiveValue::UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes type)
+{
+ // Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions
+ // between CSS_PX and relative lengths (see cssPixelsPerInch comment in CSSHelper.h for the topic treatment).
+ switch (type) {
+ case CSSPrimitiveValue::CSS_NUMBER:
+ return CSSPrimitiveValue::UNumber;
+ case CSSPrimitiveValue::CSS_PERCENTAGE:
+ return CSSPrimitiveValue::UPercent;
+ case CSSPrimitiveValue::CSS_PX:
+ case CSSPrimitiveValue::CSS_CM:
+ case CSSPrimitiveValue::CSS_MM:
+ case CSSPrimitiveValue::CSS_IN:
+ case CSSPrimitiveValue::CSS_PT:
+ case CSSPrimitiveValue::CSS_PC:
+ return CSSPrimitiveValue::ULength;
+ case CSSPrimitiveValue::CSS_MS:
+ case CSSPrimitiveValue::CSS_S:
+ return CSSPrimitiveValue::UTime;
+ case CSSPrimitiveValue::CSS_DEG:
+ case CSSPrimitiveValue::CSS_RAD:
+ case CSSPrimitiveValue::CSS_GRAD:
+ case CSSPrimitiveValue::CSS_TURN:
+ return CSSPrimitiveValue::UAngle;
+ case CSSPrimitiveValue::CSS_HZ:
+ case CSSPrimitiveValue::CSS_KHZ:
+ return CSSPrimitiveValue::UFrequency;
+ default:
+ return CSSPrimitiveValue::UOther;
+ }
+}
+
typedef HashMap<const CSSPrimitiveValue*, String> CSSTextCache;
static CSSTextCache& cssTextCache()
{
@@ -55,7 +88,7 @@ static CSSTextCache& cssTextCache()
}
// A more stylish solution than sharing would be to turn CSSPrimitiveValue (or CSSValues in general) into non-virtual,
-// non-refcounted simple type with value semantics. In practice these sharing tricks get similar memory benefits
+// non-refcounted simple type with value semantics. In practice these sharing tricks get similar memory benefits
// with less need for refactoring.
inline PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createUncachedIdentifier(int identifier)
@@ -274,7 +307,6 @@ void CSSPrimitiveValue::cleanup()
case CSS_STRING:
case CSS_URI:
case CSS_ATTR:
- case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
case CSS_PARSER_HEXCOLOR:
if (m_value.string)
m_value.string->deref();
@@ -408,26 +440,24 @@ double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* r
return zoomedResult;
}
-void CSSPrimitiveValue::setFloatValue(unsigned short unitType, double floatValue, ExceptionCode& ec)
+void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionCode& ec)
{
- ec = 0;
-
- if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION) {
- ec = INVALID_ACCESS_ERR;
- return;
- }
-
- cleanup();
-
- m_value.num = floatValue;
- m_type = unitType;
+ // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
+ // No other engine supports mutating style through this API. Computed style is always read-only anyway.
+ // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
+ ec = NO_MODIFICATION_ALLOWED_ERR;
}
-static double scaleFactorForConversion(unsigned short unitType)
+static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType)
{
double factor = 1.0;
+ // FIXME: the switch can be replaced by an array of scale factors.
switch (unitType) {
+ // These are "canonical" units in their respective categories.
case CSSPrimitiveValue::CSS_PX:
+ case CSSPrimitiveValue::CSS_DEG:
+ case CSSPrimitiveValue::CSS_MS:
+ case CSSPrimitiveValue::CSS_HZ:
break;
case CSSPrimitiveValue::CSS_CM:
factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
@@ -444,6 +474,19 @@ static double scaleFactorForConversion(unsigned short unitType)
case CSSPrimitiveValue::CSS_PC:
factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt
break;
+ case CSSPrimitiveValue::CSS_RAD:
+ factor = 180 / piDouble;
+ break;
+ case CSSPrimitiveValue::CSS_GRAD:
+ factor = 0.9;
+ break;
+ case CSSPrimitiveValue::CSS_TURN:
+ factor = 360;
+ break;
+ case CSSPrimitiveValue::CSS_S:
+ case CSSPrimitiveValue::CSS_KHZ:
+ factor = 1000;
+ break;
default:
break;
}
@@ -451,69 +494,103 @@ static double scaleFactorForConversion(unsigned short unitType)
return factor;
}
-double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec)
+double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec) const
{
- ec = 0;
- if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION) {
+ double result = 0;
+ bool success = getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
+ if (!success) {
ec = INVALID_ACCESS_ERR;
return 0.0;
}
- if (unitType == m_type || unitType < CSS_PX || unitType > CSS_PC)
- return m_value.num;
+ ec = 0;
+ return result;
+}
+
+double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) const
+{
+ double result = 0;
+ getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
+ return result;
+}
+
+CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category)
+{
+ // The canonical unit type is chosen according to the way CSSParser::validUnit() chooses the default unit
+ // in each category (based on unitflags).
+ switch (category) {
+ case UNumber:
+ return CSS_NUMBER;
+ case ULength:
+ return CSS_PX;
+ case UPercent:
+ return CSS_UNKNOWN; // Cannot convert between numbers and percent.
+ case UTime:
+ return CSS_MS;
+ case UAngle:
+ return CSS_DEG;
+ case UFrequency:
+ return CSS_HZ;
+ default:
+ return CSS_UNKNOWN;
+ }
+}
- double convertedValue = m_value.num;
+bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, double* result) const
+{
+ if (m_type < CSS_NUMBER || (m_type > CSS_DIMENSION && m_type < CSS_TURN) || requestedUnitType < CSS_NUMBER || (requestedUnitType > CSS_DIMENSION && requestedUnitType < CSS_TURN))
+ return false;
+ if (requestedUnitType == m_type || requestedUnitType == CSS_DIMENSION) {
+ *result = m_value.num;
+ return true;
+ }
- // First convert the value from m_type into CSSPixels
- double factor = scaleFactorForConversion(m_type);
- convertedValue *= factor;
+ UnitTypes sourceUnitType = static_cast<UnitTypes>(m_type);
+ UnitCategory sourceCategory = unitCategory(sourceUnitType);
+ ASSERT(sourceCategory != UOther);
- // Now convert from CSSPixels to the specified unitType
- factor = scaleFactorForConversion(unitType);
- convertedValue /= factor;
+ UnitTypes targetUnitType = requestedUnitType;
+ UnitCategory targetCategory = unitCategory(targetUnitType);
+ ASSERT(targetCategory != UOther);
- return convertedValue;
-}
+ // Cannot convert between unrelated unit categories if one of them is not UNumber.
+ if (sourceCategory != targetCategory && sourceCategory != UNumber && targetCategory != UNumber)
+ return false;
-double CSSPrimitiveValue::getDoubleValue(unsigned short unitType)
-{
- if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION)
- return 0;
+ if (targetCategory == UNumber) {
+ // We interpret conversion to CSS_NUMBER as conversion to a canonical unit in this value's category.
+ targetUnitType = canonicalUnitTypeForCategory(sourceCategory);
+ if (targetUnitType == CSS_UNKNOWN)
+ return false;
+ }
- if (unitType == m_type || unitType < CSS_PX || unitType > CSS_PC)
- return m_value.num;
+ if (sourceUnitType == CSS_NUMBER) {
+ // We interpret conversion from CSS_NUMBER in the same way as CSSParser::validUnit() while using non-strict mode.
+ sourceUnitType = canonicalUnitTypeForCategory(targetCategory);
+ if (sourceUnitType == CSS_UNKNOWN)
+ return false;
+ }
double convertedValue = m_value.num;
- // First convert the value from m_type into CSSPixels
- double factor = scaleFactorForConversion(m_type);
+ // First convert the value from m_type to canonical type.
+ double factor = conversionToCanonicalUnitsScaleFactor(sourceUnitType);
convertedValue *= factor;
- // Now convert from CSSPixels to the specified unitType
- factor = scaleFactorForConversion(unitType);
+ // Now convert from canonical type to the target unitType.
+ factor = conversionToCanonicalUnitsScaleFactor(targetUnitType);
convertedValue /= factor;
- return convertedValue;
+ *result = convertedValue;
+ return true;
}
-
-void CSSPrimitiveValue::setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode& ec)
+void CSSPrimitiveValue::setStringValue(unsigned short, const String&, ExceptionCode& ec)
{
- ec = 0;
-
- if (m_type < CSS_STRING || m_type > CSS_ATTR || stringType < CSS_STRING || stringType > CSS_ATTR) {
- ec = INVALID_ACCESS_ERR;
- return;
- }
-
- cleanup();
-
- if (stringType != CSS_IDENT) {
- m_value.string = stringValue.impl();
- m_value.string->ref();
- m_type = stringType;
- }
- // FIXME: parse ident
+ // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
+ // No other engine supports mutating style through this API. Computed style is always read-only anyway.
+ // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
+ ec = NO_MODIFICATION_ALLOWED_ERR;
}
String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const
@@ -523,7 +600,6 @@ String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const
case CSS_STRING:
case CSS_ATTR:
case CSS_URI:
- case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
return m_value.string;
case CSS_IDENT:
return valueOrPropertyName(m_value.ident);
@@ -541,7 +617,6 @@ String CSSPrimitiveValue::getStringValue() const
case CSS_STRING:
case CSS_ATTR:
case CSS_URI:
- case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
return m_value.string;
case CSS_IDENT:
return valueOrPropertyName(m_value.ident);
@@ -608,7 +683,7 @@ bool CSSPrimitiveValue::parseString(const String& /*string*/, bool /*strict*/)
return false;
}
-int CSSPrimitiveValue::getIdent()
+int CSSPrimitiveValue::getIdent() const
{
if (m_type != CSS_IDENT)
return 0;
@@ -823,11 +898,6 @@ String CSSPrimitiveValue::cssText() const
}
break;
#endif
- case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
- text = "-webkit-var(";
- text += m_value.string;
- text += ")";
- break;
case CSS_PARSER_OPERATOR: {
char c = static_cast<char>(m_value.ident);
text = String(&c, 1U);
@@ -877,7 +947,6 @@ CSSParserValue CSSPrimitiveValue::parserValue() const
break;
case CSS_STRING:
case CSS_URI:
- case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
case CSS_PARSER_HEXCOLOR:
value.string.characters = const_cast<UChar*>(m_value.string->characters());
value.string.length = m_value.string->length();