From 4c164469d43cf248e72d384137d59fbd7204afcb Mon Sep 17 00:00:00 2001
From: Tor Andersson <tor@ghostscript.com>
Date: Fri, 19 Nov 2004 08:49:17 +0100
Subject: rewrite of render loop part 1

---
 Jamfile                   |   4 +-
 include/fitz/colorspace.h |   2 +
 include/fitz/font.h       |   2 +-
 include/fitz/pixmap.h     |   1 +
 include/fitz/render.h     |  59 +++++-
 mupdf/colorspace1.c       |   4 +-
 mupdf/font.c              |  19 +-
 mupdf/image2.c            |   2 +-
 mupdf/interpret.c         |   2 +-
 mupdf/type3.c             |  19 +-
 render/glyphcache.c       |  12 +-
 render/pixmap.c           |   9 +
 render/rastnone.c         | 379 ++++++++++++++++++++++++++++++++++
 render/render.c           | 511 ++++++++++++++++++++++++++++++++++------------
 render/scale.c            |   4 +-
 test/pdfrip.c             |   2 +-
 test/x11pdf.c             |   2 +-
 tree/colorspace.c         |   4 +-
 18 files changed, 857 insertions(+), 180 deletions(-)
 create mode 100644 render/rastnone.c

diff --git a/Jamfile b/Jamfile
index a92637ac..4a56f5a9 100644
--- a/Jamfile
+++ b/Jamfile
@@ -87,10 +87,8 @@ Library libfitz :
 	render/fill.c
 	render/stroke.c
 	render/scale.c
+	render/rastnone.c
 	render/render.c
-	render/rendertext.c
-	render/renderpath.c
-	render/renderimage.c
 ;
 
 Library libmupdf :
diff --git a/include/fitz/colorspace.h b/include/fitz/colorspace.h
index 1d6c9a64..f6fae48c 100644
--- a/include/fitz/colorspace.h
+++ b/include/fitz/colorspace.h
@@ -4,6 +4,8 @@ typedef struct fz_colorcube1_s fz_colorcube1;
 typedef struct fz_colorcube3_s fz_colorcube3;
 typedef struct fz_colorcube4_s fz_colorcube4;
 
+enum { FZ_MAXCOLORS = 32 };
+
 struct fz_colorspace_s
 {
 	int refs;
diff --git a/include/fitz/font.h b/include/fitz/font.h
index ea1ad692..7e925461 100644
--- a/include/fitz/font.h
+++ b/include/fitz/font.h
@@ -42,7 +42,7 @@ struct fz_font_s
 
 struct fz_glyph_s
 {
-	int w, h, lsb, top;
+	int x, y, w, h;
 	unsigned char *bitmap;
 };
 
diff --git a/include/fitz/pixmap.h b/include/fitz/pixmap.h
index ecd45270..6d0391fa 100644
--- a/include/fitz/pixmap.h
+++ b/include/fitz/pixmap.h
@@ -13,6 +13,7 @@ struct fz_pixmap_s
 	fz_sample *samples;
 };
 
+fz_error *fz_newpixmapwithrect(fz_pixmap **mapp, fz_irect bbox, int n);
 fz_error *fz_newpixmap(fz_pixmap **mapp, int x, int y, int w, int h, int n);
 void fz_debugpixmap(fz_pixmap *map);
 void fz_clearpixmap(fz_pixmap *map);
diff --git a/include/fitz/render.h b/include/fitz/render.h
index 6e171a06..807b6227 100644
--- a/include/fitz/render.h
+++ b/include/fitz/render.h
@@ -1,25 +1,64 @@
 typedef struct fz_renderer_s fz_renderer;
+typedef struct fz_rastfuncs_s fz_rastfuncs;
+
+#define FZ_BYTE unsigned char
+#define FZ_PID \
+	FZ_BYTE *src, int w, int h, int nx, int ny, \
+	FZ_BYTE *dst0, int dstw, \
+	int u0, int v0, int fa, int fb, int fc, int fd
+#define FZ_PIM \
+	FZ_BYTE *src, int w, int h, int nx, int ny, \
+	FZ_BYTE *dst0, int dstw, \
+	FZ_BYTE *msk0, int mskw, \
+	int u0, int v0, int fa, int fb, int fc, int fd
+
+struct fz_rastfuncs_s
+{
+	void (*mask_g)(int, FZ_BYTE*, FZ_BYTE*);
+	void (*mask_i1)(int, FZ_BYTE*, FZ_BYTE*);
+	void (*mask_o1)(int, FZ_BYTE*, FZ_BYTE*);
+	void (*mask_i1o1)(int, FZ_BYTE*, FZ_BYTE*, FZ_BYTE*);
+	void (*mask_o4w3)(int, FZ_BYTE*, FZ_BYTE*, FZ_BYTE*);
+	void (*mask_i1o4w3)(int, FZ_BYTE*, FZ_BYTE*, FZ_BYTE*, FZ_BYTE*);
+
+	void (*img1_g)(FZ_PID);
+	void (*img1_i1)(FZ_PID);
+	void (*img1_o1)(FZ_PID);
+	void (*img1_i1o1)(FZ_PIM);
+	void (*img1_o4w3)(FZ_PID, FZ_BYTE*);
+	void (*img1_i1o4w3)(FZ_PIM, FZ_BYTE*);
+
+	void (*img4_g)(FZ_PID);
+	void (*img4_o4)(FZ_PID);
+	void (*img4_i1o4)(FZ_PIM);
+};
+
+#undef FZ_PIM
+#undef FZ_PID
+#undef FZ_BYTE
 
 struct fz_renderer_s
 {
+	int maskonly;
 	fz_colorspace *model;
 	fz_glyphcache *cache;
 	fz_gel *gel;
 	fz_ael *ael;
+
+	fz_rastfuncs rast;
+
 	fz_irect clip;
-	fz_pixmap *tmp;
-	fz_pixmap *acc;
-	unsigned char r, g, b;
-	int hasrgb;
+	fz_pixmap *dest;
+	fz_pixmap *over;
+	fz_pixmap *mask;
+	unsigned char rgb[3];
+	int flag;
 };
 
-fz_error *fz_newrenderer(fz_renderer **gcp, fz_colorspace *pcm, int gcmem);
+void fz_defaultrastfuncs(fz_rastfuncs *);
+
+fz_error *fz_newrenderer(fz_renderer **gcp, fz_colorspace *pcm, int maskonly, int gcmem);
 void fz_droprenderer(fz_renderer *gc);
 
