Summary
TextChunksHelper.calculateTextBoundingBoxH() falls back to /FontBBox when the font descriptor has no /Ascent and no /Descent. When that FontBBox is [0 0 0 0], both ascent and descent become 0 and every text chunk of that font gets a height of exactly zero.
A font bounding box whose four elements are all zero carries no size information — it does not mean the glyphs have no size. Propagating it as a literal 0 produces a chunk that no consumer can distinguish from a glyph that genuinely has no extent.
Affected code
wcag-validation/src/main/java/org/verapdf/gf/model/factory/chunks/TextChunksHelper.java:
double[] fontBoundingBox = font.getBoundingBox(); // [0, 0, 0, 0]
Double descent = font.getDescent(); // null - no /Descent
if (descent == null) {
descent = fontBoundingBox[1]; // -> 0.0
}
Double ascent = font.getAscent(); // null - no /Ascent
if (ascent == null) {
ascent = fontBoundingBox[3]; // -> 0.0
}
Reproducing
repro-issueB-zero-fontbbox.pdf — 1.8 KB, hand-written, readable in a text editor. The generator script and both repro files are here; there are no third-party dependencies.
A single Type 3 font with the conventional /FontMatrix [0.001 0 0 0.001 0 0] and /Widths [500 500 500], so nothing unusual is going on with the font matrix. The only anomaly is:
/FontBBox [ 0 0 0 0 ]
/FontDescriptor << /Type /FontDescriptor /FontName /ReproType3B /Flags 32
/FontBBox [ 0 0 0 0 ] /ItalicAngle 0 /StemV 80 >>
— all-zero in both places, and no /Ascent, no /Descent. The content stream is a plain Tj with no kerning at all, so issue A cannot interfere.
Result, running the file through a veraPDF-based text consumer (opendataloader-pdf 2.x, which bundles veraPDF 1.31.99):
poppler (pdftotext) : ABC
veraPDF-based : (empty file - 0 bytes, no exception, no warning, no log entry)
Impact
The chunk itself is produced; it just has height == 0. Consumers that filter by height then drop it. In opendataloader-pdf, TextProcessor.filterTinyText discards any chunk with height <= 1.0:
if (chunk.getBoundingBox().getHeight() <= 1.0) {
list.set(i, null);
}
The document that led me here is a 156-page PowerPoint export in which all 156 embedded Type 3 fonts have /FontBBox [0 0 0 0] and no /Ascent or /Descent. It extracted 0 characters, and the run was reported as a success — no exception, no warning, nothing in the log. Everything needed to lay the text out is present in the file; it is read and then thrown away. (That document separately also hits #1623; the attached repro file does not, so it isolates this problem.)
I would argue the zero height is wrong regardless of what any particular downstream consumer does with it: a text chunk that reports zero height is stating something about the document that is not true.
Possible fix
Treat "no usable vertical metrics" as unknown rather than as zero, and fall back to a common em split:
if (ascent == 0.0 && descent == 0.0) {
ascent = 0.8 / verticalScalingFactor;
descent = -0.2 / verticalScalingFactor;
}
Dividing by the vertical scaling factor expresses the values in glyph space, so this holds for a Type 3 font with any FontMatrix as well as for ordinary fonts.
The exact constants are a proposal, not a claim. 0.8/−0.2 is a widely used default, but any reasonable pair works; the point is not to propagate a meaningless 0. If you would rather derive the extent from the d1 operands in the Type 3 CharProcs, or from /FontMatrix alone, or expose it as a setting, I am happy to rework the patch — I have no attachment to these numbers.
Fix
Proposed in veraPDF/veraPDF-validation#750
Summary
TextChunksHelper.calculateTextBoundingBoxH()falls back to/FontBBoxwhen the font descriptor has no/Ascentand no/Descent. When thatFontBBoxis[0 0 0 0], both ascent and descent become0and every text chunk of that font gets a height of exactly zero.A font bounding box whose four elements are all zero carries no size information — it does not mean the glyphs have no size. Propagating it as a literal
0produces a chunk that no consumer can distinguish from a glyph that genuinely has no extent.Affected code
wcag-validation/src/main/java/org/verapdf/gf/model/factory/chunks/TextChunksHelper.java:Reproducing
repro-issueB-zero-fontbbox.pdf— 1.8 KB, hand-written, readable in a text editor. The generator script and both repro files are here; there are no third-party dependencies.A single Type 3 font with the conventional
/FontMatrix [0.001 0 0 0.001 0 0]and/Widths [500 500 500], so nothing unusual is going on with the font matrix. The only anomaly is:— all-zero in both places, and no
/Ascent, no/Descent. The content stream is a plainTjwith no kerning at all, so issue A cannot interfere.Result, running the file through a veraPDF-based text consumer (opendataloader-pdf 2.x, which bundles veraPDF 1.31.99):
Impact
The chunk itself is produced; it just has
height == 0. Consumers that filter by height then drop it. In opendataloader-pdf,TextProcessor.filterTinyTextdiscards any chunk withheight <= 1.0:The document that led me here is a 156-page PowerPoint export in which all 156 embedded Type 3 fonts have
/FontBBox [0 0 0 0]and no/Ascentor/Descent. It extracted 0 characters, and the run was reported as a success — no exception, no warning, nothing in the log. Everything needed to lay the text out is present in the file; it is read and then thrown away. (That document separately also hits #1623; the attached repro file does not, so it isolates this problem.)I would argue the zero height is wrong regardless of what any particular downstream consumer does with it: a text chunk that reports zero height is stating something about the document that is not true.
Possible fix
Treat "no usable vertical metrics" as unknown rather than as zero, and fall back to a common em split:
Dividing by the vertical scaling factor expresses the values in glyph space, so this holds for a Type 3 font with any
FontMatrixas well as for ordinary fonts.The exact constants are a proposal, not a claim.
0.8/−0.2is a widely used default, but any reasonable pair works; the point is not to propagate a meaningless0. If you would rather derive the extent from thed1operands in the Type 3CharProcs, or from/FontMatrixalone, or expose it as a setting, I am happy to rework the patch — I have no attachment to these numbers.Fix
Proposed in veraPDF/veraPDF-validation#750