Summary
Graphical bounding boxes (policy.graphical.boundingBoxes) currently apply to a single, exact 1-based page. This proposes two open-ended page values so one box can span pages without knowing the document length up front:
0 — the box covers every page.
-N — the box covers page N through the last page (so -2 is "all but the first page", e.g. a logo or footer on every page except the cover).
Any positive value keeps meaning the exact page, as today.
Motivation
Fixed regions are ideal for logos, watermarks, stamps, and letterhead that sit in the same spot on every page. Without an "all pages" (or "from page N onward") option, a caller has to know the page count and emit one box per page. These sentinels let a single box cover the whole document (or a tail of it) with no page-count knowledge.
Reference implementation (phileas-dotnet)
This is already implemented in phileas-dotnet so the two engines can match. The change is entirely in how PdfRedactor decides whether a box applies to a page:
internal static bool BoxAppliesToPage(BoundingBox box, int pageNumber) => box.Page switch
{
0 => true, // all pages
< 0 => pageNumber >= -box.Page, // from page N to the last page
_ => box.Page == pageNumber // an exact page
};
This is used in place of the old boundingBoxes.Where(b => b.Page == pageNumber) filter when painting each page. The BoundingBox.page documentation was updated to describe the 0 / -N convention.
Proposed Java change
- In the PDF redactor, replace the exact
box.getPage() == pageNumber match with the equivalent predicate (0 → all pages, negative → from |page| to the last page, otherwise the exact page).
- Document the
page field convention on the bounding-box model.
- No schema/type change is required —
page is already an integer.
Acceptance criteria
- An exact page value still matches only that page.
page = 0 covers every page of a multi-page PDF.
page = -N covers pages N through the last page (and -2 excludes the first page).
- Unit tests for the page-matching predicate, plus an end-to-end test confirming an all-pages box redacts every page.
Notes
This keeps phileas (Java) and phileas-dotnet in sync. phileas-dotnet is a port of this engine and currently diverges on this behavior.
Summary
Graphical bounding boxes (
policy.graphical.boundingBoxes) currently apply to a single, exact 1-based page. This proposes two open-endedpagevalues so one box can span pages without knowing the document length up front:0— the box covers every page.-N— the box covers page N through the last page (so-2is "all but the first page", e.g. a logo or footer on every page except the cover).Any positive value keeps meaning the exact page, as today.
Motivation
Fixed regions are ideal for logos, watermarks, stamps, and letterhead that sit in the same spot on every page. Without an "all pages" (or "from page N onward") option, a caller has to know the page count and emit one box per page. These sentinels let a single box cover the whole document (or a tail of it) with no page-count knowledge.
Reference implementation (phileas-dotnet)
This is already implemented in phileas-dotnet so the two engines can match. The change is entirely in how
PdfRedactordecides whether a box applies to a page:This is used in place of the old
boundingBoxes.Where(b => b.Page == pageNumber)filter when painting each page. TheBoundingBox.pagedocumentation was updated to describe the0/-Nconvention.Proposed Java change
box.getPage() == pageNumbermatch with the equivalent predicate (0→ all pages, negative → from|page|to the last page, otherwise the exact page).pagefield convention on the bounding-box model.pageis already an integer.Acceptance criteria
page = 0covers every page of a multi-page PDF.page = -Ncovers pages N through the last page (and-2excludes the first page).Notes
This keeps phileas (Java) and phileas-dotnet in sync. phileas-dotnet is a port of this engine and currently diverges on this behavior.