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
28namespace blink {
29
30struct SameSizeAsCSSProperty {
31    uint32_t bitfields;
32    void* value;
33};
34
35COMPILE_ASSERT(sizeof(CSSProperty) == sizeof(SameSizeAsCSSProperty), CSSProperty_should_stay_small);
36
37CSSPropertyID 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
48void 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
55enum LogicalBoxSide { BeforeSide, EndSide, AfterSide, StartSide };
56enum PhysicalBoxSide { TopSide, RightSide, BottomSide, LeftSide };
57
58static 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
163enum LogicalExtent { LogicalWidth, LogicalHeight };
164
165static 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
172static 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
179CSSPropertyID 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
259bool 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