Extended Color: Experiment with strongly typed ColorComponents
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 13 Jun 2020 16:42:58 +0000 (16:42 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 13 Jun 2020 16:42:58 +0000 (16:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=212396

Reviewed by Darin Adler.

Source/WebCore:

Adds simple explicit types for sRGBA, LinearSRGBA, DisplayP3,
LinearDisplayP3, XYZA and HSLA colors. Conversion to/from
ColorComponents<float> is easy but explicit to make conversions
easier to spot.

The goal is to add type clarity (you know when you are dealing
with an sRGB color vs. a DisplayP3 color) and make dealing with
the colors nicer (color.red rather than color[0]). It also allows
us to simplify the naming of functions that convert between color
types as now only the output type needs to be in the function name.

* Headers.cmake:
Add new header, ColorTypes.h

* WebCore.xcodeproj/project.pbxproj:
Add new header, ColorTypes.h

* css/parser/CSSPropertyParserHelpers.cpp:
(WebCore::CSSPropertyParserHelpers::parseHSLParameters):
Switch from hslToSRGB({ ... }) to toSRGBA(HSLAColor { ... })

* editing/cocoa/DataDetection.mm:
(WebCore::DataDetection::detectContentInRange):
Update to use toHSLA() and HSLA<float> making the code a bit more readable.

* platform/graphics/Color.cpp:
(WebCore::Color::lightened const):
(WebCore::Color::darkened const):
(WebCore::Color::isDark const):
(WebCore::Color::lightness const):
(WebCore::Color::luminance const):
(WebCore::Color::colorSpaceAndComponents const):
(WebCore::Color::toSRGBASimpleColorLossy const):
(WebCore::Color::toSRGBALossy const):
(WebCore::Color::toSRGBAComponentsLossy const): Deleted.
* platform/graphics/Color.h:
Renames toSRGBAComponentsLossy() to toSRGBALossy() which now returns
a SRGBA<float>.

* platform/graphics/ColorMatrix.h:
(WebCore::ColorMatrix::transformColorComponents const): Deleted.
Remove transformColorComponents, keeping just transformedColorComponents
to simplify the interface. With late conversion to ColorComponents, the
latter is more straightforward to use in most cases anyway.

* platform/graphics/ColorUtilities.cpp:
(WebCore::linearToRGBColorComponent):
(WebCore::rgbToLinearColorComponent):
(WebCore::toLinearSRGBA):
(WebCore::toSRGBA):
(WebCore::toLinearDisplayP3):
(WebCore::toDisplayP3):
(WebCore::toXYZ):
(WebCore::lightness):
(WebCore::luminance):
(WebCore::contrastRatio):
(WebCore::toHSLA):
(WebCore::premultiplied):
(WebCore::rgbToLinearComponents): Deleted.
(WebCore::linearToRGBComponents): Deleted.
(WebCore::xyzToLinearSRGB): Deleted.
(WebCore::linearSRGBToXYZ): Deleted.
(WebCore::XYZToLinearP3): Deleted.
(WebCore::linearP3ToXYZ): Deleted.
(WebCore::p3ToSRGB): Deleted.
(WebCore::sRGBToP3): Deleted.
(WebCore::sRGBToHSL): Deleted.
(WebCore::hslToSRGB): Deleted.
* platform/graphics/ColorUtilities.h:
Rename / rework conversion and utility functions to operate on explicit Color
types. In doing so, simplify the names of the conversion functions so only name
the output type. For instance:

    ColorComponents<float> p3ToSRGB(const ColorComponents<float>&);

is now

    SRGBA<float> toSRGBA(const DisplayP3<float>&);

as the input type is implicit in the call. A little duplication was needed
for linearToRGBColorComponent/rgbToLinearColorComponent (as it was used for
both sRGB and DisplayP3 linearization), but mostly things stay the same.

* platform/graphics/ExtendedColor.cpp:
(WebCore::ExtendedColor::toSRGBALossy const):
(WebCore::ExtendedColor::toSRGBAComponentsLossy const): Deleted.
* platform/graphics/ExtendedColor.h:
Renamed toSRGBAComponentsLossy() to toSRGBALossy() and have it
return a SRGBA<float>.

* platform/graphics/SimpleColor.h:
(WebCore::SimpleColor::asSRGBA const):
(WebCore::makeSimpleColor):
(WebCore::SimpleColor::asSRGBFloatComponents const): Deleted.
Rename asSRGBFloatComponents() to asSRGBA<T>() and have it
return a SRGBA<float>. Replace makeSimpleColor taking FloatComponents
with one taking a SRGBA<float>, making it much clearer that this
is only valid for sRGB.

* platform/graphics/filters/FELighting.cpp:
(WebCore::FELighting::drawLighting):
Rework to support seperate types for SRGB<float> and LinearSRGBA<float>.

* platform/graphics/filters/FELighting.cpp:
(WebCore::FELighting::drawLighting):
* platform/graphics/filters/FilterOperation.cpp:
(WebCore::BasicColorMatrixFilterOperation::transformColor const):
(WebCore::BasicComponentTransferFilterOperation::transformColor const):
(WebCore::InvertLightnessFilterOperation::transformColor const):
(WebCore::InvertLightnessFilterOperation::inverseTransformColor const):
* platform/graphics/filters/FilterOperation.h:
(WebCore::FilterOperation::transformColor const):
(WebCore::FilterOperation::inverseTransformColor const):
* platform/graphics/filters/FilterOperations.cpp:
(WebCore::FilterOperations::transformColor const):
(WebCore::FilterOperations::inverseTransformColor const):
Use SRGBA<float> rather than ColorComponents<float> to make it clear
that the filters only work on sRGB colors right now.

* rendering/RenderTheme.cpp:
(WebCore::RenderTheme::disabledTextColor const):
* rendering/TextPaintStyle.cpp:
(WebCore::textColorIsLegibleAgainstBackgroundColor):
* platform/graphics/cairo/CairoUtilities.cpp:
(WebCore::setSourceRGBAFromColor):
* platform/graphics/cairo/GradientCairo.cpp:
(WebCore::addColorStopRGBA):
(WebCore::setCornerColorRGBA):
(WebCore::interpolateColorStop):
* platform/graphics/gtk/ColorGtk.cpp:
(WebCore::Color::operator GdkRGBA const):
* platform/graphics/texmap/TextureMapperGL.cpp:
(WebCore::TextureMapperGL::drawBorder):
(WebCore::TextureMapperGL::drawNumber):
(WebCore::prepareFilterProgram):
(WebCore::TextureMapperGL::drawSolidColor):
(WebCore::TextureMapperGL::clearColor):
* platform/graphics/win/ColorDirect2D.cpp:
(WebCore::Color::operator D2D1_COLOR_F const):
(WebCore::Color::operator D2D1_VECTOR_4F const):
* platform/graphics/win/GradientDirect2D.cpp:
(WebCore::Gradient::generateGradient):
* platform/graphics/win/GraphicsContextDirect2D.cpp:
(WebCore::GraphicsContext::colorWithGlobalAlpha const):
Update to call toSRGBALossy() rather than toSRGBAComponentsLossy().

Source/WebKit:

* UIProcess/API/wpe/WebKitColor.cpp:
(webkitColorFillFromWebCoreColor):
* UIProcess/gtk/ViewGestureControllerGtk.cpp:
(WebKit::ViewGestureController::beginSwipeGesture):
* WebProcess/WebPage/WebFrame.cpp:
(WebKit::WebFrame::getDocumentBackgroundColor):
Update to call toSRGBALossy() rather than toSRGBAComponentsLossy().

Tools:

* TestWebKitAPI/Tests/WebCore/ColorTests.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebCore/ExtendedColorTests.cpp:
(TestWebKitAPI::TEST):
Update for changed names (e.g. toSRGBAComponentsLossy() -> toSRGBALossy())
and use of explicit types.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@263000 268f45cc-cd09-0410-ab3c-d52691b4dbfc

34 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Headers.cmake
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp
Source/WebCore/editing/cocoa/DataDetection.mm
Source/WebCore/platform/graphics/Color.cpp
Source/WebCore/platform/graphics/Color.h
Source/WebCore/platform/graphics/ColorMatrix.h
Source/WebCore/platform/graphics/ColorTypes.h [new file with mode: 0644]
Source/WebCore/platform/graphics/ColorUtilities.cpp
Source/WebCore/platform/graphics/ColorUtilities.h
Source/WebCore/platform/graphics/ExtendedColor.cpp
Source/WebCore/platform/graphics/ExtendedColor.h
Source/WebCore/platform/graphics/SimpleColor.h
Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
Source/WebCore/platform/graphics/cairo/GradientCairo.cpp
Source/WebCore/platform/graphics/filters/FELighting.cpp
Source/WebCore/platform/graphics/filters/FilterOperation.cpp
Source/WebCore/platform/graphics/filters/FilterOperation.h
Source/WebCore/platform/graphics/filters/FilterOperations.cpp
Source/WebCore/platform/graphics/gtk/ColorGtk.cpp
Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
Source/WebCore/platform/graphics/win/ColorDirect2D.cpp
Source/WebCore/platform/graphics/win/GradientDirect2D.cpp
Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp
Source/WebCore/rendering/RenderTheme.cpp
Source/WebCore/rendering/TextPaintStyle.cpp
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/wpe/WebKitColor.cpp
Source/WebKit/UIProcess/gtk/ViewGestureControllerGtk.cpp
Source/WebKit/WebProcess/WebPage/WebFrame.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebCore/ColorTests.cpp
Tools/TestWebKitAPI/Tests/WebCore/ExtendedColorTests.cpp

index 1fef5d5..30a94ea 100644 (file)
@@ -1,3 +1,156 @@
+2020-06-13  Sam Weinig  <weinig@apple.com>
+
+        Extended Color: Experiment with strongly typed ColorComponents
+        https://bugs.webkit.org/show_bug.cgi?id=212396
+
+        Reviewed by Darin Adler.
+
+        Adds simple explicit types for sRGBA, LinearSRGBA, DisplayP3, 
+        LinearDisplayP3, XYZA and HSLA colors. Conversion to/from
+        ColorComponents<float> is easy but explicit to make conversions
+        easier to spot.
+
+        The goal is to add type clarity (you know when you are dealing
+        with an sRGB color vs. a DisplayP3 color) and make dealing with
+        the colors nicer (color.red rather than color[0]). It also allows
+        us to simplify the naming of functions that convert between color 
+        types as now only the output type needs to be in the function name.
+        * Headers.cmake:
+        Add new header, ColorTypes.h
+
+        * WebCore.xcodeproj/project.pbxproj:
+        Add new header, ColorTypes.h
+
+        * css/parser/CSSPropertyParserHelpers.cpp:
+        (WebCore::CSSPropertyParserHelpers::parseHSLParameters):
+        Switch from hslToSRGB({ ... }) to toSRGBA(HSLAColor { ... })
+
+        * editing/cocoa/DataDetection.mm:
+        (WebCore::DataDetection::detectContentInRange):
+        Update to use toHSLA() and HSLA<float> making the code a bit more readable.
+
+        * platform/graphics/Color.cpp:
+        (WebCore::Color::lightened const):
+        (WebCore::Color::darkened const):
+        (WebCore::Color::isDark const):
+        (WebCore::Color::lightness const):
+        (WebCore::Color::luminance const):
+        (WebCore::Color::colorSpaceAndComponents const):
+        (WebCore::Color::toSRGBASimpleColorLossy const):
+        (WebCore::Color::toSRGBALossy const):
+        (WebCore::Color::toSRGBAComponentsLossy const): Deleted.
+        * platform/graphics/Color.h:
+        Renames toSRGBAComponentsLossy() to toSRGBALossy() which now returns
+        a SRGBA<float>.
+        
+        * platform/graphics/ColorMatrix.h:
+        (WebCore::ColorMatrix::transformColorComponents const): Deleted.
+        Remove transformColorComponents, keeping just transformedColorComponents
+        to simplify the interface. With late conversion to ColorComponents, the
+        latter is more straightforward to use in most cases anyway.
+        
+        * platform/graphics/ColorUtilities.cpp:
+        (WebCore::linearToRGBColorComponent):
+        (WebCore::rgbToLinearColorComponent):
+        (WebCore::toLinearSRGBA):
+        (WebCore::toSRGBA):
+        (WebCore::toLinearDisplayP3):
+        (WebCore::toDisplayP3):
+        (WebCore::toXYZ):
+        (WebCore::lightness):
+        (WebCore::luminance):
+        (WebCore::contrastRatio):
+        (WebCore::toHSLA):
+        (WebCore::premultiplied):
+        (WebCore::rgbToLinearComponents): Deleted.
+        (WebCore::linearToRGBComponents): Deleted.
+        (WebCore::xyzToLinearSRGB): Deleted.
+        (WebCore::linearSRGBToXYZ): Deleted.
+        (WebCore::XYZToLinearP3): Deleted.
+        (WebCore::linearP3ToXYZ): Deleted.
+        (WebCore::p3ToSRGB): Deleted.
+        (WebCore::sRGBToP3): Deleted.
+        (WebCore::sRGBToHSL): Deleted.
+        (WebCore::hslToSRGB): Deleted.
+        * platform/graphics/ColorUtilities.h:
+        Rename / rework conversion and utility functions to operate on explicit Color 
+        types. In doing so, simplify the names of the conversion functions so only name
+        the output type. For instance:
+
+            ColorComponents<float> p3ToSRGB(const ColorComponents<float>&);
+            
+        is now 
+        
+            SRGBA<float> toSRGBA(const DisplayP3<float>&);
+        
+        as the input type is implicit in the call. A little duplication was needed 
+        for linearToRGBColorComponent/rgbToLinearColorComponent (as it was used for
+        both sRGB and DisplayP3 linearization), but mostly things stay the same.
+        
+        * platform/graphics/ExtendedColor.cpp:
+        (WebCore::ExtendedColor::toSRGBALossy const):
+        (WebCore::ExtendedColor::toSRGBAComponentsLossy const): Deleted.
+        * platform/graphics/ExtendedColor.h:
+        Renamed toSRGBAComponentsLossy() to toSRGBALossy() and have it
+        return a SRGBA<float>.
+
+        * platform/graphics/SimpleColor.h:
+        (WebCore::SimpleColor::asSRGBA const):
+        (WebCore::makeSimpleColor):
+        (WebCore::SimpleColor::asSRGBFloatComponents const): Deleted.
+        Rename asSRGBFloatComponents() to asSRGBA<T>() and have it 
+        return a SRGBA<float>. Replace makeSimpleColor taking FloatComponents
+        with one taking a SRGBA<float>, making it much clearer that this
+        is only valid for sRGB.
+
+        * platform/graphics/filters/FELighting.cpp:
+        (WebCore::FELighting::drawLighting):
+        Rework to support seperate types for SRGB<float> and LinearSRGBA<float>.
+
+        * platform/graphics/filters/FELighting.cpp:
+        (WebCore::FELighting::drawLighting):
+        * platform/graphics/filters/FilterOperation.cpp:
+        (WebCore::BasicColorMatrixFilterOperation::transformColor const):
+        (WebCore::BasicComponentTransferFilterOperation::transformColor const):
+        (WebCore::InvertLightnessFilterOperation::transformColor const):
+        (WebCore::InvertLightnessFilterOperation::inverseTransformColor const):
+        * platform/graphics/filters/FilterOperation.h:
+        (WebCore::FilterOperation::transformColor const):
+        (WebCore::FilterOperation::inverseTransformColor const):
+        * platform/graphics/filters/FilterOperations.cpp:
+        (WebCore::FilterOperations::transformColor const):
+        (WebCore::FilterOperations::inverseTransformColor const):
+        Use SRGBA<float> rather than ColorComponents<float> to make it clear
+        that the filters only work on sRGB colors right now.
+
+        * rendering/RenderTheme.cpp:
+        (WebCore::RenderTheme::disabledTextColor const):
+        * rendering/TextPaintStyle.cpp:
+        (WebCore::textColorIsLegibleAgainstBackgroundColor):
+        * platform/graphics/cairo/CairoUtilities.cpp:
+        (WebCore::setSourceRGBAFromColor):
+        * platform/graphics/cairo/GradientCairo.cpp:
+        (WebCore::addColorStopRGBA):
+        (WebCore::setCornerColorRGBA):
+        (WebCore::interpolateColorStop):
+        * platform/graphics/gtk/ColorGtk.cpp:
+        (WebCore::Color::operator GdkRGBA const):
+        * platform/graphics/texmap/TextureMapperGL.cpp:
+        (WebCore::TextureMapperGL::drawBorder):
+        (WebCore::TextureMapperGL::drawNumber):
+        (WebCore::prepareFilterProgram):
+        (WebCore::TextureMapperGL::drawSolidColor):
+        (WebCore::TextureMapperGL::clearColor):
+        * platform/graphics/win/ColorDirect2D.cpp:
+        (WebCore::Color::operator D2D1_COLOR_F const):
+        (WebCore::Color::operator D2D1_VECTOR_4F const):
+        * platform/graphics/win/GradientDirect2D.cpp:
+        (WebCore::Gradient::generateGradient):
+        * platform/graphics/win/GraphicsContextDirect2D.cpp:
+        (WebCore::GraphicsContext::colorWithGlobalAlpha const):
+        Update to call toSRGBALossy() rather than toSRGBAComponentsLossy().
+
 2020-06-13  Tetsuharu Ohzeki  <tetsuharu.ohzeki@gmail.com>
 
         Remove FileError.h
index b9b8b90..52d4386 100644 (file)
@@ -1082,6 +1082,7 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS
     platform/graphics/ColorHash.h
     platform/graphics/ColorMatrix.h
     platform/graphics/ColorSpace.h
+    platform/graphics/ColorTypes.h
     platform/graphics/ColorUtilities.h
     platform/graphics/ComplexTextController.h
     platform/graphics/ConcreteImageBuffer.h
index 6eb5b48..697bbbe 100644 (file)
                7AF9B20D18CFB5F400C64BEF /* JSVTTRegion.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AF9B20918CFB5F200C64BEF /* JSVTTRegion.h */; };
                7AF9B20F18CFB5F400C64BEF /* JSVTTRegionList.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AF9B20B18CFB5F300C64BEF /* JSVTTRegionList.h */; };
                7BE7427381FA906FBB4F0F2C /* JSSVGGraphicsElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 950C4C02BED8936F818E2F99 /* JSSVGGraphicsElement.h */; };
