Replace PassRef with Ref/Ref&& across the board.
[WebKit-https.git] / Source / WebCore / css / CSSPrimitiveValue.h
index 180de6d..edd762a 100644 (file)
 #ifndef CSSPrimitiveValue_h
 #define CSSPrimitiveValue_h
 
+#include "CSSPropertyNames.h"
 #include "CSSValue.h"
+#include "CSSValueKeywords.h"
 #include "Color.h"
+#include "LayoutUnit.h"
 #include <wtf/Forward.h>
 #include <wtf/MathExtras.h>
 #include <wtf/PassRefPtr.h>
 
 namespace WebCore {
 
+class CSSCalcValue;
+class CSSToLengthConversionData;
 class Counter;
 class DashboardRegion;
 class Pair;
@@ -37,22 +42,42 @@ class Quad;
 class RGBColor;
 class Rect;
 class RenderStyle;
-class CSSWrapShape;
+class CSSBasicShape;
+
+#if ENABLE(CSS_SCROLL_SNAP)
+class LengthRepeat;
+#endif
 
 struct Length;
+struct LengthSize;
+
+// Max/min values for CSS, needs to slightly smaller/larger than the true max/min values to allow for rounding without overflowing.
+// Subtract two (rather than one) to allow for values to be converted to float and back without exceeding the LayoutUnit::max.
+const int maxValueForCssLength = intMaxForLayoutUnit - 2;
+const int minValueForCssLength = intMinForLayoutUnit + 2;
 
-template<typename T, T max, T min> inline T roundForImpreciseConversion(double value)
+// Dimension calculations are imprecise, often resulting in values of e.g.
+// 44.99998. We need to go ahead and round if we're really close to the next
+// integer value.
+template<typename T> inline T roundForImpreciseConversion(double value)
 {
-    // Dimension calculations are imprecise, often resulting in values of e.g.
-    // 44.99998.  We need to go ahead and round if we're really close to the
-    // next integer value.
     value += (value < 0) ? -0.01 : +0.01;
-    return ((value > max) || (value < min)) ? 0 : static_cast<T>(value);
+    return ((value > std::numeric_limits<T>::max()) || (value < std::numeric_limits<T>::min())) ? 0 : static_cast<T>(value);
+}
+
+template<> inline float roundForImpreciseConversion(double value)
+{
+    double ceiledValue = ceil(value);
+    double proximityToNextInt = ceiledValue - value;
+    if (proximityToNextInt <= 0.01 && value > 0)
+        return static_cast<float>(ceiledValue);
+    if (proximityToNextInt >= 0.99 && value < 0)
+        return static_cast<float>(floor(value));
+    return static_cast<float>(value);
 }
 
 class CSSPrimitiveValue : public CSSValue {
 public:
-    static const int UnitTypesBits = 8;
     enum UnitTypes {
         CSS_UNKNOWN = 0,
         CSS_NUMBER = 1,
@@ -80,8 +105,22 @@ public:
         CSS_COUNTER = 23,
         CSS_RECT = 24,
         CSS_RGBCOLOR = 25,
+        // From CSS Values and Units. Viewport-percentage Lengths (vw/vh/vmin/vmax).
+        CSS_VW = 26,
+        CSS_VH = 27,
+        CSS_VMIN = 28,
+        CSS_VMAX = 29,
+        CSS_DPPX = 30,
+        CSS_DPI = 31,
+        CSS_DPCM = 32,
+        CSS_FR = 33,
+#if ENABLE(CSS_SCROLL_SNAP)
+        CSS_LENGTH_REPEAT = 34,
+#endif
         CSS_PAIR = 100, // We envision this being exposed as a means of getting computed style values for pairs (border-spacing/radius, background-position, etc.)
+#if ENABLE(DASHBOARD_SUPPORT)
         CSS_DASHBOARD_REGION = 101, // FIXME: Dashboard region should not be a primitive value.
+#endif
         CSS_UNICODE_RANGE = 102,
 
         // These next types are just used internally to allow us to translate back and forth from CSSPrimitiveValues to CSSParserValues.
@@ -95,15 +134,23 @@ public:
         // These are from CSS3 Values and Units, but that isn't a finished standard yet
         CSS_TURN = 107,
         CSS_REMS = 108,
+        CSS_CHS = 109,
 
         // This is used internally for counter names (as opposed to counter values)
-        CSS_COUNTER_NAME = 109,
+        CSS_COUNTER_NAME = 110,
 
-        // This is used by the CSS Exclusions draft
-        CSS_SHAPE = 110,
+        // This is used by the CSS Shapes draft
+        CSS_SHAPE = 111,
 
         // Used by border images.
-        CSS_QUAD = 111
+        CSS_QUAD = 112,
+
+        CSS_CALC = 113,
+        CSS_CALC_PERCENTAGE_WITH_NUMBER = 114,
+        CSS_CALC_PERCENTAGE_WITH_LENGTH = 115,
+
+        CSS_PROPERTY_ID = 117,
+        CSS_VALUE_ID = 118
     };
 
     // This enum follows the CSSParser::Units enum augmented with UNIT_FREQUENCY for frequencies.
@@ -114,40 +161,115 @@ public:
         UAngle,
         UTime,
         UFrequency,
+#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
+        UResolution,
+#endif
         UOther
     };
+    static UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes);
 
