Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ description = "A font renderer written (mostly) in pure, safe Rust"
repository = "https://github.com/google/font-rs"

[features]
default = ["std"]

sse = []
std = []
35 changes: 21 additions & 14 deletions src/accumulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,29 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::mem;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;

#[cfg(all(feature = "sse", not(feature = "std")))]
use core::arch::x86_64::*;

#[cfg(target_arch = "x86_64")]
#[cfg(all(feature = "sse", feature = "std"))]
use std::arch::x86_64::*;

#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(all(feature = "sse", not(feature = "std")))]
use core::mem;

macro_rules! _mm_shuffle {
($z:expr, $y:expr, $x:expr, $w:expr) => {
($z << 6) | ($y << 4) | ($x << 2) | $w
};
}
#[cfg(all(feature = "sse", feature = "std"))]
use std::mem;

#[cfg(feature = "sse")]
pub fn accumulate(src: &[f32]) -> Vec<u8> {
macro_rules! _mm_shuffle {
($z:expr, $y:expr, $x:expr, $w:expr) => {
($z << 6) | ($y << 4) | ($x << 2) | $w
};
}

// SIMD instructions force us to align data since we iterate each 4 elements
// So:
// n (0) => 0
Expand Down Expand Up @@ -68,9 +75,9 @@ pub fn accumulate(src: &[f32]) -> Vec<u8> {

#[cfg(not(feature = "sse"))]
pub fn accumulate(src: &[f32]) -> Vec<u8> {
let mut acc = 0.0;
src.iter()
.map(|c| {
let mut acc = 0.0f32;
src.into_iter()
.map(|&c| {
// This would translate really well to SIMD
acc += c;
let y = acc.abs();
Expand All @@ -88,8 +95,8 @@ mod tests {
// accumulate fn
fn accumulate_simple_impl(src: &[f32]) -> Vec<u8> {
let mut acc = 0.0;
src.iter()
.map(|c| {
src.into_iter()
.map(|&c| {
acc += c;
let y = acc.abs();
let y = if y < 1.0 { y } else { 1.0 };
Expand Down
28 changes: 28 additions & 0 deletions src/float32.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

use core::intrinsics::*;

/// Abstraction for floating point intrinsics in no_std mode
pub trait Float32 {
fn abs(self) -> f32;
fn floor(self) -> f32;
fn ceil(self) -> f32;
fn sqrt(self) -> f32;
}

impl Float32 for f32 {
fn abs(self) -> f32 {
unsafe { fabsf32(self) }
}

fn floor(self) -> f32 {
unsafe { floorf32(self) }
}

fn ceil(self) -> f32 {
unsafe { ceilf32(self) }
}

fn sqrt(self) -> f32 {
unsafe { sqrtf32(self) }
}
}
37 changes: 27 additions & 10 deletions src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,33 @@

//! A simple renderer for TrueType fonts

use std::collections::HashMap;
#[cfg(not(feature = "std"))]
use alloc::collections::BTreeMap;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
#[cfg(not(feature = "std"))]
use alloc::str;
#[cfg(not(feature = "std"))]
use alloc::fmt;
#[cfg(not(feature = "std"))]
use alloc::fmt::{Debug, Display, Formatter};

#[cfg(feature = "std")]
use std::collections::BTreeMap;
#[cfg(feature = "std")]
use std::str;
#[cfg(feature = "std")]
use std::fmt;
#[cfg(feature = "std")]
use std::fmt::{Debug, Display, Formatter};
use std::result::Result;

use geom::{affine_pt, Affine, Point};
use raster::Raster;

#[derive(PartialEq, Eq, Hash)]
#[cfg(not(feature = "std"))]
use float32::Float32;

#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct Tag(u32);

impl Tag {
Expand All @@ -34,13 +52,13 @@ impl Tag {
impl Display for Tag {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let &Tag(tag) = self;
let buf = vec![
let buf = [
((tag >> 24) & 0xff) as u8,
((tag >> 16) & 0xff) as u8,
((tag >> 8) & 0xff) as u8,
(tag & 0xff) as u8,
];
f.write_str(&String::from_utf8(buf).unwrap())
f.write_str(str::from_utf8(&buf).unwrap())
}
}

Expand Down Expand Up @@ -672,7 +690,7 @@ impl<'a> CompoundGlyph<'a> {

pub struct Font<'a> {
_version: u32,
_tables: HashMap<Tag, &'a [u8]>,
_tables: BTreeMap<Tag, &'a [u8]>,
head: Head<'a>,
maxp: Maxp<'a>,
cmap: Option<Cmap<'a>>,
Expand Down Expand Up @@ -739,7 +757,7 @@ impl<'a> Font<'a> {
}
}
_ => {
println!("unhandled glyph case");
unreachable!("unhandled glyph case");
}
}
}
Expand Down Expand Up @@ -776,8 +794,7 @@ impl<'a> Font<'a> {
})
}
_ => {
println!("glyph {} error", glyph_id);
None
unreachable!("glyph {} error", glyph_id);
}
}
}
Expand Down Expand Up @@ -950,7 +967,7 @@ pub fn parse(data: &[u8]) -> Result<Font, FontError> {
let _search_range = get_u16(data, 6).unwrap();
let _entry_selector = get_u16(data, 8).unwrap();
let _range_shift = get_u16(data, 10).unwrap();
let mut tables = HashMap::new();
let mut tables = BTreeMap::new();
for i in 0..num_tables {
let header = &data[12 + i * 16..12 + (i + 1) * 16];
let tag = get_u32(header, 0).unwrap();
Expand Down
4 changes: 4 additions & 0 deletions src/geom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

//! Geometry primitive data structures and manipulations

#[cfg(not(feature = "std"))]
use alloc::fmt::{Debug, Formatter, Result};

#[cfg(feature = "std")]
use std::fmt::{Debug, Formatter, Result};

#[derive(Copy, Clone)]
Expand Down
10 changes: 10 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,19 @@

//! A very high performance font renderer.

#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc, core_intrinsics))]

#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;

#[macro_use]
pub mod macros;
pub mod accumulate;
pub mod font;
pub mod geom;
pub mod raster;

#[cfg(not(feature = "std"))]
mod float32;
9 changes: 7 additions & 2 deletions src/raster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@

//! An antialiased rasterizer for quadratic Beziers

use std::cmp::min;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;

use accumulate::accumulate;
use geom::Point;

#[cfg(not(feature = "std"))]
use float32::Float32;

// TODO: sort out crate structure. Right now we want this when compiling raster as a binary,
// but need it commented out when compiling showttf
//mod geom;
Expand Down Expand Up @@ -59,7 +63,8 @@ impl Raster {
if p0.y < 0.0 {
x -= p0.y * dxdy;
}
for y in y0..min(self.h, p1.y.ceil() as usize) {
let ymin = self.h.min(p1.y.ceil() as usize);
for y in y0..ymin {
let linestart = y * self.w;
let dy = ((y + 1) as f32).min(p1.y) - (y as f32).max(p0.y);
let xnext = x + dxdy * dy;
Expand Down