From f7cf22cde82aba7e3a10ec5fd1f5fd6b61f9660c Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Thu, 26 Sep 2013 19:21:34 +0300 Subject: [PATCH v8 13/15] glib: Accessors for document structure references Implements functions to work with PopplerStructureElement objects which are references to other entities in the document. Whether an element is a reference can be checked with poppler_structure_element_is_reference(), and poppler_structure_element_get_reference_type() returns the type of object referenced. For POPPLER_STRUCTURE_REFERENCE_LINK references, a PopplerAction (or PopplerLinkMapping) can be retrieved using the poppler_structure_element_get_reference_link_action() or poppler_structure_element_get_reference_link_mapping() methods. --- glib/poppler-structure-element.cc | 120 ++++++++++++++++++++++++++++++++++++++ glib/poppler-structure-element.h | 14 +++++ 2 files changed, 134 insertions(+) diff --git a/glib/poppler-structure-element.cc b/glib/poppler-structure-element.cc index 3ace95d..02d89e8 100644 --- a/glib/poppler-structure-element.cc +++ b/glib/poppler-structure-element.cc @@ -858,6 +858,126 @@ poppler_text_span_is_link (PopplerTextSpan *poppler_text_span) } /** + * poppler_structure_element_is_reference: + * @poppler_structure_element: A #PopplerStructureElement + * + * Return value: Whether the element is a reference to another object. + */ +gboolean +poppler_structure_element_is_reference (PopplerStructureElement *poppler_structure_element) +{ + g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), FALSE); + g_assert (poppler_structure_element->elem); + + return poppler_structure_element->elem->isObjectRef (); +} + +/** + * poppler_structure_element_get_reference_type: + * @poppler_structure_element: A #PopplerStructureElement + * + * Return value: The type of object pointed to by the reference, a value of + * #PopplerStructureReference. + */ +PopplerStructureReference +poppler_structure_element_get_reference_type (PopplerStructureElement *poppler_structure_element) +{ + PopplerStructureReference reftype = POPPLER_STRUCTURE_REFERENCE_UNKNOWN; + + g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), reftype); + g_assert (poppler_structure_element->elem); + + if (poppler_structure_element->elem->isObjectRef ()) + { + Object obj; + const Ref ref = poppler_structure_element->elem->getObjectRef (); + XRef *xref = poppler_structure_element->document->doc->getXRef (); + + if (xref->fetch(ref.num, ref.gen, &obj)->isDict("Annot")) + { + reftype = POPPLER_STRUCTURE_REFERENCE_ANNOT; + Object subtype; + if (obj.dictLookup("Subtype", &subtype)->isName("Link")) + reftype = POPPLER_STRUCTURE_REFERENCE_LINK; + subtype.free(); + } + + obj.free(); + } + + return reftype; +} + + +static AnnotLink * +_poppler_structure_element_find_annot_link (PopplerStructureElement *poppler_structure_element) +{ + if (poppler_structure_element_get_reference_type (poppler_structure_element) + != POPPLER_STRUCTURE_REFERENCE_LINK) + return NULL; + + gint num = poppler_structure_element_get_page (poppler_structure_element); + if (num < 0 || num >= poppler_document_get_n_pages (poppler_structure_element->document)) + return NULL; + + Page *page = poppler_structure_element->document->doc->getPage (num + 1); + Links links(page->getAnnots ()); + + for (gint i = 0; i < links.getNumLinks (); i++) + { + AnnotLink *link = links.getLink (i); + const StructElement *parent = poppler_structure_element->document->doc->getStructTreeRoot ()->findParentElement (link->getTreeKey()); + if (parent == poppler_structure_element->elem) + return link; + } + + return NULL; +} + +/** + * poppler_structure_element_get_reference_link: + * @poppler_structure_element: A #PopplerStructureElement + * + * Return value: (transfer full): The #PopplerAction associated to the + * link, or %NULL if the element is not a reference pointing to + * a link. + */ +PopplerAction * +poppler_structure_element_get_reference_link_action (PopplerStructureElement *poppler_structure_element) +{ + g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); + g_assert (poppler_structure_element->elem); + + AnnotLink *link = _poppler_structure_element_find_annot_link (poppler_structure_element); + return link ? _poppler_action_new (poppler_structure_element->document, link->getAction (), NULL) : NULL; +} + +/** + * poppler_structure_element_get_reference_link_mapping: + * @poppler_structure_element: a #PopplerStructureElement + * + * Return value: (transfer full): The #PopplerLinkMapping for the pointed + * object, or %NULL if the element is not a reference pointing to + * a link. + */ +PopplerLinkMapping * +poppler_structure_element_get_reference_link_mapping (PopplerStructureElement *poppler_structure_element) +{ + g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); + g_assert (poppler_structure_element->elem); + + AnnotLink *link = _poppler_structure_element_find_annot_link (poppler_structure_element); + if (link == NULL) + return NULL; + + gint page_num = poppler_structure_element_get_page (poppler_structure_element); + + return _poppler_link_mapping_new_from_annot_link (poppler_structure_element->document, + page_num, + link); +} + +/** * poppler_structure_element_get_form_field: * @poppler_structure_element: A #PopplerStructureElement * diff --git a/glib/poppler-structure-element.h b/glib/poppler-structure-element.h index a0c5043..8f6ad3f 100644 --- a/glib/poppler-structure-element.h +++ b/glib/poppler-structure-element.h @@ -82,6 +82,16 @@ typedef enum { POPPLER_STRUCTURE_ELEMENT_FORM, } PopplerStructureElementKind; +/** + * PopplerStructureReference: + */ +typedef enum { + POPPLER_STRUCTURE_REFERENCE_UNKNOWN, + POPPLER_STRUCTURE_REFERENCE_ANNOT, + POPPLER_STRUCTURE_REFERENCE_LINK, +} PopplerStructureReference; + + typedef struct _PopplerTextSpan PopplerTextSpan; struct _PopplerTextSpan { gchar *text; @@ -118,6 +128,10 @@ GList *poppler_structure_element_get_text_spans gboolean recursive); const gchar *poppler_structure_element_get_alt_text (PopplerStructureElement *poppler_structure_element); const gchar *poppler_structure_element_get_actual_text (PopplerStructureElement *poppler_structure_element); +gboolean poppler_structure_element_is_reference (PopplerStructureElement *poppler_structure_element); +PopplerStructureReference poppler_structure_element_get_reference_type (PopplerStructureElement *poppler_structure_element); +PopplerAction *poppler_structure_element_get_reference_link_action (PopplerStructureElement *poppler_structure_element); +PopplerLinkMapping *poppler_structure_element_get_reference_link_mapping (PopplerStructureElement *poppler_structure_element); PopplerFormField *poppler_structure_element_get_form_field (PopplerStructureElement *poppler_structure_element); PopplerFormFieldMapping *poppler_structure_element_get_form_field_mapping (PopplerStructureElement *poppler_structure_element); -- 1.8.4