Without a destination size, Windows.Data.Pdf draws each page at its size in DIPs, so whatever it
rasterizes (images, Type 3 glyphs, transparency groups) reaches the sheet at about 96 dpi,
whatever the driver's resolution. Read the resolution from the job's DEVMODE (ignoring a negative
DMRES_* quality level in dmPrintQuality), set it on the Direct2D context, render each page at that
many pixels and scale the result back to the page size by its final pixel size.
This ports upstream ArcticLampyrid/winprint.rs 9819158, a4da89b and 5d49639 (released in 0.3.x)
onto this fork's stream loader and multi-threaded factory. It leaves out a4da89b's scopeguard
around job setup: DxgiPrintContext's Drop already cancels an unfinished job here.
Co-Authored-By: ArcticLampyrid <ArcticLampyrid@outlook.com>
Co-Authored-By: Justin Capella <4584655+b1tninja@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PropertyValue::QName was written with OwnedName's Display, which puts
the namespace URI in front ("{uri}psk:LongEdgeFirst"). That is not a
valid QName, so PTMergeAndValidatePrintTicket rejects any delta ticket
carrying a QName value copied from a driver's PrintCapabilities with
0x80040005 (E_DELTA_PRINTTICKET_FORMAT). The Microsoft IPP Class
Driver lists Letter, A4 and Executive with such a property, so
printing those sizes fails (storytold/pdfcraft#3823).
Write the value as prefix:local, and declare the value's prefix on the
root so a namespace used only in a value stays bound.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Windows.Data.Pdf renders a page on several worker threads that share the
device context passed to RenderPageToDeviceContext. With a single-threaded
factory Direct2D takes no locks, so those threads race inside d2d1.dll:
access violations reading near null (d2d1.dll+0x93fd4, address 0x338) or
executing freed memory (BEX64), mostly on long jobs of scanned pages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xsd:integer collapses whitespace, so a value such as " 16900 " is valid.
Toshiba's "Universal Printer 2" driver emits such values in its
PrintCapabilities, and the reader rejected the whole document with
"Invalid integer", so PrintCapabilities::fetch failed for these printers
(storytold/pdfcraft#2430).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the probe-then-fetch pattern with a grow-on-demand loop: start with a
null buffer and reallocate whenever EnumPrintersW returns ERROR_INSUFFICIENT_BUFFER,
so a printer list change between the two calls no longer causes a failure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>