From acbfd3dc73f78ee546eb097cc1fb69389bc2608e Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Thu, 26 Sep 2013 19:21:34 +0300 Subject: [PATCH 2/2] glib: Methods to obtain link information from structure elements Implements functions to work with PopplerStructureElement objects of type POPPLER_STRUCTURE_REFERENCE_LINK: - poppler_structure_element_link_get_action() retrieves the PopplerAction associated with the link. - poppler_page_get_link_mapping_for_structure_element() obtains the PopplerLinkMapping associated with the link referenced by a structure element. --- glib/poppler-page.cc | 37 +++++++++++++ glib/poppler-page.h | 3 ++ glib/poppler-private.h | 3 ++ glib/poppler-structure-element.cc | 102 ++++++++++++++++++++++++++++++++++++ glib/poppler-structure-element.h | 1 + glib/reference/poppler-sections.txt | 2 + 6 files changed, 148 insertions(+) diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc index 34db46f..402e7c4 100644 --- a/glib/poppler-page.cc +++ b/glib/poppler-page.cc @@ -1412,6 +1412,43 @@ poppler_page_get_form_field_mapping_for_structure_element (PopplerPage } /** + * poppler_page_get_link_mapping_for_structure_element: + * @page: A #PopplerPage. + * @structure_element: A #PopplerStructureElement. + * + * Obtains the #PopplerLinkMapping for a link associated with a structure + * element of type %POPPLER_STRUCTURE_ELEMENT_LINK. The returned value + * must be freed with poppler_link_mapping_free(). + * + * Return value: (transfer full): A #PopplerLinkMapping; or %NULL if + * the element is not a %POPPLER_STRUCTURE_ELEMENT_LINK or if the + * given structure element does not have content in the page. + */ +PopplerLinkMapping * +poppler_page_get_link_mapping_for_structure_element (PopplerPage *page, + PopplerStructureElement *structure_element) +{ + g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL); + g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (structure_element), NULL); + + if (page->index != poppler_structure_element_get_page (structure_element)) + return NULL; + + AnnotLink *annot_link = + _poppler_structure_element_link_get_annot_link (structure_element); + + if (annot_link == NULL) + return NULL; + + PopplerLinkMapping *result = + _poppler_link_mapping_new_from_annot_link (structure_element->document, + page->index, + annot_link); + delete annot_link; + return result; +} + +/** * poppler_page_get_annot_mapping: * @page: A #PopplerPage * diff --git a/glib/poppler-page.h b/glib/poppler-page.h index f611b2d..12727a5 100644 --- a/glib/poppler-page.h +++ b/glib/poppler-page.h @@ -92,6 +92,9 @@ GList *poppler_page_get_form_field_mapping (PopplerPage *pa PopplerFormFieldMapping * poppler_page_get_form_field_mapping_for_structure_element(PopplerPage *page, PopplerStructureElement *structure_element); +PopplerLinkMapping * + poppler_page_get_link_mapping_for_structure_element (PopplerPage *page, + PopplerStructureElement *structure_element); 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); diff --git a/glib/poppler-private.h b/glib/poppler-private.h index 86ceb6f..a393c95 100644 --- a/glib/poppler-private.h +++ b/glib/poppler-private.h @@ -140,6 +140,9 @@ PopplerFormFieldMapping *_poppler_form_field_mapping_new_from_form_field (Popple PopplerLinkMapping *_poppler_link_mapping_new_from_annot_link (PopplerDocument *document, gint page_num, AnnotLink *link); +AnnotLink *_poppler_structure_element_link_get_annot_link (PopplerStructureElement* element); + + char *_poppler_goo_string_to_utf8(GooString *s); diff --git a/glib/poppler-structure-element.cc b/glib/poppler-structure-element.cc index 834f33b..6a7f78e 100644 --- a/glib/poppler-structure-element.cc +++ b/glib/poppler-structure-element.cc @@ -1230,6 +1230,35 @@ poppler_structure_element_get_placement (PopplerStructureElement *poppler_struct return attr_to_enum (poppler_structure_element); } +typedef enum { + REFERENCE_UNKNOWN, + REFERENCE_ANNOT, + REFERENCE_ANNOT_LINK, +} ReferenceType; + +static ReferenceType +_element_reference_type (StructElement *element, XRef *xref) +{ + g_assert (element != NULL); + + ReferenceType reftype = REFERENCE_UNKNOWN; + if (element->isObjectRef ()) + { + Object obj; + const Ref ref = element->getObjectRef (); + if (xref->fetch(ref.num, ref.gen, &obj)->isDict("Annot")) + { + reftype = REFERENCE_ANNOT; + Object subtype; + if (obj.dictLookup("Subtype", &subtype)->isName("Link")) + reftype = REFERENCE_ANNOT_LINK; + subtype.free(); + } + } + + return reftype; +} + /** * poppler_structure_element_get_writing_mode: * @poppler_structure_element: A #PopplerStructureElement @@ -1273,6 +1302,51 @@ convert_border_style (Object *object, PopplerStructureBorderStyle *values) } } +AnnotLink * +_poppler_structure_element_link_get_annot_link (PopplerStructureElement *element) +{ + /* Find the object reference that points to a link annotation */ + StructElement *objref = NULL; + XRef *xref = element->document->doc->getXRef (); + + for (guint i = 0; i < element->elem->getNumChildren (); i++) + { + StructElement *child = element->elem->getChild (i); + if (_element_reference_type (child, xref) == REFERENCE_ANNOT_LINK) + { + objref = child; + break; + } + } + + if (objref == NULL) + return NULL; + + /* The object pointed by "objref" is an AnnotLink */ + Object annot; + if (!xref->fetch(objref->getObjectRef ().num, objref->getObjectRef ().gen, &annot)->isDict ()) + { + annot.free(); + return NULL; + } + + Object annotRef; + annotRef.initRef (objref->getObjectRef ().num, objref->getObjectRef ().gen); + AnnotLink *annot_link = new AnnotLink (element->document->doc, + annot.getDict (), + &annotRef); + annotRef.free(); + annot.free(); + + if (!annot_link->isOk ()) + { + delete annot_link; + annot_link = NULL; + } + + return annot_link; +} + /** * poppler_structure_element_get_border_style: * @poppler_structure_element: A #PopplerStructureElement @@ -2291,3 +2365,31 @@ poppler_structure_element_get_table_summary (PopplerStructureElement *poppler_st g_assert_not_reached (); return NULL; } + +/** + * poppler_structure_element_link_get_action: + * @poppler_structure_element: A #PopplerStructureElement + * + * Return value: (transfer full): The #PopplerAction associated to the + * link, or %NULL if the element is not a link element. + */ +PopplerAction * +poppler_structure_element_link_get_action (PopplerStructureElement *poppler_structure_element) +{ + g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); + g_return_val_if_fail (poppler_structure_element->elem != NULL, NULL); + + if (poppler_structure_element->elem->getType () != StructElement::Link) + return NULL; + + AnnotLink *annot_link = + _poppler_structure_element_link_get_annot_link (poppler_structure_element); + + if (annot_link == NULL) + return NULL; + + PopplerAction *result = _poppler_action_new (poppler_structure_element->document, + annot_link->getAction (), NULL); + delete annot_link; + return result; +} diff --git a/glib/poppler-structure-element.h b/glib/poppler-structure-element.h index 7702a53..256d764 100644 --- a/glib/poppler-structure-element.h +++ b/glib/poppler-structure-element.h @@ -331,6 +331,7 @@ guint poppler_structure_element_get_table_column_span gchar **poppler_structure_element_get_table_headers (PopplerStructureElement *poppler_structure_element); PopplerStructureTableScope poppler_structure_element_get_table_scope (PopplerStructureElement *poppler_structure_element); gchar *poppler_structure_element_get_table_summary (PopplerStructureElement *poppler_structure_element); +PopplerAction *poppler_structure_element_link_get_action (PopplerStructureElement *poppler_structure_element); #define POPPLER_TYPE_STRUCTURE_ELEMENT_ITER (poppler_structure_element_iter_get_type ()) GType poppler_structure_element_iter_get_type (void) G_GNUC_CONST; diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt index a5dcb75..f341a0a 100644 --- a/glib/reference/poppler-sections.txt +++ b/glib/reference/poppler-sections.txt @@ -76,6 +76,7 @@ poppler_text_attributes_new poppler_text_attributes_copy poppler_text_attributes_free poppler_page_get_form_field_mapping_for_structure_element +poppler_page_get_link_mapping_for_structure_element POPPLER_PAGE @@ -660,6 +661,7 @@ poppler_structure_element_get_table_column_span poppler_structure_element_get_table_headers poppler_structure_element_get_table_scope poppler_structure_element_get_table_summary +poppler_structure_element_link_get_action poppler_text_span_copy poppler_text_span_free poppler_text_span_is_fixed_width_font -- 1.9.3