diff --git a/demo/client/src/mesh-debugger.ts b/demo/client/src/mesh-debugger.ts index 2a8d1ded..c8aec258 100644 --- a/demo/client/src/mesh-debugger.ts +++ b/demo/client/src/mesh-debugger.ts @@ -20,13 +20,13 @@ import {BUILTIN_FONT_URI, GlyphStorage, PathfinderGlyph} from "./text"; import { unwrapNull, UINT32_SIZE, UINT32_MAX } from "./utils"; import {PathfinderView} from "./view"; -const CHARACTER: string = 'o'; +const CHARACTER: string = 'r'; -const FONT: string = 'nimbus-sans'; +const FONT: string = 'eb-garamond'; -const POINT_LABEL_FONT: string = "36px sans-serif"; +const POINT_LABEL_FONT: string = "12px sans-serif"; const POINT_LABEL_OFFSET: glmatrix.vec2 = glmatrix.vec2.fromValues(12.0, 12.0); -const POINT_RADIUS: number = 6.0; +const POINT_RADIUS: number = 2.0; class MeshDebuggerAppController extends AppController { start() { diff --git a/demo/server/Cargo.toml b/demo/server/Cargo.toml index e40ae375..9237f709 100644 --- a/demo/server/Cargo.toml +++ b/demo/server/Cargo.toml @@ -7,7 +7,9 @@ authors = ["Patrick Walton "] app_units = "0.5" base64 = "0.6" bincode = "0.8" +env_logger = "0.3" euclid = "0.15" +log = "0.3" rocket = "0.3" rocket_codegen = "0.3" rocket_contrib = "0.3" diff --git a/demo/server/src/main.rs b/demo/server/src/main.rs index 0020533b..293edd14 100644 --- a/demo/server/src/main.rs +++ b/demo/server/src/main.rs @@ -8,6 +8,7 @@ extern crate app_units; extern crate base64; extern crate bincode; +extern crate env_logger; extern crate euclid; extern crate fontsan; extern crate pathfinder_font_renderer; @@ -615,6 +616,8 @@ impl<'a> Responder<'a> for Shader { } fn main() { + drop(env_logger::init()); + rocket::ignite().mount("/", routes![ partition_font, partition_svg_paths, diff --git a/partitioner/src/geometry.rs b/partitioner/src/geometry.rs index e10258fc..2c2fe998 100644 --- a/partitioner/src/geometry.rs +++ b/partitioner/src/geometry.rs @@ -1,11 +1,17 @@ -// partitionfinder/geometry.rs +// pathfinder/partitioner/src/geometry.rs +// +// Copyright © 2017 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. use euclid::approxeq::ApproxEq; use euclid::{Point2D, Vector2D}; use std::cmp::Ordering; -const NEWTON_RAPHSON_ITERATIONS: u8 = 8; - pub(crate) trait ApproxOrdered { fn approx_ordered(&self) -> bool; } @@ -84,23 +90,6 @@ pub fn sample_quadratic_bezier(t: f32, p0: &Point2D, p1: &Point2D, p2: p0.lerp(*p1, t).lerp(p1.lerp(*p2, t), t) } -pub fn sample_quadratic_bezier_deriv(t: f32, - p0: &Point2D, - p1: &Point2D, - p2: &Point2D) - -> Vector2D { - // https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Quadratic_B.C3.A9zier_curves - // FIXME(pcwalton): Can this be made faster? - ((*p1 - *p0) * (1.0 - t) + (*p2 - *p1) * t) * 2.0 -} - -pub fn sample_quadratic_bezier_deriv_deriv(p0: &Point2D, p1: &Point2D, p2: &Point2D) - -> Vector2D { - // https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Quadratic_B.C3.A9zier_curves - // FIXME(pcwalton): Can this be made faster? - (*p2 - *p1 * 2.0 + p0.to_vector()) * 2.0 -} - pub fn solve_line_t_for_x(x: f32, a: &Point2D, b: &Point2D) -> f32 { if b.x == a.x { 0.0 @@ -109,28 +98,22 @@ pub fn solve_line_t_for_x(x: f32, a: &Point2D, b: &Point2D) -> f32 { } } -pub(crate) fn newton_raphson(f: F, dfdx: DFDX, mut x_guess: f32) -> f32 - where F: Fn(f32) -> f32, DFDX: Fn(f32) -> f32 { - for _ in 0..NEWTON_RAPHSON_ITERATIONS { - let y = f(x_guess); - if y.approx_eq(&0.0) { - break - } - let yy = dfdx(x_guess); - x_guess -= y / yy - } - x_guess -} - +// Use the Citardauq Formula to avoid precision problems. +// +// https://math.stackexchange.com/a/311397 pub fn solve_quadratic_bezier_t_for_x(x: f32, p0: &Point2D, p1: &Point2D, p2: &Point2D) -> f32 { - // TODO(pcwalton): Use the quadratic equation instead. - newton_raphson(|t| sample_quadratic_bezier(t, p0, p1, p2).x - x, - |t| sample_quadratic_bezier_deriv(t, p0, p1, p2).x, - 0.5) + let (p0x, p1x, p2x, x) = (p0.x as f64, p1.x as f64, p2.x as f64, x as f64); + + let a = p0x - 2.0 * p1x + p2x; + let b = -2.0 * p0x + 2.0 * p1x; + let c = p0x - x; + + let t = 2.0 * c / (-b - (b * b - 4.0 * a * c).sqrt()); + t.max(0.0).min(1.0) as f32 } pub fn solve_quadratic_bezier_y_for_x(x: f32, diff --git a/partitioner/src/lib.rs b/partitioner/src/lib.rs index 699deedd..016b477d 100644 --- a/partitioner/src/lib.rs +++ b/partitioner/src/lib.rs @@ -1,4 +1,12 @@ -// partitionfinder/lib.rs +// pathfinder/partitioner/src/lib.rs +// +// Copyright © 2017 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. #![feature(alloc_jemalloc)] diff --git a/partitioner/src/partitioner.rs b/partitioner/src/partitioner.rs index 2bbc34df..3578d93a 100644 --- a/partitioner/src/partitioner.rs +++ b/partitioner/src/partitioner.rs @@ -1,4 +1,12 @@ -// partitionfinder/partitioner.rs +// pathfinder/partitioner/src/partitioner.rs +// +// Copyright © 2017 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. use bit_vec::BitVec; use euclid::Point2D; @@ -448,8 +456,6 @@ impl<'a> Partitioner<'a> { let upper_curve = self.subdivide_active_edge_at(upper_active_edge_index, right_x); let lower_curve = self.subdivide_active_edge_at(lower_active_edge_index, right_x); - // NB: Order is important here—we depend on the provoking vertex! - let upper_shape = upper_curve.shape(&self.b_vertex_loop_blinn_data); let lower_shape = lower_curve.shape(&self.b_vertex_loop_blinn_data); @@ -482,6 +488,12 @@ impl<'a> Partitioner<'a> { } } + debug!("... emitting B-quad: UL {} BL {} UR {} BR {}", + upper_curve.left_curve_left, + lower_curve.left_curve_left, + upper_curve.middle_point, + lower_curve.middle_point); + match (upper_shape, lower_shape) { (Shape::Flat, Shape::Flat) | (Shape::Flat, Shape::Convex) |