import argparse
import subprocess
import sys
def pdffonts_forbid_otto_cid_cff(pdf):
proc = subprocess.run(['pdffonts', pdf], capture_output=True, text=True)
out = proc.stdout
print(out.rstrip())
if proc.returncode != 0:
print(f'FAIL: {pdf}: pdffonts exited {proc.returncode}: {proc.stderr.strip()}')
return False
if 'CID Type 0C (OT)' in out:
print(f'FAIL: {pdf}: poppler still sees a CID-keyed CFF inside an '
f'OpenType wrapper ("CID Type 0C (OT)").')
print(' FreeType does not flag such a face CID-keyed, so poppler and '
'PDFium resolve Identity-H codes as glyph indices while '
'Acrobat resolves them through the charset (#280).')
print(' Embed the bare CFF table (/FontFile3 /Subtype /CIDFontType0C) instead.')
return False
return True
def dark_pixels(pdf, dpi):
proc = subprocess.run(
['pdftoppm', '-gray', '-r', str(dpi), '-f', '1', '-l', '1', '-singlefile', pdf],
capture_output=True,
)
pgm = proc.stdout
if proc.returncode != 0 or not pgm.startswith(b'P5'):
print(f'pdftoppm exited {proc.returncode} for {pdf}: {proc.stderr.decode(errors="replace").strip()}')
return 0
tokens, pos = [], 2
while len(tokens) < 3:
while pgm[pos:pos + 1].isspace():
pos += 1
if pgm[pos:pos + 1] == b'#': pos = pgm.index(b'\n', pos) + 1
continue
start = pos
while not pgm[pos:pos + 1].isspace():
pos += 1
tokens.append(int(pgm[start:pos]))
width, height, maxval = tokens
raster = pgm[pos + 1:pos + 1 + width * height]
threshold = maxval // 2
return sum(1 for b in raster if b < threshold)
def main():
ap = argparse.ArgumentParser()
ap.add_argument('pdf')
ap.add_argument('--min-ink', type=int, required=True,
help='minimum dark-pixel count on page 1 at --dpi')
ap.add_argument('--dpi', type=int, default=100)
ap.add_argument('--forbid-otto-cid-cff', action='store_true',
help='fail if pdffonts reports "CID Type 0C (OT)"')
args = ap.parse_args()
ok = True
if args.forbid_otto_cid_cff:
ok = pdffonts_forbid_otto_cid_cff(args.pdf)
ink = dark_pixels(args.pdf, args.dpi)
if ink < args.min_ink:
print(f'FAIL: {args.pdf}: page 1 renders with {ink} dark pixels '
f'(< {args.min_ink}) at {args.dpi} dpi — poppler is drawing '
f'blanks/notdef where the text should be.')
ok = False
else:
print(f'OK: {args.pdf}: {ink} dark pixels (>= {args.min_ink}) at {args.dpi} dpi')
sys.exit(0 if ok else 1)
if __name__ == '__main__':
main()