Add the Lyon interoperability to the geometry crate
This commit is contained in:
parent
7f2003988e
commit
77f4f6b188
|
@ -13,6 +13,7 @@
|
||||||
use crate::line_segment::LineSegmentF32;
|
use crate::line_segment::LineSegmentF32;
|
||||||
use crate::point::Point2DF32;
|
use crate::point::Point2DF32;
|
||||||
use crate::simd::F32x4;
|
use crate::simd::F32x4;
|
||||||
|
use lyon_path::PathEvent;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct Segment {
|
pub struct Segment {
|
||||||
|
@ -262,3 +263,156 @@ impl<'s> CubicSegment<'s> {
|
||||||
const EPSILON: f32 = 0.001;
|
const EPSILON: f32 = 0.001;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lyon interoperability
|
||||||
|
|
||||||
|
pub struct PathEventsToSegments<I>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = PathEvent>,
|
||||||
|
{
|
||||||
|
iter: I,
|
||||||
|
first_subpath_point: Point2DF32,
|
||||||
|
last_subpath_point: Point2DF32,
|
||||||
|
just_moved: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> PathEventsToSegments<I>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = PathEvent>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
pub fn new(iter: I) -> PathEventsToSegments<I> {
|
||||||
|
PathEventsToSegments {
|
||||||
|
iter,
|
||||||
|
first_subpath_point: Point2DF32::default(),
|
||||||
|
last_subpath_point: Point2DF32::default(),
|
||||||
|
just_moved: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> Iterator for PathEventsToSegments<I>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = PathEvent>,
|
||||||
|
{
|
||||||
|
type Item = Segment;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<Segment> {
|
||||||
|
match self.iter.next()? {
|
||||||
|
PathEvent::MoveTo(to) => {
|
||||||
|
let to = Point2DF32::from_euclid(to);
|
||||||
|
self.first_subpath_point = to;
|
||||||
|
self.last_subpath_point = to;
|
||||||
|
self.just_moved = true;
|
||||||
|
self.next()
|
||||||
|
}
|
||||||
|
PathEvent::LineTo(to) => {
|
||||||
|
let to = Point2DF32::from_euclid(to);
|
||||||
|
let mut segment =
|
||||||
|
Segment::line(&LineSegmentF32::new(&self.last_subpath_point, &to));
|
||||||
|
if self.just_moved {
|
||||||
|
segment.flags.insert(SegmentFlags::FIRST_IN_SUBPATH);
|
||||||
|
}
|
||||||
|
self.last_subpath_point = to;
|
||||||
|
self.just_moved = false;
|
||||||
|
Some(segment)
|
||||||
|
}
|
||||||
|
PathEvent::QuadraticTo(ctrl, to) => {
|
||||||
|
let (ctrl, to) = (Point2DF32::from_euclid(ctrl), Point2DF32::from_euclid(to));
|
||||||
|
let mut segment =
|
||||||
|
Segment::quadratic(&LineSegmentF32::new(&self.last_subpath_point, &to), &ctrl);
|
||||||
|
if self.just_moved {
|
||||||
|
segment.flags.insert(SegmentFlags::FIRST_IN_SUBPATH);
|
||||||
|
}
|
||||||
|
self.last_subpath_point = to;
|
||||||
|
self.just_moved = false;
|
||||||
|
Some(segment)
|
||||||
|
}
|
||||||
|
PathEvent::CubicTo(ctrl0, ctrl1, to) => {
|
||||||
|
let ctrl0 = Point2DF32::from_euclid(ctrl0);
|
||||||
|
let ctrl1 = Point2DF32::from_euclid(ctrl1);
|
||||||
|
let to = Point2DF32::from_euclid(to);
|
||||||
|
let mut segment = Segment::cubic(
|
||||||
|
&LineSegmentF32::new(&self.last_subpath_point, &to),
|
||||||
|
&LineSegmentF32::new(&ctrl0, &ctrl1),
|
||||||
|
);
|
||||||
|
if self.just_moved {
|
||||||
|
segment.flags.insert(SegmentFlags::FIRST_IN_SUBPATH);
|
||||||
|
}
|
||||||
|
self.last_subpath_point = to;
|
||||||
|
self.just_moved = false;
|
||||||
|
Some(segment)
|
||||||
|
}
|
||||||
|
PathEvent::Close => {
|
||||||
|
let mut segment = Segment::line(&LineSegmentF32::new(
|
||||||
|
&self.last_subpath_point,
|
||||||
|
&self.first_subpath_point,
|
||||||
|
));
|
||||||
|
segment.flags.insert(SegmentFlags::CLOSES_SUBPATH);
|
||||||
|
self.just_moved = false;
|
||||||
|
self.last_subpath_point = self.first_subpath_point;
|
||||||
|
Some(segment)
|
||||||
|
}
|
||||||
|
PathEvent::Arc(..) => panic!("TODO: arcs"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SegmentsToPathEvents<I>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = Segment>,
|
||||||
|
{
|
||||||
|
iter: I,
|
||||||
|
buffer: Option<PathEvent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> SegmentsToPathEvents<I>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = Segment>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
pub fn new(iter: I) -> SegmentsToPathEvents<I> {
|
||||||
|
SegmentsToPathEvents { iter, buffer: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> Iterator for SegmentsToPathEvents<I>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = Segment>,
|
||||||
|
{
|
||||||
|
type Item = PathEvent;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<PathEvent> {
|
||||||
|
if let Some(event) = self.buffer.take() {
|
||||||
|
return Some(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
let segment = self.iter.next()?;
|
||||||
|
if segment.flags.contains(SegmentFlags::CLOSES_SUBPATH) {
|
||||||
|
return Some(PathEvent::Close);
|
||||||
|
}
|
||||||
|
|
||||||
|
let event = match segment.kind {
|
||||||
|
SegmentKind::None => return self.next(),
|
||||||
|
SegmentKind::Line => PathEvent::LineTo(segment.baseline.to().as_euclid()),
|
||||||
|
SegmentKind::Quadratic => PathEvent::QuadraticTo(
|
||||||
|
segment.ctrl.from().as_euclid(),
|
||||||
|
segment.baseline.to().as_euclid(),
|
||||||
|
),
|
||||||
|
SegmentKind::Cubic => PathEvent::CubicTo(
|
||||||
|
segment.ctrl.from().as_euclid(),
|
||||||
|
segment.ctrl.to().as_euclid(),
|
||||||
|
segment.baseline.to().as_euclid(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
if segment.flags.contains(SegmentFlags::FIRST_IN_SUBPATH) {
|
||||||
|
self.buffer = Some(event);
|
||||||
|
Some(PathEvent::MoveTo(segment.baseline.from().as_euclid()))
|
||||||
|
} else {
|
||||||
|
Some(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,11 +23,11 @@ use fixedbitset::FixedBitSet;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use jemallocator;
|
use jemallocator;
|
||||||
use lyon_path::iterator::PathIter;
|
use lyon_path::iterator::PathIter;
|
||||||
use lyon_path::PathEvent;
|
|
||||||
use pathfinder_geometry::line_segment::{LineSegmentF32, LineSegmentU4, LineSegmentU8};
|
use pathfinder_geometry::line_segment::{LineSegmentF32, LineSegmentU4, LineSegmentU8};
|
||||||
use pathfinder_geometry::outline::{Contour, Outline, PointIndex};
|
use pathfinder_geometry::outline::{Contour, Outline, PointIndex};
|
||||||
use pathfinder_geometry::point::Point2DF32;
|
use pathfinder_geometry::point::Point2DF32;
|
||||||
use pathfinder_geometry::segment::{Segment, SegmentFlags, SegmentKind};
|
use pathfinder_geometry::segment::{PathEventsToSegments, Segment, SegmentFlags};
|
||||||
|
use pathfinder_geometry::segment::{SegmentKind, SegmentsToPathEvents};
|
||||||
use pathfinder_geometry::simd::{F32x4, I32x4};
|
use pathfinder_geometry::simd::{F32x4, I32x4};
|
||||||
use pathfinder_geometry::stroke::{StrokeStyle, StrokeToFillIter};
|
use pathfinder_geometry::stroke::{StrokeStyle, StrokeToFillIter};
|
||||||
use pathfinder_geometry::transform::Transform2DF32;
|
use pathfinder_geometry::transform::Transform2DF32;
|
||||||
|
@ -1362,157 +1362,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Euclid interoperability
|
|
||||||
//
|
|
||||||
// TODO(pcwalton): Remove this once we're fully on Pathfinder's native geometry.
|
|
||||||
|
|
||||||
struct PathEventsToSegments<I>
|
|
||||||
where
|
|
||||||
I: Iterator<Item = PathEvent>,
|
|
||||||
{
|
|
||||||
iter: I,
|
|
||||||
first_subpath_point: Point2DF32,
|
|
||||||
last_subpath_point: Point2DF32,
|
|
||||||
just_moved: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> PathEventsToSegments<I>
|
|
||||||
where
|
|
||||||
I: Iterator<Item = PathEvent>,
|
|
||||||
{
|
|
||||||
fn new(iter: I) -> PathEventsToSegments<I> {
|
|
||||||
PathEventsToSegments {
|
|
||||||
iter,
|
|
||||||
first_subpath_point: Point2DF32::default(),
|
|
||||||
last_subpath_point: Point2DF32::default(),
|
|
||||||
just_moved: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> Iterator for PathEventsToSegments<I>
|
|
||||||
where
|
|
||||||
I: Iterator<Item = PathEvent>,
|
|
||||||
{
|
|
||||||
type Item = Segment;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Segment> {
|
|
||||||
match self.iter.next()? {
|
|
||||||
PathEvent::MoveTo(to) => {
|
|
||||||
let to = Point2DF32::from_euclid(to);
|
|
||||||
self.first_subpath_point = to;
|
|
||||||
self.last_subpath_point = to;
|
|
||||||
self.just_moved = true;
|
|
||||||
self.next()
|
|
||||||
}
|
|
||||||
PathEvent::LineTo(to) => {
|
|
||||||
let to = Point2DF32::from_euclid(to);
|
|
||||||
let mut segment =
|
|
||||||
Segment::line(&LineSegmentF32::new(&self.last_subpath_point, &to));
|
|
||||||
if self.just_moved {
|
|
||||||
segment.flags.insert(SegmentFlags::FIRST_IN_SUBPATH);
|
|
||||||
}
|
|
||||||
self.last_subpath_point = to;
|
|
||||||
self.just_moved = false;
|
|
||||||
Some(segment)
|
|
||||||
}
|
|
||||||
PathEvent::QuadraticTo(ctrl, to) => {
|
|
||||||
let (ctrl, to) = (Point2DF32::from_euclid(ctrl), Point2DF32::from_euclid(to));
|
|
||||||
let mut segment =
|
|
||||||
Segment::quadratic(&LineSegmentF32::new(&self.last_subpath_point, &to), &ctrl);
|
|
||||||
if self.just_moved {
|
|
||||||
segment.flags.insert(SegmentFlags::FIRST_IN_SUBPATH);
|
|
||||||
}
|
|
||||||
self.last_subpath_point = to;
|
|
||||||
self.just_moved = false;
|
|
||||||
Some(segment)
|
|
||||||
}
|
|
||||||
PathEvent::CubicTo(ctrl0, ctrl1, to) => {
|
|
||||||
let ctrl0 = Point2DF32::from_euclid(ctrl0);
|
|
||||||
let ctrl1 = Point2DF32::from_euclid(ctrl1);
|
|
||||||
let to = Point2DF32::from_euclid(to);
|
|
||||||
let mut segment = Segment::cubic(
|
|
||||||
&LineSegmentF32::new(&self.last_subpath_point, &to),
|
|
||||||
&LineSegmentF32::new(&ctrl0, &ctrl1),
|
|
||||||
);
|
|
||||||
if self.just_moved {
|
|
||||||
segment.flags.insert(SegmentFlags::FIRST_IN_SUBPATH);
|
|
||||||
}
|
|
||||||
self.last_subpath_point = to;
|
|
||||||
self.just_moved = false;
|
|
||||||
Some(segment)
|
|
||||||
}
|
|
||||||
PathEvent::Close => {
|
|
||||||
let mut segment = Segment::line(&LineSegmentF32::new(
|
|
||||||
&self.last_subpath_point,
|
|
||||||
&self.first_subpath_point,
|
|
||||||
));
|
|
||||||
segment.flags.insert(SegmentFlags::CLOSES_SUBPATH);
|
|
||||||
self.just_moved = false;
|
|
||||||
self.last_subpath_point = self.first_subpath_point;
|
|
||||||
Some(segment)
|
|
||||||
}
|
|
||||||
PathEvent::Arc(..) => panic!("TODO: arcs"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SegmentsToPathEvents<I>
|
|
||||||
where
|
|
||||||
I: Iterator<Item = Segment>,
|
|
||||||
{
|
|
||||||
iter: I,
|
|
||||||
buffer: Option<PathEvent>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> SegmentsToPathEvents<I>
|
|
||||||
where
|
|
||||||
I: Iterator<Item = Segment>,
|
|
||||||
{
|
|
||||||
fn new(iter: I) -> SegmentsToPathEvents<I> {
|
|
||||||
SegmentsToPathEvents { iter, buffer: None }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> Iterator for SegmentsToPathEvents<I>
|
|
||||||
where
|
|
||||||
I: Iterator<Item = Segment>,
|
|
||||||
{
|
|
||||||
type Item = PathEvent;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<PathEvent> {
|
|
||||||
if let Some(event) = self.buffer.take() {
|
|
||||||
return Some(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
let segment = self.iter.next()?;
|
|
||||||
if segment.flags.contains(SegmentFlags::CLOSES_SUBPATH) {
|
|
||||||
return Some(PathEvent::Close);
|
|
||||||
}
|
|
||||||
|
|
||||||
let event = match segment.kind {
|
|
||||||
SegmentKind::None => return self.next(),
|
|
||||||
SegmentKind::Line => PathEvent::LineTo(segment.baseline.to().as_euclid()),
|
|
||||||
SegmentKind::Quadratic => PathEvent::QuadraticTo(
|
|
||||||
segment.ctrl.from().as_euclid(),
|
|
||||||
segment.baseline.to().as_euclid(),
|
|
||||||
),
|
|
||||||
SegmentKind::Cubic => PathEvent::CubicTo(
|
|
||||||
segment.ctrl.from().as_euclid(),
|
|
||||||
segment.ctrl.to().as_euclid(),
|
|
||||||
segment.baseline.to().as_euclid(),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
if segment.flags.contains(SegmentFlags::FIRST_IN_SUBPATH) {
|
|
||||||
self.buffer = Some(event);
|
|
||||||
Some(PathEvent::MoveTo(segment.baseline.from().as_euclid()))
|
|
||||||
} else {
|
|
||||||
Some(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Path transformation utilities
|
// Path transformation utilities
|
||||||
|
|
||||||
struct PathTransformingIter<I>
|
struct PathTransformingIter<I>
|
||||||
|
|
Loading…
Reference in New Issue