Skip to content
Permalink
Browse files
Extract color model and transfer functions into their own files
https://bugs.webkit.org/show_bug.cgi?id=221105

Reviewed by Tim Horton.

Things are getting a bit cramped in ColorTypes.h and ColorConversions.
This extracts the color models into ColorModels.h and gamma transfer
functions into ColorTransferFunctions.h and generalized the transfer
functions a bit to reduce the code size.

* Headers.cmake:
* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/ColorModels.h: Added.
* platform/graphics/ColorTransferFunctions.h: Added.
* platform/graphics/ColorConversion.cpp:
* platform/graphics/ColorConversion.h:
* platform/graphics/ColorTypes.h:
Move code to new files.


Canonical link: https://commits.webkit.org/233485@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@272066 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
weinig committed Jan 29, 2021
1 parent e653e53 commit efc94503d12d15020eb951a11cda623861298afb
Showing 9 changed files with 274 additions and 200 deletions.
@@ -1,3 +1,24 @@
2021-01-29 Sam Weinig <weinig@apple.com>

Extract color model and transfer functions into their own files
https://bugs.webkit.org/show_bug.cgi?id=221105

Reviewed by Tim Horton.

Things are getting a bit cramped in ColorTypes.h and ColorConversions.
This extracts the color models into ColorModels.h and gamma transfer
functions into ColorTransferFunctions.h and generalized the transfer
functions a bit to reduce the code size.

* Headers.cmake:
* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/ColorModels.h: Added.
* platform/graphics/ColorTransferFunctions.h: Added.
* platform/graphics/ColorConversion.cpp:
* platform/graphics/ColorConversion.h:
* platform/graphics/ColorTypes.h:
Move code to new files.

2021-01-29 Zalan Bujtas <zalan@apple.com>