+               7C029C6E2493C8F800268204 /* ColorTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C029C6D2493C8F800268204 /* ColorTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C1843FE1C8B7283002EB973 /* Autofill.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C1843FC1C8B7283002EB973 /* Autofill.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C193BBB1F5E0EED0088F3E6 /* CanvasDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C193BB61F5E0EB90088F3E6 /* CanvasDirection.h */; };
                7C193BBC1F5E0EED0088F3E6 /* CanvasFillRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C193BA11F5E0EAB0088F3E6 /* CanvasFillRule.h */; };
                7AF9B20918CFB5F200C64BEF /* JSVTTRegion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVTTRegion.h; sourceTree = "<group>"; };
                7AF9B20A18CFB5F300C64BEF /* JSVTTRegionList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSVTTRegionList.cpp; sourceTree = "<group>"; };
                7AF9B20B18CFB5F300C64BEF /* JSVTTRegionList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVTTRegionList.h; sourceTree = "<group>"; };
+               7C029C6D2493C8F800268204 /* ColorTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorTypes.h; sourceTree = "<group>"; };
                7C0CEF281E4A542C008DEB80 /* JSDOMConstructorBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMConstructorBase.h; sourceTree = "<group>"; };
                7C0CEF291E4A54D3008DEB80 /* JSDOMConstructorWithDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMConstructorWithDocument.h; sourceTree = "<group>"; };
                7C0CEF2A1E4A556C008DEB80 /* JSDOMBuiltinConstructorBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMBuiltinConstructorBase.h; sourceTree = "<group>"; };
                                3103B7DE1DB01556008BB890 /* ColorHash.h */,
                                7CAC6AE8247F082000E61D59 /* ColorMatrix.h */,
                                9382DF5710A8D5C900925652 /* ColorSpace.h */,
+                               7C029C6D2493C8F800268204 /* ColorTypes.h */,
                                0FE6C76B1FBFB7A60025C053 /* ColorUtilities.cpp */,
                                0FE6C76C1FBFB7A60025C053 /* ColorUtilities.h */,
                                C2F4E7881E45AEDF006D7105 /* ComplexTextController.cpp */,
                                FE36FD1816C7826500F887C1 /* SQLTransactionState.h in Headers */,
                                FE36FD1716C7826500F887C1 /* SQLTransactionStateMachine.h in Headers */,
                                1A2E6E5A0CC55213004A2062 /* SQLValue.h in Headers */,
