char *fz_to_name(fz_context *ctx, fz_obj *obj) { obj = fz_resolve_indirect(ctx, obj); if (fz_is_name(ctx, obj)) return obj->u.n; return ""; }
static fz_obj * resolve_dest(pdf_xref *xref, fz_obj *dest) { if (fz_is_name(xref->ctx, dest) || fz_is_string(xref->ctx, dest)) { dest = pdf_lookup_dest(xref, dest); return resolve_dest(xref, dest); } else if (fz_is_array(xref->ctx, dest)) { return dest; } else if (fz_is_dict(xref->ctx, dest)) { dest = fz_dict_gets(xref->ctx, dest, "D"); return resolve_dest(xref, dest); } else if (fz_is_indirect(dest)) return dest; return NULL; }
static void writeobject(int num, int gen) { fz_error error; fz_obj *obj; fz_obj *type; error = pdf_load_object(&obj, xref, num, gen); if (error) die(error); /* skip ObjStm and XRef objects */ if (fz_is_dict(ctx, obj)) { type = fz_dict_gets(ctx, obj, "Type"); if (fz_is_name(ctx, type) && !strcmp(fz_to_name(ctx, type), "ObjStm")) { uselist[num] = 0; fz_drop_obj(ctx, obj); return; } if (fz_is_name(ctx, type) && !strcmp(fz_to_name(ctx, type), "XRef")) { uselist[num] = 0; fz_drop_obj(ctx, obj); return; } } if (!pdf_is_stream(xref, num, gen)) { fprintf(out, "%d %d obj\n", num, gen); fz_fprint_obj(ctx, out, obj, !doexpand); fprintf(out, "endobj\n\n"); } else { if (doexpand && !pdf_is_jpx_image(ctx, obj)) expandstream(obj, num, gen); else copystream(obj, num, gen); } fz_drop_obj(ctx, obj); }
static void addhexfilter(fz_obj *dict) { fz_obj *f, *dp, *newf, *newdp; fz_obj *ahx, *nullobj; ahx = fz_new_name(ctx, "ASCIIHexDecode"); nullobj = fz_new_null(ctx); newf = newdp = NULL; f = fz_dict_gets(dict, "Filter"); dp = fz_dict_gets(dict, "DecodeParms"); if (fz_is_name(f)) { newf = fz_new_array(ctx, 2); fz_array_push(newf, ahx); fz_array_push(newf, f); f = newf; if (fz_is_dict(dp)) { newdp = fz_new_array(ctx, 2); fz_array_push(newdp, nullobj); fz_array_push(newdp, dp); dp = newdp; } } else if (fz_is_array(f)) { fz_array_insert(f, ahx); if (fz_is_array(dp)) fz_array_insert(dp, nullobj); } else f = ahx; fz_dict_puts(dict, "Filter", f); if (dp) fz_dict_puts(dict, "DecodeParms", dp); fz_drop_obj(ahx); fz_drop_obj(nullobj); if (newf) fz_drop_obj(newf); if (newdp) fz_drop_obj(newdp); }
/* * Construct a filter to decode a stream, constraining * to stream length and decrypting. */ static fz_stream * pdf_open_filter(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int num, int gen) { fz_obj *filters; fz_obj *params; filters = fz_dict_getsa(stmobj, "Filter", "F"); params = fz_dict_getsa(stmobj, "DecodeParms", "DP"); chain = pdf_open_raw_filter(chain, xref, stmobj, num, gen); if (fz_is_name(filters)) return build_filter(chain, xref, filters, params, num, gen); if (fz_array_len(filters) > 0) return build_filter_chain(chain, xref, filters, params, num, gen); return chain; }
/* * Construct a filter to decode a stream, without * constraining to stream length, and without decryption. */ fz_stream * pdf_open_inline_stream(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int length) { fz_obj *filters; fz_obj *params; filters = fz_dict_getsa(stmobj, "Filter", "F"); params = fz_dict_getsa(stmobj, "DecodeParms", "DP"); /* don't close chain when we close this filter */ fz_keep_stream(chain); if (fz_is_name(filters)) return build_filter(chain, xref, filters, params, 0, 0); if (fz_array_len(filters) > 0) return build_filter_chain(chain, xref, filters, params, 0, 0); return fz_open_null(chain, length); }
/* * Load CMap stream in PDF file */ fz_error pdf_load_embedded_cmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmobj) { fz_error error = fz_okay; fz_stream *file = NULL; pdf_cmap *cmap = NULL; pdf_cmap *usecmap; fz_obj *wmode; fz_obj *obj; if ((*cmapp = pdf_find_item(xref->store, pdf_drop_cmap, stmobj))) { pdf_keep_cmap(*cmapp); return fz_okay; } error = pdf_open_stream(&file, xref, fz_to_num(stmobj), fz_to_gen(stmobj)); if (error) { error = fz_rethrow(error, "cannot open cmap stream (%d %d R)", fz_to_num(stmobj), fz_to_gen(stmobj)); goto cleanup; } error = pdf_parse_cmap(&cmap, file); if (error) { error = fz_rethrow(error, "cannot parse cmap stream (%d %d R)", fz_to_num(stmobj), fz_to_gen(stmobj)); goto cleanup; } fz_close(file); wmode = fz_dict_gets(stmobj, "WMode"); if (fz_is_int(wmode)) pdf_set_wmode(cmap, fz_to_int(wmode)); obj = fz_dict_gets(stmobj, "UseCMap"); if (fz_is_name(obj)) { error = pdf_load_system_cmap(&usecmap, fz_to_name(obj)); if (error) { error = fz_rethrow(error, "cannot load system usecmap '%s'", fz_to_name(obj)); goto cleanup; } pdf_set_usecmap(cmap, usecmap); pdf_drop_cmap(usecmap); } else if (fz_is_indirect(obj)) { error = pdf_load_embedded_cmap(&usecmap, xref, obj); if (error) { error = fz_rethrow(error, "cannot load embedded usecmap (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); goto cleanup; } pdf_set_usecmap(cmap, usecmap); pdf_drop_cmap(usecmap); } pdf_store_item(xref->store, pdf_keep_cmap, pdf_drop_cmap, stmobj, cmap); *cmapp = cmap; return fz_okay; cleanup: if (file) fz_close(file); if (cmap) pdf_drop_cmap(cmap); return error; /* already rethrown */ }
static fz_error pdf_load_colorspace_imp(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj) { if (fz_is_name(obj)) { if (!strcmp(fz_to_name(obj), "Pattern")) *csp = fz_device_gray; else if (!strcmp(fz_to_name(obj), "G")) *csp = fz_device_gray; else if (!strcmp(fz_to_name(obj), "RGB")) *csp = fz_device_rgb; else if (!strcmp(fz_to_name(obj), "CMYK")) *csp = fz_device_cmyk; else if (!strcmp(fz_to_name(obj), "DeviceGray")) *csp = fz_device_gray; else if (!strcmp(fz_to_name(obj), "DeviceRGB")) *csp = fz_device_rgb; else if (!strcmp(fz_to_name(obj), "DeviceCMYK")) *csp = fz_device_cmyk; else return fz_throw("unknown colorspace: %s", fz_to_name(obj)); return fz_okay; } else if (fz_is_array(obj)) { fz_obj *name = fz_array_get(obj, 0); if (fz_is_name(name)) { /* load base colorspace instead */ if (!strcmp(fz_to_name(name), "Pattern")) { fz_error error; obj = fz_array_get(obj, 1); if (!obj) { *csp = fz_device_gray; return fz_okay; } error = pdf_load_colorspace(csp, xref, obj); if (error) return fz_rethrow(error, "cannot load pattern (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); } else if (!strcmp(fz_to_name(name), "G")) *csp = fz_device_gray; else if (!strcmp(fz_to_name(name), "RGB")) *csp = fz_device_rgb; else if (!strcmp(fz_to_name(name), "CMYK")) *csp = fz_device_cmyk; else if (!strcmp(fz_to_name(name), "DeviceGray")) *csp = fz_device_gray; else if (!strcmp(fz_to_name(name), "DeviceRGB")) *csp = fz_device_rgb; else if (!strcmp(fz_to_name(name), "DeviceCMYK")) *csp = fz_device_cmyk; else if (!strcmp(fz_to_name(name), "CalGray")) *csp = fz_device_gray; else if (!strcmp(fz_to_name(name), "CalRGB")) *csp = fz_device_rgb; else if (!strcmp(fz_to_name(name), "CalCMYK")) *csp = fz_device_cmyk; else if (!strcmp(fz_to_name(name), "Lab")) *csp = fz_device_lab; else if (!strcmp(fz_to_name(name), "ICCBased")) return load_icc_based(csp, xref, fz_array_get(obj, 1)); else if (!strcmp(fz_to_name(name), "Indexed")) return load_indexed(csp, xref, obj); else if (!strcmp(fz_to_name(name), "I")) return load_indexed(csp, xref, obj); else if (!strcmp(fz_to_name(name), "Separation")) return load_separation(csp, xref, obj); else if (!strcmp(fz_to_name(name), "DeviceN")) return load_separation(csp, xref, obj); else return fz_throw("syntaxerror: unknown colorspace %s", fz_to_name(name)); return fz_okay; } } return fz_throw("syntaxerror: could not parse color space (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); }
static void writeobject(int num, int gen) { fz_obj *obj; fz_obj *type; obj = pdf_load_object(xref, num, gen); /* skip ObjStm and XRef objects */ if (fz_is_dict(obj)) { type = fz_dict_gets(obj, "Type"); if (fz_is_name(type) && !strcmp(fz_to_name(type), "ObjStm")) { uselist[num] = 0; fz_drop_obj(obj); return; } if (fz_is_name(type) && !strcmp(fz_to_name(type), "XRef")) { uselist[num] = 0; fz_drop_obj(obj); return; } } if (!pdf_is_stream(xref, num, gen)) { fprintf(out, "%d %d obj\n", num, gen); fz_fprint_obj(out, obj, doexpand == 0); fprintf(out, "endobj\n\n"); } else { int dontexpand = 0; if (doexpand != 0 && doexpand != expand_all) { fz_obj *o; if ((o = fz_dict_gets(obj, "Type"), !strcmp(fz_to_name(o), "XObject")) && (o = fz_dict_gets(obj, "Subtype"), !strcmp(fz_to_name(o), "Image"))) dontexpand = !(doexpand & expand_images); if (o = fz_dict_gets(obj, "Type"), !strcmp(fz_to_name(o), "Font")) dontexpand = !(doexpand & expand_fonts); if (o = fz_dict_gets(obj, "Type"), !strcmp(fz_to_name(o), "FontDescriptor")) dontexpand = !(doexpand & expand_fonts); if ((o = fz_dict_gets(obj, "Length1")) != NULL) dontexpand = !(doexpand & expand_fonts); if ((o = fz_dict_gets(obj, "Length2")) != NULL) dontexpand = !(doexpand & expand_fonts); if ((o = fz_dict_gets(obj, "Length3")) != NULL) dontexpand = !(doexpand & expand_fonts); if (o = fz_dict_gets(obj, "Subtype"), !strcmp(fz_to_name(o), "Type1C")) dontexpand = !(doexpand & expand_fonts); if (o = fz_dict_gets(obj, "Subtype"), !strcmp(fz_to_name(o), "CIDFontType0C")) dontexpand = !(doexpand & expand_fonts); } if (doexpand && !dontexpand && !pdf_is_jpx_image(ctx, obj)) expandstream(obj, num, gen); else copystream(obj, num, gen); } fz_drop_obj(obj); }
static fz_error pdf_load_image_imp(fz_pixmap **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cstm, int forcemask) { fz_stream *stm; fz_pixmap *tile; fz_obj *obj, *res; fz_error error; int w, h, bpc, n; int imagemask; int interpolate; int indexed; fz_colorspace *colorspace; fz_pixmap *mask; /* explicit mask/softmask image */ int usecolorkey; int colorkey[FZ_MAX_COLORS * 2]; float decode[FZ_MAX_COLORS * 2]; int stride; unsigned char *samples; int i, len; /* special case for JPEG2000 images */ if (pdf_is_jpx_image(dict)) { tile = NULL; error = pdf_load_jpx_image(&tile, xref, dict); if (error) return fz_rethrow(error, "cannot load jpx image"); if (forcemask) { if (tile->n != 2) { fz_drop_pixmap(tile); return fz_throw("softmask must be grayscale"); } mask = fz_alpha_from_gray(tile, 1); fz_drop_pixmap(tile); *imgp = mask; return fz_okay; } *imgp = tile; return fz_okay; } w = fz_to_int(fz_dict_getsa(dict, "Width", "W")); h = fz_to_int(fz_dict_getsa(dict, "Height", "H")); bpc = fz_to_int(fz_dict_getsa(dict, "BitsPerComponent", "BPC")); imagemask = fz_to_bool(fz_dict_getsa(dict, "ImageMask", "IM")); interpolate = fz_to_bool(fz_dict_getsa(dict, "Interpolate", "I")); indexed = 0; usecolorkey = 0; colorspace = NULL; mask = NULL; if (imagemask) bpc = 1; if (w == 0) return fz_throw("image width is zero"); if (h == 0) return fz_throw("image height is zero"); if (bpc == 0) return fz_throw("image depth is zero"); if (w > (1 << 16)) return fz_throw("image is too wide"); if (h > (1 << 16)) return fz_throw("image is too high"); obj = fz_dict_getsa(dict, "ColorSpace", "CS"); if (obj && !imagemask && !forcemask) { /* colorspace resource lookup is only done for inline images */ if (fz_is_name(obj)) { res = fz_dict_get(fz_dict_gets(rdb, "ColorSpace"), obj); if (res) obj = res; } error = pdf_load_colorspace(&colorspace, xref, obj); if (error) return fz_rethrow(error, "cannot load image colorspace"); if (!strcmp(colorspace->name, "Indexed")) indexed = 1; n = colorspace->n; } else { n = 1; } obj = fz_dict_getsa(dict, "Decode", "D"); if (obj) { for (i = 0; i < n * 2; i++) decode[i] = fz_to_real(fz_array_get(obj, i)); } else { float maxval = indexed ? (1 << bpc) - 1 : 1; for (i = 0; i < n * 2; i++) decode[i] = i & 1 ? maxval : 0; } obj = fz_dict_getsa(dict, "SMask", "Mask"); if (fz_is_dict(obj)) { /* Not allowed for inline images */ if (!cstm) { error = pdf_load_image_imp(&mask, xref, rdb, obj, NULL, 1); if (error) { if (colorspace) fz_drop_colorspace(colorspace); return fz_rethrow(error, "cannot load image mask/softmask"); } } } else if (fz_is_array(obj)) { usecolorkey = 1; for (i = 0; i < n * 2; i++) colorkey[i] = fz_to_int(fz_array_get(obj, i)); } /* Allocate now, to fail early if we run out of memory */ tile = fz_new_pixmap_with_limit(colorspace, w, h); if (!tile) { if (colorspace) fz_drop_colorspace(colorspace); if (mask) fz_drop_pixmap(mask); return fz_throw("out of memory"); } if (colorspace) fz_drop_colorspace(colorspace); tile->mask = mask; tile->interpolate = interpolate; stride = (w * n * bpc + 7) / 8; if (cstm) { stm = pdf_open_inline_stream(cstm, xref, dict, stride * h); } else { error = pdf_open_stream(&stm, xref, fz_to_num(dict), fz_to_gen(dict)); if (error) { fz_drop_pixmap(tile); return fz_rethrow(error, "cannot open image data stream (%d 0 R)", fz_to_num(dict)); } } samples = fz_calloc(h, stride); len = fz_read(stm, samples, h * stride); if (len < 0) { fz_close(stm); fz_free(samples); fz_drop_pixmap(tile); return fz_rethrow(len, "cannot read image data"); } /* Make sure we read the EOF marker (for inline images only) */ if (cstm) { unsigned char tbuf[512]; int tlen = fz_read(stm, tbuf, sizeof tbuf); if (tlen < 0) fz_catch(tlen, "ignoring error at end of image"); if (tlen > 0) fz_warn("ignoring garbage at end of image"); } fz_close(stm); /* Pad truncated images */ if (len < stride * h) { fz_warn("padding truncated image (%d 0 R)", fz_to_num(dict)); memset(samples + len, 0, stride * h - len); } /* Invert 1-bit image masks */ if (imagemask) { /* 0=opaque and 1=transparent so we need to invert */ unsigned char *p = samples; len = h * stride; for (i = 0; i < len; i++) p[i] = ~p[i]; } fz_unpack_tile(tile, samples, n, bpc, stride, indexed); fz_free(samples); if (usecolorkey) pdf_mask_color_key(tile, n, colorkey); if (indexed) { fz_pixmap *conv; fz_decode_indexed_tile(tile, decode, (1 << bpc) - 1); conv = pdf_expand_indexed_pixmap(tile); fz_drop_pixmap(tile); tile = conv; } else { fz_decode_tile(tile, decode); } *imgp = tile; return fz_okay; }
fz_error pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password) { pdf_xref *xref; fz_error error; fz_obj *encrypt, *id; fz_obj *dict, *obj; int i, repaired = 0; /* install pdf specific callback */ fz_resolve_indirect = pdf_resolve_indirect; xref = fz_malloc(sizeof(pdf_xref)); memset(xref, 0, sizeof(pdf_xref)); xref->file = fz_keep_stream(file); error = pdf_load_xref(xref, xref->scratch, sizeof xref->scratch); if (error) { fz_catch(error, "trying to repair"); if (xref->table) { fz_free(xref->table); xref->table = NULL; xref->len = 0; } if (xref->trailer) { fz_drop_obj(xref->trailer); xref->trailer = NULL; } error = pdf_repair_xref(xref, xref->scratch, sizeof xref->scratch); if (error) { pdf_free_xref(xref); return fz_rethrow(error, "cannot repair document"); } repaired = 1; } encrypt = fz_dict_gets(xref->trailer, "Encrypt"); id = fz_dict_gets(xref->trailer, "ID"); if (fz_is_dict(encrypt)) { error = pdf_new_crypt(&xref->crypt, encrypt, id); if (error) { pdf_free_xref(xref); return fz_rethrow(error, "cannot decrypt document"); } } if (pdf_needs_password(xref)) { /* Only care if we have a password */ if (password) { int okay = pdf_authenticate_password(xref, password); if (!okay) { pdf_free_xref(xref); return fz_throw("invalid password"); } } } if (repaired) { int hasroot, hasinfo; error = pdf_repair_obj_stms(xref); if (error) { pdf_free_xref(xref); return fz_rethrow(error, "cannot repair document"); } hasroot = fz_dict_gets(xref->trailer, "Root") != NULL; hasinfo = fz_dict_gets(xref->trailer, "Info") != NULL; for (i = 1; i < xref->len; i++) { if (xref->table[i].type == 0 || xref->table[i].type == 'f') continue; error = pdf_load_object(&dict, xref, i, 0); if (error) { fz_catch(error, "ignoring broken object (%d 0 R)", i); continue; } if (!hasroot) { obj = fz_dict_gets(dict, "Type"); if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "Catalog")) { obj = fz_new_indirect(i, 0, xref); fz_dict_puts(xref->trailer, "Root", obj); fz_drop_obj(obj); } } if (!hasinfo) { if (fz_dict_gets(dict, "Creator") || fz_dict_gets(dict, "Producer")) { obj = fz_new_indirect(i, 0, xref); fz_dict_puts(xref->trailer, "Info", obj); fz_drop_obj(obj); } } fz_drop_obj(dict); } } error = pdf_read_ocg(xref); if (error) { pdf_free_xref(xref); return fz_rethrow(error, "Broken Optional Content"); } *xrefp = xref; return fz_okay; }
pdf_link * pdf_load_link(pdf_xref *xref, fz_obj *dict) { fz_obj *dest; fz_obj *action; fz_obj *obj; fz_rect bbox; pdf_link_kind kind; fz_context *ctx = xref->ctx; dest = NULL; obj = fz_dict_gets(ctx, dict, "Rect"); if (obj) bbox = pdf_to_rect(ctx, obj); else bbox = fz_empty_rect; obj = fz_dict_gets(ctx, dict, "Dest"); if (obj) { kind = PDF_LINK_GOTO; dest = resolve_dest(xref, obj); } action = fz_dict_gets(ctx, dict, "A"); /* fall back to additional action button's down/up action */ if (!action) action = fz_dict_getsa(ctx, fz_dict_gets(ctx, dict, "AA"), "U", "D"); if (action) { obj = fz_dict_gets(ctx, action, "S"); if (fz_is_name(ctx, obj) && !strcmp(fz_to_name(ctx, obj), "GoTo")) { kind = PDF_LINK_GOTO; dest = resolve_dest(xref, fz_dict_gets(ctx, action, "D")); } else if (fz_is_name(ctx, obj) && !strcmp(fz_to_name(ctx, obj), "URI")) { kind = PDF_LINK_URI; dest = fz_dict_gets(ctx, action, "URI"); } else if (fz_is_name(ctx, obj) && !strcmp(fz_to_name(ctx, obj), "Launch")) { kind = PDF_LINK_LAUNCH; dest = fz_dict_gets(ctx, action, "F"); } else if (fz_is_name(ctx, obj) && !strcmp(fz_to_name(ctx, obj), "Named")) { kind = PDF_LINK_NAMED; dest = fz_dict_gets(ctx, action, "N"); } else if (fz_is_name(ctx, obj) && (!strcmp(fz_to_name(ctx, obj), "GoToR"))) { kind = PDF_LINK_ACTION; dest = action; } else { dest = NULL; } } if (dest) { pdf_link *link = fz_malloc(ctx, sizeof(pdf_link)); link->kind = kind; link->rect = bbox; link->dest = fz_keep_obj(dest); link->next = NULL; return link; } return NULL; }
/* * Create a filter given a name and param dictionary. */ static fz_stream * build_filter(fz_stream *chain, pdf_xref * xref, fz_obj * f, fz_obj * p, int num, int gen) { fz_error error; char *s; s = fz_to_name(f); if (!strcmp(s, "ASCIIHexDecode") || !strcmp(s, "AHx")) return fz_open_ahxd(chain); else if (!strcmp(s, "ASCII85Decode") || !strcmp(s, "A85")) return fz_open_a85d(chain); else if (!strcmp(s, "CCITTFaxDecode") || !strcmp(s, "CCF")) return fz_open_faxd(chain, p); else if (!strcmp(s, "DCTDecode") || !strcmp(s, "DCT")) return fz_open_dctd(chain, p); else if (!strcmp(s, "RunLengthDecode") || !strcmp(s, "RL")) return fz_open_rld(chain); else if (!strcmp(s, "FlateDecode") || !strcmp(s, "Fl")) { fz_obj *obj = fz_dict_gets(p, "Predictor"); if (fz_to_int(obj) > 1) return fz_open_predict(fz_open_flated(chain), p); return fz_open_flated(chain); } else if (!strcmp(s, "LZWDecode") || !strcmp(s, "LZW")) { fz_obj *obj = fz_dict_gets(p, "Predictor"); if (fz_to_int(obj) > 1) return fz_open_predict(fz_open_lzwd(chain, p), p); return fz_open_lzwd(chain, p); } else if (!strcmp(s, "JBIG2Decode")) { fz_obj *obj = fz_dict_gets(p, "JBIG2Globals"); if (obj) { fz_buffer *globals; error = pdf_load_stream(&globals, xref, fz_to_num(obj), fz_to_gen(obj)); if (error) fz_catch(error, "cannot load jbig2 global segments"); chain = fz_open_jbig2d(chain, globals); fz_drop_buffer(globals); return chain; } return fz_open_jbig2d(chain, NULL); } else if (!strcmp(s, "JPXDecode")) return chain; /* JPX decoding is special cased in the image loading code */ else if (!strcmp(s, "Crypt")) { fz_obj *name; if (!xref->crypt) { fz_warn("crypt filter in unencrypted document"); return chain; } name = fz_dict_gets(p, "Name"); if (fz_is_name(name)) return pdf_open_crypt_with_filter(chain, xref->crypt, fz_to_name(name), num, gen); return chain; } fz_warn("unknown filter name (%s)", s); return chain; }
static void savefont(fz_obj *dict, int num) { fz_error error; char name[1024]; char *subtype; fz_buffer *buf; fz_obj *stream = NULL; fz_obj *obj; char *ext = ""; FILE *f; char *fontname = "font"; int n; obj = fz_dict_gets(ctx, dict, "FontName"); if (obj) fontname = fz_to_name(ctx, obj); obj = fz_dict_gets(ctx, dict, "FontFile"); if (obj) { stream = obj; ext = "pfa"; } obj = fz_dict_gets(ctx, dict, "FontFile2"); if (obj) { stream = obj; ext = "ttf"; } obj = fz_dict_gets(ctx, dict, "FontFile3"); if (obj) { stream = obj; obj = fz_dict_gets(ctx, obj, "Subtype"); if (obj && !fz_is_name(ctx, obj)) die(fz_error_make(ctx, "Invalid font descriptor subtype")); subtype = fz_to_name(ctx, obj); if (!strcmp(subtype, "Type1C")) ext = "cff"; else if (!strcmp(subtype, "CIDFontType0C")) ext = "cid"; else die(fz_error_make(ctx, "Unhandled font type '%s'", subtype)); } if (!stream) { fz_warn(ctx, "Unhandled font type"); return; } buf = fz_new_buffer(ctx, 0); error = pdf_load_stream(&buf, xref, fz_to_num(stream), fz_to_gen(stream)); if (error) die(error); sprintf(name, "%s-%04d.%s", fontname, num, ext); printf("extracting font %s\n", name); f = fopen(name, "wb"); if (f == NULL) die(fz_error_make(ctx, "Error creating font file")); n = fwrite(buf->data, 1, buf->len, f); if (n < buf->len) die(fz_error_make(ctx, "Error writing font file")); if (fclose(f) < 0) die(fz_error_make(ctx, "Error closing font file")); fz_drop_buffer(ctx, buf); }
static int isfontdesc(fz_obj *obj) { fz_obj *type = fz_dict_gets(ctx, obj, "Type"); return fz_is_name(ctx, type) && !strcmp(fz_to_name(ctx, type), "FontDescriptor"); }
static int isimage(fz_obj *obj) { fz_obj *type = fz_dict_gets(ctx, obj, "Subtype"); return fz_is_name(ctx, type) && !strcmp(fz_to_name(ctx, type), "Image"); }