mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-10 11:12:43 +00:00
The collection's UCS2 CMap is parsed the first time a code needs it
A font whose /ToUnicode maps every code it shows never parses it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pq7HyDBXygTf7jcqdsjcfn
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
fc28e85fb8
commit
a00ff8fa6a
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+31
-8
@@ -6,6 +6,7 @@ use crate::font::{
|
||||
};
|
||||
use crate::{CMapResolverFn, CacheKey, FontResolverFn};
|
||||
use hayro_cmap::{BfString, CMap, CharacterCollection, CidFamily, WritingMode};
|
||||
use std::sync::OnceLock;
|
||||
use hayro_syntax::object;
|
||||
use hayro_syntax::object::Dict;
|
||||
use hayro_syntax::object::Name;
|
||||
@@ -44,7 +45,7 @@ pub(crate) struct Type0Font {
|
||||
to_unicode_is_cid_indexed: bool,
|
||||
/// PdfCraft patch (84): the character collection's UCS2 CMap (by CID), for the codes the
|
||||
/// font's own `/ToUnicode` gives nothing for, whether or not its program is embedded.
|
||||
ucs2: Option<CMap>,
|
||||
ucs2: Option<Ucs2>,
|
||||
/// PdfCraft patch: whether the CIDs belong to an Adobe character collection (Japan1, GB1,
|
||||
/// CNS1, Korea1), whose glyph numbering no substitute other than a CID-keyed CFF font shares.
|
||||
adobe_collection: bool,
|
||||
@@ -140,13 +141,10 @@ impl Type0Font {
|
||||
.as_ref()
|
||||
.and_then(|cc| cc.family.ucs2_cmap())
|
||||
.and_then(|name| (cmap_resolver)(name))
|
||||
.and_then(|data| {
|
||||
let resolver = cmap_resolver.clone();
|
||||
CMap::parse(data, move |n| (resolver)(n))
|
||||
});
|
||||
.map(|data| Ucs2 { data, resolver: cmap_resolver.clone(), map: OnceLock::new() });
|
||||
// If there is no ToUnicode map, try to get the UCS2 CMap.
|
||||
if fallback && to_unicode.is_none() && ucs2.is_some() {
|
||||
to_unicode = ucs2.take();
|
||||
if fallback && to_unicode.is_none() && let Some(ucs2_cmap) = ucs2.take().and_then(|u| u.parse()) {
|
||||
to_unicode = Some(ucs2_cmap);
|
||||
to_unicode_is_cid_indexed = true;
|
||||
}
|
||||
|
||||
@@ -477,7 +475,7 @@ impl Type0Font {
|
||||
}
|
||||
}
|
||||
// PdfCraft patch (84): then the collection's UCS2 CMap, by the code's CID.
|
||||
if let Some(ucs2) = &self.ucs2
|
||||
if let Some(ucs2) = self.ucs2.as_ref().and_then(Ucs2::cmap)
|
||||
&& let Some(s) = self.code_to_cid(code).and_then(|cid| ucs2.lookup_bf_string(cid))
|
||||
{
|
||||
return Some(s);
|
||||
@@ -487,6 +485,31 @@ impl Type0Font {
|
||||
}
|
||||
}
|
||||
|
||||
/// PdfCraft patch (84): a collection's UCS2 CMap, parsed the first time a code needs it: a font
|
||||
/// whose `/ToUnicode` maps every code it shows never parses it.
|
||||
struct Ucs2 {
|
||||
data: &'static [u8],
|
||||
resolver: CMapResolverFn,
|
||||
map: OnceLock<Option<CMap>>,
|
||||
}
|
||||
|
||||
impl Ucs2 {
|
||||
fn parse(&self) -> Option<CMap> {
|
||||
let resolver = self.resolver.clone();
|
||||
CMap::parse(self.data, move |n| (resolver)(n))
|
||||
}
|
||||
|
||||
fn cmap(&self) -> Option<&CMap> {
|
||||
self.map.get_or_init(|| self.parse()).as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Ucs2 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Ucs2").field("bytes", &self.data.len()).finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl CacheKey for Type0Font {
|
||||
fn cache_key(&self) -> u128 {
|
||||
self.cache_key
|
||||
|
||||
Reference in New Issue
Block a user