mirror of
https://github.com/storytold/deckcraft.git
synced 2026-11-10 20:39:36 -06:00
Fix up merged PRs: #588's polygon clip and nested metafiles with clip regions
Move #588's clip.rs changes into cliprect.rs, carry main's per-item clip region through the polygon clipper, and build nested-metafile items with the region field main added (the nested picture's own regions are not carried over; each item takes the canvas's current clip). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
4d7406be10
commit
389c4dd5d0
@@ -143,10 +143,10 @@ fn bbox_inside(b: [f64; 4], clip: &[P]) -> bool {
|
||||
pub(crate) fn clip_raw(raw: Raw, clip: &[P]) -> Vec<Raw> {
|
||||
let Some(cb) = pts_bbox(clip).filter(|_| clip.len() >= 3) else { return Vec::new() };
|
||||
match raw {
|
||||
Raw::Path { ops, fill, stroke, even_odd } => {
|
||||
Raw::Path { ops, fill, stroke, even_odd, region } => {
|
||||
let Some(b) = ops_bbox(&ops) else { return Vec::new() };
|
||||
if bbox_inside(b, clip) {
|
||||
return vec![Raw::Path { ops, fill, stroke, even_odd }];
|
||||
return vec![Raw::Path { ops, fill, stroke, even_odd, region }];
|
||||
}
|
||||
if disjoint(b, cb) {
|
||||
return Vec::new();
|
||||
@@ -156,34 +156,34 @@ pub(crate) fn clip_raw(raw: Raw, clip: &[P]) -> Vec<Raw> {
|
||||
if fill.is_some() {
|
||||
let f = clip_fill(&subs, clip);
|
||||
if !f.is_empty() {
|
||||
out.push(Raw::Path { ops: f, fill, stroke: None, even_odd });
|
||||
out.push(Raw::Path { ops: f, fill, stroke: None, even_odd, region: region.clone() });
|
||||
}
|
||||
}
|
||||
if stroke.is_some() {
|
||||
let s = clip_stroke(&subs, clip);
|
||||
if !s.is_empty() {
|
||||
out.push(Raw::Path { ops: s, fill: None, stroke, even_odd });
|
||||
out.push(Raw::Path { ops: s, fill: None, stroke, even_odd, region });
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
Raw::Pattern { ops, even_odd, tile } => {
|
||||
Raw::Pattern { ops, even_odd, tile, region } => {
|
||||
let Some(b) = ops_bbox(&ops) else { return Vec::new() };
|
||||
if bbox_inside(b, clip) {
|
||||
return vec![Raw::Pattern { ops, even_odd, tile }];
|
||||
return vec![Raw::Pattern { ops, even_odd, tile, region }];
|
||||
}
|
||||
if disjoint(b, cb) {
|
||||
return Vec::new();
|
||||
}
|
||||
let f = clip_fill(&flatten(&ops), clip);
|
||||
if f.is_empty() { Vec::new() } else { vec![Raw::Pattern { ops: f, even_odd, tile }] }
|
||||
if f.is_empty() { Vec::new() } else { vec![Raw::Pattern { ops: f, even_odd, tile, region }] }
|
||||
}
|
||||
Raw::Bitmap { rect, img } => crop(rect, img, clip).map(|(rect, img)| vec![Raw::Bitmap { rect, img }]).unwrap_or_default(),
|
||||
Raw::Text(mut t) => {
|
||||
Raw::Bitmap { rect, img, region } => crop(rect, img, clip).map(|(rect, img)| vec![Raw::Bitmap { rect, img, region }]).unwrap_or_default(),
|
||||
Raw::Text { text: mut t, region } => {
|
||||
// Text clips to a rectangle: the one around the polygon.
|
||||
let cur = t.clip.map_or(cb, |[a, b, d, e]| intersect(cb, [f64::from(a), f64::from(b), f64::from(d), f64::from(e)]));
|
||||
t.clip = Some(cur.map(|v| v as f32));
|
||||
vec![Raw::Text(t)]
|
||||
vec![Raw::Text { text: t, region }]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,15 +737,21 @@ impl Painter {
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
// The nested picture's own clip regions are not carried over: each item takes the
|
||||
// canvas's current clip.
|
||||
for item in &pic.items {
|
||||
if cv.full() {
|
||||
break;
|
||||
}
|
||||
let raw = match item {
|
||||
Item::Path { segs, fill, stroke, even_odd } => {
|
||||
Raw::Path { ops: ops(segs), fill: *fill, stroke: stroke.map(|(c, w)| (c, f64::from(w) * scale)), even_odd: *even_odd }
|
||||
}
|
||||
Item::Pattern { segs, even_odd, tile } => Raw::Pattern {
|
||||
Item::Path { segs, fill, stroke, even_odd, .. } => Raw::Path {
|
||||
ops: ops(segs),
|
||||
fill: *fill,
|
||||
stroke: stroke.map(|(c, w)| (c, f64::from(w) * scale)),
|
||||
even_odd: *even_odd,
|
||||
region: None,
|
||||
},
|
||||
Item::Pattern { segs, even_odd, tile, .. } => Raw::Pattern {
|
||||
ops: ops(segs),
|
||||
even_odd: *even_odd,
|
||||
tile: Arc::new(RawTile {
|
||||
@@ -754,12 +760,13 @@ impl Painter {
|
||||
px: tile.rgba.clone(),
|
||||
cell: f64::from(tile.cell[0]) * scale,
|
||||
}),
|
||||
region: None,
|
||||
},
|
||||
Item::Bitmap { rect, width, height, rgba } => {
|
||||
Item::Bitmap { rect, width, height, rgba, .. } => {
|
||||
let (a, b) = (pt(rect[0], rect[1]), pt(rect[0] + rect[2], rect[1] + rect[3]));
|
||||
let mut img = Rgba { w: *width as usize, h: *height as usize, bottom_up: false, px: rgba.clone() };
|
||||
crate::dib::flip(&mut img, a.0 > b.0, a.1 > b.1);
|
||||
Raw::Bitmap { rect: [a.0.min(b.0), a.1.min(b.1), (b.0 - a.0).abs(), (b.1 - a.1).abs()], img }
|
||||
Raw::Bitmap { rect: [a.0.min(b.0), a.1.min(b.1), (b.0 - a.0).abs(), (b.1 - a.1).abs()], img, region: None }
|
||||
}
|
||||
Item::Text(t) => {
|
||||
let mut t = t.clone();
|
||||
@@ -768,7 +775,7 @@ impl Painter {
|
||||
let (p, q) = (pt(x0, y0), pt(x1, y1));
|
||||
t.clip = Some([p.0.min(q.0) as f32, p.1.min(q.1) as f32, p.0.max(q.0) as f32, p.1.max(q.1) as f32]);
|
||||
}
|
||||
Raw::Text(t)
|
||||
Raw::Text { text: t, region: None }
|
||||
}
|
||||
};
|
||||
cv.push_device(raw);
|
||||
|
||||
Reference in New Issue
Block a user