blob: 8a1b167e57b68338b1a6b89bf8d7ba25ea6a4279 [file] [log] [blame]
/* poppler-structure.cc: glib interface to poppler
*
* Copyright (C) 2013 Igalia S.L.
* Copyright (C) 2018 Albert Astals Cid <aacid@kde.org>
*
* 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>
#include <math.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
*
* Instances of #PopplerStructureElement are used to describe the structure
* of a #PopplerDocument. To access the elements in the structure of the
* document, use poppler_structure_element_iter_new() to obtain an iterator
* for the top-level #PopplerStructureElement, and then use the
* #PopplerStructureElementIter methods to traverse the structure tree.
*/
typedef struct _PopplerStructureElementClass
{
GObjectClass parent_class;
} PopplerStructureElementClass;
G_DEFINE_TYPE (PopplerStructureElement, poppler_structure_element, G_TYPE_OBJECT)
static PopplerStructureElement *
_poppler_structure_element_new (PopplerDocument *document, const 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, nullptr, 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_object_unref (poppler_structure_element->document);
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.
*
* Since: 0.26
*/
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_CONTENT);
g_return_val_if_fail (poppler_structure_element->elem != nullptr, POPPLER_STRUCTURE_ELEMENT_CONTENT);
switch (poppler_structure_element->elem->getType ())
{
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::Art:
return POPPLER_STRUCTURE_ELEMENT_ARTICLE;
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::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::Ruby:
return POPPLER_STRUCTURE_ELEMENT_RUBY;
case StructElement::RB:
return POPPLER_STRUCTURE_ELEMENT_RUBY_BASE_TEXT;
case StructElement::RT:
return POPPLER_STRUCTURE_ELEMENT_RUBY_ANNOT_TEXT;
case StructElement::RP:
return POPPLER_STRUCTURE_ELEMENT_RUBY_PUNCTUATION;
case StructElement::Warichu:
return POPPLER_STRUCTURE_ELEMENT_WARICHU;
case StructElement::WT:
return POPPLER_STRUCTURE_ELEMENT_WARICHU_TEXT;
case StructElement::WP:
return POPPLER_STRUCTURE_ELEMENT_WARICHU_PUNCTUATION;
case StructElement::Figure:
return POPPLER_STRUCTURE_ELEMENT_FIGURE;
case StructElement::Formula:
return POPPLER_STRUCTURE_ELEMENT_FORMULA;
case StructElement::Form:
return POPPLER_STRUCTURE_ELEMENT_FORM;
/* There should never be elements of type StructElement::Unknown */
case StructElement::Unknown:
g_assert_not_reached ();
}
g_assert_not_reached ();
return POPPLER_STRUCTURE_ELEMENT_CONTENT;
}
template <typename EnumType>
struct EnumNameValue {
const gchar *name;
EnumType value;
static const EnumNameValue<EnumType> values[];
static const Attribute::Type attribute_type;
};
#define ENUM_VALUES(E, A) \
template<> const Attribute::Type EnumNameValue<E>::attribute_type = Attribute::A; \
template<> const EnumNameValue<E> EnumNameValue<E>::values[] =
ENUM_VALUES (PopplerStructurePlacement, Placement)
{
{ "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 },
{ }
};
ENUM_VALUES (PopplerStructureWritingMode, WritingMode)
{
{ "LrTb", POPPLER_STRUCTURE_WRITING_MODE_LR_TB },
{ "RlTb", POPPLER_STRUCTURE_WRITING_MODE_RL_TB },
{ "TbRl", POPPLER_STRUCTURE_WRITING_MODE_TB_RL },
{ }
};
ENUM_VALUES (PopplerStructureBorderStyle, BorderStyle)
{
{ "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 },
{ }
};
ENUM_VALUES (PopplerStructureTextAlign, TextAlign)
{
{ "Start", POPPLER_STRUCTURE_TEXT_ALIGN_START },
{ "Center", POPPLER_STRUCTURE_TEXT_ALIGN_CENTER },
{ "End", POPPLER_STRUCTURE_TEXT_ALIGN_END },
{ "Justify", POPPLER_STRUCTURE_TEXT_ALIGN_JUSTIFY },
{ }
};
ENUM_VALUES (PopplerStructureBlockAlign, BlockAlign)
{
{ "Before", POPPLER_STRUCTURE_BLOCK_ALIGN_BEFORE },
{ "Middle", POPPLER_STRUCTURE_BLOCK_ALIGN_MIDDLE },
{ "After", POPPLER_STRUCTURE_BLOCK_ALIGN_AFTER },
{ "Justify", POPPLER_STRUCTURE_BLOCK_ALIGN_JUSTIFY },
{ }
};
ENUM_VALUES (PopplerStructureInlineAlign, InlineAlign)
{
{ "Start", POPPLER_STRUCTURE_INLINE_ALIGN_START },
{ "Center", POPPLER_STRUCTURE_INLINE_ALIGN_CENTER },
{ "End", POPPLER_STRUCTURE_INLINE_ALIGN_END },
{ }
};
ENUM_VALUES (PopplerStructureTextDecoration, TextDecorationType)
{
{ "None", POPPLER_STRUCTURE_TEXT_DECORATION_NONE },
{ "Underline", POPPLER_STRUCTURE_TEXT_DECORATION_UNDERLINE },
{ "Overline", POPPLER_STRUCTURE_TEXT_DECORATION_OVERLINE },
{ "LineThrough", POPPLER_STRUCTURE_TEXT_DECORATION_LINETHROUGH },
{ }
};
ENUM_VALUES (PopplerStructureRubyAlign, RubyAlign)
{
{ "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 },
{ }
};
ENUM_VALUES (PopplerStructureRubyPosition, RubyPosition)
{
{ "Before", POPPLER_STRUCTURE_RUBY_POSITION_BEFORE },
{ "After", POPPLER_STRUCTURE_RUBY_POSITION_AFTER },
{ "Warichu", POPPLER_STRUCTURE_RUBY_POSITION_WARICHU },
{ "Inline", POPPLER_STRUCTURE_RUBY_POSITION_INLINE },
{ }
};
ENUM_VALUES (PopplerStructureGlyphOrientation, GlyphOrientationVertical)
{
{ "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 },
{ }
};
ENUM_VALUES (PopplerStructureListNumbering, ListNumbering)
{
{ "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 },
{ }
};
ENUM_VALUES (PopplerStructureFormRole, Role)
{
{ "rb", POPPLER_STRUCTURE_FORM_ROLE_RADIO_BUTTON },
{ "cb", POPPLER_STRUCTURE_FORM_ROLE_CHECKBOX },
{ "pb", POPPLER_STRUCTURE_FORM_ROLE_PUSH_BUTTON },
{ "tv", POPPLER_STRUCTURE_FORM_ROLE_TEXT_VALUE },
{ }
};
ENUM_VALUES (PopplerStructureFormState, checked)
{
{ "on", POPPLER_STRUCTURE_FORM_STATE_ON },
{ "off", POPPLER_STRUCTURE_FORM_STATE_OFF },
{ "neutral", POPPLER_STRUCTURE_FORM_STATE_NEUTRAL },
{ }
};
ENUM_VALUES (PopplerStructureTableScope, Scope)
{
{ "Row", POPPLER_STRUCTURE_TABLE_SCOPE_ROW },
{ "Column", POPPLER_STRUCTURE_TABLE_SCOPE_COLUMN },
{ "Both", POPPLER_STRUCTURE_TABLE_SCOPE_BOTH },
{ }
};
#undef ENUM_VALUES
template <typename EnumType>
static EnumType
name_to_enum (Object *name_value)
{
/*
* Non-NULL names must always be valid because Poppler
* discards the invalid attributes when parsing them.
*/
g_assert (name_value != nullptr);
for (const EnumNameValue<EnumType> *item = EnumNameValue<EnumType>::values ; item->name; item++)
if (name_value->isName (item->name))
return item->value;
g_assert_not_reached ();
return static_cast<EnumType> (-1);
}
template <typename EnumType>
static EnumType
attr_to_enum (PopplerStructureElement *poppler_structure_element)
{
const Attribute *attr =
poppler_structure_element->elem->findAttribute (EnumNameValue<EnumType>::attribute_type, true);
return name_to_enum<EnumType> ((attr != nullptr)
? attr->getValue ()
: Attribute::getDefaultValue (EnumNameValue<EnumType>::attribute_type));
}
static inline Object *
attr_value_or_default (PopplerStructureElement *poppler_structure_element,
Attribute::Type attribute_type)
{
const Attribute *attr =
poppler_structure_element->elem->findAttribute (attribute_type, true);
return attr ? attr->getValue () : Attribute::getDefaultValue (attribute_type);
}
/**
* poppler_structure_element_get_page:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the page number in which the element is contained.
*
* Return value: Number of the page that contains the element, of
* <code>-1</code> if not defined.
*
* Since: 0.26
*/
gint
poppler_structure_element_get_page (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), -1);
g_return_val_if_fail (poppler_structure_element->elem != nullptr, -1);
Ref ref;
if (poppler_structure_element->elem->getPageRef (ref))
{
return poppler_structure_element->document->doc->findPage(ref) - 1;
}
return -1;
}
/**
* poppler_structure_element_is_content:
* @poppler_structure_element: A #PopplerStructureElement
*
* Checks whether an element is actual document content.
*
* Return value: %TRUE if the element is content, or %FALSE otherwise.
*
* Since: 0.26
*/
gboolean
poppler_structure_element_is_content (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), FALSE);
g_return_val_if_fail (poppler_structure_element->elem != nullptr, FALSE);
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: %TRUE if the element is an inline element, or %FALSE otherwise.
*
* Since: 0.26
*/
gboolean
poppler_structure_element_is_inline (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), FALSE);
g_return_val_if_fail (poppler_structure_element->elem != nullptr, FALSE);
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: %TRUE if the element is a block element, or %FALSE otherwise.
*
* Since: 0.26
*/
gboolean
poppler_structure_element_is_block (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), FALSE);
g_return_val_if_fail (poppler_structure_element->elem != nullptr, FALSE);
return poppler_structure_element->elem->isBlock ();
}
/**
* poppler_structure_element_is_grouping:
* @poppler_structure_element: A #PopplerStructureElement
*
* Checks whether an element is a grouping element.
*
* Return value: %TRUE if the element is a grouping element, %FALSE
* otherwise.
*
* Since: 0.26
*/
gboolean
poppler_structure_element_is_grouping (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), FALSE);
g_return_val_if_fail (poppler_structure_element->elem != nullptr, FALSE);
return poppler_structure_element->elem->isGrouping ();
}
/**
* poppler_structure_element_get_id:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the identifier of an element.
*
* Return value: (transfer full): The identifier of the element (if
* defined), or %NULL.
*
* Since: 0.26
*/
gchar *
poppler_structure_element_get_id (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 != nullptr, NULL);
const GooString *string = poppler_structure_element->elem->getID ();
return string ? _poppler_goo_string_to_utf8 (string) : nullptr;
}
/**
* poppler_structure_element_get_title:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the title of an element.
*
* Return value: (transfer full): The title of the element, or %NULL.
*
* Since: 0.26
*/
gchar *
poppler_structure_element_get_title (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 != nullptr, NULL);
const GooString *string = poppler_structure_element->elem->getTitle ();
return string ? _poppler_goo_string_to_utf8 (string) : nullptr;
}
/**
* poppler_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 full): Text of the expanded abbreviation if the
* element text is an abbreviation or acrony, %NULL if not.
*
* Since: 0.26
*/
gchar *
poppler_structure_element_get_abbreviation (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 != nullptr, NULL);
if (poppler_structure_element->elem->getType () != StructElement::Span)
return nullptr;
const GooString *string = poppler_structure_element->elem->getExpandedAbbr ();
return string ? _poppler_goo_string_to_utf8 (string) : nullptr;
}
/**
* poppler_structure_element_get_language:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the language and country code for the content in an element,
* in two-letter ISO format, e.g. <code>en_ES</code>, or %NULL if not
* defined.
*
* Return value: (transfer full): language and country code, or %NULL.
*
* Since: 0.26
*/
gchar *
poppler_structure_element_get_language (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 != nullptr, NULL);
const GooString *string = poppler_structure_element->elem->getLanguage ();
return string ? _poppler_goo_string_to_utf8 (string) : nullptr;
}
/**
* 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 full): The alternate text representation for the
* element, or %NULL if not defined.
*
* Since: 0.26
*/
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_return_val_if_fail (poppler_structure_element->elem != nullptr, NULL);
const GooString *string = poppler_structure_element->elem->getAltText ();
return string ? _poppler_goo_string_to_utf8 (string) : nullptr;
}
/**
* 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 <emphasis>do</emphasis> 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 full): The actual text for the element, or %NULL
* if not defined.
*
* Since: 0.26
*/
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_return_val_if_fail (poppler_structure_element->elem != nullptr, NULL);
const GooString *string = poppler_structure_element->elem->getActualText ();
return string ? _poppler_goo_string_to_utf8 (string) : nullptr;
}
/**
* poppler_structure_element_get_text:
* @poppler_structure_element: A #PopplerStructureElement
* @flags: A #PopplerStructureGetTextFlags value, or
* %POPPLER_STRUCTURE_GET_TEXT_NONE to disable all the flags.
*
* Obtains the text enclosed by an element, or the text enclosed by the
* elements in the subtree (including the element itself).
*
* Return value: (transfer full): A string.
*
* Since: 0.26
*/
gchar *
poppler_structure_element_get_text (PopplerStructureElement *poppler_structure_element,
PopplerStructureGetTextFlags flags)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL);
g_return_val_if_fail (poppler_structure_element->elem != nullptr, NULL);
GooString *string =
poppler_structure_element->elem->getText (flags & POPPLER_STRUCTURE_GET_TEXT_RECURSIVE);
gchar *result = string ? _poppler_goo_string_to_utf8 (string) : nullptr;
delete string;
return result;
}
struct _PopplerStructureElementIter
{
PopplerDocument *document;
union {
const StructElement *elem;
const 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: (transfer full): a new #PopplerStructureElementIter
*
* Since: 0.26
*/
PopplerStructureElementIter *
poppler_structure_element_iter_copy (PopplerStructureElementIter *iter)
{
PopplerStructureElementIter *new_iter;
g_return_val_if_fail (iter != nullptr, 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.
*
* Since: 0.26
*/
void
poppler_structure_element_iter_free (PopplerStructureElementIter *iter)
{
if (G_UNLIKELY (iter == nullptr))
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&mdash; 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, or %NULL if document
* doesn't have structure tree.
*
* Since: 0.26
*/
PopplerStructureElementIter *
poppler_structure_element_iter_new (PopplerDocument *poppler_document)
{
PopplerStructureElementIter *iter;
g_return_val_if_fail (POPPLER_IS_DOCUMENT (poppler_document), NULL);
const StructTreeRoot *root = poppler_document->doc->getStructTreeRoot ();
if (root == nullptr)
return nullptr;
if (root->getNumChildren () == 0)
return nullptr;
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
*
* Since: 0.26
*/
gboolean
poppler_structure_element_iter_next (PopplerStructureElementIter *iter)
{
unsigned elements;
g_return_val_if_fail (iter != nullptr, FALSE);
elements = iter->is_root
? iter->root->getNumChildren ()
: iter->elem->getNumChildren ();
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
*
* Since: 0.26
*/
PopplerStructureElement *
poppler_structure_element_iter_get_element (PopplerStructureElementIter *iter)
{
g_return_val_if_fail (iter != nullptr, NULL);
const StructElement *elem = iter->is_root
? iter->root->getChild (iter->index)
: iter->elem->getChild (iter->index);
return _poppler_structure_element_new (iter->document, elem);
}
/**
* poppler_structure_element_iter_get_child:
* @parent: a #PopplerStructureElementIter
*
* Returns a new iterator to the children elements of the
* #PopplerStructureElement associated with @iter. The returned value must
* be freed with poppler_structure_element_iter_free().
*
* Return value: a new #PopplerStructureElementIter
*
* Since: 0.26
*/
PopplerStructureElementIter *
poppler_structure_element_iter_get_child (PopplerStructureElementIter *parent)
{
const StructElement *elem;
g_return_val_if_fail (parent != nullptr, NULL);
elem = parent->is_root
? parent->root->getChild (parent->index)
: parent->elem->getChild (parent->index);
if (elem->getNumChildren () > 0)
{
PopplerStructureElementIter *child = g_slice_new0 (PopplerStructureElementIter);
child->document = (PopplerDocument *) g_object_ref (parent->document);
child->elem = elem;
return child;
}
return nullptr;
}
struct _PopplerTextSpan {
gchar *text;
gchar *font_name;
guint flags;
PopplerColor color;
};
POPPLER_DEFINE_BOXED_TYPE (PopplerTextSpan,
poppler_text_span,
poppler_text_span_copy,
poppler_text_span_free)
enum {
POPPLER_TEXT_SPAN_FIXED_WIDTH = (1 << 0),
POPPLER_TEXT_SPAN_SERIF = (1 << 1),
POPPLER_TEXT_SPAN_ITALIC = (1 << 2),
POPPLER_TEXT_SPAN_BOLD = (1 << 3),
};
static PopplerTextSpan *
text_span_poppler_text_span (const TextSpan& span)
{
PopplerTextSpan *new_span = g_slice_new0 (PopplerTextSpan);
if (GooString *text = span.getText ())
new_span->text = _poppler_goo_string_to_utf8 (text);
new_span->color.red = colToDbl (span.getColor ().r) * 65535;
new_span->color.green = colToDbl (span.getColor ().g) * 65535;
new_span->color.blue = colToDbl (span.getColor ().b) * 65535;
if (span.getFont ())
{
// GfxFont sometimes does not have a family name but there
// is always a font name that can be used as fallback.
const GooString *font_name = span.getFont ()->getFamily ();
if (font_name == nullptr)
font_name = span.getFont ()->getName ();
new_span->font_name = _poppler_goo_string_to_utf8 (font_name);
if (span.getFont ()->isFixedWidth ())
new_span->flags |= POPPLER_TEXT_SPAN_FIXED_WIDTH;
if (span.getFont ()->isSerif ())
new_span->flags |= POPPLER_TEXT_SPAN_SERIF;
if (span.getFont ()->isItalic ())
new_span->flags |= POPPLER_TEXT_SPAN_ITALIC;
if (span.getFont ()->isBold ())
new_span->flags |= POPPLER_TEXT_SPAN_BOLD;
/* isBold() can return false for some fonts whose weight is heavy */
switch (span.getFont ()->getWeight ())
{
case GfxFont::W500:
case GfxFont::W600:
case GfxFont::W700:
case GfxFont::W800:
case GfxFont::W900:
new_span->flags |= POPPLER_TEXT_SPAN_BOLD;
default:
break;
}
}
return new_span;
}
/**
* poppler_text_span_copy:
* @poppler_text_span: a #PopplerTextSpan
*
* Makes a copy of a text span.
*
* Return value: (transfer full): A new #PopplerTextSpan
*
* Since: 0.26
*/
PopplerTextSpan *
poppler_text_span_copy (PopplerTextSpan *poppler_text_span)
{
PopplerTextSpan *new_span;
g_return_val_if_fail (poppler_text_span != nullptr, NULL);
new_span = g_slice_dup (PopplerTextSpan, poppler_text_span);
new_span->text = g_strdup (poppler_text_span->text);
if (poppler_text_span->font_name)
new_span->font_name = g_strdup (poppler_text_span->font_name);
return new_span;
}
/**
* poppler_text_span_free:
* @poppler_text_span: A #PopplerTextSpan
*
* Frees a text span.
*
* Since: 0.26
*/
void
poppler_text_span_free (PopplerTextSpan *poppler_text_span)
{
if (G_UNLIKELY (poppler_text_span == nullptr))
return;
g_free (poppler_text_span->text);
g_free (poppler_text_span->font_name);
g_slice_free (PopplerTextSpan, poppler_text_span);
}
/**
* poppler_text_span_is_fixed_width_font:
* @poppler_text_span: a #PopplerTextSpan
*
* Check wether a text span is meant to be rendered using a fixed-width font.
*
* Return value: Whether the span uses a fixed-width font.
*
* Since: 0.26
*/
gboolean
poppler_text_span_is_fixed_width_font (PopplerTextSpan *poppler_text_span)
{
g_return_val_if_fail (poppler_text_span != nullptr, FALSE);
return (poppler_text_span->flags & POPPLER_TEXT_SPAN_FIXED_WIDTH);
}
/**
* poppler_text_span_is_serif_font:
* @poppler_text_span: a #PopplerTextSpan
*
* Check whether a text span is meant to be rendered using a serif font.
*
* Return value: Whether the span uses a serif font.
*
* Since: 0.26
*/
gboolean
poppler_text_span_is_serif_font (PopplerTextSpan *poppler_text_span)
{
g_return_val_if_fail (poppler_text_span != nullptr, FALSE);
return (poppler_text_span->flags & POPPLER_TEXT_SPAN_SERIF);
}
/**
* poppler_text_span_is_bold_font:
* @poppler_text_span: a #PopplerTextSpan
*
* Check whether a text span is meant to be rendered using a bold font.
*
* Return value: Whether the span uses bold font.
*
* Since: 0.26
*/
gboolean
poppler_text_span_is_bold_font (PopplerTextSpan *poppler_text_span)
{
g_return_val_if_fail (poppler_text_span != nullptr, FALSE);
return (poppler_text_span->flags & POPPLER_TEXT_SPAN_BOLD);
}
/**
* poppler_text_span_get_color:
* @poppler_text_span: a #PopplerTextSpan
* @color: (out): a return location for a #PopplerColor
*
* Obtains the color in which the text is to be rendered.
*
* Since: 0.26
*/
void
poppler_text_span_get_color (PopplerTextSpan *poppler_text_span,
PopplerColor *color)
{
g_return_if_fail (poppler_text_span != nullptr);
g_return_if_fail (color != nullptr);
*color = poppler_text_span->color;
}
/**
* poppler_text_span_get_text:
* @poppler_text_span: a #PopplerTextSpan
*
* Obtains the text contained in the span.
*
* Return value: (transfer none): A string.
*
* Since: 0.26
*/
const gchar *
poppler_text_span_get_text (PopplerTextSpan *poppler_text_span)
{
g_return_val_if_fail (poppler_text_span != nullptr, NULL);
return poppler_text_span->text;
}
/**
* poppler_text_span_get_font_name:
* @poppler_text_span: a #PopplerTextSpan
*
* Obtains the name of the font in which the span is to be rendered.
*
* Return value: (transfer none): A string containing the font name, or
* %NULL if a font is not defined.
*
* Since: 0.26
*/
const gchar *
poppler_text_span_get_font_name (PopplerTextSpan *poppler_text_span)
{
g_return_val_if_fail (poppler_text_span != nullptr, NULL);
return poppler_text_span->font_name;
}
/**
* poppler_structure_element_get_text_spans:
* @poppler_structure_element: A #PopplerStructureElement
* @n_text_spans: (out): A pointer to the location where the number of elements in
* the returned array will be stored.
*
* Obtains the text enclosed by an element, as an array of #PopplerTextSpan
* structures. Each item in the list is a piece of text which share the same
* attributes, plus its attributes. The following example shows how to
* obtain and free the text spans of an element:
*
* <informalexample><programlisting>
* guint i, n_spans;
* PopplerTextSpan **text_spans =
* poppler_structure_element_get_text_spans (element, &n_spans);
* /<!-- -->* Use the text spans *<!-- -->/
* for (i = 0; i < n_spans; i++)
* poppler_text_span_free (text_spans[i]);
* g_free (text_spans);
* </programlisting></informalexample>
*
* Return value: (transfer full) (array length=n_text_spans) (element-type PopplerTextSpan):
* An array of #PopplerTextSpan elements.
*
* Since: 0.26
*/
PopplerTextSpan **
poppler_structure_element_get_text_spans (PopplerStructureElement *poppler_structure_element,
guint *n_text_spans)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL);
g_return_val_if_fail (n_text_spans != nullptr, NULL);
g_return_val_if_fail (poppler_structure_element->elem != nullptr, NULL);
if (!poppler_structure_element->elem->isContent ())
return nullptr;
const TextSpanArray spans(poppler_structure_element->elem->getTextSpans ());
PopplerTextSpan **text_spans = g_new0 (PopplerTextSpan*, spans.size ());
size_t i = 0;
for (TextSpanArray::const_iterator s = spans.begin (); s != spans.end (); ++s)
text_spans[i++] = text_span_poppler_text_span (*s);
*n_text_spans = spans.size ();
return text_spans;
}
/* General Layout Attributes */
/**
* poppler_structure_element_get_placement:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the placement type of the structure element.
*
* Return value: A #PopplerStructurePlacement value.
*
* Since: 0.26
*/
PopplerStructurePlacement
poppler_structure_element_get_placement (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element),
EnumNameValue<PopplerStructurePlacement>::values[0].value);
return attr_to_enum<PopplerStructurePlacement> (poppler_structure_element);
}
/**
* poppler_structure_element_get_writing_mode:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the writing mode (writing direction) of the content associated
* with a structure element.
*
* Return value: A #PopplerStructureWritingMode value.
*
* Since: 0.26
*/
PopplerStructureWritingMode
poppler_structure_element_get_writing_mode (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element),
EnumNameValue<PopplerStructureWritingMode>::values[0].value);
return attr_to_enum<PopplerStructureWritingMode> (poppler_structure_element);
}
static void
convert_border_style (Object *object, PopplerStructureBorderStyle *values)
{
g_assert (object != nullptr);
g_assert (values != nullptr);
if (object->isArray ())
{
g_assert (object->arrayGetLength () == 4);
for (guint i = 0; i < 4; i++)
{
Object item = object->arrayGet (i);
values[i] = name_to_enum<PopplerStructureBorderStyle> (&item);
}
}
else
{
values[0] = values[1] = values[2] = values[3] =
name_to_enum<PopplerStructureBorderStyle> (object);
}
}
/**
* poppler_structure_element_get_border_style:
* @poppler_structure_element: A #PopplerStructureElement
* @border_styles: (out) (array fixed-size=4) (element-type PopplerStructureBorderStyle):
* An array of four #PopplerStructureBorderStyle elements.
*
* Obtains the border style of a structure element. The result values
* are in before-after-start-end ordering. For example, using Western
* left-to-right writing, that is top-bottom-left-right.
*
* Since: 0.26
*/
void
poppler_structure_element_get_border_style (PopplerStructureElement *poppler_structure_element,
PopplerStructureBorderStyle *border_styles)
{
g_return_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element));
g_return_if_fail (border_styles != nullptr);
convert_border_style (attr_value_or_default (poppler_structure_element,
Attribute::BorderStyle),
border_styles);
}
static inline void
convert_doubles_array (Object *object, gdouble **values, guint *n_values)
{
g_assert (object->isArray ());
g_assert (n_values != nullptr);
g_assert (values != nullptr);
*n_values = object->arrayGetLength ();
gdouble* doubles = g_new (gdouble, *n_values);
for (guint i = 0; i < *n_values; i++)
{
doubles[i] = object->arrayGet (i).getNum ();
}
}
static inline void
convert_color (Object *object, PopplerColor *color)
{
g_assert (color != nullptr);
g_assert (object->isArray () && object->arrayGetLength () != 3);
color->red = object->arrayGet (0).getNum () * 65535;
color->green = object->arrayGet (1).getNum () * 65535;
color->blue = object->arrayGet (2).getNum () * 65535;
}
/**
* poppler_structure_element_get_color:
* @poppler_structure_element: A #PopplerStructureElement
* @color: (out): A #PopplerColor.
*
* Obtains the color of the content contained in the element.
* If this attribute is not specified, the color for this element shall
* be the current text fill color in effect at the start of its associated content.
*
* Return value: %TRUE if a color is defined for the element,
* %FALSE otherwise.
*
* Since: 0.26
*/
gboolean
poppler_structure_element_get_color (PopplerStructureElement *poppler_structure_element,
PopplerColor *color)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), FALSE);
g_return_val_if_fail (color != nullptr, FALSE);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::Color);
if (value == nullptr)
return FALSE;
convert_color (value, color);
return TRUE;
}
/**
* poppler_structure_element_get_background_color:
* @poppler_structure_element: A #PopplerStructureElement
* @color: (out): A #PopplerColor.
*
* Obtains the background color of the element. If this attribute is
* not specified, the element shall be treated as if it were transparent.
*
* Return value: %TRUE if a color is defined for the element,
* %FALSE otherwise.
*
* Since: 0.26
*/
gboolean
poppler_structure_element_get_background_color (PopplerStructureElement *poppler_structure_element,
PopplerColor *color)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), FALSE);
g_return_val_if_fail (color != nullptr, FALSE);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::BackgroundColor);
if (value == nullptr)
return FALSE;
convert_color (value, color);
return TRUE;
}
/**
* poppler_structure_element_get_border_color:
* @poppler_structure_element: A #PopplerStructureElement
* @colors: (out) (array fixed-size=4) (element-type PopplerColor): An array
* of four #PopplerColor.
*
* Obtains the color of border around the element. The result values
* are in before-after-start-end ordering (for the typical Western
* left-to-right writing, that is top-bottom-left-right).
* If this attribute is not specified, the border color for this element shall
* be the current text fill color in effect at the start of its associated
* content.
*
* Return value: %TRUE if a color is defined for the element,
* %FALSE otherwise.
*
* Since: 0.26
*/
gboolean
poppler_structure_element_get_border_color (PopplerStructureElement *poppler_structure_element,
PopplerColor *colors)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), FALSE);
g_return_val_if_fail (colors != nullptr, FALSE);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::BorderColor);
if (value == nullptr)
return FALSE;
g_assert (value->isArray ());
if (value->arrayGetLength () == 4)
{
// One color per side.
for (guint i = 0; i < 4; i++)
{
Object item = value->arrayGet (i);
convert_color (&item, &colors[i]);
}
}
else
{
// Same color in all sides.
g_assert (value->arrayGetLength () == 3);
convert_color (value, &colors[0]);
colors[1] = colors[2] = colors[3] = colors[0];
}
return TRUE;
}
static inline void
convert_double_or_4_doubles (Object *object, gdouble *value)
{
g_assert (object != nullptr);
if (object->isArray ())
{
g_assert (object->arrayGetLength () == 4);
for (guint i = 0; i < 4; i++)
{
value[i] = object->arrayGet (i).getNum ();
}
}
else
{
g_assert (object->isNum ());
value[0] = value[1] = value[2] = value[3] = object->getNum ();
}
}
/**
* poppler_structure_element_get_border_thickness:
* @poppler_structure_element: A #PopplerStructureElement
* @border_thicknesses: (out) (array fixed-size=4) (element-type gdouble):
* Array with the four values of border thicknesses.
*
* Obtains the thickness of the border of an element. The result values
* are in before-after-start-end ordering (for the typical Western
* left-to-right writing, that is top-bottom-left-right).
* A value of 0 indicates that the border shall not be drawn.
*
* Return value: %TRUE if the border thickness attribute is defined for
* the element, %FALSE otherwise.
*
* Since: 0.26
*/
gboolean
poppler_structure_element_get_border_thickness (PopplerStructureElement *poppler_structure_element,
gdouble *border_thicknesses)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), FALSE);
g_return_val_if_fail (border_thicknesses != nullptr, FALSE);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::BorderThickness);
if (value == nullptr)
return FALSE;
convert_double_or_4_doubles (value, border_thicknesses);
return TRUE;
}
/**
* poppler_structure_element_get_padding:
* @poppler_structure_element: A #PopplerStructureElement
* @paddings: (out) (array fixed-size=4) (element-type gdouble):
* Padding for the four sides of the element.
*
* Obtains the padding of an element (space around it). The result
* values are in before-after-start-end ordering. For example using
* Western left-to-right writing, that is top-bottom-left-right.
*
* Since: 0.26
*/
void
poppler_structure_element_get_padding (PopplerStructureElement *poppler_structure_element,
gdouble *paddings)
{
g_return_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element));
g_return_if_fail (paddings != nullptr);
convert_double_or_4_doubles (attr_value_or_default (poppler_structure_element,
Attribute::Padding),
paddings);
}
/* Layout Attributes for block-level structure elements */
/**
* poppler_structure_element_get_space_before:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the amount of empty space before the block-level structure element.
*
* Return value: A positive value.
*
* Since: 0.26
*/
gdouble
poppler_structure_element_get_space_before (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element), NAN);
return attr_value_or_default (poppler_structure_element, Attribute::SpaceBefore)->getNum ();
}
/**
* poppler_structure_element_get_space_after:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the amount of empty space after the block-level structure element.
*
* Return value: A positive value.
*
* Since: 0.26
*/
gdouble
poppler_structure_element_get_space_after (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element), NAN);
return attr_value_or_default (poppler_structure_element, Attribute::SpaceAfter)->getNum ();
}
/**
* poppler_structure_element_get_start_indent:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the amount of indentation at the beginning of the block-level structure element.
*
* Return value: A numeric value.
*
* Since: 0.26
*/
gdouble
poppler_structure_element_get_start_indent (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element), NAN);
return attr_value_or_default (poppler_structure_element, Attribute::StartIndent)->getNum ();
}
/**
* poppler_structure_element_get_end_indent:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the amount of indentation at the end of the block-level structure element.
*
* Return value: A numeric value.
*
* Since: 0.26
*/
gdouble
poppler_structure_element_get_end_indent (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element), NAN);
return attr_value_or_default (poppler_structure_element, Attribute::EndIndent)->getNum ();
}
/**
* poppler_structure_element_get_text_indent:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the amount of indentation of the text contained in the block-level structure element.
*
* Return value: A numeric value.
*
* Since: 0.26
*/
gdouble
poppler_structure_element_get_text_indent (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element), NAN);
return attr_value_or_default (poppler_structure_element, Attribute::TextIndent)->getNum ();
}
/**
* poppler_structure_element_get_text_align:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the text alignment mode of the text contained into a
* block-level structure element.
*
* Return value: A #PopplerStructureTextAlign value.
*
* Since: 0.26
*/
PopplerStructureTextAlign
poppler_structure_element_get_text_align (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element),
EnumNameValue<PopplerStructureTextAlign>::values[0].value);
return attr_to_enum<PopplerStructureTextAlign> (poppler_structure_element);
}
/**
* poppler_structure_element_get_bounding_box:
* @poppler_structure_element: A #PopplerStructureElement
* @bounding_box: (out): A #PopplerRectangle.
*
* Obtains the size of the bounding box of a block-level structure element.
*
* Return value: %TRUE if a bounding box is defined for the element,
* %FALSE otherwise.
*
* Since: 0.26
*/
gboolean
poppler_structure_element_get_bounding_box (PopplerStructureElement *poppler_structure_element,
PopplerRectangle *bounding_box)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element), FALSE);
g_return_val_if_fail (bounding_box != nullptr, FALSE);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::BBox);
if (value == nullptr)
return FALSE;
gdouble dimensions[4];
convert_double_or_4_doubles (value, dimensions);
bounding_box->x1 = dimensions[0];
bounding_box->y1 = dimensions[1];
bounding_box->x2 = dimensions[2];
bounding_box->y2 = dimensions[3];
return TRUE;
}
/**
* poppler_structure_element_get_width:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the width of the block-level structure element. Note that for elements which do
* not specify a width, it has to be calculated, and in this case -1 is returned.
*
* Return value: A positive value if a width is defined, or -1
* if the width is to be calculated automatically.
*
* Since: 0.26
*/
gdouble
poppler_structure_element_get_width (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element), NAN);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::Width);
return value->isName ("Auto") ? -1.0 : value->getNum ();
}
/**
* poppler_structure_element_get_height:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the height of the block-level structure element. Note that for elements which do
* not specify a height, it has to be calculated, and in this case -1 is returned.
*
* Return value: A positive value if a width is defined, or -1
* if the height is to be calculated automatically.
*
* Since: 0.26
*/
gdouble
poppler_structure_element_get_height (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element), NAN);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::Height);
return value->isName ("Auto") ? -1.0 : value->getNum ();
}
/**
* poppler_structure_element_get_block_align:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the block-alignment mode of the block-level structure element.
*
* Return value: A #PopplerStructureBlockAlign value.
*
* Since: 0.26
*/
PopplerStructureBlockAlign
poppler_structure_element_get_block_align (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element),
EnumNameValue<PopplerStructureBlockAlign>::values[0].value);
return attr_to_enum<PopplerStructureBlockAlign> (poppler_structure_element);
}
/**
* poppler_structure_element_get_inline_align:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the inline-alignment mode of the block-level structure element.
*
* Return value: A #PopplerStructureInlineAlign value.
*
* Since: 0.26
*/
PopplerStructureInlineAlign
poppler_structure_element_get_inline_align (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_block (poppler_structure_element),
EnumNameValue<PopplerStructureInlineAlign>::values[0].value);
return attr_to_enum<PopplerStructureInlineAlign> (poppler_structure_element);
}
/**
* poppler_structure_element_get_table_border_style:
* @poppler_structure_element: A #PopplerStructureElement
* @border_styles: (out) (array fixed-size=4) (element-type PopplerStructureBorderStyle):
* An array of four #PopplerStructureBorderStyle elements.
*
* Obtains the table cell border style of a block-level structure element. The result values
* are in before-after-start-end ordering. For example, using Western
* left-to-right writing, that is top-bottom-left-right.
*
* Since: 0.26
*/
void
poppler_structure_element_get_table_border_style (PopplerStructureElement *poppler_structure_element,
PopplerStructureBorderStyle *border_styles)
{
g_return_if_fail (poppler_structure_element_is_block (poppler_structure_element));
g_return_if_fail (border_styles != nullptr);
convert_border_style (attr_value_or_default (poppler_structure_element,
Attribute::TBorderStyle),
border_styles);
}
/**
* poppler_structure_element_get_table_padding:
* @poppler_structure_element: A #PopplerStructureElement
* @paddings: (out) (array fixed-size=4) (element-type gdouble):
* Padding for the four sides of the element.
*
* Obtains the padding between the table cell’s content rectangle and the
* surrounding border of a block-level structure element. The result
* values are in before-after-start-end ordering (for the typical
* Western left-to-right writing, that is top-bottom-left-right).
*
* Since: 0.26
*/
void
poppler_structure_element_get_table_padding (PopplerStructureElement *poppler_structure_element,
gdouble *paddings)
{
g_return_if_fail (poppler_structure_element_is_block (poppler_structure_element));
g_return_if_fail (paddings != nullptr);
convert_double_or_4_doubles (attr_value_or_default (poppler_structure_element,
Attribute::TPadding),
paddings);
}
/* Layout Attributes for inline-level structure elements */
/**
* poppler_structure_element_get_baseline_shift:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains how much the text contained in the inline-level structure element should be shifted,
* measuring from the baseline of the glyphs.
*
* Return value: A numeric value.
*
* Since: 0.26
*/
gdouble
poppler_structure_element_get_baseline_shift (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_inline (poppler_structure_element), NAN);
return attr_value_or_default (poppler_structure_element, Attribute::BaselineShift)->getNum ();
}
/**
* poppler_structure_element_get_line_height:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the line height for the text contained in the inline-level structure element.
* Note that for elements which do not specify a line height, it has to be calculated,
* and in this case -1 is returned.
*
* Return value: A positive value if a line height is defined, or -1
* if the height is to be calculated automatically.
*
* Since: 0.26
*/
gdouble
poppler_structure_element_get_line_height (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_inline (poppler_structure_element), NAN);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::LineHeight);
return (value->isName ("Normal") || value->isName ("Auto")) ? -1.0 : value->getNum ();
}
/**
* poppler_structure_element_get_text_decoration_color:
* @poppler_structure_element: A #PopplerStructureElement
* @color: (out): A #PopplerColor.
*
* Obtains the color of the text decoration for the text contained
* in the inline-level structure element.
* If this attribute is not specified, the color for this element shall be the current fill
* color in effect at the start of its associated content.
*
* Return value: %TRUE if a color is defined for the element,
* %FALSE otherwise.
*
* Since: 0.26
*/
gboolean
poppler_structure_element_get_text_decoration_color (PopplerStructureElement *poppler_structure_element,
PopplerColor *color)
{
g_return_val_if_fail (poppler_structure_element_is_inline (poppler_structure_element), FALSE);
g_return_val_if_fail (color != nullptr, FALSE);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::TextDecorationColor);
if (value == nullptr)
return FALSE;
convert_color (value, color);
return FALSE;
}
/**
* poppler_structure_element_get_text_decoration_thickness:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the thickness of the text decoration for the text contained
* in the inline-level structure element.
* If this attribute is not specified, it shall be derived from the current
* stroke thickness in effect at the start of the element’s associated content.
*
* Return value: Thickness of the text decoration, or NAN if not defined.
*
* Since: 0.26
*/
gdouble
poppler_structure_element_get_text_decoration_thickness (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_inline (poppler_structure_element), NAN);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::TextDecorationThickness);
return (value == nullptr) ? NAN : value->getNum ();
}
/**
* poppler_structure_element_get_text_decoration_type:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the text decoration type of the text contained in the
* inline-level structure element.
*
* Return value: A #PopplerStructureTextDecoration value.
*
* Since: 0.26
*/
PopplerStructureTextDecoration
poppler_structure_element_get_text_decoration_type (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_inline (poppler_structure_element),
EnumNameValue<PopplerStructureTextDecoration>::values[0].value);
return attr_to_enum<PopplerStructureTextDecoration> (poppler_structure_element);
}
/**
* poppler_structure_element_get_ruby_align:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the alignment for the ruby text contained in a
* inline-level structure element.
*
* Return value: A #PopplerStructureRubyAlign value.
*
* Since: 0.26
*/
PopplerStructureRubyAlign
poppler_structure_element_get_ruby_align (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_inline (poppler_structure_element),
EnumNameValue<PopplerStructureRubyAlign>::values[0].value);
return attr_to_enum<PopplerStructureRubyAlign> (poppler_structure_element);
}
/**
* poppler_structure_element_get_ruby_position:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the position for the ruby text contained in a
* inline-level structure element.
*
* Return value: A #PopplerStructureRubyPosition value.
*
* Since: 0.26
*/
PopplerStructureRubyPosition
poppler_structure_element_get_ruby_position (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_inline (poppler_structure_element),
EnumNameValue<PopplerStructureRubyPosition>::values[0].value);
return attr_to_enum<PopplerStructureRubyPosition> (poppler_structure_element);
}
/**
* poppler_structure_element_get_glyph_orientation:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the glyph orientation for the text contained in a
* inline-level structure element.
*
* Return value: A #PopplerStructureGlyphOrientation value.
*
* Since: 0.26
*/
PopplerStructureGlyphOrientation
poppler_structure_element_get_glyph_orientation (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_inline (poppler_structure_element),
EnumNameValue<PopplerStructureGlyphOrientation>::values[0].value);
return attr_to_enum<PopplerStructureGlyphOrientation> (poppler_structure_element);
}
/* Column Attributes */
/**
* poppler_structure_element_get_column_count:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the number of columns used to lay out the content contained
* in the grouping element.
*
* Return value: Number of columns.
*
* Since: 0.26
*/
guint
poppler_structure_element_get_column_count (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_is_grouping (poppler_structure_element), 0);
return static_cast<guint> (attr_value_or_default (poppler_structure_element,
Attribute::ColumnCount)->getInt ());
}
/**
* poppler_structure_element_get_column_gaps:
* @poppler_structure_element: A #PopplerStructureElement
* @n_values: (out): Size of the returned array.
*
* Obtains the size of the gaps in between adjacent columns. Returns an
* array of elements: the first one is the size of the gap in between
* columns 1 and 2, second is the size between columns 2 and 3, and so on.
*
* For elements which use a single column, %NULL is returned and @n_values
* is set to zero.
*
* If the attribute is undefined, %NULL is returned and @n_values is set
* to a non-zero value.
*
* The array with the results is allocated by the function. When it is
* not needed anymore, be sure to call g_free() on it.
*
* Return value: (transfer full) (array length=n_values) (element-type gdouble):
* Array containing the values for the column gaps, or %NULL if the
* array is empty or the attribute is not defined.
*
* Since: 0.26
*/
gdouble *
poppler_structure_element_get_column_gaps (PopplerStructureElement *poppler_structure_element,
guint *n_values)
{
g_return_val_if_fail (poppler_structure_element_is_grouping (poppler_structure_element), NULL);
g_return_val_if_fail (n_values != nullptr, NULL);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::ColumnGap);
if (value == nullptr)
{
*n_values = static_cast<guint> (-1);
return nullptr;
}
gdouble *result = nullptr;
convert_doubles_array (value, &result, n_values);
return result;
}
/**
* poppler_structure_element_get_column_widths:
* @poppler_structure_element: A #PopplerStructureElement
* @n_values: (out): Size of the returned array.
*
* Obtains an array with the widths of the columns.
*
* The array with the results is allocated by the function. When it is
* not needed anymore, be sure to call g_free() on it.
*
* Return value: (transfer full) (array length=n_values) (element-type gdouble):
* Array containing widths of the columns, or %NULL if the attribute
* is not defined.
*
* Since: 0.26
*/
gdouble *
poppler_structure_element_get_column_widths (PopplerStructureElement *poppler_structure_element,
guint *n_values)
{
g_return_val_if_fail (poppler_structure_element_is_grouping (poppler_structure_element), NULL);
g_return_val_if_fail (n_values != nullptr, NULL);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::ColumnWidths);
if (value == nullptr)
return nullptr;
gdouble *result = nullptr;
convert_doubles_array (value, &result, n_values);
return result;
}
/* List Attribute */
/**
* poppler_structure_element_get_list_numbering:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the list numbering style for list items.
*
* Return value: A #PopplerStructureListNumbering value.
*
* Since: 0.26
*/
PopplerStructureListNumbering
poppler_structure_element_get_list_numbering (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_get_kind (poppler_structure_element) == POPPLER_STRUCTURE_ELEMENT_LIST_ITEM,
EnumNameValue<PopplerStructureListNumbering>::values[0].value);
return attr_to_enum<PopplerStructureListNumbering> (poppler_structure_element);
}
/* PrintField Attributes */
/**
* poppler_structure_element_get_form_role:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the role of a form structure element that is part of a form, or is
* a form field. This hints how the control for the element is intended
* to be rendered.
*
* Return value: A #PopplerStructureFormRole value.
*
* Since: 0.26
*/
PopplerStructureFormRole
poppler_structure_element_get_form_role (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_get_kind (poppler_structure_element) == POPPLER_STRUCTURE_ELEMENT_FORM,
EnumNameValue<PopplerStructureFormRole>::values[0].value);
/*
* The Role attribute can actually be undefined.
*/
Object *value = attr_value_or_default (poppler_structure_element, Attribute::Role);
if (value == nullptr)
return POPPLER_STRUCTURE_FORM_ROLE_UNDEFINED;
return name_to_enum<PopplerStructureFormRole> (value);
}
/**
* poppler_structure_element_get_form_state:
* @poppler_structure_element: A #PopplerStructureElement
*
* For a structure element that is a form field, obtains in which state
* the associated control is expected to be rendered.
*
* Return value: A #PopplerStructureFormState value.
*
* Since: 0.26
*/
PopplerStructureFormState
poppler_structure_element_get_form_state (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_get_kind (poppler_structure_element) == POPPLER_STRUCTURE_ELEMENT_FORM,
EnumNameValue<PopplerStructureFormState>::values[0].value);
return attr_to_enum<PopplerStructureFormState> (poppler_structure_element);
}
/**
* poppler_structure_element_get_form_description:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the textual description of the form element. Note that the
* description is for informative purposes, and it is not intended
* to be rendered. For example, assistive technologies may use the
* description field to provide an alternate way of presenting an
* element to the user.
*
* The returned string is allocated by the function. When it is
* not needed anymore, be sure to call g_free() on it.
*
* Return value: (transfer full): A string, or %NULL if the attribute
* is not defined.
*
* Since: 0.26
*/
gchar *
poppler_structure_element_get_form_description (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_get_kind (poppler_structure_element) == POPPLER_STRUCTURE_ELEMENT_FORM, NULL);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::Desc);
if (value == nullptr)
return nullptr;
if (value->isString ())
return _poppler_goo_string_to_utf8 (value->getString ());
if (value->isName ())
return g_strdup (value->getName ());
g_assert_not_reached ();
return nullptr;
}
/* Table Attributes */
/**
* poppler_structure_element_get_table_row_span:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the number of rows the table element spans to.
*
* Return value: A positive, non-zero value.
*
* Since: 0.26
*/
guint
poppler_structure_element_get_table_row_span (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_get_kind (poppler_structure_element) == POPPLER_STRUCTURE_ELEMENT_TABLE, 0);
return static_cast<guint> (attr_value_or_default (poppler_structure_element,
Attribute::RowSpan)->getInt ());
}
/**
* poppler_structure_element_get_table_column_span:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the number of columns the table element spans to.
*
* Return value: A positive, non-zero value.
*
* Since: 0.26
*/
guint
poppler_structure_element_get_table_column_span (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_get_kind (poppler_structure_element) == POPPLER_STRUCTURE_ELEMENT_TABLE, 0);
return static_cast<guint> (attr_value_or_default (poppler_structure_element,
Attribute::ColSpan)->getInt ());
}
/**
* poppler_structure_element_get_table_headers:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains an array with the names of the table column headers. This is only
* useful for table header row elements.
*
* The array with the results is allocated by the function. The number
* of items in the returned array can be obtained with g_strv_length().
* The returned value must be freed using g_strfreev().
*
* Return value: (transfer full) (array zero-terminated=1) (element-type gchar*):
* Zero-terminated array of strings with the table header names,
* or %NULL if the attribute is not defined.
*
* Since: 0.26
*/
gchar **
poppler_structure_element_get_table_headers (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_get_kind (poppler_structure_element) == POPPLER_STRUCTURE_ELEMENT_TABLE, NULL);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::Headers);
if (value == nullptr)
return nullptr;
g_assert (value->isArray ());
const guint n_values = value->arrayGetLength ();
gchar **result = g_new0 (gchar*, n_values + 1);
for (guint i = 0; i < n_values; i++)
{
Object item = value->arrayGet (i);
if (item.isString ())
result[i] = _poppler_goo_string_to_utf8 (item.getString ());
else if (item.isName ())
result[i] = g_strdup (item.getName ());
else
g_assert_not_reached ();
}
return result;
}
/**
* poppler_structure_element_get_table_scope:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the scope of a table structure element.
*
* Return value: A #PopplerStructureTableScope value.
*
* Since: 0.26
*/
PopplerStructureTableScope
poppler_structure_element_get_table_scope (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (poppler_structure_element_get_kind (poppler_structure_element) == POPPLER_STRUCTURE_ELEMENT_TABLE,
EnumNameValue<PopplerStructureTableScope>::values[0].value);
return attr_to_enum<PopplerStructureTableScope> (poppler_structure_element);
}
/**
* poppler_structure_element_get_table_summary:
* @poppler_structure_element: A #PopplerStructureElement
*
* Obtains the textual summary of the contents of the table element. Note that
* the summary is meant for informative purposes, and it is not intended
* to be rendered. For example, assistive technologies may use the
* description field to provide an alternate way of presenting an element
* to the user, or a document indexer may want to scan it for additional
* keywords.
*
* The returned string is allocated by the function. When it is
* not needed anymore, be sure to call g_free() on it.
*
* Return value: (transfer full): A string, or %NULL if the attribute
* is not defined.
*
* Since: 0.26
*/
gchar *
poppler_structure_element_get_table_summary (PopplerStructureElement *poppler_structure_element)
{
g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL);
Object *value = attr_value_or_default (poppler_structure_element, Attribute::Summary);
if (value == nullptr)
return nullptr;
if (value->isString ())
return _poppler_goo_string_to_utf8 (value->getString ());
if (value->isName ())
return g_strdup (value->getName ());
g_assert_not_reached ();
return nullptr;
}