| 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 // "initial" instead of the initial values for certain shorthands, so |
| 314 // these are special-cased here. |
| 315 // TODO(timloh): Don't use "initial" in shorthands and remove this |
| 316 // special-casing |
| 317 static bool allowInitialInShorthand(CSSPropertyID propertyID) |
| 318 { |
| 319 switch (propertyID) { |
| 320 case CSSPropertyBorder: |
| 321 case CSSPropertyBorderTop: |
| 322 case CSSPropertyBorderRight: |
| 323 case CSSPropertyBorderBottom: |
| 324 case CSSPropertyBorderLeft: |
| 325 case CSSPropertyOutline: |
| 326 case CSSPropertyColumnRule: |
| 327 case CSSPropertyColumns: |
| 328 case CSSPropertyFlex: |
| 329 case CSSPropertyFlexFlow: |
| 330 case CSSPropertyGridColumn: |
| 331 case CSSPropertyGridRow: |
| 332 case CSSPropertyGridArea: |
| 333 case CSSPropertyGridGap: |
| 334 case CSSPropertyMotion: |
| 335 case CSSPropertyWebkitMarginCollapse: |
| 336 case CSSPropertyListStyle: |
| 337 case CSSPropertyWebkitTextEmphasis: |
| 338 case CSSPropertyWebkitTextStroke: |
| 339 return true; |
| 340 default: |
| 341 return false; |
| 342 } |
| 343 } |
| 344 |
| 345 // TODO(timloh): This should go away eventually, see crbug.com/471917 |
| 346 static bool allowImplicitInitialInShorthand(CSSPropertyID propertyID) |
| 347 { |
| 348 return propertyID == CSSPropertyBackground || propertyID == CSSPropertyWebki
tMask; |
| 349 } |
| 350 |
| 351 StylePropertySerializer::CommonCheckResult StylePropertySerializer::commonShorth
andChecks(const StylePropertyShorthand& shorthand, String& result) const |
| 352 { |
| 353 int longhandCount = shorthand.length(); |
| 354 DCHECK_LE(longhandCount, 17); |
| 355 const CSSValue* longhands[17] = {}; |
| 356 |
| 357 bool hasImportant = false; |
| 358 bool hasNonImportant = false; |
| 359 |
| 360 for (int i = 0; i < longhandCount; i++) { |
| 361 int index = m_propertySet.findPropertyIndex(shorthand.properties()[i]); |
| 362 if (index == -1) |
| 363 return Invalid; |
| 364 PropertyValueForSerializer value = m_propertySet.propertyAt(index); |
| 365 |
| 366 hasImportant |= value.isImportant(); |
| 367 hasNonImportant |= !value.isImportant(); |
| 368 longhands[i] = value.value(); |
| 369 } |
| 370 |
| 371 if (hasImportant && hasNonImportant) |
| 372 return Invalid; |
| 373 |
| 374 // TODO(timloh): This should be isCSSWideKeyword() |
| 375 if (longhands[0]->isInitialValue() || longhands[0]->isInheritedValue()) { |
| 376 bool success = true; |
| 377 for (int i = 1; i < longhandCount; i++) { |
| 378 if (!longhands[i]->equals(*longhands[0])) { |
| 379 // This should just return Invalid but some shorthands currently |
| 380 // allow 'initial' for their longhands. |
| 381 success = false; |
| 382 break; |
| 383 } |
| 384 } |
| 385 if (success) { |
| 386 result = longhands[0]->cssText(); |
| 387 return Valid; |
| 388 } |
| 389 } |
| 390 |
| 391 bool allowInitial = allowInitialInShorthand(shorthand.id()); |
| 392 bool allowImplicitInitial = allowInitial || allowImplicitInitialInShorthand(
shorthand.id()); |
| 393 for (int i = 0; i < longhandCount; i++) { |
| 394 const CSSValue& value = *longhands[i]; |
| 395 if (value.isImplicitInitialValue()) { |
| 396 if (allowImplicitInitial) |
| 397 continue; |
| 398 return Invalid; |
| 399 } |
| 400 if (!allowInitial && value.isInitialValue()) |
| 401 return Invalid; |
| 402 // TODO(timloh): This should also check unset |
| 403 if (value.isInheritedValue()) |
| 404 return Invalid; |
| 405 } |
| 406 |
| 407 return Unknown; |
| 408 } |
| 409 |
| 327 String StylePropertySerializer::getPropertyValue(CSSPropertyID propertyID) const | 410 String StylePropertySerializer::getPropertyValue(CSSPropertyID propertyID) const |
| 328 { | 411 { |
| 329 // Shorthand and 4-values properties | 412 const StylePropertyShorthand& shorthand = shorthandForProperty(propertyID); |
| 413 // TODO(timloh): This is weird, why do we call this with non-shorthands at a
ll? |
| 414 if (!shorthand.length()) |
| 415 return String(); |
| 416 |
| 417 String result; |
| 418 CommonCheckResult commonCheckResult = commonShorthandChecks(shorthand, resul
t); |
| 419 if (commonCheckResult == Valid) |
| 420 return result; |
| 421 if (commonCheckResult == Invalid) |
| 422 return String(); |
| 423 |
| 330 switch (propertyID) { | 424 switch (propertyID) { |
| 331 case CSSPropertyAnimation: | 425 case CSSPropertyAnimation: |
| 332 return getLayeredShorthandValue(animationShorthand()); | 426 return getLayeredShorthandValue(animationShorthand()); |
| 333 case CSSPropertyBorderSpacing: | 427 case CSSPropertyBorderSpacing: |
| 334 return borderSpacingValue(borderSpacingShorthand()); | 428 return borderSpacingValue(borderSpacingShorthand()); |
| 335 case CSSPropertyBackgroundPosition: | 429 case CSSPropertyBackgroundPosition: |
| 336 return getLayeredShorthandValue(backgroundPositionShorthand()); | 430 return getLayeredShorthandValue(backgroundPositionShorthand()); |
| 337 case CSSPropertyBackgroundRepeat: | 431 case CSSPropertyBackgroundRepeat: |
| 338 return backgroundRepeatPropertyValue(); | 432 return backgroundRepeatPropertyValue(); |
| 339 case CSSPropertyBackground: | 433 case CSSPropertyBackground: |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 default: | 504 default: |
| 411 return String(); | 505 return String(); |
| 412 } | 506 } |
| 413 } | 507 } |
| 414 | 508 |
| 415 String StylePropertySerializer::borderSpacingValue(const StylePropertyShorthand&
shorthand) const | 509 String StylePropertySerializer::borderSpacingValue(const StylePropertyShorthand&
shorthand) const |
| 416 { | 510 { |
| 417 const CSSValue* horizontalValue = m_propertySet.getPropertyCSSValue(shorthan
d.properties()[0]); | 511 const CSSValue* horizontalValue = m_propertySet.getPropertyCSSValue(shorthan
d.properties()[0]); |
| 418 const CSSValue* verticalValue = m_propertySet.getPropertyCSSValue(shorthand.
properties()[1]); | 512 const CSSValue* verticalValue = m_propertySet.getPropertyCSSValue(shorthand.
properties()[1]); |
| 419 | 513 |
| 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(); | 514 String horizontalValueCSSText = horizontalValue->cssText(); |
| 427 String verticalValueCSSText = verticalValue->cssText(); | 515 String verticalValueCSSText = verticalValue->cssText(); |
| 428 if (horizontalValueCSSText == verticalValueCSSText) | 516 if (horizontalValueCSSText == verticalValueCSSText) |
| 429 return horizontalValueCSSText; | 517 return horizontalValueCSSText; |
| 430 return horizontalValueCSSText + ' ' + verticalValueCSSText; | 518 return horizontalValueCSSText + ' ' + verticalValueCSSText; |
| 431 } | 519 } |
| 432 | 520 |
| 433 void StylePropertySerializer::appendFontLonghandValueIfNotNormal(CSSPropertyID p
ropertyID, StringBuilder& result, String& commonValue) const | 521 void StylePropertySerializer::appendFontLonghandValueIfNotNormal(CSSPropertyID p
ropertyID, StringBuilder& result) const |
| 434 { | 522 { |
| 435 int foundPropertyIndex = m_propertySet.findPropertyIndex(propertyID); | 523 int foundPropertyIndex = m_propertySet.findPropertyIndex(propertyID); |
| 436 ASSERT(foundPropertyIndex != -1); | 524 ASSERT(foundPropertyIndex != -1); |
| 437 | 525 |
| 438 const CSSValue* val = m_propertySet.propertyAt(foundPropertyIndex).value(); | 526 const CSSValue* val = m_propertySet.propertyAt(foundPropertyIndex).value(); |
| 439 if (val->isPrimitiveValue() && toCSSPrimitiveValue(val)->getValueID() == CSS
ValueNormal) { | 527 if (val->isPrimitiveValue() && toCSSPrimitiveValue(val)->getValueID() == CSS
ValueNormal) |
| 440 commonValue = String(); | |
| 441 return; | 528 return; |
| 442 } | |
| 443 | 529 |
| 444 char prefix = '\0'; | 530 char prefix = '\0'; |
| 445 switch (propertyID) { | 531 switch (propertyID) { |
| 446 case CSSPropertyFontStyle: | 532 case CSSPropertyFontStyle: |
| 447 break; // No prefix. | 533 break; // No prefix. |
| 448 case CSSPropertyFontFamily: | 534 case CSSPropertyFontFamily: |
| 449 case CSSPropertyFontStretch: | 535 case CSSPropertyFontStretch: |
| 450 case CSSPropertyFontVariantCaps: | 536 case CSSPropertyFontVariantCaps: |
| 451 case CSSPropertyFontVariantLigatures: | 537 case CSSPropertyFontVariantLigatures: |
| 452 case CSSPropertyFontVariantNumeric: | 538 case CSSPropertyFontVariantNumeric: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 467 // In the font-variant shorthand a "none" ligatures value needs to be expand
ed. | 553 // In the font-variant shorthand a "none" ligatures value needs to be expand
ed. |
| 468 if (propertyID == CSSPropertyFontVariantLigatures | 554 if (propertyID == CSSPropertyFontVariantLigatures |
| 469 && val->isPrimitiveValue() | 555 && val->isPrimitiveValue() |
| 470 && toCSSPrimitiveValue(val)->getValueID() == CSSValueNone) { | 556 && toCSSPrimitiveValue(val)->getValueID() == CSSValueNone) { |
| 471 value = "no-common-ligatures no-discretionary-ligatures no-historical-li
gatures no-contextual"; | 557 value = "no-common-ligatures no-discretionary-ligatures no-historical-li
gatures no-contextual"; |
| 472 } else { | 558 } else { |
| 473 value = m_propertySet.propertyAt(foundPropertyIndex).value()->cssText(); | 559 value = m_propertySet.propertyAt(foundPropertyIndex).value()->cssText(); |
| 474 } | 560 } |
| 475 | 561 |
| 476 result.append(value); | 562 result.append(value); |
| 477 if (!commonValue.isNull() && commonValue != value) | |
| 478 commonValue = String(); | |
| 479 } | 563 } |
| 480 | 564 |
| 481 String StylePropertySerializer::fontValue() const | 565 String StylePropertySerializer::fontValue() const |
| 482 { | 566 { |
| 483 if (!isPropertyShorthandAvailable(fontShorthand()) && !shorthandHasOnlyIniti
alOrInheritedValue(fontShorthand())) | |
| 484 return emptyString(); | |
| 485 | |
| 486 int fontSizePropertyIndex = m_propertySet.findPropertyIndex(CSSPropertyFontS
ize); | 567 int fontSizePropertyIndex = m_propertySet.findPropertyIndex(CSSPropertyFontS
ize); |
| 487 int fontFamilyPropertyIndex = m_propertySet.findPropertyIndex(CSSPropertyFon
tFamily); | 568 int fontFamilyPropertyIndex = m_propertySet.findPropertyIndex(CSSPropertyFon
tFamily); |
| 488 int fontVariantCapsPropertyIndex = m_propertySet.findPropertyIndex(CSSProper
tyFontVariantCaps); | 569 int fontVariantCapsPropertyIndex = m_propertySet.findPropertyIndex(CSSProper
tyFontVariantCaps); |
| 489 int fontVariantLigaturesPropertyIndex = m_propertySet.findPropertyIndex(CSSP
ropertyFontVariantLigatures); | 570 int fontVariantLigaturesPropertyIndex = m_propertySet.findPropertyIndex(CSSP
ropertyFontVariantLigatures); |
| 490 int fontVariantNumericPropertyIndex = m_propertySet.findPropertyIndex(CSSPro
pertyFontVariantNumeric); | 571 int fontVariantNumericPropertyIndex = m_propertySet.findPropertyIndex(CSSPro
pertyFontVariantNumeric); |
| 491 DCHECK_NE(fontSizePropertyIndex, -1); | 572 DCHECK_NE(fontSizePropertyIndex, -1); |
| 492 DCHECK_NE(fontFamilyPropertyIndex, -1); | 573 DCHECK_NE(fontFamilyPropertyIndex, -1); |
| 493 DCHECK_NE(fontVariantCapsPropertyIndex, -1); | 574 DCHECK_NE(fontVariantCapsPropertyIndex, -1); |
| 494 DCHECK_NE(fontVariantLigaturesPropertyIndex, -1); | 575 DCHECK_NE(fontVariantLigaturesPropertyIndex, -1); |
| 495 DCHECK_NE(fontVariantNumericPropertyIndex, -1); | 576 DCHECK_NE(fontVariantNumericPropertyIndex, -1); |
| 496 | 577 |
| 497 PropertyValueForSerializer fontSizeProperty = m_propertySet.propertyAt(fontS
izePropertyIndex); | 578 PropertyValueForSerializer fontSizeProperty = m_propertySet.propertyAt(fontS
izePropertyIndex); |
| 498 PropertyValueForSerializer fontFamilyProperty = m_propertySet.propertyAt(fon
tFamilyPropertyIndex); | 579 PropertyValueForSerializer fontFamilyProperty = m_propertySet.propertyAt(fon
tFamilyPropertyIndex); |
| 499 PropertyValueForSerializer fontVariantCapsProperty = m_propertySet.propertyA
t(fontVariantCapsPropertyIndex); | 580 PropertyValueForSerializer fontVariantCapsProperty = m_propertySet.propertyA
t(fontVariantCapsPropertyIndex); |
| 500 PropertyValueForSerializer fontVariantLigaturesProperty = m_propertySet.prop
ertyAt(fontVariantLigaturesPropertyIndex); | 581 PropertyValueForSerializer fontVariantLigaturesProperty = m_propertySet.prop
ertyAt(fontVariantLigaturesPropertyIndex); |
| 501 PropertyValueForSerializer fontVariantNumericProperty = m_propertySet.proper
tyAt(fontVariantNumericPropertyIndex); | 582 PropertyValueForSerializer fontVariantNumericProperty = m_propertySet.proper
tyAt(fontVariantNumericPropertyIndex); |
| 502 | 583 |
| 503 // Check that non-initial font-variant subproperties are not conflicting wit
h this serialization. | 584 // Check that non-initial font-variant subproperties are not conflicting wit
h this serialization. |
| 504 const CSSValue* ligaturesValue = fontVariantLigaturesProperty.value(); | 585 const CSSValue* ligaturesValue = fontVariantLigaturesProperty.value(); |
| 505 const CSSValue* numericValue = fontVariantNumericProperty.value(); | 586 const CSSValue* numericValue = fontVariantNumericProperty.value(); |
| 506 if ((ligaturesValue->isPrimitiveValue() | 587 if ((ligaturesValue->isPrimitiveValue() |
| 507 && toCSSPrimitiveValue(ligaturesValue)->getValueID() != CSSValueNormal) | 588 && toCSSPrimitiveValue(ligaturesValue)->getValueID() != CSSValueNormal) |
| 508 || ligaturesValue->isValueList() | 589 || ligaturesValue->isValueList() |
| 509 || (numericValue->isPrimitiveValue() | 590 || (numericValue->isPrimitiveValue() |
| 510 && toCSSPrimitiveValue(numericValue)->getValueID() != CSSValueNormal) | 591 && toCSSPrimitiveValue(numericValue)->getValueID() != CSSValueNormal) |
| 511 || numericValue->isValueList()) | 592 || numericValue->isValueList()) |
| 512 return emptyString(); | 593 return emptyString(); |
| 513 | 594 |
| 514 String commonValue = fontSizeProperty.value()->cssText(); | |
| 515 StringBuilder result; | 595 StringBuilder result; |
| 516 appendFontLonghandValueIfNotNormal(CSSPropertyFontStyle, result, commonValue
); | 596 appendFontLonghandValueIfNotNormal(CSSPropertyFontStyle, result); |
| 517 | 597 |
| 518 const CSSValue* val = fontVariantCapsProperty.value(); | 598 const CSSValue* val = fontVariantCapsProperty.value(); |
| 519 if (val->isPrimitiveValue() | 599 if (val->isPrimitiveValue() |
| 520 && (toCSSPrimitiveValue(val)->getValueID() != CSSValueSmallCaps | 600 && (toCSSPrimitiveValue(val)->getValueID() != CSSValueSmallCaps |
| 521 && toCSSPrimitiveValue(val)->getValueID() != CSSValueNormal)) | 601 && toCSSPrimitiveValue(val)->getValueID() != CSSValueNormal)) |
| 522 return emptyString(); | 602 return emptyString(); |
| 523 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantCaps, result, commo
nValue); | 603 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantCaps, result); |
| 524 | 604 |
| 525 appendFontLonghandValueIfNotNormal(CSSPropertyFontWeight, result, commonValu
e); | 605 appendFontLonghandValueIfNotNormal(CSSPropertyFontWeight, result); |
| 526 appendFontLonghandValueIfNotNormal(CSSPropertyFontStretch, result, commonVal
ue); | 606 appendFontLonghandValueIfNotNormal(CSSPropertyFontStretch, result); |
| 527 if (!result.isEmpty()) | 607 if (!result.isEmpty()) |
| 528 result.append(' '); | 608 result.append(' '); |
| 529 result.append(fontSizeProperty.value()->cssText()); | 609 result.append(fontSizeProperty.value()->cssText()); |
| 530 appendFontLonghandValueIfNotNormal(CSSPropertyLineHeight, result, commonValu
e); | 610 appendFontLonghandValueIfNotNormal(CSSPropertyLineHeight, result); |
| 531 if (!result.isEmpty()) | 611 if (!result.isEmpty()) |
| 532 result.append(' '); | 612 result.append(' '); |
| 533 result.append(fontFamilyProperty.value()->cssText()); | 613 result.append(fontFamilyProperty.value()->cssText()); |
| 534 if (isInitialOrInherit(commonValue)) | |
| 535 return commonValue; | |
| 536 return result.toString(); | 614 return result.toString(); |
| 537 } | 615 } |
| 538 | 616 |
| 539 String StylePropertySerializer::fontVariantValue() const | 617 String StylePropertySerializer::fontVariantValue() const |
| 540 { | 618 { |
| 541 if (!isPropertyShorthandAvailable(fontVariantShorthand())) { | |
| 542 if (!shorthandHasOnlyInitialOrInheritedValue(fontVariantShorthand())) | |
| 543 return String(); | |
| 544 return m_propertySet.getPropertyValue(CSSPropertyFontVariantLigatures); | |
| 545 } | |
| 546 | |
| 547 StringBuilder result; | 619 StringBuilder result; |
| 548 | 620 |
| 549 // TODO(drott): Decide how we want to return ligature values in shorthands,
reduced to "none" or | 621 // TODO(drott): Decide how we want to return ligature values in shorthands,
reduced to "none" or |
| 550 // spelled out, filed as W3C bug: | 622 // spelled out, filed as W3C bug: |
| 551 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=29594 | 623 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=29594 |
| 552 String dummyCommonValue; | 624 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantLigatures, result); |
| 553 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantLigatures, result,
dummyCommonValue); | 625 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantCaps, result); |
| 554 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantCaps, result, dummy
CommonValue); | 626 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantNumeric, result); |
| 555 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantNumeric, result, du
mmyCommonValue); | |
| 556 | 627 |
| 557 if (result.isEmpty()) { | 628 if (result.isEmpty()) { |
| 558 return "normal"; | 629 return "normal"; |
| 559 } | 630 } |
| 560 | 631 |
| 561 return result.toString(); | 632 return result.toString(); |
| 562 } | 633 } |
| 563 | 634 |
| 564 String StylePropertySerializer::get4Values(const StylePropertyShorthand& shortha
nd) const | 635 String StylePropertySerializer::get4Values(const StylePropertyShorthand& shortha
nd) const |
| 565 { | 636 { |
| 566 // Assume the properties are in the usual order top, right, bottom, left. | 637 // Assume the properties are in the usual order top, right, bottom, left. |
| 567 int topValueIndex = m_propertySet.findPropertyIndex(shorthand.properties()[0
]); | 638 int topValueIndex = m_propertySet.findPropertyIndex(shorthand.properties()[0
]); |
| 568 int rightValueIndex = m_propertySet.findPropertyIndex(shorthand.properties()
[1]); | 639 int rightValueIndex = m_propertySet.findPropertyIndex(shorthand.properties()
[1]); |
| 569 int bottomValueIndex = m_propertySet.findPropertyIndex(shorthand.properties(
)[2]); | 640 int bottomValueIndex = m_propertySet.findPropertyIndex(shorthand.properties(
)[2]); |
| 570 int leftValueIndex = m_propertySet.findPropertyIndex(shorthand.properties()[
3]); | 641 int leftValueIndex = m_propertySet.findPropertyIndex(shorthand.properties()[
3]); |
| 571 | 642 |
| 572 if (topValueIndex == -1 || rightValueIndex == -1 || bottomValueIndex == -1 |
| leftValueIndex == -1) | 643 if (topValueIndex == -1 || rightValueIndex == -1 || bottomValueIndex == -1 |
| leftValueIndex == -1) |
| 573 return String(); | 644 return String(); |
| 574 | 645 |
| 575 PropertyValueForSerializer top = m_propertySet.propertyAt(topValueIndex); | 646 PropertyValueForSerializer top = m_propertySet.propertyAt(topValueIndex); |
| 576 PropertyValueForSerializer right = m_propertySet.propertyAt(rightValueIndex)
; | 647 PropertyValueForSerializer right = m_propertySet.propertyAt(rightValueIndex)
; |
| 577 PropertyValueForSerializer bottom = m_propertySet.propertyAt(bottomValueInde
x); | 648 PropertyValueForSerializer bottom = m_propertySet.propertyAt(bottomValueInde
x); |
| 578 PropertyValueForSerializer left = m_propertySet.propertyAt(leftValueIndex); | 649 PropertyValueForSerializer left = m_propertySet.propertyAt(leftValueIndex); |
| 579 | 650 |
| 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()); | 651 bool showLeft = !right.value()->equals(*left.value()); |
| 597 bool showBottom = !top.value()->equals(*bottom.value()) || showLeft; | 652 bool showBottom = !top.value()->equals(*bottom.value()) || showLeft; |
| 598 bool showRight = !top.value()->equals(*right.value()) || showBottom; | 653 bool showRight = !top.value()->equals(*right.value()) || showBottom; |
| 599 | 654 |
| 600 StringBuilder result; | 655 StringBuilder result; |
| 601 result.append(top.value()->cssText()); | 656 result.append(top.value()->cssText()); |
| 602 if (showRight) { | 657 if (showRight) { |
| 603 result.append(' '); | 658 result.append(' '); |
| 604 result.append(right.value()->cssText()); | 659 result.append(right.value()->cssText()); |
| 605 } | 660 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 618 { | 673 { |
| 619 const unsigned size = shorthand.length(); | 674 const unsigned size = shorthand.length(); |
| 620 | 675 |
| 621 // Begin by collecting the properties into a vector. | 676 // Begin by collecting the properties into a vector. |
| 622 HeapVector<Member<const CSSValue>> values(size); | 677 HeapVector<Member<const CSSValue>> values(size); |
| 623 // If the below loop succeeds, there should always be at minimum 1 layer. | 678 // If the below loop succeeds, there should always be at minimum 1 layer. |
| 624 size_t numLayers = 1U; | 679 size_t numLayers = 1U; |
| 625 | 680 |
| 626 for (size_t i = 0; i < size; i++) { | 681 for (size_t i = 0; i < size; i++) { |
| 627 values[i] = m_propertySet.getPropertyCSSValue(shorthand.properties()[i])
; | 682 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()) { | 683 if (values[i]->isBaseValueList()) { |
| 632 const CSSValueList* valueList = toCSSValueList(values[i]); | 684 const CSSValueList* valueList = toCSSValueList(values[i]); |
| 633 numLayers = std::max(numLayers, valueList->length()); | 685 numLayers = std::max(numLayers, valueList->length()); |
| 634 } | 686 } |
| 635 } | 687 } |
| 636 | 688 |
| 637 StringBuilder result; | 689 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 | 690 |
| 643 // Now stitch the properties together. Implicit initial values are flagged a
s such and | 691 // Now stitch the properties together. Implicit initial values are flagged a
s such and |
| 644 // can safely be omitted. | 692 // can safely be omitted. |
| 645 for (size_t layer = 0; layer < numLayers; layer++) { | 693 for (size_t layer = 0; layer < numLayers; layer++) { |
| 646 StringBuilder layerResult; | 694 StringBuilder layerResult; |
| 647 bool useRepeatXShorthand = false; | 695 bool useRepeatXShorthand = false; |
| 648 bool useRepeatYShorthand = false; | 696 bool useRepeatYShorthand = false; |
| 649 bool useSingleWordShorthand = false; | 697 bool useSingleWordShorthand = false; |
| 650 bool foundPositionXCSSProperty = false; | 698 bool foundPositionXCSSProperty = false; |
| 651 bool foundPositionYCSSProperty = false; | 699 bool foundPositionYCSSProperty = false; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 if (useSingleWordShorthand) | 765 if (useSingleWordShorthand) |
| 718 useSingleWordShorthand = false; | 766 useSingleWordShorthand = false; |
| 719 layerResult.append(value->cssText()); | 767 layerResult.append(value->cssText()); |
| 720 } | 768 } |
| 721 if (property == CSSPropertyBackgroundPositionX || property == CS
SPropertyWebkitMaskPositionX) | 769 if (property == CSSPropertyBackgroundPositionX || property == CS
SPropertyWebkitMaskPositionX) |
| 722 foundPositionXCSSProperty = true; | 770 foundPositionXCSSProperty = true; |
| 723 if (property == CSSPropertyBackgroundPositionY || property == CS
SPropertyWebkitMaskPositionY) { | 771 if (property == CSSPropertyBackgroundPositionY || property == CS
SPropertyWebkitMaskPositionY) { |
| 724 foundPositionYCSSProperty = true; | 772 foundPositionYCSSProperty = true; |
| 725 // background-position is a special case. If only the first
offset is specified, | 773 // background-position is a special case. If only the first
offset is specified, |
| 726 // the second one defaults to "center", not the same value. | 774 // the second one defaults to "center", not the same value. |
| 727 if (hasCommonValue && !value->isInitialValue() && !value->is
InheritedValue()) | |
| 728 hasCommonValue = false; | |
| 729 } | 775 } |
| 730 } | 776 } |
| 731 | |
| 732 if (hasCommonValue && !commonValue) | |
| 733 commonValue = value; | |
| 734 else if (!value->equals(*commonValue)) | |
| 735 hasCommonValue = false; | |
| 736 } | 777 } |
| 737 if (!layerResult.isEmpty()) { | 778 if (!layerResult.isEmpty()) { |
| 738 if (!result.isEmpty()) | 779 if (!result.isEmpty()) |
| 739 result.appendLiteral(", "); | 780 result.appendLiteral(", "); |
| 740 result.append(layerResult); | 781 result.append(layerResult); |
| 741 } | 782 } |
| 742 } | 783 } |
| 743 | 784 |
| 744 if (hasCommonValue && (commonValue->isInitialValue() || commonValue->isInher
itedValue())) | |
| 745 return commonValue->cssText(); | |
| 746 | |
| 747 return result.toString(); | 785 return result.toString(); |
| 748 } | 786 } |
| 749 | 787 |
| 750 String StylePropertySerializer::getShorthandValue(const StylePropertyShorthand&
shorthand, String separator) const | 788 String StylePropertySerializer::getShorthandValue(const StylePropertyShorthand&
shorthand, String separator) const |
| 751 { | 789 { |
| 752 String commonValue; | |
| 753 StringBuilder result; | 790 StringBuilder result; |
| 754 for (unsigned i = 0; i < shorthand.length(); ++i) { | 791 for (unsigned i = 0; i < shorthand.length(); ++i) { |
| 755 const CSSValue* value = m_propertySet.getPropertyCSSValue(shorthand.prop
erties()[i]); | 792 const CSSValue* value = m_propertySet.getPropertyCSSValue(shorthand.prop
erties()[i]); |
| 756 if (!value) | |
| 757 return String(); | |
| 758 String valueText = value->cssText(); | 793 String valueText = value->cssText(); |
| 759 if (!i) | |
| 760 commonValue = valueText; | |
| 761 else if (!commonValue.isNull() && commonValue != valueText) | |
| 762 commonValue = String(); | |
| 763 if (value->isInitialValue()) | 794 if (value->isInitialValue()) |
| 764 continue; | 795 continue; |
| 765 if (!result.isEmpty()) | 796 if (!result.isEmpty()) |
| 766 result.append(separator); | 797 result.append(separator); |
| 767 result.append(valueText); | 798 result.append(valueText); |
| 768 } | 799 } |
| 769 if (isInitialOrInherit(commonValue)) | |
| 770 return commonValue; | |
| 771 return result.toString(); | 800 return result.toString(); |
| 772 } | 801 } |
| 773 | 802 |
| 774 // only returns a non-null value if all properties have the same, non-null value | 803 // only returns a non-null value if all properties have the same, non-null value |
| 775 String StylePropertySerializer::getCommonValue(const StylePropertyShorthand& sho
rthand) const | 804 String StylePropertySerializer::getCommonValue(const StylePropertyShorthand& sho
rthand) const |
| 776 { | 805 { |
| 777 String res; | 806 String res; |
| 778 bool lastPropertyWasImportant = false; | |
| 779 for (unsigned i = 0; i < shorthand.length(); ++i) { | 807 for (unsigned i = 0; i < shorthand.length(); ++i) { |
| 780 const CSSValue* value = m_propertySet.getPropertyCSSValue(shorthand.prop
erties()[i]); | 808 const CSSValue* value = m_propertySet.getPropertyCSSValue(shorthand.prop
erties()[i]); |
| 781 // FIXME: CSSInitialValue::cssText should generate the right value. | 809 // FIXME: CSSInitialValue::cssText should generate the right value. |
| 782 if (!value) | |
| 783 return String(); | |
| 784 String text = value->cssText(); | 810 String text = value->cssText(); |
| 785 if (text.isNull()) | |
| 786 return String(); | |
| 787 if (res.isNull()) | 811 if (res.isNull()) |
| 788 res = text; | 812 res = text; |
| 789 else if (res != text) | 813 else if (res != text) |
| 790 return String(); | 814 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 } | 815 } |
| 797 return res; | 816 return res; |
| 798 } | 817 } |
| 799 | 818 |
| 800 String StylePropertySerializer::borderPropertyValue() const | 819 String StylePropertySerializer::borderPropertyValue() const |
| 801 { | 820 { |
| 802 const StylePropertyShorthand properties[3] = { borderWidthShorthand(), borde
rStyleShorthand(), borderColorShorthand() }; | 821 const StylePropertyShorthand properties[3] = { borderWidthShorthand(), borde
rStyleShorthand(), borderColorShorthand() }; |
| 803 String commonValue; | |
| 804 StringBuilder result; | 822 StringBuilder result; |
| 805 for (size_t i = 0; i < WTF_ARRAY_LENGTH(properties); ++i) { | 823 for (size_t i = 0; i < WTF_ARRAY_LENGTH(properties); ++i) { |
| 806 String value = getCommonValue(properties[i]); | 824 String value = getCommonValue(properties[i]); |
| 807 if (value.isNull()) | 825 if (value.isNull()) |
| 808 return String(); | 826 return String(); |
| 809 if (!i) | |
| 810 commonValue = value; | |
| 811 else if (!commonValue.isNull() && commonValue != value) | |
| 812 commonValue = String(); | |
| 813 if (value == "initial") | 827 if (value == "initial") |
| 814 continue; | 828 continue; |
| 815 if (!result.isEmpty()) | 829 if (!result.isEmpty()) |
| 816 result.append(' '); | 830 result.append(' '); |
| 817 result.append(value); | 831 result.append(value); |
| 818 } | 832 } |
| 819 if (isInitialOrInherit(commonValue)) | |
| 820 return commonValue; | |
| 821 return result.isEmpty() ? String() : result.toString(); | 833 return result.isEmpty() ? String() : result.toString(); |
| 822 } | 834 } |
| 823 | 835 |
| 824 static void appendBackgroundRepeatValue(StringBuilder& builder, const CSSValue&
repeatXCSSValue, const CSSValue& repeatYCSSValue) | 836 static void appendBackgroundRepeatValue(StringBuilder& builder, const CSSValue&
repeatXCSSValue, const CSSValue& repeatYCSSValue) |
| 825 { | 837 { |
| 826 // FIXME: Ensure initial values do not appear in CSS_VALUE_LISTS. | 838 // FIXME: Ensure initial values do not appear in CSS_VALUE_LISTS. |
| 827 DEFINE_STATIC_LOCAL(CSSPrimitiveValue, initialRepeatValue, (CSSPrimitiveValu
e::createIdentifier(CSSValueRepeat))); | 839 DEFINE_STATIC_LOCAL(CSSPrimitiveValue, initialRepeatValue, (CSSPrimitiveValu
e::createIdentifier(CSSValueRepeat))); |
| 828 const CSSPrimitiveValue& repeatX = repeatXCSSValue.isInitialValue() ? initia
lRepeatValue : toCSSPrimitiveValue(repeatXCSSValue); | 840 const CSSPrimitiveValue& repeatX = repeatXCSSValue.isInitialValue() ? initia
lRepeatValue : toCSSPrimitiveValue(repeatXCSSValue); |
| 829 const CSSPrimitiveValue& repeatY = repeatYCSSValue.isInitialValue() ? initia
lRepeatValue : toCSSPrimitiveValue(repeatYCSSValue); | 841 const CSSPrimitiveValue& repeatY = repeatYCSSValue.isInitialValue() ? initia
lRepeatValue : toCSSPrimitiveValue(repeatYCSSValue); |
| 830 CSSValueID repeatXValueId = repeatX.getValueID(); | 842 CSSValueID repeatXValueId = repeatX.getValueID(); |
| 831 CSSValueID repeatYValueId = repeatY.getValueID(); | 843 CSSValueID repeatYValueId = repeatY.getValueID(); |
| 832 if (repeatXValueId == repeatYValueId) { | 844 if (repeatXValueId == repeatYValueId) { |
| 833 builder.append(repeatX.cssText()); | 845 builder.append(repeatX.cssText()); |
| 834 } else if (repeatXValueId == CSSValueNoRepeat && repeatYValueId == CSSValueR
epeat) { | 846 } else if (repeatXValueId == CSSValueNoRepeat && repeatYValueId == CSSValueR
epeat) { |
| 835 builder.appendLiteral("repeat-y"); | 847 builder.appendLiteral("repeat-y"); |
| 836 } else if (repeatXValueId == CSSValueRepeat && repeatYValueId == CSSValueNoR
epeat) { | 848 } else if (repeatXValueId == CSSValueRepeat && repeatYValueId == CSSValueNoR
epeat) { |
| 837 builder.appendLiteral("repeat-x"); | 849 builder.appendLiteral("repeat-x"); |
| 838 } else { | 850 } else { |
| 839 builder.append(repeatX.cssText()); | 851 builder.append(repeatX.cssText()); |
| 840 builder.appendLiteral(" "); | 852 builder.appendLiteral(" "); |
| 841 builder.append(repeatY.cssText()); | 853 builder.append(repeatY.cssText()); |
| 842 } | 854 } |
| 843 } | 855 } |
| 844 | 856 |
| 845 String StylePropertySerializer::backgroundRepeatPropertyValue() const | 857 String StylePropertySerializer::backgroundRepeatPropertyValue() const |
| 846 { | 858 { |
| 847 const CSSValue* repeatX = m_propertySet.getPropertyCSSValue(CSSPropertyBackg
roundRepeatX); | 859 const CSSValue* repeatX = m_propertySet.getPropertyCSSValue(CSSPropertyBackg
roundRepeatX); |
| 848 const CSSValue* repeatY = m_propertySet.getPropertyCSSValue(CSSPropertyBackg
roundRepeatY); | 860 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 | 861 |
| 856 const CSSValueList* repeatXList = 0; | 862 const CSSValueList* repeatXList = 0; |
| 857 int repeatXLength = 1; | 863 int repeatXLength = 1; |
| 858 if (repeatX->isValueList()) { | 864 if (repeatX->isValueList()) { |
| 859 repeatXList = toCSSValueList(repeatX); | 865 repeatXList = toCSSValueList(repeatX); |
| 860 repeatXLength = repeatXList->length(); | 866 repeatXLength = repeatXList->length(); |
| 861 } else if (!repeatX->isPrimitiveValue()) { | 867 } else if (!repeatX->isPrimitiveValue()) { |
| 862 return String(); | 868 return String(); |
| 863 } | 869 } |
| 864 | 870 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 877 if (i) | 883 if (i) |
| 878 builder.appendLiteral(", "); | 884 builder.appendLiteral(", "); |
| 879 | 885 |
| 880 const CSSValue* xValue = repeatXList ? repeatXList->item(i % repeatXList
->length()) : repeatX; | 886 const CSSValue* xValue = repeatXList ? repeatXList->item(i % repeatXList
->length()) : repeatX; |
| 881 const CSSValue* yValue = repeatYList ? repeatYList->item(i % repeatYList
->length()) : repeatY; | 887 const CSSValue* yValue = repeatYList ? repeatYList->item(i % repeatYList
->length()) : repeatY; |
| 882 appendBackgroundRepeatValue(builder, *xValue, *yValue); | 888 appendBackgroundRepeatValue(builder, *xValue, *yValue); |
| 883 } | 889 } |
| 884 return builder.toString(); | 890 return builder.toString(); |
| 885 } | 891 } |
| 886 | 892 |
| 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 | 893 } // namespace blink |
| OLD | NEW |