summaryrefslogtreecommitdiff
path: root/render/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/render.c')
-rw-r--r--render/render.c421
1 files changed, 313 insertions, 108 deletions
diff --git a/render/render.c b/render/render.c
index d7359d90..1e152410 100644
--- a/render/render.c
+++ b/render/render.c
@@ -11,6 +11,7 @@ struct fz_renderer_s
int x, y, w, h;
fz_pixmap *tmp;
fz_pixmap *acc;
+ short r, g, b;
};
fz_error *
@@ -66,119 +67,40 @@ fz_freerenderer(fz_renderer *gc)
if (gc->ael)
fz_freeael(gc->ael);
if (gc->tmp)
- fz_droppixmap(gc->tmp);
+ fz_freepixmap(gc->tmp);
if (gc->acc)
- fz_droppixmap(gc->acc);
+ fz_freepixmap(gc->acc);
fz_free(gc);
}
-fz_error *
-fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
+static void blitglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo)
{
- fz_error *error;
- fz_node *node;
- int oldmode;
-
- oldmode = gc->mode;
- gc->mode = OVER;
-
-printf("renderover ; acc=3,1\n");
-
- error = fz_newpixmap(&gc->acc, gc->x, gc->y, gc->w, gc->h, 3, 1);
- if (error)
- return error;
-
- fz_clearpixmap(gc->acc);
+ int sx, sy, dx, dy, a, b, c;
- for (node = over->super.child; node; node = node->next)
+ for (sy = 0; sy < gl->h; sy++)
{
- gc->tmp = nil;
- error = fz_rendernode(gc, node, ctm);
- if (error)
- return error;
- if (gc->tmp)
+ for (sx = 0; sx < gl->w; sx++)
{
-printf(" over -> %d,%d\n", gc->tmp->n, gc->tmp->a);
- fz_blendover(gc->acc, gc->tmp, gc->acc);
- fz_droppixmap(gc->tmp);
- }
-else printf(" -> nil\n");
- }
-
- gc->tmp = gc->acc;
- gc->acc = nil;
-
- gc->mode = oldmode;
-
- return nil;
-}
-
-fz_error *
-fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
-{
- fz_error *error;
- fz_pixmap *colorpix;
- fz_pixmap *shapepix;
- fz_node *color;
- fz_node *shape;
- int oldmode;
-
- color = mask->super.child;
- shape = color->next;
-
-// if (fz_ispathnode(shape) && fz_iscolornode(color))
-// return rcolorpath(gc, shape, color, ctm);
-// if (fz_istextnode(shape) && fz_iscolornode(color))
-// return rcolortext(gc, shape, color, ctm);
-
- oldmode = gc->mode;
- gc->mode = MASK;
-
-printf("rendermask\n");
-
- gc->tmp = nil;
- error = fz_rendernode(gc, color, ctm);
- if (error)
- return error;
- colorpix = gc->tmp;
-
-printf(" -> color %d,%d\n", colorpix->n, colorpix->a);
-
- gc->tmp = nil;
- error = fz_rendernode(gc, shape, ctm);
- if (error)
- return error;
- shapepix = gc->tmp;
-
-printf(" -> shape %d,%d\n", shapepix->n, shapepix->a);
-
- error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, colorpix->n, 1);
- if (error)
- return error;
-
-printf(" -> blend %d,%d\n", gc->tmp->n, gc->tmp->a);
-
- fz_blendmask(gc->tmp, colorpix, shapepix);
-
- fz_droppixmap(shapepix);
- fz_droppixmap(colorpix);
-
- gc->mode = oldmode;
+ dx = xo + sx + gl->lsb - out->x;
+ dy = yo - sy + gl->top - out->y;
- return nil;
-}
+ if (dx < 0) continue;
+ if (dy < 0) continue;
+ if (dx >= out->w) continue;
+ if (dy >= out->h) continue;
-fz_error *
-fz_rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm)
-{
-printf("rendertransform\n");
- ctm = fz_concat(ctm, transform->m);
- return fz_rendernode(gc, transform->super.child, ctm);
+ 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 blitglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo)
+static void blitcolorglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo, short r, short g, short b)
{
- int sx, sy, dx, dy, a, b, c;
+ int sx, sy, dx, dy, sa, ssa;
+ short *p;
for (sy = 0; sy < gl->h; sy++)
{
@@ -192,10 +114,14 @@ static void blitglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo)
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;
+ sa = gl->bitmap[sx + sy * gl->w] * 64;
+ ssa = (1 << 14) - sa;
+
+ p = out->samples + dx * 4 + dy * out->stride;
+ p[0] = ((r * sa) >> 14) + ((p[0] * ssa) >> 14);
+ p[1] = ((g * sa) >> 14) + ((p[1] * ssa) >> 14);
+ p[2] = ((b * sa) >> 14) + ((p[2] * ssa) >> 14);
+ p[3] = sa + ((ssa * p[3]) >> 14);
}
}
}
@@ -209,7 +135,7 @@ fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm)
int g, i, ix, iy;
fz_matrix tm, trm;
-printf("rendertext ; tmp=0,1\n");
+puts("render text");
error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, 0, 1);
if (error)
@@ -243,10 +169,158 @@ printf("rendertext ; tmp=0,1\n");
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;
+
+puts("render (mask color text)");
+
+ gc->r = color->r * (1 << 14);
+ gc->g = color->g * (1 << 14);
+ gc->b = color->b * (1 << 14);
+
+ tm = text->trm;
+
+ for (i = 0; i < text->len; i++)
+ {
+ g = text->els[i].g;
+ 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->r, gc->g, gc->b);
+ }
+
+ 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)
{
-printf("renderpath ; tmp=nil\n");
+ fz_error *error;
+
+puts("render path");
+
+ fz_resetgel(gc->gel, 17, 15);
+
+ if (path->paint == FZ_STROKE)
+ {
+ if (path->dash)
+ fz_dashpath(gc->gel, path, ctm, 0.2);
+ else
+ fz_strokepath(gc->gel, path, ctm, 0.2);
+ }
+ else
+ fz_fillpath(gc->gel, path, ctm, 0.2);
+
+ fz_sortgel(gc->gel);
+
+ error = fz_newpixmap(&gc->tmp, 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 r = gc->r;
+ short g = gc->g;
+ short b = gc->b;
+ 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] = ((r * sa) >> 14) + ((p[0] * ssa) >> 14);
+ p[1] = ((g * sa) >> 14) + ((p[1] * ssa) >> 14);
+ p[2] = ((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)
+{
+puts("render (mask color path)");
+
+ fz_resetgel(gc->gel, 17, 15);
+
+ if (path->paint == FZ_STROKE)
+ {
+ if (path->dash)
+ fz_dashpath(gc->gel, path, ctm, 0.2);
+ else
+ fz_strokepath(gc->gel, path, ctm, 0.2);
+ }
+ else
+ fz_fillpath(gc->gel, path, ctm, 0.2);
+
+ fz_sortgel(gc->gel);
+
+ gc->r = color->r * (1 << 14);
+ gc->g = color->g * (1 << 14);
+ gc->b = color->b * (1 << 14);
+
+ fz_scanconvert(gc->gel, gc->ael, path->paint == FZ_EOFILL, blitcolorspan, gc);
+
return nil;
}
@@ -259,9 +333,9 @@ fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm)
short b = color->b * (1 << 14);
int x, y;
-printf("rendercolor %d %d %d ; tmp=3,0\n", r, g, b);
+puts("render color");
- error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, 3, 0);
+ error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, 3, 1);
if (error)
return error;
@@ -273,12 +347,142 @@ printf("rendercolor %d %d %d ; tmp=3,0\n", r, g, b);
*p++ = r;
*p++ = g;
*p++ = b;
+ *p++ = 1 << 14;
}
}
return nil;
}
+static fz_error *
+fz_renderoverchild(fz_renderer *gc, fz_node *node, fz_matrix ctm)
+{
+ fz_error *error;
+
+ if (node->next)
+ {
+ error = fz_renderoverchild(gc, node->next, ctm);
+ if (error)
+ return error;
+ }
+
+ gc->tmp = nil;
+ error = fz_rendernode(gc, node, ctm);
+ if (error)
+ return error;
+
+ if (gc->tmp)
+ {
+ fz_blendover(gc->tmp, gc->acc);
+ fz_freepixmap(gc->tmp);
+ gc->tmp = nil;
+ }
+
+ return nil;
+}
+
+fz_error *
+fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
+{
+ fz_error *error;
+ fz_pixmap *oldacc = nil;
+ int oldmode;
+
+
+ /* uh-oh! we have a new over cluster */
+ if (gc->mode != OVER)
+ {
+puts("render over");
+ oldacc = gc->acc;
+ error = fz_newpixmap(&gc->acc, gc->x, gc->y, gc->w, gc->h, 3, 1);
+ if (error)
+ return error;
+ fz_clearpixmap(gc->acc);
+ }
+
+ oldmode = gc->mode;
+ gc->mode = OVER;
+
+ gc->tmp = nil;
+
+ if (over->super.child)
+ {
+ error = fz_renderoverchild(gc, over->super.child, ctm);
+ if (error)
+ return error;
+ }
+
+ gc->mode = oldmode;
+
+ /* uh-oh! end of over cluster */
+ if (gc->mode != OVER)
+ {
+printf("end over\n");
+ gc->tmp = gc->acc;
+ gc->acc = oldacc;
+ }
+
+ return nil;
+}
+
+fz_error *
+fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
+{
+ fz_error *error;
+ fz_pixmap *colorpix;
+ fz_pixmap *shapepix;
+ fz_node *color;
+ fz_node *shape;
+ int oldmode;
+
+ color = mask->super.child;
+ shape = color->next;
+
+ if (gc->mode == OVER)
+ {
+ if (fz_ispathnode(shape) && fz_iscolornode(color))
+ return rcolorpath(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);
+ }
+
+ oldmode = gc->mode;
+ gc->mode = MASK;
+
+ gc->tmp = nil;
+ error = fz_rendernode(gc, color, ctm);
+ if (error)
+ return error;
+ colorpix = gc->tmp;
+
+ gc->tmp = nil;
+ error = fz_rendernode(gc, shape, ctm);
+ if (error)
+ return error;
+ shapepix = gc->tmp;
+
+ error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, colorpix->n, 1);
+ if (error)
+ return error;
+
+ fz_blendmask(gc->tmp, colorpix, shapepix);
+
+ fz_freepixmap(shapepix);
+ fz_freepixmap(colorpix);
+
+ gc->mode = oldmode;
+
+ return nil;
+}
+
+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);
+}
+
fz_error *
fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm)
{
@@ -321,6 +525,7 @@ fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, f
return error;
*outp = gc->tmp;
+ gc->tmp = nil;
return nil;
}