commit f260ef5fb86a9c2d8437c0a52f5ec928bbc0122a
parent 51f5ea9c7917f23a5e79937c07d6e9bc186eab05
Author: Jonathan Kew <jkew@mozilla.com>
Date: Tue, 2 Dec 2025 16:49:02 +0000
Bug 2003460 - Fix font-weight matching behavior for "simple" font families to more closely follow the spec (and our behavior for richer, multi-weight families). r=layout-reviewers,firefox-style-system-reviewers,emilio
Differential Revision: https://phabricator.services.mozilla.com/D274775
Diffstat:
6 files changed, 96 insertions(+), 2 deletions(-)
diff --git a/gfx/thebes/SharedFontList.cpp b/gfx/thebes/SharedFontList.cpp
@@ -334,7 +334,7 @@ bool Family::FindAllFacesForStyleInternal(FontList* aList,
// calculate which one we want.
// Note that we cannot simply return it as not all 4 faces are necessarily
// present.
- bool wantBold = aStyle.weight.IsBold();
+ bool wantBold = aStyle.weight.PreferBold();
bool wantItalic = !aStyle.style.IsNormal();
uint8_t faceIndex =
(wantItalic ? kItalicMask : 0) | (wantBold ? kBoldMask : 0);
diff --git a/layout/style/ServoStyleConstsInlines.h b/layout/style/ServoStyleConstsInlines.h
@@ -1105,6 +1105,10 @@ inline void StyleFontStyle::ToString(nsACString& aString) const {
inline bool StyleFontWeight::IsBold() const { return *this >= BOLD_THRESHOLD; }
+inline bool StyleFontWeight::PreferBold() const {
+ return *this > PREFER_BOLD_THRESHOLD;
+}
+
inline bool StyleFontStyle::IsItalic() const { return *this == ITALIC; }
inline float StyleFontStyle::ObliqueAngle() const {
diff --git a/servo/components/style/values/computed/font.rs b/servo/components/style/values/computed/font.rs
@@ -188,12 +188,18 @@ impl FontWeight {
value: 600 << FONT_WEIGHT_FRACTION_BITS,
});
+ /// The threshold above which CSS font matching prefers bolder faces
+ /// over lighter ones.
+ pub const PREFER_BOLD_THRESHOLD: FontWeight = FontWeight(FontWeightFixedPoint {
+ value: 500 << FONT_WEIGHT_FRACTION_BITS,
+ });
+
/// Returns the `normal` keyword value.
pub fn normal() -> Self {
Self::NORMAL
}
- /// Weither this weight is bold
+ /// Whether this weight is bold
pub fn is_bold(&self) -> bool {
*self >= Self::BOLD_THRESHOLD
}
diff --git a/servo/ports/geckolib/cbindgen.toml b/servo/ports/geckolib/cbindgen.toml
@@ -1077,6 +1077,7 @@ renaming_overrides_prefixing = true
bool IsNormal() const { return *this == NORMAL; }
inline bool IsBold() const;
+ inline bool PreferBold() const;
"""
"FontStyle" = """
diff --git a/testing/web-platform/tests/css/css-fonts/matching/font-weight-search-direction-ref.html b/testing/web-platform/tests/css/css-fonts/matching/font-weight-search-direction-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+
+<style>
+@font-face {
+ font-family: simple;
+ font-weight: normal;
+ src: url("/fonts/Lato-Medium.ttf");
+}
+@font-face {
+ font-family: simple;
+ font-weight: bold;
+ src: url("/fonts/Lato-Bold.ttf");
+}
+</style>
+
+<div style='font: normal 24px "simple"'>This should be normal weight</div>
+<div style='font: normal 24px "simple"'>This should be normal weight</div>
+<div style='font: normal 24px "simple"'>This should be normal weight</div>
+<div style='font: normal 24px "simple"'>This should be normal weight</div>
+<div style='font: bold 24px "simple"'>This should be bold weight</div>
+<div style='font: bold 24px "simple"'>This should be bold weight</div>
+<div style='font: bold 24px "simple"'>This should be bold weight</div>
+<div style='font: bold 24px "simple"'>This should be bold weight</div>
+
+<br>
+
+<div style='font: normal 24px "Times New Roman", "simple"'>This should be normal weight</div>
+<div style='font: normal 24px "Times New Roman", "simple"'>This should be normal weight</div>
+<div style='font: normal 24px "Times New Roman", "simple"'>This should be normal weight</div>
+<div style='font: normal 24px "Times New Roman", "simple"'>This should be normal weight</div>
+<div style='font: bold 24px "Times New Roman", "simple"'>This should be bold weight</div>
+<div style='font: bold 24px "Times New Roman", "simple"'>This should be bold weight</div>
+<div style='font: bold 24px "Times New Roman", "simple"'>This should be bold weight</div>
+<div style='font: bold 24px "Times New Roman", "simple"'>This should be bold weight</div>
diff --git a/testing/web-platform/tests/css/css-fonts/matching/font-weight-search-direction.html b/testing/web-platform/tests/css/css-fonts/matching/font-weight-search-direction.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+
+<title>CSS Fonts 4: Font matching algorithm</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"/>
+<link rel="help" href="https://drafts.csswg.org/css-fonts/#font-style-matching">
+<link rel=match href="font-weight-search-direction-ref.html">
+<meta name="assert" content="If the desired weight is greater than 500,
+ weights greater than or equal to the desired weight are checked in ascending order
+ followed by weights below the desired weight in descending order
+ until a match is found.">
+
+<style>
+@font-face {
+ font-family: "simple";
+ font-weight: normal;
+ src: url("/fonts/Lato-Medium.ttf");
+}
+@font-face {
+ font-family: "simple";
+ font-weight: bold;
+ src: url("/fonts/Lato-Bold.ttf");
+}
+</style>
+
+<!-- The "simple" family has just normal and bold weights; check that various
+ font-weight values select the expected face. -->
+<div style='font: 100 24px "simple"'>This should be normal weight</div>
+<div style='font: 400 24px "simple"'>This should be normal weight</div>
+<div style='font: 499 24px "simple"'>This should be normal weight</div>
+<div style='font: 500 24px "simple"'>This should be normal weight</div>
+<div style='font: 501 24px "simple"'>This should be bold weight</div>
+<div style='font: 600 24px "simple"'>This should be bold weight</div>
+<div style='font: 700 24px "simple"'>This should be bold weight</div>
+<div style='font: 900 24px "simple"'>This should be bold weight</div>
+
+<br>
+
+<!-- If the Times New Roman family is present, it normally has the "standard 4" faces,
+ so should behave similarly. -->
+<div style='font: 100 24px "Times New Roman", "simple"'>This should be normal weight</div>
+<div style='font: 400 24px "Times New Roman", "simple"'>This should be normal weight</div>
+<div style='font: 499 24px "Times New Roman", "simple"'>This should be normal weight</div>
+<div style='font: 500 24px "Times New Roman", "simple"'>This should be normal weight</div>
+<div style='font: 501 24px "Times New Roman", "simple"'>This should be bold weight</div>
+<div style='font: 600 24px "Times New Roman", "simple"'>This should be bold weight</div>
+<div style='font: 700 24px "Times New Roman", "simple"'>This should be bold weight</div>
+<div style='font: 900 24px "Times New Roman", "simple"'>This should be bold weight</div>