Title: [278070] trunk/Source/WebCore
Revision
278070
Author
wei...@apple.com
Date
2021-05-25 18:10:08 -0700 (Tue, 25 May 2021)

Log Message

Support byte components for all bounded RGB color types, not just SRGBA
https://bugs.webkit.org/show_bug.cgi?id=226222

Reviewed by Darin Adler.

We currently arbitrarily restrict byte components (e.g. SRGBA<uint8_t>)
to just SRGBA by only supporting conversion for that one color type. Support
for any bounded (e.g. [0..1]) RGB type would have the same semantics and
be useful now that we can get pixel buffers that are not SRGBA only out
of ImageBuffer.

To do this, we replace the ColorConversion specializations for this type
of conversion, and inline it directly in the main conversion convert function,
allowing for a more complex conditional without SFINAE complexity.

To make things a bit simpler, this also simplifies the RGB color type descriptors
to no longer be templates, as the description of the types is always float
based, regardless of the component used. This allows for a simpler new helper,
SelfWithReplacementComponent, to convert to and from ColorType<float>/ColorType<uint8_t>.

* platform/graphics/ColorConversion.cpp:
(WebCore::SRGBA<uint8_t>>::convert): Deleted.
* platform/graphics/ColorConversion.h:
(WebCore::ColorConversion::convert):
(WebCore::ColorConversion::handleToFloatConversion):
(WebCore::ColorConversion::handleToByteConversion):
* platform/graphics/ColorTypes.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (278069 => 278070)


--- trunk/Source/WebCore/ChangeLog	2021-05-26 00:37:19 UTC (rev 278069)
+++ trunk/Source/WebCore/ChangeLog	2021-05-26 01:10:08 UTC (rev 278070)
@@ -1,3 +1,33 @@
+2021-05-25  Sam Weinig  <wei...@apple.com>
+
+        Support byte components for all bounded RGB color types, not just SRGBA
+        https://bugs.webkit.org/show_bug.cgi?id=226222
+
+        Reviewed by Darin Adler.
+
+        We currently arbitrarily restrict byte components (e.g. SRGBA<uint8_t>)
+        to just SRGBA by only supporting conversion for that one color type. Support
+        for any bounded (e.g. [0..1]) RGB type would have the same semantics and
+        be useful now that we can get pixel buffers that are not SRGBA only out
+        of ImageBuffer.
+
+        To do this, we replace the ColorConversion specializations for this type
+        of conversion, and inline it directly in the main conversion convert function,
+        allowing for a more complex conditional without SFINAE complexity.
+
+        To make things a bit simpler, this also simplifies the RGB color type descriptors
+        to no longer be templates, as the description of the types is always float
+        based, regardless of the component used. This allows for a simpler new helper,
+        SelfWithReplacementComponent, to convert to and from ColorType<float>/ColorType<uint8_t>.
+
+        * platform/graphics/ColorConversion.cpp:
+        (WebCore::SRGBA<uint8_t>>::convert): Deleted.
+        * platform/graphics/ColorConversion.h:
+        (WebCore::ColorConversion::convert):
+        (WebCore::ColorConversion::handleToFloatConversion):
+        (WebCore::ColorConversion::handleToByteConversion):
+        * platform/graphics/ColorTypes.h:
+
 2021-05-25  Chris Dumez  <cdu...@apple.com>
 
         CSP does not apply to AudioWorklets

Modified: trunk/Source/WebCore/platform/graphics/ColorConversion.cpp (278069 => 278070)


--- trunk/Source/WebCore/platform/graphics/ColorConversion.cpp	2021-05-26 00:37:19 UTC (rev 278069)
+++ trunk/Source/WebCore/platform/graphics/ColorConversion.cpp	2021-05-26 01:10:08 UTC (rev 278070)
@@ -273,22 +273,6 @@
     };
 }
 
-// MARK: SRGBA<uint8_t> conversions.
-
-SRGBA<float> ColorConversion<SRGBA<float>, SRGBA<uint8_t>>::convert(const SRGBA<uint8_t>& color)
-{
-    return makeFromComponents<SRGBA<float>>(asColorComponents(color).map([](uint8_t value) -> float {
-        return value / 255.0f;
-    }));
-}
-
-SRGBA<uint8_t> ColorConversion<SRGBA<uint8_t>, SRGBA<float>>::convert(const SRGBA<float>& color)
-{
-    return makeFromComponents<SRGBA<uint8_t>>(asColorComponents(color).map([](float value) -> uint8_t {
-        return std::clamp(std::lround(value * 255.0f), 0l, 255l);
-    }));
-}
-
 // MARK: Conversion functions for raw color components with associated color spaces.
 
 ColorComponents<float, 4> converColorComponents(ColorSpace inputColorSpace, ColorComponents<float, 4> inputColorComponents, ColorSpace outputColorSpace)

