Skip to content

Commit cf36dbb

Browse files
committed
Add a feature for enabling compilation for no_std
This commit adds two new features: "std" (which is enabled by default) and "libm". When "std" is enabled, floating point intrinsics are used from libstd. When "libm" is enabled, it brings in the pure Rust libm implementation to handle floating point instrinsics in software mode. By disabling the "std" feature and enabling "libm", this crate can be effectively used on no_std platforms, like embedded systems. This is a breaking change, as it adds an "std" default feature that, when disabled without enabling "libm", causes a compile error. Users who are currently using zeno with "default-features = false" without preparation will have their compilation break. Rel: dfrg/swash#4 Signed-off-by: John Nunley <[email protected]>
1 parent a1928c8 commit cf36dbb

File tree

5 files changed

+86
-2
lines changed

5 files changed

+86
-2
lines changed

Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ homepage = "https://github.com/dfrg/zeno"
1212
readme = "README.md"
1313

1414
[dependencies]
15+
libm = { version = "0.2.7", default-features = false, optional = true }
1516

1617
[features]
17-
default = ["eval"]
18+
default = ["eval", "std"]
1819
eval = []
20+
std = []
21+

src/geometry.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Geometric primitives.
22
3+
use crate::F32Ext;
4+
35
use core::borrow::Borrow;
46
use core::ops::{Add, Div, Mul, Sub};
57

src/lib.rs

+78-1
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,13 @@ constructors are provided which take a scratch instance as an argument and
264264
redirect all transient allocations to the reusable storage.
265265
*/
266266

267+
#![cfg_attr(not(feature = "std"), no_std)]
268+
269+
#[cfg(not(any(feature = "std", feature = "libm")))]
270+
compile_error! { "Either the std or libm feature must be enabled" }
271+
272+
extern crate alloc;
273+
267274
mod command;
268275
mod geometry;
269276
#[cfg(feature = "eval")]
@@ -301,7 +308,77 @@ pub use svg_parser::validate_svg;
301308
#[cfg(feature = "eval")]
302309
pub use traversal::{Vertex, Vertices, Walk};
303310

311+
macro_rules! define_f32_ext {
312+
($($fpname:ident($($argname:ident: $argty:ty),*) -> $ret:ty => $libmname:ident;)*) => {
313+
/// An extension trait defining floating point operations.
314+
trait F32Ext {
315+
$(
316+
fn $fpname(self, $($argname:$argty),*) -> $ret;
317+
)*
318+
}
319+
320+
#[cfg(feature = "std")]
321+
impl F32Ext for f32 {
322+
$(
323+
fn $fpname(self, $($argname:$argty),*) -> $ret {
324+
// This instrinsic is natively defined in libstd.
325+
f32::$fpname(self, $($argname),*)
326+
}
327+
)*
328+
}
329+
330+
#[cfg(all(not(feature = "std"), feature = "libm"))]
331+
impl F32Ext for f32 {
332+
$(
333+
fn $fpname(self, $($argname:$argty),*) -> $ret {
334+
// Use the libm version of this instrinsic.
335+
<$ret>::libm_cvt(libm::$libmname(
336+
self.into(),
337+
$(($argname).into()),*
338+
) as _)
339+
}
340+
)*
341+
}
342+
}
343+
}
344+
345+
define_f32_ext! {
346+
abs() -> f32 => fabs;
347+
acos() -> f32 => acos;
348+
atan2(x:f32) -> f32 => atan2;
349+
ceil() -> f32 => ceil;
350+
cos() -> f32 => cos;
351+
floor() -> f32 => floor;
352+
sin_cos() -> (f32, f32) => sincos;
353+
sqrt() -> f32 => sqrt;
354+
powf(x:f32) -> f32 => powf;
355+
powi(x:i32) -> f32 => pow;
356+
tan() -> f32 => tan;
357+
}
358+
359+
#[cfg(all(not(feature = "std"), feature = "libm"))]
360+
trait LibmCvt {
361+
type Input;
362+
fn libm_cvt(input: Self::Input) -> Self;
363+
}
364+
365+
#[cfg(all(not(feature = "std"), feature = "libm"))]
366+
impl LibmCvt for f32 {
367+
type Input = f64;
368+
fn libm_cvt(input: f64) -> f32 {
369+
input as f32
370+
}
371+
}
372+
373+
#[cfg(all(not(feature = "std"), feature = "libm"))]
374+
impl LibmCvt for (f32, f32) {
375+
type Input = (f64, f64);
376+
fn libm_cvt((a, b): (f64, f64)) -> (f32, f32) {
377+
(a as f32, b as f32)
378+
}
379+
}
380+
304381
// Prep for no_std support when core supports FP intrinsics.
305382
mod lib {
306-
pub use std::vec::Vec;
383+
pub use alloc::vec::Vec;
307384
}

src/path_builder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use super::command::Command;
44
use super::geometry::{Angle, BoundsBuilder, Point, Transform};
5+
use super::F32Ext;
56

67
use crate::lib::Vec;
78

src/segment.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use super::command::Command;
44
use super::geometry::*;
5+
use super::F32Ext;
56

67
use core::borrow::Borrow;
78

0 commit comments

Comments
 (0)