forked from NotAShelf/beer
Config: Add italic and bold fonts
This commit is contained in:
parent
cadefd387b
commit
227ed8d30c
4 changed files with 189 additions and 34 deletions
|
|
@ -144,6 +144,10 @@ pub struct Colors {
|
||||||
pub struct Main {
|
pub struct Main {
|
||||||
/// Primary font family, resolved via fontconfig.
|
/// Primary font family, resolved via fontconfig.
|
||||||
pub font: String,
|
pub font: String,
|
||||||
|
/// Bold font family, resolved via fontconfig.
|
||||||
|
pub font_bold: Option<String>,
|
||||||
|
/// Italic font family, resolved via fontconfig.
|
||||||
|
pub font_italic: Option<String>,
|
||||||
/// Font size in pixels.
|
/// Font size in pixels.
|
||||||
pub font_size: u32,
|
pub font_size: u32,
|
||||||
/// `TERM` value exported to the child shell.
|
/// `TERM` value exported to the child shell.
|
||||||
|
|
@ -166,6 +170,8 @@ impl Default for Main {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
font: "monospace".to_string(),
|
font: "monospace".to_string(),
|
||||||
|
font_italic: None,
|
||||||
|
font_bold: None,
|
||||||
font_size: 16,
|
font_size: 16,
|
||||||
term: "beer".to_string(),
|
term: "beer".to_string(),
|
||||||
initial_cols: 80,
|
initial_cols: 80,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ use fontconfig::{CharSet, Fontconfig, Pattern};
|
||||||
use freetype::bitmap::PixelMode;
|
use freetype::bitmap::PixelMode;
|
||||||
use freetype::face::{LoadFlag, StyleFlag};
|
use freetype::face::{LoadFlag, StyleFlag};
|
||||||
use freetype::{Face, Library, Matrix, Vector};
|
use freetype::{Face, Library, Matrix, Vector};
|
||||||
use harfbuzz_rs_now as harfbuzz;
|
use harfbuzz_rs_now::{self as harfbuzz};
|
||||||
use lru::LruCache;
|
use lru::LruCache;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
|
@ -128,11 +128,15 @@ struct FaceEntry {
|
||||||
pub struct Fonts {
|
pub struct Fonts {
|
||||||
library: Library,
|
library: Library,
|
||||||
fontconfig: Fontconfig,
|
fontconfig: Fontconfig,
|
||||||
family: String,
|
primary_family: String,
|
||||||
|
italic_family: Option<String>,
|
||||||
|
bold_family: Option<String>,
|
||||||
size_px: u32,
|
size_px: u32,
|
||||||
metrics: CellMetrics,
|
metrics: CellMetrics,
|
||||||
/// All loaded faces; indices into this vector are stable.
|
/// All loaded faces; indices into this vector are stable.
|
||||||
faces: Vec<FaceEntry>,
|
primary_faces: Vec<FaceEntry>,
|
||||||
|
italic_faces: Option<Vec<FaceEntry>>,
|
||||||
|
bold_faces: Option<Vec<FaceEntry>>,
|
||||||
/// Index of each style variant, by [`Style::index`]; filled on demand.
|
/// Index of each style variant, by [`Style::index`]; filled on demand.
|
||||||
styled: [Option<usize>; 4],
|
styled: [Option<usize>; 4],
|
||||||
/// Fallback faces resolved by coverage, deduplicated by file path.
|
/// Fallback faces resolved by coverage, deduplicated by file path.
|
||||||
|
|
@ -145,13 +149,30 @@ pub struct Fonts {
|
||||||
shape_cache: LruCache<(Box<str>, usize), Option<ShapedCluster>>,
|
shape_cache: LruCache<(Box<str>, usize), Option<ShapedCluster>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct FontStyles {
|
||||||
|
primary: String,
|
||||||
|
italics: Option<String>,
|
||||||
|
bold: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontStyles {
|
||||||
|
pub fn all(regular: impl Into<String>, italics: Option<String>, bold: Option<String>) -> Self {
|
||||||
|
FontStyles {
|
||||||
|
primary: regular.into(),
|
||||||
|
italics,
|
||||||
|
bold,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Fonts {
|
impl fmt::Debug for Fonts {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("Fonts")
|
f.debug_struct("Fonts")
|
||||||
.field("family", &self.family)
|
.field("family", &self.primary_family)
|
||||||
.field("size_px", &self.size_px)
|
.field("size_px", &self.size_px)
|
||||||
.field("metrics", &self.metrics)
|
.field("metrics", &self.metrics)
|
||||||
.field("faces", &self.faces.len())
|
.field("faces", &self.primary_faces.len())
|
||||||
.field("cached", &self.cache.len())
|
.field("cached", &self.cache.len())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
|
|
@ -159,21 +180,71 @@ impl fmt::Debug for Fonts {
|
||||||
|
|
||||||
impl Fonts {
|
impl Fonts {
|
||||||
/// Resolve `family` at `size_px` and compute the cell metrics.
|
/// Resolve `family` at `size_px` and compute the cell metrics.
|
||||||
pub fn new(family: &str, size_px: u32) -> Result<Self, FontError> {
|
pub fn new(family: FontStyles, size_px: u32) -> Result<Self, FontError> {
|
||||||
let library = Library::init()?;
|
let library = Library::init()?;
|
||||||
let fontconfig = Fontconfig::new().ok_or(FontError::FontconfigInit)?;
|
let fontconfig = Fontconfig::new().ok_or(FontError::FontconfigInit)?;
|
||||||
|
|
||||||
let regular = resolve_face(&library, &fontconfig, family, Style::default(), size_px)?;
|
let regular = resolve_face(
|
||||||
let metrics = cell_metrics(®ular.face, family)?;
|
&library,
|
||||||
|
&fontconfig,
|
||||||
|
&family.primary,
|
||||||
|
Style::default(),
|
||||||
|
size_px,
|
||||||
|
)?;
|
||||||
|
let italic = family
|
||||||
|
.italics
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|i| {
|
||||||
|
Some(
|
||||||
|
resolve_face(
|
||||||
|
&library,
|
||||||
|
&fontconfig,
|
||||||
|
&i,
|
||||||
|
Style {
|
||||||
|
italic: true,
|
||||||
|
bold: false,
|
||||||
|
},
|
||||||
|
size_px,
|
||||||
|
)
|
||||||
|
.ok(),
|
||||||
|
)
|
||||||
|
.flatten()
|
||||||
|
})
|
||||||
|
.map(|x| vec![x]);
|
||||||
|
let bold = family
|
||||||
|
.bold
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|b| {
|
||||||
|
Some(
|
||||||
|
resolve_face(
|
||||||
|
&library,
|
||||||
|
&fontconfig,
|
||||||
|
&b,
|
||||||
|
Style {
|
||||||
|
bold: true,
|
||||||
|
italic: false,
|
||||||
|
},
|
||||||
|
size_px,
|
||||||
|
)
|
||||||
|
.ok(),
|
||||||
|
)
|
||||||
|
.flatten()
|
||||||
|
})
|
||||||
|
.map(|x| vec![x]);
|
||||||
|
let metrics = cell_metrics(®ular.face, &family.primary)?;
|
||||||
|
|
||||||
let cap = |n| NonZeroUsize::new(n).expect("cache cap is nonzero");
|
let cap = |n| NonZeroUsize::new(n).expect("cache cap is nonzero");
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
library,
|
library,
|
||||||
fontconfig,
|
fontconfig,
|
||||||
family: family.to_owned(),
|
primary_family: family.primary.to_owned(),
|
||||||
|
bold_family: family.bold.and_then(|i| Some(i.to_owned())),
|
||||||
|
italic_family: family.italics.and_then(|i| Some(i.to_owned())),
|
||||||
|
bold_faces: bold,
|
||||||
|
italic_faces: italic,
|
||||||
size_px,
|
size_px,
|
||||||
metrics,
|
metrics,
|
||||||
faces: vec![regular],
|
primary_faces: vec![regular],
|
||||||
styled: [Some(0), None, None, None],
|
styled: [Some(0), None, None, None],
|
||||||
fallbacks: HashMap::new(),
|
fallbacks: HashMap::new(),
|
||||||
cache: LruCache::new(cap(GLYPH_CACHE_CAP)),
|
cache: LruCache::new(cap(GLYPH_CACHE_CAP)),
|
||||||
|
|
@ -186,13 +257,28 @@ impl Fonts {
|
||||||
self.metrics
|
self.metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_face(&self, face_idx: usize, style: Style) -> &FaceEntry {
|
||||||
|
match style {
|
||||||
|
Style { italic: true, .. } => {
|
||||||
|
&self.italic_faces.as_ref().unwrap_or(&self.primary_faces)[face_idx]
|
||||||
|
}
|
||||||
|
Style { bold: true, .. } => {
|
||||||
|
&self.bold_faces.as_ref().unwrap_or(&self.primary_faces)[face_idx]
|
||||||
|
}
|
||||||
|
Style {
|
||||||
|
bold: false,
|
||||||
|
italic: false,
|
||||||
|
} => &self.primary_faces[face_idx],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the rasterized glyph for `c` in `style`, rasterizing and caching
|
/// Return the rasterized glyph for `c` in `style`, rasterizing and caching
|
||||||
/// it on first use.
|
/// it on first use.
|
||||||
pub fn glyph(&mut self, c: char, style: Style) -> Result<&Glyph, FontError> {
|
pub fn glyph(&mut self, c: char, style: Style) -> Result<&Glyph, FontError> {
|
||||||
let key = (c, style.index());
|
let key = (c, style.index());
|
||||||
if self.cache.get(&key).is_none() {
|
if self.cache.get(&key).is_none() {
|
||||||
let idx = self.face_for(c, style)?;
|
let idx = self.face_for(c, style)?;
|
||||||
let face = &self.faces[idx].face;
|
let face = &self.get_face(idx, style).face;
|
||||||
// Synthesize bold/italic only when the resolved face lacks the real
|
// Synthesize bold/italic only when the resolved face lacks the real
|
||||||
// variant (most monospace families ship both).
|
// variant (most monospace families ship both).
|
||||||
let (synth_bold, synth_italic) = synth_flags(face, style);
|
let (synth_bold, synth_italic) = synth_flags(face, style);
|
||||||
|
|
@ -213,7 +299,7 @@ impl Fonts {
|
||||||
) -> Result<&Glyph, FontError> {
|
) -> Result<&Glyph, FontError> {
|
||||||
let key = (gid, face_idx, style.index());
|
let key = (gid, face_idx, style.index());
|
||||||
if self.gcache.get(&key).is_none() {
|
if self.gcache.get(&key).is_none() {
|
||||||
let face = &self.faces[face_idx].face;
|
let face = &self.get_face(face_idx, style).face;
|
||||||
let (synth_bold, synth_italic) = synth_flags(face, style);
|
let (synth_bold, synth_italic) = synth_flags(face, style);
|
||||||
let glyph = rasterize_index(face, gid, synth_bold, synth_italic)?;
|
let glyph = rasterize_index(face, gid, synth_bold, synth_italic)?;
|
||||||
self.gcache.put(key, glyph);
|
self.gcache.put(key, glyph);
|
||||||
|
|
@ -231,7 +317,7 @@ impl Fonts {
|
||||||
/// those at blit time instead.
|
/// those at blit time instead.
|
||||||
pub fn glyph_scaled(&mut self, c: char, style: Style, scale: f32) -> Result<Glyph, FontError> {
|
pub fn glyph_scaled(&mut self, c: char, style: Style, scale: f32) -> Result<Glyph, FontError> {
|
||||||
let idx = self.face_for(c, style)?;
|
let idx = self.face_for(c, style)?;
|
||||||
let face = &self.faces[idx].face;
|
let face = &self.get_face(idx, style).face;
|
||||||
let (synth_bold, synth_italic) = synth_flags(face, style);
|
let (synth_bold, synth_italic) = synth_flags(face, style);
|
||||||
rasterize_scaled(face, c, scale.max(0.01), synth_bold, synth_italic)
|
rasterize_scaled(face, c, scale.max(0.01), synth_bold, synth_italic)
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +347,7 @@ impl Fonts {
|
||||||
|
|
||||||
fn shape_uncached(&mut self, base: char, cluster: &str, style: Style) -> Option<ShapedCluster> {
|
fn shape_uncached(&mut self, base: char, cluster: &str, style: Style) -> Option<ShapedCluster> {
|
||||||
let face_idx = self.face_for(base, style).ok()?;
|
let face_idx = self.face_for(base, style).ok()?;
|
||||||
let font = self.hb_font(face_idx)?;
|
let font = self.hb_font(style, face_idx)?;
|
||||||
let buffer = harfbuzz::UnicodeBuffer::new().add_str(cluster);
|
let buffer = harfbuzz::UnicodeBuffer::new().add_str(cluster);
|
||||||
let output = harfbuzz::shape(font, buffer, &[]);
|
let output = harfbuzz::shape(font, buffer, &[]);
|
||||||
let infos = output.get_glyph_infos();
|
let infos = output.get_glyph_infos();
|
||||||
|
|
@ -288,9 +374,26 @@ impl Fonts {
|
||||||
/// Lazily build the HarfBuzz font for `face_idx` from the same file bytes
|
/// Lazily build the HarfBuzz font for `face_idx` from the same file bytes
|
||||||
/// FreeType loaded. The bytes are leaked to `'static`: a face lives for the
|
/// FreeType loaded. The bytes are leaked to `'static`: a face lives for the
|
||||||
/// process, and only the handful actually used to shape clusters allocate.
|
/// process, and only the handful actually used to shape clusters allocate.
|
||||||
fn hb_font(&mut self, face_idx: usize) -> Option<&harfbuzz::Owned<harfbuzz::Font<'static>>> {
|
fn hb_font(
|
||||||
if self.faces[face_idx].hb.is_none() {
|
&mut self,
|
||||||
let entry = &self.faces[face_idx];
|
style: Style,
|
||||||
|
face_idx: usize,
|
||||||
|
) -> Option<&harfbuzz::Owned<harfbuzz::Font<'static>>> {
|
||||||
|
let entry = match style {
|
||||||
|
Style { italic: true, .. } => &mut self
|
||||||
|
.italic_faces
|
||||||
|
.as_mut()
|
||||||
|
.unwrap_or(&mut self.primary_faces)[face_idx],
|
||||||
|
Style { bold: true, .. } => {
|
||||||
|
&mut self.bold_faces.as_mut().unwrap_or(&mut self.primary_faces)[face_idx]
|
||||||
|
}
|
||||||
|
Style {
|
||||||
|
bold: false,
|
||||||
|
italic: false,
|
||||||
|
} => &mut self.primary_faces[face_idx],
|
||||||
|
};
|
||||||
|
|
||||||
|
if entry.hb.is_none() {
|
||||||
let bytes = std::fs::read(&entry.path).ok()?;
|
let bytes = std::fs::read(&entry.path).ok()?;
|
||||||
let leaked: &'static [u8] = Box::leak(bytes.into_boxed_slice());
|
let leaked: &'static [u8] = Box::leak(bytes.into_boxed_slice());
|
||||||
let face = harfbuzz::Face::from_bytes(leaked, entry.index);
|
let face = harfbuzz::Face::from_bytes(leaked, entry.index);
|
||||||
|
|
@ -298,9 +401,9 @@ impl Fonts {
|
||||||
let scale = self.size_px as i32 * 64;
|
let scale = self.size_px as i32 * 64;
|
||||||
font.set_scale(scale, scale);
|
font.set_scale(scale, scale);
|
||||||
font.set_ppem(self.size_px, self.size_px);
|
font.set_ppem(self.size_px, self.size_px);
|
||||||
self.faces[face_idx].hb = Some(font);
|
entry.hb = Some(font);
|
||||||
}
|
}
|
||||||
self.faces[face_idx].hb.as_ref()
|
entry.hb.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pick the face that should render `c`: the requested style if it has the
|
/// Pick the face that should render `c`: the requested style if it has the
|
||||||
|
|
@ -308,17 +411,17 @@ impl Fonts {
|
||||||
/// coverage match. Falls back to the styled face (rendering `.notdef`).
|
/// coverage match. Falls back to the styled face (rendering `.notdef`).
|
||||||
fn face_for(&mut self, c: char, style: Style) -> Result<usize, FontError> {
|
fn face_for(&mut self, c: char, style: Style) -> Result<usize, FontError> {
|
||||||
let styled = self.styled_face(style)?;
|
let styled = self.styled_face(style)?;
|
||||||
if face_has_glyph(&self.faces[styled].face, c) {
|
if face_has_glyph(&self.get_face(styled, style).face, c) {
|
||||||
return Ok(styled);
|
return Ok(styled);
|
||||||
}
|
}
|
||||||
if let Some(regular) = self.styled[0]
|
if let Some(regular) = self.styled[0]
|
||||||
&& regular != styled
|
&& regular != styled
|
||||||
&& face_has_glyph(&self.faces[regular].face, c)
|
&& face_has_glyph(&self.get_face(styled, style).face, c)
|
||||||
{
|
{
|
||||||
return Ok(regular);
|
return Ok(regular);
|
||||||
}
|
}
|
||||||
for &idx in self.fallbacks.values() {
|
for &idx in self.fallbacks.values() {
|
||||||
if face_has_glyph(&self.faces[idx].face, c) {
|
if face_has_glyph(&self.get_face(styled, style).face, c) {
|
||||||
return Ok(idx);
|
return Ok(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -332,16 +435,33 @@ impl Fonts {
|
||||||
return Ok(idx);
|
return Ok(idx);
|
||||||
}
|
}
|
||||||
let regular = self.styled[0].expect("regular face is loaded at construction");
|
let regular = self.styled[0].expect("regular face is loaded at construction");
|
||||||
|
let family = match style {
|
||||||
|
Style { italic: true, .. } => {
|
||||||
|
self.italic_family.as_ref().unwrap_or(&self.primary_family)
|
||||||
|
}
|
||||||
|
Style { bold: true, .. } => self.bold_family.as_ref().unwrap_or(&self.primary_family),
|
||||||
|
_ => &self.primary_family,
|
||||||
|
};
|
||||||
|
let faces = match style {
|
||||||
|
Style { italic: true, .. } => {
|
||||||
|
&mut self.bold_faces.as_mut().unwrap_or(&mut self.primary_faces)
|
||||||
|
}
|
||||||
|
Style { bold: true, .. } => &mut self
|
||||||
|
.italic_faces
|
||||||
|
.as_mut()
|
||||||
|
.unwrap_or(&mut self.primary_faces),
|
||||||
|
_ => &mut self.primary_faces,
|
||||||
|
};
|
||||||
let idx = match resolve_face(
|
let idx = match resolve_face(
|
||||||
&self.library,
|
&self.library,
|
||||||
&self.fontconfig,
|
&self.fontconfig,
|
||||||
&self.family,
|
&family,
|
||||||
style,
|
style,
|
||||||
self.size_px,
|
self.size_px,
|
||||||
) {
|
) {
|
||||||
Ok(entry) => {
|
Ok(entry) => {
|
||||||
self.faces.push(entry);
|
faces.push(entry);
|
||||||
self.faces.len() - 1
|
faces.len() - 1
|
||||||
}
|
}
|
||||||
Err(_) => regular,
|
Err(_) => regular,
|
||||||
};
|
};
|
||||||
|
|
@ -367,13 +487,13 @@ impl Fonts {
|
||||||
if size_face(&face, self.size_px).is_err() {
|
if size_face(&face, self.size_px).is_err() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
self.faces.push(FaceEntry {
|
self.primary_faces.push(FaceEntry {
|
||||||
face,
|
face,
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
index: index as u32,
|
index: index as u32,
|
||||||
hb: None,
|
hb: None,
|
||||||
});
|
});
|
||||||
let idx = self.faces.len() - 1;
|
let idx = self.primary_faces.len() - 1;
|
||||||
self.fallbacks.insert(path, idx);
|
self.fallbacks.insert(path, idx);
|
||||||
Ok(Some(idx))
|
Ok(Some(idx))
|
||||||
}
|
}
|
||||||
|
|
@ -651,8 +771,18 @@ fn expand_mono(src: &[u8], width: usize, pitch: i32, height: usize) -> Vec<u8> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
impl FontStyles {
|
||||||
|
pub fn regular(name: impl Into<String>) -> Self {
|
||||||
|
FontStyles {
|
||||||
|
primary: name.into(),
|
||||||
|
italics: None,
|
||||||
|
bold: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn fonts() -> Fonts {
|
fn fonts() -> Fonts {
|
||||||
Fonts::new("monospace", 16).expect("system has a monospace font")
|
Fonts::new(FontStyles::regular("monospace"), 16).expect("system has a monospace font")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use std::num::NonZeroU16;
|
||||||
use beer_protocols::graphics::{PLACEHOLDER, diacritic_value};
|
use beer_protocols::graphics::{PLACEHOLDER, diacritic_value};
|
||||||
use beer_protocols::text_size::{HAlign, VAlign};
|
use beer_protocols::text_size::{HAlign, VAlign};
|
||||||
|
|
||||||
use crate::font::{CellMetrics, Fonts, Glyph, GlyphData, Style};
|
use crate::font::{CellMetrics, FontStyles, Fonts, Glyph, GlyphData, Style};
|
||||||
use crate::grid::{Cell, Color, CursorShape, Flags, Grid, Underline};
|
use crate::grid::{Cell, Color, CursorShape, Flags, Grid, Underline};
|
||||||
use crate::theme::{Plane, Rgb, Theme};
|
use crate::theme::{Plane, Rgb, Theme};
|
||||||
|
|
||||||
|
|
@ -141,8 +141,12 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rebuild the font set at a new size (font-resize bindings).
|
/// Rebuild the font set at a new size (font-resize bindings).
|
||||||
pub fn set_font(&mut self, family: &str, size_px: u32) -> Result<(), crate::font::FontError> {
|
pub fn set_font(
|
||||||
self.fonts = Fonts::new(family, size_px)?;
|
&mut self,
|
||||||
|
fonts: FontStyles,
|
||||||
|
size_px: u32,
|
||||||
|
) -> Result<(), crate::font::FontError> {
|
||||||
|
self.fonts = Fonts::new(fonts, size_px)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ use calloop::{EventLoop, Interest, LoopHandle, Mode, PostAction, RegistrationTok
|
||||||
use calloop_wayland_source::WaylandSource;
|
use calloop_wayland_source::WaylandSource;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::font::Fonts;
|
use crate::font::{FontStyles, Fonts};
|
||||||
use crate::grid::{Cell, CursorShape, Grid, MouseProtocol, UrlHit};
|
use crate::grid::{Cell, CursorShape, Grid, MouseProtocol, UrlHit};
|
||||||
use crate::pty::Pty;
|
use crate::pty::Pty;
|
||||||
use crate::render::Renderer;
|
use crate::render::Renderer;
|
||||||
|
|
@ -207,7 +207,15 @@ pub fn run(config: Config, config_path: Option<std::path::PathBuf>) -> anyhow::R
|
||||||
// First commit with no buffer kicks off the initial configure.
|
// First commit with no buffer kicks off the initial configure.
|
||||||
window.commit();
|
window.commit();
|
||||||
|
|
||||||
let fonts = Fonts::new(&config.main.font, config.main.font_size).context("load font")?;
|
let fonts = Fonts::new(
|
||||||
|
FontStyles::all(
|
||||||
|
&config.main.font,
|
||||||
|
config.main.font_italic.clone(),
|
||||||
|
config.main.font_bold.clone(),
|
||||||
|
),
|
||||||
|
config.main.font_size,
|
||||||
|
)
|
||||||
|
.context("load font")?;
|
||||||
let mut renderer = Renderer::new(fonts);
|
let mut renderer = Renderer::new(fonts);
|
||||||
renderer.set_padding(config.main.pad_x, config.main.pad_y);
|
renderer.set_padding(config.main.pad_x, config.main.pad_y);
|
||||||
|
|
||||||
|
|
@ -1176,7 +1184,14 @@ impl App {
|
||||||
self.to_phys(self.config.main.pad_y),
|
self.to_phys(self.config.main.pad_y),
|
||||||
);
|
);
|
||||||
let px = self.to_phys(self.font_size).max(1);
|
let px = self.to_phys(self.font_size).max(1);
|
||||||
if let Err(err) = self.renderer.set_font(&self.config.main.font, px) {
|
if let Err(err) = self.renderer.set_font(
|
||||||
|
FontStyles::all(
|
||||||
|
&self.config.main.font,
|
||||||
|
self.config.main.font_italic.clone(),
|
||||||
|
self.config.main.font_bold.clone(),
|
||||||
|
),
|
||||||
|
px,
|
||||||
|
) {
|
||||||
tracing::warn!("rasterize font at scale {}: {err:#}", self.scale120);
|
tracing::warn!("rasterize font at scale {}: {err:#}", self.scale120);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue