Checkpoint
This commit is contained in:
parent
58dadad8ec
commit
e9a84a21e4
11 changed files with 376 additions and 181 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3243,6 +3243,7 @@ dependencies = [
|
||||||
"async-task",
|
"async-task",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bindgen 0.65.1",
|
"bindgen 0.65.1",
|
||||||
|
"bitflags 2.4.0",
|
||||||
"block",
|
"block",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cbindgen",
|
"cbindgen",
|
||||||
|
|
|
@ -58,6 +58,7 @@ slotmap = "1.0.6"
|
||||||
bytemuck = { version = "1.14.0", features = ["derive"] }
|
bytemuck = { version = "1.14.0", features = ["derive"] }
|
||||||
schemars.workspace = true
|
schemars.workspace = true
|
||||||
plane-split = "0.18.0"
|
plane-split = "0.18.0"
|
||||||
|
bitflags = "2.4.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
backtrace = "0.3"
|
backtrace = "0.3"
|
||||||
|
|
|
@ -13,6 +13,7 @@ use std::{
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
};
|
};
|
||||||
|
use util::ResultExt;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct App(Arc<Mutex<AppContext>>);
|
pub struct App(Arc<Mutex<AppContext>>);
|
||||||
|
@ -173,7 +174,9 @@ impl AppContext {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for dirty_window_id in dirty_window_ids {
|
for dirty_window_id in dirty_window_ids {
|
||||||
self.update_window(dirty_window_id, |cx| cx.draw());
|
self.update_window(dirty_window_id, |cx| cx.draw())
|
||||||
|
.unwrap() // We know we have the window.
|
||||||
|
.log_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ impl<T> Flatten<T> for Result<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct SharedString(ArcCow<'static, str>);
|
pub struct SharedString(ArcCow<'static, str>);
|
||||||
|
|
||||||
impl Default for SharedString {
|
impl Default for SharedString {
|
||||||
|
|
|
@ -6,8 +6,8 @@ mod mac;
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, Bounds, FontFeatures, FontId, FontMetrics, FontStyle, FontWeight, GlyphId,
|
AnyWindowHandle, Bounds, FontFeatures, FontId, FontStyle, FontWeight, GlyphId, LineLayout,
|
||||||
LineLayout, Pixels, Point, Result, RunStyle, Scene, SharedString, Size,
|
Pixels, Point, Result, RunStyle, Scene, SharedString, Size,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use async_task::Runnable;
|
use async_task::Runnable;
|
||||||
|
@ -25,7 +25,6 @@ use std::{
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
pub use time::UtcOffset;
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub use events::*;
|
pub use events::*;
|
||||||
|
@ -34,6 +33,7 @@ pub use keystroke::*;
|
||||||
pub use mac::*;
|
pub use mac::*;
|
||||||
#[cfg(any(test, feature = "test"))]
|
#[cfg(any(test, feature = "test"))]
|
||||||
pub use test::*;
|
pub use test::*;
|
||||||
|
pub use time::UtcOffset;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub(crate) fn current_platform() -> Arc<dyn Platform> {
|
pub(crate) fn current_platform() -> Arc<dyn Platform> {
|
||||||
|
@ -154,19 +154,12 @@ pub trait PlatformDispatcher: Send + Sync {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PlatformTextSystem: Send + Sync {
|
pub trait PlatformTextSystem: Send + Sync {
|
||||||
fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> anyhow::Result<()>;
|
fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> Result<()>;
|
||||||
fn all_families(&self) -> Vec<String>;
|
fn all_font_families(&self) -> Vec<String>;
|
||||||
fn load_family(&self, name: &str, features: &FontFeatures) -> anyhow::Result<Vec<FontId>>;
|
fn select_font(&self, descriptor: FontDescriptor) -> Result<FontId>;
|
||||||
fn select_font(
|
|
||||||
&self,
|
|
||||||
font_ids: &[FontId],
|
|
||||||
weight: FontWeight,
|
|
||||||
style: FontStyle,
|
|
||||||
) -> anyhow::Result<FontId>;
|
|
||||||
fn font_metrics(&self, font_id: FontId) -> FontMetrics;
|
fn font_metrics(&self, font_id: FontId) -> FontMetrics;
|
||||||
fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId)
|
fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>>;
|
||||||
-> anyhow::Result<Bounds<f32>>;
|
fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>>;
|
||||||
fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> anyhow::Result<Size<f32>>;
|
|
||||||
fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option<GlyphId>;
|
fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option<GlyphId>;
|
||||||
fn rasterize_glyph(
|
fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
|
@ -404,3 +397,24 @@ impl ClipboardItem {
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub struct FontDescriptor {
|
||||||
|
family: SharedString,
|
||||||
|
features: FontFeatures,
|
||||||
|
weight: FontWeight,
|
||||||
|
style: FontStyle,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct FontMetrics {
|
||||||
|
pub units_per_em: u32,
|
||||||
|
pub ascent: f32,
|
||||||
|
pub descent: f32,
|
||||||
|
pub line_gap: f32,
|
||||||
|
pub underline_position: f32,
|
||||||
|
pub underline_thickness: f32,
|
||||||
|
pub cap_height: f32,
|
||||||
|
pub x_height: f32,
|
||||||
|
pub bounding_box: Bounds<f32>,
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#![allow(unused, non_upper_case_globals)]
|
#![allow(unused, non_upper_case_globals)]
|
||||||
|
|
||||||
use std::ptr;
|
|
||||||
|
|
||||||
use crate::FontFeatures;
|
use crate::FontFeatures;
|
||||||
use cocoa::appkit::CGFloat;
|
use cocoa::appkit::CGFloat;
|
||||||
use core_foundation::{base::TCFType, number::CFNumber};
|
use core_foundation::{base::TCFType, number::CFNumber};
|
||||||
|
@ -13,6 +11,7 @@ use core_text::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use font_kit::font::Font;
|
use font_kit::font::Font;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
const kCaseSensitiveLayoutOffSelector: i32 = 1;
|
const kCaseSensitiveLayoutOffSelector: i32 = 1;
|
||||||
const kCaseSensitiveLayoutOnSelector: i32 = 0;
|
const kCaseSensitiveLayoutOnSelector: i32 = 0;
|
||||||
|
@ -108,243 +107,243 @@ const kTypographicExtrasType: i32 = 14;
|
||||||
const kVerticalFractionsSelector: i32 = 1;
|
const kVerticalFractionsSelector: i32 = 1;
|
||||||
const kVerticalPositionType: i32 = 10;
|
const kVerticalPositionType: i32 = 10;
|
||||||
|
|
||||||
pub fn apply_features(font: &mut Font, features: &FontFeatures) {
|
pub fn apply_features(font: &mut Font, features: FontFeatures) {
|
||||||
// See https://chromium.googlesource.com/chromium/src/+/66.0.3359.158/third_party/harfbuzz-ng/src/hb-coretext.cc
|
// See https://chromium.googlesource.com/chromium/src/+/66.0.3359.158/third_party/harfbuzz-ng/src/hb-coretext.cc
|
||||||
// for a reference implementation.
|
// for a reference implementation.
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.calt,
|
features.calt(),
|
||||||
kContextualAlternatesType,
|
kContextualAlternatesType,
|
||||||
kContextualAlternatesOnSelector,
|
kContextualAlternatesOnSelector,
|
||||||
kContextualAlternatesOffSelector,
|
kContextualAlternatesOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.case,
|
features.case(),
|
||||||
kCaseSensitiveLayoutType,
|
kCaseSensitiveLayoutType,
|
||||||
kCaseSensitiveLayoutOnSelector,
|
kCaseSensitiveLayoutOnSelector,
|
||||||
kCaseSensitiveLayoutOffSelector,
|
kCaseSensitiveLayoutOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.cpsp,
|
features.cpsp(),
|
||||||
kCaseSensitiveLayoutType,
|
kCaseSensitiveLayoutType,
|
||||||
kCaseSensitiveSpacingOnSelector,
|
kCaseSensitiveSpacingOnSelector,
|
||||||
kCaseSensitiveSpacingOffSelector,
|
kCaseSensitiveSpacingOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.frac,
|
features.frac(),
|
||||||
kFractionsType,
|
kFractionsType,
|
||||||
kDiagonalFractionsSelector,
|
kDiagonalFractionsSelector,
|
||||||
kNoFractionsSelector,
|
kNoFractionsSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.liga,
|
features.liga(),
|
||||||
kLigaturesType,
|
kLigaturesType,
|
||||||
kCommonLigaturesOnSelector,
|
kCommonLigaturesOnSelector,
|
||||||
kCommonLigaturesOffSelector,
|
kCommonLigaturesOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.onum,
|
features.onum(),
|
||||||
kNumberCaseType,
|
kNumberCaseType,
|
||||||
kLowerCaseNumbersSelector,
|
kLowerCaseNumbersSelector,
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ordn,
|
features.ordn(),
|
||||||
kVerticalPositionType,
|
kVerticalPositionType,
|
||||||
kOrdinalsSelector,
|
kOrdinalsSelector,
|
||||||
kNormalPositionSelector,
|
kNormalPositionSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.pnum,
|
features.pnum(),
|
||||||
kNumberSpacingType,
|
kNumberSpacingType,
|
||||||
kProportionalNumbersSelector,
|
kProportionalNumbersSelector,
|
||||||
4,
|
4,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss01,
|
features.ss01(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltOneOnSelector,
|
kStylisticAltOneOnSelector,
|
||||||
kStylisticAltOneOffSelector,
|
kStylisticAltOneOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss02,
|
features.ss02(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltTwoOnSelector,
|
kStylisticAltTwoOnSelector,
|
||||||
kStylisticAltTwoOffSelector,
|
kStylisticAltTwoOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss03,
|
features.ss03(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltThreeOnSelector,
|
kStylisticAltThreeOnSelector,
|
||||||
kStylisticAltThreeOffSelector,
|
kStylisticAltThreeOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss04,
|
features.ss04(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltFourOnSelector,
|
kStylisticAltFourOnSelector,
|
||||||
kStylisticAltFourOffSelector,
|
kStylisticAltFourOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss05,
|
features.ss05(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltFiveOnSelector,
|
kStylisticAltFiveOnSelector,
|
||||||
kStylisticAltFiveOffSelector,
|
kStylisticAltFiveOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss06,
|
features.ss06(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltSixOnSelector,
|
kStylisticAltSixOnSelector,
|
||||||
kStylisticAltSixOffSelector,
|
kStylisticAltSixOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss07,
|
features.ss07(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltSevenOnSelector,
|
kStylisticAltSevenOnSelector,
|
||||||
kStylisticAltSevenOffSelector,
|
kStylisticAltSevenOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss08,
|
features.ss08(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltEightOnSelector,
|
kStylisticAltEightOnSelector,
|
||||||
kStylisticAltEightOffSelector,
|
kStylisticAltEightOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss09,
|
features.ss09(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltNineOnSelector,
|
kStylisticAltNineOnSelector,
|
||||||
kStylisticAltNineOffSelector,
|
kStylisticAltNineOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss10,
|
features.ss10(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltTenOnSelector,
|
kStylisticAltTenOnSelector,
|
||||||
kStylisticAltTenOffSelector,
|
kStylisticAltTenOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss11,
|
features.ss11(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltElevenOnSelector,
|
kStylisticAltElevenOnSelector,
|
||||||
kStylisticAltElevenOffSelector,
|
kStylisticAltElevenOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss12,
|
features.ss12(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltTwelveOnSelector,
|
kStylisticAltTwelveOnSelector,
|
||||||
kStylisticAltTwelveOffSelector,
|
kStylisticAltTwelveOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss13,
|
features.ss13(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltThirteenOnSelector,
|
kStylisticAltThirteenOnSelector,
|
||||||
kStylisticAltThirteenOffSelector,
|
kStylisticAltThirteenOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss14,
|
features.ss14(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltFourteenOnSelector,
|
kStylisticAltFourteenOnSelector,
|
||||||
kStylisticAltFourteenOffSelector,
|
kStylisticAltFourteenOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss15,
|
features.ss15(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltFifteenOnSelector,
|
kStylisticAltFifteenOnSelector,
|
||||||
kStylisticAltFifteenOffSelector,
|
kStylisticAltFifteenOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss16,
|
features.ss16(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltSixteenOnSelector,
|
kStylisticAltSixteenOnSelector,
|
||||||
kStylisticAltSixteenOffSelector,
|
kStylisticAltSixteenOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss17,
|
features.ss17(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltSeventeenOnSelector,
|
kStylisticAltSeventeenOnSelector,
|
||||||
kStylisticAltSeventeenOffSelector,
|
kStylisticAltSeventeenOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss18,
|
features.ss18(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltEighteenOnSelector,
|
kStylisticAltEighteenOnSelector,
|
||||||
kStylisticAltEighteenOffSelector,
|
kStylisticAltEighteenOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss19,
|
features.ss19(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltNineteenOnSelector,
|
kStylisticAltNineteenOnSelector,
|
||||||
kStylisticAltNineteenOffSelector,
|
kStylisticAltNineteenOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.ss20,
|
features.ss20(),
|
||||||
kStylisticAlternativesType,
|
kStylisticAlternativesType,
|
||||||
kStylisticAltTwentyOnSelector,
|
kStylisticAltTwentyOnSelector,
|
||||||
kStylisticAltTwentyOffSelector,
|
kStylisticAltTwentyOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.subs,
|
features.subs(),
|
||||||
kVerticalPositionType,
|
kVerticalPositionType,
|
||||||
kInferiorsSelector,
|
kInferiorsSelector,
|
||||||
kNormalPositionSelector,
|
kNormalPositionSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.sups,
|
features.sups(),
|
||||||
kVerticalPositionType,
|
kVerticalPositionType,
|
||||||
kSuperiorsSelector,
|
kSuperiorsSelector,
|
||||||
kNormalPositionSelector,
|
kNormalPositionSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.swsh,
|
features.swsh(),
|
||||||
kContextualAlternatesType,
|
kContextualAlternatesType,
|
||||||
kSwashAlternatesOnSelector,
|
kSwashAlternatesOnSelector,
|
||||||
kSwashAlternatesOffSelector,
|
kSwashAlternatesOffSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.titl,
|
features.titl(),
|
||||||
kStyleOptionsType,
|
kStyleOptionsType,
|
||||||
kTitlingCapsSelector,
|
kTitlingCapsSelector,
|
||||||
kNoStyleOptionsSelector,
|
kNoStyleOptionsSelector,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.tnum,
|
features.tnum(),
|
||||||
kNumberSpacingType,
|
kNumberSpacingType,
|
||||||
kMonospacedNumbersSelector,
|
kMonospacedNumbersSelector,
|
||||||
4,
|
4,
|
||||||
);
|
);
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
font,
|
font,
|
||||||
features.zero,
|
features.zero(),
|
||||||
kTypographicExtrasType,
|
kTypographicExtrasType,
|
||||||
kSlashedZeroOnSelector,
|
kSlashedZeroOnSelector,
|
||||||
kSlashedZeroOffSelector,
|
kSlashedZeroOffSelector,
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use super::ns_string;
|
use super::ns_string;
|
||||||
use crate::{
|
use crate::{point, px, size, Bounds, Pixels, PlatformScreen, PlatformScreenHandle, ScreenId};
|
||||||
platform, point, px, size, Bounds, Pixels, PlatformScreen, PlatformScreenHandle, ScreenId,
|
|
||||||
};
|
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::NSScreen,
|
appkit::NSScreen,
|
||||||
base::{id, nil},
|
base::{id, nil},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, size, Bounds, FontFeatures, FontId, FontMetrics, FontStyle, FontWeight, Glyph,
|
platform::FontDescriptor, point, px, size, Bounds, FontFeatures, FontId, FontMetrics,
|
||||||
GlyphId, LineLayout, Pixels, PlatformTextSystem, Point, RasterizationOptions, Run, RunStyle,
|
FontStyle, FontWeight, Glyph, GlyphId, LineLayout, Pixels, PlatformTextSystem, Point,
|
||||||
Size,
|
RasterizationOptions, Result, Run, RunStyle, SharedString, Size,
|
||||||
};
|
};
|
||||||
use cocoa::appkit::{CGFloat, CGPoint};
|
use cocoa::appkit::{CGFloat, CGPoint};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
|
@ -31,6 +31,7 @@ use pathfinder_geometry::{
|
||||||
transform2d::Transform2F,
|
transform2d::Transform2F,
|
||||||
vector::{Vector2F, Vector2I},
|
vector::{Vector2F, Vector2I},
|
||||||
};
|
};
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::{cell::RefCell, char, cmp, convert::TryFrom, ffi::c_void, sync::Arc};
|
use std::{cell::RefCell, char, cmp, convert::TryFrom, ffi::c_void, sync::Arc};
|
||||||
|
|
||||||
use super::open_type;
|
use super::open_type;
|
||||||
|
@ -44,7 +45,9 @@ struct TextSystemState {
|
||||||
memory_source: MemSource,
|
memory_source: MemSource,
|
||||||
system_source: SystemSource,
|
system_source: SystemSource,
|
||||||
fonts: Vec<font_kit::font::Font>,
|
fonts: Vec<font_kit::font::Font>,
|
||||||
|
font_selections: HashMap<FontDescriptor, FontId>,
|
||||||
font_ids_by_postscript_name: HashMap<String, FontId>,
|
font_ids_by_postscript_name: HashMap<String, FontId>,
|
||||||
|
font_ids_by_family_name: HashMap<SharedString, SmallVec<[FontId; 4]>>,
|
||||||
postscript_names_by_font_id: HashMap<FontId, String>,
|
postscript_names_by_font_id: HashMap<FontId, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,8 +57,10 @@ impl MacTextSystem {
|
||||||
memory_source: MemSource::empty(),
|
memory_source: MemSource::empty(),
|
||||||
system_source: SystemSource::new(),
|
system_source: SystemSource::new(),
|
||||||
fonts: Vec::new(),
|
fonts: Vec::new(),
|
||||||
font_ids_by_postscript_name: Default::default(),
|
font_selections: HashMap::default(),
|
||||||
postscript_names_by_font_id: Default::default(),
|
font_ids_by_postscript_name: HashMap::default(),
|
||||||
|
font_ids_by_family_name: HashMap::default(),
|
||||||
|
postscript_names_by_font_id: HashMap::default(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,11 +72,11 @@ impl Default for MacTextSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlatformTextSystem for MacTextSystem {
|
impl PlatformTextSystem for MacTextSystem {
|
||||||
fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> anyhow::Result<()> {
|
fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> Result<()> {
|
||||||
self.0.write().add_fonts(fonts)
|
self.0.write().add_fonts(fonts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn all_families(&self) -> Vec<String> {
|
fn all_font_families(&self) -> Vec<String> {
|
||||||
self.0
|
self.0
|
||||||
.read()
|
.read()
|
||||||
.system_source
|
.system_source
|
||||||
|
@ -79,32 +84,49 @@ impl PlatformTextSystem for MacTextSystem {
|
||||||
.expect("core text should never return an error")
|
.expect("core text should never return an error")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_family(&self, name: &str, features: &FontFeatures) -> anyhow::Result<Vec<FontId>> {
|
fn select_font(&self, descriptor: FontDescriptor) -> Result<FontId> {
|
||||||
self.0.write().load_family(name, features)
|
let lock = self.0.upgradable_read();
|
||||||
}
|
if let Some(font_id) = lock.font_selections.get(&descriptor) {
|
||||||
|
Ok(*font_id)
|
||||||
|
} else {
|
||||||
|
let mut lock = parking_lot::RwLockUpgradableReadGuard::upgrade(lock);
|
||||||
|
let candidates =
|
||||||
|
if let Some(font_ids) = lock.font_ids_by_family_name.get(&descriptor.family) {
|
||||||
|
font_ids.as_slice()
|
||||||
|
} else {
|
||||||
|
let font_ids = lock.load_family(&descriptor.family, descriptor.features)?;
|
||||||
|
lock.font_ids_by_family_name
|
||||||
|
.insert(descriptor.family.clone(), font_ids);
|
||||||
|
lock.font_ids_by_family_name[&descriptor.family].as_ref()
|
||||||
|
};
|
||||||
|
|
||||||
fn select_font(
|
let candidate_properties = candidates
|
||||||
&self,
|
.iter()
|
||||||
font_ids: &[FontId],
|
.map(|font_id| lock.fonts[font_id.0].properties())
|
||||||
weight: FontWeight,
|
.collect::<SmallVec<[_; 4]>>();
|
||||||
style: FontStyle,
|
|
||||||
) -> anyhow::Result<FontId> {
|
let ix = font_kit::matching::find_best_match(
|
||||||
self.0.read().select_font(font_ids, weight, style)
|
&candidate_properties,
|
||||||
|
&font_kit::properties::Properties {
|
||||||
|
style: descriptor.style.into(),
|
||||||
|
weight: descriptor.weight.into(),
|
||||||
|
stretch: Default::default(),
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(candidates[ix])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn font_metrics(&self, font_id: FontId) -> FontMetrics {
|
fn font_metrics(&self, font_id: FontId) -> FontMetrics {
|
||||||
self.0.read().font_metrics(font_id)
|
self.0.read().font_metrics(font_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn typographic_bounds(
|
fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>> {
|
||||||
&self,
|
|
||||||
font_id: FontId,
|
|
||||||
glyph_id: GlyphId,
|
|
||||||
) -> anyhow::Result<Bounds<f32>> {
|
|
||||||
self.0.read().typographic_bounds(font_id, glyph_id)
|
self.0.read().typographic_bounds(font_id, glyph_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> anyhow::Result<Size<f32>> {
|
fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>> {
|
||||||
self.0.read().advance(font_id, glyph_id)
|
self.0.read().advance(font_id, glyph_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +169,7 @@ impl PlatformTextSystem for MacTextSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextSystemState {
|
impl TextSystemState {
|
||||||
fn add_fonts(&mut self, fonts: &[Arc<Vec<u8>>]) -> anyhow::Result<()> {
|
fn add_fonts(&mut self, fonts: &[Arc<Vec<u8>>]) -> Result<()> {
|
||||||
self.memory_source.add_fonts(
|
self.memory_source.add_fonts(
|
||||||
fonts
|
fonts
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -156,13 +178,16 @@ impl TextSystemState {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_family(&mut self, name: &str, features: &FontFeatures) -> anyhow::Result<Vec<FontId>> {
|
fn load_family(
|
||||||
let mut font_ids = Vec::new();
|
&mut self,
|
||||||
|
name: &SharedString,
|
||||||
|
features: FontFeatures,
|
||||||
|
) -> Result<SmallVec<[FontId; 4]>> {
|
||||||
|
let mut font_ids = SmallVec::new();
|
||||||
let family = self
|
let family = self
|
||||||
.memory_source
|
.memory_source
|
||||||
.select_family_by_name(name)
|
.select_family_by_name(name.as_ref())
|
||||||
.or_else(|_| self.system_source.select_family_by_name(name))?;
|
.or_else(|_| self.system_source.select_family_by_name(name.as_ref()))?;
|
||||||
for font in family.fonts() {
|
for font in family.fonts() {
|
||||||
let mut font = font.load()?;
|
let mut font = font.load()?;
|
||||||
open_type::apply_features(&mut font, features);
|
open_type::apply_features(&mut font, features);
|
||||||
|
@ -178,42 +203,53 @@ impl TextSystemState {
|
||||||
Ok(font_ids)
|
Ok(font_ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_font(
|
// fn select_font(
|
||||||
&self,
|
// &mut self,
|
||||||
font_ids: &[FontId],
|
// family: &SharedString,
|
||||||
weight: FontWeight,
|
// weight: FontWeight,
|
||||||
style: FontStyle,
|
// style: FontStyle,
|
||||||
) -> anyhow::Result<FontId> {
|
// features: FontFeatures,
|
||||||
let candidates = font_ids
|
// ) -> Result<FontId> {
|
||||||
.iter()
|
// let candidates = if let Some(font_ids) = self.font_ids_by_family_name.get(family) {
|
||||||
.map(|font_id| self.fonts[font_id.0].properties())
|
// font_ids
|
||||||
.collect::<Vec<_>>();
|
// } else {
|
||||||
let idx = font_kit::matching::find_best_match(
|
// let font_ids = if let Some(font_ids) = self.font_ids_by_family_name.get(family) {
|
||||||
&candidates,
|
// font_ids.as_slice()
|
||||||
&font_kit::properties::Properties {
|
// } else {
|
||||||
style: style.into(),
|
// self.font_ids_by_family_name
|
||||||
weight: weight.into(),
|
// .insert(family.clone())
|
||||||
stretch: Default::default(),
|
// .or_insert(font_ids).as_slice()
|
||||||
},
|
// };
|
||||||
)?;
|
|
||||||
Ok(font_ids[idx])
|
// };
|
||||||
}
|
|
||||||
|
// let font_properties = candidates
|
||||||
|
// .iter()
|
||||||
|
// .map(|font_id| self.fonts[font_id.0].properties())
|
||||||
|
// .collect::<SmallVec<[_; 4]>>();
|
||||||
|
|
||||||
|
// // let idx = font_kit::matching::find_best_match(
|
||||||
|
// // &candidates,
|
||||||
|
// // &font_kit::properties::Properties {
|
||||||
|
// // style: style.into(),
|
||||||
|
// // weight: weight.into(),
|
||||||
|
// // stretch: Default::default(),
|
||||||
|
// // },
|
||||||
|
// // )?;
|
||||||
|
// // Ok(font_ids[idx])
|
||||||
|
// }
|
||||||
|
|
||||||
fn font_metrics(&self, font_id: FontId) -> FontMetrics {
|
fn font_metrics(&self, font_id: FontId) -> FontMetrics {
|
||||||
self.fonts[font_id.0].metrics().into()
|
self.fonts[font_id.0].metrics().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn typographic_bounds(
|
fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>> {
|
||||||
&self,
|
|
||||||
font_id: FontId,
|
|
||||||
glyph_id: GlyphId,
|
|
||||||
) -> anyhow::Result<Bounds<f32>> {
|
|
||||||
Ok(self.fonts[font_id.0]
|
Ok(self.fonts[font_id.0]
|
||||||
.typographic_bounds(glyph_id.into())?
|
.typographic_bounds(glyph_id.into())?
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> anyhow::Result<Size<f32>> {
|
fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>> {
|
||||||
Ok(self.fonts[font_id.0].advance(glyph_id.into())?.into())
|
Ok(self.fonts[font_id.0].advance(glyph_id.into())?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,7 +695,7 @@ impl From<FontStyle> for FontkitStyle {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn test_glyph_offsets() -> anyhow::Result<()> {
|
// fn test_glyph_offsets() -> crate::Result<()> {
|
||||||
// let fonts = FontSystem::new();
|
// let fonts = FontSystem::new();
|
||||||
// let zapfino = fonts.load_family("Zapfino", &Default::default())?;
|
// let zapfino = fonts.load_family("Zapfino", &Default::default())?;
|
||||||
// let zapfino_regular = RunStyle {
|
// let zapfino_regular = RunStyle {
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
mod font_cache;
|
mod font_features;
|
||||||
mod line_wrapper;
|
mod line_wrapper;
|
||||||
mod text_layout_cache;
|
mod text_layout_cache;
|
||||||
|
|
||||||
pub use font_cache::*;
|
pub use font_features::*;
|
||||||
use line_wrapper::*;
|
use line_wrapper::*;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
|
||||||
pub use text_layout_cache::*;
|
pub use text_layout_cache::*;
|
||||||
|
|
||||||
use crate::{Hsla, Pixels, PlatformTextSystem, Point, Result, Size, UnderlineStyle};
|
use crate::{Hsla, Pixels, PlatformTextSystem, Point, Result, Size, UnderlineStyle};
|
||||||
|
@ -19,8 +17,13 @@ use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
|
pub struct FontId(pub usize);
|
||||||
|
|
||||||
|
#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
|
pub struct FontFamilyId(pub usize);
|
||||||
|
|
||||||
pub struct TextSystem {
|
pub struct TextSystem {
|
||||||
font_cache: Arc<FontCache>,
|
|
||||||
text_layout_cache: Arc<TextLayoutCache>,
|
text_layout_cache: Arc<TextLayoutCache>,
|
||||||
platform_text_system: Arc<dyn PlatformTextSystem>,
|
platform_text_system: Arc<dyn PlatformTextSystem>,
|
||||||
wrapper_pool: Mutex<HashMap<(FontId, Pixels), Vec<LineWrapper>>>,
|
wrapper_pool: Mutex<HashMap<(FontId, Pixels), Vec<LineWrapper>>>,
|
||||||
|
@ -29,7 +32,7 @@ pub struct TextSystem {
|
||||||
impl TextSystem {
|
impl TextSystem {
|
||||||
pub fn new(platform_text_system: Arc<dyn PlatformTextSystem>) -> Self {
|
pub fn new(platform_text_system: Arc<dyn PlatformTextSystem>) -> Self {
|
||||||
TextSystem {
|
TextSystem {
|
||||||
font_cache: Arc::new(FontCache::new(platform_text_system.clone())),
|
// font_cache: Arc::new(FontCache::new(platform_text_system.clone())),
|
||||||
text_layout_cache: Arc::new(TextLayoutCache::new(platform_text_system.clone())),
|
text_layout_cache: Arc::new(TextLayoutCache::new(platform_text_system.clone())),
|
||||||
platform_text_system,
|
platform_text_system,
|
||||||
wrapper_pool: Mutex::new(HashMap::default()),
|
wrapper_pool: Mutex::new(HashMap::default()),
|
||||||
|
@ -37,7 +40,8 @@ impl TextSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn font_family_name(&self, family_id: FontFamilyId) -> Result<Arc<str>> {
|
pub fn font_family_name(&self, family_id: FontFamilyId) -> Result<Arc<str>> {
|
||||||
self.font_cache.family_name(family_id)
|
todo!()
|
||||||
|
// self.font_cache.family_name(family_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_font_family(
|
pub fn load_font_family(
|
||||||
|
@ -45,16 +49,19 @@ impl TextSystem {
|
||||||
names: &[&str],
|
names: &[&str],
|
||||||
features: &FontFeatures,
|
features: &FontFeatures,
|
||||||
) -> Result<FontFamilyId> {
|
) -> Result<FontFamilyId> {
|
||||||
self.font_cache.load_family(names, features)
|
todo!()
|
||||||
|
// self.font_cache.load_family(names, features)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an arbitrary font family that is available on the system.
|
/// Returns an arbitrary font family that is available on the system.
|
||||||
pub fn known_existing_font_family(&self) -> FontFamilyId {
|
pub fn known_existing_font_family(&self) -> FontFamilyId {
|
||||||
self.font_cache.known_existing_family()
|
todo!()
|
||||||
|
// self.font_cache.known_existing_family()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_font(&self, family_id: FontFamilyId) -> FontId {
|
pub fn default_font(&self, family_id: FontFamilyId) -> FontId {
|
||||||
self.font_cache.default_font(family_id)
|
todo!()
|
||||||
|
// self.font_cache.default_font(family_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_font(
|
pub fn select_font(
|
||||||
|
@ -63,55 +70,67 @@ impl TextSystem {
|
||||||
weight: FontWeight,
|
weight: FontWeight,
|
||||||
style: FontStyle,
|
style: FontStyle,
|
||||||
) -> Result<FontId> {
|
) -> Result<FontId> {
|
||||||
self.font_cache.select_font(family_id, weight, style)
|
todo!()
|
||||||
|
// self.font_cache.select_font(family_id, weight, style)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_font_metric<F, T>(&self, font_id: FontId, f: F) -> T
|
// pub fn read_font_metric<F, T>(&self, font_id: FontId, f: F) -> T
|
||||||
where
|
// where
|
||||||
F: FnOnce(&FontMetrics) -> T,
|
// F: FnOnce(&FontMetrics) -> T,
|
||||||
T: 'static,
|
// T: 'static,
|
||||||
{
|
// {
|
||||||
self.font_cache.read_metric(font_id, f)
|
// todo!()
|
||||||
}
|
// // self.font_cache.read_metric(font_id, f)
|
||||||
|
// }
|
||||||
|
|
||||||
pub fn bounding_box(&self, font_id: FontId, font_size: Pixels) -> Size<Pixels> {
|
pub fn bounding_box(&self, font_id: FontId, font_size: Pixels) -> Size<Pixels> {
|
||||||
self.font_cache.bounding_box(font_id, font_size)
|
todo!()
|
||||||
|
// self.font_cache.bounding_box(font_id, font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn em_width(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
pub fn em_width(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
||||||
self.font_cache.em_width(font_id, font_size)
|
todo!()
|
||||||
|
// self.font_cache.em_width(font_id, font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn em_advance(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
pub fn em_advance(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
||||||
self.font_cache.em_advance(font_id, font_size)
|
todo!()
|
||||||
|
// self.font_cache.em_advance(font_id, font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn line_height(&self, font_size: Pixels) -> Pixels {
|
pub fn line_height(&self, font_size: Pixels) -> Pixels {
|
||||||
self.font_cache.line_height(font_size)
|
todo!()
|
||||||
|
// self.font_cache.line_height(font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cap_height(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
pub fn cap_height(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
||||||
self.font_cache.cap_height(font_id, font_size)
|
todo!()
|
||||||
|
// self.font_cache.cap_height(font_id, font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn x_height(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
pub fn x_height(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
||||||
self.font_cache.x_height(font_id, font_size)
|
todo!()
|
||||||
|
// self.font_cache.x_height(font_id, font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ascent(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
pub fn ascent(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
||||||
self.font_cache.ascent(font_id, font_size)
|
todo!()
|
||||||
|
// self.font_cache.ascent(font_id, font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn descent(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
pub fn descent(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
||||||
self.font_cache.descent(font_id, font_size)
|
todo!()
|
||||||
|
// self.font_cache.descent(font_id, font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn em_size(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
pub fn em_size(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
||||||
self.font_cache.em_size(font_id, font_size)
|
todo!()
|
||||||
|
// self.font_cache.em_size(font_id, font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn baseline_offset(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
pub fn baseline_offset(&self, font_id: FontId, font_size: Pixels) -> Pixels {
|
||||||
self.font_cache.baseline_offset(font_id, font_size)
|
todo!()
|
||||||
|
// self.font_cache.baseline_offset(font_id, font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout_str<'a>(
|
pub fn layout_str<'a>(
|
||||||
|
@ -235,44 +254,6 @@ impl Display for FontStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct FontFeatures {
|
|
||||||
pub calt: Option<bool>,
|
|
||||||
pub case: Option<bool>,
|
|
||||||
pub cpsp: Option<bool>,
|
|
||||||
pub frac: Option<bool>,
|
|
||||||
pub liga: Option<bool>,
|
|
||||||
pub onum: Option<bool>,
|
|
||||||
pub ordn: Option<bool>,
|
|
||||||
pub pnum: Option<bool>,
|
|
||||||
pub ss01: Option<bool>,
|
|
||||||
pub ss02: Option<bool>,
|
|
||||||
pub ss03: Option<bool>,
|
|
||||||
pub ss04: Option<bool>,
|
|
||||||
pub ss05: Option<bool>,
|
|
||||||
pub ss06: Option<bool>,
|
|
||||||
pub ss07: Option<bool>,
|
|
||||||
pub ss08: Option<bool>,
|
|
||||||
pub ss09: Option<bool>,
|
|
||||||
pub ss10: Option<bool>,
|
|
||||||
pub ss11: Option<bool>,
|
|
||||||
pub ss12: Option<bool>,
|
|
||||||
pub ss13: Option<bool>,
|
|
||||||
pub ss14: Option<bool>,
|
|
||||||
pub ss15: Option<bool>,
|
|
||||||
pub ss16: Option<bool>,
|
|
||||||
pub ss17: Option<bool>,
|
|
||||||
pub ss18: Option<bool>,
|
|
||||||
pub ss19: Option<bool>,
|
|
||||||
pub ss20: Option<bool>,
|
|
||||||
pub subs: Option<bool>,
|
|
||||||
pub sups: Option<bool>,
|
|
||||||
pub swsh: Option<bool>,
|
|
||||||
pub titl: Option<bool>,
|
|
||||||
pub tnum: Option<bool>,
|
|
||||||
pub zero: Option<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct RunStyle {
|
pub struct RunStyle {
|
||||||
pub color: Hsla,
|
pub color: Hsla,
|
||||||
|
|
162
crates/gpui3/src/text_system/font_features.rs
Normal file
162
crates/gpui3/src/text_system/font_features.rs
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
use schemars::{
|
||||||
|
schema::{InstanceType, Schema, SchemaObject, SingleOrVec},
|
||||||
|
JsonSchema,
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! create_definitions {
|
||||||
|
($($(#[$meta:meta])* ($name:ident, $idx:expr)),* $(,)?) => {
|
||||||
|
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub struct FontFeatures {
|
||||||
|
enabled: u64,
|
||||||
|
disabled: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontFeatures {
|
||||||
|
$(
|
||||||
|
pub fn $name(&self) -> Option<bool> {
|
||||||
|
if (self.enabled & (1 << $idx)) != 0 {
|
||||||
|
Some(true)
|
||||||
|
} else if (self.disabled & (1 << $idx)) != 0 {
|
||||||
|
Some(false)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for FontFeatures {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let mut debug = f.debug_struct("FontFeatures");
|
||||||
|
$(
|
||||||
|
if let Some(value) = self.$name() {
|
||||||
|
debug.field(stringify!($name), &value);
|
||||||
|
};
|
||||||
|
)*
|
||||||
|
debug.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> serde::Deserialize<'de> for FontFeatures {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
use serde::de::{MapAccess, Visitor};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
struct FontFeaturesVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for FontFeaturesVisitor {
|
||||||
|
type Value = FontFeatures;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("a map of font features")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||||
|
where
|
||||||
|
M: MapAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut enabled: u64 = 0;
|
||||||
|
let mut disabled: u64 = 0;
|
||||||
|
|
||||||
|
while let Some((key, value)) = access.next_entry::<String, Option<bool>>()? {
|
||||||
|
let idx = match key.as_str() {
|
||||||
|
$(stringify!($name) => $idx,)*
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
match value {
|
||||||
|
Some(true) => enabled |= 1 << idx,
|
||||||
|
Some(false) => disabled |= 1 << idx,
|
||||||
|
None => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(FontFeatures { enabled, disabled })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let features = deserializer.deserialize_map(FontFeaturesVisitor)?;
|
||||||
|
Ok(features)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl serde::Serialize for FontFeatures {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
use serde::ser::SerializeMap;
|
||||||
|
|
||||||
|
let mut map = serializer.serialize_map(None)?;
|
||||||
|
|
||||||
|
$(
|
||||||
|
let feature = stringify!($name);
|
||||||
|
if let Some(value) = self.$name() {
|
||||||
|
map.serialize_entry(feature, &value)?;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
map.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JsonSchema for FontFeatures {
|
||||||
|
fn schema_name() -> String {
|
||||||
|
"FontFeatures".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> Schema {
|
||||||
|
let mut schema = SchemaObject::default();
|
||||||
|
let properties = &mut schema.object().properties;
|
||||||
|
let feature_schema = Schema::Object(SchemaObject {
|
||||||
|
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Boolean))),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
$(
|
||||||
|
properties.insert(stringify!($name).to_owned(), feature_schema.clone());
|
||||||
|
)*
|
||||||
|
|
||||||
|
schema.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
create_definitions!(
|
||||||
|
(calt, 0),
|
||||||
|
(case, 1),
|
||||||
|
(cpsp, 2),
|
||||||
|
(frac, 3),
|
||||||
|
(liga, 4),
|
||||||
|
(onum, 5),
|
||||||
|
(ordn, 6),
|
||||||
|
(pnum, 7),
|
||||||
|
(ss01, 8),
|
||||||
|
(ss02, 9),
|
||||||
|
(ss03, 10),
|
||||||
|
(ss04, 11),
|
||||||
|
(ss05, 12),
|
||||||
|
(ss06, 13),
|
||||||
|
(ss07, 14),
|
||||||
|
(ss08, 15),
|
||||||
|
(ss09, 16),
|
||||||
|
(ss10, 17),
|
||||||
|
(ss11, 18),
|
||||||
|
(ss12, 19),
|
||||||
|
(ss13, 20),
|
||||||
|
(ss14, 21),
|
||||||
|
(ss15, 22),
|
||||||
|
(ss16, 23),
|
||||||
|
(ss17, 24),
|
||||||
|
(ss18, 25),
|
||||||
|
(ss19, 26),
|
||||||
|
(ss20, 27),
|
||||||
|
(subs, 28),
|
||||||
|
(sups, 29),
|
||||||
|
(swsh, 30),
|
||||||
|
(titl, 31),
|
||||||
|
(tnum, 32),
|
||||||
|
(zero, 33)
|
||||||
|
);
|
|
@ -215,7 +215,7 @@ impl Boundary {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{App, FontWeight};
|
use crate::{App, FontFeatures, FontWeight};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrap_line() {
|
fn test_wrap_line() {
|
||||||
|
@ -291,7 +291,7 @@ mod tests {
|
||||||
let text_system = cx.text_system().clone();
|
let text_system = cx.text_system().clone();
|
||||||
|
|
||||||
let family = text_system
|
let family = text_system
|
||||||
.load_font_family(&["Helvetica"], &Default::default())
|
.load_font_family(&["Helvetica"], &FontFeatures::default())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let font_id = text_system
|
let font_id = text_system
|
||||||
.select_font(family, Default::default(), Default::default())
|
.select_font(family, Default::default(), Default::default())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue