| /* poppler-structure.cc: glib interface to poppler |
| * |
| * Copyright (C) 2013 Igalia S.L. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2, or (at your option) |
| * any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "config.h" |
| |
| #ifndef __GI_SCANNER__ |
| #include <StructTreeRoot.h> |
| #include <StructElement.h> |
| #include <GlobalParams.h> |
| #include <UnicodeMap.h> |
| #endif /* !__GI_SCANNER__ */ |
| |
| #include "poppler.h" |
| #include "poppler-private.h" |
| #include "poppler-structure-element.h" |
| |
| |
| /** |
| * SECTION:poppler-structure-element |
| * @short_description: Document structure element. |
| * @title: PopplerStructureElement |
| * @see_also: #PopplerStructure |
| * |
| * Instances of #PopplerStructureElement are used to describe the structure |
| * of a #PopplerDocument. To access the elements in the structure of the |
| * document, first use poppler_document_get_structure() to obtain its |
| * #PopplerStructure, and then use poppler_structure_get_n_children() |
| * and poppler_structure_get_child() to enumerate the top level elements. |
| */ |
| |
| static PopplerStructureElement * |
| _poppler_structure_element_new (PopplerDocument *document, StructElement *element); |
| |
| |
| struct _PopplerStructureElementIter |
| { |
| PopplerDocument *document; |
| union { |
| StructElement *elem; |
| StructTreeRoot *root; |
| }; |
| gboolean is_root; |
| unsigned index; |
| }; |
| |
| POPPLER_DEFINE_BOXED_TYPE (PopplerStructureElementIter, |
| poppler_structure_element_iter, |
| poppler_structure_element_iter_copy, |
| poppler_structure_element_iter_free) |
| |
| /** |
| * poppler_structure_element_iter_copy: |
| * @iter: a #PopplerStructureElementIter |
| * |
| * Creates a new #PopplerStructureElementIter as a copy of @iter. The |
| * returned value must be freed with poppler_structure_element_iter_free(). |
| * |
| * Return value: a new #PopplerStructureElementIter |
| */ |
| PopplerStructureElementIter * |
| poppler_structure_element_iter_copy (PopplerStructureElementIter *iter) |
| { |
| PopplerStructureElementIter *new_iter; |
| |
| g_return_val_if_fail (iter != NULL, NULL); |
| |
| new_iter = g_slice_dup (PopplerStructureElementIter, iter); |
| new_iter->document = (PopplerDocument *) g_object_ref (new_iter->document); |
| |
| return new_iter; |
| } |
| |
| /** |
| * poppler_structure_element_iter_free: |
| * @iter: a #PopplerStructureElementIter |
| * |
| * Frees @iter. |
| */ |
| void |
| poppler_structure_element_iter_free (PopplerStructureElementIter *iter) |
| { |
| if (G_UNLIKELY (iter == NULL)) |
| return; |
| |
| g_object_unref (iter->document); |
| g_slice_free (PopplerStructureElementIter, iter); |
| } |
| |
| /** |
| * poppler_structure_element_iter_new: |
| * @poppler_document: a #PopplerDocument. |
| * |
| * Returns the root #PopplerStructureElementIter for @document, or %NULL. The |
| * returned value must be freed with * poppler_structure_element_iter_free(). |
| * |
| * Documents may have an associated structure tree &mdashmostly, Tagged-PDF |
| * compliant documents— which can be used to obtain information about |
| * the document structure and its contents. Each node in the tree contains |
| * a #PopplerStructureElement. |
| * |
| * Here is a simple example that walks the whole tree: |
| * |
| * <informalexample><programlisting> |
| * static void |
| * walk_structure (PopplerStructureElementIter *iter) |
| * { |
| * do { |
| * /<!-- -->* Get the element and do something with it *<!-- -->/ |
| * PopplerStructureElementIter *child = poppler_structure_element_iter_get_child (iter); |
| * if (child) |
| * walk_structure (child); |
| * poppler_structure_element_iter_free (child); |
| * } while (poppler_structure_element_iter_next (iter)); |
| * } |
| * ... |
| * { |
| * iter = poppler_structure_element_iter_new (document); |
| * walk_structure (iter); |
| * poppler_structure_element_iter_free (iter); |
| * } |
| * </programlisting></informalexample> |
| * |
| * Return value: (transfer full): a new #PopplerStructureElementIter |
| */ |
| PopplerStructureElementIter * |
| poppler_structure_element_iter_new (PopplerDocument *poppler_document) |
| { |
| PopplerStructureElementIter *iter; |
| StructTreeRoot *root; |
| |
| g_return_val_if_fail (POPPLER_IS_DOCUMENT (poppler_document), NULL); |
| |
| root = poppler_document->doc->getStructTreeRoot (); |
| if (root == NULL) |
| return NULL; |
| |
| if (root->getNumElements () == 0) |
| return NULL; |
| |
| iter = g_slice_new0 (PopplerStructureElementIter); |
| iter->document = (PopplerDocument *) g_object_ref (poppler_document); |
| iter->is_root = TRUE; |
| iter->root = root; |
| |
| return iter; |
| } |
| |
| /** |
| * poppler_structure_element_iter_next: |
| * @iter: a #PopplerStructureElementIter |
| * |
| * Sets @iter to point to the next structure element at the current level |
| * of the tree, if valid. See poppler_structure_element_iter_new() for more |
| * information. |
| * |
| * Return value: %TRUE, if @iter was set to the next structure element |
| */ |
| gboolean |
| poppler_structure_element_iter_next (PopplerStructureElementIter *iter) |
| { |
| unsigned elements; |
| |
| g_return_val_if_fail (iter != NULL, FALSE); |
| |
| elements = iter->is_root |
| ? iter->root->getNumElements () |
| : iter->elem->getNumElements (); |
| |
| return ++iter->index < elements; |
| } |
| |
| /** |
| * poppler_structure_element_iter_get_element: |
| * @iter: a #PopplerStructureElementIter |
| * |
| * Returns the #PopplerStructureElementIter associated with @iter. |
| * |
| * Return value: (transfer full): a new #PopplerStructureElementIter |
| */ |
| PopplerStructureElement * |
| poppler_structure_element_iter_get_element (PopplerStructureElementIter *iter) |
| { |
| StructElement *elem; |
| |
| g_return_val_if_fail (iter != NULL, NULL); |
| |
| elem = iter->is_root |
| ? iter->root->getElement (iter->index) |
| : iter->elem->getElement (iter->index); |
| |
| return _poppler_structure_element_new (iter->document, elem); |
| } |
| |
| /** |
| * poppler_structure_element_iter_get_child: |
| * @parent: a #PopplerStructureElementIter |
| * |
| * Return value: a new #PopplerStructureElementIter |
| */ |
| PopplerStructureElementIter * |
| poppler_structure_element_iter_get_child (PopplerStructureElementIter *parent) |
| { |
| StructElement *elem; |
| |
| g_return_val_if_fail (parent != NULL, NULL); |
| |
| elem = parent->is_root |
| ? parent->root->getElement (parent->index) |
| : parent->elem->getElement (parent->index); |
| |
| if (elem->getNumElements () > 0) |
| { |
| PopplerStructureElementIter *child = g_slice_new0 (PopplerStructureElementIter); |
| child->document = (PopplerDocument *) g_object_ref (parent->document); |
| child->elem = elem; |
| return child; |
| } |
| |
| return NULL; |
| } |
| |
| |
| static PopplerStructureElementKind |
| _poppler_structelement_type_to_poppler_structure_element_kind (StructElement::Type type) |
| { |
| switch (type) |
| { |
| case StructElement::Unknown: |
| return POPPLER_STRUCTURE_ELEMENT_UNKNOWN; |
| case StructElement::MCID: |
| return POPPLER_STRUCTURE_ELEMENT_CONTENT; |
| case StructElement::OBJR: |
| return POPPLER_STRUCTURE_ELEMENT_OBJECT_REFERENCE; |
| case StructElement::Document: |
| return POPPLER_STRUCTURE_ELEMENT_DOCUMENT; |
| case StructElement::Part: |
| return POPPLER_STRUCTURE_ELEMENT_PART; |
| case StructElement::Sect: |
| return POPPLER_STRUCTURE_ELEMENT_SECTION; |
| case StructElement::Div: |
| return POPPLER_STRUCTURE_ELEMENT_DIV; |
| case StructElement::Span: |
| return POPPLER_STRUCTURE_ELEMENT_SPAN; |
| case StructElement::Quote: |
| return POPPLER_STRUCTURE_ELEMENT_QUOTE; |
| case StructElement::Note: |
| return POPPLER_STRUCTURE_ELEMENT_NOTE; |
| case StructElement::Reference: |
| return POPPLER_STRUCTURE_ELEMENT_REFERENCE; |
| case StructElement::BibEntry: |
| return POPPLER_STRUCTURE_ELEMENT_BIBENTRY; |
| case StructElement::Code: |
| return POPPLER_STRUCTURE_ELEMENT_CODE; |
| case StructElement::Link: |
| return POPPLER_STRUCTURE_ELEMENT_LINK; |
| case StructElement::Annot: |
| return POPPLER_STRUCTURE_ELEMENT_ANNOT; |
| case StructElement::Ruby: |
| return POPPLER_STRUCTURE_ELEMENT_RUBY; |
| case StructElement::Warichu: |
| return POPPLER_STRUCTURE_ELEMENT_WARICHU; |
| case StructElement::BlockQuote: |
| return POPPLER_STRUCTURE_ELEMENT_BLOCKQUOTE; |
| case StructElement::Caption: |
| return POPPLER_STRUCTURE_ELEMENT_CAPTION; |
| case StructElement::NonStruct: |
| return POPPLER_STRUCTURE_ELEMENT_NONSTRUCT; |
| case StructElement::TOC: |
| return POPPLER_STRUCTURE_ELEMENT_TOC; |
| case StructElement::TOCI: |
| return POPPLER_STRUCTURE_ELEMENT_TOC_ITEM; |
| case StructElement::Index: |
| return POPPLER_STRUCTURE_ELEMENT_INDEX; |
| case StructElement::Private: |
| return POPPLER_STRUCTURE_ELEMENT_PRIVATE; |
| case StructElement::P: |
| return POPPLER_STRUCTURE_ELEMENT_PARAGRAPH; |
| case StructElement::H: |
| return POPPLER_STRUCTURE_ELEMENT_HEADING; |
| case StructElement::H1: |
| return POPPLER_STRUCTURE_ELEMENT_HEADING_1; |
| case StructElement::H2: |
| return POPPLER_STRUCTURE_ELEMENT_HEADING_2; |
| case StructElement::H3: |
| return POPPLER_STRUCTURE_ELEMENT_HEADING_3; |
| case StructElement::H4: |
| return POPPLER_STRUCTURE_ELEMENT_HEADING_4; |
| case StructElement::H5: |
| return POPPLER_STRUCTURE_ELEMENT_HEADING_5; |
| case StructElement::H6: |
| return POPPLER_STRUCTURE_ELEMENT_HEADING_6; |
| case StructElement::L: |
| return POPPLER_STRUCTURE_ELEMENT_LIST; |
| case StructElement::LI: |
| return POPPLER_STRUCTURE_ELEMENT_LIST_ITEM; |
| case StructElement::Lbl: |
| return POPPLER_STRUCTURE_ELEMENT_LIST_LABEL; |
| case StructElement::LBody: |
| return POPPLER_STRUCTURE_ELEMENT_LIST_BODY; |
| case StructElement::Table: |
| return POPPLER_STRUCTURE_ELEMENT_TABLE; |
| case StructElement::TR: |
| return POPPLER_STRUCTURE_ELEMENT_TABLE_ROW; |
| case StructElement::TH: |
| return POPPLER_STRUCTURE_ELEMENT_TABLE_HEADING; |
| case StructElement::TD: |
| return POPPLER_STRUCTURE_ELEMENT_TABLE_DATA; |
| case StructElement::THead: |
| return POPPLER_STRUCTURE_ELEMENT_TABLE_HEADER; |
| case StructElement::TFoot: |
| return POPPLER_STRUCTURE_ELEMENT_TABLE_FOOTER; |
| case StructElement::TBody: |
| return POPPLER_STRUCTURE_ELEMENT_TABLE_BODY; |
| case StructElement::Figure: |
| return POPPLER_STRUCTURE_ELEMENT_FIGURE; |
| case StructElement::Formula: |
| return POPPLER_STRUCTURE_ELEMENT_FORMULA; |
| case StructElement::Form: |
| return POPPLER_STRUCTURE_ELEMENT_FORM; |
| default: |
| g_assert_not_reached (); |
| } |
| } |
| |
| static GBool |
| _rgb_array_to_doubles(Array *array, double rgb[3]) |
| { |
| double r, g, b; |
| Object obj; |
| |
| if (array->getLength() != 3) |
| return FALSE; |
| |
| if (!array->getNF(0, &obj)->isReal()) goto not_a_real; |
| r = obj.getReal(); |
| obj.free(); |
| |
| if (!array->getNF(1, &obj)->isReal()) goto not_a_real; |
| g = obj.getReal(); |
| obj.free(); |
| |
| if (!array->getNF(2, &obj)->isReal()) goto not_a_real; |
| b = obj.getReal(); |
| obj.free(); |
| |
| rgb[0] = r; |
| rgb[1] = g; |
| rgb[2] = b; |
| |
| return TRUE; |
| |
| not_a_real: |
| obj.free(); |
| return FALSE; |
| } |
| |
| |
| static GVariant* |
| _g_variant_new_from_rgb_array (Array *array) |
| { |
| double v[3]; |
| |
| g_return_val_if_fail (array->getLength () == 3, NULL); |
| |
| if (!_rgb_array_to_doubles (array, v)) |
| return NULL; |
| |
| return g_variant_new ("(ddd)", v[0], v[1], v[2]); |
| } |
| |
| |
| static GVariant* |
| _g_variant_new_from_rgb_array_or_x4 (Array *array) |
| { |
| double v[12]; |
| |
| if (array->getLength() == 3) |
| { |
| if (!_rgb_array_to_doubles (array, v)) |
| return NULL; |
| |
| v[ 9] = v[6] = v[3] = v[0]; |
| v[10] = v[7] = v[4] = v[1]; |
| v[11] = v[8] = v[5] = v[2]; |
| } |
| else if (array->getLength () == 4) |
| { |
| for (int i = 0; i < 4; i++) |
| { |
| Object item; |
| if (!array->get(i, &item)->isArray()) |
| return NULL; |
| if (!_rgb_array_to_doubles (item.getArray(), &v[i * 3])) |
| return NULL; |
| } |
| } |
| else |
| return NULL; |
| |
| return g_variant_new ("((ddd)(ddd)(ddd)(ddd))", |
| v[ 0], v[ 1], v[ 2], |
| v[ 3], v[ 4], v[ 5], |
| v[ 6], v[ 7], v[ 8], |
| v[ 9], v[10], v[11]); |
| } |
| |
| |
| template <typename EnumType> |
| struct EnumNameValue { |
| const gchar *name; |
| EnumType value; |
| |
| static const EnumNameValue<EnumType> values[]; |
| static const EnumType null = static_cast<EnumType> (-1); |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructurePlacement> EnumNameValue<PopplerStructurePlacement>::values[] = |
| { |
| { "Block", POPPLER_STRUCTURE_PLACEMENT_BLOCK }, |
| { "Inline", POPPLER_STRUCTURE_PLACEMENT_INLINE }, |
| { "Before", POPPLER_STRUCTURE_PLACEMENT_BEFORE }, |
| { "Start", POPPLER_STRUCTURE_PLACEMENT_START }, |
| { "End", POPPLER_STRUCTURE_PLACEMENT_END }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureWritingMode> EnumNameValue<PopplerStructureWritingMode>::values[] = |
| { |
| { "LrTb", POPPLER_STRUCTURE_WRITING_MODE_LR_TB }, |
| { "RlTb", POPPLER_STRUCTURE_WRITING_MODE_RL_TB }, |
| { "TbRl", POPPLER_STRUCTURE_WRITING_MODE_TB_RL }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureBorderStyle> EnumNameValue<PopplerStructureBorderStyle>::values[] = |
| { |
| { "None", POPPLER_STRUCTURE_BORDER_STYLE_NONE }, |
| { "Hidden", POPPLER_STRUCTURE_BORDER_STYLE_HIDDEN }, |
| { "Dotted", POPPLER_STRUCTURE_BORDER_STYLE_DOTTED }, |
| { "Dashed", POPPLER_STRUCTURE_BORDER_STYLE_DASHED }, |
| { "Solid", POPPLER_STRUCTURE_BORDER_STYLE_SOLID }, |
| { "Double", POPPLER_STRUCTURE_BORDER_STYLE_DOUBLE }, |
| { "Groove", POPPLER_STRUCTURE_BORDER_STYLE_GROOVE }, |
| { "Inset", POPPLER_STRUCTURE_BORDER_STYLE_INSET }, |
| { "Outset", POPPLER_STRUCTURE_BORDER_STYLE_OUTSET }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureTextAlign> EnumNameValue<PopplerStructureTextAlign>::values[] = |
| { |
| { "Start", POPPLER_STRUCTURE_TEXT_ALIGN_START }, |
| { "Center", POPPLER_STRUCTURE_TEXT_ALIGN_CENTER }, |
| { "End", POPPLER_STRUCTURE_TEXT_ALIGN_END }, |
| { "Justify", POPPLER_STRUCTURE_TEXT_ALIGN_JUSTIFY }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureBlockAlign> EnumNameValue<PopplerStructureBlockAlign>::values[] = |
| { |
| { "Before", POPPLER_STRUCTURE_BLOCK_ALIGN_BEFORE }, |
| { "Middle", POPPLER_STRUCTURE_BLOCK_ALIGN_MIDDLE }, |
| { "After", POPPLER_STRUCTURE_BLOCK_ALIGN_AFTER }, |
| { "Justify", POPPLER_STRUCTURE_BLOCK_ALIGN_JUSTIFY }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureInlineAlign> EnumNameValue<PopplerStructureInlineAlign>::values[] = |
| { |
| { "Start", POPPLER_STRUCTURE_INLINE_ALIGN_START }, |
| { "Center", POPPLER_STRUCTURE_INLINE_ALIGN_CENTER }, |
| { "End", POPPLER_STRUCTURE_INLINE_ALIGN_END }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureTextDecoration> EnumNameValue<PopplerStructureTextDecoration>::values[] = |
| { |
| { "None", POPPLER_STRUCTURE_TEXT_DECORATION_NONE }, |
| { "Underline", POPPLER_STRUCTURE_TEXT_DECORATION_UNDERLINE }, |
| { "Overline", POPPLER_STRUCTURE_TEXT_DECORATION_OVERLINE }, |
| { "LineThrough", POPPLER_STRUCTURE_TEXT_DECORATION_LINETHROUGH }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureRubyAlign> EnumNameValue<PopplerStructureRubyAlign>::values[] = |
| { |
| { "Start", POPPLER_STRUCTURE_RUBY_ALIGN_START }, |
| { "Center", POPPLER_STRUCTURE_RUBY_ALIGN_CENTER }, |
| { "End", POPPLER_STRUCTURE_RUBY_ALIGN_END }, |
| { "Justify", POPPLER_STRUCTURE_RUBY_ALIGN_JUSTIFY }, |
| { "Distribute", POPPLER_STRUCTURE_RUBY_ALIGN_DISTRIBUTE }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureRubyPosition> EnumNameValue<PopplerStructureRubyPosition>::values[] = |
| { |
| { "Before", POPPLER_STRUCTURE_RUBY_POSITION_BEFORE }, |
| { "After", POPPLER_STRUCTURE_RUBY_POSITION_AFTER }, |
| { "Warichu", POPPLER_STRUCTURE_RUBY_POSITION_WARICHU }, |
| { "Inline", POPPLER_STRUCTURE_RUBY_POSITION_INLINE }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureGlyphOrientation> EnumNameValue<PopplerStructureGlyphOrientation>::values[] = |
| { |
| { "Auto", POPPLER_STRUCTURE_GLYPH_ORIENTATION_AUTO }, |
| { "90", POPPLER_STRUCTURE_GLYPH_ORIENTATION_90 }, |
| { "180", POPPLER_STRUCTURE_GLYPH_ORIENTATION_180 }, |
| { "270", POPPLER_STRUCTURE_GLYPH_ORIENTATION_270 }, |
| { "360", POPPLER_STRUCTURE_GLYPH_ORIENTATION_0 }, |
| { "-90", POPPLER_STRUCTURE_GLYPH_ORIENTATION_270 }, |
| { "-180", POPPLER_STRUCTURE_GLYPH_ORIENTATION_180 }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureListNumbering> EnumNameValue<PopplerStructureListNumbering>::values[] = |
| { |
| { "None", POPPLER_STRUCTURE_LIST_NUMBERING_NONE }, |
| { "Disc", POPPLER_STRUCTURE_LIST_NUMBERING_DISC }, |
| { "Circle", POPPLER_STRUCTURE_LIST_NUMBERING_CIRCLE }, |
| { "Square", POPPLER_STRUCTURE_LIST_NUMBERING_SQUARE }, |
| { "Decimal", POPPLER_STRUCTURE_LIST_NUMBERING_DECIMAL }, |
| { "UpperRoman", POPPLER_STRUCTURE_LIST_NUMBERING_UPPER_ROMAN }, |
| { "LowerRoman", POPPLER_STRUCTURE_LIST_NUMBERING_LOWER_ROMAN }, |
| { "UpperAlpha", POPPLER_STRUCTURE_LIST_NUMBERING_UPPER_ALPHA }, |
| { "LowerAlpha", POPPLER_STRUCTURE_LIST_NUMBERING_LOWER_ALPHA }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureRole> EnumNameValue<PopplerStructureRole>::values[] = |
| { |
| { "rb", POPPLER_STRUCTURE_ROLE_RADIO_BUTTON }, |
| { "cb", POPPLER_STRUCTURE_ROLE_CHECKBOX }, |
| { "pb", POPPLER_STRUCTURE_ROLE_PUSH_BUTTON }, |
| { "tv", POPPLER_STRUCTURE_ROLE_TEXT_VALUE }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureChecked> EnumNameValue<PopplerStructureChecked>::values[] = |
| { |
| { "on", POPPLER_STRUCTURE_CHECKED_ON }, |
| { "off", POPPLER_STRUCTURE_CHECKED_OFF }, |
| { "neutral", POPPLER_STRUCTURE_CHECKED_NEUTRAL }, |
| { NULL } |
| }; |
| |
| template<> |
| const EnumNameValue<PopplerStructureScope> EnumNameValue<PopplerStructureScope>::values[] = |
| { |
| { "Row", POPPLER_STRUCTURE_SCOPE_ROW }, |
| { "Column", POPPLER_STRUCTURE_SCOPE_COLUMN }, |
| { "Both", POPPLER_STRUCTURE_SCOPE_BOTH }, |
| { NULL } |
| }; |
| |
| template <typename EnumType> |
| static EnumType |
| name_to_enum (Object *name_value, |
| EnumType default_value = EnumType::null) |
| { |
| if (!name_value) |
| return default_value; |
| |
| for (const EnumNameValue<EnumType> *item = EnumNameValue<EnumType>::values ; item->name; item++) |
| if (name_value->isName (item->name)) |
| return item->value; |
| |
| return default_value; |
| } |
| |
| |
| template <typename EnumType> |
| static GVariant* |
| name_to_variant_enum (Object *name_value, |
| EnumType default_value = EnumNameValue<EnumType>::null) |
| { |
| EnumType value = name_to_enum<EnumType> (name_value, default_value); |
| return value == EnumNameValue<EnumType>::null ? NULL : g_variant_new_uint32 (value); |
| } |
| |
| |
| static GVariant* |
| string_to_variant (Object *object) |
| { |
| if (object->isName ()) |
| return g_variant_new_string (object->getName ()); |
| if (object->isString ()) |
| { |
| gchar *utf8_string = _poppler_goo_string_to_utf8 (object->getString ()); |
| GVariant* result = g_variant_new_string (utf8_string); |
| g_free (utf8_string); |
| return result; |
| } |
| return NULL; |
| } |
| |
| |
| static GVariant* |
| _g_variant_new_from_border_style (Object *object) |
| { |
| PopplerStructureBorderStyle border_style[4]; |
| |
| if (object->isArray () && object->arrayGetLength () == 4) |
| { |
| Object item; |
| for (int i = 0; i < 4; i++) |
| border_style[i] = name_to_enum<PopplerStructureBorderStyle> (object->arrayGet (i, &item), |
| POPPLER_STRUCTURE_BORDER_STYLE_NONE); |
| } |
| else if (object->isName ()) |
| { |
| border_style[0] = border_style[1] = border_style[2] = border_style[3] = |
| name_to_enum <PopplerStructureBorderStyle> (object, POPPLER_STRUCTURE_BORDER_STYLE_NONE); |
| } |
| else |
| return NULL; |
| |
| return g_variant_new ("(uuuu)", |
| border_style[0], |
| border_style[1], |
| border_style[2], |
| border_style[3]); |
| } |
| |
| |
| static GVariant* |
| _g_variant_new_from_number_or_x4 (Object *object) |
| { |
| double v[4]; |
| |
| if (object->isArray () && object->arrayGetLength () == 4) |
| { |
| Object item; |
| for (int i = 0; i < 4; i++) |
| { |
| if (object->arrayGet (i, &item)->isReal ()) |
| v[i] = item.getReal (); |
| else if (item.isInt ()) |
| v[i] = (double) item.getInt (); |
| else |
| return NULL; |
| } |
| } |
| else if (object->isReal ()) |
| v[0] = v[1] = v[2] = v[3] = object->getReal (); |
| else if (object->isInt ()) |
| v[0] = v[1] = v[2] = v[3] = (double) object->getInt (); |
| else |
| return NULL; |
| |
| return g_variant_new ("(dddd)", v[0], v[1], v[2], v[3]); |
| } |
| |
| |
| static inline GVariant* |
| _g_variant_new_from_number_x4 (Object *object) |
| { |
| return object->isArray () ? _g_variant_new_from_number_or_x4 (object) : NULL; |
| } |
| |
| |
| static GVariant* |
| _g_variant_new_from_number (Object *object) |
| { |
| if (object->isReal ()) |
| return g_variant_new_double (object->getReal ()); |
| if (object->isInt ()) |
| return g_variant_new_double ((double) object->getInt ()); |
| return NULL; |
| } |
| |
| |
| static GVariant* |
| _g_variant_new_from_number_or_auto (Object *object) |
| { |
| if (object->isName ("Auto")) |
| return g_variant_new ("md", NULL); |
| if (object->isReal ()) |
| return g_variant_new ("md", object->getReal ()); |
| if (object->isInt ()) |
| return g_variant_new ("md", (double) object->getInt ()); |
| return NULL; |
| } |
| |
| |
| static inline GVariant* |
| _g_variant_new_from_number_or_auto_or_normal (Object *object) |
| { |
| return object->isName ("Normal") ? g_variant_new ("md", NULL) |
| : _g_variant_new_from_number_or_auto (object); |
| } |
| |
| |
| static GVariant* |
| _g_variant_new_number_array (Object *object) |
| { |
| GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ad")); |
| |
| if (object->isReal ()) |
| g_variant_builder_add (builder, "d", object->getReal ()); |
| else if (object->isInt ()) |
| g_variant_builder_add (builder, "d", (double) object->getInt ()); |
| else if (object->isArray ()) |
| { |
| for (int i = 0; i < object->arrayGetLength (); i++) |
| { |
| Object item; |
| if (object->arrayGet (i, &item)->isReal ()) |
| g_variant_builder_add (builder, "d", item.getReal ()); |
| else if (item.isInt ()) |
| g_variant_builder_add (builder, "d", (double) item.getInt ()); |
| } |
| } |
| |
| GVariant *value = g_variant_new ("ad", builder); |
| g_variant_builder_unref (builder); |
| return value; |
| } |
| |
| |
| static GVariant* |
| _g_variant_new_string_array (Object *object) |
| { |
| GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); |
| |
| if (object->isName ()) |
| g_variant_builder_add (builder, "s", object->getName ()); |
| else if (object->isString ()) |
| { |
| gchar *utf8_string = _poppler_goo_string_to_utf8 (object->getString ()); |
| g_variant_builder_add (builder, "s", utf8_string); |
| g_free (utf8_string); |
| } |
| else if (object->isArray ()) |
| { |
| for (int i = 0; i < object->arrayGetLength (); i++) |
| { |
| Object item; |
| if (object->arrayGet (i, &item)->isName ()) |
| g_variant_builder_add (builder, "s", object->getName ()); |
| else if (object->isString ()) |
| { |
| gchar *utf8_string = _poppler_goo_string_to_utf8 (object->getString ()); |
| g_variant_builder_add (builder, "s", utf8_string); |
| g_free (utf8_string); |
| } |
| } |
| } |
| |
| GVariant *value = g_variant_new ("as", builder); |
| g_variant_builder_unref (builder); |
| return value; |
| } |
| |
| |
| static inline Object* |
| attr_value_or_default (PopplerStructureElement *poppler_structure_element, |
| Attribute::Type attribute_type, |
| gboolean inherit) |
| { |
| Object *value = Attribute::getDefaultValue (attribute_type); |
| const Attribute *attr; |
| |
| if ((attr = poppler_structure_element->elem->findAttribute (attribute_type, inherit))) |
| value = attr->getValue (); |
| |
| return value; |
| } |
| |
| |
| static void _poppler_text_span_free (gpointer data) |
| { |
| PopplerTextSpan *span = (PopplerTextSpan*) data; |
| g_free (span->text); |
| g_free (span->font_name); |
| g_free (span->link_target); |
| g_slice_free (PopplerTextSpan, data); |
| } |
| |
| |
| typedef struct _PopplerStructureElementClass PopplerStructureElementClass; |
| struct _PopplerStructureElementClass |
| { |
| GObjectClass parent_class; |
| }; |
| |
| G_DEFINE_TYPE (PopplerStructureElement, poppler_structure_element, G_TYPE_OBJECT); |
| |
| |
| static PopplerStructureElement * |
| _poppler_structure_element_new (PopplerDocument *document, StructElement *element) |
| { |
| PopplerStructureElement *poppler_structure_element; |
| |
| g_assert (POPPLER_IS_DOCUMENT (document)); |
| g_assert (element); |
| |
| poppler_structure_element = (PopplerStructureElement *) g_object_new (POPPLER_TYPE_STRUCTURE_ELEMENT, NULL, NULL); |
| poppler_structure_element->document = (PopplerDocument *) g_object_ref (document); |
| poppler_structure_element->elem = element; |
| |
| return poppler_structure_element; |
| } |
| |
| |
| static void |
| poppler_structure_element_init (PopplerStructureElement *poppler_structure_element) |
| { |
| } |
| |
| |
| static void |
| poppler_structure_element_finalize (GObject *object) |
| { |
| PopplerStructureElement *poppler_structure_element = POPPLER_STRUCTURE_ELEMENT (object); |
| |
| /* poppler_structure_element->elem is owned by the StructTreeRoot */ |
| g_free (poppler_structure_element->language); |
| g_free (poppler_structure_element->text_r); |
| g_free (poppler_structure_element->text); |
| g_free (poppler_structure_element->title); |
| g_free (poppler_structure_element->id); |
| g_object_unref (poppler_structure_element->document); |
| g_list_free_full (poppler_structure_element->text_spans, _poppler_text_span_free); |
| |
| G_OBJECT_CLASS (poppler_structure_element_parent_class)->finalize (object); |
| } |
| |
| |
| static void |
| poppler_structure_element_class_init (PopplerStructureElementClass *klass) |
| { |
| GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
| gobject_class->finalize = poppler_structure_element_finalize; |
| } |
| |
| |
| /** |
| * poppler_structure_element_get_kind: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Return value: A #PopplerStructureElementKind value. |
| */ |
| PopplerStructureElementKind |
| poppler_structure_element_get_kind (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), POPPLER_STRUCTURE_ELEMENT_UNKNOWN); |
| g_assert (poppler_structure_element->elem); |
| |
| return _poppler_structelement_type_to_poppler_structure_element_kind (poppler_structure_element->elem->getType ()); |
| } |
| |
| /** |
| * poppler_structure_element_get_page: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Return value: Number of the page that contains the element, of |
| * <code>-1</code> if not defined. |
| */ |
| gint |
| poppler_structure_element_get_page (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), POPPLER_STRUCTURE_ELEMENT_UNKNOWN); |
| g_assert (poppler_structure_element->elem); |
| |
| Ref ref; |
| if (poppler_structure_element->elem->getPageRef (ref)) |
| { |
| return poppler_structure_element->document->doc->findPage(ref.num, ref.gen) - 1; |
| } |
| |
| return -1; |
| } |
| |
| /** |
| * poppler_structure_element_is_content: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Checks whether an element is actual document content. |
| * |
| * Return value: Whether the element is content. |
| */ |
| gboolean |
| poppler_structure_element_is_content (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->isContent (); |
| } |
| |
| /** |
| * poppler_structure_element_is_inline: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Checks whether an element is an inline element. |
| * |
| * Return value: Whether the element is inline. |
| */ |
| gboolean |
| poppler_structure_element_is_inline (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->isInline (); |
| } |
| |
| /** |
| * poppler_structure_element_is_block: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Checks whether an element is a block element. |
| * |
| * Return value: Whether the element is block. |
| */ |
| gboolean |
| poppler_structure_element_is_block (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->isBlock (); |
| } |
| |
| /** |
| * poppler_structure_element_get_id: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Return value: (transfer none): The identifier of the element (if |
| * defined), or %NULL. |
| */ |
| const gchar* |
| poppler_structure_element_get_id (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); |
| g_assert (poppler_structure_element->elem); |
| |
| if (!poppler_structure_element->id && poppler_structure_element->elem->getID ()) |
| poppler_structure_element->id = _poppler_goo_string_to_utf8 (poppler_structure_element->elem->getID ()); |
| |
| return poppler_structure_element->id; |
| } |
| |
| /** |
| * poppler_structure_element_get_title: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Return value: (transfer none): The title of the element (if defined), |
| * or %NULL. |
| */ |
| const gchar* |
| poppler_structure_element_get_title (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); |
| g_assert (poppler_structure_element->elem); |
| |
| if (!poppler_structure_element->title && poppler_structure_element->elem->getTitle ()) |
| poppler_structure_element->title = _poppler_goo_string_to_utf8 (poppler_structure_element->elem->getTitle ()); |
| |
| return poppler_structure_element->title; |
| } |
| |
| /** |
| * popppler_structure_element_get_abbreviation: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Acronyms and abbreviations contained in elements of type |
| * #POPPLER_STRUCTURE_ELEMENT_SPAN may have an associated expanded |
| * text form, which can be retrieved using this function. |
| * |
| * Return value: (transfer none): Text of the expanded abbreviation, if the |
| * element text is an abbreviation or acronym. |
| */ |
| const gchar* |
| poppler_structure_element_get_abbreviation (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); |
| g_assert (poppler_structure_element->elem); |
| |
| if (poppler_structure_element->elem->getType () != StructElement::Span) |
| return NULL; |
| |
| if (!poppler_structure_element->text_abbrev && poppler_structure_element->elem->getExpandedAbbr ()) |
| poppler_structure_element->text_abbrev = _poppler_goo_string_to_utf8 (poppler_structure_element->elem->getExpandedAbbr ()); |
| |
| return poppler_structure_element->text_abbrev; |
| } |
| |
| /** |
| * poppler_structure_element_get_language: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Return value: (transfer none): language and country code, in two-letter |
| * ISO format, e.g. <code>en_US</code>, or %NULL if not defined. |
| */ |
| const gchar* |
| poppler_structure_element_get_language (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); |
| g_assert (poppler_structure_element->elem); |
| |
| if (!poppler_structure_element->language && poppler_structure_element->elem->getLanguage ()) |
| poppler_structure_element->language = _poppler_goo_string_to_utf8 (poppler_structure_element->elem->getLanguage ()); |
| |
| return poppler_structure_element->language; |
| } |
| |
| /** |
| * poppler_structure_element_get_alt_text: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Obtains the “alternate” text representation of the element (and its child |
| * elements). This is mostly used for non-text elements like images and |
| * figures, to specify a textual description of the element. |
| * |
| * Note that for elements containing proper text, the function |
| * poppler_structure_element_get_text() must be used instead. |
| * |
| * Return value: (transfer none): The alternate text representation for the |
| * element, or %NULL if not defined. |
| */ |
| const gchar* |
| poppler_structure_element_get_alt_text (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); |
| g_assert (poppler_structure_element->elem); |
| |
| if (!poppler_structure_element->alt_text && poppler_structure_element->elem->getAltText ()) |
| { |
| GooString *s = poppler_structure_element->elem->getAltText (); |
| if (s) |
| poppler_structure_element->alt_text = _poppler_goo_string_to_utf8 (s); |
| delete s; |
| } |
| |
| return poppler_structure_element->alt_text; |
| } |
| |
| /** |
| * poppler_structure_element_get_actual_text: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Obtains the actual text enclosed by the element (and its child elements). |
| * The actual text is mostly used for non-text elements like images and |
| * figures which <em>do</em> have the graphical appearance of text, like |
| * a logo. For those the actual text is the equivalent text to those |
| * graphical elements which look like text when rendered. |
| * |
| * Note that for elements containing proper text, the function |
| * poppler_structure_element_get_text() must be used instead. |
| * |
| * Return value: (transfer none): The actual text for the element, or %NULL |
| * if not defined. |
| */ |
| const gchar* |
| poppler_structure_element_get_actual_text (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); |
| g_assert (poppler_structure_element->elem); |
| |
| if (!poppler_structure_element->actual_text && poppler_structure_element->elem->getActualText ()) |
| { |
| GooString *s = poppler_structure_element->elem->getActualText (); |
| if (s) |
| poppler_structure_element->actual_text = _poppler_goo_string_to_utf8 (s); |
| delete s; |
| } |
| |
| return poppler_structure_element->actual_text; |
| } |
| |
| /** |
| * poppler_structure_element_get_text: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * @recursive: If %TRUE, the text of child elements is gathered recursively |
| * in logical order and returned as part of the result. |
| * |
| * Obtains the text enclosed by an element, or the subtree under an element. |
| * |
| * Return value: (transfer none): A string. |
| */ |
| const gchar* |
| poppler_structure_element_get_text (PopplerStructureElement *poppler_structure_element, |
| gboolean recursive) |
| { |
| if (recursive) |
| { |
| if (!poppler_structure_element->text_r) |
| { |
| GooString *s = poppler_structure_element->elem->getText (NULL, gTrue); |
| if (s) |
| poppler_structure_element->text_r = _poppler_goo_string_to_utf8 (s); |
| delete s; |
| } |
| return poppler_structure_element->text_r; |
| } |
| |
| if (!poppler_structure_element->text) |
| { |
| GooString *s = poppler_structure_element->elem->getText (NULL, gFalse); |
| if (s) |
| poppler_structure_element->text = _poppler_goo_string_to_utf8 (s); |
| delete s; |
| } |
| return poppler_structure_element->text; |
| } |
| |
| |
| class SpanBuilder { |
| public: |
| SpanBuilder(): |
| font(), text(), link(), |
| map(globalParams->getTextEncoding()), |
| glist(NULL), |
| flags(0), |
| color(0) |
| {} |
| |
| ~SpanBuilder() { |
| map->decRefCnt(); |
| g_list_free_full (glist, _poppler_text_span_free); |
| } |
| |
| void process(const MCOpArray& ops) { |
| for (MCOpArray::const_iterator i = ops.begin(); i != ops.end(); ++i) |
| process(*i); |
| } |
| |
| void process(const MCOp& op) { |
| if (op.type == MCOp::Unichar) { |
| int n = map->mapUnicode(op.unichar, buf, sizeof(buf)); |
| text.append(buf, n); |
| return; |
| } |
| |
| Guint oldFlags = flags; |
| |
| if (op.type == MCOp::Flags) { |
| if (op.flags & MCOp::FlagFontBold) |
| flags |= POPPLER_TEXT_SPAN_BOLD; |
| else |
| flags &= ~POPPLER_TEXT_SPAN_BOLD; |
| |
| if (op.flags & MCOp::FlagFontFixed) |
| flags |= POPPLER_TEXT_SPAN_FIXED_WIDTH; |
| else |
| flags &= ~POPPLER_TEXT_SPAN_FIXED_WIDTH; |
| |
| if (op.flags & MCOp::FlagFontItalic) |
| flags |= POPPLER_TEXT_SPAN_ITALIC; |
| else |
| flags &= ~POPPLER_TEXT_SPAN_ITALIC; |
| } |
| |
| if (op.type == MCOp::Color && (color = op.color.rgbPixel ())) { |
| flags |= POPPLER_TEXT_SPAN_COLOR; |
| } else { |
| flags &= ~POPPLER_TEXT_SPAN_COLOR; |
| } |
| |
| if (op.type == MCOp::FontName) { |
| if (op.value) { |
| flags |= POPPLER_TEXT_SPAN_FONT; |
| font.append(op.value); |
| } else { |
| flags &= ~POPPLER_TEXT_SPAN_FONT; |
| } |
| } |
| |
| if (flags != oldFlags) |
| newSpan(); |
| } |
| |
| void newSpan() { |
| // If there is no text, do not append a new PopplerTextSpan |
| // and keep the attributes/flags for the next span. |
| if (text.getLength ()) { |
| PopplerTextSpan *span = g_slice_new0 (PopplerTextSpan); |
| span->color = color; |
| span->flags = flags; |
| span->text = _poppler_goo_string_to_utf8 (&text); |
| text.clear(); |
| |
| if (font.getLength()) { |
| span->font_name = _poppler_goo_string_to_utf8 (&font); |
| font.clear(); |
| } |
| |
| if (link.getLength()) { |
| assert(flags & POPPLER_TEXT_SPAN_LINK); |
| span->link_target = _poppler_goo_string_to_utf8 (&link); |
| } |
| |
| glist = g_list_append (glist, span); |
| } |
| |
| // Link is always cleared |
| link.clear(); |
| } |
| |
| GList* end() { |
| GList *result = glist; |
| glist = NULL; |
| return result; |
| } |
| |
| private: |
| GooString font; |
| GooString text; |
| GooString link; |
| UnicodeMap *map; |
| GList *glist; |
| char buf[8]; |
| Guint flags; |
| Guint color; |
| }; |
| |
| |
| /** |
| * poppler_structure_element_get_text_spans: |
| * @poppler_structure_element: A #PopplerStructureElement |
| * |
| * Obtains the text enclosed by an element, as a #GList of #PopplerTextSpan |
| * structures. Each item in the list is a piece of text which share the same |
| * attributes, plus its attributes. |
| * |
| * Return value: (transfer none) (element-type PopplerTextSpan): A #GList |
| * of #PopplerTextSpan structures. |
| */ |
| GList* |
| poppler_structure_element_get_text_spans (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); |
| g_assert (poppler_structure_element->elem); |
| |
| if (!poppler_structure_element->elem->isContent ()) |
| return NULL; |
| |
| if (!poppler_structure_element->text_spans) |
| { |
| SpanBuilder builder; |
| builder.process(poppler_structure_element->elem->getMCOps ()); |
| poppler_structure_element->text_spans = builder.end(); |
| } |
| return poppler_structure_element->text_spans; |
| } |
| |
| /** |
| * poppler_text_span_is_fixed_width: |
| * @poppler_text_span: a #PopplerTextSpan |
| */ |
| gboolean |
| poppler_text_span_is_fixed_width (PopplerTextSpan *poppler_text_span) |
| { |
| return (poppler_text_span->flags & POPPLER_TEXT_SPAN_FIXED_WIDTH); |
| } |
| |
| /** |
| * poppler_text_span_is_serif_font: |
| * @poppler_text_span: a #PopplerTextSpan |
| */ |
| gboolean |
| poppler_text_span_is_serif_font (PopplerTextSpan *poppler_text_span) |
| { |
| return (poppler_text_span->flags & POPPLER_TEXT_SPAN_SERIF_FONT); |
| } |
| |
| /** |
| * poppler_text_span_is_bols: |
| * @poppler_text_span: a #PopplerTextSpan |
| */ |
| gboolean |
| poppler_text_span_is_bold (PopplerTextSpan *poppler_text_span) |
| { |
| return (poppler_text_span->flags & POPPLER_TEXT_SPAN_BOLD); |
| } |
| |
| /** |
| * poppler_text_span_is_link: |
| * @poppler_text_span: a #PopplerTextSpan |
| */ |
| gboolean |
| poppler_text_span_is_link (PopplerTextSpan *poppler_text_span) |
| { |
| return (poppler_text_span->flags & POPPLER_TEXT_SPAN_LINK); |
| } |
| |
| /** |
| * poppler_structure_element_get_attribute: |
| * @poppler_structure_element: A #PopplerStructureElement. |
| * @attribute: A #PopperStructureAttribute value. |
| * @value (out): A #GValue in which to return the value of the attribute. |
| * @inherit: Whether to look up for inheritable attribute values in the |
| * ancestors of the element, if the attribute is not defined in the |
| * element. |
| * |
| * <table> |
| * <title>Types returned for each attribute</title> |
| * <thead> |
| * <tr> |
| * <th>Attributes</th> |
| * <th>Returned type</th> |
| * </tr> |
| * </thead> |
| * <tbody> |
| * <tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_PLACEMENT</code></td> |
| * <td>A #PopplerStructurePlacement value, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_WRITING_MODE</code></td> |
| * <td>A #PopplerStructureWritingMode value, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_TEXT_ALIGN</code></td> |
| * <td>A #PopplerStructureTextAlign, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_BLOCK_ALIGN</code></td> |
| * <td>A #PopplerStructureBlockAlign, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_INLINE_ALIGN</code></td> |
| * <td>A #PopplerStructureInlineAlign, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_TEXT_DECORATION</code></td> |
| * <td>A #PopplerStructureTextDecoration value, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_RUBY_ALIGN</code></td> |
| * <td>A #PopplerStructureRubyAlign value, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_RUBY_POSITION</code></td> |
| * <td>A #PopplerStructureRubyPosition value, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_GLYPH_ORIENTATION</code></td> |
| * <td>A #PopplerStructureGlyphOrientation value, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_LIST_NUMBERING</code></td> |
| * <td>A #PopplerStructureListNumbering value, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_ROLE</code></td> |
| * <td>A #PopplerStructureRole value, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_CHECKED</code></td> |
| * <td>A #PopplerStructureChecked value, as a <code>guint32</code>.</td> |
| * </tr><tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_SCOPE</code></td> |
| * <td>A #PopplerStructureScope value, as a <code>guint32</code>.</td> |
| * </tr> |
| * <tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_DESCRIPTION</code></td> |
| * <td rowspan="2">A string, as a <code>const gchar*</code>.</td> |
| * </tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_SUMMARY</code></td></tr> |
| * <tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_SPACE_BEFORE</code></td> |
| * <td rowspan="10">Number, as a <code>double</code>.</td> |
| * </tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_SPACE_AFTER</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_START_INDENT</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_END_INDENT</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_TEXT_INDENT</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_BASELINE_SHIFT</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_TEXT_DECORATION_THICKNESS</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_COUNT</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_ROW_SPAN</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_SPAN</code></td></tr> |
| * <tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_GAP</code></td> |
| * <td rowspan="2"> |
| * An array of <code>double</code> numbers. The type of the |
| * returned #GVariant is <code>ad</code>. |
| * </td> |
| * </tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_WIDTHS</code></td></tr> |
| * <tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_WIDTH</code></td> |
| * <td rowspan="3"> |
| * A maybe-double number. That is, a #GVariant with type |
| * <code>md</code>. If the number is undefined, the value |
| * is meant to be calculated automatically. |
| * </td> |
| * </tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_HEIGHT</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_LINE_HEIGHT</code></td></tr> |
| * <tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_COLOR</code></td> |
| * <td rowspan="3"> |
| * A 3-tuple of doubles, with values in the <code>[0, 1]</code> range, |
| * in red-green-blue (RGB) order. The type of the returned #GVariant is |
| * <code>(ddd)</code>. |
| * </td> |
| * </tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_BACKGROUND_COLOR</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_TEXT_DECORATION_COLOR</code></td></tr> |
| * <tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_BORDER_COLOR</code></td> |
| * <td>A 4-tuple of 3-tuples. Each one of the tuples is a RGB color, |
| * being each color component a double in the <code>[0, 1]</code> |
| * range. The four returned colors are in top-right-bottom-left |
| * order. The type of the returned #GVariant is |
| * <code>((ddd)(ddd)(ddd)(ddd))</code>. |
| * </td> |
| * </tr> |
| * <tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_BORDER_STYLE</code></td> |
| * <td rowspan="2"> |
| * A 4-tuple of #PopplerStructureBorderStyle values, each one as a |
| * %guint32, in top-right-bottom-left order. The type of the |
| * returned #GVariant is <code>(uuuu)</code>. |
| * </td> |
| * </tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_TABLE_BORDER_STYLE</code></td></tr> |
| * <tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_BORDER_THICKNESS</code></td> |
| * <td rowspan="4"> |
| * A 4-tuple of #double numbers, in top-right-bottom-left order. |
| * The type of the returned #GVariant is <code>(dddd)</code>. |
| * </td> |
| * </tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_TABLE_PADDING</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_PADDING</code></td></tr> |
| * <tr><td><code>POPPLER_STRUCTURE_ATTRIBUTE_BBOX</code></td></tr> |
| * <tr> |
| * <td><code>POPPLER_STRUCTURE_ATTRIBUTE_HEADERS</code></td> |
| * <td>An array of strings, each string being a <code>const gchar*</code>. |
| * The type of the returned #GVariant is <code>as</code>.</td> |
| * </tr> |
| * </tbody> |
| * </table> |
| * |
| * Return value: (transfer full): A #GVariant, with value varying depending |
| * on the attribute requested, as specified in the table. If the |
| * attribute is not defined, <code>NULL</code> is returned. |
| */ |
| GVariant* |
| poppler_structure_element_get_attribute (PopplerStructureElement *poppler_structure_element, |
| PopplerStructureAttribute attribute, |
| gboolean inherit) |
| { |
| Object *value = NULL; |
| |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); |
| g_return_val_if_fail (attribute != POPPLER_STRUCTURE_ATTRIBUTE_UNKNOWN, NULL); |
| g_return_val_if_fail (attribute != POPPLER_STRUCTURE_ATTRIBUTE_USER_PROPERTY, NULL); |
| |
| switch (attribute) |
| { |
| case POPPLER_STRUCTURE_ATTRIBUTE_PLACEMENT: |
| return name_to_variant_enum<PopplerStructurePlacement> (attr_value_or_default (poppler_structure_element, |
| Attribute::Placement, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_WRITING_MODE: |
| return name_to_variant_enum<PopplerStructureWritingMode> (attr_value_or_default (poppler_structure_element, |
| Attribute::WritingMode, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_BACKGROUND_COLOR: |
| value = attr_value_or_default (poppler_structure_element, Attribute::BackgroundColor, inherit); |
| return (value && value->isArray ()) ? _g_variant_new_from_rgb_array (value->getArray ()) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_BORDER_COLOR: |
| value = attr_value_or_default (poppler_structure_element, Attribute::BorderColor, inherit); |
| return (value && value->isArray ()) ? _g_variant_new_from_rgb_array_or_x4 (value->getArray ()) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_BORDER_STYLE: |
| value = attr_value_or_default (poppler_structure_element, Attribute::BorderStyle, inherit); |
| return value ?_g_variant_new_from_border_style (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_BORDER_THICKNESS: |
| value = attr_value_or_default (poppler_structure_element, Attribute::BorderThickness, inherit); |
| return value ? _g_variant_new_from_number_or_x4 (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_COLOR: |
| value = attr_value_or_default (poppler_structure_element, Attribute::Color, inherit); |
| return (value && value->isArray ()) ? _g_variant_new_from_rgb_array (value->getArray ()) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_PADDING: |
| value = attr_value_or_default (poppler_structure_element, Attribute::Padding, inherit); |
| return value ? _g_variant_new_from_number_or_x4 (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_SPACE_BEFORE: |
| value = attr_value_or_default (poppler_structure_element, Attribute::SpaceBefore, inherit); |
| return value ? _g_variant_new_from_number (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_SPACE_AFTER: |
| value = attr_value_or_default (poppler_structure_element, Attribute::SpaceAfter, inherit); |
| return value ? _g_variant_new_from_number (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_START_INDENT: |
| value = attr_value_or_default (poppler_structure_element, Attribute::StartIndent, inherit); |
| return value ? _g_variant_new_from_number (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_END_INDENT: |
| value = attr_value_or_default (poppler_structure_element, Attribute::EndIndent, inherit); |
| return value ? _g_variant_new_from_number (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_TEXT_INDENT: |
| value = attr_value_or_default (poppler_structure_element, Attribute::TextIndent, inherit); |
| return value ? _g_variant_new_from_number (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_TEXT_ALIGN: |
| return name_to_variant_enum<PopplerStructureTextAlign> (attr_value_or_default (poppler_structure_element, |
| Attribute::TextAlign, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_BBOX: |
| value = attr_value_or_default (poppler_structure_element, Attribute::BBox, inherit); |
| return value ? _g_variant_new_from_number_x4 (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_WIDTH: |
| value = attr_value_or_default (poppler_structure_element, Attribute::Width, inherit); |
| return value ? _g_variant_new_from_number_or_auto (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_HEIGHT: |
| value = attr_value_or_default (poppler_structure_element, Attribute::Height, inherit); |
| return value ? _g_variant_new_from_number_or_auto (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_BLOCK_ALIGN: |
| return name_to_variant_enum<PopplerStructureBlockAlign> (attr_value_or_default (poppler_structure_element, |
| Attribute::BlockAlign, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_INLINE_ALIGN: |
| return name_to_variant_enum<PopplerStructureInlineAlign> (attr_value_or_default (poppler_structure_element, |
| Attribute::InlineAlign, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_TABLE_BORDER_STYLE: |
| value = attr_value_or_default (poppler_structure_element, Attribute::TBorderStyle, inherit); |
| return value ?_g_variant_new_from_border_style (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_TABLE_PADDING: |
| value = attr_value_or_default (poppler_structure_element, Attribute::TPadding, inherit); |
| return value ? _g_variant_new_from_number_or_x4 (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_BASELINE_SHIFT: |
| value = attr_value_or_default (poppler_structure_element, Attribute::BaselineShift, inherit); |
| return value ? _g_variant_new_from_number (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_LINE_HEIGHT: |
| value = attr_value_or_default (poppler_structure_element, Attribute::LineHeight, inherit); |
| return value ? _g_variant_new_from_number_or_auto_or_normal (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_TEXT_DECORATION_COLOR: |
| value = attr_value_or_default (poppler_structure_element, Attribute::TextDecorationColor, inherit); |
| return (value && value->isArray ()) ? _g_variant_new_from_rgb_array (value->getArray ()) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_TEXT_DECORATION_THICKNESS: |
| value = attr_value_or_default (poppler_structure_element, Attribute::LineHeight, inherit); |
| return value ? _g_variant_new_from_number (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_TEXT_DECORATION: |
| return name_to_variant_enum<PopplerStructureTextDecoration> (attr_value_or_default (poppler_structure_element, |
| Attribute::TextDecorationType, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_RUBY_ALIGN: |
| return name_to_variant_enum<PopplerStructureRubyAlign> (attr_value_or_default (poppler_structure_element, |
| Attribute::RubyAlign, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_RUBY_POSITION: |
| return name_to_variant_enum<PopplerStructureRubyPosition> (attr_value_or_default (poppler_structure_element, |
| Attribute::RubyPosition, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_GLYPH_ORIENTATION: |
| return name_to_variant_enum<PopplerStructureGlyphOrientation> (attr_value_or_default (poppler_structure_element, |
| Attribute::GlyphOrientationVertical, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_COUNT: |
| value = attr_value_or_default (poppler_structure_element, Attribute::ColumnCount, inherit); |
| return value ? _g_variant_new_from_number (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_GAP: |
| value = attr_value_or_default (poppler_structure_element, Attribute::ColumnGap, inherit); |
| return value ? _g_variant_new_number_array (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_WIDTHS: |
| value = attr_value_or_default (poppler_structure_element, Attribute::ColumnGap, inherit); |
| return value ? _g_variant_new_number_array (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_LIST_NUMBERING: |
| return name_to_variant_enum<PopplerStructureListNumbering> (attr_value_or_default (poppler_structure_element, |
| Attribute::ListNumbering, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_ROLE: |
| return name_to_variant_enum<PopplerStructureRole> (attr_value_or_default (poppler_structure_element, |
| Attribute::Role, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_CHECKED: |
| return name_to_variant_enum<PopplerStructureChecked> (attr_value_or_default (poppler_structure_element, |
| Attribute::checked, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_DESCRIPTION: |
| return string_to_variant (attr_value_or_default (poppler_structure_element, |
| Attribute::Desc, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_ROW_SPAN: |
| value = attr_value_or_default (poppler_structure_element, Attribute::RowSpan, inherit); |
| return value ? _g_variant_new_from_number (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_SPAN: |
| value = attr_value_or_default (poppler_structure_element, Attribute::ColSpan, inherit); |
| return value ? _g_variant_new_from_number (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_HEADERS: |
| value = attr_value_or_default (poppler_structure_element, Attribute::Headers, inherit); |
| return value ? _g_variant_new_string_array (value) : NULL; |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_SCOPE: |
| return name_to_variant_enum<PopplerStructureScope> (attr_value_or_default (poppler_structure_element, |
| Attribute::Scope, inherit)); |
| case POPPLER_STRUCTURE_ATTRIBUTE_SUMMARY: |
| return string_to_variant (attr_value_or_default (poppler_structure_element, Attribute::Summary, inherit)); |
| |
| case POPPLER_STRUCTURE_ATTRIBUTE_USER_PROPERTY: |
| case POPPLER_STRUCTURE_ATTRIBUTE_UNKNOWN: |
| default: |
| g_assert_not_reached (); |
| return NULL; |
| } |
| } |
| |
| /** |
| * 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 |
| * |
| * Return value: (transfer full): A #PopplerFormField, or %NULL if |
| * the element is not a %POPPLER_STRUCTURE_ELEMENT_FORM. |
| */ |
| PopplerFormField * |
| poppler_structure_element_get_form_field (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); |
| g_assert (poppler_structure_element->elem); |
| |
| if (poppler_structure_element->elem->getType () != StructElement::Form) |
| return NULL; |
| |
| // TODO Handle elements which have a Role attribute (used sometimes for |
| // non-editable widgets, to describe their appearance). Editable |
| // fields have only a single child, with the field identifier. |
| if (poppler_structure_element->elem->getNumElements () != 1) |
| return NULL; |
| |
| gint field_id = -1; |
| const StructElement *child = poppler_structure_element->elem->getElement (0); |
| if (child->isContent ()) |
| { |
| if (child->isObjectRef ()) |
| { |
| // TODO Handle this case -- I have yet to see a PDF using this. |
| } |
| else |
| { |
| // Element contains the form field ID as the MCID attribute. |
| field_id = child->getMCID (); |
| } |
| } |
| |
| if (field_id < 0) |
| return NULL; |
| |
| return (field_id < 0) ? NULL : poppler_document_get_form_field (poppler_structure_element->document, |
| field_id); |
| } |
| |
| /** |
| * poppler_structure_element_get_form_field_mapping: |
| * @poppler_structure_element: a #PopplerStructureElement |
| * |
| * Return value: (transfer full): A #PopplerFormFieldMapping, or %NULL if |
| * the element is not a %POPPLER_STRUCTURE_ELEMENT_FORM |
| */ |
| PopplerFormFieldMapping * |
| poppler_structure_element_get_form_field_mapping (PopplerStructureElement *poppler_structure_element) |
| { |
| g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL); |
| g_assert (poppler_structure_element->elem); |
| |
| PopplerFormField *field = poppler_structure_element_get_form_field (poppler_structure_element); |
| if (field == NULL) |
| return NULL; |
| |
| gint page_num = poppler_structure_element_get_page (poppler_structure_element); |
| return _poppler_form_field_mapping_new_from_form_field (field, page_num); |
| } |