Skip to content

Commit

Permalink
FromKurbo is just ToOutline now — finish genericizing PenOperations
Browse files Browse the repository at this point in the history
Tomorrow will tackle the rest of Logicalshift/flo_curves#14 testing
needs.
  • Loading branch information
ctrlcctrlv committed Feb 6, 2022
1 parent 0808d76 commit 52e1d85
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 131 deletions.
2 changes: 1 addition & 1 deletion src/outline.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub mod contour;
pub use contour::Reverse;
mod conv;
pub use conv::IntoGlifPoints;
pub use conv::{IntoGlifPoints, ToOutline};
pub mod create;
mod kurbo;
pub use self::kurbo::*;
Expand Down
2 changes: 1 addition & 1 deletion src/outline/conv.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod penops;
pub use penops::{IntoPenOperations, PenOperations};
pub use penops::{IntoPenOperations, PenOperations, SplitPenOperations, ToOutline};

use super::{Contour, GlifContour};

Expand Down
171 changes: 156 additions & 15 deletions src/outline/conv/penops.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use crate::error::GlifParserError;
use crate::point::IsValid;
use crate::point::{GlifPoint, PointData, PointType, WhichHandle};
use PointType::*;
use crate::outline::Contour;
use crate::outline::contour::{PrevNext as _, State as _};
use crate::outline::refigure::RefigurePointTypes as _;
use crate::outline::{Contour, Outline};
use crate::point::IsValid;
use crate::point::{Handle, GlifPoint, Point, PointData, PointType, WhichHandle};
use PointType::*;

