mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-30 04:37:29 -06:00
Fix #36: the font menus list the installed fonts, with a search field
Type > Font, the Character, Properties and Glyphs panels and Find Font list every installed font by default, as the reference app does, instead of the four bundled families. The family dropdowns get a search field that filters the list as you type (Enter picks the first match) and open on the current font. Show System Fonts, which no longer means anything, becomes Refresh Font List (text.rescanFonts): it picks up fonts installed since the app started and redraws type set in them without editing the document. text.fontList lets MCP agents list the families and a family's styles. Root cause: the font lists came from FontDb::families(), which only held the bundled fonts until something scanned the system fonts (fixed with #130). The Type > Font menu, rebuilt every frame, now builds its items once per font change, and renderers lay type out again when the fonts change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
49e8413ebe
commit
f12428264c
@@ -274,6 +274,9 @@ type ClipPaintEntry = (Arc<Node>, Option<Arc<Node>>, Option<Arc<Node>>);
|
||||
/// Reusable renderer (keeps the render context, decoded images and glyph caches between frames).
|
||||
pub struct Renderer {
|
||||
texts: PtrMap<usize, (Arc<Node>, Arc<TextGeom>)>,
|
||||
/// The [`vectorcraft_text::FontDb::generation`] `texts` was laid out with: type lays out
|
||||
/// again when fonts are added or rescanned.
|
||||
text_fonts: u64,
|
||||
/// Clip regions per clipping path (see [`Self::clip_of`]).
|
||||
clips: PtrMap<usize, ClipEntry>,
|
||||
/// Context reused when rendering single-threaded (`threads == 0`).
|
||||
@@ -376,6 +379,7 @@ impl Renderer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
texts: PtrMap::default(),
|
||||
text_fonts: 0,
|
||||
clips: PtrMap::default(),
|
||||
ctx_st: None,
|
||||
threads: default_threads(),
|
||||
@@ -1142,6 +1146,11 @@ impl Renderer {
|
||||
|
||||
/// Cached glyph geometry for a text node (keyed by Arc identity like paths).
|
||||
fn text_geom_of(&mut self, a: &Arc<Node>, t: &TextObject) -> Arc<TextGeom> {
|
||||
let fonts = vectorcraft_text::FontDb::global().generation();
|
||||
if fonts != self.text_fonts {
|
||||
self.texts.clear();
|
||||
self.text_fonts = fonts;
|
||||
}
|
||||
let key = Arc::as_ptr(a) as usize;
|
||||
if let Some((node, g)) = self.texts.get(&key)
|
||||
&& Arc::ptr_eq(node, a)
|
||||
@@ -1528,6 +1537,8 @@ mod tests_cmykblend;
|
||||
#[cfg(test)]
|
||||
mod tests_container;
|
||||
#[cfg(test)]
|
||||
mod tests_fontchange;
|
||||
#[cfg(test)]
|
||||
mod tests_freeform;
|
||||
#[cfg(test)]
|
||||
mod tests_isolation;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
//! Type redraws in a font that becomes available while it is on screen (fonts added, Refresh Font
|
||||
//! List).
|
||||
|
||||
use vectorcraft_doc::text::{CharStyle, TextObject};
|
||||
use vectorcraft_doc::{Node, NodeKind};
|
||||
use vectorcraft_geom::Point;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// The bundled Source Serif 4 renamed `family` (as long as the original name).
|
||||
fn serif_as(family: &str) -> Vec<u8> {
|
||||
let mut data = include_bytes!("../../../assets/fonts/SourceSerif4-Regular.ttf").to_vec();
|
||||
let utf16 = |s: &str| s.encode_utf16().flat_map(u16::to_be_bytes).collect::<Vec<u8>>();
|
||||
for (from, to) in [(utf16("Source Serif 4"), utf16(family)), (b"Source Serif 4".to_vec(), family.as_bytes().to_vec())] {
|
||||
assert_eq!(from.len(), to.len());
|
||||
let mut i = 0;
|
||||
while let Some(at) = data[i..].windows(from.len()).position(|w| w == from) {
|
||||
data[i + at..i + at + to.len()].copy_from_slice(&to);
|
||||
i += at + to.len();
|
||||
}
|
||||
}
|
||||
data
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_redraws_when_its_font_becomes_available() {
|
||||
const FAMILY: &str = "Arrival Serif4";
|
||||
let mut d = Document::new(300.0, 150.0);
|
||||
let style = CharStyle { size: 60.0, font_family: FAMILY.into(), ..Default::default() };
|
||||
let mut n = Node::new(NodeId(0), NodeKind::Text(Box::new(TextObject::point(Point::new(10.0, 100.0), "Hamburg", style))));
|
||||
n.id = d.alloc_id();
|
||||
let l = d.layers[0].id;
|
||||
d.insert(Some(l), 0, n).unwrap();
|
||||
let opts = RenderOptions { background: Some([255, 255, 255, 255]), ..Default::default() };
|
||||
let mut r = Renderer::new();
|
||||
let before = r.render(&d, 300, 150, Affine::IDENTITY, &opts).pixels;
|
||||
assert!(vectorcraft_text::FontDb::global().add_font(serif_as(FAMILY)) > 0);
|
||||
let after = r.render(&d, 300, 150, Affine::IDENTITY, &opts).pixels;
|
||||
assert_ne!(before, after, "drawn in the font that arrived");
|
||||
assert_eq!(after, Renderer::new().render(&d, 300, 150, Affine::IDENTITY, &opts).pixels, "as a new renderer draws it");
|
||||
}
|
||||
Reference in New Issue
Block a user