Repository navigation
Conversation
storytold#2684) Printing a page that draws with a Type 3 font, as Chrome writes them, could close the whole app on Windows: the crash is native, inside Windows.Data.Pdf drawing into Direct2D's print control, so nothing in PdfCraft can catch it. Print as image avoided it. On Windows printers the pages that draw with Type 3 fonts are now rendered at the Print as image resolution and sent as pictures; the other pages stay vector. Save as PDF, browsers, macOS and Linux keep the pages as they are. - pdfcraft-print: type3_pages() reads each page's fonts, form XObjects, tiling patterns, soft masks and the appearances of the annotations that print, bounded by a seen-set, a depth limit and a read budget (past them, the page counts as using a Type 3 font). Settings::type3_raster asks for it; impose_with_pictures() draws a page's picture in its place; spool::TYPE3_AS_IMAGE is cfg!(windows). - engine: print_pdf renders the pages found (print_raster::pictures, sharing its render step with rasterize); print_type3_pages(). - ui: the Print dialog sets it for Windows printers, says so when a page being printed uses Type 3 fonts, and logs the pages. New string in all 22 catalogs (machine translations). - automation: doc_print type3_as_image, on by default for Windows printers, lists the pages sent as pictures. Fixes storytold#2684
This was referenced Oct 18, 2026
Open
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Printing to a printer on Windows no longer hands the Windows print component pages that draw with Type 3 fonts. Those pages are rendered by PdfCraft at the Print as image resolution (300 dpi unless changed in Advanced) and sent as pictures; every other page of the job stays vector, as before. Fixes #2684.
Why. @mtlcl410 reproduced the crash on Windows 11 with a virtual printer (FinePrint) and narrowed it to the Type 3 font Chrome wrote for the recipe's text: a glyph followed by code
0x0Fwas enough. Windows.Data.Pdf renders the same page fine on its own, so the crash is in the print path (Windows.Data.Pdf drawing into Direct2D's print control, through craft-print). It is native (0xC0000094or0xC0000005), so nothing in PdfCraft can catch it and the whole app closes. Print as image (#1965) avoided it. This takes direction 2 of that comment: only the pages that need it become pictures, and only on Windows.How.
pdfcraft_print::type3_pages(doc, pages, content)finds the pages whose print draws with a Type 3 font. It reads resources, not content streams: the page's fonts (inherited ones too), and through form XObjects (forms in forms), tiling patterns, soft-mask groups (a shading pattern's too) and the appearances of the annotations that print under the chosen Comments & Forms. It never panics and is bounded: a seen-set per page, a depth limit (64) and a budget of 20,000 reads per page. A page whose resources go past the limit or the budget counts as using a Type 3 font, because the picture is the safe side. Broken entries (a/Resourcesthat is a number, missing objects, a/SMaskthat is/None, cyclic forms) are not Type 3 fonts.print::Settings::type3_raster: Option<Raster>asks for this.Session::print_pdfrenders the pages found the same way Print as image does (print_raster::pictures, sharing its render step withrasterize) andpdfcraft_print::impose_with_picturesdraws each picture in its page's place, over the displayed page and turned back into user space, so imposition, rotation, crops and labels are unchanged. The picture already shows what prints of the page, so its annotations are not drawn again. The other pages go throughpage_formas before.imposeisimpose_with_pictureswith no pictures.spool::TYPE3_AS_IMAGE(cfg!(windows)) says where this applies. The Print dialog setstype3_rasterfor a printer on Windows, not for Save as PDF, not in a browser and not when Print as image is already on. CUPS gets the PDF as it was.log::info!).doc_printtakestype3_as_image(default on when printing to a printer on Windows, off otherwise) and lists the pages it sent as pictures (1-based) astype3_as_imagein its result.How you verified it
cargo fmt --check-D warningson the crates I changed:cargo clippy -p pdfcraft-print -p pdfcraft-engine -p pdfcraft-automation -p pdfcraft-ui-egui --all-targets -- -D warningsis cleancargo test -p pdfcraft-print(28 passed),cargo test -p pdfcraft-engine --lib(276 passed, 1 ignored),cargo test -p pdfcraft-automation --test automation(176 passed),cargo test -p pdfcraft-ui-egui --lib --test print(428 passed, 1 ignored; 14 passed). I ran the test files that cover this change, not every ui-egui test file.cargo xtask layers,cargo xtask assetsandcargo xtask parity: layers OK (37 crates), assets OK after re-pinning the 22 catalog hashes inATTRIBUTION.toml, parity OKWhat I reproduced, and what I didn't. I could not reproduce the crash itself.
/FontMatrix), and a hand-written Skia-style Type 3 font with the issue's sequence, a glyph followed by code0x0Fwhosed1box is all zeros.pdfcraft-cli run(doc_print, printer"Microsoft Print to PDF"named explicitly,type3_as_image: false, so the old vector path). That printer'sPORTPROMPT:port asks where to save the file. The prompt couldn't be answered from a headless run, so those jobs stopped when the job was created, with0x8007003F(the print was cancelled), or waited for an answer. Job creation comes before any page is drawn, so Direct2D's print control never drew a Type 3 page here: the crash is neither reproduced nor ruled out with Microsoft Print to PDF. One run with this change, where the Type 3 page went as a picture, completed (spooled 1 sheet(s)).Tests. I saw each new test fail with the fix reverted, then pass with it:
pdfcraft-print:type3_fonts_are_found_through_forms_patterns_soft_masks_and_printed_annotations(detection off:left: [] right: [1, 2, 3, 4, 5, 6, 8, 9]),a_picture_replaces_its_page_on_the_sheet_and_the_other_pages_stay_vector(impose_with_picturesignoring the pictures:one picture each, left: 0 right: 2),type3_detection_survives_malformed_cyclic_deep_and_huge_resources(detection off:left: []; without the seen-set the cyclic forms page came back as Type 3 through the depth limit:left: [3, 7, 8, 9]; without the depth limit and the budget:left: [9]).pdfcraft-engine:pages_with_type3_fonts_print_as_pictures_and_the_others_stay_vector(detection off:left: [] right: [0, 2]; detection on butprint_pdfnot routing the pages:two pictures, and no Type 3 font left to send, left: (1, 0) right: (0, 2), so the Type 3 font went to the printer),printing_type3_pages_as_pictures_survives_broken_resources(without the seen-set: the cyclic page was reported, so theis_emptyassertion failed).pdfcraft-automation:doc_print_sends_type3_pages_as_images(detection off: notype3_as_imagein the result).pdfcraft-ui-egui(tests/print.rs):type3_pages_go_to_windows_printers_as_images_and_the_dialog_says_so(detection off:left: [] right: [0]; the dialog not settingtype3_raster:left: None right: Some(Raster { dpi: 300.0, grayscale: false })). On Windows this test checks the dialog's note and settings; elsewhere it checks that nothing changes.Never-crash
unwrap/expect/panic!/unreachable!/todo!outside testsunsafeProvenance
cargo xtask assets --writere-pinned their hashes); native speakers are welcome to improve them.Security
--rootconfinement unchanged:doc_printwrites through the sameresolvepathParity and reach
parity/acrobat-features.toml:print.print-as-imagenotes say pages with Type 3 fonts go this way on their own on Windows printers, with the new tests as evidencedoc_printtype3_as_image, with an end-to-end testcrates/print/README.md(it still said print as image was not done) and a ROADMAP progress-log lineAnything a reviewer should look at first
TYPE3_AS_IMAGEiscfg!(windows), so macOS and Linux and Save as PDF keep vector output. Direction 1 (Type 3 text to paths, still vector) or direction 3 (a helper process) could replace this later. The picture pages are larger in the spool, as with Print as image ([Bug Report] [PdfCraft] Print Error #2514).impose.impose_with_picturesis a new public function next toimpose, instead of building a mixed source document. That keeps page numbers, crops (Label) and Comments & Forms exactly as they were for the vector pages.