| ... | ... | @@ -1,7 +1,8 @@ |
| 1 | 1 | use onestore::page::text::Paragraph; |
| 2 | 2 | use parley::{ |
| 3 | | Affinity, Alignment, AlignmentOptions, BoundingBox, FontContext, FontFamily, FontStyle, |
| 4 | | FontWeight, Layout, LayoutContext, OverflowWrap, PositionedLayoutItem, StyleProperty, |
| 3 | Affinity, Alignment, AlignmentOptions, BoundingBox, FontContext, FontFamily, FontFamilyName, |
| 4 | FontStyle, FontWeight, GenericFamily, Layout, LayoutContext, OverflowWrap, |
| 5 | PositionedLayoutItem, StyleProperty, |
| 5 | 6 | editing::{Cursor, Selection}, |
| 6 | 7 | }; |
| 7 | 8 | use skrifa::{FontRef, MetadataProvider, raw::TableProvider, string::StringId}; |
| ... | ... | @@ -139,8 +140,13 @@ impl TextEngine { |
| 139 | 140 | return Err(LayoutError::InvalidFontSize); |
| 140 | 141 | } |
| 141 | 142 | let properties = [ |
| 142 | | StyleProperty::FontFamily(FontFamily::named( |
| 143 | | format.font.as_deref().unwrap_or("Arial"), |
| 143 | StyleProperty::FontFamily(FontFamily::List( |
| 144 | vec![ |
| 145 | FontFamilyName::named(format.font.as_deref().unwrap_or("Arial")), |
| 146 | // A missing family otherwise falls back per script and can put digits in an emoji font. |
| 147 | GenericFamily::SansSerif.into(), |
| 148 | ] |
| 149 | .into(), |
| 144 | 150 | )), |
| 145 | 151 | StyleProperty::FontSize(size), |
| 146 | 152 | StyleProperty::FontWeight(if format.bold == Some(true) { |
| ... | ... | @@ -522,6 +528,27 @@ mod tests { |
| 522 | 528 | ); |
| 523 | 529 | } |
| 524 | 530 | |
| 531 | #[test] |
| 532 | fn missing_family_keeps_digits_in_the_letters_face() { |
| 533 | let paragraph = Paragraph::new( |
| 534 | "Monday, August 10, 2026".into(), |
| 535 | Format { |
| 536 | font: Some("Snowbound Missing Family".into()), |
| 537 | ..Format::default() |
| 538 | }, |
| 539 | ); |
| 540 | let layout = TextEngine::default().layout(&paragraph, 468.0).unwrap(); |
| 541 | let fonts = layout |
| 542 | .lines() |
| 543 | .flat_map(|(line, _)| { |
| 544 | line.runs() |
| 545 | .map(|run| run.font().font.data.id()) |
| 546 | .collect::<Vec<_>>() |
| 547 | }) |
| 548 | .collect::<BTreeSet<_>>(); |
| 549 | assert_eq!(fonts.len(), 1); |
| 550 | } |
| 551 | |
| 525 | 552 | #[test] |
| 526 | 553 | fn highlights_share_line_geometry_without_changing_wraps() { |
| 527 | 554 | let paragraph = Paragraph::from_runs([ |