Repository navigation
M11: Add Printer Marks (crop, bleed, registration, colour bars, page information) - #3038
Open
saad-mughal435 wants to merge 1 commit into
Open
saad-mughal435 wants to merge 1 commit into
saad-mughal435 wants to merge 1 commit into
Conversation
Crop and bleed marks, registration targets, a CMYK colour bar and a page-information line, placed around any page box (the trim box by default) for commercial printing. They are written as printer's mark annotations, which is the subtype ISO 32000-2 12.5.6.20 defines for exactly these graphics, each carrying the spec's /MN name. Annotations rather than baked page content, so that adding marks is not a destructive edit: the page's content stream and resources are untouched, and the marks come off again. The rest of the codebase already handles the subtype (a11y keeps printer marks out of the structure tree, redact keeps them, the renderer's inspector skips them), so this adds the producer those filters were waiting for. Crop, bleed and registration marks and the page information draw in a Separation with the colorant name All (8.6.6.4), so they reach every plate. The colour bar's patches are DeviceCMYK. Boxes resolve as 14.11.2 requires: the crop box defaults to the media box and the bleed, trim and art boxes to the crop box, each clipped to the media box. The colour bar and page information are placed beyond whatever the corner marks and targets actually occupy, measured from those marks rather than re-derived from the style, so they cannot land inside a registration target or inside bleed marks that sit further out than the reference box does. Marks reach outside the box by design, so they need room on the sheet. grow_media enlarges the media box to fit them, on the page itself so a shared /Pages node keeps the size other pages inherit; removal puts the original back, or takes the entry away again when the page had no media box of its own. Without grow_media the pages whose marks fall outside are reported, never dropped. Only marks PdfCraft wrote are removed, so another producer's survive. The code lives in a new crates/prepress, the L4 slot the layer table and the sideways-edge list already reserved for print production. Registry ids print.printer_marks and print.printer_marks.remove, tools doc_printer_marks and doc_remove_printer_marks. Still missing, and said so in the parity notes: a dialog, Acrobat's mark styles beyond the default geometry, marks on a layer, and text that reads upright on a page with /Rotate.
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
Print Production ▸ Add Printer Marks, the first of gap 18's print-production tools: crop and bleed marks, registration targets, a CMYK colour bar and a page-information line, placed around any page box (the trim box by default).
They are written as printer's mark annotations, the subtype ISO 32000-2 §12.5.6.20 defines for exactly these graphics (registration targets, colour bars, cut marks), each carrying the spec's
/MNname. Annotations rather than baked page content, so adding marks is not a destructive edit: the page's content stream and resources are untouched and the marks come off again. The rest of the codebase already handles the subtype correctly (a11ykeeps printer marks out of the structure tree,redactkeeps them, the renderer's inspector skips them), so this adds the producer those filters were already written for.Details worth knowing:
Separationwith the colorant nameAll(§8.6.6.4), so they reach every plate. The colour bar's patches areDeviceCMYK.grow_mediaenlarges the media box to fit them, writing it on the page so a shared/Pagesnode keeps the size other pages inherit; removal puts the original back, or takes the entry away again when the page had no media box of its own. Withoutgrow_media, the pages whose marks fall outside are reported, never dropped./PCPrinterMark) are removed, so another producer's marks survive.The code lives in a new
crates/prepress— the L4 slotxtask/src/layers.rsand itsSIDEWAYSlist already reserved for print production, so this fills a reserved seat rather than inventing a crate. Registry idsprint.printer_marksandprint.printer_marks.remove; toolsdoc_printer_marksanddoc_remove_printer_marks.How you verified it
cargo fmt --check-D warningson the crates I changedcargo xtask layersandcargo xtask assetsTests. 22 unit tests in
crates/prepress/src/tests.rs(box resolution and malformed boxes, per-mark geometry, the no-overlap property across four styles, refusals, media-box growth and restoration, hostile pages) plus an end-to-endprinter_marks_go_on_report_what_did_not_fit_and_come_off_againincrates/automation/tests/automation.rsthat goes through the tools, saves, reopens and removes.Three of them I watched fail before the fix, by reverting it:
offset + registration_reach, the distance to a target's centre; the target extends another reach past that, so the colour bar landed inside it. The default style hid this (24 > 22.25) and the extreme style in the table exposed it. Reverting to the style-derived band failsthe_colour_bar_and_page_information_clear_the_corner_marks_and_targets.removal puts the sheet back(left: (248.25, 374.65),right: (200.0, 300.0)).growing_an_inherited_media_box_leaves_the_other_pages_and_the_file_as_they_were.Never-crash
unwrap/expect/panic!/unreachable!/todo!outside tests (the crate carries thedenyattribute)MAX_MEASUREcaps every style measurement and non-finite values are refused with a message naming which one;saturating_addon the counters and page numbersunsafehostile_pages_and_an_empty_selection_never_panicruns both entry points over huge, reversed, degenerate, non-numeric and rotated pages, a dangling/Annotsreference and a junk/Annotsarray, with and withoutgrow_mediaProvenance
WinAnsiEncodingthroughpdfcraft-fonts, and text it cannot draw is refused rather than written as?, matchingadd_watermark./MNnames, §8.6.6.4 theAllcolorant, §14.11.2 page boxes, §7.7.3.4 inheritance) and from prepress practice, not from reading another implementationcargo xtask assetspassesSecurity
--rootconfinement is untouchedprepressusescos,fonts,model,serdeandthiserror, all already in the treeParity and reach
print.printer-marksset topartial, with notes saying what is still missing: a dialog, Acrobat's mark styles beyond the default geometry, Japanese mark styles, marks on a layer, and text that reads upright on a rotated pagedoc_printer_marksanddoc_remove_printer_marks, which reportmarks,clipped,grownandno_bleedcrates/prepress/README.md;docs/gaps.mdgap 18;docs/architecture.md(the L4 row, andprepresstaken off the not-yet-existing list);ROADMAP.mdprogress log and revision history;docs/target-app-parity.mdL Print rowAnything a reviewer should look at first
Three judgement calls I would like pinned or corrected:
PrinterMarkhandling acrossa11y,redactandrenderas the intended design. If PdfCraft would rather bake marks into the content stream (which is what some prepress workflows expect on output), say so: the geometry and the drawing code are reusable, only the writing changes.prepresswas reserved in the layer table and inSIDEWAYS, so I filled it rather than putting this inprint(which is L4 and so could not reachorganize's page-box code anyway) or inedit. If you would rather it went elsewhere, it is a contained move.docs/target-app-parity.mdL Print said 15 shipped where the checklist measures 17, so it was already stale before this PR. I set the row to the measured numbers and noted in the revision history that the counts were re-read, following the precedent of the 2026-10-11 row. I did not re-judge the readiness score or the hours. Say the word and I will revert that row to text-only changes.One deliberate restraint: marks are placed in unrotated user space, so on a page with
/Rotatethey stay locked to the trim geometry and the page-information text turns with the page rather than reading upright. That is in the README, the parity notes and a test./PCStampRotateand #1398 show the house pattern for counter-rotating, so this is a clean follow-up, but I did not want to guess at the right behaviour for marks (which belong to the sheet, not the reading orientation) without a steer.