use float_cmp::ApproxEq;

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, IsVariant, Unwrap)]
pub enum PenOperations {
MoveTo(GlifPoint),
LineTo(GlifPoint),
Expand All @@ -17,6 +19,18 @@ pub enum PenOperations {

use PenOperations::*;

impl PenOperations {
pub fn len(&self) -> usize {
match self {
MoveTo(..) => 1,
LineTo(..) => 1,
QuadTo(..) => 2,
CurveTo(..) => 3,
Close => 0,
}
}
}

impl Default for PenOperations {
/// By default, create a move_to to origin.
fn default() -> Self {
Expand All @@ -29,8 +43,20 @@ impl IsValid for PenOperations {
match self {
MoveTo(gp) => gp.ptype == PointType::Move && gp.is_valid(),
LineTo(gp) => gp.ptype == PointType::Line && gp.is_valid(),
QuadTo(gpb, gp) => gp.ptype != PointType::OffCurve && gp.is_valid() && gpb.ptype == PointType::OffCurve && gpb.is_valid(),
CurveTo(gpb, gp2a, gp) => gp.ptype != PointType::OffCurve && gp.is_valid() && gpb.ptype == PointType::OffCurve && gpb.is_valid() && gp2a.ptype == PointType::OffCurve && gp2a.is_valid(),
QuadTo(gpb, gp) => {
gp.ptype != PointType::OffCurve
&& gp.is_valid()
&& gpb.ptype == PointType::OffCurve
&& gpb.is_valid()
}
CurveTo(gpb, gp2a, gp) => {
gp.ptype != PointType::OffCurve
&& gp.is_valid()
&& gpb.ptype == PointType::OffCurve
&& gpb.is_valid()
&& gp2a.ptype == PointType::OffCurve
&& gp2a.is_valid()
}
Close => true,
}
}
Expand Down Expand Up @@ -73,7 +99,7 @@ impl<PD: PointData> IntoPenOperations for Contour<PD> {
} else {
PenOperations::LineTo(point.into())
}
},
}
PointType::QCurve => {
PenOperations::QuadTo(GlifPoint::from_handle(&point, WhichHandle::A), point.into())
}
Expand All @@ -99,9 +125,8 @@ impl<PD: PointData> IntoPenOperations for Contour<PD> {
if self.last().unwrap().ptype == Curve && self.first().unwrap().ptype == Curve {
let lp = pen_vec.last().unwrap().clone();
if let PenOperations::CurveTo(p1, p2, _p3) = lp {
*pen_vec.last_mut().unwrap() = PenOperations::CurveTo(
p1, p2, self.first().unwrap().into()
);
*pen_vec.last_mut().unwrap() =
PenOperations::CurveTo(p1, p2, self.first().unwrap().into());
}
}
pen_vec.push(PenOperations::Close);
Expand All @@ -111,8 +136,124 @@ impl<PD: PointData> IntoPenOperations for Contour<PD> {
}
}

/*
impl PenOperations {
pub fn split(self) -> Vec<Self> {
pub type PenOperationsPath = Vec<Vec<PenOperations>>;

pub trait SplitPenOperations {
fn split_pen_operations(self) -> PenOperationsPath;
}

impl SplitPenOperations for Vec<PenOperations> {
/// Split a long vec of pen operations into constitutent contours.
fn split_pen_operations(self) -> PenOperationsPath {
let mut koutline = vec![];
let mut kcontour = vec![];
let mut last_was_close = false;
let iterable: Vec<_> = if *self.iter().last().unwrap() != Close {
self.into_iter().chain([Close].into_iter()).collect()
} else {
self.into_iter().collect()
};
for p in iterable {
let kpv = &p;
if p.is_move_to() {
if kcontour.len() > 0 {
koutline.push(kcontour);
}
kcontour = vec![p.clone()];
} else if kpv.len() > 0 {
kcontour.push(p.clone());
} else if kpv.len() == 0 && !last_was_close {
let lp: Vec<GlifPoint> = kcontour.last().unwrap().clone().into();
let lp = lp.last().unwrap();
let removed = kcontour.remove(0);
let rm = removed.unwrap_move_to();
let _fp = kcontour.first().unwrap().clone();
if rm.x.approx_eq(lp.x, (f32::EPSILON, 4))
&& rm.y.approx_eq(lp.y, (f32::EPSILON, 4))
{
kcontour.insert(0, PenOperations::CurveTo(rm.clone(), rm.clone(), rm));
} else {
kcontour.insert(0, PenOperations::LineTo(rm));
}
}
last_was_close = p.is_close();
}

if kcontour.len() > 0 {
koutline.push(kcontour);
}

koutline
}
}

pub trait ToOutline<PD: PointData> {
fn to_outline(&self) -> Outline<PD>;
}

impl<PD: PointData> ToOutline<PD> for PenOperationsPath {
fn to_outline(&self) -> Outline<PD> {
let mut ret: Outline<PD> = Outline::new();

for skc in self.iter() {
let skc_len = skc.len();
let mut contour: Contour<PD> = Contour::new();
let mut next_points: Vec<GlifPoint>;
for (i, el) in skc.iter().enumerate() {
let points: Vec<GlifPoint> = el.clone().into();
if i != skc_len - 1 {
next_points = skc[i + 1].clone().into();
} else {
next_points = skc[0].clone().into();
}

let mut point = Point::<PD> {
name: None,
data: None,
x: points[0].x.into(),
y: points[0].y.into(),
smooth: false,
// These will be fixed below, if needed
a: Handle::Colocated,
b: Handle::Colocated,
ptype: (el).into(),
};

match point.ptype {
PointType::Move => {}
PointType::Curve => {
if next_points.len() == 3 {
point.a = Handle::At(next_points[2].x.into(), next_points[2].y.into());
}
if let Some(p) = points.get(1) {
point.b = Handle::At(p.x.into(), p.y.into());
} else {
log::warn!("Expected a next handle that does not exist")
}
}
PointType::Line => {
if next_points.len() == 3 {
// Lines aren't allowed to have off-curve points in glif format
point.ptype = PointType::Curve;
point.a = Handle::At(next_points[2].x.into(), next_points[2].y.into());
}
}
_ => unreachable!("Got an illegal point type {:?}", point.ptype),
}
contour.push(point);
}

let first = contour.first().unwrap();
let last = contour.last().unwrap();
let (x, y, _a, b) = (last.x, last.y, last.a, last.b);
if contour.len() >= 2 && x == first.x && y == first.y {
contour.pop().unwrap();
contour.first_mut().unwrap().b = b;
}

ret.push(contour);
}

ret
}
}*/
}
Loading

0 comments on commit 52e1d85

Please sign in to comment.