diff options
Diffstat (limited to 'pdf/pdf_check.c')
-rw-r--r-- | pdf/pdf_check.c | 348 |
1 files changed, 307 insertions, 41 deletions
diff --git a/pdf/pdf_check.c b/pdf/pdf_check.c index 00933bdf..19a6d957 100644 --- a/pdf/pdf_check.c +++ b/pdf/pdf_check.c @@ -66,7 +66,7 @@ * stores all the objects (which we don't want to do because its wasteful) and checking * to see if its already tested a given resource for spots/transparency. * This is a temporary allocation, big enough to hold all the objects in the file (1 per bit) - * each time we have fully checked a resource we add it here, when checking a resoruce we + * each time we have fully checked a resource we add it here, when checking a resource we * first check this list to see if its already been checked, in which case we can skip * it. When done we release the memory. */ @@ -74,6 +74,7 @@ typedef struct { bool transparent; bool has_overprint; /* Does it have OP or op in an ExtGState? */ pdf_dict *spot_dict; + pdf_array *font_array; uint32_t size; byte *CheckedResources; } pdfi_check_tracker_t; @@ -84,6 +85,7 @@ static inline bool resource_is_checked(pdfi_check_tracker_t *tracker, pdf_obj *o { uint32_t byte_offset; byte bit_offset; + int object_num; if(tracker->CheckedResources == NULL) return 0; @@ -91,14 +93,15 @@ static inline bool resource_is_checked(pdfi_check_tracker_t *tracker, pdf_obj *o /* objects with object number 0 are directly defined, we can't * store those so just return immediately */ - if (o->object_num > 0 && (o->object_num >> 3) < tracker->size) { + object_num = pdf_object_num(o); + if (object_num > 0 && (object_num >> 3) < tracker->size) { /* CheckedResources is a byte array, each byte represents * 8 objects. So the object number / 8 is the byte offset * into the array, and then object number % 8 is the bit * within that byte that we want. */ - bit_offset = 0x01 << (o->object_num % 8); - byte_offset = o->object_num >> 3; + bit_offset = 0x01 << (object_num % 8); + byte_offset = object_num >> 3; /* If its already set, then return that. */ if (tracker->CheckedResources[byte_offset] & bit_offset) @@ -116,12 +119,13 @@ pdfi_check_free_tracker(pdf_context *ctx, pdfi_check_tracker_t *tracker) { gs_free_object(ctx->memory, tracker->CheckedResources, "pdfi_check_free_tracker(flags)"); pdfi_countdown(tracker->spot_dict); + pdfi_countdown(tracker->font_array); memset(tracker, 0, sizeof(*tracker)); return 0; } static int -pdfi_check_init_tracker(pdf_context *ctx, pdfi_check_tracker_t *tracker) +pdfi_check_init_tracker(pdf_context *ctx, pdfi_check_tracker_t *tracker, pdf_array **fonts_array, pdf_array **spot_array) { int code = 0; @@ -136,16 +140,25 @@ pdfi_check_init_tracker(pdf_context *ctx, pdfi_check_tracker_t *tracker) memset(tracker->CheckedResources, 0x00, tracker->size); if (ctx->device_state.spot_capable || - (ctx->pgs->device->icc_struct->overprint_control) == gs_overprint_control_simulate) { + (ctx->pgs->device->icc_struct->overprint_control) == gs_overprint_control_simulate || + spot_array != NULL) + { code = pdfi_dict_alloc(ctx, 32, &tracker->spot_dict); if (code < 0) goto cleanup; pdfi_countup(tracker->spot_dict); } + if (fonts_array != NULL) { + code = pdfi_array_alloc(ctx, 0, &tracker->font_array); + if (code < 0) + goto cleanup; + pdfi_countup(tracker->font_array); + } + return 0; - cleanup: +cleanup: pdfi_check_free_tracker(ctx, tracker); return code; } @@ -164,6 +177,9 @@ static int pdfi_check_ColorSpace_dict(pdf_context *ctx, pdf_dict *cspace_dict, if (resource_is_checked(tracker, (pdf_obj *)cspace_dict)) return 0; + if (pdfi_type_of(cspace_dict) != PDF_DICT) + return_error(gs_error_typecheck); + if (pdfi_dict_entries(cspace_dict) > 0) { code = pdfi_loop_detector_mark(ctx); /* Mark the start of the ColorSpace dictionary loop */ if (code < 0) @@ -197,7 +213,7 @@ static int pdfi_check_ColorSpace_dict(pdf_context *ctx, pdf_dict *cspace_dict, } code = pdfi_dict_next(ctx, cspace_dict, &Key, &Value, &index); - if (code == 0 && Value->type == PDF_ARRAY) + if (code == 0 && pdfi_type_of(Value) == PDF_ARRAY) break; pdfi_countdown(Key); Key = NULL; @@ -235,6 +251,9 @@ static int pdfi_check_Shading(pdf_context *ctx, pdf_obj *shading, if (code < 0) return code; + if (pdfi_type_of(shading_dict) != PDF_DICT) + return_error(gs_error_typecheck); + code = pdfi_dict_knownget(ctx, shading_dict, "ColorSpace", (pdf_obj **)&o); if (code > 0) { code = pdfi_check_ColorSpace_for_spots(ctx, o, shading_dict, page_dict, tracker->spot_dict); @@ -257,13 +276,16 @@ static int pdfi_check_Shading_dict(pdf_context *ctx, pdf_dict *shading_dict, if (resource_is_checked(tracker, (pdf_obj *)shading_dict)) return 0; + if (pdfi_type_of(shading_dict) != PDF_DICT) + return_error(gs_error_typecheck); + if (pdfi_dict_entries(shading_dict) > 0) { code = pdfi_loop_detector_mark(ctx); /* Mark the start of the Shading dictionary loop */ if (code < 0) return code; code = pdfi_dict_first(ctx, shading_dict, &Key, &Value, &index); - if (code < 0 || !(Value->type == PDF_DICT || Value->type == PDF_STREAM)) + if (code < 0 || !(pdfi_type_of(Value) == PDF_DICT || pdfi_type_of(Value) == PDF_STREAM)) goto error1; i = 1; @@ -290,7 +312,7 @@ static int pdfi_check_Shading_dict(pdf_context *ctx, pdf_dict *shading_dict, } code = pdfi_dict_next(ctx, shading_dict, &Key, &Value, &index); - if (code == 0 && Value->type == PDF_DICT) + if (code == 0 && pdfi_type_of(Value) == PDF_DICT) break; pdfi_countdown(Key); Key = NULL; @@ -326,6 +348,9 @@ static int pdfi_check_XObject(pdf_context *ctx, pdf_dict *xobject, pdf_dict *pag if (resource_is_checked(tracker, (pdf_obj *)xobject)) return 0; + if (pdfi_type_of(xobject) != PDF_DICT) + return_error(gs_error_typecheck); + code = pdfi_dict_get_type(ctx, xobject, "Subtype", PDF_NAME, (pdf_obj **)&n); if (code >= 0) { if (pdfi_name_is((const pdf_name *)n, "Image")) { @@ -417,6 +442,9 @@ static int pdfi_check_XObject_dict(pdf_context *ctx, pdf_dict *xobject_dict, pdf if (resource_is_checked(tracker, (pdf_obj *)xobject_dict)) return 0; + if (pdfi_type_of(xobject_dict) != PDF_DICT) + return_error(gs_error_typecheck); + if (pdfi_dict_entries(xobject_dict) > 0) { code = pdfi_loop_detector_mark(ctx); /* Mark the start of the XObject dictionary loop */ if (code < 0) @@ -425,7 +453,7 @@ static int pdfi_check_XObject_dict(pdf_context *ctx, pdf_dict *xobject_dict, pdf code = pdfi_dict_first(ctx, xobject_dict, &Key, &Value, &index); if (code < 0) goto error_exit; - if (Value->type != PDF_STREAM) + if (pdfi_type_of(Value) != PDF_STREAM) goto error_exit; i = 1; @@ -457,7 +485,7 @@ static int pdfi_check_XObject_dict(pdf_context *ctx, pdf_dict *xobject_dict, pdf } code = pdfi_dict_next(ctx, xobject_dict, &Key, &Value, &index); - if (code == 0 && Value->type == PDF_STREAM) + if (code == 0 && pdfi_type_of(Value) == PDF_STREAM) break; pdfi_countdown(Key); Key = NULL; @@ -490,6 +518,9 @@ static int pdfi_check_ExtGState(pdf_context *ctx, pdf_dict *extgstate_dict, pdf_ if (resource_is_checked(tracker, (pdf_obj *)extgstate_dict)) return 0; + if (pdfi_type_of(extgstate_dict) != PDF_DICT) + return_error(gs_error_typecheck); + if (pdfi_dict_entries(extgstate_dict) > 0) { /* See if /OP or /op is true */ code = pdfi_dict_get_bool(ctx, extgstate_dict, "OP", &overprint); @@ -502,14 +533,16 @@ static int pdfi_check_ExtGState(pdf_context *ctx, pdf_dict *extgstate_dict, pdf_ /* Check SMask */ code = pdfi_dict_knownget(ctx, extgstate_dict, "SMask", &o); if (code > 0) { - if (o->type == PDF_NAME) { - if (!pdfi_name_is((pdf_name *)o, "None")) { - pdfi_countdown(o); - tracker->transparent = true; - return 0; - } - } else { - if (o->type == PDF_DICT) { + switch (pdfi_type_of(o)) { + case PDF_NAME: + if (!pdfi_name_is((pdf_name *)o, "None")) { + pdfi_countdown(o); + tracker->transparent = true; + return 0; + } + break; + case PDF_DICT: + { pdf_obj *G = NULL; tracker->transparent = true; @@ -526,6 +559,8 @@ static int pdfi_check_ExtGState(pdf_context *ctx, pdf_dict *extgstate_dict, pdf_ pdfi_countdown(o); return code; } + default: + break; } } pdfi_countdown(o); @@ -577,6 +612,9 @@ static int pdfi_check_ExtGState_dict(pdf_context *ctx, pdf_dict *extgstate_dict, if (resource_is_checked(tracker, (pdf_obj *)extgstate_dict)) return 0; + if (pdfi_type_of(extgstate_dict) != PDF_DICT) + return_error(gs_error_typecheck); + if (pdfi_dict_entries(extgstate_dict) > 0) { code = pdfi_loop_detector_mark(ctx); /* Mark the start of the ColorSpace dictionary loop */ if (code < 0) @@ -611,7 +649,7 @@ static int pdfi_check_ExtGState_dict(pdf_context *ctx, pdf_dict *extgstate_dict, } code = pdfi_dict_next(ctx, extgstate_dict, &Key, &Value, &index); - if (code == 0 && Value->type == PDF_DICT) + if (code == 0 && pdfi_type_of(Value) == PDF_DICT) break; pdfi_countdown(Key); Key = NULL; @@ -644,6 +682,9 @@ static int pdfi_check_Pattern(pdf_context *ctx, pdf_dict *pattern, pdf_dict *pag if (resource_is_checked(tracker, (pdf_obj *)pattern)) return 0; + if (pdfi_type_of(pattern) != PDF_DICT) + return_error(gs_error_typecheck); + if (tracker->spot_dict != NULL) { code = pdfi_dict_knownget(ctx, pattern, "Shading", &o); if (code > 0) @@ -677,7 +718,7 @@ int pdfi_check_Pattern_transparency(pdf_context *ctx, pdf_dict *pattern, pdf_dic bool *transparent) { int code; - pdfi_check_tracker_t tracker = {0, 0, NULL, 0, NULL}; + pdfi_check_tracker_t tracker = {0, 0, NULL, NULL, 0, NULL}; /* NOTE: We use a "null" tracker that won't do any optimization to prevent * checking the same resource twice. @@ -708,6 +749,9 @@ static int pdfi_check_Pattern_dict(pdf_context *ctx, pdf_dict *pattern_dict, pdf if (resource_is_checked(tracker, (pdf_obj *)pattern_dict)) return 0; + if (pdfi_type_of(pattern_dict) != PDF_DICT) + return_error(gs_error_typecheck); + if (pdfi_dict_entries(pattern_dict) > 0) { code = pdfi_loop_detector_mark(ctx); /* Mark the start of the Pattern dictionary loop */ if (code < 0) @@ -717,7 +761,7 @@ static int pdfi_check_Pattern_dict(pdf_context *ctx, pdf_dict *pattern_dict, pdf if (code < 0) goto error1; - if(Value->type != PDF_DICT && Value->type != PDF_STREAM) + if (pdfi_type_of(Value) != PDF_DICT && pdfi_type_of(Value) != PDF_STREAM) goto transparency_exit; i = 1; @@ -748,7 +792,7 @@ static int pdfi_check_Pattern_dict(pdf_context *ctx, pdf_dict *pattern_dict, pdf } code = pdfi_dict_next(ctx, pattern_dict, &Key, &Value, &index); - if (code == 0 && (Value->type == PDF_DICT || Value->type == PDF_STREAM)) + if (code == 0 && (pdfi_type_of(Value) == PDF_DICT || pdfi_type_of(Value) == PDF_STREAM)) break; pdfi_countdown(Key); Key = NULL; @@ -771,7 +815,8 @@ error1: /* * This routine checks a Font dictionary to see if it contains any spot - * colour definitions, or transparency usage. + * colour definitions, or transparency usage. While we are here, if the tracker's font_array + * is not NULL, pick up the font information and store it in the array. */ static int pdfi_check_Font(pdf_context *ctx, pdf_dict *font, pdf_dict *page_dict, pdfi_check_tracker_t *tracker) @@ -782,22 +827,186 @@ static int pdfi_check_Font(pdf_context *ctx, pdf_dict *font, pdf_dict *page_dict if (resource_is_checked(tracker, (pdf_obj *)font)) return 0; - if (font->type != PDF_DICT) + if (pdfi_type_of(font) != PDF_DICT) return_error(gs_error_typecheck); - code = pdfi_dict_knownget_type(ctx, font, "Subtype", PDF_NAME, &o); - if (code > 0) { - if (pdfi_name_is((pdf_name *)o, "Type3")) { - pdfi_countdown(o); - o = NULL; + if (tracker->font_array != NULL) { + /* If we get to here this is a font we have not seen before. We need + * to make a new font array big enough to hold the existing entries +1 + * copy the existing entries to the new array and free the old array. + * Finally create a dictionary with all the font information we want + * and add it to the array. + */ + pdf_array *new_fonts = NULL; + int index = 0; + pdf_obj *array_obj = NULL; + pdf_dict *font_info_dict = NULL; - code = pdfi_dict_knownget_type(ctx, font, "Resources", PDF_DICT, &o); - if (code > 0) - (void)pdfi_check_Resources(ctx, (pdf_dict *)o, page_dict, tracker); + /* Let's start by gathering the information we need and storing it in a dictionary */ + code = pdfi_dict_alloc(ctx, 4, &font_info_dict); + if (code < 0) + return code; + pdfi_countup(font_info_dict); + + if (font->object_num != 0) { + pdf_num *int_obj = NULL; + + code = pdfi_object_alloc(ctx, PDF_INT, 0, (pdf_obj **)&int_obj); + if (code >= 0) { + pdfi_countup(int_obj); + int_obj->value.i = font->object_num; + code = pdfi_dict_put(ctx, font_info_dict, "ObjectNum", (pdf_obj *)int_obj); + pdfi_countdown(int_obj); + } + if (code < 0) { + pdfi_countdown(font_info_dict); + return code; + } + } + + code = pdfi_dict_get(ctx, font, "BaseFont", &array_obj); + if (code >= 0) { + code = pdfi_dict_put(ctx, font_info_dict, "BaseFont", array_obj); + if (code < 0) { + pdfi_countdown(array_obj); + pdfi_countdown(font_info_dict); + return code; + } + } + pdfi_countdown(array_obj); + array_obj = NULL; + + code = pdfi_dict_get(ctx, font, "ToUnicode", &array_obj); + if (code >= 0) + code = pdfi_dict_put(ctx, font_info_dict, "ToUnicode", PDF_TRUE_OBJ); + else + code = pdfi_dict_put(ctx, font_info_dict, "ToUnicode", PDF_FALSE_OBJ); + pdfi_countdown(array_obj); + array_obj = NULL; + if (code < 0) + return code; + + code = pdfi_dict_get(ctx, font, "FontDescriptor", &array_obj); + if (code >= 0) { + bool known = false; + + (void)pdfi_dict_known(ctx, (pdf_dict *)array_obj, "FontFile", &known); + if (!known) { + (void)pdfi_dict_known(ctx, (pdf_dict *)array_obj, "FontFile2", &known); + if (!known) { + (void)pdfi_dict_known(ctx, (pdf_dict *)array_obj, "FontFile3", &known); + } + } + + if (known >= 0) + code = pdfi_dict_put(ctx, font_info_dict, "Embedded", PDF_TRUE_OBJ); + else + code = pdfi_dict_put(ctx, font_info_dict, "Embedded", PDF_FALSE_OBJ); + } else + code = pdfi_dict_put(ctx, font_info_dict, "Embedded", PDF_FALSE_OBJ); + + pdfi_countdown(array_obj); + array_obj = NULL; + + if (code < 0) + return code; + + + code = pdfi_dict_knownget_type(ctx, font, "Subtype", PDF_NAME, &array_obj); + if (code >= 0) { + code = pdfi_dict_put(ctx, font_info_dict, "Subtype", array_obj); + if (code < 0) { + pdfi_countdown(array_obj); + pdfi_countdown(font_info_dict); + return code; + } + + if (pdfi_name_is((pdf_name *)array_obj, "Type3")) { + pdfi_countdown(o); + o = NULL; + + code = pdfi_dict_knownget_type(ctx, font, "Resources", PDF_DICT, &o); + if (code > 0) + (void)pdfi_check_Resources(ctx, (pdf_dict *)o, page_dict, tracker); + } + + if (pdfi_name_is((const pdf_name *)array_obj, "Type0")){ + pdf_array *descendants = NULL; + pdf_dict *desc_font = NULL; + + code = pdfi_dict_get(ctx, font, "DescendantFonts", (pdf_obj **)&descendants); + if (code >= 0) { + code = pdfi_array_get(ctx, descendants, 0, (pdf_obj **)&desc_font); + if (code >= 0){ + pdf_array *desc_array = NULL; + + code = pdfi_array_alloc(ctx, 0, &desc_array); + pdfi_countup(desc_array); + if (code >= 0) { + pdf_array *saved = tracker->font_array; + + tracker->font_array = desc_array; + (void)pdfi_check_Font(ctx, desc_font, page_dict, tracker); + (void)pdfi_dict_put(ctx, font_info_dict, "Descendants", (pdf_obj *)tracker->font_array); + pdfi_countdown((pdf_obj *)tracker->font_array); + tracker->font_array = saved; + } + pdfi_countdown(descendants); + pdfi_countdown(desc_font); + } + } + } + } + pdfi_countdown(array_obj); + array_obj = NULL; + + code = pdfi_array_alloc(ctx, pdfi_array_size(tracker->font_array) + 1, &new_fonts); + if (code < 0) { + pdfi_countdown(font_info_dict); + return code; + } + pdfi_countup(new_fonts); + + for (index = 0; index < pdfi_array_size(tracker->font_array); index++) { + code = pdfi_array_get(ctx, tracker->font_array, index, &array_obj); + if (code < 0) { + pdfi_countdown(font_info_dict); + pdfi_countdown(new_fonts); + return code; + } + code = pdfi_array_put(ctx, new_fonts, index, array_obj); + pdfi_countdown(array_obj); + if (code < 0) { + pdfi_countdown(font_info_dict); + pdfi_countdown(new_fonts); + return code; + } + } + code = pdfi_array_put(ctx, new_fonts, index, (pdf_obj *)font_info_dict); + if (code < 0) { + pdfi_countdown(font_info_dict); + pdfi_countdown(new_fonts); + return code; } + pdfi_countdown(font_info_dict); + pdfi_countdown(tracker->font_array); + tracker->font_array = new_fonts; + } else { + code = pdfi_dict_knownget_type(ctx, font, "Subtype", PDF_NAME, &o); + if (code > 0) { + if (pdfi_name_is((pdf_name *)o, "Type3")) { + pdfi_countdown(o); + o = NULL; + + code = pdfi_dict_knownget_type(ctx, font, "Resources", PDF_DICT, &o); + if (code > 0) + (void)pdfi_check_Resources(ctx, (pdf_dict *)o, page_dict, tracker); + } + } + + pdfi_countdown(o); + o = NULL; } - pdfi_countdown(o); - o = NULL; return 0; } @@ -815,6 +1024,9 @@ static int pdfi_check_Font_dict(pdf_context *ctx, pdf_dict *font_dict, pdf_dict if (resource_is_checked(tracker, (pdf_obj *)font_dict)) return 0; + if (pdfi_type_of(font_dict) != PDF_DICT) + return_error(gs_error_typecheck); + if (pdfi_dict_entries(font_dict) > 0) { code = pdfi_loop_detector_mark(ctx); /* Mark the start of the Font dictionary loop */ if (code < 0) @@ -846,7 +1058,7 @@ static int pdfi_check_Font_dict(pdf_context *ctx, pdf_dict *font_dict, pdf_dict } code = pdfi_dict_next(ctx, font_dict, &Key, &Value, &index); - if (code == 0 && Value->type == PDF_DICT) + if (code == 0 && pdfi_type_of(Value) == PDF_DICT) break; pdfi_countdown(Key); Key = NULL; @@ -875,6 +1087,9 @@ static int pdfi_check_Resources(pdf_context *ctx, pdf_dict *Resources_dict, if (resource_is_checked(tracker, (pdf_obj *)Resources_dict)) return 0; + if (pdfi_type_of(Resources_dict) != PDF_DICT) + return_error(gs_error_typecheck); + /* First up, check any colour spaces, for new spot colours. * We only do this if asked because its expensive. spot_dict being NULL * means we aren't interested in spot colours (not a DeviceN or Separation device) @@ -937,6 +1152,9 @@ static int pdfi_check_annot_for_transparency(pdf_context *ctx, pdf_dict *annot, if (resource_is_checked(tracker, (pdf_obj *)annot)) return 0; + if (pdfi_type_of(annot) != PDF_DICT) + return_error(gs_error_typecheck); + /* Check #1 Does the (Normal) Appearnce stream use any Resources which include transparency. * We check this first, because this also checks for spot colour spaces. Once we've done that we * can exit the checks as soon as we detect transparency. @@ -1035,6 +1253,9 @@ static int pdfi_check_Annots_for_transparency(pdf_context *ctx, pdf_array *annot if (resource_is_checked(tracker, (pdf_obj *)annots_array)) return 0; + if (pdfi_type_of(annots_array) != PDF_ARRAY) + return_error(gs_error_typecheck); + for (i=0; i < pdfi_array_size(annots_array); i++) { code = pdfi_array_get_type(ctx, annots_array, (uint64_t)i, PDF_DICT, (pdf_obj **)&annot); if (code >= 0) { @@ -1084,6 +1305,10 @@ static int pdfi_check_page_inner(pdf_context *ctx, pdf_dict *page_dict, tracker->transparent = false; + if (pdfi_type_of(page_dict) != PDF_DICT) + return_error(gs_error_typecheck); + + /* Check if the page dictionary has a page Group entry (for spots). * Page group should mean the page has transparency but we ignore it for the purposes * of transparency detection. See above. @@ -1104,7 +1329,7 @@ static int pdfi_check_page_inner(pdf_context *ctx, pdf_dict *page_dict, code = pdfi_dict_knownget_type(ctx, page_dict, "Resources", PDF_DICT, (pdf_obj **)&Resources); if (code > 0) code = pdfi_check_Resources(ctx, Resources, page_dict, tracker); - if ((code < 0 && ctx->args.pdfstoponerror) || (code == gs_error_stackoverflow)) + if ((code < 0 && ctx->args.pdfstoponerror) || (code == gs_error_pdf_stackoverflow)) goto exit; /* If we are drawing Annotations, check to see if the page uses any Annots */ @@ -1130,7 +1355,7 @@ static int pdfi_check_page_inner(pdf_context *ctx, pdf_dict *page_dict, * Sets ctx->page.has_transparency and ctx->page.num_spots * do_setup -- indicates whether to actually set up the device with the spot count. */ -int pdfi_check_page(pdf_context *ctx, pdf_dict *page_dict, bool do_setup) +int pdfi_check_page(pdf_context *ctx, pdf_dict *page_dict, pdf_array **fonts_array, pdf_array **spots_array, bool do_setup) { int code; int spots = 0; @@ -1145,7 +1370,7 @@ int pdfi_check_page(pdf_context *ctx, pdf_dict *page_dict, bool do_setup) * TODO: Should probably look into that.. */ pdfi_device_set_flags(ctx); - code = pdfi_check_init_tracker(ctx, &tracker); + code = pdfi_check_init_tracker(ctx, &tracker, fonts_array, spots_array); if (code < 0) goto exit; @@ -1191,7 +1416,7 @@ int pdfi_check_page(pdf_context *ctx, pdf_dict *page_dict, bool do_setup) code = pdfi_dict_first(ctx, tracker.spot_dict, (pdf_obj **)&Key, &Value, &index); while (code >= 0) { - if (Key->type == PDF_NAME) { + if (pdfi_type_of(Key) == PDF_NAME) { table[a].data = ((pdf_string *)Key)->data; table[a].size = ((pdf_string *)Key)->length; table[a++].persistent = false; @@ -1263,6 +1488,47 @@ int pdfi_check_page(pdf_context *ctx, pdf_dict *page_dict, bool do_setup) ctx->page.has_OP = false; exit: + if (fonts_array != NULL) { + *fonts_array = tracker.font_array; + pdfi_countup(*fonts_array); + } + + if (spots_array != NULL && tracker.spot_dict != NULL && pdfi_dict_entries(tracker.spot_dict) != 0) { + pdf_array *new_array = NULL; + pdf_name *Key = NULL; + pdf_obj *Value = NULL; + uint64_t index = 0, a_index = 0; + + index = pdfi_dict_entries(tracker.spot_dict); + + code = pdfi_array_alloc(ctx, index, &new_array); + if (code < 0) + goto error; + pdfi_countup(new_array); + + code = pdfi_dict_first(ctx, tracker.spot_dict, (pdf_obj **)&Key, &Value, &index); + while (code >= 0) + { + if (pdfi_type_of(Key) == PDF_NAME) { + code = pdfi_array_put(ctx, new_array, a_index++, (pdf_obj *)Key); + if (code < 0) { + pdfi_countdown(new_array); + pdfi_countdown(Key); + pdfi_countdown(Value); + goto error; + } + } + + pdfi_countdown(Key); + Key = NULL; + pdfi_countdown(Value); + Value = NULL; + code = pdfi_dict_next(ctx, tracker.spot_dict, (pdf_obj **)&Key, &Value, &index); + } + code = 0; + *spots_array = new_array; + } +error: (void)pdfi_check_free_tracker(ctx, &tracker); return code; } |