static void sweepref(fz_obj *obj) { int num = fz_to_num(obj); int gen = fz_to_gen(obj); if (num < 0 || num >= xref->len) return; if (uselist[num]) return; uselist[num] = 1; /* Bake in /Length in stream objects */ fz_try(ctx) { if (pdf_is_stream(xref, num, gen)) { fz_obj *len = fz_dict_gets(obj, "Length"); if (fz_is_indirect(len)) { uselist[fz_to_num(len)] = 0; len = fz_resolve_indirect(len); fz_dict_puts(obj, "Length", len); } } } fz_catch(ctx) { /* Leave broken */ } sweepobj(fz_resolve_indirect(obj)); }
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 renumberobj(fz_obj *obj) { int i; fz_context *ctx = xref->ctx; if (fz_is_dict(obj)) { int n = fz_dict_len(obj); for (i = 0; i < n; i++) { fz_obj *key = fz_dict_get_key(obj, i); fz_obj *val = fz_dict_get_val(obj, i); if (fz_is_indirect(val)) { val = fz_new_indirect(ctx, renumbermap[fz_to_num(val)], 0, xref); fz_dict_put(obj, key, val); fz_drop_obj(val); } else { renumberobj(val); } } } else if (fz_is_array(obj)) { int n = fz_array_len(obj); for (i = 0; i < n; i++) { fz_obj *val = fz_array_get(obj, i); if (fz_is_indirect(val)) { val = fz_new_indirect(ctx, renumbermap[fz_to_num(val)], 0, xref); fz_array_put(obj, i, val); fz_drop_obj(val); } else { renumberobj(val); } } } }
static void renumberobjs(void) { pdf_xref_entry *oldxref; int newlen; int num; /* Apply renumber map to indirect references in all objects in xref */ renumberobj(xref->trailer); for (num = 0; num < xref->len; num++) { fz_obj *obj = xref->table[num].obj; if (fz_is_indirect(obj)) { obj = fz_new_indirect(ctx, renumbermap[fz_to_num(obj)], 0, xref); pdf_update_object(xref, num, 0, obj); fz_drop_obj(obj); } else { renumberobj(obj); } } /* Create new table for the reordered, compacted xref */ oldxref = xref->table; xref->table = fz_malloc_array(xref->ctx, xref->len, sizeof(pdf_xref_entry)); xref->table[0] = oldxref[0]; /* Move used objects into the new compacted xref */ newlen = 0; for (num = 1; num < xref->len; num++) { if (uselist[num]) { if (newlen < renumbermap[num]) newlen = renumbermap[num]; xref->table[renumbermap[num]] = oldxref[num]; } else { if (oldxref[num].obj) fz_drop_obj(oldxref[num].obj); } } fz_free(xref->ctx, oldxref); /* Update the used objects count in compacted xref */ xref->len = newlen + 1; /* Update list of used objects to fit with compacted xref */ for (num = 1; num < xref->len; num++) uselist[num] = 1; }
static void sweepobj(fz_obj *obj) { int i; if (fz_is_indirect(obj)) sweepref(obj); else if (fz_is_dict(ctx, obj)) for (i = 0; i < fz_dict_len(ctx, obj); i++) sweepobj(fz_dict_get_val(ctx, obj, i)); else if (fz_is_array(ctx, obj)) for (i = 0; i < fz_array_len(ctx, obj); i++) sweepobj(fz_array_get(ctx, obj, i)); }
static void sweepobj(fz_obj *obj) { int i; if (fz_is_indirect(obj)) sweepref(obj); else if (fz_is_dict(obj)) { int n = fz_dict_len(obj); for (i = 0; i < n; i++) sweepobj(fz_dict_get_val(obj, i)); } else if (fz_is_array(obj)) { int n = fz_array_len(obj); for (i = 0; i < n; i++) sweepobj(fz_array_get(obj, i)); } }
fz_obj * pdf_resolve_indirect(fz_obj *ref) { if (fz_is_indirect(ref)) { pdf_xref *xref = fz_get_indirect_xref(ref); int num = fz_to_num(ref); int gen = fz_to_gen(ref); if (xref) { fz_error error = pdf_cache_object(xref, num, gen); if (error) { fz_catch(error, "cannot load object (%d %d R) into cache", num, gen); return ref; } if (xref->table[num].obj) return xref->table[num].obj; } } return ref; }
/* * 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 load_indexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) { fz_error error; fz_colorspace *cs; struct indexed *idx; fz_obj *baseobj = fz_array_get(array, 1); fz_obj *highobj = fz_array_get(array, 2); fz_obj *lookup = fz_array_get(array, 3); fz_colorspace *base; int i, n; error = pdf_load_colorspace(&base, xref, baseobj); if (error) return fz_rethrow(error, "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj)); idx = fz_malloc(sizeof(struct indexed)); idx->base = base; idx->high = fz_to_int(highobj); idx->high = CLAMP(idx->high, 0, 255); n = base->n * (idx->high + 1); idx->lookup = fz_malloc(n); memset(idx->lookup, 0, n); cs = fz_new_colorspace("Indexed", 1); cs->to_rgb = indexed_to_rgb; cs->free_data = free_indexed; cs->data = idx; if (fz_is_string(lookup) && fz_to_str_len(lookup) == n) { unsigned char *buf = (unsigned char *) fz_to_str_buf(lookup); for (i = 0; i < n; i++) idx->lookup[i] = buf[i]; } else if (fz_is_indirect(lookup)) { fz_stream *file; error = pdf_open_stream(&file, xref, fz_to_num(lookup), fz_to_gen(lookup)); if (error) { fz_drop_colorspace(cs); return fz_rethrow(error, "cannot open colorspace lookup table (%d 0 R)", fz_to_num(lookup)); } i = fz_read(file, idx->lookup, n); if (i < 0) { fz_drop_colorspace(cs); return fz_throw("cannot read colorspace lookup table (%d 0 R)", fz_to_num(lookup)); } fz_close(file); } else { fz_drop_colorspace(cs); return fz_throw("cannot parse colorspace lookup table"); } *csp = cs; return fz_okay; }
void *fz_get_indirect_xref(fz_obj *obj) { if (fz_is_indirect(obj)) return obj->u.r.xref; return NULL; }
int fz_to_gen(fz_obj *obj) { if (fz_is_indirect(obj)) return obj->u.r.gen; return 0; }
int fz_to_num(fz_obj *obj) { if (fz_is_indirect(obj)) return obj->u.r.num; return 0; }