Matterhorn 31-030 · PDF/UA-1 UA1:7.21.8-1
.notdef glyph in text: the empty box PDF/UA forbids
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
| Standard | Reference |
|---|---|
| Matterhorn Protocol 1.1 | Checkpoint 31 (Fonts), index 31-030 |
| PDF/UA-1 (ISO 14289-1) | Clause 7.21.8-1 |
| WCAG 2.1 | 1.3.1 Info and Relationships — Level A |
| EN 301 549 / Section 508 / ADA Title II | All 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. |
Related conditions
- 31-011 The embedded font program does not contain glyphs for all referenced glyphsThe subset embedded in the file is missing glyphs the content stream asks for — very common when a document is edited after subsetting.
- 10-001 Character code cannot be mapped to UnicodeA glyph is painted whose character code has no Unicode equivalent reachable through the font's ToUnicode CMap, encoding, or glyph names. The text renders correctly but cannot be extracted.
- 31-025 The embedded font program for a symbolic TrueType font contains no cmapA symbolic TrueType font must contain at least one cmap subtable.
- 31-026 A symbolic TrueType font has multiple cmaps but none is a (3,0) Microsoft Symbol cmapWith multiple cmaps present, a (3,0) symbol cmap is required to disambiguate.
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.
- 31-001 CIDSystemInfo Registry values are not identicalThe CMap and the descendant CID font must agree on the character collection registry.
- 31-002 CIDSystemInfo Ordering values are not identicalThe CMap and the descendant CID font must agree on the character collection ordering.
- 31-003 CIDSystemInfo Supplement of the CID font is lower than that of the CMapThe font's character collection supplement must be at least as new as the CMap's, or the CMap may reference CIDs the font does not define.
- 31-004 A Type 2 CID font contains neither a stream nor the name Identity as CIDToGIDMapCIDToGIDMap must be either the name /Identity or a stream mapping CIDs to glyph indices.
- 31-005 A Type 2 CID font does not contain a CIDToGIDMap entryThe entry is absent entirely.
- 31-006 A CMap is neither listed in ISO 32000-1 Table 118 nor embeddedA predefined CMap must be one of the standard names; anything else must be embedded in the file.
- 31-007 The WMode entry in a CMap dictionary is not identical to the WMode value in the CMap streamWriting mode (horizontal or vertical) must be declared consistently in the dictionary and the stream.
- 31-008 A CMap references another CMap which is not listed in ISO 32000-1 Table 118A UseCMap chain must terminate at a predefined CMap.
- 31-009 For a font used by text intended to be rendered the font program is not embeddedPDF/UA-1 requires every font used for visible text to be embedded, so the document renders and extracts identically everywhere. A glyph counts as rendered if the text render mode is not 3.
- 31-010 A font program is embedded that is not legally embeddable for unlimited, universal renderingThe font's embedding permission bits forbid the kind of embedding used. Machines can read the flags but the flags may not reflect the actual licence.
- 31-011 The embedded font program does not contain glyphs for all referenced glyphsThe subset embedded in the file is missing glyphs the content stream asks for — very common when a document is edited after subsetting.
- 31-012 A glyph present in an embedded Type 1 font program is not listed in CharSetCharSet must accurately list the glyphs in the embedded subset.
- 31-013 A glyph listed in CharSet is not present in the Type 1 font programCharSet promises glyphs the font does not contain.
- 31-014 A glyph present in an embedded CID font program is not listed in CIDSetCIDSet must accurately list the CIDs in the embedded subset.
- 31-015 A glyph listed in CIDSet is not present in the CID font programCIDSet promises CIDs the font does not contain.
- 31-016 Glyph widths in the font dictionary and the font program differThe /Widths array must agree with the embedded font program.
- 31-017 A non-symbolic TrueType font has no non-symbolic cmapA font declared non-symbolic must actually carry a (3,1) or (1,0) cmap subtable.
- 31-018 A glyph cannot be looked up by any non-symbolic cmap entrySome rendered glyph is unreachable through the declared cmap tables.
- 31-019 The font dictionary for a non-symbolic TrueType font does not contain an Encoding entryNon-symbolic TrueType fonts must declare an /Encoding.
- 31-020 The Encoding dictionary for a non-symbolic TrueType font does not contain BaseEncodingIf /Encoding is a dictionary it must name a /BaseEncoding.
- 31-021 BaseEncoding is neither MacRomanEncoding nor WinAnsiEncodingOnly MacRomanEncoding and WinAnsiEncoding are permitted for non-symbolic TrueType fonts.
- 31-022 Differences contains glyph names not listed in the Adobe Glyph ListGlyph names in /Differences must be resolvable through the Adobe Glyph List so a processor can derive Unicode.
- 31-023 Differences present but the font has no (3,1) Microsoft Unicode cmapThe Differences array is resolved through the (3,1) cmap; without it the mapping is undefined.
- 31-024 The Encoding entry is present in the font dictionary for a symbolic TrueType fontSymbolic TrueType fonts must not carry an /Encoding; the font's own cmap governs.
- 31-025 The embedded font program for a symbolic TrueType font contains no cmapA symbolic TrueType font must contain at least one cmap subtable.
- 31-026 A symbolic TrueType font has multiple cmaps but none is a (3,0) Microsoft Symbol cmapWith multiple cmaps present, a (3,0) symbol cmap is required to disambiguate.
- 31-027 A font dictionary does not contain the ToUnicode entry and no exemption appliesA ToUnicode CMap is required unless the font uses MacRoman/MacExpert/WinAnsi encoding, or is a Type 1/Type 3 whose glyph names are all in the Adobe Glyph List or the Symbol set, or is a Type 0 whose descendant uses a standard Adobe character collection, or is a non-symbolic TrueType.
- 31-028 Unicode values in the ToUnicode CMap are zeroU+0000 is not a valid mapping target; it usually means the producer could not determine the character and wrote a placeholder.
- 31-029 Unicode values in the ToUnicode CMap are U+FEFF or U+FFFEByte-order marks are not characters and must not appear as mapping targets.
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.
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 .