diff options
-rw-r--r-- | include/mupdf/content.h | 37 | ||||
-rw-r--r-- | include/mupdf/rsrc.h | 11 | ||||
-rw-r--r-- | mupdf/build.c | 109 | ||||
-rw-r--r-- | mupdf/colorspace.c | 54 | ||||
-rw-r--r-- | mupdf/image.c | 201 | ||||
-rw-r--r-- | mupdf/interpret.c | 157 |
6 files changed, 381 insertions, 188 deletions
diff --git a/include/mupdf/content.h b/include/mupdf/content.h index b57a4d96..a7bfac22 100644 --- a/include/mupdf/content.h +++ b/include/mupdf/content.h @@ -2,9 +2,37 @@ * content stream parsing */ +typedef struct pdf_material_s pdf_material; typedef struct pdf_gstate_s pdf_gstate; typedef struct pdf_csi_s pdf_csi; +enum +{ + PDF_MFILL, + PDF_MSTROKE +}; + +enum +{ + PDF_MNONE, + PDF_MCOLOR, + PDF_MLAB, + PDF_MINDEXED, + PDF_MTILE, + PDF_MSHADE +}; + +struct pdf_material_s +{ + int kind; + fz_colorspace *cs; + float v[32]; + pdf_indexed *indexed; + // lookup + // tile + // shade +}; + struct pdf_gstate_s { /* path stroking */ @@ -17,10 +45,8 @@ struct pdf_gstate_s float dashlist[32]; /* materials */ - fz_colorspace *strokecs; - float stroke[32]; - fz_colorspace *fillcs; - float fill[32]; + pdf_material stroke; + pdf_material fill; /* text state */ float charspace; @@ -58,6 +84,9 @@ struct pdf_csi_s /* build.c */ void pdf_initgstate(pdf_gstate *gs); +fz_error *pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs); +fz_error *pdf_setcolor(pdf_csi *csi, int what, float *v); + fz_error *pdf_buildstrokepath(pdf_gstate *gs, fz_pathnode *path); fz_error *pdf_buildfillpath(pdf_gstate *gs, fz_pathnode *path, int evenodd); fz_error *pdf_addfillshape(pdf_gstate *gs, fz_node *shape); diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h index 4b656910..0fb28cf0 100644 --- a/include/mupdf/rsrc.h +++ b/include/mupdf/rsrc.h @@ -28,6 +28,16 @@ void pdf_freefunction(pdf_function *func); * ColorSpace */ +typedef struct pdf_indexed_s pdf_indexed; + +struct pdf_indexed_s +{ + fz_colorspace super; /* hmmm... */ + fz_colorspace *base; + int high; + unsigned char *lookup; +}; + extern fz_colorspace *pdf_devicegray; extern fz_colorspace *pdf_devicergb; extern fz_colorspace *pdf_devicecmyk; @@ -61,6 +71,7 @@ struct pdf_image_s { fz_image super; fz_image *mask; /* explicit mask with subimage */ + pdf_indexed *indexed; float decode[32]; int bpc; int stride; diff --git a/mupdf/build.c b/mupdf/build.c index 6d0129ea..c2acde08 100644 --- a/mupdf/build.c +++ b/mupdf/build.c @@ -12,11 +12,13 @@ pdf_initgstate(pdf_gstate *gs) gs->dashlen = 0; memset(gs->dashlist, 0, sizeof(gs->dashlist)); - gs->strokecs = pdf_devicegray; - gs->stroke[0] = 0; + gs->stroke.kind = PDF_MCOLOR; + gs->stroke.cs = pdf_devicegray; + gs->stroke.v[0] = 0; - gs->fillcs = pdf_devicegray; - gs->fill[0] = 0; + gs->fill.kind = PDF_MCOLOR; + gs->fill.cs = pdf_devicegray; + gs->fill.v[0] = 0; gs->charspace = 0; gs->wordspace = 0; @@ -31,6 +33,83 @@ pdf_initgstate(pdf_gstate *gs) } fz_error * +pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs) +{ + pdf_gstate *gs = csi->gstate + csi->gtop; + fz_error *error; + pdf_material *mat; + + error = pdf_flushtext(csi); + if (error) + return error; + + mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; + + mat->kind = PDF_MCOLOR; + mat->cs = cs; + + mat->v[0] = 0; // FIXME: default color + mat->v[1] = 0; // FIXME: default color + mat->v[2] = 0; // FIXME: default color + mat->v[3] = 1; // FIXME: default color + + if (!strcmp(cs->name, "Indexed")) + { + mat->kind = PDF_MINDEXED; + mat->indexed = (pdf_indexed*)cs; + mat->cs = mat->indexed->base; + } + + if (!strcmp(cs->name, "Lab")) + mat->kind = PDF_MLAB; + + return nil; +} + +fz_error * +pdf_setcolor(pdf_csi *csi, int what, float *v) +{ + pdf_gstate *gs = csi->gstate + csi->gtop; + fz_error *error; + pdf_indexed *ind; + pdf_material *mat; + int i, k; + + error = pdf_flushtext(csi); + if (error) + return error; + + mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; + + switch (mat->kind) + { + case PDF_MCOLOR: + for (i = 0; i < mat->cs->n; i++) + mat->v[i] = v[i]; + break; + + case PDF_MLAB: + mat->v[0] = v[0] / 100.0; + mat->v[1] = (v[1] + 100) / 200.0; + mat->v[2] = (v[2] + 100) / 200.0; + break; + + case PDF_MINDEXED: + ind = mat->indexed; + i = CLAMP(v[0], 0, ind->high); + for (k = 0; k < ind->base->n; k++) + mat->v[k] = ind->lookup[ind->base->n * i + k] / 255.0; + break; + + default: + return fz_throw("syntaxerror: color not compatible with material"); + } + + return nil; +} + + +fz_error * pdf_buildstrokepath(pdf_gstate *gs, fz_pathnode *path) { fz_error *error; @@ -89,13 +168,31 @@ addcolorshape(pdf_gstate *gs, fz_node *shape, fz_colorspace *cs, float *v) fz_error * pdf_addfillshape(pdf_gstate *gs, fz_node *shape) { - return addcolorshape(gs, shape, gs->fillcs, gs->fill); + switch (gs->fill.kind) + { + case PDF_MNONE: + fz_insertnode(gs->head, shape); + return nil; + case PDF_MCOLOR: + return addcolorshape(gs, shape, gs->fill.cs, gs->fill.v); + default: + return fz_throw("unimplemented material"); + } } fz_error * pdf_addstrokeshape(pdf_gstate *gs, fz_node *shape) { - return addcolorshape(gs, shape, gs->strokecs, gs->stroke); + switch (gs->stroke.kind) + { + case PDF_MNONE: + fz_insertnode(gs->head, shape); + return nil; + case PDF_MCOLOR: + return addcolorshape(gs, shape, gs->stroke.cs, gs->stroke.v); + default: + return fz_throw("unimplemented material"); + } } fz_error * diff --git a/mupdf/colorspace.c b/mupdf/colorspace.c index 1b2eff61..b4ba8aa8 100644 --- a/mupdf/colorspace.c +++ b/mupdf/colorspace.c @@ -356,9 +356,13 @@ static inline float cielabinvg(float x) static void labtoxyz(fz_colorspace *fzcs, float *lab, float *xyz) { struct cielab *cs = (struct cielab *) fzcs; - float lstar = lab[0]; - float astar = MAX(MIN(lab[1], cs->range[1]), cs->range[0]); - float bstar = MAX(MIN(lab[2], cs->range[3]), cs->range[2]); + float tmp[3]; + tmp[0] = lab[0] * 100; + tmp[1] = lab[1] * 200 - 100; + tmp[2] = lab[2] * 200 - 100; + float lstar = tmp[0]; + float astar = MAX(MIN(tmp[1], cs->range[1]), cs->range[0]); + float bstar = MAX(MIN(tmp[2], cs->range[3]), cs->range[2]); float l = ((lstar * 16.0) / 116.0) + (astar / 500.0); float m = (lstar * 16.0) / 116.0; float n = ((lstar * 16.0) / 116.0) - (bstar / 200.0); @@ -370,13 +374,17 @@ static void labtoxyz(fz_colorspace *fzcs, float *lab, float *xyz) static void xyztolab(fz_colorspace *fzcs, float *xyz, float *lab) { struct cielab *cs = (struct cielab *) fzcs; + float tmp[3]; float yyn = xyz[1] / cs->white[1]; if (yyn < 0.008856) - lab[0] = 116.0 * yyn * (1.0 / 3.0) - 16.0; + tmp[0] = 116.0 * yyn * (1.0 / 3.0) - 16.0; else - lab[0] = 903.3 * yyn; - lab[1] = 500 * (cielabinvg(xyz[0]/cs->white[0]) - cielabinvg(xyz[1]/cs->white[1])); - lab[2] = 200 * (cielabinvg(xyz[1]/cs->white[1]) - cielabinvg(xyz[2]/cs->white[2])); + tmp[0] = 903.3 * yyn; + tmp[1] = 500 * (cielabinvg(xyz[0]/cs->white[0]) - cielabinvg(xyz[1]/cs->white[1])); + tmp[2] = 200 * (cielabinvg(xyz[1]/cs->white[1]) - cielabinvg(xyz[2]/cs->white[2])); + lab[0] = tmp[0] / 100.0; + lab[1] = (tmp[1] + 100) / 200.0; + lab[2] = (tmp[2] + 100) / 200.0; } static fz_error * @@ -576,27 +584,25 @@ loadseparation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) * Indexed */ -struct indexed -{ - fz_colorspace super; - fz_colorspace *base; - int high; - float *lookup; -}; - +/* only called for images... */ static void indexedtoxyz(fz_colorspace *fzcs, float *ind, float *xyz) { - struct indexed *cs = (struct indexed *)fzcs; - int i = ind[0] * 255; // FIXME + pdf_indexed *cs = (pdf_indexed *)fzcs; + float alt[32]; + int i, k; + i = ind[0] * 255; i = CLAMP(i, 0, cs->high); - cs->base->toxyz(cs->base, cs->lookup + i * cs->base->n, xyz); +printf("indexedtoxyz: %d\n", i); + for (k = 0; k < cs->base->n; k++) + alt[k] = cs->lookup[i * cs->base->n + k] / 255.0; + cs->base->toxyz(cs->base, alt, xyz); } static void freeindexed(fz_colorspace *fzcs) { - struct indexed *cs = (struct indexed *)fzcs; + pdf_indexed *cs = (pdf_indexed *)fzcs; fz_freecolorspace(cs->base); fz_free(cs->lookup); } @@ -605,7 +611,7 @@ static fz_error * loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) { fz_error *error; - struct indexed *cs; + pdf_indexed *cs; fz_obj *baseobj = fz_arrayget(array, 1); fz_obj *highobj = fz_arrayget(array, 2); fz_obj *lookup = fz_arrayget(array, 3); @@ -620,7 +626,7 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) if (error) return error; - cs = fz_malloc(sizeof(struct indexed)); + cs = fz_malloc(sizeof(pdf_indexed)); if (!cs) { fz_freecolorspace(base); @@ -634,7 +640,7 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) n = base->n * (cs->high + 1); - cs->lookup = fz_malloc(n * sizeof(float)); + cs->lookup = fz_malloc(n); if (!cs->lookup) { freeindexed((fz_colorspace*)cs); @@ -646,7 +652,7 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) unsigned char *buf = fz_tostringbuf(lookup); int i; for (i = 0; i < n; i++) - cs->lookup[i] = buf[i] / 255.0; // FIXME base range + cs->lookup[i] = buf[i]; } if (fz_isindirect(lookup)) @@ -662,7 +668,7 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) } for (i = 0; i < n && i < (buf->wp - buf->rp); i++) - cs->lookup[i] = buf->rp[i] / 255.0; // FIXME base range + cs->lookup[i] = buf->rp[i]; fz_freebuffer(buf); } diff --git a/mupdf/image.c b/mupdf/image.c index 019e6129..2e90d9cb 100644 --- a/mupdf/image.c +++ b/mupdf/image.c @@ -6,10 +6,9 @@ static inline int getbit(const unsigned char *buf, int x) return ( buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1; } -static void loadtile1(pdf_image *src, fz_pixmap *dst) +static void loadtile1(pdf_image *src, fz_pixmap *dst, int n) { int x, y, k; - int n = dst->n; for (y = dst->y; y < dst->y + dst->h; y++) { unsigned char *s = src->samples->bp + y * src->stride; @@ -22,28 +21,25 @@ static void loadtile1(pdf_image *src, fz_pixmap *dst) } } -static void loadtile1a(pdf_image *src, fz_pixmap *dst) +static void loadtile1a(pdf_image *src, fz_pixmap *dst, int n) { int x, y, k; - int sn = src->super.n; - int dn = dst->n; for (y = dst->y; y < dst->y + dst->h; y++) { unsigned char *s = src->samples->bp + y * src->stride; unsigned char *d = dst->samples + y * dst->w * dst->n; for (x = dst->x; x < dst->x + dst->w; x++) { - d[x * dn + 0] = 255; - for (k = 0; k < sn; k++) - d[x * dn + k + 1] = getbit(s, x * sn + k); + d[x * (n+1) + 0] = 255; + for (k = 0; k < n; k++) + d[x * (n+1) + k + 1] = getbit(s, x * n + k); } } } -static void loadtile8(pdf_image *src, fz_pixmap *dst) +static void loadtile8(pdf_image *src, fz_pixmap *dst, int n) { int x, y, k; - int n = src->super.n; for (y = dst->y; y < dst->y + dst->h; y++) { unsigned char *s = src->samples->bp + y * src->stride; @@ -54,10 +50,9 @@ static void loadtile8(pdf_image *src, fz_pixmap *dst) } } -static void loadtile8a(pdf_image *src, fz_pixmap *dst) +static void loadtile8a(pdf_image *src, fz_pixmap *dst, int n) { int x, y, k; - int n = dst->n; for (y = dst->y; y < dst->y + dst->h; y++) { unsigned char *s = src->samples->bp + y * src->stride; @@ -65,19 +60,30 @@ static void loadtile8a(pdf_image *src, fz_pixmap *dst) for (x = dst->x; x < dst->x + dst->w; x++) { *d++ = 255; - for (k = 1; k < n; k++) + for (k = 0; k < n; k++) *d++ = *s++; } } } static void -decodetile(fz_pixmap *pix, int bpc, int a, float *decode, int scale) +decodetile(fz_pixmap *pix, int bpc, int a, float *decode) { unsigned char table[32][256]; float twon = (1 << bpc) - 1; int x, y, k, i; + int isdefault = 1; + for (k = 0; k < pix->n - a; k++) + { + int min = decode[k * 2 + 0] * 255; + int max = decode[k * 2 + 1] * 255; + if (min != 0 || max != 255) + isdefault = 0; + } + if (isdefault) + return; + for (i = 0; i < (1 << bpc); i++) { for (k = 0; k < pix->n - a; k++) @@ -85,7 +91,7 @@ decodetile(fz_pixmap *pix, int bpc, int a, float *decode, int scale) float min = decode[k * 2 + 0]; float max = decode[k * 2 + 1]; float f = min + i * (max - min) / twon; - table[k][i] = f * scale; + table[k][i] = f * 255; } } @@ -106,6 +112,7 @@ static fz_error * loadtile(fz_image *img, fz_pixmap *tile) { pdf_image *src = (pdf_image*)img; + fz_error *error; assert(tile->n == img->n + 1); assert(tile->x >= 0); @@ -113,35 +120,72 @@ loadtile(fz_image *img, fz_pixmap *tile) assert(tile->x + tile->w <= img->w); assert(tile->y + tile->h <= img->h); - if (img->a) + if (src->indexed) { + fz_pixmap *tmp; + int x, y, k, i; + + error = fz_newpixmap(&tmp, tile->x, tile->y, tile->w, tile->h, 1); + if (error) + return error; + switch (src->bpc) { - case 1: loadtile1(src, tile); break; - // case 2: loadtile2(src, tile); break; - // case 4: loadtile4(src, tile); break; - case 8: loadtile8(src, tile); break; + case 1: loadtile1(src, tmp, 1); break; + // case 2: loadtile2(src, tmp, 1); break; + // case 4: loadtile4(src, tmp, 1); break; + case 8: loadtile8(src, tmp, 1); break; default: return fz_throw("rangecheck: unsupported bit depth: %d", src->bpc); } + + for (y = 0; y < tile->h; y++) + { + for (x = 0; x < tile->w; x++) + { + tile->samples[(y * tile->w + x) * tile->n] = 255; + i = tmp->samples[y * tile->w + x]; + i = CLAMP(i, 0, src->indexed->high); + for (k = 0; k < src->indexed->base->n; k++) + { + tile->samples[(y * tile->w + x) * tile->n + k + 1] = + src->indexed->lookup[i * src->indexed->base->n + k]; + } + } + } + + fz_freepixmap(tmp); } + else { - switch (src->bpc) + if (img->a) { - case 1: loadtile1a(src, tile); break; - // case 2: loadtile2a(src, tile); break; - // case 4: loadtile4a(src, tile); break; - case 8: loadtile8a(src, tile); break; - default: - return fz_throw("rangecheck: unsupported bit depth: %d", src->bpc); + switch (src->bpc) + { + case 1: loadtile1(src, tile, img->n + img->a); break; + // case 2: loadtile2(src, tile, img->n + img->a); break; + // case 4: loadtile4(src, tile, img->n + img->a); break; + case 8: loadtile8(src, tile, img->n + img->a); break; + default: + return fz_throw("rangecheck: unsupported bit depth: %d", src->bpc); + } + } + else + { + switch (src->bpc) + { + case 1: loadtile1a(src, tile, img->n); break; + // case 2: loadtile2a(src, tile, img->n); break; + // case 4: loadtile4a(src, tile, img->n); break; + case 8: loadtile8a(src, tile, img->n); break; + default: + return fz_throw("rangecheck: unsupported bit depth: %d", src->bpc); + } } - } - if (img->cs && !strcmp(img->cs->name, "Indexed")) - decodetile(tile, src->bpc, !src->super.a, src->decode, 1); - else - decodetile(tile, src->bpc, !src->super.a, src->decode, 255); + decodetile(tile, src->bpc, !img->a, src->decode); + } return nil; } @@ -151,24 +195,27 @@ 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; fz_obj *obj; int i; + int w, h, bpc; + int n = 0; + int a = 0; + fz_colorspace *cs = nil; + pdf_indexed *indexed = nil; + int stride; + img = fz_malloc(sizeof(pdf_image)); if (!img) return fz_outofmem; - img->super.loadtile = loadtile; - img->super.free = nil; - img->super.cs = nil; + w = fz_toint(fz_dictgets(dict, "Width")); + h = fz_toint(fz_dictgets(dict, "Height")); + bpc = fz_toint(fz_dictgets(dict, "BitsPerComponent")); - img->super.w = fz_toint(fz_dictgets(dict, "Width")); - 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); +printf("loading image "); fz_debugobj(dict); printf("\n"); +printf(" geometry %d x %d @ %d\n", w, h, bpc); cs = nil; obj = fz_dictgets(dict, "ColorSpace"); @@ -182,45 +229,52 @@ printf("load image %d x %d @ %d\n", img->super.w, img->super.h, img->bpc); if (error) return error; + if (!strcmp(cs->name, "Indexed")) + { +printf(" indexed!\n"); + indexed = (pdf_indexed*)cs; + cs = indexed->base; + } + + n = cs->n; + a = 0; + fz_dropobj(obj); } ismask = fz_tobool(fz_dictgets(dict, "ImageMask")); - if (!ismask) - { - img->super.cs = cs; - img->super.n = cs->n; - img->super.a = 0; - } - else + if (ismask) { - img->super.cs = nil; - img->super.n = 0; - img->super.a = 1; +printf(" image mask!\n"); + n = 0; + a = 1; } - img->stride = ((img->super.w * (img->super.n + img->super.a)) * img->bpc + 7) / 8; - 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)); + { +printf(" decode array!\n"); + if (img->indexed) + for (i = 0; i < 2; i++) + img->decode[i] = fz_toreal(fz_arrayget(obj, i)); + else + for (i = 0; i < (n + a) * 2; i++) + img->decode[i] = fz_toreal(fz_arrayget(obj, i)); + } else { - if (cs && !strcmp(cs->name, "IndexedXXX")) - for (i = 0; i < (img->super.n + img->super.a) * 2; i++) + if (img->indexed) + for (i = 0; i < 2; i++) img->decode[i] = i & 1 ? (1 << img->bpc) - 1 : 0; else - for (i = 0; i < (img->super.n + img->super.a) * 2; i++) + for (i = 0; i < (n + a) * 2; i++) img->decode[i] = i & 1; } -printf(" colorspace %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"); + if (indexed) + stride = (w * bpc + 7) / 8; + else + stride = (w * (n + a) * bpc + 7) / 8; error = pdf_loadstream(&img->samples, xref, fz_tonum(ref), fz_togen(ref)); if (error) @@ -230,7 +284,7 @@ printf("]\n"); return error; } - if (img->samples->wp - img->samples->bp != img->stride * img->super.h) + if (img->samples->wp - img->samples->bp < stride * h) { /* TODO: colorspace? */ fz_freebuffer(img->samples); @@ -246,6 +300,23 @@ printf("]\n"); *p = ~*p; } +printf(" decode [ "); +for (i = 0; i < (n + a) * 2; i++) +printf("%g ", img->decode[i]); +printf("]\n"); +printf("\n"); + + img->super.loadtile = loadtile; + img->super.free = nil; + img->super.cs = cs; + img->super.w = w; + img->super.h = h; + img->super.n = n; + img->super.a = a; + img->indexed = indexed; + img->stride = stride; + img->bpc = bpc; + *imgp = img; return nil; diff --git a/mupdf/interpret.c b/mupdf/interpret.c index eb9f60e0..cdee9fea 100644 --- a/mupdf/interpret.c +++ b/mupdf/interpret.c @@ -127,6 +127,8 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) float a, b, c, d, e, f; float x, y, w, h; fz_matrix m; + float v[32]; + int what; int i; if (strlen(buf) > 1) @@ -297,102 +299,75 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) else if (!strcmp(buf, "cs")) { - fz_obj *dict; - fz_obj *obj; - - if (csi->top != 1) - goto syntaxerror; - - error = pdf_flushtext(csi); - if (error) return error; - - obj = csi->stack[0]; - - if (!strcmp(fz_toname(obj), "DeviceGray")) - gstate->fillcs = pdf_devicegray; - else if (!strcmp(fz_toname(obj), "DeviceRGB")) - gstate->fillcs = pdf_devicergb; - else if (!strcmp(fz_toname(obj), "DeviceCMYK")) - gstate->fillcs = pdf_devicecmyk; - else - { - dict = fz_dictgets(rdb, "ColorSpace"); - if (!dict) - return fz_throw("syntaxerror: missing colorspace resource"); - obj = fz_dictget(dict, obj); - if (!obj) - return fz_throw("syntaxerror: missing colorspace resource"); - if (fz_isindirect(obj)) - gstate->fillcs = pdf_findresource(xref->rcolorspace, obj); - else - return fz_throw("syntaxerror: inline colorspace in dict"); - if (!gstate->fillcs) - return fz_throw("syntaxerror: missing colorspace resource"); - } - - // FIXME set default color + what = PDF_MFILL; + goto Lsetcolorspace; } else if (!strcmp(buf, "CS")) { - fz_obj *dict; + fz_colorspace *cs; fz_obj *obj; + what = PDF_MSTROKE; + +Lsetcolorspace: if (csi->top != 1) goto syntaxerror; - error = pdf_flushtext(csi); - if (error) return error; - obj = csi->stack[0]; if (!strcmp(fz_toname(obj), "DeviceGray")) - gstate->strokecs = pdf_devicegray; + cs = pdf_devicegray; else if (!strcmp(fz_toname(obj), "DeviceRGB")) - gstate->strokecs = pdf_devicergb; + cs = pdf_devicergb; else if (!strcmp(fz_toname(obj), "DeviceCMYK")) - gstate->strokecs = pdf_devicecmyk; + cs = pdf_devicecmyk; else { - dict = fz_dictgets(rdb, "ColorSpace"); + fz_obj *dict = fz_dictgets(rdb, "ColorSpace"); if (!dict) return fz_throw("syntaxerror: missing colorspace resource"); obj = fz_dictget(dict, obj); if (!obj) return fz_throw("syntaxerror: missing colorspace resource"); if (fz_isindirect(obj)) - gstate->strokecs = pdf_findresource(xref->rcolorspace, obj); + cs = pdf_findresource(xref->rcolorspace, obj); else return fz_throw("syntaxerror: inline colorspace in dict"); - if (!gstate->strokecs) + if (!cs) return fz_throw("syntaxerror: missing colorspace resource"); } - // FIXME set default color + error = pdf_setcolorspace(csi, what, cs); + if (error) return error; } else if (!strcmp(buf, "sc") || !strcmp(buf, "scn")) { - if (csi->top != gstate->fillcs->n) + if (gstate->fill.kind == PDF_MINDEXED && csi->top != 1) + goto syntaxerror; + else if (csi->top != gstate->fill.cs->n) goto syntaxerror; - - error = pdf_flushtext(csi); - if (error) return error; for (i = 0; i < csi->top; i++) - gstate->fill[i] = fz_toreal(csi->stack[i]); + v[i] = fz_toreal(csi->stack[i]); + + error = pdf_setcolor(csi, PDF_MFILL, v); + if (error) return error; } else if (!strcmp(buf, "SC") || !strcmp(buf, "SCN")) { - if (csi->top != gstate->strokecs->n) + if (gstate->stroke.kind == PDF_MINDEXED && csi->top != 1) + goto syntaxerror; + else if (csi->top != gstate->stroke.cs->n) goto syntaxerror; - - error = pdf_flushtext(csi); - if (error) return error; for (i = 0; i < csi->top; i++) - gstate->stroke[i] = fz_toreal(csi->stack[i]); + v[i] = fz_toreal(csi->stack[i]); + + error = pdf_setcolor(csi, PDF_MFILL, v); + if (error) return error; } else if (!strcmp(buf, "rg")) @@ -400,13 +375,14 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) if (csi->top != 3) goto syntaxerror; - error = pdf_flushtext(csi); - if (error) return error; + v[0] = fz_toreal(csi->stack[0]); + v[1] = fz_toreal(csi->stack[1]); + v[2] = fz_toreal(csi->stack[2]); - gstate->fillcs = pdf_devicergb; - gstate->fill[0] = fz_toreal(csi->stack[0]); - gstate->fill[1] = fz_toreal(csi->stack[1]); - gstate->fill[2] = fz_toreal(csi->stack[2]); + error = pdf_setcolorspace(csi, PDF_MFILL, pdf_devicergb); + if (error) return error; + error = pdf_setcolor(csi, PDF_MFILL, v); + if (error) return error; } else if (!strcmp(buf, "RG")) @@ -414,13 +390,14 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) if (csi->top != 3) goto syntaxerror; - error = pdf_flushtext(csi); - if (error) return error; + v[0] = fz_toreal(csi->stack[0]); + v[1] = fz_toreal(csi->stack[1]); + v[2] = fz_toreal(csi->stack[2]); - gstate->strokecs = pdf_devicergb; - gstate->stroke[0] = fz_toreal(csi->stack[0]); - gstate->stroke[1] = fz_toreal(csi->stack[1]); - gstate->stroke[2] = fz_toreal(csi->stack[2]); + error = pdf_setcolorspace(csi, PDF_MSTROKE, pdf_devicergb); + if (error) return error; + error = pdf_setcolor(csi, PDF_MSTROKE, v); + if (error) return error; } else if (!strcmp(buf, "BT")) @@ -776,50 +753,52 @@ fprintf(stderr, "syntaxerror: unknown keyword '%s'\n", buf); if (csi->top != 1) goto syntaxerror; - error = pdf_flushtext(csi); + v[0] = fz_toreal(csi->stack[0]); + error = pdf_setcolorspace(csi, PDF_MFILL, pdf_devicegray); + if (error) return error; + error = pdf_setcolor(csi, PDF_MFILL, v); if (error) return error; - - gstate->fillcs = pdf_devicegray; - gstate->fill[0] = fz_toreal(csi->stack[0]); break; case 'G': if (csi->top != 1) goto syntaxerror; - error = pdf_flushtext(csi); + v[0] = fz_toreal(csi->stack[0]); + error = pdf_setcolorspace(csi, PDF_MSTROKE, pdf_devicegray); + if (error) return error; + error = pdf_setcolor(csi, PDF_MSTROKE, v); if (error) return error; - - gstate->strokecs = pdf_devicegray; - gstate->stroke[0] = fz_toreal(csi->stack[0]); break; case 'k': if (csi->top != 4) goto syntaxerror; - error = pdf_flushtext(csi); - if (error) return error; + v[0] = fz_toreal(csi->stack[0]); + v[1] = fz_toreal(csi->stack[1]); + v[2] = fz_toreal(csi->stack[2]); + v[3] = fz_toreal(csi->stack[3]); - gstate->fillcs = pdf_devicecmyk; - gstate->fill[0] = fz_toreal(csi->stack[0]); - gstate->fill[1] = fz_toreal(csi->stack[1]); - gstate->fill[2] = fz_toreal(csi->stack[2]); - gstate->fill[3] = fz_toreal(csi->stack[3]); + error = pdf_setcolorspace(csi, PDF_MFILL, pdf_devicecmyk); + if (error) return error; + error = pdf_setcolor(csi, PDF_MFILL, v); + if (error) return error; break; case 'K': if (csi->top != 4) goto syntaxerror; - error = pdf_flushtext(csi); - if (error) return error; + v[0] = fz_toreal(csi->stack[0]); + v[1] = fz_toreal(csi->stack[1]); + v[2] = fz_toreal(csi->stack[2]); + v[3] = fz_toreal(csi->stack[3]); - gstate->strokecs = pdf_devicecmyk; - gstate->stroke[0] = fz_toreal(csi->stack[0]); - gstate->stroke[1] = fz_toreal(csi->stack[1]); - gstate->stroke[2] = fz_toreal(csi->stack[2]); - gstate->stroke[3] = fz_toreal(csi->stack[3]); + error = pdf_setcolorspace(csi, PDF_MSTROKE, pdf_devicecmyk); + if (error) return error; + error = pdf_setcolor(csi, PDF_MSTROKE, v); + if (error) return error; break; case '\'': |