Matterhorn 31-008 · PDF/UA-1 UA1:7.21.3.3-2

Embedded CMap that inherits from an unlisted CMap

BlockerCheckpoint 31: FontsWCAG 1.3.1 (A)

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

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

Check a PDF free

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 .