summaryrefslogtreecommitdiff
path: root/render/scanconv.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/scanconv.c')
-rw-r--r--render/scanconv.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/render/scanconv.c b/render/scanconv.c
new file mode 100644
index 00000000..b2d32363
--- /dev/null
+++ b/render/scanconv.c
@@ -0,0 +1,176 @@
+#include <fitz.h>
+
+static inline void
+addspan(short *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, short *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, short *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;
+ }
+}
+
+/* XXX */
+
+unsigned char pixmap[1000 * 1000];
+
+void
+fz_emitdeltas(short *list, int y, int x, int n)
+{
+ short a = 0;
+ short d = 0;
+ while (n--) {
+ d = *list++;
+ a += d;
+ pixmap[y * 1000 + x] = 0xff - a;
+ x ++;
+ }
+}
+
+void
+savestuff(void)
+{
+ FILE *f = fopen("out.pgm", "w");
+ fprintf(f, "P5\n1000 1000\n255\n");
+ fwrite(pixmap, 1, 1000 * 1000, f);
+ fclose(f);
+}
+
+/* XXX */
+
+void
+fz_emitdeltas0(short *list, int y, int xofs, int n)
+{
+ int d = 0;
+ while (n--)
+ d += *list++;
+}
+
+fz_error *
+fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill)
+{
+ fz_error *error;
+ short *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 ymin = fz_idiv(gel->ymin, gel->vs);
+ int ymax = fz_idiv(gel->ymax, gel->vs) + 1;
+
+ int xofs = xmin * gel->hs;
+ int hs = gel->hs;
+ int vs = gel->vs;
+
+ if (gel->len == 0)
+ return nil;
+
+memset(pixmap, 0xff, sizeof pixmap);
+
+printf("bbox [%d %d %d %d] samp %d/%d edges %d\n",
+ xmin, ymin, xmax, ymax, hs, vs, gel->len);
+
+ deltas = fz_malloc(sizeof(short) * (xmax - xmin));
+ if (!deltas)
+ return fz_outofmem;
+ memset(deltas, 0, sizeof(short) * (xmax - xmin));
+
+ 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) {
+ fz_emitdeltas(deltas, yd, xmin, xmax - xmin);
+ memset(deltas, 0, sizeof(short) * (xmax - xmin));
+ }
+ yd = yc;
+
+ error = fz_insertael(ael, gel, y, &e);
+ if (error) {
+ fz_free(deltas);
+ return error;
+ }
+
+// { int i; for (i = 0; i < ael->len; i++)
+// pixmap[yd * 1000 + (ael->edges[i]->x / hs)] = 0; }
+
+ if (eofill)
+ evenodd(ael, deltas, xofs, hs);
+ else
+ nonzerowinding(ael, deltas, xofs, hs);
+
+ fz_advanceael(ael);
+
+ if (ael->len > 0)
+ y ++;
+ else if (e < gel->len)
+ y = gel->edges[e].y;
+ }
+
+ fz_emitdeltas(deltas, yd, xmin, xmax - xmin);
+
+ savestuff();
+
+ return nil;
+}
+