source: webkit/trunk/Source/WebCore/css/CSSPrimitiveValue.h @ 107688

Last change on this file since 107688 was 107688, checked in by mikelawther@chromium.org, 12 years ago

CSS3 calc: embed calc expressions in CSSPrimitiveValue
https://bugs.webkit.org/show_bug.cgi?id=78446

Source/WebCore:

Reviewed by Ojan Vafai.

Adds calc expressions to CSSPrimitiveValue. This enables simple (ie no mixing of
percents with numbers/lengths) expressions to be evaluated on most properties.

Tests: css3/calc/block-mask-overlay-image-outset-expected.html

css3/calc/css3-radial-gradients-expected.html
css3/calc/gradient-color-stops-expected.html

  • css/CSSCalculationValue.cpp:

(WebCore::CSSCalcValue::computeLengthPx):
(WebCore):
(WebCore::CSSCalcPrimitiveValue::doubleValue):
(CSSCalcPrimitiveValue):
(WebCore::CSSCalcPrimitiveValue::computeLengthPx):
(CSSCalcBinaryOperation):
(WebCore::CSSCalcBinaryOperation::computeLengthPx):

  • css/CSSCalculationValue.h:

(CSSCalcExpressionNode):
(CSSCalcValue):

  • css/CSSParser.cpp:

(WebCore::CSSParser::createPrimitiveNumericValue):
(WebCore::CSSParser::parseValidPrimitive):

  • css/CSSPrimitiveValue.cpp:

(WebCore::isValidCSSUnitTypeForDoubleConversion):
(WebCore::CSSPrimitiveValue::primitiveType):
(WebCore::CSSPrimitiveValue::init):
(WebCore):
(WebCore::CSSPrimitiveValue::cleanup):
(WebCore::CSSPrimitiveValue::computeLengthDouble):
(WebCore::CSSPrimitiveValue::getDoubleValue):
(WebCore::CSSPrimitiveValue::getDoubleValueInternal):
(WebCore::CSSPrimitiveValue::customCssText):

  • css/CSSPrimitiveValue.h:

(WebCore):
(WebCore::CSSPrimitiveValue::isLength):
(WebCore::CSSPrimitiveValue::isNumber):
(WebCore::CSSPrimitiveValue::isPercentage):
(WebCore::CSSPrimitiveValue::isPx):
(WebCore::CSSPrimitiveValue::isCalculated):
(WebCore::CSSPrimitiveValue::isCalculatedPercentageNumber):
(WebCore::CSSPrimitiveValue::isCalculatedPercentageLength):
(CSSPrimitiveValue):
(WebCore::CSSPrimitiveValue::getValue):
(WebCore::CSSPrimitiveValue::cssCalcValue):

  • css/CSSStyleApplyProperty.cpp:

(WebCore::ApplyPropertyBorderRadius::applyValue):

LayoutTests:

Reviewed by Ojan Vafai.

  • css3/calc/block-mask-overlay-image-outset-expected.html: Renamed from LayoutTests/css3/calc/block-mask-overlay-image-outset-expected-mismatch.html.
  • css3/calc/border-expected.txt:
  • css3/calc/calc-errors-expected.txt:
  • css3/calc/css3-radial-gradients-expected.html: Renamed from LayoutTests/css3/calc/css3-radial-gradients-expected-mismatch.html.
  • css3/calc/font-expected.txt:
  • css3/calc/font-monospace-expected.txt:
  • css3/calc/font-size-expected.txt:
  • css3/calc/font-size-fractional-expected.txt:
  • css3/calc/getComputedStyle-margin-percentage-expected.txt:
  • css3/calc/gradient-color-stops-expected.html: Renamed from LayoutTests/css3/calc/gradient-color-stops-expected-mismatch.html.
  • css3/calc/line-height-expected.txt:
  • css3/calc/margin-expected.txt:
  • css3/calc/padding-expected.txt:
  • css3/calc/simple-calcs-expected.txt:
  • css3/calc/table-border-spacing-expected.txt:
  • Property svn:eol-style set to native
File size: 13.2 KB
Line 
1/*
2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB.  If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22#ifndef CSSPrimitiveValue_h
23#define CSSPrimitiveValue_h
24
25#include "CSSValue.h"
26#include "Color.h"
27#include <wtf/Forward.h>
28#include <wtf/MathExtras.h>
29#include <wtf/PassRefPtr.h>
30
31namespace WebCore {
32
33class CSSCalcValue;
34class Counter;
35class DashboardRegion;
36class Pair;
37class Quad;
38class RGBColor;
39class Rect;
40class RenderStyle;
41class CSSWrapShape;
42
43struct Length;
44
45template<typename T, T max, T min> inline T roundForImpreciseConversion(double value)
46{
47    // Dimension calculations are imprecise, often resulting in values of e.g.
48    // 44.99998.  We need to go ahead and round if we're really close to the
49    // next integer value.
50    value += (value < 0) ? -0.01 : +0.01;
51    return ((value > max) || (value < min)) ? 0 : static_cast<T>(value);
52}
53
54class CSSPrimitiveValue : public CSSValue {
55public:
56    enum UnitTypes {
57        CSS_UNKNOWN = 0,
58        CSS_NUMBER = 1,
59        CSS_PERCENTAGE = 2,
60        CSS_EMS = 3,
61        CSS_EXS = 4,
62        CSS_PX = 5,
63        CSS_CM = 6,
64        CSS_MM = 7,
65        CSS_IN = 8,
66        CSS_PT = 9,
67        CSS_PC = 10,
68        CSS_DEG = 11,
69        CSS_RAD = 12,
70        CSS_GRAD = 13,
71        CSS_MS = 14,
72        CSS_S = 15,
73        CSS_HZ = 16,
74        CSS_KHZ = 17,
75        CSS_DIMENSION = 18,
76        CSS_STRING = 19,
77        CSS_URI = 20,
78        CSS_IDENT = 21,
79        CSS_ATTR = 22,
80        CSS_COUNTER = 23,
81        CSS_RECT = 24,
82        CSS_RGBCOLOR = 25,
83        CSS_PAIR = 100, // We envision this being exposed as a means of getting computed style values for pairs (border-spacing/radius, background-position, etc.)
84        CSS_DASHBOARD_REGION = 101, // FIXME: Dashboard region should not be a primitive value.
85        CSS_UNICODE_RANGE = 102,
86
87        // These next types are just used internally to allow us to translate back and forth from CSSPrimitiveValues to CSSParserValues.
88        CSS_PARSER_OPERATOR = 103,
89        CSS_PARSER_INTEGER = 104,
90        CSS_PARSER_HEXCOLOR = 105,
91
92        // This is used internally for unknown identifiers
93        CSS_PARSER_IDENTIFIER = 106,
94
95        // These are from CSS3 Values and Units, but that isn't a finished standard yet
96        CSS_TURN = 107,
97        CSS_REMS = 108,
98
99        // This is used internally for counter names (as opposed to counter values)
100        CSS_COUNTER_NAME = 109,
101
102        // This is used by the CSS Exclusions draft
103        CSS_SHAPE = 110,
104
105        // Used by border images.
106        CSS_QUAD = 111,
107
108        CSS_CALC = 112,
109        CSS_CALC_PERCENTAGE_WITH_NUMBER = 113,
110        CSS_CALC_PERCENTAGE_WITH_LENGTH = 114
111    };
112
113    // This enum follows the CSSParser::Units enum augmented with UNIT_FREQUENCY for frequencies.
114    enum UnitCategory {
115        UNumber,
116        UPercent,
117        ULength,
118        UAngle,
119        UTime,
120        UFrequency,
121        UOther
122    };
123
124    bool isAngle() const
125    {
126        return m_primitiveUnitType == CSS_DEG
127               || m_primitiveUnitType == CSS_RAD
128               || m_primitiveUnitType == CSS_GRAD
129               || m_primitiveUnitType == CSS_TURN;
130    }
131    bool isAttr() const { return m_primitiveUnitType == CSS_ATTR; }
132    bool isCounter() const { return m_primitiveUnitType == CSS_COUNTER; }
133    bool isFontIndependentLength() const { return m_primitiveUnitType >= CSS_PX && m_primitiveUnitType <= CSS_PC; }
134    bool isFontRelativeLength() const
135    {
136        return m_primitiveUnitType == CSS_EMS || m_primitiveUnitType == CSS_EXS || m_primitiveUnitType == CSS_REMS;
137    }
138    bool isIdent() const { return m_primitiveUnitType == CSS_IDENT; }
139    bool isLength() const
140    {
141        unsigned short type = primitiveType();
142        return (type >= CSS_EMS && type <= CSS_PC) || type == CSS_REMS;
143    }
144    bool isNumber() const { return primitiveType() == CSS_NUMBER; }
145    bool isPercentage() const { return primitiveType() == CSS_PERCENTAGE; }
146    bool isPx() const { return primitiveType() == CSS_PX; }
147    bool isRect() const { return m_primitiveUnitType == CSS_RECT; }
148    bool isRGBColor() const { return m_primitiveUnitType == CSS_RGBCOLOR; }
149    bool isShape() const { return m_primitiveUnitType == CSS_SHAPE; }
150    bool isString() const { return m_primitiveUnitType == CSS_STRING; }
151    bool isTime() const { return m_primitiveUnitType == CSS_S || m_primitiveUnitType == CSS_MS; }
152    bool isURI() const { return m_primitiveUnitType == CSS_URI; }
153    bool isCalculated() const { return m_primitiveUnitType == CSS_CALC; }
154    bool isCalculatedPercentageWithNumber() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_NUMBER; }
155    bool isCalculatedPercentageWithLength() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_LENGTH; }
156
157    static PassRefPtr<CSSPrimitiveValue> createIdentifier(int identifier) { return adoptRef(new CSSPrimitiveValue(identifier)); }
158    static PassRefPtr<CSSPrimitiveValue> createColor(unsigned rgbValue) { return adoptRef(new CSSPrimitiveValue(rgbValue)); }
159    static PassRefPtr<CSSPrimitiveValue> create(double value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); }
160    static PassRefPtr<CSSPrimitiveValue> create(const String& value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); }
161
162    template<typename T> static PassRefPtr<CSSPrimitiveValue> create(T value)
163    {
164        return adoptRef(new CSSPrimitiveValue(value));
165    }
166
167    // This value is used to handle quirky margins in reflow roots (body, td, and th) like WinIE.
168    // The basic idea is that a stylesheet can use the value __qem (for quirky em) instead of em.
169    // When the quirky value is used, if you're in quirks mode, the margin will collapse away
170    // inside a table cell.
171    static PassRefPtr<CSSPrimitiveValue> createAllowingMarginQuirk(double value, UnitTypes type)
172    {
173        CSSPrimitiveValue* quirkValue = new CSSPrimitiveValue(value, type);
174        quirkValue->m_isQuirkValue = true;
175        return adoptRef(quirkValue);
176    }
177
178    ~CSSPrimitiveValue();
179
180    void cleanup();
181
182    unsigned short primitiveType() const;
183
184    double computeDegrees();
185
186    enum TimeUnit { Seconds, Milliseconds };
187    template <typename T, TimeUnit timeUnit> T computeTime()
188    {
189        if (timeUnit == Seconds && m_primitiveUnitType == CSS_S)
190            return getValue<T>();
191        if (timeUnit == Seconds && m_primitiveUnitType == CSS_MS)
192            return getValue<T>() / 1000;
193        if (timeUnit == Milliseconds && m_primitiveUnitType == CSS_MS)
194            return getValue<T>();
195        if (timeUnit == Milliseconds && m_primitiveUnitType == CSS_S)
196            return getValue<T>() * 1000;
197        ASSERT_NOT_REACHED();
198        return 0;
199    }
200
201    /*
202     * computes a length in pixels out of the given CSSValue. Need the RenderStyle to get
203     * the fontinfo in case val is defined in em or ex.
204     *
205     * The metrics have to be a bit different for screen and printer output.
206     * For screen output we assume 1 inch == 72 px, for printer we assume 300 dpi
207     *
208     * this is screen/printer dependent, so we probably need a config option for this,
209     * and some tool to calibrate.
210     */
211    template<typename T> T computeLength(RenderStyle* currStyle, RenderStyle* rootStyle, float multiplier = 1.0f, bool computingFontSize = false);
212
213    // Converts to a Length, mapping various unit types appropriately.
214    template<int> Length convertToLength(RenderStyle* currStyle, RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false);
215
216    // use with care!!!
217    void setPrimitiveType(unsigned short type) { m_primitiveUnitType = type; }
218
219    double getDoubleValue(unsigned short unitType, ExceptionCode&) const;
220    double getDoubleValue(unsigned short unitType) const;
221    double getDoubleValue() const;
222
223    void setFloatValue(unsigned short unitType, double floatValue, ExceptionCode&);
224    float getFloatValue(unsigned short unitType, ExceptionCode& ec) const { return getValue<float>(unitType, ec); }
225    float getFloatValue(unsigned short unitType) const { return getValue<float>(unitType); }
226    float getFloatValue() const { return getValue<float>(); }
227
228    int getIntValue(unsigned short unitType, ExceptionCode& ec) const { return getValue<int>(unitType, ec); }
229    int getIntValue(unsigned short unitType) const { return getValue<int>(unitType); }
230    int getIntValue() const { return getValue<int>(); }
231
232    template<typename T> inline T getValue(unsigned short unitType, ExceptionCode& ec) const { return clampTo<T>(getDoubleValue(unitType, ec)); }
233    template<typename T> inline T getValue(unsigned short unitType) const { return clampTo<T>(getDoubleValue(unitType)); }
234    template<typename T> inline T getValue() const { return clampTo<T>(getDoubleValue()); }
235
236    void setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode&);
237    String getStringValue(ExceptionCode&) const;
238    String getStringValue() const;
239
240    Counter* getCounterValue(ExceptionCode&) const;
241    Counter* getCounterValue() const { return m_primitiveUnitType != CSS_COUNTER ? 0 : m_value.counter; }
242
243    Rect* getRectValue(ExceptionCode&) const;
244    Rect* getRectValue() const { return m_primitiveUnitType != CSS_RECT ? 0 : m_value.rect; }
245
246    Quad* getQuadValue(ExceptionCode&) const;
247    Quad* getQuadValue() const { return m_primitiveUnitType != CSS_QUAD ? 0 : m_value.quad; }
248
249    PassRefPtr<RGBColor> getRGBColorValue(ExceptionCode&) const;
250    RGBA32 getRGBA32Value() const { return m_primitiveUnitType != CSS_RGBCOLOR ? 0 : m_value.rgbcolor; }
251
252    Pair* getPairValue(ExceptionCode&) const;
253    Pair* getPairValue() const { return m_primitiveUnitType != CSS_PAIR ? 0 : m_value.pair; }
254
255    DashboardRegion* getDashboardRegionValue() const { return m_primitiveUnitType != CSS_DASHBOARD_REGION ? 0 : m_value.region; }
256
257    CSSWrapShape* getShapeValue() const { return m_primitiveUnitType != CSS_SHAPE ? 0 : m_value.shape; }
258   
259    CSSCalcValue* cssCalcValue() const { return m_primitiveUnitType != CSS_CALC ? 0 : m_value.calc; }
260
261    int getIdent() const { return m_primitiveUnitType == CSS_IDENT ? m_value.ident : 0; }
262
263    template<typename T> inline operator T() const; // Defined in CSSPrimitiveValueMappings.h
264
265    String customCssText() const;
266
267    bool isQuirkValue() { return m_isQuirkValue; }
268
269    void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*);
270
271protected:
272    CSSPrimitiveValue(ClassType, int ident);
273    CSSPrimitiveValue(ClassType, const String&, UnitTypes);
274
275private:
276    CSSPrimitiveValue();
277    // FIXME: int vs. unsigned overloading is too subtle to distinguish the color and identifier cases.
278    CSSPrimitiveValue(int ident);
279    CSSPrimitiveValue(unsigned color); // RGB value
280    CSSPrimitiveValue(const Length&);
281    CSSPrimitiveValue(const String&, UnitTypes);
282    CSSPrimitiveValue(double, UnitTypes);
283
284    template<typename T> CSSPrimitiveValue(T); // Defined in CSSPrimitiveValueMappings.h
285    template<typename T> CSSPrimitiveValue(T* val)
286        : CSSValue(PrimitiveClass)
287    {
288        init(PassRefPtr<T>(val));
289    }
290
291    template<typename T> CSSPrimitiveValue(PassRefPtr<T> val)
292        : CSSValue(PrimitiveClass)
293    {
294        init(val);
295    }
296
297    static void create(int); // compile-time guard
298    static void create(unsigned); // compile-time guard
299    template<typename T> operator T*(); // compile-time guard
300
301    static PassRefPtr<CSSPrimitiveValue> createUncachedIdentifier(int identifier);
302    static PassRefPtr<CSSPrimitiveValue> createUncachedColor(unsigned rgbValue);
303    static PassRefPtr<CSSPrimitiveValue> createUncached(double value, UnitTypes type);
304
305    static UnitTypes canonicalUnitTypeForCategory(UnitCategory category);
306
307    void init(PassRefPtr<Counter>);
308    void init(PassRefPtr<Rect>);
309    void init(PassRefPtr<Pair>);
310    void init(PassRefPtr<Quad>);
311    void init(PassRefPtr<DashboardRegion>); // FIXME: Dashboard region should not be a primitive value.
312    void init(PassRefPtr<CSSWrapShape>);
313    void init(PassRefPtr<CSSCalcValue>);
314    bool getDoubleValueInternal(UnitTypes targetUnitType, double* result) const;
315
316    double computeLengthDouble(RenderStyle* currentStyle, RenderStyle* rootStyle, float multiplier, bool computingFontSize);
317
318    union {
319        int ident;
320        double num;
321        StringImpl* string;
322        Counter* counter;
323        Rect* rect;
324        Quad* quad;
325        unsigned rgbcolor;
326        Pair* pair;
327        DashboardRegion* region;
328        CSSWrapShape* shape;
329        CSSCalcValue* calc;
330    } m_value;
331};
332
333} // namespace WebCore
334
335#endif // CSSPrimitiveValue_h
Note: See TracBrowser for help on using the repository browser.