Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (269956 => 269957)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2020-11-18 16:03:50 UTC (rev 269957)
@@ -1,3 +1,12 @@
+2020-11-18 Chris Lord <[email protected]>
+
+ Make CSS font shorthands parsable within a worker (i.e. without CSSValuePool)
+ https://bugs.webkit.org/show_bug.cgi?id=202794
+
+ Reviewed by Darin Adler.
+
+ * web-platform-tests/html/canvas/element/text-styles/2d.text.font.parse.invalid-expected.txt:
+
2020-11-18 Commit Queue <[email protected]>
Unreviewed, reverting r269940.
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/text-styles/2d.text.font.parse.invalid-expected.txt (269956 => 269957)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/text-styles/2d.text.font.parse.invalid-expected.txt 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/text-styles/2d.text.font.parse.invalid-expected.txt 2020-11-18 16:03:50 UTC (rev 269957)
@@ -1,5 +1,5 @@
2d.text.font.parse.invalid
Actual output:
-FAIL Canvas test: 2d.text.font.parse.invalid assert_equals: ctx.font === '20px serif' (got 13px sans-serif[string], expected 20px serif[string]) expected "20px serif" but got "13px sans-serif"
+PASS Canvas test: 2d.text.font.parse.invalid
Modified: trunk/Source/WebCore/ChangeLog (269956 => 269957)
--- trunk/Source/WebCore/ChangeLog 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/ChangeLog 2020-11-18 16:03:50 UTC (rev 269957)
@@ -1,3 +1,71 @@
+2020-11-18 Chris Lord <[email protected]>
+
+ Make CSS font shorthands parsable within a worker (i.e. without CSSValuePool)
+ https://bugs.webkit.org/show_bug.cgi?id=202794
+
+ Reviewed by Darin Adler.
+
+ Add functions to make it possible to parse CSS font shorthand
+ properties without using CSS values, so it can be done safely off of
+ the main thread. To support and test this, also add functions to make
+ it possible to resolve those properties into a style without
+ StyleBuilder and use that within CanvasRenderingContext2D.
+
+ No new tests, covered by existing tests.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * css/parser/CSSParser.cpp:
+ (WebCore::CSSParser::parseFontWorkerSafe):
+ * css/parser/CSSParser.h:
+ * css/parser/CSSPropertyParser.cpp:
+ (WebCore::consumeFontWeight):
+ (WebCore::consumeFontStretchKeywordValue):
+ (WebCore::consumeFontStyle):
+ (WebCore::consumeFamilyName):
+ * css/parser/CSSPropertyParser.h:
+ * css/parser/CSSPropertyParserHelpers.cpp:
+ (WebCore::CSSPropertyParserHelpers::CalcParser::consumePercentRaw):
+ (WebCore::CSSPropertyParserHelpers::CalcParser::consumeAngleRaw):
+ (WebCore::CSSPropertyParserHelpers::CalcParser::consumeLengthRaw):
+ (WebCore::CSSPropertyParserHelpers::CalcParser::consumeLengthOrPercentRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeNumberRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeNumber):
+ (WebCore::CSSPropertyParserHelpers::consumeFontWeightNumberRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeFontWeightNumber):
+ (WebCore::CSSPropertyParserHelpers::consumeLengthRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeLength):
+ (WebCore::CSSPropertyParserHelpers::consumePercent):
+ (WebCore::CSSPropertyParserHelpers::consumeLengthOrPercentRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeLengthOrPercent):
+ (WebCore::CSSPropertyParserHelpers::consumeAngleRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeIdentRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeIdent):
+ (WebCore::CSSPropertyParserHelpers::consumeIdentRangeRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeFontVariantCSS21Raw):
+ (WebCore::CSSPropertyParserHelpers::consumeFontWeightKeywordValueRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeFontWeightRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeFontStretchKeywordValueRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeFontStyleKeywordValueRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeFontStyleRaw):
+ (WebCore::CSSPropertyParserHelpers::concatenateFamilyName):
+ (WebCore::CSSPropertyParserHelpers::consumeFamilyNameRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeGenericFamilyRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeFontFamilyRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeFontSizeRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeLineHeightRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeFontWorkerSafe):
+ (WebCore::CSSPropertyParserHelpers::genericFontFamilyFromValueID):
+ * css/parser/CSSPropertyParserHelpers.h:
+ (WebCore::CSSPropertyParserHelpers::consumeIdentRaw):
+ * html/canvas/CanvasRenderingContext2D.cpp:
+ (WebCore::CanvasRenderingContext2D::setFont):
+ * style/StyleBuilderCustom.h:
+ (WebCore::Style::BuilderCustom::applyValueFontFamily):
+ * style/StyleResolveForFontRaw.cpp: Added.
+ (WebCore::Style::resolveForFontRaw):
+ * style/StyleResolveForFontRaw.h: Added.
+
2020-11-18 Michael Catanzaro <[email protected]>
[WPE][GTK] Update Outlook user agent quirk
Modified: trunk/Source/WebCore/Sources.txt (269956 => 269957)
--- trunk/Source/WebCore/Sources.txt 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/Sources.txt 2020-11-18 16:03:50 UTC (rev 269957)
@@ -2427,6 +2427,7 @@
style/StylePendingResources.cpp
style/StyleRelations.cpp
style/StyleResolveForDocument.cpp
+style/StyleResolveForFontRaw.cpp
style/StyleResolver.cpp
style/StyleScope.cpp
style/StyleScopeRuleSets.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (269956 => 269957)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-11-18 16:03:50 UTC (rev 269957)
@@ -5136,6 +5136,7 @@
E4D33F44252C50E200837D05 /* LayoutIntegrationLineIteratorLegacyPath.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D33F43252C50E200837D05 /* LayoutIntegrationLineIteratorLegacyPath.h */; };
E4D33F46252C50FC00837D05 /* LayoutIntegrationLineIteratorModernPath.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D33F45252C50FB00837D05 /* LayoutIntegrationLineIteratorModernPath.h */; };
E4D58EB517B4DBDC00CBDCA8 /* StyleResolveForDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D58EB317B4DBDC00CBDCA8 /* StyleResolveForDocument.h */; };
+ E4D68EB517B4DBDC00CBDCA8 /* StyleResolveForFontRaw.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D68EB317B4DBDC00CBDCA8 /* StyleResolveForFontRaw.h */; };
E4D58EB917B4ED8900CBDCA8 /* StyleFontSizeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D58EB717B4ED8900CBDCA8 /* StyleFontSizeFunctions.h */; };
E4D58EBB17B8F12800CBDCA8 /* ElementTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4D988B417BFD1F60084FB88 /* TextNodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */; };
@@ -16286,6 +16287,8 @@
E4D33F45252C50FB00837D05 /* LayoutIntegrationLineIteratorModernPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutIntegrationLineIteratorModernPath.h; sourceTree = "<group>"; };
E4D58EB217B4DBDC00CBDCA8 /* StyleResolveForDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleResolveForDocument.cpp; sourceTree = "<group>"; };
E4D58EB317B4DBDC00CBDCA8 /* StyleResolveForDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleResolveForDocument.h; sourceTree = "<group>"; };
+ E4D68EB217B4DBDC00CBDCA8 /* StyleResolveForFontRaw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleResolveForFontRaw.cpp; sourceTree = "<group>"; };
+ E4D68EB317B4DBDC00CBDCA8 /* StyleResolveForFontRaw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleResolveForFontRaw.h; sourceTree = "<group>"; };
E4D58EB617B4ED8900CBDCA8 /* StyleFontSizeFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleFontSizeFunctions.cpp; sourceTree = "<group>"; };
E4D58EB717B4ED8900CBDCA8 /* StyleFontSizeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleFontSizeFunctions.h; sourceTree = "<group>"; };
E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementTraversal.h; sourceTree = "<group>"; };
@@ -28867,6 +28870,8 @@
E461802C1C8DD2900026C02C /* StyleRelations.h */,
E4D58EB217B4DBDC00CBDCA8 /* StyleResolveForDocument.cpp */,
E4D58EB317B4DBDC00CBDCA8 /* StyleResolveForDocument.h */,
+ E4D68EB217B4DBDC00CBDCA8 /* StyleResolveForFontRaw.cpp */,
+ E4D68EB317B4DBDC00CBDCA8 /* StyleResolveForFontRaw.h */,
E139866115478474001E3F65 /* StyleResolver.cpp */,
E139866215478474001E3F65 /* StyleResolver.h */,
E461D65C1BB0C7F000CB5645 /* StyleScope.cpp */,
@@ -34518,6 +34523,7 @@
BC2272870E82E70700E7F975 /* StyleReflection.h in Headers */,
E461802D1C8DD2900026C02C /* StyleRelations.h in Headers */,
E4D58EB517B4DBDC00CBDCA8 /* StyleResolveForDocument.h in Headers */,
+ E4D68EB517B4DBDC00CBDCA8 /* StyleResolveForFontRaw.h in Headers */,
E139866415478474001E3F65 /* StyleResolver.h in Headers */,
E4BBED4D14FCDBA1003F0B98 /* StyleRule.h in Headers */,
E4946EAF156E64DD00D3297F /* StyleRuleImport.h in Headers */,
Modified: trunk/Source/WebCore/css/parser/CSSParser.cpp (269956 => 269957)
--- trunk/Source/WebCore/css/parser/CSSParser.cpp 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/css/parser/CSSParser.cpp 2020-11-18 16:03:50 UTC (rev 269957)
@@ -138,6 +138,15 @@
return CSSParserFastPaths::parseHexColor(string);
}
+Optional<CSSPropertyParserHelpers::FontRaw> CSSParser::parseFontWorkerSafe(const String& string, CSSParserMode cssParserMode)
+{
+ CSSTokenizer tokenizer(string);
+ CSSParserTokenRange range(tokenizer.tokenRange());
+ range.consumeWhitespace();
+
+ return CSSPropertyParserHelpers::consumeFontWorkerSafe(range, cssParserMode);
+}
+
RefPtr<CSSValue> CSSParser::parseSingleValue(CSSPropertyID propertyID, const String& string, const CSSParserContext& context)
{
if (string.isEmpty())
Modified: trunk/Source/WebCore/css/parser/CSSParser.h (269956 => 269957)
--- trunk/Source/WebCore/css/parser/CSSParser.h 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/css/parser/CSSParser.h 2020-11-18 16:03:50 UTC (rev 269957)
@@ -44,6 +44,10 @@
class RenderStyle;
template<typename> struct SRGBA;
+namespace CSSPropertyParserHelpers {
+struct FontRaw;
+}
+
namespace Style {
class BuilderState;
}
@@ -92,6 +96,8 @@
static Optional<SRGBA<uint8_t>> parseNamedColor(StringView);
static Optional<SRGBA<uint8_t>> parseHexColor(StringView);
+ static Optional<CSSPropertyParserHelpers::FontRaw> parseFontWorkerSafe(const String&, CSSParserMode = HTMLStandardMode);
+
private:
ParseResult parseValue(MutableStyleProperties&, CSSPropertyID, const String&, bool important);
Modified: trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp (269956 => 269957)
--- trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp 2020-11-18 16:03:50 UTC (rev 269957)
@@ -54,7 +54,6 @@
#include "CSSParserIdioms.h"
#include "CSSPendingSubstitutionValue.h"
#include "CSSPrimitiveValueMappings.h"
-#include "CSSPropertyParserHelpers.h"
#include "CSSReflectValue.h"
#include "CSSShadowValue.h"
#include "CSSTimingFunctionValue.h"
@@ -864,16 +863,16 @@
return consumeIdent<CSSValueNormal, CSSValueSmallCaps>(range);
}
-static RefPtr<CSSPrimitiveValue> consumeFontWeightKeywordValue(CSSParserTokenRange& range)
-{
- return consumeIdent<CSSValueNormal, CSSValueBold, CSSValueBolder, CSSValueLighter>(range);
-}
-
static RefPtr<CSSPrimitiveValue> consumeFontWeight(CSSParserTokenRange& range)
{
- if (auto result = consumeFontWeightKeywordValue(range))
- return result;
- return consumeFontWeightNumber(range);
+ if (auto result = consumeFontWeightRaw(range)) {
+ return switchOn(*result, [] (CSSValueID valueID) {
+ return CSSValuePool::singleton().createIdentifierValue(valueID);
+ }, [] (double weightNumber) {
+ return CSSValuePool::singleton().createValue(weightNumber, CSSUnitType::CSS_NUMBER);
+ });
+ }
+ return nullptr;
}
static RefPtr<CSSPrimitiveValue> consumeFontWeightAbsoluteKeywordValue(CSSParserTokenRange& range)
@@ -910,7 +909,9 @@
static RefPtr<CSSPrimitiveValue> consumeFontStretchKeywordValue(CSSParserTokenRange& range)
{
- return consumeIdent<CSSValueUltraCondensed, CSSValueExtraCondensed, CSSValueCondensed, CSSValueSemiCondensed, CSSValueNormal, CSSValueSemiExpanded, CSSValueExpanded, CSSValueExtraExpanded, CSSValueUltraExpanded>(range);
+ if (auto valueID = consumeFontStretchKeywordValueRaw(range))
+ return CSSValuePool::singleton().createIdentifierValue(*valueID);
+ return nullptr;
}
#if ENABLE(VARIATION_FONTS)
@@ -965,26 +966,16 @@
static RefPtr<CSSFontStyleValue> consumeFontStyle(CSSParserTokenRange& range, CSSParserMode cssParserMode)
{
- auto result = consumeFontStyleKeywordValue(range);
- if (!result)
- return nullptr;
-
- auto valueID = result->valueID();
- if (valueID == CSSValueNormal || valueID == CSSValueItalic)
- return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(valueID));
- ASSERT(result->valueID() == CSSValueOblique);
+ if (auto result = consumeFontStyleRaw(range, cssParserMode)) {
#if ENABLE(VARIATION_FONTS)
- if (!range.atEnd()) {
- if (auto angle = consumeAngle(range, cssParserMode)) {
- if (fontStyleIsWithinRange(angle->value<float>(CSSUnitType::CSS_DEG)))
- return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(CSSValueOblique), WTFMove(angle));
- return nullptr;
+ if (result->style == CSSValueOblique && result->angle) {
+ return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(CSSValueOblique),
+ CSSValuePool::singleton().createValue(result->angle->value, result->angle->type));
}
+#endif
+ return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(result->style));
}
-#else
- UNUSED_PARAM(cssParserMode);
-#endif
- return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(CSSValueOblique));
+ return nullptr;
}
#if ENABLE(VARIATION_FONTS)
@@ -1018,30 +1009,9 @@
}
#endif
-static String concatenateFamilyName(CSSParserTokenRange& range)
-{
- StringBuilder builder;
- bool addedSpace = false;
- const CSSParserToken& firstToken = range.peek();
- while (range.peek().type() == IdentToken) {
- if (!builder.isEmpty()) {
- builder.append(' ');
- addedSpace = true;
- }
- builder.append(range.consumeIncludingWhitespace().value());
- }
- if (!addedSpace && isCSSWideKeyword(firstToken.id()))
- return String();
- return builder.toString();
-}
-
static RefPtr<CSSValue> consumeFamilyName(CSSParserTokenRange& range)
{
- if (range.peek().type() == StringToken)
- return CSSValuePool::singleton().createFontFamilyValue(range.consumeIncludingWhitespace().value().toString());
- if (range.peek().type() != IdentToken)
- return nullptr;
- String familyName = concatenateFamilyName(range);
+ auto familyName = consumeFamilyNameRaw(range);
if (familyName.isNull())
return nullptr;
return CSSValuePool::singleton().createFontFamilyValue(familyName);
Modified: trunk/Source/WebCore/css/parser/CSSPropertyParser.h (269956 => 269957)
--- trunk/Source/WebCore/css/parser/CSSPropertyParser.h 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParser.h 2020-11-18 16:03:50 UTC (rev 269957)
@@ -23,6 +23,7 @@
#pragma once
#include "CSSParserTokenRange.h"
+#include "CSSPropertyParserHelpers.h"
#include "StyleRule.h"
#include <wtf/text/StringView.h>
Modified: trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp (269956 => 269957)
--- trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp 2020-11-18 16:03:50 UTC (rev 269957)
@@ -130,13 +130,16 @@
Optional<double> consumePercentRaw()
{
- if (!m_calcValue || m_calcValue->category() != CalculationCategory::Percent)
+ if (!m_calcValue)
return WTF::nullopt;
+ auto category = m_calcValue->category();
+ if (category != CalculationCategory::Percent)
+ return WTF::nullopt;
m_sourceRange = m_range;
return m_calcValue->doubleValue();
}
- Optional<Angle> consumeAngleRaw()
+ Optional<AngleRaw> consumeAngleRaw()
{
if (!m_calcValue || m_calcValue->category() != CalculationCategory::Angle)
return WTF::nullopt;
@@ -144,6 +147,33 @@
return { { m_calcValue->primitiveType(), m_calcValue->doubleValue() } };
}
+ Optional<LengthRaw> consumeLengthRaw()
+ {
+ if (!m_calcValue || m_calcValue->category() != CalculationCategory::Length)
+ return WTF::nullopt;
+ m_sourceRange = m_range;
+ return { { m_calcValue->primitiveType(), m_calcValue->doubleValue() } };
+ }
+
+ Optional<LengthOrPercentRaw> consumeLengthOrPercentRaw()
+ {
+ if (!m_calcValue)
+ return WTF::nullopt;
+
+ switch (m_calcValue->category()) {
+ case CalculationCategory::Length:
+ m_sourceRange = m_range;
+ return { LengthRaw({ m_calcValue->primitiveType(), m_calcValue->doubleValue() }) };
+ case CalculationCategory::Percent:
+ case CalculationCategory::PercentLength:
+ case CalculationCategory::PercentNumber:
+ m_sourceRange = m_range;
+ return { { m_calcValue->doubleValue() } };
+ default:
+ return WTF::nullopt;
+ }
+ }
+
private:
CSSParserTokenRange& m_sourceRange;
CSSParserTokenRange m_range;
@@ -177,10 +207,12 @@
return consumeInteger(range, 1);
}
-bool consumeNumberRaw(CSSParserTokenRange& range, double& result)
+bool consumeNumberRaw(CSSParserTokenRange& range, double& result, ValueRange valueRange)
{
const CSSParserToken& token = range.peek();
if (token.type() == NumberToken) {
+ if (valueRange == ValueRangeNonNegative && token.numericValue() < 0)
+ return false;
result = range.consumeIncludingWhitespace().numericValue();
return true;
}
@@ -188,7 +220,7 @@
if (token.type() != FunctionToken)
return false;
- CalcParser calcParser(range, CalculationCategory::Number, ValueRangeAll);
+ CalcParser calcParser(range, CalculationCategory::Number, valueRange);
return calcParser.consumeNumberRaw(result);
}
@@ -196,22 +228,19 @@
RefPtr<CSSPrimitiveValue> consumeNumber(CSSParserTokenRange& range, ValueRange valueRange)
{
const CSSParserToken& token = range.peek();
- if (token.type() == NumberToken) {
- if (valueRange == ValueRangeNonNegative && token.numericValue() < 0)
- return nullptr;
- return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), token.unitType());
+ if (token.type() == FunctionToken) {
+ CalcParser calcParser(range, CalculationCategory::Number, valueRange);
+ if (const auto* calcValue = calcParser.value()) {
+ if (calcValue->category() == CalculationCategory::Number)
+ return calcParser.consumeValue();
+ }
+ return nullptr;
}
- if (token.type() != FunctionToken)
- return nullptr;
+ double number;
+ if (consumeNumberRaw(range, number, valueRange))
+ return CSSValuePool::singleton().createValue(number, token.unitType());
- CalcParser calcParser(range, CalculationCategory::Number, valueRange);
- if (const CSSCalcValue* calcValue = calcParser.value()) {
- if (calcValue->category() != CalculationCategory::Number)
- return nullptr;
- return calcParser.consumeValue();
- }
-
return nullptr;
}
@@ -222,7 +251,7 @@
}
#endif
-RefPtr<CSSPrimitiveValue> consumeFontWeightNumber(CSSParserTokenRange& range)
+Optional<double> consumeFontWeightNumberRaw(CSSParserTokenRange& range)
{
// Values less than or equal to 0 or greater than or equal to 1000 are parse errors.
auto& token = range.peek();
@@ -230,11 +259,15 @@
#if !ENABLE(VARIATION_FONTS)
&& token.numericValueType() == IntegerValueType && divisibleBy100(token.numericValue())
#endif
- )
- return consumeNumber(range, ValueRangeAll);
+ ) {
+ double result;
+ if (consumeNumberRaw(range, result))
+ return result;
+ return WTF::nullopt;
+ }
if (token.type() != FunctionToken)
- return nullptr;
+ return WTF::nullopt;
// "[For calc()], the used value resulting from an _expression_ must be clamped to the range allowed in the target context."
CalcParser calcParser(range, CalculationCategory::Number, ValueRangeAll);
@@ -245,9 +278,16 @@
#endif
) {
result = std::min(std::max(result, std::nextafter(0., 1.)), std::nextafter(1000., 0.));
- return CSSValuePool::singleton().createValue(result, CSSUnitType::CSS_NUMBER);
+ return result;
}
+ return WTF::nullopt;
+}
+
+RefPtr<CSSPrimitiveValue> consumeFontWeightNumber(CSSParserTokenRange& range)
+{
+ if (auto result = consumeFontWeightNumberRaw(range))
+ return CSSValuePool::singleton().createValue(*result, CSSUnitType::CSS_NUMBER);
return nullptr;
}
@@ -259,7 +299,7 @@
|| (cssParserMode == HTMLQuirksMode && unitless == UnitlessQuirk::Allow);
}
-RefPtr<CSSPrimitiveValue> consumeLength(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
+Optional<LengthRaw> consumeLengthRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
{
const CSSParserToken& token = range.peek();
if (token.type() == DimensionToken) {
@@ -266,7 +306,7 @@
switch (token.unitType()) {
case CSSUnitType::CSS_QUIRKY_EMS:
if (cssParserMode != UASheetMode)
- return nullptr;
+ return WTF::nullopt;
FALLTHROUGH;
case CSSUnitType::CSS_EMS:
case CSSUnitType::CSS_REMS:
@@ -287,29 +327,40 @@
case CSSUnitType::CSS_Q:
break;
default:
- return nullptr;
+ return WTF::nullopt;
}
if ((valueRange == ValueRangeNonNegative && token.numericValue() < 0) || std::isinf(token.numericValue()))
- return nullptr;
- return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), token.unitType());
+ return WTF::nullopt;
+ return { { token.unitType(), range.consumeIncludingWhitespace().numericValue() } };
}
if (token.type() == NumberToken) {
if (!shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless)
|| (valueRange == ValueRangeNonNegative && token.numericValue() < 0))
- return nullptr;
+ return WTF::nullopt;
if (std::isinf(token.numericValue()))
- return nullptr;
- CSSUnitType unitType = CSSUnitType::CSS_PX;
- return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), unitType);
+ return WTF::nullopt;
+ return { { CSSUnitType::CSS_PX, range.consumeIncludingWhitespace().numericValue() } };
}
if (token.type() != FunctionToken)
- return nullptr;
+ return WTF::nullopt;
CalcParser calcParser(range, CalculationCategory::Length, valueRange);
- if (calcParser.value() && calcParser.value()->category() == CalculationCategory::Length)
- return calcParser.consumeValue();
+ return calcParser.consumeLengthRaw();
+}
+RefPtr<CSSPrimitiveValue> consumeLength(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
+{
+ const CSSParserToken& token = range.peek();
+ if (token.type() == FunctionToken) {
+ CalcParser calcParser(range, CalculationCategory::Length, valueRange);
+ if (calcParser.value() && calcParser.value()->category() == CalculationCategory::Length)
+ return calcParser.consumeValue();
+ }
+
+ if (auto result = consumeLengthRaw(range, cssParserMode, valueRange, unitless))
+ return CSSValuePool::singleton().createValue(result->value, result->type);
+
return nullptr;
}
@@ -333,7 +384,7 @@
{
const CSSParserToken& token = range.peek();
if (token.type() == FunctionToken) {
- CalcParser calcParser(range, CalculationCategory::Angle, valueRange);
+ CalcParser calcParser(range, CalculationCategory::Percent, valueRange);
if (const CSSCalcValue* calculation = calcParser.value()) {
if (calculation->category() == CalculationCategory::Percent)
return calcParser.consumeValue();
@@ -361,26 +412,54 @@
return false;
}
-RefPtr<CSSPrimitiveValue> consumeLengthOrPercent(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
+Optional<LengthOrPercentRaw> consumeLengthOrPercentRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
{
const CSSParserToken& token = range.peek();
- if (token.type() == DimensionToken || token.type() == NumberToken)
- return consumeLength(range, cssParserMode, valueRange, unitless);
- if (token.type() == PercentageToken)
- return consumePercent(range, valueRange);
+ if (token.type() == DimensionToken || token.type() == NumberToken) {
+ if (auto result = consumeLengthRaw(range, cssParserMode, valueRange, unitless))
+ return { *result };
+ return WTF::nullopt;
+ }
+ if (token.type() == PercentageToken) {
+ if (auto result = consumePercentRaw(range, valueRange))
+ return { *result };
+ return WTF::nullopt;
+ }
if (token.type() != FunctionToken)
- return nullptr;
+ return WTF::nullopt;
CalcParser calcParser(range, CalculationCategory::Length, valueRange);
if (const CSSCalcValue* calculation = calcParser.value()) {
if (canConsumeCalcValue(calculation->category(), cssParserMode))
- return calcParser.consumeValue();
+ return calcParser.consumeLengthOrPercentRaw();
}
+ return WTF::nullopt;
+}
+
+RefPtr<CSSPrimitiveValue> consumeLengthOrPercent(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
+{
+ const CSSParserToken& token = range.peek();
+ if (token.type() == FunctionToken) {
+ CalcParser calcParser(range, CalculationCategory::Length, valueRange);
+ if (const CSSCalcValue* calculation = calcParser.value()) {
+ if (canConsumeCalcValue(calculation->category(), cssParserMode))
+ return calcParser.consumeValue();
+ }
+ return nullptr;
+ }
+
+ if (auto result = consumeLengthOrPercentRaw(range, cssParserMode, valueRange, unitless)) {
+ return switchOn(*result, [] (LengthRaw length) {
+ return CSSValuePool::singleton().createValue(length.value, length.type);
+ }, [] (double percentage) {
+ return CSSValuePool::singleton().createValue(percentage, CSSUnitType::CSS_PERCENTAGE);
+ });
+ }
return nullptr;
}
-Optional<Angle> consumeAngleRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
+Optional<AngleRaw> consumeAngleRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
{
const CSSParserToken& token = range.peek();
if (token.type() == DimensionToken) {
@@ -502,13 +581,27 @@
return nullptr;
}
-RefPtr<CSSPrimitiveValue> consumeIdent(CSSParserTokenRange& range)
+Optional<CSSValueID> consumeIdentRaw(CSSParserTokenRange& range)
{
if (range.peek().type() != IdentToken)
- return nullptr;
- return CSSValuePool::singleton().createIdentifierValue(range.consumeIncludingWhitespace().id());
+ return WTF::nullopt;
+ return range.consumeIncludingWhitespace().id();
}
+RefPtr<CSSPrimitiveValue> consumeIdent(CSSParserTokenRange& range)
+{
+ if (auto result = consumeIdentRaw(range))
+ return CSSValuePool::singleton().createIdentifierValue(*result);
+ return nullptr;
+}
+
+Optional<CSSValueID> consumeIdentRangeRaw(CSSParserTokenRange& range, CSSValueID lower, CSSValueID upper)
+{
+ if (range.peek().id() < lower || range.peek().id() > upper)
+ return WTF::nullopt;
+ return consumeIdentRaw(range);
+}
+
RefPtr<CSSPrimitiveValue> consumeIdentRange(CSSParserTokenRange& range, CSSValueID lower, CSSValueID upper)
{
if (range.peek().id() < lower || range.peek().id() > upper)
@@ -1818,6 +1911,225 @@
return nullptr;
}
+Optional<CSSValueID> consumeFontVariantCSS21Raw(CSSParserTokenRange& range)
+{
+ return consumeIdentRaw<CSSValueNormal, CSSValueSmallCaps>(range);
+}
+
+Optional<CSSValueID> consumeFontWeightKeywordValueRaw(CSSParserTokenRange& range)
+{
+ return consumeIdentRaw<CSSValueNormal, CSSValueBold, CSSValueBolder, CSSValueLighter>(range);
+}
+
+Optional<FontWeightRaw> consumeFontWeightRaw(CSSParserTokenRange& range)
+{
+ if (auto result = consumeFontWeightKeywordValueRaw(range))
+ return { *result };
+ if (auto result = consumeFontWeightNumberRaw(range))
+ return { *result };
+ return WTF::nullopt;
+}
+
+Optional<CSSValueID> consumeFontStretchKeywordValueRaw(CSSParserTokenRange& range)
+{
+ return consumeIdentRaw<CSSValueUltraCondensed, CSSValueExtraCondensed, CSSValueCondensed, CSSValueSemiCondensed, CSSValueNormal, CSSValueSemiExpanded, CSSValueExpanded, CSSValueExtraExpanded, CSSValueUltraExpanded>(range);
+}
+
+Optional<CSSValueID> consumeFontStyleKeywordValueRaw(CSSParserTokenRange& range)
+{
+ return consumeIdentRaw<CSSValueNormal, CSSValueItalic, CSSValueOblique>(range);
+}
+
+Optional<FontStyleRaw> consumeFontStyleRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+{
+ auto result = consumeFontStyleKeywordValueRaw(range);
+ if (!result)
+ return WTF::nullopt;
+
+ auto ident = *result;
+ if (ident == CSSValueNormal || ident == CSSValueItalic)
+ return { { ident, WTF::nullopt } };
+ ASSERT(ident == CSSValueOblique);
+#if ENABLE(VARIATION_FONTS)
+ if (!range.atEnd()) {
+ if (auto angle = consumeAngleRaw(range, cssParserMode)) {
+ auto angleInDegrees = CSSPrimitiveValue::computeDegrees(angle->type, angle->value);
+ if (fontStyleIsWithinRange(angleInDegrees))
+ return { { CSSValueOblique, WTFMove(angle) } };
+ return WTF::nullopt;
+ }
+ }
+#else
+ UNUSED_PARAM(cssParserMode);
+#endif
+ return { { CSSValueOblique, WTF::nullopt } };
+}
+
+String concatenateFamilyName(CSSParserTokenRange& range)
+{
+ StringBuilder builder;
+ bool addedSpace = false;
+ const CSSParserToken& firstToken = range.peek();
+ while (range.peek().type() == IdentToken) {
+ if (!builder.isEmpty()) {
+ builder.append(' ');
+ addedSpace = true;
+ }
+ builder.append(range.consumeIncludingWhitespace().value());
+ }
+ if (!addedSpace && isCSSWideKeyword(firstToken.id()))
+ return String();
+ return builder.toString();
+}
+
+String consumeFamilyNameRaw(CSSParserTokenRange& range)
+{
+ if (range.peek().type() == StringToken)
+ return range.consumeIncludingWhitespace().value().toString();
+ if (range.peek().type() != IdentToken)
+ return String();
+ return concatenateFamilyName(range);
+}
+
+Optional<CSSValueID> consumeGenericFamilyRaw(CSSParserTokenRange& range)
+{
+ return consumeIdentRangeRaw(range, CSSValueSerif, CSSValueWebkitBody);
+}
+
+Optional<WTF::Vector<FontFamilyRaw>> consumeFontFamilyRaw(CSSParserTokenRange& range)
+{
+ WTF::Vector<FontFamilyRaw> list;
+ do {
+ if (auto ident = consumeGenericFamilyRaw(range))
+ list.append({ *ident });
+ else {
+ auto familyName = consumeFamilyNameRaw(range);
+ if (familyName.isNull())
+ return WTF::nullopt;
+ list.append({ familyName });
+ }
+ } while (consumeCommaIncludingWhitespace(range));
+ return list;
+}
+
+Optional<FontSizeRaw> consumeFontSizeRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
+{
+ if (range.peek().id() >= CSSValueXxSmall && range.peek().id() <= CSSValueLarger) {
+ if (auto ident = consumeIdentRaw(range))
+ return { *ident };
+ return WTF::nullopt;
+ }
+
+ if (auto result = consumeLengthOrPercentRaw(range, cssParserMode, ValueRangeNonNegative, unitless))
+ return { *result };
+
+ return WTF::nullopt;
+}
+
+Optional<LineHeightRaw> consumeLineHeightRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+{
+ if (range.peek().id() == CSSValueNormal) {
+ if (auto ident = consumeIdentRaw(range))
+ return { *ident };
+ return WTF::nullopt;
+ }
+
+ double number;
+ if (consumeNumberRaw(range, number, ValueRangeNonNegative))
+ return { number };
+
+ if (auto lengthOrPercent = consumeLengthOrPercentRaw(range, cssParserMode, ValueRangeNonNegative))
+ return { *lengthOrPercent };
+
+ return WTF::nullopt;
+}
+
+Optional<FontRaw> consumeFontWorkerSafe(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+{
+ // Let's check if there is an inherit or initial somewhere in the shorthand.
+ CSSParserTokenRange rangeCopy = range;
+ while (!rangeCopy.atEnd()) {
+ CSSValueID id = rangeCopy.consumeIncludingWhitespace().id();
+ if (id == CSSValueInherit || id == CSSValueInitial)
+ return WTF::nullopt;
+ }
+
+ FontRaw result;
+
+ while (!range.atEnd()) {
+ CSSValueID id = range.peek().id();
+ if (!result.style) {
+ if ((result.style = consumeFontStyleRaw(range, cssParserMode)))
+ continue;
+ }
+ if (!result.variantCaps && (id == CSSValueNormal || id == CSSValueSmallCaps)) {
+ // Font variant in the shorthand is particular, it only accepts normal or small-caps.
+ // See https://drafts.csswg.org/css-fonts/#propdef-font
+ if ((result.variantCaps = consumeFontVariantCSS21Raw(range)))
+ continue;
+ }
+ if (!result.weight) {
+ if ((result.weight = consumeFontWeightRaw(range)))
+ continue;
+ }
+ if (!result.stretch) {
+ if ((result.stretch = consumeFontStretchKeywordValueRaw(range)))
+ continue;
+ }
+ break;
+ }
+
+ if (range.atEnd())
+ return WTF::nullopt;
+
+ // Now a font size _must_ come.
+ if (auto size = consumeFontSizeRaw(range, cssParserMode))
+ result.size = *size;
+ else
+ return WTF::nullopt;
+
+ if (range.atEnd())
+ return WTF::nullopt;
+
+ if (consumeSlashIncludingWhitespace(range)) {
+ if (!(result.lineHeight = consumeLineHeightRaw(range, cssParserMode)))
+ return WTF::nullopt;
+ }
+
+ // Font family must come now.
+ if (auto family = consumeFontFamilyRaw(range))
+ result.family = *family;
+ else
+ return WTF::nullopt;
+
+ if (!range.atEnd())
+ return WTF::nullopt;
+
+ return result;
+}
+
+const AtomString& genericFontFamilyFromValueID(CSSValueID ident)
+{
+ switch (ident) {
+ case CSSValueSerif:
+ return serifFamily.get();
+ case CSSValueSansSerif:
+ return sansSerifFamily.get();
+ case CSSValueCursive:
+ return cursiveFamily.get();
+ case CSSValueFantasy:
+ return fantasyFamily.get();
+ case CSSValueMonospace:
+ return monospaceFamily.get();
+ case CSSValueWebkitPictograph:
+ return pictographFamily.get();
+ case CSSValueSystemUi:
+ return systemUiFamily.get();
+ default:
+ return emptyAtom();
+ }
+}
+
} // namespace CSSPropertyParserHelpers
} // namespace WebCore
Modified: trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.h (269956 => 269957)
--- trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.h 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.h 2020-11-18 16:03:50 UTC (rev 269957)
@@ -37,6 +37,8 @@
#include "CSSValuePool.h"
#include "Length.h" // For ValueRange
#include <wtf/OptionSet.h>
+#include <wtf/Variant.h>
+#include <wtf/Vector.h>
namespace WebCore {
@@ -55,28 +57,41 @@
enum class UnitlessQuirk { Allow, Forbid };
enum class AllowXResolutionUnit { Allow, Forbid };
-struct Angle {
+struct AngleRaw {
CSSUnitType type;
double value;
};
+struct LengthRaw {
+ CSSUnitType type;
+ double value;
+};
+
+using LengthOrPercentRaw = WTF::Variant<LengthRaw, double>;
+
RefPtr<CSSPrimitiveValue> consumeInteger(CSSParserTokenRange&, double minimumValue = -std::numeric_limits<double>::max());
RefPtr<CSSPrimitiveValue> consumePositiveInteger(CSSParserTokenRange&);
-bool consumeNumberRaw(CSSParserTokenRange&, double& result);
+bool consumeNumberRaw(CSSParserTokenRange&, double& result, ValueRange = ValueRangeAll);
RefPtr<CSSPrimitiveValue> consumeNumber(CSSParserTokenRange&, ValueRange);
+Optional<double> consumeFontWeightNumberRaw(CSSParserTokenRange&);
RefPtr<CSSPrimitiveValue> consumeFontWeightNumber(CSSParserTokenRange&);
+Optional<LengthRaw> consumeLengthRaw(CSSParserTokenRange&, CSSParserMode, ValueRange, UnitlessQuirk = UnitlessQuirk::Forbid);
RefPtr<CSSPrimitiveValue> consumeLength(CSSParserTokenRange&, CSSParserMode, ValueRange, UnitlessQuirk = UnitlessQuirk::Forbid);
Optional<double> consumePercentRaw(CSSParserTokenRange&, ValueRange = ValueRangeAll);
RefPtr<CSSPrimitiveValue> consumePercent(CSSParserTokenRange&, ValueRange);
+Optional<LengthOrPercentRaw> consumeLengthOrPercentRaw(CSSParserTokenRange&, CSSParserMode, ValueRange, UnitlessQuirk = UnitlessQuirk::Forbid);
RefPtr<CSSPrimitiveValue> consumeLengthOrPercent(CSSParserTokenRange&, CSSParserMode, ValueRange, UnitlessQuirk = UnitlessQuirk::Forbid);
-Optional<Angle> consumeAngleRaw(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk);
+Optional<AngleRaw> consumeAngleRaw(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk = UnitlessQuirk::Forbid);
RefPtr<CSSPrimitiveValue> consumeAngle(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk = UnitlessQuirk::Forbid);
RefPtr<CSSPrimitiveValue> consumeTime(CSSParserTokenRange&, CSSParserMode, ValueRange, UnitlessQuirk = UnitlessQuirk::Forbid);
RefPtr<CSSPrimitiveValue> consumeResolution(CSSParserTokenRange&, AllowXResolutionUnit = AllowXResolutionUnit::Forbid);
+Optional<CSSValueID> consumeIdentRaw(CSSParserTokenRange&);
RefPtr<CSSPrimitiveValue> consumeIdent(CSSParserTokenRange&);
+Optional<CSSValueID> consumeIdentRangeRaw(CSSParserTokenRange&, CSSValueID lower, CSSValueID upper);
RefPtr<CSSPrimitiveValue> consumeIdentRange(CSSParserTokenRange&, CSSValueID lower, CSSValueID upper);
template<CSSValueID, CSSValueID...> inline bool identMatches(CSSValueID id);
+template<CSSValueID... allowedIdents> Optional<CSSValueID> consumeIdentRaw(CSSParserTokenRange&);
template<CSSValueID... allowedIdents> RefPtr<CSSPrimitiveValue> consumeIdent(CSSParserTokenRange&);
RefPtr<CSSPrimitiveValue> consumeCustomIdent(CSSParserTokenRange&);
@@ -115,6 +130,40 @@
RefPtr<CSSValue> consumeFilter(CSSParserTokenRange&, const CSSParserContext&, AllowedFilterFunctions);
RefPtr<CSSShadowValue> consumeSingleShadow(CSSParserTokenRange&, CSSParserMode, bool allowInset, bool allowSpread);
+struct FontStyleRaw {
+ CSSValueID style;
+ Optional<AngleRaw> angle;
+};
+using FontWeightRaw = WTF::Variant<CSSValueID, double>;
+using FontSizeRaw = WTF::Variant<CSSValueID, CSSPropertyParserHelpers::LengthOrPercentRaw>;
+using LineHeightRaw = WTF::Variant<CSSValueID, double, CSSPropertyParserHelpers::LengthOrPercentRaw>;
+using FontFamilyRaw = WTF::Variant<CSSValueID, String>;
+
+struct FontRaw {
+ Optional<FontStyleRaw> style;
+ Optional<CSSValueID> variantCaps;
+ Optional<FontWeightRaw> weight;
+ Optional<CSSValueID> stretch;
+ FontSizeRaw size;
+ Optional<LineHeightRaw> lineHeight;
+ WTF::Vector<FontFamilyRaw> family;
+};
+
+Optional<CSSValueID> consumeFontVariantCSS21Raw(CSSParserTokenRange&);
+Optional<CSSValueID> consumeFontWeightKeywordValueRaw(CSSParserTokenRange&);
+Optional<FontWeightRaw> consumeFontWeightRaw(CSSParserTokenRange&);
+Optional<CSSValueID> consumeFontStretchKeywordValueRaw(CSSParserTokenRange&);
+Optional<CSSValueID> consumeFontStyleKeywordValueRaw(CSSParserTokenRange&);
+Optional<FontStyleRaw> consumeFontStyleRaw(CSSParserTokenRange&, CSSParserMode);
+String concatenateFamilyName(CSSParserTokenRange&);
+String consumeFamilyNameRaw(CSSParserTokenRange&);
+Optional<CSSValueID> consumeGenericFamilyRaw(CSSParserTokenRange&);
+Optional<WTF::Vector<FontFamilyRaw>> consumeFontFamilyRaw(CSSParserTokenRange&);
+Optional<FontSizeRaw> consumeFontSizeRaw(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk = UnitlessQuirk::Forbid);
+Optional<LineHeightRaw> consumeLineHeightRaw(CSSParserTokenRange&, CSSParserMode);
+Optional<FontRaw> consumeFontWorkerSafe(CSSParserTokenRange&, CSSParserMode);
+const AtomString& genericFontFamilyFromValueID(CSSValueID);
+
// Template implementations are at the bottom of the file for readability.
template<typename... emptyBaseCase> inline bool identMatches(CSSValueID) { return false; }
@@ -123,6 +172,13 @@
return id == head || identMatches<tail...>(id);
}
+template<CSSValueID... names> Optional<CSSValueID> consumeIdentRaw(CSSParserTokenRange& range)
+{
+ if (range.peek().type() != IdentToken || !identMatches<names...>(range.peek().id()))
+ return WTF::nullopt;
+ return range.consumeIncludingWhitespace().id();
+}
+
template<CSSValueID... names> RefPtr<CSSPrimitiveValue> consumeIdent(CSSParserTokenRange& range)
{
if (range.peek().type() != IdentToken || !identMatches<names...>(range.peek().id()))
Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp (269956 => 269957)
--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp 2020-11-18 16:03:50 UTC (rev 269957)
@@ -36,16 +36,21 @@
#include "CSSFontSelector.h"
#include "CSSParser.h"
#include "CSSPropertyNames.h"
+#include "CSSPropertyParserHelpers.h"
#include "Gradient.h"
#include "ImageBuffer.h"
#include "ImageData.h"
#include "InspectorInstrumentation.h"
+#include "NodeRenderStyle.h"
#include "Path2D.h"
#include "RenderTheme.h"
#include "ResourceLoadObserver.h"
#include "RuntimeEnabledFeatures.h"
+#include "Settings.h"
#include "StyleBuilder.h"
+#include "StyleFontSizeFunctions.h"
#include "StyleProperties.h"
+#include "StyleResolveForFontRaw.h"
#include "TextMetrics.h"
#include "TextRun.h"
#include <wtf/CheckedArithmetic.h>
@@ -134,16 +139,10 @@
if (newFont == state().unparsedFont && state().font.realized())
return;
- auto parsedStyle = MutableStyleProperties::create();
- CSSParser::parseValue(parsedStyle, CSSPropertyFont, newFont, true, strictToCSSParserMode(!m_usesCSSCompatibilityParseMode));
- if (parsedStyle->isEmpty())
- return;
-
- String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont);
-
// According to http://lists.w3.org/Archives/Public/public-html/2009Jul/0947.html,
- // the "inherit" and "initial" values must be ignored.
- if (fontValue == "inherit" || fontValue == "initial")
+ // the "inherit" and "initial" values must be ignored. parseFontWorkerSafe() ignores these.
+ auto fontRaw = CSSParser::parseFontWorkerSafe(newFont, strictToCSSParserMode(!m_usesCSSCompatibilityParseMode));
+ if (!fontRaw)
return;
// The parse succeeded.
@@ -153,38 +152,20 @@
// Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work
// relative to the canvas.
- auto newStyle = RenderStyle::createPtr();
-
Document& document = canvas().document();
document.updateStyleIfNeeded();
+ FontCascadeDescription fontDescription;
if (auto* computedStyle = canvas().computedStyle())
- newStyle->setFontDescription(FontCascadeDescription { computedStyle->fontDescription() });
+ fontDescription = FontCascadeDescription { computedStyle->fontDescription() };
else {
- FontCascadeDescription defaultFontDescription;
- defaultFontDescription.setOneFamily(DefaultFontFamily);
- defaultFontDescription.setSpecifiedSize(DefaultFontSize);
- defaultFontDescription.setComputedSize(DefaultFontSize);
-
- newStyle->setFontDescription(WTFMove(defaultFontDescription));
+ fontDescription.setOneFamily(DefaultFontFamily);
+ fontDescription.setSpecifiedSize(DefaultFontSize);
+ fontDescription.setComputedSize(DefaultFontSize);
}
- newStyle->fontCascade().update(&document.fontSelector());
-
- // Now map the font property longhands into the style.
-
- Style::MatchResult matchResult;
- auto parentStyle = RenderStyle::clone(*newStyle);
- Style::Builder styleBuilder(*newStyle, { document, parentStyle }, matchResult, { });
-
- styleBuilder.applyPropertyValue(CSSPropertyFontFamily, parsedStyle->getPropertyCSSValue(CSSPropertyFontFamily).get());
- styleBuilder.applyPropertyValue(CSSPropertyFontStyle, parsedStyle->getPropertyCSSValue(CSSPropertyFontStyle).get());
- styleBuilder.applyPropertyValue(CSSPropertyFontVariantCaps, parsedStyle->getPropertyCSSValue(CSSPropertyFontVariantCaps).get());
- styleBuilder.applyPropertyValue(CSSPropertyFontWeight, parsedStyle->getPropertyCSSValue(CSSPropertyFontWeight).get());
- styleBuilder.applyPropertyValue(CSSPropertyFontSize, parsedStyle->getPropertyCSSValue(CSSPropertyFontSize).get());
- styleBuilder.applyPropertyValue(CSSPropertyLineHeight, parsedStyle->getPropertyCSSValue(CSSPropertyLineHeight).get());
-
- modifiableState().font.initialize(document.fontSelector(), *newStyle);
+ if (auto fontStyle = Style::resolveForFontRaw(*fontRaw, WTFMove(fontDescription), document))
+ modifiableState().font.initialize(document.fontSelector(), *fontStyle);
}
static CanvasTextAlign toCanvasTextAlign(TextAlign textAlign)
Modified: trunk/Source/WebCore/style/StyleBuilderCustom.h (269956 => 269957)
--- trunk/Source/WebCore/style/StyleBuilderCustom.h 2020-11-18 15:36:33 UTC (rev 269956)
+++ trunk/Source/WebCore/style/StyleBuilderCustom.h 2020-11-18 16:03:50 UTC (rev 269957)
@@ -31,6 +31,7 @@
#include "CSSFontValue.h"
#include "CSSGradientValue.h"
#include "CSSGridTemplateAreasValue.h"
+#include "CSSPropertyParserHelpers.h"
#include "CSSRegisteredCustomProperty.h"
#include "CSSShadowValue.h"
#include "Counter.h"
@@ -1012,40 +1013,11 @@
// If the family name was resolved by the CSS parser from a system font ID, then it is generic.
isGenericFamily = fontFamily.fromSystemFontID;
} else {
- switch (contentValue.valueID()) {
- case CSSValueWebkitBody:
+ if (contentValue.valueID() == CSSValueWebkitBody)
family = builderState.document().settings().standardFontFamily();
- break;
- case CSSValueSerif:
- family = serifFamily;
+ else {
isGenericFamily = true;
- break;
- case CSSValueSansSerif:
- family = sansSerifFamily;
- isGenericFamily = true;
- break;
- case CSSValueCursive:
- family = cursiveFamily;
- isGenericFamily = true;
- break;
- case CSSValueFantasy:
- family = fantasyFamily;
- isGenericFamily = true;
- break;
- case CSSValueMonospace:
- family = monospaceFamily;
- isGenericFamily = true;
- break;
- case CSSValueWebkitPictograph:
- family = pictographFamily;
- isGenericFamily = true;
- break;
- case CSSValueSystemUi:
- family = systemUiFamily;
- isGenericFamily = true;
- break;
- default:
- break;
+ family = CSSPropertyParserHelpers::genericFontFamilyFromValueID(contentValue.valueID());
}
}
Added: trunk/Source/WebCore/style/StyleResolveForFontRaw.cpp (0 => 269957)
--- trunk/Source/WebCore/style/StyleResolveForFontRaw.cpp (rev 0)
+++ trunk/Source/WebCore/style/StyleResolveForFontRaw.cpp 2020-11-18 16:03:50 UTC (rev 269957)
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2020 Metrological Group B.V.
+ * Copyright (C) 2020 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StyleResolveForFontRaw.h"
+
+#include "CSSFontSelector.h"
+#include "CSSPropertyParserHelpers.h"
+#include "Document.h"
+#include "FontCascadeDescription.h"
+#include "RenderStyle.h"
+#include "StyleFontSizeFunctions.h"
+
+namespace WebCore {
+
+namespace Style {
+
+using namespace CSSPropertyParserHelpers;
+
+Optional<RenderStyle> resolveForFontRaw(const FontRaw& fontRaw, FontCascadeDescription&& fontDescription, Document& document)
+{
+ auto fontStyle = RenderStyle::create();
+
+ auto getParentStyle = [&] () -> std::unique_ptr<RenderStyle> {
+ auto parentStyle = RenderStyle::clonePtr(fontStyle);
+ parentStyle->setFontDescription(FontCascadeDescription(fontDescription));
+ parentStyle->fontCascade().update(&document.fontSelector());
+ return parentStyle;
+ };
+
+ // Map the font property longhands into the style.
+ float parentSize = fontDescription.specifiedSize();
+
+ // Font family applied in the same way as StyleBuilderCustom::applyValueFontFamily
+ // Before mapping in a new font-family property, we should reset the generic family.
+ bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
+
+ Vector<AtomString> families;
+ families.reserveInitialCapacity(fontRaw.family.size());
+
+ for (auto& item : fontRaw.family) {
+ AtomString family;
+ bool isGenericFamily = false;
+ switchOn(item, [&] (CSSValueID ident) {
+ isGenericFamily = ident != CSSValueWebkitBody;
+ family = isGenericFamily ? CSSPropertyParserHelpers::genericFontFamilyFromValueID(ident)
+ : document.settings().standardFontFamily();
+ }, [&] (const String& familyString) {
+ family = familyString;
+ });
+
+ if (family.isEmpty())
+ continue;
+ if (families.isEmpty())
+ fontDescription.setIsSpecifiedFont(!isGenericFamily);
+ families.uncheckedAppend(family);
+ }
+
+ if (families.isEmpty())
+ return WTF::nullopt;
+ fontDescription.setFamilies(families);
+
+ if (fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize) {
+ if (CSSValueID sizeIdentifier = fontDescription.keywordSizeAsIdentifier()) {
+ auto size = Style::fontSizeForKeyword(sizeIdentifier, !oldFamilyUsedFixedDefaultSize, document);
+ fontDescription.setSpecifiedSize(size);
+ fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(size, fontDescription.isAbsoluteSize(), false, &fontStyle, document));
+ }
+ }
+
+ // Font style applied in the same way as BuilderConverter::convertFontStyleFromValue
+ if (fontRaw.style) {
+ switch (fontRaw.style->style) {
+ case CSSValueNormal:
+ break;
+
+ case CSSValueItalic:
+ fontDescription.setItalic(italicValue());
+ break;
+
+ case CSSValueOblique: {
+ float degrees;
+ if (fontRaw.style->angle)
+ degrees = static_cast<float>(CSSPrimitiveValue::computeDegrees(fontRaw.style->angle->type, fontRaw.style->angle->value));
+ else
+ degrees = 0;
+ fontDescription.setItalic(FontSelectionValue(degrees));
+ break;
+ }
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+ fontDescription.setFontStyleAxis((fontRaw.style && fontRaw.style->style == CSSValueItalic) ? FontStyleAxis::ital : FontStyleAxis::slnt);
+
+ if (fontRaw.variantCaps) {
+ switch (*fontRaw.variantCaps) {
+ case CSSValueNormal:
+ fontDescription.setVariantCaps(FontVariantCaps::Normal);
+ break;
+ case CSSValueSmallCaps:
+ fontDescription.setVariantCaps(FontVariantCaps::Small);
+ break;
+ case CSSValueAllSmallCaps:
+ fontDescription.setVariantCaps(FontVariantCaps::AllSmall);
+ break;
+ case CSSValuePetiteCaps:
+ fontDescription.setVariantCaps(FontVariantCaps::Petite);
+ break;
+ case CSSValueAllPetiteCaps:
+ fontDescription.setVariantCaps(FontVariantCaps::AllPetite);
+ break;
+ case CSSValueUnicase:
+ fontDescription.setVariantCaps(FontVariantCaps::Unicase);
+ break;
+ case CSSValueTitlingCaps:
+ fontDescription.setVariantCaps(FontVariantCaps::Titling);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ if (fontRaw.weight) {
+ auto weight = switchOn(*fontRaw.weight, [&] (CSSValueID ident) {
+ switch (ident) {
+ case CSSValueNormal:
+ return normalWeightValue();
+ case CSSValueBold:
+ return boldWeightValue();
+ case CSSValueBolder:
+ return FontCascadeDescription::bolderWeight(fontDescription.weight());
+ case CSSValueLighter:
+ return FontCascadeDescription::lighterWeight(fontDescription.weight());
+ default:
+ ASSERT_NOT_REACHED();
+ return normalWeightValue();
+ }
+ }, [&] (double weight) {
+ return FontSelectionValue::clampFloat(weight);
+ });
+ fontDescription.setWeight(weight);
+ }
+
+ fontDescription.setKeywordSizeFromIdentifier(CSSValueInvalid);
+ float size = switchOn(fontRaw.size, [&] (CSSValueID ident) {
+ switch (ident) {
+ case CSSValueXxSmall:
+ case CSSValueXSmall:
+ case CSSValueSmall:
+ case CSSValueMedium:
+ case CSSValueLarge:
+ case CSSValueXLarge:
+ case CSSValueXxLarge:
+ case CSSValueWebkitXxxLarge:
+ fontDescription.setKeywordSizeFromIdentifier(ident);
+ return Style::fontSizeForKeyword(ident, fontDescription.useFixedDefaultSize(), document);
+ case CSSValueLarger:
+ return parentSize * 1.2f;
+ case CSSValueSmaller:
+ return parentSize / 1.2f;
+ default:
+ return 0.f;
+ }
+ }, [&] (const CSSPropertyParserHelpers::LengthOrPercentRaw& lengthOrPercent) {
+ return switchOn(lengthOrPercent, [&] (const CSSPropertyParserHelpers::LengthRaw& length) {
+ auto parentStyle = getParentStyle();
+ CSSToLengthConversionData conversionData { parentStyle.get(), nullptr, parentStyle.get(), document.renderView(), 1.0f, CSSPropertyFontSize };
+ return static_cast<float>(CSSPrimitiveValue::computeNonCalcLengthDouble(conversionData, length.type, length.value));
+ }, [&] (double percentage) {
+ return static_cast<float>((parentSize * percentage) / 100.0);
+ });
+ });
+
+ if (size > 0) {
+ fontDescription.setSpecifiedSize(size);
+ fontDescription.setComputedSize(size);
+ }
+
+ if (fontRaw.lineHeight) {
+ Optional<Length> lineHeight = switchOn(*fontRaw.lineHeight, [&] (CSSValueID ident) {
+ if (ident == CSSValueNormal)
+ return Optional<Length>(RenderStyle::initialLineHeight());
+ return Optional<Length>(WTF::nullopt);
+ }, [&] (double number) {
+ return Optional<Length>(Length(number * 100.0, Percent));
+ }, [&] (const CSSPropertyParserHelpers::LengthOrPercentRaw& lengthOrPercent) {
+ return switchOn(lengthOrPercent, [&] (const CSSPropertyParserHelpers::LengthRaw& length) {
+ auto parentStyle = getParentStyle();
+ CSSToLengthConversionData conversionData { parentStyle.get(), nullptr, parentStyle.get(), document.renderView(), 1.0f, CSSPropertyLineHeight };
+ return Optional<Length>(Length(clampTo<float>(CSSPrimitiveValue::computeNonCalcLengthDouble(conversionData, length.type, length.value), minValueForCssLength, maxValueForCssLength), Fixed));
+ }, [&] (double percentage) {
+ return Optional<Length>(Length((fontDescription.computedSize() * static_cast<int>(percentage)) / 100, Fixed));
+ });
+ });
+
+ if (lineHeight)
+ fontStyle.setLineHeight(WTFMove(lineHeight.value()));
+ }
+
+ fontStyle.setFontDescription(WTFMove(fontDescription));
+ fontStyle.fontCascade().update(&document.fontSelector());
+
+ return fontStyle;
+}
+
+}
+}
Added: trunk/Source/WebCore/style/StyleResolveForFontRaw.h (0 => 269957)
--- trunk/Source/WebCore/style/StyleResolveForFontRaw.h (rev 0)
+++ trunk/Source/WebCore/style/StyleResolveForFontRaw.h 2020-11-18 16:03:50 UTC (rev 269957)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 Metrological Group B.V.
+ * Copyright (C) 2020 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/OptionSet.h>
+
+namespace WebCore {
+
+class Document;
+class RenderStyle;
+
+namespace CSSPropertyParserHelpers {
+struct FontRaw;
+}
+
+namespace Style {
+
+Optional<RenderStyle> resolveForFontRaw(const CSSPropertyParserHelpers::FontRaw&, FontCascadeDescription&&, Document&);
+
+}
+}