forked from 1b-agent/opencadstudio-upstream
web: render plot preview in-page instead of a new tab
A plot preview should show the plotted result on screen instead of
producing a file. The web build now does: the plotted PDF bytes
are rasterised with the hayro pipeline already used for PDF underlays
(150 DPI, first 12 pages) and shown in an in-page overlay with
Download-PDF and Close actions.
The previous strategy opened a new tab via window.open from the async
plot task; browsers withhold popups without a live user gesture, and
embedded hosts ship no PDF viewer plugin at all — so the fallback
download fired and preview behaved like an export. Plain PNG <img>
elements need neither permission.
(cherry picked from commit 8722d84910)
This commit is contained in:
1 parent
c8386c6d3a
commit
4d1f9d5960
3 files changed
+194
-34
No files matched your search
@@ -126,7 +126,13 @@ fn rasterize_uncached(path: &str, page: &str, dpi: f32, transparent: bool) -> Op
|
||||
let bytes = source_bytes(path)?;
|
||||
let pdf = Pdf::new(bytes).ok()?;
|
||||
let page_no = page.trim().parse::<usize>().unwrap_or(1).max(1);
|
||||
let page = pdf.pages().get(page_no - 1)?;
|
||||
raster_pdf_page(&pdf, page_no - 1, dpi, transparent)
|
||||
}
|
||||
|
||||
/// Rasterise one 0-based page index at `dpi`. Screen DPIs clamp the longest
|
||||
/// side; higher (print) DPIs refuse an oversized page instead of rescaling.
|
||||
fn raster_pdf_page(pdf: &Pdf, index: usize, dpi: f32, transparent: bool) -> Option<Arc<PdfPage>> {
|
||||
let page = pdf.pages().get(index)?;
|
||||
let mut scale = dpi / 72.0;
|
||||
let mut effective_dpi = dpi;
|
||||
// Page size in points, straight from the file's MediaBox/CropBox.
|
||||
@@ -179,6 +185,19 @@ fn rasterize_uncached(path: &str, page: &str, dpi: f32, transparent: bool) -> Op
|
||||
}))
|
||||
}
|
||||
|
||||
/// One-shot rasterisation of freshly generated PDF bytes (plot preview).
|
||||
/// Uncached: the bytes differ on every plot, so a cache would only grow.
|
||||
/// Returns at most `max_pages` pages; larger plots preview their first pages.
|
||||
pub fn rasterize_bytes_pages(bytes: Arc<Vec<u8>>, dpi: f32, max_pages: usize) -> Vec<Arc<PdfPage>> {
|
||||
let Ok(pdf) = Pdf::new(bytes) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let count = pdf.pages().len().min(max_pages);
|
||||
(0..count)
|
||||
.filter_map(|index| raster_pdf_page(&pdf, index, dpi, false))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn unpremultiply(pixels: &mut [u8]) {
|
||||
for px in pixels.chunks_exact_mut(4) {
|
||||
let a = px[3] as u32;
|
||||
@@ -441,4 +460,23 @@ mod tests {
|
||||
"a print raster over the pixel budget is refused, not rescaled"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_pages_render_every_page_up_to_the_cap() {
|
||||
let mut document = PdfDocument::new("multi-page");
|
||||
for _ in 0..3 {
|
||||
document
|
||||
.pages
|
||||
.push(OutputPage::new(Mm(50.8), Mm(25.4), Vec::new()));
|
||||
}
|
||||
let bytes = Arc::new(document.save(&PdfSaveOptions::default(), &mut Vec::new()));
|
||||
|
||||
let all = rasterize_bytes_pages(bytes.clone(), 72.0, 10);
|
||||
assert_eq!(all.len(), 3);
|
||||
assert_eq!((all[0].width, all[0].height), (144, 72));
|
||||
assert_eq!(all[0].dpi, 72.0);
|
||||
|
||||
let capped = rasterize_bytes_pages(bytes, 72.0, 2);
|
||||
assert_eq!(capped.len(), 2);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user