Matterhorn 10-001 · PDF/UA-1 UA1:7.2-2

Text you can see, copy as gibberish

Blocker Checkpoint 10: Character Mappings WCAG 1.3.1 (A)

A 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.

The condition, as the protocol states it. “Character code cannot be mapped to Unicode.”

Matterhorn Protocol 1.1, checkpoint 10, index 10-001, section UA1:7.2-2. Software can decide this one on its own.

What a screen reader actually does

The reader announces nothing, or announces replacement characters, for text that is plainly visible on screen. Copy-paste produces garbage.

Two paths through a font, and only one of them is checked by looking

Painting a glyph and reading it back are different operations that use different parts of the font dictionary.

To draw, the viewer takes the character code from the content stream, resolves it through the font’s encoding to a glyph, and paints the outline. Everything needed is present in almost every PDF ever made, because a file where this fails looks visibly broken and somebody notices immediately.

To extract, a reader takes the same character code and needs a Unicode value for it. ISO 32000-1 gives three routes, tried in order:

  1. a /ToUnicode CMap in the font dictionary, mapping codes to Unicode;
  2. a named encoding — WinAnsiEncoding, MacRomanEncoding — whose meaning is defined;
  3. glyph names in the font’s /Differences array that appear in the Adobe Glyph List, from which a Unicode value can be derived.

This condition fires when a code reaches the end of that list with nothing. The glyph is on the page. There is no character behind it.

What the user hears

Nothing, or noise.

A screen reader asking for the text of a paragraph gets back a string of unmapped codes. Depending on the reader and the platform it announces silence, or “unknown character” repeatedly, or a run of replacement characters. In every case the user is told there is something there and not what.

The failure is worse than untagged content, because untagged content is at least consistent — the reader never reaches it and the user never knows it exists. Here the structure is fine, the reading order may be perfect, the element is announced as a paragraph, and its contents are a void. The user knows they are missing something and has no way to get at it.

It also takes out everything downstream of extraction: copy and paste, search, quoting, translation, text-to-speech in any other tool, and the automated checkers that read text to judge it.

Where it comes from

Aggressively subset fonts with no ToUnicode. A generator embeds only the glyphs used and names them g23, g87, uni0000. There is no encoding and no recognisable glyph name, so routes two and three are dead, and it did not write route one.

Symbolic fonts used for text. Icon fonts, ornament fonts, and — the common serious case — a font that draws Hebrew or Arabic through a custom encoding rather than a standard one. The codes mean something to that font and nothing to anyone else.

Ligatures and composed forms. A single glyph that draws “ffi” or a Hebrew letter with its vowel points needs a ToUnicode entry that maps one code to several Unicode values. Generators that assume one-to-one drop these.

LaTeX with older font setups. Type 1 fonts with custom encodings were standard for years. \usepackage[T1]{fontenc} with modern engines or \usepackage{cmap} fixes it at the source.

Converted or repaired files. Anything that has been through a page-extraction or repair tool that rebuilt the fonts.

How to check it free

Copy and paste. Select a paragraph, copy, paste into a plain text editor — not Word, which will try to be helpful. Squares, question marks, mojibake or nothing means the mapping is broken. This is faster than any tool and it is the test that matters, because it is exactly what a reader does.

veraPDF reports it against clause 7.2 and names the font and the code.

Acrobat Pro’s Accessibility Check does not test for it. Its Reliable character encoding check is related and reports far less.

On the command line, pdftotext from poppler writes what a reader would get:

pdftotext -layout document.pdf - | head -40

If that output is empty or full of replacement characters while the page is plainly full of text, this is why.

How to fix it free, in Acrobat Pro

There is no Tags-panel route: this is below the structure tree, in the font dictionaries.

Preflight can sometimes rebuild it. Print Production → Preflight, search the fixups for embed and for Unicode. Acrobat can synthesise a ToUnicode CMap where the glyph names are standard. Where they are g17, it cannot, and it will tell you so.

Otherwise, fix it upstream and re-export, which is the honest answer more often than not:

  • Word and InDesign produce correct mappings with any normally-installed font. A file that fails usually used a font that was itself damaged or was converted after export.
  • LaTeX: \usepackage[T1]{fontenc} and \usepackage{cmap}, or move to LuaLaTeX or XeLaTeX, which embed OpenType fonts with proper mappings.
  • Ghostscript and headless converters are a frequent source; check their font-embedding flags before blaming the document.

Where Taggart differs

tounicode-repair is not a safe fix and never runs from a batch, because reconstructing a mapping means asserting what a glyph means and a wrong assertion is invisible: the text extracts cleanly and says the wrong thing, which is worse than extracting nothing.

It also refuses to be talked out of the finding by a name that merely looks plausible. The standard excuses a Type 1 font whose glyph names all resolve through the Adobe Glyph List, and the obvious way to approximate that is to test the shape of the name — which lets g17 through, because it is a letter followed by digits. g17 is exactly the name a subsetting tool invents when it has no real one, so the approximation excused the single commonest instance of the condition it was meant to catch. Taggart excludes those prefixes by name.

So it reports what it can reconstruct and what it cannot, separately, per font:

Font ABCDEF+Assistant (subset, 42 codes): 39 codes recoverable from Adobe Glyph List names, 3 with no route to Unicode (g17, g88, g104).

The recoverable ones it can write on request, with the derivation shown. The three it cannot are reported as exactly that — not silently left out, and not filled with a guess. A document with three unmappable codes out of forty-two is a document whose text is 93% extractable, and knowing which 7% is missing is the difference between a fixable file and an unusable one.

How Taggart handles it

Taggart detects this condition automatically. It is reported as a blocker, with the page, the structure path and the object id of every occurrence.

The fix is Repair ToUnicode CMaps. It changes what the document means, so Taggart proposes it and waits for your approval rather than applying it unattended.

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 page look fine?

Because drawing and reading are separate paths through a font. To paint a glyph the viewer needs the code, the encoding and the glyph outline, and those are all present. To read it back it needs a mapping from the code to a Unicode value, and that is a different table entirely. A file can have one and not the other, and nothing about the rendering hints at it.

How do I test it in five seconds?

Select a paragraph in any PDF viewer, copy it, and paste into a plain text editor. If what comes back is squares, question marks, mojibake or nothing, the mapping is broken. It is the fastest accessibility test there is and it needs no tools.

Is this the same as a missing ToUnicode CMap?

Related but not the same. A missing ToUnicode CMap is condition 31-027 and is about the font dictionary; this one is about a specific character code that ends up with no Unicode value by any route — no ToUnicode entry, no usable encoding, no recognised glyph name. A font can have a ToUnicode CMap that simply does not cover every code it uses.

Can it be fixed without re-exporting?

Sometimes. Where the glyph names are standard, or the font's encoding is one of the named ones, the mapping can be reconstructed. Where the font is subset with names like g17 and g102 and no encoding worth the word, there is nothing left to reconstruct from and the answer is to re-export from the source with the font embedded properly.

Where this sits in the standards

Standards this condition maps to
StandardReference
Matterhorn Protocol 1.1 Checkpoint 10 (Character Mappings), index 10-001
PDF/UA-1 (ISO 14289-1) Clause 7.2-2
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.

Other conditions in checkpoint 10

Checkpoint 10 covers character mappings. 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’s validator is free and unlimited — every machine-checkable Matterhorn condition, no page cap, no watermark, no account needed.

Check a PDF free

Verified against a real document on . Last updated .