diff options
author | Martin Robinson <mrobinson@igalia.com> | 2024-04-05 12:22:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-05 10:22:36 +0000 |
commit | 77b2e88fb7a2d3e672b5d223ba2ae8f2d15de853 (patch) | |
tree | b7fb12562b4d0ae4dff4346d7537588570c3e6e9 /components | |
parent | 14bf1c5434cd4cd9412a601a556e6c757c466b92 (diff) | |
download | servo-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.rs | 39 |
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), |