mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 21:44:57 +00:00
Merge pull request #7471 from dotCooCoo/fix/followup-7319
.ai save: a clipping path cut away outside keeps its text wrap options
This commit is contained in:
@@ -1187,6 +1187,28 @@ fn a_symbol_definition_is_written_only_with_room_for_its_instance() {
|
||||
}
|
||||
}
|
||||
|
||||
/// A symbol definition without room for its group, asked for by an instance in art drawn for an
|
||||
/// object (a stained instance's art), is left out and leaves the writing of that art as it was.
|
||||
#[test]
|
||||
fn a_symbol_definition_without_room_in_drawn_art_is_left_out() {
|
||||
let mut doc = Document::new(200.0, 100.0);
|
||||
let layer = doc.layers[0].id;
|
||||
let dot = square(&mut doc, Rect::new(0.0, 0.0, 10.0, 10.0), Color::gray(0.5));
|
||||
doc.symbols.push(Symbol { dynamic: false, name: "Dot".into(), art: Arc::new(dot) });
|
||||
let inner = instance(&mut doc, "Dot", Affine::IDENTITY);
|
||||
doc.symbols.push(Symbol { dynamic: false, name: "Badge".into(), art: Arc::new(inner) });
|
||||
let mut stained = instance(&mut doc, "Badge", Affine::translate((50.0, 10.0)));
|
||||
stained.appearance = Appearance::basic(solid(Color::rgb(1.0, 0.0, 0.0)), Paint::None, 0.0).into();
|
||||
doc.insert(Some(layer), usize::MAX, stained).unwrap();
|
||||
let read = crate::import::objects_read(&export_ai_editing(&doc, &opts()).unwrap().program).unwrap();
|
||||
for max in 0..read {
|
||||
let out = export_within(&doc, &opts(), max).unwrap();
|
||||
assert!(out.warnings.iter().any(|w| w == writer::OBJECT_LIMIT), "room for {max} of {read}");
|
||||
let objects = crate::import::objects_read(&out.program).unwrap();
|
||||
assert!(objects <= max, "{objects} objects read with room for {max}");
|
||||
}
|
||||
}
|
||||
|
||||
/// The writer's limit is the reader's, which its warning names.
|
||||
#[test]
|
||||
fn the_object_limit_is_the_readers() {
|
||||
@@ -10563,14 +10585,15 @@ fn text_wrap_options_of_type_and_envelopes_are_read_back() {
|
||||
}
|
||||
|
||||
/// A clipping path inside art cut to a clipping object is written as its fills and its strokes,
|
||||
/// two objects: its text wrap options are written once, whether it has both or only strokes.
|
||||
/// two objects: its text wrap options are written once, whether it has both or only strokes, and
|
||||
/// with its strokes when the region outside leaves nothing of its fills.
|
||||
#[test]
|
||||
fn a_clipping_path_written_as_its_paint_keeps_one_text_wrap() {
|
||||
for fill in [solid(Color::gray(0.5)), Paint::None] {
|
||||
for (fill, left, width) in [(solid(Color::gray(0.5)), 20.0, 2.0), (Paint::None, 20.0, 2.0), (solid(Color::gray(0.5)), 101.0, 4.0)] {
|
||||
let mut doc = Document::new(200.0, 100.0);
|
||||
let layer = doc.layers[0].id;
|
||||
let mut cutter = clipping(&mut doc, shapes::rectangle(Rect::new(20.0, 20.0, 80.0, 80.0)));
|
||||
cutter.appearance = Appearance::basic(fill, solid(Color::BLACK), 2.0).into();
|
||||
let mut cutter = clipping(&mut doc, shapes::rectangle(Rect::new(left, 20.0, left + 60.0, 80.0)));
|
||||
cutter.appearance = Appearance::basic(fill, solid(Color::BLACK), width).into();
|
||||
let cutter = wrapped(cutter, 5.0, true);
|
||||
let member = square(&mut doc, Rect::new(30.0, 30.0, 120.0, 60.0), Color::rgb(1.0, 0.0, 0.0));
|
||||
let inner = group(&mut doc, vec![cutter, member], true);
|
||||
|
||||
@@ -1102,22 +1102,25 @@ impl<'a> Writer<'a> {
|
||||
|
||||
/// A container's members, the first one's outline cutting the others: its fills painted
|
||||
/// behind them (cut to the region outside too), its strokes over them, not cut by it. Its text
|
||||
/// wrap options are written once: with its fills, or without fills with its strokes.
|
||||
/// wrap options are written once: with its fills, or with its strokes when no fill object is
|
||||
/// written (it has no fills, or the region outside leaves nothing of them).
|
||||
fn clip_contents(&mut self, children: &[Arc<Node>]) {
|
||||
let Some((first, rest)) = children.split_first() else { return };
|
||||
// Nothing to clip by hides the clipped art.
|
||||
let Some((outline, rule)) = vectorcraft_effects::clip_outline(first) else { return };
|
||||
let mut paint = first.clip_paint();
|
||||
if let (Some(_), Some(stroke)) = (&paint.fill, &mut paint.stroke)
|
||||
&& stroke.extras().wrap.is_some()
|
||||
{
|
||||
stroke.extras_mut().wrap = None;
|
||||
}
|
||||
let outer = self.clip.clone();
|
||||
let region = self.cut(&PathData::from_bezpath(&outline), rule);
|
||||
self.clip = Some(region);
|
||||
if let Some(fill) = &paint.fill {
|
||||
let objects = self.objects;
|
||||
self.node(fill);
|
||||
if self.objects > objects
|
||||
&& let Some(stroke) = &mut paint.stroke
|
||||
&& stroke.extras().wrap.is_some()
|
||||
{
|
||||
stroke.extras_mut().wrap = None;
|
||||
}
|
||||
}
|
||||
for c in rest {
|
||||
self.node(c);
|
||||
|
||||
@@ -233,6 +233,7 @@ impl Writer<'_> {
|
||||
if !self.take_objects(1) {
|
||||
self.defining_symbols.pop();
|
||||
self.keep_since(before);
|
||||
(self.in_look, self.drawn) = (in_look, drawn);
|
||||
return false;
|
||||
}
|
||||
// The art is written in the symbol's space, from the state `0 A` and `0 Xw` set, from the
|
||||
|
||||
Reference in New Issue
Block a user