Bug 1862061 - Remove -moz-font-smoothing-background-color. r=gfx-reviewers,desktop-theme-reviewers,devtools-reviewers,dao,gw

See comments in the bug for reasoning. macOS hasn't used subpixel AA for
quite a while.

Emulating this macOS AA on vibrant backgrounds was the only point of
this feature.

This allows to simplify the WebRender code quite a bit, too.

Differential Revision: https://phabricator.services.mozilla.com/D192311
This commit is contained in:
Emilio Cobos Álvarez 2023-11-01 09:14:29 +00:00
parent df77520266
commit c25b3b246f
42 changed files with 49 additions and 733 deletions

View file

@ -280,7 +280,6 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
"color",
"column-rule-color",
"flood-color",
"-moz-font-smoothing-background-color",
"lighting-color",
"outline-color",
"scrollbar-color",

View file

@ -2078,7 +2078,6 @@ class GFX2D_API Factory {
#ifdef XP_DARWIN
static already_AddRefed<ScaledFont> CreateScaledFontForMacFont(
CGFontRef aCGFont, const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
const DeviceColor& aFontSmoothingBackgroundColor,
bool aUseFontSmoothing = true, bool aApplySyntheticBold = false,
bool aHasColorGlyphs = false);
#endif

View file

@ -594,11 +594,10 @@ already_AddRefed<UnscaledFont> Factory::CreateUnscaledFontFromFontDescriptor(
#ifdef XP_DARWIN
already_AddRefed<ScaledFont> Factory::CreateScaledFontForMacFont(
CGFontRef aCGFont, const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
const DeviceColor& aFontSmoothingBackgroundColor, bool aUseFontSmoothing,
bool aApplySyntheticBold, bool aHasColorGlyphs) {
return MakeAndAddRef<ScaledFontMac>(
aCGFont, aUnscaledFont, aSize, false, aFontSmoothingBackgroundColor,
aUseFontSmoothing, aApplySyntheticBold, aHasColorGlyphs);
bool aUseFontSmoothing, bool aApplySyntheticBold, bool aHasColorGlyphs) {
return MakeAndAddRef<ScaledFontMac>(aCGFont, aUnscaledFont, aSize, false,
aUseFontSmoothing, aApplySyntheticBold,
aHasColorGlyphs);
}
#endif

View file

@ -499,7 +499,6 @@ bool ScaledFontDWrite::GetWRFontInstanceOptions(
if (Factory::GetBGRSubpixelOrder()) {
options.flags |= wr::FontInstanceFlags::SUBPIXEL_BGR;
}
options.bg_color = wr::ToColorU(DeviceColor());
options.synthetic_italics =
wr::DegreesToSyntheticItalics(GetSyntheticObliqueAngle());

View file

@ -402,7 +402,6 @@ bool ScaledFontFontconfig::GetWRFontInstanceOptions(
if (UseSubpixelPosition()) {
options.flags |= wr::FontInstanceFlags::SUBPIXEL_POSITION;
}
options.bg_color = wr::ToColorU(DeviceColor());
options.synthetic_italics =
wr::DegreesToSyntheticItalics(GetSyntheticObliqueAngle());

View file

@ -93,7 +93,6 @@ bool ScaledFontFreeType::GetWRFontInstanceOptions(
options.flags |= wr::FontInstanceFlags::SUBPIXEL_POSITION;
}
options.flags |= wr::FontInstanceFlags::EMBEDDED_BITMAPS;
options.bg_color = wr::ToColorU(DeviceColor());
options.synthetic_italics =
wr::DegreesToSyntheticItalics(GetSyntheticObliqueAngle());

View file

@ -125,12 +125,10 @@ CTFontRef CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont, CGFloat aSize,
ScaledFontMac::ScaledFontMac(CGFontRef aFont,
const RefPtr<UnscaledFont>& aUnscaledFont,
Float aSize, bool aOwnsFont,
const DeviceColor& aFontSmoothingBackgroundColor,
bool aUseFontSmoothing, bool aApplySyntheticBold,
bool aHasColorGlyphs)
: ScaledFontBase(aUnscaledFont, aSize),
mFont(aFont),
mFontSmoothingBackgroundColor(aFontSmoothingBackgroundColor),
mUseFontSmoothing(aUseFontSmoothing),
mApplySyntheticBold(aApplySyntheticBold),
mHasColorGlyphs(aHasColorGlyphs) {
@ -146,12 +144,10 @@ ScaledFontMac::ScaledFontMac(CGFontRef aFont,
ScaledFontMac::ScaledFontMac(CTFontRef aFont,
const RefPtr<UnscaledFont>& aUnscaledFont,
const DeviceColor& aFontSmoothingBackgroundColor,
bool aUseFontSmoothing, bool aApplySyntheticBold,
bool aHasColorGlyphs)
: ScaledFontBase(aUnscaledFont, CTFontGetSize(aFont)),
mCTFont(aFont),
mFontSmoothingBackgroundColor(aFontSmoothingBackgroundColor),
mUseFontSmoothing(aUseFontSmoothing),
mApplySyntheticBold(aApplySyntheticBold),
mHasColorGlyphs(aHasColorGlyphs) {
@ -457,7 +453,6 @@ bool ScaledFontMac::GetWRFontInstanceOptions(
if (mHasColorGlyphs) {
options.flags |= wr::FontInstanceFlags::EMBEDDED_BITMAPS;
}
options.bg_color = wr::ToColorU(mFontSmoothingBackgroundColor);
options.synthetic_italics =
wr::DegreesToSyntheticItalics(GetSyntheticObliqueAngle());
*aOutOptions = Some(options);
@ -480,11 +475,6 @@ ScaledFontMac::InstanceData::InstanceData(
if (aOptions->flags & wr::FontInstanceFlags::EMBEDDED_BITMAPS) {
mHasColorGlyphs = true;
}
if (aOptions->bg_color.a != 0) {
mFontSmoothingBackgroundColor =
DeviceColor::FromU8(aOptions->bg_color.r, aOptions->bg_color.g,
aOptions->bg_color.b, aOptions->bg_color.a);
}
}
}
@ -731,10 +721,9 @@ already_AddRefed<ScaledFont> UnscaledFontMac::CreateScaledFont(
font = CTFontCreateWithFontDescriptor(fontDesc, aGlyphSize, nullptr);
}
}
scaledFont = new ScaledFontMac(
font, this, instanceData.mFontSmoothingBackgroundColor,
instanceData.mUseFontSmoothing, instanceData.mApplySyntheticBold,
instanceData.mHasColorGlyphs);
scaledFont = new ScaledFontMac(font, this, instanceData.mUseFontSmoothing,
instanceData.mApplySyntheticBold,
instanceData.mHasColorGlyphs);
} else {
CGFontRef fontRef = mFont;
if (aNumVariations > 0) {
@ -746,7 +735,6 @@ already_AddRefed<ScaledFont> UnscaledFontMac::CreateScaledFont(
}
scaledFont = new ScaledFontMac(fontRef, this, aGlyphSize, fontRef != mFont,
instanceData.mFontSmoothingBackgroundColor,
instanceData.mUseFontSmoothing,
instanceData.mApplySyntheticBold,
instanceData.mHasColorGlyphs);

View file

@ -34,17 +34,13 @@ class UnscaledFontMac;
class ScaledFontMac : public ScaledFontBase {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontMac, override)
ScaledFontMac(
CGFontRef aFont, const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
bool aOwnsFont = false,
const DeviceColor& aFontSmoothingBackgroundColor = DeviceColor(),
bool aUseFontSmoothing = true, bool aApplySyntheticBold = false,
bool aHasColorGlyphs = false);
ScaledFontMac(
CTFontRef aFont, const RefPtr<UnscaledFont>& aUnscaledFont,
const DeviceColor& aFontSmoothingBackgroundColor = DeviceColor(),
bool aUseFontSmoothing = true, bool aApplySyntheticBold = false,
bool aHasColorGlyphs = false);
ScaledFontMac(CGFontRef aFont, const RefPtr<UnscaledFont>& aUnscaledFont,
Float aSize, bool aOwnsFont = false,
bool aUseFontSmoothing = true, bool aApplySyntheticBold = false,
bool aHasColorGlyphs = false);
ScaledFontMac(CTFontRef aFont, const RefPtr<UnscaledFont>& aUnscaledFont,
bool aUseFontSmoothing = true, bool aApplySyntheticBold = false,
bool aHasColorGlyphs = false);
~ScaledFontMac();
FontType GetType() const override { return FontType::MAC; }
@ -66,10 +62,6 @@ class ScaledFontMac : public ScaledFontBase {
bool UseSubpixelPosition() const override { return true; }
DeviceColor FontSmoothingBackgroundColor() {
return mFontSmoothingBackgroundColor;
}
cairo_font_face_t* CreateCairoFontFace(
cairo_font_options_t* aFontOptions) override;
@ -81,23 +73,19 @@ class ScaledFontMac : public ScaledFontBase {
CTFontRef
mCTFont; // only created if CTFontDrawGlyphs is available, otherwise null
DeviceColor mFontSmoothingBackgroundColor;
bool mUseFontSmoothing;
bool mApplySyntheticBold;
bool mHasColorGlyphs;
struct InstanceData {
explicit InstanceData(ScaledFontMac* aScaledFont)
: mFontSmoothingBackgroundColor(
aScaledFont->mFontSmoothingBackgroundColor),
mUseFontSmoothing(aScaledFont->mUseFontSmoothing),
: mUseFontSmoothing(aScaledFont->mUseFontSmoothing),
mApplySyntheticBold(aScaledFont->mApplySyntheticBold),
mHasColorGlyphs(aScaledFont->mHasColorGlyphs) {}
InstanceData(const wr::FontInstanceOptions* aOptions,
const wr::FontInstancePlatformOptions* aPlatformOptions);
DeviceColor mFontSmoothingBackgroundColor;
bool mUseFontSmoothing;
bool mApplySyntheticBold;
bool mHasColorGlyphs;

View file

@ -58,8 +58,7 @@ nsFont::MaxDifference nsFont::CalcDifference(const nsFont& aOther) const {
return MaxDifference::eLayoutAffecting;
}
if ((smoothing != aOther.smoothing) ||
(fontSmoothingBackgroundColor != aOther.fontSmoothingBackgroundColor)) {
if (smoothing != aOther.smoothing) {
return MaxDifference::eVisual;
}
@ -267,8 +266,6 @@ void nsFont::AddFontFeaturesToStyle(gfxFontStyle* aStyle,
if (smoothing == NS_FONT_SMOOTHING_GRAYSCALE) {
aStyle->useGrayscaleAntialiasing = true;
}
aStyle->fontSmoothingBackgroundColor = fontSmoothingBackgroundColor.ToColor();
}
void nsFont::AddFontVariationsToStyle(gfxFontStyle* aStyle) const {

View file

@ -41,12 +41,6 @@ struct nsFont final {
mozilla::StyleFontSizeAdjust sizeAdjust =
mozilla::StyleFontSizeAdjust::None();
// The estimated background color behind the text. Enables a special
// rendering mode when the alpha component > 0. Only used for text in the
// chrome.
mozilla::StyleAbsoluteColor fontSmoothingBackgroundColor =
mozilla::StyleAbsoluteColor::TRANSPARENT_BLACK;
// Language system tag, to override document language;
// this is an OpenType "language system" tag represented as a 32-bit integer
// (see http://www.microsoft.com/typography/otspec/languagetags.htm).

View file

@ -582,7 +582,6 @@ class gfxContext final {
mozilla::gfx::AntialiasMode aaMode;
bool patternTransformChanged;
Matrix patternTransform;
DeviceColor fontSmoothingBackgroundColor;
// This is used solely for using minimal intermediate surface size.
Point deviceOffset;
#ifdef DEBUG

View file

@ -4583,7 +4583,6 @@ gfxFontStyle::gfxFontStyle()
sizeAdjust(0.0f),
baselineOffset(0.0f),
languageOverride(NO_FONT_LANGUAGE_OVERRIDE),
fontSmoothingBackgroundColor(NS_RGBA(0, 0, 0, 0)),
weight(FontWeight::NORMAL),
stretch(FontStretch::NORMAL),
style(FontSlantStyle::NORMAL),
@ -4610,7 +4609,6 @@ gfxFontStyle::gfxFontStyle(FontSlantStyle aStyle, FontWeight aWeight,
: size(aSize),
baselineOffset(0.0f),
languageOverride(aLanguageOverride),
fontSmoothingBackgroundColor(NS_RGBA(0, 0, 0, 0)),
weight(aWeight),
stretch(aStretch),
style(aStyle),

View file

@ -147,10 +147,6 @@ struct gfxFontStyle {
// in order to get correct glyph shapes.)
uint32_t languageOverride;
// The estimated background color behind the text. Enables a special
// rendering mode when NS_GET_A(.) > 0. Only used for text in the chrome.
nscolor fontSmoothingBackgroundColor;
// The Font{Weight,Stretch,SlantStyle} fields are each a 16-bit type.
// The weight of the font: 100, 200, ... 900.
@ -253,8 +249,7 @@ struct gfxFontStyle {
(variationSettings == other.variationSettings) &&
(languageOverride == other.languageOverride) &&
mozilla::NumbersAreBitwiseIdentical(autoOpticalSize,
other.autoOpticalSize) &&
(fontSmoothingBackgroundColor == other.fontSmoothingBackgroundColor);
other.autoOpticalSize);
}
};

View file

@ -39,7 +39,6 @@ gfxMacFont::gfxMacFont(const RefPtr<UnscaledFontMac>& aUnscaledFont,
: gfxFont(aUnscaledFont, aFontEntry, aFontStyle),
mCGFont(nullptr),
mCTFont(nullptr),
mFontSmoothingBackgroundColor(aFontStyle->fontSmoothingBackgroundColor),
mVariationFont(aFontEntry->HasVariations()) {
mApplySyntheticBold = aFontStyle->NeedsSyntheticBold(aFontEntry);
@ -534,7 +533,6 @@ already_AddRefed<ScaledFont> gfxMacFont::GetScaledFont(
bool hasColorGlyphs = fe->HasColorBitmapTable() || fe->TryGetColorGlyphs();
RefPtr<ScaledFont> newScaledFont = Factory::CreateScaledFontForMacFont(
GetCGFontRef(), GetUnscaledFont(), GetAdjustedSize(),
ToDeviceColor(mFontSmoothingBackgroundColor),
!mStyle.useGrayscaleAntialiasing, ApplySyntheticBold(), hasColorGlyphs);
if (!newScaledFont) {
return nullptr;

View file

@ -83,7 +83,6 @@ class gfxMacFont final : public gfxFont {
mozilla::UniquePtr<gfxFontShaper> mCoreTextShaper;
Metrics mMetrics;
nscolor mFontSmoothingBackgroundColor;
bool mVariationFont; // true if font has OpenType variations
};

View file

@ -314,15 +314,6 @@ static inline wr::ColorF ToColorF(const gfx::DeviceColor& color) {
return c;
}
static inline wr::ColorU ToColorU(const gfx::DeviceColor& color) {
wr::ColorU c;
c.r = uint8_t(color.r * 255.0f);
c.g = uint8_t(color.g * 255.0f);
c.b = uint8_t(color.b * 255.0f);
c.a = uint8_t(color.a * 255.0f);
return c;
}
static inline wr::LayoutPoint ToLayoutPoint(
const mozilla::LayoutDevicePoint& point) {
wr::LayoutPoint p;

View file

@ -366,355 +366,3 @@ in order to fold the two passes into one:
Instead of outputting the two different colors in two separate passes, we output them from the same pass,
as two separate fragment shader outputs.
Those outputs can then be treated as two different sources in the blend equation.
## Subpixel Text Rendering to Transparent Destinations with a Background Color Hint
### Motivation
As we've seen in the previous section, subpixel text drawing has the limitation that it only works on opaque destinations.
In other words, if you use the `subpixeltextblend` function to draw something to a transparent surface,
and then composite that surface onto on opaque background,
the result will generally be different from drawing the text directly onto the opaque background.
Let's express that inequality in code.
```
- vec4 text_color
- vec4 mask
- vec4 transparency = vec4(0.0, 0.0, 0.0, 0.0)
- vec4 background with background.a == 1.0
over(subpixeltextblend(text_color, mask, transparency), background).rgb
is, in general, not equal to
subpixeltextblend(text_color, mask, background).rgb
```
However, one interesting observation is that if the background is black, the two *are* equal:
```
vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
over(subpixeltextblend(text_color, mask, transparency), black).r
= subpixeltextblend(text_color, mask, transparency).r +
(1 - subpixeltextblend(text_color, mask, transparency).a) * black.r
= subpixeltextblend(text_color, mask, transparency).r +
(1 - subpixeltextblend(text_color, mask, transparency).a) * 0
= subpixeltextblend(text_color, mask, transparency).r
= text_color.r * mask.r + (1 - text_color.a * mask.r) * transparency.r
= text_color.r * mask.r + (1 - text_color.a * mask.r) * 0
= text_color.r * mask.r + (1 - text_color.a * mask.r) * black.r
= subpixeltextblend(text_color, mask, black).r
```
So it works out for black backgrounds. The further your *actual* background color gets away from black,
the more incorrect your result will be.
If it works for black, is there a way to make it work for other colors?
This is the motivating question for this third way of text blending:
We want to be able to specify an *estimated background color*, and have a blending function
`vec4 subpixeltextblend_withbgcolor(vec4 text_color, vec4 mask, vec4 bg_color, vec4 dest)`,
in such a way that the error we get by using an intermediate surface is somehow in relation
to the error we made when estimating the background color. In particular, if we estimated
the background color perfectly, we want the intermediate surface to go unnoticed.
Expressed as code:
```
over(subpixeltextblend_withbgcolor(text_color, mask, bg_color, transparency), bg_color)
should always be equal to
subpixeltextblend(text_color, mask, bg_color)
```
This is one of three constraints we'd like `subpixeltextblend_withbgcolor` to satisfy.
The next constraint is the following: If `dest` is already opaque, `subpixeltextblend_withbgcolor`
should have the same results as `subpixeltextblend`, and the background color hint should be ignored.
```
If dest.a == 1.0,
subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest)
should always be equal to
subpixeltextblend(text_color, mask, dest)
```
And there's a third condition we'd like it to fulfill:
In places where the mask is zero, the destination should be unaffected.
```
subpixeltextblend_withbgcolor(text_color, transparency, bg_color, dest)
should always be equal to
dest
```
### Use cases
The primary use case for such a blend method is text on top of vibrant areas of a window on macOS.
Vibrant backgrounds with behind-window blending are computed by the window server, and they are tinted
in a color that's based on the chosen vibrancy type.
The window's rgba buffer is transparent in the vibrant areas. Window contents, even text, are drawn onto
that transparent rgba buffer. Then the window server composites the window onto an opaque backdrop.
So the results on the screen are computed as follows:
```glsl
window_buffer_pixel = subpixeltextblend_withbgcolor(text_color, mask, bg_color, transparency);
screen_pixel = over(window_buffer_pixel, window_backdrop);
```
### Prior art
Apple has implemented such a method of text blending in CoreGraphics, specifically for rendering text onto vibrant backgrounds.
It's hidden behind the private API `CGContextSetFontSmoothingBackgroundColor` and is called by AppKit internally before
calling the `-[NSView drawRect:]` method of your `NSVisualEffectView`, with the appropriate font smoothing background color
for the vibrancy type of that view.
I'm not aware of any public documentation of this way of text blending.
It seems to be considered an implementation detail by Apple, and is probably hidden by default because it can be a footgun:
If the font smoothing background color you specify is very different from the actual background that our surface is placed
on top of, the text will look glitchy.
### Deriving the blending function from first principles
Before we dive into the math, let's repeat our goal once more.
We want to create a blending function of the form
`vec4 subpixeltextblend_withbgcolor(vec4 text_color, vec4 mask, vec4 bg_color, vec4 dest)`
(with `bg_color` being an opaque color)
which satisfies the following three constraints:
```
Constraint I:
over(subpixeltextblend_withbgcolor(text_color, mask, bg_color, transparency), bg_color)
should always be equal to
subpixeltextblend(text_color, mask, bg_color)
Constraint II:
If dest.a == 1.0,
subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest)
should always be equal to
subpixeltextblend(text_color, mask, dest)
Constraint II:
subpixeltextblend_withbgcolor(text_color, transparency, bg_color, dest)
should always be equal to
dest
```
Constraint I and constraint II are about what happens depending on the destination's alpha.
In particular: If the destination is completely transparent, we should blend into the
estimated background color, and if it's completely opaque, we should blend into the destination color.
In fact, we really want to blend into `over(dest, bg_color)`: we want `bg_color` to be used
as a backdrop *behind* the current destination. So let's combine constraints I and II into a new
constraint IV:
```
Constraint IV:
over(subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest), bg_color)
should always be equal to
subpixeltextblend(text_color, mask, over(dest, bg_color))
```
Let's look at just the left side of that equation and rejiggle it a bit:
```
over(subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest), bg_color).r
= subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest).r +
(1 - subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest).a) * bg_color.r
<=>
over(subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest), bg_color).r -
(1 - subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest).a) * bg_color.r
= subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest).r
```
Now insert the right side of constraint IV:
```
subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest).r
= over(subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest), bg_color).r -
(1 - subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest).a) * bg_color.r
= subpixeltextblend(text_color, mask, over(dest, bg_color)).r -
(1 - subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest).a) * bg_color.r
```
Our blend function is almost finished. We just need select an alpha for our result.
Constraints I, II and IV don't really care about the alpha value. But constraint III requires that:
```
subpixeltextblend_withbgcolor(text_color, transparency, bg_color, dest).a
should always be equal to
dest.a
```
so the computation of the alpha value somehow needs to take into account the mask.
Let's say we have an unknown function `make_alpha(text_color.a, mask)` which returns
a number between 0 and 1 and which is 0 if the mask is entirely zero, and let's defer
the actual implementation of that function until later.
Now we can define the alpha of our overall function using the `over` function:
```
subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest).a
:= make_alpha(text_color.a, mask) + (1 - make_alpha(text_color.a, mask)) * dest.a
```
We can plug this in to our previous result:
```
subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest).r
= subpixeltextblend(text_color, mask, over(dest, bg_color)).r
- (1 - subpixeltextblend_withbgcolor(text_color, mask, bg_color, dest).a) * bg_color.r
= subpixeltextblend(text_color, mask, over(dest, bg_color)).r
- (1 - (make_alpha(text_color.a, mask) +
(1 - make_alpha(text_color.a, mask)) * dest.a)) * bg_color.r
= text_color.r * mask.r + (1 - text_color.a * mask.r) * over(dest, bg_color).r
- (1 - (make_alpha(text_color.a, mask)
+ (1 - make_alpha(text_color.a, mask)) * dest.a)) * bg_color.r
= text_color.r * mask.r
+ (1 - text_color.a * mask.r) * (dest.r + (1 - dest.a) * bg_color.r)
- (1 - (make_alpha(text_color.a, mask)
+ (1 - make_alpha(text_color.a, mask)) * dest.a)) * bg_color.r
= text_color.r * mask.r
+ (1 - text_color.a * mask.r) * (dest.r + (1 - dest.a) * bg_color.r)
- (1 - (make_alpha(text_color.a, mask)
+ (1 - make_alpha(text_color.a, mask)) * dest.a)) * bg_color.r
= text_color.r * mask.r
+ (dest.r + (1 - dest.a) * bg_color.r)
- (text_color.a * mask.r) * (dest.r + (1 - dest.a) * bg_color.r)
- (1 - make_alpha(text_color.a, mask)
- (1 - make_alpha(text_color.a, mask)) * dest.a) * bg_color.r
= text_color.r * mask.r
+ dest.r + (1 - dest.a) * bg_color.r
- text_color.a * mask.r * dest.r
- text_color.a * mask.r * (1 - dest.a) * bg_color.r
- (1 - make_alpha(text_color.a, mask)
- (1 - make_alpha(text_color.a, mask)) * dest.a) * bg_color.r
= text_color.r * mask.r
+ dest.r + (1 - dest.a) * bg_color.r
- text_color.a * mask.r * dest.r
- text_color.a * mask.r * (1 - dest.a) * bg_color.r
- ((1 - make_alpha(text_color.a, mask)) * 1
- (1 - make_alpha(text_color.a, mask)) * dest.a) * bg_color.r
= text_color.r * mask.r
+ dest.r + (1 - dest.a) * bg_color.r
- text_color.a * mask.r * dest.r
- text_color.a * mask.r * (1 - dest.a) * bg_color.r
- ((1 - make_alpha(text_color.a, mask)) * (1 - dest.a)) * bg_color.r
= text_color.r * mask.r
+ dest.r - text_color.a * mask.r * dest.r
+ (1 - dest.a) * bg_color.r
- text_color.a * mask.r * (1 - dest.a) * bg_color.r
- (1 - make_alpha(text_color.a, mask)) * (1 - dest.a) * bg_color.r
= text_color.r * mask.r
+ (1 - text_color.a * mask.r) * dest.r
+ (1 - dest.a) * bg_color.r
- text_color.a * mask.r * (1 - dest.a) * bg_color.r
- (1 - make_alpha(text_color.a, mask)) * (1 - dest.a) * bg_color.r
= text_color.r * mask.r
+ (1 - text_color.a * mask.r) * dest.r
+ (1 - text_color.a * mask.r) * (1 - dest.a) * bg_color.r
- (1 - make_alpha(text_color.a, mask)) * (1 - dest.a) * bg_color.r
= text_color.r * mask.r
+ (1 - text_color.a * mask.r) * dest.r
+ ((1 - text_color.a * mask.r)
- (1 - make_alpha(text_color.a, mask))) * (1 - dest.a) * bg_color.r
= text_color.r * mask.r
+ (1 - text_color.a * mask.r) * dest.r
+ (1 - text_color.a * mask.r
- 1 + make_alpha(text_color.a, mask)) * (1 - dest.a) * bg_color.r
= text_color.r * mask.r
+ (1 - text_color.a * mask.r) * dest.r
+ (make_alpha(text_color.a, mask) - text_color.a * mask.r) * (1 - dest.a) * bg_color.r
```
We now have a term of the form `A + B + C`, with `A` and `B` being guaranteed to
be between zero and one.
We also want `C` to be between zero and one.
We can use this restriction to help us decide on an implementation of `make_alpha`.
If we define `make_alpha` as
```glsl
float make_alpha(text_color_a, mask) {
float max_rgb = max(max(mask.r, mask.g), mask.b);
return text_color_a * max_rgb;
}
```
, then `(make_alpha(text_color.a, mask) - text_color.a * mask.r)` becomes
`(text_color.a * max(max(mask.r, mask.g), mask.b) - text_color.a * mask.r)`, which is
`text_color.a * (max(max(mask.r, mask.g), mask.b) - mask.r)`, and the subtraction will
always yield something that's greater or equal to zero for r, g, and b,
because we will subtract each channel from the maximum of the channels.
Putting this all together, we have:
```glsl
vec4 subpixeltextblend_withbgcolor(vec4 text_color, vec4 mask, vec4 bg_color, vec4 dest) {
float max_rgb = max(max(mask.r, mask.g), mask.b);
vec4 result;
result.r = text_color.r * mask.r + (1 - text_color.a * mask.r) * dest.r +
text_color.a * bg_color.r * (max_rgb - mask.r) * (1 - dest.a);
result.g = text_color.g * mask.g + (1 - text_color.a * mask.g) * dest.g +
text_color.a * bg_color.g * (max_rgb - mask.g) * (1 - dest.a);
result.b = text_color.b * mask.b + (1 - text_color.a * mask.b) * dest.b +
text_color.a * bg_color.b * (max_rgb - mask.b) * (1 - dest.a);
result.a = text_color.a * max_rgb + (1 - text_color.a * max_rgb) * dest.a;
return result;
}
```
This is the final form of this blend function. It satisfies all of the four constraints.
### Implementing it with OpenGL
Our color channel equations consist of three pieces:
- `text_color.r * mask.r`, which simply gets added to the rest.
- `(1 - text_color.a * mask.r) * dest.r`, a factor which gets multiplied with the destination color.
- `text_color.a * bg_color.r * (max_rgb - mask.r) * (1 - dest.a)`, a factor which gets multiplied
with "one minus destination alpha".
We will need three passes. Each pass modifies the color channels in the destination.
This means that the part that uses `dest.r` needs to be applied first.
Then we can apply the part that uses `1 - dest.a`.
(This means that the first pass needs to leave `dest.a` untouched.)
And the final pass can apply the `result.a` equation and modify `dest.a`.
```
pub fn set_blend_mode_subpixel_with_bg_color_pass0(&self) {
self.gl.blend_func_separate(gl::ZERO, gl::ONE_MINUS_SRC_COLOR, gl::ZERO, gl::ONE);
}
pub fn set_blend_mode_subpixel_with_bg_color_pass1(&self) {
self.gl.blend_func_separate(gl::ONE_MINUS_DST_ALPHA, gl::ONE, gl::ZERO, gl::ONE);
}
pub fn set_blend_mode_subpixel_with_bg_color_pass2(&self) {
self.gl.blend_func_separate(gl::ONE, gl::ONE, gl::ONE, gl::ONE_MINUS_SRC_ALPHA);
}
Pass0:
oFragColor = vec4(text.color.a) * mask;
Pass1:
oFragColor = vec4(text.color.a) * text.bg_color * (vec4(mask.a) - mask);
Pass2:
oFragColor = text.color * mask;
result_after_pass0.r = 0 * (text_color.a * mask.r) + (1 - text_color.a * mask.r) * dest.r
result_after_pass0.a = 0 * (text_color.a * mask.a) + 1 * dest.a
result_after_pass1.r = (1 - result_after_pass0.a) * (text_color.a * (mask.max_rgb - mask.r) * bg_color.r) + 1 * result_after_pass0.r
result_after_pass1.a = 0 * (text_color.a * (mask.max_rgb - mask.a) * bg_color.a) + 1 * result_after_pass0.a
result_after_pass2.r = 1 * (text_color.r * mask.r) + 1 * result_after_pass1.r
result_after_pass2.a = 1 * (text_color.a * mask.max_rgb) + (1 - text_color.a * mask.max_rgb) * result_after_pass1.a
```
Instead of computing `max_rgb` in the shader, we can just require the font rasterization code to fill
`mask.a` with the `max_rgb` value.

View file

@ -186,10 +186,6 @@ void brush_vs(
int color_mode = prim_user_data.x & 0xffff;
int blend_mode = prim_user_data.x >> 16;
if (color_mode == COLOR_MODE_FROM_PASS) {
color_mode = uMode;
}
#endif
// Derive the texture coordinates for this image, based on
@ -289,20 +285,14 @@ void brush_vs(
v_color = image_data.color;
#endif
break;
case COLOR_MODE_SUBPX_BG_PASS2:
case COLOR_MODE_IMAGE:
v_mask_swizzle = vec2(1.0, 0.0);
v_color = image_data.color;
break;
case COLOR_MODE_SUBPX_BG_PASS0:
case COLOR_MODE_COLOR_BITMAP:
v_mask_swizzle = vec2(1.0, 0.0);
v_color = vec4(image_data.color.a);
break;
case COLOR_MODE_SUBPX_BG_PASS1:
v_mask_swizzle = vec2(-1.0, 1.0);
v_color = vec4(image_data.color.a) * image_data.background_color;
break;
case COLOR_MODE_SUBPX_DUAL_SOURCE:
v_mask_swizzle = vec2(image_data.color.a, 0.0);
v_color = image_data.color;

View file

@ -25,16 +25,12 @@ varying highp vec2 vClipMaskUv;
#ifdef WR_VERTEX_SHADER
#define COLOR_MODE_FROM_PASS 0
#define COLOR_MODE_ALPHA 1
#define COLOR_MODE_SUBPX_BG_PASS0 2
#define COLOR_MODE_SUBPX_BG_PASS1 3
#define COLOR_MODE_SUBPX_BG_PASS2 4
#define COLOR_MODE_SUBPX_DUAL_SOURCE 5
#define COLOR_MODE_BITMAP_SHADOW 6
#define COLOR_MODE_COLOR_BITMAP 7
#define COLOR_MODE_IMAGE 8
#define COLOR_MODE_MULTIPLY_DUAL_SOURCE 9
#define COLOR_MODE_ALPHA 0
#define COLOR_MODE_SUBPX_DUAL_SOURCE 1
#define COLOR_MODE_BITMAP_SHADOW 2
#define COLOR_MODE_COLOR_BITMAP 3
#define COLOR_MODE_IMAGE 4
#define COLOR_MODE_MULTIPLY_DUAL_SOURCE 5
uniform HIGHP_SAMPLER_FLOAT sampler2D sPrimitiveHeadersF;
uniform HIGHP_SAMPLER_FLOAT isampler2D sPrimitiveHeadersI;

View file

@ -19,7 +19,7 @@ varying highp vec4 v_uv_clip;
#ifdef WR_VERTEX_SHADER
#define VECS_PER_TEXT_RUN 2
#define VECS_PER_TEXT_RUN 1
#define GLYPHS_PER_GPU_BLOCK 2U
#ifdef WR_FEATURE_GLYPH_TRANSFORM
@ -66,12 +66,11 @@ GlyphResource fetch_glyph_resource(int address) {
struct TextRun {
vec4 color;
vec4 bg_color;
};
TextRun fetch_text_run(int address) {
vec4 data[2] = fetch_from_gpu_cache_2(address);
return TextRun(data[0], data[1]);
vec4 data = fetch_from_gpu_cache_1(address);
return TextRun(data);
}
vec2 get_snap_bias(int subpx_dir) {
@ -112,10 +111,6 @@ void main() {
TextRun text = fetch_text_run(ph.specific_prim_address);
vec2 text_offset = ph.local_rect.p1;
if (color_mode == COLOR_MODE_FROM_PASS) {
color_mode = uMode;
}
// Note that the unsnapped reference frame relative offset has already
// been subtracted from the prim local rect origin during batching.
// It was done this way to avoid pushing both the snapped and the
@ -249,19 +244,10 @@ void main() {
v_color = text.color;
#endif
break;
case COLOR_MODE_SUBPX_BG_PASS2:
v_mask_swizzle = vec3(1.0, 0.0, 0.0);
v_color = text.color;
break;
case COLOR_MODE_SUBPX_BG_PASS0:
case COLOR_MODE_COLOR_BITMAP:
v_mask_swizzle = vec3(1.0, 0.0, 0.0);
v_color = vec4(text.color.a);
break;
case COLOR_MODE_SUBPX_BG_PASS1:
v_mask_swizzle = vec3(-1.0, 1.0, 0.0);
v_color = vec4(text.color.a) * text.bg_color;
break;
case COLOR_MODE_SUBPX_DUAL_SOURCE:
#ifdef SWGL_BLEND
swgl_blendSubpixelText(text.color);

View file

@ -50,10 +50,6 @@ uniform bool u_mali_workaround_dummy;
// Vertex shader attributes and uniforms
//======================================================================================
#ifdef WR_VERTEX_SHADER
// A generic uniform that shaders can optionally use to configure
// an operation mode for this batch.
uniform int uMode;
// Uniform inputs
uniform mat4 uTransform; // Orthographic projection

View file

@ -347,21 +347,6 @@ impl AlphaBatchList {
let mut selected_batch_index = None;
match key.blend_mode {
BlendMode::SubpixelWithBgColor => {
for (batch_index, batch) in self.batches.iter().enumerate().rev() {
// Some subpixel batches are drawn in two passes. Because of this, we need
// to check for overlaps with every batch (which is a bit different
// than the normal batching below).
if self.batch_rects[batch_index].intersects(z_bounding_rect) {
break;
}
if batch.key.is_compatible_with(&key) {
selected_batch_index = Some(batch_index);
break;
}
}
}
BlendMode::Advanced(_) if self.break_advanced_blend_batches => {
// don't try to find a batch
}
@ -711,7 +696,6 @@ impl AlphaBatchBuilder {
BlendMode::Alpha |
BlendMode::PremultipliedAlpha |
BlendMode::PremultipliedDestOut |
BlendMode::SubpixelWithBgColor |
BlendMode::SubpixelDualSource |
BlendMode::Advanced(_) |
BlendMode::MultiplyDualSource |
@ -1194,18 +1178,11 @@ impl BatchBuilder {
let (blend_mode, color_mode) = match glyph_format {
GlyphFormat::Subpixel |
GlyphFormat::TransformedSubpixel => {
if run.used_font.bg_color.a != 0 {
(
BlendMode::SubpixelWithBgColor,
ShaderColorMode::FromRenderPassMode,
)
} else {
debug_assert!(ctx.use_dual_source_blending);
(
BlendMode::SubpixelDualSource,
ShaderColorMode::SubpixelDualSource,
)
}
debug_assert!(ctx.use_dual_source_blending);
(
BlendMode::SubpixelDualSource,
ShaderColorMode::SubpixelDualSource,
)
}
GlyphFormat::Alpha |
GlyphFormat::TransformedAlpha |

View file

@ -549,7 +549,6 @@ impl Drop for Texture {
pub struct Program {
id: gl::GLuint,
u_transform: gl::GLint,
u_mode: gl::GLint,
u_texture_size: gl::GLint,
source_info: ProgramSourceInfo,
is_initialized: bool,
@ -1074,7 +1073,6 @@ pub struct Device {
bound_vao: gl::GLuint,
bound_read_fbo: (FBOId, DeviceIntPoint),
bound_draw_fbo: FBOId,
program_mode_id: UniformLocation,
default_read_fbo: FBOId,
default_draw_fbo: FBOId,
@ -1915,7 +1913,6 @@ impl Device {
bound_vao: 0,
bound_read_fbo: (FBOId(0), DeviceIntPoint::zero()),
bound_draw_fbo: FBOId(0),
program_mode_id: UniformLocation::INVALID,
default_read_fbo: FBOId(0),
default_draw_fbo: FBOId(0),
@ -2175,7 +2172,6 @@ impl Device {
// Shader state
self.bound_program = 0;
self.program_mode_id = UniformLocation::INVALID;
self.gl.use_program(0);
// Reset common state
@ -2532,7 +2528,6 @@ impl Device {
// If we get here, the link succeeded, so get the uniforms.
program.is_initialized = true;
program.u_transform = self.gl.get_uniform_location(program.id, "uTransform");
program.u_mode = self.gl.get_uniform_location(program.id, "uMode");
program.u_texture_size = self.gl.get_uniform_location(program.id, "uTextureSize");
Ok(())
@ -2553,7 +2548,6 @@ impl Device {
self.gl.use_program(program.id);
self.bound_program = program.id;
self.bound_program_name = program.source_info.full_name_cstr.clone();
self.program_mode_id = UniformLocation(program.u_mode);
}
true
}
@ -3044,7 +3038,6 @@ impl Device {
let program = Program {
id: pid,
u_transform: 0,
u_mode: 0,
u_texture_size: 0,
source_info,
is_initialized: false,
@ -3104,14 +3097,6 @@ impl Device {
.uniform_matrix_4fv(program.u_transform, false, &transform.to_array());
}
pub fn switch_mode(&self, mode: i32) {
debug_assert!(self.inside_frame);
#[cfg(debug_assertions)]
debug_assert!(self.shader_is_ready);
self.gl.uniform_1i(self.program_mode_id.0, mode);
}
/// Sets the uTextureSize uniform. Most shaders do not require this to be called
/// as they use the textureSize GLSL function instead.
pub fn set_shader_texture_size(
@ -3933,24 +3918,6 @@ impl Device {
(gl::ONE, gl::ONE),
);
}
pub fn set_blend_mode_subpixel_with_bg_color_pass0(&mut self) {
self.set_blend_factors(
(gl::ZERO, gl::ONE_MINUS_SRC_COLOR),
(gl::ZERO, gl::ONE),
);
}
pub fn set_blend_mode_subpixel_with_bg_color_pass1(&mut self) {
self.set_blend_factors(
(gl::ONE_MINUS_DST_ALPHA, gl::ONE),
(gl::ZERO, gl::ONE),
);
}
pub fn set_blend_mode_subpixel_with_bg_color_pass2(&mut self) {
self.set_blend_factors(
(gl::ONE, gl::ONE),
(gl::ONE, gl::ONE_MINUS_SRC_ALPHA),
);
}
pub fn set_blend_mode_subpixel_dual_source(&mut self) {
self.set_blend_factors(
(gl::ONE, gl::ONE_MINUS_SRC1_COLOR),

View file

@ -109,9 +109,6 @@ impl TextRunTemplate {
// corresponds to `fetch_glyph` in the shaders
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.common.gpu_cache_handle) {
request.push(ColorF::from(self.font.color).premultiplied());
// this is the only case where we need to provide plain color to GPU
let bg_color = ColorF::from(self.font.bg_color);
request.push([bg_color.r, bg_color.g, bg_color.b, 1.0]);
let mut gpu_block = [0.0; 4];
for (i, src) in self.glyphs.iter().enumerate() {
@ -244,7 +241,7 @@ impl TextRunPrimitive {
surface: &SurfaceInfo,
spatial_node_index: SpatialNodeIndex,
transform: &LayoutToWorldTransform,
mut allow_subpixel: bool,
allow_subpixel: bool,
raster_space: RasterSpace,
spatial_tree: &SpatialTree,
) -> bool {
@ -360,10 +357,6 @@ impl TextRunPrimitive {
..specified_font.clone()
};
// If we are using special estimated background subpixel blending, then
// we can allow it regardless of what the surface says.
allow_subpixel |= self.used_font.bg_color.a != 0;
// If using local space glyphs, we don't want subpixel AA.
if !allow_subpixel || !use_subpixel_aa {
self.used_font.disable_subpixel_aa();

View file

@ -302,16 +302,12 @@ fn flag_changed(before: DebugFlags, after: DebugFlags, select: DebugFlags) -> Op
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub enum ShaderColorMode {
FromRenderPassMode = 0,
Alpha = 1,
SubpixelWithBgColorPass0 = 2,
SubpixelWithBgColorPass1 = 3,
SubpixelWithBgColorPass2 = 4,
SubpixelDualSource = 5,
BitmapShadow = 6,
ColorBitmap = 7,
Image = 8,
MultiplyDualSource = 9,
Alpha = 0,
SubpixelDualSource = 1,
BitmapShadow = 2,
ColorBitmap = 3,
Image = 4,
MultiplyDualSource = 5,
}
impl From<GlyphFormat> for ShaderColorMode {
@ -645,7 +641,6 @@ pub enum BlendMode {
PremultipliedAlpha,
PremultipliedDestOut,
SubpixelDualSource,
SubpixelWithBgColor,
Advanced(MixBlendMode),
MultiplyDualSource,
Screen,
@ -2837,23 +2832,6 @@ impl Renderer {
BlendMode::SubpixelDualSource => {
self.device.set_blend_mode_subpixel_dual_source();
}
BlendMode::SubpixelWithBgColor => {
// Using the three pass "component alpha with font smoothing
// background color" rendering technique:
//
// /webrender/doc/text-rendering.md
//
self.device.set_blend_mode_subpixel_with_bg_color_pass0();
// need to make sure the shader is bound
shader.bind(
&mut self.device,
projection,
None,
&mut self.renderer_errors,
&mut self.profile,
);
self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass0 as _);
}
BlendMode::Advanced(mode) => {
if self.enable_advanced_blend_barriers {
self.device.gl().blend_barrier_khr();
@ -2904,44 +2882,6 @@ impl Renderer {
&batch.key.textures,
stats
);
if batch.key.blend_mode == BlendMode::SubpixelWithBgColor {
self.set_blend_mode_subpixel_with_bg_color_pass1(framebuffer_kind);
// re-binding the shader after the blend mode change
shader.bind(
&mut self.device,
projection,
None,
&mut self.renderer_errors,
&mut self.profile,
);
self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass1 as _);
// When drawing the 2nd and 3rd passes, we know that the VAO, textures etc
// are all set up from the previous draw_instanced_batch call,
// so just issue a draw call here to avoid re-uploading the
// instances and re-binding textures etc.
self.device
.draw_indexed_triangles_instanced_u16(6, batch.instances.len() as i32);
self.set_blend_mode_subpixel_with_bg_color_pass2(framebuffer_kind);
// re-binding the shader after the blend mode change
shader.bind(
&mut self.device,
projection,
None,
&mut self.renderer_errors,
&mut self.profile,
);
self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass2 as _);
self.device
.draw_indexed_triangles_instanced_u16(6, batch.instances.len() as i32);
}
if batch.key.blend_mode == BlendMode::SubpixelWithBgColor {
prev_blend_mode = BlendMode::None;
}
}
self.set_blend(false, framebuffer_kind);
@ -5454,24 +5394,6 @@ impl Renderer {
}
}
fn set_blend_mode_subpixel_with_bg_color_pass1(&mut self, framebuffer_kind: FramebufferKind) {
if framebuffer_kind == FramebufferKind::Main &&
self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
self.device.set_blend_mode_show_overdraw();
} else {
self.device.set_blend_mode_subpixel_with_bg_color_pass1();
}
}
fn set_blend_mode_subpixel_with_bg_color_pass2(&mut self, framebuffer_kind: FramebufferKind) {
if framebuffer_kind == FramebufferKind::Main &&
self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
self.device.set_blend_mode_show_overdraw();
} else {
self.device.set_blend_mode_subpixel_with_bg_color_pass2();
}
}
/// Clears the texture with a given color.
fn clear_texture(&mut self, texture: &Texture, color: [f32; 4]) {
self.device.bind_draw_target(DrawTarget::from_texture(

View file

@ -438,7 +438,6 @@ impl BrushShader {
BlendMode::Alpha |
BlendMode::PremultipliedAlpha |
BlendMode::PremultipliedDestOut |
BlendMode::SubpixelWithBgColor |
BlendMode::Screen |
BlendMode::PlusLighter |
BlendMode::Exclusion => {

View file

@ -11,7 +11,6 @@ use std::sync::Arc;
// local imports
use crate::IdNamespace;
use crate::channel::Sender;
use crate::color::ColorU;
use crate::units::LayoutPoint;
/// Hashable floating-point storage for font size.
@ -289,10 +288,6 @@ impl Default for SyntheticItalics {
pub struct FontInstanceOptions {
pub render_mode: FontRenderMode,
pub flags: FontInstanceFlags,
/// When bg_color.a is != 0 and render_mode is FontRenderMode::Subpixel,
/// the text will be rendered with bg_color.r/g/b as an opaque estimated
/// background color.
pub bg_color: ColorU,
pub synthetic_italics: SyntheticItalics,
}
@ -301,7 +296,6 @@ impl Default for FontInstanceOptions {
FontInstanceOptions {
render_mode: FontRenderMode::Subpixel,
flags: Default::default(),
bg_color: ColorU::new(0, 0, 0, 0),
synthetic_italics: SyntheticItalics::disabled(),
}
}

View file

@ -827,7 +827,6 @@ impl FontInstanceMap {
options: Some(FontInstanceOptions {
render_mode: instance.render_mode,
flags: instance.flags,
bg_color: instance.bg_color,
synthetic_italics: instance.synthetic_italics,
}),
platform_options: instance.platform_options,

View file

@ -1,8 +0,0 @@
---
root:
items:
- text: "A"
origin: 30 220
size: 200
color: black
font: "FreeSans.ttf"

View file

@ -1,15 +0,0 @@
# verify that drawing a text run on an off-screen surface with a
# specified background color gives the same result as drawing a
# subpixel text run directly on the background.
---
root:
items:
- type: stacking-context
transform-style: preserve-3d
items:
- text: "A"
origin: 30 220
size: 200
color: black
font: "FreeSans.ttf"
bg-color: white

View file

@ -59,7 +59,6 @@ skip_on(android,device) == shadow-partial-glyph.yaml shadow-partial-glyph-ref.ya
fuzzy(2,212) platform(linux) == shadow-transforms.yaml shadow-transforms.png
fuzzy(2,370) platform(linux) == raster-space.yaml raster-space.png
skip_on(android) skip_on(mac,>=10.14) != allow-subpixel.yaml allow-subpixel-ref.yaml # Android: we don't enable sub-px aa on this platform.
skip_on(android,device) fuzzy-if(platform(swgl),1,1085) == bg-color.yaml bg-color-ref.yaml # Fails on Pixel2
!= large-glyphs.yaml blank.yaml
!= large-line-decoration.yaml blank.yaml
skip_on(android,device) == snap-text-offset.yaml snap-text-offset-ref.yaml

View file

@ -745,7 +745,6 @@ impl YamlFrameReader {
&mut self,
font_key: FontKey,
size: f32,
bg_color: Option<ColorU>,
flags: FontInstanceFlags,
synthetic_italics: SyntheticItalics,
wrench: &mut Wrench,
@ -753,14 +752,13 @@ impl YamlFrameReader {
let font_render_mode = self.font_render_mode;
*self.font_instances
.entry((font_key, size.into(), flags, bg_color, synthetic_italics))
.entry((font_key, size.into(), flags, synthetic_italics))
.or_insert_with(|| {
wrench.add_font_instance(
font_key,
size,
flags,
font_render_mode,
bg_color,
synthetic_italics,
)
})
@ -1350,7 +1348,6 @@ impl YamlFrameReader {
) {
let size = item["size"].as_pt_to_f32().unwrap_or(16.0);
let color = item["color"].as_colorf().unwrap_or(ColorF::BLACK);
let bg_color = item["bg-color"].as_colorf().map(|c| c.into());
let synthetic_italics = if let Some(angle) = item["synthetic-italics"].as_f32() {
SyntheticItalics::from_degrees(angle)
} else if item["synthetic-italics"].as_bool().unwrap_or(false) {
@ -1385,7 +1382,6 @@ impl YamlFrameReader {
let font_key = self.get_or_create_font(desc, wrench);
let font_instance_key = self.get_or_create_font_instance(font_key,
size,
bg_color,
flags,
synthetic_italics,
wrench);

View file

@ -19,7 +19,6 @@
/* These properties are not included in 'all'. */
-moz-context-properties: initial;
-moz-control-character-visibility: initial;
-moz-font-smoothing-background-color: initial;
-moz-min-font-size-ratio: initial;
-moz-box-collapse: initial;

View file

@ -98,17 +98,16 @@ const char* gInaccessibleProperties[] = {
"-moz-inert",
"-moz-script-level", // parsed by UA sheets only
"-moz-math-variant",
"-moz-math-display", // parsed by UA sheets only
"-moz-top-layer", // parsed by UA sheets only
"-moz-min-font-size-ratio", // parsed by UA sheets only
"-moz-box-collapse", // chrome-only internal properties
"-moz-font-smoothing-background-color", // chrome-only internal properties
"-moz-subtree-hidden-only-visually", // chrome-only internal properties
"-moz-window-input-region-margin", // chrome-only internal properties
"-moz-window-opacity", // chrome-only internal properties
"-moz-window-transform", // chrome-only internal properties
"-moz-window-transform-origin", // chrome-only internal properties
"-moz-window-shadow", // chrome-only internal properties
"-moz-math-display", // parsed by UA sheets only
"-moz-top-layer", // parsed by UA sheets only
"-moz-min-font-size-ratio", // parsed by UA sheets only
"-moz-box-collapse", // chrome-only internal properties
"-moz-subtree-hidden-only-visually", // chrome-only internal properties
"-moz-window-input-region-margin", // chrome-only internal properties
"-moz-window-opacity", // chrome-only internal properties
"-moz-window-transform", // chrome-only internal properties
"-moz-window-transform-origin", // chrome-only internal properties
"-moz-window-shadow", // chrome-only internal properties
};
inline int is_inaccessible(const char* aPropName) {

View file

@ -13457,15 +13457,6 @@ if (false) {
"2px",
],
};
gCSSProperties["-moz-font-smoothing-background-color"] = {
// domProp: "MozFontSmoothingBackgroundColor",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: ["transparent"],
other_values: ["green", "#fc3"],
invalid_values: ["000000", "ff00ff"],
};
}
gCSSProperties["scrollbar-color"] = {

View file

@ -493,18 +493,6 @@ ${helpers.single_keyword(
affects="paint",
)}
${helpers.predefined_type(
"-moz-font-smoothing-background-color",
"color::MozFontSmoothingBackgroundColor",
"computed::color::MozFontSmoothingBackgroundColor::TRANSPARENT_BLACK",
engines="gecko",
animation_value_type="none",
gecko_ffi_name="mFont.fontSmoothingBackgroundColor",
enabled_in="chrome",
spec="None (Nonstandard internal property)",
affects="paint",
)}
${helpers.predefined_type(
"-moz-min-font-size-ratio",
"Percentage",

View file

@ -19,9 +19,6 @@ pub use crate::values::specified::color::{ColorScheme, ForcedColorAdjust, PrintC
/// The computed value of the `color` property.
pub type ColorPropertyValue = AbsoluteColor;
/// The computed value of `-moz-font-smoothing-background-color`.
pub type MozFontSmoothingBackgroundColor = AbsoluteColor;
/// A computed value for `<color>`.
pub type Color = GenericColor<Percentage>;

View file

@ -925,38 +925,6 @@ impl ToComputedValue for Color {
}
}
/// Specified color value for `-moz-font-smoothing-background-color`.
///
/// This property does not support `currentcolor`. We could drop it at
/// parse-time, but it's not exposed to the web so it doesn't really matter.
///
/// We resolve it to `transparent` instead.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
pub struct MozFontSmoothingBackgroundColor(pub Color);
impl Parse for MozFontSmoothingBackgroundColor {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Color::parse(context, input).map(MozFontSmoothingBackgroundColor)
}
}
impl ToComputedValue for MozFontSmoothingBackgroundColor {
type ComputedValue = AbsoluteColor;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
self.0
.to_computed_value(context)
.resolve_to_absolute(&AbsoluteColor::TRANSPARENT_BLACK)
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
MozFontSmoothingBackgroundColor(Color::from_absolute_color(*computed))
}
}
impl SpecifiedValueInfo for Color {
const SUPPORTED_TYPES: u8 = CssType::COLOR;

View file

@ -379,7 +379,6 @@ tooltip {
tooltip {
appearance: auto;
-moz-default-appearance: tooltip;
-moz-font-smoothing-background-color: -moz-mac-tooltip;
white-space: pre-wrap;

View file

@ -57,7 +57,6 @@ menubar > menu[_moz-menuactive="true"] {
menubar > menu[_moz-menuactive="true"][open="true"] {
color: -moz-menuhovertext;
background-color: -moz-menuhover;
-moz-font-smoothing-background-color: -moz-mac-active-menuitem;
}
/* Internal content */

View file

@ -94,7 +94,6 @@ menucaption {
flex-shrink: 0;
list-style-image: none;
max-width: 42em;
-moz-font-smoothing-background-color: -moz-mac-menuitem;
@media (-moz-platform: linux) {
padding: 4px 6px;
@ -110,13 +109,11 @@ menuitem {
&:where([disabled="true"]) {
color: var(--panel-disabled-color);
text-shadow: none;
-moz-font-smoothing-background-color: -moz-mac-menuitem;
}
&:where([_moz-menuactive]:not([disabled="true"])) {
color: -moz-menuhovertext;
background-color: -moz-menuhover;
-moz-font-smoothing-background-color: -moz-mac-active-menuitem;
}
&:where([_moz-menuactive="true"][disabled="true"]) {

View file

@ -58,7 +58,6 @@ panel {
display: flex;
box-sizing: border-box;
-moz-font-smoothing-background-color: var(--panel-background, -moz-mac-menupopup);
padding: var(--panel-padding);
color: var(--panel-color);
background: var(--panel-background);