[poppler] [PATCH 5/6] Tagged-PDF: Expose the structure tree in poppler-glib

Adrian Perez aperez at igalia.com
Wed May 29 16:47:30 PDT 2013


From: Adrian Perez de Castro <aperez at igalia.com>

Implements two new GObject classes, which build upon StructTreeRoot
and StructElement to expose the document structure of tagged PDFs
in the GLib binding:

- PopplerStructure wraps StrucTreeRoot, and contains additional utility
  methods to search for elements in the structure tree.
- PopplerStructureElement wraps StructElement, and does the heavy lifting
	of exposing data in GLib-friendly data types.

For standard attributes, to avoid cluttering the class with fmethods, a
single poppler_structure_element_get_attribute() method is implemented,
which returns either NULL (for undefined attributes) or a GVariant
containing a sensible representation of the value.
---
 glib/Makefile.am                    |    4 +
 glib/poppler-document.cc            |   22 +
 glib/poppler-document.h             |    1 +
 glib/poppler-private.h              |   24 +
 glib/poppler-structure-element.cc   | 1289 +++++++++++++++++++++++++++++++++++
 glib/poppler-structure-element.h    |  346 ++++++++++
 glib/poppler-structure.cc           |  349 ++++++++++
 glib/poppler-structure.h            |   43 ++
 glib/poppler.h                      |    3 +
 glib/reference/poppler-docs.sgml    |    2 +
 glib/reference/poppler-sections.txt |   86 +++
 glib/reference/poppler.types        |    2 +
 12 files changed, 2171 insertions(+)
 create mode 100644 glib/poppler-structure-element.cc
 create mode 100644 glib/poppler-structure-element.h
 create mode 100644 glib/poppler-structure.cc
 create mode 100644 glib/poppler-structure.h

diff --git a/glib/Makefile.am b/glib/Makefile.am
index a38e052..645cfd3 100644
--- a/glib/Makefile.am
+++ b/glib/Makefile.am
@@ -41,6 +41,8 @@ poppler_glib_public_headers =			\
 	poppler-layer.h				\
 	poppler-media.h				\
 	poppler-movie.h				\
+	poppler-structure.h			\
+	poppler-structure-element.h		\
 	poppler.h
 
 poppler_glib_includedir = $(includedir)/poppler/glib
@@ -67,6 +69,8 @@ libpoppler_glib_la_SOURCES =			\
 	poppler-cached-file-loader.h		\
 	poppler-input-stream.cc			\
 	poppler-input-stream.h			\
+	poppler-structure.cc			\
+	poppler-structure-element.cc		\
 	poppler.cc				\
 	poppler-private.h
 
diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc
index 61d92e8..bc39314 100644
--- a/glib/poppler-document.cc
+++ b/glib/poppler-document.cc
@@ -1220,6 +1220,28 @@ poppler_document_get_metadata (PopplerDocument *document)
   return retval;
 }
 
+/**
+ * poppler_document_get_structure:
+ * @document: A #PopplerDocument
+ *
+ * Returns the #PopplerStructure of the document. This object is owned by
+ * the called.
+ *
+ * Return value: (transfer full): The #PopplerStructure of the document.
+ */
+PopplerStructure *
+poppler_document_get_structure (PopplerDocument *document)
+{
+  StructTreeRoot *tree_root;
+
+  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);
+
+  tree_root = document->doc->getStructTreeRoot ();
+  if (!tree_root) return NULL;
+
+  return _poppler_structure_new (document, tree_root);
+}
+
 static void
 poppler_document_get_property (GObject    *object,
 			       guint       prop_id,
diff --git a/glib/poppler-document.h b/glib/poppler-document.h
index a34e88c..97cea4a 100644
--- a/glib/poppler-document.h
+++ b/glib/poppler-document.h
@@ -213,6 +213,7 @@ PopplerPageLayout  poppler_document_get_page_layout        (PopplerDocument *doc
 PopplerPageMode    poppler_document_get_page_mode          (PopplerDocument *document);
 PopplerPermissions poppler_document_get_permissions        (PopplerDocument *document);
 gchar             *poppler_document_get_metadata           (PopplerDocument *document);
+PopplerStructure  *poppler_document_get_structure          (PopplerDocument *document);
 
 /* Attachments */
 guint              poppler_document_get_n_attachments      (PopplerDocument  *document);
diff --git a/glib/poppler-private.h b/glib/poppler-private.h
index ab39b49..95841f3 100644
--- a/glib/poppler-private.h
+++ b/glib/poppler-private.h
@@ -17,6 +17,7 @@
 #include <OptionalContent.h>
 #include <CairoOutputDev.h>
 #include <FileSpec.h>
+#include <StructElement.h>
 #endif
 
 struct _PopplerDocument
@@ -95,6 +96,26 @@ struct _PopplerLayer
   gchar *title;
 };
 
+struct _PopplerStructure
+{
+  /*< private >*/
+  GObject parent_instance;
+  PopplerDocument *document;
+  StructTreeRoot *root;
+  PopplerStructureElement **children;
+};
+
+struct _PopplerStructureElement
+{
+  /*< private >*/
+  GObject parent_instance;
+  StructElement *elem;
+  gchar *text;
+  gchar *text_r;
+  GList *text_spans;
+  PopplerStructureElement **children;
+};
+
 GList         *_poppler_document_get_layers (PopplerDocument *document);
 GList         *_poppler_document_get_layer_rbgroup (PopplerDocument *document,
 						    Layer           *layer);
@@ -120,6 +141,9 @@ PopplerAnnot      *_poppler_annot_free_text_new (Annot *annot);
 PopplerAnnot      *_poppler_annot_file_attachment_new (Annot *annot);
 PopplerAnnot      *_poppler_annot_movie_new (Annot *annot);
 PopplerAnnot      *_poppler_annot_screen_new (Annot *annot);
+PopplerStructure  *_poppler_structure_new (PopplerDocument *poppler_document,
+                                           StructTreeRoot  *struct_tree_root);
+PopplerStructureElement *_poppler_structure_element_new (StructElement *struct_element);
 
 char *_poppler_goo_string_to_utf8(GooString *s);
 gboolean _poppler_convert_pdf_date_to_gtime (GooString *date,
diff --git a/glib/poppler-structure-element.cc b/glib/poppler-structure-element.cc
new file mode 100644
index 0000000..38da928
--- /dev/null
+++ b/glib/poppler-structure-element.cc
@@ -0,0 +1,1289 @@
+/* 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 <StructElement.h>
+#include <GlobalParams.h>
+#include <UnicodeMap.h>
+#endif /* !__GI_SCANNER__ */
+
+#include "poppler.h"
+#include "poppler-private.h"
+#include "poppler-structure-element.h"
+
+
+static inline 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::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::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);
+}
+
+
+/**
+ * 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.
+ */
+
+typedef struct _PopplerStructureElementClass PopplerStructureElementClass;
+struct _PopplerStructureElementClass
+{
+  GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (PopplerStructureElement, poppler_structure_element, G_TYPE_OBJECT);
+
+
+PopplerStructureElement*
+_poppler_structure_element_new (StructElement *element)
+{
+  PopplerStructureElement *poppler_structure_element;
+
+  g_assert (element);
+
+  poppler_structure_element = (PopplerStructureElement *) g_object_new (POPPLER_TYPE_STRUCTURE_ELEMENT, NULL, NULL);
+  poppler_structure_element->text     = NULL;
+  poppler_structure_element->text_r   = NULL;
+  poppler_structure_element->children = NULL;
+  poppler_structure_element->elem     = element;
+
+  if (element->getNumElements ())
+    poppler_structure_element->children = (PopplerStructureElement**) g_new0 (PopplerStructureElement*,
+                                                                              element->getNumElements ());
+  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->text_r);
+  g_free (poppler_structure_element->text);
+  g_list_free_full (poppler_structure_element->text_spans, _poppler_text_span_free);
+
+  if (poppler_structure_element->children)
+    {
+      for (unsigned i = 0; i < poppler_structure_element->elem->getNumElements (); i++)
+        g_object_unref (poppler_structure_element->children[i]);
+      g_free (poppler_structure_element->children);
+    }
+
+  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_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_n_children:
+ * @poppler_structure_element: A #PopplerStructureElement
+ *
+ * Gets the number of children of @structure_element.
+ *
+ * Return value: Number of children elements.
+ */
+guint
+poppler_structure_element_get_n_children (PopplerStructureElement *poppler_structure_element)
+{
+  g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), 0);
+  g_assert (poppler_structure_element->elem);
+
+  return poppler_structure_element->elem->getNumElements ();
+}
+
+/**
+ * poppler_structure_element_get_child:
+ * @poppler_structure_element: A #PopplerStructureElement
+ * @index: Index of the children element to obtain.
+ *
+ * Return value: (transfer none): A #PopplerStructureElement.
+ */
+PopplerStructureElement*
+poppler_structure_element_get_child (PopplerStructureElement *poppler_structure_element,
+                                     guint                    index)
+{
+  g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL);
+  g_assert (poppler_structure_element->elem);
+  g_assert (poppler_structure_element->elem->getNumElements () >= 0);
+  g_return_val_if_fail (index < (guint) poppler_structure_element->elem->getNumElements (), NULL);
+
+  if (!poppler_structure_element->children[index])
+    {
+      poppler_structure_element->children[index] = _poppler_structure_element_new (poppler_structure_element->elem->getElement (index));
+      g_object_ref_sink (poppler_structure_element->children[index]);
+    }
+  return poppler_structure_element->children[index];
+}
+
+/**
+ * poppler_structure_element_get_language:
+ * @poppler_structure_element: A #PopplerStructureElement
+ * @inherit: Whether to check the language from the parent elements if it is
+ *    not defined for the element.
+ *
+ * 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,
+                                        gboolean                 inherit)
+{
+    g_return_val_if_fail (POPPLER_IS_STRUCTURE_ELEMENT (poppler_structure_element), NULL);
+    g_assert (poppler_structure_element->elem);
+
+    return poppler_structure_element->elem->getLang ();
+}
+
+/**
+ * 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);
+          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);
+      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 == mcOpUnichar) {
+      int n = map->mapUnicode(op.unichar, buf, sizeof(buf));
+      text.append(buf, n);
+      return;
+    }
+
+    Guint oldFlags = flags;
+
+    if (op.type == mcOpFlags) {
+      if (op.flags & mcOpFlagFontBold)
+        flags |= POPPLER_TEXT_SPAN_BOLD;
+      else
+        flags &= ~POPPLER_TEXT_SPAN_BOLD;
+
+      if (op.flags & mcOpFlagFontFixed)
+        flags |= POPPLER_TEXT_SPAN_FIXED_WIDTH;
+      else
+        flags &= ~POPPLER_TEXT_SPAN_FIXED_WIDTH;
+
+      if (op.flags & mcOpFlagFontItalic)
+        flags |= POPPLER_TEXT_SPAN_ITALIC;
+      else
+        flags &= ~POPPLER_TEXT_SPAN_ITALIC;
+    }
+
+    if (op.type == mcOpColor && (color = op.color.rgbPixel ())) {
+      flags |= POPPLER_TEXT_SPAN_COLOR;
+    } else {
+      flags &= ~POPPLER_TEXT_SPAN_COLOR;
+    }
+
+    if (op.type == mcOpFontName) {
+      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_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;
+    }
+}
diff --git a/glib/poppler-structure-element.h b/glib/poppler-structure-element.h
new file mode 100644
index 0000000..134cef7
--- /dev/null
+++ b/glib/poppler-structure-element.h
@@ -0,0 +1,346 @@
+/* poppler-structure-element.h: 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.
+ */
+
+#ifndef __POPPLER_STRUCTURE_ELEMENT_H__
+#define __POPPLER_STRUCTURE_ELEMENT_H__
+
+#include <glib-object.h>
+#include "poppler.h"
+
+G_BEGIN_DECLS
+
+#define POPPLER_TYPE_STRUCTURE_ELEMENT    (poppler_structure_element_get_type ())
+#define POPPLER_STRUCTURE_ELEMENT(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_STRUCTURE_ELEMENT, PopplerStructureElement))
+#define POPPLER_IS_STRUCTURE_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_STRUCTURE_ELEMENT))
+
+/**
+ * PopplerStructureElementKind:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_ELEMENT_UNKNOWN,
+  POPPLER_STRUCTURE_ELEMENT_CONTENT,
+  POPPLER_STRUCTURE_ELEMENT_DOCUMENT,
+  POPPLER_STRUCTURE_ELEMENT_PART,
+  POPPLER_STRUCTURE_ELEMENT_ARTICLE,
+  POPPLER_STRUCTURE_ELEMENT_SECTION,
+  POPPLER_STRUCTURE_ELEMENT_DIV,
+  POPPLER_STRUCTURE_ELEMENT_SPAN,
+  POPPLER_STRUCTURE_ELEMENT_QUOTE,
+  POPPLER_STRUCTURE_ELEMENT_NOTE,
+  POPPLER_STRUCTURE_ELEMENT_REFERENCE,
+  POPPLER_STRUCTURE_ELEMENT_BIBENTRY,
+  POPPLER_STRUCTURE_ELEMENT_CODE,
+  POPPLER_STRUCTURE_ELEMENT_LINK,
+  POPPLER_STRUCTURE_ELEMENT_ANNOT,
+  POPPLER_STRUCTURE_ELEMENT_RUBY,
+  POPPLER_STRUCTURE_ELEMENT_WARICHU,
+  POPPLER_STRUCTURE_ELEMENT_BLOCKQUOTE,
+  POPPLER_STRUCTURE_ELEMENT_CAPTION,
+  POPPLER_STRUCTURE_ELEMENT_NONSTRUCT,
+  POPPLER_STRUCTURE_ELEMENT_TOC,
+  POPPLER_STRUCTURE_ELEMENT_TOC_ITEM,
+  POPPLER_STRUCTURE_ELEMENT_INDEX,
+  POPPLER_STRUCTURE_ELEMENT_PRIVATE,
+  POPPLER_STRUCTURE_ELEMENT_PARAGRAPH,
+  POPPLER_STRUCTURE_ELEMENT_HEADING,
+  POPPLER_STRUCTURE_ELEMENT_HEADING_1,
+  POPPLER_STRUCTURE_ELEMENT_HEADING_2,
+  POPPLER_STRUCTURE_ELEMENT_HEADING_3,
+  POPPLER_STRUCTURE_ELEMENT_HEADING_4,
+  POPPLER_STRUCTURE_ELEMENT_HEADING_5,
+  POPPLER_STRUCTURE_ELEMENT_HEADING_6,
+  POPPLER_STRUCTURE_ELEMENT_LIST,
+  POPPLER_STRUCTURE_ELEMENT_LIST_ITEM,
+  POPPLER_STRUCTURE_ELEMENT_LIST_LABEL,
+  POPPLER_STRUCTURE_ELEMENT_TABLE,
+  POPPLER_STRUCTURE_ELEMENT_TABLE_ROW,
+  POPPLER_STRUCTURE_ELEMENT_TABLE_HEADING,
+  POPPLER_STRUCTURE_ELEMENT_TABLE_DATA,
+  POPPLER_STRUCTURE_ELEMENT_TABLE_HEADER,
+  POPPLER_STRUCTURE_ELEMENT_TABLE_FOOTER,
+  POPPLER_STRUCTURE_ELEMENT_TABLE_BODY,
+  POPPLER_STRUCTURE_ELEMENT_FIGURE,
+  POPPLER_STRUCTURE_ELEMENT_FORMULA,
+  POPPLER_STRUCTURE_ELEMENT_FORM,
+} PopplerStructureElementKind;
+
+/**
+ * PopplerStructureAttribute:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_ATTRIBUTE_UNKNOWN,
+  POPPLER_STRUCTURE_ATTRIBUTE_USER_PROPERTY,
+  POPPLER_STRUCTURE_ATTRIBUTE_PLACEMENT,
+  POPPLER_STRUCTURE_ATTRIBUTE_WRITING_MODE,
+  POPPLER_STRUCTURE_ATTRIBUTE_BACKGROUND_COLOR,
+  POPPLER_STRUCTURE_ATTRIBUTE_BORDER_COLOR,
+  POPPLER_STRUCTURE_ATTRIBUTE_BORDER_STYLE,
+  POPPLER_STRUCTURE_ATTRIBUTE_BORDER_THICKNESS,
+  POPPLER_STRUCTURE_ATTRIBUTE_COLOR,
+  POPPLER_STRUCTURE_ATTRIBUTE_PADDING,
+  POPPLER_STRUCTURE_ATTRIBUTE_SPACE_BEFORE,
+  POPPLER_STRUCTURE_ATTRIBUTE_SPACE_AFTER,
+  POPPLER_STRUCTURE_ATTRIBUTE_START_INDENT,
+  POPPLER_STRUCTURE_ATTRIBUTE_END_INDENT,
+  POPPLER_STRUCTURE_ATTRIBUTE_TEXT_INDENT,
+  POPPLER_STRUCTURE_ATTRIBUTE_TEXT_ALIGN,
+  POPPLER_STRUCTURE_ATTRIBUTE_BBOX,
+  POPPLER_STRUCTURE_ATTRIBUTE_WIDTH,
+  POPPLER_STRUCTURE_ATTRIBUTE_HEIGHT,
+  POPPLER_STRUCTURE_ATTRIBUTE_BLOCK_ALIGN,
+  POPPLER_STRUCTURE_ATTRIBUTE_INLINE_ALIGN,
+  POPPLER_STRUCTURE_ATTRIBUTE_TABLE_BORDER_STYLE,
+  POPPLER_STRUCTURE_ATTRIBUTE_TABLE_PADDING,
+  POPPLER_STRUCTURE_ATTRIBUTE_BASELINE_SHIFT,
+  POPPLER_STRUCTURE_ATTRIBUTE_LINE_HEIGHT,
+  POPPLER_STRUCTURE_ATTRIBUTE_TEXT_DECORATION_COLOR,
+  POPPLER_STRUCTURE_ATTRIBUTE_TEXT_DECORATION_THICKNESS,
+  POPPLER_STRUCTURE_ATTRIBUTE_TEXT_DECORATION,
+  POPPLER_STRUCTURE_ATTRIBUTE_RUBY_ALIGN,
+  POPPLER_STRUCTURE_ATTRIBUTE_RUBY_POSITION,
+  POPPLER_STRUCTURE_ATTRIBUTE_GLYPH_ORIENTATION,
+  POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_COUNT,
+  POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_GAP,
+  POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_WIDTHS,
+  POPPLER_STRUCTURE_ATTRIBUTE_LIST_NUMBERING,
+  POPPLER_STRUCTURE_ATTRIBUTE_ROLE,
+  POPPLER_STRUCTURE_ATTRIBUTE_CHECKED,
+  POPPLER_STRUCTURE_ATTRIBUTE_DESCRIPTION,
+  POPPLER_STRUCTURE_ATTRIBUTE_ROW_SPAN,
+  POPPLER_STRUCTURE_ATTRIBUTE_COLUMN_SPAN,
+  POPPLER_STRUCTURE_ATTRIBUTE_HEADERS,
+  POPPLER_STRUCTURE_ATTRIBUTE_SCOPE,
+  POPPLER_STRUCTURE_ATTRIBUTE_SUMMARY,
+} PopplerStructureAttribute;
+
+/**
+ * PopplerStructurePlacement:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_PLACEMENT_BLOCK,
+  POPPLER_STRUCTURE_PLACEMENT_INLINE,
+  POPPLER_STRUCTURE_PLACEMENT_BEFORE,
+  POPPLER_STRUCTURE_PLACEMENT_START,
+  POPPLER_STRUCTURE_PLACEMENT_END,
+} PopplerStructurePlacement;
+
+/**
+ * PopplerStructureWritingMode:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_WRITING_MODE_LR_TB,
+  POPPLER_STRUCTURE_WRITING_MODE_RL_TB,
+  POPPLER_STRUCTURE_WRITING_MODE_TB_RL,
+} PopplerStructureWritingMode;
+
+/**
+ * PopplerStructureBorderStyle:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_BORDER_STYLE_NONE,
+  POPPLER_STRUCTURE_BORDER_STYLE_HIDDEN,
+  POPPLER_STRUCTURE_BORDER_STYLE_DOTTED,
+  POPPLER_STRUCTURE_BORDER_STYLE_DASHED,
+  POPPLER_STRUCTURE_BORDER_STYLE_SOLID,
+  POPPLER_STRUCTURE_BORDER_STYLE_DOUBLE,
+  POPPLER_STRUCTURE_BORDER_STYLE_GROOVE,
+  POPPLER_STRUCTURE_BORDER_STYLE_INSET,
+  POPPLER_STRUCTURE_BORDER_STYLE_OUTSET,
+} PopplerStructureBorderStyle;
+
+/**
+ * PopplerStructureTextAlign:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_TEXT_ALIGN_START,
+  POPPLER_STRUCTURE_TEXT_ALIGN_CENTER,
+  POPPLER_STRUCTURE_TEXT_ALIGN_END,
+  POPPLER_STRUCTURE_TEXT_ALIGN_JUSTIFY,
+} PopplerStructureTextAlign;
+
+/**
+ * PopplerStructureBlockAlign:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_BLOCK_ALIGN_BEFORE,
+  POPPLER_STRUCTURE_BLOCK_ALIGN_MIDDLE,
+  POPPLER_STRUCTURE_BLOCK_ALIGN_AFTER,
+  POPPLER_STRUCTURE_BLOCK_ALIGN_JUSTIFY,
+} PopplerStructureBlockAlign;
+
+/**
+ * PopplerStructureInlineAlign:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_INLINE_ALIGN_START,
+  POPPLER_STRUCTURE_INLINE_ALIGN_CENTER,
+  POPPLER_STRUCTURE_INLINE_ALIGN_END,
+} PopplerStructureInlineAlign;
+
+/**
+ * PopplerStructureTextDecoration:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_TEXT_DECORATION_NONE,
+  POPPLER_STRUCTURE_TEXT_DECORATION_UNDERLINE,
+  POPPLER_STRUCTURE_TEXT_DECORATION_OVERLINE,
+  POPPLER_STRUCTURE_TEXT_DECORATION_LINETHROUGH,
+} PopplerStructureTextDecoration;
+
+/**
+ * PopplerStructureRubyAlign:
+ */
+typedef enum
+{
+  POPPLER_STRUCTURE_RUBY_ALIGN_START,
+  POPPLER_STRUCTURE_RUBY_ALIGN_CENTER,
+  POPPLER_STRUCTURE_RUBY_ALIGN_END,
+  POPPLER_STRUCTURE_RUBY_ALIGN_JUSTIFY,
+  POPPLER_STRUCTURE_RUBY_ALIGN_DISTRIBUTE,
+} PopplerStructureRubyAlign;
+
+/**
+ * PopplerStructureRubyPosition:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_RUBY_POSITION_BEFORE,
+  POPPLER_STRUCTURE_RUBY_POSITION_AFTER,
+  POPPLER_STRUCTURE_RUBY_POSITION_WARICHU,
+  POPPLER_STRUCTURE_RUBY_POSITION_INLINE,
+} PopplerStructureRubyPosition;
+
+/**
+ * PopplerStructureGlyphOrientation:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_GLYPH_ORIENTATION_AUTO,
+  POPPLER_STRUCTURE_GLYPH_ORIENTATION_0 = POPPLER_STRUCTURE_GLYPH_ORIENTATION_AUTO,
+  POPPLER_STRUCTURE_GLYPH_ORIENTATION_90,
+  POPPLER_STRUCTURE_GLYPH_ORIENTATION_180,
+  POPPLER_STRUCTURE_GLYPH_ORIENTATION_270,
+} PopplerStructureGlyphOrientation;
+
+/**
+ * PopplerStructureListNumbering:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_LIST_NUMBERING_NONE,
+  POPPLER_STRUCTURE_LIST_NUMBERING_DISC,
+  POPPLER_STRUCTURE_LIST_NUMBERING_CIRCLE,
+  POPPLER_STRUCTURE_LIST_NUMBERING_SQUARE,
+  POPPLER_STRUCTURE_LIST_NUMBERING_DECIMAL,
+  POPPLER_STRUCTURE_LIST_NUMBERING_UPPER_ROMAN,
+  POPPLER_STRUCTURE_LIST_NUMBERING_LOWER_ROMAN,
+  POPPLER_STRUCTURE_LIST_NUMBERING_UPPER_ALPHA,
+  POPPLER_STRUCTURE_LIST_NUMBERING_LOWER_ALPHA,
+} PopplerStructureListNumbering;
+
+/**
+ * PopplerStructureRole:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_ROLE_RADIO_BUTTON,
+  POPPLER_STRUCTURE_ROLE_PUSH_BUTTON,
+  POPPLER_STRUCTURE_ROLE_TEXT_VALUE,
+  POPPLER_STRUCTURE_ROLE_CHECKBOX,
+} PopplerStructureRole;
+
+/**
+ * PopplerStructureChecked:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_CHECKED_ON,
+  POPPLER_STRUCTURE_CHECKED_OFF,
+  POPPLER_STRUCTURE_CHECKED_NEUTRAL,
+} PopplerStructureChecked;
+
+/**
+ * PopplerStructureScope:
+ */
+typedef enum {
+  POPPLER_STRUCTURE_SCOPE_ROW,
+  POPPLER_STRUCTURE_SCOPE_COLUMN,
+  POPPLER_STRUCTURE_SCOPE_BOTH,
+} PopplerStructureScope;
+
+
+typedef struct _PopplerTextSpan PopplerTextSpan;
+struct _PopplerTextSpan {
+  gchar *text;
+  gchar *font_name;
+  gchar *link_target;
+  guint  flags;
+  guint  color; /* 0x00RRGGBB */
+};
+
+enum {
+  POPPLER_TEXT_SPAN_FIXED_WIDTH = (1 << 0),
+  POPPLER_TEXT_SPAN_SERIF_FONT  = (1 << 1),
+  POPPLER_TEXT_SPAN_ITALIC      = (1 << 2),
+  POPPLER_TEXT_SPAN_BOLD        = (1 << 3),
+  POPPLER_TEXT_SPAN_LINK        = (1 << 4),
+  POPPLER_TEXT_SPAN_COLOR       = (1 << 5),
+  POPPLER_TEXT_SPAN_FONT        = (1 << 6),
+};
+
+
+static inline gboolean poppler_text_span_is_fixed_width (PopplerTextSpan *poppler_text_span)
+{
+  return (poppler_text_span->flags & POPPLER_TEXT_SPAN_FIXED_WIDTH);
+}
+
+static inline gboolean poppler_text_span_is_serif_font (PopplerTextSpan *poppler_text_span)
+{
+  return (poppler_text_span->flags & POPPLER_TEXT_SPAN_SERIF_FONT);
+}
+
+static inline gboolean poppler_text_span_is_bold (PopplerTextSpan *poppler_text_span)
+{
+  return (poppler_text_span->flags & POPPLER_TEXT_SPAN_BOLD);
+}
+
+static inline gboolean poppler_text_span_is_link (PopplerTextSpan *poppler_text_span)
+{
+  return (poppler_text_span->flags & POPPLER_TEXT_SPAN_LINK);
+}
+
+
+GType                       poppler_structure_element_get_type          (void) G_GNUC_CONST;
+PopplerStructureElementKind poppler_structure_element_get_kind          (PopplerStructureElement  *poppler_structure_element);
+gboolean                    poppler_structure_element_is_content        (PopplerStructureElement  *poppler_structure_element);
+gboolean                    poppler_structure_element_is_inline         (PopplerStructureElement  *poppler_structure_element);
+gboolean                    poppler_structure_element_is_block          (PopplerStructureElement  *poppler_structure_element);
+guint                       poppler_structure_element_get_n_children    (PopplerStructureElement  *poppler_structure_element);
+PopplerStructureElement    *poppler_structure_element_get_child         (PopplerStructureElement  *poppler_structure_element,
+                                                                         guint                     index);
+const gchar                *poppler_structure_element_get_language      (PopplerStructureElement  *poppler_structure_element,
+                                                                         gboolean                  inherit);
+const gchar                *poppler_structure_element_get_text          (PopplerStructureElement  *poppler_structure_element,
+                                                                         gboolean                  recursive);
+GList                      *poppler_structure_element_get_text_spans    (PopplerStructureElement  *poppler_structure_element,
+                                                                         gboolean                  recursive);
+GVariant                   *poppler_structure_element_get_attribute     (PopplerStructureElement  *poppler_structure_element,
+                                                                         PopplerStructureAttribute attribute,
+                                                                         gboolean                  inherit);
+GVariant                   *poppler_structure_element_get_user_property (PopplerStructureElement  *poppler_structure_element,
+                                                                         const gchar              *user_property_name);
+
+G_END_DECLS
+
+#endif /* !__POPPLER_STRUCTURE_ELEMENT_H__ */
diff --git a/glib/poppler-structure.cc b/glib/poppler-structure.cc
new file mode 100644
index 0000000..bedf0f1
--- /dev/null
+++ b/glib/poppler-structure.cc
@@ -0,0 +1,349 @@
+/* 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>
+#endif /* !__GI_SCANNER__ */
+
+#include "poppler.h"
+#include "poppler-private.h"
+#include "poppler-structure.h"
+
+
+static inline StructElement::Type
+_poppler_structure_element_kind_to_structelement_type (PopplerStructureElementKind kind)
+{
+  switch (kind)
+    {
+      case POPPLER_STRUCTURE_ELEMENT_UNKNOWN:
+        return StructElement::Unknown;
+      case POPPLER_STRUCTURE_ELEMENT_CONTENT:
+        return StructElement::MCID;
+      case POPPLER_STRUCTURE_ELEMENT_DOCUMENT:
+        return StructElement::Document;
+      case POPPLER_STRUCTURE_ELEMENT_PART:
+        return StructElement::Part;
+      case POPPLER_STRUCTURE_ELEMENT_SECTION:
+        return StructElement::Sect;
+      case POPPLER_STRUCTURE_ELEMENT_DIV:
+        return StructElement::Div;
+      case POPPLER_STRUCTURE_ELEMENT_SPAN:
+        return StructElement::Span;
+      case POPPLER_STRUCTURE_ELEMENT_QUOTE:
+        return StructElement::Quote;
+      case POPPLER_STRUCTURE_ELEMENT_NOTE:
+        return StructElement::Note;
+      case POPPLER_STRUCTURE_ELEMENT_REFERENCE:
+        return StructElement::Reference;
+      case POPPLER_STRUCTURE_ELEMENT_BIBENTRY:
+        return StructElement::BibEntry;
+      case POPPLER_STRUCTURE_ELEMENT_CODE:
+        return StructElement::Code;
+      case POPPLER_STRUCTURE_ELEMENT_LINK:
+        return StructElement::Link;
+      case POPPLER_STRUCTURE_ELEMENT_ANNOT:
+        return StructElement::Annot;
+      case POPPLER_STRUCTURE_ELEMENT_RUBY:
+        return StructElement::Ruby;
+      case POPPLER_STRUCTURE_ELEMENT_WARICHU:
+        return StructElement::Warichu;
+      case POPPLER_STRUCTURE_ELEMENT_BLOCKQUOTE:
+        return StructElement::BlockQuote;
+      case POPPLER_STRUCTURE_ELEMENT_CAPTION:
+        return StructElement::Caption;
+      case POPPLER_STRUCTURE_ELEMENT_NONSTRUCT:
+        return StructElement::NonStruct;
+      case POPPLER_STRUCTURE_ELEMENT_TOC:
+        return StructElement::TOC;
+      case POPPLER_STRUCTURE_ELEMENT_TOC_ITEM:
+        return StructElement::TOCI;
+      case POPPLER_STRUCTURE_ELEMENT_INDEX:
+        return StructElement::Index;
+      case POPPLER_STRUCTURE_ELEMENT_PRIVATE:
+        return StructElement::Private;
+      case POPPLER_STRUCTURE_ELEMENT_PARAGRAPH:
+        return StructElement::P;
+      case POPPLER_STRUCTURE_ELEMENT_HEADING:
+        return StructElement::H;
+      case POPPLER_STRUCTURE_ELEMENT_HEADING_1:
+        return StructElement::H1;
+      case POPPLER_STRUCTURE_ELEMENT_HEADING_2:
+        return StructElement::H2;
+      case POPPLER_STRUCTURE_ELEMENT_HEADING_3:
+        return StructElement::H3;
+      case POPPLER_STRUCTURE_ELEMENT_HEADING_4:
+        return StructElement::H4;
+      case POPPLER_STRUCTURE_ELEMENT_HEADING_5:
+        return StructElement::H5;
+      case POPPLER_STRUCTURE_ELEMENT_HEADING_6:
+        return StructElement::H6;
+      case POPPLER_STRUCTURE_ELEMENT_LIST:
+        return StructElement::L;
+      case POPPLER_STRUCTURE_ELEMENT_LIST_ITEM:
+        return StructElement::LI;
+      case POPPLER_STRUCTURE_ELEMENT_LIST_LABEL:
+        return StructElement::Lbl;
+      case POPPLER_STRUCTURE_ELEMENT_TABLE:
+        return StructElement::Table;
+      case POPPLER_STRUCTURE_ELEMENT_TABLE_ROW:
+        return StructElement::TR;
+      case POPPLER_STRUCTURE_ELEMENT_TABLE_HEADING:
+        return StructElement::TH;
+      case POPPLER_STRUCTURE_ELEMENT_TABLE_DATA:
+        return StructElement::TD;
+      case POPPLER_STRUCTURE_ELEMENT_TABLE_HEADER:
+        return StructElement::THead;
+      case POPPLER_STRUCTURE_ELEMENT_TABLE_FOOTER:
+        return StructElement::TFoot;
+      case POPPLER_STRUCTURE_ELEMENT_TABLE_BODY:
+        return StructElement::TBody;
+      case POPPLER_STRUCTURE_ELEMENT_FIGURE:
+        return StructElement::Figure;
+      case POPPLER_STRUCTURE_ELEMENT_FORMULA:
+        return StructElement::Formula;
+      case POPPLER_STRUCTURE_ELEMENT_FORM:
+        return StructElement::Form;
+      default:
+        g_assert_not_reached ();
+    }
+}
+
+
+
+/**
+ * SECTION:poppler-structure
+ * @short_description: Document structure
+ * @title: PopplerStructure
+ *
+ * #PopplerStructure is used to represent the structure of a #PopplerDocument.
+ * If a structure is defined, poppler_document_get_structure() will return a
+ * valid pointer to its #PopplerStructure, which represents the document
+ * tree. Elements can be obtained using poppler_structure_get_n_children()
+ * and poppler_structure_get_child(). Seraching for elements of a given
+ * #PopplerStructureElementType and/or page can be done using
+ * poppler_structure_find_elements().
+ *
+ * The document structure tree is formed by #PopplerStructureElement objects,
+ * describing each one of them a relevant element of the document. The
+ * logical order of the documents is that of doing a depth-first traversal
+ * of the tree. Elements may recursively contain other child elements, which
+ * can be obtained using poppler_structure_element_get_n_children() and
+ * poppler_structure_element_get_child().
+ *
+ * Elements may have attached attributes describing additional information
+ * about them. The standard attributes (as defined in the PDF specification,
+ * see #PopplerStructureAttribute for a complete list) can be obtained using
+ * poppler_structure_element_get_attribute(). Elements may also contain
+ * non-standard attributes with arbitrary names called “user properties”,
+ * see poppler_structure_element_get_user_property() for details.
+ */
+
+typedef struct _PopplerStructureClass PopplerStructureClass;
+struct _PopplerStructureClass
+{
+  GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (PopplerStructure, poppler_structure, G_TYPE_OBJECT);
+
+
+static void
+poppler_structure_init (PopplerStructure *poppler_structure)
+{
+}
+
+
+static void
+poppler_structure_finalize (GObject *object)
+{
+  PopplerStructure *poppler_structure = POPPLER_STRUCTURE (object);
+
+  /* poppler_structure->root is owned by the catalog */
+  g_object_unref (poppler_structure->document);
+
+  if (poppler_structure->children)
+    {
+      for (unsigned i = 0; i < poppler_structure->root->getNumElements (); i++)
+        g_object_unref (poppler_structure->children[i]);
+      g_free (poppler_structure->children);
+    }
+
+  G_OBJECT_CLASS (poppler_structure_parent_class)->finalize (object);
+}
+
+
+static void
+poppler_structure_class_init (PopplerStructureClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = poppler_structure_finalize;
+}
+
+
+PopplerStructure*
+_poppler_structure_new (PopplerDocument *poppler_document,
+                        StructTreeRoot  *root)
+{
+  PopplerStructure *poppler_structure;
+
+  g_return_val_if_fail (POPPLER_IS_DOCUMENT (poppler_document), NULL);
+  g_assert (root);
+
+  poppler_structure = (PopplerStructure*) g_object_new (POPPLER_TYPE_STRUCTURE, NULL, NULL);
+
+  poppler_structure->document = (PopplerDocument*) g_object_ref (poppler_document);
+  poppler_structure->root     = root;
+  poppler_structure->children = NULL;
+
+  if (root->getNumElements ())
+    poppler_structure->children = (PopplerStructureElement**) g_new0 (PopplerStructureElement*,
+                                                                      root->getNumElements ());
+  return poppler_structure;
+}
+
+
+/**
+ * poppler_structure_get_n_children:
+ * @poppler_structure: A #PopplerStructure
+ *
+ * Return value: Number of structure elements in the root of the
+ *    structure tree.
+ */
+guint
+poppler_structure_get_n_children (PopplerStructure *poppler_structure)
+{
+  g_return_val_if_fail (POPPLER_IS_STRUCTURE (poppler_structure), 0);
+  g_assert (poppler_structure->root);
+
+  return poppler_structure->root->getNumElements ();
+}
+
+/**
+ * poppler_structure_get_child:
+ * @poppler_structure: A #PopplerStructure
+ * @index: Index of the root structure element to obtain.
+ *
+ * Return value: (transfer none): A #PopplerStructureElement.
+ */
+PopplerStructureElement*
+poppler_structure_get_child (PopplerStructure *poppler_structure,
+                             guint             index)
+{
+  g_return_val_if_fail (POPPLER_IS_STRUCTURE (poppler_structure), NULL);
+  g_assert (poppler_structure->root);
+  g_assert (poppler_structure->root->getNumElements () >= 0);
+  g_return_val_if_fail (index < (guint) poppler_structure->root->getNumElements (), NULL);
+
+  if (!poppler_structure->children[index])
+    {
+      poppler_structure->children[index] = _poppler_structure_element_new (poppler_structure->root->getElement (index));
+      g_object_ref_sink (poppler_structure->children[index]);
+    }
+  return poppler_structure->children[index];
+}
+
+
+static void
+_poppler_structure_find_elements_helper (StructElement       *element,
+                                         StructElement::Type  type,
+                                         Ref                 *pageRef,
+                                         GList              **result)
+{
+  g_assert (element);
+  g_assert (result);
+
+  /* Traverse the tree depth-first, to get elements in logical order */
+  for (unsigned i = 0; i < element->getNumElements (); i++)
+    {
+      _poppler_structure_find_elements_helper (element->getElement (i),
+                                               type,
+                                               pageRef,
+                                               result);
+    }
+
+  /*
+   * If filtering by type, when the type does not match,
+   * return without adding the element to the result list.
+   */
+  if (type != StructElement::Unknown && (type != element->getType ()))
+    return;
+
+  /*
+   * If filtering by page, when the page does not match,
+   * return without adding the element to the result list.
+   */
+  if (pageRef)
+    {
+      Ref ref = element->getPageRef ();
+      if (!(pageRef->num == ref.num && pageRef->gen == ref.gen))
+        return;
+    }
+
+  /*
+   * All filtering checks passed, add element to result list.
+   */
+  *result = g_list_append (*result, _poppler_structure_element_new (element));
+}
+
+/**
+ * poppler_structure_find_elements:
+ * @poppler_structure: A #PopplerStructure.
+ * @type: A #PopplerStructureElementKind value. Use
+ *   #POPPLER_STRUCTURE_ELEMENT_UNKNOWN to return all the structure
+ *   elements, or any other value to obtain only the elements of the
+ *   given type.
+ * @page: Limit the elements returned to those whose content is to
+ *   be displayed in a certain page. Use <code>-1</code> to obtain
+ *   elements from all the pages.
+ *
+ * The elements are returned in *logical order* as defined in the
+ * PDF specification, being that the ordering resulting of a depth-first
+ * traversal of the structure tree.
+ *
+ * Return value: (element-type PopplerStructureElement) (transfer full):
+ *   A #GList of #PopplerStructureElement objects.
+ */
+GList*
+poppler_structure_find_elements (PopplerStructure           *poppler_structure,
+                                 PopplerStructureElementKind kind,
+                                 gint                        page)
+{
+  GList *result = NULL;
+  Ref *pageRef = NULL;
+
+  g_return_val_if_fail (POPPLER_IS_STRUCTURE (poppler_structure), NULL);
+
+  if (page >= 0)
+    {
+      pageRef = poppler_structure->document->doc->getCatalog ()->getPageRef(page);
+    }
+
+  for (unsigned i = 0; i < poppler_structure->root->getNumElements (); i++)
+    {
+      _poppler_structure_find_elements_helper (poppler_structure->root->getElement (i),
+                                               _poppler_structure_element_kind_to_structelement_type (kind),
+                                               pageRef,
+                                               &result);
+    }
+
+  return result;
+}
diff --git a/glib/poppler-structure.h b/glib/poppler-structure.h
new file mode 100644
index 0000000..d01d551
--- /dev/null
+++ b/glib/poppler-structure.h
@@ -0,0 +1,43 @@
+/* poppler-structure.h: 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.
+ */
+
+#ifndef __POPPLER_STRUCTURE_H__
+#define __POPPLER_STRUCTURE_H__
+
+#include <glib-object.h>
+#include "poppler.h"
+#include "poppler-structure-element.h"
+
+G_BEGIN_DECLS
+
+#define POPPLER_TYPE_STRUCTURE            (poppler_structure_get_type ())
+#define POPPLER_STRUCTURE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_STRUCTURE, PopplerStructure))
+#define POPPLER_IS_STRUCTURE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_STRUCTURE))
+
+GType                       poppler_structure_get_type                  (void) G_GNUC_CONST;
+guint                       poppler_structure_get_n_children            (PopplerStructure           *poppler_structure);
+PopplerStructureElement    *poppler_structure_get_child                 (PopplerStructure           *poppler_structure,
+                                                                         guint                       index);
+GList                      *poppler_structure_find_elements             (PopplerStructure           *poppler_structure,
+                                                                         PopplerStructureElementKind kind,
+                                                                         gint                        page);
+
+G_END_DECLS
+
+#endif /* !__POPPLER_STRUCTURE_H__ */
diff --git a/glib/poppler.h b/glib/poppler.h
index 2d190f3..3cdc077 100644
--- a/glib/poppler.h
+++ b/glib/poppler.h
@@ -202,6 +202,8 @@ typedef struct _PopplerAnnotFileAttachment PopplerAnnotFileAttachment;
 typedef struct _PopplerAnnotMovie          PopplerAnnotMovie;
 typedef struct _PopplerAnnotScreen         PopplerAnnotScreen;
 typedef struct _PopplerAnnotCalloutLine    PopplerAnnotCalloutLine;
+typedef struct _PopplerStructure           PopplerStructure;
+typedef struct _PopplerStructureElement    PopplerStructureElement;
 
 typedef enum
 {
@@ -227,5 +229,6 @@ G_END_DECLS
 #include "poppler-date.h"
 #include "poppler-movie.h"
 #include "poppler-media.h"
+#include "poppler-structure.h"
 
 #endif /* __POPPLER_GLIB_H__ */
diff --git a/glib/reference/poppler-docs.sgml b/glib/reference/poppler-docs.sgml
index a9d5158..9617ed7 100644
--- a/glib/reference/poppler-docs.sgml
+++ b/glib/reference/poppler-docs.sgml
@@ -23,6 +23,8 @@
     <xi:include href="xml/poppler-layer.xml"/>
     <xi:include href="xml/poppler-media.xml"/>
     <xi:include href="xml/poppler-movie.xml"/>
+		<xi:include href="xml/poppler-structure.xml"/>
+		<xi:include href="xml/poppler-structure-element.xml"/>
     <xi:include href="xml/poppler-features.xml"/>
   </chapter>
 
diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt
index 6fb14bc..6c4ebc9 100644
--- a/glib/reference/poppler-sections.txt
+++ b/glib/reference/poppler-sections.txt
@@ -145,6 +145,7 @@ poppler_document_get_n_attachments
 poppler_document_has_attachments
 poppler_document_get_attachments
 poppler_document_get_form_field
+poppler_document_get_structure
 poppler_index_iter_new
 poppler_index_iter_copy
 poppler_index_iter_free
@@ -535,6 +536,91 @@ poppler_movie_get_type
 </SECTION>
 
 <SECTION>
+<FILE>poppler-structure</FILE>
+<TITLE>PopplerStructure</TITLE>
+PopplerStructure
+poppler_structure_get_n_children
+poppler_structure_get_child
+poppler_structure_find_elements
+
+<SUBSECTION Standard>
+POPPLER_STRUCTURE
+POPPLER_IS_STRUCTURE
+POPPLER_TYPE_STRUCTURE
+
+<SUBSECTION Private>
+poppler_structure_get_type
+</SECTION>
+
+<SECTION>
+<FILE>poppler-structure-element</FILE>
+<TITLE>PopplerStructureElement</TITLE>
+PopplerStructureElement
+poppler_structure_element_get_element_type
+poppler_structure_element_get_n_children
+poppler_structure_element_get_child
+poppler_structure_element_get_attribute
+poppler_structure_element_get_user_property
+PopplerStructureElementType
+PopplerStructureAttribute
+PopplerStructurePlacement
+PopplerStructureWritingMode
+PopplerStructureBorderStyle
+PopplerStructureTextAlign
+PopplerStructureBlockAlign
+PopplerStructureInlineAlign
+PopplerStructureTextDecoration
+PopplerStructureRubyAlign
+PopplerStructureRubyPosition
+PopplerStructureGlyphOrientation
+PopplerStructureListNumbering
+PopplerStructureRole
+PopplerStructureChecked
+PopplerStructureScope
+
+<SUBSECTION Standard>
+POPPLER_STRUCTURE_ELEMENT
+POPPLER_IS_STRUCTURE_ELEMENT
+POPPLER_STRUCTURE_ELEMENT_TYPE
+POPPLER_TYPE_STRUCTURE_ATTRIBUTE
+POPPLER_TYPE_STRUCTURE_BLOCK_ALIGN
+POPPLER_TYPE_STRUCTURE_BORDER_STYLE
+POPPLER_TYPE_STRUCTURE_CHECKED
+POPPLER_TYPE_STRUCTURE_ELEMENT
+POPPLER_TYPE_STRUCTURE_ELEMENT_TYPE
+POPPLER_TYPE_STRUCTURE_GLYPH_ORIENTATION
+POPPLER_TYPE_STRUCTURE_INLINE_ALIGN
+POPPLER_TYPE_STRUCTURE_LIST_NUMBERING
+POPPLER_TYPE_STRUCTURE_PLACEMENT
+POPPLER_TYPE_STRUCTURE_ROLE
+POPPLER_TYPE_STRUCTURE_RUBY_ALIGN
+POPPLER_TYPE_STRUCTURE_RUBY_POSITION
+POPPLER_TYPE_STRUCTURE_SCOPE
+POPPLER_TYPE_STRUCTURE_TEXT_ALIGN
+POPPLER_TYPE_STRUCTURE_TEXT_DECORATION
+POPPLER_TYPE_STRUCTURE_WRITING_MODE
+
+<SUBSECTION Private>
+poppler_structure_element_get_type
+poppler_structure_attribute_get_type
+poppler_structure_block_align_get_type
+poppler_structure_border_style_get_type
+poppler_structure_checked_get_type
+poppler_structure_element_type_get_type
+poppler_structure_glyph_orientation_get_type
+poppler_structure_inline_align_get_type
+poppler_structure_list_numbering_get_type
+poppler_structure_placement_get_type
+poppler_structure_role_get_type
+poppler_structure_ruby_align_get_type
+poppler_structure_ruby_position_get_type
+poppler_structure_scope_get_type
+poppler_structure_text_align_get_type
+poppler_structure_text_decoration_get_type
+poppler_structure_writing_mode_get_type
+</SECTION>
+
+<SECTION>
 <FILE>poppler-features</FILE>
 POPPLER_HAS_CAIRO
 POPPLER_MAJOR_VERSION
diff --git a/glib/reference/poppler.types b/glib/reference/poppler.types
index eed9849..6d40ac3 100644
--- a/glib/reference/poppler.types
+++ b/glib/reference/poppler.types
@@ -8,3 +8,5 @@ poppler_annot_get_type
 poppler_layer_get_type
 poppler_media_get_type
 poppler_movie_get_type
+poppler_structure_get_type
+poppler_structure_element_get_type
-- 
1.8.3



More information about the poppler mailing list