mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-30 13:16:56 -06:00
Baseline grid: find the page under a grouped frame from its spread position
A group's transform can move a frame onto another page; the page lookup used the frame's bounds without its parents' transforms, so the grid took the wrong page's top margin.
This commit is contained in:
@@ -686,17 +686,18 @@ pub fn frame_specs(doc: &Document, sid: StoryId) -> Vec<FrameSpec> {
|
||||
r.is_finite() && r.x0 < a.x1 && r.x1 > a.x0 && r.y0 < a.y1 && r.y1 > a.y0
|
||||
});
|
||||
}
|
||||
// The frame's center on its spread: a group around it can move it to another page.
|
||||
let center_x = loc.as_ref().map_or(item.bounds(), |l| doc.parent_xf(l).transform_rect_bbox(item.bounds())).center().x;
|
||||
let (page_name, page, left_page) = match (spread_ref, spread) {
|
||||
(Some(designcraft_doc::SpreadRef::Doc(si)), Some(sp)) => {
|
||||
let c = item.bounds().center();
|
||||
let pi = sp.page_at_x(c.x).unwrap_or(0);
|
||||
let pi = sp.page_at_x(center_x).unwrap_or(0);
|
||||
let abs = doc.first_page_of_spread(si) + pi;
|
||||
(Some(doc.page_name(abs)), Some(abs), sp.pages.get(pi).is_some_and(|p| p.side == designcraft_doc::PageSide::Left))
|
||||
}
|
||||
(Some(designcraft_doc::SpreadRef::Parent(_)), Some(sp)) => {
|
||||
let prefix = sp.parent.as_ref().map(|p| p.prefix.clone()).unwrap_or_else(|| "A".into());
|
||||
// The side of the parent page under the frame, so a folio there aligns to the spine of its own page.
|
||||
let under = sp.page_at_x(item.bounds().center().x).and_then(|pi| sp.pages.get(pi));
|
||||
let under = sp.page_at_x(center_x).and_then(|pi| sp.pages.get(pi));
|
||||
let left = under.is_some_and(|p| p.side == designcraft_doc::PageSide::Left);
|
||||
(Some(prefix), None, left)
|
||||
}
|
||||
@@ -704,7 +705,7 @@ pub fn frame_specs(doc: &Document, sid: StoryId) -> Vec<FrameSpec> {
|
||||
};
|
||||
let section_marker = page.map(|abs| section_marker(doc, abs));
|
||||
// The page under the frame, and its bounds and margins in inner space (bounding boxes).
|
||||
let under = spread.and_then(|sp| sp.page_at_x(item.bounds().center().x).and_then(|pi| sp.pages.get(pi)));
|
||||
let under = spread.and_then(|sp| sp.page_at_x(center_x).and_then(|pi| sp.pages.get(pi)));
|
||||
let page_rect = under.map(|pg| (inv.transform_rect_bbox(pg.bounds()), inv.transform_rect_bbox(pg.margin_rect())));
|
||||
let g = &doc.settings.baseline_grid;
|
||||
let (inc, start) = tf.options.baseline_grid.unwrap_or((g.increment, under.map_or(g.start, |pg| g.origin(pg))));
|
||||
|
||||
@@ -7254,6 +7254,32 @@ fn baseline_grid_relative_to_the_top_margin_starts_at_each_pages_margin() {
|
||||
assert_eq!(lines.len(), 41);
|
||||
}
|
||||
|
||||
/// A group's transform moves a frame from the left page of a spread to the right one: the grid
|
||||
/// starts at the right page's top margin.
|
||||
#[test]
|
||||
fn baseline_grid_follows_a_grouped_frame_to_its_page() {
|
||||
use designcraft_doc::{Content, GridRelative, Item, ItemId, Shape};
|
||||
let mut d = Document::new(&NewDocument { pages: 3, facing_pages: true, margins: designcraft_doc::Margins::uniform(36.0), ..Default::default() });
|
||||
Arc::make_mut(&mut d.spreads[1]).pages[1].margins.top = 48.0;
|
||||
d.settings.baseline_grid.start = 0.0;
|
||||
d.settings.baseline_grid.increment = 13.0;
|
||||
d.settings.baseline_grid.relative_to = GridRelative::TopMargin;
|
||||
let lid = d.default_layer();
|
||||
let para = ParaFormat { para: ParaAttrs { grid_align: Some(GridAlign::AllLines), ..Default::default() }, ..Default::default() };
|
||||
let (fid, sid) = d.add_text_frame(SpreadRef::Doc(1), Rect::new(36.0, 36.0, 336.0, 582.0), lid, LOREM, para).unwrap();
|
||||
let sp = Arc::make_mut(&mut d.spreads[1]);
|
||||
let at = sp.items.iter().position(|it| it.id == fid).unwrap();
|
||||
let frame = sp.items.remove(at);
|
||||
let right = sp.pages[1].x;
|
||||
let mut g = Item::new(ItemId(d.alloc()), lid, Shape::Group, designcraft_geom::PathData::default());
|
||||
g.content = Content::Group { items: vec![frame] };
|
||||
g.xf = designcraft_geom::Affine::translate((right, 0.0));
|
||||
Arc::make_mut(&mut d.spreads[1]).items.push(Arc::new(g));
|
||||
let cs = compose_story(&d, sid, &ComposeOptions::default());
|
||||
let first = cs.frames[0].lines[0].baseline;
|
||||
assert!((first - 61.0).abs() < 1e-6, "{first}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cache_recomposes_when_the_grid_reference_or_a_top_margin_changes() {
|
||||
use designcraft_doc::GridRelative;
|
||||
|
||||
Reference in New Issue
Block a user