[poppler] 2 commits - glib/poppler-annot.cc glib/poppler-page.cc glib/poppler-private.h

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Feb 10 16:46:02 UTC 2020


 glib/poppler-annot.cc  |  109 +++++++++++++++++++++++++++++++++++++++----------
 glib/poppler-page.cc   |   65 +++++++++++++++++++++++++++--
 glib/poppler-private.h |    2 
 3 files changed, 150 insertions(+), 26 deletions(-)

New commits:
commit d27cf873b8db1ca2b20cdc16a724c63a42d6473d
Author: Nelson Benítez León <nbenitezl at gmail.com>
Date:   Tue Oct 29 19:08:30 2019 -0400

    poppler-page: minor optimization
    
    on poppler_page_get_annot_mapping().
    Let's retrieve the cropbox just once,
    on the outside of the _for_ loop.

diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc
index f232d69e..322f2d48 100644
--- a/glib/poppler-page.cc
+++ b/glib/poppler-page.cc
@@ -1383,6 +1383,7 @@ poppler_page_get_annot_mapping (PopplerPage *page)
   double width, height;
   gint i;
   Annots *annots;
+  const PDFRectangle *crop_box;
 
   g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
@@ -1391,6 +1392,7 @@ poppler_page_get_annot_mapping (PopplerPage *page)
     return nullptr;
 
   poppler_page_get_size (page, &width, &height);
+  crop_box = page->page->getCropBox ();
 
   for (i = 0; i < annots->getNumAnnots (); i++) {
     PopplerAnnotMapping *mapping;
@@ -1442,10 +1444,10 @@ poppler_page_get_annot_mapping (PopplerPage *page)
       }
 
     annot_rect = annot->getRect ();
-    rect.x1 = annot_rect->x1 - page->page->getCropBox()->x1;
-    rect.y1 = annot_rect->y1 - page->page->getCropBox()->y1;
-    rect.x2 = annot_rect->x2 - page->page->getCropBox()->x1;
-    rect.y2 = annot_rect->y2 - page->page->getCropBox()->y1;
+    rect.x1 = annot_rect->x1 - crop_box->x1;
+    rect.y1 = annot_rect->y1 - crop_box->y1;
+    rect.x2 = annot_rect->x2 - crop_box->x1;
+    rect.y2 = annot_rect->y2 - crop_box->y1;
 
     if (! (annot->getFlags () & Annot::flagNoRotate))
       rotation = page->page->getRotate ();
commit f5ff25788ef23041a498a98e0ba9718590d96db0
Author: Nelson Benítez León <nbenitezl at gmail.com>
Date:   Mon Oct 28 21:51:21 2019 -0400

    glib: automatic handle of page's cropbox on annots
    
    Core poppler annot (Annot.cc) has cropbox offsets included
    in the coordinates of the relevant fields (rect and
    quadrilaterals fields).
    
    This commit makes poppler-glib API _not_ include cropbox
    offsets when providing annot info to clients (by substracting
    cropbox offsets from the read core Annot info) and in the same
    way, assumes no cropbox offsets are included in the info
    received from clients to create new annots (cropbox offsets will
    be automatically added to the corresponding core poppler Annot).
    
    As a result of this, existent clients (like Evince) now automatically
    work right for annotations placed in pages that have a cropbox.
    
    Poppler issue: poppler/poppler#129
    Evince issue: https://gitlab.gnome.org/GNOME/evince/issues/1280

diff --git a/glib/poppler-annot.cc b/glib/poppler-annot.cc
index 4d693869..b59926b4 100644
--- a/glib/poppler-annot.cc
+++ b/glib/poppler-annot.cc
@@ -264,30 +264,49 @@ _poppler_annot_text_markup_new (Annot *annot)
   return _poppler_create_annot (POPPLER_TYPE_ANNOT_TEXT_MARKUP, annot);
 }
 
+/* If @crop_box parameter is non null, it will add the crop_box offset
+ * to the coordinates of the returned quads */
 static AnnotQuadrilaterals *
