diff options
author | Tor Andersson <tor@ghostscript.com> | 2010-01-07 16:26:15 +0100 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2010-01-07 16:26:15 +0100 |
commit | ef8397646d49affa535a5436954beb723a87ce13 (patch) | |
tree | e90172384256726a989a5bc33d9b2e6dfb76c4ac | |
parent | ce5bbd9d57287b041e249a21bc88ad87a4c4f9ff (diff) | |
download | mupdf-ef8397646d49affa535a5436954beb723a87ce13.tar.xz |
Clipping paths.
-rw-r--r-- | fitz/dev_draw.c | 155 | ||||
-rw-r--r-- | fitzdraw/pixmap.c | 2 |
2 files changed, 126 insertions, 31 deletions
diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c index 1285ae51..7a602b0a 100644 --- a/fitz/dev_draw.c +++ b/fitz/dev_draw.c @@ -4,6 +4,8 @@ #define HSUBPIX 5.0 #define VSUBPIX 5.0 +#define MAXCLIP 64 + typedef struct fz_drawdevice_s fz_drawdevice; struct fz_drawdevice_s @@ -14,6 +16,11 @@ struct fz_drawdevice_s fz_gel *gel; fz_ael *ael; fz_pixmap *dest; + struct { + fz_pixmap *dest; + fz_pixmap *mask; + } clipstack[MAXCLIP]; + int cliptop; }; static void @@ -52,6 +59,49 @@ blendover(fz_pixmap *src, fz_pixmap *dst) assert(!"blendover src and dst mismatch"); } +static void +blendmaskover(fz_pixmap *src, fz_pixmap *msk, fz_pixmap *dst) +{ + unsigned char *sp, *dp, *mp; + fz_irect sr, dr, mr; + int x, y, w, h; + + sr.x0 = src->x; + sr.y0 = src->y; + sr.x1 = src->x + src->w; + sr.y1 = src->y + src->h; + + dr.x0 = dst->x; + dr.y0 = dst->y; + dr.x1 = dst->x + dst->w; + dr.y1 = dst->y + dst->h; + + mr.x0 = msk->x; + mr.y0 = msk->y; + mr.x1 = msk->x + msk->w; + mr.y1 = msk->y + msk->h; + + dr = fz_intersectirects(sr, dr); + dr = fz_intersectirects(dr, mr); + x = dr.x0; + y = dr.y0; + w = dr.x1 - dr.x0; + h = dr.y1 - dr.y0; + + sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * src->n; + mp = msk->samples + ((y - msk->y) * msk->w + (x - msk->x)) * msk->n; + dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n; + + if (src->n == 1 && msk->n == 1 && dst->n == 1) + fz_duff_1i1o1(sp, src->w, mp, msk->w, dp, dst->w, w, h); + else if (src->n == 4 && msk->n == 1 && dst->n == 4) + fz_duff_4i1o4(sp, src->w * 4, mp, msk->w, dp, dst->w * 4, w, h); + else if (src->n == dst->n) + fz_duff_nimon(sp, src->w * src->n, src->n, mp, msk->w * msk->n, msk->n, dp, dst->w * dst->n, w, h); + else + assert(!"blendmaskover src and msk and dst mismatch"); +} + void fz_drawfillpath(void *user, fz_path *path, fz_colorspace *colorspace, float *color, float alpha) { fz_drawdevice *dev = user; @@ -139,8 +189,46 @@ void fz_drawstrokepath(void *user, fz_path *path, fz_colorspace *colorspace, flo void fz_drawclippath(void *user, fz_path *path) { fz_drawdevice *dev = user; - fz_printpath(path, 0); - printf("clippath\n"); + float expansion = fz_matrixexpansion(path->ctm); + float flatness = 0.3 / expansion; + fz_irect clip, bbox; + fz_pixmap *mask, *dest; + + if (dev->cliptop == MAXCLIP) + { + fz_warn("assert: too many clip masks on stack"); + return; + } + + if (flatness < 0.1) + flatness = 0.1; + + clip.x0 = dev->dest->x; + clip.y0 = dev->dest->y; + clip.x1 = dev->dest->x + dev->dest->w; + clip.y1 = dev->dest->y + dev->dest->h; + + fz_resetgel(dev->gel, clip); + fz_fillpath(dev->gel, path, path->ctm, flatness); + fz_sortgel(dev->gel); + + bbox = fz_boundgel(dev->gel); + bbox = fz_intersectirects(bbox, clip); + if (fz_isemptyrect(bbox)) + return; + + mask = fz_newpixmapwithrect(bbox, 1); + dest = fz_newpixmapwithrect(bbox, 4); + + memset(mask->samples, 0, mask->w * mask->h * mask->n); + memset(dest->samples, 0, dest->w * dest->h * dest->n); + + fz_scanconvert(dev->gel, dev->ael, path->winding == FZ_EVENODD, bbox, mask, NULL, 1); + + dev->clipstack[dev->cliptop].mask = mask; + dev->clipstack[dev->cliptop].dest = dev->dest; + dev->dest = dest; + dev->cliptop++; } static void drawglyph(unsigned char *argb, fz_pixmap *dst, fz_glyph *src, int xorig, int yorig) @@ -238,29 +326,22 @@ void fz_drawcliptext(void *user, fz_text *text) void fz_drawignoretext(void *user, fz_text *text) { - printf("/%s setfont\n", text->font->name); - fz_debugtext(text, 0); - printf("invisibletext\n"); } -static inline void -calcimagescale(fz_matrix ctm, int w, int h, int *odx, int *ody) +void fz_drawpopclip(void *user) { - float sx, sy; - int dx, dy; - - sx = sqrt(ctm.a * ctm.a + ctm.b * ctm.b); - dx = 1; - while (((w+dx-1)/dx)/sx > 2.0 && (w+dx-1)/dx > 1) - dx++; - - sy = sqrt(ctm.c * ctm.c + ctm.d * ctm.d); - dy = 1; - while (((h+dy-1)/dy)/sy > 2.0 && (h+dy-1)/dy > 1) - dy++; - - *odx = dx; - *ody = dy; + fz_drawdevice *dev = user; + if (dev->cliptop > 0) + { + fz_pixmap *mask = dev->clipstack[dev->cliptop-1].mask; + fz_pixmap *dest = dev->clipstack[dev->cliptop-1].dest; + fz_pixmap *scratch = dev->dest; + blendmaskover(scratch, mask, dest); + fz_freepixmap(mask); + fz_freepixmap(scratch); + dev->cliptop--; + dev->dest = dest; + } } void fz_drawdrawshade(void *user, fz_shade *shade, fz_matrix ctm) @@ -286,6 +367,26 @@ void fz_drawdrawshade(void *user, fz_shade *shade, fz_matrix ctm) fz_freepixmap(tmp); } +static inline void +calcimagescale(fz_matrix ctm, int w, int h, int *odx, int *ody) +{ + float sx, sy; + int dx, dy; + + sx = sqrt(ctm.a * ctm.a + ctm.b * ctm.b); + dx = 1; + while (((w+dx-1)/dx)/sx > 2.0 && (w+dx-1)/dx > 1) + dx++; + + sy = sqrt(ctm.c * ctm.c + ctm.d * ctm.d); + dy = 1; + while (((h+dy-1)/dy)/sy > 2.0 && (h+dy-1)/dy > 1) + dy++; + + *odx = dx; + *ody = dy; +} + void fz_drawdrawimage(void *user, fz_image *image, fz_matrix ctm) { fz_drawdevice *dev = user; @@ -303,15 +404,13 @@ void fz_drawdrawimage(void *user, fz_image *image, fz_matrix ctm) int x0, y0; int w, h; - printf("drawimage\n"); - bounds.x0 = 0; bounds.y0 = 0; bounds.x1 = 1; bounds.y1 = 1; bounds = fz_transformaabb(ctm, bounds); bbox = fz_roundrect(bounds); - + clip.x0 = dev->dest->x; clip.y0 = dev->dest->y; clip.x1 = dev->dest->x + dev->dest->w; @@ -380,11 +479,6 @@ void fz_drawdrawimage(void *user, fz_image *image, fz_matrix ctm) fz_freepixmap(tile); } -void fz_drawpopclip(void *user) -{ - printf("popclip\n"); -} - fz_device *fz_newdrawdevice(fz_colorspace *colorspace, fz_pixmap *dest) { fz_drawdevice *ddev = fz_malloc(sizeof(fz_drawdevice)); @@ -393,6 +487,7 @@ fz_device *fz_newdrawdevice(fz_colorspace *colorspace, fz_pixmap *dest) ddev->gel = fz_newgel(); ddev->ael = fz_newael(); ddev->dest = dest; + ddev->cliptop = 0; fz_device *dev = fz_malloc(sizeof(fz_device)); dev->user = ddev; diff --git a/fitzdraw/pixmap.c b/fitzdraw/pixmap.c index d5aed102..a219f0bd 100644 --- a/fitzdraw/pixmap.c +++ b/fitzdraw/pixmap.c @@ -13,7 +13,7 @@ fz_newpixmap(int x, int y, int w, int h, int n) pix->n = n; pix->samples = fz_malloc(pix->w * pix->h * pix->n * sizeof(fz_sample)); - + return pix; } |