From aa9d1b77d4f6e43368df854657f4d8893a299e2e Mon Sep 17 00:00:00 2001 From: Joshua Thijssen Date: Wed, 15 Jan 2025 17:59:32 +0100 Subject: [PATCH] up --- src/bin/gtk2-test.rs | 9 +++--- src/bin/parley.rs | 31 +++++++----------- src/font_manager/manager.rs | 48 ++++++++++++---------------- src/font_manager/sources.rs | 7 +--- src/font_manager/sources/fontique.rs | 13 -------- src/font_manager/sources/fontkit.rs | 14 +------- src/font_manager/sources/pango.rs | 17 ++++------ src/font_manager/sources/parley.rs | 33 ++++++------------- 8 files changed, 54 insertions(+), 118 deletions(-) diff --git a/src/bin/gtk2-test.rs b/src/bin/gtk2-test.rs index 92c541b..e4191c9 100644 --- a/src/bin/gtk2-test.rs +++ b/src/bin/gtk2-test.rs @@ -184,7 +184,7 @@ fn draw(manager: &FontManager, font: &FontInfo, cr: >k4::cairo::Context, layou } } -fn create_layout(manager: &mut FontManager, font: &FontInfo, text: &str, width: f64, font_size: f64) -> Layout { +fn create_layout(manager: &FontManager, font: &FontInfo, text: &str, width: f64, font_size: f64) -> Layout { let display_scale = 1.0_f32; let max_advance = Some(width as f32 * display_scale); @@ -198,12 +198,13 @@ fn create_layout(manager: &mut FontManager, font: &FontInfo, text: &str, width: // let underline_style = StyleProperty::Underline(true); // let strikethrough_style = StyleProperty::Strikethrough(true); - let font = manager.parley_load_font(&font).unwrap(); - let mut font_context = manager.parley_context_mut().expect("Failed to get parley context"); + let font_stack = manager.parley_get_font_stack(&font).unwrap(); + let binding = manager.parley_context().expect("Failed to get font context"); + let mut font_context = binding.borrow_mut(); let mut builder = layout_cx.ranged_builder(&mut font_context, &text, display_scale); builder.push_default(brush_style); - builder.push_default(font); + builder.push_default(font_stack); builder.push_default(StyleProperty::LineHeight(1.3)); builder.push_default(StyleProperty::FontSize(font_size as f32)); builder.push_default(StyleProperty::LetterSpacing(5.0)); diff --git a/src/bin/parley.rs b/src/bin/parley.rs index 8085742..22a1e47 100644 --- a/src/bin/parley.rs +++ b/src/bin/parley.rs @@ -1,15 +1,15 @@ use image::codecs::png::PngEncoder; use image::{self, Pixel, Rgba, RgbaImage}; use parley::layout::{Alignment, Glyph, GlyphRun, Layout, PositionedLayoutItem}; -use parley::style::{FontStack, FontWeight, StyleProperty}; -use parley::{FontContext, InlineBox, LayoutContext}; +use parley::style::{FontWeight, StyleProperty}; +use parley::{InlineBox, LayoutContext}; use std::fs::File; use swash::scale::image::Content; use swash::scale::{Render, ScaleContext, Scaler, Source, StrikeWith}; use swash::zeno; use swash::FontRef; use zeno::{Format, Vector}; -use fontmanager::font_manager::FontStyle; +use fontmanager::{FontManager, FontSourceType, FontStyle}; #[derive(Clone, Copy, Debug, PartialEq)] struct ColorBrush { @@ -35,21 +35,10 @@ fn main() { let padding = 20; - let mut font_cx = FontContext::new(); - - font_cx.collection.family_names().for_each(|name| { - println!("Family: {}", name); - }); - let font_stack = FontStack::from("comic sans ms"); - - let fontmanager = fontmanager::font_manager::FontManager::new(); - let Some(font_info) = fontmanager.find(vec!["arial"], FontStyle::Normal) else { - panic!("Font not found"); - }; - let font = fontmanager.load(&font_info).expect("Error loading font"); - - - + let manager = FontManager::new(); + let font_info = manager.find(FontSourceType::Parley, &["consolas", "verdana", "comic sans ms", "arial"], FontStyle::Normal).expect("font not found"); + let font_stack = manager.parley_get_font_stack(&font_info).expect("Comic sans not found"); + let font_cx = manager.parley_context().expect("Parley context not found"); let mut layout_cx = LayoutContext::new(); let mut scale_cx = ScaleContext::new(); @@ -63,7 +52,8 @@ fn main() { let text = "Some text here. Let's make it a bit longer so that line wrapping kicks in 😊. And also some اللغة العربية arabic text.\nThis is underline and strikethrough text"; // let text = fontmanager::flatland::TEXT; - let mut builder = layout_cx.ranged_builder(&mut font_cx, &text, display_scale); + let mut binding = font_cx.borrow_mut(); + let mut builder = layout_cx.ranged_builder(&mut binding, &text, display_scale); builder.push_default(brush_style); builder.push_default(font_stack); builder.push_default(StyleProperty::LineHeight(1.3)); @@ -127,9 +117,10 @@ fn main() { path.push("swash_render.png"); path }; - let output_file = File::create(output_path).unwrap(); + let output_file = File::create(output_path.clone()).unwrap(); let png_encoder = PngEncoder::new(output_file); img.write_with_encoder(png_encoder).unwrap(); + println!("Image written to: {:?}", output_path); } diff --git a/src/font_manager/manager.rs b/src/font_manager/manager.rs index 672aa1b..b0add28 100644 --- a/src/font_manager/manager.rs +++ b/src/font_manager/manager.rs @@ -1,4 +1,6 @@ +use std::cell::RefCell; use std::collections::HashMap; +use std::sync::Arc; use anyhow::anyhow; use log::error; use crate::font_manager::font_info::{FontInfo, FontStyle}; @@ -64,13 +66,15 @@ impl FontManager { } pub fn find(&self, source_type: FontSourceType, families: &[&str], style: FontStyle) -> Option { - match self.sources.get(&source_type) { - Some(source) => source.find(families, style).ok(), - None => { - error!(target: LOG_TARGET, "Unknown font source: {:?}", source_type); - None + for &fam in families { + for fi in self.available_fonts(source_type) { + if fi.family.eq_ignore_ascii_case(fam) && fi.style == style { + return Some(fi.clone()); + } } } + + None } } @@ -98,26 +102,16 @@ impl FontManager { ps.load_freetype_font(font_info) } - #[cfg(feature = "source_parley")] - pub fn parley_load_font(&self, _font_info: &FontInfo) -> Result { - let Some(source) = self.sources.get(&FontSourceType::Parley) else { - return Err(anyhow!("Parley source not found")) - }; - - let _ps = source.as_any().downcast_ref::() - .ok_or_else(|| anyhow!("Failed to downcast ParleySource"))?; - - // ps.context().load_font(font_info) - Err(anyhow!("Not implemented")) - } - #[cfg(feature = "source_pango")] - pub fn pango_load_font(&self, _font_info: &FontInfo) -> Result { - let Some(_source) = self.sources.get(&FontSourceType::Pango) else { + pub fn pango_load_font(&self, font_info: &FontInfo) -> Result { + let Some(source) = self.sources.get(&FontSourceType::Pango) else { return Err(anyhow!("Pango source not found")) }; - Err(anyhow!("Not implemented")) + let ps = source.as_any().downcast_ref::() + .ok_or_else(|| anyhow!("Failed to downcast PangoSource"))?; + + ps.load_font(font_info) } #[cfg(feature = "source_pango")] @@ -133,7 +127,7 @@ impl FontManager { } #[cfg(feature = "source_parley")] - pub fn parley_context(&self) -> Result<&parley::FontContext, anyhow::Error> { + pub fn parley_context(&self) -> Result>, anyhow::Error> { let Some(source) = self.sources.get(&FontSourceType::Parley) else { return Err(anyhow!("Parley source not found")) }; @@ -144,17 +138,15 @@ impl FontManager { Ok(ps.context()) } - #[cfg(feature = "source_parley")] - pub fn parley_context_mut(&mut self) -> Result<&mut parley::FontContext, anyhow::Error> { - let Some(source) = self.sources.get_mut(&FontSourceType::Parley) else { + pub fn parley_get_font_stack(&self, font_info: &FontInfo) -> Result { + let Some(source) = self.sources.get(&FontSourceType::Parley) else { return Err(anyhow!("Parley source not found")) }; - let ps= source.as_any_mut().downcast_mut::() + let ps = source.as_any().downcast_ref::() .ok_or_else(|| anyhow!("Failed to downcast ParleySource"))?; - Ok(ps.context_mut()) + Ok(ps.get_font_stack(font_info.family.clone())) } - } diff --git a/src/font_manager/sources.rs b/src/font_manager/sources.rs index 08f1d7e..e3c7f65 100644 --- a/src/font_manager/sources.rs +++ b/src/font_manager/sources.rs @@ -1,4 +1,4 @@ -use crate::font_manager::font_info::{FontInfo, FontStyle}; +use crate::font_manager::font_info::FontInfo; use std::any::Any; use std::path::{Path, PathBuf}; @@ -14,22 +14,17 @@ pub mod pango; pub trait FontSource: AsAny { fn new() -> Self where Self: Sized; fn available_fonts(&self) -> &[FontInfo]; - fn find(&self, family: &[&str], style: FontStyle) -> Result; } pub trait AsAny { #[allow(unused)] fn as_any(&self) -> &dyn Any; - fn as_any_mut(&mut self) -> &mut dyn Any; } impl AsAny for T { fn as_any(&self) -> &dyn Any { self } - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } } #[derive(Clone, Copy, Hash, Eq, PartialEq, Debug)] diff --git a/src/font_manager/sources/fontique.rs b/src/font_manager/sources/fontique.rs index 424cb78..fce4535 100644 --- a/src/font_manager/sources/fontique.rs +++ b/src/font_manager/sources/fontique.rs @@ -1,7 +1,6 @@ use std::collections::HashSet; use std::path::PathBuf; use log::info; -use anyhow::Error; use fontique::{Collection, CollectionOptions, SourceKind}; use crate::font_manager::font_info::{FontInfo, FontStyle}; use crate::font_manager::sources::{resolve_symlink, FontSource, FontSourceType}; @@ -74,16 +73,4 @@ impl FontSource for FontiqueSource { fn available_fonts(&self) -> &[FontInfo] { &self.font_info } - - fn find(&self, family: &[&str], style: FontStyle) -> Result { - for &fam in family { - for fi in &self.font_info { - if fi.family.eq_ignore_ascii_case(fam) && fi.style == style { - return Ok(fi.clone()); - } - } - } - - Err(Error::msg("Font not found")) - } } \ No newline at end of file diff --git a/src/font_manager/sources/fontkit.rs b/src/font_manager/sources/fontkit.rs index 958bfed..9636eb9 100644 --- a/src/font_manager/sources/fontkit.rs +++ b/src/font_manager/sources/fontkit.rs @@ -2,7 +2,7 @@ use crate::font_manager::manager::LOG_TARGET; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use std::sync::{Arc, Mutex}; -use anyhow::{anyhow, Error}; +use anyhow::anyhow; use font_kit::handle::Handle; use font_kit::source::SystemSource; use freetype::{Face, Library}; @@ -53,18 +53,6 @@ impl FontSource for FontKitSource { fn available_fonts(&self) -> &[FontInfo] { &self.font_info } - - fn find(&self, family: &[&str], style: FontStyle) -> Result { - for &fam in family { - for fi in &self.font_info { - if fi.family.eq_ignore_ascii_case(fam) && fi.style == style { - return Ok(fi.clone()); - } - } - } - - Err(Error::msg("Font not found")) - } } impl FontKitSource { diff --git a/src/font_manager/sources/pango.rs b/src/font_manager/sources/pango.rs index 87bc50f..fca95e1 100644 --- a/src/font_manager/sources/pango.rs +++ b/src/font_manager/sources/pango.rs @@ -84,21 +84,16 @@ impl FontSource for PangoSource { fn available_fonts(&self) -> &[FontInfo] { &self.font_info } +} - fn find(&self, family: &[&str], style: FontStyle) -> Result { - for &fam in family { - for fi in &self.font_info { - if fi.family.eq_ignore_ascii_case(fam) && fi.style == style { - return Ok(fi.clone()); - } - } - } +impl PangoSource { + pub fn load_font(&self, info: &FontInfo) -> Result { + let family = self.font_map.load_font(&self.context, &self.get_description(info, 12.0)) + .ok_or_else(|| Error::msg("Failed to load font"))?; - Err(Error::msg("Font not found")) + Ok(family) } -} -impl PangoSource { pub fn get_description(&self, info: &FontInfo, size: f64) -> pangocairo::pango::FontDescription { let mut desc = pangocairo::pango::FontDescription::new(); desc.set_family(&info.family.clone()); diff --git a/src/font_manager/sources/parley.rs b/src/font_manager/sources/parley.rs index 16ab7b7..172a51d 100644 --- a/src/font_manager/sources/parley.rs +++ b/src/font_manager/sources/parley.rs @@ -1,14 +1,15 @@ +use std::borrow::Cow; use std::collections::HashSet; use std::path::PathBuf; -use anyhow::Error; use log::info; use std::cell::RefCell; +use std::sync::Arc; use crate::font_manager::font_info::{FontInfo, FontStyle}; use crate::font_manager::sources::{resolve_symlink, FontSource, FontSourceType}; // #[allow(unused)] pub struct ParleySource { - context: RefCell, + context: Arc>, font_info: Vec } @@ -65,7 +66,7 @@ impl FontSource for ParleySource { info!("Loaded {} fonts from parley.", font_info.len()); Self { - context: RefCell::new(context), + context: Arc::new(RefCell::new(context)), font_info, } } @@ -73,30 +74,16 @@ impl FontSource for ParleySource { fn available_fonts(&self) -> &[FontInfo] { &self.font_info } - - fn find(&self, family: &[&str], style: FontStyle) -> Result { - for &fam in family { - for fi in &self.font_info { - if fi.family.eq_ignore_ascii_case(fam) && fi.style == style { - return Ok(fi.clone()); - } - } - } - - Err(Error::msg("Font not found")) - } } impl ParleySource { - pub fn context(&self) -> RefCell { - self.context + pub fn context(&self) -> Arc> { + self.context.clone() } - pub fn context_mut(&mut self) -> &mut parley::FontContext { - &mut self.context.borrow_mut() + pub fn get_font_stack(&self, family: String) -> parley::FontStack { + parley::FontStack::Single( + parley::style::FontFamily::Named(Cow::Owned(family)) + ) } - - // pub fn load_font(&self, _font_info: &FontInfo) -> Result { - // Err(anyhow!("Not implemented")) - // } } \ No newline at end of file