Use the Citardauq Formula in the partitioner as well as the shader to avoid precision problems.
Addresses the issue with the Nimbus Sans "o" mentioned in #24.
This commit is contained in:
parent
632202e5eb
commit
444e7bbf96
|
@ -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() {
|
||||
|
|
|
@ -7,7 +7,9 @@ authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
|||
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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<f32>, p1: &Point2D<f32>, p2:
|
|||
p0.lerp(*p1, t).lerp(p1.lerp(*p2, t), t)
|
||||
}
|
||||
|
||||
pub fn sample_quadratic_bezier_deriv(t: f32,
|
||||
p0: &Point2D<f32>,
|
||||
p1: &Point2D<f32>,
|
||||
p2: &Point2D<f32>)
|
||||
-> Vector2D<f32> {
|
||||
// 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<f32>, p1: &Point2D<f32>, p2: &Point2D<f32>)
|
||||
-> Vector2D<f32> {
|
||||
// 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<f32>, b: &Point2D<f32>) -> f32 {
|
||||
if b.x == a.x {
|
||||
0.0
|
||||
|
@ -109,28 +98,22 @@ pub fn solve_line_t_for_x(x: f32, a: &Point2D<f32>, b: &Point2D<f32>) -> f32 {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn newton_raphson<F, DFDX>(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<f32>,
|
||||
p1: &Point2D<f32>,
|
||||
p2: &Point2D<f32>)
|
||||
-> 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,
|
||||
|
|
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(alloc_jemalloc)]
|
||||
|
||||
|
|
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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) |
|
||||
|
|
Loading…
Reference in New Issue