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. |
11 * | 11 * |
12 * This library is distributed in the hope that it will be useful, | 12 * This library is distributed in the hope that it will be useful, |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 * Library General Public License for more details. | 15 * Library General Public License for more details. |
16 * | 16 * |
17 * You should have received a copy of the GNU Library General Public License | 17 * You should have received a copy of the GNU Library General Public License |
18 * along with this library; see the file COPYING.LIB. If not, write to | 18 * along with this library; see the file COPYING.LIB. If not, write to |
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 * Boston, MA 02110-1301, USA. | 20 * Boston, MA 02110-1301, USA. |
21 */ | 21 */ |
22 | 22 |
23 #include "core/css/StylePropertySerializer.h" | 23 #include "core/css/StylePropertySerializer.h" |
24 | 24 |
25 #include "core/CSSValueKeywords.h" | 25 #include "core/CSSValueKeywords.h" |
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/CSSIdentifierValue.h" |
28 #include "core/css/CSSPendingSubstitutionValue.h" | 29 #include "core/css/CSSPendingSubstitutionValue.h" |
29 #include "core/css/CSSPropertyMetadata.h" | 30 #include "core/css/CSSPropertyMetadata.h" |
30 #include "core/css/CSSValuePool.h" | 31 #include "core/css/CSSValuePool.h" |
31 #include "wtf/StdLibExtras.h" | 32 #include "wtf/StdLibExtras.h" |
32 #include "wtf/text/StringBuilder.h" | 33 #include "wtf/text/StringBuilder.h" |
33 #include <bitset> | 34 #include <bitset> |
34 | 35 |
35 namespace blink { | 36 namespace blink { |
36 | 37 |
37 StylePropertySerializer::StylePropertySetForSerializer::StylePropertySetForSeria
lizer(const StylePropertySet& properties) | 38 StylePropertySerializer::StylePropertySetForSerializer::StylePropertySetForSeria
lizer(const StylePropertySet& properties) |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 return horizontalValueCSSText; | 502 return horizontalValueCSSText; |
502 return horizontalValueCSSText + ' ' + verticalValueCSSText; | 503 return horizontalValueCSSText + ' ' + verticalValueCSSText; |
503 } | 504 } |
504 | 505 |
505 void StylePropertySerializer::appendFontLonghandValueIfNotNormal(CSSPropertyID p
ropertyID, StringBuilder& result) const | 506 void StylePropertySerializer::appendFontLonghandValueIfNotNormal(CSSPropertyID p
ropertyID, StringBuilder& result) const |
506 { | 507 { |
507 int foundPropertyIndex = m_propertySet.findPropertyIndex(propertyID); | 508 int foundPropertyIndex = m_propertySet.findPropertyIndex(propertyID); |
508 ASSERT(foundPropertyIndex != -1); | 509 ASSERT(foundPropertyIndex != -1); |
509 | 510 |
510 const CSSValue* val = m_propertySet.propertyAt(foundPropertyIndex).value(); | 511 const CSSValue* val = m_propertySet.propertyAt(foundPropertyIndex).value(); |
511 if (val->isPrimitiveValue() && toCSSPrimitiveValue(val)->getValueID() == CSS
ValueNormal) | 512 if (val->isIdentifierValue() && toCSSIdentifierValue(val)->getValueID() == C
SSValueNormal) |
512 return; | 513 return; |
513 | 514 |
514 char prefix = '\0'; | 515 char prefix = '\0'; |
515 switch (propertyID) { | 516 switch (propertyID) { |
516 case CSSPropertyFontStyle: | 517 case CSSPropertyFontStyle: |
517 break; // No prefix. | 518 break; // No prefix. |
518 case CSSPropertyFontFamily: | 519 case CSSPropertyFontFamily: |
519 case CSSPropertyFontStretch: | 520 case CSSPropertyFontStretch: |
520 case CSSPropertyFontVariantCaps: | 521 case CSSPropertyFontVariantCaps: |
521 case CSSPropertyFontVariantLigatures: | 522 case CSSPropertyFontVariantLigatures: |
522 case CSSPropertyFontVariantNumeric: | 523 case CSSPropertyFontVariantNumeric: |
523 case CSSPropertyFontWeight: | 524 case CSSPropertyFontWeight: |
524 prefix = ' '; | 525 prefix = ' '; |
525 break; | 526 break; |
526 case CSSPropertyLineHeight: | 527 case CSSPropertyLineHeight: |
527 prefix = '/'; | 528 prefix = '/'; |
528 break; | 529 break; |
529 default: | 530 default: |
530 ASSERT_NOT_REACHED(); | 531 ASSERT_NOT_REACHED(); |
531 } | 532 } |
532 | 533 |
533 if (prefix && !result.isEmpty()) | 534 if (prefix && !result.isEmpty()) |
534 result.append(prefix); | 535 result.append(prefix); |
535 | 536 |
536 String value; | 537 String value; |
537 // In the font-variant shorthand a "none" ligatures value needs to be expand
ed. | 538 // In the font-variant shorthand a "none" ligatures value needs to be expand
ed. |
538 if (propertyID == CSSPropertyFontVariantLigatures | 539 if (propertyID == CSSPropertyFontVariantLigatures |
539 && val->isPrimitiveValue() | 540 && val->isIdentifierValue() |
540 && toCSSPrimitiveValue(val)->getValueID() == CSSValueNone) { | 541 && toCSSIdentifierValue(val)->getValueID() == CSSValueNone) { |
541 value = "no-common-ligatures no-discretionary-ligatures no-historical-li
gatures no-contextual"; | 542 value = "no-common-ligatures no-discretionary-ligatures no-historical-li
gatures no-contextual"; |
542 } else { | 543 } else { |
543 value = m_propertySet.propertyAt(foundPropertyIndex).value()->cssText(); | 544 value = m_propertySet.propertyAt(foundPropertyIndex).value()->cssText(); |
544 } | 545 } |
545 | 546 |
546 result.append(value); | 547 result.append(value); |
547 } | 548 } |
548 | 549 |
549 String StylePropertySerializer::fontValue() const | 550 String StylePropertySerializer::fontValue() const |
550 { | 551 { |
(...skipping 10 matching lines...) Expand all Loading... |
561 | 562 |
562 PropertyValueForSerializer fontSizeProperty = m_propertySet.propertyAt(fontS
izePropertyIndex); | 563 PropertyValueForSerializer fontSizeProperty = m_propertySet.propertyAt(fontS
izePropertyIndex); |
563 PropertyValueForSerializer fontFamilyProperty = m_propertySet.propertyAt(fon
tFamilyPropertyIndex); | 564 PropertyValueForSerializer fontFamilyProperty = m_propertySet.propertyAt(fon
tFamilyPropertyIndex); |
564 PropertyValueForSerializer fontVariantCapsProperty = m_propertySet.propertyA
t(fontVariantCapsPropertyIndex); | 565 PropertyValueForSerializer fontVariantCapsProperty = m_propertySet.propertyA
t(fontVariantCapsPropertyIndex); |
565 PropertyValueForSerializer fontVariantLigaturesProperty = m_propertySet.prop
ertyAt(fontVariantLigaturesPropertyIndex); | 566 PropertyValueForSerializer fontVariantLigaturesProperty = m_propertySet.prop
ertyAt(fontVariantLigaturesPropertyIndex); |
566 PropertyValueForSerializer fontVariantNumericProperty = m_propertySet.proper
tyAt(fontVariantNumericPropertyIndex); | 567 PropertyValueForSerializer fontVariantNumericProperty = m_propertySet.proper
tyAt(fontVariantNumericPropertyIndex); |
567 | 568 |
568 // Check that non-initial font-variant subproperties are not conflicting wit
h this serialization. | 569 // Check that non-initial font-variant subproperties are not conflicting wit
h this serialization. |
569 const CSSValue* ligaturesValue = fontVariantLigaturesProperty.value(); | 570 const CSSValue* ligaturesValue = fontVariantLigaturesProperty.value(); |
570 const CSSValue* numericValue = fontVariantNumericProperty.value(); | 571 const CSSValue* numericValue = fontVariantNumericProperty.value(); |
571 if ((ligaturesValue->isPrimitiveValue() | 572 if ((ligaturesValue->isIdentifierValue() |
572 && toCSSPrimitiveValue(ligaturesValue)->getValueID() != CSSValueNormal) | 573 && toCSSIdentifierValue(ligaturesValue)->getValueID() != CSSValueNormal) |
573 || ligaturesValue->isValueList() | 574 || ligaturesValue->isValueList() |
574 || (numericValue->isPrimitiveValue() | 575 || (numericValue->isIdentifierValue() |
575 && toCSSPrimitiveValue(numericValue)->getValueID() != CSSValueNormal) | 576 && toCSSIdentifierValue(numericValue)->getValueID() != CSSValueNormal) |
576 || numericValue->isValueList()) | 577 || numericValue->isValueList()) |
577 return emptyString(); | 578 return emptyString(); |
578 | 579 |
579 StringBuilder result; | 580 StringBuilder result; |
580 appendFontLonghandValueIfNotNormal(CSSPropertyFontStyle, result); | 581 appendFontLonghandValueIfNotNormal(CSSPropertyFontStyle, result); |
581 | 582 |
582 const CSSValue* val = fontVariantCapsProperty.value(); | 583 const CSSValue* val = fontVariantCapsProperty.value(); |
583 if (val->isPrimitiveValue() | 584 if (val->isIdentifierValue() |
584 && (toCSSPrimitiveValue(val)->getValueID() != CSSValueSmallCaps | 585 && (toCSSIdentifierValue(val)->getValueID() != CSSValueSmallCaps |
585 && toCSSPrimitiveValue(val)->getValueID() != CSSValueNormal)) | 586 && toCSSIdentifierValue(val)->getValueID() != CSSValueNormal)) |
586 return emptyString(); | 587 return emptyString(); |
587 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantCaps, result); | 588 appendFontLonghandValueIfNotNormal(CSSPropertyFontVariantCaps, result); |
588 | 589 |
589 appendFontLonghandValueIfNotNormal(CSSPropertyFontWeight, result); | 590 appendFontLonghandValueIfNotNormal(CSSPropertyFontWeight, result); |
590 appendFontLonghandValueIfNotNormal(CSSPropertyFontStretch, result); | 591 appendFontLonghandValueIfNotNormal(CSSPropertyFontStretch, result); |
591 if (!result.isEmpty()) | 592 if (!result.isEmpty()) |
592 result.append(' '); | 593 result.append(' '); |
593 result.append(fontSizeProperty.value()->cssText()); | 594 result.append(fontSizeProperty.value()->cssText()); |
594 appendFontLonghandValueIfNotNormal(CSSPropertyLineHeight, result); | 595 appendFontLonghandValueIfNotNormal(CSSPropertyLineHeight, result); |
595 if (!result.isEmpty()) | 596 if (!result.isEmpty()) |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 if ((propertyIndex < size - 1 && m_propertySet.isPropertyImplicit(pr
operty)) | 706 if ((propertyIndex < size - 1 && m_propertySet.isPropertyImplicit(pr
operty)) |
706 && (property == CSSPropertyBackgroundRepeatX || property == CSSP
ropertyWebkitMaskRepeatX)) { | 707 && (property == CSSPropertyBackgroundRepeatX || property == CSSP
ropertyWebkitMaskRepeatX)) { |
707 ASSERT(shorthand.properties()[propertyIndex + 1] == CSSPropertyB
ackgroundRepeatY | 708 ASSERT(shorthand.properties()[propertyIndex + 1] == CSSPropertyB
ackgroundRepeatY |
708 || shorthand.properties()[propertyIndex + 1] == CSSPropertyW
ebkitMaskRepeatY); | 709 || shorthand.properties()[propertyIndex + 1] == CSSPropertyW
ebkitMaskRepeatY); |
709 const CSSValue& yValue = values[propertyIndex + 1]->isValueList(
) ? | 710 const CSSValue& yValue = values[propertyIndex + 1]->isValueList(
) ? |
710 toCSSValueList(values[propertyIndex + 1])->item(layer) : *va
lues[propertyIndex + 1]; | 711 toCSSValueList(values[propertyIndex + 1])->item(layer) : *va
lues[propertyIndex + 1]; |
711 | 712 |
712 | 713 |
713 // FIXME: At some point we need to fix this code to avoid return
ing an invalid shorthand, | 714 // FIXME: At some point we need to fix this code to avoid return
ing an invalid shorthand, |
714 // since some longhand combinations are not serializable into a
single shorthand. | 715 // since some longhand combinations are not serializable into a
single shorthand. |
715 if (!value->isPrimitiveValue() || !yValue.isPrimitiveValue()) | 716 if (!value->isIdentifierValue() || !yValue.isIdentifierValue()) |
716 continue; | 717 continue; |
717 | 718 |
718 CSSValueID xId = toCSSPrimitiveValue(value)->getValueID(); | 719 CSSValueID xId = toCSSIdentifierValue(value)->getValueID(); |
719 CSSValueID yId = toCSSPrimitiveValue(yValue).getValueID(); | 720 CSSValueID yId = toCSSIdentifierValue(yValue).getValueID(); |
720 // Maybe advance propertyIndex to look at the next CSSValue in t
he list for the checks below. | 721 // Maybe advance propertyIndex to look at the next CSSValue in t
he list for the checks below. |
721 if (xId == yId) { | 722 if (xId == yId) { |
722 useSingleWordShorthand = true; | 723 useSingleWordShorthand = true; |
723 property = shorthand.properties()[++propertyIndex]; | 724 property = shorthand.properties()[++propertyIndex]; |
724 } else if (xId == CSSValueRepeat && yId == CSSValueNoRepeat) { | 725 } else if (xId == CSSValueRepeat && yId == CSSValueNoRepeat) { |
725 useRepeatXShorthand = true; | 726 useRepeatXShorthand = true; |
726 property = shorthand.properties()[++propertyIndex]; | 727 property = shorthand.properties()[++propertyIndex]; |
727 } else if (xId == CSSValueNoRepeat && yId == CSSValueRepeat) { | 728 } else if (xId == CSSValueNoRepeat && yId == CSSValueRepeat) { |
728 useRepeatYShorthand = true; | 729 useRepeatYShorthand = true; |
729 property = shorthand.properties()[++propertyIndex]; | 730 property = shorthand.properties()[++propertyIndex]; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 if (!result.isEmpty()) | 816 if (!result.isEmpty()) |
816 result.append(' '); | 817 result.append(' '); |
817 result.append(value); | 818 result.append(value); |
818 } | 819 } |
819 return result.isEmpty() ? String() : result.toString(); | 820 return result.isEmpty() ? String() : result.toString(); |
820 } | 821 } |
821 | 822 |
822 static void appendBackgroundRepeatValue(StringBuilder& builder, const CSSValue&
repeatXCSSValue, const CSSValue& repeatYCSSValue) | 823 static void appendBackgroundRepeatValue(StringBuilder& builder, const CSSValue&
repeatXCSSValue, const CSSValue& repeatYCSSValue) |
823 { | 824 { |
824 // FIXME: Ensure initial values do not appear in CSS_VALUE_LISTS. | 825 // FIXME: Ensure initial values do not appear in CSS_VALUE_LISTS. |
825 DEFINE_STATIC_LOCAL(CSSPrimitiveValue, initialRepeatValue, (CSSPrimitiveValu
e::createIdentifier(CSSValueRepeat))); | 826 DEFINE_STATIC_LOCAL(CSSIdentifierValue, initialRepeatValue, (CSSIdentifierVa
lue::create(CSSValueRepeat))); |
826 const CSSPrimitiveValue& repeatX = repeatXCSSValue.isInitialValue() ? initia
lRepeatValue : toCSSPrimitiveValue(repeatXCSSValue); | 827 const CSSIdentifierValue& repeatX = repeatXCSSValue.isInitialValue() ? initi
alRepeatValue : toCSSIdentifierValue(repeatXCSSValue); |
827 const CSSPrimitiveValue& repeatY = repeatYCSSValue.isInitialValue() ? initia
lRepeatValue : toCSSPrimitiveValue(repeatYCSSValue); | 828 const CSSIdentifierValue& repeatY = repeatYCSSValue.isInitialValue() ? initi
alRepeatValue : toCSSIdentifierValue(repeatYCSSValue); |
828 CSSValueID repeatXValueId = repeatX.getValueID(); | 829 CSSValueID repeatXValueId = repeatX.getValueID(); |
829 CSSValueID repeatYValueId = repeatY.getValueID(); | 830 CSSValueID repeatYValueId = repeatY.getValueID(); |
830 if (repeatXValueId == repeatYValueId) { | 831 if (repeatXValueId == repeatYValueId) { |
831 builder.append(repeatX.cssText()); | 832 builder.append(repeatX.cssText()); |
832 } else if (repeatXValueId == CSSValueNoRepeat && repeatYValueId == CSSValueR
epeat) { | 833 } else if (repeatXValueId == CSSValueNoRepeat && repeatYValueId == CSSValueR
epeat) { |
833 builder.append("repeat-y"); | 834 builder.append("repeat-y"); |
834 } else if (repeatXValueId == CSSValueRepeat && repeatYValueId == CSSValueNoR
epeat) { | 835 } else if (repeatXValueId == CSSValueRepeat && repeatYValueId == CSSValueNoR
epeat) { |
835 builder.append("repeat-x"); | 836 builder.append("repeat-x"); |
836 } else { | 837 } else { |
837 builder.append(repeatX.cssText()); | 838 builder.append(repeatX.cssText()); |
838 builder.append(' '); | 839 builder.append(' '); |
839 builder.append(repeatY.cssText()); | 840 builder.append(repeatY.cssText()); |
840 } | 841 } |
841 } | 842 } |
842 | 843 |
843 String StylePropertySerializer::backgroundRepeatPropertyValue() const | 844 String StylePropertySerializer::backgroundRepeatPropertyValue() const |
844 { | 845 { |
845 const CSSValue& repeatX = *m_propertySet.getPropertyCSSValue(CSSPropertyBack
groundRepeatX); | 846 const CSSValue& repeatX = *m_propertySet.getPropertyCSSValue(CSSPropertyBack
groundRepeatX); |
846 const CSSValue& repeatY = *m_propertySet.getPropertyCSSValue(CSSPropertyBack
groundRepeatY); | 847 const CSSValue& repeatY = *m_propertySet.getPropertyCSSValue(CSSPropertyBack
groundRepeatY); |
847 | 848 |
848 const CSSValueList* repeatXList = 0; | 849 const CSSValueList* repeatXList = 0; |
849 int repeatXLength = 1; | 850 int repeatXLength = 1; |
850 if (repeatX.isValueList()) { | 851 if (repeatX.isValueList()) { |
851 repeatXList = &toCSSValueList(repeatX); | 852 repeatXList = &toCSSValueList(repeatX); |
852 repeatXLength = repeatXList->length(); | 853 repeatXLength = repeatXList->length(); |
853 } else if (!repeatX.isPrimitiveValue()) { | 854 } else if (!repeatX.isIdentifierValue()) { |
854 return String(); | 855 return String(); |
855 } | 856 } |
856 | 857 |
857 const CSSValueList* repeatYList = 0; | 858 const CSSValueList* repeatYList = 0; |
858 int repeatYLength = 1; | 859 int repeatYLength = 1; |
859 if (repeatY.isValueList()) { | 860 if (repeatY.isValueList()) { |
860 repeatYList = &toCSSValueList(repeatY); | 861 repeatYList = &toCSSValueList(repeatY); |
861 repeatYLength = repeatYList->length(); | 862 repeatYLength = repeatYList->length(); |
862 } else if (!repeatY.isPrimitiveValue()) { | 863 } else if (!repeatY.isIdentifierValue()) { |
863 return String(); | 864 return String(); |
864 } | 865 } |
865 | 866 |
866 size_t shorthandLength = lowestCommonMultiple(repeatXLength, repeatYLength); | 867 size_t shorthandLength = lowestCommonMultiple(repeatXLength, repeatYLength); |
867 StringBuilder builder; | 868 StringBuilder builder; |
868 for (size_t i = 0; i < shorthandLength; ++i) { | 869 for (size_t i = 0; i < shorthandLength; ++i) { |
869 if (i) | 870 if (i) |
870 builder.append(", "); | 871 builder.append(", "); |
871 | 872 |
872 const CSSValue& xValue = repeatXList ? repeatXList->item(i % repeatXList
->length()) : repeatX; | 873 const CSSValue& xValue = repeatXList ? repeatXList->item(i % repeatXList
->length()) : repeatX; |
873 const CSSValue& yValue = repeatYList ? repeatYList->item(i % repeatYList
->length()) : repeatY; | 874 const CSSValue& yValue = repeatYList ? repeatYList->item(i % repeatYList
->length()) : repeatY; |
874 appendBackgroundRepeatValue(builder, xValue, yValue); | 875 appendBackgroundRepeatValue(builder, xValue, yValue); |
875 } | 876 } |
876 return builder.toString(); | 877 return builder.toString(); |
877 } | 878 } |
878 | 879 |
879 } // namespace blink | 880 } // namespace blink |
OLD | NEW |