From a68cb06715548f46b56825ba91c5102bcd31cbb0 Mon Sep 17 00:00:00 2001 From: tannevaled Date: Thu, 27 Aug 2026 15:23:46 +0200 Subject: [PATCH] deps: draw the faxes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit reader v0.5.0 decodes /CCITTFaxDecode. 67 of the 1 633 real forms in the corpus carry a fax and 6 of their pages have nothing else on them, so those pages drew blank; requiring an older reader here would leave them blank for anyone who asked only for this package, since minimum version selection gives them the version this go.mod names. fax_test.go guards it with a fax rather than a version string: one Group 4 row, three white pixels then five black, coded in horizontal mode and built in the test so nobody else's scan enters the repository. Against reader v0.4.2 it fails with "the black part of the fax is not black: (6,4) = 255,255,255,255". Measured through this package over the first page of all 1 633 real forms, 69 pages change: one from blank to drawn (fr-cerfa/cerfa_11818, 0 inked pixels to 28 989), fourteen with more ink, and fifty-one with less — those were showing their own compressed bytes as a stencil, which #20 stopped and this finishes. Co-Authored-By: Claude Opus 5 --- fax_test.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 fax_test.go diff --git a/fax_test.go b/fax_test.go new file mode 100644 index 0000000..7fd483c --- /dev/null +++ b/fax_test.go @@ -0,0 +1,69 @@ +package render + +import ( + "testing" + + "github.com/go-pdfkit/reader" +) + +// TestAFaxIsDrawn guards the dependency, not this package's own code. +// +// 67 of the 1 633 real forms in the corpus carry a CCITT-encoded image and 6 of +// their pages have nothing else on them, so those pages drew blank until +// go-pdfkit/reader v0.5.0 decoded the filter. Requiring an older reader here +// would put the blank pages back for anyone who asked only for this package, +// and nothing in this suite would notice: a package's own tests never see its +// callers' module graph. +// +// The fax is built here rather than committed, so nobody else's scan enters the +// repository. It is one Group 4 row, three white pixels then five black, coded +// in horizontal mode: 001 for the mode, then the white run of three and the +// black run of five from Tables 2 and 3 of ITU-T T.4. +func TestAFaxIsDrawn(t *testing.T) { + bits := "001" + "1000" + "0011" + data := make([]byte, (len(bits)+7)/8) + for i, c := range bits { + if c == '1' { + data[i/8] |= 1 << (7 - uint(i%8)) + } + } + w := reader.NewWriter("1.7") + pagesRef := w.Reserve() + img := w.Add(&reader.Stream{Dict: reader.Dict{ + "Type": reader.Name("XObject"), "Subtype": reader.Name("Image"), + "Width": reader.Integer(8), "Height": reader.Integer(1), + "ColorSpace": reader.Name("DeviceGray"), "BitsPerComponent": reader.Integer(1), + "Filter": reader.Name("CCITTFaxDecode"), + "DecodeParms": reader.Dict{"K": reader.Integer(-1), + "Columns": reader.Integer(8), "Rows": reader.Integer(1)}, + }, Raw: data}) + pageRef := w.Add(reader.Dict{"Type": reader.Name("Page"), "Parent": pagesRef, + "MediaBox": nums(0, 0, 8, 8), + "Resources": reader.Dict{"XObject": reader.Dict{"F": img}}, + "Contents": w.Add(&reader.Stream{Dict: reader.Dict{}, + Raw: []byte("q 8 0 0 8 0 0 cm /F Do Q")})}) + w.Put(pagesRef, reader.Dict{"Type": reader.Name("Pages"), + "Kids": reader.Array{pageRef}, "Count": reader.Integer(1)}) + out, err := w.Finish(reader.Dict{"Root": w.Add(reader.Dict{ + "Type": reader.Name("Catalog"), "Pages": pagesRef})}) + if err != nil { + t.Fatal(err) + } + d, err := reader.Open(out) + if err != nil { + t.Fatal(err) + } + pic, err := Page(d, 1, Options{Scale: 1}) + if err != nil { + t.Fatal(err) + } + // The right five pixels of the row are black and the left three are white. + // A reader that hands back the fax undecoded draws nothing at all, which is + // what the six blank pages were. + if !isWhite(pic, 1, 4) { + t.Errorf("the white part of the fax is not white: %s", pixel(pic, 1, 4)) + } + if !isBlack(pic, 6, 4) { + t.Errorf("the black part of the fax is not black: %s", pixel(pic, 6, 4)) + } +} diff --git a/go.mod b/go.mod index 4f5c08b..97793b5 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/go-gfx/gfx v0.10.0 github.com/go-opentype/fonts v0.9.0 github.com/go-opentype/opentype v0.10.0 - github.com/go-pdfkit/reader v0.4.2 + github.com/go-pdfkit/reader v0.5.0 ) require github.com/go-pdfkit/pdffont v0.3.0 diff --git a/go.sum b/go.sum index 96588d0..39b7e36 100644 --- a/go.sum +++ b/go.sum @@ -6,5 +6,5 @@ github.com/go-opentype/opentype v0.10.0 h1:cZVMZ3RVkcijXmxlmpqyVkjlNc33aSB2ugKVW github.com/go-opentype/opentype v0.10.0/go.mod h1:AOixevJf7XQaH7+WG+OMIOZEbYPXfMqklVk26Y6YTUU= github.com/go-pdfkit/pdffont v0.3.0 h1:G5DKcAmsZJ0e17QhSrcUaL7PKEXKjUx4P/iGMl7bAbI= github.com/go-pdfkit/pdffont v0.3.0/go.mod h1:bfmNLna1l1CljNX/Utg55YzFylovfmI7sJnvgA3bzKI= -github.com/go-pdfkit/reader v0.4.2 h1:0/qPShLzdG/roH4i13dwDTHnS7mEBVTaCBGwCZQhOH0= -github.com/go-pdfkit/reader v0.4.2/go.mod h1:fQFOVfCMUui1AdvD4qhimdyvvNr9KvvJ1S7IuKZjyV8= +github.com/go-pdfkit/reader v0.5.0 h1:DaJ5C6eKXPRG9Cdu+olA/0KLmsQgyHEC1coteQQuBxU= +github.com/go-pdfkit/reader v0.5.0/go.mod h1:fQFOVfCMUui1AdvD4qhimdyvvNr9KvvJ1S7IuKZjyV8=