-create_annot_quads_from_poppler_quads (GArray *quads)
+create_annot_quads_from_poppler_quads (GArray             *quads,
+                                       const PDFRectangle *crop_box)
 {
+  PDFRectangle zerobox;
   g_assert (quads->len > 0);
 
+  if (!crop_box) {
+    zerobox = PDFRectangle();
+    crop_box = &zerobox;
+  }
+
   auto quads_array = std::make_unique<AnnotQuadrilaterals::AnnotQuadrilateral[]>(quads->len);
   for (guint i = 0; i < quads->len; i++) {
     PopplerQuadrilateral *quadrilateral = &g_array_index (quads, PopplerQuadrilateral, i);
 
     quads_array[i] = AnnotQuadrilaterals::AnnotQuadrilateral (
-      quadrilateral->p1.x, quadrilateral->p1.y,
-      quadrilateral->p2.x, quadrilateral->p2.y,
-      quadrilateral->p3.x, quadrilateral->p3.y,
-      quadrilateral->p4.x, quadrilateral->p4.y);
+      quadrilateral->p1.x + crop_box->x1, quadrilateral->p1.y + crop_box->y1,
+      quadrilateral->p2.x + crop_box->x1, quadrilateral->p2.y + crop_box->y1,
+      quadrilateral->p3.x + crop_box->x1, quadrilateral->p3.y + crop_box->y1,
+      quadrilateral->p4.x + crop_box->x1, quadrilateral->p4.y + crop_box->y1);
   }
 
   return new AnnotQuadrilaterals (std::move(quads_array), quads->len);
 }
 
+/* If @crop_box parameter is non null, it will substract the crop_box offset
+ * from the coordinates of the returned #PopplerQuadrilateral array */
 static GArray *