+                               7C029C6E2493C8F800268204 /* ColorTypes.h in Headers */,
                                93F1996308245E59001E9ABC /* SSLKeyGenerator.h in Headers */,
                                26B999911803B3C900D01121 /* StackAllocator.h in Headers */,
                                BC7FA62D0D1F0EFF00DB22A9 /* StaticNodeList.h in Headers */,
index 0ebfad1..1823975 100644 (file)
@@ -640,7 +640,7 @@ static Color parseHSLParameters(CSSParserTokenRange& range, CSSParserMode cssPar
     if (!args.atEnd())
         return Color();
 
-    return makeSimpleColor(hslToSRGB({ static_cast<float>(colorArray[0]), static_cast<float>(colorArray[1]), static_cast<float>(colorArray[2]), static_cast<float>(alpha) }));
+    return makeSimpleColor(toSRGBA(HSLA<float> { static_cast<float>(colorArray[0]), static_cast<float>(colorArray[1]), static_cast<float>(colorArray[2]), static_cast<float>(alpha) }));
 }
 
 static Color parseColorFunctionParameters(CSSParserTokenRange& range)
index f97f4f9..aafdee0 100644 (file)
@@ -619,13 +619,13 @@ NSArray *DataDetection::detectContentInRange(const SimpleRange& contextRange, Da
                 if (renderStyle) {
                     auto textColor = renderStyle->visitedDependentColor(CSSPropertyColor);
                     if (textColor.isValid()) {
-                        auto [hue, saturation, lightness, alpha] = sRGBToHSL(textColor.toSRGBAComponentsLossy());
+                        auto hsla = toHSLA(textColor.toSRGBALossy());
 
                         // Force the lightness of the underline color to the middle, and multiply the alpha by 38%,
                         // so the color will appear on light and dark backgrounds, since only one color can be specified.
-                        float overrideLightness = 0.5f;
-                        float overrideAlphaMultiplier = 0.38f;
-                        auto underlineColor = makeSimpleColor(hslToSRGB({ hue, saturation, overrideLightness, overrideAlphaMultiplier * alpha }));
+                        hsla.lightness = 0.5f;
+                        hsla.alpha *= 0.38f;
+                        auto underlineColor = makeSimpleColor(toSRGBA(hsla));
 
                         anchorElement->setInlineStyleProperty(CSSPropertyColor, CSSValueCurrentcolor);
                         anchorElement->setInlineStyleProperty(CSSPropertyTextDecorationColor, underlineColor.serializationForCSS());
index f9e056d..ff5f1e5 100644 (file)
@@ -106,7 +106,7 @@ Color Color::lightened() const
     if (isSimple() && asSimple() == black)
         return lightenedBlack;
 
-    auto [r, g, b, a] = toSRGBAComponentsLossy();
+    auto [r, g, b, a] = toSRGBALossy();
     float v = std::max({ r, g, b });
 
     if (v == 0.0f)
@@ -123,7 +123,7 @@ Color Color::darkened() const
     if (isSimple() && asSimple() == white)
         return darkenedWhite;
     
-    auto [r, g, b, a] = toSRGBAComponentsLossy();
+    auto [r, g, b, a] = toSRGBALossy();
 
     float v = std::max({ r, g, b });
     float multiplier = std::max(0.0f, (v - 0.33f) / v);
@@ -134,7 +134,7 @@ Color Color::darkened() const
 bool Color::isDark() const
 {
     // FIXME: This should probably be using luminance.
-    auto [r, g, b, a] = toSRGBAComponentsLossy();
+    auto [r, g, b, a] = toSRGBALossy();
     float largestNonAlphaChannel = std::max({ r, g, b });
     return a > 0.5 && largestNonAlphaChannel < 0.5;
 }
@@ -142,13 +142,13 @@ bool Color::isDark() const
 float Color::lightness() const
 {
     // FIXME: This can probably avoid conversion to sRGB by having per-colorspace algorithms for HSL.
-    return WebCore::lightness(toSRGBAComponentsLossy());
+    return WebCore::lightness(toSRGBALossy());
 }
 
 float Color::luminance() const
 {
     // FIXME: This can probably avoid conversion to sRGB by having per-colorspace algorithms for luminance (e.g. convertToXYZ(c).yComponent()).
-    return WebCore::luminance(toSRGBAComponentsLossy());
+    return WebCore::luminance(toSRGBALossy());
 }
 
 Color Color::blend(const Color& source) const
@@ -242,21 +242,21 @@ std::pair<ColorSpace, ColorComponents<float>> Color::colorSpaceAndComponents() c
 {
     if (isExtended())
         return { asExtended().colorSpace(), asExtended().components() };
-    return { ColorSpace::SRGB, asSimple().asSRGBFloatComponents() };
+    return { ColorSpace::SRGB, asColorComponents(asSimple().asSRGBA<float>()) };
 }
 
 SimpleColor Color::toSRGBASimpleColorLossy() const
 {
     if (isExtended())
-        return makeSimpleColor(asExtended().toSRGBAComponentsLossy());
+        return makeSimpleColor(asExtended().toSRGBALossy());
     return asSimple();
 }
 
-ColorComponents<float> Color::toSRGBAComponentsLossy() const
+SRGBA<float> Color::toSRGBALossy() const
 {
     if (isExtended())
-        return asExtended().toSRGBAComponentsLossy();
-    return asSimple().asSRGBFloatComponents();
+        return asExtended().toSRGBALossy();
+    return asSimple().asSRGBA<float>();
 }
 
 Color blend(const Color& from, const Color& to, double progress)
index cb8f0a0..a35a0dd 100644 (file)
@@ -133,7 +133,7 @@ public:
     WEBCORE_EXPORT SimpleColor toSRGBASimpleColorLossy() const;
 
     // This will convert non-sRGB colorspace colors into sRGB.
-    WEBCORE_EXPORT ColorComponents<float> toSRGBAComponentsLossy() const;
+    WEBCORE_EXPORT SRGBA<float> toSRGBALossy() const;
 
     WEBCORE_EXPORT Color lightened() const;
     WEBCORE_EXPORT Color darkened() const;
index aa339fa..e2313f4 100644 (file)
@@ -41,7 +41,6 @@ public:
         static_assert(sizeof...(Ts) == Rows * Columns);
     }
 
-    constexpr void transformColorComponents(ColorComponents<float>&) const;
     constexpr ColorComponents<float> transformedColorComponents(const ColorComponents<float>&) const;
 
     constexpr float at(size_t row, size_t column) const
@@ -101,12 +100,6 @@ inline ColorMatrix<3, 3> hueRotateColorMatrix(float angleInDegrees)
 }
 
 template<size_t Columns, size_t Rows>
-constexpr void ColorMatrix<Columns, Rows>::transformColorComponents(ColorComponents<float>& inputVector) const
-{
-    inputVector = transformedColorComponents(inputVector);
-}
-
-template<size_t Columns, size_t Rows>
 constexpr ColorComponents<float> ColorMatrix<Columns, Rows>::transformedColorComponents(const ColorComponents<float>& inputVector) const
 {
     static_assert(ColorComponents<float>::Size >= Rows);
diff --git a/Source/WebCore/platform/graphics/ColorTypes.h b/Source/WebCore/platform/graphics/ColorTypes.h
new file mode 100644 (file)
index 0000000..bd73dff
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "ColorComponents.h"
+
+namespace WebCore {
+
+template<typename T> struct SRGBA {
+    T red;
+    T green;
+    T blue;
+    T alpha;
+};
+
+template<typename T> constexpr ColorComponents<T> asColorComponents(const SRGBA<T>& c)
+{
+    return { c.red, c.green, c.blue, c.alpha };
+}
+
+template<typename T> constexpr SRGBA<T> asSRGBA(const ColorComponents<T>& c)
+{
+    return { c[0], c[1], c[2], c[3] };
+}
+
+template<typename T, typename Functor> void forEachNonAlphaComponent(SRGBA<T>& color, Functor&& f)
+{
+    color.red = f(color.red);
+    color.green = f(color.green);
+    color.blue = f(color.blue);
+}
+
+template<typename T> struct LinearSRGBA {
+    T red;
+    T green;
+    T blue;
+    T alpha;
+};
+
+template<typename T> constexpr ColorComponents<T> asColorComponents(const LinearSRGBA<T>& c)
+{
+    return { c.red, c.green, c.blue, c.alpha };
+}
+
+template<typename T> constexpr LinearSRGBA<T> asLinearSRGBA(const ColorComponents<T>& c)
+{
+    return { c[0], c[1], c[2], c[3] };
+}
+
+template<typename T> struct DisplayP3 {
+    T red;
+    T green;
+    T blue;
+    T alpha;
+};
+
+template<typename T> constexpr ColorComponents<T> asColorComponents(const DisplayP3<T>& c)
+{
+    return { c.red, c.green, c.blue, c.alpha };
+}
+
+template<typename T> constexpr DisplayP3<T> asDisplayP3(const ColorComponents<T>& c)
+{
+    return { c[0], c[1], c[2], c[3] };
+}
+
+template<typename T> struct LinearDisplayP3 {
+    T red;
+    T green;
+    T blue;
+    T alpha;
+};
+
+template<typename T> constexpr ColorComponents<T> asColorComponents(const LinearDisplayP3<T>& c)
+{
+    return { c.red, c.green, c.blue, c.alpha };
+}
+
+template<typename T> constexpr LinearDisplayP3<T> asLinearDisplayP3(const ColorComponents<T>& c)
+{
+    return { c[0], c[1], c[2], c[3] };
+}
+
+template<typename T> struct HSLA {
+    T hue;
+    T saturation;
+    T lightness;
+    T alpha;
+};
+
+template<typename T> constexpr ColorComponents<T> asColorComponents(const HSLA<T>& c)
+{
+    return { c.hue, c.saturation, c.lightness, c.alpha };
+}
+
+template<typename T> constexpr HSLA<T> asHSLA(const ColorComponents<T>& c)
+{
+    return { c[0], c[1], c[2], c[3] };
+}
+
+template<typename T> struct XYZA {
+    T x;
+    T y;
+    T z;
+    T alpha;
+};
+
+template<typename T> constexpr ColorComponents<T> asColorComponents(const XYZA<T>& c)
+{
+    return { c.x, c.y, c.z, c.alpha };
+}
+
+template<typename T> constexpr XYZA<T> asXYZA(const ColorComponents<T>& c)
+{
+    return { c[0], c[1], c[2], c[3] };
+}
+
+} // namespace WebCore
index 88acb61..36a5a15 100644 (file)
 
 #include "ColorComponents.h"
 #include "ColorMatrix.h"
+#include "ColorTypes.h"
 
 namespace WebCore {
 
-// These are the standard sRGB <-> linearRGB conversion functions (https://en.wikipedia.org/wiki/SRGB).
+// These are the standard sRGB <-> linearRGB / standard DisplayP3 <-> LinearDisplayP3 conversion functions (https://en.wikipedia.org/wiki/SRGB).
 float linearToRGBColorComponent(float c)
 {
     if (c < 0.0031308f)
@@ -48,27 +49,47 @@ float rgbToLinearColorComponent(float c)
     return clampTo<float>(std::pow((c + 0.055f) / 1.055f, 2.4f), 0, 1);
 }
 
-ColorComponents<float> rgbToLinearComponents(const ColorComponents<float>& RGBColor)
+LinearSRGBA<float> toLinearSRGBA(const SRGBA<float>& color)
 {
     return {
-        rgbToLinearColorComponent(RGBColor[0]),
-        rgbToLinearColorComponent(RGBColor[1]),
-        rgbToLinearColorComponent(RGBColor[2]),
-        RGBColor[3]
+        rgbToLinearColorComponent(color.red),
+        rgbToLinearColorComponent(color.green),
+        rgbToLinearColorComponent(color.blue),
+        color.alpha
     };
 }
 
-ColorComponents<float> linearToRGBComponents(const ColorComponents<float>& linearRGB)
+SRGBA<float> toSRGBA(const LinearSRGBA<float>& color)
 {
     return {
-        linearToRGBColorComponent(linearRGB[0]),
-        linearToRGBColorComponent(linearRGB[1]),
-        linearToRGBColorComponent(linearRGB[2]),
-        linearRGB[3]
+        linearToRGBColorComponent(color.red),
+        linearToRGBColorComponent(color.green),
+        linearToRGBColorComponent(color.blue),
+        color.alpha
     };
 }
 
-static ColorComponents<float> xyzToLinearSRGB(const ColorComponents<float>& XYZComponents)
+LinearDisplayP3<float> toLinearDisplayP3(const DisplayP3<float>& color)
+{
+    return {
+        rgbToLinearColorComponent(color.red),
+        rgbToLinearColorComponent(color.green),
+        rgbToLinearColorComponent(color.blue),
+        color.alpha
+    };
+}
+
+DisplayP3<float> toDisplayP3(const LinearDisplayP3<float>& color)
+{
+    return {
+        linearToRGBColorComponent(color.red),
+        linearToRGBColorComponent(color.green),
+        linearToRGBColorComponent(color.blue),
+        color.alpha
+    };
+}
+
+static LinearSRGBA<float> toLinearSRGBA(const XYZA<float>& color)
 {
     // https://en.wikipedia.org/wiki/SRGB
     // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
@@ -77,10 +98,10 @@ static ColorComponents<float> xyzToLinearSRGB(const ColorComponents<float>& XYZC
         -0.9692660f,  1.8760108f,  0.0415560f,
          0.0556434f, -0.2040259f,  1.0572252f
     };
-    return xyzToLinearSRGBMatrix.transformedColorComponents(XYZComponents);
+    return asLinearSRGBA(xyzToLinearSRGBMatrix.transformedColorComponents(asColorComponents(color)));
 }
 
-static ColorComponents<float> linearSRGBToXYZ(const ColorComponents<float>& XYZComponents)
+static XYZA<float> toXYZ(const LinearSRGBA<float>& color)
 {
     // https://en.wikipedia.org/wiki/SRGB
     // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
@@ -89,72 +110,63 @@ static ColorComponents<float> linearSRGBToXYZ(const ColorComponents<float>& XYZC
         0.2126729f,  0.7151522f,  0.0721750f,
         0.0193339f,  0.1191920f,  0.9503041f
     };
-    return linearSRGBToXYZMatrix.transformedColorComponents(XYZComponents);
+    return asXYZA(linearSRGBToXYZMatrix.transformedColorComponents(asColorComponents(color)));
 }
 
-static ColorComponents<float> XYZToLinearP3(const ColorComponents<float>& XYZComponents)
+static LinearDisplayP3<float> toLinearDisplayP3(const XYZA<float>& color)
 {
     // https://drafts.csswg.org/css-color/#color-conversion-code
-    constexpr ColorMatrix<3, 3> xyzToLinearSRGBMatrix {
+    constexpr ColorMatrix<3, 3> xyzToLinearDisplayP3Matrix {
          2.493496911941425f,  -0.9313836179191239f, -0.4027107844507168f,
         -0.8294889695615747f,  1.7626640603183463f,  0.0236246858419436f,
          0.0358458302437845f, -0.0761723892680418f,  0.9568845240076872f
     };
-    return xyzToLinearSRGBMatrix.transformedColorComponents(XYZComponents);
+    return asLinearDisplayP3(xyzToLinearDisplayP3Matrix.transformedColorComponents(asColorComponents(color)));
 }
 
-static ColorComponents<float> linearP3ToXYZ(const ColorComponents<float>& XYZComponents)
+static XYZA<float> toXYZ(const LinearDisplayP3<float>& color)
 {
     // https://drafts.csswg.org/css-color/#color-conversion-code
-    constexpr ColorMatrix<3, 3> linearP3ToXYZMatrix {
+    constexpr ColorMatrix<3, 3> linearDisplayP3ToXYZMatrix {
         0.4865709486482162f, 0.2656676931690931f, 0.198217285234363f,
         0.2289745640697488f, 0.6917385218365064f, 0.079286914093745f,
         0.0f,                0.0451133818589026f, 1.043944368900976f
     };
-    return linearP3ToXYZMatrix.transformedColorComponents(XYZComponents);
+    return asXYZA(linearDisplayP3ToXYZMatrix.transformedColorComponents(asColorComponents(color)));
 }
 
-ColorComponents<float> p3ToSRGB(const ColorComponents<float>& p3)
+SRGBA<float> toSRGBA(const DisplayP3<float>& color)
 {
-    auto linearP3 = rgbToLinearComponents(p3);
-    auto xyz = linearP3ToXYZ(linearP3);
-    auto linearSRGB = xyzToLinearSRGB(xyz);
-    return linearToRGBComponents(linearSRGB);
+    return toSRGBA(toLinearSRGBA(toXYZ(toLinearDisplayP3(color))));
 }
 
-ColorComponents<float> sRGBToP3(const ColorComponents<float>& sRGB)
+DisplayP3<float> toDisplayP3(const SRGBA<float>& color)
 {
-    auto linearSRGB = rgbToLinearComponents(sRGB);
-    auto xyz = linearSRGBToXYZ(linearSRGB);
-    auto linearP3 = XYZToLinearP3(xyz);
-    return linearToRGBComponents(linearP3);
+    return toDisplayP3(toLinearDisplayP3(toXYZ(toLinearSRGBA(color))));
 }
 
-float lightness(const ColorComponents<float>& sRGBCompontents)
+float lightness(const SRGBA<float>& color)
 {
-    auto [r, g, b, a] = sRGBCompontents;
-
+    auto [r, g, b, a] = color;
     auto [min, max] = std::minmax({ r, g, b });
-
     return 0.5f * (max + min);
 }
 
-float luminance(const ColorComponents<float>& sRGBComponents)
+float luminance(const SRGBA<float>& color)
 {
-    // NOTE: This is the equivilent of `linearSRGBToXYZ(rgbToLinearComponents(sRGBComponents))[1]`
+    // NOTE: This is the equivalent of toXYZA(toLinearSRGBA(color)).y
     // FIMXE: If we can generalize ColorMatrix a bit more, it might be nice to write this as:
-    //      auto linearSRGBComponents = rgbToLinearComponents(sRGBComponents);
-    //      return linearSRGBComponents * linearSRGBToXYZMatrix.row(1);
-    auto [r, g, b, a] = rgbToLinearComponents(sRGBComponents);
+    //      return toLinearSRGBA(color) * linearSRGBToXYZMatrix.row(1);
+    auto [r, g, b, a] = toLinearSRGBA(color);
     return 0.2126f * r + 0.7152f * g + 0.0722f * b;
 }
 
-float contrastRatio(const ColorComponents<float>& componentsA, const ColorComponents<float>& componentsB)
+float contrastRatio(const SRGBA<float>& colorA, const SRGBA<float>& colorB)
 {
     // Uses the WCAG 2.0 definition of contrast ratio.
     // https://www.w3.org/TR/WCAG20/#contrast-ratiodef
-    float lighterLuminance = luminance(componentsA);
-    float darkerLuminance = luminance(componentsB);
+    float lighterLuminance = luminance(colorA);
+    float darkerLuminance = luminance(colorB);
 
     if (lighterLuminance < darkerLuminance)
         std::swap(lighterLuminance, darkerLuminance);
@@ -162,10 +174,10 @@ float contrastRatio(const ColorComponents<float>& componentsA, const ColorCompon
     return (lighterLuminance + 0.05) / (darkerLuminance + 0.05);
 }
 
-ColorComponents<float> sRGBToHSL(const ColorComponents<float>& sRGBCompontents)
+HSLA<float> toHSLA(const SRGBA<float>& color)
 {
     // http://en.wikipedia.org/wiki/HSL_color_space.
-    auto [r, g, b, alpha] = sRGBCompontents;
+    auto [r, g, b, alpha] = color;
 
     auto [min, max] = std::minmax({ r, g, b });
     float chroma = max - min;
@@ -221,9 +233,9 @@ static float calcHue(float temp1, float temp2, float hueVal)
 // Explanation of this algorithm can be found in the CSS Color 4 Module
 // specification at https://drafts.csswg.org/css-color-4/#hsl-to-rgb with
 // further explanation available at http://en.wikipedia.org/wiki/HSL_color_space
-ColorComponents<float> hslToSRGB(const ColorComponents<float>& hslColor)
+SRGBA<float> toSRGBA(const HSLA<float>& color)
 {
-    auto [hue, saturation, lightness, alpha] = hslColor;
+    auto [hue, saturation, lightness, alpha] = color;
 
     // Convert back to RGB.
     if (!saturation) {
@@ -247,9 +259,9 @@ ColorComponents<float> hslToSRGB(const ColorComponents<float>& hslColor)
     };
 }
 
-ColorComponents<float> premultiplied(const ColorComponents<float>& sRGBComponents)
+SRGBA<float> premultiplied(const SRGBA<float>& color)
 {
-    auto [r, g, b, a] = sRGBComponents;
+    auto [r, g, b, a] = color;
     return {
         r * a,
         g * a,
index d371602..224080a 100644 (file)
 
 namespace WebCore {
 
-template<typename> struct ColorComponents;
+template<typename> struct DisplayP3;
+template<typename> struct HSLA;
+template<typename> struct LinearDisplayP3;
+template<typename> struct LinearSRGBA;
+template<typename> struct SRGBA;
 
 // 0-1 components, result is clamped.
 float linearToRGBColorComponent(float);
 float rgbToLinearColorComponent(float);
 
-ColorComponents<float> rgbToLinearComponents(const ColorComponents<float>&);
-ColorComponents<float> linearToRGBComponents(const ColorComponents<float>&);
+LinearSRGBA<float> toLinearSRGBA(const SRGBA<float>&);
+SRGBA<float> toSRGBA(const LinearSRGBA<float>&);
 
-ColorComponents<float> p3ToSRGB(const ColorComponents<float>&);
-ColorComponents<float> sRGBToP3(const ColorComponents<float>&);
+LinearDisplayP3<float> toLinearDisplayP3(const DisplayP3<float>&);
+DisplayP3<float> toDisplayP3(const LinearDisplayP3<float>&);
 
-WEBCORE_EXPORT ColorComponents<float> sRGBToHSL(const ColorComponents<float>&);
-WEBCORE_EXPORT ColorComponents<float> hslToSRGB(const ColorComponents<float>&);
+SRGBA<float> toSRGBA(const DisplayP3<float>&);
+DisplayP3<float> toDisplayP3(const SRGBA<float>&);
 
-float lightness(const ColorComponents<float>& sRGBCompontents);
-float luminance(const ColorComponents<float>& sRGBCompontents);
-float contrastRatio(const ColorComponents<float>& sRGBCompontentsA, const ColorComponents<float>& sRGBCompontentsB);
+WEBCORE_EXPORT HSLA<float> toHSLA(const SRGBA<float>&);
+WEBCORE_EXPORT SRGBA<float> toSRGBA(const HSLA<float>&);
 
-ColorComponents<float> premultiplied(const ColorComponents<float>& sRGBCompontents);
+float lightness(const SRGBA<float>&);
+float luminance(const SRGBA<float>&);
+
+float contrastRatio(const SRGBA<float>&, const SRGBA<float>&);
+
+SRGBA<float> premultiplied(const SRGBA<float>&);
 
 inline uint8_t convertPrescaledToComponentByte(float f)
 {
index 61e5030..fd2e3a8 100644 (file)
@@ -27,6 +27,7 @@
 #include "ExtendedColor.h"
 
 #include "Color.h"
+#include "ColorTypes.h"
 #include "ColorUtilities.h"
 #include <wtf/Hasher.h>
 #include <wtf/MathExtras.h>
@@ -80,18 +81,18 @@ Ref<ExtendedColor> ExtendedColor::invertedColorWithAlpha(float overrideAlpha) co
     return ExtendedColor::create(1.0f - c1, 1.0f - c2, 1.0f - c3, overrideAlpha, colorSpace());
 }
 
-ColorComponents<float> ExtendedColor::toSRGBAComponentsLossy() const
+SRGBA<float> ExtendedColor::toSRGBALossy() const
 {
     switch (m_colorSpace) {
     case ColorSpace::SRGB:
-        return m_components;
+        return asSRGBA(m_components);
     case ColorSpace::LinearRGB:
-        return linearToRGBComponents(m_components);
+        return toSRGBA(asLinearSRGBA(m_components));
     case ColorSpace::DisplayP3:
-        return p3ToSRGB(m_components);
+        return toSRGBA(asDisplayP3(m_components));
     }
     ASSERT_NOT_REACHED();
-    return { };
+    return { 0, 0, 0, 0 };
 }
 
 bool ExtendedColor::isWhite() const
index 3f392d9..503e33f 100644 (file)
@@ -34,6 +34,7 @@
 namespace WebCore {
 
 class Color;
+template<typename> struct SRGBA;
 
 class ExtendedColor : public RefCounted<ExtendedColor> {
 public:
@@ -51,7 +52,7 @@ public:
     Ref<ExtendedColor> colorWithAlpha(float) const;
     Ref<ExtendedColor> invertedColorWithAlpha(float) const;
 
-    ColorComponents<float> toSRGBAComponentsLossy() const;
+    SRGBA<float> toSRGBALossy() const;
 
     bool isWhite() const;
     bool isBlack() const;
index 42a22f3..00c79bc 100644 (file)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "ColorComponents.h"
+#include "ColorTypes.h"
 #include "ColorUtilities.h"
 #include <wtf/text/WTFString.h>
 
@@ -65,10 +66,7 @@ public:
         return { static_cast<uint8_t>(0xFF - redComponent()), static_cast<uint8_t>(0xFF - greenComponent()), static_cast<uint8_t>(0xFF - blueComponent()), alpha };
     }
 
-    constexpr ColorComponents<float> asSRGBFloatComponents() const
-    {
-        return { convertToComponentFloat(redComponent()), convertToComponentFloat(greenComponent()), convertToComponentFloat(blueComponent()),  convertToComponentFloat(alphaComponent()) };
-    }
+    template<typename T> constexpr SRGBA<T> asSRGBA() const;
 
     template<std::size_t N>
     constexpr uint8_t get() const
@@ -122,9 +120,9 @@ constexpr SimpleColor makeSimpleColor(int r, int g, int b, int a)
     return { static_cast<uint8_t>(std::clamp(r, 0, 0xFF)), static_cast<uint8_t>(std::clamp(g, 0, 0xFF)), static_cast<uint8_t>(std::clamp(b, 0, 0xFF)), static_cast<uint8_t>(std::clamp(a, 0, 0xFF)) };
 }
 
-inline SimpleColor makeSimpleColor(const ColorComponents<float>& sRGBComponents)
+inline SimpleColor makeSimpleColor(const SRGBA<float>& sRGBA)
 {
-    auto [r, g, b, a] = sRGBComponents;
+    auto [r, g, b, a] = sRGBA;
     return makeSimpleColorFromFloats(r, g, b, a);
 }
 
@@ -133,6 +131,15 @@ inline SimpleColor makeSimpleColorFromFloats(float r, float g, float b, float a)
     return { convertToComponentByte(r), convertToComponentByte(g), convertToComponentByte(b), convertToComponentByte(a) };
 }
 
+template<typename T> constexpr SRGBA<T> SimpleColor::asSRGBA() const
+{
+    if constexpr (std::is_floating_point_v<T>)
+        return { convertToComponentFloat(redComponent()), convertToComponentFloat(greenComponent()), convertToComponentFloat(blueComponent()),  convertToComponentFloat(alphaComponent()) };
+    else
+        return { redComponent(), greenComponent(), blueComponent(), alphaComponent() };
+}
+
+
 } // namespace WebCore
 
 namespace std {
index 34d935b..92b81d3 100644 (file)
@@ -83,7 +83,7 @@ void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr)
 
 void setSourceRGBAFromColor(cairo_t* context, const Color& color)
 {
-    auto [r, g, b, a] = color.toSRGBAComponentsLossy();
+    auto [r, g, b, a] = color.toSRGBALossy();
     cairo_set_source_rgba(context, r, g, b, a);
 }
 
index 7ee0aac..1fe5c96 100644 (file)
@@ -43,7 +43,7 @@ void Gradient::platformDestroy()
 
 static void addColorStopRGBA(cairo_pattern_t *gradient, Gradient::ColorStop stop, float globalAlpha)
 {
-    auto [r, g, b, a] = stop.color.toSRGBAComponentsLossy();
+    auto [r, g, b, a] = stop.color.toSRGBALossy();
     cairo_pattern_add_color_stop_rgba(gradient, stop.offset, r, g, b, a * globalAlpha);
 }
 
@@ -55,7 +55,7 @@ typedef struct point_t {
 
 static void setCornerColorRGBA(cairo_pattern_t* gradient, int id, Gradient::ColorStop stop, float globalAlpha)
 {
-    auto [r, g, b, a] = stop.color.toSRGBAComponentsLossy();
+    auto [r, g, b, a] = stop.color.toSRGBALossy();
     cairo_mesh_pattern_set_corner_color_rgba(gradient, id, r, g, b, a * globalAlpha);
 }
 
@@ -135,8 +135,8 @@ static void addConicSector(cairo_pattern_t *gradient, float cx, float cy, float
 
 static Gradient::ColorStop interpolateColorStop(Gradient::ColorStop from, Gradient::ColorStop to)
 {
-    auto [r1, g1, b1, a1] = from.color.toSRGBAComponentsLossy();
-    auto [r2, g2, b2, a2] = to.color.toSRGBAComponentsLossy();
+    auto [r1, g1, b1, a1] = from.color.toSRGBALossy();
+    auto [r2, g2, b2, a2] = to.color.toSRGBALossy();
 
     float offset = from.offset + (to.offset - from.offset) * 0.5f;
     float r = r1 + (r2 - r1) * 0.5f;
index dd0c1a7..bc40dcf 100644 (file)
@@ -404,8 +404,13 @@ bool FELighting::drawLighting(Uint8ClampedArray& pixels, int width, int height)
     data.widthDecreasedByOne = width - 1;
     data.heightDecreasedByOne = height - 1;
     
-    auto lightColor = (operatingColorSpace() == ColorSpace::LinearRGB) ? rgbToLinearComponents(m_lightingColor.toSRGBAComponentsLossy()) : m_lightingColor.toSRGBAComponentsLossy();
-    paintingData.initialLightingData.colorVector = FloatPoint3D(lightColor[0], lightColor[1], lightColor[2]);
+    if (operatingColorSpace() == ColorSpace::LinearRGB) {
+        auto [r, g, b, a] = toLinearSRGBA(m_lightingColor.toSRGBALossy());
+        paintingData.initialLightingData.colorVector = FloatPoint3D(r, g, b);
+    } else {
+        auto [r, g, b, a] = m_lightingColor.toSRGBALossy();
+        paintingData.initialLightingData.colorVector = FloatPoint3D(r, g, b);
+    }
     m_lightSource->initPaintingData(*this, paintingData);
 
     // Top left.
index 12749f4..f057c24 100644 (file)
@@ -85,27 +85,23 @@ RefPtr<FilterOperation> BasicColorMatrixFilterOperation::blend(const FilterOpera
     return BasicColorMatrixFilterOperation::create(WebCore::blend(fromAmount, m_amount, progress), m_type);
 }
 
-bool BasicColorMatrixFilterOperation::transformColor(ColorComponents<float>& colorComponents) const
+bool BasicColorMatrixFilterOperation::transformColor(SRGBA<float>& color) const
 {
     switch (m_type) {
     case GRAYSCALE: {
-        auto matrix = grayscaleColorMatrix(m_amount);
-        matrix.transformColorComponents(colorComponents);
+        color = asSRGBA(grayscaleColorMatrix(m_amount).transformedColorComponents(asColorComponents(color)));
         return true;
     }
     case SEPIA: {
-        auto matrix = sepiaColorMatrix(m_amount);
-        matrix.transformColorComponents(colorComponents);
+        color = asSRGBA(sepiaColorMatrix(m_amount).transformedColorComponents(asColorComponents(color)));
         return true;
     }
     case HUE_ROTATE: {
-        auto matrix = hueRotateColorMatrix(m_amount);
-        matrix.transformColorComponents(colorComponents);
+        color = asSRGBA(hueRotateColorMatrix(m_amount).transformedColorComponents(asColorComponents(color)));
         return true;
     }
     case SATURATE: {
-        auto matrix = saturationColorMatrix(m_amount);
-        matrix.transformColorComponents(colorComponents);
+        color = asSRGBA(saturationColorMatrix(m_amount).transformedColorComponents(asColorComponents(color)));
         return true;
     }
     default:
@@ -152,30 +148,30 @@ RefPtr<FilterOperation> BasicComponentTransferFilterOperation::blend(const Filte
     return BasicComponentTransferFilterOperation::create(WebCore::blend(fromAmount, m_amount, progress), m_type);
 }
 
-bool BasicComponentTransferFilterOperation::transformColor(ColorComponents<float>& colorComponents) const
+bool BasicComponentTransferFilterOperation::transformColor(SRGBA<float>& color) const
 {
     switch (m_type) {
     case OPACITY:
-        colorComponents[3] *= m_amount;
+        color.alpha *= m_amount;
         return true;
     case INVERT: {
-        float oneMinusAmount = 1.f - m_amount;
-        colorComponents[0] = 1 - (oneMinusAmount + colorComponents[0] * (m_amount - oneMinusAmount));
-        colorComponents[1] = 1 - (oneMinusAmount + colorComponents[1] * (m_amount - oneMinusAmount));
-        colorComponents[2] = 1 - (oneMinusAmount + colorComponents[2] * (m_amount - oneMinusAmount));
+        float oneMinusAmount = 1.0f - m_amount;
+        forEachNonAlphaComponent(color, [&](float component) {
+            return 1.0f - (oneMinusAmount + component * (m_amount - oneMinusAmount));
+        });
         return true;
     }
     case CONTRAST: {
         float intercept = -(0.5f * m_amount) + 0.5f;
-        colorComponents[0] = clampTo<float>(intercept + m_amount * colorComponents[0], 0, 1);
-        colorComponents[1] = clampTo<float>(intercept + m_amount * colorComponents[1], 0, 1);
-        colorComponents[2] = clampTo<float>(intercept + m_amount * colorComponents[2], 0, 1);
+        forEachNonAlphaComponent(color, [&](float component) {
+            return std::clamp<float>(intercept + m_amount * component, 0.0f, 1.0f);
+        });
         return true;
     }
     case BRIGHTNESS:
-        colorComponents[0] = std::max<float>(m_amount * colorComponents[0], 0);
-        colorComponents[1] = std::max<float>(m_amount * colorComponents[1], 0);
-        colorComponents[2] = std::max<float>(m_amount * colorComponents[2], 0);
+        forEachNonAlphaComponent(color, [&](float component) {
+            return std::max<float>(m_amount * component, 0.0f);
+        });
         return true;
     default:
         ASSERT_NOT_REACHED();
@@ -226,15 +222,15 @@ RefPtr<FilterOperation> InvertLightnessFilterOperation::blend(const FilterOperat
     return InvertLightnessFilterOperation::create();
 }
 
-bool InvertLightnessFilterOperation::transformColor(ColorComponents<float>& sRGBColorComponents) const
+bool InvertLightnessFilterOperation::transformColor(SRGBA<float>& color) const
 {
-    auto hslComponents = sRGBToHSL(sRGBColorComponents);
+    auto hsla = toHSLA(color);
     
     // Rotate the hue 180deg.
-    hslComponents[0] = fmod(hslComponents[0] + 0.5f, 1.0f);
+    hsla.hue = std::fmod(hsla.hue + 0.5f, 1.0f);
     
     // Convert back to RGB.
-    sRGBColorComponents = hslToSRGB(hslComponents);
+    auto hueRotatedSRGBA = toSRGBA(hsla);
     
     // Apply the matrix. See rdar://problem/41146650 for how this matrix was derived.
     constexpr ColorMatrix<5, 3> toDarkModeMatrix {
@@ -242,28 +238,28 @@ bool InvertLightnessFilterOperation::transformColor(ColorComponents<float>& sRGB
         0.030f, -0.741f, -0.089f, 0.0f, 1.0f,
         0.030f,  0.059f, -0.890f, 0.0f, 1.0f
     };
-    toDarkModeMatrix.transformColorComponents(sRGBColorComponents);
+    color = asSRGBA(toDarkModeMatrix.transformedColorComponents(asColorComponents(hueRotatedSRGBA)));
     return true;
 }
 
-bool InvertLightnessFilterOperation::inverseTransformColor(ColorComponents<float>& sRGBColorComponents) const
+bool InvertLightnessFilterOperation::inverseTransformColor(SRGBA<float>& color) const
 {
-    auto rgbComponents = sRGBColorComponents;
-
     // Apply the matrix.
     constexpr ColorMatrix<5, 3> toLightModeMatrix {
         -1.300f, -0.097f,  0.147f, 0.0f, 1.25f,
         -0.049f, -1.347f,  0.146f, 0.0f, 1.25f,
         -0.049f, -0.097f, -1.104f, 0.0f, 1.25f
     };
-    toLightModeMatrix.transformColorComponents(rgbComponents);
+    auto convertedToLightMode = asSRGBA(toLightModeMatrix.transformedColorComponents(asColorComponents(color)));
 
     // Convert to HSL.
-    auto hslComponents = sRGBToHSL(rgbComponents);
+    auto hsla = toHSLA(convertedToLightMode);
+
     // Hue rotate by 180deg.
-    hslComponents[0] = fmod(hslComponents[0] + 0.5f, 1.0f);
+    hsla.hue = std::fmod(hsla.hue + 0.5f, 1.0f);
+
     // And return RGB.
-    sRGBColorComponents = hslToSRGB(hslComponents);
+    color = toSRGBA(hsla);
     return true;
 }
 
index 76f3e0d..f3593c1 100644 (file)
@@ -46,7 +46,7 @@ class CachedResourceLoader;
 class CachedSVGDocumentReference;
 class FilterEffect;
 struct ResourceLoaderOptions;
-template<typename> struct ColorComponents;
+template<typename> struct SRGBA;
 
 class FilterOperation : public ThreadSafeRefCounted<FilterOperation> {
 public:
@@ -80,8 +80,8 @@ public:
         return nullptr;
     }
     
-    virtual bool transformColor(ColorComponents<float>&) const { return false; }
-    virtual bool inverseTransformColor(ColorComponents<float>&) const { return false; }
+    virtual bool transformColor(SRGBA<float>&) const { return false; }
+    virtual bool inverseTransformColor(SRGBA<float>&) const { return false; }
 
     OperationType type() const { return m_type; }
 
@@ -229,7 +229,7 @@ private:
     {
     }
 
-    bool transformColor(ColorComponents<float>&) const override;
+    bool transformColor(SRGBA<float>&) const override;
 
     double m_amount;
 };
@@ -264,7 +264,7 @@ private:
     {
     }
 
-    bool transformColor(ColorComponents<float>&) const override;
+    bool transformColor(SRGBA<float>&) const override;
 
     double m_amount;
 };
@@ -291,8 +291,8 @@ private:
     {
     }
 
-    bool transformColor(ColorComponents<float>&) const final;
-    bool inverseTransformColor(ColorComponents<float>&) const final;
+    bool transformColor(SRGBA<float>&) const final;
+    bool inverseTransformColor(SRGBA<float>&) const final;
 };
 
 class WEBCORE_EXPORT BlurFilterOperation : public FilterOperation {
index c8c14c1..cbda087 100644 (file)
@@ -111,14 +111,14 @@ bool FilterOperations::transformColor(Color& color) const
     if (color.isSemantic())
         return false;
 
-    auto sRGBAComponents = color.toSRGBAComponentsLossy();
+    auto sRGBAColor = color.toSRGBALossy();
 
     for (auto& operation : m_operations) {
-        if (!operation->transformColor(sRGBAComponents))
+        if (!operation->transformColor(sRGBAColor))
             return false;
     }
 
-    color = makeSimpleColor(sRGBAComponents);
+    color = makeSimpleColor(sRGBAColor);
     return true;
 }
 
@@ -130,14 +130,14 @@ bool FilterOperations::inverseTransformColor(Color& color) const
     if (color.isSemantic())
         return false;
 
-    auto sRGBAComponents = color.toSRGBAComponentsLossy();
+    auto sRGBAColor = color.toSRGBALossy();
 
     for (auto& operation : m_operations) {
-        if (!operation->inverseTransformColor(sRGBAComponents))
+        if (!operation->inverseTransformColor(sRGBAColor))
             return false;
     }
 
-    color = makeSimpleColor(sRGBAComponents);
+    color = makeSimpleColor(sRGBAColor);
     return true;
 }
 
index 15b68a0..c175105 100644 (file)
@@ -38,7 +38,7 @@ Color::Color(const GdkRGBA& c)
 
 Color::operator GdkRGBA() const
 {
-    auto [r, g, b, a] = toSRGBAComponentsLossy();
+    auto [r, g, b, a] = toSRGBALossy();
     return { r, g, b, a };
 }
 
index e5f068c..ecf42c5 100644 (file)
@@ -253,7 +253,7 @@ void TextureMapperGL::drawBorder(const Color& color, float width, const FloatRec
     Ref<TextureMapperShaderProgram> program = data().getShaderProgram(TextureMapperShaderProgram::SolidColor);
     glUseProgram(program->programID());
 
-    auto [r, g, b, a] = premultiplied(color.toSRGBAComponentsLossy());
+    auto [r, g, b, a] = premultiplied(color.toSRGBALossy());
     glUniform4f(program->colorLocation(), r, g, b, a);
     glLineWidth(width);
 
@@ -275,7 +275,7 @@ void TextureMapperGL::drawNumber(int number, const Color& color, const FloatPoin
     cairo_t* cr = cairo_create(surface);
 
     // Since we won't swap R+B when uploading a texture, paint with the swapped R+B color.
-    auto [r, g, b, a] = color.toSRGBAComponentsLossy();
+    auto [r, g, b, a] = color.toSRGBALossy();
     cairo_set_source_rgba(cr, b, g, r, a);
 
     cairo_rectangle(cr, 0, 0, width, height);
@@ -414,7 +414,7 @@ static void prepareFilterProgram(TextureMapperShaderProgram& program, const Filt
             break;
         case 1:
             // Second pass: we need the shadow color and the content texture for compositing.
-            auto [r, g, b, a] = premultiplied(shadow.color().toSRGBAComponentsLossy());
+            auto [r, g, b, a] = premultiplied(shadow.color().toSRGBALossy());
             glUniform4f(program.colorLocation(), r, g, b, a);
             glUniform2f(program.blurRadiusLocation(), 0, shadow.stdDeviation() / float(size.height()));
             glUniform2f(program.shadowOffsetLocation(), 0, 0);
@@ -676,7 +676,7 @@ void TextureMapperGL::drawSolidColor(const FloatRect& rect, const Transformation
     Ref<TextureMapperShaderProgram> program = data().getShaderProgram(options);
     glUseProgram(program->programID());
 
-    auto [r, g, b, a] = premultiplied(color.toSRGBAComponentsLossy());
+    auto [r, g, b, a] = premultiplied(color.toSRGBALossy());
     glUniform4f(program->colorLocation(), r, g, b, a);
     if (a < 1 && isBlendingAllowed)
         flags |= ShouldBlend;
@@ -686,7 +686,7 @@ void TextureMapperGL::drawSolidColor(const FloatRect& rect, const Transformation
 
 void TextureMapperGL::clearColor(const Color& color)
 {
-    auto [r, g, b, a] = color.toSRGBAComponentsLossy();
+    auto [r, g, b, a] = color.toSRGBALossy();
     glClearColor(r, g, b, a);
     glClear(GL_COLOR_BUFFER_BIT);
 }
index 05833dd..b87fbf8 100644 (file)
@@ -41,13 +41,13 @@ Color::Color(D2D1_COLOR_F color)
 
 Color::operator D2D1_COLOR_F() const
 {
-    auto [r, g, b, a] = toSRGBAComponentsLossy();
+    auto [r, g, b, a] = toSRGBALossy();
     return D2D1::ColorF(r, g, b, a);
 }
 
 Color::operator D2D1_VECTOR_4F() const
 {
-    auto [r, g, b, a] = toSRGBAComponentsLossy();
+    auto [r, g, b, a] = toSRGBALossy();
     return D2D1::Vector4F(r, g, b, a);
 }
 
index 0bcb592..fe96143 100644 (file)
@@ -72,7 +72,7 @@ void Gradient::generateGradient(ID2D1RenderTarget* renderTarget)
     Vector<D2D1_GRADIENT_STOP> gradientStops;
     // FIXME: Add support for ExtendedColor.
     for (auto stop : m_stops) {
-        auto [r, g, b, a] stop.color.toSRGBAComponentsLossy();
+        auto [r, g, b, a] stop.color.toSRGBALossy();
         gradientStops.append(D2D1::GradientStop(stop.offset, D2D1::ColorF(r, g, b, a)));
     }
 
index 209bba9..cbc51ea 100644 (file)
@@ -379,7 +379,7 @@ void GraphicsContextPlatformPrivate::rotate(float angle)
 
 D2D1_COLOR_F GraphicsContext::colorWithGlobalAlpha(const Color& color) const
 {
-    auto [r, g, b, a] = color.toSRGBAComponentsLossy();
+    auto [r, g, b, a] = color.toSRGBALossy();
     return D2D1::ColorF(r, g, b, a * m_data->currentGlobalAlpha());
 }
 
index a125516..a21d52c 100644 (file)
@@ -1401,7 +1401,7 @@ Color RenderTheme::disabledTextColor(const Color& textColor, const Color& backgr
     // If there's not very much contrast between the disabled color and the background color,
     // just leave the text color alone. We don't want to change a good contrast color scheme so that it has really bad contrast.
     // If the contrast was already poor, then it doesn't do any good to change it to a different poor contrast color scheme.
-    if (contrastRatio(disabledColor.toSRGBAComponentsLossy(), backgroundColor.toSRGBAComponentsLossy()) < minColorContrastValue)
+    if (contrastRatio(disabledColor.toSRGBALossy(), backgroundColor.toSRGBALossy()) < minColorContrastValue)
         return textColor;
 
     return disabledColor;
index 8e72a95..38290bc 100644 (file)
@@ -63,7 +63,7 @@ bool textColorIsLegibleAgainstBackgroundColor(const Color& textColor, const Colo
 {
     // Uses the WCAG 2.0 definition of legibility: a contrast ratio of 4.5:1 or greater.
     // https://www.w3.org/TR/WCAG20/#visual-audio-contrast-contrast
-    return contrastRatio(textColor.toSRGBAComponentsLossy(), backgroundColor.toSRGBAComponentsLossy()) > 4.5;
+    return contrastRatio(textColor.toSRGBALossy(), backgroundColor.toSRGBALossy()) > 4.5;
 }
 
 static Color adjustColorForVisibilityOnBackground(const Color& textColor, const Color& backgroundColor)
index d47e823..e0b499c 100644 (file)
@@ -1,3 +1,18 @@
+2020-06-13  Sam Weinig  <weinig@apple.com>
+
+        Extended Color: Experiment with strongly typed ColorComponents
+        https://bugs.webkit.org/show_bug.cgi?id=212396
+
+        Reviewed by Darin Adler.
+
+        * UIProcess/API/wpe/WebKitColor.cpp:
+        (webkitColorFillFromWebCoreColor):
+        * UIProcess/gtk/ViewGestureControllerGtk.cpp:
+        (WebKit::ViewGestureController::beginSwipeGesture):
+        * WebProcess/WebPage/WebFrame.cpp:
+        (WebKit::WebFrame::getDocumentBackgroundColor):
+        Update to call toSRGBALossy() rather than toSRGBAComponentsLossy().
+
 2020-06-13  Tetsuharu Ohzeki  <tetsuharu.ohzeki@gmail.com>
 
         Remove FileError.h
index 9297ad4..0c0a37d 100644 (file)
@@ -83,7 +83,7 @@ void webkitColorFillFromWebCoreColor(const WebCore::Color& webCoreColor, WebKitC
 {
     RELEASE_ASSERT(webCoreColor.isValid());
 
-    auto [r, g, b, a] = webCoreColor.toSRGBAComponentsLossy();
+    auto [r, g, b, a] = webCoreColor.toSRGBALossy();
     color->red = r;
     color->green = g;
     color->blue = b;
index a163538..e6fedd0 100644 (file)
@@ -337,7 +337,7 @@ void ViewGestureController::beginSwipeGesture(WebBackForwardListItem* targetItem
         if (color.isValid()) {
             m_backgroundColorForCurrentSnapshot = color;
             if (!m_currentSwipeSnapshotPattern) {
-                auto [red, green, blue, alpha] = color.toSRGBAComponentsLossy();
+                auto [red, green, blue, alpha] = color.toSRGBALossy();
                 m_currentSwipeSnapshotPattern = adoptRef(cairo_pattern_create_rgba(red, green, blue, alpha));
             }
         }
index 7a05913..9d76794 100644 (file)
@@ -660,7 +660,7 @@ bool WebFrame::getDocumentBackgroundColor(double* red, double* green, double* bl
     if (!bgColor.isValid())
         return false;
 
-    auto [r, g, b, a] = bgColor.toSRGBAComponentsLossy();
+    auto [r, g, b, a] = bgColor.toSRGBALossy();
     *red = r;
     *green = g;
     *blue = b;
index 7184398..baa9545 100644 (file)
@@ -1,3 +1,17 @@
+2020-06-13  Sam Weinig  <weinig@apple.com>
+
+        Extended Color: Experiment with strongly typed ColorComponents
+        https://bugs.webkit.org/show_bug.cgi?id=212396
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WebCore/ColorTests.cpp:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebCore/ExtendedColorTests.cpp:
+        (TestWebKitAPI::TEST):
+        Update for changed names (e.g. toSRGBAComponentsLossy() -> toSRGBALossy())
+        and use of explicit types.
+
 2020-06-13  Diego Pino Garcia  <dpino@igalia.com>
 
         Unreviewed, fix configuration setting of WPE Debug (Tests JS) bot
index 37e9509..04ac5aa 100644 (file)
@@ -37,15 +37,15 @@ TEST(Color, RGBToHSL_White)
 {
     Color color = Color::white;
 
-    auto [hue, saturation, lightness, alpha] = sRGBToHSL(color.toSRGBAComponentsLossy());
+    auto hslaColor = toHSLA(color.toSRGBALossy());
 
-    EXPECT_FLOAT_EQ(0, hue);
-    EXPECT_FLOAT_EQ(0, saturation);
-    EXPECT_FLOAT_EQ(1, lightness);
+    EXPECT_FLOAT_EQ(0, hslaColor.hue);
+    EXPECT_FLOAT_EQ(0, hslaColor.saturation);
+    EXPECT_FLOAT_EQ(1, hslaColor.lightness);
     
-    EXPECT_FLOAT_EQ(color.lightness(), lightness);
+    EXPECT_FLOAT_EQ(color.lightness(), hslaColor.lightness);
     
-    auto roundTrippedColor = Color(makeSimpleColor(hslToSRGB({ hue, saturation, lightness, alpha })));
+    auto roundTrippedColor = makeSimpleColor(toSRGBA(hslaColor));
     EXPECT_EQ(color, roundTrippedColor);
 }
 
@@ -53,15 +53,15 @@ TEST(Color, RGBToHSL_Black)
 {
     Color color = Color::black;
 
-    auto [hue, saturation, lightness, alpha] = sRGBToHSL(color.toSRGBAComponentsLossy());
+    auto hslaColor = toHSLA(color.toSRGBALossy());
 
-    EXPECT_FLOAT_EQ(0, hue);
-    EXPECT_FLOAT_EQ(0, saturation);
-    EXPECT_FLOAT_EQ(0, lightness);
+    EXPECT_FLOAT_EQ(0, hslaColor.hue);
+    EXPECT_FLOAT_EQ(0, hslaColor.saturation);
+    EXPECT_FLOAT_EQ(0, hslaColor.lightness);
 
-    EXPECT_FLOAT_EQ(color.lightness(), lightness);
+    EXPECT_FLOAT_EQ(color.lightness(), hslaColor.lightness);
 
-    auto roundTrippedColor = Color(makeSimpleColor(hslToSRGB({ hue, saturation, lightness, alpha })));
+    auto roundTrippedColor = makeSimpleColor(toSRGBA(hslaColor));
     EXPECT_EQ(color, roundTrippedColor);
 }
 
@@ -69,15 +69,15 @@ TEST(Color, RGBToHSL_Red)
 {
     Color color = makeSimpleColor(255, 0, 0);
 
-    auto [hue, saturation, lightness, alpha] = sRGBToHSL(color.toSRGBAComponentsLossy());
+    auto hslaColor = toHSLA(color.toSRGBALossy());
 
-    EXPECT_FLOAT_EQ(0, hue);
-    EXPECT_FLOAT_EQ(1, saturation);
-    EXPECT_FLOAT_EQ(0.5, lightness);
+    EXPECT_FLOAT_EQ(0, hslaColor.hue);
+    EXPECT_FLOAT_EQ(1, hslaColor.saturation);
+    EXPECT_FLOAT_EQ(0.5, hslaColor.lightness);
 
-    EXPECT_FLOAT_EQ(color.lightness(), lightness);
+    EXPECT_FLOAT_EQ(color.lightness(), hslaColor.lightness);
 
-    auto roundTrippedColor = Color(makeSimpleColor(hslToSRGB({ hue, saturation, lightness, alpha })));
+    auto roundTrippedColor = makeSimpleColor(toSRGBA(hslaColor));
     EXPECT_EQ(color, roundTrippedColor);
 }
 
@@ -85,15 +85,15 @@ TEST(Color, RGBToHSL_Green)
 {
     Color color = makeSimpleColor(0, 255, 0);
 
-    auto [hue, saturation, lightness, alpha] = sRGBToHSL(color.toSRGBAComponentsLossy());
+    auto hslaColor = toHSLA(color.toSRGBALossy());
 
-    EXPECT_FLOAT_EQ(0.33333334, hue);
-    EXPECT_FLOAT_EQ(1, saturation);
-    EXPECT_FLOAT_EQ(0.5, lightness);
+    EXPECT_FLOAT_EQ(0.33333334, hslaColor.hue);
+    EXPECT_FLOAT_EQ(1, hslaColor.saturation);
+    EXPECT_FLOAT_EQ(0.5, hslaColor.lightness);
 
-    EXPECT_FLOAT_EQ(color.lightness(), lightness);
+    EXPECT_FLOAT_EQ(color.lightness(), hslaColor.lightness);
 
-    auto roundTrippedColor = Color(makeSimpleColor(hslToSRGB({ hue, saturation, lightness, alpha })));
+    auto roundTrippedColor = makeSimpleColor(toSRGBA(hslaColor));
     EXPECT_EQ(color, roundTrippedColor);
 }
 
@@ -101,15 +101,15 @@ TEST(Color, RGBToHSL_Blue)
 {
     Color color = makeSimpleColor(0, 0, 255);
 
-    auto [hue, saturation, lightness, alpha] = sRGBToHSL(color.toSRGBAComponentsLossy());
+    auto hslaColor = toHSLA(color.toSRGBALossy());
 
-    EXPECT_FLOAT_EQ(0.66666669, hue);
-    EXPECT_FLOAT_EQ(1, saturation);
-    EXPECT_FLOAT_EQ(0.5, lightness);
+    EXPECT_FLOAT_EQ(0.66666669, hslaColor.hue);
+    EXPECT_FLOAT_EQ(1, hslaColor.saturation);
+    EXPECT_FLOAT_EQ(0.5, hslaColor.lightness);
 
-    EXPECT_FLOAT_EQ(color.lightness(), lightness);
+    EXPECT_FLOAT_EQ(color.lightness(), hslaColor.lightness);
 
-    auto roundTrippedColor = Color(makeSimpleColor(hslToSRGB({ hue, saturation, lightness, alpha })));
+    auto roundTrippedColor = makeSimpleColor(toSRGBA(hslaColor));
     EXPECT_EQ(color, roundTrippedColor);
 }
 
@@ -117,15 +117,15 @@ TEST(Color, RGBToHSL_DarkGray)
 {
     Color color = Color::darkGray;
 
-    auto [hue, saturation, lightness, alpha] = sRGBToHSL(color.toSRGBAComponentsLossy());
+    auto hslaColor = toHSLA(color.toSRGBALossy());
 
-    EXPECT_FLOAT_EQ(0, hue);
-    EXPECT_FLOAT_EQ(0, saturation);
-    EXPECT_FLOAT_EQ(0.50196078431372548, lightness);
+    EXPECT_FLOAT_EQ(0, hslaColor.hue);
+    EXPECT_FLOAT_EQ(0, hslaColor.saturation);
+    EXPECT_FLOAT_EQ(0.50196078431372548, hslaColor.lightness);
     
-    EXPECT_FLOAT_EQ(color.lightness(), lightness);
+    EXPECT_FLOAT_EQ(color.lightness(), hslaColor.lightness);
 
-    auto roundTrippedColor = Color(makeSimpleColor(hslToSRGB({ hue, saturation, lightness, alpha })));
+    auto roundTrippedColor = makeSimpleColor(toSRGBA(hslaColor));
     EXPECT_EQ(color, roundTrippedColor);
 }
 
@@ -133,15 +133,15 @@ TEST(Color, RGBToHSL_Gray)
 {
     Color color = Color::gray;
 
-    auto [hue, saturation, lightness, alpha] = sRGBToHSL(color.toSRGBAComponentsLossy());
+    auto hslaColor = toHSLA(color.toSRGBALossy());
 
-    EXPECT_FLOAT_EQ(0, hue);
-    EXPECT_FLOAT_EQ(0, saturation);
-    EXPECT_FLOAT_EQ(0.62745098039215685, lightness);
+    EXPECT_FLOAT_EQ(0, hslaColor.hue);
+    EXPECT_FLOAT_EQ(0, hslaColor.saturation);
+    EXPECT_FLOAT_EQ(0.62745098039215685, hslaColor.lightness);
 
-    EXPECT_FLOAT_EQ(color.lightness(), lightness);
+    EXPECT_FLOAT_EQ(color.lightness(), hslaColor.lightness);
 
-    auto roundTrippedColor = Color(makeSimpleColor(hslToSRGB({ hue, saturation, lightness, alpha })));
+    auto roundTrippedColor = makeSimpleColor(toSRGBA(hslaColor));
     EXPECT_EQ(color, roundTrippedColor);
 }
 
@@ -149,15 +149,15 @@ TEST(Color, RGBToHSL_LightGray)
 {
     Color color = Color::lightGray;
 
-    auto [hue, saturation, lightness, alpha] = sRGBToHSL(color.toSRGBAComponentsLossy());
+    auto hslaColor = toHSLA(color.toSRGBALossy());
 
-    EXPECT_FLOAT_EQ(0, hue);
-    EXPECT_FLOAT_EQ(0, saturation);
-    EXPECT_FLOAT_EQ(0.75294117647058822, lightness);
+    EXPECT_FLOAT_EQ(0, hslaColor.hue);
+    EXPECT_FLOAT_EQ(0, hslaColor.saturation);
+    EXPECT_FLOAT_EQ(0.75294117647058822, hslaColor.lightness);
 
-    EXPECT_FLOAT_EQ(color.lightness(), lightness);
+    EXPECT_FLOAT_EQ(color.lightness(), hslaColor.lightness);
 
-    auto roundTrippedColor = Color(makeSimpleColor(hslToSRGB({ hue, saturation, lightness, alpha })));
+    auto roundTrippedColor = makeSimpleColor(toSRGBA(hslaColor));
     EXPECT_EQ(color, roundTrippedColor);
 }
 
index 0d8c6a7..0f5e604 100644 (file)
@@ -237,27 +237,25 @@ TEST(ExtendedColor, ReturnValues)
 
 TEST(ExtendedColor, P3ConversionToSRGB)
 {
-    {
-        Color p3Color { makeExtendedColor(1.0, 0.5, 0.25, 0.75, ColorSpace::DisplayP3) };
-        EXPECT_TRUE(p3Color.isExtended());
-
-        auto sRGBComponents = p3Color.toSRGBAComponentsLossy();
-        EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBComponents.components[0], 1.0f));
-        EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBComponents.components[1], 0.462537885f));
-        EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBComponents.components[2], 0.149147838f));
-        EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBComponents.components[3], 0.75f));
-    }
-
-    {
-        Color linearColor { makeExtendedColor(1.0, 0.5, 0.25, 0.75, ColorSpace::LinearRGB) };
-        EXPECT_TRUE(linearColor.isExtended());
-        auto sRGBComponents = linearColor.toSRGBAComponentsLossy();
-        EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBComponents.components[0], 1.0f));
-        EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBComponents.components[1], 0.735356927f));
-        EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBComponents.components[2], 0.537098706f));
-        EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBComponents.components[3], 0.75f));
-    }
+    Color p3Color { makeExtendedColor(1.0, 0.5, 0.25, 0.75, ColorSpace::DisplayP3) };
+    EXPECT_TRUE(p3Color.isExtended());
+
+    auto sRGBAColor = p3Color.toSRGBALossy();
+    EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBAColor.red, 1.0f));
+    EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBAColor.green, 0.462537885f));
+    EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBAColor.blue, 0.149147838f));
+    EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBAColor.alpha, 0.75f));
 }
 
+TEST(ExtendedColor, LinearSRGBConversionToSRGB)
+{
+    Color linearColor { makeExtendedColor(1.0, 0.5, 0.25, 0.75, ColorSpace::LinearRGB) };
+    EXPECT_TRUE(linearColor.isExtended());
+    auto sRGBAColor = linearColor.toSRGBALossy();
+    EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBAColor.red, 1.0f));
+    EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBAColor.green, 0.735356927f));
+    EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBAColor.blue, 0.537098706f));
+    EXPECT_TRUE(WTF::areEssentiallyEqual(sRGBAColor.alpha, 0.75f));
+}
 
 } // namespace TestWebKitAPI