char to_the_left = 0;
char fail = 0;
while(t) {
+ /* this check doesn't work out with cmp() because during horizontal
+ processing, both segments ending as well as segments starting will
+ be active in this scanline */
+ //double d = cmp(t, p1, p2);
double d = single_cmp(t, p1);
+ if(d>=0 && to_the_left) {
+ segment_t*s = a->list;
+ while(s) {
+ fprintf(stderr, "[%d] %f/%f (%d,%d) -> (%d,%d)\n", s->nr,
+ single_cmp(s,p1), cmp(s,p1,p2),
+ s->a.x, s->a.y, s->b.x, s->b.y);
+ s = s->right;
+ }
+ }
assert(!(d>=0 && to_the_left));
if(d<0) to_the_left=1;
t = t->right;
if(a->root) {
move_to_root(a, left);
-
if(left) {
LINK(s,leftchild,a->root);
// steal right child from (previous) root
} else {
LINK(s,rightchild,a->root);
}
-
- /*if(cmp(a->root, s->a, s->b) < 0) {
- LINK(s,rightchild,a->root);
- // steal left child from (previous) root
- LINK(s,leftchild,a->root->leftchild);
- a->root->leftchild = 0;
- } else {
- LINK(s,leftchild,a->root);
- // steal right child from (previous) root
- LINK(s,rightchild,a->root->rightchild);
- a->root->rightchild = 0;
- }*/
}
a->root = s;
a->root->parent = 0;
segment_t* actlist_rightmost(actlist_t*a)
{
/* this is only used in checks, so it doesn't matter that it's slow */
+#ifndef CHECKS
+ fprintf(stderr, "Warning: actlist_rightmost should not be used\n");
+#endif
segment_t*s = a->list;
segment_t*last = 0;
while(s) {
actlist_insert_after(a, left, s);
}
-
-segment_t* actlist_left(actlist_t*a, segment_t*s)
-{
- return s->left;
-}
-
-segment_t* actlist_right(actlist_t*a, segment_t*s)
-{
- if(s) return s->right;
- else return a->list;
-}
-
void actlist_swap(actlist_t*a, segment_t*s1, segment_t*s2)
{
#ifdef SPLAY
#endif
} actlist_t;
+#define actlist_left(a,s) ((s)->left)
+#define actlist_right(a,s) ((s)?(s)->right:(a)->list)
+
actlist_t* actlist_new();
void actlist_destroy(actlist_t*a);
int actlist_size(actlist_t*a);
void actlist_insert(actlist_t*a, point_t p1, point_t p2, segment_t*s);
void actlist_delete(actlist_t*a, segment_t*s);
void actlist_swap(actlist_t*a, segment_t*s1, segment_t*s2);
-segment_t* actlist_left(actlist_t*a, segment_t*s);
segment_t* actlist_leftmost(actlist_t*a);
segment_t* actlist_rightmost(actlist_t*a);
-segment_t* actlist_right(actlist_t*a, segment_t*s);
#endif
#include "../mem.h"
#include "poly.h"
+/* factor that determines into how many line fragments a spline is converted */
+#define SUBFRACTION (2.4)
+
static edge_t*edge_new(int x1, int y1, int x2, int y2)
{
edge_t*s = rfx_calloc(sizeof(edge_t));
int y1 = ceil(_y1);
int x2 = ceil(_x2);
int y2 = ceil(_y2);
+
if(x1!=x2 || y1!=y2) {
edge_t*s = edge_new(x1, y1, x2, y2);
s->next = poly->edges;
{
gfxpoly_t*p = gfxpoly_new(gridsize);
- /* factor that determines into how many line fragments a spline is converted */
- double subfraction = 2.4;//0.3
-
double z = 1.0 / gridsize;
double lastx=0, lasty=0;
gfxpoly_add_edge(p, lastx, lasty, x, y);
} else if(line->type == gfx_splineTo) {
int parts = (int)(sqrt(fabs(line->x-2*line->sx+lastx) +
- fabs(line->y-2*line->sy+lasty))*subfraction);
+ fabs(line->y-2*line->sy+lasty))*SUBFRACTION);
if(!parts) parts = 1;
double stepsize = 1.0/parts;
int i;
lasty = y;
line = line->next;
}
-
+
gfxline_free(line);
return p;
}
+typedef struct _gfxstroke {
+ segment_dir_t dir;
+ point_t*stroke;
+ fillstyle_t*fs;
+ int num_points;
+} gfxstroke_t;
+typedef struct _gfxcompactpoly {
+ double gridsize;
+ int num_strokes;
+ gfxstroke_t strokes[0];
+} gfxcompactpoly_t;
+
static char* readline(FILE*fi)
{
char c;
#endif
} status_t;
-int compare_events_simple(const void*_a,const void*_b)
+/* compare_events_simple differs from compare_events in that it schedules
+ events from left to right regardless of type. It's only used in horizontal
+ processing, in order to get an x-wise sorting of the current scanline */
+static int compare_events_simple(const void*_a,const void*_b)
{
event_t* a = (event_t*)_a;
event_t* b = (event_t*)_b;
return 0;
}
-int compare_events(const void*_a,const void*_b)
+static int compare_events(const void*_a,const void*_b)
{
event_t* a = (event_t*)_a;
event_t* b = (event_t*)_b;
continue;
}
segment_t*s = segment_new(l->a.x, l->a.y, l->b.x, l->b.y, initial, polygon_nr);
+#ifdef DEBUG
if(l->tmp)
s->nr = l->tmp;
-#ifdef DEBUG
fprintf(stderr, "[%d] (%d,%d) -> (%d,%d) %s\n",
s->nr, s->a.x, s->a.y, s->b.x, s->b.y,
s->dir==DIR_UP?"up":"down");
// omit horizontal lines
if(s->pos.y != p.y) {
edge_t*e = rfx_calloc(sizeof(edge_t));
+#ifdef DEBUG
e->tmp = s->nr;
+#endif
e->a = s->pos;
e->b = p;
assert(e->a.y != e->b.y);
s->pos = p;
}
-/* by restricting the recalculation of line segments to a range between the lowest
- and the highest modified segment, we only do about a 33% overprocessing of fill
- styles. (update: that statistic might be outdated now that xmin/xmax are double) */
typedef struct _segrange {
double xmin;
segment_t*segmin;
actlist_dump(actlist, y-1);
#endif
#ifdef CHECKS
- /* FIXME: this actually fails sometimes */
actlist_verify(actlist, y-1);
#endif
do {
#include "../q.h"
//#define DEBUG
-#define CHECKS
+//#define CHECKS
#define SPLAY
typedef enum {DIR_UP, DIR_DOWN} segment_dir_t;
point_t a;
point_t b;
fillstyle_t*style;
+#ifdef DEBUG
int tmp;
+#endif
struct _edge *next;
} edge_t;