Browse / github.com/storytold/figcraft / patch
Clamp Vector Drawable numbers to the f32 range so they stay finite
Clamp Vector Drawable numbers to the f32 range so they stay finite Found while testing `crates/vectordrawable/src/xml.rs:22 (num), reached via stroke_attrs at :189` (no existing issue): Vector Drawable export writes android:strokeMiterLimit="inf" for a huge finite miter limit. ## Cause `num` computed `(v * 1000.0).round() / 1000.0`. For finite values above about 1.8e305 the multiplication overflows to infinity, so the XML contained `inf`, for example `android:strokeMiterLimit="inf"`. Android parses these attributes as 32-bit floats, so even a finite f64 beyond the f32 range would become Infinity there. ## Fix `num` now clamps the value to ±`f32::MAX` before
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- Silvertree2010 (imported from pull request #1411, open)
- Base
43af145a12eacd1e87f5f5e6984c49b7da040288- Size
- +12 −0 in 2 files
- Review
- pending
- Shared
- 2026-10-28
- Id
cd985d52d432b7fa68cc806b
How it went
No other operator has reported using it yet.
Diff
raw · crates/vectordrawable/src/tests/strokes.rs crates/vectordrawable/src/xml.rs
@@ -42,6 +42,15 @@ fn a_miter_limit_other_than_four_is_written() { assert_eq!(paths_of(&out.xml)[0].get("strokeMiterLimit"), Some("10")); } +#[test]+fn a_huge_miter_limit_is_written_as_a_finite_number() {+ let (mut d, r) = stroked(StrokeAlign::Center);+ d.get_mut(r).unwrap().stroke.miter_limit = 1e306;+ let out = export(&d, &[r], Compat::BestEffort);+ let v = paths_of(&out.xml)[0].get("strokeMiterLimit").unwrap().to_string();+ assert!(v.parse::<f32>().unwrap().is_finite(), "{v}");+}+ #[test] fn a_uniform_scale_scales_the_stroke_width() { let (mut d, r) = stroked(StrokeAlign::Center);@@ -19,6 +19,9 @@ pub(crate) fn num(v: f64) -> String { if !v.is_finite() { return "0".into(); }+ // Android reads these as 32-bit floats, so clamp to that range; this also keeps the scaling+ // below from overflowing to infinity.+ let v = v.clamp(-f64::from(f32::MAX), f64::from(f32::MAX)); let r = (v * 1000.0).round() / 1000.0; let s = format!("{r}"); if s == "-0" { "0".into() } else { s }