Brushes: built-in Bristle Brushes library with one bristle brush for each tip shape

Window > Brush Libraries > Bristle Brushes holds ten original bristle
brushes generated in code, one for each tip shape: Fine Liner, Pointed
Flat, Stubby Round, Dry Scrub, Soft Dome, Filbert, Angled Round, Angled
Flat, Fan Blender and Grass Fan. Their names and values are VectorCraft's
own, and every value lies inside the range the bristle brush keeps.

A test checks the ranges, that every tip shape is covered, that no name
matches a default brush or another library's brush, that adding the
library is one undo step and a second add adds nothing, and that a saved
library reopens with the same brushes. The library and brush names have
rows in every catalog. docs/mcp.md lists the library.
This commit is contained in:
dotCooCoo
2026-11-11 18:33:53 -08:00
parent 7f3a046b18
commit 123c9b5e7d
34 changed files with 413 additions and 14 deletions
+29 -1
View File
@@ -11,7 +11,9 @@ use std::collections::HashSet;
use std::sync::{Arc, LazyLock};
use serde_json::{Value, json};
use vectorcraft_brush::{self as brush, ArtBrush, Brush, BrushKind, Calligraphic, Colorization, PatternBrush, PatternFit, Scatter, Variation};
use vectorcraft_brush::{
self as brush, ArtBrush, Bristle, BristleShape, Brush, BrushKind, Calligraphic, Colorization, PatternBrush, PatternFit, Scatter, Variation,
};
use vectorcraft_color::{Color, Paint};
use vectorcraft_doc::{Appearance, AppearanceItem, Document, FillLayer, Node, NodeId, NodeKind, PatternDef, Symbol};
use vectorcraft_geom::{Affine, FillRule, PathData, Point, Rect, SubPath, shapes};
@@ -169,6 +171,7 @@ pub struct BuiltinBrushLibrary {
pub const BUILTIN: &[BuiltinBrushLibrary] = &[
BuiltinBrushLibrary { id: "art-ribbons", name: "Art Ribbons", make: art_ribbons },
BuiltinBrushLibrary { id: "calligraphic-nibs", name: "Calligraphic Nibs", make: calligraphic_nibs },
BuiltinBrushLibrary { id: "bristle-brushes", name: "Bristle Brushes", make: bristle_brushes },
BuiltinBrushLibrary { id: "pattern-borders", name: "Pattern Borders", make: pattern_borders },
BuiltinBrushLibrary { id: "scatter-shapes", name: "Scatter Shapes", make: scatter_shapes },
BuiltinBrushLibrary { id: "game-trails", name: "Game Trails", make: game_trails },
@@ -290,6 +293,31 @@ fn calligraphic_nibs() -> BrushLibrary {
built("Calligraphic Nibs", Document::new(100.0, 100.0), brushes)
}
/// A bristle brush: `shape`, then size (pt), bristle length, density, thickness, paint opacity
/// and stiffness (%).
fn bristle(name: &str, shape: BristleShape, [size, length, density, thickness, opacity, stiffness]: [f64; 6]) -> Brush {
Brush { name: name.into(), kind: BrushKind::Bristle(Bristle { shape, size, length, density, thickness, opacity, stiffness }) }
}
/// Bristle Brushes: one bristle brush for each tip shape, from a fine liner to wide fans for
/// blending and texture.
fn bristle_brushes() -> BrushLibrary {
use BristleShape::*;
let brushes = vec![
bristle("Fine Liner", RoundPoint, [2.0, 140.0, 30.0, 30.0, 90.0, 75.0]),
bristle("Pointed Flat", FlatPoint, [5.0, 120.0, 55.0, 35.0, 80.0, 60.0]),
bristle("Stubby Round", RoundBlunt, [8.0, 60.0, 70.0, 50.0, 85.0, 80.0]),
bristle("Dry Scrub", FlatBlunt, [10.0, 40.0, 25.0, 60.0, 60.0, 95.0]),
bristle("Soft Dome", RoundCurve, [12.0, 160.0, 85.0, 20.0, 45.0, 25.0]),
bristle("Filbert", FlatCurve, [9.0, 110.0, 65.0, 40.0, 70.0, 45.0]),
bristle("Angled Round", RoundAngle, [7.0, 130.0, 50.0, 35.0, 75.0, 55.0]),
bristle("Angled Flat", FlatAngle, [11.0, 100.0, 60.0, 45.0, 80.0, 65.0]),
bristle("Fan Blender", RoundFan, [16.0, 220.0, 40.0, 15.0, 35.0, 20.0]),
bristle("Grass Fan", FlatFan, [20.0, 260.0, 15.0, 25.0, 65.0, 35.0]),
];
built("Bristle Brushes", Document::new(100.0, 100.0), brushes)
}
fn border(name: &str, side: Node, corner: Option<Node>, fit: PatternFit) -> Brush {
let kind = BrushKind::Pattern(PatternBrush { side, outer_corner: corner.clone(), inner_corner: corner, fit, ..Default::default() });
Brush { name: name.into(), kind }
+75 -3
View File
@@ -104,7 +104,7 @@ fn the_builtin_libraries_are_original_brushes_generated_in_code() {
let list = run(&mut s, "brush.libraries", json!({}));
let libs = list["libraries"].as_array().unwrap();
let ids: Vec<&str> = libs.iter().map(|l| l["id"].as_str().unwrap()).collect();
assert_eq!(ids, ["art-ribbons", "calligraphic-nibs", "pattern-borders", "scatter-shapes", "game-trails", "energy-beams"]);
assert_eq!(ids, ["art-ribbons", "calligraphic-nibs", "bristle-brushes", "pattern-borders", "scatter-shapes", "game-trails", "energy-beams"]);
assert!(libs.iter().all(|l| l["category"] == "builtIn"));
let lib = run(&mut s, "brush.library", json!({"library": "art ribbons"}));
assert_eq!(
@@ -117,13 +117,13 @@ fn the_builtin_libraries_are_original_brushes_generated_in_code() {
trails["brushes"].as_array().unwrap().iter().map(|b| b["name"].as_str().unwrap()).collect::<Vec<_>>(),
["Speed Line", "Dash Trail", "Burst Ray", "Zigzag"]
);
assert_eq!(libs[4]["count"].as_u64(), Some(4));
assert_eq!(libs[5]["count"].as_u64(), Some(4));
let beams = run(&mut s, "brush.library", json!({"library": "energy-beams"}));
assert_eq!(
beams["brushes"].as_array().unwrap().iter().map(|b| b["name"].as_str().unwrap()).collect::<Vec<_>>(),
["Laser Bolt", "Plasma Arc", "Charge Wave", "Spark Trail"]
);
assert_eq!(libs[5]["count"].as_u64(), Some(4));
assert_eq!(libs[6]["count"].as_u64(), Some(4));
run(&mut s, "file.new", json!({"width": 200, "height": 200}));
let id = run(&mut s, "shape.rectangle", json!({"x": 10, "y": 20, "width": 40, "height": 8}))["id"].as_u64().unwrap();
let added = run(&mut s, "brush.addFromLibrary", json!({"library": "energy-beams", "name": "Laser Bolt", "apply": true, "ids": [id]}));
@@ -132,6 +132,7 @@ fn the_builtin_libraries_are_original_brushes_generated_in_code() {
for (id, kind) in [
("art-ribbons", "art"),
("calligraphic-nibs", "calligraphic"),
("bristle-brushes", "bristle"),
("pattern-borders", "pattern"),
("scatter-shapes", "scatter"),
("game-trails", "art"),
@@ -165,6 +166,77 @@ fn the_builtin_libraries_are_original_brushes_generated_in_code() {
assert!(s.execute("brush.library", &json!({"library": "nope"})).is_err());
}
/// Bristle Brushes: one brush per tip shape, every value inside the range the brush keeps (a value
/// outside would be clamped without notice), names no other library or default brush uses; added
/// in one step, not twice, and saved as a library they reopen unchanged.
#[test]
fn the_bristle_brushes_library_covers_every_tip_shape_within_the_bristle_ranges() {
use vectorcraft_brush::{Bristle, BristleShape};
let mut s = session();
let (_, lib) = cmd::brushlib::library(&s, "bristle-brushes").unwrap();
assert_eq!(lib.name, "Bristle Brushes");
let names: Vec<String> = lib.brushes.iter().map(|b| b.name.clone()).collect();
assert!((8..=10).contains(&names.len()), "{names:?}");
let within = |v: f64, (lo, hi): (f64, f64)| (lo..=hi).contains(&v);
let mut shapes = vec![];
for b in &lib.brushes {
let BrushKind::Bristle(x) = &b.kind else { panic!("{} is not a bristle brush", b.name) };
assert!(within(x.size, Bristle::SIZE_RANGE) && within(x.length, Bristle::LENGTH_RANGE), "{}", b.name);
for v in [x.density, x.thickness, x.opacity, x.stiffness] {
assert!(within(v, Bristle::PERCENT_RANGE), "{}: {v}", b.name);
}
let mut kept = b.clone();
kept.sanitize();
assert_eq!(&kept, b, "sanitizing changes {}", b.name);
assert!(b.name.chars().count() <= Bristle::MAX_NAME_CHARS, "{}", b.name);
if !shapes.contains(&x.shape) {
shapes.push(x.shape);
}
}
let every = [
BristleShape::RoundPoint,
BristleShape::FlatPoint,
BristleShape::RoundBlunt,
BristleShape::FlatBlunt,
BristleShape::RoundCurve,
BristleShape::FlatCurve,
BristleShape::RoundAngle,
BristleShape::FlatAngle,
BristleShape::RoundFan,
BristleShape::FlatFan,
];
assert!(every.iter().all(|x| shapes.contains(x)), "{shapes:?}");
// Names of its own: no default brush's, no other built-in library's, none twice.
let defaults: Vec<&str> = vectorcraft_brush::defaults().iter().map(|b| b.name.as_str()).collect();
let others: Vec<String> = cmd::brushlib::BUILTIN
.iter()
.filter(|b| b.id != "bristle-brushes")
.flat_map(|b| cmd::brushlib::library(&s, b.id).unwrap().1.brushes.iter().map(|x| x.name.clone()).collect::<Vec<_>>())
.collect();
for (i, n) in names.iter().enumerate() {
assert!(!defaults.contains(&n.as_str()) && !others.contains(n) && !names[..i].contains(n), "{n}");
}
// Added to a document in one undo step; adding them again adds nothing.
let before = (undo_len(&s), brushes(&s));
let r = run(&mut s, "brush.addFromLibrary", json!({"library": "Bristle Brushes"}));
assert_eq!(strs(&r["added"]), names.iter().map(String::as_str).collect::<Vec<_>>());
assert_eq!(undo_len(&s), before.0 + 1);
assert_eq!(brushes(&s), [before.1.clone(), names.clone()].concat());
for b in &lib.brushes {
assert_eq!(&brush(&s, &b.name), b);
}
let again = undo_len(&s);
let r = run(&mut s, "brush.addFromLibrary", json!({"library": "bristle-brushes"}));
assert_eq!((strs(&r["added"]).len(), strs(&r["existing"]).len(), undo_len(&s)), (0, names.len(), again));
// Saved as a library and loaded back: the same brushes, in the same order.
let saved = run(&mut s, "brush.saveLibrary", json!({ "names": names, "name": "Bristles" }));
let b64 = saved["dataBase64"].as_str().unwrap().to_string();
let r = run(&mut s, "brush.loadLibrary", json!({"dataBase64": b64, "name": "Bristles.vectorcraft"}));
let (_, reopened) = cmd::brushlib::library(&s, r["library"].as_str().unwrap()).unwrap();
assert_eq!(reopened.brushes, lib.brushes);
}
#[test]
fn a_saved_library_reopens_and_its_brushes_join_another_document_in_one_step() {
let dir = folder("user");
+11
View File
@@ -5974,6 +5974,17 @@ axis Y Axis Y ос
Charge Wave Вълна на заряд
Spark Trail Следа от искри
Calligraphic Nibs Калиграфски писци
Bristle Brushes Четки с косъм
Fine Liner Тънък контур
Pointed Flat Заострена плоска
Stubby Round Къса кръгла
Dry Scrub Сухо търкане
Soft Dome Мек купол
Filbert Плоска овална
Angled Round Скосена кръгла
Angled Flat Скосена плоска
Fan Blender Ветрило за смесване
Grass Fan Ветрило за трева
Pattern Borders Бордюри с мостри
Scatter Shapes Разсеяни фигури
Save Brush Library… Запази библиотека с четки…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -6024,6 +6024,17 @@ axis Y Axis Y osa
Charge Wave Talas naboja
Spark Trail Trag iskri
Calligraphic Nibs Kaligrafski vrhovi
Bristle Brushes Četkice s čekinjama
Fine Liner Tanka linija
Pointed Flat Šiljata ravna
Stubby Round Kratka okrugla
Dry Scrub Suho trljanje
Soft Dome Meka kupola
Filbert Ovalna ravna
Angled Round Kosa okrugla
Angled Flat Kosa ravna
Fan Blender Lepeza za stapanje
Grass Fan Lepeza za travu
Pattern Borders Ivice od uzoraka
Scatter Shapes Raspršeni oblici
Save Brush Library… Sačuvaj biblioteku četkica…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -607,6 +607,17 @@ antiAlias Sharp Nítid
Calligraphic Brush Pinzell cal·ligràfic
Calligraphic Brush Options Opcions del pinzell cal·ligràfic
Calligraphic Nibs Plomes cal·ligràfiques
Bristle Brushes Pinzells de cerres
Fine Liner Traç fi
Pointed Flat Pla punxegut
Stubby Round Rodó curt
Dry Scrub Fregat sec
Soft Dome Cúpula suau
Filbert Llengua de gat
Angled Round Rodó bisellat
Angled Flat Pla bisellat
Fan Blender Ventall difuminador
Grass Fan Ventall d'herba
Can't export “{name}”. No es pot exportar “{name}”.
Can't open “{name}”. No es pot obrir “{name}”.
Can't print these settings: see the Summary No es poden imprimir aquests paràmetres: consulta el resum
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -6209,6 +6209,17 @@ axis Y Axis osa Y
Charge Wave Nabíjecí vlna
Spark Trail Jiskrová stopa
Calligraphic Nibs Kaligrafická pera
Bristle Brushes Štětinové štětce
Fine Liner Jemná linka
Pointed Flat Špičatý plochý
Stubby Round Krátký kulatý
Dry Scrub Suché drhnutí
Soft Dome Měkká kopule
Filbert Plochý oválný
Angled Round Šikmý kulatý
Angled Flat Šikmý plochý
Fan Blender Vějíř na prolínání
Grass Fan Vějíř na trávu
Pattern Borders Vzorkové okraje
Scatter Shapes Rozptýlené tvary
Save Brush Library… Uložit knihovnu štětců…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -5989,6 +5989,17 @@ axis Y Axis Y-akse
Charge Wave Opladningsbølge
Spark Trail Gnistsvær
Calligraphic Nibs Kalligrafiske penne
Bristle Brushes Børstepensler
Fine Liner Fin streg
Pointed Flat Spids flad
Stubby Round Kort rund
Dry Scrub Tør skrubning
Soft Dome Blød kuppel
Filbert Oval flad
Angled Round Skrå rund
Angled Flat Skrå flad
Fan Blender Blendevifte
Grass Fan Græsvifte
Pattern Borders Mønsterborter
Scatter Shapes Spredte former
Save Brush Library… Gem penselbibliotek…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -5792,6 +5792,17 @@ axis Y Axis Y-Achse
Charge Wave Ladewelle
Spark Trail Funkenspur
Calligraphic Nibs Kalligrafie-Federn
Bristle Brushes Borstenpinsel-Set
Fine Liner Feiner Liner
Pointed Flat Spitzer Flachpinsel
Stubby Round Kurzer Rundpinsel
Dry Scrub Trockenes Schrubben
Soft Dome Weiche Kuppel
Filbert Katzenzunge
Angled Round Schräger Rundpinsel
Angled Flat Schräger Flachpinsel
Fan Blender Fächer zum Verblenden
Grass Fan Grasfächer
Pattern Borders Musterbordüren
Scatter Shapes Streuformen
Save Brush Library… Pinsel-Bibliothek speichern…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -6160,6 +6160,17 @@ axis Y Axis Άξονας Y
Charge Wave Κύμα φόρτισης
Spark Trail Ίχνος σπινθήρων
Calligraphic Nibs Καλλιγραφικές πένες
Bristle Brushes Πινέλα με τρίχες
Fine Liner Λεπτή γραμμή
Pointed Flat Μυτερό πλακέ
Stubby Round Κοντό στρογγυλό
Dry Scrub Ξηρό τρίψιμο
Soft Dome Μαλακός θόλος
Filbert Γλώσσα γάτας
Angled Round Λοξό στρογγυλό
Angled Flat Λοξό πλακέ
Fan Blender Βεντάλια ανάμειξης
Grass Fan Βεντάλια για γρασίδι
Pattern Borders Περιθώρια μοτίβου
Scatter Shapes Σχήματα διασποράς
Save Brush Library… Αποθήκευση βιβλιοθήκης πινέλων…
Can't render this file because it is too large.
+11
View File
@@ -6151,6 +6151,17 @@ axis Y Axis Eje Y
Charge Wave Onda de carga
Spark Trail Estela de chispas
Calligraphic Nibs Plumillas caligráficas
Bristle Brushes Pinceles de cerdas
Fine Liner Delineador fino
Pointed Flat Plano puntiagudo
Stubby Round Redondo corto
Dry Scrub Frotado seco
Soft Dome Cúpula suave
Filbert Lengua de gato
Angled Round Redondo biselado
Angled Flat Plano biselado
Fan Blender Abanico difuminador
Grass Fan Abanico de hierba
Pattern Borders Bordes de motivo
Scatter Shapes Formas de dispersión
Save Brush Library… Guardar biblioteca de pinceles…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -6239,6 +6239,17 @@ axis Y Axis Y-akseli
Charge Wave Latausaalto
Spark Trail Kipinävanne
Calligraphic Nibs Kalligrafiakärjet
Bristle Brushes Harjassiveltimet
Fine Liner Ohut viiva
Pointed Flat Suippo litteä
Stubby Round Lyhyt pyöreä
Dry Scrub Kuiva hankaus
Soft Dome Pehmeä kupu
Filbert Kissankieli
Angled Round Vino pyöreä
Angled Flat Vino litteä
Fan Blender Sekoitusviuhka
Grass Fan Ruohoviuhka
Pattern Borders Kuvioreunukset
Scatter Shapes Sirontamuodot
Save Brush Library… Tallenna sivellinkirjasto…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -6204,6 +6204,17 @@ axis Y Axis Axe Y
Charge Wave Vague de charge
Spark Trail Traînée d'étincelles
Calligraphic Nibs Plumes calligraphiques
Bristle Brushes Pinceaux à soies
Fine Liner Traceur fin
Pointed Flat Plat pointu
Stubby Round Rond court
Dry Scrub Frottis sec
Soft Dome Dôme doux
Filbert Langue de chat
Angled Round Rond biseauté
Angled Flat Plat biseauté
Fan Blender Éventail estompeur
Grass Fan Éventail à herbe
Pattern Borders Bordures de motif
Scatter Shapes Formes de dispersion
Save Brush Library… Enregistrer la bibliothèque de formes…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -689,6 +689,17 @@ antiAlias Sharp शार्प
Calligraphic Brush कैलिग्राफिक ब्रश
Calligraphic Brush Options कैलिग्राफिक ब्रश ऑप्शन्स
Calligraphic Nibs कैलिग्राफिक निब्स
Bristle Brushes ब्रिसल ब्रश संग्रह
Fine Liner बारीक लाइनर
Pointed Flat नुकीला फ्लैट
Stubby Round छोटा गोल
Dry Scrub सूखी रगड़
Soft Dome मुलायम गुंबद
Filbert फिल्बर्ट
Angled Round तिरछा गोल
Angled Flat तिरछा फ्लैट
Fan Blender मिश्रण पंखा
Grass Fan घास पंखा
Can't export “{name}”. "{name}" निर्यात नहीं कर सकते।
Can't open “{name}”. "{name}" नहीं खोल सकते हैं।
Can't print these settings: see the Summary इन सेटिंग्स को मुद्रित नहीं कर सकते: सारांश देखें
Can't render this file because it is too large.
+11
View File
@@ -6192,6 +6192,17 @@ axis Y Axis Y tengely
Charge Wave Töltéshullám
Spark Trail Szikracsík
Calligraphic Nibs Kalligrafikus tollhegyek
Bristle Brushes Sörteecsetek
Fine Liner Finom kontúr
Pointed Flat Hegyes lapos
Stubby Round Rövid kerek
Dry Scrub Száraz dörzsölés
Soft Dome Lágy kupola
Filbert Macskanyelv
Angled Round Ferde kerek
Angled Flat Ferde lapos
Fan Blender Elmosó legyező
Grass Fan Fűlegyező
Pattern Borders Mintázatszegélyek
Scatter Shapes Szórt alakzatok
Save Brush Library… Ecsetkönyvtár mentése…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -5989,6 +5989,17 @@ axis Y Axis Sumbu Y
Charge Wave Gelombang Muatan
Spark Trail Jejak Percikan
Calligraphic Nibs Pena kaligrafi
Bristle Brushes Kuas-kuas bristle
Fine Liner Garis halus
Pointed Flat Pipih runcing
Stubby Round Bulat pendek
Dry Scrub Gosok kering
Soft Dome Kubah lembut
Filbert Pipih oval
Angled Round Bulat miring
Angled Flat Pipih miring
Fan Blender Kipas pembaur
Grass Fan Kipas rumput
Pattern Borders Bingkai pola
Scatter Shapes Bentuk sebar
Save Brush Library… Simpan pustaka kuas…
Can't render this file because it contains an unexpected character in line 2328 and column 5.
+11
View File
@@ -5826,6 +5826,17 @@ axis Y Axis Asse Y
Charge Wave Onda di carica
Spark Trail Scia di scintille
Calligraphic Nibs Pennini calligrafici
Bristle Brushes Pennelli a setole
Fine Liner Tratto fine
Pointed Flat Piatto appuntito
Stubby Round Tondo corto
Dry Scrub Strofinato secco
Soft Dome Cupola morbida
Filbert Lingua di gatto
Angled Round Tondo obliquo
Angled Flat Piatto obliquo
Fan Blender Ventaglio sfumino
Grass Fan Ventaglio per erba
Pattern Borders Bordi a motivo
Scatter Shapes Forme a dispersione
Save Brush Library… Salva libreria pennelli…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -5891,6 +5891,17 @@ axis Y Axis Y 軸
Charge Wave チャージウェーブ
Spark Trail スパークトレイル
Calligraphic Nibs カリグラフィペン先
Bristle Brushes 剛毛ブラシ集
Fine Liner 細線ライナー
Pointed Flat 先細平筆
Stubby Round 短丸筆
Dry Scrub ドライスクラブ
Soft Dome ソフトドーム
Filbert フィルバート
Angled Round 斜め丸筆
Angled Flat 斜め平筆
Fan Blender ぼかし扇筆
Grass Fan 草描き扇筆
Pattern Borders パターンボーダー
Scatter Shapes 散布シェイプ
Save Brush Library… ブラシライブラリを保存…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -6160,6 +6160,17 @@ axis Y Axis Y ღერძი
Charge Wave მუხტის ტალღა
Spark Trail ნაპერწკლის კვალი
Calligraphic Nibs კალიგრაფიული წვერები
Bristle Brushes ჯაგრის ფუნჯები
Fine Liner წვრილი ხაზი
Pointed Flat წაწვეტებული ბრტყელი
Stubby Round მოკლე მრგვალი
Dry Scrub მშრალი ხეხვა
Soft Dome რბილი გუმბათი
Filbert ოვალური ბრტყელი
Angled Round დახრილი მრგვალი
Angled Flat დახრილი ბრტყელი
Fan Blender შერევის მარაო
Grass Fan ბალახის მარაო
Pattern Borders პატერნის ბორდიურები
Scatter Shapes გაბნეული ფიგურები
Save Brush Library… ფუნჯების ბიბლიოთეკის შენახვა…
Can't render this file because it is too large.
+11
View File
@@ -5787,6 +5787,17 @@ axis Y Axis Y축
Charge Wave 차지 웨이브
Spark Trail 스파크 트레일
Calligraphic Nibs 서예 펜촉
Bristle Brushes 강모 브러시 모음
Fine Liner 가는 라이너
Pointed Flat 뾰족한 평붓
Stubby Round 짧은 둥근 붓
Dry Scrub 마른 문지르기
Soft Dome 부드러운 돔
Filbert 필버트
Angled Round 사선 둥근 붓
Angled Flat 사선 평붓
Fan Blender 블렌딩 부채붓
Grass Fan 잔디 부채붓
Pattern Borders 패턴 테두리
Scatter Shapes 흩뿌리기 모양
Save Brush Library… 브러시 라이브러리 저장…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -6040,6 +6040,17 @@ axis Y Axis Y-as
Charge Wave Laadgolf
Spark Trail Vonkenspoor
Calligraphic Nibs Kalligrafische penpunten
Bristle Brushes Borstelpenselen
Fine Liner Fijne liner
Pointed Flat Spitse platte
Stubby Round Korte ronde
Dry Scrub Droog schrobben
Soft Dome Zachte koepel
Filbert Kattentong
Angled Round Schuine ronde
Angled Flat Schuine platte
Fan Blender Vervloeiwaaier
Grass Fan Graswaaier
Pattern Borders Patroonranden
Scatter Shapes Strooivormen
Save Brush Library… Penseelbibliotheek opslaan…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -6063,6 +6063,17 @@ axis Y Axis Oś Y
Charge Wave Fala ładunku
Spark Trail Ślad iskier
Calligraphic Nibs Stalówki kaligraficzne
Bristle Brushes Pędzle włosiankowe
Fine Liner Cienka linia
Pointed Flat Szpiczasty płaski
Stubby Round Krótki okrągły
Dry Scrub Suche szorowanie
Soft Dome Miękka kopuła
Filbert Koci język
Angled Round Skośny okrągły
Angled Flat Skośny płaski
Fan Blender Wachlarz do mieszania
Grass Fan Wachlarz do trawy
Pattern Borders Obramowania wzorków
Scatter Shapes Kształty rozproszone
Save Brush Library… Zapisz bibliotekę pędzli…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -6124,6 +6124,17 @@ axis Y Axis Eixo Y
Charge Wave Onda de carga
Spark Trail Rastro de faíscas
Calligraphic Nibs Penas Caligráficas
Bristle Brushes Pincéis de Cerdas
Fine Liner Traço Fino
Pointed Flat Chato Pontudo
Stubby Round Redondo Curto
Dry Scrub Esfregado Seco
Soft Dome Cúpula Suave
Filbert Língua de Gato
Angled Round Redondo Chanfrado
Angled Flat Chato Chanfrado
Fan Blender Leque Esfumador
Grass Fan Leque de Grama
Pattern Borders Bordas de Padrão
Scatter Shapes Formas de Dispersão
Save Brush Library… Salvar Biblioteca de Pincéis…
Can't render this file because it contains an unexpected character in line 6 and column 47.
+11
View File
@@ -5820,6 +5820,17 @@ axis Y Axis Ось Y
Charge Wave Волна заряда
Spark Trail Искра-след
Calligraphic Nibs Каллиграфические перья
Bristle Brushes Щетинные кисти
Fine Liner Тонкий лайнер
Pointed Flat Заострённая плоская
Stubby Round Короткая круглая
Dry Scrub Сухое растирание
Soft Dome Мягкий купол
Filbert Кошачий язык
Angled Round Скошенная круглая
Angled Flat Скошенная плоская
Fan Blender Веер для растушёвки
Grass Fan Веер для травы
Pattern Borders Узорные каймы
Scatter Shapes Рассеянные фигуры
Save Brush Library… Сохранить библиотеку кистей…
Can't render this file because it is too large.
+11
View File
@@ -6232,6 +6232,17 @@ axis Y Axis Y-axel
Charge Wave Laddningsvåg
Spark Trail Gnistsvår
Calligraphic Nibs Kalligrafiska pennspetsar
Bristle Brushes Borstpenslar
Fine Liner Fin linje
Pointed Flat Spetsig platt
Stubby Round Kort rund
Dry Scrub Torr skrubbning
Soft Dome Mjuk kupol
Filbert Oval platt
Angled Round Sned rund
Angled Flat Sned platt
Fan Blender Blandande solfjäder
Grass Fan Grässolfjäder
Pattern Borders Mönsterbårder
Scatter Shapes Spridningsformer
Save Brush Library… Spara penselbibliotek…
Can't render this file because it contains an unexpected character in line 5 and column 25.
+11
View File
@@ -6165,6 +6165,17 @@ axis Y Axis Y ekseni
Charge Wave Şarj Dalgası
Spark Trail Kıvılcım İzi
Calligraphic Nibs Kaligrafi Uçları
Bristle Brushes Kıl Fırçalar
Fine Liner İnce Çizgi
Pointed Flat Sivri Düz
Stubby Round Kısa Yuvarlak
Dry Scrub Kuru Ovma
Soft Dome Yumuşak Kubbe
Filbert Kedi Dili
Angled Round Eğik Yuvarlak
Angled Flat Eğik Düz
Fan Blender Harmanlama Yelpazesi
Grass Fan Çim Yelpazesi
Pattern Borders Desen Kenarlıkları
Scatter Shapes Dağılım Şekilleri
Save Brush Library… Fırça Kitaplığını Kaydet…
Can't render this file because it contains an unexpected character in line 5 and column 25.
+11
View File
@@ -5806,6 +5806,17 @@ axis Y Axis Вісь Y
Charge Wave Хвиля заряду
Spark Trail Слід іскор
Calligraphic Nibs Каліграфічні пера
Bristle Brushes Щетинні пензлі
Fine Liner Тонкий лайнер
Pointed Flat Загострений плаский
Stubby Round Короткий круглий
Dry Scrub Сухе розтирання
Soft Dome М'який купол
Filbert Котячий язик
Angled Round Скошений круглий
Angled Flat Скошений плаский
Fan Blender Віяло для розтушовування
Grass Fan Віяло для трави
Pattern Borders Візерункові облямівки
Scatter Shapes Розсіяні фігури
Save Brush Library… Зберегти бібліотеку пензлів…
Can't render this file because it contains an unexpected character in line 182 and column 5.
+11
View File
@@ -5807,6 +5807,17 @@ axis Y Axis Trục Y
Charge Wave Sóng nạp
Spark Trail Vệt tia lửa
Calligraphic Nibs Ngòi bút thư pháp
Bristle Brushes Bộ cọ lông
Fine Liner Nét mảnh
Pointed Flat Cọ dẹt nhọn
Stubby Round Cọ tròn ngắn
Dry Scrub Chà khô
Soft Dome Vòm mềm
Filbert Cọ lưỡi mèo
Angled Round Cọ tròn xiên
Angled Flat Cọ dẹt xiên
Fan Blender Cọ quạt hòa trộn
Grass Fan Cọ quạt vẽ cỏ
Pattern Borders Viền họa tiết
Scatter Shapes Hình phân tán
Save Brush Library… Lưu thư viện cọ…
Can't render this file because it contains an unexpected character in line 204 and column 5.
+11
View File
@@ -6047,6 +6047,17 @@ axis Y Axis Y 轴
Charge Wave 充能波
Spark Trail 火花尾迹
Calligraphic Nibs 书法笔尖
Bristle Brushes 鬃毛画笔集
Fine Liner 细勾线笔
Pointed Flat 尖头平笔
Stubby Round 短圆笔
Dry Scrub 干擦
Soft Dome 柔和圆顶
Filbert 榛形笔
Angled Round 斜圆笔
Angled Flat 斜平笔
Fan Blender 混色扇形笔
Grass Fan 画草扇形笔
Pattern Borders 图案边框
Scatter Shapes 散布形状
Save Brush Library… 保存画笔库…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+11
View File
@@ -5844,6 +5844,17 @@ axis Y Axis Y 軸
Charge Wave 充能波
Spark Trail 火花尾跡
Calligraphic Nibs 書法筆尖
Bristle Brushes 鬃毛筆刷集
Fine Liner 細勾線筆
Pointed Flat 尖頭平筆
Stubby Round 短圓筆
Dry Scrub 乾擦
Soft Dome 柔和圓頂
Filbert 榛形筆
Angled Round 斜圓筆
Angled Flat 斜平筆
Fan Blender 混色扇形筆
Grass Fan 畫草扇形筆
Pattern Borders 圖樣邊框
Scatter Shapes 散佈形狀
Save Brush Library… 儲存筆刷資料庫…
Can't render this file because it contains an unexpected character in line 6 and column 47.
@@ -132,6 +132,7 @@ fn the_window_menu_and_the_brushes_panel_open_brush_libraries() {
[
json!("art-ribbons"),
json!("calligraphic-nibs"),
json!("bristle-brushes"),
json!("pattern-borders"),
json!("scatter-shapes"),
json!("game-trails"),
+3 -3
View File
@@ -630,8 +630,8 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
libraries ([public source](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/apply-and-edit-strokes/create-new-brush-libraries.html),
[import](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/apply-and-edit-strokes/import-brushes-from-brush-libraries-or-other-files.html)):
Window › Brush Libraries and the Brushes panel's Brush Libraries Menu open each library in a library panel of
its own (six original libraries generated in code: Art Ribbons, Calligraphic Nibs, Pattern Borders, Scatter
Shapes, Game Trails and Energy Beams; User Defined; Other Library… reads the brushes of any document VectorCraft opens); a
its own (seven original libraries generated in code: Art Ribbons, Calligraphic Nibs, Bristle Brushes (one
bristle brush for each tip shape), Pattern Borders, Scatter Shapes, Game Trails and Energy Beams; User Defined; Other Library… reads the brushes of any document VectorCraft opens); a
click adds a
brush to the document's Brushes with the patterns, symbols and other resources its art uses, as one undo
step (applied to the selected paths in the same step), dragging one onto a path adds and applies it and
@@ -649,7 +649,7 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
Game HUD with Health Fill, Mana Glow, Damage Flash, Quest Outline, Coin Shine and Boss Alert, and Status Effects
with Poison Tint, Freeze Edge, Burn Aura, Stun Pulse, Stealth Fade and Shield Buff; User Defined; Other
Library…; `graphicStyle.libraries`, `graphicStyle.addFromLibrary`).
- **Missing:** more built-in brush libraries beyond the six shipped (and further graphic-style libraries beyond the eight shipped, and further symbol libraries beyond Basic
- **Missing:** more built-in brush libraries beyond the seven shipped (and further graphic-style libraries beyond the eight shipped, and further symbol libraries beyond Basic
Shapes, UI Frames, Map Markers, Inventory Icons and Skill Icons; original, generated in code, never Adobe's); dynamic symbols' `.ai` read and write;
Global Edit of groups holding type or images, rotated copies as matches and highlighting matches before the
start; 9-slice guides outside the symbol's art (a dragged guide stops at the art's edge).
+2 -2
View File
@@ -3223,8 +3223,8 @@ error.
## Brush libraries
Brush libraries are read-only sets of brushes: six generated in code (Art Ribbons, Calligraphic Nibs, Pattern
Borders, Scatter Shapes, Game Trails, Energy Beams), the `.vectorcraft` files in the user library folder of the desktop app (User
Brush libraries are read-only sets of brushes: seven generated in code (Art Ribbons, Calligraphic Nibs, Bristle
Brushes with one bristle brush for each tip shape, Pattern Borders, Scatter Shapes, Game Trails, Energy Beams), the `.vectorcraft` files in the user library folder of the desktop app (User
Defined) and the brushes of any document loaded with `brush.loadLibrary` (a document without brushes of its own has
the default ones). `brush.libraries` lists them (`id`, `name`, `category`: `builtIn`, `user` or `loaded`, `count`) and
`brush.library {library}` returns one's brushes (`name`, `type`; `library` is an id or a name).
+1 -1
View File
@@ -149,7 +149,7 @@ native wording review, layout checks and a web Devanagari font remain. [Notes](l
| M7 | Type (point/area/path, editing, styles, OpenType, threading, glyphs) | Spell check engine: `text.spelling.check` and `text.spelling.suggest` on craft-proof and the custom dictionary and Ignore All commands and Auto Spell Check with its right-click suggestions, Ignore All and Add to Dictionary, and Spelling › Auto Spell Check in the context menu of type, and the Edit Custom Dictionary dialog (#4936; the Check Spelling dialog remains); Right-aligned area type sets the text after a line's last tab against the right edge, the text before it at its stops (#6147); A line a soft return ends is justified as a wrapped line is (#6137); Indian-language pattern hyphenation preserves syllables in both composers (#4947); 🟡 Hanging punctuation keeps its published amounts under Glyph Scaling, and Standard burasagari counts a hung line start as room; Fullwidth `!` / `?` keep an upright fallback in vertical type; Hyphenation… and Justification… per paragraph (#2310, #2755), Auto Leading also driving the Character panel's Leading, the Alt+↑/↓ leading nudge and Fill with Placeholder Text; Document-point character controls after object/group scaling (#1034; optional font-size preservation remains separate), Character/Paragraph Styles (explicit Auto-leading resets and local leading overrides), per-paragraph paragraph attributes, mixed paragraph alignment indication (headless regressions, full integration CI and visual review pass), Area Type Options (with Width/Height, Auto Size and Shrink Text to Fit; overflow reported to agents and vertical Align), type areas resized by their handles and reshaped with Direct Selection, threaded text, Fit Headline, Glyphs, OpenType panel (including font-defined Stylistic Sets), Find Font (Document, Recent and System replacement sources, #5217), installed system fonts in every font menu (fonts registered with Windows outside its font folders, the XDG and Flatpak host font folders on Linux, and fonts installed while the app runs, listed when it comes back to the front; searchable; the Character and Properties menus show each family's sample of the selected text, preview it live under the pointer or ↑/↓, show recently applied families first (#3515), filter by script and kind, list a family's styles, and star favourites; the Glyphs panel and Find Font's Replace With use the same menu without the live preview) and found by name on open/import (full-name aliases and Missing Fonts searches verified, #1258; Windows font-service QA pending), variable fonts' named instances as styles, CJK names in the UI, input methods (marked text in place, candidate window at the caret; Japanese IME), Text Wrap (offset, invert, both sides of an object; follows edits), Type on a Path effects and Options with draggable start/centre/end brackets (slide, flip), tab stops + Tabs panel (Above Text floats it over the selected text, its ruler at the canvas zoom so stops line up with the columns, #729), inline symbols in text (beyond parity), Hebrew/Arabic bidirectional text, Paragraph Direction, Every-line/Single-line Composer per object (ragged text too) done; paint-only Arabic harakat keep joining with GDEF-mark ownership and Insert Kashidas tatweels on the base letter's paint (`tests::harakat`); tab leaders, spell check, vertical type pending | 45–60 |
| M8 | Transform & distort (Puppet Warp, Liquify tools, Envelopes, Blends, Perspective Grid) | ✅ done (M8.1–M8.20 on 2026-10-06, fidelity pass): Liquify Tool Options with one shared brush, pen pressure, hold-to-apply, a safe scope and incremental strokes; tool options that last; Puppet Warp rotation, multi-select, Control bar and a rest-shape session that follows Undo; Width tool on compound paths; Envelope dialogs with preview, Reset with Warp/Mesh, full Envelope Options, type/images/symbols/appearance/gradients/patterns distorted on canvas and in every export, warps that keep their frame, Edit Contents, mesh handles and Control bar; Blend Options, anchor-targeted Blend tool, editable spine, keys picked on the canvas, faithful interpolation and knockout; Anchor Point spine conversion/handle editing and selection priority (#2544), with #2425 Shift reshape preserved; Perspective Grid with Define Grid, presets, lock/snap/rulers, widgets, the 1–4 plane switch, movable planes, Perspective Selection scale/copy/perpendicular/Transform Again, and type and symbols truly projected with Edit Text. Left: Anti-Alias and Preserve Shape output, warp-envelope point editing, brush interpolation in blends, Free Transform/Scale/Reflect along a rotated box | 2–4 |
| M9 | Live effects (+ 3D & Materials) | 🟡 2D effects done incl. Effect → Pathfinder, Color Adjustments and Document Raster Effects Settings; PDF export warns when the pixel cap lowers raster-effect resolution; Artistic › Colored Pencil, Cutout, Dry Brush, Film Grain, Fresco, Neon Glow, Paint Daubs, Palette Knife, Poster Edges, Rough Pastels, Smudge Stick, Sponge, Underpainting and Watercolor and Sketch › Halftone Pattern, Bas Relief, Charcoal, Conté Crayon, Photocopy, Stamp, Torn Edges and Water Paper done (57/57 Photoshop filters); Revolve with automatic smooth vector shading, default-on circular caps and continuous rims, Extrude & Bevel, Inflate and Rotate with one to ten colored directional lights and four original lighting presets; SVG Filters, remaining raster effects and 3D materials and shadows pending | 81–130 |
| M10 | Brushes, symbols, patterns, Repeat | 🟡 pattern swatches (5 tile types, Pattern Options, editing mode, SVG `<pattern>`/PDF export) and live Repeat (radial/grid/mirror) done; interactive selected mirror axis implemented (focused and native checks passed; full CI blocked by an unrelated text test); symbol libraries done (Window › Symbol Libraries, five generated libraries (Basic Shapes, UI Frames, Map Markers, Inventory Icons, Skill Icons), User Defined, Other Library…, Save Symbols); brush libraries done (Window › Brush Libraries, six generated libraries, User Defined, Other Library…, Save Brushes); symbol editing shows draggable 9-slice guides (#5280), with guides outside the artwork still unsupported; brushes/symbols in progress | 23–37 |
| M10 | Brushes, symbols, patterns, Repeat | 🟡 pattern swatches (5 tile types, Pattern Options, editing mode, SVG `<pattern>`/PDF export) and live Repeat (radial/grid/mirror) done; interactive selected mirror axis implemented (focused and native checks passed; full CI blocked by an unrelated text test); symbol libraries done (Window › Symbol Libraries, five generated libraries (Basic Shapes, UI Frames, Map Markers, Inventory Icons, Skill Icons), User Defined, Other Library…, Save Symbols); brush libraries done (Window › Brush Libraries, seven generated libraries including Bristle Brushes, User Defined, Other Library…, Save Brushes); symbol editing shows draggable 9-slice guides (#5280), with guides outside the artwork still unsupported; brushes/symbols in progress | 23–37 |
| M11 | Artboards & views (selected-set deletion shared by Artboards menu, trash and Properties, retaining artboard 1 when all are selected; Artboard deletion keys keep the first of an all-selected set and protect artwork; history prunes invalid indices while preserving valid multiselection (history tests and full workspace CI pass); click-to-fit objects with the Artboard tool (#1227), artboard escape routing and document setup modal handoff done; artboard panel/tool with Move Artwork for X/Y fields and Artboard Options, Trim View, middle-button pan, print tiling and the status bar's artboard navigator with synchronized Artboard tool selection done; Window › Arrange › Tile and Consolidate All Windows done; multiple windows, presentation polish) (cached canvas reprojection preserves scale during resize, rotation and DPI changes; regression-tested and contributor-confirmed 2026-10-19; estimates unchanged) (cached canvas dimensions match the renderer limit before cache-key creation, view construction and worker submission; regression-tested; estimates unchanged); status-bar pointer coordinates follow the active ruler origin and General units | 🟡; Artboard Options shares existing presets and orientation controls and can fit artwork without moving it; artwork fitting includes all drawn document art across artboards and off-board; artwork bounds are cached by active document and revision, and selection uses the shared bounds cache across artboards | 15–25 |
| M12 | Advanced color & art (CMYK/ICC, separations, Gradient Mesh, Live Paint, Image Trace, Graphs) | 🟡 Gradient Mesh, Live Paint, Image Trace (junction-returning pieces retain their positioned boundaries; a simpler contour walk with identical output; an edge's sub-pixel shift is the same from either side; notches read only their own piece; collapsed loops keep few segments; large images trace with a warning; Auto Color keeps rare distinct colours; quick presets trace at once and the Image Trace button opens the adjustment controls; Properties reopens them; tiny fitted contours retain islands and holes; Create Strokes: exact crop EDT, Guo–Hall thinning and maximal-disc graph simplification; 15 presets, the 14 documented ones each with an enhanced version; Ignore Color, Shapes, Auto Grouping and Gradients options; measured in `image-trace-quality.md`; closed outlines retain their interior after straightening; the Flat Logo mode places edges to a fraction of a pixel, restores sharp corners, snaps lines and circles, and refuses gradients; live trace result bounds and selection highlights exclude the retained bitmap except in source-image views), Recolor Artwork, colour management (ICC, soft proofing, separations preview), Graphs (all 9 tools, Graph Data/Type, group-selected series colours persist through regenerate/save/open) done; Graph Design and Marker designs, Transpose and Switch x/y, `\|` label line breaks, the pie options, drop shadows, the legend across the top, overlapping widths, First Row/Column in Front, filled lines, kept label formatting and the Graph Data worksheet done; graph Column designs pending; Vector Halftone Preview keeps the selection box without drawing dot selection marks (#6369) | 6–10 |
| M13 | Automation (Actions ✅ record/playback, persisted; variables, scripting, batch) | 🟡 MCP `add_text` exposes existing vertical point, area and path type; `script.run` and File › Scripts › Other Script… run JavaScript files, and Window › Script Console shows their output; the script document model and batch work remain | 18–27 |
+5 -4
View File
@@ -218,7 +218,7 @@ dominate; 3D, graphs and automation are specialist). They sum to 105. Feature de
| Drawing tools (Pen, Curvature, Pencil, shapes, Shaper) | 7 | 85% | Shaper construction widget, Pencil/Pen nuances, Blob Brush options, Touch Type, Dimension tool; see [ui-parity.md](ui-parity.md) | 8–13 | estimated; Curvature point display regression-tested (#1236, in part); Polygon/Star exact-size count persistence regression-covered; Live Corners' Relative rounding done (#3091), score unchanged; Copy and Cut with the Pen or Curvature tool take the anchors a Cmd/Ctrl-lent Direct Selection picked (#6123), score and hours unchanged |
| Path operations, Pathfinder, Shape Builder, Live Paint | 5 | 80% | Shape Builder on the reporter's file (#937: art past 4,096 segments is cut by lines again; unconfirmed on the file itself); gap detection shares Live Paint’s finder, with a 72 pt custom cap and the existing options; Live Paint Gap Options | 4–8 | estimated; Shape Builder Gap Detection shares Live Paint’s spatial gap finder and temporary merge bridges (#2526); Custom is capped at 72 pt in the existing options dialog (lowered from 86%: open issues); compound attributes regression-tested (#1197); single-result source names survive SVG export/import (#1293), with [SVG ID semantics](https://www.w3.org/TR/SVG2/struct.html#IDAttribute) and original-shape tests; Simplify component selection and preview regression-tested (#1272); Simplify of a Direct Selection part of a path regression-tested (`tests/simplify_part.rs`); Divide open-cutting-path geometry and appearance regression-tested (#1307); the Shape Builder's edge-source grid is bounded in memory and files a segment once per cell (`planar.rs` test `rect_index_holds_a_bounded_number_of_references`); live compound shapes (Make, Alt-click, member Shape Modes, Release, Expand, saved and exported) regression-tested (#4522) |
| Colour, swatches, gradients, patterns, mesh, recolor | 7 | 92% | 30.0's gradient additions are done (dither, perceptual blending, presets); freeform gradients in SVG/PDF, mixed spot/process gradients in SVG, PDF gradients mixing a spot color with RGB or Lab stops, and dithered spot gradient fills and Perceptual spot gradients with RGB or Lab stops other than white or more than 4,096 stops on their curve, which PDF export writes as images in process colors | 4–7 | estimated; Recolor model selection is available through the engine and MCP (#2520), and the dialog's color sliders (HSB, RGB, CMYK, Lab, Tint for a spot color) edit the selected row's new color in its mode, and the Edit tab's Global Adjust sliders (Saturation, Brightness, Temperature, Luminosity, -100% to 100%) change every recolored color at once (lowered from 96%: target moved); unpainted zero-width stroke restoration fixed (#1253), score and hours unchanged; Eyedropper source reads regression-tested (#1251); screen-bounded Recolor Edit chip list (#3416), score and hours unchanged |
| Strokes, brushes, width profiles | 5 | 88% | Shift-double-click adjoining adjustment is implemented; brush libraries are done (six generated libraries including Game Trails and Energy Beams, User Defined, Other Library…, Save Brushes); Art brush Overlap and Pattern brush auto corners are done; remaining: pen pressure on macOS, Stylus Wheel, more built-in brush libraries, tilt, bearing and rotation for Art, Pattern and Bristle brushes and on native Wayland and the web | 8–15 | estimated; width-point creation and adjoining adjustment regression-tested; dialog layout reviewed; evidence below; finite-arithmetic follow-up regressions and full CI passed (evidence below) |
| Strokes, brushes, width profiles | 5 | 88% | Shift-double-click adjoining adjustment is implemented; brush libraries are done (seven generated libraries including Bristle Brushes, Game Trails and Energy Beams, User Defined, Other Library…, Save Brushes); Art brush Overlap and Pattern brush auto corners are done; remaining: pen pressure on macOS, Stylus Wheel, more built-in brush libraries, tilt, bearing and rotation for Art, Pattern and Bristle brushes and on native Wayland and the web | 8–15 | estimated; width-point creation and adjoining adjustment regression-tested; dialog layout reviewed; evidence below; finite-arithmetic follow-up regressions and full CI passed (evidence below) |
| Appearance, transparency, graphic styles, masks | 5 | 97% | raster effect reach in preview bounds | 1–2 | estimated; Transform typing, sliders, preview, and undo are covered in `crates/ui-egui/src/panels/tests_appearance.rs` |
| 3D and Materials (and Turntable) | 4 | ~25% | live Revolve with automatic smooth vector shading and default-on continuous circular caps, Extrude & Bevel (twist, taper, caps, five bevel shapes), Inflate and Rotate with Position presets (colored Inflate uses smooth membrane lighting; white-light Inflate retains its existing shading; Extrude & Bevel and Rotate retain planar shading; one to ten colored lights, shared neutral ambient, painter visibility); materials, light presets, shadows, ray tracing, the rest of 3D Classic (Revolve, Rotate, Map Art), Turntable views, textures, map art and shading in 3D export | 30–55 | estimated (Extrude & Bevel, Inflate and Rotate added 2026-10-12) |
| Type core | 9 | 80% | Auto-leading style resets are implemented; Hyphenation… and Justification… options are done (#2310, #2755), and a paragraph's Auto Leading also sets the Character panel's Leading, the Alt+↑/↓ leading nudge and Fill with Placeholder Text; remaining: Optical Margin Alignment, Middle Eastern features beyond bidi layout, optional group font-size preservation; transformed character controls fixed (#1034), see [type-parity.md](type-parity.md) | 14–19 | estimated; eleven-language pattern hyphenation in both composers, with grapheme and shaping-cluster protection (#4947, `hyphen::tests` and `layout::wrapping_tests`); Sanskrit patterns pending an allowlisted source; recent-font groups in font pickers (#3515); full-name font matches regression-tested (#1258); mixed paragraph alignment indication implemented; headless regressions, full integration CI and visual review pass; localized legacy family-name fallback with loaded/catalog regressions (#2208); Fractional Widths per type object regression-tested; color emoji fonts with bitmap glyphs (`sbix`, `CBDT`) draw and export; threading ports: every selected area type and type on a path shows its in and out ports (empty, arrow, red "+"), and the Selection tool threads from either, the in port into a frame before it, and a double-click on a threaded port breaks the thread there (`threads::tests::break_splits_the_thread_and_the_story_flows_into_the_first_part`, `select::tests::a_double_click_on_a_threaded_port_breaks_the_thread`, `canvas::tests::a_double_click_on_a_threaded_out_port_breaks_the_thread`) (#2572; `select::tests::a_click_on_the_in_port_threads_into_a_frame_before_it`, `text::tests::selected_type_shows_its_ports_in_each_state`, `threads::tests::add_before_threads_the_story_from_the_new_frame_into_the_clicked_one`, live screenshot); the Glyphs panel highlights and scrolls to the character selected with the Type tool (#4908, `panels::glyphs` tests); the OpenType panel lists only `ss01`–`ss20` sets present in the selected font and uses its custom names when supplied; Type-range desktop Copy publishes styled art and keeps font family, size and color on canvas Paste after editing (#5636); paint-only Arabic harakat keep joining with conditional GDEF-mark ownership and Insert Kashidas base-letter paint (`tests::harakat`) |
@@ -487,7 +487,7 @@ about 1–1.5 agent-hours each, so the other rows (estimated on the older scale)
| Drawing tools | 7 | 86% | rough-square Shaper recognition and orientation steps corrected; editable Shaper Groups landed; Pencil: Alt key toggles to Smooth Tool (#2001); remaining: Shaper construction widget/gesture refinements, pencil and the remaining pen modifier nuances, Blob Brush Merge Only with Selection, Touch Type, Live Corners' Relative rounding | 7–12 |
| Path operations, Pathfinder, Shape Builder, Live Paint | 5 | 86% | Live Paint gap options, Shape Builder gap detection, options (Tool Options dialog, clicking a stroke in merge mode) and Shift-drag marquee | 3–6 |
| Colour, swatches, gradients, patterns, mesh, recolor | 7 | 96% | freeform gradients in SVG/PDF and mixed spot/process gradients in SVG (exported as stops; PDF export keeps the spot inks in a DeviceN shading, except next to RGB or Lab stops; dithered fills and Perceptual gradients with RGB or Lab stops other than white or more than 4,096 stops on their curve are written as images in process colors), pattern fills in Expand | 2–4; Eyedropper source reads regression-tested (#1251) |
| Strokes, brushes, width profiles | 5 | 90% | more built-in brush libraries (six generated in code including Game Trails and Energy Beams are done; Art brush Overlap and Pattern brush auto corners are done), pen pressure on macOS (the windowing layer reports none there), Stylus Wheel, tilt, bearing and rotation for Art, Pattern and Bristle brushes and on native Wayland and the web | 8–15 |
| Strokes, brushes, width profiles | 5 | 90% | more built-in brush libraries (seven generated in code including Bristle Brushes, Game Trails and Energy Beams are done; Art brush Overlap and Pattern brush auto corners are done), pen pressure on macOS (the windowing layer reports none there), Stylus Wheel, tilt, bearing and rotation for Art, Pattern and Bristle brushes and on native Wayland and the web | 8–15 |
| Appearance, transparency, graphic styles, masks | 5 | 98% | raster effect reach in preview bounds (flattener presets apply in PDF, EPS and print) | 1–2 |
| Live vector effects | 5 | 85% | Outline Object, Pathfinder Hard/Soft Mix and Trap (since done: #3061, #3063, #3785), SVG Filters, Transform Patterns and Scale Strokes & Effects on a fill's or stroke's own Transform effect | 6–10 |
| 3D and Materials | 4 | ~25% | Initial Revolve, Extrude & Bevel, Inflate and Rotate, with simple lighting; materials, light presets, shadows, ray tracing, Revolve (Classic), Rotate (Classic), Map Art and more complete visibility remain | 25–45 |
@@ -539,7 +539,7 @@ since 2026-10-01.
| **Interaction fidelity:** modifiers, cursors, small behaviours | ~30–40% | The dedicated pass hasn't started, and there has been no side-by-side session with Illustrator yet. A power user notices this first |
| **Look & feel** | ~75–80% | Measured against Illustrator 2026 screenshots (2026-10-02); the panels added since haven't been re-measured |
| **File interop** | ~85% | SVG/SVGZ, PDF and PDF-compatible `.ai` (and legacy version 7 `.ai` out, keeping layers, groups and type as text), EPS, DXF, EMF/WMF, raster formats, PSD export and PSD/PSB placement (merged image), Place and Links, Package, Print, clipboard flavours. Affinity documents (Affinity 1–3) open natively as editable art, checked against 51 pinned public files (33 current `.af`), with selected saved-thumbnail comparisons and every-board native/SVG/PDF/PSD checks for current files; Affinity export is missing and effects, adjustments and brushes don't import. Affinity isn't an Illustrator feature, so this doesn't raise the parity score. The editing copy inside an Illustrator EPS or `.ai` is read for its structure: layers, groups, names, hidden objects and type, colours, gradients, transparency, images and every artboard (see Out of scope for what it doesn't read yet); DWG has no open spec |
| **Bundled content:** brush, symbol, style and swatch libraries | ~46% | Ours are original and generated in code, and far fewer than Illustrator ships; symbol libraries have five (Basic Shapes, UI Frames with default 9-slice, Map Markers, Inventory Icons, Skill Icons), graphic style libraries eight (including Game HUD and Status Effects) and brush libraries six (Art Ribbons, Calligraphic Nibs, Pattern Borders, Scatter Shapes, Game Trails, Energy Beams) beside User Defined and Other Library… |
| **Bundled content:** brush, symbol, style and swatch libraries | ~46% | Ours are original and generated in code, and far fewer than Illustrator ships; symbol libraries have five (Basic Shapes, UI Frames with default 9-slice, Map Markers, Inventory Icons, Skill Icons), graphic style libraries eight (including Game HUD and Status Effects) and brush libraries seven (Art Ribbons, Calligraphic Nibs, Bristle Brushes, Pattern Borders, Scatter Shapes, Game Trails, Energy Beams) beside User Defined and Other Library… |
| **Performance** | unverified | Multithreaded, off-thread rendering and caches are in place. The last budget run (2026-10-01, loaded machine) measured 290 ms for a 50k-path fit against a 16 ms budget. Re-run `vectorcraft-cli perf` on an idle machine |
| **Robustness** | good, new | ~2,840 tests, property tests, no panics in shipped code (lints, the `guard` safety net, import fuzzing), Data Recovery. Missing: a corpus of real-world files, Windows/Linux/browser QA |
| **Platforms and 1.0 polish** | ~60% | The macOS app and the web build work, and Finder opens every readable format with the macOS app (#295, #354); on macOS the menus are in the system menu bar, laid out as a Mac app's, with the in-window menus as a fallback (`--in-window-menus`; verified on Windows and by cross-compilation, not yet by hand on a Mac); hybrid-graphics laptops render on the power-saving GPU by default on Windows and macOS (#306), and Windows starts on Direct3D 12, falling back to OpenGL, and loads no Vulkan driver unless `WGPU_BACKEND` asks for it (#545: Vulkan flickered black on an Intel GPU, DX12 and OpenGL didn't; #806: a faulty Vulkan driver crashed the app before its window appeared; verified by unit tests and the reporter's runs with `WGPU_BACKEND`), and Linux on the GPU the desktop runs on, since a Wayland compositor may refuse frames from the other one; a window that fails on its GPU while starting up starts again on the next one instead of crashing (#502; the dual-GPU Wayland case is verified by unit tests and cross-compilation, not on such hardware); web drops land in the document they were dropped on (#359); desktop drops carry no pointer position (winit 0.30), so a dropped document opens as a tab of its own and a picture or text is placed in the middle of the view, while the web places anything dropped on the canvas and opens what is dropped off it, as Illustrator does (#472); a web page that loses its WebGPU device or WebGL context restarts its graphics with the same documents (#369); on Linux/Wayland the clipboard reads the compositor's own (data-control) and copied image files paste, but files can't be dropped on the window under native Wayland until eframe moves to winit 0.31 (#398; the Wayland side is verified by compilation only), so Preferences › Performance › Linux Display Server › X11 (XWayland) opens the window through XWayland, where drops work (#1151; verified by unit tests and cross-compilation, not on a Wayland desktop); on Linux the Paste menu checks the system clipboard on a background thread, so a clipboard owner that never answers no longer freezes the window, while Windows and macOS keep their quick in-line check (#510; the X11 hang verified by the contributor, here by headless tests); on KDE Plasma 6.3+ under Wayland, pens and pen displays reach the app only under XWayland (`WAYLAND_DISPLAY=`) or with KWin's `KWIN_WAYLAND_EMULATE_TABLET=1`, since winit 0.30 has no Wayland tablet input (#491, not verified on hardware); Windows/Linux packaging and accessibility are pending |
@@ -823,7 +823,8 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- **Expand of symbol instances:** Object › Expand turns selected symbol instances (without effects, not in perspective, in groups or placed documents too) into their art as Break Link to Symbol places it, one level deep, as one undo step; the Expand dialog's Fill and Stroke reach that art (`object.expand`, `crates/engine/src/tests/expand_symbols.rs`; estimated, score unchanged).
- **Reset Transformation** ([Transform symbols](https://helpx.adobe.com/illustrator/desktop/manage-objects/traces-mockups-symbols/transform-symbols.html), [Symbols panel options](https://helpx.adobe.com/illustrator/desktop/manage-objects/traces-mockups-symbols/symbols-panel-options.html)): the Symbols panel menu's Reset Transformation and the Control bar's Reset, shown while symbol instances are selected, give the selected instances their symbol's own scale again, without rotation or shear, as one undo step (`symbol.instance.resetTransform`); an instance in perspective is left as it is. VectorCraft's own rules: each instance keeps the center of its bounding box in place, reflection is removed too, and the menu item and the button are enabled only while a selected instance would change. Tests: `tests::brushsym::reset_transformation_restores_the_symbols_scale_and_keeps_the_center`, `reset_transformation_keeps_the_center_of_art_away_from_the_origin`, `reset_transformation_ignores_a_stored_size_that_is_not_positive`, `reset_transformation_leaves_unchanged_instances_and_refuses_bad_ids`, `panels::symbols::tests::reset_transformation_is_enabled_for_a_transformed_instance_and_resets_it`.
- **Expand of dimensions:** Object › Expand, Expand Appearance, Create Outlines and Outline Stroke turn a dimension whose art they change into a plain group of that art, which stays as it is through later moves, scales and edits of what it measured; undo gives the live dimension back (`crates/engine/tests/it/dimensions.rs`; VectorCraft's own rule; estimated, score unchanged).
- **Brush libraries** ([public source](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/apply-and-edit-strokes/create-new-brush-libraries.html), [import](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/apply-and-edit-strokes/import-brushes-from-brush-libraries-or-other-files.html), [Brushes panel](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/apply-and-edit-strokes/brushes-panel-overview.html)): Window › Brush Libraries, the Brushes panel's Brush Libraries Menu and its menu's Open Brush Library open each library in a library panel of its own, as swatch, graphic style and symbol libraries do. The built-in libraries (Art Ribbons, Calligraphic Nibs, Pattern Borders, Scatter Shapes, Game Trails, Energy Beams) are original brushes generated in code (`crates/engine/src/cmd/brushlib.rs`); Striped Ribbon's art is filled with the library's own pattern and Sparkles scatters the library's own symbol; Game Trails adds motion art brushes (Speed Line, Dash Trail, Burst Ray, Zigzag); Energy Beams adds laser and plasma art brushes (Laser Bolt, Plasma Arc, Charge Wave, Spark Trail). A click on a brush adds it to the document's Brushes as one undo step with every resource its art uses (patterns, symbols, swatches, graphic styles, images), makes it the current brush and, with paths selected, applies it to them in the same step; a brush the document already has is not added again and a different brush of the same name comes in numbered ("Wave 2"). Shift/Cmd-clicks select brushes for Add to Brushes; a brush dragged onto a path is added and applied to it, and one dragged onto the Brushes panel is added. Save Brushes… / the Brushes panel's Save Brush Library… write the document's brushes (or the selected ones) as a `.vectorcraft` library into the `Brushes` folder next to the preferences, listed under User Defined, or to a file; Other Library… reads the brushes of any document VectorCraft opens. Thumbnails, in the library panels, the Brushes panel and Brush Options, render brush art with the patterns and symbols it uses. Copying brushed art now carries the patterns and symbols its brush's art uses too. Tests: `crates/engine/src/tests/brushlib.rs`, `crates/ui-egui/src/panels/tests_brush_libraries.rs`, `panels::brushes::tests::library_brush_previews_show_the_patterns_their_art_uses`, `canvas::tests::a_library_brush_dropped_on_a_path_is_added_and_applied_in_one_step`.
- **Brush libraries** ([public source](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/apply-and-edit-strokes/create-new-brush-libraries.html), [import](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/apply-and-edit-strokes/import-brushes-from-brush-libraries-or-other-files.html), [Brushes panel](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/apply-and-edit-strokes/brushes-panel-overview.html)): Window › Brush Libraries, the Brushes panel's Brush Libraries Menu and its menu's Open Brush Library open each library in a library panel of its own, as swatch, graphic style and symbol libraries do. The built-in libraries (Art Ribbons, Calligraphic Nibs, Bristle Brushes, Pattern Borders, Scatter Shapes, Game Trails, Energy Beams) are original brushes generated in code (`crates/engine/src/cmd/brushlib.rs`); Striped Ribbon's art is filled with the library's own pattern and Sparkles scatters the library's own symbol; Game Trails adds motion art brushes (Speed Line, Dash Trail, Burst Ray, Zigzag); Energy Beams adds laser and plasma art brushes (Laser Bolt, Plasma Arc, Charge Wave, Spark Trail). A click on a brush adds it to the document's Brushes as one undo step with every resource its art uses (patterns, symbols, swatches, graphic styles, images), makes it the current brush and, with paths selected, applies it to them in the same step; a brush the document already has is not added again and a different brush of the same name comes in numbered ("Wave 2"). Shift/Cmd-clicks select brushes for Add to Brushes; a brush dragged onto a path is added and applied to it, and one dragged onto the Brushes panel is added. Save Brushes… / the Brushes panel's Save Brush Library… write the document's brushes (or the selected ones) as a `.vectorcraft` library into the `Brushes` folder next to the preferences, listed under User Defined, or to a file; Other Library… reads the brushes of any document VectorCraft opens. Thumbnails, in the library panels, the Brushes panel and Brush Options, render brush art with the patterns and symbols it uses. Copying brushed art now carries the patterns and symbols its brush's art uses too. Tests: `crates/engine/src/tests/brushlib.rs`, `crates/ui-egui/src/panels/tests_brush_libraries.rs`, `panels::brushes::tests::library_brush_previews_show_the_patterns_their_art_uses`, `canvas::tests::a_library_brush_dropped_on_a_path_is_added_and_applied_in_one_step`.
- **Bristle Brushes library** ([What's new](https://helpx.adobe.com/illustrator/desktop/new-features/whats-new.html), [About brushes](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/apply-and-edit-strokes/about-brushes.html)): Window › Brush Libraries › Bristle Brushes holds ten bristle brushes, one for each tip shape (Fine Liner, Pointed Flat, Stubby Round, Dry Scrub, Soft Dome, Filbert, Angled Round, Angled Flat, Fan Blender, Grass Fan). The brushes, their names and their values are VectorCraft's own, and every value lies inside the range the bristle brush keeps (`brush.libraries`, `brush.addFromLibrary`; `the_bristle_brushes_library_covers_every_tip_shape_within_the_bristle_ranges`).
- A canvas context menu: right-click selects the object under the pointer and lists what applies to the selection (Undo/Redo, clipboard, group, isolation, join, Remove Anchor Points when anchors are selected, masks, compound paths, guides, Transform, Arrange, Select, Export Selection, and on type Bullets and Numbering and Spelling › Auto Spell Check, checked while it is on), or the view commands on empty canvas.
- A right-click over locked objects adds an Unlock submenu to the canvas context menu. The submenu lists up to 20 locked objects under the pointer, topmost first, by the name the Layers panel shows, and choosing one unlocks it (`layer.setProps`). A locked group is listed as one item. Objects on hidden, locked or template layers are not listed.
- Native macOS save sheets offer a localised Format menu (#866), built from the request's existing format filters. It selects the suggested filename's format and updates the suffix when changed, including legacy `.drawcraft` names. `apps/vectorcraft/src/mac_save_format.rs` has filename regressions; an actual native SVG save, selection of PDF and cancellation without changing the saved document were verified.