See the discussion in bug 2052936. The comparators are relatively expensive. Cleanup a bit nsStyleUtil includes while at it. Differential Revision: https://phabricator.services.mozilla.com/D311685
175 lines
5.4 KiB
C++
175 lines
5.4 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 "nsIFrame.h"
|
|
#include "nsStyleStruct.h"
|
|
#include "nsStyleUtil.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 <>
|
|
bool StyleColor::DependsOnCurrentColor() const;
|
|
|
|
static bool OptionalDependsOnCurrentColor(const StyleOptional<StyleColor>& o) {
|
|
return o.IsSome() && o.AsSome().DependsOnCurrentColor();
|
|
}
|
|
|
|
using ColorFunction = StyleColorFunction<StyleColor>;
|
|
|
|
template <>
|
|
bool ColorFunction::DependsOnCurrentColor() const {
|
|
switch (tag) {
|
|
case Tag::Rgb:
|
|
return OptionalDependsOnCurrentColor(AsRgb()._0);
|
|
case Tag::Hsl:
|
|
return OptionalDependsOnCurrentColor(AsHsl()._0);
|
|
case Tag::Hwb:
|
|
return OptionalDependsOnCurrentColor(AsHwb()._0);
|
|
case Tag::Lab:
|
|
return OptionalDependsOnCurrentColor(AsLab()._0);
|
|
case Tag::Lch:
|
|
return OptionalDependsOnCurrentColor(AsLch()._0);
|
|
case Tag::Oklab:
|
|
return OptionalDependsOnCurrentColor(AsOklab()._0);
|
|
case Tag::Oklch:
|
|
return OptionalDependsOnCurrentColor(AsOklch()._0);
|
|
case Tag::Color:
|
|
return OptionalDependsOnCurrentColor(AsColor()._0);
|
|
case Tag::Alpha:
|
|
return AsAlpha()._0.DependsOnCurrentColor();
|
|
}
|
|
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unknown color function type");
|
|
}
|
|
|
|
using ColorMix = StyleGenericColorMix<StyleColor, StylePercentage>;
|
|
|
|
template <>
|
|
bool ColorMix::DependsOnCurrentColor() const {
|
|
for (const auto& colorMixItem : items.AsSpan()) {
|
|
if (colorMixItem.color.DependsOnCurrentColor()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template <>
|
|
bool StyleColor::DependsOnCurrentColor() const {
|
|
switch (tag) {
|
|
case Tag::Absolute:
|
|
return false;
|
|
case Tag::ColorFunction:
|
|
return AsColorFunction()->DependsOnCurrentColor();
|
|
case Tag::CurrentColor:
|
|
return true;
|
|
case Tag::ColorMix:
|
|
return AsColorMix()->DependsOnCurrentColor();
|
|
case Tag::ContrastColor:
|
|
return AsContrastColor()->DependsOnCurrentColor();
|
|
}
|
|
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unknown color type");
|
|
}
|
|
|
|
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
|