| Index: Source/core/css/CSSPrimitiveValue.h
|
| diff --git a/Source/core/css/CSSPrimitiveValue.h b/Source/core/css/CSSPrimitiveValue.h
|
| index 3f7b65ed10fa47ffdcee0ea063f26b3bc7687402..1820b226d24c511e3c90c80db830cb3cfecda590 100644
|
| --- a/Source/core/css/CSSPrimitiveValue.h
|
| +++ b/Source/core/css/CSSPrimitiveValue.h
|
| @@ -31,6 +31,7 @@
|
| #include "wtf/Forward.h"
|
| #include "wtf/MathExtras.h"
|
| #include "wtf/PassRefPtr.h"
|
| +#include "wtf/RefCounted.h"
|
| #include "wtf/text/StringHash.h"
|
|
|
| namespace blink {
|
| @@ -70,56 +71,58 @@ template<> inline float roundForImpreciseConversion(double value)
|
| // CSSPrimitiveValues are immutable. This class has manual ref-counting
|
| // of unioned types and does not have the code necessary
|
| // to handle any kind of mutations.
|
| +// In some cases, CSSPrimitiveValue is a tagged pointer. If isTaggedPtr() returns
|
| +// true, |this| is an invalid pointer and member variables should not be accessed.
|
| class CORE_EXPORT CSSPrimitiveValue : public CSSValue {
|
| public:
|
| enum UnitType {
|
| - CSS_UNKNOWN = 0,
|
| - CSS_NUMBER = 1,
|
| - CSS_PERCENTAGE = 2,
|
| - CSS_EMS = 3,
|
| - CSS_EXS = 4,
|
| - CSS_PX = 5,
|
| - CSS_CM = 6,
|
| - CSS_MM = 7,
|
| - CSS_IN = 8,
|
| - CSS_PT = 9,
|
| - CSS_PC = 10,
|
| - CSS_DEG = 11,
|
| - CSS_RAD = 12,
|
| - CSS_GRAD = 13,
|
| - CSS_MS = 14,
|
| - CSS_S = 15,
|
| - CSS_HZ = 16,
|
| - CSS_KHZ = 17,
|
| - CSS_CUSTOM_IDENT = 19,
|
| - CSS_URI = 20,
|
| - CSS_IDENT = 21,
|
| - CSS_ATTR = 22,
|
| - CSS_COUNTER = 23,
|
| - CSS_RECT = 24,
|
| - CSS_RGBCOLOR = 25,
|
| - CSS_VW = 26,
|
| - CSS_VH = 27,
|
| - CSS_VMIN = 28,
|
| - CSS_VMAX = 29,
|
| - CSS_DPPX = 30,
|
| - CSS_DPI = 31,
|
| - CSS_DPCM = 32,
|
| - CSS_FR = 33,
|
| - CSS_INTEGER = 34,
|
| - CSS_PAIR = 100,
|
| - CSS_TURN = 107,
|
| - CSS_REMS = 108,
|
| - CSS_CHS = 109,
|
| - CSS_SHAPE = 111,
|
| - CSS_QUAD = 112,
|
| - CSS_CALC = 113,
|
| - CSS_CALC_PERCENTAGE_WITH_NUMBER = 114,
|
| - CSS_CALC_PERCENTAGE_WITH_LENGTH = 115,
|
| - CSS_STRING = 116,
|
| - CSS_PROPERTY_ID = 117,
|
| - CSS_VALUE_ID = 118,
|
| - CSS_QEM = 119
|
| + CSS_UNKNOWN,
|
| + CSS_NUMBER,
|
| + CSS_PERCENTAGE,
|
| + CSS_EMS,
|
| + CSS_EXS,
|
| + CSS_PX,
|
| + CSS_CM,
|
| + CSS_MM,
|
| + CSS_IN,
|
| + CSS_PT,
|
| + CSS_PC,
|
| + CSS_DEG,
|
| + CSS_RAD,
|
| + CSS_GRAD,
|
| + CSS_MS,
|
| + CSS_S,
|
| + CSS_HZ,
|
| + CSS_KHZ,
|
| + CSS_CUSTOM_IDENT,
|
| + CSS_URI,
|
| + CSS_IDENT,
|
| + CSS_ATTR,
|
| + CSS_COUNTER,
|
| + CSS_RECT,
|
| + CSS_RGBCOLOR,
|
| + CSS_VW,
|
| + CSS_VH,
|
| + CSS_VMIN,
|
| + CSS_VMAX,
|
| + CSS_DPPX,
|
| + CSS_DPI,
|
| + CSS_DPCM,
|
| + CSS_FR,
|
| + CSS_INTEGER,
|
| + CSS_PAIR,
|
| + CSS_TURN,
|
| + CSS_REMS,
|
| + CSS_CHS,
|
| + CSS_SHAPE,
|
| + CSS_QUAD,
|
| + CSS_CALC,
|
| + CSS_CALC_PERCENTAGE_WITH_NUMBER,
|
| + CSS_CALC_PERCENTAGE_WITH_LENGTH,
|
| + CSS_STRING,
|
| + CSS_PROPERTY_ID,
|
| + CSS_VALUE_ID,
|
| + CSS_QEM
|
| };
|
|
|
| enum LengthUnitType {
|
| @@ -138,6 +141,21 @@ public:
|
| LengthUnitTypeCount,
|
| };
|
|
|
| + union CSSPrimitiveValueData {
|
| + CSSPropertyID propertyID;
|
| + CSSValueID valueID;
|
| + double num;
|
| + StringImpl* string;
|
| + RGBA32 rgbcolor;
|
| + // FIXME: oilpan: Should be members, but no support for members in unions. Just trace the raw ptr for now.
|
| + CSSBasicShape* shape;
|
| + CSSCalcValue* calc;
|
| + Counter* counter;
|
| + Pair* pair;
|
| + Rect* rect;
|
| + Quad* quad;
|
| + };
|
| +
|
| typedef Vector<double, CSSPrimitiveValue::LengthUnitTypeCount> CSSLengthArray;
|
| typedef BitVector CSSLengthTypeArray;
|
|
|
| @@ -163,22 +181,22 @@ public:
|
|
|
| bool isAngle() const
|
| {
|
| - return m_primitiveUnitType == CSS_DEG
|
| - || m_primitiveUnitType == CSS_RAD
|
| - || m_primitiveUnitType == CSS_GRAD
|
| - || m_primitiveUnitType == CSS_TURN;
|
| + return type() == CSS_DEG
|
| + || type() == CSS_RAD
|
| + || type() == CSS_GRAD
|
| + || type() == CSS_TURN;
|
| }
|
| - bool isAttr() const { return m_primitiveUnitType == CSS_ATTR; }
|
| - bool isCounter() const { return m_primitiveUnitType == CSS_COUNTER; }
|
| - bool isCustomIdent() const { return m_primitiveUnitType == CSS_CUSTOM_IDENT; }
|
| + bool isAttr() const { return type() == CSS_ATTR; }
|
| + bool isCounter() const { return type() == CSS_COUNTER; }
|
| + bool isCustomIdent() const { return type() == CSS_CUSTOM_IDENT; }
|
| bool isFontRelativeLength() const
|
| {
|
| - return m_primitiveUnitType == CSS_EMS
|
| - || m_primitiveUnitType == CSS_EXS
|
| - || m_primitiveUnitType == CSS_REMS
|
| - || m_primitiveUnitType == CSS_CHS;
|
| + return type() == CSS_EMS
|
| + || type() == CSS_EXS
|
| + || type() == CSS_REMS
|
| + || type() == CSS_CHS;
|
| }
|
| - bool isViewportPercentageLength() const { return isViewportPercentageLength(static_cast<UnitType>(m_primitiveUnitType)); }
|
| + bool isViewportPercentageLength() const { return isViewportPercentageLength(type()); }
|
| static bool isViewportPercentageLength(UnitType type) { return type >= CSS_VW && type <= CSS_VMAX; }
|
| static bool isLength(UnitType type)
|
| {
|
| @@ -188,13 +206,13 @@ public:
|
| bool isNumber() const { return primitiveType() == CSS_NUMBER || primitiveType() == CSS_INTEGER; }
|
| bool isPercentage() const { return primitiveType() == CSS_PERCENTAGE; }
|
| bool isPx() const { return primitiveType() == CSS_PX; }
|
| - bool isRect() const { return m_primitiveUnitType == CSS_RECT; }
|
| - bool isRGBColor() const { return m_primitiveUnitType == CSS_RGBCOLOR; }
|
| - bool isShape() const { return m_primitiveUnitType == CSS_SHAPE; }
|
| - bool isString() const { return m_primitiveUnitType == CSS_STRING; }
|
| - bool isTime() const { return m_primitiveUnitType == CSS_S || m_primitiveUnitType == CSS_MS; }
|
| - bool isURI() const { return m_primitiveUnitType == CSS_URI; }
|
| - bool isCalculated() const { return m_primitiveUnitType == CSS_CALC; }
|
| + bool isRect() const { return type() == CSS_RECT; }
|
| + bool isRGBColor() const { return type() == CSS_RGBCOLOR; }
|
| + bool isShape() const { return type() == CSS_SHAPE; }
|
| + bool isString() const { return type() == CSS_STRING; }
|
| + bool isTime() const { return type() == CSS_S || type() == CSS_MS; }
|
| + bool isURI() const { return type() == CSS_URI; }
|
| + bool isCalculated() const { return type() == CSS_CALC; }
|
| bool isCalculatedPercentageWithNumber() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_NUMBER; }
|
| bool isCalculatedPercentageWithLength() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_LENGTH; }
|
| static bool isDotsPerInch(UnitType type) { return type == CSS_DPI; }
|
| @@ -202,24 +220,63 @@ public:
|
| static bool isDotsPerCentimeter(UnitType type) { return type == CSS_DPCM; }
|
| static bool isResolution(UnitType type) { return type >= CSS_DPPX && type <= CSS_DPCM; }
|
| bool isFlex() const { return primitiveType() == CSS_FR; }
|
| - bool isValueID() const { return m_primitiveUnitType == CSS_VALUE_ID; }
|
| + bool isValueID() const { return type() == CSS_VALUE_ID; }
|
| bool colorIsDerivedFromElement() const;
|
|
|
| static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createIdentifier(CSSValueID valueID)
|
| {
|
| - return adoptRefWillBeNoop(new CSSPrimitiveValue(valueID));
|
| + CSSTaggedPtrValue taggedPtr;
|
| + taggedPtr.flag = 1;
|
| + taggedPtr.type = static_cast<uintptr_t>(CSSPrimitiveValue::CSS_VALUE_ID);
|
| + taggedPtr.value = static_cast<uintptr_t>(valueID);
|
| + return adoptRefWillBeNoop(toPtr(taggedPtr));
|
| }
|
| static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createIdentifier(CSSPropertyID propertyID)
|
| {
|
| - return adoptRefWillBeNoop(new CSSPrimitiveValue(propertyID));
|
| + CSSTaggedPtrValue taggedPtr;
|
| + taggedPtr.flag = 1;
|
| + taggedPtr.type = static_cast<uintptr_t>(CSSPrimitiveValue::CSS_PROPERTY_ID);
|
| + taggedPtr.value = static_cast<uintptr_t>(propertyID);
|
| + return adoptRefWillBeNoop(toPtr(taggedPtr));
|
| }
|
| static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createColor(RGBA32 rgbValue)
|
| {
|
| - return adoptRefWillBeNoop(new CSSPrimitiveValue(rgbValue));
|
| + bool canFitColor;
|
| +#if CPU(32BIT)
|
| + canFitColor = alphaChannel(rgbValue) == 0 || alphaChannel(rgbValue) == 255;
|
| +#elif CPU(64BIT)
|
| + canFitColor = true;
|
| +#endif
|
| + if (!canFitColor)
|
| + return adoptRefWillBeNoop(new CSSPrimitiveValue(rgbValue));
|
| +
|
| + CSSTaggedPtrValue taggedPtr;
|
| + taggedPtr.flag = 1;
|
| + taggedPtr.type = static_cast<uintptr_t>(CSSPrimitiveValue::CSS_RGBCOLOR);
|
| +
|
| + packedColor colorToStore;
|
| + colorToStore.red = static_cast<uintptr_t>(redChannel(rgbValue));
|
| + colorToStore.green = static_cast<uintptr_t>(greenChannel(rgbValue));
|
| + colorToStore.blue = static_cast<uintptr_t>(blueChannel(rgbValue));
|
| +#if CPU(32BIT)
|
| + colorToStore.alpha = static_cast<uintptr_t>(alphaChannel(rgbValue) == 255 ? 1 : 0);
|
| +#elif CPU(64BIT)
|
| + colorToStore.alpha = static_cast<uintptr_t>(alphaChannel(rgbValue));
|
| +#endif
|
| + taggedPtr.value = *reinterpret_cast<uintptr_t*>(&colorToStore);
|
| + return adoptRefWillBeNoop(toPtr(taggedPtr));
|
| }
|
| static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> create(double value, UnitType type)
|
| {
|
| - return adoptRefWillBeNoop(new CSSPrimitiveValue(value, type));
|
| + uint64_t& doubleAsBits = reinterpret_cast<uint64_t&>(value);
|
| + if ((doubleAsBits & mantissaTruncationMask) != 0)
|
| + return adoptRefWillBeNoop(new CSSPrimitiveValue(value, type));
|
| +
|
| + CSSTaggedPtrValue taggedPtr;
|
| + taggedPtr.flag = 1;
|
| + taggedPtr.type = static_cast<uintptr_t>(type);
|
| + taggedPtr.value = doubleAsBits >> doubleShiftAmount;
|
| + return adoptRefWillBeNoop(toPtr(taggedPtr));
|
| }
|
| static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> create(const String& value, UnitType type)
|
| {
|
| @@ -264,36 +321,49 @@ public:
|
| // Converts to a Length (Fixed, Percent or Calculated)
|
| Length convertToLength(const CSSToLengthConversionData&);
|
|
|
| - double getDoubleValue() const;
|
| + double getDoubleValue() const
|
| + {
|
| + if (type() == CSS_CALC)
|
| + return getCalcDoubleValue();
|
| + return value().num;
|
| + }
|
| +
|
| + double getCalcDoubleValue() const;
|
| +
|
| float getFloatValue() const { return getValue<float>(); }
|
| int getIntValue() const { return getValue<int>(); }
|
| template<typename T> inline T getValue() const { return clampTo<T>(getDoubleValue()); }
|
|
|
| String getStringValue() const;
|
|
|
| - Counter* getCounterValue() const { return m_primitiveUnitType != CSS_COUNTER ? 0 : m_value.counter; }
|
| + Counter* getCounterValue() const { return type() != CSS_COUNTER ? 0 : value().counter; }
|
|
|
| - Rect* getRectValue() const { return m_primitiveUnitType != CSS_RECT ? 0 : m_value.rect; }
|
| + Rect* getRectValue() const { return type() != CSS_RECT ? 0 : value().rect; }
|
|
|
| - Quad* getQuadValue() const { return m_primitiveUnitType != CSS_QUAD ? 0 : m_value.quad; }
|
| + Quad* getQuadValue() const { return type() != CSS_QUAD ? 0 : value().quad; }
|
|
|
| - RGBA32 getRGBA32Value() const { return m_primitiveUnitType != CSS_RGBCOLOR ? 0 : m_value.rgbcolor; }
|
| + RGBA32 getRGBA32Value() const { return type() != CSS_RGBCOLOR ? 0 : value().rgbcolor; }
|
|
|
| - Pair* getPairValue() const { return m_primitiveUnitType != CSS_PAIR ? 0 : m_value.pair; }
|
| + Pair* getPairValue() const { return type() != CSS_PAIR ? 0 : value().pair; }
|
|
|
| - CSSBasicShape* getShapeValue() const { return m_primitiveUnitType != CSS_SHAPE ? 0 : m_value.shape; }
|
| + CSSBasicShape* getShapeValue() const { return type() != CSS_SHAPE ? 0 : value().shape; }
|
|
|
| - CSSCalcValue* cssCalcValue() const { return m_primitiveUnitType != CSS_CALC ? 0 : m_value.calc; }
|
| + CSSCalcValue* cssCalcValue() const { return type() != CSS_CALC ? 0 : value().calc; }
|
|
|
| - CSSPropertyID getPropertyID() const { return m_primitiveUnitType == CSS_PROPERTY_ID ? m_value.propertyID : CSSPropertyInvalid; }
|
| - CSSValueID getValueID() const { return m_primitiveUnitType == CSS_VALUE_ID ? m_value.valueID : CSSValueInvalid; }
|
| + CSSPropertyID getPropertyID() const { return type() == CSS_PROPERTY_ID ? value().propertyID : CSSPropertyInvalid; }
|
| + CSSValueID getValueID() const { return type() == CSS_VALUE_ID ? value().valueID : CSSValueInvalid; }
|
|
|
| template<typename T> inline operator T() const; // Defined in CSSPrimitiveValueMappings.h
|
|
|
| static const char* unitTypeToString(UnitType);
|
| String customCSSText() const;
|
|
|
| - bool isQuirkValue() { return m_isQuirkValue; }
|
| + inline bool isQuirkValue() const
|
| + {
|
| + if (isTaggedPtr())
|
| + return false;
|
| + return m_isQuirkValue;
|
| + }
|
|
|
| bool equals(const CSSPrimitiveValue&) const;
|
|
|
| @@ -343,20 +413,86 @@ private:
|
|
|
| double computeLengthDouble(const CSSToLengthConversionData&);
|
|
|
| - union {
|
| - CSSPropertyID propertyID;
|
| - CSSValueID valueID;
|
| - double num;
|
| - StringImpl* string;
|
| - RGBA32 rgbcolor;
|
| - // FIXME: oilpan: Should be members, but no support for members in unions. Just trace the raw ptr for now.
|
| - CSSBasicShape* shape;
|
| - CSSCalcValue* calc;
|
| - Counter* counter;
|
| - Pair* pair;
|
| - Rect* rect;
|
| - Quad* quad;
|
| - } m_value;
|
| + // Useful bit masks for dealing with tagged pointer doubles.
|
| +#if CPU(32BIT)
|
| + static const unsigned doubleShiftAmount = 32 + 7;
|
| + static const uint64_t mantissaTruncationMask = 0x7fffffffff;
|
| +#elif CPU(64BIT)
|
| + static const unsigned doubleShiftAmount = 7;
|
| + static const uint64_t mantissaTruncationMask = 0x7f;
|
| +#endif
|
| +
|
| + // Struct for storing RGB values.
|
| + typedef struct {
|
| + unsigned red : 8;
|
| + unsigned green : 8;
|
| + unsigned blue : 8;
|
| +#if CPU(32BIT)
|
| + unsigned alpha : 1;
|
| +#elif CPU(64BIT)
|
| + unsigned alpha : 8;
|
| +#endif
|
| + } packedColor;
|
| +
|
| + // Getter/setter functions that account for tagged pointer optimization.
|
| + inline bool isTaggedPtr() const
|
| + {
|
| + return reinterpret_cast<uintptr_t>(this) & 1;
|
| + }
|
| +
|
| + static inline CSSPrimitiveValue* toPtr(CSSTaggedPtrValue taggedPtr)
|
| + {
|
| + return reinterpret_cast<CSSPrimitiveValue*&>(taggedPtr);
|
| + }
|
| +
|
| + inline CSSTaggedPtrValue toTaggedPtr() const
|
| + {
|
| + CSSPrimitiveValue* nonConstThis = const_cast<CSSPrimitiveValue*>(this);
|
| + return reinterpret_cast<CSSTaggedPtrValue&&>(nonConstThis);
|
| + }
|
| +
|
| + inline UnitType type() const
|
| + {
|
| + if (!isTaggedPtr())
|
| + return static_cast<UnitType>(m_primitiveUnitType);
|
| + return static_cast<UnitType>(toTaggedPtr().type);
|
| + }
|
| +
|
| + inline CSSPrimitiveValueData value() const
|
| + {
|
| + if (!isTaggedPtr())
|
| + return m_value;
|
| +
|
| + CSSPrimitiveValueData data;
|
| + switch (type()) {
|
| + case CSSPrimitiveValue::CSS_PROPERTY_ID:
|
| + data.propertyID = static_cast<CSSPropertyID>(toTaggedPtr().value);
|
| + break;
|
| + case CSSPrimitiveValue::CSS_VALUE_ID:
|
| + data.valueID = static_cast<CSSValueID>(toTaggedPtr().value);
|
| + break;
|
| + case CSSPrimitiveValue::CSS_RGBCOLOR: {
|
| + uintptr_t valueRawVar = toTaggedPtr().value;
|
| + packedColor color = *reinterpret_cast<packedColor*>(&valueRawVar);
|
| + unsigned alpha;
|
| +#if CPU(32BIT)
|
| + alpha = color.alpha == 1 ? 255 : 0;
|
| +#elif CPU(64BIT)
|
| + alpha = color.alpha;
|
| +#endif
|
| + data.rgbcolor = makeRGBA(color.red, color.green, color.blue, alpha);
|
| + break;
|
| + }
|
| + default:
|
| + uint64_t shiftedValue = toTaggedPtr().value;
|
| + shiftedValue = shiftedValue << doubleShiftAmount;
|
| + data.num = *reinterpret_cast<double*>(&shiftedValue);
|
| + break;
|
| + }
|
| + return data;
|
| + }
|
| +
|
| + CSSPrimitiveValueData m_value;
|
| };
|
|
|
| typedef CSSPrimitiveValue::CSSLengthArray CSSLengthArray;
|
| @@ -366,4 +502,19 @@ DEFINE_CSS_VALUE_TYPE_CASTS(CSSPrimitiveValue, isPrimitiveValue());
|
|
|
| } // namespace blink
|
|
|
| +namespace WTF {
|
| +
|
| +#if !ENABLE(OILPAN)
|
| +// Must be defined *after* CSSPrimitiveValue to compile with the correct adopted() method.
|
| +template<> inline PassRefPtr<blink::CSSPrimitiveValue> adoptRef<blink::CSSPrimitiveValue>(blink::CSSPrimitiveValue* p)
|
| +{
|
| + // Immediates (non-pointers) end in a 1.
|
| + if (!(reinterpret_cast<uintptr_t>(p) & 1))
|
| + adopted(p);
|
| + return PassRefPtr<blink::CSSPrimitiveValue>(p, PassRefPtr<blink::CSSPrimitiveValue>::AdoptRef);
|
| +}
|
| +#endif
|
| +
|
| +} // namespace WTF
|
| +
|
| #endif // CSSPrimitiveValue_h
|
|
|