-fz_error *fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm);
-fz_error *fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm);
-fz_error *fz_rendertransform(fz_renderer *gc, fz_transformnode *xform, fz_matrix ctm);
-fz_error *fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm);
-fz_error *fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm);
 fz_error *fz_rendertree(fz_pixmap **out, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, fz_irect bbox, int white);
 
diff --git a/mupdf/colorspace1.c b/mupdf/colorspace1.c
index d666904d..5d943fdb 100644
--- a/mupdf/colorspace1.c
+++ b/mupdf/colorspace1.c
@@ -430,7 +430,7 @@ static void separationtoxyz(fz_colorspace *fzcs, float *sep, float *xyz)
 {
 	struct separation *cs = (struct separation *)fzcs;
 	fz_error *error;
-	float alt[32];
+	float alt[FZ_MAXCOLORS];
 
 	error = pdf_evalfunction(cs->tint, sep, fzcs->n, alt, cs->base->n);
 	if (error)
@@ -513,7 +513,7 @@ static void
 indexedtoxyz(fz_colorspace *fzcs, float *ind, float *xyz)
 {
 	pdf_indexed *cs = (pdf_indexed *)fzcs;
-	float alt[32];
+	float alt[FZ_MAXCOLORS];
 	int i, k;
 	i = ind[0] * 255;
 	i = CLAMP(i, 0, cs->high);
diff --git a/mupdf/font.c b/mupdf/font.c
index 229ef932..e2debc85 100644
--- a/mupdf/font.c
+++ b/mupdf/font.c
@@ -110,8 +110,8 @@ ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm)
 
 	glyph->w = 0;
 	glyph->h = 0;
-	glyph->lsb = 0;
-	glyph->top = 0;
+	glyph->x = 0;
+	glyph->y = 0;
 	glyph->bitmap = nil;
 
 	/* freetype mutilates complex glyphs if they are loaded
@@ -161,10 +161,21 @@ ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm)
 
 	glyph->w = face->glyph->bitmap.width;
 	glyph->h = face->glyph->bitmap.rows;
-	glyph->lsb = face->glyph->bitmap_left;
-	glyph->top = face->glyph->bitmap_top;
+	glyph->x = face->glyph->bitmap_left;
+	glyph->y = face->glyph->bitmap_top - glyph->h;
 	glyph->bitmap = face->glyph->bitmap.buffer;
 
+	int i;
+    unsigned char tmp[glyph->w * glyph->h];
+    memcpy(tmp, glyph->bitmap, glyph->w * glyph->h);
+
+    for (i = 0; i < glyph->h; i++)
+    {
+        memcpy( glyph->bitmap + i * glyph->w,
+                tmp + (glyph->h - i - 1) * glyph->w,
+                glyph->w );
+    }
+
 	return nil;
 }
 
diff --git a/mupdf/image2.c b/mupdf/image2.c
index 485766e6..d46bdd0e 100644
--- a/mupdf/image2.c
+++ b/mupdf/image2.c
@@ -141,7 +141,7 @@ static void loadtile8a(pdf_image *src, fz_pixmap *dst, int n)
 static void
 decodetile(fz_pixmap *pix, int bpc, int skip, float *decode)
 {
-	unsigned char table[32][256];
+	unsigned char table[FZ_MAXCOLORS][256];
 	float invtwon = 1.0 / ((1 << bpc) - 1);
 	int x, y, k, i;
 
diff --git a/mupdf/interpret.c b/mupdf/interpret.c
index 6f6f1aaf..c0a9b882 100644
--- a/mupdf/interpret.c
+++ b/mupdf/interpret.c
@@ -228,7 +228,7 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf)
 	float a, b, c, d, e, f;
 	float x, y, w, h;
 	fz_matrix m;
-	float v[32];
+	float v[FZ_MAXCOLORS];
 	int what;
 	int i;
 
diff --git a/mupdf/type3.c b/mupdf/type3.c
index a2612b82..ee7708c0 100644
--- a/mupdf/type3.c
+++ b/mupdf/type3.c
@@ -27,7 +27,6 @@ t3render(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm)
 	fz_pixmap *pixmap;
 	fz_matrix ctm;
 	fz_irect bbox;
-	int i;
 
 	if (cid < 0 || cid > 255)
 		return fz_throw("rangecheck: glyph out of range");
@@ -43,7 +42,7 @@ t3render(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm)
 	ctm = fz_concat(font->matrix, trm);
 	bbox = fz_roundrect(fz_boundtree(tree, ctm));
 
-	error = fz_newrenderer(&gc, nil, GCMEM);
+	error = fz_newrenderer(&gc, pdf_devicegray, 1, GCMEM);
 	if (error)
 		return error;
 	error = fz_rendertree(&pixmap, gc, tree, ctm, bbox, 0);
@@ -53,24 +52,12 @@ t3render(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm)
 
 	assert(pixmap->n == 1);
 
-	glyph->lsb = pixmap->x;
-	glyph->top = pixmap->h + pixmap->y;
+	glyph->x = pixmap->x;
+	glyph->y = pixmap->y;
 	glyph->w = pixmap->w;
 	glyph->h = pixmap->h;
 	glyph->bitmap = pixmap->samples;
 
-	unsigned char tmp[pixmap->w * pixmap->h];
-	memcpy(tmp, pixmap->samples, pixmap->w * pixmap->h);
-
-	for (i = 0; i < pixmap->h; i++)
-	{
-		memcpy(	pixmap->samples + i * pixmap->w,
-				tmp + (pixmap->h - i - 1) * pixmap->w,
-				pixmap->w );
-	}
-
-	/* XXX flip bitmap in ftrender instead; free pixmap */
-
 	return nil;
 }
 
diff --git a/render/glyphcache.c b/render/glyphcache.c
index 1d3b8117..a5f9f2b6 100644
--- a/render/glyphcache.c
+++ b/render/glyphcache.c
@@ -37,7 +37,7 @@ struct fz_val_s
 {
 	fz_hash *ent;
 	unsigned char *data;
-	short w, h, lsb, top;
+	short w, h, x, y;
 	int uses;
 };
 
@@ -239,7 +239,7 @@ fz_debugglyphcache(fz_glyphcache *arena)
 				k->c / 65536.0,
 				k->d / 65536.0,
 				k->e, k->f,
-				b->w, b->h, b->lsb, b->top);
+				b->w, b->h, b->x, b->y);
 		}
 	}
 
