forked from 1b-agent/opencadstudio-upstream
web: harden plot preview after adversarial review
Three reviewers (security, correctness, performance) converged on:
- Download PDF died on the second click: Closure::once_into_js throws
when invoked twice. The handler is now a plain FnMut kept for the
overlay's lifetime.
- Rasterisation was bounded by page count, not pixels: 12 A0 sheets at
150 DPI peaked near 1.8 GB of RGBA plus ~1.7 GB of decoded images,
and a drawing declaring absurd paper sizes made the rasteriser
saturate its u16 dimensions into a ~17 GB allocation that aborts the
tab. Preview now computes a uniform DPI under a 64-Mpx total budget
(floor 24 DPI) from the page tree before allocating, with a per-page
4096-px edge clamp.
- Overlays stacked when previewing twice and their blob URLs were only
revoked via Close. The overlay is now single-instance (id-tagged);
a replacement or Close revokes every URL through a shared registry.
- emit_image resampled before probing the XObject cache, so a title
block placed on 12 layouts ran 12 Lanczos passes to embed once.
The cache is now probed with the target dimensions first.
- Preview downloads are named {stem}_preview.pdf instead of a constant
plot_preview.pdf, and the page label says 'first N of M' when the
preview is capped while the PDF keeps every page.
This commit is contained in:
1 parent
6306359390
commit
2a05479d69
5 files changed
+218
-25
No files matched your search
+20
-4
@@ -3266,8 +3266,9 @@ impl OpenCADStudio {
|
||||
// PDF and open it in a browser tab for the browser print dialog.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
let stem = self.active_stem("_layouts");
|
||||
let work = move || {
|
||||
crate::io::print_to_printer::preview_pages_pdf(&pages)
|
||||
crate::io::print_to_printer::preview_pages_pdf(&stem, &pages)
|
||||
.map(|_| crate::t!("Opened plot preview.").into_owned())
|
||||
.map_err(|e| crate::tf!("Preview failed: {e}").into_owned())
|
||||
};
|
||||
@@ -3523,9 +3524,10 @@ impl OpenCADStudio {
|
||||
// in a browser tab, where the browser's own print dialog takes over.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
let stem = self.active_stem("");
|
||||
background_task(
|
||||
move || {
|
||||
crate::io::print_to_printer::preview_page_pdf(&page)
|
||||
crate::io::print_to_printer::preview_page_pdf(&stem, &page)
|
||||
.map(|_| crate::t!("Opened plot preview.").into_owned())
|
||||
.map_err(|e| crate::tf!("Preview failed: {e}").into_owned())
|
||||
},
|
||||
@@ -3631,6 +3633,18 @@ impl OpenCADStudio {
|
||||
dir.join(format!("{stem}_{ts}.pdf"))
|
||||
}
|
||||
|
||||
/// File stem of the active drawing for default output names, with an
|
||||
/// optional suffix (e.g. "_layouts" for print-all). Falls back to
|
||||
/// "drawing" when the tab has never been saved.
|
||||
fn active_stem(&self, suffix: &str) -> String {
|
||||
self.tabs[self.active_tab]
|
||||
.current_path
|
||||
.as_deref()
|
||||
.and_then(|path| path.file_stem())
|
||||
.map(|stem| format!("{}{}", stem.to_string_lossy(), suffix))
|
||||
.unwrap_or_else(|| format!("drawing{suffix}"))
|
||||
}
|
||||
|
||||
/// Open the full Plot / Print dialog, seeding its state from the active
|
||||
/// layout's plot settings and the printers found on the system.
|
||||
pub(super) fn on_plot_dialog_open(&mut self) -> Task<Message> {
|
||||
@@ -4454,8 +4468,9 @@ impl OpenCADStudio {
|
||||
// Preview renders to a temp PDF and opens it — never a save dialog,
|
||||
// whatever the output target is.
|
||||
if preview {
|
||||
let stem = self.active_stem("");
|
||||
let work = move || {
|
||||
crate::io::print_to_printer::preview_page_pdf(&page)
|
||||
crate::io::print_to_printer::preview_page_pdf(&stem, &page)
|
||||
.map(|_| crate::t!("Opened plot preview.").into_owned())
|
||||
.map_err(|e| crate::tf!("Preview failed: {e}").into_owned())
|
||||
};
|
||||
@@ -4479,8 +4494,9 @@ impl OpenCADStudio {
|
||||
let page = self.layout_plot_page();
|
||||
|
||||
if preview {
|
||||
let stem = self.active_stem("");
|
||||
let work = move || {
|
||||
crate::io::print_to_printer::preview_page_pdf(&page)
|
||||
crate::io::print_to_printer::preview_page_pdf(&stem, &page)
|
||||
.map(|_| crate::t!("Opened plot preview.").into_owned())
|
||||
.map_err(|e| crate::tf!("Preview failed: {e}").into_owned())
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user