Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions profile-opentype/src/checks/opentype/fsselection.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use fontations::{
skrifa::raw::{
tables::{head::MacStyle, os2::SelectionFlags},
TableProvider,
skrifa::{
raw::{
tables::{head::MacStyle, os2::SelectionFlags},
TableProvider,
},
string::StringId,
MetadataProvider,
},
write::from_obj::ToOwnedTable,
};
Expand All @@ -24,6 +28,7 @@ use fontspector_checkapi::{prelude::*, testfont, FileTypeConvert};
the bold and italic bits in head.macStyle per the OpenType spec.
",
proposal = "https://github.com/fonttools/fontbakery/issues/4829", // legacy check
proposal = "https://github.com/fonttools/fontspector/issues/577",
hotfix = fix_fsselection,
)]
fn fsselection(f: &Testable, _context: &Context) -> CheckFnResult {
Expand Down Expand Up @@ -66,6 +71,22 @@ fn fsselection(f: &Testable, _context: &Context) -> CheckFnResult {
));
}
}

let wws_seen = fs_flags.contains(SelectionFlags::WWS);
let has_name_id_21 = font
.font()
.localized_strings(StringId::WWS_FAMILY_NAME)
.english_or_first();
let has_name_id_22 = font
.font()
.localized_strings(StringId::WWS_SUBFAMILY_NAME)
.english_or_first();
if has_name_id_21.is_none() && has_name_id_22.is_none() && !wws_seen {
problems.push(Status::warn(
"bad-fsSelection-wws-bit",
"If no name id 21 and 22 (WWS Family Name/WWS Subfamily Name), 'OS/2' fsSelection flag for WWS should be set.",
));
}
return_result(problems)
}

Expand All @@ -92,3 +113,32 @@ fn fix_fsselection(t: &mut Testable) -> FixFnResult {
t.set(f.rebuild_with_new_table(&os2)?);
Ok(true)
}

#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used)]

use fontspector_checkapi::{
codetesting::{
assert_messages_contain, assert_results_contain, run_check_with_config, test_able,
},
StatusCode, TestableType,
};
use std::collections::HashMap;

#[test]
fn test_fsselection() {
let testable = test_able("mada/Mada-Regular.ttf");
let results = run_check_with_config(
super::fsselection,
TestableType::Single(&testable),
HashMap::new(),
);
assert_messages_contain(&results, "fsSelection flag for WWS should be set.");
assert_results_contain(
&results,
StatusCode::Warn,
Some("bad-fsSelection-wws-bit".to_string()),
);
}
}
76 changes: 76 additions & 0 deletions profile-universal/src/checks/fsselection_wws.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use fontations::skrifa::{
raw::{tables::os2::SelectionFlags, TableProvider},
string::StringId,
MetadataProvider,
};
use fontspector_checkapi::{prelude::*, skip, testfont, FileTypeConvert};

// NOTE: This check is not part of OpenType profile, because we do not check
// if the names are consistent with weight/width/slope – therefore we cannot
// be 100% sure if WWS should be set or not.
// It's based on best practices -> therefore in Universal profile.

#[check(
id = "universal/fsselection_wws",
title = "Checking OS/2 fsSelection WWS bit.",
rationale = "
According to the opentype spec fsSelection bit 8 should be set if:

The font has 'name' table strings consistent with a
weight/width/slope family without requiring use of name IDs 21 and 22.
",
proposal = "https://github.com/fonttools/fontspector/issues/577"
)]
fn fsselection_wws(f: &Testable, _context: &Context) -> CheckFnResult {
let font = testfont!(f);
skip!(!font.has_table(b"name"), "no-name", "No name table.");

let mut problems = vec![];

let fs_flags = font.font().os2()?.fs_selection();
let wws_seen = fs_flags.contains(SelectionFlags::WWS);
let has_name_id_21 = font
.font()
.localized_strings(StringId::WWS_FAMILY_NAME)
.english_or_first();
let has_name_id_22 = font
.font()
.localized_strings(StringId::WWS_SUBFAMILY_NAME)
.english_or_first();
if has_name_id_21.is_none() && has_name_id_22.is_none() && !wws_seen {
problems.push(Status::warn(
"bad-fsSelection-wws-bit",
"If the font has 'name' table strings consistent with a weight/width/slope family without requiring use of name IDs 21 and 22, 'OS/2' fsSelection flag for WWS should be set.",
));
}
return_result(problems)
}

#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used)]

use fontspector_checkapi::{
codetesting::{
assert_messages_contain, assert_results_contain, run_check_with_config, test_able,
},
StatusCode, TestableType,
};
use std::collections::HashMap;

#[test]
fn test_fsselection_wws() {
let testable = test_able("mada/Mada-Regular.ttf");
let results = run_check_with_config(
super::fsselection_wws,
TestableType::Single(&testable),
HashMap::new(),
);
assert_messages_contain(&results, "fsSelection flag for WWS should be set.");
assert_results_contain(
&results,
StatusCode::Warn,
Some("bad-fsSelection-wws-bit".to_string()),
);
}
}
2 changes: 2 additions & 0 deletions profile-universal/src/checks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mod file_size;
mod fontdata_namecheck;
#[cfg(not(target_family = "wasm"))]
mod freetype_rasterizer;
mod fsselection_wws;
mod fvar_name_entries;
mod gpos7;
mod gpos_kerning_info;
Expand Down Expand Up @@ -96,6 +97,7 @@ pub use file_size::file_size;
pub use fontdata_namecheck::fontdata_namecheck;
#[cfg(not(target_family = "wasm"))]
pub use freetype_rasterizer::freetype_rasterizer;
pub use fsselection_wws::fsselection_wws;
pub use fvar_name_entries::fvar_name_entries;
pub use gpos7::gpos7;
pub use gpos_kerning_info::gpos_kerning_info;
Expand Down
1 change: 1 addition & 0 deletions profile-universal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ impl fontspector_checkapi::Plugin for Universal {
.add_and_register_check(checks::has_glyphs)
.add_and_register_check(checks::has_unicodes)
.add_and_register_check(checks::required_name_ids)
.add_and_register_check(checks::fsselection_wws)
.build("universal", cr)

// Checks which don't make sense any more
Expand Down
Loading