static fz_error * loadcalgray(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict) { fz_error *error; struct calgray *cs; fz_obj *tmp; error = pdf_resolve(&dict, xref); if (error) return error; cs = fz_malloc(sizeof(struct calgray)); if (!cs) return fz_outofmem; pdf_logrsrc("load CalGray\n"); initcs((fz_colorspace*)cs, "CalGray", 1, graytoxyz, xyztogray, nil); cs->white[0] = 1.0; cs->white[1] = 1.0; cs->white[2] = 1.0; cs->black[0] = 0.0; cs->black[1] = 0.0; cs->black[2] = 0.0; cs->gamma = 1.0; tmp = fz_dictgets(dict, "WhitePoint"); if (fz_isarray(tmp)) { cs->white[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->white[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->white[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "BlackPoint"); if (fz_isarray(tmp)) { cs->black[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->black[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->black[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Gamma"); if (fz_isreal(tmp)) cs->gamma = fz_toreal(tmp); fz_dropobj(dict); *csp = (fz_colorspace*) cs; return nil; }
static fz_colorspace * loadlab(pdf_xref *xref, fz_obj *dict) { struct cielab *cs; fz_obj *tmp; cs = fz_malloc(sizeof(struct cielab)); pdf_logrsrc("load Lab\n"); initcs((fz_colorspace*)cs, "Lab", 3, labtoxyz, xyztolab, nil); cs->white[0] = 1.0; cs->white[1] = 1.0; cs->white[2] = 1.0; cs->black[0] = 0.0; cs->black[1] = 0.0; cs->black[2] = 0.0; cs->range[0] = -100; cs->range[1] = 100; cs->range[2] = -100; cs->range[3] = 100; tmp = fz_dictgets(dict, "WhitePoint"); if (fz_isarray(tmp)) { cs->white[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->white[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->white[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "BlackPoint"); if (fz_isarray(tmp)) { cs->black[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->black[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->black[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Range"); if (fz_isarray(tmp)) { cs->range[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->range[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->range[2] = fz_toreal(fz_arrayget(tmp, 2)); cs->range[3] = fz_toreal(fz_arrayget(tmp, 3)); } return (fz_colorspace*) cs; }
static fz_error pdf_loadpagecontents(fz_buffer **bufp, pdf_xref *xref, fz_obj *obj) { fz_error error; if (fz_isarray(obj)) { error = pdf_loadpagecontentsarray(bufp, xref, obj); if (error) return fz_rethrow(error, "cannot load content stream array (%d 0 R)", fz_tonum(obj)); } else if (pdf_isstream(xref, fz_tonum(obj), fz_togen(obj))) { error = pdf_loadstream(bufp, xref, fz_tonum(obj), fz_togen(obj)); if (error) return fz_rethrow(error, "cannot load content stream (%d 0 R)", fz_tonum(obj)); } else { fz_warn("page contents missing, leaving page blank"); *bufp = fz_newbuffer(0); } return fz_okay; }
static fz_obj * resolvedest(pdf_xref *xref, fz_obj *dest) { if (fz_isname(dest) || fz_isstring(dest)) { dest = pdf_lookupdest(xref, dest); return resolvedest(xref, dest); } else if (fz_isarray(dest)) { return dest; /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=275 */ } else if (fz_isdict(dest)) { dest = fz_dictgets(dest, "D"); return resolvedest(xref, dest); } else if (fz_isindirect(dest)) return dest; return nil; }
static fz_obj * resolvedest(pdf_xref *xref, fz_obj *dest) { if (fz_isname(dest)) { dest = fz_dictget(xref->dests, dest); if (dest) pdf_resolve(&dest, xref); /* XXX */ return resolvedest(xref, dest); } else if (fz_isstring(dest)) { dest = fz_dictget(xref->dests, dest); if (dest) pdf_resolve(&dest, xref); /* XXX */ return resolvedest(xref, dest); } else if (fz_isarray(dest)) { return fz_arrayget(dest, 0); } else if (fz_isdict(dest)) { dest = fz_dictgets(dest, "D"); return resolvedest(xref, dest); } else if (fz_isindirect(dest)) return dest; return nil; }
static fz_obj * resolvedest(pdf_xref *xref, fz_obj *dest) { if (fz_isname(dest) || fz_isstring(dest)) { dest = pdf_lookupdest(xref, dest); return resolvedest(xref, dest); } else if (fz_isarray(dest)) { return fz_arrayget(dest, 0); } else if (fz_isdict(dest)) { dest = fz_dictgets(dest, "D"); return resolvedest(xref, dest); } else if (fz_isindirect(dest)) return dest; return nil; }
static void addhexfilter(fz_obj *dict) { fz_obj *f, *dp, *newf, *newdp; fz_obj *ahx, *nullobj; ahx = fz_newname("ASCIIHexDecode"); nullobj = fz_newnull(); newf = newdp = nil; f = fz_dictgets(dict, "Filter"); dp = fz_dictgets(dict, "DecodeParms"); if (fz_isname(f)) { newf = fz_newarray(2); fz_arraypush(newf, ahx); fz_arraypush(newf, f); f = newf; if (fz_isdict(dp)) { newdp = fz_newarray(2); fz_arraypush(newdp, nullobj); fz_arraypush(newdp, dp); dp = newdp; } } else if (fz_isarray(f)) { fz_arrayinsert(f, ahx); if (fz_isarray(dp)) fz_arrayinsert(dp, nullobj); } else f = ahx; fz_dictputs(dict, "Filter", f); if (dp) fz_dictputs(dict, "DecodeParms", dp); fz_dropobj(ahx); fz_dropobj(nullobj); if (newf) fz_dropobj(newf); if (newdp) fz_dropobj(newdp); }
fz_error* setPageMediaBox( pdf_xref* pdfXRef, fz_obj* pageObj, fz_rect mediaBox ) { fz_error *error; fz_obj *objMedia; fz_irect mRect; fz_obj *objInt; // Delete the CropBox. This is done because we are reducing // the size of the media box and CropBox is of no use to us fz_dictdels(pageObj, "CropBox"); //objMedia = fz_dictgets(pageObj, "CropBox"); //if (objMedia == NULL) return fz_throw("no CropBox entry"); //error = pdf_resolve(&objMedia, pdfXRef); //if (error) return fz_rethrow(error, "cannot resolve page bounds"); //if (! fz_isarray(objMedia)) return fz_throw("cannot find page bounds"); //fz_rect cRect = pdf_torect(objMedia); // Get the media box objMedia = fz_dictgets(pageObj, "MediaBox"); if (objMedia == NULL) return fz_throw("no MediaBox entry"); error = pdf_resolve(&objMedia, pdfXRef); if (error) return fz_rethrow(error, "cannot resolve page bounds"); if (! fz_isarray(objMedia)) return fz_throw("cannot find page bounds"); // We have the MediaBox array here mRect = fz_roundrect(mediaBox); error = fz_newint(&objInt, mRect.x0); if (error) return fz_rethrow(error, "cannot allocate int"); fz_arrayput(objMedia, 0, objInt); fz_dropobj(objInt); error = fz_newint(&objInt, mRect.y0); if (error) return fz_rethrow(error, "cannot allocate int"); fz_arrayput(objMedia, 1, objInt); fz_dropobj(objInt); error = fz_newint(&objInt, mRect.x1); if (error) return fz_rethrow(error, "cannot allocate int"); fz_arrayput(objMedia, 2, objInt); fz_dropobj(objInt); error = fz_newint(&objInt, mRect.y1); if (error) return fz_rethrow(error, "cannot allocate int"); fz_arrayput(objMedia, 3, objInt); fz_dropobj(objInt); return NULL; }
static fz_colorspace * loadcalgray(pdf_xref *xref, fz_obj *dict) { struct calgray *cs; fz_obj *tmp; cs = fz_malloc(sizeof(struct calgray)); pdf_logrsrc("load CalGray\n"); initcs((fz_colorspace*)cs, "CalGray", 1, graytoxyz, xyztogray, nil); cs->white[0] = 1.0; cs->white[1] = 1.0; cs->white[2] = 1.0; cs->black[0] = 0.0; cs->black[1] = 0.0; cs->black[2] = 0.0; cs->gamma = 1.0; tmp = fz_dictgets(dict, "WhitePoint"); if (fz_isarray(tmp)) { cs->white[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->white[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->white[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "BlackPoint"); if (fz_isarray(tmp)) { cs->black[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->black[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->black[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Gamma"); if (fz_isreal(tmp)) cs->gamma = fz_toreal(tmp); return (fz_colorspace*) cs; }
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; pdf_logrsrc("n = %d\n", n); error = pdf_resolve(&baseobj, xref); if (error) return error; error = pdf_loadcolorspace(&base, xref, baseobj); fz_dropobj(baseobj); if (error) return error; error = pdf_loadfunction(&tint, xref, tintobj); if (error) { fz_dropcolorspace(base); return error; } cs = fz_malloc(sizeof(struct separation)); if (!cs) { pdf_dropfunction(tint); fz_dropcolorspace(base); return fz_outofmem; } initcs((fz_colorspace*)cs, n == 1 ? "Separation" : "DeviceN", n, separationtoxyz, nil, dropseparation); cs->base = base; cs->tint = tint; pdf_logrsrc("}\n"); *csp = (fz_colorspace*)cs; return nil; }
int epdf_index_item_page_get(const Epdf_Document *doc, const Epdf_Index_Item *item) { fz_obj *dest; int p; int n; int g; if (!item || !item->link) return -1; if (PDF_LGOTO != item->link->kind) return -1; dest = item->link->dest; p = 0; if (fz_isint(dest)) { p = fz_toint(dest); return p; } if (fz_isdict(dest)) { /* The destination is linked from a Go-To action's D array */ fz_obj *D; D = fz_dictgets(dest, "D"); if (D && fz_isarray(D)) dest = fz_arrayget(D, 0); } n = fz_tonum(dest); g = fz_togen(dest); for (p = 1; p <= epdf_document_page_count_get(doc); p++) { fz_obj *page; int np; int gp; page = pdf_getpageobject(doc->xref, p); if (!page) continue; np = fz_tonum(page); gp = fz_togen(page); if (n == np && g == gp) return p-1; } return 0; }
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_showtext(pdf_csi *csi, fz_obj *text) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_font *font = gstate->font; fz_error *error; unsigned char *buf; unsigned char *end; int i, len; int cpt, cid; if (fz_isarray(text)) { for (i = 0; i < fz_arraylen(text); i++) { fz_obj *item = fz_arrayget(text, i); if (fz_isstring(item)) { error = pdf_showtext(csi, item); if (error) return fz_rethrow(error, "cannot draw text item"); } else { showspace(csi, - fz_toreal(item) * gstate->size / 1000.0); } } return fz_okay; } buf = (unsigned char *)fz_tostrbuf(text); len = fz_tostrlen(text); end = buf + len; while (buf < end) { buf = pdf_decodecmap(font->encoding, buf, &cpt); cid = pdf_lookupcmap(font->encoding, cpt); if (cid == -1) cid = 0; error = showglyph(csi, cid); if (error) return fz_rethrow(error, "cannot draw glyph"); if (cpt == 32) showspace(csi, gstate->wordspace); } return fz_okay; }
static void sweepobj(fz_obj *obj) { int i; if (fz_isindirect(obj)) sweepref(obj); else if (fz_isdict(obj)) for (i = 0; i < fz_dictlen(obj); i++) sweepobj(fz_dictgetval(obj, i)); else if (fz_isarray(obj)) for (i = 0; i < fz_arraylen(obj); i++) sweepobj(fz_arrayget(obj, i)); }
void pdf_showtext(pdf_csi *csi, fz_obj *text) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_fontdesc *fontdesc = gstate->font; unsigned char *buf; unsigned char *end; int i, len; int cpt, cid; if (!fontdesc) { fz_warn("cannot draw text since font and size not set"); return; } if (fz_isarray(text)) { for (i = 0; i < fz_arraylen(text); i++) { fz_obj *item = fz_arrayget(text, i); if (fz_isstring(item)) pdf_showtext(csi, item); else pdf_showspace(csi, - fz_toreal(item) * gstate->size * 0.001f); } } if (fz_isstring(text)) { buf = (unsigned char *)fz_tostrbuf(text); len = fz_tostrlen(text); end = buf + len; while (buf < end) { buf = pdf_decodecmap(fontdesc->encoding, buf, &cpt); cid = pdf_lookupcmap(fontdesc->encoding, cpt); if (cid == -1) cid = 0; pdf_showglyph(csi, cid); if (cpt == 32) pdf_showspace(csi, gstate->wordspace); } } }
static fz_error gatherdimensions(int page, fz_obj *pageobj) { fz_obj *ref; fz_rect bbox; fz_obj *obj; int j; obj = ref = fz_dictgets(pageobj, "MediaBox"); if (!fz_isarray(obj)) return fz_throw("cannot find page bounds (%d %d R)", fz_tonum(ref), fz_togen(ref)); bbox = pdf_torect(obj); for (j = 0; j < dims; j++) if (!memcmp(dim[j]->u.dim.bbox, &bbox, sizeof (fz_rect))) break; if (j < dims) return fz_okay; dims++; dim = fz_realloc(dim, dims * sizeof (struct info *)); if (!dim) return fz_throw("out of memory"); dim[dims - 1] = fz_malloc(sizeof (struct info)); if (!dim[dims - 1]) return fz_throw("out of memory"); dim[dims - 1]->u.dim.bbox = fz_malloc(sizeof (fz_rect)); if (!dim[dims - 1]->u.dim.bbox) return fz_throw("out of memory"); dim[dims - 1]->page = page; dim[dims - 1]->pageobj = pageobj; dim[dims - 1]->ref = nil; memcpy(dim[dims - 1]->u.dim.bbox, &bbox, sizeof (fz_rect)); return fz_okay; }
static void renumberobj(fz_obj *obj) { int i; if (fz_isdict(obj)) { for (i = 0; i < fz_dictlen(obj); i++) { fz_obj *key = fz_dictgetkey(obj, i); fz_obj *val = fz_dictgetval(obj, i); if (fz_isindirect(val)) { val = fz_newindirect(renumbermap[fz_tonum(val)], 0, xref); fz_dictput(obj, key, val); fz_dropobj(val); } else { renumberobj(val); } } } else if (fz_isarray(obj)) { for (i = 0; i < fz_arraylen(obj); i++) { fz_obj *val = fz_arrayget(obj, i); if (fz_isindirect(val)) { val = fz_newindirect(renumbermap[fz_tonum(val)], 0, xref); fz_arrayput(obj, i, val); fz_dropobj(val); } else { renumberobj(val); } } } }
/* * Build a chain of filters given filter names and param dicts. * If head is given, start filter chain with it. * Assume ownership of head. */ static fz_error * buildfilterchain(fz_filter **filterp, fz_filter *head, fz_obj *fs, fz_obj *ps) { fz_error *error; fz_filter *newhead; fz_filter *tail; fz_obj *f; fz_obj *p; int i; for (i = 0; i < fz_arraylen(fs); i++) { f = fz_arrayget(fs, i); if (fz_isarray(ps)) p = fz_arrayget(ps, i); else p = nil; error = buildonefilter(&tail, f, p); if (error) return fz_rethrow(error, "cannot create filter"); if (head) { error = fz_newpipeline(&newhead, head, tail); fz_dropfilter(head); fz_dropfilter(tail); if (error) { fz_dropfilter(newhead); return fz_rethrow(error, "cannot create pipeline filter"); } head = newhead; } else head = tail; } *filterp = head; return fz_okay; }
void pdf_showtext(pdf_csi *csi, fz_obj *text) { pdf_gstate *gstate = csi->gstate + csi->gtop; int i; if (fz_isarray(text)) { for (i = 0; i < fz_arraylen(text); i++) { fz_obj *item = fz_arrayget(text, i); if (fz_isstring(item)) pdf_showstring(csi, (unsigned char *)fz_tostrbuf(item), fz_tostrlen(item)); else pdf_showspace(csi, - fz_toreal(item) * gstate->size * 0.001f); } } else if (fz_isstring(text)) { pdf_showstring(csi, (unsigned char *)fz_tostrbuf(text), fz_tostrlen(text)); } }
static fz_error gatherimages(int page, fz_obj *pageobj, fz_obj *dict) { int i; for (i = 0; i < fz_dictlen(dict); i++) { fz_obj *ref; fz_obj *imagedict; fz_obj *type; fz_obj *width; fz_obj *height; fz_obj *bpc = nil; fz_obj *filter = nil; fz_obj *mask; fz_obj *cs = nil; fz_obj *altcs; int k; imagedict = ref = fz_dictgetval(dict, i); if (!fz_isdict(imagedict)) return fz_throw("not an image dict (%d %d R)", fz_tonum(ref), fz_togen(ref)); type = fz_dictgets(imagedict, "Subtype"); if (!fz_isname(type)) return fz_throw("not an image subtype (%d %d R)", fz_tonum(ref), fz_togen(ref)); if (strcmp(fz_toname(type), "Image")) continue; filter = fz_dictgets(imagedict, "Filter"); if (filter && !fz_isname(filter) && !fz_isarray(filter)) return fz_throw("not an image filter (%d %d R)", fz_tonum(ref), fz_togen(ref)); mask = fz_dictgets(imagedict, "ImageMask"); altcs = nil; cs = fz_dictgets(imagedict, "ColorSpace"); if (fz_isarray(cs)) { fz_obj *cses = cs; cs = fz_arrayget(cses, 0); if (fz_isname(cs) && (!strcmp(fz_toname(cs), "DeviceN") || !strcmp(fz_toname(cs), "Separation"))) { altcs = fz_arrayget(cses, 2); if (fz_isarray(altcs)) altcs = fz_arrayget(altcs, 0); } } if (fz_isbool(mask) && fz_tobool(mask)) { if (cs) fz_warn("image mask (%d %d R) may not have colorspace", fz_tonum(ref), fz_togen(ref)); } if (cs && !fz_isname(cs)) return fz_throw("not an image colorspace (%d %d R)", fz_tonum(ref), fz_togen(ref)); if (altcs && !fz_isname(altcs)) return fz_throw("not an image alternate colorspace (%d %d R)", fz_tonum(ref), fz_togen(ref)); width = fz_dictgets(imagedict, "Width"); if (!fz_isint(width)) return fz_throw("not an image width (%d %d R)", fz_tonum(ref), fz_togen(ref)); height = fz_dictgets(imagedict, "Height"); if (!fz_isint(height)) return fz_throw("not an image height (%d %d R)", fz_tonum(ref), fz_togen(ref)); bpc = fz_dictgets(imagedict, "BitsPerComponent"); if (!fz_tobool(mask) && !fz_isint(bpc)) return fz_throw("not an image bits per component (%d %d R)", fz_tonum(ref), fz_togen(ref)); if (fz_tobool(mask) && fz_isint(bpc) && fz_toint(bpc) != 1) return fz_throw("not an image mask bits per component (%d %d R)", fz_tonum(ref), fz_togen(ref)); for (k = 0; k < images; k++) if (fz_tonum(image[k]->ref) == fz_tonum(ref) && fz_togen(image[k]->ref) == fz_togen(ref)) break; if (k < images) continue; images++; image = fz_realloc(image, images * sizeof (struct info *)); if (!image) return fz_throw("out of memory"); image[images - 1] = fz_malloc(sizeof (struct info)); if (!image[images - 1]) return fz_throw("out of memory"); image[images - 1]->page = page; image[images - 1]->pageobj = pageobj; image[images - 1]->ref = ref; image[images - 1]->u.image.width = width; image[images - 1]->u.image.height = height; image[images - 1]->u.image.bpc = bpc; image[images - 1]->u.image.filter = filter; image[images - 1]->u.image.cs = cs; image[images - 1]->u.image.altcs = altcs; } return fz_okay; }
static fz_colorspace * loadcalrgb(pdf_xref *xref, fz_obj *dict) { struct calrgb *cs; fz_obj *tmp; int i; cs = fz_malloc(sizeof(struct calrgb)); pdf_logrsrc("load CalRGB\n"); initcs((fz_colorspace*)cs, "CalRGB", 3, rgbtoxyz, xyztorgb, nil); cs->white[0] = 1.0; cs->white[1] = 1.0; cs->white[2] = 1.0; cs->black[0] = 0.0; cs->black[1] = 0.0; cs->black[2] = 0.0; cs->gamma[0] = 1.0; cs->gamma[1] = 1.0; cs->gamma[2] = 1.0; cs->matrix[0] = 1.0; cs->matrix[1] = 0.0; cs->matrix[2] = 0.0; cs->matrix[3] = 0.0; cs->matrix[4] = 1.0; cs->matrix[5] = 0.0; cs->matrix[6] = 0.0; cs->matrix[7] = 0.0; cs->matrix[8] = 1.0; tmp = fz_dictgets(dict, "WhitePoint"); if (fz_isarray(tmp)) { cs->white[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->white[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->white[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "BlackPoint"); if (fz_isarray(tmp)) { cs->black[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->black[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->black[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Gamma"); if (fz_isarray(tmp)) { cs->gamma[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->gamma[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->gamma[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Matrix"); if (fz_isarray(tmp)) { for (i = 0; i < 9; i++) cs->matrix[i] = fz_toreal(fz_arrayget(tmp, i)); } fz_invert3x3(cs->invmat, cs->matrix); return (fz_colorspace*) cs; }
static fz_error loadsimplefont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict) { fz_error error; fz_obj *descriptor = nil; fz_obj *encoding = nil; fz_obj *widths = nil; unsigned short *etable = nil; pdf_fontdesc *fontdesc; fz_irect bbox; FT_Face face; FT_CharMap cmap; int kind; int symbolic; char *basefont; char *fontname; char *estrings[256]; char ebuffer[256][32]; int i, k, n; int fterr; basefont = fz_toname(fz_dictgets(dict, "BaseFont")); fontname = cleanfontname(basefont); /* * Load font file */ fontdesc = pdf_newfontdesc(); if (!fontdesc) return fz_rethrow(-1, "out of memory"); pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("basefont0 %s\n", basefont); pdf_logfont("basefont1 %s\n", fontname); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor && basefont == fontname) error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, nil); else error = pdf_loadbuiltinfont(fontdesc, fontname); if (error) goto cleanup; face = fontdesc->font->ftface; kind = ftkind(face); pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name); bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM; bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM; bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM; bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM; pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); if (bbox.x0 == bbox.x1) fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000); else fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* * Encoding */ symbolic = fontdesc->flags & 4; if (face->num_charmaps > 0) cmap = face->charmaps[0]; else cmap = nil; for (i = 0; i < face->num_charmaps; i++) { FT_CharMap test = face->charmaps[i]; if (kind == TYPE1) { if (test->platform_id == 7) cmap = test; } if (kind == TRUETYPE) { if (test->platform_id == 1 && test->encoding_id == 0) cmap = test; if (test->platform_id == 3 && test->encoding_id == 1) cmap = test; } } if (cmap) { fterr = FT_Set_Charmap(face, cmap); if (fterr) fz_warn("freetype could not set cmap: %s", ft_errorstring(fterr)); } else fz_warn("freetype could not find any cmaps"); etable = fz_malloc(sizeof(unsigned short) * 256); if (!etable) goto cleanup; for (i = 0; i < 256; i++) { estrings[i] = nil; etable[i] = 0; } encoding = fz_dictgets(dict, "Encoding"); if (encoding && !(kind == TRUETYPE && symbolic)) { if (fz_isname(encoding)) pdf_loadencoding(estrings, fz_toname(encoding)); if (fz_isdict(encoding)) { fz_obj *base, *diff, *item; base = fz_dictgets(encoding, "BaseEncoding"); if (fz_isname(base)) pdf_loadencoding(estrings, fz_toname(base)); else if (!fontdesc->isembedded) pdf_loadencoding(estrings, "StandardEncoding"); diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { n = fz_arraylen(diff); k = 0; for (i = 0; i < n; i++) { item = fz_arrayget(diff, i); if (fz_isint(item)) k = fz_toint(item); if (fz_isname(item)) estrings[k++] = fz_toname(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } if (kind == TYPE1) { pdf_logfont("encode type1/cff by strings\n"); for (i = 0; i < 256; i++) if (estrings[i]) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, i); } if (kind == TRUETYPE) { /* Unicode cmap */ if (face->charmap && face->charmap->platform_id == 3) { pdf_logfont("encode truetype via unicode\n"); for (i = 0; i < 256; i++) if (estrings[i]) { int aglbuf[256]; int aglnum; aglnum = pdf_lookupagl(estrings[i], aglbuf, nelem(aglbuf)); if (aglnum != 1) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, aglbuf[0]); } else etable[i] = ftcharindex(face, i); } /* MacRoman cmap */ else if (face->charmap && face->charmap->platform_id == 1) { pdf_logfont("encode truetype via macroman\n"); for (i = 0; i < 256; i++) if (estrings[i]) { k = mrecode(estrings[i]); if (k <= 0) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, k); } else etable[i] = ftcharindex(face, i); } /* Symbolic cmap */ else { pdf_logfont("encode truetype symbolic\n"); for (i = 0; i < 256; i++) { etable[i] = ftcharindex(face, i); fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) { error = fz_throw("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr)); goto cleanup; } if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } } } } else { pdf_logfont("encode builtin\n"); for (i = 0; i < 256; i++) { etable[i] = ftcharindex(face, i); if (etable[i] == 0) continue; if (FT_HAS_GLYPH_NAMES(face)) { fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) { error = fz_throw("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr)); goto cleanup; } if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } } } error = pdf_newidentitycmap(&fontdesc->encoding, 0, 1); if (error) goto cleanup; fontdesc->ncidtogid = 256; fontdesc->cidtogid = etable; error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* * Widths */ pdf_setdefaulthmtx(fontdesc, fontdesc->missingwidth); widths = fz_dictgets(dict, "Widths"); if (widths) { int first, last; first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); if (first < 0 || last > 255 || first > last) first = last = 0; for (i = 0; i < last - first + 1; i++) { int wid = fz_toint(fz_arrayget(widths, i)); error = pdf_addhmtx(fontdesc, i + first, i + first, wid); if (error) goto cleanup; } } else { fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); if (fterr) fz_warn("freetype set character size: %s", ft_errorstring(fterr)); for (i = 0; i < 256; i++) { error = pdf_addhmtx(fontdesc, i, i, ftwidth(fontdesc, i)); if (error) goto cleanup; } } error = pdf_endhmtx(fontdesc); if (error) goto cleanup; pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: fz_free(etable); fz_dropfont(fontdesc->font); fz_free(fontdesc); return fz_rethrow(error, "cannot load simple font"); }
static void printinfo(char *filename, int show, int page) { int i; int j; #define PAGE_FMT "\t% 6d (% 6d %1d R): " if (show & DIMENSIONS && dims > 0) { printf("MediaBox: "); printf("\n"); for (i = 0; i < dims; i++) { printf(PAGE_FMT "[ %g %g %g %g ]\n", dim[i]->page, fz_tonum(dim[i]->pageobj), fz_togen(dim[i]->pageobj), dim[i]->u.dim.bbox->x0, dim[i]->u.dim.bbox->y0, dim[i]->u.dim.bbox->x1, dim[i]->u.dim.bbox->y1); } printf("\n"); for (i = 0; i < dims; i++) { fz_free(dim[i]->u.dim.bbox); fz_free(dim[i]); } fz_free(dim); dim = nil; dims = 0; } if (show & FONTS && fonts > 0) { printf("Fonts (%d):\n", fonts); for (i = 0; i < fonts; i++) { printf(PAGE_FMT "%s '%s' (%d %d R)\n", font[i]->page, fz_tonum(font[i]->pageobj), fz_togen(font[i]->pageobj), fz_toname(font[i]->u.font.subtype), fz_toname(font[i]->u.font.name), fz_tonum(font[i]->ref), fz_togen(font[i]->ref)); } printf("\n"); for (i = 0; i < fonts; i++) fz_free(font[i]); fz_free(font); font = nil; fonts = 0; } if (show & IMAGES && images > 0) { printf("Images (%d):\n", images); for (i = 0; i < images; i++) { printf(PAGE_FMT "[ ", image[i]->page, fz_tonum(image[i]->pageobj), fz_togen(image[i]->pageobj)); if (fz_isarray(image[i]->u.image.filter)) for (j = 0; j < fz_arraylen(image[i]->u.image.filter); j++) { printf("%s%s", fz_toname(fz_arrayget(image[i]->u.image.filter, j)), j == fz_arraylen(image[i]->u.image.filter) - 1 ? "" : " "); } else if (image[i]->u.image.filter) printf("%s", fz_toname(image[i]->u.image.filter)); else printf("Raw"); printf(" ] %dx%d %dbpc %s%s%s (%d %d R)\n", fz_toint(image[i]->u.image.width), fz_toint(image[i]->u.image.height), image[i]->u.image.bpc ? fz_toint(image[i]->u.image.bpc) : 1, image[i]->u.image.cs ? fz_toname(image[i]->u.image.cs) : "ImageMask", image[i]->u.image.altcs ? " " : "", image[i]->u.image.altcs ? fz_toname(image[i]->u.image.altcs) : "", fz_tonum(image[i]->ref), fz_togen(image[i]->ref)); } printf("\n"); for (i = 0; i < images; i++) fz_free(image[i]); fz_free(image); image = nil; images = 0; } if (show & SHADINGS && shadings > 0) { printf("Shading patterns (%d):\n", shadings); for (i = 0; i < shadings; i++) { char *shadingtype[] = { "", "Function", "Axial", "Radial", "Free-form triangle mesh", "Lattice-form triangle mesh", "Coons patch mesh", "Tensor-product patch mesh", }; printf(PAGE_FMT "%s (%d %d R)\n", shading[i]->page, fz_tonum(shading[i]->pageobj), fz_togen(shading[i]->pageobj), shadingtype[fz_toint(shading[i]->u.shading.type)], fz_tonum(shading[i]->ref), fz_togen(shading[i]->ref)); } printf("\n"); for (i = 0; i < shadings; i++) fz_free(shading[i]); fz_free(shading); shading = nil; shadings = 0; } if (show & PATTERNS && patterns > 0) { printf("Patterns (%d):\n", patterns); for (i = 0; i < patterns; i++) { char *patterntype[] = { "", "Tiling", "Shading", }; char *painttype[] = { "", "Colored", "Uncolored", }; char *tilingtype[] = { "", "Constant spacing", "No distortion", "Constant space/fast tiling", }; printf(PAGE_FMT "%s %s %s (%d %d R)\n", pattern[i]->page, fz_tonum(pattern[i]->pageobj), fz_togen(pattern[i]->pageobj), patterntype[fz_toint(pattern[i]->u.pattern.pattern)], painttype[fz_toint(pattern[i]->u.pattern.paint)], tilingtype[fz_toint(pattern[i]->u.pattern.tiling)], fz_tonum(pattern[i]->ref), fz_togen(pattern[i]->ref)); } printf("\n"); for (i = 0; i < patterns; i++) fz_free(pattern[i]); fz_free(pattern); pattern = nil; patterns = 0; } if (show & XOBJS && forms > 0) { printf("Form xobjects (%d):\n", forms); for (i = 0; i < forms; i++) { printf(PAGE_FMT "%s%s (%d %d R)\n", form[i]->page, fz_tonum(form[i]->pageobj), fz_togen(form[i]->pageobj), form[i]->u.form.group ? "Group" : "", form[i]->u.form.reference ? "Reference" : "", fz_tonum(form[i]->ref), fz_togen(form[i]->ref)); } printf("\n"); for (i = 0; i < forms; i++) fz_free(form[i]); fz_free(form); form = nil; forms = 0; } if (show & XOBJS && psobjs > 0) { printf("Postscript xobjects (%d):\n", psobjs); for (i = 0; i < psobjs; i++) { printf(PAGE_FMT "(%d %d R)\n", psobj[i]->page, fz_tonum(psobj[i]->pageobj), fz_togen(psobj[i]->pageobj), fz_tonum(psobj[i]->ref), fz_togen(psobj[i]->ref)); } printf("\n"); for (i = 0; i < psobjs; i++) fz_free(psobj[i]); fz_free(psobj); psobj = nil; psobjs = 0; } }
fz_error* processErrorPage( soPdfFile* inFile, fz_obj *pageObj, int pageNo, fz_rect *bbRect, fz_error *error ) { // Wrap the error error = fz_rethrow(error, "Cannot process page %d", pageNo + 1); // If we are not supposed to proceed with error then it ends if (p_proceedWithErrors == false) return error; // Save the error in the list if (g_errorCount >= MAX_ERRORS_BEFORE_STOP) return soPdfErrorList(error); g_errorList[g_errorCount++] = error; // Get the box for the page fz_obj *obj = fz_dictgets(pageObj, "CropBox"); if (!obj) obj = fz_dictgets(pageObj, "MediaBox"); error = pdf_resolve(&obj, inFile->xref); if (error) return fz_rethrow(error, "Cannot proceed with error %d", pageNo + 1); if (!fz_isarray(obj)) return fz_throw("Cannot find page bounds : %d", pageNo + 1); fz_rect bbox = pdf_torect(obj); fz_rect mediaBox; mediaBox.x0 = MIN(bbox.x0, bbox.x1); mediaBox.y0 = MIN(bbox.y0, bbox.y1); mediaBox.x1 = MAX(bbox.x0, bbox.x1); mediaBox.y1 = MAX(bbox.y0, bbox.y1); float mbHeight = mediaBox.y1 - mediaBox.y0; switch(p_mode) { case FitHeight: case FitWidth: bbRect[0] = mediaBox; break; case Fit2xHeight: case Fit2xWidth: { float overlap = (mbHeight * (float)(p_overlap / 100)) / 2; bbRect[0] = mediaBox; bbRect[0].y0 = bbRect[0].y0 + (float)(0.5 * mbHeight) - overlap; bbRect[1] = mediaBox; bbRect[1].y1 = bbRect[1].y1 - (float)(0.5 * mbHeight) + overlap; } break; case SmartFitHeight: case SmartFitWidth: default: return fz_throw("Mode(%d) not yet implemented.", p_mode); break; } return NULL; }
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 * loadcalrgb(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict) { fz_error *error; struct calrgb *cs; fz_obj *tmp; int i; error = pdf_resolve(&dict, xref); if (error) return error; cs = fz_malloc(sizeof(struct calrgb)); if (!cs) return fz_outofmem; pdf_logrsrc("load CalRGB\n"); initcs((fz_colorspace*)cs, "CalRGB", 3, rgbtoxyz, xyztorgb, nil); cs->white[0] = 1.0; cs->white[1] = 1.0; cs->white[2] = 1.0; cs->black[0] = 0.0; cs->black[1] = 0.0; cs->black[2] = 0.0; cs->gamma[0] = 1.0; cs->gamma[1] = 1.0; cs->gamma[2] = 1.0; cs->matrix[0] = 1.0; cs->matrix[1] = 0.0; cs->matrix[2] = 0.0; cs->matrix[3] = 0.0; cs->matrix[4] = 1.0; cs->matrix[5] = 0.0; cs->matrix[6] = 0.0; cs->matrix[7] = 0.0; cs->matrix[8] = 1.0; tmp = fz_dictgets(dict, "WhitePoint"); if (fz_isarray(tmp)) { cs->white[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->white[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->white[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "BlackPoint"); if (fz_isarray(tmp)) { cs->black[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->black[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->black[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Gamma"); if (fz_isarray(tmp)) { cs->gamma[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->gamma[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->gamma[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Matrix"); if (fz_isarray(tmp)) { for (i = 0; i < 9; i++) cs->matrix[i] = fz_toreal(fz_arrayget(tmp, i)); } fz_invert3x3(cs->invmat, cs->matrix); fz_dropobj(dict); *csp = (fz_colorspace*) cs; return nil; }
static fz_error loadcidfont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *encoding, fz_obj *tounicode) { fz_error error; fz_obj *widths; fz_obj *descriptor; pdf_fontdesc *fontdesc; FT_Face face; fz_bbox bbox; int kind; char collection[256]; char *basefont; int i, k, fterr; fz_obj *obj; int dw; /* Get font name and CID collection */ basefont = fz_toname(fz_dictgets(dict, "BaseFont")); { fz_obj *cidinfo; char tmpstr[64]; int tmplen; cidinfo = fz_dictgets(dict, "CIDSystemInfo"); if (!cidinfo) return fz_throw("cid font is missing info"); obj = fz_dictgets(cidinfo, "Registry"); tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj)); memcpy(tmpstr, fz_tostrbuf(obj), tmplen); tmpstr[tmplen] = '\0'; fz_strlcpy(collection, tmpstr, sizeof collection); fz_strlcat(collection, "-", sizeof collection); obj = fz_dictgets(cidinfo, "Ordering"); tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj)); memcpy(tmpstr, fz_tostrbuf(obj), tmplen); tmpstr[tmplen] = '\0'; fz_strlcat(collection, tmpstr, sizeof collection); } /* Load font file */ fontdesc = pdf_newfontdesc(); pdf_logfont("load cid font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("basefont %s\n", basefont); pdf_logfont("collection %s\n", collection); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor) error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, collection, basefont); else error = fz_throw("syntaxerror: missing font descriptor"); if (error) goto cleanup; face = fontdesc->font->ftface; kind = ftkind(face); bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM; bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM; bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM; bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM; pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); if (bbox.x0 == bbox.x1) fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000); else fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* Encoding */ error = fz_okay; if (fz_isname(encoding)) { pdf_logfont("encoding /%s\n", fz_toname(encoding)); if (!strcmp(fz_toname(encoding), "Identity-H")) fontdesc->encoding = pdf_newidentitycmap(0, 2); else if (!strcmp(fz_toname(encoding), "Identity-V")) fontdesc->encoding = pdf_newidentitycmap(1, 2); else error = pdf_loadsystemcmap(&fontdesc->encoding, fz_toname(encoding)); } else if (fz_isindirect(encoding)) { pdf_logfont("encoding %d %d R\n", fz_tonum(encoding), fz_togen(encoding)); error = pdf_loadembeddedcmap(&fontdesc->encoding, xref, encoding); } else { error = fz_throw("syntaxerror: font missing encoding"); } if (error) goto cleanup; pdf_setfontwmode(fontdesc, pdf_getwmode(fontdesc->encoding)); pdf_logfont("wmode %d\n", pdf_getwmode(fontdesc->encoding)); if (kind == TRUETYPE) { fz_obj *cidtogidmap; cidtogidmap = fz_dictgets(dict, "CIDToGIDMap"); if (fz_isindirect(cidtogidmap)) { fz_buffer *buf; pdf_logfont("cidtogidmap stream\n"); error = pdf_loadstream(&buf, xref, fz_tonum(cidtogidmap), fz_togen(cidtogidmap)); if (error) goto cleanup; fontdesc->ncidtogid = (buf->len) / 2; fontdesc->cidtogid = fz_malloc(fontdesc->ncidtogid * sizeof(unsigned short)); for (i = 0; i < fontdesc->ncidtogid; i++) fontdesc->cidtogid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1]; fz_dropbuffer(buf); } /* if truetype font is external, cidtogidmap should not be identity */ /* so we map from cid to unicode and then map that through the (3 1) */ /* unicode cmap to get a glyph id */ else if (fontdesc->font->ftsubstitute) { pdf_logfont("emulate ttf cidfont\n"); fterr = FT_Select_Charmap(face, ft_encoding_unicode); if (fterr) { error = fz_throw("fonterror: no unicode cmap when emulating CID font: %s", ft_errorstring(fterr)); goto cleanup; } if (!strcmp(collection, "Adobe-CNS1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Japan2")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Japan2-UCS2"); else if (!strcmp(collection, "Adobe-Korea1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Korea1-UCS2"); else error = fz_okay; if (error) { error = fz_rethrow(error, "cannot load system cmap %s", collection); goto cleanup; } } } error = pdf_loadtounicode(fontdesc, xref, nil, collection, tounicode); if (error) goto cleanup; /* Horizontal */ dw = 1000; obj = fz_dictgets(dict, "DW"); if (obj) dw = fz_toint(obj); pdf_setdefaulthmtx(fontdesc, dw); widths = fz_dictgets(dict, "W"); if (widths) { int c0, c1, w; for (i = 0; i < fz_arraylen(widths); ) { c0 = fz_toint(fz_arrayget(widths, i)); obj = fz_arrayget(widths, i + 1); if (fz_isarray(obj)) { for (k = 0; k < fz_arraylen(obj); k++) { w = fz_toint(fz_arrayget(obj, k)); pdf_addhmtx(fontdesc, c0 + k, c0 + k, w); } i += 2; } else { c1 = fz_toint(obj); w = fz_toint(fz_arrayget(widths, i + 2)); pdf_addhmtx(fontdesc, c0, c1, w); i += 3; } } } pdf_endhmtx(fontdesc); /* Vertical */ if (pdf_getwmode(fontdesc->encoding) == 1) { int dw2y = 880; int dw2w = -1000; obj = fz_dictgets(dict, "DW2"); if (obj) { dw2y = fz_toint(fz_arrayget(obj, 0)); dw2w = fz_toint(fz_arrayget(obj, 1)); } pdf_setdefaultvmtx(fontdesc, dw2y, dw2w); widths = fz_dictgets(dict, "W2"); if (widths) { int c0, c1, w, x, y; for (i = 0; i < fz_arraylen(widths); ) { c0 = fz_toint(fz_arrayget(widths, i)); obj = fz_arrayget(widths, i + 1); if (fz_isarray(obj)) { for (k = 0; k < fz_arraylen(obj); k += 3) { w = fz_toint(fz_arrayget(obj, k + 0)); x = fz_toint(fz_arrayget(obj, k + 1)); y = fz_toint(fz_arrayget(obj, k + 2)); pdf_addvmtx(fontdesc, c0 + k, c0 + k, x, y, w); } i += 2; } else { c1 = fz_toint(obj); w = fz_toint(fz_arrayget(widths, i + 2)); x = fz_toint(fz_arrayget(widths, i + 3)); y = fz_toint(fz_arrayget(widths, i + 4)); pdf_addvmtx(fontdesc, c0, c1, x, y, w); i += 5; } } } pdf_endvmtx(fontdesc); } pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: pdf_dropfont(fontdesc); return fz_rethrow(error, "cannot load cid font (%d %d R)", fz_tonum(dict), fz_togen(dict)); }
static fz_error loadsimplefont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict) { fz_error error; fz_obj *descriptor; fz_obj *encoding; fz_obj *widths; unsigned short *etable = nil; pdf_fontdesc *fontdesc; fz_bbox bbox; FT_Face face; FT_CharMap cmap; int kind; int symbolic; char *basefont; char *fontname; char *estrings[256]; char ebuffer[256][32]; int i, k, n; int fterr; basefont = fz_toname(fz_dictgets(dict, "BaseFont")); fontname = cleanfontname(basefont); /* Load font file */ fontdesc = pdf_newfontdesc(); pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("basefont %s -> %s\n", basefont, fontname); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor) error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, nil, basefont); else error = pdf_loadbuiltinfont(fontdesc, fontname); if (error) goto cleanup; face = fontdesc->font->ftface; kind = ftkind(face); pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name); bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM; bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM; bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM; bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM; pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); if (bbox.x0 == bbox.x1) fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000); else fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* Encoding */ symbolic = fontdesc->flags & 4; if (face->num_charmaps > 0) cmap = face->charmaps[0]; else cmap = nil; for (i = 0; i < face->num_charmaps; i++) { FT_CharMap test = face->charmaps[i]; if (kind == TYPE1) { if (test->platform_id == 7) cmap = test; } if (kind == TRUETYPE) { if (test->platform_id == 1 && test->encoding_id == 0) cmap = test; if (test->platform_id == 3 && test->encoding_id == 1) cmap = test; } } if (cmap) { fterr = FT_Set_Charmap(face, cmap); if (fterr) fz_warn("freetype could not set cmap: %s", ft_errorstring(fterr)); } else fz_warn("freetype could not find any cmaps"); etable = fz_malloc(sizeof(unsigned short) * 256); for (i = 0; i < 256; i++) { estrings[i] = nil; etable[i] = 0; } encoding = fz_dictgets(dict, "Encoding"); if (encoding) { if (fz_isname(encoding)) pdf_loadencoding(estrings, fz_toname(encoding)); if (fz_isdict(encoding)) { fz_obj *base, *diff, *item; base = fz_dictgets(encoding, "BaseEncoding"); if (fz_isname(base)) pdf_loadencoding(estrings, fz_toname(base)); else if (!fontdesc->isembedded && !symbolic) pdf_loadencoding(estrings, "StandardEncoding"); /* cf. http://bugs.ghostscript.com/show_bug.cgi?id=690615 and http://code.google.com/p/sumatrapdf/issues/detail?id=687 */ /* try to extract an encoding from the font or synthesize a likely one */ /* note: FT_Get_Name_Index fails for symbolic CFF fonts, so let them be encoded by index */ else if (!fontdesc->encoding && !ftloadt1encoding(face, estrings) && !(symbolic && !strcmp(FT_Get_X11_Font_Format(face), "CFF"))) pdf_loadencoding(estrings, "StandardEncoding"); diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { n = fz_arraylen(diff); k = 0; for (i = 0; i < n; i++) { item = fz_arrayget(diff, i); if (fz_isint(item)) k = fz_toint(item); if (fz_isname(item)) estrings[k++] = fz_toname(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } } /* start with the builtin encoding */ for (i = 0; i < 256; i++) etable[i] = ftcharindex(face, i); /* encode by glyph name where we can */ if (kind == TYPE1) { pdf_logfont("encode type1/cff by strings\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) { int aglcode = pdf_lookupagl(estrings[i]); char **aglnames = pdf_lookupaglnames(aglcode); while (*aglnames) { etable[i] = FT_Get_Name_Index(face, *aglnames); if (etable[i]) break; aglnames++; } } } } } /* encode by glyph name where we can */ if (kind == TRUETYPE) { /* Unicode cmap */ if (!symbolic && face->charmap && face->charmap->platform_id == 3) { pdf_logfont("encode truetype via unicode\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { int aglcode = pdf_lookupagl(estrings[i]); if (!aglcode) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, aglcode); } } } /* MacRoman cmap */ else if (!symbolic && face->charmap && face->charmap->platform_id == 1) { pdf_logfont("encode truetype via macroman\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { k = mrecode(estrings[i]); if (k <= 0) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, k); } } } /* Symbolic cmap */ else { pdf_logfont("encode truetype symbolic\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) etable[i] = ftcharindex(face, i); } } } } /* try to reverse the glyph names from the builtin encoding */ for (i = 0; i < 256; i++) { if (etable[i] && !estrings[i]) { if (FT_HAS_GLYPH_NAMES(face)) { fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) fz_warn("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr)); if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } else { estrings[i] = (char*) pdf_winansi[i]; /* discard const */ } } } /* Prevent encoding Differences from being overwritten by reloading them */ /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=115 */ if (fz_isdict(encoding)) { fz_obj *diff, *item; diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { n = fz_arraylen(diff); k = 0; for (i = 0; i < n; i++) { item = fz_arrayget(diff, i); if (fz_isint(item)) k = fz_toint(item); if (fz_isname(item)) estrings[k++] = fz_toname(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } fontdesc->encoding = pdf_newidentitycmap(0, 1); fontdesc->ncidtogid = 256; fontdesc->cidtogid = etable; error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* Widths */ pdf_setdefaulthmtx(fontdesc, fontdesc->missingwidth); widths = fz_dictgets(dict, "Widths"); if (widths) { int first, last; first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); if (first < 0 || last > 255 || first > last) first = last = 0; for (i = 0; i < last - first + 1; i++) { int wid = fz_toint(fz_arrayget(widths, i)); pdf_addhmtx(fontdesc, i + first, i + first, wid); } } else { fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); if (fterr) fz_warn("freetype set character size: %s", ft_errorstring(fterr)); for (i = 0; i < 256; i++) { pdf_addhmtx(fontdesc, i, i, ftwidth(fontdesc, i)); } } pdf_endhmtx(fontdesc); pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: if (etable != fontdesc->cidtogid) fz_free(etable); pdf_dropfont(fontdesc); return fz_rethrow(error, "cannot load simple font (%d %d R)", fz_tonum(dict), fz_togen(dict)); }
static fz_error pdf_loadcolorspaceimp(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj) { if (fz_isname(obj)) { if (!strcmp(fz_toname(obj), "DeviceGray")) *csp = pdf_devicegray; else if (!strcmp(fz_toname(obj), "DeviceRGB")) *csp = pdf_devicergb; else if (!strcmp(fz_toname(obj), "DeviceCMYK")) *csp = pdf_devicecmyk; else if (!strcmp(fz_toname(obj), "G")) *csp = pdf_devicegray; else if (!strcmp(fz_toname(obj), "RGB")) *csp = pdf_devicergb; else if (!strcmp(fz_toname(obj), "CMYK")) *csp = pdf_devicecmyk; else if (!strcmp(fz_toname(obj), "Pattern")) *csp = pdf_devicepattern; else return fz_throw("unknown colorspace: %s", fz_toname(obj)); return fz_okay; } else if (fz_isarray(obj)) { fz_obj *name = fz_arrayget(obj, 0); if (fz_isname(name)) { if (!strcmp(fz_toname(name), "CalCMYK")) *csp = pdf_devicecmyk; #ifdef USECAL else if (!strcmp(fz_toname(name), "CalGray")) *csp = loadcalgray(xref, fz_arrayget(obj, 1)); else if (!strcmp(fz_toname(name), "CalRGB")) *csp = loadcalrgb(xref, fz_arrayget(obj, 1)); else if (!strcmp(fz_toname(name), "Lab")) *csp = loadlab(xref, fz_arrayget(obj, 1)); #else else if (!strcmp(fz_toname(name), "CalGray")) *csp = pdf_devicegray; else if (!strcmp(fz_toname(name), "CalRGB")) *csp = pdf_devicergb; else if (!strcmp(fz_toname(name), "Lab")) *csp = pdf_devicelab; #endif else if (!strcmp(fz_toname(name), "ICCBased")) return loadiccbased(csp, xref, fz_arrayget(obj, 1)); else if (!strcmp(fz_toname(name), "Indexed")) return loadindexed(csp, xref, obj); else if (!strcmp(fz_toname(name), "I")) return loadindexed(csp, xref, obj); else if (!strcmp(fz_toname(name), "Separation")) return loadseparation(csp, xref, obj); else if (!strcmp(fz_toname(name), "DeviceN")) return loadseparation(csp, xref, obj); /* load base colorspace instead */ else if (!strcmp(fz_toname(name), "Pattern")) { fz_error error; obj = fz_arrayget(obj, 1); if (!obj) { *csp = pdf_devicepattern; return fz_okay; } error = pdf_loadcolorspace(csp, xref, obj); if (error) return fz_rethrow(error, "cannot load pattern"); } else if (!strcmp(fz_toname(name), "DeviceGray")) *csp = pdf_devicegray; else if (!strcmp(fz_toname(name), "DeviceRGB")) *csp = pdf_devicergb; else if (!strcmp(fz_toname(name), "DeviceCMYK")) *csp = pdf_devicecmyk; else if (!strcmp(fz_toname(name), "G")) *csp = pdf_devicegray; else if (!strcmp(fz_toname(name), "RGB")) *csp = pdf_devicergb; else if (!strcmp(fz_toname(name), "CMYK")) *csp = pdf_devicecmyk; else return fz_throw("syntaxerror: unknown colorspace %s", fz_toname(name)); return fz_okay; } } return fz_throw("syntaxerror: could not parse color space"); }
static fz_error * loadlab(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict) { fz_error *error; struct cielab *cs; fz_obj *tmp; error = pdf_resolve(&dict, xref); if (error) return error; cs = fz_malloc(sizeof(struct cielab)); if (!cs) return fz_outofmem; pdf_logrsrc("load Lab\n"); initcs((fz_colorspace*)cs, "Lab", 3, labtoxyz, xyztolab, nil); cs->white[0] = 1.0; cs->white[1] = 1.0; cs->white[2] = 1.0; cs->black[0] = 0.0; cs->black[1] = 0.0; cs->black[2] = 0.0; cs->range[0] = -100; cs->range[1] = 100; cs->range[2] = -100; cs->range[3] = 100; tmp = fz_dictgets(dict, "WhitePoint"); if (fz_isarray(tmp)) { cs->white[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->white[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->white[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "BlackPoint"); if (fz_isarray(tmp)) { cs->black[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->black[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->black[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Range"); if (fz_isarray(tmp)) { cs->range[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->range[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->range[2] = fz_toreal(fz_arrayget(tmp, 2)); cs->range[3] = fz_toreal(fz_arrayget(tmp, 3)); } fz_dropobj(dict); *csp = (fz_colorspace*) cs; return nil; }