mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-29 12:17:14 -06:00
Merge main into feat/live-rasterize-effect
This commit is contained in:
@@ -377,6 +377,11 @@ fn open_loaded(s: &mut Session, loaded: Loaded, links: Resolved, path: Option<St
|
||||
doc.template = false;
|
||||
doc.title = s.next_untitled();
|
||||
}
|
||||
// A .ai (or .ait) another app wrote carries no open Layers rows we read: all of them start
|
||||
// closed, its top-level layers as its groups (#1475). Ours carry their own.
|
||||
if matches!(format.id, "ai" | "ait") && !restored && doc.layers_open.is_none() {
|
||||
doc.layers_open = Some(vec![]);
|
||||
}
|
||||
// Save writes the file back only in a format it writes, only a whole PDF (see
|
||||
// [`LoadOptions::is_partial`]), and a .ai file only when it carried the native document (Save
|
||||
// writes .ai that way).
|
||||
|
||||
@@ -374,3 +374,43 @@ fn bled_file_opens_on_its_artboard(name: &str, key: &str) {
|
||||
open(&mut s, name, &file, json!({})).unwrap();
|
||||
assert_eq!(names(&s.doc().unwrap().doc.layers), ["Art"], "{name}: the editing data's layers are read");
|
||||
}
|
||||
|
||||
/// The rows that open in the Layers panel (layers, sublayers and groups), and which of them are
|
||||
/// open.
|
||||
fn open_rows(s: &Session) -> (Vec<String>, Vec<String>) {
|
||||
let st = s.doc().unwrap();
|
||||
let (mut rows, mut open) = (vec![], vec![]);
|
||||
st.doc.walk(|n| {
|
||||
if n.children().is_some() {
|
||||
rows.push(n.name.clone().unwrap_or_default());
|
||||
if st.layers_open.contains(n.id) {
|
||||
open.push(n.name.clone().unwrap_or_default());
|
||||
}
|
||||
}
|
||||
});
|
||||
(rows, open)
|
||||
}
|
||||
|
||||
/// #1475: a `.ai` another app wrote keeps no open rows VectorCraft reads, so it opens with every
|
||||
/// row closed, its top-level layers as its groups; a `.ai` VectorCraft wrote, and other formats,
|
||||
/// open as before (with their top-level layers open unless the file says otherwise).
|
||||
#[test]
|
||||
fn an_illustrator_ai_file_opens_with_its_layers_closed() {
|
||||
let mut s = Session::new();
|
||||
for file in [ai::ai(&compressed(&ai::sample_data()), ai::page_pdf()), ai::eps(&ai::sample_data(), ai::page_ps())] {
|
||||
let r = open(&mut s, "art.ai", &file, json!({})).unwrap();
|
||||
assert_eq!((&r["format"], &r["restored"]), (&json!("ai"), &json!(false)), "{r}");
|
||||
let (rows, open) = open_rows(&s);
|
||||
assert!(rows.contains(&"Art".into()) && rows.contains(&"Pair".into()) && rows.contains(&"Sub".into()), "{rows:?}");
|
||||
assert_eq!(open, Vec::<String>::new(), "{r}");
|
||||
}
|
||||
// The same art as an EPS: its top-level layers open.
|
||||
open(&mut s, "art.eps", &ai::eps(&ai::sample_data(), ai::page_ps()), json!({})).unwrap();
|
||||
assert_eq!(open_rows(&s).1, ["Art", "Hidden"]);
|
||||
// Saved as .ai by VectorCraft, it opens with the rows it was saved with.
|
||||
let saved = s.execute("document.save", &json!({"format": "ai"})).unwrap();
|
||||
let bytes = vectorcraft_format::base64_decode(saved["dataBase64"].as_str().unwrap()).unwrap();
|
||||
let r = open(&mut s, "again.ai", &bytes, json!({})).unwrap();
|
||||
assert_eq!(r["restored"], json!(true), "{r}");
|
||||
assert_eq!(open_rows(&s).1, ["Art", "Hidden"]);
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ static NEXT_DOC_UID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64
|
||||
|
||||
/// The rows open in the Layers panel: the layers, sublayers and groups that show what they hold.
|
||||
/// A document opens with the ones it was saved with ([`Document::layers_open`]), else with only
|
||||
/// its top-level layers open.
|
||||
/// its top-level layers open (a `.ai` another app wrote opens with none open).
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct OpenRows {
|
||||
ids: std::collections::HashSet<NodeId>,
|
||||
@@ -1007,7 +1007,7 @@ impl Default for Prefs {
|
||||
font_preview_size: s("medium"),
|
||||
recent_fonts_count: 10,
|
||||
missing_glyph_protection: true,
|
||||
highlight_alternate_glyphs: true,
|
||||
highlight_alternate_glyphs: false,
|
||||
placeholder_text: true,
|
||||
units_general: s("points"),
|
||||
units_stroke: s("points"),
|
||||
|
||||
@@ -391,13 +391,22 @@ fn use_precise_cursors_swaps_the_tools_own_pointers_for_a_crosshair() {
|
||||
("pen", Cursor::Pen),
|
||||
("addAnchor", Cursor::PenAdd),
|
||||
("deleteAnchor", Cursor::PenDelete),
|
||||
("anchorPoint", Cursor::Pen),
|
||||
("curvature", Cursor::Pen),
|
||||
("mesh", Cursor::PenAdd),
|
||||
("anchorPoint", Cursor::AnchorPoint),
|
||||
("curvature", Cursor::Curvature),
|
||||
("mesh", Cursor::MeshAdd),
|
||||
("eyedropper", Cursor::Eyedropper),
|
||||
("slice", Cursor::Slice),
|
||||
("blend", Cursor::Blend),
|
||||
("shapeBuilder", Cursor::ShapeBuilder),
|
||||
("paintbrush", Cursor::Paintbrush),
|
||||
("blobBrush", Cursor::BlobBrush),
|
||||
("shaper", Cursor::Shaper),
|
||||
("pencil", Cursor::Pencil),
|
||||
("smooth", Cursor::Smooth),
|
||||
("pathEraser", Cursor::PathEraser),
|
||||
("join", Cursor::Join),
|
||||
("eraser", Cursor::Eraser),
|
||||
("knife", Cursor::Knife),
|
||||
];
|
||||
for (tool, c) in own {
|
||||
assert_eq!(cursor(&mut s, tool), c, "{tool} off");
|
||||
@@ -415,15 +424,6 @@ fn use_precise_cursors_swaps_the_tools_own_pointers_for_a_crosshair() {
|
||||
"polygon",
|
||||
"star",
|
||||
"flare",
|
||||
"paintbrush",
|
||||
"blobBrush",
|
||||
"shaper",
|
||||
"pencil",
|
||||
"smooth",
|
||||
"pathEraser",
|
||||
"join",
|
||||
"eraser",
|
||||
"knife",
|
||||
"mirrorCut",
|
||||
"lineCut",
|
||||
"rectCut",
|
||||
@@ -440,7 +440,7 @@ fn use_precise_cursors_swaps_the_tools_own_pointers_for_a_crosshair() {
|
||||
assert_eq!(cursor(&mut s, tool), Cursor::Crosshair, "{tool} on");
|
||||
}
|
||||
assert_eq!(cursor(&mut s, "type"), Cursor::Text);
|
||||
assert_eq!(cursor(&mut s, "scissors"), Cursor::NotAllowed);
|
||||
assert_eq!(cursor(&mut s, "scissors"), Cursor::ScissorsNotAllowed);
|
||||
s.execute("prefs.set", &json!({"key": "usePreciseCursors", "value": false})).unwrap();
|
||||
for (tool, c) in own {
|
||||
assert_eq!(cursor(&mut s, tool), c, "{tool} off again");
|
||||
@@ -467,6 +467,8 @@ fn precise_cursors_replace_every_pen_state() {
|
||||
Cursor::BlendAnchor,
|
||||
Cursor::ShapeBuilder,
|
||||
Cursor::ShapeBuilderErase,
|
||||
Cursor::AnchorPoint,
|
||||
Cursor::Curvature,
|
||||
] {
|
||||
assert_eq!(c.precise(), Cursor::Crosshair, "{c:?}");
|
||||
}
|
||||
@@ -1284,6 +1286,18 @@ fn show_font_names_in_english_preference_is_stored() {
|
||||
assert!(s.prefs.font_names_in_english);
|
||||
}
|
||||
|
||||
/// Preferences › Type › Highlight Alternate Glyphs (#394): off by default so OpenType
|
||||
/// substitutions are not pink on every canvas until the user turns the preference on.
|
||||
#[test]
|
||||
fn highlight_alternate_glyphs_preference_is_off_by_default() {
|
||||
let mut s = Session::new();
|
||||
assert!(!s.prefs.highlight_alternate_glyphs, "off by default");
|
||||
set_pref(&mut s, "highlightAlternateGlyphs", json!(true));
|
||||
assert!(s.prefs.highlight_alternate_glyphs);
|
||||
set_pref(&mut s, "highlightAlternateGlyphs", json!(false));
|
||||
assert!(!s.prefs.highlight_alternate_glyphs);
|
||||
}
|
||||
|
||||
/// Preferences › Hyphenation › Exceptions (#394): `prefs.set` pushes the list into the hyphenator
|
||||
/// and bumps open documents so type reflows. Parsing of the list is covered in `vectorcraft-text`.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user