[dia] Bug 611299 - prefer relative image path for svg/shape export



commit d461bd21220f0ae2ec5350685ef40fe2c7b87b52
Author: Hans Breuer <hans breuer org>
Date:   Sun Aug 1 20:43:06 2010 +0200

    Bug 611299 - prefer relative image path for svg/shape export
    
    lib/dia_dirs.[hc] : dia_relativize_filename() to be reused elsewhere
    lib/libdia.def : export it
    lib/diasvgrenderer.c : if an included image is in the same directory as the main file use a relative path
    plug-ins/svg/svg-import.c : support relative image path, too.

 lib/dia_dirs.c            |   31 +++++++++++++++++++++++++++++++
 lib/dia_dirs.h            |    1 +
 lib/diasvgrenderer.c      |   12 ++++++++----
 lib/libdia.def            |    1 +
 plug-ins/svg/svg-import.c |   22 ++++++++++++++++------
 5 files changed, 57 insertions(+), 10 deletions(-)
---
diff --git a/lib/dia_dirs.c b/lib/dia_dirs.c
index 4111b14..7fe4cb0 100644
--- a/lib/dia_dirs.c
+++ b/lib/dia_dirs.c
@@ -263,3 +263,34 @@ dia_get_absolute_filename (const gchar *filename)
   g_free(fullname);
   return canonical;
 }
+
+/** Calculate a filename relative to the basepath of a master file
+ * @param master The main filename
+ * @param slave  A filename to become relative to the master
+ * @return Relative filename or NULL if there is no common base path
+ */
+gchar *
+dia_relativize_filename (const gchar *master, const gchar *slave)
+{
+  gchar *bp1;
+  gchar *bp2;
+  gchar * rel = NULL;
+
+  if (!g_path_is_absolute (master) || !g_path_is_absolute (slave))
+    return NULL;
+
+  bp1 = g_path_get_dirname (master);
+  bp2 = g_path_get_dirname (slave);
+
+  if (g_str_has_prefix (bp1, bp2)) {
+    gchar *p;
+    rel = g_strdup (slave + strlen (bp1) + 1);
+    /* flip backslashes */
+    for (p = rel; *p != '\0'; p++)
+      if (*p == '\\') *p = '/';    
+  }
+  g_free (bp1);
+  g_free (bp2);
+  
+  return rel;
+}
\ No newline at end of file
diff --git a/lib/dia_dirs.h b/lib/dia_dirs.h
index 355a535..2ca8154 100644
--- a/lib/dia_dirs.h
+++ b/lib/dia_dirs.h
@@ -32,6 +32,7 @@ gchar *dia_get_lib_directory  (const gchar* subdir);
 gchar *dia_config_filename    (const gchar* file);
 gboolean dia_config_ensure_dir  (const gchar* filename);
 gchar *dia_get_absolute_filename (const gchar *filename);
+gchar *dia_relativize_filename (const gchar *master, const gchar *slave);
 gchar *dia_get_canonical_path (const gchar *path);
 const gchar *dia_message_filename (const gchar *filename);
 
diff --git a/lib/diasvgrenderer.c b/lib/diasvgrenderer.c
index 94fd431..068a6ad 100644
--- a/lib/diasvgrenderer.c
+++ b/lib/diasvgrenderer.c
@@ -44,6 +44,7 @@
 #include "message.h"
 #include "dia_xml_libxml.h"
 #include "dia_image.h"
+#include "dia_dirs.h"
 
 #include "diasvgrenderer.h"
 #include "textline.h"
@@ -730,7 +731,7 @@ draw_image(DiaRenderer *self,
   DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self);
   xmlNodePtr node;
   gchar d_buf[DTOSTR_BUF_SIZE];
-  gchar *uri;
+  gchar *uri = NULL;
 
   node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"image", NULL);
 
@@ -742,9 +743,12 @@ draw_image(DiaRenderer *self,
   xmlSetProp(node, (const xmlChar *)"width", (xmlChar *) d_buf);
   dia_svg_dtostr(d_buf, height);
   xmlSetProp(node, (const xmlChar *)"height", (xmlChar *) d_buf);
-  
-  uri = g_filename_to_uri(dia_image_filename(image), NULL, NULL);
-  if (uri)
+
+  /* if the image file location is relative to the SVG file's store 
+   * a relative path */
+  if ((uri = dia_relativize_filename (renderer->filename, dia_image_filename(image))) != NULL)
+    xmlSetProp(node, (const xmlChar *)"xlink:href", (xmlChar *) uri);
+  else if ((uri = g_filename_to_uri(dia_image_filename(image), NULL, NULL)) != NULL)
     xmlSetProp(node, (const xmlChar *)"xlink:href", (xmlChar *) uri);
   else /* not sure if this fallbach is better than nothing */
     xmlSetProp(node, (const xmlChar *)"xlink:href", (xmlChar *) dia_image_filename(image));
diff --git a/lib/libdia.def b/lib/libdia.def
index 43fbfd3..5c77427 100644
--- a/lib/libdia.def
+++ b/lib/libdia.def
@@ -251,6 +251,7 @@ EXPORTS
  dia_get_data_directory
  dia_get_lib_directory
  dia_get_absolute_filename
+ dia_relativize_filename
  dia_get_canonical_path
 
  dia_image_add_ref
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index b4d5397..eb1c032 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -668,7 +668,7 @@ read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
 }
 
 static GList *
-read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list) 
+read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, const gchar *filename_svg)
 {
   xmlChar *str;
   real x = 0, y = 0, width = 0, height = 0;
@@ -702,6 +702,16 @@ read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
     str = xmlGetProp(node, (const xmlChar *)"href");
   if (str) {
     filename = g_filename_from_uri((gchar *) str, NULL, NULL);
+    if (!filename || !g_path_is_absolute (filename)) {
+      /* if image file path is relative use the main path */
+      gchar *dir = g_path_get_dirname (filename_svg);
+      gchar *absfn = g_build_path (G_DIR_SEPARATOR_S, 
+	                           dir, filename ? filename : (gchar *)str, NULL);
+
+      g_free (filename);
+      g_free (dir);
+      filename = absfn;
+    }
     xmlFree(str);
   }
   new_obj = create_standard_image(x, y, width, height, filename ? filename : "<broken>");
@@ -717,7 +727,7 @@ read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
  * Can be called recusively to allow groups in groups.
  */
 static GList*
-read_items (xmlNodePtr startnode, DiaSvgStyle *parent_gs)
+read_items (xmlNodePtr startnode, DiaSvgStyle *parent_gs, const gchar *filename_svg)
 {
   xmlNodePtr node;
   GList *items = NULL;
@@ -735,7 +745,7 @@ read_items (xmlNodePtr startnode, DiaSvgStyle *parent_gs)
       dia_svg_style_init (group_gs, parent_gs);
       dia_svg_parse_style (node, group_gs, user_scale);
 
-      moreitems = read_items (node->xmlChildrenNode, group_gs);
+      moreitems = read_items (node->xmlChildrenNode, group_gs, filename_svg);
 
       if (moreitems) {
         DiaObject *group = group_create (moreitems);
@@ -762,13 +772,13 @@ read_items (xmlNodePtr startnode, DiaSvgStyle *parent_gs)
     } else if(!xmlStrcmp(node->name, (const xmlChar *)"path")) {
       items = read_path_svg(node, parent_gs, items);
     } else if(!xmlStrcmp(node->name, (const xmlChar *)"image")) {
-      items = read_image_svg(node, parent_gs, items);
+      items = read_image_svg(node, parent_gs, items, filename_svg);
     } else {
       /* everything else is treated like a group _without grouping_, i.e. we dive into unknown stuff */
       /* this allows to import stuff generated by 'dot' with links for the nodes */
       GList *moreitems;
 
-      moreitems = read_items (node->xmlChildrenNode, parent_gs);
+      moreitems = read_items (node->xmlChildrenNode, parent_gs, filename_svg);
       if (moreitems) {
         items = g_list_concat (items, moreitems);
       }
@@ -867,7 +877,7 @@ import_svg(const gchar *filename, DiagramData *dia, void* user_data)
       xmlFree (sviewbox);
   }
   
-  items = read_items (root->xmlChildrenNode, NULL);
+  items = read_items (root->xmlChildrenNode, NULL, filename);
   for (item = items; item != NULL; item = g_list_next (item)) {
     DiaObject *obj = (DiaObject *)item->data;
     layer_add_object(dia->active_layer, obj);



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