|
|
@ -12,8 +12,6 @@ use unicode_segmentation::UnicodeSegmentation;
|
|
|
|
use super::font_loader::*;
|
|
|
|
use super::font_loader::*;
|
|
|
|
use super::font_options::*;
|
|
|
|
use super::font_options::*;
|
|
|
|
|
|
|
|
|
|
|
|
const DEFAULT_FONT_SIZE: f32 = 14.0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(new, Clone, Hash, PartialEq, Eq, Debug)]
|
|
|
|
#[derive(new, Clone, Hash, PartialEq, Eq, Debug)]
|
|
|
|
struct ShapeKey {
|
|
|
|
struct ShapeKey {
|
|
|
|
pub cells: Vec<String>,
|
|
|
|
pub cells: Vec<String>,
|
|
|
@ -22,7 +20,7 @@ struct ShapeKey {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct CachingShaper {
|
|
|
|
pub struct CachingShaper {
|
|
|
|
pub options: Option<FontOptions>,
|
|
|
|
options: FontOptions,
|
|
|
|
font_loader: FontLoader,
|
|
|
|
font_loader: FontLoader,
|
|
|
|
blob_cache: LruCache<ShapeKey, Vec<TextBlob>>,
|
|
|
|
blob_cache: LruCache<ShapeKey, Vec<TextBlob>>,
|
|
|
|
shape_context: ShapeContext,
|
|
|
|
shape_context: ShapeContext,
|
|
|
@ -30,11 +28,12 @@ pub struct CachingShaper {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl CachingShaper {
|
|
|
|
impl CachingShaper {
|
|
|
|
pub fn new(device_scale_factor: f32) -> CachingShaper {
|
|
|
|
pub fn new(scale_factor: f32) -> CachingShaper {
|
|
|
|
let scale_factor = points_to_pixels(device_scale_factor);
|
|
|
|
let options = FontOptions::default();
|
|
|
|
|
|
|
|
let font_size = options.size * scale_factor;
|
|
|
|
CachingShaper {
|
|
|
|
CachingShaper {
|
|
|
|
options: None,
|
|
|
|
options,
|
|
|
|
font_loader: FontLoader::new(DEFAULT_FONT_SIZE * scale_factor),
|
|
|
|
font_loader: FontLoader::new(font_size),
|
|
|
|
blob_cache: LruCache::new(10000),
|
|
|
|
blob_cache: LruCache::new(10000),
|
|
|
|
shape_context: ShapeContext::new(),
|
|
|
|
shape_context: ShapeContext::new(),
|
|
|
|
scale_factor,
|
|
|
|
scale_factor,
|
|
|
@ -42,21 +41,8 @@ impl CachingShaper {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn current_font_pair(&mut self) -> Arc<FontPair> {
|
|
|
|
fn current_font_pair(&mut self) -> Arc<FontPair> {
|
|
|
|
let default_key = FontKey {
|
|
|
|
let default_key = FontKey::default();
|
|
|
|
italic: false,
|
|
|
|
let font_key = FontKey::from(&self.options);
|
|
|
|
bold: false,
|
|
|
|
|
|
|
|
font_selection: FontSelection::Default,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let font_key = self
|
|
|
|
|
|
|
|
.options
|
|
|
|
|
|
|
|
.as_ref()
|
|
|
|
|
|
|
|
.map(|options| FontKey {
|
|
|
|
|
|
|
|
italic: options.italic,
|
|
|
|
|
|
|
|
bold: options.bold,
|
|
|
|
|
|
|
|
font_selection: options.fallback_list.first().unwrap().clone().into(),
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.unwrap_or_else(|| default_key.clone());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(font_pair) = self.font_loader.get_or_load(&font_key) {
|
|
|
|
if let Some(font_pair) = self.font_loader.get_or_load(&font_key) {
|
|
|
|
return font_pair;
|
|
|
|
return font_pair;
|
|
|
@ -68,26 +54,28 @@ impl CachingShaper {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn current_size(&self) -> f32 {
|
|
|
|
pub fn current_size(&self) -> f32 {
|
|
|
|
self.options
|
|
|
|
self.options.size * self.scale_factor
|
|
|
|
.as_ref()
|
|
|
|
|
|
|
|
.map(|options| options.size)
|
|
|
|
|
|
|
|
.unwrap_or(DEFAULT_FONT_SIZE)
|
|
|
|
|
|
|
|
* self.scale_factor
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn update_font(&mut self, guifont_setting: &str) -> bool {
|
|
|
|
pub fn update_scale_factor(&mut self, scale_factor: f32) {
|
|
|
|
let new_options = FontOptions::parse(guifont_setting, DEFAULT_FONT_SIZE);
|
|
|
|
trace!("scale_factor changed: {:.2}", scale_factor);
|
|
|
|
|
|
|
|
self.scale_factor = scale_factor;
|
|
|
|
|
|
|
|
self.reset_font_loader();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if new_options != self.options && new_options.is_some() {
|
|
|
|
pub fn update_font(&mut self, guifont_setting: &str) {
|
|
|
|
self.font_loader =
|
|
|
|
trace!("Updating font: {}", guifont_setting);
|
|
|
|
FontLoader::new(new_options.as_ref().unwrap().size * self.scale_factor);
|
|
|
|
|
|
|
|
self.blob_cache.clear();
|
|
|
|
|
|
|
|
self.options = new_options;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
true
|
|
|
|
self.options = FontOptions::parse(guifont_setting);
|
|
|
|
} else {
|
|
|
|
self.reset_font_loader();
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn reset_font_loader(&mut self) {
|
|
|
|
|
|
|
|
let font_size = self.options.size * self.scale_factor;
|
|
|
|
|
|
|
|
trace!("Using font_size: {:.2}px", font_size);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.font_loader = FontLoader::new(font_size);
|
|
|
|
|
|
|
|
self.blob_cache.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn metrics(&mut self) -> Metrics {
|
|
|
|
fn metrics(&mut self) -> Metrics {
|
|
|
@ -156,44 +144,26 @@ impl CachingShaper {
|
|
|
|
// Create font fallback list
|
|
|
|
// Create font fallback list
|
|
|
|
let mut font_fallback_keys = Vec::new();
|
|
|
|
let mut font_fallback_keys = Vec::new();
|
|
|
|
|
|
|
|
|
|
|
|
// Add guifont fallback list
|
|
|
|
// Add parsed fonts from guifont
|
|
|
|
if let Some(options) = &self.options {
|
|
|
|
font_fallback_keys.extend(self.options.font_list.iter().map(|font_name| FontKey {
|
|
|
|
font_fallback_keys.extend(options.fallback_list.iter().map(|font_name| FontKey {
|
|
|
|
italic: self.options.italic || italic,
|
|
|
|
italic: options.italic || italic,
|
|
|
|
bold: self.options.bold || bold,
|
|
|
|
bold: options.bold || bold,
|
|
|
|
font_selection: font_name.into(),
|
|
|
|
font_selection: font_name.into(),
|
|
|
|
}));
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
// Add default font
|
|
|
|
// Add default font
|
|
|
|
font_fallback_keys.push(FontKey {
|
|
|
|
font_fallback_keys.push(FontKey {
|
|
|
|
italic: self.options.italic || italic,
|
|
|
|
italic: options.italic || italic,
|
|
|
|
bold: self.options.bold || bold,
|
|
|
|
bold: options.bold || bold,
|
|
|
|
font_selection: FontSelection::Default,
|
|
|
|
font_selection: FontSelection::Default,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Add skia fallback
|
|
|
|
// Add skia fallback
|
|
|
|
font_fallback_keys.push(FontKey {
|
|
|
|
font_fallback_keys.push(FontKey {
|
|
|
|
italic,
|
|
|
|
italic: options.italic || italic,
|
|
|
|
bold,
|
|
|
|
bold: options.bold || bold,
|
|
|
|
font_selection: cluster.chars()[0].ch.into(),
|
|
|
|
font_selection: cluster.chars()[0].ch.into(),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// No confgured option. Default to not italic and not bold versions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add default font
|
|
|
|
|
|
|
|
font_fallback_keys.push(FontKey {
|
|
|
|
|
|
|
|
italic,
|
|
|
|
|
|
|
|
bold,
|
|
|
|
|
|
|
|
font_selection: FontSelection::Default,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add skia fallback
|
|
|
|
|
|
|
|
font_fallback_keys.push(FontKey {
|
|
|
|
|
|
|
|
italic,
|
|
|
|
|
|
|
|
bold,
|
|
|
|
|
|
|
|
font_selection: cluster.chars()[0].ch.into(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add last resort
|
|
|
|
// Add last resort
|
|
|
|
font_fallback_keys.push(FontKey {
|
|
|
|
font_fallback_keys.push(FontKey {
|
|
|
@ -312,25 +282,3 @@ impl CachingShaper {
|
|
|
|
self.blob_cache.get(&key).unwrap()
|
|
|
|
self.blob_cache.get(&key).unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn points_to_pixels(value: f32) -> f32 {
|
|
|
|
|
|
|
|
// Fonts in neovim are using points, not pixels.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Skia docs is incorrectly stating it uses points, but uses pixels:
|
|
|
|
|
|
|
|
// https://api.skia.org/classSkFont.html#a7e28a156a517d01bc608c14c761346bf
|
|
|
|
|
|
|
|
// https://github.com/mono/SkiaSharp/issues/1147#issuecomment-587421201
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// So, we need to convert points to pixels.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// In reality, this depends on DPI/PPI of monitor, but here we only care about converting
|
|
|
|
|
|
|
|
// from points to pixels, so this is standard constant values.
|
|
|
|
|
|
|
|
let pixels_per_inch = 96.0;
|
|
|
|
|
|
|
|
let points_per_inch = 72.0;
|
|
|
|
|
|
|
|
// On macos points == pixels
|
|
|
|
|
|
|
|
#[cfg(target_os = "macos")]
|
|
|
|
|
|
|
|
let points_per_inch = 96.0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let pixels_per_point = pixels_per_inch / points_per_inch;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
value * pixels_per_point
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|