-    static bool isUnitTypeLength(int type) { return (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) ||
-                                                    type == CSSPrimitiveValue::CSS_REMS; }
-
-    bool isLength() const { return isUnitTypeLength(m_type); }
-
-    static PassRefPtr<CSSPrimitiveValue> createIdentifier(int identifier) { return adoptRef(new CSSPrimitiveValue(identifier)); }
-    static PassRefPtr<CSSPrimitiveValue> createColor(unsigned rgbValue) { return adoptRef(new CSSPrimitiveValue(rgbValue)); }
-    static PassRefPtr<CSSPrimitiveValue> create(double value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); }
-    static PassRefPtr<CSSPrimitiveValue> create(const String& value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); }
+    bool isAngle() const
+    {
+        return m_primitiveUnitType == CSS_DEG
+               || m_primitiveUnitType == CSS_RAD
+               || m_primitiveUnitType == CSS_GRAD
+               || m_primitiveUnitType == CSS_TURN;
+    }
+    bool isAttr() const { return m_primitiveUnitType == CSS_ATTR; }
+    bool isCounter() const { return m_primitiveUnitType == CSS_COUNTER; }
+    bool isFontIndependentLength() const { return m_primitiveUnitType >= CSS_PX && m_primitiveUnitType <= CSS_PC; }
+    bool isFontRelativeLength() const
+    {
+        return m_primitiveUnitType == CSS_EMS
+            || m_primitiveUnitType == CSS_EXS
+            || m_primitiveUnitType == CSS_REMS
+            || m_primitiveUnitType == CSS_CHS;
+    }
+    bool isLength() const
+    {
+        unsigned short type = primitiveType();
+        return (type >= CSS_EMS && type <= CSS_PC) || type == CSS_REMS || type == CSS_CHS || isViewportPercentageLength();
+    }
+    bool isNumber() const { return primitiveType() == CSS_NUMBER; }
+    bool isPercentage() const { return primitiveType() == CSS_PERCENTAGE; }
+    bool isPx() const { return primitiveType() == CSS_PX; }
+    bool isRect() const { return m_primitiveUnitType == CSS_RECT; }
+#if ENABLE(CSS_SCROLL_SNAP)
+    bool isLengthRepeat() const { return m_primitiveUnitType == CSS_LENGTH_REPEAT; }
+#endif
+    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 isCalculatedPercentageWithNumber() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_NUMBER; }
+    bool isCalculatedPercentageWithLength() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_LENGTH; }
+    bool isDotsPerInch() const { return primitiveType() == CSS_DPI; }
+    bool isDotsPerPixel() const { return primitiveType() == CSS_DPPX; }
+    bool isDotsPerCentimeter() const { return primitiveType() == CSS_DPCM; }
+    bool isResolution() const
+    {
+        unsigned short type = primitiveType();
+        return type >= CSS_DPPX && type <= CSS_DPCM;
+    }
 
-    template<typename T> static PassRefPtr<CSSPrimitiveValue> create(T value)
+    bool isViewportPercentageLength() const { return m_primitiveUnitType >= CSS_VW && m_primitiveUnitType <= CSS_VMAX; }
+    bool isViewportPercentageWidth() const { return m_primitiveUnitType == CSS_VW; }
+    bool isViewportPercentageHeight() const { return m_primitiveUnitType == CSS_VH; }
+    bool isViewportPercentageMax() const { return m_primitiveUnitType == CSS_VMAX; }
+    bool isViewportPercentageMin() const { return m_primitiveUnitType == CSS_VMIN; }
+    bool isValueID() const { return m_primitiveUnitType == CSS_VALUE_ID; }
+    bool isFlex() const { return primitiveType() == CSS_FR; }
+
+    static Ref<CSSPrimitiveValue> createIdentifier(CSSValueID valueID) { return adoptRef(*new CSSPrimitiveValue(valueID)); }
+    static Ref<CSSPrimitiveValue> createIdentifier(CSSPropertyID propertyID) { return adoptRef(*new CSSPrimitiveValue(propertyID)); }
+    static Ref<CSSPrimitiveValue> createParserOperator(int parserOperator) { return adoptRef(*new CSSPrimitiveValue(parserOperator)); }
+
+    static Ref<CSSPrimitiveValue> createColor(unsigned rgbValue) { return adoptRef(*new CSSPrimitiveValue(rgbValue)); }
+    static Ref<CSSPrimitiveValue> create(double value, UnitTypes type) { return adoptRef(*new CSSPrimitiveValue(value, type)); }
+    static Ref<CSSPrimitiveValue> create(const String& value, UnitTypes type) { return adoptRef(*new CSSPrimitiveValue(value, type)); }
+    static Ref<CSSPrimitiveValue> create(const Length& value, const RenderStyle* style) { return adoptRef(*new CSSPrimitiveValue(value, style)); }
+    static Ref<CSSPrimitiveValue> create(const LengthSize& value, const RenderStyle* style) { return adoptRef(*new CSSPrimitiveValue(value, style)); }
+
+    template<typename T> static Ref<CSSPrimitiveValue> create(T value)
     {
-        return adoptRef(new CSSPrimitiveValue(value));
+        return adoptRef(*new CSSPrimitiveValue(value));
     }
 
     // This value is used to handle quirky margins in reflow roots (body, td, and th) like WinIE.
     // The basic idea is that a stylesheet can use the value __qem (for quirky em) instead of em.
     // When the quirky value is used, if you're in quirks mode, the margin will collapse away
     // inside a table cell.
-    static PassRefPtr<CSSPrimitiveValue> createAllowingMarginQuirk(double value, UnitTypes type)
+    static Ref<CSSPrimitiveValue> createAllowingMarginQuirk(double value, UnitTypes type)
     {
         CSSPrimitiveValue* quirkValue = new CSSPrimitiveValue(value, type);
         quirkValue->m_isQuirkValue = true;
-        return adoptRef(quirkValue);
+        return adoptRef(*quirkValue);
     }
 
-    virtual ~CSSPrimitiveValue();
+    ~CSSPrimitiveValue();
 
     void cleanup();
 