@@ -319,8 +319,8 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz
 		val->uses ++;
 		glyph->w = val->w;
 		glyph->h = val->h;
-		glyph->lsb = val->lsb;
-		glyph->top = val->top;
+		glyph->x = val->x;
+		glyph->y = val->y;
 		glyph->bitmap = val->data;
 
 		bubble(arena, val - arena->lru);
@@ -354,8 +354,8 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz
 	val->uses = 0;
 	val->w = glyph->w;
 	val->h = glyph->h;
-	val->lsb = glyph->lsb;
-	val->top = glyph->top;
+	val->x = glyph->x;
+	val->y = glyph->y;
 	val->data = arena->buffer + arena->used;
 
 	arena->used += size;
diff --git a/render/pixmap.c b/render/pixmap.c
index 396b8784..21f36ee0 100644
--- a/render/pixmap.c
+++ b/render/pixmap.c
@@ -24,6 +24,15 @@ fz_newpixmap(fz_pixmap **pixp, int x, int y, int w, int h, int n)
 	return nil;
 }
 
+fz_error *
+fz_newpixmapwithrect(fz_pixmap **pixp, fz_irect r, int n)
+{
+	return fz_newpixmap(pixp,
+				r.min.x, r.min.y,
+				r.max.x - r.min.x,
+				r.max.y - r.min.y, n);
+}
+
 void
 fz_droppixmap(fz_pixmap *pix)
 {
diff --git a/render/rastnone.c b/render/rastnone.c
new file mode 100644
index 00000000..4e4066fa
--- /dev/null
+++ b/render/rastnone.c
@@ -0,0 +1,379 @@
+#include <fitz.h>
+
+typedef unsigned char byte;
+
+/*
+ * Mask -- blit one span (clipped and adjusted)
+ *
+ *	mask_g
+ *	mask_i1
+ *	mask_o1
+ *	mask_i1o1
+ *	mask_o4w3
+ *	mask_i1o4w3
+ */
+
+static void mask_g(int n, byte *src, byte *pix)
+{
+	memcpy(pix, src, n);
+}
+
+static void mask_i1(int n, byte *src, byte *dst)
+{
+	while (n--)
+	{
+		dst[0] = fz_mul255(src[0], dst[0]);
+		src++;
+		dst++;
+	}
+}
+
+static void mask_o1(int n, byte *src, byte *dst)
+{
+	while (n--)
+	{
+		dst[0] = src[0] + fz_mul255(dst[0], 255 - src[0]);
+		src++;
+		dst++;
+	}
+}
+
+static void mask_i1o1(int n, byte *src, byte *msk, byte *dst)
+{
+	while (n--)
+	{
+		byte sa = fz_mul255(src[0], msk[0]);
+		dst[0] = sa + fz_mul255(dst[0], 255 - sa);
+		src++;
+		msk++;
+		dst++;
+	}
+}
+
+static void mask_o4w3(int n, byte *src, byte *dst, byte *rgb)
+{
+	byte sa, ssa;
+	while (n--)
+	{
+		sa = src[0];
+		ssa = 255 - sa;
+		dst[0] = sa + fz_mul255(dst[0], ssa);
+		dst[1] = rgb[0] + fz_mul255((short)dst[1] - rgb[0], ssa);
+		dst[2] = rgb[1] + fz_mul255((short)dst[2] - rgb[1], ssa);
+		dst[3] = rgb[2] + fz_mul255((short)dst[3] - rgb[2], ssa);
+		src ++;
+		dst += 4;
+	}
+}
+
+static void mask_i1o4w3(int n, byte *src, byte *msk, byte *dst, byte *rgb)
+{
+	byte sa, ssa;
+	while (n--)
+	{
+		sa = fz_mul255(src[0], msk[0]);
+		ssa = 255 - sa;
+		dst[0] = sa + fz_mul255(dst[0], ssa);
+		dst[1] = rgb[0] + fz_mul255((short)dst[1] - rgb[0], ssa);
+		dst[2] = rgb[1] + fz_mul255((short)dst[2] - rgb[1], ssa);
+		dst[3] = rgb[2] + fz_mul255((short)dst[3] - rgb[2], ssa);
+		src ++;
+		msk ++;
+		dst += 4;
+	}
+}
+
+/*
+ * Image -- blit entire image
+ *
+ *	img1_g
+ *	img1_i1
+ *	img1_o1
+ *	img1_i1o1
+ *	img1_o4w3
+ *	img1_i1o4w3
+ *
+ *	img4_g
+ *	img4_o4
+ *	img4_i1o4
+ */
+
+#define lerpmsk(a,b,t) (a + (((b - a) * t) >> 16))
+
+static inline byte getmsk(byte *s, int w, int h, int u, int v)
+{
+	if (u < 0 || u >= w) return 0;
+	if (v < 0 || v >= h) return 0;
+	return s[w * v + u];
+}
+
+static inline int samplemsk(byte *s, int w, int h, int u, int v)
+{
+	int ui = u >> 16;
+	int vi = v >> 16;
+	int ud = u & 0xFF;
+	int vd = v & 0xFF;
+	int a = getmsk(s, w, h, ui, vi);
+	int b = getmsk(s, w, h, ui+1, vi);
+	int c = getmsk(s, w, h, ui, vi+1);
+	int d = getmsk(s, w, h, ui+1, vi+1);
+	int ab = lerpmsk(a, b, ud);
+	int cd = lerpmsk(c, d, ud);
+	return lerpmsk(ab, cd, vd);
+}
+
+static inline void lerpargb(byte *dst, byte *a, byte *b, int t)
+{
+	dst[0] = lerpmsk(a[0], b[0], t);
+	dst[1] = lerpmsk(a[1], b[1], t);
+	dst[2] = lerpmsk(a[2], b[2], t);
+	dst[3] = lerpmsk(a[3], b[3], t);
+}
+
+static inline byte *getargb(byte *s, int w, int h, int u, int v)
+{
+	static byte zero[4] = { 0, 0, 0, 0 };
+	if (u < 0 || u >= w) return zero;
+	if (v < 0 || v >= h) return zero;
+	return s + ((w * v + u) << 2);
+}
+
+static inline void sampleargb(byte *s, int w, int h, int u, int v, byte *abcd)
+{
+	byte ab[4];
+	byte cd[4];
+	int ui = u >> 16;
+	int vi = v >> 16;
+	int ud = u & 0xFF;
+	int vd = v & 0xFF;
+	byte *a = getargb(s, w, h, ui, vi);
+	byte *b = getargb(s, w, h, ui+1, vi);
+	byte *c = getargb(s, w, h, ui, vi+1);
+	byte *d = getargb(s, w, h, ui+1, vi+1);
+	lerpargb(ab, a, b, ud);
+	lerpargb(cd, c, d, ud);
+	lerpargb(abcd, ab, cd, vd);
+}
+
+#define PSRC byte *src, int w, int h, int nx, int ny
+#define PDST byte *dst0, int dstw
+#define PMSK byte *msk0, int mskw
+#define PCTM int u0, int v0, int fa, int fb, int fc, int fd
+
+#if 0
+static void example(PSRC, PDST, PMSK, PCTM)
+{
+	while (ny--)
+	{
+		byte *dst = dst0;
+		byte *msk = msk0;
+		int u = u0;
+		int v = v0;
+		while (nx--)
+		{
+			// dst[0] = ... msk[0] ... sample(s, w, h, u, v);
+			dst ++;
+			msk ++;
+			u += fa;
+			v += fb;
+		}
+		u0 += fc;
+		v0 += fd;
+		dst0 += dstw;
+		msk0 += mskw;
+	}
+}
+#endif
+
+#define BLOOP \
+	while (ny--) \
+	{ \
+		byte *dst = dst0; \
+		int u = u0; \
+		int v = v0; \
+		while (nx--) \
+
+#define ELOOP \
+		u0 += fc; \
+		v0 += fd; \
+		dst0 += dstw; \
+	}
+
+#define BLOOPM \
+	while (ny--) \
+	{ \
+		byte *dst = dst0; \
+		byte *msk = msk0; \
+		int u = u0; \
+		int v = v0; \
+		while (nx--) \
+
+#define ELOOPM \
+		u0 += fc; \
+		v0 += fd; \
+		dst0 += dstw; \
+		msk0 += mskw; \
+	}
+
+static void img1_g(PSRC, PDST, PCTM)
+{
+	BLOOP
+	{
+		dst[0] = samplemsk(src, w, h, u, v);
+		dst ++;
+		u += fa;
+		v += fb;
+	}
+	ELOOP
+}
+
+static void img1_i1(PSRC, PDST, PCTM)
+{
+	BLOOP
+	{
+		dst[0] = fz_mul255(dst[0], samplemsk(src, w, h, u, v));
+		dst ++;
+		u += fa;
+		v += fb;
+	}
+	ELOOP
+}
+
+static void img1_o1(PSRC, PDST, PCTM)
+{
+	BLOOP
+	{
+		byte sa = samplemsk(src, w, h, u, v);
+		dst[0] = sa + fz_mul255(dst[0], 255 - sa);
+		dst ++;
+		u += fa;
+		v += fb;
+	}
+	ELOOP
+}
+
+static void img1_i1o1(PSRC, PDST, PMSK, PCTM)
+{
+	BLOOPM
+	{
+		byte sa = fz_mul255(msk[0], samplemsk(src, w, h, u, v));
+		dst[0] = sa + fz_mul255(dst[0], 255 - sa);
+		dst ++;
+		msk ++;
+		u += fa;
+		v += fb;
+	}
+	ELOOPM
+}
+
+static void img1_o4w3(PSRC, PDST, PCTM, byte *rgb)
+{
+	BLOOP
+	{
+		byte sa = samplemsk(src, w, h, u, v);
+		byte ssa = 255 - sa;
+		dst[0] = sa + fz_mul255(dst[0], ssa);
+		dst[1] = rgb[0] + fz_mul255((short)dst[1] - rgb[0], ssa);
+		dst[2] = rgb[1] + fz_mul255((short)dst[2] - rgb[1], ssa);
+		dst[3] = rgb[2] + fz_mul255((short)dst[3] - rgb[2], ssa);
+		dst += 4;
+		u += fa;
+		v += fb;
+	}
+	ELOOP
+}
+
+static void img1_i1o4w3(PSRC, PDST, PMSK, PCTM, byte *rgb)
+{
+	BLOOPM
+	{
+		byte sa = fz_mul255(msk[0], samplemsk(src, w, h, u, v));
+		byte ssa = 255 - sa;
+		dst[0] = sa + fz_mul255(dst[0], ssa);
+		dst[1] = rgb[0] + fz_mul255((short)dst[1] - rgb[0], ssa);
+		dst[2] = rgb[1] + fz_mul255((short)dst[2] - rgb[1], ssa);
+		dst[3] = rgb[2] + fz_mul255((short)dst[3] - rgb[2], ssa);
+		dst += 4;
+		msk ++;
+		u += fa;
+		v += fb;
+	}
+	ELOOPM
+}
+
+static void img4_g(PSRC, PDST, PCTM)
+{
+	BLOOP
+	{
+		sampleargb(src, w, h, u, v, dst);
+		dst += 4;
+		u += fa;
+		v += fb;
+	}
+	ELOOP
+}
+
+static void img4_o4(PSRC, PDST, PCTM)
+{
+	byte argb[4];
+	BLOOP
+	{
+		sampleargb(src, w, h, u, v, argb);
+		byte ssa = 255 - argb[0];
+		dst[0] = argb[0] + fz_mul255(dst[0], ssa);
+		dst[1] = argb[1] + fz_mul255((short)dst[1] - argb[1], ssa);
+		dst[2] = argb[2] + fz_mul255((short)dst[2] - argb[2], ssa);
+		dst[3] = argb[3] + fz_mul255((short)dst[3] - argb[3], ssa);
+		dst += 4;
+		u += fa;
+		v += fb;
+	}
+	ELOOP
+}
+
+static void img4_i1o4(PSRC, PDST, PMSK, PCTM)
+{
+	byte argb[4];
+	BLOOPM
+	{
+		sampleargb(src, w, h, u, v, argb);
+		byte sa = fz_mul255(msk[0], argb[0]);
+		byte ssa = 255 - sa;
+		dst[0] = argb[0] + fz_mul255(dst[0], ssa);
+		dst[1] = argb[1] + fz_mul255((short)dst[1] - argb[1], ssa);
+		dst[2] = argb[2] + fz_mul255((short)dst[2] - argb[2], ssa);
+		dst[3] = argb[3] + fz_mul255((short)dst[3] - argb[3], ssa);
+		dst += 4;
+		msk ++;
+		u += fa;
+		v += fb;
+	}
+	ELOOPM
+}
+
+/*
+ *
+ */
+
+void
+fz_defaultrastfuncs(fz_rastfuncs *tab)
+{
+	tab->mask_g = mask_g;
+	tab->mask_i1 = mask_i1;
+	tab->mask_o1 = mask_o1;
+	tab->mask_i1o1 = mask_i1o1;
+	tab->mask_o4w3 = mask_o4w3;
+	tab->mask_i1o4w3 = mask_i1o4w3;
+
+	tab->img1_g = img1_g;
+	tab->img1_i1 = img1_i1;
+	tab->img1_o1 = img1_o1;
+	tab->img1_i1o1 = img1_i1o1;
+	tab->img1_o4w3 = img1_o4w3;
+	tab->img1_i1o4w3 = img1_i1o4w3;
+
+	tab->img4_g = img4_g;
+	tab->img4_o4 = img4_o4;
+	tab->img4_i1o4 = img4_i1o4;
+}
+
diff --git a/render/render.c b/render/render.c
index 62bce18d..672f312f 100644
--- a/render/render.c
+++ b/render/render.c
@@ -1,30 +1,27 @@
 #include <fitz.h>
 
-fz_error *fz_rendercolortext(fz_renderer*, fz_textnode*, fz_colornode*, fz_matrix);
-fz_error *fz_rendercolorpath(fz_renderer*, fz_pathnode*, fz_colornode*, fz_matrix);
-fz_error *fz_rendertext(fz_renderer*, fz_textnode*, fz_matrix);
-fz_error *fz_renderpath(fz_renderer*, fz_pathnode*, fz_matrix);
+#define FNONE 0
+#define FOVER 1
+#define FMASK 2
+#define FRGB 4
 
-fz_error *fz_rendercolorimage(fz_renderer*, fz_imagenode*, fz_colornode*, fz_matrix);
-fz_error *fz_renderimage(fz_renderer*, fz_imagenode*, fz_matrix);
+static fz_error *rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm);
 
 fz_error *
-fz_newrenderer(fz_renderer **gcp, fz_colorspace *processcolormodel, int gcmem)
+fz_newrenderer(fz_renderer **gcp, fz_colorspace *pcm, int maskonly, int gcmem)
 {
 	fz_error *error;
 	fz_renderer *gc;
 
-	gc = *gcp = fz_malloc(sizeof(fz_renderer));
+	gc = fz_malloc(sizeof(fz_renderer));
 	if (!gc)
 		return fz_outofmem;
 
-	gc->model = processcolormodel;
+	gc->maskonly = maskonly;
+	gc->model = pcm;
 	gc->cache = nil;
 	gc->gel = nil;
 	gc->ael = nil;
-	gc->tmp = nil;
-	gc->acc = nil;
-	gc->hasrgb = 0;
 
 	error = fz_newglyphcache(&gc->cache, gcmem / 32, gcmem);
 	if (error)
@@ -38,230 +35,483 @@ fz_newrenderer(fz_renderer **gcp, fz_colorspace *processcolormodel, int gcmem)
 	if (error)
 		goto cleanup;
 
+	fz_defaultrastfuncs(&gc->rast);
+
+	gc->dest = nil;
+	gc->mask = nil;
+	gc->over = nil;
+	gc->rgb[0] = 0;
+	gc->rgb[1] = 0;
+	gc->rgb[2] = 0;
+	gc->flag = 0;
+
+	*gcp = gc;
 	return nil;
 
 cleanup:
-	if (gc->cache)
-		fz_dropglyphcache(gc->cache);
-	if (gc->gel)
-		fz_dropgel(gc->gel);
-	if (gc->ael)
-		fz_dropael(gc->ael);
+	if (gc->model) fz_dropcolorspace(gc->model);
+	if (gc->cache) fz_dropglyphcache(gc->cache);
+	if (gc->gel) fz_dropgel(gc->gel);
+	if (gc->ael) fz_dropael(gc->ael);
 	fz_free(gc);
-
 	return error;
 }
 
 void
 fz_droprenderer(fz_renderer *gc)
 {
-	if (gc->cache)
-		fz_dropglyphcache(gc->cache);
-	if (gc->gel)
-		fz_dropgel(gc->gel);
-	if (gc->ael)
-		fz_dropael(gc->ael);
-	if (gc->tmp)
-		fz_droppixmap(gc->tmp);
-	if (gc->acc)
-		fz_droppixmap(gc->acc);
+	if (gc->dest) fz_droppixmap(gc->dest);
+	if (gc->mask) fz_droppixmap(gc->mask);
+	if (gc->over) fz_droppixmap(gc->over);
+
+	if (gc->model) fz_dropcolorspace(gc->model);
+	if (gc->cache) fz_dropglyphcache(gc->cache);
+	if (gc->gel) fz_dropgel(gc->gel);
+	if (gc->ael) fz_dropael(gc->ael);
 	fz_free(gc);
 }
 
-fz_error *
-fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm)
+/*
+ * Transform
+ */
+
+static fz_error *
+rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm)
+{
+	fz_error *error;
+printf("transform [%g %g %g %g %g %g]\n",
+transform->m.a, transform->m.b,
+transform->m.c, transform->m.d,
+transform->m.e, transform->m.f);
+puts("{");
+	ctm = fz_concat(transform->m, ctm);
+	error = rendernode(gc, transform->super.first, ctm);
+puts("}");
+	return error;
+}
+
+/*
+ * Color
+ */
+
+static fz_error *
+rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm)
 {
 	fz_error *error;
-	int x, y, w, h;
 	float rgb[3];
 	unsigned char *p;
+	int n;
 
-	assert(gc->model);
+	if (gc->maskonly)
+		return fz_throw("assert: mask only renderer");
+	if (gc->model->n != 3)
+		return fz_throw("assert: non-rgb renderer");
 
 	fz_convertcolor(color->cs, color->samples, gc->model, rgb);
-	gc->r = rgb[0] * 255;
-	gc->g = rgb[1] * 255;
-	gc->b = rgb[2] * 255;
+	gc->rgb[0] = rgb[0] * 255;
+	gc->rgb[1] = rgb[1] * 255;
+	gc->rgb[2] = rgb[2] * 255;
 
-	x = gc->clip.min.x;
-	y = gc->clip.min.y;
-	w = gc->clip.max.x - gc->clip.min.x;
-	h = gc->clip.max.y - gc->clip.min.y;
+printf("color %s [%d %d %d]\n", color->cs->name, gc->rgb[0], gc->rgb[1], gc->rgb[2]);
 
-	error = fz_newpixmap(&gc->tmp, x, y, w, h, 4);
+	error = fz_newpixmapwithrect(&gc->dest, gc->clip, 4);
 	if (error)
 		return error;
 
-	p = gc->tmp->samples;
+	p = gc->dest->samples;
+	n = gc->dest->w * gc->dest->h;
+
+	while (n--)
+	{
+		p[0] = 255;
+		p[1] = gc->rgb[0];
+		p[2] = gc->rgb[1];
+		p[3] = gc->rgb[2];
+		p += 4;
+	}
+
+	return nil;
+}
+
+/*
+ * Path
+ */
+
+enum { HS = 17, VS = 15, SF = 1 };
+
+struct spandata
+{
+	fz_rastfuncs *rast;
+	int x, n;
+	fz_pixmap *dst;
+	fz_pixmap *msk;
+	unsigned char *rgb;
+	int flag;
+};
+
+static void spanfunc(int y, int x, int n, unsigned char *path, void *userdata)
+{
+	struct spandata *user = userdata;
+	fz_rastfuncs *rast = user->rast;
+	fz_pixmap *dst = user->dst;
+	fz_pixmap *msk = user->msk;
+	unsigned char *d;
+	unsigned char *m = nil;
 
-	for (y = 0; y < gc->tmp->h; y++)
+	path += user->x;
+
+	d = dst->samples + ( (y - dst->y) * dst->w + (x - dst->x) ) * dst->n;
+	if (msk)
+		m = msk->samples + ( (y - msk->y) * msk->w + (x - msk->x) ) * msk->n;
+
+	switch (user->flag)
 	{
-		for (x = 0; x < gc->tmp->w; x++)
+	case FNONE:
+		rast->mask_g(user->n, path, d); break;
+	case FOVER:
+		rast->mask_o1(user->n, path, d); break;
+	case FOVER | FMASK:
+		rast->mask_i1o1(user->n, path, m, d); break;
+	case FOVER | FRGB:
+		rast->mask_o4w3(user->n, path, d, user->rgb); break;
+	case FOVER | FMASK | FRGB:
+		rast->mask_i1o4w3(user->n, path, m, d, user->rgb); break;
+	default:
+		assert(!"impossible flag in path span function");
+	}
+}
+
+static fz_error *
+renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm)
+{
+	struct spandata user;
+	fz_error *error;
+	float flatness;
+	fz_irect gbox;
+	fz_irect clip;
+
+	flatness = 0.3 / fz_matrixexpansion(ctm);
+	if (flatness < 0.1)
+		flatness = 0.1;
+
+	fz_resetgel(gc->gel, HS, VS);
+
+	if (path->paint == FZ_STROKE)
+	{
+		if (path->dash)
+			error = fz_dashpath(gc->gel, path, ctm, flatness);
+		else
+			error = fz_strokepath(gc->gel, path, ctm, flatness);
+	}
+	else
+		error = fz_fillpath(gc->gel, path, ctm, flatness);
+	if (error)
+		return error;
+
+	fz_sortgel(gc->gel);
+
+	gbox = fz_boundgel(gc->gel);
+	clip = fz_intersectirects(gc->clip, gbox);
+
+//printf("path clip[%d %d %d %d]\n", clip.min.x, clip.min.y, clip.max.x, clip.max.y);
+
+	user.rast = &gc->rast;
+	user.x = clip.min.x - gbox.min.x;
+	user.n = clip.max.x - clip.min.x;
+	user.flag = gc->flag;
+
+	if (gc->flag == FNONE)
+	{
+		error = fz_newpixmapwithrect(&gc->dest, clip, 1);
+		if (error)
+			return error;
+		fz_clearpixmap(gc->dest);
+		user.dst = gc->dest;
+		user.msk = nil;
+		user.rgb = gc->rgb;
+	}
+	else
+	{
+		user.dst = gc->over;
+		user.msk = gc->mask;
+		user.rgb = gc->rgb;
+	}
+
+	error = fz_scanconvert(gc->gel, gc->ael, path->paint == FZ_EOFILL,
+				clip.min.y, clip.max.y, spanfunc, &user);
+	if (error)
+		return error;
+
+	return nil;
+}
+
+/*
+ * Text
+ */
+
+static void copyglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig, int yorig)
+{
+	int x, y;
+
+	xorig += src->x;
+	yorig += src->y;
+
+	for (y = 0; y < src->h; y++)
+		for (x = 0; x < src->w; x++)
 		{
-			*p++ = 255;
-			*p++ = gc->r;
-			*p++ = gc->g;
-			*p++ = gc->b;
+			int dx = xorig + x - dst->x;
+			int dy = yorig + y - dst->y;
+
+			if (dx < 0) {puts("dx<0");continue;}
+			if (dy < 0) {puts("dy<0");continue;}
+			if (dx >= dst->w) {puts("dx>w");continue;}
+			if (dy >= dst->h) {puts("dy>h");continue;}
+
+			int a = src->bitmap[x + y * src->w];
+			int b = dst->samples[dx + dy * dst->w];
+			int c = a + fz_mul255(b, 255 - a);
+			dst->samples[dx + dy * dst->w] = a;
 		}
+}
+
+static fz_error *
+rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm)
+{
+	fz_error *error;
+	fz_irect tbox;
+	fz_irect clip;
+	fz_matrix tm, trm;
+	fz_glyph glyph;
+	int i, x, y, cid;
+
+	tbox = fz_roundrect(fz_boundnode((fz_node*)text, ctm));
+	clip = fz_intersectirects(gc->clip, tbox);
+
+printf("text %s n=%d [%g %g %g %g] clip[%d %d %d %d]\n",
+	text->font->name, text->len,
+	text->trm.a, text->trm.b, text->trm.c, text->trm.d,
+	clip.min.x, clip.min.y, clip.max.x, clip.max.y);
+fflush(stdout);
+
+	clip.min.x ++;
+	clip.min.y ++;
+	clip.max.x ++;
+	clip.max.y ++;
+
+	error = fz_newpixmapwithrect(&gc->dest, clip, 1);
+	if (error)
+		return error;
+
+	fz_clearpixmap(gc->dest);
+
+	tm = text->trm;
+
+	for (i = 0; i < text->len; i++)
+	{
+		cid = text->els[i].cid;
+		tm.e = text->els[i].x;
+		tm.f = text->els[i].y;
+		trm = fz_concat(tm, ctm);
+		x = fz_floor(trm.e);
+		y = fz_floor(trm.f);
+		trm.e = (trm.e - fz_floor(trm.e));
+		trm.f = (trm.f - fz_floor(trm.f));
+
+		error = fz_renderglyph(gc->cache, &glyph, text->font, cid, trm);
+		if (error)
+			return error;
+
+		copyglyph(gc, gc->dest, &glyph, x, y);
 	}
 
 	return nil;
 }
 
-fz_error *
-fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
+/*
+ * Image
+ */
+
+static fz_error *
+renderimage(fz_renderer *gc, fz_imagenode *image, fz_matrix ctm)
+{
+	return nil;
+}
+
+/*
+ * Over, Mask and Blend
+ */
+
+static fz_error *
+renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
 {
 	fz_error *error;
 	fz_node *child;
 	int cluster = 0;;
 
-	if (!gc->acc)
-	{
-		int x = gc->clip.min.x;
-		int y = gc->clip.min.y;
-		int w = gc->clip.max.x - gc->clip.min.x;
-		int h = gc->clip.max.y - gc->clip.min.y;
+printf("over\n{\n");
 
-		error = fz_newpixmap(&gc->acc, x, y, w, h, gc->model ? 4 : 1);
+	if (!gc->over)
+	{
+printf("  alloc dest!\n");
+		error = fz_newpixmapwithrect(&gc->over, gc->clip, gc->maskonly ? 1 : 4);
 		if (error)
 			return error;
-
-		fz_clearpixmap(gc->acc);
-
+		fz_clearpixmap(gc->over);
 		cluster = 1;
 	}
 
 	for (child = over->super.first; child; child = child->next)
 	{
-		error = fz_rendernode(gc, child, ctm);
+		error = rendernode(gc, child, ctm);
 		if (error)
 			return error;
-
-		if (gc->tmp)
+		if (gc->dest)
 		{
-			fz_blendover(gc->tmp, gc->acc);
-			fz_droppixmap(gc->tmp);
-			gc->tmp = nil;
+			fz_blendover(gc->dest, gc->over);
+			fz_droppixmap(gc->dest);
+			gc->dest = nil;
 		}
 	}
 
 	if (cluster)
 	{
-		gc->tmp = gc->acc;
-		gc->acc = nil;
+		gc->dest = gc->over;
+		gc->over = nil;
 	}
 
+printf("}\n");
+
 	return nil;
 }
 
-fz_error *
-fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
+static fz_error *
+rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
 {
 	fz_error *error;
-	fz_pixmap *oldacc;
-	fz_pixmap *colorpix;
+	fz_pixmap *oldover;
+	fz_pixmap *oldmask;
+	fz_irect oldclip;
+	fz_irect newclip;
 	fz_pixmap *shapepix;
-	fz_node *color;
+	fz_pixmap *colorpix;
 	fz_node *shape;
-	fz_irect newclip;
-	fz_irect oldclip;
-	int x, y, w, h;
+	fz_node *color;
+	float rgb[3];
 
 	shape = mask->super.first;
 	color = shape->next;
 
-	if (gc->acc)
+	/* special case black voodo */
+	if (gc->flag & FOVER)
 	{
-		if (fz_ispathnode(shape) && fz_iscolornode(color))
-			return fz_rendercolorpath(gc, (fz_pathnode*)shape, (fz_colornode*)color, ctm);
-		if (fz_istextnode(shape) && fz_iscolornode(color))
-			return fz_rendercolortext(gc, (fz_textnode*)shape, (fz_colornode*)color, ctm);
-		if (fz_isimagenode(shape) && fz_iscolornode(color))
-			return fz_rendercolorimage(gc, (fz_imagenode*)shape, (fz_colornode*)color, ctm);
+		if (fz_iscolornode(color))
+		{
+			fz_colornode *colorn = (fz_colornode*)color;
+
+			fz_convertcolor(colorn->cs, colorn->samples, gc->model, rgb);
+			gc->rgb[0] = rgb[0] * 255;
+			gc->rgb[1] = rgb[1] * 255;
+			gc->rgb[2] = rgb[2] * 255;
+			gc->flag |= FRGB;
+
+			/* we know these handle FOVER | FRGB */
+			if (fz_ispathnode(shape))
+				return renderpath(gc, (fz_pathnode*)shape, ctm);
+			if (fz_istextnode(shape))
+				return rendertext(gc, (fz_textnode*)shape, ctm);
+			if (fz_isimagenode(shape))
+				return renderimage(gc, (fz_imagenode*)shape, ctm);
+		}
 	}
 
-	oldacc = gc->acc;
 	oldclip = gc->clip;
+	oldover = gc->over;
+	oldmask = gc->mask;
+
 	newclip = fz_roundrect(fz_boundnode(shape, ctm));
 	newclip = fz_intersectirects(newclip, gc->clip);
 
-	gc->acc = nil;
 	gc->clip = newclip;
+	gc->over = nil;
+	gc->mask = nil;
 
-	gc->tmp = nil;
-	error = fz_rendernode(gc, color, ctm);
+printf("mask\n{\n");
+
+	error = rendernode(gc, color, ctm);
 	if (error)
 		return error;
-	colorpix = gc->tmp;
+	colorpix = gc->dest;
+	gc->dest = nil;
 
-	gc->tmp = nil;
-	error = fz_rendernode(gc, shape, ctm);
+	error = rendernode(gc, shape, ctm);
 	if (error)
 		return error;
-	shapepix = gc->tmp;
-
-	x = gc->clip.min.x;
-	y = gc->clip.min.y;
-	w = gc->clip.max.x - gc->clip.min.x;
-	h = gc->clip.max.y - gc->clip.min.y;
+	shapepix = gc->dest;
+	gc->dest = nil;
 
-	error = fz_newpixmap(&gc->tmp, x, y, w, h, colorpix->n);
+	error = fz_newpixmapwithrect(&gc->dest, gc->clip, colorpix->n);
 	if (error)
 		return error;
 
-	fz_clearpixmap(gc->tmp);
+	fz_clearpixmap(gc->dest);
+
+	fz_blendmask(gc->dest, colorpix, shapepix);
 
-	fz_blendmask(gc->tmp, colorpix, shapepix);
+//fz_debugpixmap(gc->dest);getchar();
 
 	fz_droppixmap(shapepix);
 	fz_droppixmap(colorpix);
 
-	gc->acc = oldacc;
+	gc->over = oldover;
+	gc->mask = oldmask;
 	gc->clip = oldclip;
 
+printf("}\n");
+
 	return nil;
 }
 
-fz_error *
-fz_rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm)
-{
-	ctm = fz_concat(transform->m, ctm);
-	return fz_rendernode(gc, transform->super.first, ctm);
-}
+/*
+ * Dispatch
+ */
 
