aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2024-04-05 12:22:36 +0200
committerGitHub <noreply@github.com>2024-04-05 10:22:36 +0000
commit77b2e88fb7a2d3e672b5d223ba2ae8f2d15de853 (patch)
treeb7fb12562b4d0ae4dff4346d7537588570c3e6e9 /components
parent14bf1c5434cd4cd9412a601a556e6c757c466b92 (diff)
downloadservo-77b2e88fb7a2d3e672b5d223ba2ae8f2d15de853.tar.gz
servo-77b2e88fb7a2d3e672b5d223ba2ae8f2d15de853.zip
gfx: Do not apply scale to `CoreText` font metrics (#31996)
Since the original version of the CoreText font code, it has scaled the metrics from CoreText by an unusual scale: ``` let scale = px_to_pt(self.ctfont.pt_size()) / (ascent + descent); ``` It's unclear what this scale was trying to accomplish. Note that it's passing the return value of `pt_size()` to `px_to_pt` which seems backward. This scale seems bogus, but perhaps it's based on a misconception about what its returned from CoreText. Unlike the return values of `CGFont` methods, which are returned in font units, the ones from `CTFont` are "scaled according to the point size and matrix of the font reference." Indeed, when just interpreting these values as pixel values, the results more or less match Firefox and Chrome. This becomes much more obvious now that we have support for `ex` units. Even when not using `ex`, you can sometimes see the top parts of glyphs cut off due to this scaling. This change removes the scaling and simply interpets the return values of `CTFont` methods as pixels. It addresses all of the issues mentioned above. Note that this path will eventually just be a fallback path and metrics will come from sfnt tables in the future.
Diffstat (limited to 'components')
-rw-r--r--components/gfx/platform/macos/font.rs39
1 files changed, 12 insertions, 27 deletions
diff --git a/components/gfx/platform/macos/font.rs b/components/gfx/platform/macos/font.rs
index 0535dbe22cb..f8088b24412 100644
--- a/components/gfx/platform/macos/font.rs
+++ b/components/gfx/platform/macos/font.rs
@@ -14,7 +14,6 @@ use core_foundation::base::CFIndex;
use core_foundation::data::CFData;
use core_foundation::string::UniChar;
use core_graphics::font::CGGlyph;
-use core_graphics::geometry::CGRect;
use core_text::font::CTFont;
use core_text::font_descriptor::{
kCTFontDefaultOrientation, SymbolicTraitAccessors, TraitAccessors,
@@ -38,19 +37,10 @@ pub struct FontTable {
}
// assumes 72 points per inch, and 96 px per inch
-fn px_to_pt(px: f64) -> f64 {
- px / 96. * 72.
-}
-
-// assumes 72 points per inch, and 96 px per inch
fn pt_to_px(pt: f64) -> f64 {
pt / 72. * 96.
}
-fn au_from_pt(pt: f64) -> Au {
- Au::from_f64_px(pt_to_px(pt))
-}
-
impl FontTable {
pub fn wrap(data: CFData) -> FontTable {
FontTable { data }
@@ -281,43 +271,38 @@ impl FontHandleMethods for FontHandle {
// TODO(mrobinson): Gecko first tries to get metrics from the SFNT tables via
// HarfBuzz and only afterward falls back to platform APIs. We should do something
// similar here. This will likely address issue #201 mentioned below.
- let bounding_rect: CGRect = self.ctfont.bounding_box();
let ascent = self.ctfont.ascent();
let descent = self.ctfont.descent();
- let em_size = Au::from_f64_px(self.ctfont.pt_size());
let leading = self.ctfont.leading();
-
- let scale = px_to_pt(self.ctfont.pt_size()) / (ascent + descent);
+ let x_height = self.ctfont.x_height();
+ let underline_thickness = self.ctfont.underline_thickness();
let line_gap = (ascent + descent + leading + 0.5).floor();
- let max_advance = au_from_pt(bounding_rect.size.width);
+ let max_advance = Au::from_f64_px(self.ctfont.bounding_box().size.width);
let average_advance = self
.glyph_index('0')
.and_then(|idx| self.glyph_h_advance(idx))
.map(Au::from_f64_px)
.unwrap_or(max_advance);
- let underline_size = au_from_pt(self.ctfont.underline_thickness());
- let x_height = au_from_pt(self.ctfont.x_height() * scale);
-
let metrics = FontMetrics {
- underline_size,
+ underline_size: Au::from_f64_au(underline_thickness),
// TODO(Issue #201): underline metrics are not reliable. Have to pull out of font table
// directly.
//
// see also: https://bugs.webkit.org/show_bug.cgi?id=16768
// see also: https://bugreports.qt-project.org/browse/QTBUG-13364
- underline_offset: au_from_pt(self.ctfont.underline_position()),
+ underline_offset: Au::from_f64_px(self.ctfont.underline_position()),
// There is no way to get these from CoreText or CoreGraphics APIs, so
// derive them from the other font metrics. These should eventually be
// found in the font tables directly when #201 is fixed.
- strikeout_size: underline_size,
- strikeout_offset: x_height.scale_by(0.5) + underline_size.scale_by(0.5),
- leading: au_from_pt(leading),
- x_height,
- em_size,
- ascent: au_from_pt(ascent * scale),
- descent: au_from_pt(descent * scale),
+ strikeout_size: Au::from_f64_px(underline_thickness),
+ strikeout_offset: Au::from_f64_px((x_height + underline_thickness) / 2.0),
+ leading: Au::from_f64_px(leading),
+ x_height: Au::from_f64_px(x_height),
+ em_size: Au::from_f64_px(self.ctfont.pt_size()),
+ ascent: Au::from_f64_px(ascent),
+ descent: Au::from_f64_px(descent),
max_advance,
average_advance,
line_gap: Au::from_f64_px(line_gap),