38ddefc6b07c40e397f970ae25318ebd507a96ff
[WebKit-https.git] / Source / WebCore / css / CSSProperty.cpp
1 /**
2  * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22 #include "CSSProperty.h"
23
24 #include "CSSValueList.h"
25 #include "RenderStyleConstants.h"
26 #include "StylePropertyShorthand.h"
27
28 #include <wtf/text/StringBuilder.h>
29
30 namespace WebCore {
31
32 struct SameSizeAsCSSProperty {
33     uint32_t bitfields;
34     void* value;
35 };
36
37 COMPILE_ASSERT(sizeof(CSSProperty) == sizeof(SameSizeAsCSSProperty), CSSProperty_should_stay_small);
38
39 CSSPropertyID StylePropertyMetadata::shorthandID() const
40 {
41     if (!m_isSetFromShorthand)
42         return CSSPropertyInvalid;
43
44     Vector<StylePropertyShorthand> shorthands = matchingShorthandsForLonghand(static_cast<CSSPropertyID>(m_propertyID));
45     ASSERT(shorthands.size() && m_indexInShorthandsVector >= 0 && m_indexInShorthandsVector < shorthands.size());
46     return shorthands[m_indexInShorthandsVector].id();
47 }
48
49 void CSSProperty::wrapValueInCommaSeparatedList()
50 {
51     RefPtr<CSSValue> value = m_value.release();
52     m_value = CSSValueList::createCommaSeparated();
53     toCSSValueList(m_value.get())->append(value.release());
54 }
55
56 enum LogicalBoxSide { BeforeSide, EndSide, AfterSide, StartSide };
57 enum PhysicalBoxSide { TopSide, RightSide, BottomSide, LeftSide };
58
59 static CSSPropertyID resolveToPhysicalProperty(TextDirection direction, WritingMode writingMode, LogicalBoxSide logicalSide, const StylePropertyShorthand& shorthand)
60 {
61     if (direction == LTR) {
62         if (writingMode == TopToBottomWritingMode) {
63             // The common case. The logical and physical box sides match.
64             // Left = Start, Right = End, Before = Top, After = Bottom
65             return shorthand.properties()[logicalSide];
66         }
67
68         if (writingMode == BottomToTopWritingMode) {
69             // Start = Left, End = Right, Before = Bottom, After = Top.
70             switch (logicalSide) {
71             case StartSide:
72                 return shorthand.properties()[LeftSide];
73             case EndSide:
74                 return shorthand.properties()[RightSide];
75             case BeforeSide:
76                 return shorthand.properties()[BottomSide];
77             default:
78                 return shorthand.properties()[TopSide];
79             }
80         }
81
82         if (writingMode == LeftToRightWritingMode) {
83             // Start = Top, End = Bottom, Before = Left, After = Right.
84             switch (logicalSide) {
85             case StartSide:
86                 return shorthand.properties()[TopSide];
87             case EndSide:
88                 return shorthand.properties()[BottomSide];
89             case BeforeSide:
90                 return shorthand.properties()[LeftSide];
91             default:
92                 return shorthand.properties()[RightSide];
93             }
94         }
95
96         // Start = Top, End = Bottom, Before = Right, After = Left
97         switch (logicalSide) {
98         case StartSide:
99             return shorthand.properties()[TopSide];
100         case EndSide:
101             return shorthand.properties()[BottomSide];
102         case BeforeSide:
103             return shorthand.properties()[RightSide];
104         default:
105             return shorthand.properties()[LeftSide];
106         }
107     }
108
109     if (writingMode == TopToBottomWritingMode) {
110         // Start = Right, End = Left, Before = Top, After = Bottom
111         switch (logicalSide) {
112         case StartSide:
113             return shorthand.properties()[RightSide];
114         case EndSide:
115             return shorthand.properties()[LeftSide];
116         case BeforeSide:
117             return shorthand.properties()[TopSide];
118         default:
119             return shorthand.properties()[BottomSide];
120         }
121     }
122
123     if (writingMode == BottomToTopWritingMode) {
124         // Start = Right, End = Left, Before = Bottom, After = Top
125         switch (logicalSide) {
126         case StartSide:
127             return shorthand.properties()[RightSide];
128         case EndSide:
129             return shorthand.properties()[LeftSide];
130         case BeforeSide:
131             return shorthand.properties()[BottomSide];
132         default:
133             return shorthand.properties()[TopSide];
134         }
135     }
136
137     if (writingMode == LeftToRightWritingMode) {
138         // Start = Bottom, End = Top, Before = Left, After = Right
139         switch (logicalSide) {
140         case StartSide:
141             return shorthand.properties()[BottomSide];
142         case EndSide:
143             return shorthand.properties()[TopSide];
144         case BeforeSide:
145             return shorthand.properties()[LeftSide];
146         default:
147             return shorthand.properties()[RightSide];
148         }
149     }
150
151     // Start = Bottom, End = Top, Before = Right, After = Left
152     switch (logicalSide) {
153     case StartSide:
154         return shorthand.properties()[BottomSide];
155     case EndSide:
156         return shorthand.properties()[TopSide];
157     case BeforeSide:
158         return shorthand.properties()[RightSide];
159     default:
160         return shorthand.properties()[LeftSide];
161     }
162 }
163
164 enum LogicalExtent { LogicalWidth, LogicalHeight };
165
166 static CSSPropertyID resolveToPhysicalProperty(WritingMode writingMode, LogicalExtent logicalSide, const CSSPropertyID* properties)
167 {
168     if (writingMode == TopToBottomWritingMode || writingMode == BottomToTopWritingMode)
169         return properties[logicalSide];
170     return logicalSide == LogicalWidth ? properties[1] : properties[0];
171 }
172
173 static const StylePropertyShorthand& borderDirections()
174 {
175     static const CSSPropertyID properties[4] = { CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft };
176     DEFINE_STATIC_LOCAL(StylePropertyShorthand, borderDirections, (CSSPropertyBorder, properties, WTF_ARRAY_LENGTH(properties)));
177     return borderDirections;
178 }
179
180 CSSPropertyID CSSProperty::resolveDirectionAwareProperty(CSSPropertyID propertyID, TextDirection direction, WritingMode writingMode)
181 {
182     switch (propertyID) {
183     case CSSPropertyWebkitMarginEnd:
184         return resolveToPhysicalProperty(direction, writingMode, EndSide, marginShorthand());
185     case CSSPropertyWebkitMarginStart:
186         return resolveToPhysicalProperty(direction, writingMode, StartSide, marginShorthand());
187     case CSSPropertyWebkitMarginBefore:
188         return resolveToPhysicalProperty(direction, writingMode, BeforeSide, marginShorthand());
189     case CSSPropertyWebkitMarginAfter:
190         return resolveToPhysicalProperty(direction, writingMode, AfterSide, marginShorthand());
191     case CSSPropertyWebkitPaddingEnd:
192         return resolveToPhysicalProperty(direction, writingMode, EndSide, paddingShorthand());
193     case CSSPropertyWebkitPaddingStart:
194         return resolveToPhysicalProperty(direction, writingMode, StartSide, paddingShorthand());
195     case CSSPropertyWebkitPaddingBefore:
196         return resolveToPhysicalProperty(direction, writingMode, BeforeSide, paddingShorthand());
197     case CSSPropertyWebkitPaddingAfter:
198         return resolveToPhysicalProperty(direction, writingMode, AfterSide, paddingShorthand());
199     case CSSPropertyWebkitBorderEnd:
200         return resolveToPhysicalProperty(direction, writingMode, EndSide, borderDirections());
201     case CSSPropertyWebkitBorderStart:
202         return resolveToPhysicalProperty(direction, writingMode, StartSide, borderDirections());
203     case CSSPropertyWebkitBorderBefore:
204         return resolveToPhysicalProperty(direction, writingMode, BeforeSide, borderDirections());
205     case CSSPropertyWebkitBorderAfter:
206         return resolveToPhysicalProperty(direction, writingMode, AfterSide, borderDirections());
207     case CSSPropertyWebkitBorderEndColor:
208         return resolveToPhysicalProperty(direction, writingMode, EndSide, borderColorShorthand());
209     case CSSPropertyWebkitBorderStartColor:
210         return resolveToPhysicalProperty(direction, writingMode, StartSide, borderColorShorthand());
211     case CSSPropertyWebkitBorderBeforeColor:
212         return resolveToPhysicalProperty(direction, writingMode, BeforeSide, borderColorShorthand());
213     case CSSPropertyWebkitBorderAfterColor:
214         return resolveToPhysicalProperty(direction, writingMode, AfterSide, borderColorShorthand());
215     case CSSPropertyWebkitBorderEndStyle:
216         return resolveToPhysicalProperty(direction, writingMode, EndSide, borderStyleShorthand());
217     case CSSPropertyWebkitBorderStartStyle:
218         return resolveToPhysicalProperty(direction, writingMode, StartSide, borderStyleShorthand());
219     case CSSPropertyWebkitBorderBeforeStyle:
220         return resolveToPhysicalProperty(direction, writingMode, BeforeSide, borderStyleShorthand());
221     case CSSPropertyWebkitBorderAfterStyle:
222         return resolveToPhysicalProperty(direction, writingMode, AfterSide, borderStyleShorthand());
223     case CSSPropertyWebkitBorderEndWidth:
224         return resolveToPhysicalProperty(direction, writingMode, EndSide, borderWidthShorthand());
225     case CSSPropertyWebkitBorderStartWidth:
226         return resolveToPhysicalProperty(direction, writingMode, StartSide, borderWidthShorthand());
227     case CSSPropertyWebkitBorderBeforeWidth:
228         return resolveToPhysicalProperty(direction, writingMode, BeforeSide, borderWidthShorthand());
229     case CSSPropertyWebkitBorderAfterWidth:
230         return resolveToPhysicalProperty(direction, writingMode, AfterSide, borderWidthShorthand());
231     case CSSPropertyWebkitLogicalWidth: {
232         const CSSPropertyID properties[2] = { CSSPropertyWidth, CSSPropertyHeight };
233         return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
234     }
235     case CSSPropertyWebkitLogicalHeight: {
236         const CSSPropertyID properties[2] = { CSSPropertyWidth, CSSPropertyHeight };
237         return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
238     }
239     case CSSPropertyWebkitMinLogicalWidth: {
240         const CSSPropertyID properties[2] = { CSSPropertyMinWidth, CSSPropertyMinHeight };
241         return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
242     }
243     case CSSPropertyWebkitMinLogicalHeight: {
244         const CSSPropertyID properties[2] = { CSSPropertyMinWidth, CSSPropertyMinHeight };
245         return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
246     }
247     case CSSPropertyWebkitMaxLogicalWidth: {
248         const CSSPropertyID properties[2] = { CSSPropertyMaxWidth, CSSPropertyMaxHeight };
249         return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
250     }
251     case CSSPropertyWebkitMaxLogicalHeight: {
252         const CSSPropertyID properties[2] = { CSSPropertyMaxWidth, CSSPropertyMaxHeight };
253         return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
254     }
255     default:
256         return propertyID;
257     }
258 }
259
260 } // namespace WebCore