From f0eabc17d6ec113c6e765ac3272f19623a6cbd4e Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 6 Jul 2016 13:15:49 +0200 Subject: Start slimming pdf_page. We want to turn pdf_page into a thin wrapper around a pdf_obj, so that any updates to the underlying PDF objects will be reflected without having to reload the pdf_page. --- include/mupdf/fitz/document.h | 14 +- include/mupdf/pdf/annot.h | 5 +- include/mupdf/pdf/page.h | 21 ++- platform/x11/pdfapp.c | 5 +- source/fitz/document.c | 4 +- source/pdf/pdf-annot-edit.c | 40 +++--- source/pdf/pdf-annot.c | 13 +- source/pdf/pdf-appearance.c | 29 ++--- source/pdf/pdf-clean-file.c | 2 +- source/pdf/pdf-clean.c | 63 ++++----- source/pdf/pdf-interpret.c | 2 +- source/pdf/pdf-page.c | 294 +++++++++++++++++++++--------------------- source/pdf/pdf-run.c | 23 ++-- source/pdf/pdf-xref.c | 9 -- source/tools/pdfmerge.c | 2 +- source/tools/pdfposter.c | 24 ++-- 16 files changed, 269 insertions(+), 281 deletions(-) diff --git a/include/mupdf/fitz/document.h b/include/mupdf/fitz/document.h index 1f3f474d..889b66b1 100644 --- a/include/mupdf/fitz/document.h +++ b/include/mupdf/fitz/document.h @@ -40,7 +40,7 @@ typedef fz_link *(fz_page_load_links_fn)(fz_context *ctx, fz_page *page); typedef fz_rect *(fz_page_bound_page_fn)(fz_context *ctx, fz_page *page, fz_rect *); typedef void (fz_page_run_page_contents_fn)(fz_context *ctx, fz_page *page, fz_device *dev, const fz_matrix *transform, fz_cookie *cookie); typedef void (fz_page_drop_page_imp_fn)(fz_context *ctx, fz_page *page); -typedef fz_transition *(fz_page_page_presentation_fn)(fz_context *ctx, fz_page *page, float *duration); +typedef fz_transition *(fz_page_page_presentation_fn)(fz_context *ctx, fz_page *page, fz_transition *transition, float *duration); typedef fz_annot *(fz_page_first_annot_fn)(fz_context *ctx, fz_page *page); @@ -334,15 +334,15 @@ void *fz_new_annot(fz_context *ctx, int size); /* fz_page_presentation: Get the presentation details for a given page. - duration: NULL, or a pointer to a place to set the page duration in - seconds. (Will be set to 0 if unspecified). + transition: A pointer to a transition struct to fill out. - Returns: a pointer to a transition structure, or NULL if there isn't - one. + duration: A pointer to a place to set the page duration in seconds. + Will be set to 0 if no transition is specified for the page. - Does not throw exceptions. + Returns: a pointer to a the transition structure, or NULL if there is no + transition specified for the page. */ -fz_transition *fz_page_presentation(fz_context *ctx, fz_page *page, float *duration); +fz_transition *fz_page_presentation(fz_context *ctx, fz_page *page, fz_transition *transition, float *duration); /* fz_has_permission: Check permission flags on document. diff --git a/include/mupdf/pdf/annot.h b/include/mupdf/pdf/annot.h index ed18aae1..e6ea5b8d 100644 --- a/include/mupdf/pdf/annot.h +++ b/include/mupdf/pdf/annot.h @@ -59,6 +59,7 @@ struct pdf_annot_s { fz_annot super; pdf_page *page; + fz_matrix page_ctm, inv_page_ctm; pdf_obj *obj; fz_rect rect; fz_rect pagerect; @@ -81,7 +82,7 @@ pdf_obj *pdf_load_name_tree(fz_context *ctx, pdf_document *doc, pdf_obj *which); fz_link *pdf_load_link_annots(fz_context *ctx, pdf_document *, pdf_obj *annots, const fz_matrix *page_ctm); void pdf_transform_annot(fz_context *ctx, pdf_annot *annot); -void pdf_load_annots(fz_context *ctx, pdf_document *, pdf_page *page, pdf_obj *annots); +void pdf_load_annots(fz_context *ctx, pdf_document *, pdf_page *page, pdf_obj *annots, const fz_matrix *page_transform); void pdf_update_annot(fz_context *ctx, pdf_document *, pdf_annot *annot); void pdf_drop_annots(fz_context *ctx, pdf_annot *annot_list); @@ -155,6 +156,6 @@ pdf_annot *pdf_poll_changed_annot(fz_context *ctx, pdf_document *idoc, pdf_page /* pdf_new_annot: Internal function for creating a new pdf annotation. */ -pdf_annot *pdf_new_annot(fz_context *ctx, pdf_page *page); +pdf_annot *pdf_new_annot(fz_context *ctx, pdf_page *page, const fz_matrix *page_ctm, const fz_matrix *inv_page_ctm); #endif diff --git a/include/mupdf/pdf/page.h b/include/mupdf/pdf/page.h index 43634d46..e3efb1e7 100644 --- a/include/mupdf/pdf/page.h +++ b/include/mupdf/pdf/page.h @@ -19,7 +19,7 @@ int pdf_lookup_anchor(fz_context *ctx, pdf_document *doc, const char *name); Copy any inheritable page keys into the actual page object, removing any dependencies on the page tree parents. */ -void pdf_flatten_inheritable_page_items(fz_context *ctx, pdf_document *doc, pdf_obj *page); +void pdf_flatten_inheritable_page_items(fz_context *ctx, pdf_obj *page); /* pdf_load_page: Load a page and its resources. @@ -32,9 +32,12 @@ void pdf_flatten_inheritable_page_items(fz_context *ctx, pdf_document *doc, pdf_ number: page number, where 0 is the first page of the document. */ pdf_page *pdf_load_page(fz_context *ctx, pdf_document *doc, int number); - void pdf_drop_page(fz_context *ctx, pdf_page *page); +void pdf_page_transform(fz_context *ctx, pdf_page *page, fz_rect *mediabox, fz_matrix *ctm); +pdf_obj *pdf_page_resources(fz_context *ctx, pdf_page *page); +pdf_obj *pdf_page_contents(fz_context *ctx, pdf_page *page); + fz_link *pdf_load_links(fz_context *ctx, pdf_page *page); /* @@ -159,7 +162,7 @@ void pdf_clean_annot_contents(fz_context *ctx, pdf_document *doc, pdf_annot *ann /* Presentation interface. */ -fz_transition *pdf_page_presentation(fz_context *ctx, pdf_page *page, float *duration); +fz_transition *pdf_page_presentation(fz_context *ctx, pdf_page *page, fz_transition *transition, float *duration); /* * Page tree, pages and related objects @@ -169,23 +172,17 @@ struct pdf_page_s { fz_page super; pdf_document *doc; + pdf_obj *obj; - fz_matrix ctm; /* calculated from mediabox and rotate */ - fz_rect mediabox; - int rotate; int transparency; - pdf_obj *resources; - pdf_obj *contents; + fz_link *links; pdf_annot *annots; pdf_annot **annot_tailp; pdf_annot *changed_annots; pdf_annot *deleted_annots; pdf_annot *tmp_annots; - pdf_obj *me; - float duration; - int transition_present; - fz_transition transition; + int incomplete; }; diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c index 532c217b..c3231995 100644 --- a/platform/x11/pdfapp.c +++ b/platform/x11/pdfapp.c @@ -907,7 +907,6 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai if (transition) { - fz_transition *new_trans; app->new_image = app->image; app->image = NULL; if (app->grayscale) @@ -916,9 +915,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai colorspace = app->colorspace; app->image = fz_new_pixmap_with_bbox(app->ctx, colorspace, &ibounds, app->image->alpha); app->duration = 0; - new_trans = fz_page_presentation(app->ctx, app->page, &app->duration); - if (new_trans) - app->transition = *new_trans; + fz_page_presentation(app->ctx, app->page, &app->transition, &app->duration); if (app->duration == 0) app->duration = 5; app->in_transit = fz_generate_transition(app->ctx, app->image, app->old_image, app->new_image, 0, &app->transition); diff --git a/source/fitz/document.c b/source/fitz/document.c index 5c913012..02c30459 100644 --- a/source/fitz/document.c +++ b/source/fitz/document.c @@ -398,7 +398,7 @@ fz_drop_page(fz_context *ctx, fz_page *page) } fz_transition * -fz_page_presentation(fz_context *ctx, fz_page *page, float *duration) +fz_page_presentation(fz_context *ctx, fz_page *page, fz_transition *transition, float *duration) { float dummy; if (duration) @@ -406,7 +406,7 @@ fz_page_presentation(fz_context *ctx, fz_page *page, float *duration) else duration = &dummy; if (page && page->page_presentation && page) - return page->page_presentation(ctx, page, duration); + return page->page_presentation(ctx, page, transition, duration); return NULL; } diff --git a/source/pdf/pdf-annot-edit.c b/source/pdf/pdf-annot-edit.c index e09a6129..4aa856b0 100644 --- a/source/pdf/pdf-annot-edit.c +++ b/source/pdf/pdf-annot-edit.c @@ -92,6 +92,8 @@ pdf_create_annot(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_annot_ty pdf_annot *annot = NULL; pdf_obj *annot_obj = pdf_new_dict(ctx, doc, 0); pdf_obj *ind_obj = NULL; + fz_rect mediabox; + fz_matrix page_ctm, inv_page_ctm; fz_var(annot); fz_var(ind_obj); @@ -100,11 +102,11 @@ pdf_create_annot(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_annot_ty int ind_obj_num; fz_rect rect = {0.0, 0.0, 0.0, 0.0}; const char *type_str = annot_type_str(type); - pdf_obj *annot_arr = pdf_dict_get(ctx, page->me, PDF_NAME_Annots); + pdf_obj *annot_arr = pdf_dict_get(ctx, page->obj, PDF_NAME_Annots); if (annot_arr == NULL) { annot_arr = pdf_new_array(ctx, doc, 0); - pdf_dict_put_drop(ctx, page->me, PDF_NAME_Annots, annot_arr); + pdf_dict_put_drop(ctx, page->obj, PDF_NAME_Annots, annot_arr); } pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Type, PDF_NAME_Annot); @@ -115,7 +117,10 @@ pdf_create_annot(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_annot_ty /* Make printable as default */ pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_F, pdf_new_int(ctx, doc, F_Print)); - annot = pdf_new_annot(ctx, page); + pdf_page_transform(ctx, page, &mediabox, &page_ctm); + fz_invert_matrix(&inv_page_ctm, &page_ctm); + + annot = pdf_new_annot(ctx, page, &page_ctm, &inv_page_ctm); annot->rect = rect; annot->pagerect = rect; annot->ap = NULL; @@ -191,7 +196,7 @@ pdf_delete_annot(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_annot * annot->ap = NULL; /* Recreate the "Annots" array with this annot removed */ - old_annot_arr = pdf_dict_get(ctx, page->me, PDF_NAME_Annots); + old_annot_arr = pdf_dict_get(ctx, page->obj, PDF_NAME_Annots); if (old_annot_arr) { @@ -211,7 +216,7 @@ pdf_delete_annot(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_annot * if (pdf_is_indirect(ctx, old_annot_arr)) pdf_update_object(ctx, doc, pdf_to_num(ctx, old_annot_arr), annot_arr); else - pdf_dict_put(ctx, page->me, PDF_NAME_Annots, annot_arr); + pdf_dict_put(ctx, page->obj, PDF_NAME_Annots, annot_arr); if (pdf_is_indirect(ctx, annot->obj)) pdf_delete_object(ctx, doc, pdf_to_num(ctx, annot->obj)); @@ -234,12 +239,9 @@ pdf_delete_annot(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_annot * void pdf_set_markup_annot_quadpoints(fz_context *ctx, pdf_document *doc, pdf_annot *annot, fz_point *qp, int n) { - fz_matrix ctm; pdf_obj *arr = pdf_new_array(ctx, doc, n*2); int i; - fz_invert_matrix(&ctm, &annot->page->ctm); - pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_QuadPoints, arr); for (i = 0; i < n; i++) @@ -247,7 +249,7 @@ pdf_set_markup_annot_quadpoints(fz_context *ctx, pdf_document *doc, pdf_annot *a fz_point pt = qp[i]; pdf_obj *r; - fz_transform_point(&pt, &ctm); + fz_transform_point(&pt, &annot->inv_page_ctm); r = pdf_new_real(ctx, doc, pt.x); pdf_array_push_drop(ctx, arr, r); r = pdf_new_real(ctx, doc, pt.y); @@ -259,20 +261,17 @@ static void update_rect(fz_context *ctx, pdf_annot *annot) { pdf_to_rect(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME_Rect), &annot->rect); annot->pagerect = annot->rect; - fz_transform_rect(&annot->pagerect, &annot->page->ctm); + fz_transform_rect(&annot->pagerect, &annot->page_ctm); } void pdf_set_ink_annot_list(fz_context *ctx, pdf_document *doc, pdf_annot *annot, fz_point *pts, int *counts, int ncount, float color[3], float thickness) { - fz_matrix ctm; pdf_obj *list = pdf_new_array(ctx, doc, ncount); pdf_obj *bs, *col; fz_rect rect; int i, k = 0; - fz_invert_matrix(&ctm, &annot->page->ctm); - pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_InkList, list); for (i = 0; i < ncount; i++) @@ -286,7 +285,7 @@ pdf_set_ink_annot_list(fz_context *ctx, pdf_document *doc, pdf_annot *annot, fz_ { fz_point pt = pts[k]; - fz_transform_point(&pt, &ctm); + fz_transform_point(&pt, &annot->inv_page_ctm); if (i == 0 && j == 0) { @@ -346,16 +345,14 @@ static void find_free_font_name(fz_context *ctx, pdf_obj *fdict, char *buf, int void pdf_set_text_annot_position(fz_context *ctx, pdf_document *doc, pdf_annot *annot, fz_point pt) { - fz_matrix ctm; fz_rect rect; int flags; - fz_invert_matrix(&ctm, &annot->page->ctm); rect.x0 = pt.x; rect.x1 = pt.x + TEXT_ANNOT_SIZE; rect.y0 = pt.y; rect.y1 = pt.y + TEXT_ANNOT_SIZE; - fz_transform_rect(&rect, &ctm); + fz_transform_rect(&rect, &annot->inv_page_ctm); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect)); @@ -401,16 +398,13 @@ void pdf_set_free_text_details(fz_context *ctx, pdf_document *doc, pdf_annot *an pdf_font_desc *font_desc = NULL; pdf_da_info da_info; fz_buffer *fzbuf = NULL; - fz_matrix ctm; fz_point page_pos; - fz_invert_matrix(&ctm, &annot->page->ctm); - - dr = pdf_dict_get(ctx, annot->page->me, PDF_NAME_Resources); + dr = pdf_dict_get(ctx, annot->page->obj, PDF_NAME_Resources); if (!dr) { dr = pdf_new_dict(ctx, doc, 1); - pdf_dict_put_drop(ctx, annot->page->me, PDF_NAME_Resources, dr); + pdf_dict_put_drop(ctx, annot->page->obj, PDF_NAME_Resources, dr); } /* Ensure the resource dictionary includes a font dict */ @@ -459,7 +453,7 @@ void pdf_set_free_text_details(fz_context *ctx, pdf_document *doc, pdf_annot *an pdf_measure_text(ctx, font_desc, (unsigned char *)text, strlen(text), &bounds); page_pos = *pos; - fz_transform_point(&page_pos, &ctm); + fz_transform_point(&page_pos, &annot->inv_page_ctm); bounds.x0 *= font_size; bounds.x1 *= font_size; diff --git a/source/pdf/pdf-annot.c b/source/pdf/pdf-annot.c index a81108dc..830e2091 100644 --- a/source/pdf/pdf-annot.c +++ b/source/pdf/pdf-annot.c @@ -481,7 +481,7 @@ fz_annot_type pdf_annot_obj_type(fz_context *ctx, pdf_obj *obj) return -1; } -pdf_annot *pdf_new_annot(fz_context *ctx, pdf_page *page) +pdf_annot *pdf_new_annot(fz_context *ctx, pdf_page *page, const fz_matrix *page_ctm, const fz_matrix *inv_page_ctm) { pdf_annot *annot = fz_new_annot(ctx, sizeof(pdf_annot)); @@ -491,21 +491,26 @@ pdf_annot *pdf_new_annot(fz_context *ctx, pdf_page *page) annot->super.next_annot = (fz_annot_next_fn*)pdf_next_annot; annot->page = page; + annot->page_ctm = *page_ctm; + annot->inv_page_ctm = *inv_page_ctm; return annot; } void -pdf_load_annots(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_obj *annots) +pdf_load_annots(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_obj *annots, const fz_matrix *page_ctm) { pdf_annot *annot, **itr; pdf_obj *obj, *ap, *as, *n, *rect; int i, len, keep_annot; + fz_matrix inv_page_ctm; fz_var(annot); fz_var(itr); fz_var(keep_annot); + fz_invert_matrix(&inv_page_ctm, page_ctm); + itr = &page->annots; len = pdf_array_len(ctx, annots); @@ -521,7 +526,7 @@ pdf_load_annots(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_obj *ann { obj = pdf_array_get(ctx, annots, i); - annot = pdf_new_annot(ctx, page); + annot = pdf_new_annot(ctx, page, page_ctm, &inv_page_ctm); *itr = annot; annot->obj = pdf_keep_obj(ctx, obj); itr = &annot->next; @@ -578,7 +583,7 @@ pdf_load_annots(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_obj *ann pdf_to_rect(ctx, rect, &annot->rect); annot->pagerect = annot->rect; - fz_transform_rect(&annot->pagerect, &page->ctm); + fz_transform_rect(&annot->pagerect, page_ctm); annot->ap = NULL; annot->annot_type = pdf_annot_obj_type(ctx, obj); annot->widget_type = annot->annot_type == FZ_ANNOT_WIDGET ? pdf_field_type(ctx, doc, obj) : PDF_WIDGET_TYPE_NOT_WIDGET; diff --git a/source/pdf/pdf-appearance.c b/source/pdf/pdf-appearance.c index 029b131d..234949b4 100644 --- a/source/pdf/pdf-appearance.c +++ b/source/pdf/pdf-appearance.c @@ -1568,30 +1568,25 @@ static void update_rect(fz_context *ctx, pdf_annot *annot) { pdf_to_rect(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME_Rect), &annot->rect); annot->pagerect = annot->rect; - fz_transform_rect(&annot->pagerect, &annot->page->ctm); + fz_transform_rect(&annot->pagerect, &annot->page_ctm); } void pdf_set_annot_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *annot, fz_rect *rect, fz_display_list *disp_list) { pdf_obj *obj = annot->obj; - const fz_matrix *page_ctm = &annot->page->ctm; - fz_matrix ctm; - fz_matrix mat = fz_identity; fz_device *dev = NULL; pdf_xobject *xobj = NULL; pdf_obj *resources; fz_buffer *contents; - fz_invert_matrix(&ctm, page_ctm); - fz_var(dev); fz_try(ctx) { pdf_obj *ap_obj; fz_rect trect = *rect; - fz_transform_rect(&trect, &ctm); + fz_transform_rect(&trect, &annot->inv_page_ctm); pdf_dict_put_drop(ctx, obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &trect)); @@ -1602,7 +1597,7 @@ void pdf_set_annot_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *ann if (ap_obj == NULL) { - ap_obj = pdf_new_xobject(ctx, doc, &trect, &mat); + ap_obj = pdf_new_xobject(ctx, doc, &trect, &fz_identity); pdf_dict_putl_drop(ctx, obj, ap_obj, PDF_NAME_AP, PDF_NAME_N, NULL); } else @@ -1610,7 +1605,7 @@ void pdf_set_annot_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *ann pdf_xref_ensure_incremental_object(ctx, doc, pdf_to_num(ctx, ap_obj)); /* Update bounding box and matrix in reused xobject obj */ pdf_dict_put_drop(ctx, ap_obj, PDF_NAME_BBox, pdf_new_rect(ctx, doc, &trect)); - pdf_dict_put_drop(ctx, ap_obj, PDF_NAME_Matrix, pdf_new_matrix(ctx, doc, &mat)); + pdf_dict_put_drop(ctx, ap_obj, PDF_NAME_Matrix, pdf_new_matrix(ctx, doc, &fz_identity)); } resources = pdf_dict_get(ctx, ap_obj, PDF_NAME_Resources); @@ -1618,7 +1613,7 @@ void pdf_set_annot_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *ann contents = fz_new_buffer(ctx, 0); dev = pdf_new_pdf_device(ctx, doc, &fz_identity, &trect, resources, contents); - fz_run_display_list(ctx, disp_list, dev, &ctm, &fz_infinite_rect, NULL); + fz_run_display_list(ctx, disp_list, dev, &annot->inv_page_ctm, &fz_infinite_rect, NULL); fz_drop_device(ctx, dev); pdf_update_stream(ctx, doc, ap_obj, contents, 0); @@ -1630,7 +1625,7 @@ void pdf_set_annot_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *ann { /* Update bounding box and matrix also in the xobject structure */ xobj->bbox = trect; - xobj->matrix = mat; + xobj->matrix = fz_identity; xobj->iteration++; pdf_drop_xobject(ctx, xobj); } @@ -1685,7 +1680,7 @@ quadpoints(fz_context *ctx, pdf_document *doc, pdf_obj *annot, int *nout) void pdf_set_markup_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *annot, float color[3], float alpha, float line_thickness, float line_height) { - const fz_matrix *page_ctm = &annot->page->ctm; + const fz_matrix *page_ctm = &annot->page_ctm; fz_path *path = NULL; fz_stroke_state *stroke = NULL; fz_device *dev = NULL; @@ -1793,7 +1788,7 @@ static fz_colorspace *pdf_to_color(fz_context *ctx, pdf_document *doc, pdf_obj * void pdf_update_ink_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *annot) { - const fz_matrix *page_ctm = &annot->page->ctm; + const fz_matrix *page_ctm = &annot->page_ctm; fz_path *path = NULL; fz_stroke_state *stroke = NULL; fz_device *dev = NULL; @@ -2090,7 +2085,7 @@ void pdf_update_text_annot_appearance(fz_context *ctx, pdf_document *doc, pdf_an static float yellow[3] = {1.0, 1.0, 0.0}; static float black[3] = {0.0, 0.0, 0.0}; - const fz_matrix *page_ctm = &annot->page->ctm; + const fz_matrix *page_ctm = &annot->page_ctm; fz_display_list *dlist = NULL; fz_device *dev = NULL; fz_colorspace *cs = NULL; @@ -2156,9 +2151,9 @@ void pdf_update_text_annot_appearance(fz_context *ctx, pdf_document *doc, pdf_an void pdf_update_free_text_annot_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *annot) { - const fz_matrix *page_ctm = &annot->page->ctm; + const fz_matrix *page_ctm = &annot->page_ctm; pdf_obj *obj = annot->obj; - pdf_obj *dr = pdf_dict_get(ctx, annot->page->me, PDF_NAME_Resources); + pdf_obj *dr = pdf_dict_get(ctx, annot->page->obj, PDF_NAME_Resources); fz_display_list *dlist = NULL; fz_device *dev = NULL; font_info font_rec; @@ -2340,7 +2335,7 @@ static float logo_color[3] = {(float)0x25/(float)0xFF, (float)0x72/(float)0xFF, void pdf_set_signature_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *annot, char *name, char *dn, char *date) { - const fz_matrix *page_ctm = &annot->page->ctm; + const fz_matrix *page_ctm = &annot->page_ctm; pdf_obj *obj = annot->obj; pdf_obj *dr = pdf_dict_getl(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root, PDF_NAME_AcroForm, PDF_NAME_DR, NULL); fz_display_list *dlist = NULL; diff --git a/source/pdf/pdf-clean-file.c b/source/pdf/pdf-clean-file.c index 0464e8cc..b261aa91 100644 --- a/source/pdf/pdf-clean-file.c +++ b/source/pdf/pdf-clean-file.c @@ -29,7 +29,7 @@ static void retainpage(fz_context *ctx, pdf_document *doc, pdf_obj *parent, pdf_ { pdf_obj *pageref = pdf_lookup_page_obj(ctx, doc, page-1); - pdf_flatten_inheritable_page_items(ctx, doc, pageref); + pdf_flatten_inheritable_page_items(ctx, pageref); pdf_dict_put(ctx, pageref, PDF_NAME_Parent, parent); diff --git a/source/pdf/pdf-clean.c b/source/pdf/pdf-clean.c index d09cc4f7..ff54e6e7 100644 --- a/source/pdf/pdf-clean.c +++ b/source/pdf/pdf-clean.c @@ -132,16 +132,17 @@ void pdf_clean_page_contents(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_processor *proc_filter = NULL; pdf_obj *new_obj = NULL; pdf_obj *new_ref = NULL; + pdf_obj *res_ref = NULL; pdf_obj *res = NULL; - pdf_obj *ref = NULL; pdf_obj *obj; pdf_obj *contents; + pdf_obj *resources; fz_buffer *buffer; fz_var(new_obj); fz_var(new_ref); fz_var(res); - fz_var(ref); + fz_var(res_ref); fz_var(proc_buffer); fz_var(proc_filter); @@ -151,20 +152,23 @@ void pdf_clean_page_contents(fz_context *ctx, pdf_document *doc, pdf_page *page, { res = pdf_new_dict(ctx, doc, 1); + contents = pdf_page_contents(ctx, page); + resources = pdf_page_resources(ctx, page); + proc_buffer = pdf_new_buffer_processor(ctx, buffer, ascii); - proc_filter = pdf_new_filter_processor(ctx, proc_buffer, doc, page->resources, res); + proc_filter = pdf_new_filter_processor(ctx, proc_buffer, doc, resources, res); - pdf_process_contents(ctx, proc_filter, doc, page->resources, page->contents, cookie); + pdf_process_contents(ctx, proc_filter, doc, resources, contents, cookie); + + /* Deal with page content stream. */ - contents = page->contents; if (pdf_is_array(ctx, contents)) { /* create a new object to replace the array */ new_obj = pdf_new_dict(ctx, doc, 1); new_ref = pdf_add_object(ctx, doc, new_obj); - pdf_drop_obj(ctx, page->contents); - page->contents = contents = pdf_keep_obj(ctx, new_ref); - pdf_dict_put(ctx, page->me, PDF_NAME_Contents, contents); + contents = new_ref; + pdf_dict_put(ctx, page->obj, PDF_NAME_Contents, contents); } else { @@ -172,6 +176,8 @@ void pdf_clean_page_contents(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_dict_del(ctx, contents, PDF_NAME_DecodeParms); } + pdf_update_stream(ctx, doc, contents, buffer, 0); + /* Now deal with resources. The spec allows for Type3 fonts and form * XObjects to omit a resource dictionary and look in the parent. * Avoid that by flattening here as part of the cleaning. This could @@ -187,55 +193,45 @@ void pdf_clean_page_contents(fz_context *ctx, pdf_document *doc, pdf_page *page, for (i = 0; i < l; i++) { pdf_obj *o = pdf_dict_get(ctx, pdf_dict_get_val(ctx, obj, i), PDF_NAME_SMask); - if (!o) continue; o = pdf_dict_get(ctx, o, PDF_NAME_G); if (!o) continue; - /* Transparency group XObject */ - pdf_clean_stream_object(ctx, doc, o, page->resources, cookie, 1, ascii); + pdf_clean_stream_object(ctx, doc, o, resources, cookie, 1, ascii); } } - /* ColorSpace - no cleaning possible */ - /* Pattern */ obj = pdf_dict_get(ctx, res, PDF_NAME_Pattern); if (obj) { int i, l; - l = pdf_dict_len(ctx, obj); for (i = 0; i < l; i++) { pdf_obj *pat = pdf_dict_get_val(ctx, obj, i); - if (!pat) continue; if (pdf_to_int(ctx, pdf_dict_get(ctx, pat, PDF_NAME_PatternType)) == 1) - pdf_clean_stream_object(ctx, doc, pat, page->resources, cookie, 0, ascii); + pdf_clean_stream_object(ctx, doc, pat, resources, cookie, 0, ascii); } } - /* Shading - no cleaning possible */ - /* XObject */ obj = pdf_dict_get(ctx, res, PDF_NAME_XObject); if (obj) { int i, l; - l = pdf_dict_len(ctx, obj); for (i = 0; i < l; i++) { pdf_obj *xobj = pdf_dict_get_val(ctx, obj, i); - - if (!pdf_name_eq(ctx, PDF_NAME_Form, pdf_dict_get(ctx, xobj, PDF_NAME_Subtype))) + if (!xobj) continue; - - pdf_clean_stream_object(ctx, doc, xobj, page->resources, cookie, 1, ascii); + if (pdf_name_eq(ctx, PDF_NAME_Form, pdf_dict_get(ctx, xobj, PDF_NAME_Subtype))) + pdf_clean_stream_object(ctx, doc, xobj, resources, cookie, 1, ascii); } } @@ -244,34 +240,31 @@ void pdf_clean_page_contents(fz_context *ctx, pdf_document *doc, pdf_page *page, if (obj) { int i, l; - l = pdf_dict_len(ctx, obj); for (i = 0; i < l; i++) { pdf_obj *o = pdf_dict_get_val(ctx, obj, i); - + if (!o) + continue; if (pdf_name_eq(ctx, PDF_NAME_Type3, pdf_dict_get(ctx, o, PDF_NAME_Subtype))) - { - pdf_clean_type3(ctx, doc, o, page->resources, cookie, ascii); - } + pdf_clean_type3(ctx, doc, o, resources, cookie, ascii); } } /* ProcSet - no cleaning possible. Inherit this from the old dict. */ - obj = pdf_dict_get(ctx, page->resources, PDF_NAME_ProcSet); + obj = pdf_dict_get(ctx, resources, PDF_NAME_ProcSet); if (obj) pdf_dict_put(ctx, res, PDF_NAME_ProcSet, obj); + /* ColorSpace - no cleaning possible. */ /* Properties - no cleaning possible. */ if (proc_fn) (*proc_fn)(ctx, buffer, res, proc_arg); - pdf_update_stream(ctx, doc, contents, buffer, 0); - pdf_drop_obj(ctx, page->resources); - ref = pdf_add_object(ctx, doc, res); - page->resources = pdf_keep_obj(ctx, ref); - pdf_dict_put(ctx, page->me, PDF_NAME_Resources, ref); + /* Update resource dictionary */ + res_ref = pdf_add_object(ctx, doc, res); + pdf_dict_put(ctx, page->obj, PDF_NAME_Resources, res_ref); } fz_always(ctx) { @@ -280,8 +273,8 @@ void pdf_clean_page_contents(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_drop_buffer(ctx, buffer); pdf_drop_obj(ctx, new_obj); pdf_drop_obj(ctx, new_ref); + pdf_drop_obj(ctx, res_ref); pdf_drop_obj(ctx, res); - pdf_drop_obj(ctx, ref); } fz_catch(ctx) { diff --git a/source/pdf/pdf-interpret.c b/source/pdf/pdf-interpret.c index af5a0ed5..f3b875cd 100644 --- a/source/pdf/pdf-interpret.c +++ b/source/pdf/pdf-interpret.c @@ -1256,7 +1256,7 @@ pdf_process_annot(fz_context *ctx, pdf_processor *proc, pdf_document *doc, pdf_p proc->op_cm(ctx, proc, annot->matrix.a, annot->matrix.b, annot->matrix.c, annot->matrix.d, annot->matrix.e, annot->matrix.f); - proc->op_Do_form(ctx, proc, NULL, annot->ap, page->resources); + proc->op_Do_form(ctx, proc, NULL, annot->ap, pdf_page_resources(ctx, page)); proc->op_Q(ctx, proc); } } diff --git a/source/pdf/pdf-page.c b/source/pdf/pdf-page.c index 430c033b..6a88412d 100644 --- a/source/pdf/pdf-page.c +++ b/source/pdf/pdf-page.c @@ -219,7 +219,7 @@ pdf_lookup_anchor(fz_context *ctx, pdf_document *doc, const char *name) } static pdf_obj * -pdf_lookup_inherited_page_item(fz_context *ctx, pdf_document *doc, pdf_obj *node, pdf_obj *key) +pdf_lookup_inherited_page_item(fz_context *ctx, pdf_obj *node, pdf_obj *key) { pdf_obj *node2 = node; pdf_obj *val; @@ -259,28 +259,28 @@ pdf_lookup_inherited_page_item(fz_context *ctx, pdf_document *doc, pdf_obj *node } static void -pdf_flatten_inheritable_page_item(fz_context *ctx, pdf_document *doc, pdf_obj *page, pdf_obj *key) +pdf_flatten_inheritable_page_item(fz_context *ctx, pdf_obj *page, pdf_obj *key) { - pdf_obj *val = pdf_lookup_inherited_page_item(ctx, doc, page, key); + pdf_obj *val = pdf_lookup_inherited_page_item(ctx, page, key); if (val) pdf_dict_put(ctx, page, key, val); } void -pdf_flatten_inheritable_page_items(fz_context *ctx, pdf_document *doc, pdf_obj *page) +pdf_flatten_inheritable_page_items(fz_context *ctx, pdf_obj *page) { - pdf_flatten_inheritable_page_item(ctx, doc, page, PDF_NAME_MediaBox); - pdf_flatten_inheritable_page_item(ctx, doc, page, PDF_NAME_CropBox); - pdf_flatten_inheritable_page_item(ctx, doc, page, PDF_NAME_Rotate); - pdf_flatten_inheritable_page_item(ctx, doc, page, PDF_NAME_Resources); + pdf_flatten_inheritable_page_item(ctx, page, PDF_NAME_MediaBox); + pdf_flatten_inheritable_page_item(ctx, page, PDF_NAME_CropBox); + pdf_flatten_inheritable_page_item(ctx, page, PDF_NAME_Rotate); + pdf_flatten_inheritable_page_item(ctx, page, PDF_NAME_Resources); } /* We need to know whether to install a page-level transparency group */ -static int pdf_resources_use_blending(fz_context *ctx, pdf_document *doc, pdf_obj *rdb); +static int pdf_resources_use_blending(fz_context *ctx, pdf_obj *rdb); static int -pdf_extgstate_uses_blending(fz_context *ctx, pdf_document *doc, pdf_obj *dict) +pdf_extgstate_uses_blending(fz_context *ctx, pdf_obj *dict) { pdf_obj *obj = pdf_dict_get(ctx, dict, PDF_NAME_BM); if (obj && !pdf_name_eq(ctx, obj, PDF_NAME_Normal)) @@ -289,27 +289,27 @@ pdf_extgstate_uses_blending(fz_context *ctx, pdf_document *doc, pdf_obj *dict) } static int -pdf_pattern_uses_blending(fz_context *ctx, pdf_document *doc, pdf_obj *dict) +pdf_pattern_uses_blending(fz_context *ctx, pdf_obj *dict) { pdf_obj *obj; obj = pdf_dict_get(ctx, dict, PDF_NAME_Resources); - if (pdf_resources_use_blending(ctx, doc, obj)) + if (pdf_resources_use_blending(ctx, obj)) return 1; obj = pdf_dict_get(ctx, dict, PDF_NAME_ExtGState); - return pdf_extgstate_uses_blending(ctx, doc, obj); + return pdf_extgstate_uses_blending(ctx, obj); } static int -pdf_xobject_uses_blending(fz_context *ctx, pdf_document *doc, pdf_obj *dict) +pdf_xobject_uses_blending(fz_context *ctx, pdf_obj *dict) { pdf_obj *obj = pdf_dict_get(ctx, dict, PDF_NAME_Resources); if (pdf_name_eq(ctx, pdf_dict_getp(ctx, dict, "Group/S"), PDF_NAME_Transparency)) return 1; - return pdf_resources_use_blending(ctx, doc, obj); + return pdf_resources_use_blending(ctx, obj); } static int -pdf_resources_use_blending(fz_context *ctx, pdf_document *doc, pdf_obj *rdb) +pdf_resources_use_blending(fz_context *ctx, pdf_obj *rdb) { pdf_obj *obj; int i, n, useBM = 0; @@ -330,19 +330,19 @@ pdf_resources_use_blending(fz_context *ctx, pdf_document *doc, pdf_obj *rdb) obj = pdf_dict_get(ctx, rdb, PDF_NAME_ExtGState); n = pdf_dict_len(ctx, obj); for (i = 0; i < n; i++) - if (pdf_extgstate_uses_blending(ctx, doc, pdf_dict_get_val(ctx, obj, i))) + if (pdf_extgstate_uses_blending(ctx, pdf_dict_get_val(ctx, obj, i))) goto found; obj = pdf_dict_get(ctx, rdb, PDF_NAME_Pattern); n = pdf_dict_len(ctx, obj); for (i = 0; i < n; i++) - if (pdf_pattern_uses_blending(ctx, doc, pdf_dict_get_val(ctx, obj, i))) + if (pdf_pattern_uses_blending(ctx, pdf_dict_get_val(ctx, obj, i))) goto found; obj = pdf_dict_get(ctx, rdb, PDF_NAME_XObject); n = pdf_dict_len(ctx, obj); for (i = 0; i < n; i++) - if (pdf_xobject_uses_blending(ctx, doc, pdf_dict_get_val(ctx, obj, i))) + if (pdf_xobject_uses_blending(ctx, pdf_dict_get_val(ctx, obj, i))) goto found; if (0) { @@ -363,62 +363,65 @@ found: return useBM; } -static void -pdf_load_transition(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_obj *transdict) +fz_transition * +pdf_page_presentation(fz_context *ctx, pdf_page *page, fz_transition *transition, float *duration) { - pdf_obj *name; - pdf_obj *obj; - int type; + pdf_obj *obj, *transdict; + + *duration = pdf_to_real(ctx, pdf_dict_get(ctx, page->obj, PDF_NAME_Dur)); + + transdict = pdf_dict_get(ctx, page->obj, PDF_NAME_Trans); + if (!transdict) + return NULL; obj = pdf_dict_get(ctx, transdict, PDF_NAME_D); - page->transition.duration = (obj ? pdf_to_real(ctx, obj) : 1); - page->transition.vertical = !pdf_name_eq(ctx, pdf_dict_get(ctx, transdict, PDF_NAME_Dm), PDF_NAME_H); - page->transition.outwards = !pdf_name_eq(ctx, pdf_dict_get(ctx, transdict, PDF_NAME_M), PDF_NAME_I); + transition->duration = (obj ? pdf_to_real(ctx, obj) : 1); + + transition->vertical = !pdf_name_eq(ctx, pdf_dict_get(ctx, transdict, PDF_NAME_Dm), PDF_NAME_H); + transition->outwards = !pdf_name_eq(ctx, pdf_dict_get(ctx, transdict, PDF_NAME_M), PDF_NAME_I); /* FIXME: If 'Di' is None, it should be handled differently, but * this only affects Fly, and we don't implement that currently. */ - page->transition.direction = (pdf_to_int(ctx, pdf_dict_get(ctx, transdict, PDF_NAME_Di))); + transition->direction = (pdf_to_int(ctx, pdf_dict_get(ctx, transdict, PDF_NAME_Di))); /* FIXME: Read SS for Fly when we implement it */ /* FIXME: Read B for Fly when we implement it */ - name = pdf_dict_get(ctx, transdict, PDF_NAME_S); - if (pdf_name_eq(ctx, name, PDF_NAME_Split)) - type = FZ_TRANSITION_SPLIT; - else if (pdf_name_eq(ctx, name, PDF_NAME_Blinds)) - type = FZ_TRANSITION_BLINDS; - else if (pdf_name_eq(ctx, name, PDF_NAME_Box)) - type = FZ_TRANSITION_BOX; - else if (pdf_name_eq(ctx, name, PDF_NAME_Wipe)) - type = FZ_TRANSITION_WIPE; - else if (pdf_name_eq(ctx, name, PDF_NAME_Dissolve)) - type = FZ_TRANSITION_DISSOLVE; - else if (pdf_name_eq(ctx, name, PDF_NAME_Glitter)) - type = FZ_TRANSITION_GLITTER; - else if (pdf_name_eq(ctx, name, PDF_NAME_Fly)) - type = FZ_TRANSITION_FLY; - else if (pdf_name_eq(ctx, name, PDF_NAME_Push)) - type = FZ_TRANSITION_PUSH; - else if (pdf_name_eq(ctx, name, PDF_NAME_Cover)) - type = FZ_TRANSITION_COVER; - else if (pdf_name_eq(ctx, name, PDF_NAME_Uncover)) - type = FZ_TRANSITION_UNCOVER; - else if (pdf_name_eq(ctx, name, PDF_NAME_Fade)) - type = FZ_TRANSITION_FADE; + obj = pdf_dict_get(ctx, transdict, PDF_NAME_S); + if (pdf_name_eq(ctx, obj, PDF_NAME_Split)) + transition->type = FZ_TRANSITION_SPLIT; + else if (pdf_name_eq(ctx, obj, PDF_NAME_Blinds)) + transition->type = FZ_TRANSITION_BLINDS; + else if (pdf_name_eq(ctx, obj, PDF_NAME_Box)) + transition->type = FZ_TRANSITION_BOX; + else if (pdf_name_eq(ctx, obj, PDF_NAME_Wipe)) + transition->type = FZ_TRANSITION_WIPE; + else if (pdf_name_eq(ctx, obj, PDF_NAME_Dissolve)) + transition->type = FZ_TRANSITION_DISSOLVE; + else if (pdf_name_eq(ctx, obj, PDF_NAME_Glitter)) + transition->type = FZ_TRANSITION_GLITTER; + else if (pdf_name_eq(ctx, obj, PDF_NAME_Fly)) + transition->type = FZ_TRANSITION_FLY; + else if (pdf_name_eq(ctx, obj, PDF_NAME_Push)) + transition->type = FZ_TRANSITION_PUSH; + else if (pdf_name_eq(ctx, obj, PDF_NAME_Cover)) + transition->type = FZ_TRANSITION_COVER; + else if (pdf_name_eq(ctx, obj, PDF_NAME_Uncover)) + transition->type = FZ_TRANSITION_UNCOVER; + else if (pdf_name_eq(ctx, obj, PDF_NAME_Fade)) + transition->type = FZ_TRANSITION_FADE; else - type = FZ_TRANSITION_NONE; - page->transition.type = type; + transition->type = FZ_TRANSITION_NONE; + + return transition; } fz_rect * -pdf_bound_page(fz_context *ctx, pdf_page *page, fz_rect *bounds) +pdf_bound_page(fz_context *ctx, pdf_page *page, fz_rect *mediabox) { - fz_matrix mtx; - fz_rect mediabox = page->mediabox; - fz_transform_rect(&mediabox, fz_rotate(&mtx, page->rotate)); - bounds->x0 = bounds->y0 = 0; - bounds->x1 = mediabox.x1 - mediabox.x0; - bounds->y1 = mediabox.y1 - mediabox.y0; - return bounds; + fz_matrix page_ctm; + pdf_page_transform(ctx, page, mediabox, &page_ctm); + fz_transform_rect(mediabox, &page_ctm); + return mediabox; } fz_link * @@ -427,6 +430,72 @@ pdf_load_links(fz_context *ctx, pdf_page *page) return fz_keep_link(ctx, page->links); } +pdf_obj * +pdf_page_resources(fz_context *ctx, pdf_page *page) +{ + return pdf_lookup_inherited_page_item(ctx, page->obj, PDF_NAME_Resources); +} + +pdf_obj * +pdf_page_contents(fz_context *ctx, pdf_page *page) +{ + return pdf_dict_get(ctx, page->obj, PDF_NAME_Contents); +} + +void +pdf_page_transform(fz_context *ctx, pdf_page *page, fz_rect *page_mediabox, fz_matrix *page_ctm) +{ + pdf_obj *pageobj = page->obj; + pdf_obj *obj; + fz_rect mediabox, cropbox, realbox; + float userunit = 1; + int rotate; + + obj = pdf_dict_get(ctx, pageobj, PDF_NAME_UserUnit); + if (pdf_is_real(ctx, obj)) + userunit = pdf_to_real(ctx, obj); + + pdf_to_rect(ctx, pdf_lookup_inherited_page_item(ctx, pageobj, PDF_NAME_MediaBox), &mediabox); + if (fz_is_empty_rect(&mediabox)) + { + mediabox.x0 = 0; + mediabox.y0 = 0; + mediabox.x1 = 612; + mediabox.y1 = 792; + } + + pdf_to_rect(ctx, pdf_lookup_inherited_page_item(ctx, pageobj, PDF_NAME_CropBox), &cropbox); + if (!fz_is_empty_rect(&cropbox)) + fz_intersect_rect(&mediabox, &cropbox); + + page_mediabox->x0 = fz_min(mediabox.x0, mediabox.x1); + page_mediabox->y0 = fz_min(mediabox.y0, mediabox.y1); + page_mediabox->x1 = fz_max(mediabox.x0, mediabox.x1); + page_mediabox->y1 = fz_max(mediabox.y0, mediabox.y1); + + if (page_mediabox->x1 - page_mediabox->x0 < 1 || page_mediabox->y1 - page_mediabox->y0 < 1) + *page_mediabox = fz_unit_rect; + + rotate = pdf_to_int(ctx, pdf_lookup_inherited_page_item(ctx, pageobj, PDF_NAME_Rotate)); + + /* Snap page rotation to 0, 90, 180 or 270 */ + if (rotate < 0) + rotate = 360 - ((-rotate) % 360); + if (rotate >= 360) + rotate = rotate % 360; + rotate = 90*((rotate + 45)/90); + if (rotate >= 360) + rotate = 0; + + /* Compute transform from fitz' page space (upper left page origin, y descending, 72 dpi) + * to PDF user space (arbitary page origin, y ascending, UserUnit dpi). */ + fz_rotate(page_ctm, -rotate); + realbox = *page_mediabox; + fz_transform_rect(&realbox, page_ctm); + fz_pre_translate(page_ctm, -realbox.x0, -realbox.y1); + fz_post_scale(page_ctm, userunit, -userunit); +} + static void pdf_drop_page_imp(fz_context *ctx, pdf_page *page) { @@ -435,8 +504,6 @@ pdf_drop_page_imp(fz_context *ctx, pdf_page *page) if (page == NULL) return; - pdf_drop_obj(ctx, page->resources); - pdf_drop_obj(ctx, page->contents); if (page->links) fz_drop_link(ctx, page->links); if (page->annots) @@ -450,7 +517,8 @@ pdf_drop_page_imp(fz_context *ctx, pdf_page *page) * annotations are destroyed. doc->focus_obj * keeps track of the actual annotation object. */ doc->focus = NULL; - pdf_drop_obj(ctx, page->me); + + pdf_drop_obj(ctx, page->obj); fz_drop_document(ctx, &page->doc->super); } @@ -474,8 +542,8 @@ pdf_new_page(fz_context *ctx, pdf_document *doc) page->super.run_page_contents = (fz_page_run_page_contents_fn *)pdf_run_page_contents; page->super.page_presentation = (fz_page_page_presentation_fn *)pdf_page_presentation; - page->resources = NULL; - page->contents = NULL; + page->obj = NULL; + page->transparency = 0; page->links = NULL; page->annots = NULL; @@ -483,7 +551,6 @@ pdf_new_page(fz_context *ctx, pdf_document *doc) page->deleted_annots = NULL; page->tmp_annots = NULL; page->incomplete = 0; - page->me = NULL; return page; } @@ -493,78 +560,31 @@ pdf_load_page(fz_context *ctx, pdf_document *doc, int number) { pdf_page *page; pdf_annot *annot; - pdf_obj *pageobj, *pageref, *obj; - fz_rect mediabox, cropbox, realbox; - float userunit; - fz_matrix mat; + pdf_obj *pageobj, *obj; if (doc->file_reading_linearly) { - pageref = pdf_progressive_advance(ctx, doc, number); - if (pageref == NULL) + pageobj = pdf_progressive_advance(ctx, doc, number); + if (pageobj == NULL) fz_throw(ctx, FZ_ERROR_TRYLATER, "page %d not available yet", number); } else - pageref = pdf_lookup_page_obj(ctx, doc, number); - pageobj = pdf_resolve_indirect_chain(ctx, pageref); + pageobj = pdf_lookup_page_obj(ctx, doc, number); page = pdf_new_page(ctx, doc); - page->me = pdf_keep_obj(ctx, pageobj); - - obj = pdf_dict_get(ctx, pageobj, PDF_NAME_UserUnit); - if (pdf_is_real(ctx, obj)) - userunit = pdf_to_real(ctx, obj); - else - userunit = 1; - - pdf_to_rect(ctx, pdf_lookup_inherited_page_item(ctx, doc, pageobj, PDF_NAME_MediaBox), &mediabox); - if (fz_is_empty_rect(&mediabox)) - { - fz_warn(ctx, "cannot find page size for page %d", number + 1); - mediabox.x0 = 0; - mediabox.y0 = 0; - mediabox.x1 = 612; - mediabox.y1 = 792; - } - - pdf_to_rect(ctx, pdf_lookup_inherited_page_item(ctx, doc, pageobj, PDF_NAME_CropBox), &cropbox); - if (!fz_is_empty_rect(&cropbox)) - fz_intersect_rect(&mediabox, &cropbox); - - page->mediabox.x0 = fz_min(mediabox.x0, mediabox.x1) * userunit; - page->mediabox.y0 = fz_min(mediabox.y0, mediabox.y1) * userunit; - page->mediabox.x1 = fz_max(mediabox.x0, mediabox.x1) * userunit; - page->mediabox.y1 = fz_max(mediabox.y0, mediabox.y1) * userunit; - - if (page->mediabox.x1 - page->mediabox.x0 < 1 || page->mediabox.y1 - page->mediabox.y0 < 1) - { - fz_warn(ctx, "invalid page size in page %d", number + 1); - page->mediabox = fz_unit_rect; - } - - page->rotate = pdf_to_int(ctx, pdf_lookup_inherited_page_item(ctx, doc, pageobj, PDF_NAME_Rotate)); - /* Snap page->rotate to 0, 90, 180 or 270 */ - if (page->rotate < 0) - page->rotate = 360 - ((-page->rotate) % 360); - if (page->rotate >= 360) - page->rotate = page->rotate % 360; - page->rotate = 90*((page->rotate + 45)/90); - if (page->rotate > 360) - page->rotate = 0; - - fz_pre_rotate(fz_scale(&page->ctm, 1, -1), -page->rotate); - realbox = page->mediabox; - fz_transform_rect(&realbox, &page->ctm); - fz_pre_scale(fz_translate(&mat, -realbox.x0, -realbox.y0), userunit, userunit); - fz_concat(&page->ctm, &page->ctm, &mat); + page->obj = pdf_keep_obj(ctx, pageobj); + /* Pre-load annotations and links */ fz_try(ctx) { obj = pdf_dict_get(ctx, pageobj, PDF_NAME_Annots); if (obj) { - page->links = pdf_load_link_annots(ctx, doc, obj, &page->ctm); - pdf_load_annots(ctx, doc, page, obj); + fz_rect page_mediabox; + fz_matrix page_ctm; + pdf_page_transform(ctx, page, &page_mediabox, &page_ctm); + page->links = pdf_load_link_annots(ctx, doc, obj, &page_ctm); + pdf_load_annots(ctx, doc, page, obj, &page_ctm); } } fz_catch(ctx) @@ -576,32 +596,16 @@ pdf_load_page(fz_context *ctx, pdf_document *doc, int number) page->links = NULL; } - page->duration = pdf_to_real(ctx, pdf_dict_get(ctx, pageobj, PDF_NAME_Dur)); - - obj = pdf_dict_get(ctx, pageobj, PDF_NAME_Trans); - page->transition_present = (obj != NULL); - if (obj) - { - pdf_load_transition(ctx, doc, page, obj); - } - - // TODO: inherit - page->resources = pdf_lookup_inherited_page_item(ctx, doc, pageobj, PDF_NAME_Resources); - if (page->resources) - pdf_keep_obj(ctx, page->resources); - - obj = pdf_dict_get(ctx, pageobj, PDF_NAME_Contents); + /* Scan for transparency */ fz_try(ctx) { - page->contents = pdf_keep_obj(ctx, obj); - - if (pdf_resources_use_blending(ctx, doc, page->resources)) + pdf_obj *resources = pdf_page_resources(ctx, page); + if (pdf_resources_use_blending(ctx, resources)) page->transparency = 1; else if (pdf_name_eq(ctx, pdf_dict_getp(ctx, pageobj, "Group/S"), PDF_NAME_Transparency)) page->transparency = 1; - for (annot = page->annots; annot && !page->transparency; annot = annot->next) - if (annot->ap && pdf_resources_use_blending(ctx, doc, annot->ap->resources)) + if (annot->ap && pdf_resources_use_blending(ctx, annot->ap->resources)) page->transparency = 1; } fz_catch(ctx) diff --git a/source/pdf/pdf-run.c b/source/pdf/pdf-run.c index e84604fb..f806b120 100644 --- a/source/pdf/pdf-run.c +++ b/source/pdf/pdf-run.c @@ -3,10 +3,12 @@ static void pdf_run_annot_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_annot *annot, fz_device *dev, const fz_matrix *ctm, char *event, fz_cookie *cookie) { - fz_matrix local_ctm; + fz_matrix local_ctm, page_ctm; + fz_rect mediabox; pdf_processor *proc; - fz_concat(&local_ctm, &page->ctm, ctm); + pdf_page_transform(ctx, page, &mediabox, &page_ctm); + fz_concat(&local_ctm, &page_ctm, ctm); proc = pdf_new_run_processor(ctx, dev, &local_ctm, event, NULL, 0); fz_try(ctx) @@ -19,21 +21,24 @@ pdf_run_annot_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf static void pdf_run_page_contents_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_device *dev, const fz_matrix *ctm, char *event, fz_cookie *cookie) { - fz_matrix local_ctm; + fz_matrix local_ctm, page_ctm; + pdf_obj *resources; + pdf_obj *contents; + fz_rect mediabox; pdf_processor *proc; - fz_concat(&local_ctm, &page->ctm, ctm); + pdf_page_transform(ctx, page, &mediabox, &page_ctm); + fz_concat(&local_ctm, &page_ctm, ctm); + + resources = pdf_page_resources(ctx, page); + contents = pdf_page_contents(ctx, page); if (page->transparency) - { - fz_rect mediabox = page->mediabox; fz_begin_group(ctx, dev, fz_transform_rect(&mediabox, &local_ctm), 1, 0, 0, 1); - } proc = pdf_new_run_processor(ctx, dev, &local_ctm, event, NULL, 0); - fz_try(ctx) - pdf_process_contents(ctx, proc, doc, page->resources, page->contents, cookie); + pdf_process_contents(ctx, proc, doc, resources, contents, cookie); fz_always(ctx) pdf_drop_processor(ctx, proc); fz_catch(ctx) diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c index 82fe7db1..48a5d316 100644 --- a/source/pdf/pdf-xref.c +++ b/source/pdf/pdf-xref.c @@ -2284,15 +2284,6 @@ pdf_lookup_metadata(fz_context *ctx, pdf_document *doc, const char *key, char *b return -1; } -fz_transition * -pdf_page_presentation(fz_context *ctx, pdf_page *page, float *duration) -{ - *duration = page->duration; - if (!page->transition_present) - return NULL; - return &page->transition; -} - /* Initializers for the fz_document interface. diff --git a/source/tools/pdfmerge.c b/source/tools/pdfmerge.c index bda2ffb7..6874e8b9 100644 --- a/source/tools/pdfmerge.c +++ b/source/tools/pdfmerge.c @@ -41,7 +41,7 @@ static void page_merge(int page_from, int page_to, pdf_graft_map *graft_map) fz_try(ctx) { page_ref = pdf_lookup_page_obj(ctx, doc_src, page_from - 1); - pdf_flatten_inheritable_page_items(ctx, doc_src, page_ref); + pdf_flatten_inheritable_page_items(ctx, page_ref); /* Make a new page object dictionary to hold the items we copy from the source page. */ page_dict = pdf_new_dict(ctx, doc_des, 4); diff --git a/source/tools/pdfposter.c b/source/tools/pdfposter.c index 81ca0d75..66eaa3a5 100644 --- a/source/tools/pdfposter.c +++ b/source/tools/pdfposter.c @@ -58,6 +58,8 @@ static void decimatepages(fz_context *ctx, pdf_document *doc) pdf_obj *oldroot, *root, *pages, *kids; int num_pages = pdf_count_pages(ctx, doc); int page, kidcount; + fz_rect mediabox; + fz_matrix page_ctm; oldroot = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root); pages = pdf_dict_get(ctx, oldroot, PDF_NAME_Pages); @@ -78,9 +80,13 @@ static void decimatepages(fz_context *ctx, pdf_document *doc) { pdf_page *page_details = pdf_load_page(ctx, doc, page); int xf = x_factor, yf = y_factor; + float w, h; int x, y; - float w = page_details->mediabox.x1 - page_details->mediabox.x0; - float h = page_details->mediabox.y1 - page_details->mediabox.y0; + + pdf_page_transform(ctx, page_details, &mediabox, &page_ctm); + + w = mediabox.x1 - mediabox.x0; + h = mediabox.y1 - mediabox.y0; if (xf == 0 && yf == 0) { @@ -103,21 +109,21 @@ static void decimatepages(fz_context *ctx, pdf_document *doc) fz_rect mb; newpageobj = pdf_copy_dict(ctx, pdf_lookup_page_obj(ctx, doc, page)); - pdf_flatten_inheritable_page_items(ctx, doc, newpageobj); + pdf_flatten_inheritable_page_items(ctx, newpageobj); newpageref = pdf_add_object(ctx, doc, newpageobj); newmediabox = pdf_new_array(ctx, doc, 4); - mb.x0 = page_details->mediabox.x0 + (w/xf)*x; + mb.x0 = mediabox.x0 + (w/xf)*x; if (x == xf-1) - mb.x1 = page_details->mediabox.x1; + mb.x1 = mediabox.x1; else - mb.x1 = page_details->mediabox.x0 + (w/xf)*(x+1); - mb.y0 = page_details->mediabox.y0 + (h/yf)*y; + mb.x1 = mediabox.x0 + (w/xf)*(x+1); + mb.y0 = mediabox.y0 + (h/yf)*y; if (y == yf-1) - mb.y1 = page_details->mediabox.y1; + mb.y1 = mediabox.y1; else - mb.y1 = page_details->mediabox.y0 + (h/yf)*(y+1); + mb.y1 = mediabox.y0 + (h/yf)*(y+1); pdf_array_push(ctx, newmediabox, pdf_new_real(ctx, doc, mb.x0)); pdf_array_push(ctx, newmediabox, pdf_new_real(ctx, doc, mb.y0)); -- cgit v1.2.3