Based on current editor's draft of CSS Color 4 spec (2026-02-27). Updated binary search+MINDE originally implemented by tlouw; added raytrace GMA. GMAs are selectable by config pref layout.css.gamut-mapping.method Initial WPTs are under css/css-color/gamut-mapping/. Values were verified against colorjs and coloraide libraries where possible. Differential Revision: https://phabricator.services.mozilla.com/D287185
112 lines
3.6 KiB
C++
112 lines
3.6 KiB
C++
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/ComputedStyle.h"
|
|
#include "mozilla/ComputedStyleInlines.h"
|
|
#include "mozilla/StaticPrefs_layout.h"
|
|
#include "mozilla/StyleColorInlines.h"
|
|
#include "mozilla/dom/BindingDeclarations.h"
|
|
#include "nsIFrame.h"
|
|
#include "nsStyleStruct.h"
|
|
|
|
namespace mozilla {
|
|
|
|
template <>
|
|
bool StyleColor::MaybeTransparent() const {
|
|
// We know that the color is opaque when it's a numeric color with
|
|
// alpha == 1.0.
|
|
return !IsAbsolute() || AsAbsolute().alpha != 1.0f;
|
|
}
|
|
|
|
template <>
|
|
StyleAbsoluteColor StyleColor::ResolveColor(
|
|
const StyleAbsoluteColor& aForegroundColor) const {
|
|
if (IsAbsolute()) {
|
|
return AsAbsolute();
|
|
}
|
|
|
|
if (IsCurrentColor()) {
|
|
return aForegroundColor;
|
|
}
|
|
|
|
return Servo_ResolveColor(this, &aForegroundColor);
|
|
}
|
|
|
|
template <>
|
|
nscolor StyleColor::CalcColor(nscolor aColor) const {
|
|
return ResolveColor(StyleAbsoluteColor::FromColor(aColor)).ToColor();
|
|
}
|
|
|
|
template <>
|
|
nscolor StyleColor::CalcColor(
|
|
const StyleAbsoluteColor& aForegroundColor) const {
|
|
return ResolveColor(aForegroundColor).ToColor();
|
|
}
|
|
|
|
template <>
|
|
nscolor StyleColor::CalcColor(const ComputedStyle& aStyle) const {
|
|
return ResolveColor(aStyle.StyleText()->mColor).ToColor();
|
|
}
|
|
|
|
template <>
|
|
nscolor StyleColor::CalcColor(const nsIFrame* aFrame) const {
|
|
return ResolveColor(aFrame->StyleText()->mColor).ToColor();
|
|
}
|
|
|
|
StyleAbsoluteColor StyleAbsoluteColor::ToColorSpace(
|
|
StyleColorSpace aColorSpace) const {
|
|
return Servo_ConvertColorSpace(this, aColorSpace);
|
|
}
|
|
|
|
nscolor StyleAbsoluteColor::ToColor() const {
|
|
constexpr StyleColorSpace DEST_COLOR_SPACE = StyleColorSpace::Srgb;
|
|
|
|
constexpr float MIN = 0.0f;
|
|
constexpr float MAX = 1.0f;
|
|
|
|
auto translatedColor = ToColorSpace(DEST_COLOR_SPACE);
|
|
|
|
// We KNOW the values are in srgb so we can do a quick gamut limit check
|
|
// here and avoid calling into Servo_GamutMapColorUsing* and let it
|
|
// return early anyway.
|
|
auto isColorInGamut = translatedColor.components._0 >= MIN &&
|
|
translatedColor.components._0 <= MAX &&
|
|
translatedColor.components._1 >= MIN &&
|
|
translatedColor.components._1 <= MAX &&
|
|
translatedColor.components._2 >= MIN &&
|
|
translatedColor.components._2 <= MAX;
|
|
|
|
if (!isColorInGamut) {
|
|
switch (StaticPrefs::layout_css_gamut_mapping_method()) {
|
|
case 1:
|
|
translatedColor =
|
|
Servo_GamutMapColorUsingBinarySearchMINDE(this, DEST_COLOR_SPACE);
|
|
break;
|
|
case 2:
|
|
translatedColor =
|
|
Servo_GamutMapColorUsingRaytrace(this, DEST_COLOR_SPACE);
|
|
break;
|
|
default:
|
|
// 0 (default), or any other value
|
|
// If gamut mapping is not enabled, we just naively clip the colors at
|
|
// sRGB gamut limits. This will go away completely when gamut mapping is
|
|
// enabled.
|
|
translatedColor.components._0 =
|
|
std::clamp(translatedColor.components._0, MIN, MAX);
|
|
translatedColor.components._1 =
|
|
std::clamp(translatedColor.components._1, MIN, MAX);
|
|
translatedColor.components._2 =
|
|
std::clamp(translatedColor.components._2, MIN, MAX);
|
|
}
|
|
}
|
|
|
|
return NS_RGBA(
|
|
nsStyleUtil::FloatToColorComponent(translatedColor.components._0),
|
|
nsStyleUtil::FloatToColorComponent(translatedColor.components._1),
|
|
nsStyleUtil::FloatToColorComponent(translatedColor.components._2),
|
|
nsStyleUtil::FloatToColorComponent(translatedColor.alpha));
|
|
}
|
|
|
|
} // namespace mozilla
|