Matterhorn 31-025 · PDF/UA-1 UA1:7.21.6-9
Symbolic TrueType font program with no cmap table
A symbolic TrueType font must contain at least one cmap subtable.
The condition, as the protocol states it. “The embedded font program for a symbolic TrueType font contains no cmap.”
Matterhorn Protocol 1.1, checkpoint 31, index 31-025, section UA1:7.21.6-9. Software can decide this one on its own.
What a screen reader actually does
No character mapping is available at all.
What the cmap does for a symbolic font
A TrueType font program is a set of tables. The cmap table maps character codes to glyph numbers, usually through several subtables for different platforms and encodings. For a symbolic TrueType font in a PDF — one whose font descriptor has the Symbolic flag and which, under PDF/UA, has no /Encoding (31-024) — the cmap is the whole of the route from a byte in the content stream to a glyph. ISO 32000-1 has the viewer look the byte up in the (3,0) Microsoft Symbol subtable, or failing that the (1,0) Macintosh one. There is no encoding, no glyph name and no other step.
PDF/UA-1 clause 7.21.6 requires a symbolic TrueType program to have a cmap. Condition 31-025 is one that has none.
What that looks like, from the test file we built for this page — ttx -l lists the tables, and there is no cmap among them:
$ ttx -l font.ttf
Listing table info for "font.ttf":
tag checksum length offset
---- ---------- -------- --------
OS/2 0x44DF44BC 96 280
glyf 0x63956868 78 392
head 0x59B77F1C 54 156
hhea 0x057A01C4 36 212
hmtx 0x028A0064 8 376
loca 0x001A0034 8 384
maxp 0x00050006 32 248
name 0xB20BA7D3 129 472
post 0x00290025 40 604
What breaks
With no cmap, ISO 32000-1 has run out of instructions: a byte that cannot be mapped any of the specified ways may be mapped however the viewer chooses. Viewers then try whatever they have — the glyph names in the program’s post table, for one. On our test file, whose glyphs carry ordinary names, Poppler and PDFium both drew the right glyphs. We then removed the names from the program and tried again: Poppler drew a .notdef box for every character, and PDFium drew nothing at all. Two viewers, two different failures, and neither of them visible in the file’s dictionaries.
What the user hears
Extraction does not use the cmap. A symbolic TrueType font has to carry a ToUnicode CMap under PDF/UA (31-027), and readers use that. If it has one, the screen reader gets the intended characters while the page shows whatever the viewer improvised; if it has none, the font also fails 31-027 and the reader gets nothing either way.
Where it comes from
A font program subset for use inside a composite (Type 0) font does not need a cmap: the CIDToGIDMap does that job, and some subsetting tools leave the cmap out. Reuse such a program as a simple symbolic TrueType font and it fails this condition. Hand-assembled files and font conversions that drop tables they consider optional produce the same result.
How to check it free
- Find the font’s object number with
pdffonts file.pdfand follow/FontDescriptorto/FontFile2withqpdf --show-object=12 file.pdf. - Write the program out:
qpdf --show-object=19 --filtered-stream-data file.pdf > font.ttf, as documented in the qpdf manual. - List its tables with
ttx -l font.ttffrom fontTools. No line startingcmapis the condition.
veraPDF parses embedded TrueType programs and checks the cmap requirements for symbolic fonts in its PDF/UA-1 profile.
Acrobat Pro can browse an embedded font’s glyphs — All tools → Use print production → Preflight, then Options → Browse Internal Structure of All Document Fonts — which Adobe’s advanced preflight inspections page describes as a view of glyph outlines and coordinates. Adobe does not document a list of the program’s tables there, and the window cannot edit fonts.
How to fix it free
Re-export from the source. A program missing its cmap was damaged somewhere between the font file and the PDF, and the fix is to go back to a stage before that. For character-encoding problems generally, Adobe’s guidance in Create and verify PDF accessibility is to use a different font, preferably OpenType, in the source and re-create the PDF; Adobe also says some of these problems cannot be repaired within Acrobat, and documents no way to edit a font program there.
Rebuilding a cmap in place is possible only if you know what each code was meant to draw, which is the information the missing table held. If the glyphs have meaningful names, or the font has a ToUnicode CMap you trust and a glyph order you can match to it, fontTools can write a (3,0) subtable mapping 0xF000 plus each byte to its glyph. Then check every glyph on the page, because there is nothing to check the result against except your eyes.
What Taggart does, and doesn’t
Taggart reads the PDF’s font dictionaries; it does not parse embedded font programs. It reports this condition only where it can see from the dictionary that the cmap cannot be there — a symbolic TrueType font whose program is not embedded:
/Pictograms is a symbolic TrueType font with no embedded font program, so its cmap tables cannot be verified.
That file also gets 31-009 for the missing program, and usually 31-027.
For an embedded program with no cmap — the case this condition describes — Taggart reports nothing. We ran it on the test file above, which has a ToUnicode CMap and no /Encoding, and it produced no finding for any font condition. A Taggart report without 31-025 says nothing about an embedded program’s tables; use veraPDF or ttx. 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
Is a TrueType font without a cmap even valid?
Not by the font format's own rules: the OpenType specification lists cmap among the tables every font must have. A program without one has usually been cut down for a context that did not use it, and PDF/UA spells out that a symbolic font in a PDF cannot do without it.
Will the page look wrong?
Not necessarily. With no cmap there is no defined route from a byte to a glyph, so each viewer improvises, and some improvise well: Poppler and PDFium both drew the right glyphs from our test file. That is luck rather than conformance, and a different viewer, or a different font, may not share it.
Does Taggart check it?
Only when the font program is not embedded, where it reports that the cmap cannot be verified. It does not open embedded programs, so an embedded font with no cmap gets no finding. Use veraPDF or fontTools.
Where this sits in the standards
| Standard | Reference |
|---|---|
| Matterhorn Protocol 1.1 | Checkpoint 31 (Fonts), index 31-025 |
| PDF/UA-1 (ISO 14289-1) | Clause 7.21.6-9 |
| 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-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-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-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-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.
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-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 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 .