summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-10-19 08:21:10 +0200
committerTor Andersson <tor@ghostscript.com>2004-10-19 08:21:10 +0200
commit4d9498561d4a73ffa2389e9fecd8893ff823a95c (patch)
treec25e45034de17227f9652f1375c8b2c473b76757 /render
parent117725ec61dc4953f4070dacfb2aab7024a7df36 (diff)
downloadmupdf-4d9498561d4a73ffa2389e9fecd8893ff823a95c.tar.xz
8-bit rendering and span scissoring
Diffstat (limited to 'render')
-rw-r--r--render/pixmap.c70
-rw-r--r--render/render.c307
-rw-r--r--render/renderpath.c139
-rw-r--r--render/rendertext.c139
-rw-r--r--render/scanconv.c33
5 files changed, 357 insertions, 331 deletions
diff --git a/render/pixmap.c b/render/pixmap.c
index 5dd8bcda..84a542b9 100644
--- a/render/pixmap.c
+++ b/render/pixmap.c
@@ -18,13 +18,13 @@ fz_newpixmap(fz_pixmap **pixp, fz_colorspace *cs, int x, int y, int w, int h, in
pix->a = a;
pix->stride = (pix->n + pix->a) * pix->w;
- pix->samples = fz_malloc(sizeof(short) * pix->stride * pix->h);
+ pix->samples = fz_malloc(sizeof(unsigned char) * pix->stride * pix->h);
if (!pix->samples) {
fz_free(pix);
return fz_outofmem;
}
- memset(pix->samples, 0, sizeof(short) * pix->stride * pix->h);
+ memset(pix->samples, 0, sizeof(unsigned char) * pix->stride * pix->h);
return nil;
}
@@ -39,7 +39,7 @@ fz_freepixmap(fz_pixmap *pix)
void
fz_clearpixmap(fz_pixmap *pix)
{
- memset(pix->samples, 0, sizeof(short) * pix->stride * pix->h);
+ memset(pix->samples, 0, sizeof(unsigned char) * pix->stride * pix->h);
}
void
@@ -47,37 +47,47 @@ fz_debugpixmap(fz_pixmap *pix)
{
int x, y;
- FILE *f = fopen("out.ppm", "w");
+ FILE *ppm = fopen("out.ppm", "w");
+ FILE *pgm = fopen("out.pgm", "w");
+
+ fprintf(ppm, "P6\n%d %d\n255\n", pix->w, pix->h);
+ fprintf(pgm, "P5\n%d %d\n255\n", pix->w, pix->h);
if (pix->n == 3 && pix->a == 1)
{
- fprintf(f, "P6\n%d %d\n255\n", pix->w, pix->h);
for (y = 0; y < pix->h; y++)
for (x = 0; x < pix->w; x++)
{
- int r = (pix->samples[x * 4 + y * pix->stride + 0] * 255) >> 14;
- int g = (pix->samples[x * 4 + y * pix->stride + 1] * 255) >> 14;
- int b = (pix->samples[x * 4 + y * pix->stride + 2] * 255) >> 14;
- int a = (pix->samples[x * 4 + y * pix->stride + 3] * 255) >> 14;
- putc(((r * a) / 255) + (255 - a), f);
- putc(((g * a) / 255) + (255 - a), f);
- putc(((b * a) / 255) + (255 - a), f);
- // putc(a, f);
- // putc(a, f);
- // putc(a, f);
+ int r = pix->samples[x * 4 + y * pix->stride + 0];
+ int g = pix->samples[x * 4 + y * pix->stride + 1];
+ int b = pix->samples[x * 4 + y * pix->stride + 2];
+ int a = pix->samples[x * 4 + y * pix->stride + 3];
+
+ //putc(r, ppm);
+ //putc(g, ppm);
+ //putc(b, ppm);
+ putc(((r * a) / 255) + (255 - a), ppm);
+ putc(((g * a) / 255) + (255 - a), ppm);
+ putc(((b * a) / 255) + (255 - a), ppm);
+
+ putc(a, pgm);
}
}
else if (pix->n == 0 && pix->a == 1)
{
- fprintf(f, "P5\n%d %d\n255\n", pix->w, pix->h);
for (y = 0; y < pix->h; y++)
for (x = 0; x < pix->w; x++)
{
- int a = (pix->samples[x + y * pix->stride] * 255) >> 14;
- putc(a, f);
+ int a = pix->samples[x + y * pix->stride];
+ putc(0, ppm);
+ putc(0, ppm);
+ putc(0, ppm);
+ putc(a, pgm);
}
}
- fclose(f);
+
+ fclose(ppm);
+ fclose(pgm);
}
void
@@ -92,18 +102,18 @@ fz_blendover(fz_pixmap *src, fz_pixmap *dst)
for (y = 0; y < dst->h; y++)
{
- short *s = &src->samples[y * src->stride];
- short *d = &dst->samples[y * dst->stride];
+ unsigned char *s = &src->samples[y * src->stride];
+ unsigned char *d = &dst->samples[y * dst->stride];
for (x = 0; x < dst->w; x++)
{
int sa = s[3];
- int ssa = (1 << 14) - sa;
+ int ssa = 255 - sa;
- d[0] = ((s[0] * sa) >> 14) + ((d[0] * ssa) >> 14);
- d[1] = ((s[1] * sa) >> 14) + ((d[1] * ssa) >> 14);
- d[2] = ((s[2] * sa) >> 14) + ((d[2] * ssa) >> 14);
- d[3] = sa + ((ssa * d[3]) >> 14);
+ d[0] = fz_mul255(s[0], sa) + fz_mul255(d[0], ssa);
+ d[1] = fz_mul255(s[1], sa) + fz_mul255(d[1], ssa);
+ d[2] = fz_mul255(s[2], sa) + fz_mul255(d[2], ssa);
+ d[3] = sa + fz_mul255(d[3], ssa);
s += 4;
d += 4;
@@ -124,15 +134,15 @@ fz_blendmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
for (y = 0; y < dst->h; y++)
{
- short *d = &dst->samples[y * dst->stride];
- short *s = &src->samples[y * src->stride];
- short *m = &msk->samples[y * msk->stride];
+ unsigned char *d = &dst->samples[y * dst->stride];
+ unsigned char *s = &src->samples[y * src->stride];
+ unsigned char *m = &msk->samples[y * msk->stride];
for (x = 0; x < dst->w; x++)
{
for (k = 0; k < dst->n; k++)
*d++ = *s++;
- *d++ = (*m++ * *s++) >> 14;
+ *d++ = fz_mul255(*m++, *s++);
}
}
}
diff --git a/render/render.c b/render/render.c
index fab6262d..d46d5b71 100644
--- a/render/render.c
+++ b/render/render.c
@@ -1,19 +1,9 @@
#include <fitz.h>
-enum { NONE, OVER, MASK };
-
-struct fz_renderer_s
-{
- fz_colorspace *model;
- fz_glyphcache *cache;
- fz_gel *gel;
- fz_ael *ael;
- int mode;
- int x, y, w, h;
- fz_pixmap *tmp;
- fz_pixmap *acc;
- short r, g, b;
-};
+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);
fz_error *
fz_newrenderer(fz_renderer **gcp, fz_colorspace *processcolormodel)
@@ -29,7 +19,7 @@ fz_newrenderer(fz_renderer **gcp, fz_colorspace *processcolormodel)
gc->cache = nil;
gc->gel = nil;
gc->ael = nil;
- gc->mode = NONE;
+ gc->mode = FZ_RNONE;
gc->tmp = nil;
gc->acc = nil;
@@ -75,263 +65,6 @@ fz_freerenderer(fz_renderer *gc)
fz_free(gc);
}
-static void blitglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo)
-{
- int sx, sy, dx, dy, a, b, c;
-
- for (sy = 0; sy < gl->h; sy++)
- {
- for (sx = 0; sx < gl->w; sx++)
- {
- dx = xo + sx + gl->lsb - out->x;
- dy = yo - sy + gl->top - out->y;
-
- if (dx < 0) continue;
- if (dy < 0) continue;
- if (dx >= out->w) continue;
- if (dy >= out->h) continue;
-
- a = gl->bitmap[sx + sy * gl->w] * 64;
- b = out->samples[dx + dy * out->stride];
- c = MAX(a, b);
- out->samples[dx + dy * out->stride] = c;
- }
- }
-}
-
-static void blitcolorglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo, fz_renderer *gc)
-{
- int sx, sy, dx, dy, sa, ssa;
- short *p;
-
- for (sy = 0; sy < gl->h; sy++)
- {
- for (sx = 0; sx < gl->w; sx++)
- {
- dx = xo + sx + gl->lsb - out->x;
- dy = yo - sy + gl->top - out->y;
-
- if (dx < 0) continue;
- if (dy < 0) continue;
- if (dx >= out->w) continue;
- if (dy >= out->h) continue;
-
- sa = gl->bitmap[sx + sy * gl->w] * 64;
- ssa = (1 << 14) - sa;
-
- p = out->samples + dx * 4 + dy * out->stride;
- p[0] = ((gc->r * sa) >> 14) + ((p[0] * ssa) >> 14);
- p[1] = ((gc->g * sa) >> 14) + ((p[1] * ssa) >> 14);
- p[2] = ((gc->b * sa) >> 14) + ((p[2] * ssa) >> 14);
- p[3] = sa + ((ssa * p[3]) >> 14);
- }
- }
-}
-
-fz_error *
-fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm)
-{
- fz_error *error;
- fz_glyph gl;
- float x, y;
- int g, i, ix, iy;
- fz_matrix tm, trm;
-
-puts("render text");
-
- error = fz_newpixmap(&gc->tmp, nil, gc->x, gc->y, gc->w, gc->h, 0, 1);
- if (error)
- return error;
-
- tm = text->trm;
-
- for (i = 0; i < text->len; i++)
- {
- g = text->els[i].cid;
- x = text->els[i].x;
- y = text->els[i].y;
-
- tm.e = x;
- tm.f = y;
- trm = fz_concat(tm, ctm);
-
- ix = floor(trm.e);
- iy = floor(trm.f);
-
- trm.e = (trm.e - floor(trm.e));
- trm.f = (trm.f - floor(trm.f));
-
- error = fz_renderglyph(gc->cache, &gl, text->font, g, trm);
- if (error)
- return error;
-
- blitglyph(gc->tmp, &gl, ix, iy);
- }
-
- return nil;
-}
-
-static fz_error *
-rcolortext(fz_renderer *gc, fz_textnode *text, fz_colornode *color, fz_matrix ctm)
-{
- fz_error *error;
- fz_glyph gl;
- float x, y;
- int g, i, ix, iy;
- fz_matrix tm, trm;
- float rgb[3];
-
-puts("render (mask color text)");
-
- fz_convertcolor(color->cs, color->samples, gc->model, rgb);
- gc->r = rgb[0] * (1 << 14);
- gc->g = rgb[1] * (1 << 14);
- gc->b = rgb[2] * (1 << 14);
-
- tm = text->trm;
-
- for (i = 0; i < text->len; i++)
- {
- g = text->els[i].cid;
- x = text->els[i].x;
- y = text->els[i].y;
-
- tm.e = x;
- tm.f = y;
- trm = fz_concat(tm, ctm);
-
- ix = floor(trm.e);
- iy = floor(trm.f);
-
- trm.e = (trm.e - floor(trm.e));
- trm.f = (trm.f - floor(trm.f));
-
- error = fz_renderglyph(gc->cache, &gl, text->font, g, trm);
- if (error)
- return error;
-
- blitcolorglyph(gc->acc, &gl, ix, iy, gc);
- }
-
- return nil;
-}
-
-static void blitspan(int y, int x, int n, short *list, void *userdata)
-{
- fz_pixmap *pix = (fz_pixmap*)userdata;
-
- if (y < 0) return;
- if (y >= pix->h) return;
- short d = 0;
- while (x < 0 && n) {
- d += *list++; n--; x ++;
- }
- if (x + n >= pix->w)
- n = pix->w - x;
- short *p = pix->samples + (y - pix->y) * pix->stride + (x - pix->x);
- while (n--)
- {
- d += *list++;
- *p++ = d * 64;
- }
-}
-
-fz_error *
-fz_renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm)
-{
- fz_error *error;
-
-puts("render path");
-
- float flatness = 0.3 / ctm.a;
-
- fz_resetgel(gc->gel, 16, 16);
-
- if (path->paint == FZ_STROKE)
- {
- if (path->dash)
- fz_dashpath(gc->gel, path, ctm, flatness);
- else
- fz_strokepath(gc->gel, path, ctm, flatness);
- }
- else
- fz_fillpath(gc->gel, path, ctm, flatness);
-
- fz_sortgel(gc->gel);
-
- error = fz_newpixmap(&gc->tmp, nil, gc->x, gc->y, gc->w, gc->h, 0, 1);
- if (error)
- return error;
-
- fz_clearpixmap(gc->tmp);
-
- fz_scanconvert(gc->gel, gc->ael, path->paint == FZ_EOFILL, blitspan, gc->tmp);
-
- return nil;
-}
-
-static void blitcolorspan(int y, int x, int n, short *list, void *userdata)
-{
- fz_renderer *gc = userdata;
- fz_pixmap *pix = gc->acc;
- short *p;
- short d, sa, ssa;
-
- assert(pix->n == 3);
- assert(pix->a == 1);
-
- p = pix->samples + (y - pix->y) * pix->stride + (x - pix->x) * 4;
- d = 0;
-
- while (n --)
- {
- d += *list++;
-
- sa = d * 64;
- ssa = (1 << 14) - sa;
-
- p[0] = ((gc->r * sa) >> 14) + ((p[0] * ssa) >> 14);
- p[1] = ((gc->g * sa) >> 14) + ((p[1] * ssa) >> 14);
- p[2] = ((gc->b * sa) >> 14) + ((p[2] * ssa) >> 14);
- p[3] = sa + ((ssa * p[3]) >> 14);
-
- p += 4;
- }
-}
-
-static fz_error *
-rcolorpath(fz_renderer *gc, fz_pathnode *path, fz_colornode *color, fz_matrix ctm)
-{
- float rgb[3];
-
-puts("render (mask color path)");
-
- float flatness = 0.3 / ctm.a;
-
- fz_resetgel(gc->gel, 17, 15);
-
- if (path->paint == FZ_STROKE)
- {
- if (path->dash)
- fz_dashpath(gc->gel, path, ctm, flatness);
- else
- fz_strokepath(gc->gel, path, ctm, flatness);
- }
- else
- fz_fillpath(gc->gel, path, ctm, flatness);
-
- fz_sortgel(gc->gel);
-
- fz_convertcolor(color->cs, color->samples, gc->model, rgb);
- gc->r = rgb[0] * (1 << 14);
- gc->g = rgb[1] * (1 << 14);
- gc->b = rgb[2] * (1 << 14);
-
- fz_scanconvert(gc->gel, gc->ael, path->paint == FZ_EOFILL, blitcolorspan, gc);
-
- return nil;
-}
-
fz_error *
fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm)
{
@@ -340,9 +73,9 @@ fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm)
float rgb[3];
fz_convertcolor(color->cs, color->samples, gc->model, rgb);
- gc->r = rgb[0] * (1 << 14);
- gc->g = rgb[1] * (1 << 14);
- gc->b = rgb[2] * (1 << 14);
+ gc->r = rgb[0] * 255;
+ gc->g = rgb[1] * 255;
+ gc->b = rgb[2] * 255;
puts("render color");
@@ -352,13 +85,13 @@ puts("render color");
for (y = 0; y < gc->tmp->h; y++)
{
- short *p = &gc->tmp->samples[y * gc->tmp->stride];
+ unsigned char *p = &gc->tmp->samples[y * gc->tmp->stride];
for (x = 0; x < gc->tmp->w; x++)
{
*p++ = gc->r;
*p++ = gc->g;
*p++ = gc->b;
- *p++ = 1 << 14;
+ *p++ = 255;
}
}
@@ -398,12 +131,11 @@ fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
fz_error *error;
fz_pixmap *oldacc = nil;
int oldmode;
-
+int i;
/* uh-oh! we have a new over cluster */
- if (gc->mode != OVER)
+ if (gc->mode != FZ_ROVER)
{
-puts("render over");
oldacc = gc->acc;
error = fz_newpixmap(&gc->acc, gc->model, gc->x, gc->y, gc->w, gc->h, 3, 1);
if (error)
@@ -412,7 +144,7 @@ puts("render over");
}
oldmode = gc->mode;
- gc->mode = OVER;
+ gc->mode = FZ_ROVER;
gc->tmp = nil;
@@ -426,9 +158,8 @@ puts("render over");
gc->mode = oldmode;
/* uh-oh! end of over cluster */
- if (gc->mode != OVER)
+ if (gc->mode != FZ_ROVER)
{
-printf("end over\n");
gc->tmp = gc->acc;
gc->acc = oldacc;
}
@@ -449,16 +180,16 @@ fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
color = mask->super.child;
shape = color->next;
- if (gc->mode == OVER)
+ if (gc->mode == FZ_ROVER)
{
if (fz_ispathnode(shape) && fz_iscolornode(color))
- return rcolorpath(gc, (fz_pathnode*)shape, (fz_colornode*)color, ctm);
+ return fz_rendercolorpath(gc, (fz_pathnode*)shape, (fz_colornode*)color, ctm);
if (fz_istextnode(shape) && fz_iscolornode(color))
- return rcolortext(gc, (fz_textnode*)shape, (fz_colornode*)color, ctm);
+ return fz_rendercolortext(gc, (fz_textnode*)shape, (fz_colornode*)color, ctm);
}
oldmode = gc->mode;
- gc->mode = MASK;
+ gc->mode = FZ_RMASK;
gc->tmp = nil;
error = fz_rendernode(gc, color, ctm);
@@ -489,7 +220,6 @@ fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
fz_error *
fz_rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm)
{
-puts("render transform");
ctm = fz_concat(transform->m, ctm);
return fz_rendernode(gc, transform->super.child, ctm);
}
@@ -537,7 +267,6 @@ fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, f
*outp = gc->tmp;
gc->tmp = nil;
-
return nil;
}
diff --git a/render/renderpath.c b/render/renderpath.c
new file mode 100644
index 00000000..9e805a53
--- /dev/null
+++ b/render/renderpath.c
@@ -0,0 +1,139 @@
+#include <fitz.h>
+
+enum { HS = 17, VS = 15 };
+
+static fz_error *pathtogel(fz_gel *gel, fz_pathnode *path, fz_matrix ctm)
+{
+ float flatness = 0.3 / ctm.a;
+ if (flatness < 0.1)
+ flatness = 0.1;
+
+ if (path->paint == FZ_STROKE)
+ {
+ if (path->dash)
+ return fz_dashpath(gel, path, ctm, flatness);
+ return fz_strokepath(gel, path, ctm, flatness);
+ }
+ return fz_fillpath(gel, path, ctm, flatness);
+}
+
+static void blitcolorspan(int y, int x0, int n, short *list, void *userdata)
+{
+ fz_renderer *gc = userdata;
+ fz_pixmap *pix = gc->acc;
+ unsigned char sa;
+ unsigned char ssa;
+ unsigned char *p;
+ unsigned char r = gc->r;
+ unsigned char g = gc->g;
+ unsigned char b = gc->b;
+
+ sa = 0;
+
+ while (x0 < pix->x)
+ {
+ sa += *list++;
+ x0 ++;
+ n --;
+ }
+
+ if (n > pix->w)
+ n = pix->w;
+
+ p = &pix->samples[(y - pix->y) * pix->stride + (x0 - pix->x) * 4];
+
+ while (n--)
+ {
+ sa += *list++;
+ ssa = 255 - sa;
+
+ p[0] = fz_mul255(r, sa) + fz_mul255(p[0], ssa);
+ p[1] = fz_mul255(g, sa) + fz_mul255(p[1], ssa);
+ p[2] = fz_mul255(b, sa) + fz_mul255(p[2], ssa);
+ p[3] = sa + fz_mul255(p[3], ssa);
+
+ p += 4;
+ }
+}
+
+static void blitalphaspan(int y, int x0, int n, short *list, void *userdata)
+{
+ fz_pixmap *pix = userdata;
+ unsigned char a;
+ unsigned char *p;
+
+ a = 0;
+
+ while (x0 < pix->x)
+ {
+ a += *list++;
+ x0 ++;
+ n --;
+ }
+
+ if (n > pix->w)
+ n = pix->w;
+
+ p = &pix->samples[(y - pix->y) * pix->stride + (x0 - pix->x) * 4];
+
+ while (n--)
+ {
+ a += *list++;
+ *p++ = a;
+ }
+}
+
+fz_error *
+fz_rendercolorpath(fz_renderer *gc, fz_pathnode *path, fz_colornode *color, fz_matrix ctm)
+{
+ fz_error *error;
+ float rgb[3];
+
+ fz_resetgel(gc->gel, HS, VS);
+
+ error = pathtogel(gc->gel, path, ctm);
+ if (error)
+ return error;
+
+ fz_sortgel(gc->gel);
+
+ fz_convertcolor(color->cs, color->samples, gc->model, rgb);
+ gc->r = rgb[0] * 255;
+ gc->g = rgb[1] * 255;
+ gc->b = rgb[2] * 255;
+
+ fz_scanconvert(gc->gel, gc->ael,
+ path->paint == FZ_EOFILL,
+ gc->y, gc->y + gc->h,
+ blitcolorspan, gc);
+
+ return nil;
+}
+
+fz_error *
+fz_renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm)
+{
+ fz_error *error;
+
+ fz_resetgel(gc->gel, HS, VS);
+
+ error = pathtogel(gc->gel, path, ctm);
+ if (error)
+ return error;
+
+ fz_sortgel(gc->gel);
+
+ error = fz_newpixmap(&gc->tmp, nil, gc->x, gc->y, gc->w, gc->h, 0, 1);
+ if (error)
+ return error;
+
+ fz_clearpixmap(gc->tmp);
+
+ fz_scanconvert(gc->gel, gc->ael,
+ path->paint == FZ_EOFILL,
+ gc->y, gc->y + gc->h,
+ blitalphaspan, gc->tmp);
+
+ return nil;
+}
+
diff --git a/render/rendertext.c b/render/rendertext.c
new file mode 100644
index 00000000..cc181657
--- /dev/null
+++ b/render/rendertext.c
@@ -0,0 +1,139 @@
+#include <fitz.h>
+
+static void blitalphaglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo)
+{
+ int sx, sy, dx, dy, a, b, c;
+
+ for (sy = 0; sy < gl->h; sy++)
+ {
+ for (sx = 0; sx < gl->w; sx++)
+ {
+ dx = xo + sx + gl->lsb - out->x;
+ dy = yo - sy + gl->top - out->y;
+
+ if (dx < 0) continue;
+ if (dy < 0) continue;
+ if (dx >= out->w) continue;
+ if (dy >= out->h) continue;
+
+ a = gl->bitmap[sx + sy * gl->w];
+ b = out->samples[dx + dy * out->stride];
+ c = MAX(a, b);
+ out->samples[dx + dy * out->stride] = c;
+ }
+ }
+}
+
+static void blitcolorglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo, fz_renderer *gc)
+{
+ int sx, sy, dx, dy, sa, ssa;
+ unsigned char *p;
+
+ for (sy = 0; sy < gl->h; sy++)
+ {
+ for (sx = 0; sx < gl->w; sx++)
+ {
+ dx = xo + sx + gl->lsb - out->x;
+ dy = yo - sy + gl->top - out->y;
+
+ if (dx < 0) continue;
+ if (dy < 0) continue;
+ if (dx >= out->w) continue;
+ if (dy >= out->h) continue;
+
+ sa = gl->bitmap[sx + sy * gl->w];
+ ssa = 255 - sa;
+
+ p = out->samples + dx * 4 + dy * out->stride;
+ p[0] = fz_mul255(gc->r, sa) + fz_mul255(p[0], ssa);
+ p[1] = fz_mul255(gc->g, sa) + fz_mul255(p[1], ssa);
+ p[2] = fz_mul255(gc->b, sa) + fz_mul255(p[2], ssa);
+ p[3] = sa + fz_mul255(ssa, p[3]);
+ }
+ }
+}
+
+fz_error *
+fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm)
+{
+ fz_error *error;
+ fz_glyph gl;
+ float x, y;
+ int g, i, ix, iy;
+ fz_matrix tm, trm;
+
+ error = fz_newpixmap(&gc->tmp, nil, gc->x, gc->y, gc->w, gc->h, 0, 1);
+ if (error)
+ return error;
+
+ tm = text->trm;
+
+ for (i = 0; i < text->len; i++)
+ {
+ g = text->els[i].cid;
+ x = text->els[i].x;
+ y = text->els[i].y;
+
+ tm.e = x;
+ tm.f = y;
+ trm = fz_concat(tm, ctm);
+
+ ix = floor(trm.e);
+ iy = floor(trm.f);
+
+ trm.e = (trm.e - floor(trm.e));
+ trm.f = (trm.f - floor(trm.f));
+
+ error = fz_renderglyph(gc->cache, &gl, text->font, g, trm);
+ if (error)
+ return error;
+
+ blitalphaglyph(gc->tmp, &gl, ix, iy);
+ }
+
+ return nil;
+}
+
+fz_error *
+fz_rendercolortext(fz_renderer *gc, fz_textnode *text, fz_colornode *color, fz_matrix ctm)
+{
+ fz_error *error;
+ fz_glyph gl;
+ float x, y;
+ int g, i, ix, iy;
+ fz_matrix tm, trm;
+ float rgb[3];
+
+ fz_convertcolor(color->cs, color->samples, gc->model, rgb);
+ gc->r = rgb[0] * 255;
+ gc->g = rgb[1] * 255;
+ gc->b = rgb[2] * 255;
+
+ tm = text->trm;
+
+ for (i = 0; i < text->len; i++)
+ {
+ g = text->els[i].cid;
+ x = text->els[i].x;
+ y = text->els[i].y;
+
+ tm.e = x;
+ tm.f = y;
+ trm = fz_concat(tm, ctm);
+
+ ix = floor(trm.e);
+ iy = floor(trm.f);
+
+ trm.e = (trm.e - floor(trm.e));
+ trm.f = (trm.f - floor(trm.f));
+
+ error = fz_renderglyph(gc->cache, &gl, text->font, g, trm);
+ if (error)
+ return error;
+
+ blitcolorglyph(gc->acc, &gl, ix, iy, gc);
+ }
+
+ return nil;
+}
+
diff --git a/render/scanconv.c b/render/scanconv.c
index 662c5c62..b2689ae2 100644
--- a/render/scanconv.c
+++ b/render/scanconv.c
@@ -76,7 +76,7 @@ fz_emitdeltas(short *list, int y, int xofs, int n)
*/
fz_error *
-fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill,
+fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, int y0, int y1,
void (*blitfunc)(int,int,int,short*,void*), void *blitdata)
{
fz_error *error;
@@ -86,8 +86,8 @@ fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill,
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 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;
@@ -96,10 +96,11 @@ fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill,
if (gel->len == 0)
return nil;
- deltas = fz_malloc(sizeof(short) * (xmax - xmin));
+ deltas = fz_malloc(sizeof(short) * (xmax - xmin + 1));
if (!deltas)
return fz_outofmem;
- memset(deltas, 0, sizeof(short) * (xmax - xmin));
+
+ memset(deltas, 0, sizeof(short) * (xmax - xmin + 1));
e = 0;
y = gel->edges[0].y;
@@ -110,8 +111,11 @@ fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill,
{
yc = fz_idiv(y, vs);
if (yc != yd) {
- blitfunc(yd, xmin, xmax - xmin, deltas, blitdata);
- memset(deltas, 0, sizeof(short) * (xmax - xmin));
+ if (yd >= y0 && yd < y1)
+ {
+ blitfunc(yd, xmin, xmax - xmin, deltas, blitdata);
+ memset(deltas, 0, sizeof(short) * (xmax - xmin + 1));
+ }
}
yd = yc;
@@ -121,10 +125,13 @@ fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill,
return error;
}
- if (eofill)
- evenodd(ael, deltas, xofs, hs);
- else
- nonzerowinding(ael, deltas, xofs, hs);
+ if (yd >= y0 && yd < y1)
+ {
+ if (eofill)
+ evenodd(ael, deltas, xofs, hs);
+ else
+ nonzerowinding(ael, deltas, xofs, hs);
+ }
fz_advanceael(ael);
@@ -134,8 +141,10 @@ fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill,
y = gel->edges[e].y;
}
- blitfunc(yd, xmin, xmax - xmin, deltas, blitdata);
+ if (yd >= y0 && yd < y1)
+ blitfunc(yd, xmin, xmax - xmin, deltas, blitdata);
+ fz_free(deltas);
return nil;
}