diff options
Diffstat (limited to 'render/renderpath.c')
-rw-r--r-- | render/renderpath.c | 139 |
1 files changed, 139 insertions, 0 deletions
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; +} + |