Matterhorn 31-011 · PDF/UA-1 UA1:7.21.4.1-3

Font subset missing a glyph the text still uses

BlockerCheckpoint 31: FontsWCAG 1.3.1 (A)

The subset embedded in the file is missing glyphs the content stream asks for — very common when a document is edited after subsetting.

The condition, as the protocol states it. “For a font used by text the font program is embedded but it does not contain glyphs for all of the glyphs referenced by the text used for rendering.”

Matterhorn Protocol 1.1, checkpoint 31, index 31-011, section UA1:7.21.4.1-3. Software can decide this one on its own.

What a screen reader actually does

The viewer draws a blank or a box where the missing glyph should be. What a screen reader hears comes from the ToUnicode map, not the glyph — often the character the page fails to show, or nothing if the map was not updated either.

What the condition is

Most PDFs embed a subset: only the glyphs the document uses, under a name with a six-letter tag such as ABCDEF+Calibri. That keeps files small, and it works as long as the subset is built from the text it will have to draw.

This condition is a font whose embedded program does not contain a glyph that the text asks for. In the file Taggart’s test suite uses for this page, the font is a CID font with an Identity CIDToGIDMap, so each two-byte code is simply a glyph index:

BT /F1 36 Tf 40 40 Td <0001 0002 0003 0004> Tj ET

/DescendantFonts [ << /Subtype /CIDFontType2
                      /BaseFont /JBATCH+Subset
                      /CIDToGIDMap /Identity
                      /FontDescriptor << /FontFile2 … >> >> ]

The embedded program holds four glyphs, numbered 0 to 3. The text asks for glyph 4. For a simple font the route is longer — code, then encoding, then glyph name, then glyph — but the failure is the same: the last step lands on nothing.

What breaks, and what a screen-reader user hears

The viewer draws the font’s .notdef glyph instead, which in most fonts is an empty rectangle or nothing at all. Poppler renders the test file as three boxes and a blank where the fourth should be.

What a screen reader gets is a separate question, because extraction never consults the glyph. It goes from the code to Unicode through the ToUnicode CMap, and in the test file that map is complete: pdftotext returns ABCD. The screen-reader user hears four letters; the sighted reader sees three and a gap. Neither has any reason to suspect the other is getting something different.

Whether the missing character is also unreadable depends on how the file got this way. When text is edited after the font was subset, the ToUnicode map is often left as it was too, and then the code reaches no character either — that is 10-001, and the reader hears nothing where the gap is.

Where it comes from

Text edited after the font was subset. An editor that changes or adds text and reuses the existing subset, rather than re-embedding the font with the new characters, produces exactly the test file: codes that point past the end of the program.

Merged or optimised files. Two documents carrying different subsets of the same font can end up sharing one, if a tool that merges or slims files treats them as the same font. The subset tag exists to keep them apart, but only a tool that respects it is protected by it.

Form fields. A field whose appearance is drawn in an embedded subset can only show the characters that subset has. A value typed later that needs another glyph runs into this condition.

How to check it free

Look, then copy. A box or a blank where a character should be is the visible half. Copy that line and paste it into a plain text editor: if the paste contains a character the page does not show, the glyph is missing from the program and the mapping is not.

veraPDF tests this under clause 7.21.4.1, one glyph at a time, and leaves out text in rendering mode 3.

Acrobat Pro’s Preflight inventory shows what is actually in each embedded font. Select Use print production → Preflight from the All tools menu, then Options → Create Inventory. Adobe’s page on Preflight reports says the inventory shows which glyphs in a font are embedded, what they look like and which character they are supposed to represent, and suggests it for exactly this — resolving a missing-glyph error. To look at a single font’s glyphs in detail, the advanced inspections page describes Options → Browse Internal Structure of All Document Fonts.

pdffonts from Poppler is less help here than usual: its sub column tells you a font is a subset, not what the subset lacks.

How to fix it free

Re-export from the source document. The subset is then built from the text as it now stands, with the font installed, and every glyph the page uses is in it. This is the only fix that works in general.

Acrobat cannot add glyphs to an embedded subset. Adobe’s font browser is read-only — its page says you can navigate the fonts but cannot edit them — and none of the Preflight fixups Adobe documents replaces a subset with a fuller one.

If the text was edited in a PDF editor, the edit is what broke it, so make the change in the source instead, or redo it in a tool that re-embeds the font rather than reusing the subset.

For form fields, the fix is in whatever built the form: the font a field draws its value in has to carry every glyph a person might type, which in practice means not subsetting it.

What Taggart does

Taggart does not detect this condition. It does not open embedded font programs: it reads the font dictionaries and the content streams, so it knows which codes each font is used with — that is how it finds codes missing from a ToUnicode CMap — but it does not know which glyphs the program contains.

On the test file it reports nothing about the font at all. What it does instead is refuse to vouch for it: 31-011 is on the list of conditions Taggart does not check, and its conformance statement stops short of a PDF/UA claim — and the identifier is not written into the file — until a person confirms them. In the app that is a checkbox, I have checked these conditions by hand, or with another validator. For this one, veraPDF or the Preflight inventory above is how to earn the tick.

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

Why does the text copy correctly when the page shows a gap?

Because copying never looks at the glyph. Extraction goes from the character code to Unicode through the ToUnicode CMap or the encoding; drawing goes from the same code to a glyph in the font program. A file can have the first route intact and the second broken, and then the clipboard holds a letter the page does not show.

Is every box or blank in a PDF a missing glyph?

No. The box is the font's .notdef glyph, and a viewer draws it whenever a lookup fails: the glyph is not in the program (this condition), it is in the program but unreachable through the cmap (31-018), or the font was never embedded and the substitute lacks it (31-009). Acrobat's Preflight inventory shows which glyphs a font actually holds, which tells the three apart.

Can a subset be completed after the fact?

Only by embedding a program that has the glyph, and it has to be the same font at the same version, or the widths in the font dictionary stop matching (31-016). In practice that means re-exporting from the source, where the font is installed and the subset is built from the final text.

Does invisible text count?

No. The requirement is about glyphs referenced for rendering. Text in rendering mode 3, which is how an OCR layer sits invisibly over a scan, draws nothing, so its font does not need the glyphs.

Where this sits in the standards

Standards this condition maps to
StandardReference
Matterhorn Protocol 1.1Checkpoint 31 (Fonts), index 31-011
PDF/UA-1 (ISO 14289-1)Clause 7.21.4.1-3
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 .