summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_page.c')
-rw-r--r--pdf/pdf_page.c304
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;