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; }
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 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_rect pdf_torect(fz_obj *array) { fz_rect r; float a = fz_toreal(fz_arrayget(array, 0)); float b = fz_toreal(fz_arrayget(array, 1)); float c = fz_toreal(fz_arrayget(array, 2)); float d = fz_toreal(fz_arrayget(array, 3)); r.x0 = MIN(a, c); r.y0 = MIN(b, d); r.x1 = MAX(a, c); r.y1 = MAX(b, d); return r; }
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 fz_error loadtype0(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict) { fz_error error; fz_obj *dfonts; fz_obj *dfont; fz_obj *subtype; fz_obj *encoding; fz_obj *tounicode; dfonts = fz_dictgets(dict, "DescendantFonts"); if (!dfonts) return fz_throw("cid font is missing descendant fonts"); dfont = fz_arrayget(dfonts, 0); subtype = fz_dictgets(dfont, "Subtype"); encoding = fz_dictgets(dict, "Encoding"); tounicode = fz_dictgets(dict, "ToUnicode"); if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "CIDFontType0")) error = loadcidfont(fontdescp, xref, dfont, encoding, tounicode); else if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "CIDFontType2")) error = loadcidfont(fontdescp, xref, dfont, encoding, tounicode); else error = fz_throw("syntaxerror: unknown cid font type"); if (error) return fz_rethrow(error, "cannot load descendant font (%d %d R)", fz_tonum(dfont), fz_togen(dfont)); return fz_okay; }
void pdf_loadannots(pdf_comment **cp, pdf_link **lp, pdf_xref *xref, fz_obj *annots) { pdf_comment *comment; pdf_link *link; fz_obj *subtype; fz_obj *obj; int i; comment = nil; link = nil; pdf_logpage("load annotations {\n"); for (i = 0; i < fz_arraylen(annots); i++) { obj = fz_arrayget(annots, i); subtype = fz_dictgets(obj, "Subtype"); if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "Link")) { pdf_link *temp = pdf_loadlink(xref, obj); if (temp) { temp->next = link; link = temp; } } } pdf_logpage("}\n"); *cp = comment; *lp = link; }
fz_error * pdf_loadannots(pdf_comment **cp, pdf_link **lp, pdf_xref *xref, fz_obj *annots) { fz_error *error; pdf_comment *comment; pdf_link *link; fz_obj *subtype; fz_obj *obj; int i; comment = nil; link = nil; pdf_logpage("load annotations {\n"); for (i = 0; i < fz_arraylen(annots); i++) { obj = fz_arrayget(annots, i); error = pdf_resolve(&obj, xref); if (error) goto cleanup; subtype = fz_dictgets(obj, "Subtype"); if (!strcmp(fz_toname(subtype), "Link")) { pdf_link *temp = nil; error = pdf_loadlink(&temp, xref, obj); fz_dropobj(obj); if (error) goto cleanup; if (temp) { temp->next = link; link = temp; } } else { error = loadcomment(&comment, xref, obj); fz_dropobj(obj); if (error) goto cleanup; } } pdf_logpage("}\n"); *cp = comment; *lp = link; return nil; cleanup: pdf_droplink(link); return error; }
fz_error pdf_loadannots(pdf_comment **cp, pdf_link **lp, pdf_xref *xref, fz_obj *annots) { fz_error error; pdf_comment *comment; pdf_link *link; fz_obj *subtype; fz_obj *obj; int i; comment = nil; link = nil; pdf_logpage("load annotations {\n"); for (i = 0; i < fz_arraylen(annots); i++) { obj = fz_arrayget(annots, i); subtype = fz_dictgets(obj, "Subtype"); if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "Link")) { pdf_link *temp = nil; error = pdf_loadlink(&temp, xref, obj); if (error) { if (link) pdf_droplink(link); return fz_rethrow(error, "cannot load annotation link"); } if (temp) { temp->next = link; link = temp; } } else { error = loadcomment(&comment, xref, obj); if (error) { if (link) pdf_droplink(link); return fz_rethrow(error, "cannot load annotation comment"); } } } pdf_logpage("}\n"); *cp = comment; *lp = link; return fz_okay; }
/* * 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; }
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; }
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; }
int pdf_isjpximage(fz_obj *dict) { fz_obj *filter; int i; filter = fz_dictgets(dict, "Filter"); if (!strcmp(fz_toname(filter), "JPXDecode")) return 1; for (i = 0; i < fz_arraylen(filter); i++) if (!strcmp(fz_toname(fz_arrayget(filter, i)), "JPXDecode")) return 1; return 0; }
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 * 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; }
fz_matrix pdf_tomatrix(fz_obj *array) { fz_matrix m; m.a = fz_toreal(fz_arrayget(array, 0)); m.b = fz_toreal(fz_arrayget(array, 1)); m.c = fz_toreal(fz_arrayget(array, 2)); m.d = fz_toreal(fz_arrayget(array, 3)); m.e = fz_toreal(fz_arrayget(array, 4)); m.f = fz_toreal(fz_arrayget(array, 5)); return m; }
static fz_error * loadtype0(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; fz_obj *dfonts; fz_obj *dfont; fz_obj *subtype; fz_obj *encoding; fz_obj *tounicode; dfonts = fz_dictgets(dict, "DescendantFonts"); error = pdf_resolve(&dfonts, xref); if (error) return fz_rethrow(error, "cannot find DescendantFonts"); dfont = fz_arrayget(dfonts, 0); error = pdf_resolve(&dfont, xref); if (error) { fz_dropobj(dfonts); return fz_rethrow(error, "cannot find descendant font"); } subtype = fz_dictgets(dfont, "Subtype"); encoding = fz_dictgets(dict, "Encoding"); tounicode = fz_dictgets(dict, "ToUnicode"); if (!strcmp(fz_toname(subtype), "CIDFontType0")) error = loadcidfont(fontp, xref, dfont, ref, encoding, tounicode); else if (!strcmp(fz_toname(subtype), "CIDFontType2")) error = loadcidfont(fontp, xref, dfont, ref, encoding, tounicode); else error = fz_throw("syntaxerror: unknown cid font type"); fz_dropobj(dfont); fz_dropobj(dfonts); if (error) return fz_rethrow(error, "cannot load descendant font"); return fz_okay; }
void editflushobjects(void) { fz_error *error; fz_obj *results; int i; error = pdf_transplant(editxref, src, &results, editobjects); if (error) die(error); for (i = 0; i < fz_arraylen(results); i++) { error = fz_arraypush(editpagelist, fz_arrayget(results, i)); if (error) die(error); } fz_dropobj(results); }
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); } } } }
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 void loadcolorkey(int *colorkey, int bpc, int indexed, fz_obj *obj) { int scale = 1; int i; pdf_logimage("keyed mask\n"); if (!indexed) { switch (bpc) { case 1: scale = 255; break; case 2: scale = 85; break; case 4: scale = 17; break; case 8: scale = 1; break; } } for (i = 0; i < fz_arraylen(obj); i++) colorkey[i] = fz_toint(fz_arrayget(obj, i)) * scale; }
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 pdf_loadpagecontentsarray(fz_buffer **bigbufp, pdf_xref *xref, fz_obj *list) { fz_error error; fz_buffer *big; fz_buffer *one; int i; pdf_logpage("multiple content streams: %d\n", fz_arraylen(list)); /* TODO: openstream, read, close into big buffer at once */ big = fz_newbuffer(32 * 1024); for (i = 0; i < fz_arraylen(list); i++) { fz_obj *stm = fz_arrayget(list, i); error = pdf_loadstream(&one, xref, fz_tonum(stm), fz_togen(stm)); if (error) { fz_dropbuffer(big); return fz_rethrow(error, "cannot load content stream part %d/%d (%d %d R)", i + 1, fz_arraylen(list), fz_tonum(stm), fz_togen(stm)); } if (big->len + one->len + 1 > big->cap) fz_resizebuffer(big, big->len + one->len + 1); memcpy(big->data + big->len, one->data, one->len); big->data[big->len + one->len] = ' '; big->len += one->len + 1; fz_dropbuffer(one); } *bigbufp = big; return fz_okay; }
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 * 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; }
int copyPdfFile( soPdfFile* inFile, soPdfFile* outFile ) { fz_error *error; int pageTreeNum, pageTreeGen; assert(inFile != NULL); assert(outFile != NULL); // // Process every page in the source file // { printf("\nProcessing input page : "); for (int pageNo = 0; pageNo < pdf_getpagecount(inFile->pageTree); pageNo++) { displayPageNumber(pageNo + 1, !pageNo); // Get the page object from the source fz_obj *pageRef = inFile->pageTree->pref[pageNo]; fz_obj *pageObj = pdf_getpageobject(inFile->pageTree, pageNo); // // Process the page. Each page can be split into up-to 3 pages // fz_rect bbRect[3]; error = processPage(inFile, pageNo, bbRect, 3); if (error) return soPdfError(error); for (int ctr = 0; ctr < 3; ctr++) { // Check if this was a blank page if (fz_isemptyrect(bbRect[ctr])) break; // // copy the source page dictionary entry. The way this is done is basically // by making a copy of the page dict object in the source file, and adding // the copy in the source file. Then the copied page dict object is // referenced and added to the destination file. // // This convoluted procedure is done because the copy is done by pdf_transplant // function that accepts a source and destination. Whatever is referenced by // destination object is deep copied // // allocate an object id and generation id in source file // // There is a bug in mupdf where the object allocation returns // 0 oid and 0 gid when the input pdf file has iref stream // so to work around the issue, we wrap the pdf_allocojbect // in a for loop 10 times to get the number // int sNum, sGen, tries; for (tries = 0; tries < 10; tries++) { error = pdf_allocobject(inFile->xref, &sNum, &sGen); if (error) return soPdfError(error); // If sNum is non zero then the allocation was successful if (sNum != 0) break; pdf_updateobject(inFile->xref, sNum, sGen, pageObj); } // If we didn't succeed even after 10 tries then this file // is not going to work. if (tries >= 10) return soPdfError(fz_throw("cannot allocate object because of mupdf bug")); // make a deep copy of the original page dict fz_obj *pageObj2; error = fz_deepcopydict(&pageObj2, pageObj); if (error) return soPdfError(error); // update the source file with the duplicate page object pdf_updateobject(inFile->xref, sNum, sGen, pageObj2); fz_dropobj(pageObj2); // create an indirect reference to the page object fz_obj *pageRef2; error = fz_newindirect(&pageRef2, sNum, sGen); if (error) return soPdfError(error); // delete the parent dictionary entry // Do we need to delete any other dictionary entry // like annot, tabs, metadata, etc fz_dictdels(pageObj2, "Parent"); // Set the media box setPageMediaBox(inFile->xref, pageObj2, bbRect[ctr]); // Set the rotation based on input switch(p_mode) { // no rotation if fit height case FitHeight: case Fit2xHeight: break; // rotate -90 deg if fit width case Fit2xWidth: case FitWidth: setPageRotate(pageObj2, p_reverseLandscape ? 90 : -90); break; case SmartFitHeight: case SmartFitWidth: default: return soPdfError(fz_throw("Mode(%d) not yet implemented.", p_mode)); break; } // push the indirect reference to the destination list for copy by pdf_transplant error = fz_arraypush(outFile->editobjs, pageRef2); if (error) return soPdfError(error); } } } // flush the objects into destination from source { fz_obj *results; int outPages; printf("\nCopying output page : "); error = pdf_transplant(outFile->xref, inFile->xref, &results, outFile->editobjs); if (error) return soPdfError(error); outPages = fz_arraylen(results); for (int ctr = 0; ctr < outPages; ctr++) { displayPageNumber(ctr + 1, !ctr); error = fz_arraypush(outFile->pagelist, fz_arrayget(results, p_reverseLandscape ? outPages - 1 - ctr : ctr)); if (error) return soPdfError(error); } fz_dropobj(results); } // flush page tree // Create page tree and add back-links { fz_obj *pageTreeObj; fz_obj *pageTreeRef; // allocate a new object in out file for pageTree object error = pdf_allocobject(outFile->xref, &pageTreeNum, &pageTreeGen); if (error) return soPdfError(error); // Create a page tree object error = fz_packobj(&pageTreeObj, "<</Type/Pages/Count %i/Kids %o>>", fz_arraylen(outFile->pagelist), outFile->pagelist); if (error) return soPdfError(error); // Update the xref entry with the pageTree object pdf_updateobject(outFile->xref, pageTreeNum, pageTreeGen, pageTreeObj); fz_dropobj(pageTreeObj); // Create a reference to the pageTree object error = fz_newindirect(&pageTreeRef, pageTreeNum, pageTreeGen); if (error) return soPdfError(error); // // For every page in the output file, update the parent entry // for (int ctr = 0; ctr < fz_arraylen(outFile->pagelist); ctr++) { fz_obj *pageObj; int num = fz_tonum(fz_arrayget(outFile->pagelist, ctr)); int gen = fz_togen(fz_arrayget(outFile->pagelist, ctr)); // Get the page object from xreft error = pdf_loadobject(&pageObj, outFile->xref, num, gen); if (error) return soPdfError(error); // Update the parent entry in the page dictionary error = fz_dictputs(pageObj, "Parent", pageTreeRef); if (error) return soPdfError(error); // Update the entry with the updated page object pdf_updateobject(outFile->xref, num, gen, pageObj); fz_dropobj(pageObj); } } // Create catalog and root entries { fz_obj *catObj, *infoObj; int rootNum, rootGen; int infoNum, infoGen; // // Copy the info catalog to the destination // alloc an object id and gen id in destination file error = pdf_allocobject(outFile->xref, &infoNum, &infoGen); if (error) return soPdfError(error); // make a deep copy of the original page dict error = fz_deepcopydict(&infoObj, inFile->xref->info); if (error) return soPdfError(error); // update the dest file with object pdf_updateobject(outFile->xref, infoNum, infoGen, infoObj); outFile->xref->info = infoObj; fz_dropobj(infoObj); // // root/catalog object creation error = pdf_allocobject(outFile->xref, &rootNum, &rootGen); if (error) return soPdfError(error); error = fz_packobj(&catObj, "<</Type/Catalog /Pages %r>>", pageTreeNum, pageTreeGen); if (error) return soPdfError(error); pdf_updateobject(outFile->xref, rootNum, rootGen, catObj); fz_dropobj(catObj); // Create trailer error = fz_packobj(&outFile->xref->trailer, "<</Root %r /Info %r>>", rootNum, rootGen, infoNum, infoGen); if (error) return soPdfError(error); } // Update the info in the target file and save the xref printf("\nSaving.\n"); error = setPageInfo(inFile, outFile); if (error) return soPdfError(error); error = pdf_savexref(outFile->xref, outFile->fileName, NULL); if (error) return soPdfError(error); if (g_errorCount != 0) { printf("\nFollowing issues encounted were ignored.\n\n"); for (int ctr = g_errorCount - 1; ctr >= 0; ctr--) soPdfError(g_errorList[ctr]); } printf("\nSaved.\n"); return 0; }
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 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)); }