mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-14 19:26:56 -04:00
Fix #683: Preferences > Type > Additional Fonts Folder
VectorCraft found fonts only in the system's font folders (and, on Windows, those font services activate). A new preference names one more folder, read with its subfolders after the platform's: its fonts are listed in the font menus and used as if installed, without installing them. - vectorcraft_text::set_user_font_dirs / user_font_dirs: folders system_font_dirs adds to every scan (none on wasm). - prefs fontsFolder (Type > Options > Additional Fonts Folder), trimmed; when it changes after the first scan, the fonts are scanned again at once, so the folder's fonts appear (or go) and type in them lays out again. - The label is translated where Additional Plug-ins Folder is. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
b61089e5c6
commit
e92bbdbdac
14 files changed
+69
-4
No files matched your search
+1
-1
@@ -4,7 +4,7 @@ VectorCraft is a clean-room, open-source, pure-Rust reimplementation of the Adob
|
||||
|
||||
This file tracks **how far we are and what's left**. Time estimates are wall-clock hours of continuous Claude Opus 5.5 agent work (including builds and the CI gate), given both for **one agent** and for **4–6 parallel agents** on disjoint crates. They are counted from the remaining work (see [Parity estimate](#parity-estimate)), calibrated against measured throughput, and updated as work lands.
|
||||
|
||||
_Last updated: 2026-10-09 (after placed documents (File › Place of a `.vectorcraft` file, linked), M4.14–M4.98, M8.1–M8.20, M14.4–M14.7, the MCP prompts, resource templates, completions and logging, the 2026-10-07 issue fixes, the Layers panel rework and the 2026-10-08 community contributions: Pen and shape-tool modifiers, path editing, Layers, Artboards, Swatches/Brushes and dialogs, Japanese composition and PDF text, Hebrew/Arabic type, interface languages (Spanish among them), the font menu, saved selections, MCP and EPS, the missing-font export warning (#319), open paths in the Shape Builder (#374), PDF/`.ai` import keeping strokes live and hidden and nested layers (#372), per-corner Live Corners (#381), SVG type opening at the size it draws at (#396), the Wayland clipboard with copied-file paste (#398), ruler guides that can be selected, moved and deleted (#414), two batches of Preferences options that were stored but unused (#394), skeleton reads with `document.find` for large documents over MCP (#416) and anchors dragged with Direct Selection snapping to points, segments and smart guides, clipped SVG layers opening as clipping layers (#420), PDF/`.ai` layers read on pages of tens of millions of operators (#419), Document Color Mode putting RGB greys on the black plate on request and converting pattern tiles (#421) and movable dialogs with Offset Path's Joins dropdown (#423) and numeric fields scrubbed by dragging their label (#400), stroke weight presets in the stroke unit (#426), the Appearance panel's Opacity popup (#430), type on a path brackets, flip and Type on a Path Options that keep the type in place (#429), Layers rows dragged with a ghost and dropped on the trash or New Layer (#435), tool flyouts opening on a right or corner press (#436), tool flyouts torn off into floating toolbars (#437), the Shape Builder's erase mode deleting edges too (#439), installed fonts registered outside the font folders and fonts installed while the app runs listed in the font menus (#443), alike circular corners on rectangles that aren't square (#442), tool cursors as OS cursors so the pointer no longer trails over the canvas (#444), artboards copied and pasted with their art (#446), guides dragged out of the rulers snapping to the art's side midpoints and the artboards, artboard guides (#451), the toolbar's double arrow and Window › Toolbars › Double Column switching between one and two columns in any window height (#455), the Smart Guides display options and Snapping Tolerance (#394), Font Size and Leading combo boxes with preset lists in the Character and Properties panels and the Control bar (#458), screenshots pasted from the clipboard on macOS, Windows and the web (#457), the Properties panel's Fill and Stroke matching the Control bar's, Illustrator's Window menu panel keys (Shift+F7 for Align…) and Alt-wheel zoom whatever the wheel preference (Discord feedback), the point/area type widget (Discord feedback), groups in legacy Illustrator .ai files (Discord feedback), a rotating desktop log file (#465), image controls in the Control bar and Properties panel: Image Trace with its presets, Mask, Crop Image, Embed/Unembed, and an Image Trace object's preset, Expand and Release (Discord feedback), the Pen working as the Anchor Point tool with Alt held over a selected path's handles and anchors, and anchor buttons that convert, connect and cut paths at the selected anchors (Discord feedback), Japanese hanging punctuation (burasagari, #463), Escape leaving Presentation Mode with no screen mode saved across restarts, documents dropped on the desktop app opening as tabs of their own and a note that an `.ai` file's art off its artboards isn't in the part read (#472), Add/Delete Anchor Point tool icons drawn from the Pen tool's (#479), EPS import running more of PostScript Level 3 (patterns, Type 3 fonts, mesh shadings, masked images, VM and resource probes), and a preview that stands in saying why (Discord feedback, #466, #469, #474), chords with modifiers recorded in Edit › Keyboard Shortcuts (#487), Type Object Selection by Path Only (#394), Anti-aliased Artwork (#394), Show Pixel Grid (#394), pen and touch taps pressed and lifted within one frame clicking where they tapped and the Linux/Wayland pen-tablet workaround (#491), bounding-box resizes landing on the other objects' anchors and centres with labels, and the Rotate, Scale, Shear and Reflect tools snapping their drags (#482), Shift-drag marquees that toggle the objects or anchors they reach and a Lasso whose Alt subtraction keeps the rest of the selection (#483), the mouse wheel stepping the focused numeric field, the dialogs' and preferences' drag values made such fields (#485), Show The Home Screen When No Documents Are Open (#394), Numbers Without Units Are Points (#394), Auto-Collapse Iconic Panels (#394), the Contextual Task Bar moved by its handle and its More Options menu pinning and resetting its position, a designed macOS DMG windoLine truncated
|
||||
_Last updated: 2026-10-09 (after placed documents (File › Place of a `.vectorcraft` file, linked), M4.14–M4.98, M8.1–M8.20, M14.4–M14.7, the MCP prompts, resource templates, completions and logging, the 2026-10-07 issue fixes, the Layers panel rework and the 2026-10-08 community contributions: Pen and shape-tool modifiers, path editing, Layers, Artboards, Swatches/Brushes and dialogs, Japanese composition and PDF text, Hebrew/Arabic type, interface languages (Spanish among them), the font menu, saved selections, MCP and EPS, the missing-font export warning (#319), open paths in the Shape Builder (#374), PDF/`.ai` import keeping strokes live and hidden and nested layers (#372), per-corner Live Corners (#381), SVG type opening at the size it draws at (#396), the Wayland clipboard with copied-file paste (#398), ruler guides that can be selected, moved and deleted (#414), two batches of Preferences options that were stored but unused (#394), skeleton reads with `document.find` for large documents over MCP (#416) and anchors dragged with Direct Selection snapping to points, segments and smart guides, clipped SVG layers opening as clipping layers (#420), PDF/`.ai` layers read on pages of tens of millions of operators (#419), Document Color Mode putting RGB greys on the black plate on request and converting pattern tiles (#421) and movable dialogs with Offset Path's Joins dropdown (#423) and numeric fields scrubbed by dragging their label (#400), stroke weight presets in the stroke unit (#426), the Appearance panel's Opacity popup (#430), type on a path brackets, flip and Type on a Path Options that keep the type in place (#429), Layers rows dragged with a ghost and dropped on the trash or New Layer (#435), tool flyouts opening on a right or corner press (#436), tool flyouts torn off into floating toolbars (#437), the Shape Builder's erase mode deleting edges too (#439), installed fonts registered outside the font folders and fonts installed while the app runs listed in the font menus (#443), alike circular corners on rectangles that aren't square (#442), tool cursors as OS cursors so the pointer no longer trails over the canvas (#444), artboards copied and pasted with their art (#446), guides dragged out of the rulers snapping to the art's side midpoints and the artboards, artboard guides (#451), the toolbar's double arrow and Window › Toolbars › Double Column switching between one and two columns in any window height (#455), the Smart Guides display options and Snapping Tolerance (#394), Font Size and Leading combo boxes with preset lists in the Character and Properties panels and the Control bar (#458), screenshots pasted from the clipboard on macOS, Windows and the web (#457), the Properties panel's Fill and Stroke matching the Control bar's, Illustrator's Window menu panel keys (Shift+F7 for Align…) and Alt-wheel zoom whatever the wheel preference (Discord feedback), the point/area type widget (Discord feedback), groups in legacy Illustrator .ai files (Discord feedback), a rotating desktop log file (#465), image controls in the Control bar and Properties panel: Image Trace with its presets, Mask, Crop Image, Embed/Unembed, and an Image Trace object's preset, Expand and Release (Discord feedback), the Pen working as the Anchor Point tool with Alt held over a selected path's handles and anchors, and anchor buttons that convert, connect and cut paths at the selected anchors (Discord feedback), Japanese hanging punctuation (burasagari, #463), Escape leaving Presentation Mode with no screen mode saved across restarts, documents dropped on the desktop app opening as tabs of their own and a note that an `.ai` file's art off its artboards isn't in the part read (#472), Add/Delete Anchor Point tool icons drawn from the Pen tool's (#479), EPS import running more of PostScript Level 3 (patterns, Type 3 fonts, mesh shadings, masked images, VM and resource probes), and a preview that stands in saying why (Discord feedback, #466, #469, #474), chords with modifiers recorded in Edit › Keyboard Shortcuts (#487), Type Object Selection by Path Only (#394), Anti-aliased Artwork (#394), Show Pixel Grid (#394), pen and touch taps pressed and lifted within one frame clicking where they tapped and the Linux/Wayland pen-tablet workaround (#491), bounding-box resizes landing on the other objects' anchors and centres with labels, and the Rotate, Scale, Shear and Reflect tools snapping their drags (#482), Shift-drag marquees that toggle the objects or anchors they reach and a Lasso whose Alt subtraction keeps the rest of the selection (#483), the mouse wheel stepping the focused numeric field, the dialogs' and preferences' drag values made such fields (#485), Show The Home Screen When No Documents Are Open (#394), Numbers Without Units Are Points (#394), Auto-Collapse Iconic Panels (#394), the Contextual Task Bar moved by its handle and its More Options menu pinning and resetting its position, a designed macOS DMG windoLine truncated
|
||||
|
||||
## Where we are
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ fn font_list(_: &mut Session, p: &Value) -> Result<Value> {
|
||||
}
|
||||
}
|
||||
|
||||
fn rescan(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
pub(crate) fn rescan(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
let db = vectorcraft_text::FontDb::global();
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let faces = db.load_system_fonts();
|
||||
@@ -283,6 +283,21 @@ fn rescan(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// Type › Options › Additional Fonts Folder (#683) adds its folder to the system font scan,
|
||||
/// trimmed; clearing it takes the folder out again.
|
||||
#[test]
|
||||
fn the_additional_fonts_folder_joins_the_font_scan() {
|
||||
let mut s = Session::new();
|
||||
let dir = std::env::temp_dir().join("vectorcraft-fonts-folder-pref");
|
||||
s.execute("prefs.set", &json!({"key": "fontsFolder", "value": format!(" {} ", dir.display())})).unwrap();
|
||||
assert_eq!(vectorcraft_text::user_font_dirs(), std::slice::from_ref(&dir));
|
||||
if !cfg!(target_arch = "wasm32") {
|
||||
assert!(vectorcraft_text::system_font_dirs().contains(&dir));
|
||||
}
|
||||
s.execute("prefs.set", &json!({"key": "fontsFolder", "value": ""})).unwrap();
|
||||
assert!(vectorcraft_text::user_font_dirs().is_empty() && !vectorcraft_text::system_font_dirs().contains(&dir));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_flag_missing_replace_and_select() {
|
||||
let mut s = Session::new();
|
||||
|
||||
@@ -187,6 +187,7 @@ pub const PREF_SPECS: &[PrefSpec] = &[
|
||||
p!("missingGlyphProtection", "Type", "Options", "Enable Missing Glyph Protection", bool),
|
||||
p!("highlightAlternateGlyphs", "Type", "Options", "Highlight Alternate Glyphs", bool),
|
||||
p!("placeholderText", "Type", "Options", "Fill New Type Objects With Placeholder Text", bool),
|
||||
p!("fontsFolder", "Type", "Options", "Additional Fonts Folder", text),
|
||||
// Units
|
||||
p!("unitsGeneral", "Units", "", "General", choice(UNITS)),
|
||||
p!("unitsStroke", "Units", "", "Stroke", choice(UNITS)),
|
||||
@@ -460,7 +461,18 @@ impl Session {
|
||||
let grid_changed = p.gridline_every != self.prefs.gridline_every || p.grid_subdivisions != self.prefs.grid_subdivisions;
|
||||
let history_changed = p.history_states != self.prefs.history_states;
|
||||
let tile_edge_changed = p.pattern_tile_edge_color != self.prefs.pattern_tile_edge_color;
|
||||
let fonts_folder_changed = p.fonts_folder != self.prefs.fonts_folder;
|
||||
self.prefs = p;
|
||||
if fonts_folder_changed {
|
||||
let folder = self.prefs.fonts_folder.trim();
|
||||
vectorcraft_text::set_user_font_dirs(if folder.is_empty() { vec![] } else { vec![folder.into()] });
|
||||
// Once the fonts were scanned, scan again now: the folder's fonts appear (or go) in the
|
||||
// font menus, and type in them lays out again. The first scan reads it anyway.
|
||||
if vectorcraft_text::FontDb::global().installed_fonts_changed() {
|
||||
// Its result only counts the faces cataloged.
|
||||
let _ = super::fonts::rescan(self, &serde_json::Value::Null);
|
||||
}
|
||||
}
|
||||
vectorcraft_render::set_default_threads(u16::try_from(self.prefs.render_threads).ok());
|
||||
for st in &mut self.docs {
|
||||
if history_changed {
|
||||
|
||||
@@ -480,6 +480,9 @@ pub struct Prefs {
|
||||
// Hyphenation
|
||||
pub hyphenation_language: String,
|
||||
pub hyphenation_exceptions: String,
|
||||
/// Type › Options › Additional Fonts Folder: a folder (read with its subfolders) whose fonts
|
||||
/// are listed and used as if installed (#683); empty for none.
|
||||
pub fonts_folder: String,
|
||||
// Performance & Storage (Plug-ins & Scratch Disks)
|
||||
pub plugins_folder: String,
|
||||
pub scratch_primary: String,
|
||||
@@ -696,6 +699,7 @@ impl Default for Prefs {
|
||||
slice_line_color: s("#ff3f3f"),
|
||||
hyphenation_language: s("English: USA"),
|
||||
hyphenation_exceptions: String::new(),
|
||||
fonts_folder: String::new(),
|
||||
plugins_folder: String::new(),
|
||||
scratch_primary: s("Startup"),
|
||||
scratch_secondary: s("None"),
|
||||
|
||||
@@ -878,6 +878,31 @@ pub fn set_platform_font_files(list: PlatformFontFiles) {
|
||||
let _ = list;
|
||||
}
|
||||
|
||||
/// Folders the user adds to the font scan (Preferences › Type › Additional Fonts Folder, #683),
|
||||
/// read with their subfolders after the platform's.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
static USER_FONT_DIRS: std::sync::RwLock<Vec<PathBuf>> = std::sync::RwLock::new(Vec::new());
|
||||
|
||||
/// Have [`system_font_dirs`] also read `dirs` (#683), so the fonts in them are listed and used as
|
||||
/// if installed. The next check for installed fonts ([`FontDb::installed_fonts_changed`]) then
|
||||
/// reports the change, and a scan catalogs them.
|
||||
pub fn set_user_font_dirs(dirs: Vec<PathBuf>) {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
*USER_FONT_DIRS.write().unwrap_or_else(std::sync::PoisonError::into_inner) = dirs;
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let _ = dirs;
|
||||
}
|
||||
|
||||
/// The folders [`set_user_font_dirs`] added (none on wasm).
|
||||
pub fn user_font_dirs() -> Vec<PathBuf> {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
return USER_FONT_DIRS.read().unwrap_or_else(std::sync::PoisonError::into_inner).clone();
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
/// The platform's font folders (the system's and the user's) and the font files known to it
|
||||
/// outside them (on Windows those registered with it, and those [`set_platform_font_files`]
|
||||
/// lists), scanned by [`FontDb::global`].
|
||||
@@ -926,6 +951,7 @@ pub fn system_font_dirs() -> Vec<PathBuf> {
|
||||
let files = fonts_outside(list(), &dirs);
|
||||
dirs.extend(files);
|
||||
}
|
||||
dirs.extend(user_font_dirs());
|
||||
dirs
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ pub mod thread;
|
||||
pub use craft_fonts::{CRAFT_FONTS, CraftFont};
|
||||
pub use features::{LIGATURE_TRACKING_LIMITS, OtFeatures, explicit_ligatures, ligatures_suppressed_by};
|
||||
pub use fontdb::{
|
||||
FALLBACK_FAMILY, FontClass, FontDb, FontFace, FontMatch, FontTraits, IcfMargins, PlatformFontFiles, set_platform_font_files, style_weight,
|
||||
system_font_dirs,
|
||||
FALLBACK_FAMILY, FontClass, FontDb, FontFace, FontMatch, FontTraits, IcfMargins, PlatformFontFiles, set_platform_font_files, set_user_font_dirs,
|
||||
style_weight, system_font_dirs, user_font_dirs,
|
||||
};
|
||||
use kurbo::{Affine, BezPath, Point, Rect, Vec2};
|
||||
pub use layout::{layout, layout_with};
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
Add to Swatches Agregar a muestras
|
||||
Add Used Colors Agregar colores usados
|
||||
Additional Plug-ins Folder Carpeta de plugins adicionales
|
||||
Additional Fonts Folder Carpeta de fuentes adicionales
|
||||
Adjust Adjoining Width Points Ajustar puntos de anchura contiguos
|
||||
Adjust Color Balance… Ajustar equilibrio de color…
|
||||
Adjust Colors Ajustar colores
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -77,6 +77,7 @@
|
||||
Add to Swatches Ajouter au nuancier
|
||||
Add Used Colors Ajouter les couleurs utilisées
|
||||
Additional Plug-ins Folder Dossier de modules externes supplémentaires
|
||||
Additional Fonts Folder Dossier de polices supplémentaires
|
||||
Adjust Adjoining Width Points Ajuster les points de largeur adjacents
|
||||
Adjust Color Balance… Régler la balance des couleurs…
|
||||
Adjust Colors Régler les couleurs
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -76,6 +76,7 @@
|
||||
Add to Swatches Aggiungi ai campioni
|
||||
Add Used Colors Aggiungi colori usati
|
||||
Additional Plug-ins Folder Cartella plug-in aggiuntivi
|
||||
Additional Fonts Folder Cartella font aggiuntivi
|
||||
Adjust Adjoining Width Points Regola punti di larghezza adiacenti
|
||||
Adjust Color Balance… Regola bilanciamento colore…
|
||||
Adjust Colors Regola colori
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -724,6 +724,7 @@
|
||||
Add to Selection 選択範囲に追加
|
||||
Add to Swatches スウォッチに追加
|
||||
Additional Plug-ins Folder 追加プラグインフォルダー
|
||||
Additional Fonts Folder 追加フォントフォルダー
|
||||
Adjust Adjoining Width Points 隣接する幅ポイントを調整
|
||||
Adjust Colors カラーを調整
|
||||
Adjust Options: 調整オプション:
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -138,6 +138,7 @@
|
||||
Add to Selection Adicionar à Seleção
|
||||
Add to Swatches Adicionar às Amostras
|
||||
Additional Plug-ins Folder Pasta Adicional de Plug-ins
|
||||
Additional Fonts Folder Pasta Adicional de Fontes
|
||||
Adjust Adjoining Width Points Ajustar Pontos de Largura Adjacentes
|
||||
Adjust Color Balance… Ajustar Equilíbrio de Cores…
|
||||
Adjust Colors Ajustar Cores
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -74,6 +74,7 @@
|
||||
Add to Swatches Добавить в образцы
|
||||
Add Used Colors Добавить использованные цвета
|
||||
Additional Plug-ins Folder Папка дополнительных модулей
|
||||
Additional Fonts Folder Папка дополнительных шрифтов
|
||||
Adjust Adjoining Width Points Настроить смежные точки ширины
|
||||
Adjust Color Balance… Настроить цветовой баланс…
|
||||
Adjust Colors Настроить цвета
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -79,6 +79,7 @@
|
||||
Add to Swatches 添加到色板
|
||||
Add Used Colors 添加已用颜色
|
||||
Additional Plug-ins Folder 附加增效工具文件夹
|
||||
Additional Fonts Folder 附加字体文件夹
|
||||
Adjust Adjoining Width Points 调整相邻宽度点
|
||||
Adjust Color Balance… 调整色彩平衡…
|
||||
Adjust Colors 调整颜色
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -87,6 +87,7 @@
|
||||
Add to Swatches 新增至色票
|
||||
Add Used Colors 新增使用中的顏色
|
||||
Additional Plug-ins Folder 額外的增效模組資料夾
|
||||
Additional Fonts Folder 額外的字體資料夾
|
||||
Adjust Adjoining Width Points 調整相鄰寬度點
|
||||
Adjust Color Balance… 調整色彩平衡…
|
||||
Adjust Colors 調整顏色
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
Reference in new issue
Block a user