use std::iter;
use core::{ PathEvent, SvgEvent, FlattenedEvent, PathState };
use core::math::*;
use bezier::{
QuadraticBezierSegment, CubicBezierSegment,
QuadraticFlatteningIter, CubicFlatteningIter
};
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Segment {
Line(Point, Point),
QuadraticBezier(Point, Point, Point),
CubicBezier(Point, Point, Point, Point),
}
pub trait PathIterator : Iterator<Item=PathEvent> + Sized {
fn get_state(&self) -> &PathState;
fn flattened(self, tolerance: f32) -> FlatteningIter<Self> { FlatteningIter::new(tolerance, self) }
fn svg_iter(self) -> iter::Map<Self, fn(PathEvent)->SvgEvent> {
self.map(path_to_svg_event)
}
}
pub trait SvgIterator : Iterator<Item=SvgEvent> + Sized {
fn get_state(&self) -> &PathState;
fn flattened(self, tolerance: f32) -> FlatteningIter<SvgToPathIter<Self>> { self.path_iter().flattened(tolerance) }
fn path_iter(self) -> SvgToPathIter<Self> { SvgToPathIter::new(self) }
}
pub trait FlattenedIterator : Iterator<Item=FlattenedEvent> + Sized {
fn get_state(&self) -> &PathState;
fn path_iter(self) -> iter::Map<Self, fn(FlattenedEvent)->PathEvent> {
self.map(flattened_to_path_event)
}
fn svg_iter(self) -> iter::Map<Self, fn(FlattenedEvent)->SvgEvent> {
self.map(flattened_to_svg_event)
}
}
pub struct SegmentIterator<PathIt> {
it: PathIt,
state: PathState,
in_sub_path: bool,
}
impl<'l, PathIt:'l+Iterator<Item=PathEvent>> SegmentIterator<PathIt> {
pub fn new(it: PathIt) -> Self {
SegmentIterator {
it: it,
state: PathState::new(),
in_sub_path: false,
}
}
fn close(&mut self) -> Option<Segment> {
let first = self.state.first;
self.state.close();
self.in_sub_path = false;
if first != self.state.current {
Some(Segment::Line(first, self.state.current))
} else {
self.next()
}
}
}
impl<'l, PathIt:'l+Iterator<Item=PathEvent>> Iterator
for SegmentIterator<PathIt> {
type Item = Segment;
fn next(&mut self) -> Option<Segment> {
return match self.it.next() {
Some(PathEvent::MoveTo(to)) => {
let first = self.state.first;
self.state.move_to(to);
if self.in_sub_path && first != self.state.current {
Some(Segment::Line(first, self.state.current))
} else {
self.in_sub_path = true;
self.next()
}
}
Some(PathEvent::LineTo(to)) => {
self.in_sub_path = true;
let from = self.state.current;
self.state.line_to(to);
Some(Segment::Line(from, to))
}
Some(PathEvent::QuadraticTo(ctrl, to)) => {
self.in_sub_path = true;
let from = self.state.current;
self.state.curve_to(ctrl, to);
Some(Segment::QuadraticBezier(from, ctrl, to))
}
Some(PathEvent::CubicTo(ctrl1, ctrl2, to)) => {
self.in_sub_path = true;
let from = self.state.current;
self.state.curve_to(ctrl2, to);
Some(Segment::CubicBezier(from, ctrl1, ctrl2, to))
}
Some(PathEvent::Close) => { self.close() }
None => { None }
};
}
}
pub struct SvgToPathIter<SvgIter> {
it: SvgIter,
}
impl<SvgIter> SvgToPathIter<SvgIter> {
pub fn new(it: SvgIter) -> Self { SvgToPathIter { it: it } }
}
impl<SvgIter> PathIterator for SvgToPathIter<SvgIter>
where SvgIter : SvgIterator {
fn get_state(&self) -> &PathState { self.it.get_state() }
}
impl<SvgIter> Iterator for SvgToPathIter<SvgIter>
where SvgIter: SvgIterator {
type Item = PathEvent;
fn next(&mut self) -> Option<PathEvent> {
return match self.it.next() {
Some(svg_evt) => { Some(self.get_state().svg_to_path_event(svg_evt)) }
None => { None }
}
}
}
pub struct FlatteningIter<Iter> {
it: Iter,
current_curve: TmpFlatteningIter,
tolerance: f32,
}
enum TmpFlatteningIter {
Quadratic(QuadraticFlatteningIter),
Cubic(CubicFlatteningIter),
None,
}
impl<Iter: PathIterator> FlatteningIter<Iter> {
pub fn new(tolerance: f32, it: Iter) -> Self {
FlatteningIter {
it: it,
current_curve: TmpFlatteningIter::None,
tolerance: tolerance,
}
}
}
impl<Iter> FlattenedIterator for FlatteningIter<Iter>
where Iter : PathIterator {
fn get_state(&self) -> &PathState { self.it.get_state() }
}
impl<Iter> Iterator for FlatteningIter<Iter>
where Iter: PathIterator {
type Item = FlattenedEvent;
fn next(&mut self) -> Option<FlattenedEvent> {
match self.current_curve {
TmpFlatteningIter::Quadratic(ref mut it) => {
if let Some(point) = it.next() {
return Some(FlattenedEvent::LineTo(point));
}
}
TmpFlatteningIter::Cubic(ref mut it) => {
if let Some(point) = it.next() {
return Some(FlattenedEvent::LineTo(point));
}
}
_ => {}
}
self.current_curve = TmpFlatteningIter::None;
let current = self.get_state().current;
return match self.it.next() {
Some(PathEvent::MoveTo(to)) => { Some(FlattenedEvent::MoveTo(to)) }
Some(PathEvent::LineTo(to)) => { Some(FlattenedEvent::LineTo(to)) }
Some(PathEvent::Close) => { Some(FlattenedEvent::Close) }
Some(PathEvent::QuadraticTo(ctrl, to)) => {
self.current_curve = TmpFlatteningIter::Quadratic(
QuadraticBezierSegment {
from: current, ctrl: ctrl, to: to
}.flattening_iter(self.tolerance)
);
return self.next();
}
Some(PathEvent::CubicTo(ctrl1, ctrl2, to)) => {
self.current_curve = TmpFlatteningIter::Cubic(
CubicBezierSegment {
from: current, ctrl1: ctrl1, ctrl2: ctrl2, to: to
}.flattening_iter(self.tolerance)
);
return self.next();
}
None => { None }
}
}
}
pub struct PathStateSvgIter<Iter> {
it: Iter,
state: PathState,
}
impl<Iter: Iterator<Item=SvgEvent>> PathStateSvgIter<Iter> {
pub fn new(it: Iter) -> Self { PathStateSvgIter { it: it, state: PathState::new() } }
}
impl<Iter> SvgIterator for PathStateSvgIter<Iter>
where Iter: Iterator<Item=SvgEvent> {
fn get_state(&self) -> &PathState { &self.state }
}
impl<Iter: Iterator<Item=SvgEvent>> Iterator for PathStateSvgIter<Iter> {
type Item = SvgEvent;
fn next(&mut self) -> Option<SvgEvent> {
let next = self.it.next();
if let Some(evt) = next {
self.state.svg_event(evt);
}
return next;
}
}
pub struct PathStateIter<Iter> {
it: Iter,
state: PathState,
}
impl<Iter: Iterator<Item=PathEvent>> PathStateIter<Iter> {
pub fn new(it: Iter) -> Self { PathStateIter { it: it, state: PathState::new() } }
}
impl<Iter> PathIterator for PathStateIter<Iter>
where Iter : Iterator<Item=PathEvent> {
fn get_state(&self) -> &PathState { &self.state }
}
impl<Iter: Iterator<Item=PathEvent>> Iterator for PathStateIter<Iter> {
type Item = PathEvent;
fn next(&mut self) -> Option<PathEvent> {
let next = self.it.next();
if let Some(evt) = next {
self.state.path_event(evt);
}
return next;
}
}
fn flattened_to_path_event(evt: FlattenedEvent) -> PathEvent { evt.to_path_event() }
fn flattened_to_svg_event(evt: FlattenedEvent) -> SvgEvent { evt.to_svg_event() }
fn path_to_svg_event(evt: PathEvent) -> SvgEvent { evt.to_svg_event() }