[CSS Shapes] complex calc args for inset round vanish
[WebKit-https.git] / Source / WebCore / css / CSSPrimitiveValue.h
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 "CSSPropertyNames.h"
26 #include "CSSValue.h"
27 #include "CSSValueKeywords.h"
28 #include "Color.h"
29 #include <wtf/Forward.h>
30 #include <wtf/MathExtras.h>
31 #include <wtf/PassRefPtr.h>
32
33 namespace WebCore {
34
35 class CSSCalcValue;
36 class Counter;
37 class DashboardRegion;
38 class Pair;
39 class Quad;
40 class RGBColor;
41 class Rect;
42 class RenderStyle;
43 class CSSBasicShape;
44
45 struct Length;
46 struct LengthSize;
47
48 // Dimension calculations are imprecise, often resulting in values of e.g.
49 // 44.99998. We need to go ahead and round if we're really close to the next
50 // integer value.
51 template<typename T> inline T roundForImpreciseConversion(double value)
52 {
53     value += (value < 0) ? -0.01 : +0.01;
54     return ((value > std::numeric_limits<T>::max()) || (value < std::numeric_limits<T>::min())) ? 0 : static_cast<T>(value);
55 }
56
57 template<> inline float roundForImpreciseConversion(double value)
58 {
59     double ceiledValue = ceil(value);
60     double proximityToNextInt = ceiledValue - value;
61     if (proximityToNextInt <= 0.01 && value > 0)
62         return static_cast<float>(ceiledValue);
63     if (proximityToNextInt >= 0.99 && value < 0)
64         return static_cast<float>(floor(value));
65     return static_cast<float>(value);
66 }
67
68 class CSSPrimitiveValue : public CSSValue {
69 public:
70     enum UnitTypes {
71         CSS_UNKNOWN = 0,
72         CSS_NUMBER = 1,
73         CSS_PERCENTAGE = 2,
74         CSS_EMS = 3,
75         CSS_EXS = 4,
76         CSS_PX = 5,
77         CSS_CM = 6,
78         CSS_MM = 7,
79         CSS_IN = 8,
80         CSS_PT = 9,
81         CSS_PC = 10,
82         CSS_DEG = 11,
83         CSS_RAD = 12,
84         CSS_GRAD = 13,
85         CSS_MS = 14,
86         CSS_S = 15,
87         CSS_HZ = 16,
88         CSS_KHZ = 17,
89         CSS_DIMENSION = 18,
90         CSS_STRING = 19,
91         CSS_URI = 20,
92         CSS_IDENT = 21,
93         CSS_ATTR = 22,
94         CSS_COUNTER = 23,
95         CSS_RECT = 24,
96         CSS_RGBCOLOR = 25,
97         // From CSS Values and Units. Viewport-percentage Lengths (vw/vh/vmin/vmax).
98         CSS_VW = 26,
99         CSS_VH = 27,
100         CSS_VMIN = 28,
101         CSS_VMAX = 29,
102         CSS_DPPX = 30,
103         CSS_DPI = 31,
104         CSS_DPCM = 32,
105         CSS_FR = 33,
106         CSS_PAIR = 100, // We envision this being exposed as a means of getting computed style values for pairs (border-spacing/radius, background-position, etc.)
107 #if ENABLE(DASHBOARD_SUPPORT)
108         CSS_DASHBOARD_REGION = 101, // FIXME: Dashboard region should not be a primitive value.
109 #endif
110         CSS_UNICODE_RANGE = 102,
111
112         // These next types are just used internally to allow us to translate back and forth from CSSPrimitiveValues to CSSParserValues.
113         CSS_PARSER_OPERATOR = 103,
114         CSS_PARSER_INTEGER = 104,
115         CSS_PARSER_HEXCOLOR = 105,
116
117         // This is used internally for unknown identifiers
118         CSS_PARSER_IDENTIFIER = 106,
119
120         // These are from CSS3 Values and Units, but that isn't a finished standard yet
121         CSS_TURN = 107,
122         CSS_REMS = 108,
123         CSS_CHS = 109,
124
125         // This is used internally for counter names (as opposed to counter values)
126         CSS_COUNTER_NAME = 110,
127
128         // This is used by the CSS Shapes draft
129         CSS_SHAPE = 111,
130
131         // Used by border images.
132         CSS_QUAD = 112,
133
134         CSS_CALC = 113,
135         CSS_CALC_PERCENTAGE_WITH_NUMBER = 114,
136         CSS_CALC_PERCENTAGE_WITH_LENGTH = 115,
137
138         CSS_PROPERTY_ID = 117,
139         CSS_VALUE_ID = 118
140     };
141
142     // This enum follows the CSSParser::Units enum augmented with UNIT_FREQUENCY for frequencies.
143     enum UnitCategory {
144         UNumber,
145         UPercent,
146         ULength,
147         UAngle,
148         UTime,
149         UFrequency,
150         UViewportPercentageLength,
151 #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
152         UResolution,
153 #endif
154         UOther
155     };
156     static UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes);
157
158     bool isAngle() const
159     {
160         return m_primitiveUnitType == CSS_DEG
161                || m_primitiveUnitType == CSS_RAD
162                || m_primitiveUnitType == CSS_GRAD
163                || m_primitiveUnitType == CSS_TURN;
164     }
165     bool isAttr() const { return m_primitiveUnitType == CSS_ATTR; }
166     bool isCounter() const { return m_primitiveUnitType == CSS_COUNTER; }
167     bool isFontIndependentLength() const { return m_primitiveUnitType >= CSS_PX && m_primitiveUnitType <= CSS_PC; }
168     bool isFontRelativeLength() const
169     {
170         return m_primitiveUnitType == CSS_EMS
171             || m_primitiveUnitType == CSS_EXS
172             || m_primitiveUnitType == CSS_REMS
173             || m_primitiveUnitType == CSS_CHS;
174     }
175     bool isLength() const
176     {
177         unsigned short type = primitiveType();
178         return (type >= CSS_EMS && type <= CSS_PC) || type == CSS_REMS || type == CSS_CHS;
179     }
180     bool isNumber() const { return primitiveType() == CSS_NUMBER; }
181     bool isPercentage() const { return primitiveType() == CSS_PERCENTAGE; }
182     bool isPx() const { return primitiveType() == CSS_PX; }
183     bool isRect() const { return m_primitiveUnitType == CSS_RECT; }
184     bool isRGBColor() const { return m_primitiveUnitType == CSS_RGBCOLOR; }
185     bool isShape() const { return m_primitiveUnitType == CSS_SHAPE; }
186     bool isString() const { return m_primitiveUnitType == CSS_STRING; }
187     bool isTime() const { return m_primitiveUnitType == CSS_S || m_primitiveUnitType == CSS_MS; }
188     bool isURI() const { return m_primitiveUnitType == CSS_URI; }
189     bool isCalculated() const { return m_primitiveUnitType == CSS_CALC; }
190     bool isCalculatedPercentageWithNumber() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_NUMBER; }
191     bool isCalculatedPercentageWithLength() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_LENGTH; }
192     bool isDotsPerInch() const { return primitiveType() == CSS_DPI; }
193     bool isDotsPerPixel() const { return primitiveType() == CSS_DPPX; }
194     bool isDotsPerCentimeter() const { return primitiveType() == CSS_DPCM; }
195     bool isResolution() const
196     {
197         unsigned short type = primitiveType();
198         return type >= CSS_DPPX && type <= CSS_DPCM;
199     }
200
201     bool isViewportPercentageLength() const { return m_primitiveUnitType >= CSS_VW && m_primitiveUnitType <= CSS_VMAX; }
202     bool isViewportPercentageWidth() const { return m_primitiveUnitType == CSS_VW; }
203     bool isViewportPercentageHeight() const { return m_primitiveUnitType == CSS_VH; }
204     bool isViewportPercentageMax() const { return m_primitiveUnitType == CSS_VMAX; }
205     bool isViewportPercentageMin() const { return m_primitiveUnitType == CSS_VMIN; }
206     bool isValueID() const { return m_primitiveUnitType == CSS_VALUE_ID; }
207     bool isFlex() const { return primitiveType() == CSS_FR; }
208
209     static PassRef<CSSPrimitiveValue> createIdentifier(CSSValueID valueID) { return adoptRef(*new CSSPrimitiveValue(valueID)); }
210     static PassRef<CSSPrimitiveValue> createIdentifier(CSSPropertyID propertyID) { return adoptRef(*new CSSPrimitiveValue(propertyID)); }
211     static PassRef<CSSPrimitiveValue> createParserOperator(int parserOperator) { return adoptRef(*new CSSPrimitiveValue(parserOperator)); }
212
213     static PassRef<CSSPrimitiveValue> createColor(unsigned rgbValue) { return adoptRef(*new CSSPrimitiveValue(rgbValue)); }
214     static PassRef<CSSPrimitiveValue> create(double value, UnitTypes type) { return adoptRef(*new CSSPrimitiveValue(value, type)); }
215     static PassRef<CSSPrimitiveValue> create(const String& value, UnitTypes type) { return adoptRef(*new CSSPrimitiveValue(value, type)); }
216     static PassRef<CSSPrimitiveValue> create(const Length& value, const RenderStyle* style) { return adoptRef(*new CSSPrimitiveValue(value, style)); }
217     static PassRef<CSSPrimitiveValue> create(const LengthSize& value, const RenderStyle* style) { return adoptRef(*new CSSPrimitiveValue(value, style)); }
218
219     template<typename T> static PassRef<CSSPrimitiveValue> create(T value)
220     {
221         return adoptRef(*new CSSPrimitiveValue(value));
222     }
223
224     // This value is used to handle quirky margins in reflow roots (body, td, and th) like WinIE.
225     // The basic idea is that a stylesheet can use the value __qem (for quirky em) instead of em.
226     // When the quirky value is used, if you're in quirks mode, the margin will collapse away
227     // inside a table cell.
228     static PassRef<CSSPrimitiveValue> createAllowingMarginQuirk(double value, UnitTypes type)
229     {
230         CSSPrimitiveValue* quirkValue = new CSSPrimitiveValue(value, type);
231         quirkValue->m_isQuirkValue = true;
232         return adoptRef(*quirkValue);
233     }
234
235     ~CSSPrimitiveValue();
236
237     void cleanup();
238
239     unsigned short primitiveType() const;
240
241     double computeDegrees();
242
243     enum TimeUnit { Seconds, Milliseconds };
244     template <typename T, TimeUnit timeUnit> T computeTime()
245     {
246         if (timeUnit == Seconds && m_primitiveUnitType == CSS_S)
247             return getValue<T>();
248         if (timeUnit == Seconds && m_primitiveUnitType == CSS_MS)
249             return getValue<T>() / 1000;
250         if (timeUnit == Milliseconds && m_primitiveUnitType == CSS_MS)
251             return getValue<T>();
252         if (timeUnit == Milliseconds && m_primitiveUnitType == CSS_S)
253             return getValue<T>() * 1000;
254         ASSERT_NOT_REACHED();
255         return 0;
256     }
257
258     /*
259      * computes a length in pixels out of the given CSSValue. Need the RenderStyle to get
260      * the fontinfo in case val is defined in em or ex.
261      *
262      * The metrics have to be a bit different for screen and printer output.
263      * For screen output we assume 1 inch == 72 px, for printer we assume 300 dpi
264      *
265      * this is screen/printer dependent, so we probably need a config option for this,
266      * and some tool to calibrate.
267      */
268     template<typename T> T computeLength(const RenderStyle* currStyle, const RenderStyle* rootStyle, float multiplier = 1.0f, bool computingFontSize = false) const;
269
270     // Converts to a Length, mapping various unit types appropriately.
271     template<int> Length convertToLength(const RenderStyle* currStyle, const RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false) const;
272
273     // use with care!!!
274     void setPrimitiveType(unsigned short type) { m_primitiveUnitType = type; }
275
276     double getDoubleValue(unsigned short unitType, ExceptionCode&) const;
277     double getDoubleValue(unsigned short unitType) const;
278     double getDoubleValue() const;
279
280     void setFloatValue(unsigned short unitType, double floatValue, ExceptionCode&);
281     float getFloatValue(unsigned short unitType, ExceptionCode& ec) const { return getValue<float>(unitType, ec); }
282     float getFloatValue(unsigned short unitType) const { return getValue<float>(unitType); }
283     float getFloatValue() const { return getValue<float>(); }
284
285     int getIntValue(unsigned short unitType, ExceptionCode& ec) const { return getValue<int>(unitType, ec); }
286     int getIntValue(unsigned short unitType) const { return getValue<int>(unitType); }
287     int getIntValue() const { return getValue<int>(); }
288
289     template<typename T> inline T getValue(unsigned short unitType, ExceptionCode& ec) const { return clampTo<T>(getDoubleValue(unitType, ec)); }
290     template<typename T> inline T getValue(unsigned short unitType) const { return clampTo<T>(getDoubleValue(unitType)); }
291     template<typename T> inline T getValue() const { return clampTo<T>(getDoubleValue()); }
292
293     void setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode&);
294     String getStringValue(ExceptionCode&) const;
295     String getStringValue() const;
296
297     Counter* getCounterValue(ExceptionCode&) const;
298     Counter* getCounterValue() const { return m_primitiveUnitType != CSS_COUNTER ? 0 : m_value.counter; }
299
300     Rect* getRectValue(ExceptionCode&) const;
301     Rect* getRectValue() const { return m_primitiveUnitType != CSS_RECT ? 0 : m_value.rect; }
302
303     Quad* getQuadValue(ExceptionCode&) const;
304     Quad* getQuadValue() const { return m_primitiveUnitType != CSS_QUAD ? 0 : m_value.quad; }
305
306     PassRefPtr<RGBColor> getRGBColorValue(ExceptionCode&) const;
307     RGBA32 getRGBA32Value() const { return m_primitiveUnitType != CSS_RGBCOLOR ? 0 : m_value.rgbcolor; }
308
309     Pair* getPairValue(ExceptionCode&) const;
310     Pair* getPairValue() const { return m_primitiveUnitType != CSS_PAIR ? 0 : m_value.pair; }
311
312 #if ENABLE(DASHBOARD_SUPPORT)
313     DashboardRegion* getDashboardRegionValue() const { return m_primitiveUnitType != CSS_DASHBOARD_REGION ? 0 : m_value.region; }
314 #endif
315
316     CSSBasicShape* getShapeValue() const { return m_primitiveUnitType != CSS_SHAPE ? 0 : m_value.shape; }
317
318     CSSCalcValue* cssCalcValue() const { return m_primitiveUnitType != CSS_CALC ? 0 : m_value.calc; }
319
320     CSSPropertyID getPropertyID() const { return m_primitiveUnitType == CSS_PROPERTY_ID ? m_value.propertyID : CSSPropertyInvalid; }
321     CSSValueID getValueID() const { return m_primitiveUnitType == CSS_VALUE_ID ? m_value.valueID : CSSValueInvalid; }
322
323     template<typename T> inline operator T() const; // Defined in CSSPrimitiveValueMappings.h
324
325     String customCSSText() const;
326
327     bool isQuirkValue() { return m_isQuirkValue; }
328
329     void addSubresourceStyleURLs(ListHashSet<URL>&, const StyleSheetContents*) const;
330
331     Length viewportPercentageLength() const;
332
333     PassRefPtr<CSSPrimitiveValue> cloneForCSSOM() const;
334     void setCSSOMSafe() { m_isCSSOMSafe = true; }
335
336     bool equals(const CSSPrimitiveValue&) const;
337
338     static UnitTypes canonicalUnitTypeForCategory(UnitCategory);
339     static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType);
340
341 private:
342     CSSPrimitiveValue(CSSValueID);
343     CSSPrimitiveValue(CSSPropertyID);
344     // FIXME: int vs. unsigned overloading is too subtle to distinguish the color and operator cases.
345     CSSPrimitiveValue(int parserOperator);
346     CSSPrimitiveValue(unsigned color); // RGB value
347     CSSPrimitiveValue(const Length&);
348     CSSPrimitiveValue(const Length&, const RenderStyle*);
349     CSSPrimitiveValue(const LengthSize&, const RenderStyle*);
350     CSSPrimitiveValue(const String&, UnitTypes);
351     CSSPrimitiveValue(double, UnitTypes);
352
353     template<typename T> CSSPrimitiveValue(T); // Defined in CSSPrimitiveValueMappings.h
354     template<typename T> CSSPrimitiveValue(T* val)
355         : CSSValue(PrimitiveClass)
356     {
357         init(PassRefPtr<T>(val));
358     }
359
360     template<typename T> CSSPrimitiveValue(PassRefPtr<T> val)
361         : CSSValue(PrimitiveClass)
362     {
363         init(val);
364     }
365
366     static void create(int); // compile-time guard
367     static void create(unsigned); // compile-time guard
368     template<typename T> operator T*(); // compile-time guard
369
370     void init(const Length&);
371     void init(const LengthSize&, const RenderStyle*);
372     void init(PassRefPtr<Counter>);
373     void init(PassRefPtr<Rect>);
374     void init(PassRefPtr<Pair>);
375     void init(PassRefPtr<Quad>);
376     void init(PassRefPtr<DashboardRegion>); // FIXME: Dashboard region should not be a primitive value.
377     void init(PassRefPtr<CSSBasicShape>);
378     void init(PassRefPtr<CSSCalcValue>);
379     bool getDoubleValueInternal(UnitTypes targetUnitType, double* result) const;
380
381     double computeLengthDouble(const RenderStyle* currentStyle, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const;
382
383     union {
384         CSSPropertyID propertyID;
385         CSSValueID valueID;
386         int parserOperator;
387         double num;
388         StringImpl* string;
389         Counter* counter;
390         Rect* rect;
391         Quad* quad;
392         unsigned rgbcolor;
393         Pair* pair;
394         DashboardRegion* region;
395         CSSBasicShape* shape;
396         CSSCalcValue* calc;
397     } m_value;
398 };
399
400 CSS_VALUE_TYPE_CASTS(CSSPrimitiveValue, isPrimitiveValue())
401
402 } // namespace WebCore
403
404 #endif // CSSPrimitiveValue_h