Feature/fallback fonts (#15306)

Supersedes https://github.com/zed-industries/zed/pull/12090

fixes #5180
fixes #5055

See original PR for an example of the feature at work.

This PR changes the settings interface to be backwards compatible, and
adds the `ui_font_fallbacks`, `buffer_font_fallbacks`, and
`terminal.font_fallbacks` settings.

Release Notes:

- Added support for font fallbacks via three new settings:
`ui_font_fallbacks`, `buffer_font_fallbacks`, and
`terminal.font_fallbacks`.(#5180, #5055).

---------

Co-authored-by: Junkui Zhang <364772080@qq.com>
This commit is contained in:
Mikayla Maki 2024-07-26 16:42:21 -07:00 committed by GitHub
parent 3e31955b7f
commit a1bd7a1297
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 444 additions and 136 deletions

View file

@ -1,6 +1,6 @@
use crate::{
point, px, size, Bounds, DevicePixels, Font, FontFeatures, FontId, FontMetrics, FontRun,
FontStyle, FontWeight, GlyphId, LineLayout, Pixels, PlatformTextSystem, Point,
point, px, size, Bounds, DevicePixels, Font, FontFallbacks, FontFeatures, FontId, FontMetrics,
FontRun, FontStyle, FontWeight, GlyphId, LineLayout, Pixels, PlatformTextSystem, Point,
RenderGlyphParams, Result, ShapedGlyph, ShapedRun, SharedString, Size, SUBPIXEL_VARIANTS,
};
use anyhow::anyhow;
@ -43,7 +43,7 @@ use pathfinder_geometry::{
use smallvec::SmallVec;
use std::{borrow::Cow, char, cmp, convert::TryFrom, sync::Arc};
use super::open_type;
use super::open_type::apply_features_and_fallbacks;
#[allow(non_upper_case_globals)]
const kCGImageAlphaOnly: u32 = 7;
@ -54,6 +54,7 @@ pub(crate) struct MacTextSystem(RwLock<MacTextSystemState>);
struct FontKey {
font_family: SharedString,
font_features: FontFeatures,
font_fallbacks: Option<FontFallbacks>,
}
struct MacTextSystemState {
@ -123,11 +124,13 @@ impl PlatformTextSystem for MacTextSystem {
let font_key = FontKey {
font_family: font.family.clone(),
font_features: font.features.clone(),
font_fallbacks: font.fallbacks.clone(),
};
let candidates = if let Some(font_ids) = lock.font_ids_by_font_key.get(&font_key) {
font_ids.as_slice()
} else {
let font_ids = lock.load_family(&font.family, &font.features)?;
let font_ids =
lock.load_family(&font.family, &font.features, font.fallbacks.as_ref())?;
lock.font_ids_by_font_key.insert(font_key.clone(), font_ids);
lock.font_ids_by_font_key[&font_key].as_ref()
};
@ -212,6 +215,7 @@ impl MacTextSystemState {
&mut self,
name: &str,
features: &FontFeatures,
fallbacks: Option<&FontFallbacks>,
) -> Result<SmallVec<[FontId; 4]>> {
let name = if name == ".SystemUIFont" {
".AppleSystemUIFont"
@ -227,8 +231,7 @@ impl MacTextSystemState {
for font in family.fonts() {
let mut font = font.load()?;
open_type::apply_features(&mut font, features);
apply_features_and_fallbacks(&mut font, features, fallbacks)?;
// This block contains a precautionary fix to guard against loading fonts
// that might cause panics due to `.unwrap()`s up the chain.
{
@ -457,6 +460,7 @@ impl MacTextSystemState {
CFRange::init(utf16_start as isize, (utf16_end - utf16_start) as isize);
let font: &FontKitFont = &self.fonts[run.font_id.0];
unsafe {
string.set_attribute(
cf_range,
@ -634,7 +638,7 @@ impl From<FontStyle> for FontkitStyle {
}
}
// Some fonts may have no attributest despite `core_text` requiring them (and panicking).
// Some fonts may have no attributes despite `core_text` requiring them (and panicking).
// This is the same version as `core_text` has without `expect` calls.
mod lenient_font_attributes {
use core_foundation::{