Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: third_party/WebKit/Source/core/css/StylePropertySerializer.cpp

Issue 1988013003: Move generic shorthand serialization checks out of specific routines (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@shorthand1
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698