Matterhorn 31-030 · PDF/UA-1 UA1:7.21.8-1

.notdef glyph in text: the empty box PDF/UA forbids

BlockerCheckpoint 31: FontsWCAG 1.3.1 (A)

The content stream paints glyph index 0, which is by definition "no glyph" — typically a hollow box or nothing at all.

The condition, as the protocol states it. “One or more characters used in text showing operators reference the .notdef glyph.”

Matterhorn Protocol 1.1, checkpoint 31, index 31-030, section UA1:7.21.8-1. Software can decide this one on its own.

What a screen reader actually does

The character is missing from the visual output and from extraction.

What .notdef is

Every font has a glyph for “I have no glyph for that”. In TrueType and OpenType it is glyph 0, and in Type 1 and CFF fonts it is the glyph named .notdef. Viewers draw it when a code points at a glyph the font does not have, and most designers draw it as a hollow rectangle — the “tofu” box.

PDF/UA-1 clause 7.21.8 forbids any text-showing operator in any content stream from referencing it, whatever the text rendering mode. Condition 31-030 is text that does.

The clearest case is a composite font with an identity mapping, where the code in the content stream is the glyph number:

/Font  << /Subtype /Type0  /Encoding /Identity-H  ... >>
/DescendantFonts [ << /Subtype /CIDFontType2  /CIDToGIDMap /Identity ... >> ]
...
BT /F1 24 Tf 40 90 Td <0001 0000> Tj ET

Code <0001> is glyph 1. Code <0000> is glyph 0, .notdef. Simple fonts get there by other routes: a code that the font’s cmap does not cover, or a /Differences entry naming /.notdef or a glyph the program does not contain.

What the reader sees, and what the listener hears

This is the condition where the two diverge most. Whether a screen reader says anything depends on a separate table, the ToUnicode CMap, which knows nothing about glyphs.

The code has a Unicode mapping. A producer that could not find a glyph for a character can write glyph 0 and still record, correctly, which character was meant. Our test file does exactly that: its map says <0000> is U+2192, a right arrow. Poppler and PDFium both drew A followed by the font’s .notdef box; pdftotext extracted A→. The listener hears the arrow. The person reading the screen sees a box, and a low-vision user following both sees one thing and hears another. If the two ever discuss the document, they are discussing different texts.

The code has no mapping. Then the character is gone from both: a box on the page and nothing in the text. The ToUnicode CMap leaves it out, which is a separate failure, 10-001.

Where it comes from

A character the font does not have. An arrow, a check mark, a mathematical sign, a letter from another script, set in a font with no glyph for it. Many applications substitute a fallback font on screen; a producer that does not repeat the substitution when it writes the PDF writes glyph 0 instead.

Subsetting mistakes. A subset that leaves out a glyph the text uses makes the code point at nothing, which is also 31-011.

Broken cmaps. A simple TrueType font whose cmap does not cover a code the text uses lands on glyph 0. Programs with no cmap, or the wrong one, are 31-025 and 31-026.

Invisible text. OCR layers count: the requirement applies to text in rendering mode 3 as much as to visible text. Tesseract is careful here. Its GlyphLessFont sends all 65,536 character codes to glyph 1 rather than 0, which we confirmed on a file from Tesseract 5.5.2.

How to check it free

Look. Hollow rectangles where characters should be, at any zoom. It misses blank .notdef glyphs and invisible text, and it is easy to read past a box in a long document.

Compare the page with its text. Copy a passage and paste it beside the page. A character in the pasted text that has no counterpart on the page — the arrow from our test file — is a code with a mapping and no glyph.

veraPDF’s PDF/UA-1 profile tests every glyph the document shows and fails any whose name is .notdef. It is the free tool that answers this directly.

Acrobat Pro can show an embedded font’s glyph outlines, which helps you recognise what a missing glyph looks like in that font: All tools → Use print production → Preflight, then Options → Browse Internal Structure of All Document Fonts, as Adobe describes in advanced preflight inspections. Adobe documents it as a way to inspect glyphs; it does not say it flags .notdef.