Modified: trunk/Source/WebCore/platform/graphics/ColorConversion.h (278069 => 278070)


--- trunk/Source/WebCore/platform/graphics/ColorConversion.h	2021-05-26 00:37:19 UTC (rev 278069)
+++ trunk/Source/WebCore/platform/graphics/ColorConversion.h	2021-05-26 01:10:08 UTC (rev 278070)
@@ -114,16 +114,6 @@
     WEBCORE_EXPORT static Lab<float> convert(const XYZA<float, WhitePoint::D50>&);
 };
 
-// MARK: SRGBA<uint8_t>
-// Only sRGB supports non-floating point component types.
-template<> struct ColorConversion<SRGBA<float>, SRGBA<uint8_t>> {
-    WEBCORE_EXPORT static SRGBA<float> convert(const SRGBA<uint8_t>&);
-};
-template<> struct ColorConversion<SRGBA<uint8_t>, SRGBA<float>> {
-    WEBCORE_EXPORT static SRGBA<uint8_t> convert(const SRGBA<float>&);
-};
-
-
 // Identity conversion.
 
 template<typename ColorType> struct ColorConversion<ColorType, ColorType> {
@@ -154,19 +144,21 @@
 // │    Lab    │    ││ Gamma  │ │ GammaExtended  ││   │   ││ Gamma  │ │ GammaExtended  ││ ││ Gamma  │ │ GammaExtended  ││ ││ Gamma  │ │ GammaExtended  ││ ││ Gamma  │ │ GammaExtended  ││
 // └─────▲─────┘    │└────────┘ └────────────────┘│   │   │└────▲───┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│ │└────────┘ └────────────────┘│
 //       │          └─────────────────────────────┘   │   └─────┼───────────────────────┘ └─────────────────────────────┘ └─────────────────────────────┘ └─────────────────────────────┘
-//       │                                            │      ┌──┴──────────┬─────────────┐
-//       │                                            │      │             │             │
-// ┌───────────┐                                      │┌───────────┐ ┌───────────┐┌─────────────┐
-// │    LCH    │                                      ││    HSL    │ │    HWB    ││SRGB<uint8_t>│
-// └───────────┘                                      │└───────────┘ └───────────┘└─────────────┘
+//       │                                            │      ┌──┴──────────┐
+//       │                                            │      │             │
+// ┌───────────┐                                      │┌───────────┐ ┌───────────┐
+// │    LCH    │                                      ││    HSL    │ │    HWB    │
+// └───────────┘                                      │└───────────┘ └───────────┘
 
 template<typename Output, typename Input, typename> struct ColorConversion {
 public:
     static constexpr Output convert(const Input& color)
     {
-        // 1. Handle the special case SRGBA<uint8_t> for Input and Output.
-        if constexpr (std::is_same_v<Input, SRGBA<uint8_t>> || std::is_same_v<Output, SRGBA<uint8_t>>)
-            return convertColor<Output>(convertColor<SRGBA<float>>(color));
+        // 1. Handle the special case of Input or Output with a uint8_t component type.
+        if constexpr (std::is_same_v<typename Input::ComponentType, uint8_t>)
+            return handleToFloatConversion(color);
+        else if constexpr (std::is_same_v<typename Output::ComponentType, uint8_t>)
+            return handleToByteConversion(color);
 
         // 2. Handle all color types that are not IsRGBType<T> or IsXYZA<T> for Input and Output. For all
         //    these other color types, we can uncondtionally convert them to their "reference" color, as
@@ -194,6 +186,28 @@
     }
 
 private:
+    static inline constexpr Output handleToFloatConversion(const Input& color)
+    {
+        static_assert(IsRGBBoundedType<Input>, "Only bounded ([0..1]) RGB color types support conversion to/from bytes.");
+
+        using InputWithReplacement = ColorTypeWithReplacementComponent<Input, float>;
+        if constexpr (std::is_same_v<InputWithReplacement, Output>)
+            return makeFromComponents<InputWithReplacement>(asColorComponents(color).map([](uint8_t value) -> float { return value / 255.0f; }));
+        else
+            return convertColor<Output>(convertColor<InputWithReplacement>(color));
+    }
+
+    static inline constexpr Output handleToByteConversion(const Input& color)
+    {
+        static_assert(IsRGBBoundedType<Output>, "Only bounded ([0..1]) RGB color types support conversion to/from bytes.");
+
+        using OutputWithReplacement = ColorTypeWithReplacementComponent<Output, float>;
+        if constexpr (std::is_same_v<OutputWithReplacement, Input>)
+            return makeFromComponents<Output>(asColorComponents(color).map([](float value) -> uint8_t { return std::clamp(std::lround(value * 255.0f), 0l, 255l); }));
+        else
+            return convertColor<Output>(convertColor<OutputWithReplacement>(color));
+    }
+
     template<typename ColorType> static inline constexpr auto toLinearEncoded(const ColorType& color) -> typename ColorType::LinearCounterpart
     {
         auto [c1, c2, c3, alpha] = color;

Modified: trunk/Source/WebCore/platform/graphics/ColorTypes.h (278069 => 278070)


--- trunk/Source/WebCore/platform/graphics/ColorTypes.h	2021-05-26 00:37:19 UTC (rev 278069)
+++ trunk/Source/WebCore/platform/graphics/ColorTypes.h	2021-05-26 01:10:08 UTC (rev 278070)
@@ -158,6 +158,9 @@
 template<typename T> inline constexpr bool IsColorType = IsConvertibleToColorComponents<T> && HasComponentTypeMember<T>;
 template<typename T, typename U> inline constexpr bool IsColorTypeWithComponentType = IsConvertibleToColorComponents<T> && HasComponentType<T, U>;
 
+template<template<typename> class ColorType, typename Replacement> struct ColorTypeReplacingComponentTypeHelper { using type = ColorType<Replacement>; };
+template<template<typename> class ColorType, typename Replacement> using ColorTypeReplacingComponentType = typename ColorTypeReplacingComponentTypeHelper<ColorType, Replacement>::type;
+
 template<typename Parent> struct ColorWithAlphaHelper {
     // Helper to allow convenient syntax for working with color types.
     // e.g. auto yellowWith50PercentAlpha = Color::yellow.colorWithAlphaByte(128);
@@ -221,16 +224,18 @@
 
 
 template<typename T, typename D>
-struct BoundedGammaEncoded : RGBAType<T, D, BoundedGammaEncoded<T, D>, RGBModel<T>, typename D::template TransferFunction<TransferFunctionMode::Clamped>> {
-    using RGBAType<T, D, BoundedGammaEncoded<T, D>, RGBModel<T>, typename D::template TransferFunction<TransferFunctionMode::Clamped>>::RGBAType;
+struct BoundedGammaEncoded : RGBAType<T, D, BoundedGammaEncoded<T, D>, RGBModel<T>, typename D::template TransferFunction<T, TransferFunctionMode::Clamped>> {
+    using RGBAType<T, D, BoundedGammaEncoded<T, D>, RGBModel<T>, typename D::template TransferFunction<T, TransferFunctionMode::Clamped>>::RGBAType;
 
     using LinearCounterpart = BoundedLinearEncoded<T, D>;
     using ExtendedCounterpart = ExtendedGammaEncoded<T, D>;
+    
+    template<typename Replacement> using SelfWithReplacementComponent = BoundedGammaEncoded<Replacement, D>;
 };
 
 template<typename T, typename D>
-struct BoundedLinearEncoded : RGBAType<T, D, BoundedLinearEncoded<T, D>, RGBModel<T>, typename D::template TransferFunction<TransferFunctionMode::Clamped>> {
-    using RGBAType<T, D, BoundedLinearEncoded<T, D>, RGBModel<T>, typename D::template TransferFunction<TransferFunctionMode::Clamped>>::RGBAType;
+struct BoundedLinearEncoded : RGBAType<T, D, BoundedLinearEncoded<T, D>, RGBModel<T>, typename D::template TransferFunction<T, TransferFunctionMode::Clamped>> {
+    using RGBAType<T, D, BoundedLinearEncoded<T, D>, RGBModel<T>, typename D::template TransferFunction<T, TransferFunctionMode::Clamped>>::RGBAType;
 
     static constexpr auto linearToXYZ = D::linearToXYZ;
     static constexpr auto xyzToLinear = D::xyzToLinear;
@@ -237,11 +242,13 @@
 
     using GammaEncodedCounterpart = BoundedGammaEncoded<T, D>;
     using ExtendedCounterpart = ExtendedLinearEncoded<T, D>;
+
+    template<typename Replacement> using SelfWithReplacementComponent = BoundedLinearEncoded<Replacement, D>;
 };
 
 template<typename T, typename D>
-struct ExtendedGammaEncoded : RGBAType<T, D, ExtendedGammaEncoded<T, D>, ExtendedRGBModel<T>, typename D::template TransferFunction<TransferFunctionMode::Unclamped>> {
-    using RGBAType<T, D, ExtendedGammaEncoded<T, D>, ExtendedRGBModel<T>, typename D::template TransferFunction<TransferFunctionMode::Unclamped>>::RGBAType;
+struct ExtendedGammaEncoded : RGBAType<T, D, ExtendedGammaEncoded<T, D>, ExtendedRGBModel<T>, typename D::template TransferFunction<T, TransferFunctionMode::Unclamped>> {
+    using RGBAType<T, D, ExtendedGammaEncoded<T, D>, ExtendedRGBModel<T>, typename D::template TransferFunction<T, TransferFunctionMode::Unclamped>>::RGBAType;
 
     using LinearCounterpart = ExtendedLinearEncoded<T, D>;
     using BoundedCounterpart = BoundedGammaEncoded<T, D>;
@@ -249,8 +256,8 @@
 };
 
 template<typename T, typename D>
-struct ExtendedLinearEncoded : RGBAType<T, D, ExtendedLinearEncoded<T, D>, ExtendedRGBModel<T>, typename D::template TransferFunction<TransferFunctionMode::Unclamped>> {
-    using RGBAType<T, D, ExtendedLinearEncoded<T, D>, ExtendedRGBModel<T>, typename D::template TransferFunction<TransferFunctionMode::Unclamped>>::RGBAType;
+struct ExtendedLinearEncoded : RGBAType<T, D, ExtendedLinearEncoded<T, D>, ExtendedRGBModel<T>, typename D::template TransferFunction<T, TransferFunctionMode::Unclamped>> {
+    using RGBAType<T, D, ExtendedLinearEncoded<T, D>, ExtendedRGBModel<T>, typename D::template TransferFunction<T, TransferFunctionMode::Unclamped>>::RGBAType;
 
     static constexpr auto linearToXYZ = D::linearToXYZ;
     static constexpr auto xyzToLinear = D::xyzToLinear;
@@ -275,6 +282,11 @@
 template<typename, typename = void> inline constexpr bool HasLinearCounterpartMember = false;
 template<typename ColorType> inline constexpr bool HasLinearCounterpartMember<ColorType, std::void_t<typename ColorType::LinearCounterpart>> = true;
 
+template<typename, typename = void> inline constexpr bool HasSelfWithReplacementComponentMember = false;
+template<typename ColorType> inline constexpr bool HasSelfWithReplacementComponentMember<ColorType, std::void_t<typename ColorType::SelfWithReplacementComponent>> = true;
+
+template<typename ColorType, typename Replacement> using ColorTypeWithReplacementComponent = typename ColorType::template SelfWithReplacementComponent<Replacement>;
+
 template<typename ColorType> inline constexpr bool IsRGBType = HasDescriptorMember<ColorType>;
 template<typename ColorType> inline constexpr bool IsRGBExtendedType = IsRGBType<ColorType> && HasBoundedCounterpartMember<ColorType>;
 template<typename ColorType> inline constexpr bool IsRGBBoundedType = IsRGBType<ColorType> && HasExtendedCounterpartMember<ColorType>;
@@ -285,8 +297,8 @@
 template<typename ColorType1, typename ColorType2> inline constexpr bool IsSameRGBTypeFamilyValue<ColorType1, ColorType2, true> = std::is_same_v<typename ColorType1::Descriptor, typename ColorType2::Descriptor>;
 template<typename ColorType1, typename ColorType2> inline constexpr bool IsSameRGBTypeFamily = IsSameRGBTypeFamilyValue<ColorType1, ColorType2, IsRGBType<ColorType1> && IsRGBType<ColorType2>>;
 
-template<typename T> struct SRGBADescriptor {
-    template<TransferFunctionMode Mode> using TransferFunction = SRGBTransferFunction<T, Mode>;
+struct SRGBADescriptor {
+    template<typename T, TransferFunctionMode Mode> using TransferFunction = SRGBTransferFunction<T, Mode>;
     static constexpr WhitePoint whitePoint = WhitePoint::D65;
 
     // https://drafts.csswg.org/css-color/#color-conversion-code
@@ -302,14 +314,14 @@
     };
 };
 
-template<typename T> using SRGBA = BoundedGammaEncoded<T, SRGBADescriptor<T>>;
-template<typename T> using LinearSRGBA = BoundedLinearEncoded<T, SRGBADescriptor<T>>;
-template<typename T> using ExtendedSRGBA = ExtendedGammaEncoded<T, SRGBADescriptor<T>>;
-template<typename T> using LinearExtendedSRGBA = ExtendedLinearEncoded<T, SRGBADescriptor<T>>;
+template<typename T> using SRGBA = BoundedGammaEncoded<T, SRGBADescriptor>;
+template<typename T> using LinearSRGBA = BoundedLinearEncoded<T, SRGBADescriptor>;
+template<typename T> using ExtendedSRGBA = ExtendedGammaEncoded<T, SRGBADescriptor>;
+template<typename T> using LinearExtendedSRGBA = ExtendedLinearEncoded<T, SRGBADescriptor>;
 
 
-template<typename T> struct A98RGBDescriptor {
-    template<TransferFunctionMode Mode> using TransferFunction = A98RGBTransferFunction<T, Mode>;
+struct A98RGBDescriptor {
+    template<typename T, TransferFunctionMode Mode> using TransferFunction = A98RGBTransferFunction<T, Mode>;
     static constexpr WhitePoint whitePoint = WhitePoint::D65;
 
     // https://drafts.csswg.org/css-color/#color-conversion-code
@@ -325,12 +337,12 @@
     };
 };
 
-template<typename T> using A98RGB = BoundedGammaEncoded<T, A98RGBDescriptor<T>>;
-template<typename T> using LinearA98RGB = BoundedLinearEncoded<T, A98RGBDescriptor<T>>;
+template<typename T> using A98RGB = BoundedGammaEncoded<T, A98RGBDescriptor>;
+template<typename T> using LinearA98RGB = BoundedLinearEncoded<T, A98RGBDescriptor>;
 
 
-template<typename T> struct DisplayP3Descriptor {
-    template<TransferFunctionMode Mode> using TransferFunction = SRGBTransferFunction<T, Mode>;
+struct DisplayP3Descriptor {
+    template<typename T, TransferFunctionMode Mode> using TransferFunction = SRGBTransferFunction<T, Mode>;
     static constexpr WhitePoint whitePoint = WhitePoint::D65;
 
     // https://drafts.csswg.org/css-color/#color-conversion-code
@@ -346,12 +358,12 @@
     };
 };
 
-template<typename T> using DisplayP3 = BoundedGammaEncoded<T, DisplayP3Descriptor<T>>;
-template<typename T> using LinearDisplayP3 = BoundedLinearEncoded<T, DisplayP3Descriptor<T>>;
+template<typename T> using DisplayP3 = BoundedGammaEncoded<T, DisplayP3Descriptor>;
+template<typename T> using LinearDisplayP3 = BoundedLinearEncoded<T, DisplayP3Descriptor>;
 
 
-template<typename T> struct ProPhotoRGBDescriptor {
-    template<TransferFunctionMode Mode> using TransferFunction = ProPhotoRGBTransferFunction<T, Mode>;
+struct ProPhotoRGBDescriptor {
+    template<typename T, TransferFunctionMode Mode> using TransferFunction = ProPhotoRGBTransferFunction<T, Mode>;
     static constexpr WhitePoint whitePoint = WhitePoint::D50;
 
     // https://drafts.csswg.org/css-color/#color-conversion-code
@@ -367,12 +379,12 @@
     };
 };
 
-template<typename T> using ProPhotoRGB = BoundedGammaEncoded<T, ProPhotoRGBDescriptor<T>>;
-template<typename T> using LinearProPhotoRGB = BoundedLinearEncoded<T, ProPhotoRGBDescriptor<T>>;
+template<typename T> using ProPhotoRGB = BoundedGammaEncoded<T, ProPhotoRGBDescriptor>;
+template<typename T> using LinearProPhotoRGB = BoundedLinearEncoded<T, ProPhotoRGBDescriptor>;
 
 
-template<typename T> struct Rec2020Descriptor {
-    template<TransferFunctionMode Mode> using TransferFunction = Rec2020TransferFunction<T, Mode>;
+struct Rec2020Descriptor {
+    template<typename T, TransferFunctionMode Mode> using TransferFunction = Rec2020TransferFunction<T, Mode>;
     static constexpr WhitePoint whitePoint = WhitePoint::D65;
 
     // https://drafts.csswg.org/css-color/#color-conversion-code
@@ -388,8 +400,8 @@
     };
 };
 
-template<typename T> using Rec2020 = BoundedGammaEncoded<T, Rec2020Descriptor<T>>;
-template<typename T> using LinearRec2020 = BoundedLinearEncoded<T, Rec2020Descriptor<T>>;
+template<typename T> using Rec2020 = BoundedGammaEncoded<T, Rec2020Descriptor>;
+template<typename T> using LinearRec2020 = BoundedLinearEncoded<T, Rec2020Descriptor>;
 
 
 // MARK: - Lab Color Type.
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to