OLD | NEW |
1 /* | 1 /* |
2 * (C) 1999-2003 Lars Knoll (knoll@kde.org) | 2 * (C) 1999-2003 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. | 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. |
4 * Copyright (C) 2011 Research In Motion Limited. All rights reserved. | 4 * Copyright (C) 2011 Research In Motion Limited. All rights reserved. |
5 * Copyright (C) 2013 Intel Corporation. All rights reserved. | 5 * Copyright (C) 2013 Intel Corporation. All rights reserved. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 if (isImportant) | 217 if (isImportant) |
218 result.appendLiteral(" !important"); | 218 result.appendLiteral(" !important"); |
219 result.append(';'); | 219 result.append(';'); |
220 return result.toString(); | 220 return result.toString(); |
221 } | 221 } |
222 | 222 |
223 String StylePropertySerializer::asText() const | 223 String StylePropertySerializer::asText() const |
224 { | 224 { |
225 StringBuilder result; | 225 StringBuilder result; |
226 | 226 |
227 std::bitset<numCSSProperties> shorthandPropertyUsed; | 227 std::bitset<numCSSProperties> longhandSerialized; |
228 std::bitset<numCSSProperties> shorthandPropertyAppeared; | 228 std::bitset<numCSSProperties> shorthandAppeared; |
| 229 |
| 230 bool backgroundLonghandSeen = false; |
229 | 231 |
230 unsigned size = m_propertySet.propertyCount(); | 232 unsigned size = m_propertySet.propertyCount(); |
231 unsigned numDecls = 0; | 233 unsigned numDecls = 0; |
232 for (unsigned n = 0; n < size; ++n) { | 234 for (unsigned n = 0; n < size; ++n) { |
233 if (!m_propertySet.shouldProcessPropertyAt(n)) | 235 if (!m_propertySet.shouldProcessPropertyAt(n)) |
234 continue; | 236 continue; |
235 | 237 |
236 StylePropertySerializer::PropertyValueForSerializer property = m_propert
ySet.propertyAt(n); | 238 StylePropertySerializer::PropertyValueForSerializer property = m_propert
ySet.propertyAt(n); |
237 CSSPropertyID propertyID = property.id(); | 239 CSSPropertyID propertyID = property.id(); |
238 // Only enabled properties should be part of the style. | 240 // Only enabled properties should be part of the style. |
239 ASSERT(CSSPropertyMetadata::isEnabledProperty(propertyID)); | 241 ASSERT(CSSPropertyMetadata::isEnabledProperty(propertyID)); |
240 CSSPropertyID shorthandPropertyID = CSSPropertyInvalid; | |
241 CSSPropertyID borderFallbackShorthandProperty = CSSPropertyInvalid; | |
242 String value; | |
243 // Shorthands with variable references are not expanded at parse time | 242 // Shorthands with variable references are not expanded at parse time |
244 // and hence may still be observed during serialization. | 243 // and hence may still be observed during serialization. |
245 ASSERT(!isShorthandProperty(propertyID) || property.value()->isVariableR
eferenceValue()); | 244 ASSERT(!isShorthandProperty(propertyID) || property.value()->isVariableR
eferenceValue()); |
246 | 245 |
247 switch (propertyID) { | 246 switch (propertyID) { |
248 case CSSPropertyBackgroundAttachment: | |
249 case CSSPropertyBackgroundClip: | |
250 case CSSPropertyBackgroundColor: | |
251 case CSSPropertyBackgroundImage: | |
252 case CSSPropertyBackgroundOrigin: | |
253 case CSSPropertyBackgroundPositionX: | |
254 case CSSPropertyBackgroundPositionY: | |
255 case CSSPropertyBackgroundSize: | |
256 case CSSPropertyBackgroundRepeatX: | |
257 case CSSPropertyBackgroundRepeatY: | |
258 shorthandPropertyAppeared.set(CSSPropertyBackground - firstCSSProper
ty); | |
259 continue; | |
260 case CSSPropertyBorderTopWidth: | |
261 case CSSPropertyBorderRightWidth: | |
262 case CSSPropertyBorderBottomWidth: | |
263 case CSSPropertyBorderLeftWidth: | |
264 if (!borderFallbackShorthandProperty) | |
265 borderFallbackShorthandProperty = CSSPropertyBorderWidth; | |
266 case CSSPropertyBorderTopStyle: | |
267 case CSSPropertyBorderRightStyle: | |
268 case CSSPropertyBorderBottomStyle: | |
269 case CSSPropertyBorderLeftStyle: | |
270 if (!borderFallbackShorthandProperty) | |
271 borderFallbackShorthandProperty = CSSPropertyBorderStyle; | |
272 case CSSPropertyBorderTopColor: | |
273 case CSSPropertyBorderRightColor: | |
274 case CSSPropertyBorderBottomColor: | |
275 case CSSPropertyBorderLeftColor: | |
276 if (!borderFallbackShorthandProperty) | |
277 borderFallbackShorthandProperty = CSSPropertyBorderColor; | |
278 | |
279 // FIXME: Deal with cases where only some of border-(top|right|botto
m|left) are specified. | |
280 if (!shorthandPropertyAppeared.test(CSSPropertyBorder - firstCSSProp
erty)) { | |
281 value = borderPropertyValue(); | |
282 if (value.isNull()) | |
283 shorthandPropertyAppeared.set(CSSPropertyBorder - firstCSSPr
operty); | |
284 else | |
285 shorthandPropertyID = CSSPropertyBorder; | |
286 } else if (shorthandPropertyUsed.test(CSSPropertyBorder - firstCSSPr
operty)) { | |
287 shorthandPropertyID = CSSPropertyBorder; | |
288 } | |
289 if (!shorthandPropertyID) | |
290 shorthandPropertyID = borderFallbackShorthandProperty; | |
291 break; | |
292 case CSSPropertyBorderTopLeftRadius: | |
293 case CSSPropertyBorderTopRightRadius: | |
294 case CSSPropertyBorderBottomLeftRadius: | |
295 case CSSPropertyBorderBottomRightRadius: | |
296 shorthandPropertyID = CSSPropertyBorderRadius; | |
297 break; | |
298 case CSSPropertyWebkitBorderHorizontalSpacing: | |
299 case CSSPropertyWebkitBorderVerticalSpacing: | |
300 shorthandPropertyID = CSSPropertyBorderSpacing; | |
301 break; | |
302 case CSSPropertyFontFamily: | |
303 case CSSPropertyLineHeight: | |
304 case CSSPropertyFontSize: | |
305 case CSSPropertyFontStretch: | |
306 case CSSPropertyFontStyle: | |
307 case CSSPropertyFontVariant: | |
308 case CSSPropertyFontWeight: | |
309 // Don't use CSSPropertyFont because old UAs can't recognize them bu
t are important for editing. | |
310 break; | |
311 case CSSPropertyListStyleType: | |
312 case CSSPropertyListStylePosition: | |
313 case CSSPropertyListStyleImage: | |
314 shorthandPropertyID = CSSPropertyListStyle; | |
315 break; | |
316 case CSSPropertyMarginTop: | |
317 case CSSPropertyMarginRight: | |
318 case CSSPropertyMarginBottom: | |
319 case CSSPropertyMarginLeft: | |
320 shorthandPropertyID = CSSPropertyMargin; | |
321 break; | |
322 case CSSPropertyMotionPath: | |
323 case CSSPropertyMotionOffset: | |
324 case CSSPropertyMotionRotation: | |
325 shorthandPropertyID = CSSPropertyMotion; | |
326 break; | |
327 case CSSPropertyOutlineWidth: | |
328 case CSSPropertyOutlineStyle: | |
329 case CSSPropertyOutlineColor: | |
330 shorthandPropertyID = CSSPropertyOutline; | |
331 break; | |
332 case CSSPropertyOverflowX: | |
333 case CSSPropertyOverflowY: | |
334 shorthandPropertyID = CSSPropertyOverflow; | |
335 break; | |
336 case CSSPropertyPaddingTop: | |
337 case CSSPropertyPaddingRight: | |
338 case CSSPropertyPaddingBottom: | |
339 case CSSPropertyPaddingLeft: | |
340 shorthandPropertyID = CSSPropertyPadding; | |
341 break; | |
342 case CSSPropertyTransitionProperty: | |
343 case CSSPropertyTransitionDuration: | |
344 case CSSPropertyTransitionTimingFunction: | |
345 case CSSPropertyTransitionDelay: | |
346 shorthandPropertyID = CSSPropertyTransition; | |
347 break; | |
348 case CSSPropertyAnimationName: | |
349 case CSSPropertyAnimationDuration: | |
350 case CSSPropertyAnimationTimingFunction: | |
351 case CSSPropertyAnimationDelay: | |
352 case CSSPropertyAnimationIterationCount: | |
353 case CSSPropertyAnimationDirection: | |
354 case CSSPropertyAnimationFillMode: | |
355 case CSSPropertyAnimationPlayState: | |
356 shorthandPropertyID = CSSPropertyAnimation; | |
357 break; | |
358 case CSSPropertyFlexDirection: | |
359 case CSSPropertyFlexWrap: | |
360 shorthandPropertyID = CSSPropertyFlexFlow; | |
361 break; | |
362 case CSSPropertyFlexBasis: | |
363 case CSSPropertyFlexGrow: | |
364 case CSSPropertyFlexShrink: | |
365 shorthandPropertyID = CSSPropertyFlex; | |
366 break; | |
367 case CSSPropertyWebkitMaskPositionX: | |
368 case CSSPropertyWebkitMaskPositionY: | |
369 case CSSPropertyWebkitMaskRepeatX: | |
370 case CSSPropertyWebkitMaskRepeatY: | |
371 case CSSPropertyWebkitMaskImage: | |
372 case CSSPropertyWebkitMaskRepeat: | |
373 case CSSPropertyWebkitMaskPosition: | |
374 case CSSPropertyWebkitMaskClip: | |
375 case CSSPropertyWebkitMaskOrigin: | |
376 shorthandPropertyID = CSSPropertyWebkitMask; | |
377 break; | |
378 case CSSPropertyVariable: | 247 case CSSPropertyVariable: |
379 result.append(getCustomPropertyText(property, numDecls++)); | 248 result.append(getCustomPropertyText(property, numDecls++)); |
380 continue; | 249 continue; |
381 case CSSPropertyAll: | 250 case CSSPropertyAll: |
382 result.append(getPropertyText(propertyID, property.value()->cssText(
), property.isImportant(), numDecls++)); | 251 result.append(getPropertyText(propertyID, property.value()->cssText(
), property.isImportant(), numDecls++)); |
383 continue; | 252 continue; |
384 case CSSPropertyApplyAtRule: | 253 case CSSPropertyApplyAtRule: |
385 result.append(getApplyAtRuleText(property.value(), numDecls++)); | 254 result.append(getApplyAtRuleText(property.value(), numDecls++)); |
386 continue; | 255 continue; |
387 default: | 256 default: |
388 break; | 257 break; |
389 } | 258 } |
| 259 if (longhandSerialized.test(propertyID - firstCSSProperty)) |
| 260 continue; |
390 | 261 |
391 unsigned shortPropertyIndex = shorthandPropertyID - firstCSSProperty; | 262 Vector<StylePropertyShorthand, 4> shorthands; |
392 if (shorthandPropertyID) { | 263 getMatchingShorthandsForLonghand(propertyID, &shorthands); |
393 if (shorthandPropertyUsed.test(shortPropertyIndex)) | 264 bool serializedAsShorthand = false; |
| 265 for (const StylePropertyShorthand& shorthand : shorthands) { |
| 266 // Some aliases are implemented as a shorthand, in which case |
| 267 // we prefer to not use the shorthand. |
| 268 if (shorthand.length() == 1) |
394 continue; | 269 continue; |
395 if (!shorthandPropertyAppeared.test(shortPropertyIndex) && value.isN
ull()) | 270 |
396 value = m_propertySet.getPropertyValue(shorthandPropertyID); | 271 CSSPropertyID shorthandProperty = shorthand.id(); |
397 shorthandPropertyAppeared.set(shortPropertyIndex); | 272 int shorthandPropertyIndex = shorthandProperty - firstCSSProperty; |
| 273 // TODO(timloh): Do we actually need this check? A previous comment |
| 274 // said "old UAs can't recognize them but are important for editing" |
| 275 // but Firefox doesn't do this. |
| 276 if (shorthandProperty == CSSPropertyFont) |
| 277 continue; |
| 278 // TODO(timloh): Why is background special? |
| 279 if (shorthandProperty == CSSPropertyBackground) { |
| 280 serializedAsShorthand = true; |
| 281 backgroundLonghandSeen = true; |
| 282 break; |
| 283 } |
| 284 // We already tried serializing as this shorthand |
| 285 if (shorthandAppeared.test(shorthandPropertyIndex)) |
| 286 continue; |
| 287 |
| 288 shorthandAppeared.set(shorthandPropertyIndex); |
| 289 bool serializedOtherLonghand = false; |
| 290 for (unsigned i = 0; i < shorthand.length(); i++) { |
| 291 if (longhandSerialized.test(shorthand.properties()[i] - firstCSS
Property)) { |
| 292 serializedOtherLonghand = true; |
| 293 break; |
| 294 } |
| 295 } |
| 296 if (serializedOtherLonghand) |
| 297 continue; |
| 298 |
| 299 String shorthandResult = StylePropertySerializer::getPropertyValue(s
horthandProperty); |
| 300 if (shorthandResult.isEmpty()) |
| 301 continue; |
| 302 |
| 303 result.append(getPropertyText(shorthandProperty, shorthandResult, pr
operty.isImportant(), numDecls++)); |
| 304 serializedAsShorthand = true; |
| 305 for (unsigned i = 0; i < shorthand.length(); i++) |
| 306 longhandSerialized.set(shorthand.properties()[i] - firstCSSPrope
rty); |
| 307 break; |
398 } | 308 } |
399 | 309 |
400 if (!value.isNull()) { | 310 if (serializedAsShorthand) |
401 if (shorthandPropertyID) { | 311 continue; |
402 propertyID = shorthandPropertyID; | |
403 shorthandPropertyUsed.set(shortPropertyIndex); | |
404 } | |
405 } else { | |
406 // We should not show "initial" when the "initial" is implicit. | |
407 // If explicit "initial", we need to show. | |
408 if (property.value()->isImplicitInitialValue()) | |
409 continue; | |
410 value = property.value()->cssText(); | |
411 } | |
412 | 312 |
413 result.append(getPropertyText(propertyID, value, property.isImportant(),
numDecls++)); | 313 // TODO(timloh): This is wrong and makes declarations not round-trip. |
| 314 if (property.value()->isImplicitInitialValue()) |
| 315 continue; |
| 316 |
| 317 result.append(getPropertyText(propertyID, property.value()->cssText(), p
roperty.isImportant(), numDecls++)); |
414 } | 318 } |
415 | 319 |
416 if (shorthandPropertyAppeared.test(CSSPropertyBackground - firstCSSProperty)
) | 320 if (backgroundLonghandSeen) |
417 appendBackgroundPropertyAsText(result, numDecls); | 321 appendBackgroundPropertyAsText(result, numDecls); |
418 | 322 |
419 ASSERT(!numDecls ^ !result.isEmpty()); | 323 ASSERT(!numDecls ^ !result.isEmpty()); |
420 return result.toString(); | 324 return result.toString(); |
421 } | 325 } |
422 | 326 |
423 String StylePropertySerializer::getPropertyValue(CSSPropertyID propertyID) const | 327 String StylePropertySerializer::getPropertyValue(CSSPropertyID propertyID) const |
424 { | 328 { |
425 // Shorthand and 4-values properties | 329 // Shorthand and 4-values properties |
426 switch (propertyID) { | 330 switch (propertyID) { |
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1076 isInitialValue = false; | 980 isInitialValue = false; |
1077 if (!value->isInheritedValue()) | 981 if (!value->isInheritedValue()) |
1078 isInheritedValue = false; | 982 isInheritedValue = false; |
1079 if (isImportant != m_propertySet.propertyIsImportant(shorthand.propertie
s()[i])) | 983 if (isImportant != m_propertySet.propertyIsImportant(shorthand.propertie
s()[i])) |
1080 return false; | 984 return false; |
1081 } | 985 } |
1082 return isInitialValue || isInheritedValue; | 986 return isInitialValue || isInheritedValue; |
1083 } | 987 } |
1084 | 988 |
1085 } // namespace blink | 989 } // namespace blink |
OLD | NEW |