-    unsigned short primitiveType() const { return m_type; }
+    unsigned short primitiveType() const;
+
+    double computeDegrees();
+
+    enum TimeUnit { Seconds, Milliseconds };
+    template <typename T, TimeUnit timeUnit> T computeTime()
+    {
+        if (timeUnit == Seconds && primitiveType() == CSS_S)
+            return getValue<T>();
+        if (timeUnit == Seconds && primitiveType() == CSS_MS)
+            return getValue<T>() / 1000;
+        if (timeUnit == Milliseconds && primitiveType() == CSS_MS)
+            return getValue<T>();
+        if (timeUnit == Milliseconds && primitiveType() == CSS_S)
+            return getValue<T>() * 1000;
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
 
     /*
      * computes a length in pixels out of the given CSSValue. Need the RenderStyle to get
@@ -159,14 +281,17 @@ public:
      * this is screen/printer dependent, so we probably need a config option for this,
      * and some tool to calibrate.
      */
-    template<typename T> T computeLength(RenderStyle* currStyle, RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false);
+    template<typename T> T computeLength(const CSSToLengthConversionData&) const;
+
+    // Converts to a Length, mapping various unit types appropriately.
+    template<int> Length convertToLength(const CSSToLengthConversionData&) const;
 
     // use with care!!!
-    void setPrimitiveType(unsigned short type) { m_type = type; }
+    void setPrimitiveType(unsigned short type) { m_primitiveUnitType = type; }
 
     double getDoubleValue(unsigned short unitType, ExceptionCode&) const;
     double getDoubleValue(unsigned short unitType) const;
-    double getDoubleValue() const { return m_value.num; }
+    double getDoubleValue() const;
 
     void setFloatValue(unsigned short unitType, double floatValue, ExceptionCode&);
     float getFloatValue(unsigned short unitType, ExceptionCode& ec) const { return getValue<float>(unitType, ec); }
@@ -179,50 +304,68 @@ public:
 
     template<typename T> inline T getValue(unsigned short unitType, ExceptionCode& ec) const { return clampTo<T>(getDoubleValue(unitType, ec)); }
     template<typename T> inline T getValue(unsigned short unitType) const { return clampTo<T>(getDoubleValue(unitType)); }
-    template<typename T> inline T getValue() const { return clampTo<T>(m_value.num); }
+    template<typename T> inline T getValue() const { return clampTo<T>(getDoubleValue()); }
 
     void setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode&);
     String getStringValue(ExceptionCode&) const;
     String getStringValue() const;
 
     Counter* getCounterValue(ExceptionCode&) const;
-    Counter* getCounterValue() const { return m_type != CSS_COUNTER ? 0 : m_value.counter; }
+    Counter* getCounterValue() const { return m_primitiveUnitType != CSS_COUNTER ? 0 : m_value.counter; }
 
     Rect* getRectValue(ExceptionCode&) const;
-    Rect* getRectValue() const { return m_type != CSS_RECT ? 0 : m_value.rect; }
+    Rect* getRectValue() const { return m_primitiveUnitType != CSS_RECT ? 0 : m_value.rect; }
 
     Quad* getQuadValue(ExceptionCode&) const;
-    Quad* getQuadValue() const { return m_type != CSS_QUAD ? 0 : m_value.quad; }
+    Quad* getQuadValue() const { return m_primitiveUnitType != CSS_QUAD ? 0 : m_value.quad; }
+
+#if ENABLE(CSS_SCROLL_SNAP)
+    LengthRepeat* getLengthRepeatValue(ExceptionCode&) const;
+    LengthRepeat* getLengthRepeatValue() const { return m_primitiveUnitType != CSS_LENGTH_REPEAT ? 0 : m_value.lengthRepeat; }
+#endif
 
     PassRefPtr<RGBColor> getRGBColorValue(ExceptionCode&) const;
-    RGBA32 getRGBA32Value() const { return m_type != CSS_RGBCOLOR ? 0 : m_value.rgbcolor; }
+    RGBA32 getRGBA32Value() const { return m_primitiveUnitType != CSS_RGBCOLOR ? 0 : m_value.rgbcolor; }
 
     Pair* getPairValue(ExceptionCode&) const;
-    Pair* getPairValue() const { return m_type != CSS_PAIR ? 0 : m_value.pair; }
+    Pair* getPairValue() const { return m_primitiveUnitType != CSS_PAIR ? 0 : m_value.pair; }
+
+#if ENABLE(DASHBOARD_SUPPORT)
+    DashboardRegion* getDashboardRegionValue() const { return m_primitiveUnitType != CSS_DASHBOARD_REGION ? 0 : m_value.region; }
+#endif
 
-    DashboardRegion* getDashboardRegionValue() const { return m_type != CSS_DASHBOARD_REGION ? 0 : m_value.region; }
+    CSSBasicShape* getShapeValue() const { return m_primitiveUnitType != CSS_SHAPE ? 0 : m_value.shape; }
 
-    CSSWrapShape* getShapeValue() const { return m_type != CSS_SHAPE ? 0 : m_value.shape; }
+    CSSCalcValue* cssCalcValue() const { return m_primitiveUnitType != CSS_CALC ? 0 : m_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; }
 
-    int getIdent() const;
     template<typename T> inline operator T() const; // Defined in CSSPrimitiveValueMappings.h
 
-    String customCssText() const;
+    String customCSSText() const;
 
     bool isQuirkValue() { return m_isQuirkValue; }
 
