Matterhorn 31-008 · PDF/UA-1 UA1:7.21.3.3-2
Embedded CMap that inherits from an unlisted CMap
A UseCMap chain must terminate at a predefined CMap.
The condition, as the protocol states it. “A CMap references another CMap which is not listed in ISO 32000-1:2008, Table 118.”
Matterhorn Protocol 1.1, checkpoint 31, index 31-008, section UA1:7.21.3.3-2. Software can decide this one on its own.
What a screen reader actually does
Character code interpretation fails.
CMaps can be layered
A CMap does not have to define every mapping itself. It can name another CMap as its base and list only what is different:
14 0 obj
<< /Type /CMap
/CMapName /Custom-Additions-H
/CIDSystemInfo << /Registry (Adobe) /Ordering (Japan1) /Supplement 6 >>
/UseCMap /UniJIS-UTF8-H % everything else comes from here
/WMode 0
/Length 612 >>
stream
%!PS-Adobe-3.0 Resource-CMap
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/UniJIS-UTF8-H usecmap % the same reference, in the program
...
3 begincidchar
<EE8080> 20001
<EE8081> 20002
<EE8082> 20003
endcidchar
endcmap
endstream
The base is named twice — once by /UseCMap in the stream dictionary, once by the usecmap operator in the program — and the CMap above adds three private-use codes to it. It is a natural way to write a CMap: a vertical CMap can be written as its horizontal counterpart plus the handful of codes that change; a document’s custom characters are a standard CMap plus a few extras.
PDF/UA-1 allows the layering but restricts the base: a CMap shall not reference any other CMap except those listed in ISO 32000-1 Table 118. The 61 names there — the Identity, GB, CNS, JIS and KSC families — are the ones every conforming viewer is expected to know. UniJIS-UTF8-H, the base in the example, is a real, maintained Adobe CMap that is not on that list.
Why embedding is not enough
The example CMap is embedded, so it passes 31-006. What it embeds is three mappings. The thousands of others it relies on are in a resource the file only names.
On a machine with UniJIS-UTF8-H installed, the layers combine and the text reads normally. On a machine without it, the viewer has the three private-use codes and nothing else: it cannot even tell how many bytes make up each of the other characters, because the codespace came from the base too. A screen-reader user hears the three custom characters, if they have Unicode values, and silence or debris where the body text should be.
That is the failure in its purest form: a file that looks self-contained, passes a check for embedded CMaps, and reads correctly everywhere its author tested it.
Where it comes from
From producers that build a CMap incrementally — standard base plus additions — and embed only the additions, on the assumption that the base will be available, as it was everywhere the author tested. The standard’s line is not “available”, it is Table 118.
How to check it free
qpdf. pdffonts shows Custom in the encoding column for a font with an embedded CMap; that is where to look. qpdf file.pdf --show-object=12 prints the Type 0 font, its /Encoding points to the CMap, and qpdf file.pdf --show-object=14 shows the CMap’s dictionary. A /UseCMap with a name must be one of the 61 in Table 118. A /UseCMap that points to another stream fails as the PDF/UA text is written. Add --filtered-stream-data to read the program and look for usecmap as well, since the program can reference a base without the dictionary saying so.
veraPDF with its PDF/UA-1 profile tests CMap references under clause 7.21.3.3.
Acrobat Pro shows the CMap’s stream dictionary, including any /UseCMap, in Preflight: All tools → Use print production → Preflight, then Options → Browse Internal PDF Structure, and open the font’s Encoding from the page’s Resources. Adobe’s documentation describes it as a viewer that cannot edit the structure or fonts.
How to fix it
Acrobat cannot change a CMap. Re-export from the source, so that the font uses Identity-H with a ToUnicode CMap or the producer embeds a complete CMap — Adobe’s own advice for character-encoding problems is to re-create the PDF.
The low-level alternative is to flatten the CMap: take the base CMap resource (Adobe publishes them in its cmap-resources repository), merge its mappings with the additions into one CMap program, embed that, and remove both the /UseCMap entry and the usecmap line. The result is self-contained and passes. It is a real piece of work with plenty of room for error, and every string on the page depends on getting it right, so render and extract the result and compare both with the original.
Do not “fix” it by pointing /UseCMap at a listed CMap that looks similar. The additions were written as differences from one specific base, and a different base changes what every other code means.
What Taggart does
Taggart reports an embedded CMap whose /UseCMap entry is a name that is not in ISO 32000-1 Table 118. That is the common form of the condition, and the one a test in the repository builds.
It does not cover the rest. It reads only the /UseCMap entry in the stream dictionary, not the usecmap operator inside the CMap program; it does not follow a chain from one CMap to the next; and it accepts a /UseCMap that is an embedded stream, which ISO 32000-1 allows but the PDF/UA text does not. For those, use veraPDF or read the CMap as described above. There is no fix in Taggart.
Until October 2026 the check took every /UseCMap value for an embedded stream and reported nothing at all; the same mistake hid 31-004.
How Taggart handles it
Taggart checks for the common form of this condition automatically and reports it as a blocker. The check does not cover every form of it; what it misses is 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
What does UseCMap do?
It makes one CMap an extension of another. The referencing CMap lists only the mappings that differ, and everything else is taken from the CMap it names. ISO 32000-1 lets the /UseCMap entry be the name of a predefined CMap or a stream containing a CMap; inside the CMap program the same thing is done with the usecmap operator.
My CMap is embedded. Why is that not enough?
Because embedding the outer CMap does not embed the one it inherits from. If that one is not in ISO 32000-1 Table 118, a viewer that does not have it installed gets only the outer CMap's differences — often a handful of codes — and nothing for the rest of the text. Condition 31-006 passes, since the CMap is embedded; this condition is what catches the rest.
Can the referenced CMap be another embedded stream?
ISO 32000-1 allows it. The PDF/UA wording is stricter — a CMap shall not reference any CMap except those listed in Table 118 — so an embedded CMap built on another embedded CMap fails as written. The simplest compliant shape is a single embedded CMap with no UseCMap, or one built directly on a Table 118 name.
Does Taggart report it?
Not today. The check exists but takes every /UseCMap value for an embedded stream, so a name outside Table 118 passes. Check with veraPDF or by reading the CMap's dictionary until that is corrected.
Where this sits in the standards
| Standard | Reference |
|---|---|
| Matterhorn Protocol 1.1 | Checkpoint 31 (Fonts), index 31-008 |
| PDF/UA-1 (ISO 14289-1) | Clause 7.21.3.3-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. |
Related conditions
- 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-001 CIDSystemInfo Registry values are not identicalThe CMap and the descendant CID font must agree on the character collection registry.
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-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.
- 31-030 Characters used in text showing operators reference the .notdef glyphThe content stream paints glyph index 0, which is by definition "no glyph" — typically a hollow box or nothing at all.
Check your own file. Taggart’s validator is free and unlimited — 75 of the 87 Matterhorn conditions software can decide, with the other 12 listed for you to confirm; no watermark, no expiry, and no account needed up to 60 pages.
Checked with Taggart on a generated file that fails this condition on . The Acrobat steps follow Adobe’s documentation and were not walked through by hand. Last updated .