Skip to content

Commit

Permalink
Rework the supported status report, add concept of terminal checks
Browse files Browse the repository at this point in the history
  • Loading branch information
simoncozens committed Nov 26, 2024
1 parent 2107a9c commit 457350c
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 53 deletions.
2 changes: 1 addition & 1 deletion shaperglot-cli/src/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub fn check_command(args: &CheckArgs, language_database: shaperglot::Languages)
println!("{}", serde_json::to_string(&results).unwrap());
continue;
}
println!("{}", results.to_summary_string(args.nearly, language));
println!("{}", results.to_summary_string(language));
show_result(&results, args.verbose);
if args.fix {
for (category, fixes) in results.unique_fixes() {
Expand Down
2 changes: 1 addition & 1 deletion shaperglot-cli/src/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ pub fn report_command(args: &ReportArgs, language_database: shaperglot::Language
if results.is_unknown() {
continue;
}
println!("{}", results.to_summary_string(args.nearly, language));
println!("{}", results.to_summary_string(language));
}
}
5 changes: 5 additions & 0 deletions shaperglot-lib/src/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
font::{feature_tags, glyph_names},
language::Language,
reporter::Reporter,
ResultCode,
};
use rustybuzz::Face;
use skrifa::{raw::ReadError, FontRef, GlyphId, MetadataProvider};
Expand Down Expand Up @@ -52,7 +53,11 @@ impl<'a> Checker<'a> {
// let toml = toml::to_string(&check_object).unwrap();
// println!("Running check:\n{}", toml);
let checkresult = check_object.execute(self);
let status = checkresult.status;
results.add(checkresult);
if status == ResultCode::StopNow {
break;
}
}
results
}
Expand Down
5 changes: 4 additions & 1 deletion shaperglot-lib/src/checks/codepoint_coverage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
use serde_json::json;
use std::collections::HashSet;

