Commit d86cbb44 authored by Daniel Garcia Moreno's avatar Daniel Garcia Moreno

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.
parent 41ec35d9
- support for multi-page display: get_current_next() or get_current_nth()
to the the page nth
......@@ -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
......
......@@ -466,6 +466,32 @@ gepub_doc_get_current (GepubDoc *doc, gsize *bufsize)
return gepub_doc_get_resource (doc, doc->spine->data, 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);
}
......@@ -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
......
......@@ -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;
}
......@@ -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
......@@ -52,6 +52,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)
{
......@@ -61,6 +72,7 @@ button_pressed (GtkButton *button, GepubDoc *doc)
gepub_doc_go_next (doc);
}
update_text (doc);
print_replaced_text (doc);
}
void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment