Matterhorn 31-026 · PDF/UA-1 UA1:7.21.6-10
Symbolic TrueType font: several cmaps and no (3,0)
With multiple cmaps present, a (3,0) symbol cmap is required to disambiguate.
The condition, as the protocol states it. “The embedded font program for a symbolic TrueType font contains more than one cmap, but none of the cmap entries is a (3,0) Microsoft Symbol cmap.”
Matterhorn Protocol 1.1, checkpoint 31, index 31-026, section UA1:7.21.6-10. Software can decide this one on its own.
What a screen reader actually does
Character mapping is ambiguous.
What the condition settles
A TrueType program’s cmap table usually holds several subtables, one per platform and encoding. A typical desktop text font carries three: (0,3) Unicode, (1,0) Macintosh Roman and (3,1) Microsoft Unicode. Arial, Times New Roman and Georgia as shipped with macOS all have exactly that set. A symbol font made for Windows carries a (3,0) Microsoft Symbol subtable instead of, or as well as, the others: the copy of Wingdings on the same machine has (1,0) and (3,0).
For a symbolic TrueType font in a PDF — Symbolic flag set, no /Encoding — ISO 32000-1 tells the viewer which subtable to use: (3,0) if present, otherwise (1,0). A (3,1) subtable is not on that list, though it is the one most font software outside PDF reaches for first. When a symbolic font has several subtables and none of them is (3,0), the specification’s answer is (1,0), and a viewer that behaves like general font software might use (3,1). If the two map the same byte to different glyphs, the page depends on the viewer.
PDF/UA-1 clause 7.21.6 removes the choice: a symbolic TrueType program has either exactly one cmap subtable, or, among several, a (3,0). Condition 31-026 is several and no (3,0). Here is the cmap table of the test file we built for this page, printed by fontTools:
<cmap>
<tableVersion version="0"/>
<cmap_format_6 platformID="1" platEncID="0" language="0">
<map code="0x41" name="A"/>
<map code="0x42" name="B"/>
</cmap_format_6>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x41" name="A"/>
<map code="0x42" name="B"/>
</cmap_format_4>
</cmap>
How much it matters
Given the same byte, the two subtables answer different questions. The (1,0) subtable reads it as a Mac Roman code and the (3,1) subtable as a Unicode code point. For plain ASCII the answers coincide and nothing visible happens. Above 127 they do not: byte 0xE9 is È in Mac Roman and é in Unicode, so a symbolic font whose producer meant Unicode, shown in a viewer that follows the specification, can draw the wrong letter.
We built a variant of the test file in which the two subtables deliberately disagree. Poppler and PDFium both followed the specification and drew the glyph from the (1,0) subtable. That is reassuring about those two viewers and says nothing about the rest.
What the user hears
Extraction does not touch the cmap. A symbolic TrueType font must carry a ToUnicode CMap (31-027), and a screen reader reads that. So the listener gets what the producer intended, and the page shows what the viewer chose. Where the two differ, a person reading the screen and a person listening are reading different documents, which matters most to a low-vision user doing both at once.
Where it comes from
Embedding a whole font rather than a subset, and marking it symbolic. A text font embedded whole keeps all its subtables, (0,3), (1,0) and (3,1), and a producer that sets the Symbolic flag on any font with glyphs outside the Adobe standard Latin set — which is what the flag means — makes it symbolic. Neither step is wrong by itself; together they fail this condition.
Subsets are less exposed when the subsetting tool rebuilds the cmap with a single subtable. ReportLab does: it writes one (1,0) subtable into every TrueType subset and marks the font symbolic, which satisfies the “exactly one” branch.
How to check it free
- Find the font with
pdffonts file.pdfand follow its/FontDescriptorto/FontFile2withqpdf --show-object=. - Write the program out:
qpdf --show-object=19 --filtered-stream-data file.pdf > font.ttf(both options are in the qpdf manual). - Run
ttx -t cmap font.ttffrom fontTools and read theplatformIDandplatEncIDof each subtable infont.ttx. More than one, with noplatformID="3" platEncID="0", is the condition. Check the descriptor’s/Flagstoo: this only applies when bit 3 (value 4) is set and bit 6 (value 32) is not.
veraPDF’s PDF/UA-1 profile has a rule for this: a symbolic TrueType program’s cmap must have exactly one subtable or include (3,0).
Acrobat Pro can browse an embedded font’s glyphs through Preflight’s Options → Browse Internal Structure of All Document Fonts, reached from All tools → Use print production → Preflight, as Adobe describes in advanced preflight inspections. Adobe does not document a view of the cmap subtables there, and fonts cannot be edited in it.
How to fix it free
Re-export, embedding a subset. Many applications subset by default, and one that embeds whole fonts usually has a setting for it. If the font is a text font, it should not be symbolic at all, and a re-export that writes it as non-symbolic with a standard encoding, or as a Type 0 font, avoids the condition. Adobe’s general advice for character-encoding problems, in Create and verify PDF accessibility, is to change the font in the source, preferably to OpenType, and re-create the PDF.
Or edit the program with fontTools. Two repairs are possible, and both need you to know which subtable the producer meant:
- Keep one subtable and delete the others. If the page already draws correctly in viewers that follow the specification, they are using (1,0), and keeping only that one changes nothing for them.
- Add a (3,0) subtable built from the one that is right, mapping
0xF000plus each byte to the same glyph. Viewers that follow the specification switch to it.
Then write the program back into its /FontFile2 stream, update /Length1, and compare the page in more than one viewer.
What Taggart does, and doesn’t
No finding, at present. Taggart does not check 31-026: it does not parse embedded font programs, and unlike the neighbouring cmap conditions there is no dictionary-level case it can report instead. We ran it on the test file above, which fails this condition and nothing else, and it produced no finding for any font condition.
So a Taggart report with no 31-026 finding says nothing about this condition. Run veraPDF, or check the cmap with ttx, for any document that embeds symbolic TrueType fonts. 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
What is a (3,0) cmap?
The Microsoft Symbol subtable: platform 3, encoding 0. Symbol fonts put their glyphs at codes in a range such as U+F020 to U+F0FF, and a PDF viewer reaches them by putting the range's high byte, usually F0, in front of the byte from the content stream.
My font has exactly one cmap subtable. Am I fine?
For this condition, yes: a single subtable of any kind satisfies it. ReportLab's TrueType subsets, for example, carry exactly one, a (1,0) Macintosh subtable, and pass.
Does Taggart check it?
No. The condition is in Taggart's rule set, but its checker has no test for it and does not open embedded font programs, so a file that fails it gets no finding. Use veraPDF or fontTools.
Where this sits in the standards
| Standard | Reference |
|---|---|
| Matterhorn Protocol 1.1 | Checkpoint 31 (Fonts), index 31-026 |
| PDF/UA-1 (ISO 14289-1) | Clause 7.21.6-10 |
| 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-025 The embedded font program for a symbolic TrueType font contains no cmapA symbolic TrueType font must contain at least one cmap subtable.
- 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-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-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.
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-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 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 .