Extended Color: ColorMatrix should support smaller matrices and be constexpr
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 29 May 2020 18:14:16 +0000 (18:14 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 29 May 2020 18:14:16 +0000 (18:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=212477

Reviewed by Simon Fraser.

- Adds the ability to specify a ColorMatrix with any number of rows or columns,
  useful as most of the uses ColorMatrix did not need the full 5x4. Transformation
  act as-if the the ColorMatrix is the identify matrix for any rows or columns
  not present. For example, when transforming a ColorComponents, which is 4x1, a
  3x3 ColorMatrix of the form:

      [ a, b, c ]
      [ d, e, f ]
      [ g, h, i ]

  will behave as-if it looks like:

      [ a, b, c, 0 ]
      [ d, e, f, 0 ]
      [ g, h, i, 0 ]
      [ 0, 0, 0, 1 ]

  In practice, this means that the last component of the input vector is left
  unmodified.

- Adds ability to use ColorMatrix in constexpr statements, which will be useful
  for compile time concatenation of colorspace conversion matrices in a future
  change but is also useful for improved space efficiency of constant matrices
  already used.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
Remove ColorMatrix.cpp

* platform/graphics/ColorComponents.h:
(WebCore::ColorComponents::ColorComponents):
(WebCore::ColorComponents::operator+=):
(WebCore::ColorComponents::operator+ const):
(WebCore::ColorComponents::operator/ const):
(WebCore::ColorComponents::operator* const):
(WebCore::ColorComponents::abs const):
(WebCore::ColorComponents::get const):
(WebCore::perComponentMax):
(WebCore::perComponentMin):
(WebCore::operator==):
(WebCore::operator!=):
Make everything constexpr and move implementations out of the declarations for clarity.

* platform/graphics/ColorMatrix.cpp: Removed.
* platform/graphics/ColorMatrix.h:
(WebCore::ColorMatrix::ColorMatrix):
(WebCore::ColorMatrix::at const):
(WebCore::grayscaleColorMatrix):
(WebCore::sepiaColorMatrix):
(WebCore::saturationColorMatrix):
(WebCore::hueRotateColorMatrix):
(WebCore::ColorMatrix::transformColorComponents):
(WebCore::ColorMatrix::transformedColorComponents):
Re-write as a class templatized on the number of rows and columns. Moves factory functions
out of the class to avoid awkwardness of having to specify a dummy size when calling them
(e.g. we wouldn't want you to have to write ColorMatrix<3, 3>::grayscaleMatrix(), instead
just grayscaleColorMatrix() is much nicer).

* platform/graphics/ColorUtilities.cpp:
(WebCore::xyzToLinearSRGB):
(WebCore::linearSRGBToXYZ):
(WebCore::XYZToLinearP3):
(WebCore::linearP3ToXYZ):
* platform/graphics/filters/FilterOperation.cpp:
(WebCore::BasicColorMatrixFilterOperation::transformColor const):
(WebCore::InvertLightnessFilterOperation::transformColor const):
(WebCore::InvertLightnessFilterOperation::inverseTransformColor const):
Adopt new ColorMatrix interface.

* platform/graphics/filters/FilterOperation.h:
Remove unnecessary T in forward declaration.

* platform/graphics/ColorUtilities.h:
(WebCore::fastMultiplyBy255):
(WebCore::fastDivideBy255):
Add some missing constexprs.

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

Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/graphics/ColorComponents.h
Source/WebCore/platform/graphics/ColorMatrix.cpp [deleted file]
Source/WebCore/platform/graphics/ColorMatrix.h
Source/WebCore/platform/graphics/ColorUtilities.cpp
Source/WebCore/platform/graphics/ColorUtilities.h
Source/WebCore/platform/graphics/filters/FEMorphology.cpp
Source/WebCore/platform/graphics/filters/FilterOperation.cpp
Source/WebCore/platform/graphics/filters/FilterOperation.h

index 564abce..0826423 100644 (file)
@@ -1,3 +1,87 @@
+2020-05-29  Sam Weinig  <weinig@apple.com>
+
+        Extended Color: ColorMatrix should support smaller matrices and be constexpr
+        https://bugs.webkit.org/show_bug.cgi?id=212477
+
+        Reviewed by Simon Fraser.
+
+        - Adds the ability to specify a ColorMatrix with any number of rows or columns,
+          useful as most of the uses ColorMatrix did not need the full 5x4. Transformation
+          act as-if the the ColorMatrix is the identify matrix for any rows or columns
+          not present. For example, when transforming a ColorComponents, which is 4x1, a 
+          3x3 ColorMatrix of the form:
+
+              [ a, b, c ]
+              [ d, e, f ]
+              [ g, h, i ]
+              
+          will behave as-if it looks like:
+          
+              [ a, b, c, 0 ]
+              [ d, e, f, 0 ]
+              [ g, h, i, 0 ]
+              [ 0, 0, 0, 1 ]
+        
+          In practice, this means that the last component of the input vector is left
+          unmodified.
+
+        - Adds ability to use ColorMatrix in constexpr statements, which will be useful
+          for compile time concatenation of colorspace conversion matrices in a future
+          change but is also useful for improved space efficiency of constant matrices
+          already used.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        Remove ColorMatrix.cpp
+
+        * platform/graphics/ColorComponents.h:
+        (WebCore::ColorComponents::ColorComponents):
+        (WebCore::ColorComponents::operator+=):
+        (WebCore::ColorComponents::operator+ const):
+        (WebCore::ColorComponents::operator/ const):
+        (WebCore::ColorComponents::operator* const):
+        (WebCore::ColorComponents::abs const):
+        (WebCore::ColorComponents::get const):
+        (WebCore::perComponentMax):
+        (WebCore::perComponentMin):
+        (WebCore::operator==):
+        (WebCore::operator!=):
+        Make everything constexpr and move implementations out of the declarations for clarity.
+
+        * platform/graphics/ColorMatrix.cpp: Removed.
+        * platform/graphics/ColorMatrix.h:
+        (WebCore::ColorMatrix::ColorMatrix):
+        (WebCore::ColorMatrix::at const):
+        (WebCore::grayscaleColorMatrix):
+        (WebCore::sepiaColorMatrix):
+        (WebCore::saturationColorMatrix):
+        (WebCore::hueRotateColorMatrix):
+        (WebCore::ColorMatrix::transformColorComponents):
+        (WebCore::ColorMatrix::transformedColorComponents):
+        Re-write as a class templatized on the number of rows and columns. Moves factory functions
+        out of the class to avoid awkwardness of having to specify a dummy size when calling them 
+        (e.g. we wouldn't want you to have to write ColorMatrix<3, 3>::grayscaleMatrix(), instead
+        just grayscaleColorMatrix() is much nicer).
+
+        * platform/graphics/ColorUtilities.cpp:
+        (WebCore::xyzToLinearSRGB):
+        (WebCore::linearSRGBToXYZ):
+        (WebCore::XYZToLinearP3):
+        (WebCore::linearP3ToXYZ):
+        * platform/graphics/filters/FilterOperation.cpp:
+        (WebCore::BasicColorMatrixFilterOperation::transformColor const):
+        (WebCore::InvertLightnessFilterOperation::transformColor const):
+        (WebCore::InvertLightnessFilterOperation::inverseTransformColor const):
+        Adopt new ColorMatrix interface.
+
+        * platform/graphics/filters/FilterOperation.h:
+        Remove unnecessary T in forward declaration.
+
+        * platform/graphics/ColorUtilities.h:
+        (WebCore::fastMultiplyBy255):
+        (WebCore::fastDivideBy255):
+        Add some missing constexprs.
+
 2020-05-29  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, reverting r262245.
index 47622b9..59dc9c6 100644 (file)
@@ -1872,7 +1872,6 @@ platform/encryptedmedia/CDMProxy.cpp
 platform/graphics/ANGLEWebKitBridge.cpp
 platform/graphics/BitmapImage.cpp
 platform/graphics/Color.cpp
-platform/graphics/ColorMatrix.cpp
 platform/graphics/ColorUtilities.cpp
 platform/graphics/ComplexTextController.cpp
 platform/graphics/CrossfadeGeneratedImage.cpp
index ff6985b..1609027 100644 (file)
                7C9DBFEA1A9C489F000D6B25 /* HTMLAttachmentElement.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = HTMLAttachmentElement.idl; sourceTree = "<group>"; };
                7C9DBFEB1A9C49B1000D6B25 /* JSHTMLAttachmentElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLAttachmentElement.cpp; sourceTree = "<group>"; };
                7C9DBFEC1A9C49B1000D6B25 /* JSHTMLAttachmentElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSHTMLAttachmentElement.h; sourceTree = "<group>"; };
-               7CAC6AE6247F081F00E61D59 /* ColorMatrix.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ColorMatrix.cpp; sourceTree = "<group>"; };
                7CAC6AE8247F082000E61D59 /* ColorMatrix.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorMatrix.h; sourceTree = "<group>"; };
                7CAC6AEC247F1C5100E61D59 /* ColorComponents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorComponents.h; sourceTree = "<group>"; };
                7CB5CA3D1E525C6C00FAEF13 /* MediaQueryExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaQueryExpression.cpp; sourceTree = "<group>"; };
                                B27535390B053814002CE64F /* Color.h */,
                                7CAC6AEC247F1C5100E61D59 /* ColorComponents.h */,
                                3103B7DE1DB01556008BB890 /* ColorHash.h */,
-                               7CAC6AE6247F081F00E61D59 /* ColorMatrix.cpp */,
                                7CAC6AE8247F082000E61D59 /* ColorMatrix.h */,
                                9382DF5710A8D5C900925652 /* ColorSpace.h */,
                                0FE6C76B1FBFB7A60025C053 /* ColorUtilities.cpp */,
index 5f29e0f..fc35bbb 100644 (file)
@@ -34,77 +34,90 @@ namespace WebCore {
 
 template<typename T>
 struct ColorComponents {
-    ColorComponents(T a = 0, T b = 0, T c = 0, T d = 0)
+    constexpr static size_t Size = 4;
+
+    constexpr ColorComponents(T a = 0, T b = 0, T c = 0, T d = 0)
         : components { a, b, c, d }
     {
     }
 
-    ColorComponents(const std::array<T, 4>& values)
-        : components { values }
-    {
-    }
+    constexpr ColorComponents& operator+=(const ColorComponents&);
 
-    ColorComponents& operator+=(const ColorComponents& rhs)
-    {
-        components[0] += rhs.components[0];
-        components[1] += rhs.components[1];
-        components[2] += rhs.components[2];
-        components[3] += rhs.components[3];
-        return *this;
-    }
+    constexpr ColorComponents operator+(T) const;
+    constexpr ColorComponents operator/(T) const;
+    constexpr ColorComponents operator*(T) const;
 
-    ColorComponents operator+(T rhs) const
-    {
-        return {
-            components[0] + rhs,
-            components[1] + rhs,
-            components[2] + rhs,
-            components[3] + rhs
-        };
-    }
+    constexpr ColorComponents abs() const;
 
-    ColorComponents operator/(T denominator) const
-    {
-        return {
-            components[0] / denominator,
-            components[1] / denominator,
-            components[2] / denominator,
-            components[3] / denominator
-        };
-    }
+    template<std::size_t N>
+    constexpr T get() const;
 
-    ColorComponents operator*(T factor) const
-    {
-        return {
-            components[0] * factor,
-            components[1] * factor,
-            components[2] * factor,
-            components[3] * factor
-        };
-    }
+    std::array<T, Size> components;
+};
 
-    ColorComponents abs() const
-    {
-        return {
-            std::abs(components[0]),
-            std::abs(components[1]),
-            std::abs(components[2]),
-            std::abs(components[3])
-        };
-    }
+template<typename T>
+constexpr ColorComponents<T>& ColorComponents<T>::operator+=(const ColorComponents& rhs)
+{
+    components[0] += rhs.components[0];
+    components[1] += rhs.components[1];
+    components[2] += rhs.components[2];
+    components[3] += rhs.components[3];
+    return *this;
+}
 
-    template<std::size_t N>
-    T get() const
-    {
-        return components[N];
-    }
+template<typename T>
+constexpr ColorComponents<T> ColorComponents<T>::operator+(T rhs) const
+{
+    return {
+        components[0] + rhs,
+        components[1] + rhs,
+        components[2] + rhs,
+        components[3] + rhs
+    };
+}
 
-    std::array<T, 4> components;
-};
+template<typename T>
+constexpr ColorComponents<T> ColorComponents<T>::operator/(T denominator) const
+{
+    return {
+        components[0] / denominator,
+        components[1] / denominator,
+        components[2] / denominator,
+        components[3] / denominator
+    };
+}
 
+template<typename T>
+constexpr ColorComponents<T> ColorComponents<T>::operator*(T factor) const
+{
+    return {
+        components[0] * factor,
+        components[1] * factor,
+        components[2] * factor,
+        components[3] * factor
+    };
+}
+
+template<typename T>
+constexpr ColorComponents<T> ColorComponents<T>::abs() const
+{
+    return {
+        std::abs(components[0]),
+        std::abs(components[1]),
+        std::abs(components[2]),
+        std::abs(components[3])
+    };
+}
+
+template<typename T>
+template<std::size_t N>
+constexpr T ColorComponents<T>::get() const
+{
+    return components[N];
+}
 
 template<typename T>
-inline ColorComponents<T> perComponentMax(const ColorComponents<T>& a, const ColorComponents<T>& b)
+constexpr ColorComponents<T> perComponentMax(const ColorComponents<T>& a, const ColorComponents<T>& b)
 {
     return {
         std::max(a.components[0], b.components[0]),
@@ -115,7 +128,7 @@ inline ColorComponents<T> perComponentMax(const ColorComponents<T>& a, const Col
 }
 
 template<typename T>
-inline ColorComponents<T> perComponentMin(const ColorComponents<T>& a, const ColorComponents<T>& b)
+constexpr ColorComponents<T> perComponentMin(const ColorComponents<T>& a, const ColorComponents<T>& b)
 {
     return {
         std::min(a.components[0], b.components[0]),
@@ -126,13 +139,13 @@ inline ColorComponents<T> perComponentMin(const ColorComponents<T>& a, const Col
 }
 
 template<typename T>
-inline bool operator==(const ColorComponents<T>& a, const ColorComponents<T>& b)
+constexpr bool operator==(const ColorComponents<T>& a, const ColorComponents<T>& b)
 {
     return a.components == b.components;
 }
 
 template<typename T>
-inline bool operator!=(const ColorComponents<T>& a, const ColorComponents<T>& b)
+constexpr bool operator!=(const ColorComponents<T>& a, const ColorComponents<T>& b)
 {
     return !(a == b);
 }
@@ -142,7 +155,7 @@ inline bool operator!=(const ColorComponents<T>& a, const ColorComponents<T>& b)
 namespace std {
 
 template<typename T>
-class tuple_size<WebCore::ColorComponents<T>> : public std::integral_constant<std::size_t, 4> {
+class tuple_size<WebCore::ColorComponents<T>> : public std::integral_constant<std::size_t, WebCore::ColorComponents<T>::Size> {
 };
 
 template<std::size_t N, typename T>
diff --git a/Source/WebCore/platform/graphics/ColorMatrix.cpp b/Source/WebCore/platform/graphics/ColorMatrix.cpp
deleted file mode 100644 (file)
index 6ebd53b..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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 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 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.
- */
-
-#include "config.h"
-#include "ColorMatrix.h"
-
-#include "ColorComponents.h"
-#include <wtf/MathExtras.h>
-
-namespace WebCore {
-
-ColorMatrix::ColorMatrix()
-{
-    makeIdentity();
-}
-
-ColorMatrix::ColorMatrix(const float values[20])
-{
-    m_matrix[0][0] = values[0];
-    m_matrix[0][1] = values[1];
-    m_matrix[0][2] = values[2];
-    m_matrix[0][3] = values[3];
-    m_matrix[0][4] = values[4];
-
-    m_matrix[1][0] = values[5];
-    m_matrix[1][1] = values[6];
-    m_matrix[1][2] = values[7];
-    m_matrix[1][3] = values[8];
-    m_matrix[1][4] = values[9];
-
-    m_matrix[2][0] = values[10];
-    m_matrix[2][1] = values[11];
-    m_matrix[2][2] = values[12];
-    m_matrix[2][3] = values[13];
-    m_matrix[2][4] = values[14];
-
-    m_matrix[3][0] = values[15];
-    m_matrix[3][1] = values[16];
-    m_matrix[3][2] = values[17];
-    m_matrix[3][3] = values[18];
-    m_matrix[3][4] = values[19];
-}
-
-void ColorMatrix::makeIdentity()
-{
-    memset(m_matrix, 0, sizeof(m_matrix));
-    m_matrix[0][0] = 1;
-    m_matrix[1][1] = 1;
-    m_matrix[2][2] = 1;
-    m_matrix[3][3] = 1;
-}
-
-ColorMatrix ColorMatrix::grayscaleMatrix(float amount)
-{
-    ColorMatrix matrix;
-
-    float oneMinusAmount = clampTo(1 - amount, 0.0, 1.0);
-
-    // Values from https://www.w3.org/TR/filter-effects-1/#grayscaleEquivalent
-    matrix.m_matrix[0][0] = 0.2126f + 0.7874f * oneMinusAmount;
-    matrix.m_matrix[0][1] = 0.7152f - 0.7152f * oneMinusAmount;
-    matrix.m_matrix[0][2] = 0.0722f - 0.0722f * oneMinusAmount;
-
-    matrix.m_matrix[1][0] = 0.2126f - 0.2126f * oneMinusAmount;
-    matrix.m_matrix[1][1] = 0.7152f + 0.2848f * oneMinusAmount;
-    matrix.m_matrix[1][2] = 0.0722f - 0.0722f * oneMinusAmount;
-
-    matrix.m_matrix[2][0] = 0.2126f - 0.2126f * oneMinusAmount;
-    matrix.m_matrix[2][1] = 0.7152f - 0.7152f * oneMinusAmount;
-    matrix.m_matrix[2][2] = 0.0722f + 0.9278f * oneMinusAmount;
-    
-    return matrix;
-}
-
-ColorMatrix ColorMatrix::saturationMatrix(float amount)
-{
-    ColorMatrix matrix;
-
-    // Values from https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
-    matrix.m_matrix[0][0] = 0.213f + 0.787f * amount;
-    matrix.m_matrix[0][1] = 0.715f - 0.715f * amount;
-    matrix.m_matrix[0][2] = 0.072f - 0.072f * amount;
-
-    matrix.m_matrix[1][0] = 0.213f - 0.213f * amount;
-    matrix.m_matrix[1][1] = 0.715f + 0.285f * amount;
-    matrix.m_matrix[1][2] = 0.072f - 0.072f * amount;
-
-    matrix.m_matrix[2][0] = 0.213f - 0.213f * amount;
-    matrix.m_matrix[2][1] = 0.715f - 0.715f * amount;
-    matrix.m_matrix[2][2] = 0.072f + 0.928f * amount;
-
-    return matrix;
-}
-
-ColorMatrix ColorMatrix::hueRotateMatrix(float angleInDegrees)
-{
-    float cosHue = cos(deg2rad(angleInDegrees));
-    float sinHue = sin(deg2rad(angleInDegrees));
-
-    ColorMatrix matrix;
-
-    // Values from https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
-    matrix.m_matrix[0][0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f;
-    matrix.m_matrix[0][1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f;
-    matrix.m_matrix[0][2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f;
-
-    matrix.m_matrix[1][0] = 0.213f - cosHue * 0.213f + sinHue * 0.143f;
-    matrix.m_matrix[1][1] = 0.715f + cosHue * 0.285f + sinHue * 0.140f;
-    matrix.m_matrix[1][2] = 0.072f - cosHue * 0.072f - sinHue * 0.283f;
-
-    matrix.m_matrix[2][0] = 0.213f - cosHue * 0.213f - sinHue * 0.787f;
-    matrix.m_matrix[2][1] = 0.715f - cosHue * 0.715f + sinHue * 0.715f;
-    matrix.m_matrix[2][2] = 0.072f + cosHue * 0.928f + sinHue * 0.072f;
-
-    return matrix;
-}
-
-ColorMatrix ColorMatrix::sepiaMatrix(float amount)
-{
-    ColorMatrix matrix;
-
-    float oneMinusAmount = clampTo(1 - amount, 0.0, 1.0);
-
-    // Values from https://www.w3.org/TR/filter-effects-1/#sepiaEquivalent
-    matrix.m_matrix[0][0] = 0.393f + 0.607f * oneMinusAmount;
-    matrix.m_matrix[0][1] = 0.769f - 0.769f * oneMinusAmount;
-    matrix.m_matrix[0][2] = 0.189f - 0.189f * oneMinusAmount;
-
-    matrix.m_matrix[1][0] = 0.349f - 0.349f * oneMinusAmount;
-    matrix.m_matrix[1][1] = 0.686f + 0.314f * oneMinusAmount;
-    matrix.m_matrix[1][2] = 0.168f - 0.168f * oneMinusAmount;
-
-    matrix.m_matrix[2][0] = 0.272f - 0.272f * oneMinusAmount;
-    matrix.m_matrix[2][1] = 0.534f - 0.534f * oneMinusAmount;
-    matrix.m_matrix[2][2] = 0.131f + 0.869f * oneMinusAmount;
-
-    return matrix;
-}
-
-void ColorMatrix::transformColorComponents(ColorComponents<float>& colorComponents) const
-{
-    auto [red, green, blue, alpha] = colorComponents;
-
-    colorComponents.components[0] = m_matrix[0][0] * red + m_matrix[0][1] * green + m_matrix[0][2] * blue + m_matrix[0][3] * alpha + m_matrix[0][4];
-    colorComponents.components[1] = m_matrix[1][0] * red + m_matrix[1][1] * green + m_matrix[1][2] * blue + m_matrix[1][3] * alpha + m_matrix[1][4];
-    colorComponents.components[2] = m_matrix[2][0] * red + m_matrix[2][1] * green + m_matrix[2][2] * blue + m_matrix[2][3] * alpha + m_matrix[2][4];
-    colorComponents.components[3] = m_matrix[3][0] * red + m_matrix[3][1] * green + m_matrix[3][2] * blue + m_matrix[3][3] * alpha + m_matrix[3][4];
-}
-
-ColorComponents<float> ColorMatrix::transformedColorComponents(const ColorComponents<float>& colorComponents) const
-{
-    auto [red, green, blue, alpha] = colorComponents;
-
-    return {
-        m_matrix[0][0] * red + m_matrix[0][1] * green + m_matrix[0][2] * blue + m_matrix[0][3] * alpha + m_matrix[0][4],
-        m_matrix[1][0] * red + m_matrix[1][1] * green + m_matrix[1][2] * blue + m_matrix[1][3] * alpha + m_matrix[1][4],
-        m_matrix[2][0] * red + m_matrix[2][1] * green + m_matrix[2][2] * blue + m_matrix[2][3] * alpha + m_matrix[2][4],
-        m_matrix[3][0] * red + m_matrix[3][1] * green + m_matrix[3][2] * blue + m_matrix[3][3] * alpha + m_matrix[3][4]
-    };
-}
-
-} // namespace WebCore
index fdf5c62..172dbe8 100644 (file)
 
 #pragma once
 
-namespace WebCore {
+#include "ColorComponents.h"
+#include <math.h>
+#include <wtf/MathExtras.h>
 
-template<typename T> struct ColorComponents;
+namespace WebCore {
 
-// FIXME: This should likely be replaced by a generic matrix class. Other than
-// the specific matrix constuctors, there is nothing color specific about this.
-// Futhermore, most these don't need to be 4x5 matrices with most only needing
-// a 3x3 matrix.
+template<size_t Columns, size_t Rows>
 class ColorMatrix {
 public:
-    static ColorMatrix grayscaleMatrix(float);
-    static ColorMatrix saturationMatrix(float);
-    static ColorMatrix hueRotateMatrix(float angleInDegrees);
-    static ColorMatrix sepiaMatrix(float);
+    template<typename ...Ts>
+    explicit constexpr ColorMatrix(Ts ...input)
+        : m_matrix {{ input ... }}
+    {
+        static_assert(sizeof...(Ts) == Rows * Columns);
+    }
 
-    ColorMatrix();
-    ColorMatrix(const float[20]);
-    
-    void transformColorComponents(ColorComponents<float>&) const;
-    ColorComponents<float> transformedColorComponents(const ColorComponents<float>&) const;
+    constexpr void transformColorComponents(ColorComponents<float>&) const;
+    constexpr ColorComponents<float> transformedColorComponents(const ColorComponents<float>&) const;
 
-private:
-    void makeIdentity();
+    constexpr float at(size_t row, size_t column) const
+    {
+        return m_matrix[(row * Columns) + column];
+    }
 
-    float m_matrix[4][5];
+private:
+    std::array<float, Rows * Columns> m_matrix;
 };
 
+// FIXME: These are only used in FilterOperations.cpp. Consider moving them there.
+constexpr ColorMatrix<3, 3> grayscaleColorMatrix(float amount)
+{
+    // Values from https://www.w3.org/TR/filter-effects-1/#grayscaleEquivalent
+    float oneMinusAmount = std::clamp(1.0f - amount, 0.0f, 1.0f);
+    return ColorMatrix<3, 3> {
+        0.2126f + 0.7874f * oneMinusAmount, 0.7152f - 0.7152f * oneMinusAmount, 0.0722f - 0.0722f * oneMinusAmount,
+        0.2126f - 0.2126f * oneMinusAmount, 0.7152f + 0.2848f * oneMinusAmount, 0.0722f - 0.0722f * oneMinusAmount,
+        0.2126f - 0.2126f * oneMinusAmount, 0.7152f - 0.7152f * oneMinusAmount, 0.0722f + 0.9278f * oneMinusAmount
+    };
+}
+
+constexpr ColorMatrix<3, 3> sepiaColorMatrix(float amount)
+{
+    // Values from https://www.w3.org/TR/filter-effects-1/#sepiaEquivalent
+    float oneMinusAmount = std::clamp(1.0f - amount, 0.0f, 1.0f);
+    return ColorMatrix<3, 3> {
+        0.393f + 0.607f * oneMinusAmount, 0.769f - 0.769f * oneMinusAmount, 0.189f - 0.189f * oneMinusAmount,
+        0.349f - 0.349f * oneMinusAmount, 0.686f + 0.314f * oneMinusAmount, 0.168f - 0.168f * oneMinusAmount,
+        0.272f - 0.272f * oneMinusAmount, 0.534f - 0.534f * oneMinusAmount, 0.131f + 0.869f * oneMinusAmount
+    };
+}
+
+constexpr ColorMatrix<3, 3> saturationColorMatrix(float amount)
+{
+    // Values from https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
+    return ColorMatrix<3, 3> {
+        0.213f + 0.787f * amount,  0.715f - 0.715f * amount, 0.072f - 0.072f * amount,
+        0.213f - 0.213f * amount,  0.715f + 0.285f * amount, 0.072f - 0.072f * amount,
+        0.213f - 0.213f * amount,  0.715f - 0.715f * amount, 0.072f + 0.928f * amount
+    };
+}
+
+// NOTE: hueRotateColorMatrix is not constexpr due to use of cos/sin which are not constexpr yet.
+inline ColorMatrix<3, 3> hueRotateColorMatrix(float angleInDegrees)
+{
+    float cosHue = cos(deg2rad(angleInDegrees));
+    float sinHue = sin(deg2rad(angleInDegrees));
+
+    // Values from https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
+    return ColorMatrix<3, 3> {
+        0.213f + cosHue * 0.787f - sinHue * 0.213f, 0.715f - cosHue * 0.715f - sinHue * 0.715f, 0.072f - cosHue * 0.072f + sinHue * 0.928f,
+        0.213f - cosHue * 0.213f + sinHue * 0.143f, 0.715f + cosHue * 0.285f + sinHue * 0.140f, 0.072f - cosHue * 0.072f - sinHue * 0.283f,
+        0.213f - cosHue * 0.213f - sinHue * 0.787f, 0.715f - cosHue * 0.715f + sinHue * 0.715f, 0.072f + cosHue * 0.928f + sinHue * 0.072f
+    };
+}
+
+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);
+    
+    ColorComponents<float> result;
+    for (size_t row = 0; row < Rows; ++row) {
+        if constexpr (Columns <= ColorComponents<float>::Size) {
+            for (size_t column = 0; column < Columns; ++column)
+                result.components[row] += at(row, column) * inputVector.components[column];
+        } else if constexpr (Columns > ColorComponents<float>::Size) {
+            for (size_t column = 0; column < ColorComponents<float>::Size; ++column)
+                result.components[row] += at(row, column) * inputVector.components[column];
+            for (size_t additionalColumn = ColorComponents<float>::Size; additionalColumn < Columns; ++additionalColumn)
+                result.components[row] += at(row, additionalColumn);
+        }
+    }
+    if constexpr (ColorComponents<float>::Size > Rows) {
+        for (size_t additionalRow = Rows; additionalRow < ColorComponents<float>::Size; ++additionalRow)
+            result.components[additionalRow] = inputVector.components[additionalRow];
+    }
+
+    return result;
+}
+
 } // namespace WebCore
index daf3c94..19cecbf 100644 (file)
@@ -80,13 +80,11 @@ static ColorComponents<float> xyzToLinearSRGB(const ColorComponents<float>& XYZC
 {
     // https://en.wikipedia.org/wiki/SRGB
     // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
-    const float values[] = {
-         3.2404542f, -1.5371385f, -0.4985314f, 0.0f, 0.0f,
-        -0.9692660f,  1.8760108f,  0.0415560f, 0.0f, 0.0f,
-         0.0556434f, -0.2040259f,  1.0572252f, 0.0f, 0.0f,
-         0.0f,        0.0f,        0.0f,       1.0f, 0.0f,
+    constexpr ColorMatrix<3, 3> xyzToLinearSRGBMatrix {
+         3.2404542f, -1.5371385f, -0.4985314f,
+        -0.9692660f,  1.8760108f,  0.0415560f,
+         0.0556434f, -0.2040259f,  1.0572252f
     };
-    ColorMatrix xyzToLinearSRGBMatrix(values);
     return xyzToLinearSRGBMatrix.transformedColorComponents(XYZComponents);
 }
 
@@ -94,39 +92,33 @@ static ColorComponents<float> linearSRGBToXYZ(const ColorComponents<float>& XYZC
 {
     // https://en.wikipedia.org/wiki/SRGB
     // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
-    const float values[] = {
-        0.4124564f,  0.3575761f,  0.1804375f, 0.0f, 0.0f,
-        0.2126729f,  0.7151522f,  0.0721750f, 0.0f, 0.0f,
-        0.0193339f,  0.1191920f,  0.9503041f, 0.0f, 0.0f,
-        0.0f,        0.0f,        0.0f,       1.0f, 0.0f,
+    constexpr ColorMatrix<3, 3> linearSRGBToXYZMatrix {
+        0.4124564f,  0.3575761f,  0.1804375f,
+        0.2126729f,  0.7151522f,  0.0721750f,
+        0.0193339f,  0.1191920f,  0.9503041f
     };
-    ColorMatrix linearSRGBToXYZMatrix(values);
     return linearSRGBToXYZMatrix.transformedColorComponents(XYZComponents);
 }
 
 static ColorComponents<float> XYZToLinearP3(const ColorComponents<float>& XYZComponents)
 {
     // https://drafts.csswg.org/css-color/#color-conversion-code
-    const float values[] = {
-         2.493496911941425f,  -0.9313836179191239f, -0.4027107844507168f, 0.0f, 0.0f,
-        -0.8294889695615747f,  1.7626640603183463f,  0.0236246858419436f, 0.0f, 0.0f,
-         0.0358458302437845f, -0.0761723892680418f,  0.9568845240076872f, 0.0f, 0.0f,
-         0.0f,                 0.0f,                 0.0f,                1.0f, 0.0f,
+    constexpr ColorMatrix<3, 3> xyzToLinearSRGBMatrix {
+         2.493496911941425f,  -0.9313836179191239f, -0.4027107844507168f,
+        -0.8294889695615747f,  1.7626640603183463f,  0.0236246858419436f,
+         0.0358458302437845f, -0.0761723892680418f,  0.9568845240076872f
     };
-    ColorMatrix xyzToLinearSRGBMatrix(values);
     return xyzToLinearSRGBMatrix.transformedColorComponents(XYZComponents);
 }
 
 static ColorComponents<float> linearP3ToXYZ(const ColorComponents<float>& XYZComponents)
 {
     // https://drafts.csswg.org/css-color/#color-conversion-code
-    const float values[] = {
-        0.4865709486482162f, 0.2656676931690931f, 0.198217285234363f, 0.0f, 0.0f,
-        0.2289745640697488f, 0.6917385218365064f, 0.079286914093745f, 0.0f, 0.0f,
-        0.0f,                0.0451133818589026f, 1.043944368900976f, 0.0f, 0.0f,
-        0.0f,                0.0f,                0.0f,               1.0f, 0.0f,
+    constexpr ColorMatrix<3, 3> linearP3ToXYZMatrix {
+        0.4865709486482162f, 0.2656676931690931f, 0.198217285234363f,
+        0.2289745640697488f, 0.6917385218365064f, 0.079286914093745f,
+        0.0f,                0.0451133818589026f, 1.043944368900976f
     };
-    ColorMatrix linearP3ToXYZMatrix(values);
     return linearP3ToXYZMatrix.transformedColorComponents(XYZComponents);
 }
 
index 61f4923..9be04c7 100644 (file)
@@ -30,7 +30,7 @@
 
 namespace WebCore {
 
-template<typename T> struct ColorComponents;
+template<typename> struct ColorComponents;
 
 // 0-1 components, result is clamped.
 float linearToRGBColorComponent(float);
@@ -63,12 +63,12 @@ inline uint8_t roundAndClampColorChannel(float value)
     return std::clamp(std::round(value), 0.f, 255.f);
 }
 
-inline uint16_t fastMultiplyBy255(uint16_t value)
+constexpr uint16_t fastMultiplyBy255(uint16_t value)
 {
     return (value << 8) - value;
 }
 
-inline uint16_t fastDivideBy255(uint16_t value)
+constexpr uint16_t fastDivideBy255(uint16_t value)
 {
     // While this is an approximate algorithm for division by 255, it gives perfectly accurate results for 16-bit values.
     // FIXME: Since this gives accurate results for 16-bit values, we should get this optimization into compilers like clang.
index 8a89d13..293a507 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #include "FEMorphology.h"
 
+#include "ColorComponents.h"
 #include "ColorUtilities.h"
 #include "Filter.h"
 #include "ImageData.h"
index f4b696a..ad41948 100644 (file)
@@ -89,22 +89,22 @@ bool BasicColorMatrixFilterOperation::transformColor(ColorComponents<float>& col
 {
     switch (m_type) {
     case GRAYSCALE: {
-        ColorMatrix matrix = ColorMatrix::grayscaleMatrix(m_amount);
+        auto matrix = grayscaleColorMatrix(m_amount);
         matrix.transformColorComponents(colorComponents);
         return true;
     }
     case SEPIA: {
-        ColorMatrix matrix = ColorMatrix::sepiaMatrix(m_amount);
+        auto matrix = sepiaColorMatrix(m_amount);
         matrix.transformColorComponents(colorComponents);
         return true;
     }
     case HUE_ROTATE: {
-        ColorMatrix matrix = ColorMatrix::hueRotateMatrix(m_amount);
+        auto matrix = hueRotateColorMatrix(m_amount);
         matrix.transformColorComponents(colorComponents);
         return true;
     }
     case SATURATE: {
-        ColorMatrix matrix = ColorMatrix::saturationMatrix(m_amount);
+        auto matrix = saturationColorMatrix(m_amount);
         matrix.transformColorComponents(colorComponents);
         return true;
     }
@@ -237,14 +237,11 @@ bool InvertLightnessFilterOperation::transformColor(ColorComponents<float>& sRGB
     sRGBColorComponents = hslToSRGB(hslComponents);
     
     // Apply the matrix. See rdar://problem/41146650 for how this matrix was derived.
-    const float matrixValues[20] = {
-       -0.770,  0.059, -0.089, 0, 1,
-        0.030, -0.741, -0.089, 0, 1,
-        0.030,  0.059, -0.890, 0, 1,
-        0,      0,      0,     1, 0
+    constexpr ColorMatrix<5, 3> toDarkModeMatrix {
+       -0.770f,  0.059f, -0.089f, 0.0f, 1.0f,
+        0.030f, -0.741f, -0.089f, 0.0f, 1.0f,
+        0.030f,  0.059f, -0.890f, 0.0f, 1.0f
     };
-
-    ColorMatrix toDarkModeMatrix(matrixValues);
     toDarkModeMatrix.transformColorComponents(sRGBColorComponents);
     return true;
 }
@@ -254,13 +251,11 @@ bool InvertLightnessFilterOperation::inverseTransformColor(ColorComponents<float
     auto rgbComponents = sRGBColorComponents;
 
     // Apply the matrix.
-    const float matrixValues[20] = {
-        -1.300, -0.097,  0.147, 0, 1.25,
-        -0.049, -1.347,  0.146, 0, 1.25,
-        -0.049, -0.097, -1.104, 0, 1.25,
-         0,      0,      0,     1, 0
+    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
     };
-    ColorMatrix toLightModeMatrix(matrixValues);
     toLightModeMatrix.transformColorComponents(rgbComponents);
 
     // Convert to HSL.
index 3036b48..f794123 100644 (file)
@@ -45,7 +45,7 @@ class CachedResourceLoader;
 class CachedSVGDocumentReference;
 class FilterEffect;
 struct ResourceLoaderOptions;
-template<typename T> struct ColorComponents;
+template<typename> struct ColorComponents;
 
 class FilterOperation : public ThreadSafeRefCounted<FilterOperation> {
 public: