From 635bc8d135c7f0751a306ef68302e9192ffe433c Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Thu, 26 Sep 2013 19:21:34 +0300 Subject: [PATCH v18 4/5] 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 | 2 + glib/poppler-structure-element.cc | 107 ++++++++++++++++++++++++++++++++++++ glib/poppler-structure-element.h | 5 ++ glib/reference/poppler-sections.txt | 2 + 6 files changed, 156 insertions(+) diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc index 7e9c30e..cab1215 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 23f6ee7..611c7a2 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 baa58bf..f4db499 100644 --- a/glib/poppler-private.h +++ b/glib/poppler-private.h @@ -135,6 +135,8 @@ PopplerAnnot *_poppler_annot_line_new (Annot *annot); PopplerAnnot *_poppler_annot_circle_new (Annot *annot); PopplerAnnot *_poppler_annot_square_new (Annot *annot); +AnnotLink *_poppler_structure_element_link_get_annot_link (PopplerStructureElement* element); + PopplerLinkMapping *_poppler_link_mapping_new_from_annot_link (PopplerDocument *document, gint page_num, AnnotLink *link); diff --git a/glib/poppler-structure-element.cc b/glib/poppler-structure-element.cc index 750ccda..fe87fc4 100644 --- a/glib/poppler-structure-element.cc +++ b/glib/poppler-structure-element.cc @@ -911,6 +911,113 @@ poppler_text_span_is_bold_font (PopplerTextSpan *poppler_text_span) return (poppler_text_span->flags & POPPLER_TEXT_SPAN_BOLD); } + +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(); + } + + obj.free(); + } + + return reftype; +} + + +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->getNumElements (); i++) + { + StructElement *child = element->elem->getElement (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_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; +} + /** * poppler_text_span_get_color: * @poppler_text_span: a #PopplerTextSpan diff --git a/glib/poppler-structure-element.h b/glib/poppler-structure-element.h index 4e7824c..cb96d51 100644 --- a/glib/poppler-structure-element.h +++ b/glib/poppler-structure-element.h @@ -86,6 +86,10 @@ typedef enum { POPPLER_STRUCTURE_ELEMENT_FORM, } PopplerStructureElementKind; + +typedef struct _PopplerTextSpan PopplerTextSpan; + + GType poppler_structure_element_get_type (void) G_GNUC_CONST; PopplerStructureElementKind poppler_structure_element_get_kind (PopplerStructureElement *poppler_structure_element); gint poppler_structure_element_get_page (PopplerStructureElement *poppler_structure_element); @@ -104,6 +108,7 @@ gchar *poppler_structure_element_get_actual_text PopplerTextSpan **poppler_structure_element_get_text_spans (PopplerStructureElement *poppler_structure_element, guint *n_text_spans); PopplerFormField *poppler_structure_element_form_get_field (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 ()) diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt index 4f8bfef..67e8117 100644 --- a/glib/reference/poppler-sections.txt +++ b/glib/reference/poppler-sections.txt @@ -73,6 +73,7 @@ poppler_annot_mapping_free poppler_text_attributes_new poppler_text_attributes_copy poppler_text_attributes_free +poppler_page_get_link_mapping_for_structure_element POPPLER_PAGE @@ -612,6 +613,7 @@ poppler_structure_element_get_alt_text poppler_structure_element_get_actual_text poppler_structure_element_get_text_spans poppler_structure_element_form_get_field +poppler_structure_element_link_get_action poppler_text_span_copy poppler_text_span_free poppler_text_span_is_fixed_width_font -- 1.9.0