summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNelson Benítez León <nbenitezl@gmail.com>2019-10-28 21:51:21 -0400
committerAlbert Astals Cid <tsdgeos@yahoo.es>2020-02-10 16:42:24 +0000
commitf5ff25788ef23041a498a98e0ba9718590d96db0 (patch)
treea585009c46639a6d5a70280d82c4e3a94eb42fe5
parent8ed4623c3aad7899114ddb9754e303c97ce64e50 (diff)
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
-rw-r--r--glib/poppler-annot.cc109
-rw-r--r--glib/poppler-page.cc55
-rw-r--r--glib/poppler-private.h2
3 files changed, 144 insertions, 22 deletions
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);