#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug)]
pub struct CodepointCoverage {
strings: HashSet<String>,
code: String,
Expand Down Expand Up @@ -50,6 +50,9 @@ impl CheckImplementation for CodepointCoverage {
missing_things.join(", ")
),
);
if missing_things.len() == self.strings.len() {
fail.terminal = true;
}
fail.context = json!({"glyphs": missing_things});
fail.fixes.extend(missing_things.iter().map(|x| Fix {
fix_type: "add_codepoint".to_string(),
Expand Down
10 changes: 7 additions & 3 deletions shaperglot-lib/src/checks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ pub trait CheckImplementation {
fn execute(&self, checker: &Checker) -> (Vec<Problem>, usize);
}

#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, PartialEq, Debug)]
pub enum ScoringStrategy {
Continuous,
AllOrNothing,
}

#[derive(Delegate, Serialize, Deserialize)]
#[derive(Delegate, Serialize, Deserialize, Debug)]
#[delegate(CheckImplementation)]
#[serde(tag = "type")]
pub enum CheckType {
Expand All @@ -36,7 +36,7 @@ pub enum CheckType {
ShapingDiffers(ShapingDiffers),
}

#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug)]
pub struct Check {
pub name: String,
pub severity: ResultCode,
Expand Down Expand Up @@ -103,6 +103,10 @@ impl Check {
ResultCode::Skip
} else if problems.is_empty() {
ResultCode::Pass
} else if self.scoring_strategy == ScoringStrategy::AllOrNothing
&& problems.iter().any(|p| p.terminal)
{
ResultCode::StopNow
} else {
self.severity
},
Expand Down
4 changes: 3 additions & 1 deletion shaperglot-lib/src/checks/no_orphaned_marks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use itertools::Itertools;
use serde::{Deserialize, Serialize};
use unicode_properties::{GeneralCategory, UnicodeGeneralCategory};

#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug)]
pub struct NoOrphanedMarks {
test_strings: Vec<ShapingInput>,
has_orthography: bool,
Expand Down Expand Up @@ -67,6 +67,7 @@ impl CheckImplementation for NoOrphanedMarks {
check_name: self.name(),
message: format!("Shaper produced a dotted circle when {}", string),
code: "dotted-circle-produced".to_string(),
terminal: false,
context: serde_json::json!({
"text": previous,
"mark": codepoint.glyph_id,
Expand Down Expand Up @@ -96,6 +97,7 @@ impl CheckImplementation for NoOrphanedMarks {
.unwrap_or_else(|| format!("Glyph #{}", codepoint.glyph_id));
let fail = Problem {
check_name: self.name(),
terminal: false,
message: format!(
"Shaper didn't attach {} to {} when {}",
this_name, previous_name, string
Expand Down
2 changes: 1 addition & 1 deletion shaperglot-lib/src/checks/shaping_differs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use itertools::Itertools;
use rustybuzz::SerializeFlags;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug)]
pub struct ShapingDiffers {
pairs: Vec<(ShapingInput, ShapingInput)>,
features_optional: bool,
Expand Down
2 changes: 1 addition & 1 deletion shaperglot-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ pub use crate::{
checker::Checker,
language::Languages,
providers::Provider,
reporter::{Reporter, ResultCode},
reporter::{Reporter, ResultCode, SupportLevel},
};
3 changes: 3 additions & 0 deletions shaperglot-lib/src/providers/positional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub struct PositionalProvider;

impl Provider for PositionalProvider {
fn checks_for(&self, language: &Language) -> Vec<Check> {
if language.script() != "Arab" {
return vec![];
}
// let marks = language
// .marks
// .iter()
Expand Down
105 changes: 82 additions & 23 deletions shaperglot-lib/src/reporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum ResultCode {
Warn,
Fail,
Skip,
StopNow,
}

impl Display for ResultCode {
Expand All @@ -28,13 +29,15 @@ impl Display for ResultCode {
ResultCode::Warn => "WARN".yellow(),
ResultCode::Fail => "FAIL".red(),
ResultCode::Skip => "SKIP".blue(),
ResultCode::StopNow => "STOP".red(),
};
#[cfg(not(feature = "colored"))]
let to_string = match self {
ResultCode::Pass => "PASS",
ResultCode::Warn => "WARN",
ResultCode::Fail => "FAIL",
ResultCode::Skip => "SKIP",
ResultCode::StopNow => "STOP",
};
write!(f, "{}", to_string)
}
Expand All @@ -51,6 +54,7 @@ pub struct Problem {
pub check_name: String,
pub message: String,
pub code: String,
pub terminal: bool,
#[serde(skip_serializing_if = "Value::is_null")]
pub context: Value,
#[serde(skip_serializing_if = "Vec::is_empty")]
Expand Down Expand Up @@ -164,38 +168,93 @@ impl Reporter {
total_score / f32::from(total_weight) * 100.0
}

pub fn support_level(&self) -> SupportLevel {
if self.0.iter().any(|r| r.status == ResultCode::StopNow) {
return SupportLevel::None;
}
if self.is_unknown() {
return SupportLevel::Indeterminate;
}
if self.is_success() {
return SupportLevel::Complete;
}
if self.0.iter().any(|r| r.status == ResultCode::Fail) {
return SupportLevel::Unsupported;
}
if self.0.iter().any(|r| r.status == ResultCode::Warn) {
return SupportLevel::Incomplete;
}
SupportLevel::Supported
}

pub fn is_success(&self) -> bool {
self.0.iter().all(|r| r.problems.is_empty())
}
pub fn is_unknown(&self) -> bool {
self.0.iter().map(|r| r.total_checks).sum::<usize>() == 0
}

pub fn fixes_required(&self) -> usize {
self.unique_fixes().values().map(|v| v.len()).sum::<usize>()
}

pub fn is_nearly_success(&self, nearly: usize) -> bool {
self.unique_fixes().values().map(|v| v.len()).sum::<usize>() <= nearly
self.fixes_required() <= nearly
}

pub fn to_summary_string(&self, nearly: usize, language: &Language) -> String {
let score = if self.is_unknown() {
""
} else {
&format!(": {:.0}%", self.score())
};
let status = if self.is_unknown() {
"Cannot determine whether font supports "
} else if self.is_success() {
"Font supports "
} else if self.is_nearly_success(nearly) {
"Font nearly supports "
} else {
"Font does not fully support "
};
format!(
"{}language {} ({}){}",
status,
language.id(),
language.name(),
score
)
pub fn to_summary_string(&self, language: &Language) -> String {
match self.support_level() {
SupportLevel::Complete => {
format!(
"Font has complete support for {} ({}): 100%",
language.id(),
language.name()
)
}
SupportLevel::Supported => format!(
"Font fully supports {} ({}): {:.0}%",
language.id(),
language.name(),
self.score()
),
SupportLevel::Incomplete => format!(
"Font partially supports {} ({}): {:.0}% ({} fixes required)",
language.id(),
language.name(),
self.score(),
self.fixes_required()
),
SupportLevel::Unsupported => format!(
"Font does not support {} ({}): {:.0}% ({} fixes required)",
language.id(),
language.name(),
self.score(),
self.fixes_required()
),
SupportLevel::None => {
format!(
"Font does not attempt to support {} ({})",
language.id(),
language.name()
)
}
SupportLevel::Indeterminate => {
format!(
"Cannot determine whether font supports {} ({})",
language.id(),
language.name()
)
}
}
}
}

#[derive(Debug, Serialize, PartialEq)]
pub enum SupportLevel {
Complete, // Nothing can be improved.
Supported, // No FAILs or WARNS, but some optional SKIPs
Incomplete, // No FAILs
Unsupported, // There were FAILs
None, // Didn't even try
Indeterminate, // No checks
}
8 changes: 1 addition & 7 deletions shaperglot-web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,7 @@ pub fn check_font(font_data: &[u8]) -> Result<String, JsValue> {
}
results.push((
serde_json::to_value(&language.proto).map_err(|e| e.to_string())?,
if result.is_success() {
"supported"
} else if result.is_nearly_success(5) {
"nearly-supported"
} else {
"unsupported"
},
serde_json::to_value(result.support_level()).map_err(|e| e.to_string())?,
serde_json::to_value(&result).map_err(|e| e.to_string())?,
));
}
Expand Down
Loading

0 comments on commit 457350c

Please sign in to comment.