X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=backend%2Fpdf%2Fev-poppler.cc;h=0a073ca0b04ae48a5501281bb202e11bf30c077b;hb=cc3f21efc8104182171c9300facc16d9a79177ef;hp=4c16d22d4256679ea566cf66b5700e89a1555388;hpb=e6834c6a4fb18288143851c6020ed1795e0992a8;p=evince.git diff --git a/backend/pdf/ev-poppler.cc b/backend/pdf/ev-poppler.cc index 4c16d22d..0a073ca0 100644 --- a/backend/pdf/ev-poppler.cc +++ b/backend/pdf/ev-poppler.cc @@ -35,6 +35,7 @@ #include "ev-poppler.h" #include "ev-file-exporter.h" +#include "ev-mapping.h" #include "ev-document-find.h" #include "ev-document-misc.h" #include "ev-document-links.h" @@ -45,12 +46,18 @@ #include "ev-document-transition.h" #include "ev-document-forms.h" #include "ev-document-layers.h" +#include "ev-document-print.h" #include "ev-document-annotations.h" #include "ev-selection.h" #include "ev-transition-effect.h" #include "ev-attachment.h" #include "ev-image.h" +#include +#include +#include +#include + #if (defined (HAVE_POPPLER_PAGE_RENDER)) && (defined (HAVE_CAIRO_PDF) || defined (HAVE_CAIRO_PS)) #define HAVE_CAIRO_PRINT #endif @@ -113,6 +120,9 @@ static void pdf_document_document_images_iface_init (EvDocumentImagesIface static void pdf_document_document_forms_iface_init (EvDocumentFormsIface *iface); static void pdf_document_document_fonts_iface_init (EvDocumentFontsIface *iface); static void pdf_document_document_layers_iface_init (EvDocumentLayersIface *iface); +#ifdef HAVE_POPPLER_PAGE_RENDER +static void pdf_document_document_print_iface_init (EvDocumentPrintIface *iface); +#endif static void pdf_document_document_annotations_iface_init (EvDocumentAnnotationsIface *iface); static void pdf_document_find_iface_init (EvDocumentFindIface *iface); static void pdf_document_file_exporter_iface_init (EvFileExporterIface *iface); @@ -147,6 +157,10 @@ EV_BACKEND_REGISTER_WITH_CODE (PdfDocument, pdf_document, pdf_document_document_fonts_iface_init); EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LAYERS, pdf_document_document_layers_iface_init); +#ifdef HAVE_POPPLER_PAGE_RENDER + EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_PRINT, + pdf_document_document_print_iface_init); +#endif EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_ANNOTATIONS, pdf_document_document_annotations_iface_init); EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND, @@ -473,14 +487,11 @@ pdf_page_render (PopplerPage *page, #ifdef HAVE_POPPLER_PAGE_RENDER cairo_t *cr; - - surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, + + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - memset (cairo_image_surface_get_data (surface), 0xff, - cairo_image_surface_get_height (surface) * - cairo_image_surface_get_stride (surface)); - cr = cairo_create (surface); + switch (rc->rotation) { case 90: cairo_translate (cr, width, 0); @@ -497,6 +508,11 @@ pdf_page_render (PopplerPage *page, cairo_scale (cr, rc->scale, rc->scale); cairo_rotate (cr, rc->rotation * G_PI / 180.0); poppler_page_render (page, cr); + + cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER); + cairo_set_source_rgb (cr, 1., 1., 1.); + cairo_paint (cr); + cairo_destroy (cr); #else /* HAVE_POPPLER_PAGE_RENDER */ GdkPixbuf *pixbuf; @@ -565,6 +581,94 @@ pdf_document_set_password (EvDocumentSecurity *document_security, document->password = g_strdup (password); } + +/* reference: +http://www.pdfa.org/lib/exe/fetch.php?id=pdfa%3Aen%3Atechdoc&cache=cache&media=pdfa:techdoc:tn0001_pdfa-1_and_namespaces_2008-03-18.pdf */ +static char * +pdf_document_get_format_from_metadata (const char *metadata) +{ + xmlDocPtr doc; + xmlXPathContextPtr xpathCtx; + xmlXPathObjectPtr xpathObj; + xmlChar *part = NULL; + xmlChar *conf = NULL; + char *result = NULL; + int i; + + doc = xmlParseMemory (metadata, strlen (metadata)); + if (doc == NULL) + return NULL; /* invalid xml metadata */ + + xpathCtx = xmlXPathNewContext (doc); + if (xpathCtx == NULL) { + xmlFreeDoc (doc); + return NULL; /* invalid xpath context */ + } + + /* add pdf/a namespaces */ + xmlXPathRegisterNs (xpathCtx, BAD_CAST "x", BAD_CAST "adobe:ns:meta/"); + xmlXPathRegisterNs (xpathCtx, BAD_CAST "rdf", BAD_CAST "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + xmlXPathRegisterNs (xpathCtx, BAD_CAST "pdfaid", BAD_CAST "http://www.aiim.org/pdfa/ns/id/"); + + /* reads pdf/a part */ + /* first syntax: child node */ + xpathObj = xmlXPathEvalExpression (BAD_CAST "/x:xmpmeta/rdf:RDF/rdf:Description/pdfaid:part", xpathCtx); + if (xpathObj != NULL) { + if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr != 0) + part = xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]); + + xmlXPathFreeObject (xpathObj); + } + if (part == NULL) { + /* second syntax: attribute */ + xpathObj = xmlXPathEvalExpression (BAD_CAST "/x:xmpmeta/rdf:RDF/rdf:Description/@pdfaid:part", xpathCtx); + if (xpathObj != NULL) { + if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr != 0) + part = xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]); + + xmlXPathFreeObject (xpathObj); + } + } + + /* reads pdf/a conformance */ + /* first syntax: child node */ + xpathObj = xmlXPathEvalExpression (BAD_CAST "/x:xmpmeta/rdf:RDF/rdf:Description/pdfaid:conformance", xpathCtx); + if (xpathObj != NULL) { + if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr != 0) + conf = xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]); + + xmlXPathFreeObject (xpathObj); + } + if (conf == NULL) { + /* second syntax: attribute */ + xpathObj = xmlXPathEvalExpression (BAD_CAST "/x:xmpmeta/rdf:RDF/rdf:Description/@pdfaid:conformance", xpathCtx); + if (xpathObj != NULL) { + if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr != 0) + conf = xmlNodeGetContent (xpathObj->nodesetval->nodeTab[0]); + + xmlXPathFreeObject (xpathObj); + } + } + + if (part != NULL && conf != NULL) { + /* makes conf lowercase */ + for (i = 0; conf[i]; i++) + conf[i] = g_ascii_tolower (conf[i]); + + /* return buffer */ + result = g_strdup_printf ("PDF/A - %s%s", part, conf); + } + + /* Cleanup */ + xmlFree (part); + xmlFree (conf); + xmlXPathFreeContext (xpathCtx); + xmlFreeDoc (doc); + + return result; +} + + static EvDocumentInfo * pdf_document_get_info (EvDocument *document) { @@ -574,6 +678,8 @@ pdf_document_get_info (EvDocument *document) PopplerViewerPreferences view_prefs; PopplerPermissions permissions; EvPage *page; + char *metadata; + char *fmt; info = g_new0 (EvDocumentInfo, 1); @@ -610,8 +716,18 @@ pdf_document_get_info (EvDocument *document) "creation-date", &(info->creation_date), "mod-date", &(info->modified_date), "linearized", &(info->linearized), + "metadata", &metadata, NULL); + if (metadata != NULL) { + fmt = pdf_document_get_format_from_metadata(metadata); + if (fmt != NULL) { + g_free (info->format); + info->format = fmt; + } + g_free (metadata); + } + info->n_pages = ev_document_get_n_pages (document); if (info->n_pages > 0) { @@ -902,9 +1018,11 @@ ev_link_dest_from_dest (PdfDocument *pdf_document, g_object_unref (poppler_page); } break; - case POPPLER_DEST_FIT: + case POPPLER_DEST_FITB: + case POPPLER_DEST_FIT: ev_dest = ev_link_dest_new_fit (dest->page_num - 1); break; + case POPPLER_DEST_FITBH: case POPPLER_DEST_FITH: { PopplerPage *poppler_page; double height; @@ -918,6 +1036,7 @@ ev_link_dest_from_dest (PdfDocument *pdf_document, g_object_unref (poppler_page); } break; + case POPPLER_DEST_FITBV: case POPPLER_DEST_FITV: ev_dest = ev_link_dest_new_fitv (dest->page_num - 1, dest->left, @@ -938,15 +1057,6 @@ ev_link_dest_from_dest (PdfDocument *pdf_document, g_object_unref (poppler_page); } break; - case POPPLER_DEST_FITB: - unimplemented_dest = "POPPLER_DEST_FITB"; - break; - case POPPLER_DEST_FITBH: - unimplemented_dest = "POPPLER_DEST_FITBH"; - break; - case POPPLER_DEST_FITBV: - unimplemented_dest = "POPPLER_DEST_FITBV"; - break; case POPPLER_DEST_NAMED: ev_dest = ev_link_dest_new_named (dest->named_dest); break; @@ -1146,17 +1256,17 @@ pdf_document_links_get_links (EvDocumentLinks *document_links, for (list = mapping_list; list; list = list->next) { PopplerLinkMapping *link_mapping; - EvLinkMapping *ev_link_mapping; + EvMapping *ev_link_mapping; link_mapping = (PopplerLinkMapping *)list->data; - ev_link_mapping = g_new (EvLinkMapping, 1); - ev_link_mapping->link = ev_link_from_action (pdf_document, + ev_link_mapping = g_new (EvMapping, 1); + ev_link_mapping->data = ev_link_from_action (pdf_document, link_mapping->action); - ev_link_mapping->x1 = link_mapping->area.x1; - ev_link_mapping->x2 = link_mapping->area.x2; + ev_link_mapping->area.x1 = link_mapping->area.x1; + ev_link_mapping->area.x2 = link_mapping->area.x2; /* Invert this for X-style coordinates */ - ev_link_mapping->y1 = height - link_mapping->area.y2; - ev_link_mapping->y2 = height - link_mapping->area.y1; + ev_link_mapping->area.y1 = height - link_mapping->area.y2; + ev_link_mapping->area.y2 = height - link_mapping->area.y1; retval = g_list_prepend (retval, ev_link_mapping); } @@ -1211,17 +1321,17 @@ pdf_document_images_get_image_mapping (EvDocumentImages *document_images, for (list = mapping_list; list; list = list->next) { PopplerImageMapping *image_mapping; - EvImageMapping *ev_image_mapping; + EvMapping *ev_image_mapping; image_mapping = (PopplerImageMapping *)list->data; - ev_image_mapping = g_new (EvImageMapping, 1); + ev_image_mapping = g_new (EvMapping, 1); - ev_image_mapping->image = ev_image_new (page, image_mapping->image_id); - ev_image_mapping->x1 = image_mapping->area.x1; - ev_image_mapping->x2 = image_mapping->area.x2; - ev_image_mapping->y1 = image_mapping->area.y1; - ev_image_mapping->y2 = image_mapping->area.y2; + ev_image_mapping->data = ev_image_new (page, image_mapping->image_id); + ev_image_mapping->area.x1 = image_mapping->area.x1; + ev_image_mapping->area.y1 = image_mapping->area.y1; + ev_image_mapping->area.x2 = image_mapping->area.x2; + ev_image_mapping->area.y2 = image_mapping->area.y2; retval = g_list_prepend (retval, ev_image_mapping); } @@ -1236,10 +1346,11 @@ GdkPixbuf * pdf_document_images_get_image (EvDocumentImages *document_images, EvImage *image) { + GdkPixbuf *retval = NULL; +#ifdef HAVE_POPPLER_PAGE_GET_IMAGE PdfDocument *pdf_document; PopplerPage *poppler_page; cairo_surface_t *surface; - GdkPixbuf *retval = NULL; pdf_document = PDF_DOCUMENT (document_images); poppler_page = poppler_document_get_page (pdf_document->document, @@ -1252,7 +1363,7 @@ pdf_document_images_get_image (EvDocumentImages *document_images, } g_object_unref (poppler_page); - +#endif return retval; } @@ -1365,9 +1476,9 @@ pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnail poppler_page_get_size (POPPLER_PAGE (rc->page->backend_page), &page_width, &page_height); - *width = (gint) MAX (page_width * rc->scale, 1); - *height = (gint) MAX (page_height * rc->scale, 1); - + *width = MAX ((gint)(page_width * rc->scale + 0.5), 1); + *height = MAX ((gint)(page_height * rc->scale + 0.5), 1); + if (rc->rotation == 90 || rc->rotation == 270) { gint temp; @@ -1712,6 +1823,25 @@ pdf_document_file_exporter_iface_init (EvFileExporterIface *iface) iface->get_capabilities = pdf_document_file_exporter_get_capabilities; } +#ifdef HAVE_POPPLER_PAGE_RENDER +/* EvDocumentPrint */ +static void +pdf_document_print_print_page (EvDocumentPrint *document, + EvPage *page, + cairo_t *cr) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document); + + poppler_page_render_for_printing (POPPLER_PAGE (page->backend_page), cr); +} + +static void +pdf_document_document_print_iface_init (EvDocumentPrintIface *iface) +{ + iface->print_page = pdf_document_print_print_page; +} +#endif /* HAVE_POPPLER_PAGE_RENDER */ + static void pdf_selection_render_selection (EvSelection *selection, EvRenderContext *rc, @@ -2099,7 +2229,7 @@ pdf_document_forms_get_form_fields (EvDocumentForms *document, for (list = fields; list; list = list->next) { PopplerFormFieldMapping *mapping; - EvFormFieldMapping *field_mapping; + EvMapping *field_mapping; EvFormField *ev_field; mapping = (PopplerFormFieldMapping *)list->data; @@ -2108,13 +2238,13 @@ pdf_document_forms_get_form_fields (EvDocumentForms *document, if (!ev_field) continue; - field_mapping = g_new0 (EvFormFieldMapping, 1); - field_mapping->x1 = mapping->area.x1; - field_mapping->x2 = mapping->area.x2; - field_mapping->y1 = height - mapping->area.y2; - field_mapping->y2 = height - mapping->area.y1; - field_mapping->field = ev_field; - field_mapping->field->page = EV_PAGE (g_object_ref (page)); + field_mapping = g_new0 (EvMapping, 1); + field_mapping->area.x1 = mapping->area.x1; + field_mapping->area.x2 = mapping->area.x2; + field_mapping->area.y1 = height - mapping->area.y2; + field_mapping->area.y2 = height - mapping->area.y1; + field_mapping->data = ev_field; + ev_field->page = EV_PAGE (g_object_ref (page)); g_object_set_data_full (G_OBJECT (ev_field), "poppler-field", @@ -2402,13 +2532,13 @@ ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot, PopplerAnnotMarkup *markup; gchar *label; gdouble opacity; - gboolean is_open; PopplerRectangle poppler_rect; markup = POPPLER_ANNOT_MARKUP (poppler_annot); if (poppler_annot_markup_get_popup_rectangle (markup, &poppler_rect)) { EvRectangle ev_rect; + gboolean is_open; gdouble height; poppler_page_get_size (POPPLER_PAGE (page->backend_page), @@ -2418,17 +2548,28 @@ ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot, ev_rect.y1 = height - poppler_rect.y2; ev_rect.y2 = height - poppler_rect.y1; - g_object_set (ev_annot, "rectangle", &ev_rect, NULL); + is_open = poppler_annot_markup_get_popup_is_open (markup); + + g_object_set (ev_annot, + "rectangle", &ev_rect, + "is_open", is_open, + "has_popup", TRUE, + NULL); + } else { + /* FIXME: Use poppler_annot_markup_has_popup() when + * new poppler is released. + */ + g_object_set (ev_annot, + "has_popup", FALSE, + NULL); } label = poppler_annot_markup_get_label (markup); opacity = poppler_annot_markup_get_opacity (markup); - is_open = poppler_annot_markup_get_popup_is_open (markup); g_object_set (ev_annot, "label", label, "opacity", opacity, - "is_open", is_open, NULL); g_free (label); @@ -2457,7 +2598,7 @@ pdf_document_annotations_get_annotations (EvDocumentAnnotations *document_annota for (list = annots; list; list = list->next) { PopplerAnnotMapping *mapping; - EvAnnotationMapping *annot_mapping; + EvMapping *annot_mapping; EvAnnotation *ev_annot; mapping = (PopplerAnnotMapping *)list->data; @@ -2472,12 +2613,12 @@ pdf_document_annotations_get_annotations (EvDocumentAnnotations *document_annota if (!ev_annot->name) ev_annot->name = g_strdup_printf ("annot-%d-%d", page->index, i); - annot_mapping = g_new0 (EvAnnotationMapping, 1); - annot_mapping->x1 = mapping->area.x1; - annot_mapping->x2 = mapping->area.x2; - annot_mapping->y1 = height - mapping->area.y2; - annot_mapping->y2 = height - mapping->area.y1; - annot_mapping->annotation = ev_annot; + annot_mapping = g_new (EvMapping, 1); + annot_mapping->area.x1 = mapping->area.x1; + annot_mapping->area.x2 = mapping->area.x2; + annot_mapping->area.y1 = height - mapping->area.y2; + annot_mapping->area.y2 = height - mapping->area.y1; + annot_mapping->data = ev_annot; g_object_set_data_full (G_OBJECT (ev_annot), "poppler-annot", @@ -2518,7 +2659,6 @@ pdf_document_document_annotations_iface_init (EvDocumentAnnotationsIface *iface) static gboolean pdf_document_layers_has_layers (EvDocumentLayers *document) { -#ifdef HAVE_POPPLER_LAYERS_ITER_NEW PdfDocument *pdf_document = PDF_DOCUMENT (document); PopplerLayersIter *iter; @@ -2528,12 +2668,8 @@ pdf_document_layers_has_layers (EvDocumentLayers *document) poppler_layers_iter_free (iter); return TRUE; -#else - return FALSE; -#endif /* HAVE_POPPLER_LAYERS_ITER_NEW */ } -#ifdef HAVE_POPPLER_LAYERS_ITER_NEW static void build_layers_tree (PdfDocument *pdf_document, GtkTreeModel *model, @@ -2589,13 +2725,11 @@ build_layers_tree (PdfDocument *pdf_document, poppler_layers_iter_free (child); } while (poppler_layers_iter_next (iter)); } -#endif /* HAVE_POPPLER_LAYERS_ITER_NEW */ static GtkTreeModel * pdf_document_layers_get_layers (EvDocumentLayers *document) { GtkTreeModel *model = NULL; -#ifdef HAVE_POPPLER_LAYERS_ITER_NEW PdfDocument *pdf_document = PDF_DOCUMENT (document); PopplerLayersIter *iter; @@ -2611,8 +2745,6 @@ pdf_document_layers_get_layers (EvDocumentLayers *document) build_layers_tree (pdf_document, model, NULL, iter); poppler_layers_iter_free (iter); } - -#endif return model; } @@ -2620,42 +2752,30 @@ static void pdf_document_layers_show_layer (EvDocumentLayers *document, EvLayer *layer) { -#ifdef HAVE_POPPLER_LAYERS_ITER_NEW PdfDocument *pdf_document = PDF_DOCUMENT (document); guint layer_id = ev_layer_get_id (layer); poppler_layer_show (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id))); -#else - return; -#endif /* HAVE_POPPLER_LAYERS_ITER_NEW */ } static void pdf_document_layers_hide_layer (EvDocumentLayers *document, EvLayer *layer) { -#ifdef HAVE_POPPLER_LAYERS_ITER_NEW PdfDocument *pdf_document = PDF_DOCUMENT (document); guint layer_id = ev_layer_get_id (layer); poppler_layer_hide (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id))); -#else - return; -#endif /* HAVE_POPPLER_LAYERS_ITER_NEW */ } static gboolean pdf_document_layers_layer_is_visible (EvDocumentLayers *document, EvLayer *layer) { -#ifdef HAVE_POPPLER_LAYERS_ITER_NEW PdfDocument *pdf_document = PDF_DOCUMENT (document); guint layer_id = ev_layer_get_id (layer); return poppler_layer_is_visible (POPPLER_LAYER (g_list_nth_data (pdf_document->layers, layer_id))); -#else - return FALSE; -#endif /* HAVE_POPPLER_LAYERS_ITER_NEW */ } static void