diff --git a/c++/contourgl/Makefile b/c++/contourgl/Makefile
index afc16e4..fdd894d 100644
--- a/c++/contourgl/Makefile
+++ b/c++/contourgl/Makefile
@@ -1,8 +1,9 @@
DEPLIBS = gl x11
CXXFLAGS = -O3 -Wall -fmessage-length=0 `pkg-config --libs $(DEPLIBS)` -DGL_GLEXT_PROTOTYPES
-DEPS = contour.h contourbuilder.h
-OBJS = contour.o contourgl.o contourbuilder.o
+DEPS = contour.h contourbuilder.h geometry.h polyspan.h rendersw.h test.h \
+ contour.cpp contourbuilder.cpp polyspan.cpp rendersw.cpp test.cpp
+OBJS = contour.o contourgl.o contourbuilder.o polyspan.o rendersw.o test.o
LIBS = `pkg-config --libs $(DEPLIBS)`
TARGET = contourgl
diff --git a/c++/contourgl/contour.cpp b/c++/contourgl/contour.cpp
index 93748a7..8a5bacf 100644
--- a/c++/contourgl/contour.cpp
+++ b/c++/contourgl/contour.cpp
@@ -15,7 +15,7 @@
along with this program. If not, see .
*/
-#include
+#include
#include "contour.h"
@@ -78,11 +78,6 @@ void Contour::close() {
}
}
-void Contour::assign(const Contour &other) {
- chunks = other.chunks;
- first = other.first;
-}
-
void Contour::line_split(
Rect &ref_line_bounds,
const Rect &bounds,
@@ -118,9 +113,9 @@ void Contour::conic_split(
const Vector &min_size,
const Vector &p1,
const Vector ¢er,
- double radius,
- double radians0,
- double radians1,
+ Real radius,
+ Real radians0,
+ Real radians1,
int level )
{
assert(level > 0);
@@ -131,7 +126,7 @@ void Contour::conic_split(
{
Rect b = conic_bounds(p0, p1, center, radius, radians0, radians1);
if (bounds.intersects(b)) {
- double radians = 0.5*(radians0 + radians1);
+ Real radians = 0.5*(radians0 + radians1);
Vector p( radius*cos(radians) + center.x,
radius*sin(radians) + center.y );
conic_split(ref_line_bounds, bounds, min_size, p, center, radius, radians0, radians, level - 1);
@@ -196,9 +191,9 @@ void Contour::split(Contour &c, const Rect &bounds, const Vector &min_size) cons
{
const Vector &p0 = c.current();
Vector center;
- double radius = 0.0;
- double radians0 = 0.0;
- double radians1 = 0.0;
+ Real radius = 0.0;
+ Real radians0 = 0.0;
+ Real radians1 = 0.0;
if (conic_convert(p0, i->p1, i->t0, center, radius, radians0, radians1))
c.conic_split(line_bounds, bounds, min_size, i->p1, center, radius, radians0, radians1);
else
@@ -222,11 +217,11 @@ bool Contour::conic_convert(
const Vector &p1,
const Vector &t,
Vector &out_center,
- double &out_radius,
- double &out_radians0,
- double &out_radians1 )
+ Real &out_radius,
+ Real &out_radians0,
+ Real &out_radians1 )
{
- double tl = sqrt(t.x*t.x + t.y*t.y);
+ Real tl = sqrt(t.x*t.x + t.y*t.y);
if (fabs(tl) < 1e-6) {
out_center = Vector();
out_radius = 0.0;
@@ -238,7 +233,7 @@ bool Contour::conic_convert(
Vector d = p1 - p0;
Vector n(-t.y/tl, t.x/tl);
- double r = 0.5*(d.x*d.x + d.y*d.y)/(d.x*n.x + d.y*n.y);
+ Real r = 0.5*(d.x*d.x + d.y*d.y)/(d.x*n.x + d.y*n.y);
out_center = p0 + n*r;
out_radius = fabs(r);
out_radians0 = atan2(p0.y - out_center.y, p0.x - out_center.x);
@@ -257,9 +252,9 @@ Rect Contour::conic_bounds(
const Vector &p0,
const Vector &p1,
const Vector ¢er,
- double radius,
- double radians0,
- double radians1 )
+ Real radius,
+ Real radians0,
+ Real radians1 )
{
radius = fabs(radius);
@@ -304,3 +299,57 @@ Rect Contour::cubic_bounds(
r.p1.y = max(max(p0.y, bezier_pp0.y), max(p1.y, bezier_pp1.y));
return r;
}
+
+void Contour::transform(const Rect &from, const Rect &to) {
+ Vector s( (to.p1.x - to.p0.x)/(from.p1.x - from.p0.x),
+ (to.p1.y - to.p0.y)/(from.p1.y - from.p0.y) );
+ Vector o( to.p0.x - from.p0.x*s.x,
+ to.p0.y - from.p0.y*s.y );
+ for(Contour::ChunkList::iterator i = chunks.begin(); i != chunks.end(); ++i) {
+ i->p1 = i->p1*s + o;
+ i->t0 = i->t0*s;
+ i->t1 = i->t1*s;
+ }
+}
+
+void Contour::to_polyspan(Polyspan &polyspan) const {
+ polyspan.move_to(0.0, 0.0);
+ Vector p0;
+ for(Contour::ChunkList::const_iterator i = chunks.begin(); i != chunks.end(); ++i) {
+ switch(i->type) {
+ case Contour::CLOSE:
+ polyspan.close();
+ break;
+ case Contour::MOVE:
+ polyspan.move_to(i->p1.x, i->p1.y);
+ break;
+ case Contour::LINE:
+ polyspan.line_to(i->p1.x, i->p1.y);
+ break;
+ case Contour::CONIC: {
+ Vector center;
+ Real radius = 0.0;
+ Real radians0 = 0.0;
+ Real radians1 = 0.0;
+ if (conic_convert(p0, i->p1, i->t0, center, radius, radians0, radians1)) {
+ // TODO: fix bugs
+ Vector pp0( center.x + 2.0*radius*cos(0.5*(radians0 + radians1)),
+ center.y + 2.0*radius*sin(0.5*(radians0 + radians1)) );
+ polyspan.conic_to(pp0.x, pp0.y, i->p1.x, i->p1.y);
+ } else {
+ polyspan.line_to(i->p1.x, i->p1.y);
+ }
+ }
+ break;
+ case Contour::CUBIC: {
+ Vector pp0, pp1;
+ cubic_convert(p0, i->p1, i->t0, i->t1, pp0, pp1);
+ polyspan.cubic_to(pp0.x, pp0.y, pp1.x, pp1.y, i->p1.x, i->p1.y);
+ }
+ break;
+ default:
+ break;
+ }
+ p0 = i->p1;
+ }
+}
diff --git a/c++/contourgl/contour.h b/c++/contourgl/contour.h
index 643586e..71f9adb 100644
--- a/c++/contourgl/contour.h
+++ b/c++/contourgl/contour.h
@@ -18,84 +18,10 @@
#ifndef _CONTOUR_H_
#define _CONTOUR_H_
-#include
-#include
-
-#include
#include
-template
-bool intersects(const T &a0, const T &a1, const T &b0, const T &b1) {
- return !(std::max(b0, b1) < std::min(a0, a1))
- && !(std::max(a0, a1) < std::min(b0, b1));
-}
-
-inline double wrap_angle(double a, double round) {
- double rounds = a/round + 0.5;
- return (rounds - floor(rounds) - 0.5)*round;
-}
-
-inline bool angle_between(double a0, double a1, double a, double round) {
- if (a1 < a0) std::swap(a0, a1);
- a0 = wrap_angle(a0, round);
- a1 = wrap_angle(a1, round);
- a = wrap_angle(a, round);
- if (a < a0) a += round;
- if (a1 < a0) a1 += round;
- return a0 < a && a < a1;
-}
-
-class Vector {
-public:
- union {
- struct { double x, y; };
- struct { double coords[]; };
- };
-
- Vector():
- x(), y() { }
- Vector(double x, double y):
- x(x), y(y) { }
-
- double& operator[] (int index)
- { return coords[index]; }
- const double& operator[] (int index) const
- { return coords[index]; }
- bool is_equal_to(const Vector &other) const
- { return fabs(x - other.x) < 1e-6 && fabs(y - other.y) < 1e-6; }
-
- Vector operator+(const Vector &a) const
- { return Vector(x + a.x, y + a.y); }
- Vector operator-(const Vector &a) const
- { return Vector(x - a.x, y - a.y); }
- Vector operator*(double a) const
- { return Vector(x*a, y*a); }
- Vector operator/(double a) const
- { return Vector(x/a, y/a); }
-
- static Vector zero() { return Vector(); }
-};
-
-class Rect {
-public:
- Vector p0, p1;
-
- bool intersects(const Rect &other) const
- { return ::intersects(p0.x, p1.x, other.p0.x, other.p1.x)
- && ::intersects(p0.y, p1.y, other.p0.y, other.p1.y); }
-
- Rect expand(const Vector &p) const {
- Rect r;
- r.p0.x = std::min(std::min(p0.x, p1.x), p.x);
- r.p0.y = std::min(std::min(p0.y, p1.y), p.y);
- r.p1.x = std::max(std::max(p0.x, p1.x), p.x);
- r.p1.y = std::max(std::max(p0.y, p1.y), p.y);
- return r;
- }
-};
-
-inline bool intersects(const Rect &a, const Rect &b)
- { return a.intersects(b); }
+#include "geometry.h"
+#include "polyspan.h"
class Contour
{
@@ -133,8 +59,6 @@ public:
void conic_to(const Vector &v, const Vector &t);
void close();
- void assign(const Contour &other);
-
const ChunkList& get_chunks() const { return chunks; }
const Vector& current() const
@@ -142,6 +66,10 @@ public:
void split(Contour &c, const Rect &bounds, const Vector &min_size) const;
+ void transform(const Rect &from, const Rect &to);
+
+ void to_polyspan(Polyspan &polyspan) const;
+
private:
void line_split(
Rect &ref_line_bounds,
@@ -155,9 +83,9 @@ private:
const Vector &min_size,
const Vector &p1,
const Vector ¢er,
- double radius,
- double radians0,
- double radians1,
+ Real radius,
+ Real radians0,
+ Real radians1,
int level = 64 );
void cubic_split(
@@ -174,17 +102,17 @@ private:
const Vector &p1,
const Vector &t,
Vector &out_center,
- double &out_radius,
- double &out_radians0,
- double &out_radians1 );
+ Real &out_radius,
+ Real &out_radians0,
+ Real &out_radians1 );
static Rect conic_bounds(
const Vector &p0,
const Vector &p1,
const Vector ¢er,
- double radius,
- double radians0,
- double radians1 );
+ Real radius,
+ Real radians0,
+ Real radians1 );
static void cubic_convert(
const Vector &p0,
diff --git a/c++/contourgl/contourbuilder.cpp b/c++/contourgl/contourbuilder.cpp
index 92162f3..4084c14 100644
--- a/c++/contourgl/contourbuilder.cpp
+++ b/c++/contourgl/contourbuilder.cpp
@@ -82,7 +82,7 @@ void ContourBuilder::build_simple(vector &c) {
c.push_back(c.front());
}
-void ContourBuilder::build_car(Contour &c, const Vector &o, double s) {
+void ContourBuilder::build_car(Contour &c, const Vector &o, Real s) {
c.move_to( Vector( 5, -1)*s + o);
c.line_to( Vector( 4, -1)*s + o);
c.conic_to( Vector( 2, -1)*s + o, Vector( 0, -1)*s);
@@ -98,22 +98,22 @@ void ContourBuilder::build_car(Contour &c, const Vector &o, double s) {
}
void ContourBuilder::build(Contour &c) {
- double scale = 0.8/5.0;
+ Real scale = 0.8/5.0;
int count = 100;
- double size = (double)(count + 2)/(double)(count);
- double step = 2.0*size/(double)(count + 1);
- double origin = step - size;
- double s = 2*size*scale/(double)(count);
+ Real size = (Real)(count + 2)/(Real)(count);
+ Real step = 2.0*size/(Real)(count + 1);
+ Real origin = step - size;
+ Real s = 2*size*scale/(Real)(count);
for(int i = 0; i < count; ++i)
for(int j = 0; j < count; ++j)
build_car(c, Vector(origin + i*step, origin + j*step), s);
count = 100;
- size = (double)(count + 2)/(double)(count);
- step = 2.0*size/(double)(count + 1);
+ size = (Real)(count + 2)/(Real)(count);
+ step = 2.0*size/(Real)(count + 1);
origin = step - size;
- s = size*scale/(double)(count);
+ s = size*scale/(Real)(count);
for(int i = 0; i < count; ++i)
for(int j = 0; j < count; ++j)
build_car(c, Vector(origin + i*step, origin + j*step), s);
diff --git a/c++/contourgl/contourbuilder.h b/c++/contourgl/contourbuilder.h
index 17c4e67..1395c25 100644
--- a/c++/contourgl/contourbuilder.h
+++ b/c++/contourgl/contourbuilder.h
@@ -20,6 +20,6 @@
class ContourBuilder {
public:
static void build_simple(std::vector &c);
- static void build_car(Contour &c, const Vector &o, double s);
+ static void build_car(Contour &c, const Vector &o, Real s);
static void build(Contour &c);
};
diff --git a/c++/contourgl/contourgl.cpp b/c++/contourgl/contourgl.cpp
index 2c7b10f..14d1b0a 100644
--- a/c++/contourgl/contourgl.cpp
+++ b/c++/contourgl/contourgl.cpp
@@ -16,19 +16,19 @@
*/
#include
+#include
#include
#include
#include
#include