diff options
-rw-r--r-- | include/mupdf/content.h | 1 | ||||
-rw-r--r-- | include/mupdf/rsrc.h | 4 | ||||
-rw-r--r-- | mupdf/build.c | 27 | ||||
-rw-r--r-- | mupdf/image.c | 89 | ||||
-rw-r--r-- | mupdf/interpret.c | 26 | ||||
-rw-r--r-- | mupdf/resources.c | 2 | ||||
-rw-r--r-- | render/render.c | 2 | ||||
-rw-r--r-- | render/renderimage.c | 93 | ||||
-rw-r--r-- | render/stroke.c | 4 |
9 files changed, 228 insertions, 20 deletions
diff --git a/include/mupdf/content.h b/include/mupdf/content.h index 9448a539..b57a4d96 100644 --- a/include/mupdf/content.h +++ b/include/mupdf/content.h @@ -67,6 +67,7 @@ fz_error *pdf_addtransform(pdf_gstate *gs, fz_node *transform); fz_error *pdf_showpath(pdf_csi*, int close, int fill, int stroke, int evenodd); fz_error *pdf_showtext(pdf_csi*, fz_obj *text); fz_error *pdf_flushtext(pdf_csi*); +fz_error *pdf_showimage(pdf_csi*, pdf_image *img); /* interpret.c */ fz_error *pdf_newcsi(pdf_csi **csip); diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h index 5d977fd1..cac492c0 100644 --- a/include/mupdf/rsrc.h +++ b/include/mupdf/rsrc.h @@ -52,10 +52,10 @@ struct pdf_image_s fz_image *mask; /* explicit mask with subimage */ float decode[32]; int bpc; - unsigned char *data; + fz_buffer *data; }; -fz_error *pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *obj); +fz_error *pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *obj, fz_obj *stm); /* * CMap and Font diff --git a/mupdf/build.c b/mupdf/build.c index d235c9bc..6d0129ea 100644 --- a/mupdf/build.c +++ b/mupdf/build.c @@ -135,6 +135,33 @@ pdf_addtransform(pdf_gstate *gs, fz_node *transform) return nil; } +fz_error * +pdf_showimage(pdf_csi *csi, pdf_image *img) +{ + fz_error *error; + fz_node *node; + + error = fz_newimagenode(&node, (fz_image*)img); + if (error) + return error; + + if (img->super.n == 0 && img->super.a == 1) + { + error = pdf_addfillshape(csi->gstate + csi->gtop, node); + if (error) { + fz_freenode(node); + return error; + } + } + else + { + /* TODO image mask sub-image */ + fz_insertnode(csi->gstate[csi->gtop].head, node); + } + + return nil; +} + #if 0 BMC ... EMC object nesting can be completely fucked up diff --git a/mupdf/image.c b/mupdf/image.c index 00e6171b..a2dc624e 100644 --- a/mupdf/image.c +++ b/mupdf/image.c @@ -1,19 +1,68 @@ #include <fitz.h> #include <mupdf.h> +#define NEXTBYTE() \ + { c = *srcline++; } +#define NEEDBITS(n) \ + { while (k<(n)) { NEXTBYTE(); b = (b << 8) | c; k += 8; } } +#define DUMPBITS(n) \ + { k -= (n); } +#define GETCOMP1 NEEDBITS(1);(cc)=((b>>(k-(1)))&0x0001);DUMPBITS(1) +#define GETCOMP2 NEEDBITS(2);(cc)=((b>>(k-(2)))&0x0003);DUMPBITS(2) +#define GETCOMP4 NEEDBITS(4);(cc)=((b>>(k-(4)))&0x000f);DUMPBITS(4) +#define GETCOMP8 NEXTBYTE();(cc)=c + static fz_error *loadtile(fz_image *fzimg, fz_pixmap *tile) { + pdf_image *img = (pdf_image*)fzimg; + unsigned char *srcline; + unsigned char *dstline; + int x, y, z; + int stride; + unsigned cc, c, k, b; + + assert(fzimg->w == tile->w && fzimg->h == tile->h); + assert(fzimg->n == tile->n); + + stride = ((fzimg->w * (fzimg->n + fzimg->a)) * img->bpc + 7) / 8; + k = 0; + b = 0; + + for (y = 0; y < fzimg->h; y++) + { + srcline = img->data->bp + y * stride; + dstline = tile->samples + y * tile->stride; + + for (x = 0; x < fzimg->w; x++) + { + for (z = 0; z < fzimg->n + fzimg->a; z++) + { + switch (img->bpc) + { + case 1: GETCOMP1; *dstline++ = cc * 255; break; + case 2: GETCOMP2; *dstline++ = cc * 85; break; + case 4: GETCOMP4; *dstline++ = cc * 17; break; + case 8: GETCOMP8; *dstline++ = cc; break; + } + } + if (!fzimg->a && tile->a) + *dstline++ = 0xff; + } + } + return nil; } fz_error * -pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict) +pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; pdf_image *img; fz_colorspace *cs; int ismask; + int stride; fz_obj *obj; + int i; img = fz_malloc(sizeof(pdf_image)); if (!img) @@ -27,13 +76,14 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict) img->super.h = fz_toint(fz_dictgets(dict, "Height")); img->bpc = fz_toint(fz_dictgets(dict, "BitsPerComponent")); +printf("load image %d x %d @ %d\n", img->super.w, img->super.h, img->bpc); + cs = nil; obj = fz_dictgets(dict, "ColorSpace"); if (obj) error = pdf_loadcolorspace(&cs, xref, obj); ismask = fz_tobool(fz_dictgets(dict, "ImageMask")); - if (!ismask) { img->super.cs = cs; @@ -47,6 +97,41 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict) img->super.a = 1; } + obj = fz_dictgets(dict, "Decode"); + if (fz_isarray(obj)) + for (i = 0; i < (img->super.n + img->super.a) * 2; i++) + img->decode[i] = fz_toreal(fz_arrayget(obj, i)); + else + for (i = 0; i < (img->super.n + img->super.a) * 2; i++) + img->decode[i] = i & 1; + +printf(" cs %s\n", cs ? cs->name : "(null)"); +printf(" mask %d\n", ismask); +printf(" decode [ "); +for (i = 0; i < (img->super.n + img->super.a) * 2; i++) +printf("%g ", img->decode[i]); +printf("]\n"); + + error = pdf_loadstream(&img->data, xref, fz_tonum(ref), fz_togen(ref)); + if (error) + { + /* TODO: colorspace? */ + fz_free(img); + return error; + } + + stride = img->super.w * (img->super.n + img->super.a); + stride = (stride * img->bpc + 7) / 8; +printf(" stride = %d -> %d bytes\n", stride, stride * img->super.h); +printf(" data = %d bytes\n", img->data->wp - img->data->bp); + if (img->data->wp - img->data->bp != stride * img->super.h) + { + /* TODO: colorspace? */ + fz_freebuffer(img->data); + fz_free(img); + return fz_throw("syntaxerror: truncated image data"); + } + *imgp = img; return nil; diff --git a/mupdf/interpret.c b/mupdf/interpret.c index f9179792..ed8fff07 100644 --- a/mupdf/interpret.c +++ b/mupdf/interpret.c @@ -544,6 +544,32 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) if (error) return error; } + else if (!strcmp(buf, "Do")) + { + fz_obj *dict; + fz_obj *obj; + pdf_image *img; + + if (csi->top != 1) + goto syntaxerror; + + dict = fz_dictgets(rdb, "XObject"); + if (!dict) + return fz_throw("syntaxerror: missing xobject resource"); + + obj = fz_dictget(dict, csi->stack[0]); + if (!obj) + return fz_throw("syntaxerror: missing xobject resource"); + + img = pdf_findresource(xref->rimage, obj); + if (!img) + return fz_throw("syntaxerror: missing image resource"); + + error = pdf_showimage(csi, img); + if (error) + return error; + } + else fprintf(stderr, "syntaxerror: unknown keyword '%s'\n", buf); //return fz_throw("syntaxerror: unknown keyword '%s'", buf); diff --git a/mupdf/resources.c b/mupdf/resources.c index f859566f..a9ab1b7e 100644 --- a/mupdf/resources.c +++ b/mupdf/resources.c @@ -122,7 +122,7 @@ preloadxobject(pdf_xref *xref, fz_obj *ref) else if (!strcmp(fz_toname(subtype), "Image")) { - error = pdf_loadimage((pdf_image**)&rsrc->val, xref, obj); + error = pdf_loadimage((pdf_image**)&rsrc->val, xref, obj, ref); fz_dropobj(obj); if (error) { fz_free(rsrc); diff --git a/render/render.c b/render/render.c index 29b51480..d77c0c9d 100644 --- a/render/render.c +++ b/render/render.c @@ -80,8 +80,6 @@ fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm) gc->g = rgb[1] * 255; gc->b = rgb[2] * 255; -puts("render color"); - error = fz_newpixmap(&gc->tmp, color->cs, gc->x, gc->y, gc->w, gc->h, 3, 1); if (error) return error; diff --git a/render/renderimage.c b/render/renderimage.c index 4c6ef816..15eda833 100644 --- a/render/renderimage.c +++ b/render/renderimage.c @@ -1,27 +1,91 @@ #include <fitz.h> -static int cmpy(const void *a, const void *b) +static inline void +drawscan(fz_matrix *invmat, fz_pixmap *dst, fz_pixmap *src, int y, int x0, int x1) { - const fz_point *ap = a; - const fz_point *bp = b; - return bp->y - ap->y; + int x, k; + float u, v; + float du, dv; + fz_point p; + int iu, iv; + unsigned char c; + + p.x = x0; + p.y = y; + p = fz_transformpoint(*invmat, p); + + u = p.x; + v = p.y; + du = invmat->a; + dv = invmat->c; + + for (x = x0; x < x1; x++) + { + iu = CLAMP((int)u, 0, src->w - 1); + iv = CLAMP((int)v, 0, src->h - 1); + + for (k = 0; k < src->n + src->a; k++) + { + c = src->samples[ iv * src->stride + iu * (src->n+src->a) + k]; + dst->samples[ y * dst->stride + x * (dst->n+dst->a) + k ] = c; + } + + u += du; + v += dv; + } } -static void -drawtile(fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm) +static fz_error * +drawtile(fz_renderer *gc, fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm) { static const fz_point rect[4] = { {0, 0}, {0, 1}, {1, 1}, {1, 0} }; + fz_error *error; + fz_gel *gel = gc->gel; + fz_ael *ael = gc->ael; + fz_matrix imgmat; + fz_matrix invmat; fz_point v[4]; - int i; + int i, e, y, x0, x1; + + imgmat.a = 1.0 / tile->w; + imgmat.b = 0.0; + imgmat.c = 0.0; + imgmat.d = -1.0 / tile->h; + imgmat.e = 0.0; + imgmat.f = 1.0; + invmat = fz_invertmatrix(fz_concat(imgmat, ctm)); for (i = 0; i < 4; i++) v[i] = fz_transformpoint(ctm, rect[i]); + fz_resetgel(gel, 1, 1); + fz_insertgel(gel, v[0].x, v[0].y, v[1].x, v[1].y); + fz_insertgel(gel, v[1].x, v[1].y, v[2].x, v[2].y); + fz_insertgel(gel, v[2].x, v[2].y, v[3].x, v[3].y); + fz_insertgel(gel, v[3].x, v[3].y, v[0].x, v[0].y); + fz_sortgel(gel); - qsort(v, 4, sizeof(fz_point), cmpy); + e = 0; + y = gel->edges[0].y; - for (i = 0; i < 4; i++) - printf("%d: %g %g\n", i, v[i].x, v[i].y); + while (ael->len > 0 || e < gel->len) + { + error = fz_insertael(ael, gel, y, &e); + if (error) + return error; + x0 = ael->edges[0]->x; + x1 = ael->edges[ael->len - 1]->x; + drawscan(&invmat, out, tile, y, x0, x1); + + fz_advanceael(ael); + + if (ael->len > 0) + y ++; + else if (e < gel->len) + y = gel->edges[e].y; + } + + return nil; } fz_error * @@ -43,11 +107,18 @@ fz_renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm) if (error) goto cleanup; + fz_clearpixmap(gc->tmp); + error = image->loadtile(image, tile); if (error) goto cleanup; - drawtile(gc->tmp, tile, ctm); + error = drawtile(gc, gc->tmp, tile, ctm); + if (error) + goto cleanup; + +printf("loadtile "); fz_debugpixmap(tile); getchar(); +//printf("drawtile "); fz_debugpixmap(gc->tmp); getchar(); fz_freepixmap(tile); return nil; diff --git a/render/stroke.c b/render/stroke.c index cd4f5a13..2527e6ad 100644 --- a/render/stroke.c +++ b/render/stroke.c @@ -469,7 +469,7 @@ fz_strokepath(fz_gel *gel, fz_pathnode *path, fz_matrix ctm, float flatness) s.linecap = path->linecap; s.linejoin = path->linejoin; - s.linewidth = path->linewidth; + s.linewidth = path->linewidth * 0.5; s.miterlimit = path->miterlimit; s.sn = 0; s.bn = 0; @@ -664,7 +664,7 @@ fz_dashpath(fz_gel *gel, fz_pathnode *path, fz_matrix ctm, float flatness) s.linecap = path->linecap; s.linejoin = path->linejoin; - s.linewidth = path->linewidth; + s.linewidth = path->linewidth * 0.5; s.miterlimit = path->miterlimit; s.sn = 0; s.bn = 0; |