Skip to content

Commit 35bc37b

Browse files
committed
Truncate floating point <advance width=…> values
Closes #54 (GitHub). Works around rsms/inter#508 (GitHub). Test added for №54: [2022-10-08T11:27:29Z TRACE r#mod::bugfixes::issue54] test_data/bugfixes/issue54.glif [2022-10-08T11:27:29Z WARN glifparser::glif::read] Floating point value given as <advance> width — OpenType `hmtx` / `vmtx` will truncate it, so we do too! [2022-10-08T11:27:29Z DEBUG glifparser::outline] Outline only has corners; Outline<PD> type will treat it as a cubic. [2022-10-08T11:27:29Z TRACE r#mod::bugfixes::issue54] test_data/bugfixes/Q_.glif [2022-10-08T11:27:29Z TRACE glifparser::glif::read] <advance> parsing as int rose ParseIntError { kind: InvalidDigit } test bugfixes::issue54::test_bug_fixed ... ok
1 parent 96f3ba4 commit 35bc37b

6 files changed

Lines changed: 63 additions & 5 deletions

File tree

src/glif/read.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,21 @@ pub fn read_ufo_glif_pedantic<PD: PointData>(glif: &str, pedantry: Pedantry) ->
9595
.take_child("advance");
9696

9797
ret.width = if let Some(a) = advance {
98-
Some(a.attributes
99-
.get("width")
100-
.ok_or(input_error!("<advance> has no width"))?
101-
.parse()
102-
.or(Err(input_error!("<advance> width not int")))?)
98+
let width = a.attributes
99+
.get("width")
100+
.ok_or(input_error!("<advance> has no width"))?;
101+
let widthc = width.parse::<u64>();
102+
103+
match widthc {
104+
Err(e) => if let Ok((f, false)) = width.parse::<f32>().map(|f|(f, f.is_subnormal())) {
105+
log::warn!("Floating point value given as <advance> width — OpenType `hmtx` / `vmtx` will truncate it, so we do too!");
106+
Some(f as u64)
107+
} else {
108+
log::trace!("<advance> parsing as int rose {:?}", e);
109+
Err(input_error!("<advance> width neither int nor downgradable (not subnormal) float!"))?
110+
},
111+
Ok(i) => Some(i)
112+
}
103113
} else {
104114
None
105115
};

test_data/bugfixes/Q_.glif

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<glyph name="Q" format="2">
3+
<advance width="b0rked"/>
4+
<unicode hex="0051"/>
5+
<anchor x="787.2" y="688.0" name="_center"/>
6+
<outline>
7+
<contour>
8+
<point x="712.0" y="483.2" type="line"/>
9+
<point x="956.8" y="160.8" type="line"/>
10+
<point x="1014.0" y="81.6" type="line"/>
11+
<point x="1179.2" y="-134.0" type="line"/>
12+
<point x="1409.2" y="-134.0" type="line"/>
13+
<point x="1160.8" y="190.4" type="line"/>
14+
<point x="1088.8" y="280.4" type="line"/>
15+
<point x="933.2" y="483.2" type="line"/>
16+
</contour>
17+
<component base="O"/>
18+
</outline>
19+
</glyph>

test_data/bugfixes/issue54.glif

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<glyph name="iecyrillic" format="2">
3+
<advance width="1143.6666666666667"/>
4+
<unicode hex="0435"/>
5+
<anchor x="503.3333333333333" y="0.0" name="bottom"/>
6+
<anchor x="506.6666666666667" y="0.0" name="cedilla"/>
7+
<anchor x="972.3333333333334" y="218.0" name="ogonek"/>
8+
<anchor x="719.3333333333334" y="1304.0" name="top"/>
9+
<outline>
10+
<component base="e"/>
11+
</outline>
12+
</glyph>

tests/bugfixes/issue54.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use glifparser;
2+
3+
#[super::test]
4+
fn test_bug_fixed() {
5+
let gliffn = "test_data/bugfixes/issue54.glif";
6+
log::trace!("{}", gliffn);
7+
let glif: glifparser::Glif<()> = glifparser::glif::read_from_filename(gliffn).unwrap();
8+
assert_eq!(glif.width, Some(1143));
9+
let gliffn = "test_data/bugfixes/Q_.glif";
10+
log::trace!("{}", gliffn);
11+
let glif: Result<glifparser::Glif<()>, glifparser::error::GlifParserError> = glifparser::glif::read_from_filename(gliffn);
12+
assert!(glif.is_err());
13+
}

tests/bugfixes/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
use test_log::{self, test};
2+
3+
mod issue54;

tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mod bugfixes;

0 commit comments

Comments
 (0)