From 7da41c9ed19b9d29a484416a27065c1f13b980e1 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?I=C3=B1igo=20Mart=C3=ADnez?= <inigomartinez@gmail.com>
Date: Sun, 24 Feb 2008 01:58:49 +0100
Subject: [PATCH] Improved PopplerAnnot support.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Iñigo Martínez <inigomartinez@gmail.com>
---
 glib/poppler-page.cc |  151 ++++++++++++++++++++++++++++++++++++++++++++++++++
 glib/poppler-page.h  |   15 +++++
 glib/poppler.h       |    1 +
 3 files changed, 167 insertions(+), 0 deletions(-)

diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc
index 001bb25..440c7d2 100644
--- a/glib/poppler-page.cc
+++ b/glib/poppler-page.cc
@@ -1497,6 +1497,111 @@ poppler_page_free_form_field_mapping (GList *list)
   g_list_free (list);
 }
 
+/**
+ * poppler_page_get_annot_mapping:
+ * @page: A #PopplerPage
+ *
+ * Returns a list of #PopplerAnnotMapping items that map from a location on
+ * @page to a #PopplerAnnot.  This list must be freed with
+ * poppler_page_free_annot_mapping() when done.
+ *
+ * Return value: A #GList of #PopplerAnnotMapping
+ **/
+GList *
+poppler_page_get_annot_mapping (PopplerPage *page)
+{
+  GList *map_list = NULL;
+  Annots *annots;
+  double width, height;
+
+  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
+
+  annots = page->page->getAnnots (page->document->doc->getCatalog ());
+
+  if(!annots)
+    return NULL;
+
+  poppler_page_get_size (page, &width, &height);
+  for(gint i = 0; i < annots->getNumAnnots (); i++) {
+    PopplerAnnotMapping *mapping;
+    PopplerRectangle rect;
+    Annot *annot;
+    PDFRectangle *annot_rect;
+    gint rotation = 0;
+
+    annot = annots->getAnnot (i);
+
+    /* Create the mapping */
+    mapping = g_new (PopplerAnnotMapping, 1);
+    mapping->annot = _poppler_annot_new (annot);
+
+    annot_rect = annot->getRect ();
+    rect.x1 = annot_rect->x1;
+    rect.y1 = annot_rect->y1;
+    rect.x2 = annot_rect->x2;
+    rect.y2 = annot_rect->y2;
+
+    if (! (annot->getFlags () & Annot::flagNoRotate))
+      rotation = page->page->getRotate ();
+
+    switch (rotation)
+      {
+      case 90:
+        mapping->area.x1 = rect.y1;
+        mapping->area.y1 = height - rect.x2;
+        mapping->area.x2 = mapping->area.x1 + (rect.y2 - rect.y1);
+        mapping->area.y2 = mapping->area.y1 + (rect.x2 - rect.x1);
+        break;
+      case 180:
+        mapping->area.x1 = width - rect.x2;
+        mapping->area.y1 = height - rect.y2;
+        mapping->area.x2 = mapping->area.x1 + (rect.x2 - rect.x1);
+        mapping->area.y2 = mapping->area.y1 + (rect.y2 - rect.y1);
+        break;
+      case 270:
+        mapping->area.x1 = width - rect.y2;
+        mapping->area.y1 = rect.x1;
+        mapping->area.x2 = mapping->area.x1 + (rect.y2 - rect.y1);
+        mapping->area.y2 = mapping->area.y1 + (rect.x2 - rect.x1);
+        break;
+      default:
+        mapping->area.x1 = rect.x1;
+        mapping->area.y1 = rect.y1;
+        mapping->area.x2 = rect.x2;
+        mapping->area.y2 = rect.y2;
+      }
+
+    mapping->area.x1 -= page->page->getCropBox()->x1;
+    mapping->area.x2 -= page->page->getCropBox()->x1;
+    mapping->area.y1 -= page->page->getCropBox()->y1;
+    mapping->area.y2 -= page->page->getCropBox()->y1;
+      
+    map_list = g_list_prepend (map_list, mapping);
+  }
+
+  delete annots;
+  return g_list_reverse (map_list);
+}
+
+/**
+ * poppler_page_free_annot_mapping:
+ * @list: A list of #PopplerAnnotMapping<!-- -->s
+ *
+ * Frees a list of #PopplerAnnotMapping<!-- -->s allocated by
+ * poppler_page_get_annot_mapping().  It also frees the #PopplerAnnot<!-- -->s
+ * that each mapping contains, so if you want to keep them around, you need to
+ * copy them with poppler_annot_copy().
+ **/
+void
+poppler_page_free_annot_mapping (GList *list)
+{
+  if (!list)
+    return;
+
+  g_list_foreach (list, (GFunc) (poppler_annot_mapping_free), NULL);
+  g_list_free (list);
+}
+
 /* PopplerRectangle type */
 
 GType
@@ -1697,6 +1802,52 @@ poppler_form_field_mapping_free (PopplerFormFieldMapping *mapping)
   g_free (mapping);
 }
 
+/* PopplerAnnot Mapping Type */
+GType
+poppler_annot_mapping_get_type (void)
+{
+  static GType our_type = 0;
+
+  if (our_type == 0)
+    our_type = g_boxed_type_register_static ("PopplerAnnotMapping",
+                        (GBoxedCopyFunc) poppler_annot_mapping_copy,
+                        (GBoxedFreeFunc) poppler_annot_mapping_free);
+
+  return our_type;
+}
+
+PopplerAnnotMapping *
+poppler_annot_mapping_new (void)
+{
+  return (PopplerAnnotMapping *) g_new0 (PopplerAnnotMapping, 1);
+}
+
+PopplerAnnotMapping *
+poppler_annot_mapping_copy (PopplerAnnotMapping *mapping)
+{
+  PopplerAnnotMapping *new_mapping;
+
+  new_mapping = poppler_annot_mapping_new ();
+
+  *new_mapping = *mapping;
+  if (new_mapping->annot)
+    new_mapping->annot = (PopplerAnnot *) g_object_ref (mapping->annot);
+
+  return new_mapping;
+}
+
+void
+poppler_annot_mapping_free (PopplerAnnotMapping *mapping)
+{
+  if (!mapping)
+    return;
+
+  if (mapping->annot)
+    g_object_unref (mapping->annot);
+
+  g_free (mapping);
+}
+
 void 
 poppler_page_get_crop_box (PopplerPage *page, PopplerRectangle *rect)
 {
diff --git a/glib/poppler-page.h b/glib/poppler-page.h
index f8de186..5304d0b 100644
--- a/glib/poppler-page.h
+++ b/glib/poppler-page.h
@@ -90,6 +90,8 @@ cairo_surface_t       *poppler_page_get_image            (PopplerPage        *pa
 #endif
 GList              *poppler_page_get_form_field_mapping  (PopplerPage        *page);
 void                poppler_page_free_form_field_mapping (GList              *list);
+GList                 *poppler_page_get_annot_mapping    (PopplerPage        *page);
+void                   poppler_page_free_annot_mapping   (GList              *list);
 GdkRegion             *poppler_page_get_selection_region (PopplerPage        *page,
 							  gdouble             scale,
 							  PopplerSelectionStyle style,
@@ -192,6 +194,19 @@ PopplerFormFieldMapping *poppler_form_field_mapping_new      (void);
 PopplerFormFieldMapping *poppler_form_field_mapping_copy     (PopplerFormFieldMapping *mapping);
 void                     poppler_form_field_mapping_free     (PopplerFormFieldMapping *mapping);
 
+/* Mapping between areas on the current page and annots */
+#define POPPLER_TYPE_ANNOT_MAPPING                  (poppler_annot_mapping_get_type ())
+struct _PopplerAnnotMapping
+{
+  PopplerRectangle area;
+  PopplerAnnot *annot;
+};
+
+GType                poppler_annot_mapping_get_type (void) G_GNUC_CONST;
+PopplerAnnotMapping *poppler_annot_mapping_new      (void);
+PopplerAnnotMapping *poppler_annot_mapping_copy     (PopplerAnnotMapping *mapping);
+void                 poppler_annot_mapping_free     (PopplerAnnotMapping *mapping);
+
 G_END_DECLS
 
 #endif /* __POPPLER_PAGE_H__ */
diff --git a/glib/poppler.h b/glib/poppler.h
index ecce5c0..07ef09a 100644
--- a/glib/poppler.h
+++ b/glib/poppler.h
@@ -85,6 +85,7 @@ typedef struct _PopplerLinkMapping      PopplerLinkMapping;
 typedef struct _PopplerPageTransition   PopplerPageTransition;
 typedef struct _PopplerImageMapping     PopplerImageMapping;
 typedef struct _PopplerFormFieldMapping PopplerFormFieldMapping;
+typedef struct _PopplerAnnotMapping     PopplerAnnotMapping;
 typedef struct _PopplerPage             PopplerPage;
 typedef struct _PopplerFontInfo         PopplerFontInfo;
 typedef struct _PopplerPSFile           PopplerPSFile;
-- 
1.5.3.7

