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 15 matching lines...) Expand all Loading... | |
26 #include "core/StylePropertyShorthand.h" | 26 #include "core/StylePropertyShorthand.h" |
27 #include "core/css/CSSCustomPropertyDeclaration.h" | 27 #include "core/css/CSSCustomPropertyDeclaration.h" |
28 #include "core/css/CSSPropertyMetadata.h" | 28 #include "core/css/CSSPropertyMetadata.h" |
29 #include "core/css/CSSValuePool.h" | 29 #include "core/css/CSSValuePool.h" |
30 #include "wtf/StdLibExtras.h" | 30 #include "wtf/StdLibExtras.h" |
31 #include "wtf/text/StringBuilder.h" | 31 #include "wtf/text/StringBuilder.h" |
32 #include <bitset> | 32 #include <bitset> |
33 | 33 |
34 namespace blink { | 34 namespace blink { |
35 | 35 |
36 static bool isInitialOrInherit(const String& value) | |
37 { | |
38 return value.length() == 7 && (value == "initial" || value == "inherit"); | |
39 } | |
40 | |
41 StylePropertySerializer::StylePropertySetForSerializer::StylePropertySetForSeria lizer(const StylePropertySet& properties) | 36 StylePropertySerializer::StylePropertySetForSerializer::StylePropertySetForSeria lizer(const StylePropertySet& properties) |
42 : m_propertySet(&properties) | 37 : m_propertySet(&properties) |
43 , m_allIndex(m_propertySet->findPropertyIndex(CSSPropertyAll)) | 38 , m_allIndex(m_propertySet->findPropertyIndex(CSSPropertyAll)) |
44 , m_needToExpandAll(false) | 39 , m_needToExpandAll(false) |
45 { | 40 { |
46 if (!hasAllProperty()) | 41 if (!hasAllProperty()) |
47 return; | 42 return; |
48 | 43 |
49 StylePropertySet::PropertyReference allProperty = m_propertySet->propertyAt( m_allIndex); | 44 StylePropertySet::PropertyReference allProperty = m_propertySet->propertyAt( m_allIndex); |
50 for (unsigned i = 0; i < m_propertySet->propertyCount(); ++i) { | 45 for (unsigned i = 0; i < m_propertySet->propertyCount(); ++i) { |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
220 return result.toString(); | 215 return result.toString(); |
221 } | 216 } |
222 | 217 |
223 String StylePropertySerializer::asText() const | 218 String StylePropertySerializer::asText() const |
224 { | 219 { |
225 StringBuilder result; | 220 StringBuilder result; |
226 | 221 |
227 std::bitset<numCSSProperties> longhandSerialized; | 222 std::bitset<numCSSProperties> longhandSerialized; |
228 std::bitset<numCSSProperties> shorthandAppeared; | 223 std::bitset<numCSSProperties> shorthandAppeared; |
229 | 224 |
230 bool backgroundLonghandSeen = false; | |
231 | |
232 unsigned size = m_propertySet.propertyCount(); | 225 unsigned size = m_propertySet.propertyCount(); |
233 unsigned numDecls = 0; | 226 unsigned numDecls = 0; |
234 for (unsigned n = 0; n < size; ++n) { | 227 for (unsigned n = 0; n < size; ++n) { |
235 if (!m_propertySet.shouldProcessPropertyAt(n)) | 228 if (!m_propertySet.shouldProcessPropertyAt(n)) |
236 continue; | 229 continue; |
237 | 230 |
238 StylePropertySerializer::PropertyValueForSerializer property = m_propert ySet.propertyAt(n); | 231 StylePropertySerializer::PropertyValueForSerializer property = m_propert ySet.propertyAt(n); |
239 CSSPropertyID propertyID = property.id(); | 232 CSSPropertyID propertyID = property.id(); |
240 // Only enabled properties should be part of the style. | 233 // Only enabled properties should be part of the style. |
241 ASSERT(CSSPropertyMetadata::isEnabledProperty(propertyID)); | 234 ASSERT(CSSPropertyMetadata::isEnabledProperty(propertyID)); |
(...skipping 26 matching lines...) Expand all Loading... | |
268 if (shorthand.length() == 1) | 261 if (shorthand.length() == 1) |
269 continue; | 262 continue; |
270 | 263 |
271 CSSPropertyID shorthandProperty = shorthand.id(); | 264 CSSPropertyID shorthandProperty = shorthand.id(); |
272 int shorthandPropertyIndex = shorthandProperty - firstCSSProperty; | 265 int shorthandPropertyIndex = shorthandProperty - firstCSSProperty; |
273 // TODO(timloh): Do we actually need this check? A previous comment | 266 // TODO(timloh): Do we actually need this check? A previous comment |
274 // said "old UAs can't recognize them but are important for editing" | 267 // said "old UAs can't recognize them but are important for editing" |
275 // but Firefox doesn't do this. | 268 // but Firefox doesn't do this. |
276 if (shorthandProperty == CSSPropertyFont) | 269 if (shorthandProperty == CSSPropertyFont) |
277 continue; | 270 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 | 271 // We already tried serializing as this shorthand |
285 if (shorthandAppeared.test(shorthandPropertyIndex)) | 272 if (shorthandAppeared.test(shorthandPropertyIndex)) |
286 continue; | 273 continue; |
287 | 274 |
288 shorthandAppeared.set(shorthandPropertyIndex); | 275 shorthandAppeared.set(shorthandPropertyIndex); |
289 bool serializedOtherLonghand = false; | 276 bool serializedOtherLonghand = false; |
290 for (unsigned i = 0; i < shorthand.length(); i++) { | 277 for (unsigned i = 0; i < shorthand.length(); i++) { |
291 if (longhandSerialized.test(shorthand.properties()[i] - firstCSS Property)) { | 278 if (longhandSerialized.test(shorthand.properties()[i] - firstCSS Property)) { |
292 serializedOtherLonghand = true; | 279 serializedOtherLonghand = true; |
293 break; | 280 break; |
294 } | 281 } |
295 } | 282 } |
296 if (serializedOtherLonghand) | 283 if (serializedOtherLonghand) |
297 continue; | 284 continue; |
298 | 285 |
299 String shorthandResult = StylePropertySerializer::getPropertyValue(s horthandProperty); | 286 String shorthandResult = StylePropertySerializer::getPropertyValue(s horthandProperty); |
300 if (shorthandResult.isEmpty()) | 287 if (shorthandResult.isEmpty()) |
301 continue; | 288 continue; |
302 | 289 |
303 result.append(getPropertyText(shorthandProperty, shorthandResult, pr operty.isImportant(), numDecls++)); | 290 result.append(getPropertyText(shorthandProperty, shorthandResult, pr operty.isImportant(), numDecls++)); |
304 serializedAsShorthand = true; | 291 serializedAsShorthand = true; |
305 for (unsigned i = 0; i < shorthand.length(); i++) | 292 for (unsigned i = 0; i < shorthand.length(); i++) |
306 longhandSerialized.set(shorthand.properties()[i] - firstCSSPrope rty); | 293 longhandSerialized.set(shorthand.properties()[i] - firstCSSPrope rty); |
307 break; | 294 break; |
308 } | 295 } |
309 | 296 |
310 if (serializedAsShorthand) | 297 if (serializedAsShorthand) |
311 continue; | 298 continue; |
312 | 299 |
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++)); | 300 result.append(getPropertyText(propertyID, property.value()->cssText(), p roperty.isImportant(), numDecls++)); |
318 } | 301 } |
319 | 302 |
320 if (backgroundLonghandSeen) | |
321 appendBackgroundPropertyAsText(result, numDecls); | |
322 | |
323 ASSERT(!numDecls ^ !result.isEmpty()); | 303 ASSERT(!numDecls ^ !result.isEmpty()); |
324 return result.toString(); | 304 return result.toString(); |
325 } | 305 } |
326 | 306 |
307 // As per css-cascade, shorthands do not expand longhands to the value | |
308 // "initial", except when the shorthand is set to "initial", instead | |
309 // setting "missing" sub-properties to their initial values. This means | |
310 // that a shorthand can never represent a list of subproperties where | |
311 // some are "initial" and some are not, and so serialization should | |
312 // always fail in these cases (as per cssom). However we currently use | |
313 // "intiial" instead of the initial values for certain shorthands, so | |
alancutter (OOO until 2018)
2016/05/18 07:32:54
s/"intiial"/"initial"/?
Timothy Loh
2016/05/18 08:09:44
Done.
| |
314 // these are special-cased here. | |
alancutter (OOO until 2018)
2016/05/18 07:47:36
This sounds like it should be a TODO to remove thi
Timothy Loh
2016/05/18 08:09:43
Added a TODO. I don't think I've seen any bugs fil
| |
315 static bool allowInitialInShorthand(CSSPropertyID propertyID) | |
316 { | |
317 switch (propertyID) { | |
318 case CSSPropertyBorder: | |
319 case CSSPropertyBorderTop: | |
320 case CSSPropertyBorderRight: | |
321 case CSSPropertyBorderBottom: | |
322 case CSSPropertyBorderLeft: | |
323 case CSSPropertyOutline: | |
324 case CSSPropertyColumnRule: | |
325 case CSSPropertyColumns: | |
326 case CSSPropertyFlex: | |
327 case CSSPropertyFlexFlow: | |
328 case CSSPropertyGridColumn: | |
329 case CSSPropertyGridRow: | |
330 case CSSPropertyGridArea: | |
331 case CSSPropertyGridGap: | |
332 case CSSPropertyMotion: | |
333 case CSSPropertyWebkitMarginCollapse: | |
334 case CSSPropertyListStyle: | |
335 case CSSPropertyWebkitTextEmphasis: | |
336 case CSSPropertyWebkitTextStroke: | |
337 return true; | |
338 default: | |
339 return false; | |
340 } | |
341 } | |
342 | |
343 // TODO(timloh): This should go away eventually, see crbug.com/471917 | |
344 static bool allowImplicitInitialInShorthand(CSSPropertyID propertyID) | |
345 { | |
346 return propertyID == CSSPropertyBackground || propertyID == CSSPropertyWebki tMask; | |
347 } | |
348 | |
349 StylePropertySerializer::GenericCheckResult StylePropertySerializer::genericShor thandChecks(const StylePropertyShorthand& shorthand, String& result) const | |
350 { | |
351 int longhandCount = shorthand.length(); | |
352 DCHECK_LE(longhandCount, 17); | |
alancutter (OOO until 2018)
2016/05/18 07:47:36
Out of bounds checking should probably be in relea
Timothy Loh
2016/05/18 08:09:43
Why? This doesn't need to be in official builds. R
| |
353 const CSSValue* longhands[17] = {}; | |
354 | |
355 bool hasImportant = false; | |
356 bool hasNonImportant = false; | |
357 | |
358 for (int i = 0; i < longhandCount; i++) { | |
359 int index = m_propertySet.findPropertyIndex(shorthand.properties()[i]); | |
360 if (index == -1) | |
361 return Invalid; | |
362 PropertyValueForSerializer value = m_propertySet.propertyAt(index); | |
363 | |
364 hasImportant |= value.isImportant(); | |
365 hasNonImportant |= !value.isImportant(); | |
366 longhands[i] = value.value(); | |
367 } | |
368 | |
369 if (hasImportant && hasNonImportant) | |
370 return Invalid; | |
371 | |
372 // TODO(timloh): This should be isCSSWideKeyword() | |
373 if (longhands[0]->isInitialValue() || longhands[0]->isInheritedValue()) { | |
374 bool success = true; | |
375 for (int i = 1; i < longhandCount; i++) { | |
376 if (!longhands[i]->equals(*longhands[0])) { | |
377 // This should just return Invalid but some shorthands currently | |
378 // allow 'initial' for their longhands. | |
379 success = false; | |
380 break; | |
381 } | |
382 } | |
383 if (success) { | |
384 result = longhands[0]->cssText(); | |
385 return Valid; | |
386 } | |
387 } | |
388 | |
389 bool allowInitial = allowInitialInShorthand(shorthand.id()); | |
390 bool allowImplicitInitial = allowInitial || allowImplicitInitialInShorthand( shorthand.id()); | |
alancutter (OOO until 2018)
2016/05/18 07:47:36
TODO remove these allowances?
Timothy Loh
2016/05/18 08:09:43
implied by above TODOs
| |
391 for (int i = 0; i < longhandCount; i++) { | |
392 const CSSValue& value = *longhands[i]; | |
393 if (value.isImplicitInitialValue()) { | |
394 if (allowImplicitInitial) | |
395 continue; | |
396 return Invalid; | |
397 } | |
398 if (!allowInitial && value.isInitialValue()) | |
399 return Invalid; | |
400 // TODO(timloh): This should also check unset | |
401 if (value.isInheritedValue()) | |
402 return Invalid; | |
403 } | |
404 | |
405 | |
406 return Unknown; | |
407 } | |
408 | |
327 String StylePropertySerializer::getPropertyValue(CSSPropertyID propertyID) const | 409 String StylePropertySerializer::getPropertyValue(CSSPropertyID propertyID) const |
328 { | 410 { |
329 // Shorthand and 4-values properties | 411 const StylePropertyShorthand& shorthand = shorthandForProperty(propertyID); |
412 // TODO(timloh): This is weird, why do we call this with non-shorthands at a ll? | |
413 if (!shorthand.length()) | |
414 return String(); | |
415 | |
416 String result; | |
417 GenericCheckResult genericCheckResult = genericShorthandChecks(shorthand, re sult); | |
418 if (genericCheckResult == Valid) | |
419 return result; | |
420 if (genericCheckResult == Invalid) | |
421 return String(); | |
422 | |
330 switch (propertyID) { | 423 switch (propertyID) { |
331 case CSSPropertyAnimation: | 424 case CSSPropertyAnimation: |
332 return getLayeredShorthandValue(animationShorthand()); | 425 return getLayeredShorthandValue(animationShorthand()); |
333 case CSSPropertyBorderSpacing: | 426 case CSSPropertyBorderSpacing: |
334 return borderSpacingValue(borderSpacingShorthand()); | 427 return borderSpacingValue(borderSpacingShorthand()); |
335 case CSSPropertyBackgroundPosition: | 428 case CSSPropertyBackgroundPosition: |
336 return getLayeredShorthandValue(backgroundPositionShorthand()); | 429 return getLayeredShorthandValue(backgroundPositionShorthand()); |
337 case CSSPropertyBackgroundRepeat: | 430 case CSSPropertyBackgroundRepeat: |
338 return backgroundRepeatPropertyValue(); | 431 return backgroundRepeatPropertyValue(); |
339 case CSSPropertyBackground: | 432 case CSSPropertyBackground: |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
410 default: | 503 default: |
411 return String(); | 504 return String(); |
412 } | 505 } |
413 } | 506 } |
414 | 507 |
415 String StylePropertySerializer::borderSpacingValue(const StylePropertyShorthand& shorthand) const | 508 String StylePropertySerializer::borderSpacingValue(const StylePropertyShorthand& shorthand) const |
416 { | 509 { |
417 const CSSValue* horizontalValue = m_propertySet.getPropertyCSSValue(shorthan d.properties()[0]); | 510 const CSSValue* horizontalValue = m_propertySet.getPropertyCSSValue(shorthan d.properties()[0]); |
418 const CSSValue* verticalValue = m_propertySet.getPropertyCSSValue(shorthand. properties()[1]); | 511 const CSSValue* verticalValue = m_propertySet.getPropertyCSSValue(shorthand. properties()[1]); |
419 | 512 |
420 // While standard border-spacing property does not allow specifying border-s pacing-vertical without | |
421 // specifying border-spacing-horizontal <http://www.w3.org/TR/CSS21/tables.h tml#separated-borders>, | |
422 // -webkit-border-spacing-vertical can be set without -webkit-border-spacing -horizontal. | |
423 if (!horizontalValue || !verticalValue) | |
424 return String(); | |
425 | |
426 String horizontalValueCSSText = horizontalValue->cssText(); | 513 String horizontalValueCSSText = horizontalValue->cssText(); |
427 String verticalValueCSSText = verticalValue->cssText(); | 514 String verticalValueCSSText = verticalValue->cssText(); |
428 if (horizontalValueCSSText == verticalValueCSSText) | 515 if (horizontalValueCSSText == verticalValueCSSText) |
429 return horizontalValueCSSText; | 516 return horizontalValueCSSText; |
430 return horizontalValueCSSText + ' ' + verticalValueCSSText; | 517 return horizontalValueCSSText + ' ' + verticalValueCSSText; |
431 } | 518 } |
432 | 519 |
433 void StylePropertySerializer::appendFontLonghandValueIfNotNormal(CSSPropertyID p ropertyID, StringBuilder& result, String& commonValue) const | 520 void StylePropertySerializer::appendFontLonghandValueIfNotNormal(CSSPropertyID p ropertyID, StringBuilder& result) const |
434 { | 521 { |
435 int foundPropertyIndex = m_propertySet.findPropertyIndex(propertyID); | 522 int foundPropertyIndex = m_propertySet.findPropertyIndex(propertyID); |
436 ASSERT(foundPropertyIndex != -1); | 523 ASSERT(foundPropertyIndex != -1); |
437 | 524 |
438 const CSSValue* val = m_propertySet.propertyAt(foundPropertyIndex).value(); | 525 const CSSValue* val = m_propertySet.propertyAt(foundPropertyIndex).value(); |
439 if (val->isPrimitiveValue() && toCSSPrimitiveValue(val)->getValueID() == CSS ValueNormal) { | 526 if (val->isPrimitiveValue() && toCSSPrimitiveValue(val)->getValueID() == CSS ValueNormal) |
440 commonValue = String(); | |
441 return; | 527 return; |
442 } | |
443 | 528 |
444 char prefix = '\0'; | 529 char prefix = '\0'; |
445 switch (propertyID) { | 530 switch (propertyID) { |
446 case CSSPropertyFontStyle: | 531 case CSSPropertyFontStyle: |
447 break; // No prefix. | 532 break; // No prefix. |
448 case CSSPropertyFontFamily: | 533 case CSSPropertyFontFamily: |
449 case CSSPropertyFontStretch: | 534 case CSSPropertyFontStretch: |
450 case CSSPropertyFontVariantCaps: | 535 case CSSPropertyFontVariantCaps: |
451 case CSSPropertyFontVariantLigatures: | 536 case CSSPropertyFontVariantLigatures: |
452 case CSSPropertyFontVariantNumeric: | 537 case CSSPropertyFontVariantNumeric: |
(...skipping 14 matching lines...) Expand all Loading... | |
467 // In the font-variant shorthand a "none" ligatures value needs to be expand ed. | 552 // In the font-variant shorthand a "none" ligatures value needs to be expand ed. |
468 if (propertyID == CSSPropertyFontVariantLigatures | 553 if (propertyID == CSSPropertyFontVariantLigatures |
469 && val->isPrimitiveValue() | 554 && val->isPrimitiveValue() |
470 && toCSSPrimitiveValue(val)->getValueID() == CSSValueNone) { | 555 && toCSSPrimitiveValue(val)->getValueID() == CSSValueNone) { |
471 value = "no-common-ligatures no-discretionary-ligatures no-historical-li gatures no-contextual"; | 556 value = "no-common-ligatures no-discretionary-ligatures no-historical-li gatures no-contextual"; |
472 } else { | 557 } else { |
473 value = m_propertySet.propertyAt(foundPropertyIndex).value()->cssText(); | 558 value = m_propertySet.propertyAt(foundPropertyIndex).value()->cssText(); |
474 } | 559 } |
475 | 560 |
476 result.append(value); | 561 result.append(value); |
477 if (!commonValue.isNull() && commonValue != value) | |
478 commonValue = String(); | |
479 } | 562 } |
480 | 563 |
481 String StylePropertySerializer::fontValue() const | 564 String StylePropertySerializer::fontValue() const |
482 { | 565 { |
483 if (!isPropertyShorthandAvailable(fontShorthand()) && !shorthandHasOnlyIniti alOrInheritedValue(fontShorthand())) | |
484 return emptyString(); | |
485 | |
486 int fontSizePropertyIndex = m_propertySet.findPropertyIndex(CSSPropertyFontS ize); | 566 int fontSizePropertyIndex = m_propertySet.findPropertyIndex(CSSPropertyFontS ize); |
487 int fontFamilyPropertyIndex = m_propertySet.findPropertyIndex(CSSPropertyFon tFamily); | 567 int fontFamilyPropertyIndex = m_propertySet.findPropertyIndex(CSSPropertyFon tFamily); |
488 int fontVariantCapsPropertyIndex = m_propertySet.findPropertyIndex(CSSProper tyFontVariantCaps); | 568 int fontVariantCapsPropertyIndex = m_propertySet.findPropertyIndex(CSSProper tyFontVariantCaps); |
489 int fontVariantLigaturesPropertyIndex = m_propertySet.findPropertyIndex(CSSP ropertyFontVariantLigatures); | 569 int fontVariantLigaturesPropertyIndex = m_propertySet.findPropertyIndex(CSSP ropertyFontVariantLigatures); |
490 int fontVariantNumericPropertyIndex = m_propertySet.findPropertyIndex(CSSPro pertyFontVariantNumeric); | 570 int fontVariantNumericPropertyIndex = m_propertySet.findPropertyIndex(CSSPro pertyFontVariantNumeric); |
491 DCHECK_NE(fontSizePropertyIndex, -1); | 571 DCHECK_NE(fontSizePropertyIndex, -1); |
492 DCHECK_NE(fontFamilyPropertyIndex, -1); | 572 DCHECK_NE(fontFamilyPropertyIndex, -1); |
493 DCHECK_NE(fontVariantCapsPropertyIndex, -1); | 573 DCHECK_NE(fontVariantCapsPropertyIndex, -1); |
494 DCHECK_NE(fontVariantLigaturesPropertyIndex, -1); | 574 DCHECK_NE(fontVariantLigaturesPropertyIndex, -1); |
495 DCHECK_NE(fontVariantNumericPropertyIndex, -1); | 575 DCHECK_NE(fontVariantNumericPropertyIndex, -1); |
496 | 576 |
497 PropertyValueForSerializer fontSizeProperty = m_propertySet.propertyAt(fontS izePropertyIndex); | 577 PropertyValueForSerializer fontSizeProperty = m_propertySet.propertyAt(fontS izePropertyIndex); |
498 PropertyValueForSerializer fontFamilyProperty = m_propertySet.propertyAt(fon tFamilyPropertyIndex); | 578 PropertyValueForSerializer fontFamilyProperty = m_propertySet.propertyAt(fon tFamilyPropertyIndex); |
499 PropertyValueForSerializer fontVariantCapsProperty = m_propertySet.propertyA t(fontVariantCapsPropertyIndex); | 579 PropertyValueForSerializer fontVariantCapsProperty = m_propertySet.propertyA t(fontVariantCapsPropertyIndex); |
500 PropertyValueForSerializer fontVariantLigaturesProperty = m_propertySet.prop ertyAt(fontVariantLigaturesPropertyIndex); | 580 PropertyValueForSerializer fontVariantLigaturesProperty = m_propertySet.prop ertyAt(fontVariantLigaturesPropertyIndex); |
501 PropertyValueForSerializer fontVariantNumericProperty = m_propertySet.proper tyAt(fontVariantNumericPropertyIndex); | 581 PropertyValueForSerializer fontVariantNumericProperty = m_propertySet.proper tyAt(fontVariantNumericPropertyIndex); |
502 | 582 |
503 // Check that non-initial font-variant subproperties are not conflicting wit h this serialization. | 583 // Check that non-initial font-variant subproperties are not conflicting wit h this serialization. |
504 const CSSValue* ligaturesValue = fontVariantLigaturesProperty.value(); | 584 const CSSValue* ligaturesValue = fontVariantLigaturesProperty.value(); |
505 const CSSValue* numericValue = fontVariantNumericProperty.value(); | 585 const CSSValue* numericValue = fontVariantNumericProperty.value(); |
506 if ((ligaturesValue->isPrimitiveValue() | 586 if ((ligaturesValue->isPrimitiveValue() |
507 && toCSSPrimitiveValue(ligaturesValue)->getValueID() != CSSValueNormal) | 587 && toCSSPrimitiveValue(ligaturesValue)->getValueID() != CSSValueNormal) |
508 || ligaturesValue->isValueList() | 588 || ligaturesValue->isValueList() |
509 || (numericValue->isPrimitiveValue() | 589 || (numericValue->isPrimitiveValue() |
510 && toCSSPrimitiveValue(numericValue)->getValueID() != CSSValueNormal) | 590 && toCSSPrimitiveValue(numericValue)->getValueID() != CSSValueNormal) |
511 || numericValue->isValueList()) | 591 || numericValue->isValueList()) |
512 return emptyString(); | 592 return emptyString(); |
513 | 593 |
514 String commonValue = fontSizeProperty.value()->cssText(); | |
515 StringBuilder result; | 594 StringBuilder result; |
516 appendFontLonghandValueIfNotNormal(CSSPropertyFontStyle, result, commonValue ); | 595 appendFontLonghandValueIfNotNormal(CSSPropertyFontStyle, result); |
517 | 596 |
518 const CSSValue* val = fontVariantCapsProperty.value(); | 597 const CSSValue* val = fontVariantCapsProperty.value(); |
519 if (val->isPrimitiveValue() | 598 if (val->isPrimitiveValue() |
520 && (toCSSPrimitiveValue(val)->getValueID() != CSSValueSmallCaps | 599 && (toCSSPrimitiveValue(val)->getValueID() != CSSValueSmallCaps |
521 && toCSSPrimitiveValue(val)->getValueID() != CSSValueNormal)) | 600 && toCSSPrimitiveValue(val)->getValueID() != CSSValueNormal)) |
522 return emptyString(); | 601 return emptyString(); |
523 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantCaps, result, commo nValue); | 602 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantCaps, result); |
524 | 603 |
525 appendFontLonghandValueIfNotNormal(CSSPropertyFontWeight, result, commonValu e); | 604 appendFontLonghandValueIfNotNormal(CSSPropertyFontWeight, result); |
526 appendFontLonghandValueIfNotNormal(CSSPropertyFontStretch, result, commonVal ue); | 605 appendFontLonghandValueIfNotNormal(CSSPropertyFontStretch, result); |
527 if (!result.isEmpty()) | 606 if (!result.isEmpty()) |
528 result.append(' '); | 607 result.append(' '); |
529 result.append(fontSizeProperty.value()->cssText()); | 608 result.append(fontSizeProperty.value()->cssText()); |
530 appendFontLonghandValueIfNotNormal(CSSPropertyLineHeight, result, commonValu e); | 609 appendFontLonghandValueIfNotNormal(CSSPropertyLineHeight, result); |
531 if (!result.isEmpty()) | 610 if (!result.isEmpty()) |
532 result.append(' '); | 611 result.append(' '); |
533 result.append(fontFamilyProperty.value()->cssText()); | 612 result.append(fontFamilyProperty.value()->cssText()); |
534 if (isInitialOrInherit(commonValue)) | |
535 return commonValue; | |
536 return result.toString(); | 613 return result.toString(); |
537 } | 614 } |
538 | 615 |
539 String StylePropertySerializer::fontVariantValue() const | 616 String StylePropertySerializer::fontVariantValue() const |
540 { | 617 { |
541 if (!isPropertyShorthandAvailable(fontVariantShorthand())) { | |
542 if (!shorthandHasOnlyInitialOrInheritedValue(fontVariantShorthand())) | |
543 return String(); | |
544 return m_propertySet.getPropertyValue(CSSPropertyFontVariantLigatures); | |
545 } | |
546 | |
547 StringBuilder result; | 618 StringBuilder result; |
548 | 619 |
549 // TODO(drott): Decide how we want to return ligature values in shorthands, reduced to "none" or | 620 // TODO(drott): Decide how we want to return ligature values in shorthands, reduced to "none" or |
550 // spelled out, filed as W3C bug: | 621 // spelled out, filed as W3C bug: |
551 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=29594 | 622 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=29594 |
552 String dummyCommonValue; | 623 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantLigatures, result); |
553 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantLigatures, result, dummyCommonValue); | 624 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantCaps, result); |
554 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantCaps, result, dummy CommonValue); | 625 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantNumeric, result); |
555 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantNumeric, result, du mmyCommonValue); | |
556 | 626 |
557 if (result.isEmpty()) { | 627 if (result.isEmpty()) { |
558 return "normal"; | 628 return "normal"; |
559 } | 629 } |
560 | 630 |
561 return result.toString(); | 631 return result.toString(); |
562 } | 632 } |
563 | 633 |
564 String StylePropertySerializer::get4Values(const StylePropertyShorthand& shortha nd) const | 634 String StylePropertySerializer::get4Values(const StylePropertyShorthand& shortha nd) const |
565 { | 635 { |
566 // Assume the properties are in the usual order top, right, bottom, left. | 636 // Assume the properties are in the usual order top, right, bottom, left. |
567 int topValueIndex = m_propertySet.findPropertyIndex(shorthand.properties()[0 ]); | 637 int topValueIndex = m_propertySet.findPropertyIndex(shorthand.properties()[0 ]); |
568 int rightValueIndex = m_propertySet.findPropertyIndex(shorthand.properties() [1]); | 638 int rightValueIndex = m_propertySet.findPropertyIndex(shorthand.properties() [1]); |
569 int bottomValueIndex = m_propertySet.findPropertyIndex(shorthand.properties( )[2]); | 639 int bottomValueIndex = m_propertySet.findPropertyIndex(shorthand.properties( )[2]); |
570 int leftValueIndex = m_propertySet.findPropertyIndex(shorthand.properties()[ 3]); | 640 int leftValueIndex = m_propertySet.findPropertyIndex(shorthand.properties()[ 3]); |
571 | 641 |
572 if (topValueIndex == -1 || rightValueIndex == -1 || bottomValueIndex == -1 | | leftValueIndex == -1) | 642 if (topValueIndex == -1 || rightValueIndex == -1 || bottomValueIndex == -1 | | leftValueIndex == -1) |
573 return String(); | 643 return String(); |
574 | 644 |
575 PropertyValueForSerializer top = m_propertySet.propertyAt(topValueIndex); | 645 PropertyValueForSerializer top = m_propertySet.propertyAt(topValueIndex); |
576 PropertyValueForSerializer right = m_propertySet.propertyAt(rightValueIndex) ; | 646 PropertyValueForSerializer right = m_propertySet.propertyAt(rightValueIndex) ; |
577 PropertyValueForSerializer bottom = m_propertySet.propertyAt(bottomValueInde x); | 647 PropertyValueForSerializer bottom = m_propertySet.propertyAt(bottomValueInde x); |
578 PropertyValueForSerializer left = m_propertySet.propertyAt(leftValueIndex); | 648 PropertyValueForSerializer left = m_propertySet.propertyAt(leftValueIndex); |
579 | 649 |
580 // All 4 properties must be specified. | |
581 if (!top.value() || !right.value() || !bottom.value() || !left.value()) | |
582 return String(); | |
583 | |
584 if (top.isImportant() != right.isImportant() || right.isImportant() != botto m.isImportant() || bottom.isImportant() != left.isImportant()) | |
585 return String(); | |
586 | |
587 if (top.isInherited() && right.isInherited() && bottom.isInherited() && left .isInherited()) | |
588 return getValueName(CSSValueInherit); | |
589 | |
590 unsigned numInitial = top.value()->isInitialValue() + right.value()->isIniti alValue() + bottom.value()->isInitialValue() + left.value()->isInitialValue(); | |
591 if (numInitial == 4) | |
592 return getValueName(CSSValueInitial); | |
593 if (numInitial > 0) | |
594 return String(); | |
595 | |
596 bool showLeft = !right.value()->equals(*left.value()); | 650 bool showLeft = !right.value()->equals(*left.value()); |
597 bool showBottom = !top.value()->equals(*bottom.value()) || showLeft; | 651 bool showBottom = !top.value()->equals(*bottom.value()) || showLeft; |
598 bool showRight = !top.value()->equals(*right.value()) || showBottom; | 652 bool showRight = !top.value()->equals(*right.value()) || showBottom; |
599 | 653 |
600 StringBuilder result; | 654 StringBuilder result; |
601 result.append(top.value()->cssText()); | 655 result.append(top.value()->cssText()); |
602 if (showRight) { | 656 if (showRight) { |
603 result.append(' '); | 657 result.append(' '); |
604 result.append(right.value()->cssText()); | 658 result.append(right.value()->cssText()); |
605 } | 659 } |
(...skipping 12 matching lines...) Expand all Loading... | |
618 { | 672 { |
619 const unsigned size = shorthand.length(); | 673 const unsigned size = shorthand.length(); |
620 | 674 |
621 // Begin by collecting the properties into a vector. | 675 // Begin by collecting the properties into a vector. |
622 HeapVector<Member<const CSSValue>> values(size); | 676 HeapVector<Member<const CSSValue>> values(size); |
623 // If the below loop succeeds, there should always be at minimum 1 layer. | 677 // If the below loop succeeds, there should always be at minimum 1 layer. |
624 size_t numLayers = 1U; | 678 size_t numLayers = 1U; |
625 | 679 |
626 for (size_t i = 0; i < size; i++) { | 680 for (size_t i = 0; i < size; i++) { |
627 values[i] = m_propertySet.getPropertyCSSValue(shorthand.properties()[i]) ; | 681 values[i] = m_propertySet.getPropertyCSSValue(shorthand.properties()[i]) ; |
628 // A shorthand is not available if getPropertyCSSValue didn't resolve to anything. | |
629 if (!values[i]) | |
630 return String(); | |
631 if (values[i]->isBaseValueList()) { | 682 if (values[i]->isBaseValueList()) { |
632 const CSSValueList* valueList = toCSSValueList(values[i]); | 683 const CSSValueList* valueList = toCSSValueList(values[i]); |
633 numLayers = std::max(numLayers, valueList->length()); | 684 numLayers = std::max(numLayers, valueList->length()); |
634 } | 685 } |
635 } | 686 } |
636 | 687 |
637 StringBuilder result; | 688 StringBuilder result; |
638 // Tracks whether or not all the values are initial or all the values are in herit. | |
639 // Start out assuming there is a common value. It will get set to false belo w if there isn't one. | |
640 bool hasCommonValue = true; | |
641 const CSSValue* commonValue = nullptr; | |
642 | 689 |
643 // Now stitch the properties together. Implicit initial values are flagged a s such and | 690 // Now stitch the properties together. Implicit initial values are flagged a s such and |
644 // can safely be omitted. | 691 // can safely be omitted. |
645 for (size_t layer = 0; layer < numLayers; layer++) { | 692 for (size_t layer = 0; layer < numLayers; layer++) { |
646 StringBuilder layerResult; | 693 StringBuilder layerResult; |
647 bool useRepeatXShorthand = false; | 694 bool useRepeatXShorthand = false; |
648 bool useRepeatYShorthand = false; | 695 bool useRepeatYShorthand = false; |
649 bool useSingleWordShorthand = false; | 696 bool useSingleWordShorthand = false; |
650 bool foundPositionXCSSProperty = false; | 697 bool foundPositionXCSSProperty = false; |
651 bool foundPositionYCSSProperty = false; | 698 bool foundPositionYCSSProperty = false; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
717 if (useSingleWordShorthand) | 764 if (useSingleWordShorthand) |
718 useSingleWordShorthand = false; | 765 useSingleWordShorthand = false; |
719 layerResult.append(value->cssText()); | 766 layerResult.append(value->cssText()); |
720 } | 767 } |
721 if (property == CSSPropertyBackgroundPositionX || property == CS SPropertyWebkitMaskPositionX) | 768 if (property == CSSPropertyBackgroundPositionX || property == CS SPropertyWebkitMaskPositionX) |
722 foundPositionXCSSProperty = true; | 769 foundPositionXCSSProperty = true; |
723 if (property == CSSPropertyBackgroundPositionY || property == CS SPropertyWebkitMaskPositionY) { | 770 if (property == CSSPropertyBackgroundPositionY || property == CS SPropertyWebkitMaskPositionY) { |
724 foundPositionYCSSProperty = true; | 771 foundPositionYCSSProperty = true; |
725 // background-position is a special case. If only the first offset is specified, | 772 // background-position is a special case. If only the first offset is specified, |
726 // the second one defaults to "center", not the same value. | 773 // the second one defaults to "center", not the same value. |
727 if (hasCommonValue && !value->isInitialValue() && !value->is InheritedValue()) | |
728 hasCommonValue = false; | |
729 } | 774 } |
730 } | 775 } |
731 | |
732 if (hasCommonValue && !commonValue) | |
733 commonValue = value; | |
734 else if (!value->equals(*commonValue)) | |
735 hasCommonValue = false; | |
736 } | 776 } |
737 if (!layerResult.isEmpty()) { | 777 if (!layerResult.isEmpty()) { |
738 if (!result.isEmpty()) | 778 if (!result.isEmpty()) |
739 result.appendLiteral(", "); | 779 result.appendLiteral(", "); |
740 result.append(layerResult); | 780 result.append(layerResult); |
741 } | 781 } |
742 } | 782 } |
743 | 783 |
744 if (hasCommonValue && (commonValue->isInitialValue() || commonValue->isInher itedValue())) | |
745 return commonValue->cssText(); | |
746 | |
747 return result.toString(); | 784 return result.toString(); |
748 } | 785 } |
749 | 786 |
750 String StylePropertySerializer::getShorthandValue(const StylePropertyShorthand& shorthand, String separator) const | 787 String StylePropertySerializer::getShorthandValue(const StylePropertyShorthand& shorthand, String separator) const |
751 { | 788 { |
752 String commonValue; | |
753 StringBuilder result; | 789 StringBuilder result; |
754 for (unsigned i = 0; i < shorthand.length(); ++i) { | 790 for (unsigned i = 0; i < shorthand.length(); ++i) { |
755 const CSSValue* value = m_propertySet.getPropertyCSSValue(shorthand.prop erties()[i]); | 791 const CSSValue* value = m_propertySet.getPropertyCSSValue(shorthand.prop erties()[i]); |
756 if (!value) | |
757 return String(); | |
758 String valueText = value->cssText(); | 792 String valueText = value->cssText(); |
759 if (!i) | |
760 commonValue = valueText; | |
761 else if (!commonValue.isNull() && commonValue != valueText) | |
762 commonValue = String(); | |
763 if (value->isInitialValue()) | 793 if (value->isInitialValue()) |
764 continue; | 794 continue; |
765 if (!result.isEmpty()) | 795 if (!result.isEmpty()) |
766 result.append(separator); | 796 result.append(separator); |
767 result.append(valueText); | 797 result.append(valueText); |
768 } | 798 } |
769 if (isInitialOrInherit(commonValue)) | |
770 return commonValue; | |
771 return result.toString(); | 799 return result.toString(); |
772 } | 800 } |
773 | 801 |
774 // only returns a non-null value if all properties have the same, non-null value | 802 // only returns a non-null value if all properties have the same, non-null value |
775 String StylePropertySerializer::getCommonValue(const StylePropertyShorthand& sho rthand) const | 803 String StylePropertySerializer::getCommonValue(const StylePropertyShorthand& sho rthand) const |
776 { | 804 { |
777 String res; | 805 String res; |
778 bool lastPropertyWasImportant = false; | |
779 for (unsigned i = 0; i < shorthand.length(); ++i) { | 806 for (unsigned i = 0; i < shorthand.length(); ++i) { |
780 const CSSValue* value = m_propertySet.getPropertyCSSValue(shorthand.prop erties()[i]); | 807 const CSSValue* value = m_propertySet.getPropertyCSSValue(shorthand.prop erties()[i]); |
781 // FIXME: CSSInitialValue::cssText should generate the right value. | 808 // FIXME: CSSInitialValue::cssText should generate the right value. |
782 if (!value) | |
783 return String(); | |
784 String text = value->cssText(); | 809 String text = value->cssText(); |
785 if (text.isNull()) | |
786 return String(); | |
787 if (res.isNull()) | 810 if (res.isNull()) |
788 res = text; | 811 res = text; |
789 else if (res != text) | 812 else if (res != text) |
790 return String(); | 813 return String(); |
791 | |
792 bool currentPropertyIsImportant = m_propertySet.propertyIsImportant(shor thand.properties()[i]); | |
793 if (i && lastPropertyWasImportant != currentPropertyIsImportant) | |
794 return String(); | |
795 lastPropertyWasImportant = currentPropertyIsImportant; | |
796 } | 814 } |
797 return res; | 815 return res; |
798 } | 816 } |
799 | 817 |
800 String StylePropertySerializer::borderPropertyValue() const | 818 String StylePropertySerializer::borderPropertyValue() const |
801 { | 819 { |
802 const StylePropertyShorthand properties[3] = { borderWidthShorthand(), borde rStyleShorthand(), borderColorShorthand() }; | 820 const StylePropertyShorthand properties[3] = { borderWidthShorthand(), borde rStyleShorthand(), borderColorShorthand() }; |
803 String commonValue; | |
804 StringBuilder result; | 821 StringBuilder result; |
805 for (size_t i = 0; i < WTF_ARRAY_LENGTH(properties); ++i) { | 822 for (size_t i = 0; i < WTF_ARRAY_LENGTH(properties); ++i) { |
806 String value = getCommonValue(properties[i]); | 823 String value = getCommonValue(properties[i]); |
807 if (value.isNull()) | 824 if (value.isNull()) |
808 return String(); | 825 return String(); |
809 if (!i) | |
810 commonValue = value; | |
811 else if (!commonValue.isNull() && commonValue != value) | |
812 commonValue = String(); | |
813 if (value == "initial") | 826 if (value == "initial") |
814 continue; | 827 continue; |
815 if (!result.isEmpty()) | 828 if (!result.isEmpty()) |
816 result.append(' '); | 829 result.append(' '); |
817 result.append(value); | 830 result.append(value); |
818 } | 831 } |
819 if (isInitialOrInherit(commonValue)) | |
820 return commonValue; | |
821 return result.isEmpty() ? String() : result.toString(); | 832 return result.isEmpty() ? String() : result.toString(); |
822 } | 833 } |
823 | 834 |
824 static void appendBackgroundRepeatValue(StringBuilder& builder, const CSSValue& repeatXCSSValue, const CSSValue& repeatYCSSValue) | 835 static void appendBackgroundRepeatValue(StringBuilder& builder, const CSSValue& repeatXCSSValue, const CSSValue& repeatYCSSValue) |
825 { | 836 { |
826 // FIXME: Ensure initial values do not appear in CSS_VALUE_LISTS. | 837 // FIXME: Ensure initial values do not appear in CSS_VALUE_LISTS. |
827 DEFINE_STATIC_LOCAL(CSSPrimitiveValue, initialRepeatValue, (CSSPrimitiveValu e::createIdentifier(CSSValueRepeat))); | 838 DEFINE_STATIC_LOCAL(CSSPrimitiveValue, initialRepeatValue, (CSSPrimitiveValu e::createIdentifier(CSSValueRepeat))); |
828 const CSSPrimitiveValue& repeatX = repeatXCSSValue.isInitialValue() ? initia lRepeatValue : toCSSPrimitiveValue(repeatXCSSValue); | 839 const CSSPrimitiveValue& repeatX = repeatXCSSValue.isInitialValue() ? initia lRepeatValue : toCSSPrimitiveValue(repeatXCSSValue); |
829 const CSSPrimitiveValue& repeatY = repeatYCSSValue.isInitialValue() ? initia lRepeatValue : toCSSPrimitiveValue(repeatYCSSValue); | 840 const CSSPrimitiveValue& repeatY = repeatYCSSValue.isInitialValue() ? initia lRepeatValue : toCSSPrimitiveValue(repeatYCSSValue); |
830 CSSValueID repeatXValueId = repeatX.getValueID(); | 841 CSSValueID repeatXValueId = repeatX.getValueID(); |
831 CSSValueID repeatYValueId = repeatY.getValueID(); | 842 CSSValueID repeatYValueId = repeatY.getValueID(); |
832 if (repeatXValueId == repeatYValueId) { | 843 if (repeatXValueId == repeatYValueId) { |
833 builder.append(repeatX.cssText()); | 844 builder.append(repeatX.cssText()); |
834 } else if (repeatXValueId == CSSValueNoRepeat && repeatYValueId == CSSValueR epeat) { | 845 } else if (repeatXValueId == CSSValueNoRepeat && repeatYValueId == CSSValueR epeat) { |
835 builder.appendLiteral("repeat-y"); | 846 builder.appendLiteral("repeat-y"); |
836 } else if (repeatXValueId == CSSValueRepeat && repeatYValueId == CSSValueNoR epeat) { | 847 } else if (repeatXValueId == CSSValueRepeat && repeatYValueId == CSSValueNoR epeat) { |
837 builder.appendLiteral("repeat-x"); | 848 builder.appendLiteral("repeat-x"); |
838 } else { | 849 } else { |
839 builder.append(repeatX.cssText()); | 850 builder.append(repeatX.cssText()); |
840 builder.appendLiteral(" "); | 851 builder.appendLiteral(" "); |
841 builder.append(repeatY.cssText()); | 852 builder.append(repeatY.cssText()); |
842 } | 853 } |
843 } | 854 } |
844 | 855 |
845 String StylePropertySerializer::backgroundRepeatPropertyValue() const | 856 String StylePropertySerializer::backgroundRepeatPropertyValue() const |
846 { | 857 { |
847 const CSSValue* repeatX = m_propertySet.getPropertyCSSValue(CSSPropertyBackg roundRepeatX); | 858 const CSSValue* repeatX = m_propertySet.getPropertyCSSValue(CSSPropertyBackg roundRepeatX); |
848 const CSSValue* repeatY = m_propertySet.getPropertyCSSValue(CSSPropertyBackg roundRepeatY); | 859 const CSSValue* repeatY = m_propertySet.getPropertyCSSValue(CSSPropertyBackg roundRepeatY); |
849 if (!repeatX || !repeatY) | |
850 return String(); | |
851 if (m_propertySet.propertyIsImportant(CSSPropertyBackgroundRepeatX) != m_pro pertySet.propertyIsImportant(CSSPropertyBackgroundRepeatY)) | |
852 return String(); | |
853 if ((repeatX->isInitialValue() && repeatY->isInitialValue()) || (repeatX->is InheritedValue() && repeatY->isInheritedValue())) | |
854 return repeatX->cssText(); | |
855 | 860 |
856 const CSSValueList* repeatXList = 0; | 861 const CSSValueList* repeatXList = 0; |
857 int repeatXLength = 1; | 862 int repeatXLength = 1; |
858 if (repeatX->isValueList()) { | 863 if (repeatX->isValueList()) { |
859 repeatXList = toCSSValueList(repeatX); | 864 repeatXList = toCSSValueList(repeatX); |
860 repeatXLength = repeatXList->length(); | 865 repeatXLength = repeatXList->length(); |
861 } else if (!repeatX->isPrimitiveValue()) { | 866 } else if (!repeatX->isPrimitiveValue()) { |
862 return String(); | 867 return String(); |
863 } | 868 } |
864 | 869 |
(...skipping 12 matching lines...) Expand all Loading... | |
877 if (i) | 882 if (i) |
878 builder.appendLiteral(", "); | 883 builder.appendLiteral(", "); |
879 | 884 |
880 const CSSValue* xValue = repeatXList ? repeatXList->item(i % repeatXList ->length()) : repeatX; | 885 const CSSValue* xValue = repeatXList ? repeatXList->item(i % repeatXList ->length()) : repeatX; |
881 const CSSValue* yValue = repeatYList ? repeatYList->item(i % repeatYList ->length()) : repeatY; | 886 const CSSValue* yValue = repeatYList ? repeatYList->item(i % repeatYList ->length()) : repeatY; |
882 appendBackgroundRepeatValue(builder, *xValue, *yValue); | 887 appendBackgroundRepeatValue(builder, *xValue, *yValue); |
883 } | 888 } |
884 return builder.toString(); | 889 return builder.toString(); |
885 } | 890 } |
886 | 891 |
887 void StylePropertySerializer::appendBackgroundPropertyAsText(StringBuilder& resu lt, unsigned& numDecls) const | |
888 { | |
889 if (isPropertyShorthandAvailable(backgroundShorthand())) { | |
890 String backgroundValue = getPropertyValue(CSSPropertyBackground); | |
891 bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgrou ndImage); | |
892 result.append(getPropertyText(CSSPropertyBackground, backgroundValue, is Important, numDecls++)); | |
893 return; | |
894 } | |
895 if (shorthandHasOnlyInitialOrInheritedValue(backgroundShorthand())) { | |
896 const CSSValue* value = m_propertySet.getPropertyCSSValue(CSSPropertyBac kgroundImage); | |
897 bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgrou ndImage); | |
898 result.append(getPropertyText(CSSPropertyBackground, value->cssText(), i sImportant, numDecls++)); | |
899 return; | |
900 } | |
901 | |
902 // backgroundShorthandProperty without layered shorhand properties | |
903 const CSSPropertyID backgroundPropertyIds[] = { | |
904 CSSPropertyBackgroundImage, | |
905 CSSPropertyBackgroundAttachment, | |
906 CSSPropertyBackgroundColor, | |
907 CSSPropertyBackgroundSize, | |
908 CSSPropertyBackgroundOrigin, | |
909 CSSPropertyBackgroundClip | |
910 }; | |
911 | |
912 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(backgroundPropertyIds); ++i) { | |
913 CSSPropertyID propertyID = backgroundPropertyIds[i]; | |
914 const CSSValue* value = m_propertySet.getPropertyCSSValue(propertyID); | |
915 if (!value) | |
916 continue; | |
917 result.append(getPropertyText(propertyID, value->cssText(), m_propertySe t.propertyIsImportant(propertyID), numDecls++)); | |
918 } | |
919 | |
920 // FIXME: This is a not-so-nice way to turn x/y positions into single backgr ound-position in output. | |
921 // It is required because background-position-x/y are non-standard propertie s and WebKit generated output | |
922 // would not work in Firefox (<rdar://problem/5143183>) | |
923 // It would be a better solution if background-position was UnitType::Pair. | |
924 if (shorthandHasOnlyInitialOrInheritedValue(backgroundPositionShorthand())) { | |
925 const CSSValue* value = m_propertySet.getPropertyCSSValue(CSSPropertyBac kgroundPositionX); | |
926 bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgrou ndPositionX); | |
927 result.append(getPropertyText(CSSPropertyBackgroundPosition, value->cssT ext(), isImportant, numDecls++)); | |
928 } else if (isPropertyShorthandAvailable(backgroundPositionShorthand())) { | |
929 String positionValue = m_propertySet.getPropertyValue(CSSPropertyBackgro undPosition); | |
930 bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgrou ndPositionX); | |
931 if (!positionValue.isNull()) | |
932 result.append(getPropertyText(CSSPropertyBackgroundPosition, positio nValue, isImportant, numDecls++)); | |
933 } else { | |
934 // should check background-position-x or background-position-y. | |
935 if (const CSSValue* value = m_propertySet.getPropertyCSSValue(CSSPropert yBackgroundPositionX)) { | |
936 if (!value->isImplicitInitialValue()) { | |
937 bool isImportant = m_propertySet.propertyIsImportant(CSSProperty BackgroundPositionX); | |
938 result.append(getPropertyText(CSSPropertyBackgroundPositionX, va lue->cssText(), isImportant, numDecls++)); | |
939 } | |
940 } | |
941 if (const CSSValue* value = m_propertySet.getPropertyCSSValue(CSSPropert yBackgroundPositionY)) { | |
942 if (!value->isImplicitInitialValue()) { | |
943 bool isImportant = m_propertySet.propertyIsImportant(CSSProperty BackgroundPositionY); | |
944 result.append(getPropertyText(CSSPropertyBackgroundPositionY, va lue->cssText(), isImportant, numDecls++)); | |
945 } | |
946 } | |
947 } | |
948 | |
949 String repeatValue = m_propertySet.getPropertyValue(CSSPropertyBackgroundRep eat); | |
950 if (!repeatValue.isNull()) | |
951 result.append(getPropertyText(CSSPropertyBackgroundRepeat, repeatValue, m_propertySet.propertyIsImportant(CSSPropertyBackgroundRepeatX), numDecls++)); | |
952 } | |
953 | |
954 bool StylePropertySerializer::isPropertyShorthandAvailable(const StylePropertySh orthand& shorthand) const | |
955 { | |
956 ASSERT(shorthand.length() > 0); | |
957 | |
958 bool isImportant = m_propertySet.propertyIsImportant(shorthand.properties()[ 0]); | |
959 for (unsigned i = 0; i < shorthand.length(); ++i) { | |
960 const CSSValue* value = m_propertySet.getPropertyCSSValue(shorthand.prop erties()[i]); | |
961 if (!value || (value->isInitialValue() && !value->isImplicitInitialValue ()) || value->isInheritedValue()) | |
962 return false; | |
963 if (isImportant != m_propertySet.propertyIsImportant(shorthand.propertie s()[i])) | |
964 return false; | |
965 } | |
966 return true; | |
967 } | |
968 | |
969 bool StylePropertySerializer::shorthandHasOnlyInitialOrInheritedValue(const Styl ePropertyShorthand& shorthand) const | |
970 { | |
971 ASSERT(shorthand.length() > 0); | |
972 bool isImportant = m_propertySet.propertyIsImportant(shorthand.properties()[ 0]); | |
973 bool isInitialValue = true; | |
974 bool isInheritedValue = true; | |
975 for (unsigned i = 0; i < shorthand.length(); ++i) { | |
976 const CSSValue* value = m_propertySet.getPropertyCSSValue(shorthand.prop erties()[i]); | |
977 if (!value) | |
978 return false; | |
979 if (!value->isInitialValue()) | |
980 isInitialValue = false; | |
981 if (!value->isInheritedValue()) | |
982 isInheritedValue = false; | |
983 if (isImportant != m_propertySet.propertyIsImportant(shorthand.propertie s()[i])) | |
984 return false; | |
985 } | |
986 return isInitialValue || isInheritedValue; | |
987 } | |
988 | |
989 } // namespace blink | 892 } // namespace blink |
OLD | NEW |