mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-26 02:37:01 -06:00
Merge pull request #2665 from dotCooCoo/fix/print-tiling-artboard-edge
Print: a Print Tiling origin on an artboard's right or bottom edge is measured from that artboard
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_doc::Document;
|
||||
use vectorcraft_geom::Point;
|
||||
use vectorcraft_geom::{Point, Rect};
|
||||
use vectorcraft_pdf::{TileOrigin, TilingPage};
|
||||
|
||||
use super::fileio::pdf::pdf_error;
|
||||
@@ -30,7 +30,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Print Tiling",
|
||||
[],
|
||||
None,
|
||||
"{origin: [x, y] (document point: the top-left corner of the first page's imageable area), artboard? (0-based: the artboard it is measured from; default the printed artboard containing origin, else the first; ignored with artboards: ignore)} | {reset: true} place the printed pages as the Print Tiling tool does, saved with the print settings (tileOrigin: {placed, x, y}, from the artboard's top-left corner; it replaces the placement, and tiles start there), as one undo step; reset → the placement places them again → {tileOrigin}",
|
||||
"{origin: [x, y] (document point: the top-left corner of the first page's imageable area), artboard? (0-based: the artboard it is measured from; default the printed artboard containing origin, its edges included, else the first; ignored with artboards: ignore)} | {reset: true} place the printed pages as the Print Tiling tool does, saved with the print settings (tileOrigin: {placed, x, y}, from the artboard's top-left corner; it replaces the placement, and tiles start there), as one undo step; reset → the placement places them again → {tileOrigin}",
|
||||
has_doc,
|
||||
set_origin
|
||||
),
|
||||
@@ -77,6 +77,13 @@ fn point(p: &Value, key: &str) -> Option<Point> {
|
||||
Some(Point::new(a.first()?.as_f64()?, a.get(1)?.as_f64()?))
|
||||
}
|
||||
|
||||
/// The first of the print `regions` holding `at`: one that holds it inside or on its left or top
|
||||
/// edge, else one that holds it on its right or bottom edge or within a millionth of a point
|
||||
/// outside an edge (the edges `Document::art_on_artboard` counts).
|
||||
fn region_holding(regions: &[(Option<usize>, Rect)], at: Point) -> Option<&(Option<usize>, Rect)> {
|
||||
regions.iter().find(|(_, r)| r.contains(at)).or_else(|| regions.iter().find(|(_, r)| vectorcraft_doc::artboard_holds(*r, at)))
|
||||
}
|
||||
|
||||
fn set_origin(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let doc = &s.doc()?.doc;
|
||||
let current = settings(SET, doc, &json!({}))?;
|
||||
@@ -92,7 +99,7 @@ fn set_origin(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let i = v.as_u64().ok_or_else(|| bad(SET, "artboard must be a 0-based index"))? as usize;
|
||||
regions.iter().find(|(a, _)| a.is_none() || *a == Some(i)).ok_or_else(|| bad(SET, format!("artboard {i} doesn't print")))?
|
||||
}
|
||||
None => regions.iter().find(|(_, r)| r.contains(at)).or(regions.first()).ok_or_else(|| bad(SET, "nothing prints"))?,
|
||||
None => region_holding(®ions, at).or(regions.first()).ok_or_else(|| bad(SET, "nothing prints"))?,
|
||||
};
|
||||
let corner = picked.1.origin();
|
||||
TileOrigin { placed: true, x: at.x - corner.x, y: at.y - corner.y }
|
||||
|
||||
@@ -147,6 +147,26 @@ fn tiles_start_at_the_tile_origin_and_cover_the_art() {
|
||||
assert!(s.execute("print.tiling.set", &json!({"origin": [1e9, 2]})).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_origin_on_an_artboards_right_or_bottom_edge_is_measured_from_that_artboard() {
|
||||
// Artboard 0 is (0, 0) to (300, 200). Artboard 1 is (300, 0) to (600, 200), and its left edge is artboard 0's right edge.
|
||||
let mut s = session();
|
||||
s.execute("artboard.new", &json!({"x": 300, "y": 0, "width": 300, "height": 200})).unwrap();
|
||||
let mut placed = |x: f64, y: f64| {
|
||||
let o = s.execute("print.tiling.set", &json!({"origin": [x, y]})).unwrap()["tileOrigin"].clone();
|
||||
(o["x"].as_f64().unwrap(), o["y"].as_f64().unwrap())
|
||||
};
|
||||
assert_eq!(placed(600.0, 50.0), (300.0, 50.0), "artboard 1's right edge");
|
||||
assert_eq!(placed(450.0, 200.0), (150.0, 200.0), "artboard 1's bottom edge");
|
||||
assert_eq!(placed(600.0, 200.0), (300.0, 200.0), "artboard 1's bottom right corner");
|
||||
assert_eq!(placed(150.0, 200.0), (150.0, 200.0), "artboard 0's bottom edge");
|
||||
assert_eq!(placed(300.0, 50.0), (0.0, 50.0), "the shared edge: the artboard to its right");
|
||||
let (x, _) = placed(600.0 + 1e-9, 50.0);
|
||||
assert!((x - 300.0).abs() < 1e-6, "roundoff past the edge: {x}");
|
||||
// Beyond every artboard the origin is measured from the first.
|
||||
assert_eq!(placed(600.001, 50.0), (600.001, 50.0), "beyond the edge");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn settings_saved_before_the_tile_origin_still_load() {
|
||||
let mut s = session();
|
||||
|
||||
@@ -39,7 +39,7 @@ impl Tool for PrintTilingTool {
|
||||
fn pointer(&mut self, cx: &ToolContext, ev: &PointerEvent) -> Vec<Action> {
|
||||
match ev.kind {
|
||||
PointerKind::Down => {
|
||||
let hit = cx.doc.artboards.iter().position(|a| a.rect.contains(ev.pos));
|
||||
let hit = cx.doc.artboard_holding(ev.pos, false);
|
||||
self.drag = Some((hit, hit.and_then(|i| cx.doc.artboards.get(i)).map(|a| a.rect)));
|
||||
(self.began, self.last) = (false, ev.pos);
|
||||
vec![]
|
||||
@@ -98,7 +98,7 @@ impl Tool for PrintTilingTool {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::json;
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_doc::Selection;
|
||||
|
||||
use super::*;
|
||||
@@ -134,4 +134,31 @@ mod tests {
|
||||
assert_eq!(t.key(&c, ToolKey::Escape, Mods::default()), vec![Action::Cancel]);
|
||||
assert_eq!(crate::create("printTiling").id(), "printTiling");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_press_on_an_artboards_right_or_bottom_edge_drags_from_that_artboard() {
|
||||
// Artboard 0 is (0, 0) to (500, 500). Artboard 1 is (500, 0) to (800, 200), and its left edge lies on artboard 0's right edge.
|
||||
let (mut d, _) = doc_with_rect();
|
||||
let mut ab = d.artboards[0].clone();
|
||||
ab.rect = Rect::new(500.0, 0.0, 800.0, 200.0);
|
||||
d.artboards.push(ab);
|
||||
let (s, pd) = (Selection::default(), paint());
|
||||
let c = cx(&d, &s, &pd);
|
||||
// What a drag to 3 pt up and left of a press at (x, y) previews: the corner snaps to the
|
||||
// edges of the artboard the press picked.
|
||||
let drag = |x: f64, y: f64| {
|
||||
let mut t = PrintTilingTool::default();
|
||||
t.pointer(&c, &ev(PointerKind::Down, x, y));
|
||||
t.pointer(&c, &ev(PointerKind::Drag, x - 3.0, y - 3.0)).pop()
|
||||
};
|
||||
let preview =
|
||||
|origin: [f64; 2], artboard: Value| Some(Action::Preview("print.tiling.set".into(), json!({ "origin": origin, "artboard": artboard })));
|
||||
assert_eq!(drag(800.0, 100.0), preview([800.0, 97.0], json!(1)), "artboard 1's right edge");
|
||||
assert_eq!(drag(650.0, 200.0), preview([647.0, 200.0], json!(1)), "artboard 1's bottom edge");
|
||||
assert_eq!(drag(800.0, 200.0), preview([800.0, 200.0], json!(1)), "artboard 1's bottom right corner");
|
||||
assert_eq!(drag(300.0, 500.0), preview([297.0, 500.0], json!(0)), "artboard 0's bottom edge");
|
||||
assert_eq!(drag(500.0, 100.0), preview([500.0, 97.0], json!(1)), "the shared edge: the artboard to its right");
|
||||
assert_eq!(drag(800.0 + 1e-9, 100.0), preview([800.0, 97.0], json!(1)), "roundoff past the edge");
|
||||
assert_eq!(drag(800.001, 100.0), preview([800.001 - 3.0, 97.0], Value::Null), "beyond the edge");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user