Modified: trunk/Source/WebCore/platform/graphics/cg/ColorCG.cpp (287888 => 287889)
--- trunk/Source/WebCore/platform/graphics/cg/ColorCG.cpp 2022-01-11 18:31:19 UTC (rev 287888)
+++ trunk/Source/WebCore/platform/graphics/cg/ColorCG.cpp 2022-01-11 18:43:31 UTC (rev 287889)
@@ -88,23 +88,30 @@
return convertColor<SRGBA<uint8_t>>(makeFromComponentsClamping<SRGBA<float>>(r, g, b, a ));
}
+template<ColorSpace space>
+static CGColorTransformRef cachedCGColorTransform()
+{
+ static LazyNeverDestroyed<RetainPtr<CGColorTransformRef>> transform;
+
+ static std::once_flag onceFlag;
+ std::call_once(onceFlag, [] {
+ transform.construct(adoptCF(CGColorTransformCreate(cachedCGColorSpace<space>(), nullptr)));
+ });
+
+ return transform->get();
+}
+
Color Color::createAndLosslesslyConvertToSupportedColorSpace(CGColorRef color, OptionSet<Flags> flags)
{
+ // FIXME: This should probably use ExtendedSRGBA rather than XYZ_D50, as it is a more commonly used color space and just as expressive.
+ constexpr auto destinationColorSpace = HasCGColorSpaceMapping<ColorSpace::XYZ_D50> ? ColorSpace::XYZ_D50 : ColorSpace::SRGB;
+ ASSERT(CGColorSpaceGetNumberOfComponents(cachedCGColorSpace<destinationColorSpace>()) == 3);
+
auto sourceCGColorSpace = CGColorGetColorSpace(color);
-#if HAVE(CORE_GRAPHICS_XYZ_D50_COLOR_SPACE)
- auto destinationCGColorSpace = xyzD50ColorSpaceRef();
- auto destinationColorSpace = ColorSpace::XYZ_D50;
-#else
- auto destinationCGColorSpace = sRGBColorSpaceRef();
- auto destinationColorSpace = ColorSpace::SRGB;
-#endif
- ASSERT(CGColorSpaceGetNumberOfComponents(destinationCGColorSpace) == 3);
-
auto sourceComponents = CGColorGetComponents(color);
- CGFloat destinationComponents[3] { };
+ std::array<CGFloat, 3> destinationComponents { };
- auto transform = adoptCF(CGColorTransformCreate(destinationCGColorSpace, nullptr));
- auto result = CGColorTransformConvertColorComponents(transform.get(), sourceCGColorSpace, kCGRenderingIntentDefault, sourceComponents, destinationComponents);
+ auto result = CGColorTransformConvertColorComponents(cachedCGColorTransform<destinationColorSpace>(), sourceCGColorSpace, kCGRenderingIntentDefault, sourceComponents, destinationComponents.data());
ASSERT_UNUSED(result, result);
float a = destinationComponents[0];
@@ -143,22 +150,15 @@
// the color into either extended sRGB or normal sRGB, if extended sRGB is
// not supported.
- auto cgColorSpace = cachedNullableCGColorSpace(colorSpace);
- if (!cgColorSpace) {
-#if HAVE(CORE_GRAPHICS_EXTENDED_SRGB_COLOR_SPACE)
- auto componentsConvertedToExtendedSRGBA = callWithColorType(components, colorSpace, [] (const auto& color) {
- return asColorComponents(convertColor<ExtendedSRGBA<float>>(color).resolved());
- });
- return { extendedSRGBColorSpaceRef(), componentsConvertedToExtendedSRGBA };
-#else
- auto componentsConvertedToSRGBA = callWithColorType(components, colorSpace, [] (const auto& color) {
- return asColorComponents(convertColor<SRGBA<float>>(color).resolved());
- });
- return { sRGBColorSpaceRef(), componentsConvertedToSRGBA };
-#endif
- }
+ using FallbackColorType = std::conditional_t<HasCGColorSpaceMapping<ColorSpace::ExtendedSRGB>, ExtendedSRGBA<float>, SRGBA<float>>;
- return { cgColorSpace, components };
+ if (auto cgColorSpace = cachedNullableCGColorSpace(colorSpace))
+ return { cgColorSpace, components };
+
+ auto componentsConvertedToFallbackColorSpace = callWithColorType(components, colorSpace, [] (const auto& color) {
+ return asColorComponents(convertColor<FallbackColorType>(color).resolved());
+ });
+ return { cachedCGColorSpace<ColorSpaceFor<FallbackColorType>>(), componentsConvertedToFallbackColorSpace };
}
static RetainPtr<CGColorRef> createCGColor(const Color& color)
@@ -167,9 +167,9 @@
auto [cgColorSpace, cgCompatibleComponents] = convertToCGCompatibleComponents(colorSpace, components);
auto [c1, c2, c3, c4] = cgCompatibleComponents;
- CGFloat cgFloatComponents[4] { c1, c2, c3, c4 };
+ std::array<CGFloat, 4> cgFloatComponents { c1, c2, c3, c4 };
- return adoptCF(CGColorCreate(cgColorSpace, cgFloatComponents));
+ return adoptCF(CGColorCreate(cgColorSpace, cgFloatComponents.data()));
}
RetainPtr<CGColorRef> cachedCGColor(const Color& color)
@@ -219,11 +219,11 @@
return cgCompatibleComponents;
auto [c1, c2, c3, c4] = cgCompatibleComponents;
- CGFloat sourceComponents[4] { c1, c2, c3, c4 };
- CGFloat destinationComponents[4] { };
+ std::array<CGFloat, 4> sourceComponents { c1, c2, c3, c4 };
+ std::array<CGFloat, 4> destinationComponents { };
auto transform = adoptCF(CGColorTransformCreate(outputColorSpace.platformColorSpace(), nullptr));
- auto result = CGColorTransformConvertColorComponents(transform.get(), cgInputColorSpace, kCGRenderingIntentDefault, sourceComponents, destinationComponents);
+ auto result = CGColorTransformConvertColorComponents(transform.get(), cgInputColorSpace, kCGRenderingIntentDefault, sourceComponents.data(), destinationComponents.data());
ASSERT_UNUSED(result, result);
// FIXME: CGColorTransformConvertColorComponents doesn't copy over any alpha component.
return { static_cast<float>(destinationComponents[0]), static_cast<float>(destinationComponents[1]), static_cast<float>(destinationComponents[2]), static_cast<float>(destinationComponents[3]) };
Modified: trunk/Source/WebCore/platform/graphics/cg/GradientRendererCG.cpp (287888 => 287889)
--- trunk/Source/WebCore/platform/graphics/cg/GradientRendererCG.cpp 2022-01-11 18:31:19 UTC (rev 287888)
+++ trunk/Source/WebCore/platform/graphics/cg/GradientRendererCG.cpp 2022-01-11 18:43:31 UTC (rev 287889)
@@ -54,7 +54,7 @@
FullyTransparent
};
-static AlphaType classifyAlphaType(float alpha)
+static constexpr AlphaType classifyAlphaType(float alpha)
{
if (alpha == 1.0f)
return AlphaType::Opaque;
@@ -465,32 +465,26 @@
Vector<CGFloat, 4 * reservedStops> colorComponents;
colorComponents.reserveInitialCapacity(numberOfStops * 4);
- auto gradientColorSpace = sRGBColorSpaceRef();
+ auto cgColorSpace = [&] {
+ // FIXME: Now that we only ever use CGGradientCreateWithColorComponents, we should investigate
+ // if there is any real benefit to using sRGB when all the stops are bounded vs just using
+ // extended sRGB for all gradients.
+ if (hasOnlyBoundedSRGBColorStops(stops)) {
+ for (const auto& stop : stops) {
+ auto [r, g, b, a] = stop.color.toColorTypeLossy<SRGBA<float>>().resolved();
+ colorComponents.uncheckedAppend(r);
+ colorComponents.uncheckedAppend(g);
+ colorComponents.uncheckedAppend(b);
+ colorComponents.uncheckedAppend(a);
- // FIXME: Now that we only ever use CGGradientCreateWithColorComponents, we should investigate
- // if there is any real benefit to using sRGB when all the stops are bounded vs just using
- // extended sRGB for all gradients.
- if (hasOnlyBoundedSRGBColorStops(stops)) {
- for (const auto& stop : stops) {
- auto [r, g, b, a] = stop.color.toColorTypeLossy<SRGBA<float>>().resolved();
- colorComponents.uncheckedAppend(r);
- colorComponents.uncheckedAppend(g);
- colorComponents.uncheckedAppend(b);
- colorComponents.uncheckedAppend(a);
-
- locations.uncheckedAppend(stop.offset);
+ locations.uncheckedAppend(stop.offset);
+ }
+ return cachedCGColorSpace<ColorSpaceFor<SRGBA<float>>>();
}
- } else {
-#if HAVE(CORE_GRAPHICS_EXTENDED_SRGB_COLOR_SPACE)
- gradientColorSpace = extendedSRGBColorSpaceRef();
-#endif
+ using OutputSpaceColorType = std::conditional_t<HasCGColorSpaceMapping<ColorSpace::ExtendedSRGB>, ExtendedSRGBA<float>, SRGBA<float>>;
for (const auto& stop : stops) {
-#if HAVE(CORE_GRAPHICS_EXTENDED_SRGB_COLOR_SPACE)
- auto [r, g, b, a] = stop.color.toColorTypeLossy<ExtendedSRGBA<float>>().resolved();
-#else
- auto [r, g, b, a] = stop.color.toColorTypeLossy<SRGBA<float>>().resolved();
-#endif
+ auto [r, g, b, a] = stop.color.toColorTypeLossy<OutputSpaceColorType>().resolved();
colorComponents.uncheckedAppend(r);
colorComponents.uncheckedAppend(g);
colorComponents.uncheckedAppend(b);
@@ -498,12 +492,13 @@
locations.uncheckedAppend(stop.offset);
}
- }
+ return cachedCGColorSpace<ColorSpaceFor<OutputSpaceColorType>>();
+ }();
#if HAVE(CORE_GRAPHICS_GRADIENT_CREATE_WITH_OPTIONS)
- return Gradient { adoptCF(CGGradientCreateWithColorComponentsAndOptions(gradientColorSpace, colorComponents.data(), locations.data(), numberOfStops, gradientOptionsDictionary(colorInterpolationMethod))) };
+ return Gradient { adoptCF(CGGradientCreateWithColorComponentsAndOptions(cgColorSpace, colorComponents.data(), locations.data(), numberOfStops, gradientOptionsDictionary(colorInterpolationMethod))) };
#else
- return Gradient { adoptCF(CGGradientCreateWithColorComponents(gradientColorSpace, colorComponents.data(), locations.data(), numberOfStops)) };
+ return Gradient { adoptCF(CGGradientCreateWithColorComponents(cgColorSpace, colorComponents.data(), locations.data(), numberOfStops)) };
#endif
}
@@ -513,11 +508,7 @@
void GradientRendererCG::Shading::shadingFunction(void* info, const CGFloat* in, CGFloat* out)
{
using InterpolationSpaceColorType = typename InterpolationSpace::ColorType;
-#if HAVE(CORE_GRAPHICS_EXTENDED_SRGB_COLOR_SPACE)
- using OutputSpaceColorType = ExtendedSRGBA<float>;
-#else
- using OutputSpaceColorType = SRGBA<float>;
-#endif
+ using OutputSpaceColorType = std::conditional_t<HasCGColorSpaceMapping<ColorSpace::ExtendedSRGB>, ExtendedSRGBA<float>, SRGBA<float>>;
auto* data = ""
@@ -554,6 +545,8 @@
GradientRendererCG::Strategy GradientRendererCG::makeShading(ColorInterpolationMethod colorInterpolationMethod, const GradientColorStops& stops) const
{
+ using OutputSpaceColorType = std::conditional_t<HasCGColorSpaceMapping<ColorSpace::ExtendedSRGB>, ExtendedSRGBA<float>, SRGBA<float>>;
+
auto makeData = [&] (auto colorInterpolationMethod, auto& stops) {
auto convertColorToColorInterpolationSpace = [&] (const Color& color, auto colorInterpolationMethod) -> ColorComponents<float, 4> {
return WTF::switchOn(colorInterpolationMethod.colorSpace,
@@ -626,15 +619,18 @@
}
};
- static const CGFloat domain[2] = { 0, 1 };
-#if HAVE(CORE_GRAPHICS_EXTENDED_SRGB_COLOR_SPACE)
- static const CGFloat range[8] = { -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(), 0, 1 };
-#else
- static const CGFloat range[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
-#endif
+ constexpr auto outputSpaceComponentInfo = OutputSpaceColorType::Model::componentInfo;
+ static constexpr std::array<CGFloat, 2> domain = { 0, 1 };
+ static constexpr std::array<CGFloat, 8> range = {
+ outputSpaceComponentInfo[0].min, outputSpaceComponentInfo[0].max,
+ outputSpaceComponentInfo[1].min, outputSpaceComponentInfo[1].max,
+ outputSpaceComponentInfo[2].min, outputSpaceComponentInfo[2].max,
+ 0, 1
+ };
+
Ref dataRefCopy = data;
- return adoptCF(CGFunctionCreate(&dataRefCopy.leakRef(), 1, domain, 4, range, &callbacks));
+ return adoptCF(CGFunctionCreate(&dataRefCopy.leakRef(), domain.size() / 2, domain.data(), range.size() / 2, range.data(), &callbacks));
};
auto data = "" stops);
@@ -641,11 +637,7 @@
auto function = makeFunction(colorInterpolationMethod, data);
// FIXME: Investigate using bounded sRGB when the input stops are all bounded sRGB.
-#if HAVE(CORE_GRAPHICS_EXTENDED_SRGB_COLOR_SPACE)
- auto colorSpace = extendedSRGBColorSpaceRef();
-#else
- auto colorSpace = sRGBColorSpaceRef();
-#endif
+ auto colorSpace = cachedCGColorSpace<ColorSpaceFor<OutputSpaceColorType>>();
return Shading { WTFMove(data), WTFMove(function), colorSpace };
}