Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add conversion of font outlines to kurbo #40

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
name = "font-rs"
version = "0.1.3"
license = "Apache-2.0"
authors = [ "Raph Levien <raph@google.com>" ]
authors = [ "Raph Levien <raph.levien@gmail.com>" ]
keywords = ["font", "truetype", "ttf"]
description = "A font renderer written (mostly) in pure, safe Rust"
repository = "https://github.com/google/font-rs"
repository = "https://github.com/raphlinus/font-rs"
readme = "README.md"

[dependencies]
kurbo = { version = "0.4", optional = true }

[features]
sse = []
6 changes: 4 additions & 2 deletions src/accumulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#[cfg(feature = "sse")]
use std::mem;

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

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

#[cfg(feature = "sse")]
macro_rules! _mm_shuffle {
($z:expr, $y:expr, $x:expr, $w:expr) => {
($z << 6) | ($y << 4) | ($x << 2) | $w
Expand Down
77 changes: 71 additions & 6 deletions src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ use std::result::Result;
use geom::{affine_pt, Affine, Point};
use raster::Raster;

#[cfg(feature = "kurbo")]
use kurbo::BezPath;

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

Expand Down Expand Up @@ -633,7 +636,8 @@ struct Components<'a> {
ix: usize,
}

const ARG_1_AND_2_ARE_WORDS: u16 = 1;
const ARG_1_AND_2_ARE_WORDS: u16 = 1 << 0;
const ARGS_ARE_XY_VALUES: u16 = 1 << 1;
const WE_HAVE_A_SCALE: u16 = 1 << 3;
const MORE_COMPONENTS: u16 = 1 << 5;
const WE_HAVE_AN_X_AND_Y_SCALE: u16 = 1 << 6;
Expand All @@ -657,10 +661,17 @@ impl<'a> Iterator for Components<'a> {
arg2 = get_i16(self.data, self.ix).unwrap();
self.ix += 2;
} else {
arg1 = self.data[self.ix] as i16;
let byte1 = self.data[self.ix];
self.ix += 1;
arg2 = self.data[self.ix] as i16;
let byte2 = self.data[self.ix];
self.ix += 1;
if (flags & ARGS_ARE_XY_VALUES) != 0 {
arg1 = (byte1 as i8) as i16;
arg2 = (byte2 as i8) as i16;
} else {
arg1 = byte1 as i16;
arg2 = byte2 as i16;
}
}
let mut a = 1.0;
let mut b = 0.0;
Expand All @@ -685,9 +696,14 @@ impl<'a> Iterator for Components<'a> {
self.ix += 2;
d = a;
}
// TODO: handle non-ARGS_ARE_XY_VALUES case
let x = arg1 as f32;
let y = arg2 as f32;
let (x, y) = if (flags & ARGS_ARE_XY_VALUES) != 0 {
(arg1 as f32, arg2 as f32)
} else {
// This will require significant refactoring, we need access to
// points so we should store them instead of using only iterators.
println!("warning: need to look up point, offset ignored");
(0.0, 0.0)
};
let z = Affine::new(a, b, c, d, x, y);
self.more = (flags & MORE_COMPONENTS) != 0;
Some((glyph_index, z))
Expand Down Expand Up @@ -924,6 +940,55 @@ impl<'a> Font<'a> {
None
}
}

/// The number of glyphs in the font.
///
/// Limited to 16 bits due to limitations in OpenType.
pub fn num_glyphs(&self) -> u16 {
self.maxp.num_glyphs()
}

#[cfg(feature = "kurbo")]
pub fn get_glyph_path(&self, glyph_ix: u16) -> Option<BezPath> {
let _ = self.get_glyph(glyph_ix)?;
let affine = Default::default();
let mut bp = BezPath::new();
self.append_glyph_path(glyph_ix, &affine, &mut bp);
Some(bp)
}

#[cfg(feature = "kurbo")]
fn append_glyph_path(&self, glyph_ix: u16, z: &Affine, bp: &mut BezPath) {
if let Some(glyph) = self.get_glyph(glyph_ix) {
match glyph {
Glyph::Simple(s) => {
let mut p = s.points();
for n in s.contour_sizes() {
append_kurbo_path(bp, z, &mut path_from_pts(p.by_ref().take(n)));
}
}
Glyph::Compound(c) => {
for (glyph_ix, affine) in c.components() {
let concat = Affine::concat(z, &affine);
self.append_glyph_path(glyph_ix, &concat, bp);
}
}
Glyph::Empty => (),
}
}
}
}

#[cfg(feature = "kurbo")]
fn append_kurbo_path<I: Iterator<Item=PathOp>>(bp: &mut BezPath, z: &Affine, path: &mut I) {
for op in path {
match op {
MoveTo(p) => bp.move_to(z * p),
LineTo(p) => bp.line_to(z * p),
QuadTo(p1, p2) => bp.quad_to(z * p1, z * p2),
}
}
bp.close_path()
}

#[derive(Debug)]
Expand Down
23 changes: 23 additions & 0 deletions src/geom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ impl Point {
}
}

#[cfg(feature = "kurbo")]
impl From<Point> for kurbo::Point {
fn from(pt: Point) -> kurbo::Point {
kurbo::Point::new(pt.x as f64, pt.y as f64)
}
}

impl Debug for Point {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "({}, {})", self.x, self.y)
Expand All @@ -57,8 +64,16 @@ pub struct Affine {
f: f32,
}

impl Default for Affine {
fn default() -> Affine {
Affine { a: 1.0, b: 0.0, c: 0.0, d: 1.0, e: 0.0, f: 0.0 }
}
}

impl Affine {
/// Concatenate two affine transforms.
///
/// TODO: deprecate use of this in favor of the multiply op.
pub fn concat(t1: &Affine, t2: &Affine) -> Affine {
Affine {
a: t1.a * t2.a + t1.c * t2.b,
Expand All @@ -78,4 +93,12 @@ pub fn affine_pt(z: &Affine, p: &Point) -> Point {
}
}

impl<'a> std::ops::Mul<Point> for &'a Affine {
type Output = Point;

fn mul(self, rhs: Point) -> Point {
affine_pt(self, &rhs)
}
}

gen_new!(Affine, a: f32, b: f32, c: f32, d: f32, e: f32, f: f32);
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

//! A very high performance font renderer.

#[cfg(feature = "kurbo")]
extern crate kurbo;

#[macro_use]
pub mod macros;
pub mod accumulate;
Expand Down