Merge pull request #6791 from dotCooCoo/feat/styles-painted-sketched-library

Graphic Styles: a built-in Painted and Sketched library adds watercolor, charcoal and ink styles
This commit is contained in:
BFlat
2026-11-12 15:13:39 +07:00
committed by GitHub
34 changed files with 435 additions and 7 deletions
+84
View File
@@ -156,6 +156,7 @@ pub const STYLE_LIBRARIES: &[BuiltinStyleLibrary] = &[
BuiltinStyleLibrary { id: "outlines-rules", name: "Outlines and Rules", make: outlines_rules },
BuiltinStyleLibrary { id: "hand-drawn", name: "Hand-Drawn", make: hand_drawn },
BuiltinStyleLibrary { id: "textures", name: "Textures", make: textures },
BuiltinStyleLibrary { id: "painted-sketched", name: "Painted and Sketched", make: painted_sketched },
BuiltinStyleLibrary { id: "gradient-finishes", name: "Gradient Finishes", make: gradient_finishes },
BuiltinStyleLibrary { id: "shape-effects", name: "Shape Effects", make: shape_effects },
BuiltinStyleLibrary { id: "blends-transparency", name: "Blends and Transparency", make: blends_transparency },
@@ -323,6 +324,59 @@ fn hand_drawn() -> Vec<GraphicStyle> {
]
}
/// Painted and Sketched: one catalog paint or sketch effect over the whole appearance, so it
/// repaints the fill and the stroke together (watercolor, dry brush, pastels, charcoal and ink).
fn painted_sketched() -> Vec<GraphicStyle> {
vec![
style(
"Washed Blue",
vec![F(fill("#8ab9c9"))],
vec![fx("artistic.watercolor", json!({"brushDetail": 8.0, "shadowIntensity": 2.0, "texture": 2.0}))],
),
style(
"Bristle Ochre",
vec![F(fill("#c4975a")), S(stroke("#76533d", 1.0))],
vec![fx("artistic.dryBrush", json!({"brushSize": 4.0, "brushDetail": 7.0, "texture": 2.0}))],
),
style(
"Pastel Heather",
vec![F(fill("#a78ca5"))],
vec![fx(
"artistic.roughPastels",
json!({
"strokeLength": 8.0,
"strokeDetail": 9.0,
"texture": "canvas",
"scaling": 100.0,
"relief": 5.0,
"lightDirection": "topLeft",
"invert": false
}),
)],
),
style(
"Charcoal Shade",
vec![F(fill("#666666"))],
vec![fx("sketch.charcoal", json!({"thickness": 3.0, "detail": 3.0, "lightDarkBalance": 55.0}))],
),
style(
"Ink Contour",
vec![F(fill("#d9e2df")), S(stroke("#26323b", 1.0))],
vec![fx("brushStrokes.inkOutlines", json!({"strokeLength": 6.0, "darkIntensity": 24.0, "lightIntensity": 8.0}))],
),
style(
"Wet Ink",
vec![F(fill("#637b85"))],
vec![fx("brushStrokes.sumiE", json!({"strokeWidth": 7.0, "strokePressure": 5.0, "contrast": 20.0}))],
),
style(
"Fine Pen",
vec![F(fill("#d8d4c6"))],
vec![fx("sketch.graphicPen", json!({"strokeLength": 6.0, "lightDarkBalance": 55.0, "strokeDirection": "rightDiagonal"}))],
),
]
}
/// Textures: fills and strokes painted with the catalog's texture effects (grain, canvas and
/// burlap surfaces, craquelure, tiles, patchwork, stained glass and water paper).
fn textures() -> Vec<GraphicStyle> {
@@ -603,6 +657,36 @@ mod tests {
assert_eq!(ids.iter().position(|&i| i == "textures"), ids.iter().position(|&i| i == "hand-drawn").map(|i| i + 1), "after Hand-Drawn");
}
#[test]
fn painted_and_sketched_follows_textures_with_one_effect_per_style() {
let ids: Vec<&str> = STYLE_LIBRARIES.iter().map(|b| b.id).collect();
let at = ids.iter().position(|&id| id == "painted-sketched").expect("listed");
assert_eq!(ids[at - 1], "textures");
let lib = builtin_style_library("painted-sketched").unwrap();
assert_eq!(lib.name, "Painted and Sketched");
let names: Vec<&str> = lib.styles.iter().map(|g| g.name.as_str()).collect();
assert_eq!(names, ["Washed Blue", "Bristle Ochre", "Pastel Heather", "Charcoal Shade", "Ink Contour", "Wet Ink", "Fine Pen"]);
let effects: Vec<&str> = lib.styles.iter().flat_map(|g| g.appearance.effects.iter().map(|e| e.id.as_str())).collect();
assert_eq!(
effects,
[
"artistic.watercolor",
"artistic.dryBrush",
"artistic.roughPastels",
"sketch.charcoal",
"brushStrokes.inkOutlines",
"brushStrokes.sumiE",
"sketch.graphicPen"
]
);
assert!(lib.styles.iter().all(|g| g.appearance.items.iter().all(|i| i.effects().is_empty())), "no effects on a fill or stroke");
// No other built-in library holds a style of the same name.
for b in STYLE_LIBRARIES.iter().filter(|b| b.id != "painted-sketched") {
let other = builtin_style_library(b.id).unwrap();
assert!(other.styles.iter().all(|g| !names.contains(&g.name.as_str())), "{}", b.id);
}
}
#[test]
fn vcstyles_round_trip() {
let mut lib = (*builtin_style_library("gradient-finishes").unwrap()).clone();
+81
View File
@@ -87,6 +87,87 @@ fn builtin_libraries_are_listed_with_original_styles_using_catalogued_effects()
assert!(s.execute("graphicStyle.library", &json!({"library": "nope"})).is_err());
}
#[test]
fn painted_and_sketched_styles_set_every_effect_setting_and_reopen_applied() {
let mut s = session();
let list = run(&mut s, "graphicStyle.libraries", json!({}));
let libs = list["libraries"].as_array().unwrap();
let at = libs.iter().position(|l| l["id"] == "painted-sketched").expect("listed");
assert_eq!((libs[at]["name"].as_str(), libs[at]["count"].as_u64()), (Some("Painted and Sketched"), Some(7)));
assert_eq!(libs[at - 1]["id"], "textures");
let g = run(&mut s, "graphicStyle.library", json!({"library": "Painted and Sketched"}));
let listed: Vec<(&str, &str, Vec<&str>)> =
g["styles"].as_array().unwrap().iter().map(|x| (x["name"].as_str().unwrap(), x["fill"].as_str().unwrap(), names(&x["effects"]))).collect();
let want = [
("Washed Blue", "#8ab9c9", "artistic.watercolor"),
("Bristle Ochre", "#c4975a", "artistic.dryBrush"),
("Pastel Heather", "#a78ca5", "artistic.roughPastels"),
("Charcoal Shade", "#666666", "sketch.charcoal"),
("Ink Contour", "#d9e2df", "brushStrokes.inkOutlines"),
("Wet Ink", "#637b85", "brushStrokes.sumiE"),
("Fine Pen", "#d8d4c6", "sketch.graphicPen"),
];
assert_eq!(listed, want.iter().map(|&(n, f, e)| (n, f, vec![e])).collect::<Vec<_>>());
// Every setting of each effect is given, with the catalog's key and kind of value.
let (_, lib) = cmd::stylelib::library(&s, "painted-sketched").unwrap();
for st in &lib.styles {
let e = &st.appearance.effects[0];
let defaults = vectorcraft_render::effects::effect_info(&e.id).unwrap().defaults;
let (set, all) = (e.params.as_object().unwrap(), defaults.as_object().unwrap());
let keys = |m: &serde_json::Map<String, Value>| m.keys().cloned().collect::<Vec<_>>();
assert_eq!(keys(set), keys(all), "{}", st.name);
for (k, v) in set {
let kind = |v: &Value| (v.is_number(), v.is_string(), v.is_boolean());
assert_eq!(kind(v), kind(&all[k]), "{} / {k}", st.name);
}
}
let strokes: Vec<(&str, f64)> =
lib.styles.iter().filter(|g| g.appearance.stroke_paint() != Paint::None).map(|g| (g.name.as_str(), g.appearance.stroke_width())).collect();
assert_eq!(strokes, [("Bristle Ochre", 1.0), ("Ink Contour", 1.0)]);
// Each one adds and applies to a rectangle in one undo step.
let mut ids = vec![];
for (i, (name, fill, effect)) in want.iter().enumerate() {
let id = rect(&mut s, 10.0 + 25.0 * i as f64, 20.0, 20.0, 30.0);
let before = undo_len(&s);
let r = run(&mut s, "graphicStyle.addFromLibrary", json!({"library": "painted-sketched", "name": name, "apply": true, "ids": [id.0]}));
assert_eq!((names(&r["added"]), r["applied"].as_str()), (vec![*name], Some(*name)));
assert_eq!(undo_len(&s), before + 1, "{name}");
let node = doc(&s).node(id).unwrap();
assert_eq!(node.appearance.fill_paint(), Paint::solid(vectorcraft_color::Color::from_hex(fill).unwrap()), "{name}");
assert_eq!(node.appearance.effects.iter().map(|e| e.id.as_str()).collect::<Vec<_>>(), [*effect]);
assert_eq!(node.appearance.effects[0].params, lib.style(name).unwrap().appearance.effects[0].params, "{name}");
ids.push((id, *name));
}
// Adding one again reuses it: no new style, no undo step.
let before = (undo_len(&s), doc(&s).graphic_styles.len());
let r = run(&mut s, "graphicStyle.addFromLibrary", json!({"library": "painted-sketched", "name": "Wet Ink"}));
assert_eq!((names(&r["added"]), names(&r["existing"])), (vec![], vec!["Wet Ink"]));
assert_eq!((undo_len(&s), doc(&s).graphic_styles.len()), before);
// An unknown style or library changes nothing.
assert!(s.execute("graphicStyle.addFromLibrary", &json!({"library": "painted-sketched", "names": ["Wet Ink", "Nope"]})).is_err());
assert!(s.execute("graphicStyle.addFromLibrary", &json!({"library": "painted-and-sketched", "name": "Wet Ink"})).is_err());
assert_eq!((undo_len(&s), doc(&s).graphic_styles.len()), before);
// Saved and opened again, the styles keep their effects and the rectangles stay linked to them.
let b64 = run(&mut s, "document.serialize", json!({}))["dataBase64"].as_str().unwrap().to_string();
run(&mut s, "document.open", json!({"name": "painted.vectorcraft", "dataBase64": b64}));
for (id, name) in &ids {
let d = doc(&s);
let style = d.graphic_style(name).unwrap();
assert!(style.same_look(lib.style(name).unwrap()), "{name}");
let node = d.node(*id).unwrap();
assert_eq!((node.extras().graphic_style, &node.appearance.effects), (Some(style.id), &style.appearance.effects), "{name}");
}
// With nothing selected, `apply` only adds; empty `names` adds the whole library in order.
run(&mut s, "file.new", json!({"width": 100, "height": 100}));
let r = run(&mut s, "graphicStyle.addFromLibrary", json!({"library": "painted-sketched", "name": "Fine Pen", "apply": true}));
assert!(r.get("applied").is_none() && doc(&s).graphic_style("Fine Pen").is_some());
let r = run(&mut s, "graphicStyle.addFromLibrary", json!({"library": "painted-sketched", "names": []}));
assert_eq!((names(&r["added"]), names(&r["existing"])), (want[..6].iter().map(|w| w.0).collect::<Vec<_>>(), vec!["Fine Pen"]));
}
#[test]
fn add_dedupes_names_as_one_undo_step() {
let mut s = session();
+8
View File
@@ -1399,6 +1399,14 @@ font-technology Variable Променливи
Hair Space Тънък интервал
Hand Tool Инструмент „Ръка“
Hand-Drawn Ръчно рисувани
Painted and Sketched Рисувани и скицирани
Washed Blue Размито синьо
Bristle Ochre Охра с четка
Pastel Heather Пастелен пирен
Charcoal Shade Сянка с въглен
Ink Contour Мастилен контур
Wet Ink Мокро мастило
Fine Pen Фино перо
Handles Дръжки
Hard Light Твърда светлина
Hard Mix Твърдо смесване
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -812,6 +812,14 @@
Damp Paper Vlažni papir
Outlines and Rules Obrisi i linije
Hand-Drawn Ručno crtano
Painted and Sketched Slikano i skicirano
Washed Blue Isprano plavo
Bristle Ochre Oker kistom
Pastel Heather Pastelni vrijesak
Charcoal Shade Sjena ugljenom
Ink Contour Kontura tušem
Wet Ink Mokri tuš
Fine Pen Fino pero
Gradient Finishes Gradijentne završnice
Shape Effects Efekti oblika
Blends and Transparency Stapanja i prozirnost
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -1907,6 +1907,14 @@ digits Malayalam Malaiàlam
Hand Mà
Hand Tool Eina de mà
Hand-Drawn Dibuixat a mà
Painted and Sketched Pintat i esbossat
Washed Blue Blau rentat
Bristle Ochre Ocre de cerres
Pastel Heather Bruc pastel
Charcoal Shade Ombra de carbó
Ink Contour Contorn de tinta
Wet Ink Tinta humida
Fine Pen Ploma fina
Handles Nanses
Hard Dur
Hard Light Llum dura
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -821,6 +821,14 @@
Damp Paper Vlhký papír
Outlines and Rules Obrysy a linky
Hand-Drawn Ručně kreslené
Painted and Sketched Malované a skicované
Washed Blue Rozmytá modrá
Bristle Ochre Okr štětcem
Pastel Heather Pastelový vřes
Charcoal Shade Stín uhlem
Ink Contour Obrys tuší
Wet Ink Mokrá tuš
Fine Pen Jemné pero
Gradient Finishes Přechodové povrchy
Shape Effects Efekty tvarů
Blends and Transparency Prolnutí a průhlednost
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -758,6 +758,14 @@
Damp Paper Fugtigt papir
Outlines and Rules Konturer og linjer
Hand-Drawn Håndtegnet
Painted and Sketched Malet og skitseret
Washed Blue Udvasket blå
Bristle Ochre Børsteokker
Pastel Heather Pastellyng
Charcoal Shade Kulskygge
Ink Contour Blækkontur
Wet Ink Vådt blæk
Fine Pen Fin pen
Gradient Finishes Gradientfinish
Shape Effects Formeffekter
Blends and Transparency Blandinger og gennemsigtighed
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -1444,6 +1444,14 @@ file-filter Templates Vorlagen
Hair Space Haarspatium
Hand Tool Hand-Werkzeug
Hand-Drawn Handgezeichnet
Painted and Sketched Gemalt und skizziert
Washed Blue Verwaschenes Blau
Bristle Ochre Borstenocker
Pastel Heather Pastellheide
Charcoal Shade Kohleschatten
Ink Contour Tuschekontur
Wet Ink Nasse Tusche
Fine Pen Feine Feder
Handles Griffe
Hard Light Hartes Licht
Hard Mix Hart mischen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -1374,6 +1374,14 @@ font-technology Variable Μεταβλητές
Hair Space Πολύ λεπτό διάστημα
Hand Tool Χέρι (Hand Tool)
Hand-Drawn Σχεδιασμένο στο χέρι
Painted and Sketched Ζωγραφισμένο και σκιτσαρισμένο
Washed Blue Ξεπλυμένο μπλε
Bristle Ochre Ώχρα με πινέλο
Pastel Heather Παστέλ ρείκι
Charcoal Shade Σκιά με κάρβουνο
Ink Contour Περίγραμμα με μελάνι
Wet Ink Υγρό μελάνι
Fine Pen Λεπτή πένα
Handles Λαβές
Hard Light Έντονο φως
Hard Mix Έντονη ανάμειξη
Can't render this file because it is too large.
+8
View File
@@ -1453,6 +1453,14 @@ font-technology Variable Variables
Hair Space Espacio fino
Hand Tool Herramienta Mano
Hand-Drawn Dibujado a mano
Painted and Sketched Pintado y bocetado
Washed Blue Azul lavado
Bristle Ochre Ocre de cerdas
Pastel Heather Brezo pastel
Charcoal Shade Sombra al carboncillo
Ink Contour Contorno de tinta
Wet Ink Tinta húmeda
Fine Pen Plumilla fina
Handles Manejadores
Hard Light Luz fuerte
Hard Mix Mezcla definida
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -812,6 +812,14 @@
Damp Paper Kostea paperi
Outlines and Rules Ääriviivat ja viivat
Hand-Drawn Käsin piirretyt
Painted and Sketched Maalatut ja luonnostellut
Washed Blue Haalea sininen
Bristle Ochre Harjasokra
Pastel Heather Pastellikanerva
Charcoal Shade Hiilivarjo
Ink Contour Mustekontuuri
Wet Ink Märkä muste
Fine Pen Hieno kynä
Gradient Finishes Liukuväriviimeistelyt
Shape Effects Muototehosteet
Blends and Transparency Sulautukset ja läpinäkyvyys
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -1447,6 +1447,14 @@ font-technology Variable Variables
Hair Space Espace ultrafine
Hand Tool Outil Main
Hand-Drawn Dessiné à la main
Painted and Sketched Peint et esquissé
Washed Blue Bleu lavé
Bristle Ochre Ocre à la brosse
Pastel Heather Bruyère pastel
Charcoal Shade Ombre au fusain
Ink Contour Contour encré
Wet Ink Encre humide
Fine Pen Plume fine
Handles Poignées
Hard Light Lumière crue
Hard Mix Mélange maximal
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -2101,6 +2101,14 @@ antiAlias Sharp शार्प
Hand हैंड
Hand Tool हैंड टूल
Hand-Drawn हाथ-ड्रन
Painted and Sketched पेंट और स्केच
Washed Blue धुला नीला
Bristle Ochre ब्रश गेरू
Pastel Heather पेस्टल बैंगनी
Charcoal Shade चारकोल छाया
Ink Contour स्याही रूपरेखा
Wet Ink गीली स्याही
Fine Pen बारीक पेन
Handles हैंडल्स
Hard कठोर
Hard Light हार्ड लाइट
Can't render this file because it is too large.
+8
View File
@@ -1847,6 +1847,14 @@ file-filter Templates Sablonok
Hand Kéz
Hand Tool Kéz
Hand-Drawn Kézzel rajzolt
Painted and Sketched Festett és vázlatos
Washed Blue Kimosott kék
Bristle Ochre Sörteokker
Pastel Heather Pasztell hanga
Charcoal Shade Szénárnyék
Ink Contour Tuskontúr
Wet Ink Nedves tus
Fine Pen Finom toll
Handles Fogantyúk
Hard Szigorú
Hard Light Kemény fény
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -758,6 +758,14 @@
Damp Paper Kertas Basah
Outlines and Rules Garis luar dan garis
Hand-Drawn Gambar tangan
Painted and Sketched Lukisan dan sketsa
Washed Blue Biru luntur
Bristle Ochre Oker kuas kering
Pastel Heather Ungu pastel
Charcoal Shade Bayangan arang
Ink Contour Kontur tinta
Wet Ink Tinta basah
Fine Pen Pena halus
Gradient Finishes Finishing gradien
Shape Effects Efek bentuk
Blends and Transparency Blend dan transparansi
1 # Indonesian (id) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
758
759
760
761
762
763
764
765
766
767
768
769
770
771
+8
View File
@@ -1474,6 +1474,14 @@ file-filter Templates Modelli
Hair Space Spazio sottilissimo
Hand Tool Strumento Mano
Hand-Drawn Disegnato a mano
Painted and Sketched Dipinto e schizzato
Washed Blue Blu slavato
Bristle Ochre Ocra a setole
Pastel Heather Erica pastello
Charcoal Shade Ombra a carboncino
Ink Contour Contorno a china
Wet Ink China bagnata
Fine Pen Pennino fine
Handles Maniglie
Hard Light Luce intensa
Hard Mix Miscela intensa
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -844,6 +844,14 @@ digits Malayalam マラヤーラム数字
Damp Paper 湿った紙
Outlines and Rules アウトラインと罫線
Hand-Drawn 手描き風
Painted and Sketched 絵画とスケッチ
Washed Blue にじみブルー
Bristle Ochre 筆跡オーカー
Pastel Heather パステルヘザー
Charcoal Shade 木炭シェード
Ink Contour インク輪郭
Wet Ink 濡れ墨
Fine Pen 細いペン
Gradient Finishes グラデーション仕上げ
Shape Effects シェイプ効果
Blends and Transparency ブレンドと透明
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -718,6 +718,14 @@
Damp Paper ნესტიანი ქაღალდი
Outlines and Rules კონტურები და ხაზები
Hand-Drawn ხელით დახატული
Painted and Sketched დახატული და ესკიზური
Washed Blue გარეცხილი ლურჯი
Bristle Ochre ფუნჯის ოხრა
Pastel Heather პასტელის იისფერი
Charcoal Shade ნახშირის ჩრდილი
Ink Contour მელნის კონტური
Wet Ink სველი მელანი
Fine Pen წვრილი კალამი
Gradient Finishes გრადიენტული ზედაპირები
Shape Effects ფიგურის ეფექტები
Blends and Transparency გადასვლები და გამჭვირვალობა
Can't render this file because it is too large.
+8
View File
@@ -837,6 +837,14 @@ digits Malayalam 말라얄람어
Damp Paper 젖은 종이
Outlines and Rules 윤곽선과 괘선
Hand-Drawn 손그림
Painted and Sketched 페인팅과 스케치
Washed Blue 번진 파랑
Bristle Ochre 붓결 황토
Pastel Heather 파스텔 헤더
Charcoal Shade 목탄 음영
Ink Contour 잉크 윤곽
Wet Ink 젖은 먹
Fine Pen 가는 펜
Gradient Finishes 그레이디언트 마감
Shape Effects 모양 효과
Blends and Transparency 블렌드와 투명도
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -772,6 +772,14 @@
Damp Paper Vochtig papier
Outlines and Rules Omtrekken en lijnen
Hand-Drawn Handgetekend
Painted and Sketched Geschilderd en geschetst
Washed Blue Verwassen blauw
Bristle Ochre Borsteloker
Pastel Heather Pastelheide
Charcoal Shade Houtskoolschaduw
Ink Contour Inktcontour
Wet Ink Natte inkt
Fine Pen Fijne pen
Gradient Finishes Verloopafwerkingen
Shape Effects Vormeffecten
Blends and Transparency Vermengingen en transparantie
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -768,6 +768,14 @@
Damp Paper Wilgotny papier
Outlines and Rules Kontury i linie
Hand-Drawn Rysowane odręcznie
Painted and Sketched Malowane i szkicowane
Washed Blue Rozmyty błękit
Bristle Ochre Ochra pędzlem
Pastel Heather Pastelowy wrzos
Charcoal Shade Cień węglem
Ink Contour Kontur tuszem
Wet Ink Mokry tusz
Fine Pen Cienkie pióro
Gradient Finishes Wykończenia gradientowe
Shape Effects Efekty kształtów
Blends and Transparency Przejścia i przezroczystość
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -1278,6 +1278,14 @@ antiAlias Sharp Nítido
Hair Space Espaço Fino
Hand Tool Ferramenta Mão
Hand-Drawn Desenhado à Mão
Painted and Sketched Pintado e Esboçado
Washed Blue Azul Lavado
Bristle Ochre Ocre de Cerdas
Pastel Heather Urze Pastel
Charcoal Shade Sombra a Carvão
Ink Contour Contorno a Nanquim
Wet Ink Nanquim Úmido
Fine Pen Pena Fina
Handles Alças
Hard Light Luz Forte
Hard Mix Mistura definida
Can't render this file because it contains an unexpected character in line 6 and column 47.
+8
View File
@@ -1463,6 +1463,14 @@ file-filter Templates Шаблоны
Hair Space Волосяная шпация
Hand Tool Инструмент «Рука»
Hand-Drawn Нарисованный от руки
Painted and Sketched Живопись и эскизы
Washed Blue Размытый синий
Bristle Ochre Охра кистью
Pastel Heather Пастельный вереск
Charcoal Shade Тень углём
Ink Contour Контур тушью
Wet Ink Влажная тушь
Fine Pen Тонкое перо
Handles Маркеры
Hard Light Жёсткий свет
Hard Mix Жёсткое наложение
Can't render this file because it is too large.
+8
View File
@@ -1412,6 +1412,14 @@ font-technology Variable Variabla
Hair Space Hårfint blanksteg
Hand Tool Handverktyg
Hand-Drawn Handritad
Painted and Sketched Målat och skissat
Washed Blue Urtvättad blå
Bristle Ochre Borstockra
Pastel Heather Pastelljung
Charcoal Shade Kolskugga
Ink Contour Tuschkontur
Wet Ink Våt tusch
Fine Pen Fin penna
Handles Handtag
Hard Light Hårt ljus
Hard Mix Hård blandning
Can't render this file because it contains an unexpected character in line 5 and column 25.
+14
View File
@@ -238,6 +238,20 @@ fn anti_aliasing_method_labels_are_in_complete_catalogs() {
}
}
/// The Painted and Sketched graphic style library's name and its styles' names have a row in every
/// bundled catalog.
#[test]
fn painted_and_sketched_style_names_are_in_every_catalog() {
let lib = vectorcraft_doc::style_libs::builtin_style_library("painted-sketched").expect("built in");
let labels: Vec<&str> = std::iter::once(lib.name.as_str()).chain(lib.styles.iter().map(|g| g.name.as_str())).collect();
assert_eq!(labels.len(), 8);
for lang in LANGUAGES.iter().filter(|lang| !lang.source.is_empty()) {
for label in &labels {
assert!(lang.catalog().plain(label).is_some(), "{} is missing {label}", lang.code);
}
}
}
/// The names the EPS options' menus show (preview, overprints, flattener preset and PostScript
/// level), and Save As's Preview label.
#[test]
+8
View File
@@ -1376,6 +1376,14 @@ font-technology Variable Değişken
Hair Space Saç Alanı
Hand Tool El Aracı
Hand-Drawn elle çizilmiş
Painted and Sketched Boyanmış ve Eskiz
Washed Blue Soluk Mavi
Bristle Ochre Fırça Darbeli Toprak Sarısı
Pastel Heather Pastel Funda
Charcoal Shade Kömür Gölge
Ink Contour Mürekkep Kontur
Wet Ink Islak Mürekkep
Fine Pen İnce Kalem
Handles Kollar
Hard Light Sert Işık
Harmony Rules: Uyum Kuralları:
Can't render this file because it contains an unexpected character in line 5 and column 25.
+8
View File
@@ -1468,6 +1468,14 @@ file-filter Templates Шаблони
Hair Space Волосяна шпація
Hand Tool Інструмент «Рука»
Hand-Drawn Намальований від руки
Painted and Sketched Мальовані та ескізні
Washed Blue Розмитий синій
Bristle Ochre Охра пензлем
Pastel Heather Пастельний верес
Charcoal Shade Тінь вугіллям
Ink Contour Контур тушшю
Wet Ink Мокра туш
Fine Pen Тонке перо
Handles Маркери
Hard Light Жорстке світло
Hard Mix Жорстке накладання
Can't render this file because it contains an unexpected character in line 182 and column 5.
+8
View File
@@ -1695,6 +1695,14 @@ file-filter Templates Mẫu
Halo Vầng hào quang
Hand Tool Công cụ Bàn tay
Hand-Drawn Vẽ tay
Painted and Sketched Vẽ màu và phác thảo
Washed Blue Xanh nhạt nhòa
Bristle Ochre Vàng đất cọ khô
Pastel Heather Tím phấn màu
Charcoal Shade Bóng than
Ink Contour Đường viền mực
Wet Ink Mực ướt
Fine Pen Bút mảnh
Handles Tay nắm
Hard Cứng
Hard Light Ánh sáng mạnh
Can't render this file because it contains an unexpected character in line 204 and column 5.
+8
View File
@@ -1403,6 +1403,14 @@ file-filter Templates 模板
Hair Space 极细空格
Hand Tool 抓手工具
Hand-Drawn 手绘
Painted and Sketched 绘画与素描
Washed Blue 水洗蓝
Bristle Ochre 干刷土黄
Pastel Heather 粉彩淡紫
Charcoal Shade 炭笔阴影
Ink Contour 墨线轮廓
Wet Ink 湿墨
Fine Pen 细笔
Handles 手柄
Hard Light 强光
Hard Mix 实色混合
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -1439,6 +1439,14 @@ file-filter Templates 範本
Hair Space 極細空格
Hand Tool 手形工具
Hand-Drawn 手繪
Painted and Sketched 繪畫與素描
Washed Blue 水洗藍
Bristle Ochre 乾刷土黃
Pastel Heather 粉彩淡紫
Charcoal Shade 炭筆陰影
Ink Contour 墨線輪廓
Wet Ink 濕墨
Fine Pen 細筆
Handles 控制把手
Hard Light 實光
Hard Mix 實色混合
Can't render this file because it contains an unexpected character in line 6 and column 47.
@@ -101,6 +101,30 @@ fn clicking_a_library_style_adds_and_applies_it_in_one_step() {
assert!(last_open(&app.ui).is_none());
}
#[test]
fn painted_and_sketched_opens_from_the_window_menu_and_a_click_applies_its_style() {
let mut app = app();
let entry = crate::menus::menu_entries(&app)
.into_iter()
.find(|e| e.path == ["Window", "Graphic Style Libraries"] && e.label == "Painted and Sketched")
.expect("a Window menu item");
assert_eq!((entry.command.as_deref(), &entry.params["library"]), (Some("window.graphicStyleLibrary"), &json!("painted-sketched")));
let rect = app.run("shape.rectangle", json!({"x": 10, "y": 10, "width": 80, "height": 40})).unwrap()["id"].as_u64().unwrap();
app.run(entry.command.as_deref().unwrap(), entry.params.clone()).unwrap();
assert_eq!(last_open(&app.ui).map(|p| (p.kind.as_str(), p.id.as_str())), Some(("graphicStyles", "painted-sketched")));
let ctx = context();
let undo = undo_len(&app);
click(&mut app, &ctx, "Charcoal Shade", Modifiers::NONE, 0.0);
let (g, linked) = app.session.selection_graphic_style().expect("applied to the selection");
assert_eq!((g.name.as_str(), linked), ("Charcoal Shade", true));
assert_eq!(undo_len(&app), undo + 1, "added and applied as one undo step");
let node = app.session.doc().unwrap().doc.node(vectorcraft_doc::NodeId(rect)).unwrap().appearance.effects.clone();
assert_eq!(node.iter().map(|e| e.id.as_str()).collect::<Vec<_>>(), ["sketch.charcoal"]);
let lib = GraphicStyleLibraries::get(&app, "painted-sketched").unwrap().1;
let rows = GraphicStyleLibraries::rows(&lib, "ink");
assert_eq!(rows.iter().map(|r| r.name).collect::<Vec<_>>(), ["Ink Contour", "Wet Ink"]);
}
#[test]
fn the_window_menu_and_the_panel_open_every_library() {
let mut app = app();
+7 -5
View File
@@ -645,12 +645,14 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
Direct Selection of a path, compound path or type inside a dynamic instance also takes opacity and blend
(`transparency.set`) and a gradient or pattern fill or stroke (`paint.setFill` / `paint.setStroke`,
Eyedropper), for that instance only;
graphic style libraries (Window › Graphic Style Libraries; nine original libraries generated in code, including
graphic style libraries (Window › Graphic Style Libraries; ten original libraries generated in code, including
Game HUD with Health Fill, Mana Glow, Damage Flash, Quest Outline, Coin Shine and Boss Alert, Status Effects
with Poison Tint, Freeze Edge, Burn Aura, Stun Pulse, Stealth Fade and Shield Buff, and Textures with Fine Grain,
Canvas Weave, Burlap Sack, Cracked Glaze, Mosaic Floor, Quilted Squares, Leaded Glass and Damp Paper, painted with
the texture effects; 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 nine shipped, and further symbol libraries beyond Basic
with Poison Tint, Freeze Edge, Burn Aura, Stun Pulse, Stealth Fade and Shield Buff, Painted and Sketched with
Washed Blue, Bristle Ochre, Pastel Heather, Charcoal Shade, Ink Contour, Wet Ink and Fine Pen, and Textures with
Fine Grain, Canvas Weave, Burlap Sack, Cracked Glaze, Mosaic Floor, Quilted Squares, Leaded Glass and Damp Paper,
painted with the texture effects; 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 ten 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).
+8 -1
View File
@@ -3402,7 +3402,7 @@ as a value left out.
## Graphic style libraries
Graphic style libraries are read-only sets of graphic styles generated in code (Shadows and Glows, Outlines and
Rules, Hand-Drawn, Textures, Gradient Finishes, Shape Effects, Blends and Transparency, Game HUD, Status Effects). Textures
Rules, Hand-Drawn, Textures, Painted and Sketched, Gradient Finishes, Shape Effects, Blends and Transparency, Game HUD, Status Effects). Textures
(`textures`) paints its fills and strokes with the texture effects: Fine Grain (`texture.grain`), Canvas Weave and Burlap
Sack (`texture.texturizer`), Cracked Glaze (`texture.craquelure`), Mosaic Floor (`texture.mosaicTiles`), Quilted Squares
(`texture.patchwork`), Leaded Glass (`texture.stainedGlass`) and Damp Paper (`sketch.waterPaper`). `graphicStyle.libraries` lists them
@@ -3415,6 +3415,13 @@ the patterns the styles paint with come along. `apply: true` also applies the fi
does. Library styles keep placed gradients in unit-box space, so each object gets them at the same place relative to
its bounds.
Painted and Sketched (`painted-sketched`) holds Washed Blue, Bristle Ochre, Pastel Heather, Charcoal Shade, Ink
Contour, Wet Ink and Fine Pen. Each is a solid fill (Bristle Ochre and Ink Contour add a 1 pt stroke) under one object
effect that repaints fill and stroke together: `artistic.watercolor`, `artistic.dryBrush`, `artistic.roughPastels`,
`sketch.charcoal`, `brushStrokes.inkOutlines`, `brushStrokes.sumiE` and `sketch.graphicPen`, in that order. The
colors and effect settings are VectorCraft's own. These are raster effects, so the document's raster effects
resolution sets how fine they draw.
```json
{"name":"run_command","arguments":{"command":"graphicStyle.library","params":{"library":"hand-drawn"}}}
{"name":"run_command","arguments":{"command":"graphicStyle.addFromLibrary","params":{"library":"hand-drawn","name":"Crosshatch","apply":true}}}
+1 -1
View File
@@ -1370,7 +1370,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- **Transparency:** three-state Knockout Group (on, neutral, off), Opacity & Mask Define Knockout Shape, Page Isolated Blending and Page Knockout Group, on screen and in SVG/PDF. SVG export writes a knockout group of opaque art plainly, without masks, so shapes meeting edge to edge leave no seam; translucent, blended, masked or brushed art knocks out through masks. Blend modes match the standard formulas on screen, in SVG and in PDF, and non-isolated groups blend with the art below. Flatten Transparency with presets, a dialog and a Flattener Preview panel. Flattening for files without transparency (PDF/X-1a, PDF/X-3) in a CMYK document keeps the inks where it rasterizes, as under an image with see-through pixels: the images it makes hold ink amounts, not screen colours the file would separate again, so a C100 M6 Y41 K3 panel stays C100 M6 Y41 K3 there (#2160, `engine/src/cmd/fileio/tests_pdfx.rs`).
On the canvas, the renderer no longer draws the picture of the art below back as an image each time it copies the backdrop of a non-isolated group that blends: it keeps that picture and draws the art that follows over it. At 2880 × 1800, 50 translucent groups with Multiply members take 65 ms a frame instead of 299 ms on 8 threads (`vectorcraft-cli bench`), and the frames have the same pixels.
Type inside a group, layer, symbol instance, blend or repeat keeps its opacity, blend mode, opacity mask, Opacity & Mask Define Knockout Shape, own effects, perspective and visibility when the effects on the container outline it. Hidden type with a geometry effect of its own is left out of exports.
- **Graphic styles:** styles keep opacity and blend mode, capture groups and type, apply on top with Alt, and link to the objects using them; Redefine, Break Link, Graphic Style Options, Select All Unused, Sort by Name, and Select > Same Graphic Style / Appearance Attribute. The panel has list and thumbnail views with rendered previews, merge, reorder and drag and drop, plus a Control bar Style picker; nine generated style libraries (including Game HUD, Status Effects and Textures) save and load as `.vcstyles`.
- **Graphic styles:** styles keep opacity and blend mode, capture groups and type, apply on top with Alt, and link to the objects using them; Redefine, Break Link, Graphic Style Options, Select All Unused, Sort by Name, and Select > Same Graphic Style / Appearance Attribute. The panel has list and thumbnail views with rendered previews, merge, reorder and drag and drop, plus a Control bar Style picker; ten generated style libraries (including Game HUD, Status Effects, Painted and Sketched, whose seven styles each repaint a solid fill with one watercolor, dry brush, pastel, charcoal or ink effect, and Textures) save and load as `.vcstyles`.
The built-in Textures graphic style library (`graphicStyle.addFromLibrary {library: "textures"}`) has eight styles that paint their fills and strokes with the texture effects: Fine Grain (Grain), Canvas Weave and Burlap Sack (Texturizer), Cracked Glaze (Craquelure), Mosaic Floor (Mosaic Tiles), Quilted Squares (Patchwork), Leaded Glass (Stained Glass) and Damp Paper (Water Paper). The help page names new graphic styles for textures ([What's new](https://helpx.adobe.com/illustrator/desktop/new-features/whats-new.html)) without naming them, so the styles, their names and their settings are VectorCraft's own (`tests::stylelib::textures_styles_apply_their_texture_effects_and_keep_their_params_through_save_and_open`).
In the Graphic Styles panel, Shift-click selects a range of styles and Ctrl/Cmd-click adds or removes one.
Applying a style to several objects, and Redefine Graphic Style, give the objects one shared copy of the style's appearance instead of a copy each; an object that is edited later gets its own copy, and an object whose placed gradients are fitted to its own bounds gets its own. The undo history's memory estimate counts a shared appearance once. Saved files are unchanged (`crates/engine/src/tests/styles.rs`).