#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"
#include "ev-attachment.h"
#include "ev-image.h"
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
#if (defined (HAVE_POPPLER_PAGE_RENDER)) && (defined (HAVE_CAIRO_PDF) || defined (HAVE_CAIRO_PS))
#define HAVE_CAIRO_PRINT
#endif
#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);
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;
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)
{
PopplerViewerPreferences view_prefs;
PopplerPermissions permissions;
EvPage *page;
+ char *metadata;
+ char *fmt;
info = g_new0 (EvDocumentInfo, 1);
"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) {
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;
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,
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;
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);
}
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);
}
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;
for (list = fields; list; list = list->next) {
PopplerFormFieldMapping *mapping;
- EvFormFieldMapping *field_mapping;
+ EvMapping *field_mapping;
EvFormField *ev_field;
mapping = (PopplerFormFieldMapping *)list->data;
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",
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),
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);
for (list = annots; list; list = list->next) {
PopplerAnnotMapping *mapping;
- EvAnnotationMapping *annot_mapping;
+ EvMapping *annot_mapping;
EvAnnotation *ev_annot;
mapping = (PopplerAnnotMapping *)list->data;
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",