-create_poppler_quads_from_annot_quads (AnnotQuadrilaterals *quads_array)
+create_poppler_quads_from_annot_quads (AnnotQuadrilaterals *quads_array,
+                                       const PDFRectangle  *crop_box)
 {
   GArray *quads;
   guint   quads_len;
+  PDFRectangle zerobox;
+
+  if (!crop_box) {
+    zerobox = PDFRectangle();
+    crop_box = &zerobox;
+  }
+
 
   quads_len = quads_array->getQuadrilateralsLength();
   quads = g_array_sized_new (FALSE, FALSE,
@@ -298,14 +317,14 @@ create_poppler_quads_from_annot_quads (AnnotQuadrilaterals *quads_array)
   for (guint i = 0; i < quads_len; ++i) {
     PopplerQuadrilateral *quadrilateral = &g_array_index (quads, PopplerQuadrilateral, i);
 
-    quadrilateral->p1.x = quads_array->getX1(i);
-    quadrilateral->p1.y = quads_array->getY1(i);
-    quadrilateral->p2.x = quads_array->getX2(i);
-    quadrilateral->p2.y = quads_array->getY2(i);
-    quadrilateral->p3.x = quads_array->getX3(i);
-    quadrilateral->p3.y = quads_array->getY3(i);
-    quadrilateral->p4.x = quads_array->getX4(i);
-    quadrilateral->p4.y = quads_array->getY4(i);
+    quadrilateral->p1.x = quads_array->getX1(i) - crop_box->x1;
+    quadrilateral->p1.y = quads_array->getY1(i) - crop_box->y1;
+    quadrilateral->p2.x = quads_array->getX2(i) - crop_box->x1;
+    quadrilateral->p2.y = quads_array->getY2(i) - crop_box->y1;
+    quadrilateral->p3.x = quads_array->getX3(i) - crop_box->x1;
+    quadrilateral->p3.y = quads_array->getY3(i) - crop_box->y1;
+    quadrilateral->p4.x = quads_array->getX4(i) - crop_box->x1;
+    quadrilateral->p4.y = quads_array->getY4(i) - crop_box->y1;
   }
 
   return quads;
@@ -1007,6 +1026,28 @@ poppler_annot_get_page_index (PopplerAnnot *poppler_annot)
   return page_num <= 0 ? -1 : page_num - 1;
 }
 
+/* Returns cropbox rect for the page where the passed in @poppler_annot is in,
+ * or NULL when could not retrieve the cropbox */
+const PDFRectangle *
+_poppler_annot_get_cropbox (PopplerAnnot *poppler_annot)
+{
+  int page_index;
+
+  /* A returned zero means annot is not added to any page yet */
+  page_index = poppler_annot->annot->getPageNum();
+
+  if (page_index) {
+    Page *page;
+
+    page = poppler_annot->annot->getDoc()->getPage(page_index);
+    if (page) {
+      return page->getCropBox ();
+    }
+  }
+
+  return nullptr;
+}
+
 /**
  * poppler_annot_get_rectangle:
  * @poppler_annot: a #PopplerAnnot
@@ -1022,15 +1063,23 @@ poppler_annot_get_rectangle (PopplerAnnot     *poppler_annot,
                              PopplerRectangle *poppler_rect)
 {
   PDFRectangle *annot_rect;
+  const PDFRectangle *crop_box;
+  PDFRectangle zerobox;
 
   g_return_if_fail (POPPLER_IS_ANNOT (poppler_annot));
   g_return_if_fail (poppler_rect != nullptr);
 
+  crop_box = _poppler_annot_get_cropbox (poppler_annot);
+  if (!crop_box) {
+    zerobox = PDFRectangle();
+    crop_box = &zerobox;
+  }
+
   annot_rect = poppler_annot->annot->getRect ();
-  poppler_rect->x1 = annot_rect->x1;
-  poppler_rect->x2 = annot_rect->x2;
-  poppler_rect->y1 = annot_rect->y1;
-  poppler_rect->y2 = annot_rect->y2;
+  poppler_rect->x1 = annot_rect->x1 - crop_box->x1;
+  poppler_rect->x2 = annot_rect->x2 - crop_box->x1;
+  poppler_rect->y1 = annot_rect->y1 - crop_box->y1;
+  poppler_rect->y2 = annot_rect->y2 - crop_box->y1;
 }
 
 /**
@@ -1047,11 +1096,22 @@ void
 poppler_annot_set_rectangle (PopplerAnnot     *poppler_annot,
                              PopplerRectangle *poppler_rect)
 {
+  const PDFRectangle *crop_box;
+  PDFRectangle zerobox;
+
   g_return_if_fail (POPPLER_IS_ANNOT (poppler_annot));
   g_return_if_fail (poppler_rect != nullptr);
 
-  poppler_annot->annot->setRect (poppler_rect->x1, poppler_rect->y1,
-                                 poppler_rect->x2, poppler_rect->y2);
+  crop_box = _poppler_annot_get_cropbox (poppler_annot);
+  if (!crop_box) {
+    zerobox = PDFRectangle();
+    crop_box = &zerobox;
+  }
+
+  poppler_annot->annot->setRect (poppler_rect->x1 + crop_box->x1,
+                                 poppler_rect->y1 + crop_box->y1,
+                                 poppler_rect->x2 + crop_box->x1,
+                                 poppler_rect->y2 + crop_box->y1 );
 }
 
 /* PopplerAnnotMarkup */
@@ -1614,12 +1674,14 @@ poppler_annot_text_markup_set_quadrilaterals (PopplerAnnotTextMarkup *poppler_an
                                               GArray                 *quadrilaterals)
 {
   AnnotTextMarkup *annot;
+  const PDFRectangle* crop_box;
 
   g_return_if_fail (POPPLER_IS_ANNOT_TEXT_MARKUP (poppler_annot));
   g_return_if_fail (quadrilaterals != nullptr && quadrilaterals->len > 0);
 
   annot = static_cast<AnnotTextMarkup *>(POPPLER_ANNOT (poppler_annot)->annot);
-  AnnotQuadrilaterals *quads = create_annot_quads_from_poppler_quads (quadrilaterals);
+  crop_box = _poppler_annot_get_cropbox (POPPLER_ANNOT (poppler_annot));
+  AnnotQuadrilaterals *quads = create_annot_quads_from_poppler_quads (quadrilaterals, crop_box);
   annot->setQuadrilaterals (quads);
   delete quads;
 }
@@ -1639,13 +1701,16 @@ poppler_annot_text_markup_set_quadrilaterals (PopplerAnnotTextMarkup *poppler_an
 GArray *
 poppler_annot_text_markup_get_quadrilaterals (PopplerAnnotTextMarkup *poppler_annot)
 {
+  const PDFRectangle* crop_box;
   AnnotTextMarkup *annot;
 
   g_return_val_if_fail (POPPLER_IS_ANNOT_TEXT_MARKUP (poppler_annot), NULL);
 
   annot = static_cast<AnnotTextMarkup *>(POPPLER_ANNOT (poppler_annot)->annot);
+  crop_box = _poppler_annot_get_cropbox (POPPLER_ANNOT (poppler_annot));
+  AnnotQuadrilaterals *quads = annot->getQuadrilaterals();
 
-  return create_poppler_quads_from_annot_quads (annot->getQuadrilaterals());
+  return create_poppler_quads_from_annot_quads (quads, crop_box);
 }
 
 /* PopplerAnnotFreeText */
diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc
index 319edc50..f232d69e 100644
--- a/glib/poppler-page.cc
+++ b/glib/poppler-page.cc
@@ -1502,6 +1502,34 @@ poppler_page_free_annot_mapping (GList *list)
   g_list_free_full (list, (GDestroyNotify)poppler_annot_mapping_free);
 }
 
+/* Adds or removes (according to @add parameter) the passed in @crop_box from the
+ * passed in @quads and returns it as a new #AnnotQuadrilaterals object */
+static AnnotQuadrilaterals *
+new_quads_from_offset_cropbox (const PDFRectangle* crop_box,
+                               AnnotQuadrilaterals *quads,
+                               gboolean add)
+{
+  int len = quads->getQuadrilateralsLength();
+  auto quads_array = std::make_unique<AnnotQuadrilaterals::AnnotQuadrilateral[]>(len);
+  for (int i = 0; i < len; i++) {
+     if (add) {
+       quads_array[i] = AnnotQuadrilaterals::AnnotQuadrilateral (
+         quads->getX1(i) + crop_box->x1, quads->getY1(i) + crop_box->y1,
+         quads->getX2(i) + crop_box->x1, quads->getY2(i) + crop_box->y1,
+         quads->getX3(i) + crop_box->x1, quads->getY3(i) + crop_box->y1,
+         quads->getX4(i) + crop_box->x1, quads->getY4(i) + crop_box->y1);
+     } else {
+       quads_array[i] = AnnotQuadrilaterals::AnnotQuadrilateral (
+         quads->getX1(i) - crop_box->x1, quads->getY1(i) - crop_box->y1,
+         quads->getX2(i) - crop_box->x1, quads->getY2(i) - crop_box->y1,
+         quads->getX3(i) - crop_box->x1, quads->getY3(i) - crop_box->y1,
+         quads->getX4(i) - crop_box->x1, quads->getY4(i) - crop_box->y1);
+     }
+  }
+
+  return new AnnotQuadrilaterals (std::move(quads_array), len);
+}
+
 /**
  * poppler_page_add_annot:
  * @page: a #PopplerPage
@@ -1515,9 +1543,36 @@ void
 poppler_page_add_annot (PopplerPage  *page,
 			PopplerAnnot *annot)
 {
+  double x1, y1, x2, y2;
+  const PDFRectangle *crop_box;
+  const PDFRectangle *page_crop_box;
+
   g_return_if_fail (POPPLER_IS_PAGE (page));
   g_return_if_fail (POPPLER_IS_ANNOT (annot));
 
+  /* Add the page's cropBox to the coordinates of rect field of annot */
+  page_crop_box = page->page->getCropBox ();
+  annot->annot->getRect(&x1, &y1, &x2, &y2);
+  annot->annot->setRect(x1 + page_crop_box->x1,
+                        y1 + page_crop_box->y1,
+                        x2 + page_crop_box->x1,
+                        y2 + page_crop_box->y1);
+
+  AnnotTextMarkup *annot_markup = dynamic_cast<AnnotTextMarkup*>(annot->annot);
+  if (annot_markup) {
+    AnnotQuadrilaterals *quads;
+    crop_box = _poppler_annot_get_cropbox (annot);
+    if (crop_box) {
+      /* Handle hypothetical case of annot being added is already existing on a prior page, so
+       * first remove cropbox of the prior page before adding cropbox of the new page later */
+      quads = new_quads_from_offset_cropbox (crop_box, annot_markup->getQuadrilaterals(), FALSE);
+      annot_markup->setQuadrilaterals( quads );
+    }
+    /* Add to annot's quadrilaterals the offset for the cropbox of the new page */
+    quads = new_quads_from_offset_cropbox (page_crop_box, annot_markup->getQuadrilaterals(), TRUE);
+    annot_markup->setQuadrilaterals( quads );
+  }
+
   page->page->addAnnot (annot->annot);
 }
 
diff --git a/glib/poppler-private.h b/glib/poppler-private.h
index 86b587fd..6e7e45fe 100644
--- a/glib/poppler-private.h
+++ b/glib/poppler-private.h
@@ -140,6 +140,8 @@ PopplerAnnot      *_poppler_annot_line_new (Annot *annot);
 PopplerAnnot      *_poppler_annot_circle_new (Annot *annot);
 PopplerAnnot      *_poppler_annot_square_new (Annot *annot);
 
+const PDFRectangle *_poppler_annot_get_cropbox (PopplerAnnot *poppler_annot);
+
 char *_poppler_goo_string_to_utf8(const GooString *s);
 gboolean _poppler_convert_pdf_date_to_gtime (const GooString *date,
 					     time_t    *gdate);


More information about the poppler mailing list