Changeset 273127 in webkit
- Timestamp:
- Feb 18, 2021 9:51:08 PM (17 months ago)
- Location:
- trunk
- Files:
-
- 2 added
- 8 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/css/parsing-relative-color-syntax-expected.txt (added)
-
LayoutTests/fast/css/parsing-relative-color-syntax.html (added)
-
Source/WTF/ChangeLog (modified) (1 diff)
-
Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml (modified) (2 diffs)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/css/CSSValueKeywords.in (modified) (1 diff)
-
Source/WebCore/css/parser/CSSParserContext.cpp (modified) (2 diffs)
-
Source/WebCore/css/parser/CSSParserContext.h (modified) (2 diffs)
-
Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r273124 r273127 1 2021-02-18 Sam Weinig <weinig@apple.com> 2 3 Add experimental support for CSS Color 5 Relative Color Syntax 4 https://bugs.webkit.org/show_bug.cgi?id=221880 5 6 Reviewed by Darin Adler. 7 8 * fast/css/parsing-relative-color-syntax-expected.txt: Added. 9 * fast/css/parsing-relative-color-syntax.html: Added. 10 Add basic parsing and computed style computation tests for relative color syntax. 11 1 12 2021-02-18 Lauro Moura <lmoura@igalia.com> 2 13 -
trunk/Source/WTF/ChangeLog
r273085 r273127 1 2021-02-18 Sam Weinig <weinig@apple.com> 2 3 Add experimental support for CSS Color 5 Relative Color Syntax 4 https://bugs.webkit.org/show_bug.cgi?id=221880 5 6 Reviewed by Darin Adler. 7 8 * Scripts/Preferences/WebPreferencesExperimental.yaml: 9 Add new experimental preference for CSS Color 5 Relative Color Syntax 10 which is off by default. 11 1 12 2021-02-18 Youenn Fablet <youenn@apple.com> 2 13 -
trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml
r272983 r273127 1 # Copyright (c) 2020 Apple Inc. All rights reserved.1 # Copyright (c) 2020-2021 Apple Inc. All rights reserved. 2 2 # 3 3 # Redistribution and use in source and binary forms, with or without … … 164 164 default: false 165 165 166 CSSRelativeColorSyntaxEnabled: 167 type: bool 168 humanReadableName: "CSS Relative Color Syntax" 169 humanReadableDescription: "Enable support for CSS Relative Color Syntax defined in CSS Color 5" 170 defaultValue: 171 WebKitLegacy: 172 default: false 173 WebKit: 174 default: false 175 WebCore: 176 default: false 177 166 178 CSSTypedOMEnabled: 167 179 type: bool -
trunk/Source/WebCore/ChangeLog
r273121 r273127 1 2021-02-18 Sam Weinig <weinig@apple.com> 2 3 Add experimental support for CSS Color 5 Relative Color Syntax 4 https://bugs.webkit.org/show_bug.cgi?id=221880 5 6 Reviewed by Darin Adler. 7 8 Adds initial support for CSS Color 5 Relative Color Syntax - https://drafts.csswg.org/css-color-5/#relative-colors 9 10 This feature is off by default and can be enabled via the CSSRelativeColorSyntaxEnabled 11 experimental preference flag. 12 13 As this is the initial commit for this functionality, it is not yet complete. 14 This adds basic parsing and resolution for relative rgb(), hsl(), hwb(), lab() 15 and lch(), but does not yet implement support for calc() functions that can operate 16 on the channel keywords nor does it support using system keyword colors as the 17 origin of the relative colors. 18 19 Some additional caveats about this initial implementation that need further 20 clarification from the spec editors: 21 22 1. Currently, we only allow using the channel corresponding to to the position of that channel 23 in the replacement syntax. This means you can't do: 24 25 rgb(from red g r b) 26 27 to permute the channels. 28 29 2. For rgb(), which allows r, g, and b to be all numbers or all percentages, 30 we currently don't assume either number or percentage, and wait until some 31 constant value is provided to set the type. That means that: 32 33 rgb(from red r g 10) 34 35 will treat r, ang g as numbers, but: 36 37 rgb(from red r g 10%) 38 39 will treat r and g as percentages. This is not currently observable other than 40 that we reject something that mixes the two, such as 41 42 rgb(from red r 10 10%) 43 44 but will be fully observable once processing the channels via calc() is supported. 45 46 Test: fast/css/parsing-relative-color-syntax.html 47 48 * css/CSSValueKeywords.in: 49 * css/parser/CSSParserContext.cpp: 50 (WebCore::operator==): 51 * css/parser/CSSParserContext.h: 52 (WebCore::CSSParserContextHash::hash): 53 * css/parser/CSSPropertyParserHelpers.cpp: 54 (WebCore::CSSPropertyParserHelpers::consumeOriginColor): 55 (WebCore::CSSPropertyParserHelpers::consumeOptionalAlphaOrIdent): 56 (WebCore::CSSPropertyParserHelpers::consumeHueOrIdent): 57 (WebCore::CSSPropertyParserHelpers::consumeNumberOrIdent): 58 (WebCore::CSSPropertyParserHelpers::consumePercentOrIdent): 59 (WebCore::CSSPropertyParserHelpers::extractChannelValue): 60 (WebCore::CSSPropertyParserHelpers::resolveRelativeColorChannel): 61 (WebCore::CSSPropertyParserHelpers::consumeRelativeRGBComponent): 62 (WebCore::CSSPropertyParserHelpers::parseRelativeRGBParameters): 63 (WebCore::CSSPropertyParserHelpers::parseRGBParameters): 64 (WebCore::CSSPropertyParserHelpers::parseRelativeHSLParameters): 65 (WebCore::CSSPropertyParserHelpers::parseHSLParameters): 66 (WebCore::CSSPropertyParserHelpers::normalizeWhitenessBlackness): 67 (WebCore::CSSPropertyParserHelpers::parseRelativeHWBParameters): 68 (WebCore::CSSPropertyParserHelpers::parseHWBParameters): 69 (WebCore::CSSPropertyParserHelpers::parseRelativeLabParameters): 70 (WebCore::CSSPropertyParserHelpers::parseLabParameters): 71 (WebCore::CSSPropertyParserHelpers::parseRelativeLCHParameters): 72 (WebCore::CSSPropertyParserHelpers::parseLCHParameters): 73 (WebCore::CSSPropertyParserHelpers::parseColorFunction): 74 1 75 2021-02-18 Myles C. Maxfield <mmaxfield@apple.com> 2 76 -
trunk/Source/WebCore/css/CSSValueKeywords.in
r272987 r273127 1270 1270 //color 1271 1271 1272 // relative color identifiers 1273 // from 1274 r 1275 g 1276 b 1277 h 1278 s 1279 l 1280 // h 1281 w 1282 // b 1283 // l 1284 a 1285 // b 1286 // l 1287 c 1288 // h 1289 // alpha 1290 1272 1291 // transform 1273 1292 matrix -
trunk/Source/WebCore/css/parser/CSSParserContext.cpp
r272987 r273127 78 78 #endif 79 79 , overscrollBehaviorEnabled { document.settings().overscrollBehaviorEnabled() } 80 , relativeColorSyntaxEnabled { document.settings().cssRelativeColorSyntaxEnabled() } 80 81 , scrollBehaviorEnabled { document.settings().CSSOMViewSmoothScrollingEnabled() } 81 82 , springTimingFunctionEnabled { document.settings().springTimingFunctionEnabled() } … … 114 115 #endif 115 116 && a.overscrollBehaviorEnabled == b.overscrollBehaviorEnabled 117 && a.relativeColorSyntaxEnabled == b.relativeColorSyntaxEnabled 116 118 && a.scrollBehaviorEnabled == b.scrollBehaviorEnabled 117 119 && a.springTimingFunctionEnabled == b.springTimingFunctionEnabled -
trunk/Source/WebCore/css/parser/CSSParserContext.h
r272987 r273127 68 68 #endif 69 69 bool overscrollBehaviorEnabled { false }; 70 bool relativeColorSyntaxEnabled { false }; 70 71 bool scrollBehaviorEnabled { false }; 71 72 bool springTimingFunctionEnabled { false }; … … 103 104 hash ^= StringHash::hash(key.charset); 104 105 unsigned bits = key.isHTMLDocument << 0 106 & key.hasDocumentSecurityOrigin << 1 107 & key.isContentOpaque << 2 108 & key.useSystemAppearance << 3 109 & key.aspectRatioEnabled << 4 110 & key.colorFilterEnabled << 5 111 & key.constantPropertiesEnabled << 6 112 & key.deferredCSSParserEnabled << 7 113 & key.enforcesCSSMIMETypeInNoQuirksMode << 8 114 & key.individualTransformPropertiesEnabled << 9 115 #if ENABLE(OVERFLOW_SCROLLING_TOUCH) 116 & key.legacyOverflowScrollingTouchEnabled << 10 117 #endif 118 & key.overscrollBehaviorEnabled << 11 119 & key.relativeColorSyntaxEnabled << 12 120 & key.scrollBehaviorEnabled << 13 121 & key.springTimingFunctionEnabled << 14 105 122 #if ENABLE(TEXT_AUTOSIZING) 106 & key.textAutosizingEnabled << 1 123 & key.textAutosizingEnabled << 15 107 124 #endif 108 #if ENABLE( OVERFLOW_SCROLLING_TOUCH)109 & key. legacyOverflowScrollingTouchEnabled << 2125 #if ENABLE(CSS_TRANSFORM_STYLE_OPTIMIZED_3D) 126 & key.transformStyleOptimized3DEnabled << 16 110 127 #endif 111 & key.enforcesCSSMIMETypeInNoQuirksMode << 3 112 & key.useLegacyBackgroundSizeShorthandBehavior << 4 113 & key.springTimingFunctionEnabled << 5 114 & key.constantPropertiesEnabled << 6 115 & key.colorFilterEnabled << 7 116 & key.deferredCSSParserEnabled << 8 117 & key.hasDocumentSecurityOrigin << 9 118 & key.useSystemAppearance << 10 128 & key.useLegacyBackgroundSizeShorthandBehavior << 17 129 & key.focusVisibleEnabled << 18 119 130 #if ENABLE(ATTACHMENT_ELEMENT) 120 & key.attachmentEnabled << 1 1131 & key.attachmentEnabled << 19 121 132 #endif 122 & key.scrollBehaviorEnabled << 12 123 & key.individualTransformPropertiesEnabled << 13 124 & key.overscrollBehaviorEnabled << 14 125 #if ENABLE(CSS_TRANSFORM_STYLE_OPTIMIZED_3D) 126 & key.transformStyleOptimized3DEnabled << 15 127 #endif 128 & key.mode << 16; // Keep this last. 133 & key.mode << 20; // Keep this last. 129 134 hash ^= WTF::intHash(bits); 130 135 return hash; -
trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp
r273078 r273127 691 691 } 692 692 693 static Color consumeOriginColor(CSSParserTokenRange& args, const CSSParserContext& context) 694 { 695 auto value = consumeColor(args, context); 696 if (!value) 697 return { }; 698 699 if (value->isRGBColor()) 700 return value->color(); 701 702 ASSERT(value->isValueID()); 703 auto keyword = value->valueID(); 704 705 // FIXME: We don't have enough context in the parser to resolving a system keyword 706 // correctly. We should package up the relative color parameters and resolve the 707 // whole thing at the appropriate time when the origin color is a system keyword. 708 if (StyleColor::isSystemColor(keyword)) 709 return { }; 710 711 return StyleColor::colorFromKeyword(keyword, { }); 712 } 713 693 714 static Optional<double> consumeOptionalAlpha(CSSParserTokenRange& range) 694 715 { … … 702 723 } 703 724 725 template<CSSValueID... allowedIdents> static Optional<Variant<double, CSSValueID>> consumeOptionalAlphaOrIdent(CSSParserTokenRange& range) 726 { 727 if (auto alpha = consumeOptionalAlpha(range)) 728 return { *alpha }; 729 730 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 731 return { *ident }; 732 733 return WTF::nullopt; 734 } 735 704 736 static Optional<double> consumeHue(CSSParserTokenRange& range, const CSSParserContext& context) 705 737 { … … 710 742 } 711 743 744 template<CSSValueID... allowedIdents> static Optional<Variant<double, CSSValueID>> consumeHueOrIdent(CSSParserTokenRange& range, const CSSParserContext& context) 745 { 746 if (auto hue = consumeHue(range, context)) 747 return { *hue }; 748 749 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 750 return { *ident }; 751 752 return WTF::nullopt; 753 } 754 712 755 static double normalizeHue(double hue) 713 756 { 714 757 return std::fmod(std::fmod(hue, 360.0) + 360.0, 360.0); 758 } 759 760 template<CSSValueID... allowedIdents> static Optional<Variant<double, CSSValueID>> consumeNumberOrIdent(CSSParserTokenRange& range) 761 { 762 if (auto number = consumeNumberRaw(range)) 763 return { *number }; 764 765 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 766 return { *ident }; 767 768 return WTF::nullopt; 769 } 770 771 template<CSSValueID... allowedIdents> static Optional<Variant<double, CSSValueID>> consumePercentOrIdent(CSSParserTokenRange& range) 772 { 773 if (auto percent = consumePercentRaw(range)) 774 return { *percent }; 775 776 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 777 return { *ident }; 778 779 return WTF::nullopt; 780 } 781 782 template<CSSValueID C1, CSSValueID C2, CSSValueID C3, CSSValueID AlphaChannel, typename ColorType> static auto extractChannelValue(CSSValueID channel, const ColorType& originColor) -> typename ColorType::ComponentType 783 { 784 auto components = asColorComponents(originColor); 785 switch (channel) { 786 case C1: 787 return components[0]; 788 case C2: 789 return components[1]; 790 case C3: 791 return components[2]; 792 case AlphaChannel: 793 return components[3]; 794 default: 795 ASSERT_NOT_REACHED(); 796 } 797 798 return 0; 799 } 800 801 template<CSSValueID C1, CSSValueID C2, CSSValueID C3, CSSValueID AlphaChannel, typename ColorType, typename ValueTransformer> static decltype(auto) resolveRelativeColorChannel(const Variant<double, CSSValueID>& parsedChannel, const ColorType& originColor, ValueTransformer&& valueTransformer) 802 { 803 return switchOn(parsedChannel, 804 [&] (double value) { 805 return valueTransformer(value); 806 }, 807 [&] (CSSValueID channel) { 808 return extractChannelValue<C1, C2, C3, AlphaChannel>(channel, originColor); 809 } 810 ); 811 } 812 813 template<CSSValueID C1, CSSValueID C2, CSSValueID C3, CSSValueID AlphaChannel, typename ColorType> static decltype(auto) resolveRelativeColorChannel(const Variant<double, CSSValueID>& parsedChannel, const ColorType& originColor) 814 { 815 return resolveRelativeColorChannel<C1, C2, C3, AlphaChannel>(parsedChannel, originColor, [](auto value) { return value; }); 715 816 } 716 817 … … 749 850 } 750 851 751 static Color parseRGBParameters(CSSParserTokenRange& range, const CSSParserContext&) 852 struct RelativeRGBComponent { 853 Variant<double, CSSValueID> value; 854 Optional<RGBComponentType> type; 855 }; 856 857 template<CSSValueID C> static Optional<RelativeRGBComponent> consumeRelativeRGBComponent(CSSParserTokenRange& args, Optional<RGBComponentType> componentType) 858 { 859 if (!componentType) { 860 if (auto number = consumeNumberRaw(args)) 861 return RelativeRGBComponent { *number, RGBComponentType::Number }; 862 if (auto percent = consumePercentRaw(args)) 863 return RelativeRGBComponent { *percent, RGBComponentType::Percentage }; 864 if (auto channel = consumeIdentRaw<C>(args)) 865 return RelativeRGBComponent { *channel, WTF::nullopt }; 866 return WTF::nullopt; 867 } 868 869 switch (*componentType) { 870 case RGBComponentType::Number: { 871 if (auto number = consumeNumberRaw(args)) 872 return RelativeRGBComponent { *number, RGBComponentType::Number }; 873 if (auto channel = consumeIdentRaw<C>(args)) 874 return RelativeRGBComponent { *channel, RGBComponentType::Number }; 875 return WTF::nullopt; 876 } 877 case RGBComponentType::Percentage: { 878 if (auto percent = consumePercentRaw(args)) 879 return RelativeRGBComponent { *percent, RGBComponentType::Percentage }; 880 if (auto channel = consumeIdentRaw<C>(args)) 881 return RelativeRGBComponent { *channel, RGBComponentType::Percentage }; 882 return WTF::nullopt; 883 } 884 } 885 } 886 887 static Color parseRelativeRGBParameters(CSSParserTokenRange& args, const CSSParserContext& context) 888 { 889 ASSERT(args.peek().id() == CSSValueFrom); 890 consumeIdentRaw(args); 891 892 auto originColor = consumeOriginColor(args, context); 893 if (!originColor.isValid()) 894 return { }; 895 896 Optional<RGBComponentType> componentType; 897 auto redResult = consumeRelativeRGBComponent<CSSValueR>(args, componentType); 898 if (!redResult) 899 return { }; 900 auto red = redResult->value; 901 componentType = redResult->type; 902 903 auto greenResult = consumeRelativeRGBComponent<CSSValueG>(args, componentType); 904 if (!greenResult) 905 return { }; 906 auto green = greenResult->value; 907 componentType = greenResult->type; 908 909 auto blueResult = consumeRelativeRGBComponent<CSSValueB>(args, componentType); 910 if (!blueResult) 911 return { }; 912 auto blue = blueResult->value; 913 componentType = blueResult->type; 914 915 auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args); 916 if (!alpha) 917 return { }; 918 919 if (!args.atEnd()) 920 return { }; 921 922 // After parsing, convert identifiers to values from the origin color. 923 924 // FIXME: Do we want to being doing this in uint8_t values? Or should we use 925 // higher precision and clamp at the end? It won't make a difference until we 926 // support calculations on the origin's components. 927 auto originColorAsSRGB = originColor.toSRGBALossy<uint8_t>(); 928 929 auto resolvedComponentType = componentType.valueOr(RGBComponentType::Percentage); 930 auto channelResolver = [resolvedComponentType](auto value) { 931 return clampRGBComponent(value, resolvedComponentType); 932 }; 933 934 auto resolvedRed = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(red, originColorAsSRGB, channelResolver); 935 auto resolvedGreen = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(green, originColorAsSRGB, channelResolver); 936 auto resolvedBlue = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(blue, originColorAsSRGB, channelResolver); 937 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(*alpha, originColorAsSRGB, [](auto value) { 938 return convertFloatAlphaTo<uint8_t>(value); 939 }); 940 941 return SRGBA<uint8_t> { resolvedRed, resolvedGreen, resolvedBlue, resolvedAlpha }; 942 } 943 944 enum class RGBFunctionMode { RGB, RGBA }; 945 946 template<RGBFunctionMode Mode> static Color parseRGBParameters(CSSParserTokenRange& range, const CSSParserContext& context) 752 947 { 753 948 ASSERT(range.peek().functionId() == CSSValueRgb || range.peek().functionId() == CSSValueRgba); 754 949 auto args = consumeFunction(range); 950 951 if constexpr (Mode == RGBFunctionMode::RGB) { 952 if (context.relativeColorSyntaxEnabled && args.peek().id() == CSSValueFrom) 953 return parseRelativeRGBParameters(args, context); 954 } 755 955 756 956 struct InitialComponent { … … 812 1012 } 813 1013 814 static Color parseHSLParameters(CSSParserTokenRange& range, const CSSParserContext& context) 1014 static Color parseRelativeHSLParameters(CSSParserTokenRange& args, const CSSParserContext& context) 1015 { 1016 ASSERT(args.peek().id() == CSSValueFrom); 1017 consumeIdentRaw(args); 1018 1019 auto originColor = consumeOriginColor(args, context); 1020 if (!originColor.isValid()) 1021 return { }; 1022 1023 auto hue = consumeHueOrIdent<CSSValueH>(args, context); 1024 if (!hue) 1025 return { }; 1026 1027 auto saturation = consumePercentOrIdent<CSSValueS>(args); 1028 if (!saturation) 1029 return { }; 1030 1031 auto lightness = consumePercentOrIdent<CSSValueL>(args); 1032 if (!lightness) 1033 return { }; 1034 1035 auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args); 1036 if (!alpha) 1037 return { }; 1038 1039 if (!args.atEnd()) 1040 return { }; 1041 1042 // After parsing, convert identifiers to values from the origin color. 1043 1044 auto originColorAsHSL = originColor.toColorTypeLossy<HSLA<float>>(); 1045 1046 auto resolvedHue = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*hue, originColorAsHSL, [](auto hue) { 1047 return normalizeHue(hue); 1048 }); 1049 auto resolvedSaturation = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*saturation, originColorAsHSL, [](auto saturation) { 1050 return clampTo(saturation, 0.0, 100.0); 1051 }); 1052 auto resolvedLightness = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*lightness, originColorAsHSL, [](auto lightness) { 1053 return clampTo(lightness, 0.0, 100.0); 1054 }); 1055 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*alpha, originColorAsHSL); 1056 1057 return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(resolvedHue), static_cast<float>(resolvedSaturation), static_cast<float>(resolvedLightness), static_cast<float>(resolvedAlpha) }); 1058 } 1059 1060 enum class HSLFunctionMode { HSL, HSLA }; 1061 1062 template<HSLFunctionMode Mode> static Color parseHSLParameters(CSSParserTokenRange& range, const CSSParserContext& context) 815 1063 { 816 1064 ASSERT(range.peek().functionId() == CSSValueHsl || range.peek().functionId() == CSSValueHsla); 817 1065 auto args = consumeFunction(range); 818 1066 1067 if constexpr (Mode == HSLFunctionMode::HSL) { 1068 if (context.relativeColorSyntaxEnabled && args.peek().id() == CSSValueFrom) 1069 return parseRelativeHSLParameters(args, context); 1070 } 1071 819 1072 auto hue = consumeHue(args, context); 820 1073 if (!hue) … … 842 1095 843 1096 auto normalizedHue = normalizeHue(*hue); 844 auto normalizedSaturation = clampTo <double>(*saturation, 0.0, 100.0);845 auto normalizedLightness = clampTo <double>(*lightness, 0.0, 100.0);846 auto normalizedAlpha = clampTo <double>(*alpha, 0.0, 1.0);1097 auto normalizedSaturation = clampTo(*saturation, 0.0, 100.0); 1098 auto normalizedLightness = clampTo(*lightness, 0.0, 100.0); 1099 auto normalizedAlpha = clampTo(*alpha, 0.0, 1.0); 847 1100 848 1101 return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedSaturation), static_cast<float>(normalizedLightness), static_cast<float>(normalizedAlpha) }); … … 855 1108 static WhitenessBlackness normalizeWhitenessBlackness(double whiteness, double blackness) 856 1109 { 857 WhitenessBlackness result;858 859 1110 // Values outside of these ranges are not invalid, but are clamped to the 860 1111 // ranges defined here at computed-value time. 861 result.whiteness = clampTo<double>(whiteness, 0, 100); 862 result.blackness = clampTo<double>(blackness, 0, 100); 1112 WhitenessBlackness result { 1113 clampTo(whiteness, 0.0, 100.0), 1114 clampTo(blackness, 0.0, 100.0) 1115 }; 863 1116 864 1117 // If the sum of these two arguments is greater than 100%, then at … … 873 1126 } 874 1127 1128 static Color parseRelativeHWBParameters(CSSParserTokenRange& args, const CSSParserContext& context) 1129 { 1130 ASSERT(args.peek().id() == CSSValueFrom); 1131 consumeIdentRaw(args); 1132 1133 auto originColor = consumeOriginColor(args, context); 1134 if (!originColor.isValid()) 1135 return { }; 1136 1137 auto hue = consumeHueOrIdent<CSSValueH>(args, context); 1138 if (!hue) 1139 return { }; 1140 1141 auto whiteness = consumePercentOrIdent<CSSValueW>(args); 1142 if (!whiteness) 1143 return { }; 1144 1145 auto blackness = consumePercentOrIdent<CSSValueB>(args); 1146 if (!blackness) 1147 return { }; 1148 1149 auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args); 1150 if (!alpha) 1151 return { }; 1152 1153 if (!args.atEnd()) 1154 return { }; 1155 1156 // After parsing, convert identifiers to values from the origin color. 1157 1158 auto originColorAsHWB = originColor.toColorTypeLossy<HWBA<float>>(); 1159 1160 auto resolvedHue = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*hue, originColorAsHWB, [](auto hue) { 1161 return normalizeHue(hue); 1162 }); 1163 auto resolvedWhiteness = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*whiteness, originColorAsHWB); 1164 auto resolvedBlackness = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*blackness, originColorAsHWB); 1165 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*alpha, originColorAsHWB); 1166 1167 auto [normalizedWhitness, normalizedBlackness] = normalizeWhitenessBlackness(resolvedWhiteness, resolvedBlackness); 1168 1169 return convertColor<SRGBA<uint8_t>>(HWBA<float> { static_cast<float>(resolvedHue), static_cast<float>(normalizedWhitness), static_cast<float>(normalizedBlackness), static_cast<float>(resolvedAlpha) }); 1170 } 1171 875 1172 static Color parseHWBParameters(CSSParserTokenRange& range, const CSSParserContext& context) 876 1173 { … … 878 1175 auto args = consumeFunction(range); 879 1176 1177 if (context.relativeColorSyntaxEnabled && args.peek().id() == CSSValueFrom) 1178 return parseRelativeHWBParameters(args, context); 1179 880 1180 auto hue = consumeHue(args, context); 881 1181 if (!hue) … … 903 1203 } 904 1204 905 static Color parseLabParameters(CSSParserTokenRange& range, const CSSParserContext&) 1205 static Color parseRelativeLabParameters(CSSParserTokenRange& args, const CSSParserContext& context) 1206 { 1207 ASSERT(args.peek().id() == CSSValueFrom); 1208 consumeIdentRaw(args); 1209 1210 auto originColor = consumeOriginColor(args, context); 1211 if (!originColor.isValid()) 1212 return { }; 1213 1214 auto lightness = consumePercentOrIdent<CSSValueL>(args); 1215 if (!lightness) 1216 return { }; 1217 1218 auto aValue = consumeNumberOrIdent<CSSValueA>(args); 1219 if (!aValue) 1220 return { }; 1221 1222 auto bValue = consumeNumberOrIdent<CSSValueB>(args); 1223 if (!bValue) 1224 return { }; 1225 1226 auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args); 1227 if (!alpha) 1228 return { }; 1229 1230 if (!args.atEnd()) 1231 return { }; 1232 1233 // After parsing, convert identifiers to values from the origin color. 1234 1235 auto originColorAsLab = originColor.toColorTypeLossy<Lab<float>>(); 1236 1237 auto resolvedLightness = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*lightness, originColorAsLab, [](auto lightness) { 1238 return std::max(0.0, lightness); 1239 }); 1240 auto resolvedAValue = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*aValue, originColorAsLab); 1241 auto resolvedBValue = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*bValue, originColorAsLab); 1242 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*alpha, originColorAsLab); 1243 1244 return Lab<float> { static_cast<float>(resolvedLightness), static_cast<float>(resolvedAValue), static_cast<float>(resolvedBValue), static_cast<float>(resolvedAlpha) }; 1245 } 1246 1247 static Color parseLabParameters(CSSParserTokenRange& range, const CSSParserContext& context) 906 1248 { 907 1249 ASSERT(range.peek().functionId() == CSSValueLab); 908 1250 auto args = consumeFunction(range); 909 1251 1252 if (context.relativeColorSyntaxEnabled && args.peek().id() == CSSValueFrom) 1253 return parseRelativeLabParameters(args, context); 1254 910 1255 auto lightness = consumePercentRaw(args); 911 1256 if (!lightness) … … 932 1277 } 933 1278 1279 static Color parseRelativeLCHParameters(CSSParserTokenRange& args, const CSSParserContext& context) 1280 { 1281 ASSERT(args.peek().id() == CSSValueFrom); 1282 consumeIdentRaw(args); 1283 1284 auto originColor = consumeOriginColor(args, context); 1285 if (!originColor.isValid()) 1286 return { }; 1287 1288 auto lightness = consumePercentOrIdent<CSSValueL>(args); 1289 if (!lightness) 1290 return { }; 1291 1292 auto chroma = consumeNumberOrIdent<CSSValueC>(args); 1293 if (!chroma) 1294 return { }; 1295 1296 auto hue = consumeHueOrIdent<CSSValueH>(args, context); 1297 if (!hue) 1298 return { }; 1299 1300 auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args); 1301 if (!alpha) 1302 return { }; 1303 1304 if (!args.atEnd()) 1305 return { }; 1306 1307 auto originColorAsLCH = originColor.toColorTypeLossy<LCHA<float>>(); 1308 1309 auto resolvedLightness = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*lightness, originColorAsLCH, [](auto lightness) { 1310 return std::max(0.0, lightness); 1311 }); 1312 auto resolvedChroma = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*chroma, originColorAsLCH, [](auto chroma) { 1313 return std::max(0.0, chroma); 1314 }); 1315 auto resolvedHue = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*hue, originColorAsLCH, [](auto hue) { 1316 return normalizeHue(hue); 1317 }); 1318 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*alpha, originColorAsLCH); 1319 1320 return LCHA<float> { static_cast<float>(resolvedLightness), static_cast<float>(resolvedChroma), static_cast<float>(resolvedHue), static_cast<float>(resolvedAlpha) }; 1321 } 1322 934 1323 static Color parseLCHParameters(CSSParserTokenRange& range, const CSSParserContext& context) 935 1324 { 936 1325 ASSERT(range.peek().functionId() == CSSValueLch); 937 1326 auto args = consumeFunction(range); 1327 1328 if (context.relativeColorSyntaxEnabled && args.peek().id() == CSSValueFrom) 1329 return parseRelativeLCHParameters(args, context); 938 1330 939 1331 auto lightness = consumePercentRaw(args); … … 1132 1524 switch (functionId) { 1133 1525 case CSSValueRgb: 1526 color = parseRGBParameters<RGBFunctionMode::RGB>(colorRange, context); 1527 break; 1134 1528 case CSSValueRgba: 1135 color = parseRGBParameters (colorRange, context);1529 color = parseRGBParameters<RGBFunctionMode::RGBA>(colorRange, context); 1136 1530 break; 1137 1531 case CSSValueHsl: 1532 color = parseHSLParameters<HSLFunctionMode::HSL>(colorRange, context); 1533 break; 1138 1534 case CSSValueHsla: 1139 color = parseHSLParameters (colorRange, context);1535 color = parseHSLParameters<HSLFunctionMode::HSLA>(colorRange, context); 1140 1536 break; 1141 1537 case CSSValueHwb:
Note: See TracChangeset
for help on using the changeset viewer.