-fz_error *
-fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm)
+static fz_error *
+rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm)
 {
-	assert(gc->tmp == nil);
-
 	if (!node)
 		return nil;
 
+	gc->flag = FNONE;
+	if (gc->over) gc->flag |= FOVER;
+	if (gc->mask) gc->flag |= FMASK;
+
 	switch (node->kind)
 	{
 	case FZ_NOVER:
-		return fz_renderover(gc, (fz_overnode*)node, ctm);
+		return renderover(gc, (fz_overnode*)node, ctm);
 	case FZ_NMASK:
-		return fz_rendermask(gc, (fz_masknode*)node, ctm);
+		return rendermask(gc, (fz_masknode*)node, ctm);
 	case FZ_NTRANSFORM:
-		return fz_rendertransform(gc, (fz_transformnode*)node, ctm);
+		return rendertransform(gc, (fz_transformnode*)node, ctm);
 	case FZ_NCOLOR:
-		return fz_rendercolor(gc, (fz_colornode*)node, ctm);
+		return rendercolor(gc, (fz_colornode*)node, ctm);
 	case FZ_NPATH:
-		return fz_renderpath(gc, (fz_pathnode*)node, ctm);
+		return renderpath(gc, (fz_pathnode*)node, ctm);
 	case FZ_NTEXT:
-		return fz_rendertext(gc, (fz_textnode*)node, ctm);
+		return rendertext(gc, (fz_textnode*)node, ctm);
 	case FZ_NIMAGE:
-		return fz_renderimage(gc, (fz_imagenode*)node, ctm);
+		return renderimage(gc, (fz_imagenode*)node, ctm);
 	case FZ_NLINK:
-		return fz_rendernode(gc, ((fz_linknode*)node)->tree->root, ctm);
-	default:
-		return nil;
+		return rendernode(gc, ((fz_linknode*)node)->tree->root, ctm);
 	}
+
+	return nil;
 }
 
 fz_error *
-fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, fz_irect bbox, int white)
+fz_rendertree(fz_pixmap **outp,
+	fz_renderer *gc, fz_tree *tree, fz_matrix ctm,
+	fz_irect bbox, int white)
 {
 	fz_error *error;
 
@@ -269,27 +519,28 @@ fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, f
 
 	if (white)
 	{
-		error = fz_newpixmap(&gc->acc,
-			bbox.min.x, bbox.min.y,
-			bbox.max.x - bbox.min.x, bbox.max.y - bbox.min.y, 4);
+		assert(gc->maskonly == 0);
+
+		error = fz_newpixmapwithrect(&gc->over, bbox, 4);
 		if (error)
 			return error;
-		memset(gc->acc->samples, 0xff, gc->acc->w * gc->acc->h * gc->acc->n);
+
+		memset(gc->over->samples, 0xff, gc->over->w * gc->over->h * gc->over->n);
 	}
 
-	error = fz_rendernode(gc, tree->root, ctm);
+	error = rendernode(gc, tree->root, ctm);
 	if (error)
 		return error;
 
 	if (white)
 	{
-		*outp = gc->acc;
-		gc->acc = nil;
+		*outp = gc->over;
+		gc->over = nil;
 	}
 	else
 	{
-		*outp = gc->tmp;
-		gc->tmp = nil;
+		*outp = gc->dest;
+		gc->dest = nil;
 	}
 
 	return nil;
diff --git a/render/scale.c b/render/scale.c
index a07d52a7..6b06dcfa 100644
--- a/render/scale.c
+++ b/render/scale.c
@@ -4,7 +4,7 @@ static void
 scalerow(unsigned char *src, unsigned char *dst, int w, int ncomp, int denom)
 {
 	int x, left, k;
-	int sum[32];
+	int sum[FZ_MAXCOLORS];
 
 	left = 0;
 	for (k = 0; k < ncomp; k++)
@@ -37,7 +37,7 @@ scalecols(unsigned char *src, unsigned char *dst, int w, int ncomp, int denom)
 {
 	int x, y, k;
 	unsigned char *s;
-	int sum[32];
+	int sum[FZ_MAXCOLORS];
 
 	for (x = 0; x < w; x++)
 	{
diff --git a/test/pdfrip.c b/test/pdfrip.c
index 877be289..b34dfb11 100644
--- a/test/pdfrip.c
+++ b/test/pdfrip.c
@@ -49,7 +49,7 @@ void showpage(pdf_xref *xref, fz_obj *pageobj)
 		fz_matrix ctm;
 		fz_rect bbox;
 
-		error = fz_newrenderer(&gc, pdf_devicergb, 1024 * 512);
+		error = fz_newrenderer(&gc, pdf_devicergb, 0, 1024 * 512);
 		if (error) fz_abort(error);
 
 		ctm = fz_concat(fz_translate(0, -page->mediabox.max.y), fz_scale(zoom, -zoom));
diff --git a/test/x11pdf.c b/test/x11pdf.c
index 9b1e94c7..b02b2c58 100644
--- a/test/x11pdf.c
+++ b/test/x11pdf.c
@@ -231,7 +231,7 @@ static void pdfopen(char *filename, char *password)
 		}
 	}
 
-	error = fz_newrenderer(&rast, pdf_devicergb, 1024 * 512);
+	error = fz_newrenderer(&rast, pdf_devicergb, 0, 1024 * 512);
 	if (error) fz_abort(error);
 
 	image = nil;
diff --git a/tree/colorspace.c b/tree/colorspace.c
index f5025468..aabf531b 100644
--- a/tree/colorspace.c
+++ b/tree/colorspace.c
@@ -55,8 +55,8 @@ fz_stdconvcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *ds
 void
 fz_stdconvpixmap(fz_colorspace *srcs, fz_pixmap *src, fz_colorspace *dsts, fz_pixmap *dst)
 {
-	float srcv[32];
-	float dstv[32];
+	float srcv[FZ_MAXCOLORS];
+	float dstv[FZ_MAXCOLORS];
 	int y, x, k;
 
 	unsigned char *s = src->samples;
-- 
cgit v1.2.3