Skip to content

Commit

Permalink
New “base has width” check
Browse files Browse the repository at this point in the history
  • Loading branch information
simoncozens committed Nov 14, 2024
1 parent 440d664 commit 564e18c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
68 changes: 68 additions & 0 deletions profile-universal/src/checks/base_has_width.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use std::collections::HashMap;

use fontspector_checkapi::{constants::GlyphClass, prelude::*, testfont, FileTypeConvert};
use read_fonts::TableProvider;
use skrifa::{GlyphId, MetadataProvider};
use unicode_properties::{GeneralCategory, UnicodeGeneralCategory};

fn is_space(c: char) -> bool {
matches!(
c.general_category(),
GeneralCategory::SpaceSeparator
| GeneralCategory::LineSeparator
| GeneralCategory::ParagraphSeparator
| GeneralCategory::Format
| GeneralCategory::NonspacingMark
| GeneralCategory::Control
)
}

#[check(
id = "base_has_width",
rationale = "Base characters should have non-zero advance width.",
proposal = "Rod on chat",

This comment has been minimized.

Copy link
@felipesanches

felipesanches Nov 14, 2024

Collaborator

That's funny :-P

I'd rather open an issue, describe in more detail what was the context of the conversation and then add the issue URL here.

This comment has been minimized.

Copy link
@simoncozens

simoncozens Nov 14, 2024

Author Owner

Yeah, I know. He asked me how many fonts have this problem, so I just whipped up a check to answer. Should formalize it.

title = "Check base characters have non-zero advance width."
)]
fn base_has_width(f: &Testable, context: &Context) -> CheckFnResult {
let font = testfont!(f);
let hmtx = font.font().hmtx()?;
let mut problems = vec![];
let reverse_charmap: HashMap<_, _> = font
.font()
.charmap()
.mappings()
.map(|(c, g)| (g, c))
.collect();
for (gid, metric) in hmtx.h_metrics().iter().enumerate() {
let gid = GlyphId::new(gid as u16);
if metric.advance() == 0 && font.gdef_class(gid) != Some(GlyphClass::Mark) {
let codepoint = reverse_charmap.get(&gid);
if codepoint == Some(&0) || codepoint.is_none() {
continue;
}
if codepoint
.and_then(|c| char::from_u32(*c))
.map_or(false, is_space)
{
continue;
}
#[allow(clippy::unwrap_used)]
let name = font.glyph_name_for_id(gid, true).unwrap();
if name == "NULL" {
continue;
}
problems.push(format!("{} ({:?})", name, codepoint));
}
}
if problems.is_empty() {
Ok(Status::just_one_pass())
} else {
Ok(Status::just_one_fail(
"zero-width-bases",
&format!(
"The following glyphs had zero advance width:\n{}",
bullet_list(context, problems),
),
))
}
}
1 change: 1 addition & 0 deletions profile-universal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub struct Universal;
impl fontspector_checkapi::Plugin for Universal {
fn register(&self, cr: &mut Registry) -> Result<(), String> {
cr.register_check(checks::arabic_spacing_symbols::arabic_spacing_symbols);
cr.register_check(checks::base_has_width::base_has_width);
cr.register_check(checks::case_mapping::case_mapping);
cr.register_check(checks::cmap_format_12::cmap_format_12);
cr.register_check(checks::colorfont_tables::colorfont_tables);
Expand Down

0 comments on commit 564e18c

Please sign in to comment.