static void sweepref(fz_obj *obj) { int num = fz_tonum(obj); int gen = fz_togen(obj); if (num < 0 || num >= xref->len) return; if (uselist[num]) return; uselist[num] = 1; /* Bake in /Length in stream objects */ if (pdf_isstream(xref, num, gen)) { fz_obj *len = fz_dictgets(obj, "Length"); if (fz_isindirect(len)) { uselist[fz_tonum(len)] = 0; len = fz_resolveindirect(len); fz_dictputs(obj, "Length", len); } } sweepobj(fz_resolveindirect(obj)); }
static void showobject(int num, int gen) { fz_error error; fz_obj *obj; if (!xref) die(fz_throw("no file specified")); error = pdf_loadobject(&obj, xref, num, gen); if (error) die(error); if (pdf_isstream(xref, num, gen)) { printf("%d %d obj\n", num, gen); fz_debugobj(obj); printf("stream\n"); showstream(num, gen); printf("endstream\n"); printf("endobj\n\n"); } else { printf("%d %d obj\n", num, gen); fz_debugobj(obj); printf("endobj\n\n"); } fz_dropobj(obj); }
static fz_error * writeobject(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen) { pdf_xrefentry *x = xref->table + oid; fz_error *error; error = pdf_cacheobject(xref, oid, gen); if (error) return error; if (encrypt) pdf_cryptobj(encrypt, x->obj, oid, gen); fz_print(out, "%d %d obj\n", oid, gen); fz_printobj(out, x->obj, TIGHT); fz_print(out, "\n"); if (encrypt) pdf_cryptobj(encrypt, x->obj, oid, gen); if (pdf_isstream(xref, oid, gen)) { error = writestream(out, xref, encrypt, oid, gen); if (error) return error; } fz_print(out, "endobj\n\n"); return nil; }
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 void removeduplicateobjs(void) { int num, other; for (num = 1; num < xref->len; num++) { /* Only compare an object to objects preceeding it */ for (other = 1; other < num; other++) { fz_obj *a, *b; if (num == other || !uselist[num] || !uselist[other]) continue; /* * Comparing stream objects data contents would take too long. * * pdf_isstream calls pdf_cacheobject and ensures * that the xref table has the objects loaded. */ if (pdf_isstream(xref, num, 0) || pdf_isstream(xref, other, 0)) continue; a = xref->table[num].obj; b = xref->table[other].obj; a = fz_resolveindirect(a); b = fz_resolveindirect(b); if (fz_objcmp(a, b)) continue; /* Keep the lowest numbered object */ renumbermap[num] = MIN(num, other); renumbermap[other] = MIN(num, other); uselist[MAX(num, other)] = 0; /* One duplicate was found, do not look for another */ break; } } }
void showobject(int num, int gen) { fz_error *error; fz_obj *obj; if (!src) die(fz_throw("no file specified")); error = pdf_loadobject(&obj, src, num, gen); if (error) die(error); /* print the stream raw if we're binary */ if (pdf_isstream(src, num, gen) && showbinary) { showstream(num, gen); } else { printf("%d %d obj\n", num, gen); fz_debugobj(obj); printf("\n"); if (pdf_isstream(src, num, gen)) { printf("stream\n"); showstream(num, gen); printf("endstream\n"); } printf("endobj\n\n"); } fz_dropobj(obj); }
static void writeobject(int num, int gen) { fz_error error; fz_obj *obj; fz_obj *type; error = pdf_loadobject(&obj, xref, num, gen); if (error) die(error); /* skip ObjStm and XRef objects */ if (fz_isdict(obj)) { type = fz_dictgets(obj, "Type"); if (fz_isname(type) && !strcmp(fz_toname(type), "ObjStm")) { uselist[num] = 0; fz_dropobj(obj); return; } if (fz_isname(type) && !strcmp(fz_toname(type), "XRef")) { uselist[num] = 0; fz_dropobj(obj); return; } } if (!pdf_isstream(xref, num, gen)) { fprintf(out, "%d %d obj\n", num, gen); fz_fprintobj(out, obj, !doexpand); fprintf(out, "endobj\n\n"); } else { if (doexpand && !pdf_isjpximage(obj)) expandstream(obj, num, gen); else copystream(obj, num, gen); } fz_dropobj(obj); }
void cleanexpand(void) { fz_error *error; fz_obj *stmobj; fz_buffer *buf; fz_obj *stmlen; int i, gen; for (i = 0; i < src->len; i++) { if (src->table[i].type == 'n') { gen = src->table[i].gen; if (pdf_isstream(src, i, gen)) { error = pdf_loadobject(&stmobj, src, i, gen); if (error) die(error); error = pdf_loadstream(&buf, src, i, gen); if (error) die(error); fz_dictdels(stmobj, "Filter"); fz_dictdels(stmobj, "DecodeParms"); error = fz_newint(&stmlen, buf->wp - buf->rp); if (error) die(error); error = fz_dictputs(stmobj, "Length", stmlen); if (error) die(error); fz_dropobj(stmlen); pdf_updateobject(src, i, gen, stmobj); pdf_updatestream(src, i, gen, buf); fz_dropobj(stmobj); } } } }
fz_error pdf_loadtounicode(pdf_fontdesc *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm) { fz_error error = fz_okay; pdf_cmap *cmap; int cid; int ucsbuf[8]; int ucslen; int i; if (pdf_isstream(xref, fz_tonum(cmapstm), fz_togen(cmapstm))) { pdf_logfont("tounicode embedded cmap\n"); error = pdf_loadembeddedcmap(&cmap, xref, cmapstm); if (error) return fz_rethrow(error, "cannot load embedded cmap (%d %d R)", fz_tonum(cmapstm), fz_togen(cmapstm)); font->tounicode = pdf_newcmap(); for (i = 0; i < (strings ? 256 : 65536); i++) { cid = pdf_lookupcmap(font->encoding, i); if (cid >= 0) { ucslen = pdf_lookupcmapfull(cmap, i, ucsbuf); if (ucslen == 1) pdf_maprangetorange(font->tounicode, cid, cid, ucsbuf[0]); if (ucslen > 1) pdf_maponetomany(font->tounicode, cid, ucsbuf, ucslen); } } pdf_sortcmap(font->tounicode); pdf_dropcmap(cmap); } else if (collection) { pdf_logfont("tounicode cid collection (%s)\n", collection); error = fz_okay; if (!strcmp(collection, "Adobe-CNS1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Japan2")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan2-UCS2"); /* where's this? */ else if (!strcmp(collection, "Adobe-Korea1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Korea1-UCS2"); if (error) return fz_rethrow(error, "cannot load tounicode system cmap %s-UCS2", collection); } if (strings) { pdf_logfont("tounicode strings\n"); /* TODO one-to-many mappings */ font->ncidtoucs = 256; font->cidtoucs = fz_calloc(256, sizeof(unsigned short)); for (i = 0; i < 256; i++) { if (strings[i]) font->cidtoucs[i] = pdf_lookupagl(strings[i]); else font->cidtoucs[i] = '?'; } } if (!font->tounicode && !font->cidtoucs) { pdf_logfont("tounicode could not be loaded\n"); /* TODO: synthesize a ToUnicode if it's a freetype font with * cmap and/or post tables or if it has glyph names. */ } return fz_okay; }
fz_error pdf_loadtype3font(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) { fz_error error; char buf[256]; char *estrings[256]; pdf_fontdesc *fontdesc; fz_obj *encoding; fz_obj *widths; fz_obj *charprocs; fz_obj *obj; int first, last; int i, k, n; fz_rect bbox; fz_matrix matrix; obj = fz_dictgets(dict, "Name"); if (fz_isname(obj)) fz_strlcpy(buf, fz_toname(obj), sizeof buf); else sprintf(buf, "Unnamed-T3"); fontdesc = pdf_newfontdesc(); pdf_logfont("load type3 font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("name %s\n", buf); obj = fz_dictgets(dict, "FontMatrix"); matrix = pdf_tomatrix(obj); pdf_logfont("matrix [%g %g %g %g %g %g]\n", matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f); obj = fz_dictgets(dict, "FontBBox"); bbox = pdf_torect(obj); pdf_logfont("bbox [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); fontdesc->font = fz_newtype3font(buf, matrix); fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* Encoding */ for (i = 0; i < 256; i++) estrings[i] = nil; encoding = fz_dictgets(dict, "Encoding"); if (!encoding) { error = fz_throw("syntaxerror: Type3 font missing Encoding"); goto cleanup; } 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)); 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); error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* Widths */ pdf_setdefaulthmtx(fontdesc, 0); first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); widths = fz_dictgets(dict, "Widths"); if (!widths) { error = fz_throw("syntaxerror: Type3 font missing Widths"); goto cleanup; } for (i = first; i <= last; i++) { float w = fz_toreal(fz_arrayget(widths, i - first)); w = fontdesc->font->t3matrix.a * w * 1000; fontdesc->font->t3widths[i] = w * 0.001f; pdf_addhmtx(fontdesc, i, i, w); } pdf_endhmtx(fontdesc); /* Resources -- inherit page resources if the font doesn't have its own */ fontdesc->font->t3resources = fz_dictgets(dict, "Resources"); if (!fontdesc->font->t3resources) fontdesc->font->t3resources = rdb; if (fontdesc->font->t3resources) fz_keepobj(fontdesc->font->t3resources); if (!fontdesc->font->t3resources) fz_warn("no resource dictionary for type 3 font!"); fontdesc->font->t3xref = xref; fontdesc->font->t3run = pdf_runcontents; /* CharProcs */ charprocs = fz_dictgets(dict, "CharProcs"); if (!charprocs) { error = fz_throw("syntaxerror: Type3 font missing CharProcs"); goto cleanup; } for (i = 0; i < 256; i++) { if (estrings[i]) { obj = fz_dictgets(charprocs, estrings[i]); if (pdf_isstream(xref, fz_tonum(obj), fz_togen(obj))) { error = pdf_loadstream(&fontdesc->font->t3procs[i], xref, fz_tonum(obj), fz_togen(obj)); if (error) goto cleanup; } } } pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: fz_dropfont(fontdesc->font); fz_free(fontdesc); return fz_rethrow(error, "cannot load type3 font (%d %d R)", fz_tonum(dict), fz_togen(dict)); }