Fix loading raw data from .ttc files on macos (#38753)

# Objective

Ensure that functionality which uses the raw font data (such as
rendering text to canvas) works correctly on macOS when the specified
font is a system font that lives in an OpenType Collection (`.ttc`)
file.

## Changes made

- The `read_data_from_file` in each backend now returns a `index: u32`
in addition to `data: Vec<u8>`
- The `data` field on the `Font` type has been renamed to `raw` and the
`data` method on the `Font` type has been renamed to `raw_font`. This
allows the index to be cached as computing is moderately expensive on
macOS (on the order of 100 microseconds).
- Both of the above now store/return a `struct RawFont` instead of a
`FontData` where `RawFont` is defined as `struct RawFont { data:
FontData, index: u32 }`.
- The users of the `data` method have been updated to use the cached
index from `data` rather than calling `.index()` each time.

---------

Signed-off-by: Nico Burns <nico@nicoburns.com>
This commit is contained in:
Nico Burns 2025-08-19 12:57:48 +01:00 committed by GitHub
parent 3225d19907
commit 39629560c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 164 additions and 76 deletions

View file

@ -9,6 +9,13 @@ use style::color::AbsoluteColor;
use crate::backend::Convert;
use crate::canvas_data::Filter;
impl Convert<peniko::Font> for fonts::FontDataAndIndex {
fn convert(self) -> peniko::Font {
use std::sync::Arc;
peniko::Font::new(peniko::Blob::new(Arc::new(self.data)), self.index)
}
}
impl Convert<kurbo::Join> for LineJoinStyle {
fn convert(self) -> kurbo::Join {
match self {

View file

@ -333,8 +333,11 @@ impl GenericDrawTarget for raqote::DrawTarget {
SHARED_FONT_CACHE.with(|font_cache| {
let identifier = template.identifier();
if !font_cache.borrow().contains_key(&identifier) {
let data = std::sync::Arc::new(run.font.data().as_ref().to_vec());
let Ok(font) = Font::from_bytes(data, identifier.index()) else {
let Ok(font_data_and_index) = run.font.font_data_and_index() else {
return;
};
let data = std::sync::Arc::new(font_data_and_index.data.as_ref().to_vec());
let Ok(font) = Font::from_bytes(data, font_data_and_index.index) else {
return;
};
font_cache.borrow_mut().insert(identifier.clone(), font);

View file

@ -402,13 +402,11 @@ impl GenericDrawTarget for VelloDrawTarget {
SHARED_FONT_CACHE.with(|font_cache| {
let identifier = template.identifier();
if !font_cache.borrow().contains_key(&identifier) {
font_cache.borrow_mut().insert(
identifier.clone(),
peniko::Font::new(
peniko::Blob::from(run.font.data().as_ref().to_vec()),
identifier.index(),
),
);
let Ok(font) = run.font.font_data_and_index() else {
return;
};
let font = font.clone().convert();
font_cache.borrow_mut().insert(identifier.clone(), font);
}
let font_cache = font_cache.borrow();

View file

@ -305,13 +305,11 @@ impl GenericDrawTarget for VelloCPUDrawTarget {
SHARED_FONT_CACHE.with(|font_cache| {
let identifier = template.identifier();
if !font_cache.borrow().contains_key(&identifier) {
font_cache.borrow_mut().insert(
identifier.clone(),
peniko::Font::new(
peniko::Blob::from(run.font.data().as_ref().to_vec()),
identifier.index(),
),
);
let Ok(font) = run.font.font_data_and_index() else {
return;
};
let font = font.clone().convert();
font_cache.borrow_mut().insert(identifier.clone(), font);
}
let font_cache = font_cache.borrow();