| 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 |