From ac61413e2d12358a910fcae26e35098a0c78c24e Mon Sep 17 00:00:00 2001 From: tannevaled Date: Sun, 11 Oct 2026 19:20:55 +0200 Subject: [PATCH] The colour of the text, and the limit it reports rather than hides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit text-color is claimed, through `pdfops textcolour` in go-pdfkit/ops v0.16.0 over go-pdfkit/reader v0.8.0. It needed a new fact in reader first: an Operation now says WHICH BYTES of the stream it is, so a content stream can be edited in place. The alternative was re-serialising every operand, including an inline image's still-encoded bytes, where a formatter that is merely lossless-for-objects can change what the image means. A byte search cannot stand in for it: "BT" appears inside strings and inside an inline image's data, and in the test's fixture a search finds index 1 — in the middle of somebody's text — where the scan reports 20. ⛔ The claim is honest because the tool reports its own limit. Text drawn through a Form XObject is not recoloured, since an XObject is SHARED and recolouring one would change pages the caller did not name — so the verb COUNTS what it could not reach and says so. The failure that would have made this dishonest is a document coming back unchanged while looking converted, and that is precisely the one it refuses to be silent about. Two defects were found building it, neither by a report: - setting a colour before each text object is not enough, because a text object that sets its OWN colour overrides it. A page whose paragraphs said "1 0 0 rg" came out unchanged while the tool reported success. - a page both recoloured and watermarked came back in its original colours: `decorate` rebuilt Contents from the source's parts and threw the rewritten stream away, with nothing failing. Pasted from the tool's own output: covered 82 not covered 32 parity 71.9% (82/114), every claim verified Measured 2026-10-11 against BentoPDF 3a5f146 (v2.8.8, 114 tools), pdfops and ops at v0.16.0, reader v0.8.0, ooxml v0.2.0, opc v0.1.0, odf 3d1deee (= v0.7.0), convert 45fbb5d, render 3bb5dcf, app 1feda5d, rtf 6bc4897, markdown eafebfd, data 128b6c7. Co-Authored-By: Claude Opus 5 --- README.md | 6 +++--- parity/table.go | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 99a9496..756271e 100644 --- a/README.md +++ b/README.md @@ -766,9 +766,9 @@ bentoparity -tools ~/src/bentopdf/docs/tools -pdfops ./pdfops -src ~/src/go-pdfk ``` ``` -covered 81 -not covered 33 -parity 71.1% (81/114), every claim verified +covered 82 +not covered 32 +parity 71.9% (82/114), every claim verified ``` ⛔ **It refuses to report a figure if a single claim cannot be checked.** A diff --git a/parity/table.go b/parity/table.go index a0a8e4b..161cc9f 100644 --- a/parity/table.go +++ b/parity/table.go @@ -33,6 +33,15 @@ var BentoPDF = []Claim{ {Tool: "page-numbers", Claim: "verb:number"}, {Tool: "add-page-labels", Claim: "verb:labels"}, {Tool: "pdf-layers", Claim: "verb:layers"}, + // ⛔ text-color recolours the text in each page's OWN content stream. + // BentoPDF's page says the tool "identifies text regions on each page and + // recolors them"; text drawn through a Form XObject is not reached here, + // because an XObject is SHARED and recolouring one would change pages the + // caller did not name. The verb COUNTS what it could not reach and says + // so, which is why this is a claim rather than a refusal: the one failure + // that would make it dishonest — a document coming back unchanged while + // looking converted — is the one the tool reports out loud. + {Tool: "text-color", Claim: "verb:textcolour"}, {Tool: "bates-numbering", Claim: "verb:bates"}, // --- the file itself ---------------------------------------------------