ElyPDF: an edit keeps the page drawn until its repaint lands (R2.6)
This commit is contained in:
4 files changed
+56
-2
No files matched your search
@@ -97,9 +97,15 @@ impl PdfView {
|
||||
self.version += 1;
|
||||
self.edited += 1;
|
||||
(self.doc, self.mark) = (fresh.doc, fresh.mark);
|
||||
self.sizes = sizes(fresh.pages, &fresh.first);
|
||||
let sizes = sizes(fresh.pages, &fresh.first);
|
||||
// Same pages: old tiles stay until repainted, so nothing flashes.
|
||||
if sizes == self.sizes {
|
||||
self.stale.extend(self.tiles.keys().copied());
|
||||
} else {
|
||||
self.retire_tiles();
|
||||
}
|
||||
self.sizes = sizes;
|
||||
self.marks = fresh.marks;
|
||||
self.retire_tiles();
|
||||
self.failed.clear();
|
||||
self.text.clear();
|
||||
self.asking_text.clear();
|
||||
|
||||
@@ -164,6 +164,9 @@ impl PdfView {
|
||||
let key = TileKey { page: place.page, scale, rotate: self.rotate, dark, tx, ty };
|
||||
let rect = [tx * TILE, ty * TILE, TILE.min(dw - tx * TILE), TILE.min(dh - ty * TILE)];
|
||||
seen.insert(key);
|
||||
if self.stale.contains(&key) && !self.failed.contains(&key) {
|
||||
wanted.push((key, rect));
|
||||
}
|
||||
match self.tiles.get(&key) {
|
||||
Some(image) => tiles.push(
|
||||
drawn_tile(image.clone(), place.page, cx.entity())
|
||||
@@ -190,6 +193,7 @@ impl PdfView {
|
||||
}
|
||||
kept
|
||||
});
|
||||
self.stale.retain(|key| seen.contains(key));
|
||||
let pages_shown: Vec<usize> = shown.iter().map(|place| place.page).collect();
|
||||
self.ask_layers(&pages_shown, cx);
|
||||
self.ask_notes(pages_shown.iter().copied(), cx);
|
||||
@@ -295,6 +299,7 @@ impl PdfView {
|
||||
match painted.map(|bgra| picture((rect[2] as u32, rect[3] as u32), bgra)) {
|
||||
Ok(Some(image)) => {
|
||||
log::debug!("pdf: a tile of page {} came", key.page);
|
||||
view.stale.remove(&key);
|
||||
if let Some(old) = view.tiles.insert(key, image) {
|
||||
view.retired.push(old);
|
||||
}
|
||||
|
||||
@@ -185,3 +185,42 @@ fn tiles_beside_the_view_are_neither_asked_nor_kept() {
|
||||
}));
|
||||
settle(cx, |app| columns(app).contains(&last) && !columns(app).contains(&0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_edit_keeps_the_page_drawn_until_its_repaint_lands() {
|
||||
let dir = tempfile::tempdir().expect("a temp dir");
|
||||
let mut cx = TestAppContext::single();
|
||||
let (viewer, cx) = windowed(&mut cx, dir.path(), &[file(dir.path(), "one.pdf", &[(612.0, 792.0, &["Hello"])])], true);
|
||||
let view = shown(cx, &viewer);
|
||||
settle(cx, |app| !view.read(app).tiles.is_empty() && !view.read(app).painting);
|
||||
let before: Vec<_> = cx.update(|_, app| view.read(app).tiles.values().cloned().collect());
|
||||
let note = ely_pdf_engine::NewAnnot {
|
||||
page: 0,
|
||||
shape: ely_pdf_engine::Shape::Note((100.0, 500.0)),
|
||||
rgb: None,
|
||||
contents: "Look".into(),
|
||||
author: String::new(),
|
||||
};
|
||||
// Watches every notify, the edit's own included, before repaints.
|
||||
let blank = std::rc::Rc::new(std::cell::Cell::new(false));
|
||||
let seen = blank.clone();
|
||||
let _watch = cx.update(|_, app| {
|
||||
app.observe(&view, move |view, app| {
|
||||
let read = view.read(app);
|
||||
if read.edited == 1 && read.tiles.is_empty() {
|
||||
seen.set(true);
|
||||
}
|
||||
})
|
||||
});
|
||||
cx.update(|_, app| view.update(app, |view, cx| view.annotate("adding a note", vec![note], cx)));
|
||||
settle(cx, |app| {
|
||||
let read = view.read(app);
|
||||
read.edited == 1 && read.stale.is_empty() && !read.painting
|
||||
});
|
||||
assert!(!blank.get(), "the page never goes blank");
|
||||
let after = cx.update(|_, app| view.read(app).tiles.values().cloned().collect::<Vec<_>>());
|
||||
assert!(
|
||||
after.iter().all(|image| before.iter().all(|old| !std::sync::Arc::ptr_eq(old, image))),
|
||||
"every tile was painted again"
|
||||
);
|
||||
}
|
||||
@@ -41,6 +41,8 @@ pub struct PdfView {
|
||||
pub drawn: bool,
|
||||
/// Tiles the worker could not draw; not asked again.
|
||||
pub failed: HashSet<TileKey>,
|
||||
/// Tiles from before an edit: shown until their repaint lands.
|
||||
pub stale: HashSet<TileKey>,
|
||||
pub text: HashMap<usize, Arc<Vec<Char>>>,
|
||||
pub asking_text: HashSet<usize>,
|
||||
pub marks: Vec<Bookmark>,
|
||||
@@ -166,6 +168,7 @@ impl PdfView {
|
||||
retired: Default::default(),
|
||||
drawn: false,
|
||||
failed: HashSet::new(),
|
||||
stale: HashSet::new(),
|
||||
text: HashMap::new(),
|
||||
asking_text: HashSet::new(),
|
||||
marks: loaded.marks,
|
||||
@@ -311,6 +314,7 @@ impl PdfView {
|
||||
|
||||
/// Every page tile goes; images are freed next render.
|
||||
pub fn retire_tiles(&mut self) {
|
||||
self.stale.clear();
|
||||
for (_, image) in self.tiles.drain() {
|
||||
self.retired.push(image);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user