From 42de42d59eec5506bc0bb610ec08c192d7d00fad Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 25 Oct 2022 10:13:44 -0600 Subject: [PATCH] Do not store reference to font in shape or layout glyphs --- examples/editor-orbclient/src/main.rs | 5 +--- src/buffer.rs | 23 +++++++-------- src/font/layout.rs | 33 ++++++++++++++-------- src/font/matches.rs | 14 ++++++++-- src/font/shape.rs | 40 +++++++++++++++------------ 5 files changed, 68 insertions(+), 47 deletions(-) diff --git a/examples/editor-orbclient/src/main.rs b/examples/editor-orbclient/src/main.rs index 67c0f0a..644bfb0 100644 --- a/examples/editor-orbclient/src/main.rs +++ b/examples/editor-orbclient/src/main.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 -use cosmic_text::{FontSystem, TextAction, TextBuffer, TextCursor, TextLineIndex, TextMetrics}; +use cosmic_text::{FontSystem, TextAction, TextBuffer, TextMetrics}; use orbclient::{Color, EventOption, Renderer, Window, WindowFlag}; use std::{env, fs, thread, time::{Duration, Instant}}; @@ -103,9 +103,6 @@ fn main() { buffer.shape_until_cursor(); loop { - let font_size = buffer.metrics().font_size; - let line_height = buffer.metrics().line_height; - let mut force_drag = true; if buffer.redraw { diff --git a/src/buffer.rs b/src/buffer.rs index 97f7297..31701d1 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -117,13 +117,13 @@ impl fmt::Display for TextMetrics { } } -pub struct TextBufferLine<'a> { +pub struct TextBufferLine { text: String, - shape_opt: Option>, - layout_opt: Option>>, + shape_opt: Option, + layout_opt: Option>, } -impl<'a> TextBufferLine<'a> { +impl TextBufferLine { pub fn new(text: String) -> Self { Self { text, @@ -141,7 +141,7 @@ impl<'a> TextBufferLine<'a> { self.layout_opt = None; } - pub fn shape(&mut self, font_matches: &'a FontMatches<'a>) -> &FontShapeLine<'a> { + pub fn shape(&mut self, font_matches: &FontMatches<'_>) -> &FontShapeLine { if self.shape_opt.is_none() { self.shape_opt = Some(font_matches.shape_line(&self.text)); self.layout_opt = None; @@ -149,7 +149,7 @@ impl<'a> TextBufferLine<'a> { self.shape_opt.as_ref().unwrap() } - pub fn layout(&mut self, font_matches: &'a FontMatches<'a>, font_size: i32, width: i32) -> &[FontLayoutLine<'a>] { + pub fn layout(&mut self, font_matches: &FontMatches<'_>, font_size: i32, width: i32) -> &[FontLayoutLine] { if self.layout_opt.is_none() { let mut layout = Vec::new(); let shape = self.shape(font_matches); @@ -168,7 +168,7 @@ impl<'a> TextBufferLine<'a> { /// A buffer of text that is shaped and laid out pub struct TextBuffer<'a> { font_matches: &'a FontMatches<'a>, - lines: Vec>, + lines: Vec, metrics: TextMetrics, width: i32, height: i32, @@ -460,7 +460,7 @@ impl<'a> TextBuffer<'a> { } /// Get the lines of the original text - pub fn text_lines(&self) -> &[TextBufferLine<'a>] { + pub fn text_lines(&self) -> &[TextBufferLine] { &self.lines } @@ -769,13 +769,14 @@ impl<'a> TextBuffer<'a> { self.redraw = true; if let Some(glyph) = layout_line.glyphs.get(new_cursor_glyph) { + let font_opt = self.font_matches.get_font(&glyph.cache_key.font_id); let text_glyph = &line.text[glyph.start..glyph.end]; log::debug!( "{}, {}: '{}' ('{}'): '{}' ({:?})", self.cursor.line.get(), self.cursor.index, - glyph.font.info.family, - glyph.font.info.post_script_name, + font_opt.map_or("?", |font| font.info.family.as_str()), + font_opt.map_or("?", |font| font.info.post_script_name.as_str()), text_glyph, text_glyph ); @@ -974,7 +975,7 @@ impl<'a> TextBuffer<'a> { ); } - layout_line.draw(color, |x, y, color| { + layout_line.draw(self.font_matches, color, |x, y, color| { f(x, line_y + y, 1, 1, color); }); diff --git a/src/font/layout.rs b/src/font/layout.rs index d2ae21c..1a15ce6 100644 --- a/src/font/layout.rs +++ b/src/font/layout.rs @@ -1,38 +1,47 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 -use super::{CacheKey, Font}; +use super::{CacheKey, FontMatches}; -pub struct FontLayoutGlyph<'a> { +pub struct FontLayoutGlyph { pub start: usize, pub end: usize, pub x: f32, pub w: f32, pub rtl: bool, - pub font: &'a Font<'a>, - pub inner: (CacheKey, i32, i32), + pub cache_key: CacheKey, + pub x_int: i32, + pub y_int: i32, } -pub struct FontLayoutLine<'a> { +pub struct FontLayoutLine { pub rtl: bool, - pub glyphs: Vec>, + pub glyphs: Vec, } -impl<'a> FontLayoutLine<'a> { - pub fn draw(&self, base: u32, mut f: F) { +impl FontLayoutLine { + pub fn draw(&self, matches: &FontMatches<'_>, base: u32, mut f: F) { for glyph in self.glyphs.iter() { use swash::scale::{Render, Source, StrikeWith}; use swash::zeno::{Format, Vector}; - let mut cache = glyph.font.cache.lock().unwrap(); + let font = match matches.get_font(&glyph.cache_key.font_id) { + Some(some) => some, + None => { + log::warn!("did not find font {:?}", glyph.cache_key.font_id); + continue; + }, + }; - let (cache_key, x_int, y_int) = glyph.inner; + let mut cache = font.cache.lock().unwrap(); + + let (cache_key, x_int, y_int) = (glyph.cache_key, glyph.x_int, glyph.y_int); let image_opt = cache.entry(cache_key).or_insert_with(|| { - let mut scale_context = glyph.font.scale_context.lock().unwrap(); + let mut scale_context = font.scale_context.lock().unwrap(); // Build the scaler let mut scaler = scale_context - .builder(glyph.font.swash) + .builder(font.swash) .size(cache_key.font_size as f32) .hint(true) .build(); diff --git a/src/font/matches.rs b/src/font/matches.rs index 8b444ca..aec551e 100644 --- a/src/font/matches.rs +++ b/src/font/matches.rs @@ -57,7 +57,6 @@ impl<'a> FontMatches<'a> { missing.push(start_word + info.cluster as usize); } - let inner = info.glyph_id as swash::GlyphId; glyphs.push(FontShapeGlyph { start: start_word + info.cluster as usize, end: end_word, // Set later @@ -65,8 +64,8 @@ impl<'a> FontMatches<'a> { y_advance, x_offset, y_offset, - font, - inner, + font_id: font.info.id, + glyph_id: info.glyph_id.try_into().unwrap(), }); } @@ -325,4 +324,13 @@ impl<'a> FontMatches<'a> { FontShapeLine { rtl, spans } } + + pub fn get_font(&self, id: &fontdb::ID) -> Option<&Font> { + for font in self.fonts.iter() { + if &font.info.id == id { + return Some(font); + } + } + None + } } diff --git a/src/font/shape.rs b/src/font/shape.rs index bda4097..80d068c 100644 --- a/src/font/shape.rs +++ b/src/font/shape.rs @@ -1,58 +1,64 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 -use super::{CacheKey, Font, FontLayoutGlyph, FontLayoutLine}; +use super::{CacheKey, FontLayoutGlyph, FontLayoutLine}; -pub struct FontShapeGlyph<'a> { +pub struct FontShapeGlyph { pub start: usize, pub end: usize, pub x_advance: f32, pub y_advance: f32, pub x_offset: f32, pub y_offset: f32, - pub font: &'a Font<'a>, - pub inner: swash::GlyphId, + pub font_id: fontdb::ID, + pub glyph_id: u16, } -impl<'a> FontShapeGlyph<'a> { - fn layout(&self, font_size: i32, x: f32, y: f32, rtl: bool) -> FontLayoutGlyph<'a> { +impl FontShapeGlyph { + fn layout(&self, font_size: i32, x: f32, y: f32, rtl: bool) -> FontLayoutGlyph { let x_offset = font_size as f32 * self.x_offset; let y_offset = font_size as f32 * self.y_offset; let x_advance = font_size as f32 * self.x_advance; - let inner = CacheKey::new(self.font.info.id, self.inner, font_size, (x + x_offset, y - y_offset)); + let (cache_key, x_int, y_int) = CacheKey::new( + self.font_id, + self.glyph_id, + font_size, + (x + x_offset, y - y_offset) + ); FontLayoutGlyph { start: self.start, end: self.end, x, w: x_advance, rtl, - font: self.font, - inner, + cache_key, + x_int, + y_int, } } } -pub struct FontShapeWord<'a> { +pub struct FontShapeWord { pub blank: bool, - pub glyphs: Vec>, + pub glyphs: Vec, } -pub struct FontShapeSpan<'a> { +pub struct FontShapeSpan { pub rtl: bool, - pub words: Vec>, + pub words: Vec, } -pub struct FontShapeLine<'a> { +pub struct FontShapeLine { pub rtl: bool, - pub spans: Vec>, + pub spans: Vec, } -impl<'a> FontShapeLine<'a> { +impl FontShapeLine { pub fn layout( &self, font_size: i32, line_width: i32, - layout_lines: &mut Vec>, + layout_lines: &mut Vec, mut layout_i: usize, ) { let mut push_line = true;