diff options
Diffstat (limited to 'pdf/pdf_dict.c')
-rw-r--r-- | pdf/pdf_dict.c | 223 |
1 files changed, 152 insertions, 71 deletions
diff --git a/pdf/pdf_dict.c b/pdf/pdf_dict.c index 34356dfe..217cb6db 100644 --- a/pdf/pdf_dict.c +++ b/pdf/pdf_dict.c @@ -140,7 +140,7 @@ int pdfi_dict_from_stack(pdf_context *ctx, uint32_t indirect_num, uint32_t indir i = (index / 2) - 1; /* In PDF keys are *required* to be names, so we ought to check that here */ - if (((pdf_obj *)ctx->stack_top[-2])->type == PDF_NAME) { + if (pdfi_type_of((pdf_obj *)ctx->stack_top[-2]) == PDF_NAME) { d->list[i].key = ctx->stack_top[-2]; pdfi_countup(d->list[i].key); #if DEBUG_DICT @@ -149,7 +149,7 @@ int pdfi_dict_from_stack(pdf_context *ctx, uint32_t indirect_num, uint32_t indir d->list[i].value = ctx->stack_top[-1]; pdfi_countup(d->list[i].value); } else { - if (convert_string_keys && ((pdf_obj *)ctx->stack_top[-2])->type == PDF_STRING) { + if (convert_string_keys && (pdfi_type_of((pdf_obj *)ctx->stack_top[-2]) == PDF_STRING)) { pdf_name *n; code = pdfi_dict_name_from_string(ctx, (pdf_string *)ctx->stack_top[-2], &n); if (code < 0) { @@ -266,7 +266,7 @@ static int pdfi_dict_find_unsorted(pdf_context *ctx, pdf_dict *d, const char *Ke for (i=0;i< d->entries;i++) { t = (pdf_name *)d->list[i].key; - if (t && t->type == PDF_NAME) { + if (t && pdfi_type_of(t) == PDF_NAME) { if (pdfi_name_is((pdf_name *)t, Key)) { return i; } @@ -315,14 +315,14 @@ int pdfi_dict_get_common(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj *o = NULL; - if (d->type != PDF_DICT) + if (pdfi_type_of(d) != PDF_DICT) return_error(gs_error_typecheck); index = pdfi_dict_find(ctx, d, Key, true); if (index < 0) return index; - if (d->list[index].value->type == PDF_INDIRECT) { + if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) { pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value; if (r->ref_object_num == d->object_num) @@ -340,8 +340,11 @@ int pdfi_dict_get_common(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj * referencing and never counts down to 0, leading to a memory leak. * This is clearly an error, so flag it and don't replace the indirect reference. */ - if ((*o)->object_num == 0 || (*o)->object_num != d->object_num) - { + if ((*o) < (pdf_obj *)(uintptr_t)(TOKEN__LAST_KEY)) { + /* "FAST" object, therefore can't be a problem. */ + pdfi_countdown(d->list[index].value); + d->list[index].value = *o; + } else if ((*o)->object_num == 0 || (*o)->object_num != d->object_num) { pdfi_countdown(d->list[index].value); d->list[index].value = *o; } else { @@ -364,7 +367,7 @@ int pdfi_dict_get_no_deref(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, p *o = NULL; - if (d->type != PDF_DICT) + if (pdfi_type_of(d) != PDF_DICT) return_error(gs_error_typecheck); index = pdfi_dict_find_key(ctx, d, Key, true); @@ -386,14 +389,14 @@ int pdfi_dict_get_by_key(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, pdf *o = NULL; - if (d->type != PDF_DICT) + if (pdfi_type_of(d) != PDF_DICT) return_error(gs_error_typecheck); index = pdfi_dict_find_key(ctx, d, Key, true); if (index < 0) return index; - if (d->list[index].value->type == PDF_INDIRECT) { + if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) { pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value; code = pdfi_deref_loop_detect(ctx, r->ref_object_num, r->ref_generation_num, o); @@ -414,14 +417,14 @@ int pdfi_dict_get_ref(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_indire *o = NULL; - if (d->type != PDF_DICT) + if (pdfi_type_of(d) != PDF_DICT) return_error(gs_error_typecheck); index = pdfi_dict_find(ctx, d, Key, true); if (index < 0) return index; - if (d->list[index].value->type == PDF_INDIRECT) { + if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) { *o = (pdf_indirect_ref *)d->list[index].value; pdfi_countup(*o); return 0; @@ -444,7 +447,7 @@ static int pdfi_dict_get_no_store_R_inner(pdf_context *ctx, pdf_dict *d, const c *o = NULL; - if (d->type != PDF_DICT) + if (pdfi_type_of(d) != PDF_DICT) return_error(gs_error_typecheck); if (strKey == NULL) @@ -455,7 +458,7 @@ static int pdfi_dict_get_no_store_R_inner(pdf_context *ctx, pdf_dict *d, const c if (index < 0) return index; - if (d->list[index].value->type == PDF_INDIRECT) { + if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) { pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value; code = pdfi_dereference(ctx, r->ref_object_num, r->ref_generation_num, o); @@ -500,7 +503,7 @@ int pdfi_dict_get_type(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj_t if (code < 0) return code; - if ((*o)->type != type) { + if (pdfi_type_of(*o) != type) { pdfi_countdown(*o); *o = NULL; return_error(gs_error_typecheck); @@ -524,15 +527,14 @@ pdfi_dict_get_int2(pdf_context *ctx, pdf_dict *d, const char *Key1, int pdfi_dict_get_int(pdf_context *ctx, pdf_dict *d, const char *Key, int64_t *i) { int code; - pdf_num *n; + pdf_obj *n; - code = pdfi_dict_get_type(ctx, d, Key, PDF_INT, (pdf_obj **)&n); + code = pdfi_dict_get(ctx, d, Key, &n); if (code < 0) return code; - - *i = n->value.i; + code = pdfi_obj_to_int(ctx, n, i); pdfi_countdown(n); - return 0; + return code; } /* Get an int from dict, and if undefined, return provided default */ @@ -566,15 +568,24 @@ pdfi_dict_get_bool2(pdf_context *ctx, pdf_dict *d, const char *Key1, int pdfi_dict_get_bool(pdf_context *ctx, pdf_dict *d, const char *Key, bool *val) { int code; - pdf_bool *b; + pdf_obj *b; - code = pdfi_dict_get_type(ctx, d, Key, PDF_BOOL, (pdf_obj **)&b); + code = pdfi_dict_get(ctx, d, Key, &b); if (code < 0) return code; - *val = b->value; + if (b == PDF_TRUE_OBJ) { + *val = 1; + return 0; + } else if (b == PDF_FALSE_OBJ) { + *val = 0; + return 0; + } + pdfi_countdown(b); - return 0; + + *val = 0; /* Be consistent at least! */ + return_error(gs_error_typecheck); } int pdfi_dict_get_number2(pdf_context *ctx, pdf_dict *d, const char *Key1, const char *Key2, double *f) @@ -590,23 +601,15 @@ int pdfi_dict_get_number2(pdf_context *ctx, pdf_dict *d, const char *Key1, const int pdfi_dict_get_number(pdf_context *ctx, pdf_dict *d, const char *Key, double *f) { int code; - pdf_num *o; + pdf_obj *o; - code = pdfi_dict_get(ctx, d, Key, (pdf_obj **)&o); + code = pdfi_dict_get(ctx, d, Key, &o); if (code < 0) return code; - if (o->type == PDF_INT) { - *f = (double)(o->value.i); - } else { - if (o->type == PDF_REAL){ - *f = o->value.d; - } else { - pdfi_countdown(o); - return_error(gs_error_typecheck); - } - } + code = pdfi_obj_to_real(ctx, o, f); pdfi_countdown(o); - return 0; + + return code; } /* convenience functions for retrieving arrys, see shadings and functions */ @@ -627,7 +630,7 @@ int fill_domain_from_dict(pdf_context *ctx, float *parray, int size, pdf_dict *d code = pdfi_dict_get(ctx, dict, "Domain", (pdf_obj **)&a); if (code < 0) return code; - if (a->type != PDF_ARRAY) { + if (pdfi_type_of(a) != PDF_ARRAY) { pdfi_countdown(a); return_error(gs_error_typecheck); } @@ -659,7 +662,7 @@ int fill_float_array_from_dict(pdf_context *ctx, float *parray, int size, pdf_di code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a); if (code < 0) return code; - if (a->type != PDF_ARRAY) { + if (pdfi_type_of(a) != PDF_ARRAY) { code = gs_note_error(gs_error_typecheck); goto exit; } @@ -685,13 +688,13 @@ int fill_bool_array_from_dict(pdf_context *ctx, bool *parray, int size, pdf_dict { int code, i; pdf_array *a = NULL; - pdf_bool *o; + pdf_obj *o; uint64_t array_size; code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a); if (code < 0) return code; - if (a->type != PDF_ARRAY) { + if (pdfi_type_of(a) != PDF_ARRAY) { pdfi_countdown(a); return_error(gs_error_typecheck); } @@ -700,13 +703,20 @@ int fill_bool_array_from_dict(pdf_context *ctx, bool *parray, int size, pdf_dict return_error(gs_error_rangecheck); for (i=0;i< array_size;i++) { - code = pdfi_array_get_type(ctx, a, (uint64_t)i, PDF_BOOL, (pdf_obj **)&o); + code = pdfi_array_get(ctx, a, (uint64_t)i, (pdf_obj **)&o); if (code < 0) { pdfi_countdown(a); return_error(code); } - parray[i] = o->value; - pdfi_countdown(o); + if (o == PDF_TRUE_OBJ) { + parray[i] = 1; + } else if (o == PDF_FALSE_OBJ) { + parray[i] = 0; + } else { + pdfi_countdown(o); + pdfi_countdown(a); + return_error(gs_error_typecheck); + } } pdfi_countdown(a); return array_size; @@ -722,7 +732,7 @@ int fill_matrix_from_dict(pdf_context *ctx, float *parray, pdf_dict *dict) code = pdfi_dict_get(ctx, dict, "Matrix", (pdf_obj **)&a); if (code < 0) return code; - if (a->type != PDF_ARRAY) { + if (pdfi_type_of(a) != PDF_ARRAY) { pdfi_countdown(a); return_error(gs_error_typecheck); } @@ -758,7 +768,7 @@ int pdfi_make_float_array_from_dict(pdf_context *ctx, float **parray, pdf_dict * code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a); if (code < 0) return code; - if (a->type != PDF_ARRAY) { + if (pdfi_type_of(a) != PDF_ARRAY) { pdfi_countdown(a); return_error(gs_error_typecheck); } @@ -795,7 +805,7 @@ int pdfi_make_int_array_from_dict(pdf_context *ctx, int **parray, pdf_dict *dict code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a); if (code < 0) return code; - if (a->type != PDF_ARRAY) { + if (pdfi_type_of(a) != PDF_ARRAY) { pdfi_countdown(a); return_error(gs_error_typecheck); } @@ -828,10 +838,10 @@ int pdfi_dict_put_obj(pdf_context *ctx, pdf_dict *d, pdf_obj *Key, pdf_obj *valu int i; pdf_dict_entry *new_list; - if (d->type != PDF_DICT) + if (pdfi_type_of(d) != PDF_DICT) return_error(gs_error_typecheck); - if (Key->type != PDF_NAME) + if (pdfi_type_of(Key) != PDF_NAME) return_error(gs_error_typecheck); /* First, do we have a Key/value pair already ? */ @@ -883,6 +893,60 @@ int pdfi_dict_put_obj(pdf_context *ctx, pdf_dict *d, pdf_obj *Key, pdf_obj *valu return 0; } +/* + * Be very cautious using this routine; it does not check to see if a key already exists + * in a dictionary!. This is initially at least intended for use by the font code, to build + * a CharStrings dictionary. We do that by adding each glyph individually with a name + * created from a loop counter, so we know there cannot be any duplicates, and the time + * taken to check that each of 64K names was unique was quite significant. + * See bug #705534, the old PDF interpreter (nullpage, 72 dpi) runs this file in ~20 seconds + * pdfi runs it in around 40 seconds. With this change it runs in around 3 seconds. THis is, + * of course, an extreme example. + */ +int pdfi_dict_put_unchecked(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj *value) +{ + int i, code = 0; + pdf_dict_entry *new_list; + pdf_obj *key = NULL; + + code = pdfi_name_alloc(ctx, (byte *)Key, strlen(Key), &key); + if (code < 0) + return code; + pdfi_countup(key); + + /* Nope, its a new Key */ + if (d->size > d->entries) { + /* We have a hole, find and use it */ + for (i=0;i< d->size;i++) { + if (d->list[i].key == NULL) { + d->list[i].key = key; + d->list[i].value = value; + pdfi_countup(value); + d->entries++; + return 0; + } + } + } + + new_list = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, (d->size + 1) * sizeof(pdf_dict_entry), "pdfi_dict_put reallocate dictionary key/values"); + if (new_list == NULL) { + return_error(gs_error_VMerror); + } + memcpy(new_list, d->list, d->size * sizeof(pdf_dict_entry)); + + gs_free_object(ctx->memory, d->list, "pdfi_dict_put key/value reallocation"); + + d->list = new_list; + + d->list[d->size].key = key; + d->list[d->size].value = value; + d->size++; + d->entries++; + pdfi_countup(value); + + return 0; +} + /* Put into dictionary with key as string */ int pdfi_dict_put(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj *value) { @@ -914,15 +978,9 @@ int pdfi_dict_put_int(pdf_context *ctx, pdf_dict *d, const char *key, int64_t va int pdfi_dict_put_bool(pdf_context *ctx, pdf_dict *d, const char *key, bool value) { - int code; - pdf_bool *obj = NULL; - - code = pdfi_object_alloc(ctx, PDF_BOOL, 0, (pdf_obj **)&obj); - if (code < 0) - return code; + pdf_obj *obj = (value ? PDF_TRUE_OBJ : PDF_FALSE_OBJ); - obj->value = value; - return pdfi_dict_put(ctx, d, key, (pdf_obj *)obj); + return pdfi_dict_put(ctx, d, key, obj); } int pdfi_dict_put_name(pdf_context *ctx, pdf_dict *d, const char *key, const char *name) @@ -957,7 +1015,7 @@ int pdfi_dict_known(pdf_context *ctx, pdf_dict *d, const char *Key, bool *known) { int i; - if (d->type != PDF_DICT) + if (pdfi_type_of(d) != PDF_DICT) return_error(gs_error_typecheck); *known = false; @@ -972,7 +1030,7 @@ int pdfi_dict_known_by_key(pdf_context *ctx, pdf_dict *d, pdf_name *Key, bool *k { int i; - if (d->type != PDF_DICT) + if (pdfi_type_of(d) != PDF_DICT) return_error(gs_error_typecheck); *known = false; @@ -1030,6 +1088,25 @@ int pdfi_dict_knownget_type(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_ return 1; } +int pdfi_dict_knownget_bool(pdf_context *ctx, pdf_dict *d, const char *Key, bool *b) +{ + bool known = false; + int code; + + code = pdfi_dict_known(ctx, d, Key, &known); + if (code < 0) + return code; + + if (known == false) + return 0; + + code = pdfi_dict_get_bool(ctx, d, Key, b); + if (code < 0) + return code; + + return 1; +} + /* Like pdfi_dict_knownget_type() but retrieves numbers (two possible types) */ int pdfi_dict_knownget_number(pdf_context *ctx, pdf_dict *d, const char *Key, double *f) @@ -1055,7 +1132,7 @@ int pdfi_dict_next(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, pdf_obj **Value { int code; - if (d->type != PDF_DICT) + if (pdfi_type_of(d) != PDF_DICT) return_error(gs_error_typecheck); while (1) { @@ -1078,7 +1155,7 @@ int pdfi_dict_next(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, pdf_obj **Value continue; } - if (d->list[*index].value->type == PDF_INDIRECT) { + if (pdfi_type_of(d->list[*index].value) == PDF_INDIRECT) { pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[*index].value; pdf_obj *o; @@ -1113,7 +1190,7 @@ int pdfi_dict_key_next(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, uint64_t *i { uint64_t *i = index; - if (d->type != PDF_DICT) + if (pdfi_type_of(d) != PDF_DICT) return_error(gs_error_typecheck); while (1) { @@ -1169,7 +1246,7 @@ int64_t pdfi_stream_length(pdf_context *ctx, pdf_stream *stream) int64_t Length = 0; int code; - if (stream->type != PDF_STREAM) + if (pdfi_type_of(stream) != PDF_STREAM) return 0; if (stream->length_valid) @@ -1195,14 +1272,14 @@ int64_t pdfi_stream_length(pdf_context *ctx, pdf_stream *stream) */ gs_offset_t pdfi_stream_offset(pdf_context *ctx, pdf_stream *stream) { - if (stream->type != PDF_STREAM) + if (pdfi_type_of(stream) != PDF_STREAM) return 0; return stream->stream_offset; } pdf_stream *pdfi_stream_parent(pdf_context *ctx, pdf_stream *stream) { - if (stream->type != PDF_STREAM) + if (pdfi_type_of(stream) != PDF_STREAM) return 0; return (pdf_stream *)stream->parent_obj; } @@ -1233,11 +1310,15 @@ void pdfi_clear_stream_parent(pdf_context *ctx, pdf_stream *stream) int pdfi_dict_from_obj(pdf_context *ctx, pdf_obj *obj, pdf_dict **dict) { *dict = NULL; - if (obj->type == PDF_DICT) - *dict = (pdf_dict *)obj; - else if (obj->type == PDF_STREAM) - *dict = ((pdf_stream *)obj)->stream_dict; - else - return_error(gs_error_typecheck); + switch (pdfi_type_of(obj)) { + case PDF_DICT: + *dict = (pdf_dict *)obj; + break; + case PDF_STREAM: + *dict = ((pdf_stream *)obj)->stream_dict; + break; + default: + return_error(gs_error_typecheck); + } return 0; } |