Matterhorn 31-007 · PDF/UA-1 UA1:7.21.3.3-1

CMap WMode differs between dictionary and CMap program

BlockerCheckpoint 31: FontsWCAG 1.3.1 (A)

Writing mode (horizontal or vertical) must be declared consistently in the dictionary and the stream.

The condition, as the protocol states it. “The WMode entry in a CMap dictionary is not identical to the WMode value in the CMap stream.”

Matterhorn Protocol 1.1, checkpoint 31, index 31-007, section UA1:7.21.3.3-1. Software can decide this one on its own.

What a screen reader actually does

Text direction may be misinterpreted.

One setting, written twice

An embedded CMap is a stream. The stream’s data is a CMap program in the PostScript-derived syntax Adobe defined for CMap resources; the stream’s dictionary is ordinary PDF. Both can state the writing mode:

14 0 obj
<< /Type /CMap
   /CMapName /Custom-V
   /CIDSystemInfo << /Registry (Adobe) /Ordering (Japan1) /Supplement 6 >>
   /WMode 1                           % the dictionary says vertical
   /Length 1934 >>
stream
%!PS-Adobe-3.0 Resource-CMap
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CMapName /Custom-V def
/WMode 0 def                          % the program says horizontal
...
endcmap
endstream

0 is horizontal, 1 is vertical. In ISO 32000-1 the dictionary entry is optional and defaults to 0, as does the program’s. PDF/UA-1 requires that, where the CMap is embedded, the integer in the dictionary be identical to the value in the stream. The example above fails.

What writing mode changes

Writing mode decides which way the text advances. In horizontal mode each glyph moves the pen to the right by its width from the font’s /W array. In vertical mode it moves the pen down, using the separate vertical metrics in /W2 and /DW2, and glyphs are positioned on a vertical origin. A vertical CMap may also map a handful of codes — brackets, the long-vowel mark, some punctuation — to the vertical forms of those glyphs.

So a viewer that believes the dictionary sets the run above as a column; one that believes the program sets it as a row. The characters are the same and in the same order. Their positions are not: a column of text drawn as a row runs off the edge of its box or over its neighbours, and a row drawn as a column becomes a narrow stack.

What the reader gets

The words do not change. WMode does not alter which CID a code maps to, so the characters a screen reader receives, and their order through the structure tree, are the same in either mode. This is why the condition’s effect on speech is easy to overstate.

Its effect on everything else is not. A low-vision user magnifying the page sees whichever layout their viewer chose, which may overprint. Text selection, copy and paste, find, and any reflow view rebuild lines from glyph positions, and they rebuild different lines from different positions — so the same document can copy as one string in one viewer and in a different order in another. And untagged or partly tagged content, which a screen reader reads by position, inherits that disagreement directly.

Where it comes from

From producers that write the stream dictionary and the CMap program separately. A writer that fills in the dictionary from a template — /WMode 0 every time — and copies a vertical CMap program in from a resource file will produce this for every vertical font it embeds. So will one that derives a -V CMap from a -H one and updates the dictionary but not the program, or the reverse.

How to check it free

qpdf. Find the Type 0 font’s object number with pdffonts (an embedded CMap shows Custom in its encoding column), print the font with qpdf file.pdf --show-object=12, and follow /Encoding to the CMap. qpdf file.pdf --show-object=14 shows the dictionary’s /WMode; adding --filtered-stream-data prints the program, where you are looking for /WMode n def.

veraPDF with its PDF/UA-1 profile tests it under clause 7.21.3.3.

Acrobat Pro shows the stream dictionary 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. Per Adobe’s documentation this window is for inspection; it does not edit.

How to fix it

Acrobat has no command that edits a CMap. Re-exporting from the source is the clean fix; Adobe’s guidance on character-encoding problems also points to re-creating the PDF.

If you edit the file instead, first decide which value is true. The source document is the authority: text set vertically in the original wants 1. The CMap’s own name is a strong hint — a -V suffix means vertical by convention — and so is the font: a CIDFont with explicit /W2 vertical metrics was prepared for vertical setting. Then make the other side agree. The dictionary is the easier side to change: qpdf --json-output with --json-object writes the CMap object out, you change "/WMode", and --update-from-json applies it. Render the result against the original before keeping it.

What Taggart does

For each Type 0 font that text is set in and whose CMap is embedded, Taggart reads /WMode from the stream dictionary and the first /WMode value in the CMap program, and reports a blocker when both are present and differ:

/ABCDEF+JPMincho-Regular: the CMap dictionary declares /WMode 1 but the CMap stream declares 0.

The finding carries both values, the font’s object number and the first page it appears on.

It only compares when both sides state a value. A dictionary with no /WMode over a program that says 1 is not reported, even though the dictionary’s default is 0 and a strict reading would call that a difference; nor is the reverse. If you are checking a vertical document by hand, look for that case too.

There is no fix in Taggart. The finding stays a blocker until the file is re-made or edited, and Taggart will not write the PDF/UA identifier while it stands.

How Taggart handles it

Taggart checks for this condition automatically and reports it as a blocker, with where in the file it found it.

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 WMode?

The writing mode a CMap selects for the font it is used with: 0 for horizontal, 1 for vertical. The -H and -V pairs of predefined CMaps — UniJIS-UTF16-H and UniJIS-UTF16-V — differ chiefly in this, plus a few codes that map to vertical glyph forms in the -V version.

Why is it written in two places?

Because an embedded CMap is a PDF stream wrapped around a PostScript-style CMap program. The program sets /WMode itself, and ISO 32000-1 also gives the stream dictionary a /WMode entry. PDF/UA requires the two to be identical so that no viewer has to choose.

Does a screen reader read vertical text differently?

No. A screen reader reads characters in the order the content and the structure tree give them, and WMode does not change which characters a code maps to. What WMode changes is where each glyph is placed — down the page or across it — and that matters to people reading the page by eye and to any tool that rebuilds text from glyph positions.

Does this apply to predefined CMaps like UniJIS-UTF16-V?

No. A predefined CMap is named, not embedded, so there is no stream dictionary to disagree with it. The condition only exists for embedded CMaps.

Where this sits in the standards

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