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 "core/css/CSSProperty.h"
23
24 #include "core/StylePropertyShorthand.h"
25 #include "core/css/CSSValueList.h"
26 #include "core/rendering/style/RenderStyleConstants.h"
27
28 namespace blink {
29
30 struct SameSizeAsCSSProperty {
31 uint32_t bitfields;
32 void* value;
33 };
34
35 COMPILE_ASSERT(sizeof(CSSProperty) == sizeof(SameSizeAsCSSProperty), CSSProperty_should_stay_small);
36
shorthandID() const37 CSSPropertyID StylePropertyMetadata::shorthandID() const
38 {
39 if (!m_isSetFromShorthand)
40 return CSSPropertyInvalid;
41
42 Vector<StylePropertyShorthand, 4> shorthands;
43 getMatchingShorthandsForLonghand(static_cast<CSSPropertyID>(m_propertyID), &shorthands);
44 ASSERT(shorthands.size() && m_indexInShorthandsVector >= 0 && m_indexInShorthandsVector < shorthands.size());
45 return shorthands.at(m_indexInShorthandsVector).id();
46 }
47
wrapValueInCommaSeparatedList()48 void CSSProperty::wrapValueInCommaSeparatedList()
49 {
50 RefPtrWillBeRawPtr<CSSValue> value = m_value.release();
51 m_value = CSSValueList::createCommaSeparated();
52 toCSSValueList(m_value.get())->append(value.release());
53 }
54
55 enum LogicalBoxSide { BeforeSide, EndSide, AfterSide, StartSide };
56 enum PhysicalBoxSide { TopSide, RightSide, BottomSide, LeftSide };
57
resolveToPhysicalProperty(TextDirection direction,WritingMode writingMode,LogicalBoxSide logicalSide,const StylePropertyShorthand & shorthand)58 static CSSPropertyID resolveToPhysicalProperty(TextDirection direction, WritingMode writingMode, LogicalBoxSide logicalSide, const StylePropertyShorthand& shorthand)
59 {
60 if (direction == LTR) {
61 if (writingMode == TopToBottomWritingMode) {
62 // The common case. The logical and physical box sides match.
63 // Left = Start, Right = End, Before = Top, After = Bottom
64 return shorthand.properties()[logicalSide];
65 }
66
67 if (writingMode == BottomToTopWritingMode) {
68 // Start = Left, End = Right, Before = Bottom, After = Top.
69 switch (logicalSide) {
70 case StartSide:
71 return shorthand.properties()[LeftSide];
72 case EndSide:
73 return shorthand.properties()[RightSide];
74 case BeforeSide:
75 return shorthand.properties()[BottomSide];
76 default:
77 return shorthand.properties()[TopSide];
78 }
79 }
80
81 if (writingMode == LeftToRightWritingMode) {
82 // Start = Top, End = Bottom, Before = Left, After = Right.
83 switch (logicalSide) {
84 case StartSide:
85 return shorthand.properties()[TopSide];
86 case EndSide:
87 return shorthand.properties()[BottomSide];
88 case BeforeSide:
89 return shorthand.properties()[LeftSide];
90 default:
91 return shorthand.properties()[RightSide];
92 }
93 }
94
95 // Start = Top, End = Bottom, Before = Right, After = Left
96 switch (logicalSide) {
97 case StartSide:
98 return shorthand.properties()[TopSide];
99 case EndSide:
100 return shorthand.properties()[BottomSide];
101 case BeforeSide:
102 return shorthand.properties()[RightSide];
103 default:
104 return shorthand.properties()[LeftSide];
105 }
106 }
107
108 if (writingMode == TopToBottomWritingMode) {
109 // Start = Right, End = Left, Before = Top, After = Bottom
110 switch (logicalSide) {
111 case StartSide:
112 return shorthand.properties()[RightSide];
113 case EndSide:
114 return shorthand.properties()[LeftSide];
115 case BeforeSide:
116 return shorthand.properties()[TopSide];
117 default:
118 return shorthand.properties()[BottomSide];
119 }
120 }
121
122 if (writingMode == BottomToTopWritingMode) {
123 // Start = Right, End = Left, Before = Bottom, After = Top
124 switch (logicalSide) {
125 case StartSide:
126 return shorthand.properties()[RightSide];
127 case EndSide:
128 return shorthand.properties()[LeftSide];
129 case BeforeSide:
130 return shorthand.properties()[BottomSide];
131 default:
132 return shorthand.properties()[TopSide];
133 }
134 }
135
136 if (writingMode == LeftToRightWritingMode) {
137 // Start = Bottom, End = Top, Before = Left, After = Right
138 switch (logicalSide) {
139 case StartSide:
140 return shorthand.properties()[BottomSide];
141 case EndSide:
142 return shorthand.properties()[TopSide];
143 case BeforeSide:
144 return shorthand.properties()[LeftSide];
145 default:
146 return shorthand.properties()[RightSide];
147 }
148 }
149
150 // Start = Bottom, End = Top, Before = Right, After = Left
151 switch (logicalSide) {
152 case StartSide:
153 return shorthand.properties()[BottomSide];
154 case EndSide:
155 return shorthand.properties()[TopSide];
156 case BeforeSide:
157 return shorthand.properties()[RightSide];
158 default:
159 return shorthand.properties()[LeftSide];
160 }
161 }
162
163 enum LogicalExtent { LogicalWidth, LogicalHeight };
164
resolveToPhysicalProperty(WritingMode writingMode,LogicalExtent logicalSide,const CSSPropertyID * properties)165 static CSSPropertyID resolveToPhysicalProperty(WritingMode writingMode, LogicalExtent logicalSide, const CSSPropertyID* properties)
166 {
167 if (writingMode == TopToBottomWritingMode || writingMode == BottomToTopWritingMode)
168 return properties[logicalSide];
169 return logicalSide == LogicalWidth ? properties[1] : properties[0];
170 }
171
borderDirections()172 static const StylePropertyShorthand& borderDirections()
173 {
174 static const CSSPropertyID properties[4] = { CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft };
175 DEFINE_STATIC_LOCAL(StylePropertyShorthand, borderDirections, (CSSPropertyBorder, properties, WTF_ARRAY_LENGTH(properties)));
176 return borderDirections;
177 }
178
resolveDirectionAwareProperty(CSSPropertyID propertyID,TextDirection direction,WritingMode writingMode)179 CSSPropertyID CSSProperty::resolveDirectionAwareProperty(CSSPropertyID propertyID, TextDirection direction, WritingMode writingMode)
180 {
181 switch (propertyID) {
182 case CSSPropertyWebkitMarginEnd:
183 return resolveToPhysicalProperty(direction, writingMode, EndSide, marginShorthand());
184 case CSSPropertyWebkitMarginStart:
185 return resolveToPhysicalProperty(direction, writingMode, StartSide, marginShorthand());
186 case CSSPropertyWebkitMarginBefore:
187 return resolveToPhysicalProperty(direction, writingMode, BeforeSide, marginShorthand());
188 case CSSPropertyWebkitMarginAfter:
189 return resolveToPhysicalProperty(direction, writingMode, AfterSide, marginShorthand());
190 case CSSPropertyWebkitPaddingEnd:
191 return resolveToPhysicalProperty(direction, writingMode, EndSide, paddingShorthand());
192 case CSSPropertyWebkitPaddingStart:
193 return resolveToPhysicalProperty(direction, writingMode, StartSide, paddingShorthand());
194 case CSSPropertyWebkitPaddingBefore:
195 return resolveToPhysicalProperty(direction, writingMode, BeforeSide, paddingShorthand());
196 case CSSPropertyWebkitPaddingAfter:
197 return resolveToPhysicalProperty(direction, writingMode, AfterSide, paddingShorthand());
198 case CSSPropertyWebkitBorderEnd:
199 return resolveToPhysicalProperty(direction, writingMode, EndSide, borderDirections());
200 case CSSPropertyWebkitBorderStart:
201 return resolveToPhysicalProperty(direction, writingMode, StartSide, borderDirections());
202 case CSSPropertyWebkitBorderBefore:
203 return resolveToPhysicalProperty(direction, writingMode, BeforeSide, borderDirections());
204 case CSSPropertyWebkitBorderAfter:
205 return resolveToPhysicalProperty(direction, writingMode, AfterSide, borderDirections());
206 case CSSPropertyWebkitBorderEndColor:
207 return resolveToPhysicalProperty(direction, writingMode, EndSide, borderColorShorthand());
208 case CSSPropertyWebkitBorderStartColor:
209 return resolveToPhysicalProperty(direction, writingMode, StartSide, borderColorShorthand());
210 case CSSPropertyWebkitBorderBeforeColor:
211 return resolveToPhysicalProperty(direction, writingMode, BeforeSide, borderColorShorthand());
212 case CSSPropertyWebkitBorderAfterColor:
213 return resolveToPhysicalProperty(direction, writingMode, AfterSide, borderColorShorthand());
214 case CSSPropertyWebkitBorderEndStyle:
215 return resolveToPhysicalProperty(direction, writingMode, EndSide, borderStyleShorthand());
216 case CSSPropertyWebkitBorderStartStyle:
217 return resolveToPhysicalProperty(direction, writingMode, StartSide, borderStyleShorthand());
218 case CSSPropertyWebkitBorderBeforeStyle:
219 return resolveToPhysicalProperty(direction, writingMode, BeforeSide, borderStyleShorthand());
220 case CSSPropertyWebkitBorderAfterStyle:
221 return resolveToPhysicalProperty(direction, writingMode, AfterSide, borderStyleShorthand());
222 case CSSPropertyWebkitBorderEndWidth:
223 return resolveToPhysicalProperty(direction, writingMode, EndSide, borderWidthShorthand());
224 case CSSPropertyWebkitBorderStartWidth:
225 return resolveToPhysicalProperty(direction, writingMode, StartSide, borderWidthShorthand());
226 case CSSPropertyWebkitBorderBeforeWidth:
227 return resolveToPhysicalProperty(direction, writingMode, BeforeSide, borderWidthShorthand());
228 case CSSPropertyWebkitBorderAfterWidth:
229 return resolveToPhysicalProperty(direction, writingMode, AfterSide, borderWidthShorthand());
230 case CSSPropertyWebkitLogicalWidth: {
231 const CSSPropertyID properties[2] = { CSSPropertyWidth, CSSPropertyHeight };
232 return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
233 }
234 case CSSPropertyWebkitLogicalHeight: {
235 const CSSPropertyID properties[2] = { CSSPropertyWidth, CSSPropertyHeight };
236 return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
237 }
238 case CSSPropertyWebkitMinLogicalWidth: {
239 const CSSPropertyID properties[2] = { CSSPropertyMinWidth, CSSPropertyMinHeight };
240 return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
241 }
242 case CSSPropertyWebkitMinLogicalHeight: {
243 const CSSPropertyID properties[2] = { CSSPropertyMinWidth, CSSPropertyMinHeight };
244 return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
245 }
246 case CSSPropertyWebkitMaxLogicalWidth: {
247 const CSSPropertyID properties[2] = { CSSPropertyMaxWidth, CSSPropertyMaxHeight };
248 return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
249 }
250 case CSSPropertyWebkitMaxLogicalHeight: {
251 const CSSPropertyID properties[2] = { CSSPropertyMaxWidth, CSSPropertyMaxHeight };
252 return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
253 }
254 default:
255 return propertyID;
256 }
257 }
258
isAffectedByAllProperty(CSSPropertyID propertyID)259 bool CSSProperty::isAffectedByAllProperty(CSSPropertyID propertyID)
260 {
261 if (propertyID == CSSPropertyAll)
262 return false;
263
264 // all shorthand spec says:
265 // The all property is a shorthand that resets all CSS properties except
266 // direction and unicode-bidi. It only accepts the CSS-wide keywords.
267 // c.f. http://dev.w3.org/csswg/css-cascade/#all-shorthand
268 // So CSSPropertyUnicodeBidi and CSSPropertyDirection are not
269 // affected by all property.
270 return propertyID != CSSPropertyUnicodeBidi && propertyID != CSSPropertyDirection;
271 }
272
273 } // namespace blink
274