Add arc building methods and switch the Moiré demo to use them.
Also, stop taking points by reference in many methods, for consistency.
This commit is contained in:
parent
55be787ffd
commit
f24d93819b
|
@ -180,6 +180,7 @@ dependencies = [
|
|||
"pathfinder_gl 0.1.0",
|
||||
"pathfinder_gpu 0.1.0",
|
||||
"pathfinder_renderer 0.1.0",
|
||||
"pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
|
|
@ -97,7 +97,7 @@ impl CanvasRenderingContext2D {
|
|||
drop(self.scene.push_text(string,
|
||||
&TextStyle { size: self.current_state.font_size },
|
||||
&self.current_state.font_collection,
|
||||
&Transform2DF32::from_translation(&position),
|
||||
&Transform2DF32::from_translation(position),
|
||||
TextRenderMode::Fill,
|
||||
HintingOptions::None,
|
||||
paint_id));
|
||||
|
@ -109,7 +109,7 @@ impl CanvasRenderingContext2D {
|
|||
drop(self.scene.push_text(string,
|
||||
&TextStyle { size: self.current_state.font_size },
|
||||
&self.current_state.font_collection,
|
||||
&Transform2DF32::from_translation(&position),
|
||||
&Transform2DF32::from_translation(position),
|
||||
TextRenderMode::Stroke(self.current_state.line_width),
|
||||
HintingOptions::None,
|
||||
paint_id));
|
||||
|
@ -196,7 +196,7 @@ pub struct Path2D {
|
|||
current_contour: Contour,
|
||||
}
|
||||
|
||||
// TODO(pcwalton): `arc`, `ellipse`
|
||||
// TODO(pcwalton): `ellipse`
|
||||
impl Path2D {
|
||||
#[inline]
|
||||
pub fn new() -> Path2D {
|
||||
|
@ -230,6 +230,11 @@ impl Path2D {
|
|||
self.current_contour.push_cubic(ctrl0, ctrl1, to);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn arc(&mut self, center: Point2DF32, radius: f32, start_angle: f32, end_angle: f32) {
|
||||
self.current_contour.push_arc(center, radius, start_angle, end_angle);
|
||||
}
|
||||
|
||||
pub fn rect(&mut self, rect: RectF32) {
|
||||
self.flush_current_contour();
|
||||
self.current_contour.push_endpoint(rect.origin());
|
||||
|
|
|
@ -6,6 +6,7 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
gl = "0.6"
|
||||
pretty_env_logger = "0.3"
|
||||
sdl2 = "0.32"
|
||||
sdl2-sys = "0.32"
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ use pathfinder_renderer::options::RenderOptions;
|
|||
use sdl2::event::Event;
|
||||
use sdl2::keyboard::Keycode;
|
||||
use sdl2::video::GLProfile;
|
||||
use std::f32::consts::PI;
|
||||
use std::f32;
|
||||
|
||||
const VELOCITY: f32 = 0.02;
|
||||
|
@ -36,6 +37,8 @@ const CIRCLE_THICKNESS: f32 = 16.0;
|
|||
const COLOR_CYCLE_SPEED: f32 = 0.0025;
|
||||
|
||||
fn main() {
|
||||
pretty_env_logger::init();
|
||||
|
||||
// Set up SDL2.
|
||||
let sdl_context = sdl2::init().unwrap();
|
||||
let video = sdl_context.video().unwrap();
|
||||
|
@ -150,27 +153,14 @@ impl MoireRenderer {
|
|||
}
|
||||
|
||||
fn draw_circles(&self, canvas: &mut CanvasRenderingContext2D, center: Point2DF32) {
|
||||
let center = center.scale(self.device_pixel_ratio);
|
||||
for index in 0..CIRCLE_COUNT {
|
||||
let radius = (index + 1) as f32 * CIRCLE_SPACING * self.device_pixel_ratio;
|
||||
let mut path = Path2D::new();
|
||||
self.add_circle_subpath(&mut path,
|
||||
center.scale(self.device_pixel_ratio),
|
||||
index as f32 * CIRCLE_SPACING * self.device_pixel_ratio);
|
||||
path.arc(center, radius, 0.0, PI * 2.0);
|
||||
canvas.stroke_path(path);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_circle_subpath(&self, path: &mut Path2D, center: Point2DF32, radius: f32) {
|
||||
path.move_to(center + Point2DF32::new(0.0, -radius));
|
||||
path.quadratic_curve_to(center + Point2DF32::new(radius, -radius),
|
||||
center + Point2DF32::new(radius, 0.0));
|
||||
path.quadratic_curve_to(center + Point2DF32::new(radius, radius),
|
||||
center + Point2DF32::new(0.0, radius));
|
||||
path.quadratic_curve_to(center + Point2DF32::new(-radius, radius),
|
||||
center + Point2DF32::new(-radius, 0.0));
|
||||
path.quadratic_curve_to(center + Point2DF32::new(-radius, -radius),
|
||||
center + Point2DF32::new(0.0, -radius));
|
||||
path.close_path();
|
||||
}
|
||||
}
|
||||
|
||||
struct ColorGradient([ColorF; 5]);
|
||||
|
|
|
@ -20,7 +20,7 @@ pub struct LineSegmentF32(pub F32x4);
|
|||
|
||||
impl LineSegmentF32 {
|
||||
#[inline]
|
||||
pub fn new(from: &Point2DF32, to: &Point2DF32) -> LineSegmentF32 {
|
||||
pub fn new(from: Point2DF32, to: Point2DF32) -> LineSegmentF32 {
|
||||
LineSegmentF32(from.0.concat_xy_xy(to.0))
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
//! 2D affine transforms.
|
||||
|
||||
use crate::basic::line_segment::LineSegmentF32;
|
||||
use crate::basic::point::Point2DF32;
|
||||
use crate::basic::rect::RectF32;
|
||||
use crate::basic::transform3d::Transform3DF32;
|
||||
|
@ -24,13 +25,13 @@ pub struct Matrix2x2F32(pub F32x4);
|
|||
impl Default for Matrix2x2F32 {
|
||||
#[inline]
|
||||
fn default() -> Matrix2x2F32 {
|
||||
Self::from_scale(&Point2DF32::splat(1.0))
|
||||
Self::from_scale(Point2DF32::splat(1.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Matrix2x2F32 {
|
||||
#[inline]
|
||||
pub fn from_scale(scale: &Point2DF32) -> Matrix2x2F32 {
|
||||
pub fn from_scale(scale: Point2DF32) -> Matrix2x2F32 {
|
||||
Matrix2x2F32(F32x4::new(scale.x(), 0.0, 0.0, scale.y()))
|
||||
}
|
||||
|
||||
|
@ -66,7 +67,7 @@ impl Matrix2x2F32 {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn transform_point(&self, point: &Point2DF32) -> Point2DF32 {
|
||||
pub fn transform_point(&self, point: Point2DF32) -> Point2DF32 {
|
||||
let halves = self.0 * point.0.xxyy();
|
||||
Point2DF32(halves + halves.zwzw())
|
||||
}
|
||||
|
@ -118,13 +119,13 @@ pub struct Transform2DF32 {
|
|||
impl Default for Transform2DF32 {
|
||||
#[inline]
|
||||
fn default() -> Transform2DF32 {
|
||||
Self::from_scale(&Point2DF32::splat(1.0))
|
||||
Self::from_scale(Point2DF32::splat(1.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Transform2DF32 {
|
||||
#[inline]
|
||||
pub fn from_scale(scale: &Point2DF32) -> Transform2DF32 {
|
||||
pub fn from_scale(scale: Point2DF32) -> Transform2DF32 {
|
||||
Transform2DF32 {
|
||||
matrix: Matrix2x2F32::from_scale(scale),
|
||||
vector: Point2DF32::default(),
|
||||
|
@ -140,11 +141,8 @@ impl Transform2DF32 {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_translation(vector: &Point2DF32) -> Transform2DF32 {
|
||||
Transform2DF32 {
|
||||
matrix: Matrix2x2F32::default(),
|
||||
vector: *vector,
|
||||
}
|
||||
pub fn from_translation(vector: Point2DF32) -> Transform2DF32 {
|
||||
Transform2DF32 { matrix: Matrix2x2F32::default(), vector }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -154,10 +152,8 @@ impl Transform2DF32 {
|
|||
translation: Point2DF32,
|
||||
) -> Transform2DF32 {
|
||||
let rotation = Transform2DF32::from_rotation(theta);
|
||||
let translation = Transform2DF32::from_translation(&translation);
|
||||
Transform2DF32::from_scale(&scale)
|
||||
.post_mul(&rotation)
|
||||
.post_mul(&translation)
|
||||
let translation = Transform2DF32::from_translation(translation);
|
||||
Transform2DF32::from_scale(scale).post_mul(&rotation).post_mul(&translation)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -169,16 +165,22 @@ impl Transform2DF32 {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn transform_point(&self, point: &Point2DF32) -> Point2DF32 {
|
||||
pub fn transform_point(&self, point: Point2DF32) -> Point2DF32 {
|
||||
self.matrix.transform_point(point) + self.vector
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn transform_line_segment(&self, line_segment: &LineSegmentF32) -> LineSegmentF32 {
|
||||
LineSegmentF32::new(self.transform_point(line_segment.from()),
|
||||
self.transform_point(line_segment.to()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn transform_rect(&self, rect: &RectF32) -> RectF32 {
|
||||
let upper_left = self.transform_point(&rect.origin());
|
||||
let upper_right = self.transform_point(&rect.upper_right());
|
||||
let lower_left = self.transform_point(&rect.lower_left());
|
||||
let lower_right = self.transform_point(&rect.lower_right());
|
||||
let upper_left = self.transform_point(rect.origin());
|
||||
let upper_right = self.transform_point(rect.upper_right());
|
||||
let lower_left = self.transform_point(rect.lower_left());
|
||||
let lower_right = self.transform_point(rect.lower_right());
|
||||
let min_point = upper_left.min(upper_right).min(lower_left).min(lower_right);
|
||||
let max_point = upper_left.max(upper_right).max(lower_left).max(lower_right);
|
||||
RectF32::from_points(min_point, max_point)
|
||||
|
@ -187,7 +189,7 @@ impl Transform2DF32 {
|
|||
#[inline]
|
||||
pub fn post_mul(&self, other: &Transform2DF32) -> Transform2DF32 {
|
||||
let matrix = self.matrix.post_mul(&other.matrix);
|
||||
let vector = other.transform_point(&self.vector);
|
||||
let vector = other.transform_point(self.vector);
|
||||
Transform2DF32 { matrix, vector }
|
||||
}
|
||||
|
||||
|
@ -243,7 +245,7 @@ impl Transform2DF32 {
|
|||
|
||||
#[inline]
|
||||
pub fn post_translate(&self, vector: Point2DF32) -> Transform2DF32 {
|
||||
self.post_mul(&Transform2DF32::from_translation(&vector))
|
||||
self.post_mul(&Transform2DF32::from_translation(vector))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -253,7 +255,7 @@ impl Transform2DF32 {
|
|||
|
||||
#[inline]
|
||||
pub fn post_scale(&self, scale: Point2DF32) -> Transform2DF32 {
|
||||
self.post_mul(&Transform2DF32::from_scale(&scale))
|
||||
self.post_mul(&Transform2DF32::from_scale(scale))
|
||||
}
|
||||
|
||||
/// Returns the translation part of this matrix.
|
||||
|
@ -303,18 +305,18 @@ where
|
|||
if !segment.is_none() {
|
||||
segment
|
||||
.baseline
|
||||
.set_from(&self.transform.transform_point(&segment.baseline.from()));
|
||||
.set_from(&self.transform.transform_point(segment.baseline.from()));
|
||||
segment
|
||||
.baseline
|
||||
.set_to(&self.transform.transform_point(&segment.baseline.to()));
|
||||
.set_to(&self.transform.transform_point(segment.baseline.to()));
|
||||
if !segment.is_line() {
|
||||
segment
|
||||
.ctrl
|
||||
.set_from(&self.transform.transform_point(&segment.ctrl.from()));
|
||||
.set_from(&self.transform.transform_point(segment.ctrl.from()));
|
||||
if !segment.is_quadratic() {
|
||||
segment
|
||||
.ctrl
|
||||
.set_to(&self.transform.transform_point(&segment.ctrl.to()));
|
||||
.set_to(&self.transform.transform_point(segment.ctrl.to()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -325,7 +325,7 @@ impl ContourPolygonClipper {
|
|||
Some(prev) => *prev,
|
||||
};
|
||||
for &next in &clip_polygon {
|
||||
self.clip_against(Edge(LineSegmentF32::new(&prev, &next)));
|
||||
self.clip_against(Edge(LineSegmentF32::new(prev, next)));
|
||||
prev = next;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ use crate::clip::{self, ContourPolygonClipper, ContourRectClipper};
|
|||
use crate::dilation::ContourDilator;
|
||||
use crate::orientation::Orientation;
|
||||
use crate::segment::{Segment, SegmentFlags, SegmentKind};
|
||||
use std::f32::consts::FRAC_PI_2;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::mem;
|
||||
|
||||
|
@ -292,7 +293,10 @@ impl Contour {
|
|||
|
||||
// TODO(pcwalton): SIMD.
|
||||
#[inline]
|
||||
pub(crate) fn push_point(&mut self, point: Point2DF32, flags: PointFlags, update_bounds: bool) {
|
||||
pub(crate) fn push_point(&mut self,
|
||||
point: Point2DF32,
|
||||
flags: PointFlags,
|
||||
update_bounds: bool) {
|
||||
debug_assert!(!point.x().is_nan() && !point.y().is_nan());
|
||||
|
||||
if update_bounds {
|
||||
|
@ -354,6 +358,37 @@ impl Contour {
|
|||
self.push_point(segment.baseline.to(), PointFlags::empty(), update_bounds);
|
||||
}
|
||||
|
||||
pub fn push_arc(&mut self, center: Point2DF32, radius: f32, start_angle: f32, end_angle: f32) {
|
||||
let scale = Transform2DF32::from_scale(Point2DF32::splat(radius));
|
||||
let translation = Transform2DF32::from_translation(center);
|
||||
|
||||
let (mut angle, mut first_segment) = (start_angle, true);
|
||||
while angle < end_angle {
|
||||
let sweep_angle = f32::min(FRAC_PI_2, end_angle - angle);
|
||||
let mut segment = Segment::arc(sweep_angle);
|
||||
let rotation = Transform2DF32::from_rotation(angle);
|
||||
segment = segment.transform(&scale.post_mul(&rotation).post_mul(&translation));
|
||||
|
||||
/*
|
||||
println!("angle={} start_angle={} end_angle={} sweep_angle={} segment={:?}",
|
||||
angle,
|
||||
start_angle,
|
||||
end_angle,
|
||||
sweep_angle,
|
||||
segment);
|
||||
*/
|
||||
|
||||
if first_segment {
|
||||
self.push_full_segment(&segment, true);
|
||||
first_segment = false;
|
||||
} else {
|
||||
self.push_segment(segment, true);
|
||||
}
|
||||
|
||||
angle += sweep_angle;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn segment_after(&self, point_index: u32) -> Segment {
|
||||
debug_assert!(self.point_is_endpoint(point_index));
|
||||
|
@ -388,8 +423,8 @@ impl Contour {
|
|||
pub fn hull_segment_after(&self, prev_point_index: u32) -> LineSegmentF32 {
|
||||
let next_point_index = self.next_point_index_of(prev_point_index);
|
||||
LineSegmentF32::new(
|
||||
&self.points[prev_point_index as usize],
|
||||
&self.points[next_point_index as usize],
|
||||
self.points[prev_point_index as usize],
|
||||
self.points[next_point_index as usize],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -455,7 +490,7 @@ impl Contour {
|
|||
|
||||
pub fn transform(&mut self, transform: &Transform2DF32) {
|
||||
for (point_index, point) in self.points.iter_mut().enumerate() {
|
||||
*point = transform.transform_point(point);
|
||||
*point = transform.transform_point(*point);
|
||||
union_rect(&mut self.bounds, *point, point_index == 0);
|
||||
}
|
||||
}
|
||||
|
@ -522,8 +557,8 @@ impl Contour {
|
|||
point_index
|
||||
};
|
||||
let baseline = LineSegmentF32::new(
|
||||
&contour.points[last_endpoint_index as usize],
|
||||
&contour.points[position_index as usize],
|
||||
contour.points[last_endpoint_index as usize],
|
||||
contour.points[position_index as usize],
|
||||
);
|
||||
let point_count = point_index - last_endpoint_index + 1;
|
||||
if point_count == 3 {
|
||||
|
@ -531,13 +566,13 @@ impl Contour {
|
|||
let ctrl_position = &contour.points[ctrl_point_index];
|
||||
handle_cubic(
|
||||
self,
|
||||
Segment::quadratic(&baseline, &ctrl_position).to_cubic(),
|
||||
Segment::quadratic(&baseline, *ctrl_position).to_cubic(),
|
||||
);
|
||||
} else if point_count == 4 {
|
||||
let first_ctrl_point_index = last_endpoint_index as usize + 1;
|
||||
let ctrl_position_0 = &contour.points[first_ctrl_point_index + 0];
|
||||
let ctrl_position_1 = &contour.points[first_ctrl_point_index + 1];
|
||||
let ctrl = LineSegmentF32::new(&ctrl_position_0, &ctrl_position_1);
|
||||
let ctrl = LineSegmentF32::new(*ctrl_position_0, *ctrl_position_1);
|
||||
handle_cubic(self, Segment::cubic(&baseline, &ctrl));
|
||||
}
|
||||
|
||||
|
@ -723,24 +758,21 @@ impl<'a> Iterator for ContourIter<'a> {
|
|||
if self.index == contour.len() {
|
||||
let point1 = contour.position_of(0);
|
||||
self.index += 1;
|
||||
return Some(Segment::line(&LineSegmentF32::new(&point0, &point1)));
|
||||
return Some(Segment::line(&LineSegmentF32::new(point0, point1)));
|
||||
}
|
||||
|
||||
let point1_index = self.index;
|
||||
self.index += 1;
|
||||
let point1 = contour.position_of(point1_index);
|
||||
if contour.point_is_endpoint(point1_index) {
|
||||
return Some(Segment::line(&LineSegmentF32::new(&point0, &point1)));
|
||||
return Some(Segment::line(&LineSegmentF32::new(point0, point1)));
|
||||
}
|
||||
|
||||
let point2_index = self.index;
|
||||
let point2 = contour.position_of(point2_index);
|
||||
self.index += 1;
|
||||
if contour.point_is_endpoint(point2_index) {
|
||||
return Some(Segment::quadratic(
|
||||
&LineSegmentF32::new(&point0, &point2),
|
||||
&point1,
|
||||
));
|
||||
return Some(Segment::quadratic(&LineSegmentF32::new(point0, point2), point1));
|
||||
}
|
||||
|
||||
let point3_index = self.index;
|
||||
|
@ -748,8 +780,8 @@ impl<'a> Iterator for ContourIter<'a> {
|
|||
self.index += 1;
|
||||
debug_assert!(contour.point_is_endpoint(point3_index));
|
||||
return Some(Segment::cubic(
|
||||
&LineSegmentF32::new(&point0, &point3),
|
||||
&LineSegmentF32::new(&point1, &point2),
|
||||
&LineSegmentF32::new(point0, point3),
|
||||
&LineSegmentF32::new(point1, point2),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
|
||||
use crate::basic::line_segment::LineSegmentF32;
|
||||
use crate::basic::point::Point2DF32;
|
||||
use crate::basic::transform2d::Transform2DF32;
|
||||
use crate::util::{self, EPSILON};
|
||||
use pathfinder_simd::default::F32x4;
|
||||
use std::f32::consts::SQRT_2;
|
||||
|
||||
const MAX_NEWTON_ITERATIONS: u32 = 32;
|
||||
|
||||
|
@ -47,10 +49,10 @@ impl Segment {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn quadratic(baseline: &LineSegmentF32, ctrl: &Point2DF32) -> Segment {
|
||||
pub fn quadratic(baseline: &LineSegmentF32, ctrl: Point2DF32) -> Segment {
|
||||
Segment {
|
||||
baseline: *baseline,
|
||||
ctrl: LineSegmentF32::new(ctrl, &Point2DF32::default()),
|
||||
ctrl: LineSegmentF32::new(ctrl, Point2DF32::default()),
|
||||
kind: SegmentKind::Quadratic,
|
||||
flags: SegmentFlags::empty(),
|
||||
}
|
||||
|
@ -66,6 +68,24 @@ impl Segment {
|
|||
}
|
||||
}
|
||||
|
||||
/// Approximates an unit-length arc with a cubic Bézier curve.
|
||||
///
|
||||
/// The maximum supported `sweep_angle` is π/2 (i.e. 90°).
|
||||
pub fn arc(sweep_angle: f32) -> Segment {
|
||||
// Aleksas Riškus, "Approximation of a Cubic Bézier Curve by Circular Arcs and Vice Versa"
|
||||
// 2006.
|
||||
//
|
||||
// https://pdfs.semanticscholar.org/1639/0db1a470bd13fe428e0896671a9a5745070a.pdf
|
||||
let phi = 0.5 * sweep_angle;
|
||||
let p0 = Point2DF32::new(f32::cos(phi), f32::sin(phi));
|
||||
let p3 = p0.scale_xy(Point2DF32::new(1.0, -1.0));
|
||||
let p1 = p0 - p3.yx().scale(K);
|
||||
let p2 = p3 + p0.yx().scale(K);
|
||||
return Segment::cubic(&LineSegmentF32::new(p3, p0), &LineSegmentF32::new(p2, p1));
|
||||
|
||||
const K: f32 = 4.0 / 3.0 * (SQRT_2 - 1.0);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_line_segment(&self) -> LineSegmentF32 {
|
||||
debug_assert!(self.is_line());
|
||||
|
@ -109,7 +129,7 @@ impl Segment {
|
|||
let mut new_segment = *self;
|
||||
let p1_2 = self.ctrl.from() + self.ctrl.from();
|
||||
new_segment.ctrl =
|
||||
LineSegmentF32::new(&(self.baseline.from() + p1_2), &(p1_2 + self.baseline.to()))
|
||||
LineSegmentF32::new(self.baseline.from() + p1_2, p1_2 + self.baseline.to())
|
||||
.scale(1.0 / 3.0);
|
||||
new_segment.kind = SegmentKind::Cubic;
|
||||
new_segment
|
||||
|
@ -176,6 +196,16 @@ impl Segment {
|
|||
self.to_cubic().as_cubic_segment().sample(t)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn transform(self, transform: &Transform2DF32) -> Segment {
|
||||
Segment {
|
||||
baseline: transform.transform_line_segment(&self.baseline),
|
||||
ctrl: transform.transform_line_segment(&self.ctrl),
|
||||
kind: self.kind,
|
||||
flags: self.flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
|
@ -215,16 +245,16 @@ impl<'s> CubicSegment<'s> {
|
|||
let (baseline0, ctrl0, baseline1, ctrl1);
|
||||
if t <= 0.0 {
|
||||
let from = &self.0.baseline.from();
|
||||
baseline0 = LineSegmentF32::new(from, from);
|
||||
ctrl0 = LineSegmentF32::new(from, from);
|
||||
baseline0 = LineSegmentF32::new(*from, *from);
|
||||
ctrl0 = LineSegmentF32::new(*from, *from);
|
||||
baseline1 = self.0.baseline;
|
||||
ctrl1 = self.0.ctrl;
|
||||
} else if t >= 1.0 {
|
||||
let to = &self.0.baseline.to();
|
||||
baseline0 = self.0.baseline;
|
||||
ctrl0 = self.0.ctrl;
|
||||
baseline1 = LineSegmentF32::new(to, to);
|
||||
ctrl1 = LineSegmentF32::new(to, to);
|
||||
baseline1 = LineSegmentF32::new(*to, *to);
|
||||
ctrl1 = LineSegmentF32::new(*to, *to);
|
||||
} else {
|
||||
let tttt = F32x4::splat(t);
|
||||
|
||||
|
|
|
@ -118,51 +118,51 @@ impl Offset for Segment {
|
|||
}
|
||||
|
||||
if self.is_quadratic() {
|
||||
let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.from());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.baseline.to());
|
||||
let mut segment_0 = LineSegmentF32::new(self.baseline.from(), self.ctrl.from());
|
||||
let mut segment_1 = LineSegmentF32::new(self.ctrl.from(), self.baseline.to());
|
||||
segment_0 = segment_0.offset(distance);
|
||||
segment_1 = segment_1.offset(distance);
|
||||
let ctrl = match segment_0.intersection_t(&segment_1) {
|
||||
Some(t) => segment_0.sample(t),
|
||||
None => segment_0.to().lerp(segment_1.from(), 0.5),
|
||||
};
|
||||
let baseline = LineSegmentF32::new(&segment_0.from(), &segment_1.to());
|
||||
return Segment::quadratic(&baseline, &ctrl);
|
||||
let baseline = LineSegmentF32::new(segment_0.from(), segment_1.to());
|
||||
return Segment::quadratic(&baseline, ctrl);
|
||||
}
|
||||
|
||||
debug_assert!(self.is_cubic());
|
||||
|
||||
if self.baseline.from() == self.ctrl.from() {
|
||||
let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.to());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.to(), &self.baseline.to());
|
||||
let mut segment_0 = LineSegmentF32::new(self.baseline.from(), self.ctrl.to());
|
||||
let mut segment_1 = LineSegmentF32::new(self.ctrl.to(), self.baseline.to());
|
||||
segment_0 = segment_0.offset(distance);
|
||||
segment_1 = segment_1.offset(distance);
|
||||
let ctrl = match segment_0.intersection_t(&segment_1) {
|
||||
Some(t) => segment_0.sample(t),
|
||||
None => segment_0.to().lerp(segment_1.from(), 0.5),
|
||||
};
|
||||
let baseline = LineSegmentF32::new(&segment_0.from(), &segment_1.to());
|
||||
let ctrl = LineSegmentF32::new(&segment_0.from(), &ctrl);
|
||||
let baseline = LineSegmentF32::new(segment_0.from(), segment_1.to());
|
||||
let ctrl = LineSegmentF32::new(segment_0.from(), ctrl);
|
||||
return Segment::cubic(&baseline, &ctrl);
|
||||
}
|
||||
|
||||
if self.ctrl.to() == self.baseline.to() {
|
||||
let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.from());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.baseline.to());
|
||||
let mut segment_0 = LineSegmentF32::new(self.baseline.from(), self.ctrl.from());
|
||||
let mut segment_1 = LineSegmentF32::new(self.ctrl.from(), self.baseline.to());
|
||||
segment_0 = segment_0.offset(distance);
|
||||
segment_1 = segment_1.offset(distance);
|
||||
let ctrl = match segment_0.intersection_t(&segment_1) {
|
||||
Some(t) => segment_0.sample(t),
|
||||
None => segment_0.to().lerp(segment_1.from(), 0.5),
|
||||
};
|
||||
let baseline = LineSegmentF32::new(&segment_0.from(), &segment_1.to());
|
||||
let ctrl = LineSegmentF32::new(&ctrl, &segment_1.to());
|
||||
let baseline = LineSegmentF32::new(segment_0.from(), segment_1.to());
|
||||
let ctrl = LineSegmentF32::new(ctrl, segment_1.to());
|
||||
return Segment::cubic(&baseline, &ctrl);
|
||||
}
|
||||
|
||||
let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.from());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.ctrl.to());
|
||||
let mut segment_2 = LineSegmentF32::new(&self.ctrl.to(), &self.baseline.to());
|
||||
let mut segment_0 = LineSegmentF32::new(self.baseline.from(), self.ctrl.from());
|
||||
let mut segment_1 = LineSegmentF32::new(self.ctrl.from(), self.ctrl.to());
|
||||
let mut segment_2 = LineSegmentF32::new(self.ctrl.to(), self.baseline.to());
|
||||
segment_0 = segment_0.offset(distance);
|
||||
segment_1 = segment_1.offset(distance);
|
||||
segment_2 = segment_2.offset(distance);
|
||||
|
@ -176,8 +176,8 @@ impl Offset for Segment {
|
|||
segment_1.to().lerp(segment_2.from(), 0.5),
|
||||
),
|
||||
};
|
||||
let baseline = LineSegmentF32::new(&segment_0.from(), &segment_2.to());
|
||||
let ctrl = LineSegmentF32::new(&ctrl_0, &ctrl_1);
|
||||
let baseline = LineSegmentF32::new(segment_0.from(), segment_2.to());
|
||||
let ctrl = LineSegmentF32::new(ctrl_0, ctrl_1);
|
||||
Segment::cubic(&baseline, &ctrl)
|
||||
}
|
||||
|
||||
|
|
|
@ -236,9 +236,9 @@ impl BuiltObject {
|
|||
let right = Point2DF32::new(right, tile_origin_y);
|
||||
|
||||
let segment = if winding < 0 {
|
||||
LineSegmentF32::new(&left, &right)
|
||||
LineSegmentF32::new(left, right)
|
||||
} else {
|
||||
LineSegmentF32::new(&right, &left)
|
||||
LineSegmentF32::new(right, left)
|
||||
};
|
||||
|
||||
debug!(
|
||||
|
@ -300,14 +300,14 @@ impl BuiltObject {
|
|||
let point = Point2DF32::new(x, segment.solve_y_for_x(x));
|
||||
if !winding {
|
||||
fill_to = point;
|
||||
segment = LineSegmentF32::new(&point, &segment.to());
|
||||
segment = LineSegmentF32::new(point, segment.to());
|
||||
} else {
|
||||
fill_from = point;
|
||||
segment = LineSegmentF32::new(&segment.from(), &point);
|
||||
segment = LineSegmentF32::new(segment.from(), point);
|
||||
}
|
||||
}
|
||||
|
||||
let fill_segment = LineSegmentF32::new(&fill_from, &fill_to);
|
||||
let fill_segment = LineSegmentF32::new(fill_from, fill_to);
|
||||
let fill_tile_coords = Point2DI32::new(subsegment_tile_x, tile_y);
|
||||
self.add_fill(builder, &fill_segment, fill_tile_coords);
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ impl Scene {
|
|||
};
|
||||
if options.subpixel_aa_enabled {
|
||||
transform = transform
|
||||
.post_mul(&Transform2DF32::from_scale(&Point2DF32::new(3.0, 1.0)))
|
||||
.post_mul(&Transform2DF32::from_scale(Point2DF32::new(3.0, 1.0)))
|
||||
}
|
||||
outline.transform(&transform);
|
||||
}
|
||||
|
|
|
@ -434,8 +434,7 @@ impl ActiveEdge {
|
|||
// If necessary, draw initial line.
|
||||
if self.crossing.y() < segment.baseline.min_y() {
|
||||
let first_line_segment =
|
||||
LineSegmentF32::new(&self.crossing, &segment.baseline.upper_point())
|
||||
.orient(winding);
|
||||
LineSegmentF32::new(self.crossing, segment.baseline.upper_point()).orient(winding);
|
||||
if self
|
||||
.process_line_segment(&first_line_segment, builder, built_object, tile_y)
|
||||
.is_some()
|
||||
|
|
|
@ -93,7 +93,7 @@ impl SceneExt for Scene {
|
|||
let scale = style.size / (font.metrics().units_per_em as f32);
|
||||
let scale = Point2DF32::new(scale, -scale);
|
||||
let transform =
|
||||
Transform2DF32::from_scale(&scale).post_mul(transform).post_translate(offset);
|
||||
Transform2DF32::from_scale(scale).post_mul(transform).post_translate(offset);
|
||||
self.push_glyph(font,
|
||||
glyph.glyph_id,
|
||||
&transform,
|
||||
|
@ -147,7 +147,7 @@ impl OutlinePathBuilder {
|
|||
}
|
||||
|
||||
fn convert_point(&self, point: Point2D<f32>) -> Point2DF32 {
|
||||
self.transform.transform_point(&Point2DF32::new(point.x, point.y))
|
||||
self.transform.transform_point(Point2DF32::new(point.x, point.y))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue