[libgepub] Function to replace relative resources by epub://



commit d86cbb44bb1a8f5d00a411b591183cae71fd0d6f
Author: Daniel Garcia Moreno <danigm wadobo com>
Date:   Sat Jun 11 11:59:37 2016 +0200

    Function to replace relative resources by epub://
    
    Resources like styles or images are linked inside the xml doc with a
    relative path using as base the doc path.
    
    To render these resources in widgets like webkit this new function replaces
    with a the scheme, epub://, and converts these paths from relative to
    absolute so we can find these resources easily with the get_resource
    function.

 TODO                   |    2 +
 configure.ac           |    2 +
 libgepub/gepub-doc.c   |   36 ++++++++++++++++++-----
 libgepub/gepub-doc.h   |   43 ++++++++++++++--------------
 libgepub/gepub-utils.c |   73 ++++++++++++++++++++++++++++++++++++++++++++++++
 libgepub/gepub-utils.h |    5 ++-
 tests/test-gepub.c     |   12 ++++++++
 7 files changed, 142 insertions(+), 31 deletions(-)
---
diff --git a/TODO b/TODO
index e69de29..6ff37cf 100644
--- a/TODO
+++ b/TODO
@@ -0,0 +1,2 @@
+ - support for multi-page display: get_current_next() or get_current_nth()
+   to the the page nth
diff --git a/configure.ac b/configure.ac
index 5bbf804..3a9d85a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,7 @@ AC_PROG_INSTALL
 AC_PROG_LIBTOOL
 
 PKG_CHECK_MODULES(GEPUB,
+                  libsoup-2.4
                   glib-2.0
                   gobject-2.0
                   gio-2.0
@@ -27,6 +28,7 @@ AC_SUBST(GEPUB_CFLAGS)
 AC_SUBST(GEPUB_LIBS)
 
 PKG_CHECK_MODULES(GEPUB_TESTS,
+                  libsoup-2.4
                   glib-2.0
                   gobject-2.0
                   gtk+-3.0
diff --git a/libgepub/gepub-doc.c b/libgepub/gepub-doc.c
index 1729b16..001911f 100644
--- a/libgepub/gepub-doc.c
+++ b/libgepub/gepub-doc.c
@@ -467,6 +467,32 @@ gepub_doc_get_current (GepubDoc *doc, gsize *bufsize)
 }
 
 /**
+ * gepub_doc_get_current_with_epub_uris:
+ * @doc: a #GepubDoc
+ * @bufsize: (out): location to store the length in bytes of the contents
+ *
+ * Returns: (array length=bufsize) (transfer full): the current chapter
+ * data, with resource uris renamed so they have the epub:// prefix and all
+ * are relative to the root file
+ */
+guchar *
+gepub_doc_get_current_with_epub_uris (GepubDoc *doc, gsize *bufsize)
+{
+    guchar *content = gepub_doc_get_current (doc, bufsize);
+    guchar *replaced = NULL;
+    gchar *path = gepub_doc_get_current_path (doc);
+    // getting the basepath of the current xhtml loaded
+    gchar *base = g_path_get_dirname (path);
+
+    replaced = gepub_utils_replace_resources (content, bufsize, base);
+
+    g_free (path);
+    g_free (content);
+
+    return replaced;
+}
+
+/**
  * gepub_doc_get_text:
  * @doc: a #GepubDoc
  *
@@ -615,18 +641,12 @@ gchar *gepub_doc_get_resource_path (GepubDoc *doc, gchar *id)
 }
 
 /**
- * gepub_doc_get_resource_path:
+ * gepub_doc_get_current_path:
  * @doc: a #GepubDoc
  *
  * Returns: (transfer full): the current resource path
  */
 gchar *gepub_doc_get_current_path (GepubDoc *doc)
 {
-    GepubResource *gres = g_hash_table_lookup (doc->resources, doc->spine->data);
-    if (!gres) {
-        // not found
-        return NULL;
-    }
-
-    return g_strdup (gres->uri);
+    return gepub_doc_get_resource_path (doc, doc->spine->data);
 }
diff --git a/libgepub/gepub-doc.h b/libgepub/gepub-doc.h
index b399545..cb03101 100644
--- a/libgepub/gepub-doc.h
+++ b/libgepub/gepub-doc.h
@@ -42,27 +42,28 @@ struct _GepubResource {
 
 typedef struct _GepubResource GepubResource;
 
-GType             gepub_doc_get_type       (void) G_GNUC_CONST;
-
-GepubDoc         *gepub_doc_new            (const gchar *path);
-gchar            *gepub_doc_get_content    (GepubDoc *doc);
-gchar            *gepub_doc_get_metadata   (GepubDoc *doc, gchar *mdata);
-guchar           *gepub_doc_get_resource   (GepubDoc *doc, gchar *id, gsize *bufsize);
-guchar           *gepub_doc_get_resource_v (GepubDoc *doc, gchar *v, gsize *bufsize);
-GHashTable       *gepub_doc_get_resources  (GepubDoc *doc);
-gchar            *gepub_doc_get_resource_mime (GepubDoc *doc, gchar *v);
-gchar            *gepub_doc_get_resource_mime_by_id (GepubDoc *doc, gchar *id);
-gchar            *gepub_doc_get_current_mime (GepubDoc *doc);
-GList            *gepub_doc_get_spine      (GepubDoc *doc);
-GList            *gepub_doc_get_text       (GepubDoc *doc);
-GList            *gepub_doc_get_text_by_id (GepubDoc *doc, gchar *id);
-void              gepub_doc_free_text      (GList *tlist);
-guchar           *gepub_doc_get_current    (GepubDoc *doc, gsize *bufsize);
-gboolean          gepub_doc_go_next        (GepubDoc *doc);
-gboolean          gepub_doc_go_prev        (GepubDoc *doc);
-gchar            *gepub_doc_get_cover      (GepubDoc *doc);
-gchar            *gepub_doc_get_resource_path (GepubDoc *doc, gchar *id);
-gchar            *gepub_doc_get_current_path (GepubDoc *doc);
+GType             gepub_doc_get_type                        (void) G_GNUC_CONST;
+
+GepubDoc         *gepub_doc_new                             (const gchar *path);
+gchar            *gepub_doc_get_content                     (GepubDoc *doc);
+gchar            *gepub_doc_get_metadata                    (GepubDoc *doc, gchar *mdata);
+guchar           *gepub_doc_get_resource                    (GepubDoc *doc, gchar *id, gsize *bufsize);
+guchar           *gepub_doc_get_resource_v                  (GepubDoc *doc, gchar *v, gsize *bufsize);
+GHashTable       *gepub_doc_get_resources                   (GepubDoc *doc);
+gchar            *gepub_doc_get_resource_mime               (GepubDoc *doc, gchar *v);
+gchar            *gepub_doc_get_resource_mime_by_id         (GepubDoc *doc, gchar *id);
+gchar            *gepub_doc_get_current_mime                (GepubDoc *doc);
+GList            *gepub_doc_get_spine                       (GepubDoc *doc);
+GList            *gepub_doc_get_text                        (GepubDoc *doc);
+GList            *gepub_doc_get_text_by_id                  (GepubDoc *doc, gchar *id);
+void              gepub_doc_free_text                       (GList *tlist);
+guchar           *gepub_doc_get_current                     (GepubDoc *doc, gsize *bufsize);
+guchar           *gepub_doc_get_current_with_epub_uris      (GepubDoc *doc, gsize *bufsize);
+gboolean          gepub_doc_go_next                         (GepubDoc *doc);
+gboolean          gepub_doc_go_prev                         (GepubDoc *doc);
+gchar            *gepub_doc_get_cover                       (GepubDoc *doc);
+gchar            *gepub_doc_get_resource_path               (GepubDoc *doc, gchar *id);
+gchar            *gepub_doc_get_current_path                (GepubDoc *doc);
 
 G_END_DECLS
 
diff --git a/libgepub/gepub-utils.c b/libgepub/gepub-utils.c
index b76d2ee..645224e 100644
--- a/libgepub/gepub-utils.c
+++ b/libgepub/gepub-utils.c
@@ -16,13 +16,59 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <libsoup/soup.h>
+
 #include <libxml/tree.h>
+#include <libxml/parser.h>
 #include <stdarg.h>
 #include <string.h>
 
 #include "gepub-utils.h"
 #include "gepub-text-chunk.h"
 
+
+/**
+ * Replaces the attr value with epub:// prefix for the tagname. This
+ * function also makes the resource absolute based on the epub root
+ */
+static void
+set_epub_uri (xmlNode *node, gchar *path, gchar *tagname, gchar *attr)
+{
+    xmlNode *cur_node = NULL;
+    xmlNode *ret = NULL;
+    xmlChar *text = NULL;
+
+    SoupURI *baseURI;
+    gchar *basepath = g_strdup_printf ("epub://%s", path);
+
+    baseURI = soup_uri_new (basepath);
+    g_free (basepath);
+
+    for (cur_node = node; cur_node; cur_node = cur_node->next) {
+        if (cur_node->type == XML_ELEMENT_NODE ) {
+            text = xmlGetProp (cur_node, attr);
+            if (!strcmp (cur_node->name, tagname) && text) {
+                SoupURI *uri = soup_uri_new_with_base (baseURI, text);
+                gchar *value = soup_uri_to_string (uri, FALSE);
+
+                xmlSetProp (cur_node, attr, value);
+
+                soup_uri_free (uri);
+                g_free (value);
+            }
+            if (text) {
+                xmlFree (text);
+                text = NULL;
+            }
+        }
+
+        if (cur_node->children)
+            set_epub_uri (cur_node->children, path, tagname, attr);
+    }
+
+    soup_uri_free (baseURI);
+}
+
 gboolean
 gepub_utils_has_parent_tag (xmlNode *node, gchar *name, ...)
 {
@@ -150,3 +196,30 @@ gepub_utils_get_text_elements (xmlNode *node)
 
     return text_list;
 }
+
+/**
+ * replacing epub media paths, for css, image and svg files, to be
+ * able to provide these files to webkit from the epub file
+ **/
+guchar *
+gepub_utils_replace_resources (guchar *content, gsize *bufsize, gchar *path)
+{
+    xmlDoc *doc = NULL;
+    xmlNode *root_element = NULL;
+    guchar *buffer;
+
+    doc = xmlRecoverDoc (content);
+    root_element = xmlDocGetRootElement (doc);
+
+    // replacing css resources
+    set_epub_uri (root_element, path, "link", "href");
+    // replacing images resources
+    set_epub_uri (root_element, path, "img", "src");
+    // replacing svg images resources
+    set_epub_uri (root_element, path, "image", "xlink:href");
+
+    xmlDocDumpFormatMemory (doc, (xmlChar**)&buffer, (int*)bufsize, 1);
+    xmlFreeDoc (doc);
+
+    return buffer;
+}
diff --git a/libgepub/gepub-utils.h b/libgepub/gepub-utils.h
index 0abe2e6..1d51607 100644
--- a/libgepub/gepub-utils.h
+++ b/libgepub/gepub-utils.h
@@ -22,8 +22,9 @@
 #include <glib.h>
 #include <libxml/tree.h>
 
-xmlNode * gepub_utils_get_element_by_tag (xmlNode *node, gchar *name);
+xmlNode * gepub_utils_get_element_by_tag  (xmlNode *node, gchar *name);
 xmlNode * gepub_utils_get_element_by_attr (xmlNode *node, gchar *attr, gchar *value);
-GList *   gepub_utils_get_text_elements  (xmlNode *node);
+GList *   gepub_utils_get_text_elements   (xmlNode *node);
+guchar *  gepub_utils_replace_resources   (guchar *content, gsize *bufsize, gchar *path);
 
 #endif
diff --git a/tests/test-gepub.c b/tests/test-gepub.c
index e11b866..55c4bee 100644
--- a/tests/test-gepub.c
+++ b/tests/test-gepub.c
@@ -53,6 +53,17 @@ update_text (GepubDoc *doc)
 }
 
 void
+print_replaced_text (GepubDoc *doc)
+{
+    gsize s = 0;
+    guchar *content = NULL;
+    content = gepub_doc_get_current_with_epub_uris (doc, &s);
+
+    printf ("\n\nREPLACED:\n%s\n", content);
+    g_free (content);
+}
+
+void
 button_pressed (GtkButton *button, GepubDoc *doc)
 {
     if (!strcmp (gtk_button_get_label (button), "prev")) {
@@ -61,6 +72,7 @@ button_pressed (GtkButton *button, GepubDoc *doc)
         gepub_doc_go_next (doc);
     }
     update_text (doc);
+    print_replaced_text (doc);
 }
 
 void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]