feat(plot): Windows printer media and printable areas

The plot dialog asks CUPS printers for their sheets and margins; on Windows
the query was a stub, so every printer showed the paper catalogue with
unverified margins. The driver is now asked the way the plot dialog expects:

- windows_media (compiled and tested everywhere): the three parallel
  DeviceCapabilities tables (ids, sizes in tenths of a millimetre, 64-WCHAR
  names) become one PrinterMedia per distinct size — a rotated or
  borderless twin folds onto its sheet, catalogue sheets keep their name,
  unknown sizes carry the driver's — with the device's margins on every
  entry and the driver's default sheet found by id or by user size.
- print_to_printer (Windows): DeviceCapabilitiesW for the tables, the
  default DEVMODE for the default sheet, one portrait printer DC for the
  unprintable margins (physical offsets and extents, per device — a
  documented approximation). The DEVMODE fetch is shared with the print
  path (with_printer_devmode).
- A direct print now asks the driver for the plot's own sheet (by id, or
  as a user-defined size), so an A3 plot prints on A3 rather than shrunk
  into the driver's default; a driver that refuses the sheet is asked for
  the orientation alone.
- The capability cache remembers printers that could not be asked, so a
  slow failing query runs once per session, not on every dialog open.
- PRINTERS <name> reports a printer's sheets, margins and default sheet.

Tests: names (NUL trim, full slot, lossy), media folding and dropping,
default by id / user size / none, DC margins, paper id lookup.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
PanosandClaude Opus 5 committed 2026-09-18 18:42:03 +03:00
1 parent c36ae08fd0
commit b8472a00b4
27 files changed
+721 -40

No files matched your search

+9
View File
@@ -878,6 +878,15 @@ impl OpenCADStudio {
self.command_line.push_output(&line);
}
}
// PRINTERS <name> — what that printer reports about its sheets
// and printable area (asks the driver; may take a moment for an
// offline network queue).
cmd if cmd.starts_with("PRINTERS ") => {
let name = cmd["PRINTERS ".len()..].trim();
for line in crate::io::print_to_printer::printer_media_report(name) {
self.command_line.push_output(&line);
}
}
"EXPORT" | "EXPORTPDF" => {
return Some(Task::done(Message::PlotExport));
}