mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Merge pull request #3189 from AJMakesStuff/3179---Envelope-Distort
(3179) Envelope Distort
This commit is contained in:
@@ -1412,17 +1412,33 @@ impl<'a> Reader<'a> {
|
||||
return Ok(());
|
||||
}
|
||||
let Some(f) = self.frames.pop() else { return Ok(()) };
|
||||
let Kind::Obj(mut o) = f.kind else { return Ok(()) };
|
||||
obj::close(&mut o, &mut self.stack, f.base);
|
||||
self.obj_hidden = f.hidden;
|
||||
let Frame { kind, children, base, hidden, gs, after, .. } = f;
|
||||
let Kind::Obj(mut o) = kind else { return Ok(()) };
|
||||
obj::close(&mut o, &mut self.stack, base);
|
||||
self.obj_hidden = hidden;
|
||||
// Art made inside a dictionary (type's paths) isn't kept.
|
||||
self.gs = f.gs;
|
||||
self.after_object = f.after;
|
||||
self.gs = gs;
|
||||
self.after_object = after;
|
||||
if matches!(self.frames.last(), Some(Frame { kind: Kind::Obj(_), .. })) {
|
||||
return self.push(V::Obj(Rc::new(*o)));
|
||||
}
|
||||
match o.ty.as_str() {
|
||||
"ArtDictionary" => self.art_dictionary(&o),
|
||||
"ArtDictionary" => {
|
||||
let envelope = o.get("AIDeformOptionsKey").is_some();
|
||||
self.art_dictionary(&o);
|
||||
if envelope {
|
||||
let mut slots = vec![];
|
||||
for child in &children {
|
||||
envelope_text_slots(child, &mut slots);
|
||||
}
|
||||
for mut slot in slots {
|
||||
// The editing data keeps the source text inside the envelope's options;
|
||||
// its visible result is the outlined art the PDF page carries.
|
||||
slot.visible = false;
|
||||
self.add(slot, false)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
"Document" => self.document(&o),
|
||||
"AI11Text" => self.text_slot(&o)?,
|
||||
"SymbolInstance" => self.unreadable("symbols"),
|
||||
@@ -2336,6 +2352,17 @@ impl<'a> Reader<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The source text inside an envelope options dictionary, carried through its containing metadata.
|
||||
fn envelope_text_slots(node: &Node, out: &mut Vec<Node>) {
|
||||
if slot_of(node.name.as_deref()).is_some() {
|
||||
out.push(node.clone());
|
||||
} else if let Some(children) = node.children() {
|
||||
for child in children {
|
||||
envelope_text_slots(child, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The text objects written twice, plainly and on `%_` lines: the commented copy (`hidden`) of a
|
||||
/// story that also has a plain one goes.
|
||||
fn drop_commented_copies(layers: &mut [Arc<Node>], hidden: &HashSet<NodeId>) {
|
||||
|
||||
@@ -1332,3 +1332,23 @@ fn raster_print_page_recovers_legacy_mesh_vector_mask_and_editable_curve() {
|
||||
let r = import(wrong.as_bytes()).unwrap();
|
||||
assert!(r.warnings.iter().any(|w| w.contains("for a 100 × 100 pt page, not the file's 120 × 100 pt page")), "{:?}", r.warnings);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn envelope_options_keep_the_source_text_hidden_under_its_outlined_appearance() {
|
||||
let doc = text_document(&[("CHONKYCATS\r", 0, (8200.0, 8180.0), (0.0, 0.0), 0.0)]);
|
||||
let slot: String = text_object(0).lines().map(|line| format!("%_{line}\n")).collect();
|
||||
let envelope =
|
||||
format!("%_/ArtDictionary :\n%_1 /Int (AIDeformOptionsKey) ,\n%_198 /Real (AIDeformArtHeightKey) ,\n%_X=\n%_0 Ae\n%_u\n{slot}%_U\n%_;\n");
|
||||
let art = native_with_text(&layer("Art", true, &format!("{}\n{envelope}", square(10, 10))), &doc);
|
||||
let r = import(&eps(&page_square(10, 10), &art)).unwrap();
|
||||
assert_eq!(names(&r.document), ["Art"], "{:?}", r.warnings);
|
||||
assert_eq!(kinds(&r.document.layers[0]), ["path", "text"], "{:?}", r.warnings);
|
||||
let mut texts = vec![];
|
||||
r.document.walk(|n| {
|
||||
if let NodeKind::Text(t) = &n.kind {
|
||||
texts.push((t.plain_text(), n.visible));
|
||||
}
|
||||
});
|
||||
assert_eq!(texts, [("CHONKYCATS".to_string(), false)], "{:?}", r.warnings);
|
||||
assert!(r.warnings.is_empty(), "{:?}", r.warnings);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user