mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-07 12:12:47 +00:00
fix(edit): editor font enumeration reads a face name without building font metrics
This commit is contained in:
@@ -2,7 +2,7 @@ use super::blocks::{BlockStyle, TextBlock};
|
||||
use super::fallback::MAX_TYPE3_GLYPHS;
|
||||
use super::lines::{page_dict, text_lines};
|
||||
use super::rewrite::rewrite_block_from;
|
||||
use super::{DecodeBudget, Document, EditError, Metrics, Object, TextLine, TextSession};
|
||||
use super::{DecodeBudget, Document, EditError, Object, TextLine, TextSession};
|
||||
|
||||
/// An embedded sfnt source face, read only for the inline editor. Bytes stay in memory and
|
||||
/// are never installed, copied into assets, or used as a font for another document.
|
||||
@@ -30,7 +30,7 @@ pub fn text_editor_fonts(doc: &Document, page: usize) -> Result<Vec<TextEditorFo
|
||||
budget -= bytes.len();
|
||||
result.push(TextEditorFont {
|
||||
resource: String::from_utf8_lossy(name).into_owned(),
|
||||
face: Metrics::from_dict(doc, &font).base_font.rsplit('+').next().unwrap_or_default().to_owned(),
|
||||
face: pdfcraft_fonts::pdf::base_font_name(doc, &font).rsplit('+').next().unwrap_or_default().to_owned(),
|
||||
bytes,
|
||||
});
|
||||
}
|
||||
|
||||
+15
-10
@@ -559,6 +559,20 @@ fn number(t: &Tok) -> Option<u32> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The font's `/BaseFont` (a Type 3 font's descriptor `/FontName` when it has none), read without
|
||||
/// building its metrics, so it decodes no CMap.
|
||||
pub fn base_font_name(doc: &Document, font: &Dict) -> String {
|
||||
font.name(b"BaseFont")
|
||||
.map(|name| String::from_utf8_lossy(name).into_owned())
|
||||
.or_else(|| {
|
||||
(font.name(b"Subtype") == Some(b"Type3"))
|
||||
.then(|| dict(doc, font.get(b"FontDescriptor")))
|
||||
.flatten()
|
||||
.and_then(|d| d.name(b"FontName").map(|name| String::from_utf8_lossy(name).into_owned()))
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Codespace ranges and CID mappings from an embedded CMap stream, at most
|
||||
/// [`MAX_CMAP_RANGES`] of each (every glyph searches them).
|
||||
#[allow(clippy::type_complexity)]
|
||||
@@ -633,16 +647,7 @@ impl Metrics {
|
||||
|
||||
pub fn from_dict(doc: &Document, font: &Dict) -> Self {
|
||||
let mut m = Self::read_metrics(doc, font);
|
||||
let base = font
|
||||
.name(b"BaseFont")
|
||||
.map(|name| String::from_utf8_lossy(name).into_owned())
|
||||
.or_else(|| {
|
||||
(font.name(b"Subtype") == Some(b"Type3"))
|
||||
.then(|| dict(doc, font.get(b"FontDescriptor")))
|
||||
.flatten()
|
||||
.and_then(|d| d.name(b"FontName").map(|name| String::from_utf8_lossy(name).into_owned()))
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let base = base_font_name(doc, font);
|
||||
m.subset = base.len() > 7 && base.as_bytes()[6] == b'+' && base[..6].bytes().all(|b| b.is_ascii_uppercase());
|
||||
let (bold, italic) = style_from_name(&base);
|
||||
m.bold |= bold;
|
||||
|
||||
@@ -795,3 +795,13 @@ fn low_codes_resolve_to_the_covering_range() {
|
||||
assert_eq!(covered, [5, 6, 7, 100, 101]);
|
||||
assert_eq!((u.covering(0xFFFF).is_some(), u.covering(0x1_0001).is_some(), u.covering(0x1_0002).is_none()), (true, true, true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn base_font_name_matches_the_metrics_name() {
|
||||
let doc = Document::new_empty();
|
||||
let mut f = Dict::new();
|
||||
f.set(b"BaseFont".to_vec(), Object::name("ABCDEF+Body"));
|
||||
assert_eq!(base_font_name(&doc, &f), "ABCDEF+Body");
|
||||
assert_eq!(base_font_name(&doc, &f), Metrics::from_dict(&doc, &f).base_font);
|
||||
assert_eq!(base_font_name(&doc, &Dict::new()), "");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user