summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
Diffstat (limited to 'render')
-rw-r--r--render/pixmap.c85
-rw-r--r--render/render.c190
2 files changed, 246 insertions, 29 deletions
diff --git a/render/pixmap.c b/render/pixmap.c
index 57402d81..ac99de80 100644
--- a/render/pixmap.c
+++ b/render/pixmap.c
@@ -29,11 +29,22 @@ fz_newpixmap(fz_pixmap **pixp, int x, int y, int w, int h, int n, int a)
return nil;
}
+fz_pixmap *
+fz_keeppixmap(fz_pixmap *pix)
+{
+ pix->refcount ++;
+ return pix;
+}
+
void
-fz_freepixmap(fz_pixmap *pix)
+fz_droppixmap(fz_pixmap *pix)
{
- fz_free(pix->samples);
- fz_free(pix);
+ pix->refcount --;
+ if (pix->refcount == 0)
+ {
+ fz_free(pix->samples);
+ fz_free(pix);
+ }
}
void
@@ -46,15 +57,77 @@ void
fz_debugpixmap(fz_pixmap *pix)
{
int x, y;
+ assert(pix->n == 3 && pix->a == 1);
FILE *f = fopen("out.ppm", "w");
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++)
{
- putc(255 - pix->samples[x + y * pix->stride], f);
- putc(255 - pix->samples[x + y * pix->stride], f);
- putc(255 - pix->samples[x + y * pix->stride], f);
+ 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;
+ putc(r, f);
+ putc(g, f);
+ putc(b, f);
}
fclose(f);
}
+void
+fz_blendover(fz_pixmap *dst, fz_pixmap *fg, fz_pixmap *bg)
+{
+ int x, y;
+
+printf("dst=%d,%d fg=%d,%d bg=%d,%d\n",
+dst->n, dst->a,
+fg->n, fg->a,
+bg->n, bg->a);
+
+ assert(fg->n == bg->n);
+ assert(fg->n == 3);
+ assert(fg->a == 1);
+ assert(bg->a == 1);
+
+ for (y = 0; y < dst->h; y++)
+ {
+ short *bgp = &fg->samples[y * fg->stride];
+ short *fgp = &bg->samples[y * bg->stride];
+ short *dstp = &dst->samples[y * dst->stride];
+ for (x = 0; x < dst->w; x++)
+ {
+ dstp[0] = ((fgp[3] * (fgp[0] - bgp[0])) >> 14) + bgp[0];
+ dstp[1] = ((fgp[3] * (fgp[1] - bgp[1])) >> 14) + bgp[1];
+ dstp[2] = ((fgp[3] * (fgp[2] - bgp[2])) >> 14) + bgp[2];
+ dstp[3] = ((fgp[3] * (fgp[3] - bgp[3])) >> 14) + bgp[3];
+ dstp += 4;
+ fgp += 4;
+ bgp += 4;
+ }
+ }
+}
+
+void
+fz_blendmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *mask)
+{
+ int x, y, k;
+
+ assert(src->n == dst->n);
+ assert(src->a == 0);
+ assert(mask->n == 0);
+ assert(mask->a == 1);
+ assert(dst->a == 1);
+
+ for (y = 0; y < dst->h; y++)
+ {
+ short *dstp = &dst->samples[y * dst->stride];
+ short *srcp = &src->samples[y * src->stride];
+ short *mskp = &mask->samples[y * mask->stride];
+ for (x = 0; x < dst->w; x++)
+ {
+ for (k = 0; k < dst->n; k++)
+ *dstp++ = *srcp++;
+ *dstp++ = *mskp++;
+ }
+ }
+}
+
diff --git a/render/render.c b/render/render.c
index bb875ee3..d7359d90 100644
--- a/render/render.c
+++ b/render/render.c
@@ -1,10 +1,16 @@
#include <fitz.h>
+enum { NONE, OVER, MASK };
+
struct fz_renderer_s
{
fz_glyphcache *cache;
fz_gel *gel;
fz_ael *ael;
+ int mode;
+ int x, y, w, h;
+ fz_pixmap *tmp;
+ fz_pixmap *acc;
};
fz_error *
@@ -20,6 +26,9 @@ fz_newrenderer(fz_renderer **gcp)
gc->cache = nil;
gc->gel = nil;
gc->ael = nil;
+ gc->mode = NONE;
+ gc->tmp = nil;
+ gc->acc = nil;
error = fz_newglyphcache(&gc->cache, 1024, 65536);
if (error)
@@ -56,50 +65,118 @@ fz_freerenderer(fz_renderer *gc)
fz_freegel(gc->gel);
if (gc->ael)
fz_freeael(gc->ael);
+ if (gc->tmp)
+ fz_droppixmap(gc->tmp);
+ if (gc->acc)
+ fz_droppixmap(gc->acc);
fz_free(gc);
}
fz_error *
-fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm, fz_pixmap *out)
+fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
{
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);
for (node = over->super.child; node; node = node->next)
{
- error = fz_rendernode(gc, node, ctm, out);
+ gc->tmp = nil;
+ error = fz_rendernode(gc, node, ctm);
if (error)
return error;
+ if (gc->tmp)
+ {
+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_pixmap *out)
+fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
{
fz_error *error;
- fz_node *node;
+ fz_pixmap *colorpix;
+ fz_pixmap *shapepix;
+ fz_node *color;
+ fz_node *shape;
+ int oldmode;
- for (node = mask->super.child; node; node = node->next)
- {
- error = fz_rendernode(gc, node, ctm, out);
- if (error)
- return error;
- }
+ 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;
return nil;
}
fz_error *
-fz_rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm, fz_pixmap *out)
+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, out);
+ return fz_rendernode(gc, transform->super.child, ctm);
}
-
-void composite(fz_pixmap *out, fz_glyph *gl, int xo, int yo)
+static void blitglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo)
{
int sx, sy, dx, dy, a, b, c;
@@ -107,8 +184,8 @@ void composite(fz_pixmap *out, fz_glyph *gl, int xo, int yo)
{
for (sx = 0; sx < gl->w; sx++)
{
- dx = xo + sx + gl->lsb;
- dy = yo - sy + gl->top;
+ dx = xo + sx + gl->lsb - out->x;
+ dy = yo - sy + gl->top - out->y;
if (dx < 0) continue;
if (dy < 0) continue;
@@ -124,7 +201,7 @@ void composite(fz_pixmap *out, fz_glyph *gl, int xo, int yo)
}
fz_error *
-fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm, fz_pixmap *out)
+fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm)
{
fz_error *error;
fz_glyph gl;
@@ -132,6 +209,12 @@ fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm, fz_pixmap *out)
int g, i, ix, iy;
fz_matrix tm, trm;
+printf("rendertext ; tmp=0,1\n");
+
+ error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, 0, 1);
+ if (error)
+ return error;
+
tm = text->trm;
for (i = 0; i < text->len; i++)
@@ -154,30 +237,91 @@ fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm, fz_pixmap *out)
if (error)
return error;
- composite(out, &gl, ix, iy);
+ blitglyph(gc->tmp, &gl, ix, iy);
}
return nil;
}
fz_error *
-fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm, fz_pixmap *out)
+fz_renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm)
{
+printf("renderpath ; tmp=nil\n");
+ return nil;
+}
+
+fz_error *
+fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm)
+{
+ fz_error *error;
+ short r = color->r * (1 << 14);
+ short g = color->g * (1 << 14);
+ short b = color->b * (1 << 14);
+ int x, y;
+
+printf("rendercolor %d %d %d ; tmp=3,0\n", r, g, b);
+
+ error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, 3, 0);
+ if (error)
+ return error;
+
+ for (y = 0; y < gc->tmp->h; y++)
+ {
+ short *p = &gc->tmp->samples[y * gc->tmp->stride];
+ for (x = 0; x < gc->tmp->w; x++)
+ {
+ *p++ = r;
+ *p++ = g;
+ *p++ = b;
+ }
+ }
+
+ return nil;
+}
+
+fz_error *
+fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm)
+{
+ assert(gc->tmp == nil);
+
if (!node)
return nil;
switch (node->kind)
{
case FZ_NOVER:
- return fz_renderover(gc, (fz_overnode*)node, ctm, out);
+ return fz_renderover(gc, (fz_overnode*)node, ctm);
case FZ_NMASK:
- return fz_rendermask(gc, (fz_masknode*)node, ctm, out);
+ return fz_rendermask(gc, (fz_masknode*)node, ctm);
case FZ_NTRANSFORM:
- return fz_rendertransform(gc, (fz_transformnode*)node, ctm, out);
+ return fz_rendertransform(gc, (fz_transformnode*)node, ctm);
+ case FZ_NCOLOR:
+ return fz_rendercolor(gc, (fz_colornode*)node, ctm);
+ case FZ_NPATH:
+ return fz_renderpath(gc, (fz_pathnode*)node, ctm);
case FZ_NTEXT:
- return fz_rendertext(gc, (fz_textnode*)node, ctm, out);
+ return fz_rendertext(gc, (fz_textnode*)node, ctm);
default:
return nil;
}
}
+fz_error *
+fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, fz_rect bbox)
+{
+ fz_error *error;
+
+ gc->x = floor(bbox.min.x);
+ gc->y = floor(bbox.min.y);
+ gc->w = ceil(bbox.max.x) - floor(bbox.min.x);
+ gc->h = ceil(bbox.max.y) - floor(bbox.min.y);
+
+ error = fz_rendernode(gc, tree->root, ctm);
+ if (error)
+ return error;
+
+ *outp = gc->tmp;
+
+ return nil;
+}
+