You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pdfbox.apache.org by "pcorless (via GitHub)" <gi...@apache.org> on 2026/09/01 04:32:31 UTC
[PR] Pdfbox 6251 usecmap cidrange precedence [pdfbox]
pcorless opened a new pull request, #515:
URL: https://github.com/apache/pdfbox/pull/515
# PDFBOX-6251: a CMap's own cid mappings lose to the ones it inherits via usecmap
A CMap that starts with `usecmap` may redefine any code it inherits. It currently can't:
`useCmap` merges the parent's `cidchar`/`cidrange` mappings into the same collections as the
importing CMap's own, and since `usecmap` is read from the header, the parent's land in
`codeToCid`/`codeToCidRanges` first. `toCID` scans the range list first-match, so an inherited
range that covers a code beats the mapping the CMap declared for it.
```java
new CMapParser().parsePredefined("ETenms-B5-H").toCID(0x41, 1); // 13681, should be 34
```
`ETenms-B5-H` exists only to do this override: it uses `ETen-B5-H`, then remaps 0x20-0x7E to the
proportional latin CIDs 1-95 where the parent has the fullwidth forms at 13648+. Its parsed ranges
hold both, inherited first:
```
[0] 32..126 -> 13648 (from ETen-B5-H, always matches first)
[226] 32..126 -> 1 (its own, never reached)
```
**Scope:** 31 of the 92 bundled CMaps declare mappings of their own on top of a `usecmap`, and all
31 are affected. Two are horizontal (`ETenms-B5-H`, `UniJIS-UCS2-HW-H`); the other 29 are `-V`
variants whose own mappings select the vertical forms, so vertical CJK gets horizontal glyphs.
**Symptom:** the wrong glyph, and usually the wrong width with it — `/W` is indexed by CID, so a
wrong CID falls outside the array and the advance drops to `/DW` = 1000. Latin text renders as
`J a v a S e r v e r`.
## Fix
Inherited mappings move to `inheritedCodeToCid`/`inheritedCodeToCidRanges`, consulted only after
the CMap's own: own map -> own ranges -> inherited map -> inherited ranges.
A `usecmap` chain stays nearest-wins, which needs opposite insertion orders: the maps are keyed, so
`putAll` is last-wins (deepest first, nearer on top); the range list is first-match, so the nearer
CMap's ranges go in ahead.
Three things fell out of it:
- **`hasCIDMappings` has to count inherited mappings.** `Identity-V` declares none of its own, so
once the inherited ones move it would report false and `toCID` would return 0 for every code.
- **The maps are copied, not shared.** This kills a latent aliasing bug: the old
`codeToCid.putIfAbsent(length, mappings)` stored the parent's inner map *by reference* when the
importing CMap had no mapping of that length yet, so a later `addCIDMapping` wrote into the
cached predefined parent and corrupted it for everyone after.
- **CID 0 is a mapping, not a miss.** The private range scan returned 0 for both, which with two
range lists would send a CMap's own `cidrange` to CID 0 through to the inherited mappings. It
now returns -1 for "no range covers this"; public `toCID` still returns 0.
## Tests
Seven added to `TestCMapParser`, `mvn -pl fontbox -am test` green (214):
| Test | Covers |
|---|---|
| `testUseCmapOwnMappingsWin` | the case above, both `toCID` overloads |
| `testUseCmapChainKeepsNearestMapping` | a two-level chain stays nearest-wins |
| `testUseCmapOwnMappingsBeatInheritedRanges` | own cidchar and cidrange beat an inherited range |
| `testUseCmapOnlyInheritedMappings` | `Identity-V`, everything inherited |
| `testUseCmapDoesNotShareMappingsWithTheUsedCMap` | the used CMap isn't mutated |
| `testUseCmapOwnRangeBeatsInheritedChar` | own cidrange beats an inherited cidchar |
| `testUseCmapOwnMappingToCidZeroIsNotAFallthrough` | CID 0 is a mapping, not a miss |
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@pdfbox.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@pdfbox.apache.org
For additional commands, e-mail: dev-help@pdfbox.apache.org
Re: [PR] PDFBOX-6251 usecmap cidrange precedence [pdfbox]
Posted by "asf-gitbox-commits (via GitHub)" <gi...@apache.org>.
asf-gitbox-commits closed pull request #515: PDFBOX-6251 usecmap cidrange precedence
URL: https://github.com/apache/pdfbox/pull/515
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@pdfbox.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@pdfbox.apache.org
For additional commands, e-mail: dev-help@pdfbox.apache.org