diff options
Diffstat (limited to 'pdf/pdf_page.c')
-rw-r--r-- | pdf/pdf_page.c | 304 |
1 files changed, 240 insertions, 64 deletions
diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c index f2389fea..b413b68d 100644 --- a/pdf/pdf_page.c +++ b/pdf/pdf_page.c @@ -56,7 +56,7 @@ static int pdfi_process_page_contents(pdf_context *ctx, pdf_dict *page_dict) if (code < 0) return code; - if (o->type == PDF_INDIRECT) { + if (pdfi_type_of(o) == PDF_INDIRECT) { if (((pdf_indirect_ref *)o)->ref_object_num == page_dict->object_num) return_error(gs_error_circular_reference); @@ -77,7 +77,7 @@ static int pdfi_process_page_contents(pdf_context *ctx, pdf_dict *page_dict) } ctx->encryption.decrypt_strings = false; - if (o->type == PDF_ARRAY) { + if (pdfi_type_of(o) == PDF_ARRAY) { pdf_array *a = (pdf_array *)o; for (i=0;i < pdfi_array_size(a); i++) { @@ -85,13 +85,13 @@ static int pdfi_process_page_contents(pdf_context *ctx, pdf_dict *page_dict) code = pdfi_array_get_no_deref(ctx, a, i, (pdf_obj **)&r); if (code < 0) goto page_error; - if (r->type == PDF_STREAM) { + if (pdfi_type_of (r) == PDF_STREAM) { code = pdfi_interpret_content_stream(ctx, NULL, (pdf_stream *)r, page_dict); pdfi_countdown(r); if (code < 0) goto page_error; } else { - if (r->type != PDF_INDIRECT) { + if (pdfi_type_of(r) != PDF_INDIRECT) { pdfi_countdown(r); code = gs_note_error(gs_error_typecheck); goto page_error; @@ -108,7 +108,7 @@ static int pdfi_process_page_contents(pdf_context *ctx, pdf_dict *page_dict) code = 0; goto page_error; } - if (o1->type != PDF_STREAM) { + if (pdfi_type_of(o1) != PDF_STREAM) { pdfi_countdown(o1); code = gs_note_error(gs_error_typecheck); goto page_error; @@ -123,7 +123,7 @@ static int pdfi_process_page_contents(pdf_context *ctx, pdf_dict *page_dict) } } } else { - if (o->type == PDF_STREAM) { + if (pdfi_type_of(o) == PDF_STREAM) { code = pdfi_interpret_content_stream(ctx, NULL, (pdf_stream *)o, page_dict); } else { pdfi_countdown(o); @@ -295,14 +295,23 @@ static int pdfi_set_media_size(pdf_context *ctx, pdf_dict *page_dict) if (a == NULL) { code = pdfi_dict_get_type(ctx, page_dict, "CropBox", PDF_ARRAY, (pdf_obj **)&a); if (code >= 0 && pdfi_array_size(a) >= 4) { + pdf_obj *box_obj = NULL; + for (i=0;i<4;i++) { - code = pdfi_array_get_number(ctx, a, i, &d_crop[i]); - d_crop[i] *= userunit; + code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj); + if (code >= 0) { + code = pdfi_obj_to_real(ctx, box_obj, &d_crop[i]); + pdfi_countdown(box_obj); + } + if (code < 0) + break; } pdfi_countdown(a); - normalize_rectangle(d_crop); - memcpy(ctx->page.Crop, d_crop, 4 * sizeof(double)); - do_crop = true; + if (code >= 0) { + normalize_rectangle(d_crop); + memcpy(ctx->page.Crop, d_crop, 4 * sizeof(double)); + do_crop = true; + } } a = default_media; } @@ -313,7 +322,20 @@ static int pdfi_set_media_size(pdf_context *ctx, pdf_dict *page_dict) ctx->page.UserUnit = userunit; for (i=0;i<4;i++) { - code = pdfi_array_get_number(ctx, a, i, &d[i]); + pdf_obj *box_obj = NULL; + + code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj); + if (code >= 0) { + code = pdfi_obj_to_real(ctx, box_obj, &d[i]); + pdfi_countdown(box_obj); + } + + if (code < 0) { + pdfi_countdown(a); + pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_MEDIABOX, "pdfi_get_media_size", NULL); + code = gs_erasepage(ctx->pgs); + return 0; + } d[i] *= userunit; } pdfi_countdown(a); @@ -458,26 +480,21 @@ static void pdfi_setup_transfers(pdf_context *ctx) } } -static int store_box(pdf_context *ctx, float *box, pdf_array *a) -{ - double f; - int code = 0, i; - - for (i=0;i < 4;i++) { - code = pdfi_array_get_number(ctx, a, (uint64_t)i, &f); - if (code < 0) - return code; - box[i] = (float)f; - } - return 0; -} - -int pdfi_page_info(pdf_context *ctx, uint64_t page_num, pdf_info_t *info) +/* Return a dictionary containing information about the page. Basic information is that + * required to render the page; if extended is true then additionally contains an + * array of spot ink names and an array of dictionaries each of which contains + * information about a font used on the page. THis is normally only used for tools + * like pdf_info.ps + */ +int pdfi_page_info(pdf_context *ctx, uint64_t page_num, pdf_dict **info, bool extended) { - int code = 0; - pdf_dict *page_dict = NULL; + int code = 0, i=0; + pdf_dict *page_dict = NULL, *info_dict = NULL; + pdf_array *fonts_array = NULL, *spots_array = NULL; pdf_array *a = NULL; - double dbl = 0.0; + pdf_obj *o = NULL; + bool known = false; + double dummy; code = pdfi_page_get_dict(ctx, page_num, &page_dict); if (code < 0) @@ -488,79 +505,202 @@ int pdfi_page_info(pdf_context *ctx, uint64_t page_num, pdf_info_t *info) goto done; } - code = pdfi_check_page(ctx, page_dict, false); + code = pdfi_dict_alloc(ctx, 6, &info_dict); if (code < 0) goto done; - info->boxes = BOX_NONE; + pdfi_countup(info_dict); + + if (extended) + code = pdfi_check_page(ctx, page_dict, &fonts_array, &spots_array, false); + else + code = pdfi_check_page(ctx, page_dict, NULL, NULL, false); + if (code < 0) + goto done; + + if (spots_array != NULL) { + code = pdfi_dict_put(ctx, info_dict, "Spots", (pdf_obj *)spots_array); + if (code < 0) + goto done; + pdfi_countdown(spots_array); + } + + if (fonts_array != NULL) { + code = pdfi_dict_put(ctx, info_dict, "Fonts", (pdf_obj *)fonts_array); + if (code < 0) + goto done; + pdfi_countdown(fonts_array); + } + code = pdfi_dict_get_type(ctx, page_dict, "MediaBox", PDF_ARRAY, (pdf_obj **)&a); if (code < 0) pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_MEDIABOX, "pdfi_page_info", NULL); if (code >= 0) { - code = store_box(ctx, (float *)&info->MediaBox, a); + pdf_obj *box_obj = NULL; + + for (i = 0;i < pdfi_array_size(a); i++) { + code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj); + if (code >= 0) { + code = pdfi_obj_to_real(ctx, box_obj, &dummy); + pdfi_countdown(box_obj); + } + if (code < 0) { + pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_MEDIABOX, "pdfi_page_info", NULL); + goto done; + } + } + + code = pdfi_dict_put(ctx, info_dict, "MediaBox", (pdf_obj *)a); if (code < 0) goto done; - info->boxes |= MEDIA_BOX; pdfi_countdown(a); a = NULL; } code = pdfi_dict_get_type(ctx, page_dict, "ArtBox", PDF_ARRAY, (pdf_obj **)&a); if (code >= 0) { - code = store_box(ctx, (float *)&info->ArtBox, a); - if (code < 0) - goto done; - info->boxes |= ART_BOX; + pdf_obj *box_obj = NULL; + + for (i = 0;i < pdfi_array_size(a); i++) { + code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj); + if (code >= 0) { + code = pdfi_obj_to_real(ctx, box_obj, &dummy); + pdfi_countdown(box_obj); + } + if (code < 0) + break; + } + if (code >= 0) { + code = pdfi_dict_put(ctx, info_dict, "ArtBox", (pdf_obj *)a); + if (code < 0) + goto done; + } pdfi_countdown(a); a = NULL; } code = pdfi_dict_get_type(ctx, page_dict, "CropBox", PDF_ARRAY, (pdf_obj **)&a); if (code >= 0) { - code = store_box(ctx, (float *)&info->CropBox, a); - if (code < 0) - goto done; - info->boxes |= CROP_BOX; + pdf_obj *box_obj = NULL; + + for (i = 0;i < pdfi_array_size(a); i++) { + code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj); + if (code >= 0) { + code = pdfi_obj_to_real(ctx, box_obj, &dummy); + pdfi_countdown(box_obj); + } + if (code < 0) + break; + } + if (code >= 0) { + code = pdfi_dict_put(ctx, info_dict, "CropBox", (pdf_obj *)a); + if (code < 0) + goto done; + } pdfi_countdown(a); a = NULL; } code = pdfi_dict_get_type(ctx, page_dict, "TrimBox", PDF_ARRAY, (pdf_obj **)&a); if (code >= 0) { - code = store_box(ctx, (float *)&info->TrimBox, a); - if (code < 0) - goto done; - info->boxes |= TRIM_BOX; + pdf_obj *box_obj = NULL; + + for (i = 0;i < pdfi_array_size(a); i++) { + code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj); + if (code >= 0) { + code = pdfi_obj_to_real(ctx, box_obj, &dummy); + pdfi_countdown(box_obj); + } + if (code < 0) + break; + } + if (code >= 0) { + code = pdfi_dict_put(ctx, info_dict, "TrimBox", (pdf_obj *)a); + if (code < 0) + goto done; + } pdfi_countdown(a); a = NULL; } code = pdfi_dict_get_type(ctx, page_dict, "BleedBox", PDF_ARRAY, (pdf_obj **)&a); if (code >= 0) { - code = store_box(ctx, (float *)&info->BleedBox, a); - if (code < 0) - goto done; - info->boxes |= BLEED_BOX; + pdf_obj *box_obj = NULL; + + for (i = 0;i < pdfi_array_size(a); i++) { + code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj); + if (code >= 0) { + code = pdfi_obj_to_real(ctx, box_obj, &dummy); + pdfi_countdown(box_obj); + } + if (code < 0) + break; + } + if (code >= 0) { + code = pdfi_dict_put(ctx, info_dict, "BleedBox", (pdf_obj *)a); + if (code < 0) + goto done; + } pdfi_countdown(a); a = NULL; } code = 0; - dbl = info->Rotate = 0; - code = pdfi_dict_get_number(ctx, page_dict, "Rotate", &dbl); - code = 0; - info->Rotate = dbl; + code = pdfi_dict_get(ctx, page_dict, "Rotate", &o); + if (code >= 0) { + if (pdfi_type_of(o) == PDF_INT || pdfi_type_of(o) == PDF_REAL) { + code = pdfi_dict_put(ctx, info_dict, "Rotate", o); + if (code < 0) + goto done; + } + pdfi_countdown(o); + } - dbl = info->UserUnit = 1; - code = pdfi_dict_get_number(ctx, page_dict, "UserUnit", &dbl); - code = 0; - info->UserUnit = dbl; + code = pdfi_dict_get(ctx, page_dict, "UserUnit", &o); + if (code >= 0) { + if (pdfi_type_of(o) == PDF_INT || pdfi_type_of(o) == PDF_REAL) { + code = pdfi_dict_put(ctx, info_dict, "UserUnit", o); + if (code < 0) + goto done; + } + pdfi_countdown(o); + } + + if (ctx->page.has_transparency) + code = pdfi_dict_put(ctx, info_dict, "UsesTransparency", PDF_TRUE_OBJ); + else + code = pdfi_dict_put(ctx, info_dict, "UsesTransparency", PDF_FALSE_OBJ); + if (code < 0) + goto done; + + code = pdfi_dict_known(ctx, page_dict, "Annots", &known); + if (code >= 0 && known) + code = pdfi_dict_put(ctx, info_dict, "Annots", PDF_TRUE_OBJ); + else + code = pdfi_dict_put(ctx, info_dict, "Annots", PDF_FALSE_OBJ); + if (code < 0) + goto done; - info->HasTransparency = ctx->page.has_transparency; - info->NumSpots = ctx->page.num_spots; + code = pdfi_object_alloc(ctx, PDF_INT, 0, &o); + if (code >= 0) { + pdfi_countup(o); + ((pdf_num *)o)->value.i = ctx->page.num_spots; + code = pdfi_dict_put(ctx, info_dict, "NumSpots", o); + pdfi_countdown(o); + o = NULL; + if (code < 0) + goto done; + } done: + if (code < 0) { + pdfi_countdown(info_dict); + info_dict = NULL; + *info = NULL; + } else + *info = info_dict; + pdfi_countdown(a); pdfi_countdown(page_dict); return code; @@ -585,7 +725,7 @@ int pdfi_page_get_dict(pdf_context *ctx, uint64_t page_num, pdf_dict **dict) code = pdfi_dict_get(ctx, ctx->Root, "Pages", &o); if (code < 0) goto page_error; - if (o->type != PDF_DICT) { + if (pdfi_type_of(o) != PDF_DICT) { code = gs_note_error(gs_error_typecheck); goto page_error; } @@ -663,14 +803,35 @@ int pdfi_page_get_number(pdf_context *ctx, pdf_dict *target_dict, uint64_t *page static void release_page_DefaultSpaces(pdf_context *ctx) { if (ctx->page.DefaultGray_cs != NULL) { + if (ctx->page.DefaultGray_cs->interpreter_data != NULL) { + pdf_obj *o = (pdf_obj *)(ctx->page.DefaultGray_cs->interpreter_data); + if (o != NULL && pdfi_type_of(o) == PDF_NAME) { + pdfi_countdown(o); + ctx->page.DefaultGray_cs->interpreter_data = NULL; + } + } rc_decrement(ctx->page.DefaultGray_cs, "pdfi_page_render"); ctx->page.DefaultGray_cs = NULL; } if (ctx->page.DefaultRGB_cs != NULL) { + if (ctx->page.DefaultRGB_cs->interpreter_data != NULL) { + pdf_obj *o = (pdf_obj *)(ctx->page.DefaultRGB_cs->interpreter_data); + if (o != NULL && pdfi_type_of(o) == PDF_NAME) { + pdfi_countdown(o); + ctx->page.DefaultRGB_cs->interpreter_data = NULL; + } + } rc_decrement(ctx->page.DefaultRGB_cs, "pdfi_page_render"); ctx->page.DefaultRGB_cs = NULL; } if (ctx->page.DefaultCMYK_cs != NULL) { + if (ctx->page.DefaultCMYK_cs->interpreter_data != NULL) { + pdf_obj *o = (pdf_obj *)(ctx->page.DefaultCMYK_cs->interpreter_data); + if (o != NULL && pdfi_type_of(o) == PDF_NAME) { + pdfi_countdown(o); + ctx->page.DefaultCMYK_cs->interpreter_data = NULL; + } + } rc_decrement(ctx->page.DefaultCMYK_cs, "pdfi_page_render"); ctx->page.DefaultCMYK_cs = NULL; } @@ -684,6 +845,12 @@ static int setup_page_DefaultSpaces(pdf_context *ctx, pdf_dict *page_dict) return(pdfi_setup_DefaultSpaces(ctx, page_dict)); } +static bool +pdfi_pattern_purge_all_proc(gx_color_tile * ctile, void *proc_data) +{ + return true; +} + int pdfi_page_render(pdf_context *ctx, uint64_t page_num, bool init_graphics) { int code, code1=0; @@ -714,7 +881,7 @@ int pdfi_page_render(pdf_context *ctx, uint64_t page_num, bool init_graphics) pdfi_device_set_flags(ctx); - code = pdfi_check_page(ctx, page_dict, init_graphics); + code = pdfi_check_page(ctx, page_dict, NULL, NULL, init_graphics); if (code < 0) goto exit3; @@ -729,8 +896,12 @@ int pdfi_page_render(pdf_context *ctx, uint64_t page_num, bool init_graphics) } code = pdfi_dict_knownget_type(ctx, page_dict, "Group", PDF_DICT, (pdf_obj **)&group_dict); + /* Ignore errors retrieving the Group dictionary, we will just ignore it. This allows us + * to handle files such as Bug #705206 where the Group dictionary is a free object in a + * compressed object stream. + */ if (code < 0) - goto exit3; + pdfi_set_error(ctx, 0, NULL, E_BAD_GROUP_DICT, "pdfi_page_render", NULL); if (group_dict != NULL) page_group_known = true; @@ -864,7 +1035,12 @@ exit3: release_page_DefaultSpaces(ctx); - if (code == 0 || (!ctx->args.pdfstoponerror && code != gs_error_stackoverflow)) + /* Flush any pattern tiles. We don't want to (potentially) return to PostScript + * with any pattern tiles referencing our objects, in case the garbager runs. + */ + gx_pattern_cache_winnow(gstate_pattern_cache(ctx->pgs), pdfi_pattern_purge_all_proc, NULL); + + if (code == 0 || (!ctx->args.pdfstoponerror && code != gs_error_pdf_stackoverflow)) if (!page_dict_error && ctx->finish_page != NULL) code = ctx->finish_page(ctx); return code; |