1 /** 2 * (C) 1999-2003 Lars Knoll (knoll (at) 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 37 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 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 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 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 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 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 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