-    void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*);
+    void addSubresourceStyleURLs(ListHashSet<URL>&, const StyleSheetContents*) const;
+
+    PassRefPtr<CSSPrimitiveValue> cloneForCSSOM() const;
+    void setCSSOMSafe() { m_isCSSOMSafe = true; }
 
-protected:
-    CSSPrimitiveValue(ClassType, int ident);
-    CSSPrimitiveValue(ClassType, const String&, UnitTypes);
+    bool equals(const CSSPrimitiveValue&) const;
+
+    static UnitTypes canonicalUnitTypeForCategory(UnitCategory);
+    static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType);
 
 private:
-    CSSPrimitiveValue();
-    // FIXME: int vs. unsigned overloading is too subtle to distinguish the color and identifier cases.
-    CSSPrimitiveValue(int ident);
+    CSSPrimitiveValue(CSSValueID);
+    CSSPrimitiveValue(CSSPropertyID);
+    // FIXME: int vs. unsigned overloading is too subtle to distinguish the color and operator cases.
+    CSSPrimitiveValue(int parserOperator);
     CSSPrimitiveValue(unsigned color); // RGB value
     CSSPrimitiveValue(const Length&);
+    CSSPrimitiveValue(const Length&, const RenderStyle*);
+    CSSPrimitiveValue(const LengthSize&, const RenderStyle*);
     CSSPrimitiveValue(const String&, UnitTypes);
     CSSPrimitiveValue(double, UnitTypes);
 
@@ -243,40 +386,49 @@ private:
     static void create(unsigned); // compile-time guard
     template<typename T> operator T*(); // compile-time guard
 
-    static PassRefPtr<CSSPrimitiveValue> createUncachedIdentifier(int identifier);
-    static PassRefPtr<CSSPrimitiveValue> createUncachedColor(unsigned rgbValue);
-    static PassRefPtr<CSSPrimitiveValue> createUncached(double value, UnitTypes type);
-
-    static UnitTypes canonicalUnitTypeForCategory(UnitCategory category);
-
+    void init(const Length&);
+    void init(const LengthSize&, const RenderStyle*);
     void init(PassRefPtr<Counter>);
     void init(PassRefPtr<Rect>);
     void init(PassRefPtr<Pair>);
     void init(PassRefPtr<Quad>);
+#if ENABLE(CSS_SCROLL_SNAP)
+    void init(PassRefPtr<LengthRepeat>);
+#endif
     void init(PassRefPtr<DashboardRegion>); // FIXME: Dashboard region should not be a primitive value.
-    void init(PassRefPtr<CSSWrapShape>);
-
+    void init(PassRefPtr<CSSBasicShape>);
+    void init(PassRefPtr<CSSCalcValue>);
     bool getDoubleValueInternal(UnitTypes targetUnitType, double* result) const;
 
-    double computeLengthDouble(RenderStyle* currentStyle, RenderStyle* rootStyle, double multiplier, bool computingFontSize);
+    double computeLengthDouble(const CSSToLengthConversionData&) const;
+
+    ALWAYS_INLINE String formatNumberForCustomCSSText() const;
+    template <unsigned characterCount>
+    ALWAYS_INLINE Ref<StringImpl> formatNumberValue(const char (&characters)[characterCount]) const;
+    NEVER_INLINE Ref<StringImpl> formatNumberValue(const char* suffix, unsigned suffixLength) const;
 
-    signed m_type : UnitTypesBits;
-    mutable unsigned m_hasCachedCSSText : 1;
-    unsigned m_isQuirkValue : 1;
     union {
-        int ident;
+        CSSPropertyID propertyID;
+        CSSValueID valueID;
+        int parserOperator;
         double num;
         StringImpl* string;
         Counter* counter;
         Rect* rect;
         Quad* quad;
+#if ENABLE(CSS_SCROLL_SNAP)
+        LengthRepeat* lengthRepeat;
+#endif
         unsigned rgbcolor;
         Pair* pair;
         DashboardRegion* region;
-        CSSWrapShape* shape;
+        CSSBasicShape* shape;
+        CSSCalcValue* calc;
     } m_value;
 };
 
 } // namespace WebCore
 
+SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSPrimitiveValue, isPrimitiveValue())
+
 #endif // CSSPrimitiveValue_h