use std::collections::HashMap;
use fonts::FaceRecord;
use fonts::selection_italic as italic;
#[test]
fn test_italic_instance_detection() {
let italic_parser = italic::ItalicParser::new();
let test_cases = vec![
("Italic", true, vec!["Italic", "TestFont-Italic"]), (
"Bold Italic",
true,
vec!["Bold Italic", "TestFont-Bold Italic"],
),
(
"Light Italic",
true,
vec!["Light Italic", "TestFont-Light Italic"],
),
(
"TestFont-Italic",
true,
vec!["TestFont-Italic", "TestFont-TestFont-Italic"],
), ("Regular", false, vec![]),
("Bold", false, vec![]),
("TestFont-Regular", false, vec![]),
("Oblique", false, vec![]),
("Bold Oblique", false, vec![]),
("TestFont-Oblique", false, vec![]),
(
"Italic Oblique",
true,
vec!["Italic Oblique", "TestFont-Italic Oblique"],
), ("", false, vec![]),
("ITALIC", true, vec!["ITALIC", "TestFont-ITALIC"]), ("italic", true, vec!["italic", "TestFont-italic"]),
("ItAlIc", true, vec!["ItAlIc", "TestFont-ItAlIc"]), ];
for (name, should_be_italic, expected_instances) in test_cases {
let mut axes = HashMap::new();
axes.insert("slnt".to_string(), (-15.0, 0.0, 0.0));
let face = FaceRecord {
face_id: format!("test-{}", name.replace(" ", "_")),
ps_name: format!("TestFont-{}", name),
family_name: "Test".to_string(),
typographic_family: None,
subfamily_name: name.to_string(),
typographic_subfamily: None,
is_variable: true,
axes,
os2_italic_bit: false,
weight_class: 400,
width_class: 5,
user_font_style_italic: None,
};
let italic_instances = italic_parser.extract_italic_instances(&face);
assert_eq!(
italic_instances, expected_instances,
"Failed for name '{}': expected {:?}, got {:?}",
name, expected_instances, italic_instances
);
let has_italic = italic_parser.has_italic_named_instances(&face);
assert_eq!(
has_italic, should_be_italic,
"Failed for name '{}': expected {}, got {}",
name, should_be_italic, has_italic
);
let is_italic_by_name = italic_parser.is_italic_by_name(&face);
assert_eq!(
is_italic_by_name, should_be_italic,
"Failed for name '{}': expected {}, got {}",
name, should_be_italic, is_italic_by_name
);
println!(
"✅ '{}' -> italic: {}, instances: {:?}",
name, should_be_italic, italic_instances
);
}
}
#[test]
fn test_oblique_not_valid_italic() {
let italic_parser = italic::ItalicParser::new();
let oblique_cases = vec![
"Oblique",
"Bold Oblique",
"Light Oblique",
"TestFont-Oblique",
"OBLIQUE",
"oblique",
"ObLiQuE",
];
for name in oblique_cases {
let mut axes = HashMap::new();
axes.insert("slnt".to_string(), (-15.0, 0.0, 0.0));
let face = FaceRecord {
face_id: format!("test-{}", name.replace(" ", "_")),
ps_name: format!("TestFont-{}", name),
family_name: "Test".to_string(),
typographic_family: None,
subfamily_name: name.to_string(),
typographic_subfamily: None,
is_variable: true,
axes,
os2_italic_bit: false,
weight_class: 400,
width_class: 5,
user_font_style_italic: None,
};
let italic_instances = italic_parser.extract_italic_instances(&face);
assert!(
italic_instances.is_empty(),
"Oblique name '{}' should not produce italic instances, got: {:?}",
name,
italic_instances
);
let has_italic = italic_parser.has_italic_named_instances(&face);
assert!(
!has_italic,
"Oblique name '{}' should not be considered italic",
name
);
let is_italic_by_name = italic_parser.is_italic_by_name(&face);
assert!(
!is_italic_by_name,
"Oblique name '{}' should not be considered italic by name",
name
);
println!("✅ '{}' correctly rejected as italic", name);
}
}
#[test]
fn test_scenario_3_1_with_italic_instances() {
let italic_parser = italic::ItalicParser::new();
let mut axes = HashMap::new();
axes.insert("slnt".to_string(), (-15.0, 0.0, 0.0));
let face = FaceRecord {
face_id: "scenario-3-1-italic".to_string(),
ps_name: "TestFont-Italic".to_string(),
family_name: "Test".to_string(),
typographic_family: None,
subfamily_name: "Italic".to_string(),
typographic_subfamily: None,
is_variable: true,
axes,
os2_italic_bit: false, weight_class: 400,
width_class: 5,
user_font_style_italic: None,
};
let classification = italic_parser.classify_face(face);
assert_eq!(
classification.classification.italic_kind(),
italic::ItalicKind::Italic
);
assert!(classification.classification.vf_recipe.is_some());
let recipe = classification.classification.vf_recipe.unwrap();
assert!(recipe.axis_values.contains_key("slnt"));
assert!(classification.classification.instance_info.is_some());
let instance_info = classification.classification.instance_info.unwrap();
assert_eq!(instance_info.ps_name, "TestFont-Italic");
assert_eq!(instance_info.style_name, "Italic");
assert!(!instance_info.italic_instances.is_empty());
assert!(
instance_info
.italic_instances
.contains(&"Italic".to_string())
);
assert!(
instance_info
.italic_instances
.contains(&"TestFont-Italic".to_string())
);
println!(
"✅ Scenario 3-1 correctly detected with italic instances: {:?}",
instance_info.italic_instances
);
}
#[test]
fn test_scenario_3_1_rejects_oblique() {
let italic_parser = italic::ItalicParser::new();
let mut axes = HashMap::new();
axes.insert("slnt".to_string(), (-15.0, 0.0, 0.0));
let face = FaceRecord {
face_id: "scenario-3-1-oblique".to_string(),
ps_name: "TestFont-Oblique".to_string(),
family_name: "Test".to_string(),
typographic_family: None,
subfamily_name: "Oblique".to_string(),
typographic_subfamily: None,
is_variable: true,
axes,
os2_italic_bit: false, weight_class: 400,
width_class: 5,
user_font_style_italic: None,
};
let classification = italic_parser.classify_face(face);
assert_eq!(
classification.classification.italic_kind(),
italic::ItalicKind::Italic
);
assert!(classification.classification.vf_recipe.is_some());
let recipe = classification.classification.vf_recipe.unwrap();
assert!(recipe.axis_values.contains_key("slnt"));
assert!(classification.classification.instance_info.is_some());
let instance_info = classification.classification.instance_info.unwrap();
assert_eq!(instance_info.ps_name, "TestFont-Oblique");
assert_eq!(instance_info.style_name, "Oblique");
assert_eq!(instance_info.italic_instances, vec!["slnt-axis-capable"]);
println!("✅ Oblique font correctly handled as Level 1 permissive, not Scenario 3-1");
}