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); |
| 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; |
| 894 // TODO(rob.buis): Remove this when the legacy property parser is gone |
| 895 m_currentShorthand = propId; |
790 switch (propId) { | 896 switch (propId) { |
791 case CSSPropertyWebkitMarginCollapse: { | 897 case CSSPropertyWebkitMarginCollapse: { |
792 CSSValueID id = m_range.consumeIncludingWhitespace().id(); | 898 CSSValueID id = m_range.consumeIncludingWhitespace().id(); |
793 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebki
tMarginBeforeCollapse, id)) | 899 if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebki
tMarginBeforeCollapse, id)) |
794 return false; | 900 return false; |
795 RefPtrWillBeRawPtr<CSSValue> beforeCollapse = cssValuePool().createIdent
ifierValue(id); | 901 RefPtrWillBeRawPtr<CSSValue> beforeCollapse = cssValuePool().createIdent
ifierValue(id); |
796 addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, impor
tant); | 902 addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, impor
tant); |
797 if (m_range.atEnd()) { | 903 if (m_range.atEnd()) { |
798 addProperty(CSSPropertyWebkitMarginAfterCollapse, beforeCollapse, im
portant); | 904 addProperty(CSSPropertyWebkitMarginAfterCollapse, beforeCollapse, im
portant); |
799 return true; | 905 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 | 925 // 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. | 926 // paged-x or paged-y, then overflow-x and overflow-y should have the sa
me value. |
821 if (id == CSSValueWebkitPagedX || id == CSSValueWebkitPagedY) | 927 if (id == CSSValueWebkitPagedX || id == CSSValueWebkitPagedY) |
822 overflowXValue = cssValuePool().createIdentifierValue(CSSValueAuto); | 928 overflowXValue = cssValuePool().createIdentifierValue(CSSValueAuto); |
823 else | 929 else |
824 overflowXValue = overflowYValue; | 930 overflowXValue = overflowYValue; |
825 addProperty(CSSPropertyOverflowX, overflowXValue.release(), important); | 931 addProperty(CSSPropertyOverflowX, overflowXValue.release(), important); |
826 addProperty(CSSPropertyOverflowY, overflowYValue.release(), important); | 932 addProperty(CSSPropertyOverflowY, overflowYValue.release(), important); |
827 return true; | 933 return true; |
828 } | 934 } |
| 935 case CSSPropertyFont: { |
| 936 const CSSParserToken& token = m_range.peek(); |
| 937 if (token.id() >= CSSValueCaption && token.id() <= CSSValueStatusBar) |
| 938 return consumeSystemFont(important); |
| 939 return consumeFont(important); |
| 940 } |
829 default: | 941 default: |
| 942 m_currentShorthand = oldShorthand; |
830 return false; | 943 return false; |
831 } | 944 } |
832 } | 945 } |
833 | 946 |
834 } // namespace blink | 947 } // namespace blink |
OLD | NEW |