mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Merge pull request #3251 from MarekSpodBiedry/issue-3229
Warn on export when a font style is drawn in another style (#3229)
This commit is contained in:
@@ -301,7 +301,8 @@ fn drawn_runs(t: &vectorcraft_doc::TextObject) -> (Vec<&TextRun>, bool) {
|
||||
}
|
||||
|
||||
/// What an export that draws type (as outlines, embedded fonts or pixels) says when `d` uses font
|
||||
/// families that aren't available: their type is drawn in the fallback font, not the font it names.
|
||||
/// families that aren't available (their type is drawn in the fallback font, not the font it
|
||||
/// names) or styles that its family doesn't have (the closest style is drawn).
|
||||
pub(super) fn substitution_warning(d: &Document) -> Option<String> {
|
||||
substitution_warning_of(used_fonts(d))
|
||||
}
|
||||
@@ -309,20 +310,34 @@ pub(super) fn substitution_warning(d: &Document) -> Option<String> {
|
||||
/// [`substitution_warning`] for type set in `fonts`.
|
||||
pub(super) fn substitution_warning_of(fonts: BTreeSet<UsedFont>) -> Option<String> {
|
||||
let db = vectorcraft_text::FontDb::global();
|
||||
let mut missing: Vec<String> = fonts
|
||||
.into_iter()
|
||||
.filter(|(family, style, _)| db.resolve(family, style).is_none_or(|(_, m)| m == vectorcraft_text::FontMatch::Missing))
|
||||
.map(|(family, _, _)| family)
|
||||
.collect();
|
||||
let mut missing: Vec<String> = Vec::new();
|
||||
let mut styles: BTreeSet<String> = BTreeSet::new();
|
||||
for (family, style, _) in fonts {
|
||||
match db.resolve(&family, &style) {
|
||||
None | Some((_, vectorcraft_text::FontMatch::Missing)) => missing.push(family),
|
||||
Some((face, vectorcraft_text::FontMatch::Style)) => {
|
||||
styles.insert(format!("{family} {style} was drawn in {} {}", face.family, face.style));
|
||||
}
|
||||
Some(_) => {}
|
||||
}
|
||||
}
|
||||
// Sorted by family: its styles and versions are neighbours.
|
||||
missing.dedup();
|
||||
(!missing.is_empty()).then(|| {
|
||||
format!(
|
||||
let mut parts = Vec::new();
|
||||
if !missing.is_empty() {
|
||||
parts.push(format!(
|
||||
"fonts that aren't available were written in the fallback font, {}: {} (install them, or replace them with Find Font)",
|
||||
vectorcraft_text::FALLBACK_FAMILY,
|
||||
missing.join(", ")
|
||||
)
|
||||
})
|
||||
));
|
||||
}
|
||||
if !styles.is_empty() {
|
||||
parts.push(format!(
|
||||
"font styles that aren't available were written in the closest style: {} (pick a style the family has)",
|
||||
styles.into_iter().collect::<Vec<_>>().join(", ")
|
||||
));
|
||||
}
|
||||
(!parts.is_empty()).then(|| parts.join("; "))
|
||||
}
|
||||
|
||||
fn text(d: &Document, id: NodeId) -> Option<&vectorcraft_doc::TextObject> {
|
||||
@@ -585,6 +600,16 @@ mod open_tests {
|
||||
assert_eq!(inter["missingGlyphs"], 2, "雅 and 楽 come from a fallback font: {inter}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn export_warns_when_a_style_is_drawn_in_another_style() {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({"width": 200, "height": 200})).unwrap();
|
||||
s.execute("text.create", &json!({"x": 10, "y": 20, "text": "Hi", "font": "Source Sans 3", "style": "Black Wide"})).unwrap();
|
||||
let out = s.execute("document.export", &json!({"format": "pdf"})).unwrap();
|
||||
let warnings = out["warnings"].to_string();
|
||||
assert!(warnings.contains("Source Sans 3 Black Wide was drawn in Source Sans 3"), "{out}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opened_documents_have_exact_text_bounds() {
|
||||
let mut s = Session::new();
|
||||
|
||||
Reference in New Issue
Block a user