Compare commits

..
Author SHA1 Message Date
Dylan M. Taylor 11fec161cc Fonts: ignore variation tags the font has no axis for 2026-11-03 20:32:00 +00:00
2 changed files with 10 additions and 23 deletions
+3 -20
View File
@@ -148,19 +148,7 @@ pub fn rotate(dir: &Path) -> std::io::Result<(PathBuf, File)> {
/// One formatted log line: `<timestamp> <LEVEL> [<thread>] <target>: <message>\n`.
pub fn format_line(ts: &str, level: log::Level, thread: &str, target: &str, message: &str) -> String {
let message = message.strip_suffix('\n').unwrap_or(message);
// Messages can embed document-controlled text (a part name, a relationship id): control
// characters other than tab are escaped and each continuation line is marked, so such text
// cannot start a line that looks like a record of its own.
let mut text = String::with_capacity(message.len());
for c in message.chars() {
match c {
'\n' => text.push_str("\n | "),
'\t' => text.push(c),
c if c.is_control() => text.extend(c.escape_default()),
c => text.push(c),
}
}
format!("{ts} {level:<5} [{thread}] {target}: {text}\n")
format!("{ts} {level:<5} [{thread}] {target}: {message}\n")
}
/// Where formatted lines go besides standard error: kept in memory until a file is attached,
@@ -458,13 +446,8 @@ mod tests {
),
"2026-10-08T07:59:17.728Z WARN [main] deckcraft_pptx::opc: pptx: skipping oversized part ppt/media/image1.png\n"
);
// A multi-line message keeps its lines, each continuation marked; the record still ends in
// exactly one newline.
assert!(format_line("t", log::Level::Error, "w", "x", "a\nb\n").ends_with("x: a\n | b\n"));
// Injected line breaks and escape sequences cannot forge a record.
let line = format_line("t", log::Level::Warn, "w", "x", "part a\r\n2026 ERROR [m] y: forged\x1b[2J");
assert_eq!(line.matches('\n').count(), 2);
assert!(!line.contains('\r') && !line.contains('\x1b'));
// A multi-line message keeps its lines; the record still ends in exactly one newline.
assert!(format_line("t", log::Level::Error, "w", "x", "a\nb\n").ends_with("x: a\nb\n"));
}
#[test]
+7 -3
View File
@@ -1215,9 +1215,8 @@ impl FontDb {
fn instance(&self, family: &str, style: &str) -> Option<Arc<FontFace>> {
let open = style.find('{')?;
let base = self.find(family, style[..open].trim())?;
if base.skrifa().is_none_or(|f| f.axes().is_empty()) {
return Some(base);
}
let Some(font) = base.skrifa().filter(|f| !f.axes().is_empty()) else { return Some(base) };
let axis_tags: Vec<[u8; 4]> = font.axes().iter().map(|a| a.tag().to_be_bytes()).collect();
let mut coords = base.coords.clone();
for kv in style[open + 1..].trim_end_matches('}').split(',') {
let (k, v) = kv.split_once(':')?;
@@ -1227,6 +1226,11 @@ impl FontDb {
return None;
}
let tag = [k[0], k[1], k[2], k[3]];
// A tag the font has no axis for changes nothing; keeping it would grow the list with
// every distinct tag in the style text.
if !axis_tags.contains(&tag) {
continue;
}
match coords.iter_mut().find(|(t, _)| *t == tag) {
Some(c) => c.1 = v,
None => coords.push((tag, v)),