diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-09-27 02:15:04 +0200 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-09-27 02:15:04 +0200 |
commit | 6ddde92a3a45e970b05770633dc6a337d5d013c5 (patch) | |
tree | 1dec4612d7469839478e72d16d30a0da5755243c /render/render.c | |
download | mupdf-6ddde92a3a45e970b05770633dc6a337d5d013c5.tar.xz |
Initial import
Diffstat (limited to 'render/render.c')
-rw-r--r-- | render/render.c | 183 |
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; + } +} + |