mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-29 12:38:58 -06:00
M7: a resized page image stays blanked where the raster still has it
Two cases kept the old picture on screen after a move or resize: - A page that had no tiles when the edit applied was taken as drawn again as soon as a first tile arrived, while its backdrop still had the picture. Out of date now means its whole-page raster or any tile still waits for a replacement. - A second drag before the page was drawn again took the picture's pixels from its new frame, where the raster doesn't have it, and blanked only that. It now takes them from where the raster still has the picture and blanks that, and keeps it as the source on release. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
7a7d39f01f
commit
f632c1b0ca
@@ -1046,14 +1046,10 @@ impl DocView {
|
||||
self.pages.get(&page).map(|p| p.tex.id())
|
||||
}
|
||||
|
||||
/// Whether `page` is still drawn as it was before its last change: its raster, or on a tiled
|
||||
/// page any of its tiles, is waiting for a replacement.
|
||||
/// Whether `page` is still drawn, somewhere, as it was before its last change: its whole-page
|
||||
/// raster (a tiled page's backdrop too) or any of its tiles waits for a replacement.
|
||||
pub(crate) fn page_out_of_date(&self, page: usize) -> bool {
|
||||
if self.tiles.keys().any(|k| k.0 == page) {
|
||||
self.stale_tiles.iter().any(|k| k.0 == page)
|
||||
} else {
|
||||
self.pages.get(&page).is_some_and(|p| p.tag == STALE_TAG)
|
||||
}
|
||||
self.pages.get(&page).is_some_and(|p| p.tag == STALE_TAG) || self.stale_tiles.iter().any(|k| k.0 == page)
|
||||
}
|
||||
|
||||
/// The print preview's picture of `page`: the sheet raster when it has arrived, otherwise the
|
||||
|
||||
@@ -722,12 +722,13 @@ pub(crate) fn image_input(
|
||||
// Until the page is rendered again its raster has an applied move or resize's picture
|
||||
// where it was: it stays blanked there and drawn where it went.
|
||||
let (out_of_date, raster) = (view.page_out_of_date(page), view.page_raster(page));
|
||||
let screen = |r: Rect| Rect::from_two_pos(xf.norm_to_screen(r.min.x, r.min.y), xf.norm_to_screen(r.max.x, r.max.y));
|
||||
// Where the raster on screen has the picture: where it was before an applied move that
|
||||
// hasn't been rendered yet, else its frame. Another drag starts from there too.
|
||||
let drawn_at = view.image_selection.as_ref().and_then(|s| s.settled).filter(|_| out_of_date).map(|(from, _)| from);
|
||||
if let Some(s) = view.image_selection.as_mut().filter(|s| s.drag.is_none()) {
|
||||
match (s.settled, raster) {
|
||||
(Some((from, to)), Some(tex)) if out_of_date => {
|
||||
let screen = |r: Rect| Rect::from_two_pos(xf.norm_to_screen(r.min.x, r.min.y), xf.norm_to_screen(r.max.x, r.max.y));
|
||||
stretched_picture(painter, xf, tex, screen(from), screen(to));
|
||||
}
|
||||
(Some((from, to)), Some(tex)) if out_of_date => stretched_picture(painter, xf, tex, screen(from), screen(to)),
|
||||
_ => s.settled = None,
|
||||
}
|
||||
}
|
||||
@@ -788,7 +789,7 @@ pub(crate) fn image_input(
|
||||
if preview != b
|
||||
&& let Some(tex) = view.page_raster(page)
|
||||
{
|
||||
stretched_picture(painter, xf, tex, b, preview);
|
||||
stretched_picture(painter, xf, tex, drawn_at.map_or(b, screen), preview);
|
||||
}
|
||||
painter.rect_filled(visible, CornerRadius::ZERO, ACCENT.gamma_multiply(0.04));
|
||||
painter.rect_stroke(visible, CornerRadius::ZERO, Stroke::new(1.5, ACCENT), egui::StrokeKind::Outside);
|
||||
@@ -801,7 +802,7 @@ pub(crate) fn image_input(
|
||||
let ((u0, v0), (u1, v1)) = (xf.screen_to_norm(r.min), xf.screen_to_norm(r.max));
|
||||
Rect::from_two_pos(Pos2::new(u0, v0), Pos2::new(u1, v1))
|
||||
};
|
||||
s.settled = (preview != b).then(|| (norm(b), norm(preview)));
|
||||
s.settled = (preview != b).then(|| (drawn_at.unwrap_or_else(|| norm(b)), norm(preview)));
|
||||
}
|
||||
if preview != b {
|
||||
view.pending_edit =
|
||||
|
||||
@@ -4526,11 +4526,30 @@ fn a_resized_image_keeps_its_new_size_until_the_page_is_redrawn() {
|
||||
assert!(red(&pixels, kept) > 100, "frame {frame} after the release: the picture is not at its new size");
|
||||
assert_eq!(red(&pixels, gone), 0, "frame {frame} after the release: the picture shows at its old size");
|
||||
}
|
||||
// Resized again before the page is drawn: the raster still has the first size, so that is
|
||||
// what stays blanked while the corner moves.
|
||||
let (grip, to) = (to, at(80.0, 60.0));
|
||||
let again = egui::Rect::from_two_pos(at(62.0, 42.0), at(78.0, 58.0));
|
||||
h.hover_at(grip);
|
||||
h.run_steps(1);
|
||||
h.drag_at(grip);
|
||||
h.run_steps(1);
|
||||
for k in 1..=4 {
|
||||
h.hover_at(grip + (to - grip) * (k as f32 / 4.0));
|
||||
h.run_steps(1);
|
||||
}
|
||||
let pixels = h.render().unwrap();
|
||||
assert!(red(&pixels, again) > 20, "the second drag draws the picture at its new size");
|
||||
assert_eq!(red(&pixels, gone), 0, "the second drag shows the picture at its first size");
|
||||
h.drop_at(to);
|
||||
h.run_steps(2);
|
||||
let pixels = h.render().unwrap();
|
||||
assert_eq!(red(&pixels, gone), 0, "after the second release");
|
||||
h.state_mut().views[0].hold_rasters = false;
|
||||
support::wait_until(&mut h, "the page drawn with the resized picture", |app| !app.render_pending());
|
||||
h.run_steps(2);
|
||||
let pixels = h.render().unwrap();
|
||||
assert!(red(&pixels, kept) > 100 && red(&pixels, gone) == 0, "the page raster has the picture at its new size");
|
||||
assert!(red(&pixels, again) > 20 && red(&pixels, gone) == 0, "the page raster has the picture at its new size");
|
||||
}
|
||||
|
||||
/// Exercise actual pointer gestures on each cropped placement, without capturing private pixels.
|
||||
|
||||
Reference in New Issue
Block a user