Do not store reference to font in shape or layout glyphs
This commit is contained in:
parent
3c573df261
commit
42de42d59e
5 changed files with 68 additions and 47 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -117,13 +117,13 @@ impl fmt::Display for TextMetrics {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct TextBufferLine<'a> {
|
||||
pub struct TextBufferLine {
|
||||
text: String,
|
||||
shape_opt: Option<FontShapeLine<'a>>,
|
||||
layout_opt: Option<Vec<FontLayoutLine<'a>>>,
|
||||
shape_opt: Option<FontShapeLine>,
|
||||
layout_opt: Option<Vec<FontLayoutLine>>,
|
||||
}
|
||||
|
||||
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<TextBufferLine<'a>>,
|
||||
lines: Vec<TextBufferLine>,
|
||||
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);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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<FontLayoutGlyph<'a>>,
|
||||
pub glyphs: Vec<FontLayoutGlyph>,
|
||||
}
|
||||
|
||||
impl<'a> FontLayoutLine<'a> {
|
||||
pub fn draw<F: FnMut(i32, i32, u32)>(&self, base: u32, mut f: F) {
|
||||
impl FontLayoutLine {
|
||||
pub fn draw<F: FnMut(i32, i32, u32)>(&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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<FontShapeGlyph<'a>>,
|
||||
pub glyphs: Vec<FontShapeGlyph>,
|
||||
}
|
||||
|
||||
pub struct FontShapeSpan<'a> {
|
||||
pub struct FontShapeSpan {
|
||||
pub rtl: bool,
|
||||
pub words: Vec<FontShapeWord<'a>>,
|
||||
pub words: Vec<FontShapeWord>,
|
||||
}
|
||||
|
||||
pub struct FontShapeLine<'a> {
|
||||
pub struct FontShapeLine {
|
||||
pub rtl: bool,
|
||||
pub spans: Vec<FontShapeSpan<'a>>,
|
||||
pub spans: Vec<FontShapeSpan>,
|
||||
}
|
||||
|
||||
impl<'a> FontShapeLine<'a> {
|
||||
impl FontShapeLine {
|
||||
pub fn layout(
|
||||
&self,
|
||||
font_size: i32,
|
||||
line_width: i32,
|
||||
layout_lines: &mut Vec<FontLayoutLine<'a>>,
|
||||
layout_lines: &mut Vec<FontLayoutLine>,
|
||||
mut layout_i: usize,
|
||||
) {
|
||||
let mut push_line = true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue