summaryrefslogtreecommitdiff
path: root/render/render.c
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-09-27 02:15:04 +0200
committerTor Andersson <tor@ghostscript.com>2004-09-27 02:15:04 +0200
commit6ddde92a3a45e970b05770633dc6a337d5d013c5 (patch)
tree1dec4612d7469839478e72d16d30a0da5755243c /render/render.c
downloadmupdf-6ddde92a3a45e970b05770633dc6a337d5d013c5.tar.xz
Initial import
Diffstat (limited to 'render/render.c')
-rw-r--r--render/render.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/render/render.c b/render/render.c
new file mode 100644
index 00000000..64856dd2
--- /dev/null
+++ b/render/render.c
@@ -0,0 +1,183 @@
+#include <fitz.h>
+
+struct fz_renderer_s
+{
+ fz_glyphcache *cache;
+ fz_gel *gel;
+ fz_ael *ael;
+};
+
+fz_error *
+fz_newrenderer(fz_renderer **gcp)
+{
+ fz_error *error;
+ fz_renderer *gc;
+
+ gc = *gcp = fz_malloc(sizeof(fz_renderer));
+ if (!gc)
+ return fz_outofmem;
+
+ gc->cache = nil;
+ gc->gel = nil;
+ gc->ael = nil;
+
+ error = fz_newglyphcache(&gc->cache, 1024, 65536);
+ if (error)
+ goto cleanup;
+
+ error = fz_newgel(&gc->gel);
+ if (error)
+ goto cleanup;
+
+ error = fz_newael(&gc->ael);
+ if (error)
+ goto cleanup;
+
+ return nil;
+
+cleanup:
+ if (gc->cache)
+ fz_freeglyphcache(gc->cache);
+ if (gc->gel)
+ fz_freegel(gc->gel);
+ if (gc->ael)
+ fz_freeael(gc->ael);
+ fz_free(gc);
+
+ return error;
+}
+
+void
+fz_freerenderer(fz_renderer *gc)
+{
+ if (gc->cache)
+ fz_freeglyphcache(gc->cache);
+ if (gc->gel)
+ fz_freegel(gc->gel);
+ if (gc->ael)
+ fz_freeael(gc->ael);
+ fz_free(gc);
+}
+
+fz_error *
+fz_renderover(fz_renderer *gc, fz_over *over, fz_matrix ctm, fz_pixmap *out)
+{
+ fz_error *error;
+ fz_node *node;
+
+ for (node = over->child; node; node = node->next)
+ {
+ error = fz_rendernode(gc, node, ctm, out);
+ if (error)
+ return error;
+ }
+
+ return nil;
+}
+
+fz_error *
+fz_rendermask(fz_renderer *gc, fz_mask *mask, fz_matrix ctm, fz_pixmap *out)
+{
+ fz_error *error;
+ fz_node *node;
+
+ for (node = mask->child; node; node = node->next)
+ {
+ error = fz_rendernode(gc, node, ctm, out);
+ if (error)
+ return error;
+ }
+
+ return nil;
+}
+
+fz_error *
+fz_rendertransform(fz_renderer *gc, fz_transform *xform, fz_matrix ctm, fz_pixmap *out)
+{
+ ctm = fz_concat(ctm, xform->m);
+ return fz_rendernode(gc, xform->child, ctm, out);
+}
+
+
+void composite(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;
+ dy = yo - sy + gl->top;
+
+ 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;
+ }
+ }
+}
+
+fz_error *
+fz_rendertext(fz_renderer *gc, fz_text *text, fz_matrix ctm, fz_pixmap *out)
+{
+ fz_error *error;
+ fz_glyph gl;
+ float x, y;
+ int g, i, ix, iy;
+ fz_matrix tm, trm;
+
+ 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;
+
+ composite(out, &gl, ix, iy);
+ }
+
+ return nil;
+}
+
+fz_error *
+fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm, fz_pixmap *out)
+{
+ if (!node)
+ return nil;
+
+ switch (node->kind)
+ {
+ case FZ_NOVER:
+ return fz_renderover(gc, (fz_over*)node, ctm, out);
+ case FZ_NMASK:
+ return fz_rendermask(gc, (fz_mask*)node, ctm, out);
+ case FZ_NTRANSFORM:
+ return fz_rendertransform(gc, (fz_transform*)node, ctm, out);
+ case FZ_NTEXT:
+ return fz_rendertext(gc, (fz_text*)node, ctm, out);
+ default:
+ return nil;
+ }
+}
+