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 fz_rethrow(error, "cannot finish text node (state change)"); mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; fz_dropcolorspace(mat->cs); mat->kind = PDF_MCOLOR; mat->cs = fz_keepcolorspace(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 fz_okay; }
void pdf_initgstate(pdf_gstate *gs, fz_matrix ctm) { gs->ctm = ctm; gs->clipdepth = 0; gs->strokestate.linewidth = 1; gs->strokestate.linecap = 0; gs->strokestate.linejoin = 0; gs->strokestate.miterlimit = 10; gs->strokestate.dashphase = 0; gs->strokestate.dashlen = 0; memset(gs->strokestate.dashlist, 0, sizeof(gs->strokestate.dashlist)); gs->stroke.kind = PDF_MCOLOR; gs->stroke.colorspace = fz_keepcolorspace(fz_devicegray); gs->stroke.v[0] = 0; gs->stroke.pattern = nil; gs->stroke.shade = nil; gs->stroke.alpha = 1; gs->fill.kind = PDF_MCOLOR; gs->fill.colorspace = fz_keepcolorspace(fz_devicegray); gs->fill.v[0] = 0; gs->fill.pattern = nil; gs->fill.shade = nil; gs->fill.alpha = 1; gs->charspace = 0; gs->wordspace = 0; gs->scale = 1; gs->leading = 0; gs->font = nil; gs->size = -1; gs->render = 0; gs->rise = 0; gs->blendmode = FZ_BNORMAL; gs->softmask = nil; gs->softmaskctm = fz_identity; gs->luminosity = 0; }
void pdf_initgstate(pdf_gstate *gs) { gs->linewidth = 1.0; gs->linecap = 0; gs->linejoin = 0; gs->miterlimit = 10; gs->dashphase = 0; gs->dashlen = 0; memset(gs->dashlist, 0, sizeof(gs->dashlist)); gs->stroke.kind = PDF_MCOLOR; gs->stroke.cs = fz_keepcolorspace(pdf_devicegray); gs->stroke.v[0] = 0; gs->stroke.indexed = nil; gs->stroke.pattern = nil; gs->stroke.shade = nil; gs->stroke.alpha = 1.0; gs->fill.kind = PDF_MCOLOR; gs->fill.cs = fz_keepcolorspace(pdf_devicegray); gs->fill.v[0] = 0; gs->fill.indexed = nil; gs->fill.pattern = nil; gs->fill.shade = nil; gs->fill.alpha = 1.0; gs->blendmode = FZ_BNORMAL; gs->charspace = 0; gs->wordspace = 0; gs->scale = 1; gs->leading = 0; gs->font = nil; gs->size = -1; gs->render = 0; gs->rise = 0; gs->head = nil; }
static fz_error loadseparation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) { fz_error error; struct separation *cs; fz_obj *nameobj = fz_arrayget(array, 1); fz_obj *baseobj = fz_arrayget(array, 2); fz_obj *tintobj = fz_arrayget(array, 3); fz_colorspace *base; pdf_function *tint; int n; pdf_logrsrc("load Separation {\n"); if (fz_isarray(nameobj)) n = fz_arraylen(nameobj); else n = 1; if (n > FZ_MAXCOLORS) return fz_throw("too many components in colorspace"); pdf_logrsrc("n = %d\n", n); error = pdf_loadcolorspace(&base, xref, baseobj); if (error) return fz_rethrow(error, "cannot load base colorspace"); error = pdf_loadfunction(&tint, xref, tintobj); if (error) { fz_dropcolorspace(base); return fz_rethrow(error, "cannot load tint function"); } cs = fz_malloc(sizeof(struct separation)); initcs((fz_colorspace*)cs, n == 1 ? "Separation" : "DeviceN", n, separationtoxyz, nil, freeseparation); cs->base = fz_keepcolorspace(base); cs->tint = pdf_keepfunction(tint); fz_dropcolorspace(base); pdf_dropfunction(tint); pdf_logrsrc("}\n"); *csp = (fz_colorspace*)cs; return fz_okay; }
fz_error * pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val) { fz_error *error; switch (kind) { case PDF_KCOLORSPACE: fz_keepcolorspace(val); break; case PDF_KFUNCTION: pdf_keepfunction(val); break; case PDF_KXOBJECT: pdf_keepxobject(val); break; case PDF_KIMAGE: fz_keepimage(val); break; case PDF_KPATTERN: pdf_keeppattern(val); break; case PDF_KSHADE: fz_keepshade(val); break; case PDF_KCMAP: pdf_keepcmap(val); break; case PDF_KFONT: fz_keepfont(val); break; } if (fz_isindirect(key)) { struct refkey item; pdf_logrsrc("store item %d: %d %d R = %p\n", kind, fz_tonum(key), fz_togen(key), val); item.kind = kind; item.oid = fz_tonum(key); item.gen = fz_togen(key); error = fz_hashinsert(store->hash, &item, val); if (error) return error; } else { pdf_item *item; item = fz_malloc(sizeof(pdf_item)); if (!item) return fz_outofmem; pdf_logrsrc("store item %d: ... = %p\n", kind, val); item->kind = kind; item->key = fz_keepobj(key); item->val = val; item->next = store->root; store->root = item; } return nil; }
static void keepitem(pdf_itemkind kind, void *val) { switch (kind) { case PDF_KCOLORSPACE: fz_keepcolorspace(val); break; case PDF_KFUNCTION: pdf_keepfunction(val); break; case PDF_KXOBJECT: pdf_keepxobject(val); break; case PDF_KIMAGE: fz_keepimage(val); break; case PDF_KPATTERN: pdf_keeppattern(val); break; case PDF_KSHADE: fz_keepshade(val); break; case PDF_KCMAP: pdf_keepcmap(val); break; case PDF_KFONT: pdf_keepfont(val); break; } }
fz_error pdf_loadcolorspace(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj) { fz_error error; if ((*csp = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj))) { fz_keepcolorspace(*csp); return fz_okay; } error = pdf_loadcolorspaceimp(csp, xref, obj); if (error) return fz_rethrow(error, "cannot load colorspace"); pdf_storeitem(xref->store, PDF_KCOLORSPACE, obj, *csp); return fz_okay; }
fz_error fz_newsolidnode(fz_node **nodep, float a, fz_colorspace *cs, int n, float *v) { fz_solidnode *node; int i; node = fz_malloc(sizeof(fz_solidnode) + sizeof(float) * n); if (!node) return fz_rethrow(-1, "out of memory"); *nodep = (fz_node*)node; fz_initnode((fz_node*)node, FZ_NCOLOR); node->a = a; node->cs = fz_keepcolorspace(cs); node->n = n; for (i = 0; i < n; i++) node->samples[i] = v[i]; return fz_okay; }
void pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *colorspace) { pdf_gstate *gs = csi->gstate + csi->gtop; pdf_material *mat; pdf_flushtext(csi); mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; fz_dropcolorspace(mat->colorspace); mat->kind = PDF_MCOLOR; mat->colorspace = fz_keepcolorspace(colorspace); mat->v[0] = 0; mat->v[1] = 0; mat->v[2] = 0; mat->v[3] = 1; }
static fz_error * loadshadedict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_matrix matrix) { fz_error *error; fz_shade *shade; fz_obj *obj; int type; int i; pdf_logshade("load shade dict %d %d {\n", fz_tonum(ref), fz_togen(ref)); shade = fz_malloc(sizeof(fz_shade)); if (!shade) return fz_outofmem; shade->refs = 1; shade->usebackground = 0; shade->usefunction = 0; shade->matrix = matrix; shade->bbox = fz_infiniterect; shade->meshlen = 0; shade->meshcap = 0; shade->mesh = nil; obj = fz_dictgets(dict, "ShadingType"); type = fz_toint(obj); pdf_logshade("type %d\n", type); /* TODO: flatten indexed... */ obj = fz_dictgets(dict, "ColorSpace"); if (obj) { shade->cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj); if (shade->cs) fz_keepcolorspace(shade->cs); else { error = pdf_resolve(&obj, xref); if (error) return error; error = pdf_loadcolorspace(&shade->cs, xref, obj); if (error) return error; fz_dropobj(obj); } } pdf_logshade("colorspace %s\n", shade->cs->name); obj = fz_dictgets(dict, "Background"); if (obj) { pdf_logshade("background\n"); shade->usebackground = 1; for (i = 0; i < shade->cs->n; i++) shade->background[i] = fz_toreal(fz_arrayget(obj, i)); } obj = fz_dictgets(dict, "BBox"); if (fz_isarray(obj)) { shade->bbox = pdf_torect(obj); pdf_logshade("bbox [%g %g %g %g]\n", shade->bbox.x0, shade->bbox.y0, shade->bbox.x1, shade->bbox.y1); } switch(type) { case 1: error = pdf_loadtype1shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 2: error = pdf_loadtype2shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 3: error = pdf_loadtype3shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 4: error = pdf_loadtype4shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 5: error = pdf_loadtype5shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 6: error = pdf_loadtype6shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 7: error = pdf_loadtype7shade(shade, xref, dict, ref); if (error) goto cleanup; break; default: fz_warn("syntaxerror: unknown shading type: %d", type); break; }; pdf_logshade("}\n"); *shadep = shade; return nil; cleanup: fz_dropshade(shade); return error; }
static fz_error loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) { fz_error error; pdf_indexed *cs; fz_obj *baseobj = fz_arrayget(array, 1); fz_obj *highobj = fz_arrayget(array, 2); fz_obj *lookup = fz_arrayget(array, 3); fz_colorspace *base; int n; pdf_logrsrc("load Indexed {\n"); error = pdf_loadcolorspace(&base, xref, baseobj); if (error) return fz_rethrow(error, "cannot load base colorspace"); pdf_logrsrc("base %s\n", base->name); cs = fz_malloc(sizeof(pdf_indexed)); initcs((fz_colorspace*)cs, "Indexed", 1, nil, nil, freeindexed); cs->base = fz_keepcolorspace(base); cs->high = fz_toint(highobj); fz_dropcolorspace(base); n = base->n * (cs->high + 1); cs->lookup = fz_malloc(n); if (fz_isstring(lookup) && fz_tostrlen(lookup) == n) { unsigned char *buf; int i; pdf_logrsrc("string lookup\n"); buf = (unsigned char *) fz_tostrbuf(lookup); for (i = 0; i < n; i++) cs->lookup[i] = buf[i]; } else if (fz_isindirect(lookup)) { fz_buffer *buf; int i; pdf_logrsrc("stream lookup\n"); error = pdf_loadstream(&buf, xref, fz_tonum(lookup), fz_togen(lookup)); if (error) { fz_dropcolorspace((fz_colorspace*)cs); return fz_rethrow(error, "cannot load colorpsace lookup table"); } for (i = 0; i < n && i < (buf->wp - buf->rp); i++) cs->lookup[i] = buf->rp[i]; fz_dropbuffer(buf); } else return fz_throw("cannot parse colorspace lookup table"); pdf_logrsrc("}\n"); *csp = (fz_colorspace*)cs; return fz_okay; }
/* TODO error cleanup */ fz_error * pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; pdf_image *img; pdf_image *mask; int ismask; fz_obj *obj; fz_obj *sub; int i; int w, h, bpc; int n = 0; int a = 0; int usecolorkey = 0; fz_colorspace *cs = nil; pdf_indexed *indexed = nil; int stride; #ifndef PSP printf("LI\n"); #endif if ((*imgp = pdf_finditem(xref->store, PDF_KIMAGE, ref))) { fz_keepimage((fz_image*)*imgp); return nil; } img = fz_malloc(sizeof(pdf_image)); if (!img) return fz_outofmem; img->super.refs = 0; pdf_logimage("load image %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), img); /* * Dimensions, BPC and ColorSpace */ w = fz_toint(fz_dictgets(dict, "Width")); h = fz_toint(fz_dictgets(dict, "Height")); bpc = fz_toint(fz_dictgets(dict, "BitsPerComponent")); pdf_logimage("size %dx%d %d\n", w, h, bpc); cs = nil; obj = fz_dictgets(dict, "ColorSpace"); if (obj) { cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj); if (cs) fz_keepcolorspace(cs); else { error = pdf_resolve(&obj, xref); if (error) return error; error = pdf_loadcolorspace(&cs, xref, obj); if (error) return error; fz_dropobj(obj); } if (!strcmp(cs->name, "Indexed")) { pdf_logimage("indexed\n"); indexed = (pdf_indexed*)cs; cs = indexed->base; } n = cs->n; a = 0; pdf_logimage("colorspace %s\n", cs->name); } /* * ImageMask, Mask and SoftMask */ mask = nil; ismask = fz_tobool(fz_dictgets(dict, "ImageMask")); if (ismask) { pdf_logimage("is mask\n"); bpc = 1; n = 0; a = 1; } obj = fz_dictgets(dict, "SMask"); if (fz_isindirect(obj)) { pdf_logimage("has soft mask\n"); error = pdf_loadindirect(&sub, xref, obj); if (error) return error; error = pdf_loadimage(&mask, xref, sub, obj); if (error) return error; if (mask->super.cs != pdf_devicegray) return fz_throw("syntaxerror: SMask must be DeviceGray"); mask->super.cs = 0; mask->super.n = 0; mask->super.a = 1; fz_dropobj(sub); } obj = fz_dictgets(dict, "Mask"); if (fz_isindirect(obj)) { error = pdf_loadindirect(&sub, xref, obj); if (error) return error; if (fz_isarray(sub)) { usecolorkey = 1; loadcolorkey(img->colorkey, bpc, indexed != nil, sub); } else { pdf_logimage("has mask\n"); error = pdf_loadimage(&mask, xref, sub, obj); if (error) return error; } fz_dropobj(sub); } else if (fz_isarray(obj)) { usecolorkey = 1; loadcolorkey(img->colorkey, bpc, indexed != nil, obj); } /* * Decode */ obj = fz_dictgets(dict, "Decode"); if (fz_isarray(obj)) { pdf_logimage("decode array\n"); if (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 (indexed) for (i = 0; i < 2; i++) img->decode[i] = i & 1 ? (1 << bpc) - 1 : 0; else for (i = 0; i < (n + a) * 2; i++) img->decode[i] = i & 1; } /* * Load samples */ if (indexed) stride = (w * bpc + 7) / 8; else stride = (w * (n + a) * bpc + 7) / 8; // ccm // do not load images larger than 2MB uncompressed int early_reject = 0; if (h * stride <= 2*1024*1024) { error = pdf_loadstream(&img->samples, xref, fz_tonum(ref), fz_togen(ref)); if (error) { /* TODO: colorspace? */ fz_free(img); return error; } if (img->samples->wp - img->samples->bp < stride * h) { /* TODO: colorspace? */ fz_dropbuffer(img->samples); fz_free(img); return fz_throw("syntaxerror: truncated image data"); } /* 0 means opaque and 1 means transparent, so we invert to get alpha */ if (ismask) { unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = ~*p; } } else { #ifndef PSP printf("LI - %p - early reject\n", img); #endif img->samples = nil; early_reject = 1; } /* * Create image object */ img->super.loadtile = pdf_loadtile; img->super.drop = pdf_dropimage; 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; img->mask = (fz_image*)mask; img->usecolorkey = usecolorkey; if (img->mask) fz_keepimage(img->mask); // ccm #if 1 int bs = 0; if (img->samples) bs = (int)(img->samples->wp) - (int)(img->samples->rp); if (early_reject || (image_buffers_size + bs >= image_buffers_size_max)) { #ifndef PSP printf("LI - %p - optimized out\n", img); #endif if (img->samples) fz_dropbuffer(img->samples); if (img->mask) fz_dropimage(img->mask); fz_newbuffer(&img->samples, 8); img->super.w = 1; img->super.h = 1; img->super.n = 3; img->super.a = 0; img->super.refs = 0; unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = 0x7f; img->indexed = 0; img->stride = (1 * (3 + 0) * 8 + 7) / 8; //(w * (n + a) * bpc + 7) / 8; img->super.cs = cs; img->super.loadtile = fakeImageTile; img->bpc = 8; img->mask = NULL; img->usecolorkey = 0; } else { image_buffers_size += bs; } #endif pdf_logimage("}\n"); error = pdf_storeitem(xref->store, PDF_KIMAGE, ref, img); if (error) { fz_dropimage((fz_image*)img); return error; } *imgp = img; return nil; }
fz_error * pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file) { fz_error *error; pdf_image *img; fz_filter *filter; fz_obj *f; fz_obj *cs; fz_obj *d; int ismask; int i; img = fz_malloc(sizeof(pdf_image)); if (!img) return fz_outofmem; pdf_logimage("load inline image %p {\n", img); img->super.loadtile = pdf_loadtile; img->super.drop = pdf_dropimage; img->super.n = 0; img->super.a = 0; img->super.refs = 0; img->indexed = nil; img->usecolorkey = 0; img->mask = nil; img->super.w = fz_toint(fz_dictgetsa(dict, "Width", "W")); img->super.h = fz_toint(fz_dictgetsa(dict, "Height", "H")); img->bpc = fz_toint(fz_dictgetsa(dict, "BitsPerComponent", "BPC")); ismask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM")); d = fz_dictgetsa(dict, "Decode", "D"); cs = fz_dictgetsa(dict, "ColorSpace", "CS"); pdf_logimage("size %dx%d %d\n", img->super.w, img->super.h, img->bpc); if (ismask) { pdf_logimage("is mask\n"); img->super.cs = nil; img->super.n = 0; img->super.a = 1; img->bpc = 1; } if (cs) { img->super.cs = nil; if (fz_isname(cs)) { fz_obj *csd = fz_dictgets(rdb, "ColorSpace"); if (csd) { fz_obj *cso = fz_dictget(csd, cs); img->super.cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, cso); if (img->super.cs) fz_keepcolorspace(img->super.cs); } } if (!img->super.cs) { /* XXX danger! danger! does this resolve? */ error = pdf_loadcolorspace(&img->super.cs, xref, cs); if (error) return error; } if (!strcmp(img->super.cs->name, "Indexed")) { pdf_logimage("indexed\n"); img->indexed = (pdf_indexed*)img->super.cs; img->super.cs = img->indexed->base; } pdf_logimage("colorspace %s\n", img->super.cs->name); img->super.n = img->super.cs->n; img->super.a = 0; } if (fz_isarray(d)) { pdf_logimage("decode array\n"); if (img->indexed) for (i = 0; i < 2; i++) img->decode[i] = fz_toreal(fz_arrayget(d, i)); else for (i = 0; i < (img->super.n + img->super.a) * 2; i++) img->decode[i] = fz_toreal(fz_arrayget(d, i)); } else { 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++) img->decode[i] = i & 1; } if (img->indexed) img->stride = (img->super.w * img->bpc + 7) / 8; else img->stride = (img->super.w * (img->super.n + img->super.a) * img->bpc + 7) / 8; /* load image data */ f = fz_dictgetsa(dict, "Filter", "F"); if (f) { fz_stream *tempfile; error = pdf_buildinlinefilter(&filter, dict); if (error) return error; error = fz_openrfilter(&tempfile, filter, file); if (error) return error; i = fz_readall(&img->samples, tempfile); if (i < 0) return fz_ioerror(tempfile); fz_dropfilter(filter); fz_dropstream(tempfile); } else { error = fz_newbuffer(&img->samples, img->super.h * img->stride); if (error) return error; i = fz_read(file, img->samples->bp, img->super.h * img->stride); if (i < 0) return fz_ioerror(file); img->samples->wp += img->super.h * img->stride; } /* 0 means opaque and 1 means transparent, so we invert to get alpha */ if (ismask) { unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = ~*p; } pdf_logimage("}\n"); *imgp = img; return nil; }