[LFC][Integration] Switch over to legacy line layout when inline tree is required
@@ -1154,8 +1154,10 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS
platform/graphics/ColorConversion.h
platform/graphics/ColorHash.h
platform/graphics/ColorMatrix.h
platform/graphics/ColorModels.h
platform/graphics/ColorSerialization.h
platform/graphics/ColorSpace.h
platform/graphics/ColorTransferFunctions.h
platform/graphics/ColorTypes.h
platform/graphics/ColorUtilities.h
platform/graphics/ComplexTextController.h
@@ -3908,6 +3908,8 @@
BC06EDE40BFD6D0D00856E9D /* JSHTMLTableCellElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BC06EDE20BFD6D0D00856E9D /* JSHTMLTableCellElement.h */; };
BC06EE050BFD71AA00856E9D /* JSHTMLTableElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BC06EE030BFD71AA00856E9D /* JSHTMLTableElement.h */; };
BC073BAA0C399B1F000F5979 /* FloatConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = BC073BA90C399B1F000F5979 /* FloatConversion.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC10137C25C3624B00DC773C /* ColorModels.h in Headers */ = {isa = PBXBuildFile; fileRef = BC10137B25C3624B00DC773C /* ColorModels.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC10137F25C3631600DC773C /* ColorTransferFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = BC10137E25C3631600DC773C /* ColorTransferFunctions.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC10D76817D8EE71005E2626 /* RenderBlockFlow.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFB45F317D8E39200444446 /* RenderBlockFlow.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC124EE80C2641CD009E2349 /* BarProp.h in Headers */ = {isa = PBXBuildFile; fileRef = BC124EE50C2641CD009E2349 /* BarProp.h */; };
BC124F000C26447A009E2349 /* JSBarProp.h in Headers */ = {isa = PBXBuildFile; fileRef = BC124EFE0C26447A009E2349 /* JSBarProp.h */; };
@@ -13892,6 +13894,8 @@
BC06F24C06D18A7E004A6FA3 /* XSLTProcessor.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = XSLTProcessor.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
BC06F24D06D18A7E004A6FA3 /* XSLTProcessorLibxslt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XSLTProcessorLibxslt.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
BC073BA90C399B1F000F5979 /* FloatConversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FloatConversion.h; sourceTree = "<group>"; };
BC10137B25C3624B00DC773C /* ColorModels.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorModels.h; sourceTree = "<group>"; };
BC10137E25C3631600DC773C /* ColorTransferFunctions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorTransferFunctions.h; sourceTree = "<group>"; };
BC124EE40C2641CD009E2349 /* BarProp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BarProp.cpp; sourceTree = "<group>"; };
BC124EE50C2641CD009E2349 /* BarProp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BarProp.h; sourceTree = "<group>"; };
BC124EE60C2641CD009E2349 /* BarProp.idl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = BarProp.idl; sourceTree = "<group>"; };
@@ -26569,10 +26573,12 @@
7C514E0024AF80580050710F /* ColorConversion.h */,
3103B7DE1DB01556008BB890 /* ColorHash.h */,
7CAC6AE8247F082000E61D59 /* ColorMatrix.h */,
BC10137B25C3624B00DC773C /* ColorModels.h */,
7CD1E69224ABF6240089C419 /* ColorSerialization.cpp */,
7CD1E69124ABF6240089C419 /* ColorSerialization.h */,
BCAFEDAF25966D050030E6AA /* ColorSpace.cpp */,
9382DF5710A8D5C900925652 /* ColorSpace.h */,
BC10137E25C3631600DC773C /* ColorTransferFunctions.h */,
7C029C6D2493C8F800268204 /* ColorTypes.h */,
0FE6C76B1FBFB7A60025C053 /* ColorUtilities.cpp */,
0FE6C76C1FBFB7A60025C053 /* ColorUtilities.h */,
@@ -31486,9 +31492,11 @@
CE5169E721F1B84700EA4F78 /* ColorIOS.h in Headers */,
EDE3A5000C7A430600956A37 /* ColorMac.h in Headers */,
7CAC6AE9247F082F00E61D59 /* ColorMatrix.h in Headers */,
BC10137C25C3624B00DC773C /* ColorModels.h in Headers */,
7CD1E69324ABF6240089C419 /* ColorSerialization.h in Headers */,
9382DF5810A8D5C900925652 /* ColorSpace.h in Headers */,
BCAFEDB425968D0B0030E6AA /* ColorSpaceCG.h in Headers */,
BC10137F25C3631600DC773C /* ColorTransferFunctions.h in Headers */,
7C029C6E2493C8F800268204 /* ColorTypes.h in Headers */,
0FEAF66B23BFC39E004030DA /* ColorUtilities.h in Headers */,
BCDD454E1236C95C009A7985 /* ColumnInfo.h in Headers */,
@@ -28,6 +28,7 @@

#include "ColorComponents.h"
#include "ColorMatrix.h"
#include "ColorTransferFunctions.h"
#include <wtf/MathExtras.h>

namespace WebCore {
@@ -100,136 +101,64 @@ static constexpr ColorMatrix<3, 3> D65ToD50Matrix {

// MARK: Gamma conversions.

float A98RGBTransferFunction::fromLinearClamping(float c)
{
return clampTo<float>(fromLinearNonClamping(c), 0, 1);
}

float A98RGBTransferFunction::toLinearClamping(float c)
{
return clampTo<float>(toLinearNonClamping(c), 0, 1);
}

float A98RGBTransferFunction::fromLinearNonClamping(float c)
{
float sign = std::signbit(c) ? -1.0f : 1.0f;
return std::pow(std::abs(c), 256.0f / 563.0f) * sign;
}

float A98RGBTransferFunction::toLinearNonClamping(float c)
{
float sign = std::signbit(c) ? -1.0f : 1.0f;
return std::pow(std::abs(c), 563.0f / 256.0f) * sign;
}

float SRGBTransferFunction::fromLinearClamping(float c)
{
if (c < 0.0031308f)
return std::max<float>(12.92f * c, 0);

return clampTo<float>(1.055f * std::pow(c, 1.0f / 2.4f) - 0.055f, 0, 1);
}

float SRGBTransferFunction::toLinearClamping(float c)
{
if (c <= 0.04045f)
return std::max<float>(c / 12.92f, 0);

return clampTo<float>(std::pow((c + 0.055f) / 1.055f, 2.4f), 0, 1);
}

float SRGBTransferFunction::fromLinearNonClamping(float c)
{
float sign = std::signbit(c) ? -1.0f : 1.0f;
c = std::abs(c);

if (c < 0.0031308f)
return 12.92f * c * sign;

return (1.055f * std::pow(c, 1.0f / 2.4f) - 0.055f) * sign;
}

float SRGBTransferFunction::toLinearNonClamping(float c)
{
float sign = std::signbit(c) ? -1.0f : 1.0f;
c = std::abs(c);

if (c <= 0.04045f)
return c / 12.92f * sign;

return std::pow((c + 0.055f) / 1.055f, 2.4f) * sign;
}

template<typename TransferFunction, typename T> static auto toLinearClamping(const T& color) -> typename T::LinearCounterpart
{
auto [c1, c2, c3, alpha] = color;
return { TransferFunction::toLinearClamping(c1), TransferFunction::toLinearClamping(c2), TransferFunction::toLinearClamping(c3), alpha };
}

template<typename TransferFunction, typename T> static auto fromLinearClamping(const T& color) -> typename T::GammaEncodedCounterpart
{
auto [c1, c2, c3, alpha] = color;
return { TransferFunction::fromLinearClamping(c1), TransferFunction::fromLinearClamping(c2), TransferFunction::fromLinearClamping(c3), alpha };
}

template<typename TransferFunction, typename T> static auto toLinearNonClamping(const T& color) -> typename T::LinearCounterpart
template<typename TransferFunction, typename ColorType> static auto toLinear(const ColorType& color) -> typename ColorType::LinearCounterpart
{
auto [c1, c2, c3, alpha] = color;
return { TransferFunction::toLinearNonClamping(c1), TransferFunction::toLinearNonClamping(c2), TransferFunction::toLinearNonClamping(c3), alpha };
return { TransferFunction::toLinear(c1), TransferFunction::toLinear(c2), TransferFunction::toLinear(c3), alpha };
}

template<typename TransferFunction, typename T> static auto fromLinearNonClamping(const T& color) -> typename T::GammaEncodedCounterpart
template<typename TransferFunction, typename ColorType> static auto toGammaEncoded(const ColorType& color) -> typename ColorType::GammaEncodedCounterpart
{
auto [c1, c2, c3, alpha] = color;
return { TransferFunction::fromLinearNonClamping(c1), TransferFunction::fromLinearNonClamping(c2), TransferFunction::fromLinearNonClamping(c3), alpha };
return { TransferFunction::toGammaEncoded(c1), TransferFunction::toGammaEncoded(c2), TransferFunction::toGammaEncoded(c3), alpha };
}

// A98RGB <-> LinearA98RGB conversions.

LinearA98RGB<float> toLinearA98RGB(const A98RGB<float>& color)
{
return toLinearClamping<A98RGBTransferFunction>(color);
return toLinear<A98RGBTransferFunction<float, TransferFunctionMode::Clamped>>(color);
}

A98RGB<float> toA98RGB(const LinearA98RGB<float>& color)
{
return fromLinearClamping<A98RGBTransferFunction>(color);
return toGammaEncoded<A98RGBTransferFunction<float, TransferFunctionMode::Clamped>>(color);
}

// DisplayP3 <-> LinearDisplayP3 conversions.

LinearDisplayP3<float> toLinearDisplayP3(const DisplayP3<float>& color)
{
return toLinearClamping<SRGBTransferFunction>(color);
return toLinear<SRGBTransferFunction<float, TransferFunctionMode::Clamped>>(color);
}

DisplayP3<float> toDisplayP3(const LinearDisplayP3<float>& color)
{
return fromLinearClamping<SRGBTransferFunction>(color);
return toGammaEncoded<SRGBTransferFunction<float, TransferFunctionMode::Clamped>>(color);
}

// ExtendedSRGBA <-> LinearExtendedSRGBA conversions.

LinearExtendedSRGBA<float> toLinearExtendedSRGBA(const ExtendedSRGBA<float>& color)
{
return toLinearNonClamping<SRGBTransferFunction>(color);
return toLinear<SRGBTransferFunction<float, TransferFunctionMode::Unclamped>>(color);
}

ExtendedSRGBA<float> toExtendedSRGBA(const LinearExtendedSRGBA<float>& color)
{
return fromLinearNonClamping<SRGBTransferFunction>(color);
return toGammaEncoded<SRGBTransferFunction<float, TransferFunctionMode::Unclamped>>(color);
}

// SRGBA <-> LinearSRGBA conversions.

LinearSRGBA<float> toLinearSRGBA(const SRGBA<float>& color)
{
return toLinearClamping<SRGBTransferFunction>(color);
return toLinear<SRGBTransferFunction<float, TransferFunctionMode::Clamped>>(color);
}

SRGBA<float> toSRGBA(const LinearSRGBA<float>& color)
{
return fromLinearClamping<SRGBTransferFunction>(color);
return toGammaEncoded<SRGBTransferFunction<float, TransferFunctionMode::Clamped>>(color);
}

// MARK: Matrix conversions (to and from XYZ for all linear color types).
@@ -29,22 +29,6 @@

namespace WebCore {

// Transfer functions for colors that can be gamma encoded.

struct A98RGBTransferFunction {
static float fromLinearClamping(float);
static float toLinearClamping(float);
static float fromLinearNonClamping(float);
static float toLinearNonClamping(float);
};

struct SRGBTransferFunction {
static float fromLinearClamping(float);
static float toLinearClamping(float);
static float fromLinearNonClamping(float);
static float toLinearNonClamping(float);
};

// All color types must at least implement the following conversions to and from the XYZA color space:
// XYZA<float> toXYZA(const ColorType<float>&);
// ColorType<float> toColorType(const XYZA<float>&);
@@ -0,0 +1,118 @@
/*
* Copyright (C) 2021 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

namespace WebCore {

template<typename> struct AlphaTraits;
template<typename> struct ColorComponentRange;
template<typename> struct ExtendedRGBModel;
template<typename> struct HSLModel;
template<typename> struct LCHModel;
template<typename> struct LabModel;
template<typename> struct RGBModel;
template<typename> struct XYZModel;


template<> struct AlphaTraits<float> {
static constexpr float transparent = 0.0f;
static constexpr float opaque = 1.0f;
};

template<> struct AlphaTraits<uint8_t> {
static constexpr uint8_t transparent = 0;
static constexpr uint8_t opaque = 255;
};

template<typename T> struct ColorComponentRange {
T min;
T max;
};

template<> struct ExtendedRGBModel<float> {
static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
{ -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() },
{ -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() },
{ -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() }
} };
static constexpr bool isInvertible = false;
};

template<> struct HSLModel<float> {
static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
{ 0, 360 },
{ 0, 100 },
{ 0, 100 }
} };
static constexpr bool isInvertible = true;
};

template<> struct LabModel<float> {
static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
{ 0, std::numeric_limits<float>::infinity() },
{ -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() },
{ -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() }
} };
static constexpr bool isInvertible = false;
};

template<> struct LCHModel<float> {
static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
{ 0, std::numeric_limits<float>::infinity() },
{ 0, std::numeric_limits<float>::infinity() },
{ 0, 360 }
} };
static constexpr bool isInvertible = false;
};

template<> struct RGBModel<float> {
static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
{ 0, 1 },
{ 0, 1 },
{ 0, 1 }
} };
static constexpr bool isInvertible = true;
};

template<> struct RGBModel<uint8_t> {
static constexpr std::array<ColorComponentRange<uint8_t>, 3> ranges { {
{ 0, 255 },
{ 0, 255 },
{ 0, 255 }
} };
static constexpr bool isInvertible = true;
};

template<> struct XYZModel<float> {
static constexpr std::array<ColorComponentRange<float>, 3> ranges { {
{ -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() },
{ -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() },
{ -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() }
} };
static constexpr bool isInvertible = false;
};

}

0 comments on commit efc9450

Please sign in to comment.