Changeset 273244 in webkit
- Timestamp:
- Feb 22, 2021 9:52:13 AM (3 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r273243 r273244 1 2021-02-22 Sam Weinig <weinig@apple.com> 2 3 Add experimental support for CSS Color 5 color-mix() 4 https://bugs.webkit.org/show_bug.cgi?id=222258 5 6 Reviewed by Antti Koivisto. 7 8 * fast/css/parsing-color-mix-expected.txt: Added. 9 * fast/css/parsing-color-mix.html: Added. 10 Add parsing and computed style computation tests for color-mix(). 11 1 12 2021-02-22 Sam Weinig <weinig@apple.com> 2 13 -
trunk/Source/WTF/ChangeLog
r273236 r273244 1 2021-02-22 Sam Weinig <weinig@apple.com> 2 3 Add experimental support for CSS Color 5 color-mix() 4 https://bugs.webkit.org/show_bug.cgi?id=222258 5 6 Reviewed by Antti Koivisto. 7 8 * Scripts/Preferences/WebPreferencesExperimental.yaml: 9 Add new experimental preference for CSS Color 5 color-mix() 10 which is off by default. 11 1 12 2021-02-22 Carlos Garcia Campos <cgarcia@igalia.com> 2 13 -
trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml
r273221 r273244 114 114 default: false 115 115 116 CSSColorMixEnabled: 117 type: bool 118 humanReadableName: "CSS color-mix()" 119 humanReadableDescription: "Enable support for CSS color-mix() defined in CSS Color 5" 120 defaultValue: 121 WebKitLegacy: 122 default: false 123 WebKit: 124 default: false 125 WebCore: 126 default: false 127 116 128 CSSCustomPropertiesAndValuesEnabled: 117 129 type: bool -
trunk/Source/WebCore/ChangeLog
r273242 r273244 1 2021-02-22 Sam Weinig <weinig@apple.com> 2 3 Add experimental support for CSS Color 5 color-mix() 4 https://bugs.webkit.org/show_bug.cgi?id=222258 5 6 Reviewed by Antti Koivisto. 7 8 Adds initial support for CSS Color 5 color-mix() - https://drafts.csswg.org/css-color-5/#color-mix 9 10 This feature is off by default and can be enabled via the CSSColorMixEnabled 11 experimental preference flag. 12 13 This implementation has the same restriction on it that the recently landed 14 Relative Color Syntax does in that it does support system colors or currentColor 15 as input, since those can't be resolved at parse time. Ultimately, we will need 16 to add a late binding version of this for those cases. 17 18 Test: fast/css/parsing-color-mix.html 19 20 * css/CSSValueKeywords.in: 21 Add new keywords needed for color-mix(). 22 23 * css/parser/CSSParserContext.cpp: 24 (WebCore::operator==): 25 * css/parser/CSSParserContext.h: 26 (WebCore::CSSParserContextHash::hash): 27 Add new setting for color-mix(). 28 29 * css/parser/CSSPropertyParserHelpers.cpp: 30 (WebCore::CSSPropertyParserHelpers::HueColorAdjuster::fixupAnglesForInterpolation): 31 (WebCore::CSSPropertyParserHelpers::HueColorAdjuster::HueColorAdjuster): 32 (WebCore::CSSPropertyParserHelpers::ColorAdjuster::ColorAdjuster): 33 (WebCore::CSSPropertyParserHelpers::consumeAdjuster): 34 (WebCore::CSSPropertyParserHelpers::consumeAndUpdateAdjusterAtIndex): 35 (WebCore::CSSPropertyParserHelpers::consumeAndUpdateAdjuster): 36 (WebCore::CSSPropertyParserHelpers::consumeAdjusters): 37 (WebCore::CSSPropertyParserHelpers::consumeMixComponents): 38 (WebCore::CSSPropertyParserHelpers::normalizeAdjusterValues): 39 (WebCore::CSSPropertyParserHelpers::remainingAdjustment): 40 (WebCore::CSSPropertyParserHelpers::mixComponent): 41 (WebCore::CSSPropertyParserHelpers::mixComponentAtIndex): 42 (WebCore::CSSPropertyParserHelpers::makeColorTypeByNormalizingComponentsAfterMix): 43 (WebCore::CSSPropertyParserHelpers::makeColorTypeByNormalizingComponentsAfterMix<HWBA<float>>): 44 (WebCore::CSSPropertyParserHelpers::mix): 45 (WebCore::CSSPropertyParserHelpers::parseColorMixFunctionParametersUsingAdjusters): 46 (WebCore::CSSPropertyParserHelpers::parseColorMixFunctionParameters): 47 (WebCore::CSSPropertyParserHelpers::parseColorFunction): 48 The implementation uses a templatized ColorAdjuster struct to declartively map the 49 various mixing color spaces to their allowed adjusters and what type those adjusters 50 operate on (either double or the hue specific HueColorAdjuster). For example, for 51 LCHA we have: 52 53 using LCHColorAdjuster = ColorAdjuster<LCHA<float>, CSSValueLightness, double, CSSValueChroma, HueColorAdjuster, CSSValueHue, double, CSSValueAlpha, double>; 54 55 which indicates: 56 57 - it creates a LCHA<float> and will operate on LCHA<float> values 58 - its first channel is called "lightness" and is a double 59 - its second channel is called "chroma" and is a double 60 - its third channel is called "hue" and is a HueColorAdjuster 61 - its fourth channel is called "alpha" and is a double 62 63 This data is then used by the parsing and mixing functions to implement mixing without 64 having to write specific implementations for each mixing color space and can be expanded 65 to more spaces if needed. 66 67 * platform/graphics/Color.h: 68 (WebCore::Color::Color): 69 Add new overloaded constructor for a generic Optional<ColorType<float>> which parallels the existing 70 Optional<SRGBA<uint8_t>> allowing callers to convert WTF::nullopt to an invalid Color without checking 71 for nullopt themselves. 72 1 73 2021-02-19 Sergio Villar Senin <svillar@igalia.com> 2 74 -
trunk/Source/WebCore/css/CSSValueKeywords.in
r273127 r273244 1435 1435 xyz 1436 1436 1437 // color-mix() 1438 color-mix 1439 shorter 1440 longer 1441 increasing 1442 decreasing 1443 specified 1444 lightness 1445 chroma 1446 whiteness 1447 blackness 1448 1437 1449 // prefers-default-appearance 1438 1450 prefers -
trunk/Source/WebCore/css/parser/CSSParserContext.cpp
r273127 r273244 70 70 , aspectRatioEnabled { document.settings().aspectRatioEnabled() } 71 71 , colorFilterEnabled { document.settings().colorFilterEnabled() } 72 , colorMixEnabled { document.settings().cssColorMixEnabled() } 72 73 , constantPropertiesEnabled { document.settings().constantPropertiesEnabled() } 73 74 , deferredCSSParserEnabled { document.settings().deferredCSSParserEnabled() } … … 107 108 && a.aspectRatioEnabled == b.aspectRatioEnabled 108 109 && a.colorFilterEnabled == b.colorFilterEnabled 110 && a.colorMixEnabled == b.colorMixEnabled 109 111 && a.constantPropertiesEnabled == b.constantPropertiesEnabled 110 112 && a.deferredCSSParserEnabled == b.deferredCSSParserEnabled -
trunk/Source/WebCore/css/parser/CSSParserContext.h
r273127 r273244 60 60 bool aspectRatioEnabled { false }; 61 61 bool colorFilterEnabled { false }; 62 bool colorMixEnabled { false }; 62 63 bool constantPropertiesEnabled { false }; 63 64 bool deferredCSSParserEnabled { false }; … … 103 104 if (!key.charset.isEmpty()) 104 105 hash ^= StringHash::hash(key.charset); 106 105 107 unsigned bits = key.isHTMLDocument << 0 106 108 & key.hasDocumentSecurityOrigin << 1 … … 109 111 & key.aspectRatioEnabled << 4 110 112 & key.colorFilterEnabled << 5 111 & key.constantPropertiesEnabled << 6 112 & key.deferredCSSParserEnabled << 7 113 & key.enforcesCSSMIMETypeInNoQuirksMode << 8 114 & key.individualTransformPropertiesEnabled << 9 113 & key.colorMixEnabled << 6 114 & key.constantPropertiesEnabled << 7 115 & key.deferredCSSParserEnabled << 8 116 & key.enforcesCSSMIMETypeInNoQuirksMode << 9 117 & key.individualTransformPropertiesEnabled << 10 115 118 #if ENABLE(OVERFLOW_SCROLLING_TOUCH) 116 & key.legacyOverflowScrollingTouchEnabled << 1 0119 & key.legacyOverflowScrollingTouchEnabled << 11 117 120 #endif 118 & key.overscrollBehaviorEnabled << 1 1119 & key.relativeColorSyntaxEnabled << 1 2120 & key.scrollBehaviorEnabled << 1 3121 & key.springTimingFunctionEnabled << 1 4121 & key.overscrollBehaviorEnabled << 12 122 & key.relativeColorSyntaxEnabled << 13 123 & key.scrollBehaviorEnabled << 14 124 & key.springTimingFunctionEnabled << 15 122 125 #if ENABLE(TEXT_AUTOSIZING) 123 & key.textAutosizingEnabled << 1 5126 & key.textAutosizingEnabled << 16 124 127 #endif 125 128 #if ENABLE(CSS_TRANSFORM_STYLE_OPTIMIZED_3D) 126 & key.transformStyleOptimized3DEnabled << 1 6129 & key.transformStyleOptimized3DEnabled << 17 127 130 #endif 128 & key.useLegacyBackgroundSizeShorthandBehavior << 1 7129 & key.focusVisibleEnabled << 1 8131 & key.useLegacyBackgroundSizeShorthandBehavior << 18 132 & key.focusVisibleEnabled << 19 130 133 #if ENABLE(ATTACHMENT_ELEMENT) 131 & key.attachmentEnabled << 19134 & key.attachmentEnabled << 20 132 135 #endif 133 & key.mode << 2 0; // Keep this last.136 & key.mode << 21; // Keep this last. 134 137 hash ^= WTF::intHash(bits); 135 138 return hash; -
trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp
r273211 r273244 1481 1481 } 1482 1482 1483 struct HueColorAdjuster { 1484 enum class Type { 1485 Shorter, 1486 Longer, 1487 Increasing, 1488 Decreasing, 1489 Specified 1490 }; 1491 1492 static std::pair<double, double> fixupAnglesForInterpolation(double theta1, double theta2, Type type) 1493 { 1494 ASSERT(theta1 >= 0.0); 1495 ASSERT(theta1 <= 360.0); 1496 ASSERT(theta2 >= 0.0); 1497 ASSERT(theta2 <= 360.0); 1498 1499 switch (type) { 1500 case Type::Shorter: { 1501 auto difference = theta2 - theta1; 1502 if (difference > 180.0) 1503 return { theta1 + 360.0, theta2 }; 1504 if (difference < -180.0) 1505 return { theta1, theta2 + 360.0 }; 1506 return { theta1, theta2 }; 1507 } 1508 case Type::Longer: { 1509 auto difference = theta2 - theta1; 1510 if (difference >= 0.0 && difference < 180.0) 1511 return { theta1 + 360.0, theta2 }; 1512 if (difference >= -180.0 && difference < 0) 1513 return { theta1, theta2 + 360.0 }; 1514 return { theta1, theta2 }; 1515 } 1516 case Type::Increasing: { 1517 if (theta2 < theta1) 1518 return { theta1, theta2 + 360.0 }; 1519 return { theta1, theta2 }; 1520 } 1521 case Type::Decreasing: { 1522 if (theta1 < theta2) 1523 return { theta1 + 360.0, theta2 }; 1524 return { theta1, theta2 }; 1525 } 1526 case Type::Specified: 1527 return { theta1, theta2 }; 1528 } 1529 } 1530 1531 HueColorAdjuster(double value = 0.0, Type type = Type::Shorter) 1532 : type { type } 1533 , value { value } 1534 { 1535 } 1536 1537 Type type; 1538 double value; 1539 }; 1540 1541 template<typename C, CSSValueID ID0, typename Channel0, CSSValueID ID1, typename Channel1, CSSValueID ID2, typename Channel2, CSSValueID ID3, typename Channel3> 1542 struct ColorAdjuster { 1543 using ColorType = C; 1544 static constexpr auto channelCSSValueIDs = std::make_tuple(ID0, ID1, ID2, ID3); 1545 1546 ColorAdjuster() = default; 1547 explicit ColorAdjuster(double percentage) 1548 : channels { percentage, percentage, percentage, percentage } 1549 { 1550 } 1551 1552 std::tuple<Optional<Channel0>, Optional<Channel1>, Optional<Channel2>, Optional<Channel3>> channels; 1553 }; 1554 1555 using HSLColorAdjuster = ColorAdjuster<HSLA<float>, CSSValueHue, HueColorAdjuster, CSSValueSaturation, double, CSSValueLightness, double, CSSValueAlpha, double>; 1556 using HWBColorAdjuster = ColorAdjuster<HWBA<float>, CSSValueHue, HueColorAdjuster, CSSValueWhiteness, double, CSSValueBlackness, double, CSSValueAlpha, double>; 1557 using LCHColorAdjuster = ColorAdjuster<LCHA<float>, CSSValueLightness, double, CSSValueChroma, HueColorAdjuster, CSSValueHue, double, CSSValueAlpha, double>; 1558 using LabColorAdjuster = ColorAdjuster<Lab<float>, CSSValueLightness, double, CSSValueA, double, CSSValueB, double, CSSValueAlpha, double>; 1559 using SRGBColorAdjuster = ColorAdjuster<SRGBA<float>, CSSValueRed, double, CSSValueGreen, double, CSSValueBlue, double, CSSValueAlpha, double>; 1560 using XYZColorAdjuster = ColorAdjuster<XYZA<float, WhitePoint::D50>, CSSValueX, double, CSSValueY, double, CSSValueZ, double, CSSValueAlpha, double>; 1561 1562 template<typename Adjuster> struct ColorMixComponent { 1563 Color color; 1564 Adjuster adjuster; 1565 }; 1566 1567 template<CSSValueID Ident, typename T> struct AdjusterConsumer; 1568 1569 template<CSSValueID Ident> struct AdjusterConsumer<Ident, HueColorAdjuster> { 1570 static Optional<HueColorAdjuster> consume(CSSParserTokenRange& args) 1571 { 1572 if (!consumeIdentRaw<Ident>(args)) 1573 return WTF::nullopt; 1574 1575 HueColorAdjuster result; 1576 if (auto hueAdjustmentType = consumeHueAdjustmentType(args)) 1577 result.type = *hueAdjustmentType; 1578 1579 // FIXME: Is clamping to 0 for negative percentages the right thing to do? 1580 if (auto percentage = consumePercentRaw(args)) 1581 result.value = std::max(0.0, *percentage); 1582 1583 // FIXME: Should an adjuster without a percetange be allowed? 1584 // e.g color-mix(hsl, teal hue, red); 1585 1586 return result; 1587 } 1588 1589 static Optional<HueColorAdjuster::Type> consumeHueAdjustmentType(CSSParserTokenRange& args) 1590 { 1591 switch (args.peek().id()) { 1592 case CSSValueShorter: 1593 consumeIdentRaw(args); 1594 return HueColorAdjuster::Type::Shorter; 1595 case CSSValueLonger: 1596 consumeIdentRaw(args); 1597 return HueColorAdjuster::Type::Longer; 1598 case CSSValueIncreasing: 1599 consumeIdentRaw(args); 1600 return HueColorAdjuster::Type::Increasing; 1601 case CSSValueDecreasing: 1602 consumeIdentRaw(args); 1603 return HueColorAdjuster::Type::Decreasing; 1604 case CSSValueSpecified: 1605 consumeIdentRaw(args); 1606 return HueColorAdjuster::Type::Specified; 1607 default: 1608 return WTF::nullopt; 1609 } 1610 } 1611 }; 1612 1613 template<CSSValueID Ident> struct AdjusterConsumer<Ident, double> { 1614 static Optional<double> consume(CSSParserTokenRange& args) 1615 { 1616 if (!consumeIdentRaw<Ident>(args)) 1617 return WTF::nullopt; 1618 1619 // FIXME: Is clamping to 0 for negative percentages the right thing to do? 1620 if (auto percentage = consumePercentRaw(args)) 1621 return std::max(0.0, *percentage); 1622 1623 // FIXME: Should an adjuster without a percetange be allowed? 1624 // e.g color-mix(hsl, teal saturation, red); 1625 1626 return 0; 1627 } 1628 }; 1629 1630 template<CSSValueID Ident, typename T> inline decltype(auto) consumeAdjuster(CSSParserTokenRange& args) 1631 { 1632 return AdjusterConsumer<Ident, T>::consume(args); 1633 } 1634 1635 template<std::size_t I, typename Adjuster> static bool consumeAndUpdateAdjusterAtIndex(CSSParserTokenRange& args, Adjuster& adjuster) 1636 { 1637 using AdjusterType = std::decay_t<decltype(std::get<I>(adjuster.channels).value())>; 1638 static constexpr CSSValueID Ident = std::get<I>(Adjuster::channelCSSValueIDs); 1639 1640 if (auto adjustment = consumeAdjuster<Ident, AdjusterType>(args)) { 1641 std::get<I>(adjuster.channels) = *adjustment; 1642 return true; 1643 } 1644 return false; 1645 } 1646 1647 template<typename Adjuster> static bool consumeAndUpdateAdjuster(CSSParserTokenRange& args, Adjuster& adjuster) 1648 { 1649 if (consumeAndUpdateAdjusterAtIndex<0>(args, adjuster)) 1650 return true; 1651 if (consumeAndUpdateAdjusterAtIndex<1>(args, adjuster)) 1652 return true; 1653 if (consumeAndUpdateAdjusterAtIndex<2>(args, adjuster)) 1654 return true; 1655 if (consumeAndUpdateAdjusterAtIndex<3>(args, adjuster)) 1656 return true; 1657 return false; 1658 } 1659 1660 template<typename Adjuster> static Adjuster consumeAdjusters(CSSParserTokenRange& args) 1661 { 1662 Adjuster adjuster; 1663 while (consumeAndUpdateAdjuster(args, adjuster)) { 1664 // Keep consuming until there are no more adjusters. 1665 } 1666 1667 return adjuster; 1668 } 1669 1670 template<typename Adjuster> static Optional<ColorMixComponent<Adjuster>> consumeMixComponents(CSSParserTokenRange& args, const CSSParserContext& context) 1671 { 1672 auto originColor = consumeOriginColor(args, context); 1673 if (!originColor.isValid()) 1674 return WTF::nullopt; 1675 1676 // FIXME: Is clamping to 0 for negative percentages the right thing to do? 1677 if (auto percentage = consumePercentRaw(args)) 1678 return { { WTFMove(originColor), Adjuster { std::max(0.0, *percentage) } } }; 1679 1680 return { { WTFMove(originColor), consumeAdjusters<Adjuster>(args) } }; 1681 } 1682 1683 static std::pair<HueColorAdjuster, HueColorAdjuster> normalizeAdjusterValues(HueColorAdjuster adjuster1, HueColorAdjuster adjuster2) 1684 { 1685 if (auto sum = adjuster1.value + adjuster2.value; sum != 100.0) { 1686 adjuster1.value *= 100.0 / sum; 1687 adjuster2.value *= 100.0 / sum; 1688 } 1689 1690 return { adjuster1, adjuster2 }; 1691 } 1692 1693 static std::pair<double, double> normalizeAdjusterValues(double adjuster1, double adjuster2) 1694 { 1695 if (auto sum = adjuster1 + adjuster2; sum != 100.0) { 1696 adjuster1 *= 100.0 / sum; 1697 adjuster2 *= 100.0 / sum; 1698 } 1699 1700 return { adjuster1, adjuster2 }; 1701 } 1702 1703 static HueColorAdjuster remainingAdjustment(HueColorAdjuster adjuster) 1704 { 1705 return { 100.0 - adjuster.value, adjuster.type }; 1706 } 1707 1708 static double remainingAdjustment(double adjuster) 1709 { 1710 return 100.0 - adjuster; 1711 } 1712 1713 template<typename AdjusterType> static auto normalizeAdjusterValues(Optional<AdjusterType> adjuster1, Optional<AdjusterType> adjuster2) -> std::pair<AdjusterType, AdjusterType> 1714 { 1715 if (adjuster1 && adjuster2) 1716 return normalizeAdjusterValues(*adjuster1, *adjuster2); 1717 if (!adjuster1 && adjuster2) 1718 return { remainingAdjustment(*adjuster2), *adjuster2 }; 1719 if (adjuster1 && !adjuster2) 1720 return { *adjuster1, remainingAdjustment(*adjuster1) }; 1721 // When neigher mix component provides an adjuster, the result is the non-modified 1722 // channel from from the first color. 1723 ASSERT(!adjuster1 && !adjuster2); 1724 return { 100.0, 0.0 }; 1725 } 1726 1727 static double mixComponent(float component1, HueColorAdjuster adjustment1, float component2, HueColorAdjuster adjustment2) 1728 { 1729 // FIXME: The spec does not indicate what to do if two different hue types are specified. We always use the first one for now, 1730 // though we probably should take into account whether it was actually specified or is the default value. That normalization 1731 // should happen in normalizeAdjusterValues(). 1732 1733 auto [fixedUpComponent1, fixedUpComponent2] = HueColorAdjuster::fixupAnglesForInterpolation(component1, component2, adjustment1.type); 1734 auto result = (fixedUpComponent1 * (adjustment1.value / 100.0)) + (fixedUpComponent2 * (adjustment2.value / 100.0)); 1735 // FIXME: Check if this full normalization is needed. 1736 return normalizeHue(result); 1737 } 1738 1739 static double mixComponent(float component1, double adjustment1, float component2, double adjustment2) 1740 { 1741 return (component1 * (adjustment1 / 100.0)) + (component2 * (adjustment2 / 100.0)); 1742 } 1743 1744 template<std::size_t I, typename Adjuster> static double mixComponentAtIndex(const ColorComponents<float>& color1, const Adjuster& adjuster1, const ColorComponents<float>& color2, const Adjuster& adjuster2) 1745 { 1746 auto [normalizedAdjuster1Value, normalizedAdjuster2Value] = normalizeAdjusterValues(std::get<I>(adjuster1.channels), std::get<I>(adjuster2.channels)); 1747 return mixComponent(color1[I], normalizedAdjuster1Value, color2[I], normalizedAdjuster2Value); 1748 } 1749 1750 template<typename ColorType> inline ColorType makeColorTypeByNormalizingComponentsAfterMix(double channel0, double channel1, double channel2, double channel3) 1751 { 1752 return { static_cast<float>(channel0), static_cast<float>(channel1), static_cast<float>(channel2), static_cast<float>(channel3) }; 1753 } 1754 1755 template<> inline HWBA<float> makeColorTypeByNormalizingComponentsAfterMix<HWBA<float>>(double hue, double whiteness, double blackness, double alpha) 1756 { 1757 auto [normalizedWhitness, normalizedBlackness] = normalizeWhitenessBlackness(whiteness, blackness); 1758 return { static_cast<float>(hue), static_cast<float>(normalizedWhitness), static_cast<float>(normalizedBlackness), static_cast<float>(alpha) }; 1759 } 1760 1761 template<typename Adjuster> static typename Adjuster::ColorType mix(const ColorMixComponent<Adjuster>& mixComponents1, const ColorMixComponent<Adjuster>& mixComponents2) 1762 { 1763 using ColorType = typename Adjuster::ColorType; 1764 1765 auto color1 = asColorComponents(mixComponents1.color.template toColorTypeLossy<ColorType>()); 1766 auto color2 = asColorComponents(mixComponents2.color.template toColorTypeLossy<ColorType>()); 1767 1768 auto adjuster1 = mixComponents1.adjuster; 1769 auto adjuster2 = mixComponents2.adjuster; 1770 1771 if (!std::get<0>(adjuster1.channels) && !std::get<1>(adjuster1.channels) && !std::get<2>(adjuster1.channels) && !std::get<3>(adjuster1.channels) && !std::get<0>(adjuster2.channels) && !std::get<1>(adjuster2.channels) && !std::get<2>(adjuster2.channels) && !std::get<3>(adjuster2.channels)) { 1772 // No adjusters being specified at all is special cased to mean mix 50-50. 1773 adjuster1 = Adjuster { 50.0 }; 1774 adjuster2 = Adjuster { 50.0 }; 1775 } 1776 1777 auto channel0 = mixComponentAtIndex<0>(color1, adjuster1, color2, adjuster2); 1778 auto channel1 = mixComponentAtIndex<1>(color1, adjuster1, color2, adjuster2); 1779 auto channel2 = mixComponentAtIndex<2>(color1, adjuster1, color2, adjuster2); 1780 auto channel3 = mixComponentAtIndex<3>(color1, adjuster1, color2, adjuster2); 1781 1782 return makeColorTypeByNormalizingComponentsAfterMix<ColorType>(channel0, channel1, channel2, channel3); 1783 } 1784 1785 template<typename Adjuster> static Optional<typename Adjuster::ColorType> parseColorMixFunctionParametersUsingAdjusters(CSSParserTokenRange& args, const CSSParserContext& context) 1786 { 1787 auto mixComponents1 = consumeMixComponents<Adjuster>(args, context); 1788 if (!mixComponents1) 1789 return WTF::nullopt; 1790 1791 // FIXME: This comma is not in the grammar, but is in all the examples. 1792 if (!consumeCommaIncludingWhitespace(args)) 1793 return WTF::nullopt; 1794 1795 auto mixComponents2 = consumeMixComponents<Adjuster>(args, context); 1796 if (!mixComponents2) 1797 return WTF::nullopt; 1798 1799 return mix(*mixComponents1, *mixComponents2); 1800 } 1801 1802 static Color parseColorMixFunctionParameters(CSSParserTokenRange& range, const CSSParserContext& context) 1803 { 1804 ASSERT(range.peek().functionId() == CSSValueColorMix); 1805 1806 if (!context.colorMixEnabled) 1807 return { }; 1808 1809 auto args = consumeFunction(range); 1810 1811 auto consumeIdentAndComma = [](CSSParserTokenRange& args) { 1812 consumeIdentRaw(args); 1813 // FIXME: This comma is not in the grammar, but is in all the examples. 1814 return consumeCommaIncludingWhitespace(args); 1815 }; 1816 1817 switch (args.peek().id()) { 1818 case CSSValueHsl: { 1819 if (!consumeIdentAndComma(args)) 1820 return { }; 1821 auto hsl = parseColorMixFunctionParametersUsingAdjusters<HSLColorAdjuster>(args, context); 1822 if (!hsl) 1823 return { }; 1824 return convertColor<SRGBA<uint8_t>>(*hsl); 1825 } 1826 case CSSValueHwb: { 1827 if (!consumeIdentAndComma(args)) 1828 return { }; 1829 auto hwb = parseColorMixFunctionParametersUsingAdjusters<HWBColorAdjuster>(args, context); 1830 if (!hwb) 1831 return { }; 1832 return convertColor<SRGBA<uint8_t>>(*hwb); 1833 } 1834 case CSSValueLch: 1835 if (!consumeIdentAndComma(args)) 1836 return { }; 1837 return parseColorMixFunctionParametersUsingAdjusters<LCHColorAdjuster>(args, context); 1838 case CSSValueLab: 1839 if (!consumeIdentAndComma(args)) 1840 return { }; 1841 return parseColorMixFunctionParametersUsingAdjusters<LabColorAdjuster>(args, context); 1842 case CSSValueXyz: 1843 if (!consumeIdentAndComma(args)) 1844 return { }; 1845 return parseColorMixFunctionParametersUsingAdjusters<XYZColorAdjuster>(args, context); 1846 case CSSValueSRGB: 1847 if (!consumeIdentAndComma(args)) 1848 return { }; 1849 return parseColorMixFunctionParametersUsingAdjusters<SRGBColorAdjuster>(args, context); 1850 default: 1851 // Default to using LCH if no color space is provided as per the spec. 1852 // FIXME: This behavior is unnecessarily confusing, we should remove the default from the spec. 1853 return parseColorMixFunctionParametersUsingAdjusters<LCHColorAdjuster>(args, context); 1854 } 1855 } 1856 1483 1857 static Optional<SRGBA<uint8_t>> parseHexColor(CSSParserTokenRange& range, bool acceptQuirkyColors) 1484 1858 { … … 1547 1921 case CSSValueColor: 1548 1922 color = parseColorFunctionParameters(colorRange); 1923 break; 1924 case CSSValueColorMix: 1925 color = parseColorMixFunctionParameters(colorRange, context); 1549 1926 break; 1550 1927 default: -
trunk/Source/WebCore/platform/graphics/Color.h
r273211 r273244 74 74 75 75 Color(ColorComponents<float>, ColorSpace, OptionSet<Flags> = { }); 76 76 77 template<typename ColorType, typename std::enable_if_t<IsColorTypeWithComponentType<ColorType, float>>* = nullptr> 77 78 Color(const ColorType&, OptionSet<Flags> = { }); 79 80 template<typename ColorType, typename std::enable_if_t<IsColorTypeWithComponentType<ColorType, float>>* = nullptr> 81 Color(const Optional<ColorType>&, OptionSet<Flags> = { }); 78 82 79 83 explicit Color(WTF::HashTableEmptyValueType); … … 299 303 { 300 304 setExtendedColor(ExtendedColor::create(color), toFlagsIncludingPrivate(flags)); 305 } 306 307 template<typename ColorType, typename std::enable_if_t<IsColorTypeWithComponentType<ColorType, float>>*> 308 inline Color::Color(const Optional<ColorType>& color, OptionSet<Flags> flags) 309 { 310 if (color) 311 setExtendedColor(ExtendedColor::create(*color), toFlagsIncludingPrivate(flags)); 301 312 } 302 313
Note: See TracChangeset
for help on using the changeset viewer.