X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=sidebyside;f=backend%2Fpdf%2Fev-poppler.cc;h=0a073ca0b04ae48a5501281bb202e11bf30c077b;hb=cc3f21efc8104182171c9300facc16d9a79177ef;hp=ec2bbc0835b7f01636344c939e2930d2145c09ce;hpb=c561c0a1ff7ff46f1a1cf781b0d9b30a1599d1d7;p=evince.git diff --git a/backend/pdf/ev-poppler.cc b/backend/pdf/ev-poppler.cc index ec2bbc08..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" @@ -52,6 +53,11 @@ #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 @@ -481,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); @@ -505,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; @@ -573,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) { @@ -582,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); @@ -618,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) { @@ -910,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; @@ -926,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, @@ -946,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; @@ -1154,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); } @@ -1219,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); } @@ -1374,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; @@ -2127,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; @@ -2136,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", @@ -2430,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), @@ -2446,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); @@ -2485,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; @@ -2500,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",