Merge PR #2594: M7: write a full font program compressed and find it again on any page

This commit is contained in:
aiongg committed 2026-10-16 14:02:17 +00:00
commit 62f3375297
1 file changed
+39 -7
+39 -7
View File
@@ -195,7 +195,7 @@ pub fn embed_mapping(
// page; source subset programs stay untouched.
let existing = written(doc, fonts).find(|w| w.has_program(doc, bytes)).map(|w| w.program).or_else(|| {
doc.scan_objects().take(8192).find_map(|(r, o)| match o.as_ref() {
Object::Stream(s) if s.dict.get(b"PCFullFont").is_some() && s.raw.as_ref() == bytes => Some(Object::Ref(r)),
Object::Stream(s) if is_program(doc, s, bytes) => Some(Object::Ref(r)),
_ => None,
})
});
@@ -206,7 +206,7 @@ pub fn embed_mapping(
d.set(b"Subtype".to_vec(), Object::name("OpenType"));
}
d.set(b"PCFullFont".to_vec(), Object::Bool(true));
Object::Ref(doc.add(Object::Stream(Stream::from_raw(d, bytes.to_vec()))))
Object::Ref(doc.add(Object::Stream(Stream::flate(d, bytes))))
});
descriptor.set(if cff { b"FontFile3".to_vec() } else { b"FontFile2".to_vec() }, program);
let desc = Object::Ref(doc.add(Object::Dict(descriptor)));
@@ -264,15 +264,20 @@ struct Written {
}
impl Written {
/// Whether its program is `bytes`. The length it was written with is compared before decoding.
/// Whether its program is `bytes`.
fn has_program(&self, doc: &Document, bytes: &[u8]) -> bool {
let Object::Stream(s) = doc.resolve(&self.program).as_ref().clone() else { return false };
s.dict.get(b"PCFullFont").is_some()
&& s.dict.get(b"Length1").and_then(|l| doc.resolve(l).as_int()) == i64::try_from(bytes.len()).ok()
&& s.decoded_within(17 << 20).is_ok_and(|data| data == bytes)
matches!(doc.resolve(&self.program).as_ref(), Object::Stream(s) if is_program(doc, s, bytes))
}
}
/// Whether `s` is a full program written for `bytes`, compressed or not. The length it was
/// written with is compared before decoding.
fn is_program(doc: &Document, s: &Stream, bytes: &[u8]) -> bool {
s.dict.get(b"PCFullFont").is_some()
&& s.dict.get(b"Length1").and_then(|l| doc.resolve(l).as_int()) == i64::try_from(bytes.len()).ok()
&& s.decoded_within(17 << 20).is_ok_and(|data| data == bytes)
}
/// The `PCFull` resources in `fonts`, in order.
fn written<'a>(doc: &'a Document, fonts: &'a Dict) -> impl Iterator<Item = Written> + 'a {
fonts.iter().filter(|(key, _)| key.starts_with(b"PCFull")).take(256).filter_map(move |(key, value)| {
@@ -379,4 +384,31 @@ mod tests {
assert!(!fonts.contains(medium.as_bytes()), "{medium} is new");
assert_eq!(programs(&doc), 2);
}
#[test]
fn the_full_program_is_written_compressed_and_another_page_reuses_it() {
let bytes = include_bytes!("../../../assets/fonts/Inter-Regular.ttf");
let mut doc = Document::new_empty();
let mut first = Dict::new();
embed(&mut doc, &mut first, bytes, "Inter").unwrap();
let program = || {
doc.scan_objects()
.find_map(|(_, o)| match o.as_ref() {
Object::Stream(s) if s.dict.get(b"PCFullFont").is_some() => Some(s.clone()),
_ => None,
})
.unwrap()
};
let stream = program();
assert_eq!(stream.dict.name(b"Filter"), Some(b"FlateDecode".as_slice()));
assert!(stream.raw.len() < bytes.len(), "{} of {} bytes", stream.raw.len(), bytes.len());
assert_eq!(stream.decoded().unwrap(), bytes);
// Another page's resources don't have it, so it is found among the document's objects.
let objects = doc.scan_objects().count();
let mut second = Dict::new();
embed(&mut doc, &mut second, bytes, "Inter").unwrap();
let programs = doc.scan_objects().filter(|(_, o)| matches!(o.as_ref(), Object::Stream(s) if s.dict.get(b"PCFullFont").is_some())).count();
assert_eq!(programs, 1, "one program for both pages");
assert!(doc.scan_objects().count() > objects, "the second page gets its own resource");
}
}