mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 12:13:19 +00:00
Merge pull request #6017 from dotCooCoo/fix/ai-drawn-look-count
.ai import: drawn looks in pattern and brush art count in the note
This commit is contained in:
@@ -475,6 +475,12 @@ struct Reader<'a> {
|
||||
warnings: Vec<String>,
|
||||
/// Objects read as their drawn look (several fills or strokes, effects, brushes).
|
||||
drawn_looks: usize,
|
||||
/// The objects read as their drawn look in the art of [`Reader::brush_art`], by name: counted in
|
||||
/// [`Reader::drawn_looks`] once a brush that is kept uses the art.
|
||||
brush_art_looks: HashMap<String, usize>,
|
||||
/// The objects read as their drawn look in the art of the patterns kept, by the name the document
|
||||
/// has the pattern by: a pattern defined again counts only its last definition.
|
||||
pattern_looks: HashMap<String, usize>,
|
||||
/// Nodes read from `%_` lines.
|
||||
hidden_ids: HashSet<NodeId>,
|
||||
/// The blend part each object's dictionary names (`ShapeBlendPathType`, `ShapeBlendPathID`).
|
||||
@@ -679,6 +685,8 @@ impl<'a> Reader<'a> {
|
||||
color_model: None,
|
||||
warnings: Vec::new(),
|
||||
drawn_looks: 0,
|
||||
brush_art_looks: HashMap::new(),
|
||||
pattern_looks: HashMap::new(),
|
||||
hidden_ids: HashSet::new(),
|
||||
blend_roles: HashMap::new(),
|
||||
blend_record: None,
|
||||
|
||||
@@ -507,6 +507,7 @@ impl<'a> Reader<'a> {
|
||||
} else {
|
||||
self.v7_patterns.remove(&head.name);
|
||||
}
|
||||
self.pattern_looks.insert(def.name.clone(), sub.drawn_looks);
|
||||
self.doc.patterns.push(def);
|
||||
for (key, blob) in sub.doc.images {
|
||||
self.doc.images.entry(key).or_insert(blob);
|
||||
@@ -752,6 +753,7 @@ impl<'a> Reader<'a> {
|
||||
&& sub.frames.len() == 1
|
||||
&& sub.doc.images.is_empty();
|
||||
let Some(frame) = sub.frames.pop().filter(|f| whole && !f.children.is_empty()) else { return };
|
||||
self.brush_art_looks.insert(name.clone(), sub.drawn_looks);
|
||||
let mut art: Vec<Arc<Node>> = frame.children.iter().map(|n| Arc::new(self.doc.reid(n))).collect();
|
||||
let node = match art.len() {
|
||||
1 => art.pop().map(Arc::unwrap_or_clone),
|
||||
|
||||
@@ -914,13 +914,20 @@ impl<'a> Reader<'a> {
|
||||
}
|
||||
|
||||
/// The brushes read ([`brush::finish_brushes`]) and how many weren't; `None` when the file has
|
||||
/// no brush objects (the document keeps the default brushes).
|
||||
/// no brush objects (the document keeps the default brushes). The objects read as their drawn
|
||||
/// look in the art the brushes use count toward the note on drawn looks, once for each art.
|
||||
fn brush_library(&mut self) -> Option<(Vec<vectorcraft_brush::Brush>, usize)> {
|
||||
if !self.brush_objects {
|
||||
return None;
|
||||
}
|
||||
let drafts = std::mem::take(&mut self.brush_drafts);
|
||||
let (lib, left_out) = brush::finish_brushes(drafts, &self.brush_art, self.brush_order.as_deref());
|
||||
let used: std::collections::HashSet<NodeId> = lib.iter().flat_map(|b| b.art()).map(|a| a.id).collect();
|
||||
for (name, art) in &self.brush_art {
|
||||
if used.contains(&art.id) {
|
||||
self.drawn_looks += self.brush_art_looks.get(name).copied().unwrap_or(0);
|
||||
}
|
||||
}
|
||||
Some((lib, left_out + self.brushes_unread))
|
||||
}
|
||||
|
||||
@@ -1087,6 +1094,7 @@ impl<'a> Reader<'a> {
|
||||
warnings.push(brush::left_out_note(unread));
|
||||
}
|
||||
}
|
||||
self.drawn_looks += self.pattern_looks.values().sum::<usize>();
|
||||
if self.drawn_looks > 0 {
|
||||
warnings.push(format!(
|
||||
"objects with several fills or strokes, effects or brushes came in as their drawn look ({}): their appearance isn't editable yet",
|
||||
|
||||
@@ -2396,6 +2396,44 @@ fn a_drawn_look_stands_for_its_object() {
|
||||
assert!(r.warnings.iter().any(|w| w.contains("drawn look (1)")), "{:?}", r.warnings);
|
||||
}
|
||||
|
||||
/// An object kept as its drawn look: the look (a group), then the object on `%_` lines and its style.
|
||||
fn drawn_look_art() -> String {
|
||||
let hidden_rect = rect_path(0.0, 0.0, 10.0, 10.0).replace('\n', "\n%_");
|
||||
format!(
|
||||
"0 Ae\nu\n{RED}{}f\n{}S\nU\n%_{hidden_rect}n\n%_/ArtDictionary :\n%_/XMLUID : (Look) ; (AI10_ArtUID) ,\n%_;\n1 (Look style) XW\n",
|
||||
rect_path(0.0, 0.0, 10.0, 10.0),
|
||||
rect_path(0.0, 0.0, 10.0, 10.0),
|
||||
)
|
||||
}
|
||||
|
||||
/// A pattern's art holding an object kept as its drawn look counts in the note, as a symbol's does;
|
||||
/// a definition the same name replaces later counts no longer.
|
||||
#[test]
|
||||
fn a_drawn_look_in_a_patterns_art_is_noted() {
|
||||
let pattern = |art: &str| format!("%AI3_BeginPattern: (P)\n(P) 0 0 10 10\n0 A\n0 Xw\n{art}E\n%AI3_EndPattern\n");
|
||||
let looked = pattern(&drawn_look_art());
|
||||
let r = read_ok(&format!("{looked}{}", layer("")));
|
||||
assert_eq!(r.doc.patterns.len(), 1, "{:?}", r.warnings);
|
||||
assert!(r.warnings.iter().any(|w| w.contains("drawn look (1)")), "{:?}", r.warnings);
|
||||
let plain = pattern(&format!("{RED}{}f\n", rect_path(0.0, 0.0, 10.0, 10.0)));
|
||||
let r = read_ok(&format!("{looked}{plain}{}", layer("")));
|
||||
assert_eq!(r.doc.patterns.len(), 1, "{:?}", r.warnings);
|
||||
assert!(!r.warnings.iter().any(|w| w.contains("drawn look")), "{:?}", r.warnings);
|
||||
}
|
||||
|
||||
/// A brush's art holding an object kept as its drawn look counts in the note once a brush that is
|
||||
/// kept uses the art; art no brush uses brings no note.
|
||||
#[test]
|
||||
fn a_drawn_look_in_a_brushs_art_is_noted_when_a_brush_uses_it() {
|
||||
let section = format!("%AI8_BeginBrushPattern\n(Dot art)\n0 A\n{}%AI8_EndBrushPattern\n", drawn_look_art());
|
||||
let r = read_ok(&format!("{section}{}{}", plugin_object(SCATTER, "Spray", SPRAY), layer("")));
|
||||
let lib = vectorcraft_brush::library(&r.doc);
|
||||
assert!(matches!(brush_named(&lib, "Spray"), vectorcraft_brush::BrushKind::Scatter(_)), "{:?}", r.warnings);
|
||||
assert!(r.warnings.iter().any(|w| w.contains("drawn look (1)")), "{:?}", r.warnings);
|
||||
let r = read_ok(&format!("{section}{}{}", plugin_object(CALLIGRAPHIC, "Nib", NIB), layer("")));
|
||||
assert!(!r.warnings.iter().any(|w| w.contains("drawn look")), "{:?}", r.warnings);
|
||||
}
|
||||
|
||||
/// Editing data with one layer holding an image: `matrix` (`[a b c d tx ty]`), its size, colour
|
||||
/// space, kind and alpha channels, its samples, and the size the data comment declares.
|
||||
fn image(matrix: &str, (w, h): (u32, u32), (space, kind, alpha): (&str, u32, u32), data: &[u8], declared: usize) -> Vec<u8> {
|
||||
|
||||
Reference in New Issue
Block a user