From da24aed4935446859fbe86a594c801ab6f282c0d Mon Sep 17 00:00:00 2001
From: Masamichi Hosoda <trueroad@trueroad.jp>
Date: Sun, 25 Sep 2016 23:39:12 +0900
Subject: [PATCH v3] Add poppler_document_build_dests_tree() to glib
 frontend

Builds named destinations balanced binary tree in document.

bug 97262
---
 glib/poppler-document.cc | 91 ++++++++++++++++++++++++++++++++++++++++++++++++
 glib/poppler-document.h  |  2 ++
 2 files changed, 93 insertions(+)

diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc
index a03f1d9..6f4c290 100644
--- a/glib/poppler-document.cc
+++ b/glib/poppler-document.cc
@@ -2,6 +2,7 @@
  * Copyright (C) 2005, Red Hat, Inc.
  *
  * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97@gmail.com>
+ * Copyright (C) 2016 Masamichi Hosoda <trueroad@trueroad.jp>
  *
  * 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
@@ -712,6 +713,96 @@ poppler_document_find_dest (PopplerDocument *document,
 	return dest;
 }
 
+static gint
+_poppler_dest_compare_gbytes (gconstpointer a,
+			      gconstpointer b,
+			      gpointer user_data)
+{
+	return g_bytes_compare (a, b);
+}
+
+static void
+_poppler_dest_destroy_key (gpointer key)
+{
+	g_bytes_unref (static_cast<GBytes*>(key));
+}
+
+static void
+_poppler_dest_destroy_value (gpointer value)
+{
+	poppler_dest_free (static_cast<PopplerDest*>(value));
+}
+
+/**
+ * poppler_document_build_dests_tree:
+ * @document: A #PopplerDocument
+ *
+ * Builds named destinations balanced binary tree in @document
+ *
+ * Return value: a #GTree or %NULL if @document is not valid.
+ * The tree key is the #GBytes which constains a destination name.
+ * Note that the names can contain \0, so it is GBytes instead of gchar*.
+ * The tree value the #PopplerDest which contains a named destination.
+ * Returned value must be freed with #g_tree_destroy.
+ *
+ * Since: 0.48
+ **/
+GTree *
+poppler_document_build_dests_tree (PopplerDocument *document)
+{
+	GTree *tree;
+	Catalog *catalog;
+	LinkDest *link_dest;
+	PopplerDest *dest;
+	int i, len;
+	GBytes *key;
+
+	g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);
+
+	catalog = document->doc->getCatalog ();
+	if (catalog == NULL)
+		return NULL;
+
+	tree = g_tree_new_full (_poppler_dest_compare_gbytes, NULL,
+				_poppler_dest_destroy_key,
+				_poppler_dest_destroy_value);
+
+	// Iterate from name-dict
+	len = catalog->numDests ();
+	for (i = 0; i < len; ++i) {
+		// The names of name-dict cannot contain \0,
+		// so we can use strlen().
+		key = g_bytes_new (catalog->getDestsName (i),
+				   strlen (catalog->getDestsName (i)));
+		link_dest = catalog->getDestsDest (i);
+		if (link_dest) {
+			dest = _poppler_dest_new_goto (document, link_dest);
+			delete link_dest;
+		} else
+			dest = NULL;
+		g_tree_insert (tree, key, dest);
+	}
+
+	// Iterate form name-tree
+	len = catalog->numDestNameTree ();
+	for (i = 0; i < len; ++i) {
+		// The names of name-tree can contain \0,
+		// so we use GBytes instead of gchar*.
+		key = g_bytes_new
+			(catalog->getDestNameTreeName (i)->getCString (),
+			 catalog->getDestNameTreeName (i)->getLength ());
+		link_dest = catalog->getDestNameTreeDest (i);
+		if (link_dest) {
+			dest = _poppler_dest_new_goto (document, link_dest);
+			delete link_dest;
+		} else
+			dest = NULL;
+		g_tree_insert (tree, key, dest);
+	}
+
+	return tree;
+}
+
 char *_poppler_goo_string_to_utf8(GooString *s)
 {
   if (s == NULL) {
diff --git a/glib/poppler-document.h b/glib/poppler-document.h
index fb0ac72..9ee82b9 100644
--- a/glib/poppler-document.h
+++ b/glib/poppler-document.h
@@ -2,6 +2,7 @@
  * Copyright (C) 2004, Red Hat, Inc.
  *
  * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97@gmail.com>
+ * Copyright (C) 2016 Masamichi Hosoda <trueroad@trueroad.jp>
  *
  * 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
@@ -240,6 +241,7 @@ GList             *poppler_document_get_attachments        (PopplerDocument  *do
 /* Links */
 PopplerDest       *poppler_document_find_dest              (PopplerDocument  *document,
 							    const gchar      *link_name);
+GTree             *poppler_document_build_dests_tree       (PopplerDocument  *document);
 
 /* Form */
 PopplerFormField  *poppler_document_get_form_field         (PopplerDocument  *document,
-- 
2.8.3