How to fix it free

In the source. Find each box, choose a font that has the character, and re-create the PDF; or, if the character was never meant to be there, delete it. Adobe’s guidance for the Accessibility Checker’s Character encoding rule, in Create and verify PDF accessibility, points the same way — use a different font, preferably OpenType, and re-create the PDF — and notes that some character-encoding problems are not repairable within Acrobat. Adobe documents no way to add a glyph to an embedded font in Acrobat; its font browser cannot edit fonts.

Not in the PDF. There is no safe in-place repair. Pointing the code at a different glyph changes what is drawn, and the glyph you want is, by definition, not in the font.

What Taggart does, and doesn’t

No finding, at present. Taggart does not check 31-030: it does not resolve codes to glyphs inside embedded font programs. We ran it on the test file above, which shows .notdef and maps it to an arrow, and it produced no finding for any font condition.

The only trace in a Taggart report is indirect. If the code that reaches .notdef also has no ToUnicode entry, in a font that needs one, Taggart reports 10-001 for that code; on our test file with the arrow mapping removed it said:

1 character code(s) set in /ABCDEF+TaggartProbe are missing from its ToUnicode CMap, so that text cannot be mapped to Unicode.

with 0x0 among the missing codes. That tells you a character is unreadable, not that it draws as a box. A Taggart report without 31-030 says nothing about .notdef; run veraPDF for that. There is no repair.

It is one of the conditions Taggart does not check, and those hold the conformance claim: the PDF/UA identifier is not written until a person confirms the list — the checkbox I have checked these conditions by hand, or with another validator in the app. Run the check above before ticking it; the tick covers the whole list.

How Taggart handles it

Software could decide this one, and Taggart does not check it yet. A clean report from Taggart says nothing about it either way. It is on the list of conditions Taggart asks you to confirm before it writes the PDF/UA claim into the file; check it by hand or with another validator, as described above.

Whatever Taggart changes, the page still looks identical. Fixes edit the PDF object model, not the content streams, and every remediation is re-rendered and compared against the original at structural similarity ≥ 0.999 before you get the file back. A tool that quietly reflows your document is worse than no tool.

Frequently asked questions

Is .notdef always a visible box?

No. It is whatever the font's designer drew at glyph 0: usually a hollow rectangle, sometimes a box with a question mark or a cross, sometimes nothing at all. A blank .notdef is the worst case, because the missing character leaves no trace on the page.

Does invisible OCR text count?

Yes. The requirement applies whatever the text rendering mode, so an invisible text layer that points at .notdef fails it although nothing is drawn. Tesseract's text-only font maps every character to glyph 1 rather than 0, which keeps its OCR layers clear of it.

Does Taggart check it?

No. The condition is in Taggart's rule set, but its checker has no test for it, so a file that fails it gets no finding. When the code that reaches .notdef also has no Unicode mapping, Taggart reports 10-001 for that code, which is the only trace you will see.

Where this sits in the standards

Standards this condition maps to
StandardReference
Matterhorn Protocol 1.1Checkpoint 31 (Fonts), index 31-030
PDF/UA-1 (ISO 14289-1)Clause 7.21.8-1
WCAG 2.11.3.1 Info and Relationships — Level A
EN 301 549 / Section 508 / ADA Title IIAll three point at WCAG 2.1 Level AA for non-web documents, so a Level A or AA criterion here is in scope for each of them.

Other conditions in checkpoint 31

Checkpoint 31 covers fonts. These are its other failure conditions; the ones without a link are in the rule set but do not have a written page yet.

Check your own file. Taggart does not check this condition yet, and lists it for you to confirm. Its validator is free and checks 75 of the 87 Matterhorn conditions software can decide — no watermark, no expiry, and no account needed up to 60 pages.

Check a PDF free

Taggart does not check this condition yet. A generated file that fails it is in the repository, with a test that fails the day Taggart starts catching it. Written on . The Acrobat steps follow Adobe’s documentation and were not walked through by hand. Last updated .