Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "core/css/parser/CSSPropertyParser.h" | 6 #include "core/css/parser/CSSPropertyParser.h" |
| 7 | 7 |
| 8 #include "core/StylePropertyShorthand.h" | 8 #include "core/StylePropertyShorthand.h" |
| 9 #include "core/css/CSSCalculationValue.h" | 9 #include "core/css/CSSCalculationValue.h" |
| 10 #include "core/css/CSSFontFaceSrcValue.h" | 10 #include "core/css/CSSFontFaceSrcValue.h" |
| 11 #include "core/css/CSSFontFeatureValue.h" | 11 #include "core/css/CSSFontFeatureValue.h" |
| 12 #include "core/css/CSSPrimitiveValueMappings.h" | |
| 12 #include "core/css/CSSUnicodeRangeValue.h" | 13 #include "core/css/CSSUnicodeRangeValue.h" |
| 13 #include "core/css/CSSValuePool.h" | 14 #include "core/css/CSSValuePool.h" |
| 15 #include "core/css/FontFace.h" | |
| 14 #include "core/css/parser/CSSParserFastPaths.h" | 16 #include "core/css/parser/CSSParserFastPaths.h" |
| 15 #include "core/css/parser/CSSParserValues.h" | 17 #include "core/css/parser/CSSParserValues.h" |
| 16 #include "core/frame/UseCounter.h" | 18 #include "core/frame/UseCounter.h" |
| 19 #include "core/layout/LayoutTheme.h" | |
| 17 #include "wtf/text/StringBuilder.h" | 20 #include "wtf/text/StringBuilder.h" |
| 18 | 21 |
| 19 namespace blink { | 22 namespace blink { |
| 20 | 23 |
| 21 CSSPropertyParser::CSSPropertyParser(CSSParserValueList* valueList, const CSSPar serTokenRange& range, | 24 CSSPropertyParser::CSSPropertyParser(CSSParserValueList* valueList, const CSSPar serTokenRange& range, |
| 22 const CSSParserContext& context, WillBeHeapVector<CSSProperty, 256>& parsedP roperties, | 25 const CSSParserContext& context, WillBeHeapVector<CSSProperty, 256>& parsedP roperties, |
| 23 StyleRule::Type ruleType) | 26 StyleRule::Type ruleType) |
| 24 : m_valueList(valueList) | 27 : m_valueList(valueList) |
| 25 , m_range(range) | 28 , m_range(range) |
| 26 , m_context(context) | 29 , m_context(context) |
| 27 , m_parsedProperties(parsedProperties) | 30 , m_parsedProperties(parsedProperties) |
| 28 , m_ruleType(ruleType) | |
| 29 , m_inParseShorthand(0) | 31 , m_inParseShorthand(0) |
| 30 , m_currentShorthand(CSSPropertyInvalid) | 32 , m_currentShorthand(CSSPropertyInvalid) |
| 31 , m_implicitShorthand(false) | 33 , m_implicitShorthand(false) |
| 32 { | 34 { |
| 33 } | 35 } |
| 34 | 36 |
| 35 bool CSSPropertyParser::parseValue(CSSPropertyID unresolvedProperty, bool import ant, | 37 bool CSSPropertyParser::parseValue(CSSPropertyID unresolvedProperty, bool import ant, |
| 36 const CSSParserTokenRange& range, const CSSParserContext& context, | 38 const CSSParserTokenRange& range, const CSSParserContext& context, |
| 37 WillBeHeapVector<CSSProperty, 256>& parsedProperties, StyleRule::Type ruleTy pe) | 39 WillBeHeapVector<CSSProperty, 256>& parsedProperties, StyleRule::Type ruleTy pe) |
| 38 { | 40 { |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 493 if (fontVariant) | 495 if (fontVariant) |
| 494 values->append(fontVariant.release()); | 496 values->append(fontVariant.release()); |
| 495 } while (consumeCommaIncludingWhitespace(range)); | 497 } while (consumeCommaIncludingWhitespace(range)); |
| 496 | 498 |
| 497 if (values->length()) | 499 if (values->length()) |
| 498 return values.release(); | 500 return values.release(); |
| 499 | 501 |
| 500 return nullptr; | 502 return nullptr; |
| 501 } | 503 } |
| 502 | 504 |
| 503 static PassRefPtrWillBeRawPtr<CSSValue> consumeFontWeight(CSSParserTokenRange& r ange) | 505 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeFontWeight(CSSParserToke nRange& range) |
| 504 { | 506 { |
| 505 const CSSParserToken& token = range.peek(); | 507 const CSSParserToken& token = range.peek(); |
| 506 if (token.id() >= CSSValueNormal && token.id() <= CSSValueLighter) | 508 if (token.id() >= CSSValueNormal && token.id() <= CSSValueLighter) |
| 507 return consumeIdent(range); | 509 return consumeIdent(range); |
| 508 if (token.type() != NumberToken || token.numericValueType() != IntegerValueT ype) | 510 if (token.type() != NumberToken || token.numericValueType() != IntegerValueT ype) |
| 509 return nullptr; | 511 return nullptr; |
| 510 int weight = static_cast<int>(token.numericValue()); | 512 int weight = static_cast<int>(token.numericValue()); |
| 511 if ((weight % 100) || weight < 100 || weight > 900) | 513 if ((weight % 100) || weight < 100 || weight > 900) |
| 512 return nullptr; | 514 return nullptr; |
| 513 range.consumeIncludingWhitespace(); | 515 range.consumeIncludingWhitespace(); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 575 } | 577 } |
| 576 | 578 |
| 577 static PassRefPtrWillBeRawPtr<CSSValue> consumeTabSize(CSSParserTokenRange& rang e, CSSParserMode cssParserMode) | 579 static PassRefPtrWillBeRawPtr<CSSValue> consumeTabSize(CSSParserTokenRange& rang e, CSSParserMode cssParserMode) |
| 578 { | 580 { |
| 579 RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue = consumeInteger(range, cs sParserMode, 0); | 581 RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue = consumeInteger(range, cs sParserMode, 0); |
| 580 if (parsedValue) | 582 if (parsedValue) |
| 581 return parsedValue; | 583 return parsedValue; |
| 582 return consumeLength(range, cssParserMode, ValueRangeNonNegative); | 584 return consumeLength(range, cssParserMode, ValueRangeNonNegative); |
| 583 } | 585 } |
| 584 | 586 |
| 585 static PassRefPtrWillBeRawPtr<CSSValue> consumeFontSize(CSSParserTokenRange& ran ge, CSSParserMode cssParserMode) | 587 static PassRefPtrWillBeRawPtr<CSSValue> consumeFontSize(CSSParserTokenRange& ran ge, CSSParserMode cssParserMode, UnitlessQuirk unitless = UnitlessQuirk::Forbid) |
| 586 { | 588 { |
| 587 if (range.peek().id() >= CSSValueXxSmall && range.peek().id() <= CSSValueLar ger) | 589 if (range.peek().id() >= CSSValueXxSmall && range.peek().id() <= CSSValueLar ger) |
| 588 return consumeIdent(range); | 590 return consumeIdent(range); |
| 589 return consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative, U nitlessQuirk::Allow); | 591 return consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative, u nitless); |
| 590 } | 592 } |
| 591 | 593 |
| 592 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeLineHeight(CSSParserToke nRange& range, CSSParserMode cssParserMode) | 594 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeLineHeight(CSSParserToke nRange& range, CSSParserMode cssParserMode) |
| 593 { | 595 { |
| 594 if (range.peek().id() == CSSValueNormal) | 596 if (range.peek().id() == CSSValueNormal) |
| 595 return consumeIdent(range); | 597 return consumeIdent(range); |
| 596 | 598 |
| 597 RefPtrWillBeRawPtr<CSSPrimitiveValue> lineHeight = consumeNumber(range, Valu eRangeNonNegative); | 599 RefPtrWillBeRawPtr<CSSPrimitiveValue> lineHeight = consumeNumber(range, Valu eRangeNonNegative); |
| 598 if (lineHeight) | 600 if (lineHeight) |
| 599 return lineHeight; | 601 return lineHeight; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 644 case CSSPropertyFontFamily: | 646 case CSSPropertyFontFamily: |
| 645 return consumeFontFamily(m_range); | 647 return consumeFontFamily(m_range); |
| 646 case CSSPropertyFontWeight: | 648 case CSSPropertyFontWeight: |
| 647 return consumeFontWeight(m_range); | 649 return consumeFontWeight(m_range); |
| 648 case CSSPropertyLetterSpacing: | 650 case CSSPropertyLetterSpacing: |
| 649 case CSSPropertyWordSpacing: | 651 case CSSPropertyWordSpacing: |
| 650 return consumeSpacing(m_range, m_context.mode()); | 652 return consumeSpacing(m_range, m_context.mode()); |
| 651 case CSSPropertyTabSize: | 653 case CSSPropertyTabSize: |
| 652 return consumeTabSize(m_range, m_context.mode()); | 654 return consumeTabSize(m_range, m_context.mode()); |
| 653 case CSSPropertyFontSize: | 655 case CSSPropertyFontSize: |
| 654 return consumeFontSize(m_range, m_context.mode()); | 656 return consumeFontSize(m_range, m_context.mode(), UnitlessQuirk::Allow); |
| 655 case CSSPropertyLineHeight: | 657 case CSSPropertyLineHeight: |
| 656 return consumeLineHeight(m_range, m_context.mode()); | 658 return consumeLineHeight(m_range, m_context.mode()); |
| 657 case CSSPropertyRotate: | 659 case CSSPropertyRotate: |
| 658 return consumeRotation(m_range); | 660 return consumeRotation(m_range); |
| 659 default: | 661 default: |
| 660 return nullptr; | 662 return nullptr; |
| 661 } | 663 } |
| 662 } | 664 } |
| 663 | 665 |
| 664 static PassRefPtrWillBeRawPtr<CSSValueList> consumeFontFaceUnicodeRange(CSSParse rTokenRange& range) | 666 static PassRefPtrWillBeRawPtr<CSSValueList> consumeFontFaceUnicodeRange(CSSParse rTokenRange& range) |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 777 break; | 779 break; |
| 778 } | 780 } |
| 779 | 781 |
| 780 if (!parsedValue || !m_range.atEnd()) | 782 if (!parsedValue || !m_range.atEnd()) |
| 781 return false; | 783 return false; |
| 782 | 784 |
| 783 addProperty(propId, parsedValue.release(), false); | 785 addProperty(propId, parsedValue.release(), false); |
| 784 return true; | 786 return true; |
| 785 } | 787 } |
| 786 | 788 |
| 789 bool CSSPropertyParser::consumeSystemFont(bool important) | |
| 790 { | |
| 791 CSSValueID systemFontID = m_range.consumeIncludingWhitespace().id(); | |
| 792 ASSERT(systemFontID >= CSSValueCaption && systemFontID <= CSSValueStatusBar) ; | |
| 793 if (!m_range.atEnd()) | |
| 794 return false; | |
| 795 | |
| 796 FontStyle fontStyle = FontStyleNormal; | |
| 797 FontWeight fontWeight = FontWeightNormal; | |
| 798 float fontSize = 0; | |
| 799 AtomicString fontFamily; | |
| 800 LayoutTheme::theme().systemFont(systemFontID, fontStyle, fontWeight, fontSiz e, fontFamily); | |
| 801 | |
| 802 addProperty(CSSPropertyFontStyle, cssValuePool().createIdentifierValue(fontS tyle == FontStyleItalic ? CSSValueItalic : CSSValueNormal), important); | |
| 803 addProperty(CSSPropertyFontWeight, cssValuePool().createValue(fontWeight), i mportant); | |
| 804 addProperty(CSSPropertyFontSize, cssValuePool().createValue(fontSize, CSSPri mitiveValue::UnitType::Pixels), important); | |
| 805 RefPtrWillBeRawPtr<CSSValueList> fontFamilyList = CSSValueList::createCommaS eparated(); | |
| 806 fontFamilyList->append(cssValuePool().createFontFamilyValue(fontFamily)); | |
| 807 addProperty(CSSPropertyFontFamily, fontFamilyList.release(), important); | |
| 808 | |
| 809 addProperty(CSSPropertyFontStretch, cssValuePool().createIdentifierValue(CSS ValueNormal), important); | |
| 810 addProperty(CSSPropertyFontVariant, cssValuePool().createIdentifierValue(CSS ValueNormal), important); | |
| 811 addProperty(CSSPropertyLineHeight, cssValuePool().createIdentifierValue(CSSV alueNormal), important); | |
| 812 return true; | |
| 813 } | |
| 814 | |
| 815 bool CSSPropertyParser::consumeFont(bool important) | |
| 816 { | |
| 817 // Let's check if there is an inherit or initial somewhere in the shorthand. | |
| 818 CSSParserTokenRange range = m_range; | |
| 819 while (!range.atEnd()) { | |
| 820 CSSValueID id = range.consumeIncludingWhitespace().id(); | |
| 821 if (id == CSSValueInherit || id == CSSValueInitial) | |
| 822 return false; | |
| 823 } | |
| 824 // Optional font-style, font-variant, font-stretch and font-weight. | |
| 825 RefPtrWillBeRawPtr<CSSPrimitiveValue> fontStyle = nullptr; | |
| 826 RefPtrWillBeRawPtr<CSSPrimitiveValue> fontVariant = nullptr; | |
| 827 RefPtrWillBeRawPtr<CSSPrimitiveValue> fontWeight = nullptr; | |
| 828 RefPtrWillBeRawPtr<CSSPrimitiveValue> fontStretch = nullptr; | |
| 829 while (!m_range.atEnd()) { | |
| 830 CSSValueID id = m_range.peek().id(); | |
| 831 if (!fontStyle && CSSParserFastPaths::isValidKeywordPropertyAndValue(CSS PropertyFontStyle, id)) { | |
| 832 fontStyle = consumeIdent(m_range); | |
| 833 continue; | |
| 834 } | |
| 835 if (!fontVariant) { | |
| 836 // Font variant in the shorthand is particular, it only accepts norm al or small-caps. | |
| 837 fontVariant = consumeFontVariant(m_range); | |
| 838 if (fontVariant) | |
| 839 continue; | |
| 840 } | |
| 841 if (!fontWeight) { | |
| 842 fontWeight = consumeFontWeight(m_range); | |
| 843 if (fontWeight) | |
| 844 continue; | |
| 845 } | |
| 846 if (!fontStretch && CSSParserFastPaths::isValidKeywordPropertyAndValue(C SSPropertyFontStretch, id)) | |
| 847 fontStretch = consumeIdent(m_range); | |
| 848 else | |
| 849 break; | |
| 850 } | |
| 851 | |
| 852 if (m_range.atEnd()) | |
| 853 return false; | |
| 854 | |
| 855 addProperty(CSSPropertyFontStyle, fontStyle ? fontStyle.release() : cssValue Pool().createIdentifierValue(CSSValueNormal), important); | |
| 856 addProperty(CSSPropertyFontVariant, fontVariant ? fontVariant.release() : cs sValuePool().createIdentifierValue(CSSValueNormal), important); | |
| 857 addProperty(CSSPropertyFontWeight, fontWeight ? fontWeight.release() : cssVa luePool().createIdentifierValue(CSSValueNormal), important); | |
| 858 addProperty(CSSPropertyFontStretch, fontStretch ? fontStretch.release() : cs sValuePool().createIdentifierValue(CSSValueNormal), important); | |
| 859 | |
| 860 // Now a font size _must_ come. | |
| 861 RefPtrWillBeRawPtr<CSSValue> fontSize = consumeFontSize(m_range, m_context.m ode()); | |
| 862 if (!fontSize || m_range.atEnd()) | |
| 863 return false; | |
| 864 | |
| 865 addProperty(CSSPropertyFontSize, fontSize.release(), important); | |
| 866 | |
| 867 if (m_range.peek().type() == DelimiterToken && m_range.peek().delimiter() == '/') { | |
| 868 m_range.consumeIncludingWhitespace(); | |
| 869 RefPtrWillBeRawPtr<CSSPrimitiveValue> lineHeight = consumeLineHeight(m_r ange, m_context.mode()); | |
| 870 if (!lineHeight) | |
| 871 return false; | |
| 872 addProperty(CSSPropertyLineHeight, lineHeight.release(), important); | |
| 873 } else { | |
| 874 addProperty(CSSPropertyLineHeight, cssValuePool().createIdentifierValue( CSSValueNormal), important, true); | |
|
Timothy Loh
2015/10/06 23:45:04
implicit value here can be removed too
| |
| 875 } | |
| 876 | |
| 877 // Font family must come now. | |
| 878 RefPtrWillBeRawPtr<CSSValue> parsedFamilyValue = consumeFontFamily(m_range); | |
| 879 if (!parsedFamilyValue) | |
| 880 return false; | |
| 881 | |
| 882 addProperty(CSSPropertyFontFamily, parsedFamilyValue.release(), important); | |
| 883 | |
| 884 // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20110324/#font-prop requir es that | |
| 885 // "font-stretch", "font-size-adjust", and "font-kerning" be reset to their initial values | |
| 886 // but we don't seem to support them at the moment. They should also be adde d here once implemented. | |
| 887 return m_range.atEnd(); | |
| 888 } | |
| 889 | |
| 787 bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, bool important) | 890 bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, bool important) |
| 788 { | 891 { |
| 789 m_range.consumeWhitespace(); | 892 m_range.consumeWhitespace(); |
| 893 CSSPropertyID oldShorthand = m_currentShorthand; | |
|
Timothy Loh
2015/10/06 23:45:04
// TODO(rob.buis): Remove this when the legacy pro
| |
| 894 m_currentShorthand = propId; | |
| 790 switch (propId) { | 895 switch (propId) { |
| 791 case CSSPropertyWebkitMarginCollapse: { | 896 case CSSPropertyWebkitMarginCollapse: { |
| 792 CSSValueID id = m_range.consumeIncludingWhitespace().id(); | 897 CSSValueID id = m_range.consumeIncludingWhitespace().id(); |
| 793 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebki tMarginBeforeCollapse, id)) | 898 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebki tMarginBeforeCollapse, id)) |
| 794 return false; | 899 return false; |
| 795 RefPtrWillBeRawPtr<CSSValue> beforeCollapse = cssValuePool().createIdent ifierValue(id); | 900 RefPtrWillBeRawPtr<CSSValue> beforeCollapse = cssValuePool().createIdent ifierValue(id); |
| 796 addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, impor tant); | 901 addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, impor tant); |
| 797 if (m_range.atEnd()) { | 902 if (m_range.atEnd()) { |
| 798 addProperty(CSSPropertyWebkitMarginAfterCollapse, beforeCollapse, im portant); | 903 addProperty(CSSPropertyWebkitMarginAfterCollapse, beforeCollapse, im portant); |
| 799 return true; | 904 return true; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 819 // pagination controls, it should default to hidden. If the overflow-y v alue is anything but | 924 // pagination controls, it should default to hidden. If the overflow-y v alue is anything but |
| 820 // paged-x or paged-y, then overflow-x and overflow-y should have the sa me value. | 925 // paged-x or paged-y, then overflow-x and overflow-y should have the sa me value. |
| 821 if (id == CSSValueWebkitPagedX || id == CSSValueWebkitPagedY) | 926 if (id == CSSValueWebkitPagedX || id == CSSValueWebkitPagedY) |
| 822 overflowXValue = cssValuePool().createIdentifierValue(CSSValueAuto); | 927 overflowXValue = cssValuePool().createIdentifierValue(CSSValueAuto); |
| 823 else | 928 else |
| 824 overflowXValue = overflowYValue; | 929 overflowXValue = overflowYValue; |
| 825 addProperty(CSSPropertyOverflowX, overflowXValue.release(), important); | 930 addProperty(CSSPropertyOverflowX, overflowXValue.release(), important); |
| 826 addProperty(CSSPropertyOverflowY, overflowYValue.release(), important); | 931 addProperty(CSSPropertyOverflowY, overflowYValue.release(), important); |
| 827 return true; | 932 return true; |
| 828 } | 933 } |
| 934 case CSSPropertyFont: { | |
| 935 const CSSParserToken& token = m_range.peek(); | |
| 936 if (token.id() >= CSSValueCaption && token.id() <= CSSValueStatusBar) | |
| 937 return consumeSystemFont(important); | |
| 938 return consumeFont(important); | |
| 939 } | |
| 829 default: | 940 default: |
| 941 m_currentShorthand = oldShorthand; | |
| 830 return false; | 942 return false; |
| 831 } | 943 } |
| 832 } | 944 } |
| 833 | 945 |
| 834 } // namespace blink | 946 } // namespace blink |
| OLD | NEW |