mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 12:13:19 +00:00
Merge pull request #5886 from dotCooCoo/fix/ai-no-layers-active-artboard
.ai import: a file whose editing data has no layers also opens on its active artboard
This commit is contained in:
@@ -103,7 +103,8 @@ fn layer_tree(nodes: &[Arc<Node>]) -> Vec<Arc<Node>> {
|
||||
/// data was decompressed but its layers can't be read, and its swatches, brushes, graphic styles and
|
||||
/// variables those of the editing data's palette ([`use_palette`]), brushes ([`use_brushes`]), styles
|
||||
/// ([`use_styles`]) and variable library ([`use_variables`]) when it was decompressed: a graphic
|
||||
/// style library, which has no layers, opens with its styles. `outlined`: the PDF part's type was
|
||||
/// style library, which has no layers, opens with its styles, and editing data with no layers opens
|
||||
/// on the page of its active artboard under the checks of `place_pages`. `outlined`: the PDF part's type was
|
||||
/// read as outlines (a file whose type shows then comes in as its PDF part).
|
||||
/// `trust`: layers that draw differently from the PDF part are used all the same, with a warning.
|
||||
/// `unit`: the size in points of a unit of the PDF part's user space, its first page's `UserUnit`,
|
||||
@@ -134,10 +135,14 @@ pub fn layered_ai_from(
|
||||
};
|
||||
if !has_layers(&data) {
|
||||
let (mut visible, mut warnings) = (visible, warnings);
|
||||
let (boards, active) = ai::artboards(&data);
|
||||
if board_scale(&boards, &visible, unit).is_some() {
|
||||
visible.opened_artboard = active_page(active, &visible);
|
||||
}
|
||||
let have = visible.patterns.len();
|
||||
use_palette(&data, &mut visible);
|
||||
use_brushes(&data, &mut visible, have, &mut warnings);
|
||||
use_styles(&data, &mut visible, false, unit, None);
|
||||
use_styles(&data, &mut visible, false, unit, Some(&boards));
|
||||
use_variables(&data, &mut visible, &mut warnings);
|
||||
return (visible, warnings, false);
|
||||
}
|
||||
@@ -347,7 +352,7 @@ fn place_pages(boards: &[(String, Rect)], active: Option<usize>, doc: &mut Docum
|
||||
for ((name, _), a) in boards.iter().zip(&mut doc.artboards) {
|
||||
a.name.clone_from(name);
|
||||
}
|
||||
doc.opened_artboard = active.filter(|i| *i > 0).and_then(|i| doc.artboards.get(i)).map(|a| a.id);
|
||||
doc.opened_artboard = active_page(active, doc);
|
||||
let [(_, first), _, ..] = boards else { return };
|
||||
// Art space (y up) → the document, the first artboard's top left at the origin, as `read` has it,
|
||||
// `k` points a unit.
|
||||
@@ -362,6 +367,13 @@ fn place_pages(boards: &[(String, Rect)], active: Option<usize>, doc: &mut Docum
|
||||
}
|
||||
}
|
||||
|
||||
/// The id of the page of `doc` (a `.ai` read as its PDF part: a page per artboard) for the artboard
|
||||
/// at `active` among those of its editing data, to open the file on: `None` for the first, which a
|
||||
/// file opens on anyway, or when `doc` has no such page.
|
||||
fn active_page(active: Option<usize>, doc: &Document) -> Option<u32> {
|
||||
active.filter(|i| *i > 0).and_then(|i| doc.artboards.get(i)).map(|a| a.id)
|
||||
}
|
||||
|
||||
/// The objects in `layer` (and its sublayers) moved by the move of the page they are on.
|
||||
fn place_art(layer: &mut Node, pages: &[Rect], moves: &[Vec2]) {
|
||||
let Some(children) = layer.children_mut() else { return };
|
||||
|
||||
@@ -2335,6 +2335,49 @@ fn an_ai_file_read_as_its_pdf_part_keeps_its_active_artboard() {
|
||||
assert_eq!(d.opened_artboard, Some(2));
|
||||
}
|
||||
|
||||
/// A `.ai` whose editing data has artboards and no layers comes in as its PDF part, open on the
|
||||
/// page of the artboard the editing data names as the active one when there is a page per artboard
|
||||
/// of its size.
|
||||
#[test]
|
||||
fn an_ai_file_with_no_layers_keeps_its_active_artboard() {
|
||||
let board = |x0: i32| {
|
||||
format!(
|
||||
"%_/Dictionary :\n%_{x0} 100 /RealPointRelToROrigin\n%_ (PositionPoint1) ,\n%_{} 0 /RealPointRelToROrigin\n%_ (PositionPoint2) ,\n%_; ,\n",
|
||||
x0 + 100
|
||||
)
|
||||
};
|
||||
let no_layers = |active: &str| {
|
||||
native(&format!(
|
||||
"%_/Document :\n%_/Dictionary :\n%_/Array :\n{}{}%_; (ArtboardArray) ,\n{active}%_; /NotRecorded ,\n%_;\n",
|
||||
board(0),
|
||||
board(120)
|
||||
))
|
||||
};
|
||||
let mut pdf = pdf_part(10.0, 10.0);
|
||||
let mut page = pdf.artboards[0].clone();
|
||||
(page.id, page.rect) = (2, vectorcraft_geom::Rect::new(120.0, 0.0, 220.0, 100.0));
|
||||
pdf.artboards.push(page.clone());
|
||||
let opened = |pdf: &Document, active: &str| {
|
||||
let data = no_layers(active);
|
||||
assert!(!data.contains("%AI5_BeginLayer"));
|
||||
let (d, w, read) = crate::layered_ai(&private(&data), pdf.clone(), vec![], false, false, 1.0);
|
||||
assert!(!read && !w.iter().any(|w| w.contains("layers weren't read")), "{w:?}");
|
||||
assert_eq!(d.artboards.iter().map(|a| a.rect).collect::<Vec<_>>(), pdf.artboards.iter().map(|a| a.rect).collect::<Vec<_>>());
|
||||
d.opened_artboard
|
||||
};
|
||||
assert_eq!(opened(&pdf, "%_1 /Int (CropAreaActive) ,\n"), Some(2));
|
||||
assert_eq!(opened(&pdf, "%_0 /Int (CropAreaActive) ,\n"), None);
|
||||
assert_eq!(opened(&pdf, ""), None);
|
||||
// Not a page per artboard, or a page of another size: the pages aren't the artboards.
|
||||
let mut three = pdf.clone();
|
||||
(page.id, page.rect) = (3, vectorcraft_geom::Rect::new(240.0, 0.0, 340.0, 100.0));
|
||||
three.artboards.push(page);
|
||||
assert_eq!(opened(&three, "%_1 /Int (CropAreaActive) ,\n"), None);
|
||||
let mut other_size = pdf.clone();
|
||||
other_size.artboards[1].rect = vectorcraft_geom::Rect::new(120.0, 0.0, 320.0, 100.0);
|
||||
assert_eq!(opened(&other_size, "%_1 /Int (CropAreaActive) ,\n"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn art_moved_with_its_page_moves_its_pattern_tile() {
|
||||
// Two 100-point artboards, the second 50 below the first; an operator this doesn't know, so
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user