summaryrefslogtreecommitdiff
path: root/render/pathscan.c
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2005-06-04 15:58:45 +0200
committerTor Andersson <tor@ghostscript.com>2005-06-04 15:58:45 +0200
commit7ee19483ed81a885f464d4e93f4eefb3d4037d30 (patch)
treee4d3faf561e694ae0cc7873381450db6a011ab5a /render/pathscan.c
parentaf699a4657e103bd8fa72356eb3abebf221fe93a (diff)
downloadmupdf-7ee19483ed81a885f464d4e93f4eefb3d4037d30.tar.xz
new world order
Diffstat (limited to 'render/pathscan.c')
-rw-r--r--render/pathscan.c483
1 files changed, 0 insertions, 483 deletions
diff --git a/render/pathscan.c b/render/pathscan.c
deleted file mode 100644
index cea3a849..00000000
--- a/render/pathscan.c
+++ /dev/null
@@ -1,483 +0,0 @@
-#include <fitz.h>
-
-/*
- * Global Edge List -- list of straight path segments for scan conversion
- *
- * Stepping along the edges is with bresenham's line algorithm.
- *
- * See Mike Abrash -- Graphics Programming Black Book (notably chapter 40)
- */
-
-fz_error *
-fz_newgel(fz_gel **gelp)
-{
- fz_gel *gel;
-
- gel = *gelp = fz_malloc(sizeof(fz_gel));
- if (!gel)
- return fz_outofmem;
-
- gel->edges = nil;
-
- gel->cap = 512;
- gel->len = 0;
- gel->edges = fz_malloc(sizeof(fz_edge) * gel->cap);
- if (!gel->edges) {
- fz_free(gel);
- return fz_outofmem;
- }
-
- gel->xmin = gel->ymin = INT_MAX;
- gel->xmax = gel->ymax = INT_MIN;
- gel->hs = 1;
- gel->vs = 1;
-
- return nil;
-}
-
-void
-fz_resetgel(fz_gel *gel, int hs, int vs)
-{
- gel->xmin = gel->ymin = INT_MAX;
- gel->xmax = gel->ymax = INT_MIN;
- gel->hs = hs;
- gel->vs = vs;
- gel->len = 0;
-}
-
-void
-fz_dropgel(fz_gel *gel)
-{
- fz_free(gel->edges);
- fz_free(gel);
-}
-
-fz_irect
-fz_boundgel(fz_gel *gel)
-{
- fz_irect bbox;
- bbox.x0 = fz_idiv(gel->xmin, gel->hs);
- bbox.y0 = fz_idiv(gel->ymin, gel->vs);
- bbox.x1 = fz_idiv(gel->xmax, gel->hs) + 1;
- bbox.y1 = fz_idiv(gel->ymax, gel->vs) + 1;
- return bbox;
-}
-
-fz_error *
-fz_insertgel(fz_gel *gel, float fx0, float fy0, float fx1, float fy1)
-{
- fz_edge *edge;
- int x0, y0, x1, y1;
- int dx, dy;
- int winding;
- int width;
- int tmp;
-
- fx0 *= gel->hs;
- fy0 *= gel->vs;
- fx1 *= gel->hs;
- fy1 *= gel->vs;
-
- /* TODO: should we round or truncate? */
- x0 = fx0 < 0 ? fx0 - 0.5 : fx0 + 0.5;
- y0 = fy0 < 0 ? fy0 - 0.5 : fy0 + 0.5;
- x1 = fx1 < 0 ? fx1 - 0.5 : fx1 + 0.5;
- y1 = fy1 < 0 ? fy1 - 0.5 : fy1 + 0.5;
-
- if (y0 == y1)
- return nil;
-
- if (y0 > y1) {
- winding = -1;
- tmp = x0; x0 = x1; x1 = tmp;
- tmp = y0; y0 = y1; y1 = tmp;
- }
- else
- winding = 1;
-
- if (x0 < gel->xmin) gel->xmin = x0;
- if (x0 > gel->xmax) gel->xmax = x0;
- if (x1 < gel->xmin) gel->xmin = x1;
- if (x1 > gel->xmax) gel->xmax = x1;
-
- if (y0 < gel->ymin) gel->ymin = y0;
- if (y1 > gel->ymax) gel->ymax = y1;
-
- if (gel->len + 1 == gel->cap) {
- int newcap = gel->cap + 512;
- fz_edge *newedges = fz_realloc(gel->edges, sizeof(fz_edge) * newcap);
- if (!newedges)
- return fz_outofmem;
- gel->cap = newcap;
- gel->edges = newedges;
- }
-
- edge = &gel->edges[gel->len++];
-
- dy = y1 - y0;
- dx = x1 - x0;
- width = dx < 0 ? -dx : dx;
-
- edge->xdir = dx > 0 ? 1 : -1;
- edge->ydir = winding;
- edge->x = x0;
- edge->y = y0;
- edge->h = dy;
- edge->adjdown = dy;
-
- /* initial error term going l->r and r->l */
- if (dx >= 0)
- edge->e = 0;
- else
- edge->e = -dy + 1;
-
- /* y-major edge */
- if (dy >= width) {
- edge->xmove = 0;
- edge->adjup = width;
- }
-
- /* x-major edge */
- else {
- edge->xmove = (width / dy) * edge->xdir;
- edge->adjup = width % dy;
- }
-
- return nil;
-}
-
-void
-fz_sortgel(fz_gel *gel)
-{
- fz_edge *a = gel->edges;
- int n = gel->len;
-
- int h, i, k;
- fz_edge t;
-
- h = 1;
- if (n < 14) {
- h = 1;
- }
- else {
- while (h < n)
- h = 3 * h + 1;
- h /= 3;
- h /= 3;
- }
-
- while (h > 0)
- {
- for (i = 0; i < n; i++) {
- t = a[i];
- k = i - h;
- /* TODO: sort on y major, x minor */
- while (k >= 0 && a[k].y > t.y) {
- a[k + h] = a[k];
- k -= h;
- }
- a[k + h] = t;
- }
-
- h /= 3;
- }
-}
-
-/*
- * Active Edge List -- keep track of active edges while sweeping
- */
-
-fz_error *
-fz_newael(fz_ael **aelp)
-{
- fz_ael *ael;
-
- ael = *aelp = fz_malloc(sizeof(fz_ael));
- if (!ael)
- return fz_outofmem;
-
- ael->cap = 64;
- ael->len = 0;
- ael->edges = fz_malloc(sizeof(fz_edge*) * ael->cap);
- if (!ael->edges) {
- fz_free(ael);
- return fz_outofmem;
- }
-
- return nil;
-}
-
-void
-fz_dropael(fz_ael *ael)
-{
- fz_free(ael->edges);
- fz_free(ael);
-}
-
-static inline void
-sortael(fz_edge **a, int n)
-{
- int h, i, k;
- fz_edge *t;
-
- h = 1;
- if (n < 14) {
- h = 1;
- }
- else {
- while (h < n)
- h = 3 * h + 1;
- h /= 3;
- h /= 3;
- }
-
- while (h > 0)
- {
- for (i = 0; i < n; i++) {
- t = a[i];
- k = i - h;
- while (k >= 0 && a[k]->x > t->x) {
- a[k + h] = a[k];
- k -= h;
- }
- a[k + h] = t;
- }
-
- h /= 3;
- }
-}
-
-static fz_error *
-insertael(fz_ael *ael, fz_gel *gel, int y, int *e)
-{
- /* insert edges that start here */
- while (*e < gel->len && gel->edges[*e].y == y) {
- if (ael->len + 1 == ael->cap) {
- int newcap = ael->cap + 64;
- fz_edge **newedges = fz_realloc(ael->edges, sizeof(fz_edge*) * newcap);
- if (!newedges)
- return fz_outofmem;
- ael->edges = newedges;
- ael->cap = newcap;
- }
- ael->edges[ael->len++] = &gel->edges[(*e)++];
- }
-
- /* shell-sort the edges by increasing x */
- sortael(ael->edges, ael->len);
-
- return nil;
-}
-
-static void
-advanceael(fz_ael *ael)
-{
- fz_edge *edge;
- int i = 0;
-
- while (i < ael->len)
- {
- edge = ael->edges[i];
-
- edge->h --;
-
- /* terminator! */
- if (edge->h == 0) {
- ael->edges[i] = ael->edges[--ael->len];
- }
-
- else {
- edge->x += edge->xmove;
- edge->e += edge->adjup;
- if (edge->e > 0) {
- edge->x += edge->xdir;
- edge->e -= edge->adjdown;
- }
- i ++;
- }
- }
-}
-
-/*
- * Scan convert
- */
-
-static inline void
-addspan(unsigned char *list, int x0, int x1, int xofs, int hs)
-{
- int x0pix, x0sub;
- int x1pix, x1sub;
-
- if (x0 == x1)
- return;
-
- /* x between 0 and width of bbox */
- x0 -= xofs;
- x1 -= xofs;
-
- x0pix = x0 / hs;
- x0sub = x0 % hs;
- x1pix = x1 / hs;
- x1sub = x1 % hs;
-
- if (x0pix == x1pix)
- {
- list[x0pix] += x1sub - x0sub;
- list[x0pix+1] += x0sub - x1sub;
- }
-
- else
- {
- list[x0pix] += hs - x0sub;
- list[x0pix+1] += x0sub;
- list[x1pix] += x1sub - hs;
- list[x1pix+1] += -x1sub;
- }
-}
-
-static inline void
-nonzerowinding(fz_ael *ael, unsigned char *list, int xofs, int hs)
-{
- int winding = 0;
- int x = 0;
- int i;
- for (i = 0; i < ael->len; i++)
- {
- if (!winding && (winding + ael->edges[i]->ydir))
- x = ael->edges[i]->x;
- if (winding && !(winding + ael->edges[i]->ydir))
- addspan(list, x, ael->edges[i]->x, xofs, hs);
- winding += ael->edges[i]->ydir;
- }
-}
-
-static inline void
-evenodd(fz_ael *ael, unsigned char *list, int xofs, int hs)
-{
- int even = 0;
- int x = 0;
- int i;
- for (i = 0; i < ael->len; i++)
- {
- if (!even)
- x = ael->edges[i]->x;
- else
- addspan(list, x, ael->edges[i]->x, xofs, hs);
- even = !even;
- }
-}
-
-static inline void toalpha(unsigned char *list, int n)
-{
- int d = 0;
- while (n--)
- {
- d += *list;
- *list++ = d;
- }
-}
-
-static inline void blit(fz_pixmap *pix, int x, int y,
- unsigned char *list, int skipx, int len,
- unsigned char *rgb, int over)
-{
- unsigned char *dst;
- int cov;
-
- dst = pix->samples + ( (y - pix->y) * pix->w + (x - pix->x) ) * pix->n;
- cov = 0;
-
- while (skipx--)
- {
- cov += *list;
- *list = 0;
- ++list;
- }
-
- if (rgb)
- fz_path_w3i1o4(rgb, list, cov, len, dst);
- else if (over)
- fz_path_1o1(list, cov, len, dst);
- else
- fz_path_1c1(list, cov, len, dst);
-}
-
-fz_error *
-fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, fz_irect clip,
- fz_pixmap *pix, unsigned char *rgb, int over)
-{
- fz_error *error;
- unsigned char *deltas;
- int y, e;
- int yd, yc;
-
- int xmin = fz_idiv(gel->xmin, gel->hs);
- int xmax = fz_idiv(gel->xmax, gel->hs) + 1;
-
- int xofs = xmin * gel->hs;
- int hs = gel->hs;
- int vs = gel->vs;
-
- int skipx = clip.x0 - xmin;
- int clipn = clip.x1 - clip.x0;
-
- assert(clip.x0 >= xmin);
- assert(clip.x1 <= xmax);
-
- if (gel->len == 0)
- return nil;
-
- deltas = fz_malloc(xmax - xmin + 1);
- if (!deltas)
- return fz_outofmem;
-
- memset(deltas, 0, xmax - xmin + 1);
-
- e = 0;
- y = gel->edges[0].y;
- yc = fz_idiv(y, vs);
- yd = yc;
-
- while (ael->len > 0 || e < gel->len)
- {
- yc = fz_idiv(y, vs);
- if (yc != yd)
- {
- if (yd >= clip.y0 && yd < clip.y1)
- {
- blit(pix, xmin + skipx, yd, deltas, skipx, clipn, rgb, over);
- }
- }
- yd = yc;
-
- error = insertael(ael, gel, y, &e);
- if (error) {
- fz_free(deltas);
- return error;
- }
-
- if (yd >= clip.y0 && yd < clip.y1)
- {
- if (eofill)
- evenodd(ael, deltas, xofs, hs);
- else
- nonzerowinding(ael, deltas, xofs, hs);
- }
-
- advanceael(ael);
-
- if (ael->len > 0)
- y ++;
- else if (e < gel->len)
- y = gel->edges[e].y;
- }
-
- if (yd >= clip.y0 && yd < clip.y1)
- {
- blit(pix, xmin + skipx, yd, deltas, skipx, clipn, rgb, over);
- }
-
- fz_free(deltas);
- return nil;
-}
-