Blame c++/contourgl/contour.cpp

Ivan Mahonin faaf7d
/*
Ivan Mahonin faaf7d
    ......... 2015 Ivan Mahonin
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
    This program is free software: you can redistribute it and/or modify
Ivan Mahonin faaf7d
    it under the terms of the GNU General Public License as published by
Ivan Mahonin faaf7d
    the Free Software Foundation, either version 3 of the License, or
Ivan Mahonin faaf7d
    (at your option) any later version.
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
    This program is distributed in the hope that it will be useful,
Ivan Mahonin faaf7d
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Ivan Mahonin faaf7d
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Ivan Mahonin faaf7d
    GNU General Public License for more details.
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
    You should have received a copy of the GNU General Public License
Ivan Mahonin faaf7d
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
Ivan Mahonin faaf7d
*/
Ivan Mahonin faaf7d
Ivan Mahonin 93cbac
#include <cassert>
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
#include "contour.h"
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
using namespace std;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
const Vector Contour::blank;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::clear() {
Ivan Mahonin faaf7d
	if (!chunks.empty()) {
Ivan Mahonin faaf7d
		chunks.clear();
Ivan Mahonin faaf7d
		first = 0;
Ivan Mahonin faaf7d
	}
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::move_to(const Vector &v) {
Ivan Mahonin faaf7d
	if (chunks.empty()) {
Ivan Mahonin faaf7d
		if (!v.is_equal_to(blank))
Ivan Mahonin faaf7d
			chunks.push_back(Chunk(MOVE, v));
Ivan Mahonin faaf7d
	} else {
Ivan Mahonin faaf7d
		if (!v.is_equal_to(chunks.back().p1)) {
Ivan Mahonin faaf7d
			if (chunks.back().type == MOVE)
Ivan Mahonin faaf7d
				chunks.back().p1 = v;
Ivan Mahonin faaf7d
			else
Ivan Mahonin faaf7d
			if (chunks.back().type == CLOSE)
Ivan Mahonin faaf7d
				chunks.push_back(Chunk(MOVE, v));
Ivan Mahonin faaf7d
			else {
Ivan Mahonin faaf7d
				chunks.push_back(Chunk(CLOSE, chunks[first].p1));
Ivan Mahonin faaf7d
				chunks.push_back(Chunk(MOVE, v));
Ivan Mahonin faaf7d
			}
Ivan Mahonin faaf7d
		}
Ivan Mahonin faaf7d
	}
Ivan Mahonin faaf7d
	first = chunks.size();
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::line_to(const Vector &v) {
Ivan Mahonin faaf7d
	if (!v.is_equal_to(current()))
Ivan Mahonin faaf7d
		chunks.push_back(Chunk(LINE, v));
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::conic_to(const Vector &v, const Vector &t) {
Ivan Mahonin faaf7d
	if (!v.is_equal_to(current()))
Ivan Mahonin faaf7d
		chunks.push_back(Chunk(CONIC, v, t));
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::cubic_to(const Vector &v, const Vector &t0, const Vector &t1) {
Ivan Mahonin faaf7d
	if (!v.is_equal_to(current()))
Ivan Mahonin faaf7d
		chunks.push_back(Chunk(CUBIC, v, t0, t1));
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::close() {
Ivan Mahonin faaf7d
	if (chunks.size() > first) {
Ivan Mahonin faaf7d
		if (first > 0)
Ivan Mahonin faaf7d
			chunks.push_back(Chunk(CLOSE, chunks[first-1].p1));
Ivan Mahonin faaf7d
		else
Ivan Mahonin faaf7d
			chunks.push_back(Chunk(CLOSE, blank));
Ivan Mahonin faaf7d
		first = chunks.size();
Ivan Mahonin faaf7d
	}
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::line_split(
Ivan Mahonin faaf7d
	Rect &ref_line_bounds,
Ivan Mahonin faaf7d
	const Rect &bounds,
Ivan Mahonin faaf7d
	const Vector &min_size,
Ivan Mahonin d989ab
	const Vector &p1,
Ivan Mahonin d989ab
	int level )
Ivan Mahonin faaf7d
{
Ivan Mahonin d989ab
	assert(level > 0);
Ivan Mahonin d989ab
Ivan Mahonin d989ab
	if (allow_split_lines) {
Ivan Mahonin d989ab
		const Vector &p0 = current();
Ivan Mahonin d989ab
		if ( fabs(p1.x - p0.x) > min_size.x
Ivan Mahonin d989ab
		  || fabs(p1.y - p0.y) > min_size.y )
Ivan Mahonin d989ab
		{
Ivan Mahonin d989ab
			Vector p = (p0 + p1)*0.5;
Ivan Mahonin d989ab
			line_split(ref_line_bounds, bounds, min_size, p, level-1);
Ivan Mahonin 5890eb
			line_split(ref_line_bounds, bounds, min_size, p1, level-1);
Ivan Mahonin d989ab
			return;
Ivan Mahonin d989ab
		}
Ivan Mahonin d989ab
	}
Ivan Mahonin d989ab
Ivan Mahonin faaf7d
	line_to(p1);
Ivan Mahonin faaf7d
	return;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	// TODO: fix bugs
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	ref_line_bounds = ref_line_bounds.expand(p1);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	if (bounds.intersects(ref_line_bounds)) {
Ivan Mahonin faaf7d
		Vector s = ref_line_bounds.p1 - ref_line_bounds.p0;
Ivan Mahonin faaf7d
		if ( fabs(s.x) > min_size.x
Ivan Mahonin faaf7d
		  || fabs(s.y) > min_size.y )
Ivan Mahonin faaf7d
		{
Ivan Mahonin faaf7d
			line_to(p1);
Ivan Mahonin faaf7d
			ref_line_bounds.p0 = p1;
Ivan Mahonin faaf7d
			ref_line_bounds.p1 = p1;
Ivan Mahonin faaf7d
			return;
Ivan Mahonin faaf7d
		}
Ivan Mahonin faaf7d
	}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	if (!chunks.empty())
Ivan Mahonin faaf7d
		chunks.back().p1 = p1;
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::conic_split(
Ivan Mahonin faaf7d
	Rect &ref_line_bounds,
Ivan Mahonin faaf7d
	const Rect &bounds,
Ivan Mahonin faaf7d
	const Vector &min_size,
Ivan Mahonin faaf7d
	const Vector &p1,
Ivan Mahonin faaf7d
	const Vector &center,
Ivan Mahonin 93cbac
	Real radius,
Ivan Mahonin 93cbac
	Real radians0,
Ivan Mahonin 93cbac
	Real radians1,
Ivan Mahonin faaf7d
	int level )
Ivan Mahonin faaf7d
{
Ivan Mahonin faaf7d
	assert(level > 0);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	const Vector &p0 = current();
Ivan Mahonin faaf7d
	if ( fabs(p1.x - p0.x) > min_size.x
Ivan Mahonin faaf7d
	  || fabs(p1.y - p0.y) > min_size.y )
Ivan Mahonin faaf7d
	{
Ivan Mahonin faaf7d
		Rect b = conic_bounds(p0, p1, center, radius, radians0, radians1);
Ivan Mahonin faaf7d
		if (bounds.intersects(b)) {
Ivan Mahonin 93cbac
			Real radians = 0.5*(radians0 + radians1);
Ivan Mahonin faaf7d
			Vector p( radius*cos(radians) + center.x,
Ivan Mahonin faaf7d
					  radius*sin(radians) + center.y );
Ivan Mahonin faaf7d
			conic_split(ref_line_bounds, bounds, min_size,  p, center, radius, radians0, radians, level - 1);
Ivan Mahonin faaf7d
			conic_split(ref_line_bounds, bounds, min_size, p1, center, radius, radians, radians1, level - 1);
Ivan Mahonin faaf7d
			return;
Ivan Mahonin faaf7d
		}
Ivan Mahonin faaf7d
	}
Ivan Mahonin faaf7d
	line_split(ref_line_bounds, bounds, min_size, p1);
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::cubic_split(
Ivan Mahonin faaf7d
	Rect &ref_line_bounds,
Ivan Mahonin faaf7d
	const Rect &bounds,
Ivan Mahonin faaf7d
	const Vector &min_size,
Ivan Mahonin faaf7d
	const Vector &p1,
Ivan Mahonin faaf7d
	const Vector &bezier_pp0,
Ivan Mahonin faaf7d
	const Vector &bezier_pp1,
Ivan Mahonin faaf7d
	int level )
Ivan Mahonin faaf7d
{
Ivan Mahonin faaf7d
	assert(level > 0);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	const Vector &p0 = current();
Ivan Mahonin faaf7d
	if ( fabs(p1.x - p0.x) > min_size.x
Ivan Mahonin faaf7d
	  || fabs(p1.y - p0.y) > min_size.y )
Ivan Mahonin faaf7d
	{
Ivan Mahonin faaf7d
		Rect b = cubic_bounds(p0, p1, bezier_pp0, bezier_pp1);
Ivan Mahonin faaf7d
		if (bounds.intersects(b)) {
Ivan Mahonin faaf7d
			Vector pp = (bezier_pp0 + bezier_pp1)*0.5;
Ivan Mahonin faaf7d
			Vector pp00 = (p0 + bezier_pp0)*0.5;
Ivan Mahonin faaf7d
			Vector pp11 = (p1 + bezier_pp1)*0.5;
Ivan Mahonin faaf7d
			Vector pp01 = (pp00 + pp)*0.5;
Ivan Mahonin faaf7d
			Vector pp10 = (pp11 + pp)*0.5;
Ivan Mahonin faaf7d
			Vector p = (pp01 + pp10)*0.5;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
			cubic_split(ref_line_bounds, bounds, min_size,  p, pp00, pp01, level - 1);
Ivan Mahonin faaf7d
			cubic_split(ref_line_bounds, bounds, min_size, p1, pp10, pp11, level - 1);
Ivan Mahonin faaf7d
			return;
Ivan Mahonin faaf7d
		}
Ivan Mahonin faaf7d
	}
Ivan Mahonin faaf7d
	line_split(ref_line_bounds, bounds, min_size, p1);
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::split(Contour &c, const Rect &bounds, const Vector &min_size) const {
Ivan Mahonin f29469
	c.clear();
Ivan Mahonin f29469
Ivan Mahonin faaf7d
	Rect line_bounds;
Ivan Mahonin faaf7d
	line_bounds.p0 = c.current();
Ivan Mahonin faaf7d
	line_bounds.p1 = c.current();
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	for(ChunkList::const_iterator i = chunks.begin(); i != chunks.end(); ++i) {
Ivan Mahonin faaf7d
		switch(i->type) {
Ivan Mahonin faaf7d
		case MOVE:
Ivan Mahonin faaf7d
			c.move_to(i->p1);
Ivan Mahonin faaf7d
			line_bounds.p0 = c.current();
Ivan Mahonin faaf7d
			line_bounds.p1 = c.current();
Ivan Mahonin faaf7d
			break;
Ivan Mahonin faaf7d
		case LINE:
Ivan Mahonin faaf7d
		case CLOSE:
Ivan Mahonin 5890eb
			c.line_split(line_bounds, bounds, min_size, i->p1);
Ivan Mahonin faaf7d
			break;
Ivan Mahonin faaf7d
		case CONIC:
Ivan Mahonin faaf7d
			{
Ivan Mahonin faaf7d
				const Vector &p0 = c.current();
Ivan Mahonin faaf7d
				Vector center;
Ivan Mahonin 93cbac
				Real radius = 0.0;
Ivan Mahonin 93cbac
				Real radians0 = 0.0;
Ivan Mahonin 93cbac
				Real radians1 = 0.0;
Ivan Mahonin faaf7d
				if (conic_convert(p0, i->p1, i->t0, center, radius, radians0, radians1))
Ivan Mahonin faaf7d
					c.conic_split(line_bounds, bounds, min_size, i->p1, center, radius, radians0, radians1);
Ivan Mahonin faaf7d
				else
Ivan Mahonin faaf7d
					c.line_split(line_bounds, bounds, min_size, i->p1);
Ivan Mahonin faaf7d
			}
Ivan Mahonin faaf7d
			break;
Ivan Mahonin faaf7d
		case CUBIC:
Ivan Mahonin faaf7d
			{
Ivan Mahonin faaf7d
				const Vector &p0 = c.current();
Ivan Mahonin faaf7d
				Vector pp0, pp1;
Ivan Mahonin faaf7d
				cubic_convert(p0, i->p1, i->t0, i->t1, pp0, pp1);
Ivan Mahonin faaf7d
				c.cubic_split(line_bounds, bounds, min_size, i->p1, pp0, pp1);
Ivan Mahonin faaf7d
			}
Ivan Mahonin faaf7d
			break;
Ivan Mahonin faaf7d
		}
Ivan Mahonin faaf7d
	}
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
bool Contour::conic_convert(
Ivan Mahonin faaf7d
	const Vector &p0,
Ivan Mahonin faaf7d
	const Vector &p1,
Ivan Mahonin faaf7d
	const Vector &t,
Ivan Mahonin faaf7d
	Vector &out_center,
Ivan Mahonin 93cbac
	Real &out_radius,
Ivan Mahonin 93cbac
	Real &out_radians0,
Ivan Mahonin 93cbac
	Real &out_radians1 )
Ivan Mahonin faaf7d
{
Ivan Mahonin 93cbac
	Real tl = sqrt(t.x*t.x + t.y*t.y);
Ivan Mahonin faaf7d
	if (fabs(tl) < 1e-6) {
Ivan Mahonin faaf7d
		out_center = Vector();
Ivan Mahonin faaf7d
		out_radius = 0.0;
Ivan Mahonin faaf7d
		out_radians0 = 0.0;
Ivan Mahonin faaf7d
		out_radians1 = 0.0;
Ivan Mahonin faaf7d
		return false;
Ivan Mahonin faaf7d
	}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	Vector d = p1 - p0;
Ivan Mahonin faaf7d
	Vector n(-t.y/tl, t.x/tl);
Ivan Mahonin faaf7d
Ivan Mahonin 93cbac
	Real r = 0.5*(d.x*d.x + d.y*d.y)/(d.x*n.x + d.y*n.y);
Ivan Mahonin faaf7d
	out_center = p0 + n*r;
Ivan Mahonin faaf7d
	out_radius = fabs(r);
Ivan Mahonin faaf7d
	out_radians0 = atan2(p0.y - out_center.y, p0.x - out_center.x);
Ivan Mahonin faaf7d
	out_radians1 = atan2(p1.y - out_center.y, p1.x - out_center.x);
Ivan Mahonin faaf7d
	bool ccw = r > 0.0;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	out_radians0 = wrap_angle(out_radians0, 2.0*M_PI);
Ivan Mahonin faaf7d
	out_radians1 = wrap_angle(out_radians1, 2.0*M_PI);
Ivan Mahonin faaf7d
	if (ccw) { if (out_radians1 < out_radians0) out_radians1 += 2.0*M_PI; }
Ivan Mahonin faaf7d
	    else { if (out_radians1 > out_radians0) out_radians1 -= 2.0*M_PI; }
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	return true;
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
Rect Contour::conic_bounds(
Ivan Mahonin faaf7d
	const Vector &p0,
Ivan Mahonin faaf7d
	const Vector &p1,
Ivan Mahonin faaf7d
	const Vector &center,
Ivan Mahonin 93cbac
	Real radius,
Ivan Mahonin 93cbac
	Real radians0,
Ivan Mahonin 93cbac
	Real radians1 )
Ivan Mahonin faaf7d
{
Ivan Mahonin faaf7d
	radius = fabs(radius);
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	Rect r;
Ivan Mahonin faaf7d
	r.p0 = p0;
Ivan Mahonin faaf7d
	r.p1 = p1;
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	if (angle_between(radians0, radians1, 0.0*M_PI, 2.0*M_PI))
Ivan Mahonin faaf7d
		r = r.expand(Vector(center.x + radius, center.y));
Ivan Mahonin faaf7d
	if (angle_between(radians0, radians1, 0.5*M_PI, 2.0*M_PI))
Ivan Mahonin faaf7d
		r = r.expand(Vector(center.x, center.y + radius));
Ivan Mahonin faaf7d
	if (angle_between(radians0, radians1, 1.0*M_PI, 2.0*M_PI))
Ivan Mahonin faaf7d
		r = r.expand(Vector(center.x - radius, center.y));
Ivan Mahonin faaf7d
	if (angle_between(radians0, radians1, 1.5*M_PI, 2.0*M_PI))
Ivan Mahonin faaf7d
		r = r.expand(Vector(center.x, center.y - radius));
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
	return r;
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
void Contour::cubic_convert(
Ivan Mahonin faaf7d
	const Vector &p0,
Ivan Mahonin faaf7d
	const Vector &p1,
Ivan Mahonin faaf7d
	const Vector &t0,
Ivan Mahonin faaf7d
	const Vector &t1,
Ivan Mahonin faaf7d
	Vector &out_bezier_pp0,
Ivan Mahonin faaf7d
	Vector &out_bezier_pp1 )
Ivan Mahonin faaf7d
{
Ivan Mahonin faaf7d
	out_bezier_pp0 = t0/3.0 + p0;
Ivan Mahonin faaf7d
	out_bezier_pp1 = p1 - t1/3.0;
Ivan Mahonin faaf7d
}
Ivan Mahonin faaf7d
Ivan Mahonin faaf7d
Rect Contour::cubic_bounds(
Ivan Mahonin faaf7d
	const Vector &p0,
Ivan Mahonin faaf7d
	const Vector &p1,
Ivan Mahonin faaf7d
	const Vector &bezier_pp0,
Ivan Mahonin faaf7d
	const Vector &bezier_pp1 )
Ivan Mahonin faaf7d
{
Ivan Mahonin faaf7d
	Rect r;
Ivan Mahonin faaf7d
	r.p0.x = min(min(p0.x, bezier_pp0.x), min(p1.x, bezier_pp1.x));
Ivan Mahonin faaf7d
	r.p0.y = min(min(p0.y, bezier_pp0.y), min(p1.y, bezier_pp1.y));
Ivan Mahonin faaf7d
	r.p1.x = max(max(p0.x, bezier_pp0.x), max(p1.x, bezier_pp1.x));
Ivan Mahonin faaf7d
	r.p1.y = max(max(p0.y, bezier_pp0.y), max(p1.y, bezier_pp1.y));
Ivan Mahonin faaf7d
	return r;
Ivan Mahonin faaf7d
}
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
void Contour::transform(const Rect &from, const Rect &to) {
Ivan Mahonin 93cbac
	Vector s( (to.p1.x - to.p0.x)/(from.p1.x - from.p0.x),
Ivan Mahonin 93cbac
			  (to.p1.y - to.p0.y)/(from.p1.y - from.p0.y) );
Ivan Mahonin 93cbac
	Vector o( to.p0.x - from.p0.x*s.x,
Ivan Mahonin 93cbac
			  to.p0.y - from.p0.y*s.y );
Ivan Mahonin 93cbac
	for(Contour::ChunkList::iterator i = chunks.begin(); i != chunks.end(); ++i) {
Ivan Mahonin 93cbac
		i->p1 = i->p1*s + o;
Ivan Mahonin 93cbac
		i->t0 = i->t0*s;
Ivan Mahonin 93cbac
		i->t1 = i->t1*s;
Ivan Mahonin 93cbac
	}
Ivan Mahonin 93cbac
}
Ivan Mahonin 93cbac
Ivan Mahonin f29469
void Contour::downgrade(Contour &c, const Vector &min_size) const {
Ivan Mahonin f29469
	c.clear();
Ivan Mahonin f29469
	Rect r;
Ivan Mahonin f29469
	for(Contour::ChunkList::const_iterator i = chunks.begin(); i != chunks.end(); ++i) {
Ivan Mahonin f29469
		switch(i->type) {
Ivan Mahonin f29469
			case Contour::CLOSE:
Ivan Mahonin f29469
				c.close();
Ivan Mahonin f29469
				r.p0 = r.p1 = c.current();
Ivan Mahonin f29469
				break;
Ivan Mahonin f29469
			case Contour::MOVE:
Ivan Mahonin f29469
				c.move_to(i->p1);
Ivan Mahonin f29469
				r.p0 = r.p1 = c.current();
Ivan Mahonin f29469
				break;
Ivan Mahonin f29469
			case Contour::CONIC:
Ivan Mahonin f29469
			case Contour::CUBIC:
Ivan Mahonin f29469
			case Contour::LINE:
Ivan Mahonin f29469
				r = r.expand(i->p1);
Ivan Mahonin f29469
				if ( fabs(r.p1.x - r.p0.x) > min_size.x
Ivan Mahonin d9c2d9
				  || fabs(r.p1.y - r.p0.y) > min_size.y )
Ivan Mahonin f29469
				{
Ivan Mahonin f29469
					c.line_to(i->p1);
Ivan Mahonin f29469
					r.p0 = r.p1 = c.current();
Ivan Mahonin f29469
				}
Ivan Mahonin f29469
				break;
Ivan Mahonin f29469
		}
Ivan Mahonin f29469
	}
Ivan Mahonin f29469
}
Ivan Mahonin f29469
Ivan Mahonin 93cbac
void Contour::to_polyspan(Polyspan &polyspan) const {
Ivan Mahonin 93cbac
	polyspan.move_to(0.0, 0.0);
Ivan Mahonin 93cbac
	Vector p0;
Ivan Mahonin 93cbac
	for(Contour::ChunkList::const_iterator i = chunks.begin(); i != chunks.end(); ++i) {
Ivan Mahonin 93cbac
		switch(i->type) {
Ivan Mahonin 93cbac
			case Contour::CLOSE:
Ivan Mahonin 93cbac
				polyspan.close();
Ivan Mahonin 93cbac
				break;
Ivan Mahonin 93cbac
			case Contour::MOVE:
Ivan Mahonin 93cbac
				polyspan.move_to(i->p1.x, i->p1.y);
Ivan Mahonin 93cbac
				break;
Ivan Mahonin 93cbac
			case Contour::LINE:
Ivan Mahonin 93cbac
				polyspan.line_to(i->p1.x, i->p1.y);
Ivan Mahonin 93cbac
				break;
Ivan Mahonin 93cbac
			case Contour::CONIC: {
Ivan Mahonin 93cbac
					Vector center;
Ivan Mahonin 93cbac
					Real radius = 0.0;
Ivan Mahonin 93cbac
					Real radians0 = 0.0;
Ivan Mahonin 93cbac
					Real radians1 = 0.0;
Ivan Mahonin 93cbac
					if (conic_convert(p0, i->p1, i->t0, center, radius, radians0, radians1)) {
Ivan Mahonin 93cbac
						// TODO: fix bugs
Ivan Mahonin 93cbac
						Vector pp0( center.x + 2.0*radius*cos(0.5*(radians0 + radians1)),
Ivan Mahonin 93cbac
								    center.y + 2.0*radius*sin(0.5*(radians0 + radians1)) );
Ivan Mahonin 93cbac
						polyspan.conic_to(pp0.x, pp0.y, i->p1.x, i->p1.y);
Ivan Mahonin 93cbac
					} else {
Ivan Mahonin 93cbac
						polyspan.line_to(i->p1.x, i->p1.y);
Ivan Mahonin 93cbac
					}
Ivan Mahonin 93cbac
				}
Ivan Mahonin 93cbac
				break;
Ivan Mahonin 93cbac
			case Contour::CUBIC: {
Ivan Mahonin 93cbac
					Vector pp0, pp1;
Ivan Mahonin 93cbac
					cubic_convert(p0, i->p1, i->t0, i->t1, pp0, pp1);
Ivan Mahonin 93cbac
					polyspan.cubic_to(pp0.x, pp0.y, pp1.x, pp1.y, i->p1.x, i->p1.y);
Ivan Mahonin 93cbac
				}
Ivan Mahonin 93cbac
				break;
Ivan Mahonin 93cbac
			default:
Ivan Mahonin 93cbac
				break;
Ivan Mahonin 93cbac
		}
Ivan Mahonin 93cbac
		p0 = i->p1;
Ivan Mahonin 93cbac
	}
Ivan Mahonin 93cbac
}