[dia] Bug 598399 - PDF export landscape renderer regressions



commit b561d498fc018e2faea43dcf545d94e78340fa7b
Author: Hans Breuer <hans breuer org>
Date:   Sun Jul 10 23:03:04 2011 +0200

    Bug 598399 - PDF export landscape renderer regressions
    
    GtkPrint was used for PDF pagination. But it has issues with
    landscape due to modifying the page matrix and also showing
    the result rotated in viewers - see bug 599401 in Gtk+.
    
    With some DiaRenderer API extension (adding the update rectangle
    to begin_render()) and the new data_render_paginated() the help
    of GtkPrint is no longer necessary for PDF export.
    
    (There is still something wrong with the clipping beginning on
    the second page of the PDF, but that seems to be independent of
    using the GtkPrint backend or cairo directly.)

 app/display.c                             |    2 +-
 bindings/dia-renderer.cpp                 |    4 +-
 bindings/dia-renderer.h                   |    2 +-
 lib/diaarrowchooser.c                     |    2 +-
 lib/diagdkrenderer.c                      |    4 +-
 lib/diagramdata.c                         |   47 ++++++++++++++++-
 lib/diagramdata.h                         |    4 +-
 lib/diarenderer.c                         |    4 +-
 lib/diarenderer.h                         |    2 +-
 lib/diasvgrenderer.c                      |    2 +-
 lib/libdia.def                            |    1 +
 lib/plug-ins.h                            |    2 +-
 plug-ins/cairo/diacairo-renderer.c        |   44 +++++++++++++---
 plug-ins/cairo/diacairo.c                 |   21 ++++++--
 plug-ins/cgm/cgm.c                        |    4 +-
 plug-ins/drs/dia-render-script-renderer.c |    2 +-
 plug-ins/drs/dia-render-script.c          |    2 +-
 plug-ins/dxf/dxf-export.c                 |    8 ++--
 plug-ins/hpgl/hpgl.c                      |    2 +-
 plug-ins/libart/dialibartrenderer.c       |    2 +-
 plug-ins/metapost/render_metapost.c       |    4 +-
 plug-ins/pgf/render_pgf.c                 |    4 +-
 plug-ins/postscript/diapsrenderer.c       |    2 +-
 plug-ins/pstricks/render_pstricks.c       |    4 +-
 plug-ins/python/pydia-render.c            |    2 +-
 plug-ins/svg/render_svg.c                 |    4 +-
 plug-ins/svg/svg-import.c                 |   85 +++++++++++++++++++++++++++++
 plug-ins/vdx/vdx-export.c                 |    8 ++--
 plug-ins/wmf/wmf.cpp                      |    2 +-
 plug-ins/wpg/wpg.c                        |    2 +-
 plug-ins/xfig/xfig-export.c               |    8 ++--
 31 files changed, 230 insertions(+), 56 deletions(-)
---
diff --git a/app/display.c b/app/display.c
index ace42a5..a4ec94e 100644
--- a/app/display.c
+++ b/app/display.c
@@ -658,7 +658,7 @@ ddisplay_render_pixmap(DDisplay *ddisp, Rectangle *update)
 
   /* Erase background */
   g_return_if_fail (renderer->fill_pixel_rect != NULL);
-  DIA_RENDERER_GET_CLASS(ddisp->renderer)->begin_render(ddisp->renderer);
+  DIA_RENDERER_GET_CLASS(ddisp->renderer)->begin_render(ddisp->renderer, update);
   if (update) {
     int x0, y0, x1, y1;
 
diff --git a/bindings/dia-renderer.cpp b/bindings/dia-renderer.cpp
index a6c9645..4834a15 100644
--- a/bindings/dia-renderer.cpp
+++ b/bindings/dia-renderer.cpp
@@ -56,10 +56,10 @@ dia::Renderer::get_text_width (const gchar *text, int length) const
 }
 // called before any rendering takes palce
 void 
-dia::Renderer::begin_render ()
+dia::Renderer::begin_render (const Rectangle *update)
 {
     assert (self);
-    DIA_RENDERER_GET_CLASS(self)->begin_render (self);
+    DIA_RENDERER_GET_CLASS(self)->begin_render (self, update);
 }
 // finished rendering
 void 
diff --git a/bindings/dia-renderer.h b/bindings/dia-renderer.h
index 41671f9..8224a3e 100644
--- a/bindings/dia-renderer.h
+++ b/bindings/dia-renderer.h
@@ -50,7 +50,7 @@ public :
 
     //! called before any rendering takes palce
     //! \ingroup RendererRequired
-    virtual void begin_render ();
+    virtual void begin_render (const Rectangle *);
     //! finished rendering
     //! \ingroup RendererRequired
     virtual void end_render ();
diff --git a/lib/diaarrowchooser.c b/lib/diaarrowchooser.c
index a03cf02..38ad251 100644
--- a/lib/diaarrowchooser.c
+++ b/lib/diaarrowchooser.c
@@ -224,7 +224,7 @@ dia_arrow_preview_expose(GtkWidget *widget, GdkEventExpose *event)
     renderer = new_pixmap_renderer(win, width, height);
     renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
     renderer_pixmap_set_pixmap(renderer, win, x, y, width, height);
-    renderer_ops->begin_render(renderer);
+    renderer_ops->begin_render(renderer, NULL);
     renderer_ops->set_linewidth(renderer, linewidth);
     {
       Color color_bg, color_fg;
diff --git a/lib/diagdkrenderer.c b/lib/diagdkrenderer.c
index 0478594..b7450ed 100644
--- a/lib/diagdkrenderer.c
+++ b/lib/diagdkrenderer.c
@@ -49,7 +49,7 @@
 static int get_width_pixels (DiaRenderer *);
 static int get_height_pixels (DiaRenderer *);
 
-static void begin_render (DiaRenderer *);
+static void begin_render (DiaRenderer *, const Rectangle *update);
 static void end_render (DiaRenderer *);
 
 static void set_linewidth (DiaRenderer *renderer, real linewidth);
@@ -299,7 +299,7 @@ renderer_color_convert(DiaGdkRenderer *renderer,
 }
 
 static void 
-begin_render (DiaRenderer *object)
+begin_render (DiaRenderer *object, const Rectangle *update)
 {
 }
 
diff --git a/lib/diagramdata.c b/lib/diagramdata.c
index 38c21bc..f9341ec 100644
--- a/lib/diagramdata.c
+++ b/lib/diagramdata.c
@@ -725,7 +725,7 @@ data_render(DiagramData *data, DiaRenderer *renderer, Rectangle *update,
   guint i, active_layer;
 
   if (!renderer->is_interactive) 
-    (DIA_RENDERER_GET_CLASS(renderer)->begin_render)(renderer);
+    (DIA_RENDERER_GET_CLASS(renderer)->begin_render)(renderer, update);
   
   for (i=0; i<data->layers->len; i++) {
     layer = (Layer *) g_ptr_array_index(data->layers, i);
@@ -738,6 +738,51 @@ data_render(DiagramData *data, DiaRenderer *renderer, Rectangle *update,
     (DIA_RENDERER_GET_CLASS(renderer)->end_render)(renderer);
 }
 
+/** Call data_render() for every used page in the diagram */
+void
+data_render_paginated (DiagramData *data, DiaRenderer *renderer, gpointer user_data)
+{
+  Rectangle *extents;
+  gdouble width, height;
+  gdouble x, y, initx, inity;
+  gint xpos, ypos;
+  guint nobjs = 0;
+
+  /* the usable area of the page */
+  width = data->paper.width;
+  height = data->paper.height;
+
+  /* get extents, and make them multiples of width / height */
+  extents = &data->extents;
+  initx = extents->left;
+  inity = extents->top;
+  /* make page boundaries align with origin */
+  if (!data->paper.fitto) {
+    initx = floor(initx / width)  * width;
+    inity = floor(inity / height) * height;
+  }
+
+  /* iterate through all the pages in the diagram */
+  for (y = inity, ypos = 0; y < extents->bottom; y += height, ypos++) {
+    /* ensure we are not producing pages for epsilon */
+    if ((extents->bottom - y) < 1e-6)
+      break;
+    for (x = initx, xpos = 0; x < extents->right; x += width, xpos++) {
+      Rectangle page_bounds;
+
+      if ((extents->right - x) < 1e-6)
+	break;
+
+      page_bounds.left = x;
+      page_bounds.right = x + width;
+      page_bounds.top = y;
+      page_bounds.bottom = y + height;
+
+      data_render (data, renderer, &page_bounds, NULL, user_data);
+    }
+  }
+}
+
 void 
 data_foreach_object (DiagramData *data, GFunc func, gpointer user_data)
 {
diff --git a/lib/diagramdata.h b/lib/diagramdata.h
index 41de1dc..97e8b93 100644
--- a/lib/diagramdata.h
+++ b/lib/diagramdata.h
@@ -170,7 +170,9 @@ typedef void (*ObjectRenderer)(DiaObject *obj, DiaRenderer *renderer,
 			       gpointer data);
 void data_render(DiagramData *data, DiaRenderer *renderer, Rectangle *update,
 		 ObjectRenderer obj_renderer /* Can be NULL */,
-		 gpointer gdata);  
+		 gpointer gdata);
+void data_render_paginated(DiagramData *data, DiaRenderer *renderer, gpointer user_data);
+
 void layer_render(Layer *layer, DiaRenderer *renderer, Rectangle *update,
 		  ObjectRenderer obj_renderer /* Can be NULL */,
 		  gpointer data,
diff --git a/lib/diarenderer.c b/lib/diarenderer.c
index 67b740f..0cd5263 100644
--- a/lib/diarenderer.c
+++ b/lib/diarenderer.c
@@ -52,7 +52,7 @@ static void dia_renderer_class_init (DiaRendererClass *klass);
 static int get_width_pixels (DiaRenderer *);
 static int get_height_pixels (DiaRenderer *);
 
-static void begin_render (DiaRenderer *);
+static void begin_render (DiaRenderer *, const Rectangle *update);
 static void end_render (DiaRenderer *);
 
 static void set_linewidth (DiaRenderer *renderer, real linewidth);
@@ -309,7 +309,7 @@ dia_renderer_class_init (DiaRendererClass *klass)
 }
 
 static void 
-begin_render (DiaRenderer *object)
+begin_render (DiaRenderer *object, const Rectangle *update)
 {
   g_warning ("%s::begin_render not implemented!", 
              G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (object)));
diff --git a/lib/diarenderer.h b/lib/diarenderer.h
index 0d78319..dd7aef0 100644
--- a/lib/diarenderer.h
+++ b/lib/diarenderer.h
@@ -97,7 +97,7 @@ struct _DiaRendererClass
    */
   /*! Called before rendering begins.
      Can be used to do various pre-rendering setup. */
-  void (*begin_render) (DiaRenderer *);
+  void (*begin_render) (DiaRenderer *, const Rectangle *update);
   /*! Called after all rendering is done.
      Used to do various clean-ups.*/
   void (*end_render) (DiaRenderer *);
diff --git a/lib/diasvgrenderer.c b/lib/diasvgrenderer.c
index 8caaedb..36861e7 100644
--- a/lib/diasvgrenderer.c
+++ b/lib/diasvgrenderer.c
@@ -59,7 +59,7 @@ draw_text_line(DiaRenderer *self, TextLine *text_line,
 
 /* DiaSvgRenderer methods */
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
   DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self);
 
diff --git a/lib/libdia.def b/lib/libdia.def
index f062c62..7b5c200 100644
--- a/lib/libdia.def
+++ b/lib/libdia.def
@@ -173,6 +173,7 @@ EXPORTS
  data_real
  data_remove_all_selected
  data_render
+ data_render_paginated
  data_select
  data_set_active_layer
  data_string
diff --git a/lib/plug-ins.h b/lib/plug-ins.h
index 33c2ecf..783c389 100644
--- a/lib/plug-ins.h
+++ b/lib/plug-ins.h
@@ -48,7 +48,7 @@ G_BEGIN_DECLS
  * The list is by no means complete. If in doubt about your change
  * please ask on dia-list or alternative increment ;-)      --hb
  */
-#define DIA_PLUGIN_API_VERSION 15
+#define DIA_PLUGIN_API_VERSION 16
 
 typedef enum {
   DIA_PLUGIN_INIT_OK,
diff --git a/plug-ins/cairo/diacairo-renderer.c b/plug-ins/cairo/diacairo-renderer.c
index 8de2785..72c3655 100644
--- a/plug-ins/cairo/diacairo-renderer.c
+++ b/plug-ins/cairo/diacairo-renderer.c
@@ -80,22 +80,51 @@ static void ensure_minimum_one_device_unit(DiaCairoRenderer *renderer, real *val
  * render functions 
  */ 
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
   DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self);
   real onedu = 0.0;
+  real lmargin = 0.0, tmargin = 0.0;
+  gboolean paginated = renderer->surface && /* only with our own pagination, not GtkPrint */
+    cairo_surface_get_type (renderer->surface) == CAIRO_SURFACE_TYPE_PDF && !renderer->skip_show_page;
 
-  if (renderer->surface)
+  if (renderer->surface && !renderer->cr)
     renderer->cr = cairo_create (renderer->surface);
   else
     g_assert (renderer->cr);
 
-  cairo_scale (renderer->cr, renderer->scale, renderer->scale);
+  /* remember current state, so we can start from new with every page */
+  cairo_save (renderer->cr);
+
+  if (paginated && renderer->dia) {
+    DiagramData *data = renderer->dia;
+    /* Dia's paper.width already contains the scale, cairo needs it without 
+     * Similar for margins, Dia's without, but cairo wants them?
+     */
+    real width = (data->paper.lmargin + data->paper.width * data->paper.scaling + data->paper.rmargin)
+          * (72.0 / 2.54) + 0.5;
+    real height = (data->paper.tmargin + data->paper.height * data->paper.scaling + data->paper.bmargin)
+           * (72.0 / 2.54) + 0.5;
+    /* "Changes the size of a PDF surface for the current (and
+     * subsequent) pages." Pagination setup? */
+    cairo_pdf_surface_set_size (renderer->surface, width, height);
+    lmargin = data->paper.lmargin / data->paper.scaling;
+    tmargin = data->paper.tmargin / data->paper.scaling;
+  }
+
   /* to ensure no clipping at top/left we need some extra gymnastics,
    * otherwise a box with a line witdh one one pixel might loose the
    * top/left border as in bug #147386 */
   ensure_minimum_one_device_unit (renderer, &onedu);
-  cairo_translate (renderer->cr, -renderer->dia->extents.left + onedu, -renderer->dia->extents.top + onedu);
+
+  cairo_scale (renderer->cr, renderer->scale, renderer->scale);
+  if (update && paginated) {
+    cairo_rectangle (renderer->cr, lmargin, tmargin,
+                     update->right - update->left, update->bottom - update->top);
+    cairo_clip (renderer->cr);
+    cairo_translate (renderer->cr, -update->left + lmargin, -update->top + tmargin);
+  } else
+    cairo_translate (renderer->cr, -renderer->dia->extents.left + onedu, -renderer->dia->extents.top + onedu);
   /* no more blurred UML diagrams */
   cairo_set_antialias (renderer->cr, CAIRO_ANTIALIAS_NONE);
 
@@ -164,9 +193,8 @@ end_render(DiaRenderer *self)
  
   if (!renderer->skip_show_page)
     cairo_show_page (renderer->cr);
-  DIAG_STATE(renderer->cr)
-  if (renderer->surface)
-    cairo_surface_destroy (renderer->surface);
+  /* pop current state, so we can start from new with every page */
+  cairo_restore (renderer->cr);
   DIAG_STATE(renderer->cr)
 }
 
@@ -1028,6 +1056,8 @@ cairo_renderer_finalize (GObject *object)
   DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (object);
 
   cairo_destroy (renderer->cr);
+  if (renderer->surface)
+    cairo_surface_destroy (renderer->surface);
 #ifdef HAVE_PANGOCAIRO_H
   if (renderer->layout)
     g_object_unref (renderer->layout);  
diff --git a/plug-ins/cairo/diacairo.c b/plug-ins/cairo/diacairo.c
index 75af9f5..363198f 100644
--- a/plug-ins/cairo/diacairo.c
+++ b/plug-ins/cairo/diacairo.c
@@ -173,11 +173,17 @@ export_data(DiagramData *data, const gchar *filename,
 #endif
 #ifdef CAIRO_HAS_PDF_SURFACE
   case OUTPUT_PDF :
-#define DPI 72.0 /* 600.0? */
+#define DPI 300.0 /* 600.0? */
     /* I just don't get how the scaling is supposed to work, dpi versus page size ? */
     renderer->scale = data->paper.scaling * (72.0 / 2.54);
-    width = data->paper.width * (72.0 / 2.54) + 0.5;
-    height = data->paper.height * (72.0 / 2.54) + 0.5;
+    /* Dia's paper.width already contains the scale, cairo needs it without 
+     * Similar for margins, Dia's without, but cairo wants them. The full
+     * extents don't matter here, because we do cairo_pdf_set_size() for every page.
+     */
+    width = (data->paper.lmargin + data->paper.width * data->paper.scaling + data->paper.rmargin)
+          * (72.0 / 2.54) + 0.5;
+    height = (data->paper.tmargin + data->paper.height * data->paper.scaling + data->paper.bmargin)
+           * (72.0 / 2.54) + 0.5;
     DIAG_NOTE(g_message ("PDF Surface %dx%d\n", (int)width, (int)height));
     renderer->surface = cairo_pdf_surface_create (filename_crt,
                                                   width, height);
@@ -273,7 +279,11 @@ export_data(DiagramData *data, const gchar *filename,
   DIAG_NOTE(g_message("export_data extents %f,%f -> %f,%f", 
             data->extents.left, data->extents.top, data->extents.right, data->extents.bottom));
 
-  data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL);
+  if (OUTPUT_PDF == kind)
+    data_render_paginated(data, DIA_RENDERER(renderer), NULL);
+  else
+    data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL);
+
 #if defined CAIRO_HAS_PNG_FUNCTIONS
   if (OUTPUT_PNGA == kind || OUTPUT_PNG == kind)
     {
@@ -374,7 +384,8 @@ static const gchar *pdf_extensions[] = { "pdf", NULL };
 static DiaExportFilter pdf_export_filter = {
     N_("Cairo Portable Document Format"),
     pdf_extensions,
-    export_print_data,
+    /* not using export_print_data() due to bug 599401 */
+    export_data,
     (void*)OUTPUT_PDF,
     "cairo-pdf"
 };
diff --git a/plug-ins/cgm/cgm.c b/plug-ins/cgm/cgm.c
index 5c9bf3c..5422471 100644
--- a/plug-ins/cgm/cgm.c
+++ b/plug-ins/cgm/cgm.c
@@ -246,7 +246,7 @@ struct _CgmRenderer
 
 
 
-static void begin_render(DiaRenderer *self);
+static void begin_render(DiaRenderer *self, const Rectangle *update);
 static void end_render(DiaRenderer *self);
 static void set_linewidth(DiaRenderer *self, real linewidth);
 static void set_linecaps(DiaRenderer *self, LineCaps mode);
@@ -601,7 +601,7 @@ TextAttrCGM    *tnew, *told;
 
 
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
 }
 
diff --git a/plug-ins/drs/dia-render-script-renderer.c b/plug-ins/drs/dia-render-script-renderer.c
index 81cfe9d..87b1143 100644
--- a/plug-ins/drs/dia-render-script-renderer.c
+++ b/plug-ins/drs/dia-render-script-renderer.c
@@ -129,7 +129,7 @@ draw_object(DiaRenderer *self,
 }
 
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
   DrsRenderer *renderer = DRS_RENDERER (self);
   xmlNodePtr node;
diff --git a/plug-ins/drs/dia-render-script.c b/plug-ins/drs/dia-render-script.c
index da079b6..a390f8c 100644
--- a/plug-ins/drs/dia-render-script.c
+++ b/plug-ins/drs/dia-render-script.c
@@ -99,7 +99,7 @@ drs_data_render (DiagramData *data, DiaRenderer *renderer)
 {
   int i;
   
-  DIA_RENDERER_GET_CLASS(renderer)->begin_render(renderer);
+  DIA_RENDERER_GET_CLASS(renderer)->begin_render(renderer, NULL);
   for (i=0; i<data->layers->len; i++) {
     Layer *layer = (Layer *) g_ptr_array_index(data->layers, i);
     drs_render_layer (renderer, layer, layer == data->active_layer);
diff --git a/plug-ins/dxf/dxf-export.c b/plug-ins/dxf/dxf-export.c
index 8f94dd8..e51deb5 100644
--- a/plug-ins/dxf/dxf-export.c
+++ b/plug-ins/dxf/dxf-export.c
@@ -121,7 +121,7 @@ struct _DxfRenderer
 };
 
 
-static void begin_render(DiaRenderer *self);
+static void begin_render(DiaRenderer *self, const Rectangle *update);
 static void end_render(DiaRenderer *self);
 static void set_linewidth(DiaRenderer *self, real linewidth);
 static void set_linecaps(DiaRenderer *self, LineCaps mode);
@@ -252,7 +252,7 @@ init_attributes( DxfRenderer *renderer )
 }
 
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
 }
 
@@ -635,8 +635,8 @@ export_dxf(DiagramData *data, const gchar *filename,
     
     init_attributes(renderer);
 
-    DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer));
-  
+    DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer), NULL);
+
     for (i=0; i<data->layers->len; i++) {
         layer = (Layer *) g_ptr_array_index(data->layers, i);
 	    renderer->layername = layer->name;
diff --git a/plug-ins/hpgl/hpgl.c b/plug-ins/hpgl/hpgl.c
index e205070..1efb26e 100644
--- a/plug-ins/hpgl/hpgl.c
+++ b/plug-ins/hpgl/hpgl.c
@@ -164,7 +164,7 @@ hpgl_scale(HpglRenderer *renderer, real val)
 
 /* render functions */ 
 static void
-begin_render(DiaRenderer *object)
+begin_render(DiaRenderer *object, const Rectangle *update)
 {
     HpglRenderer *renderer = HPGL_RENDERER (object);
     int i;
diff --git a/plug-ins/libart/dialibartrenderer.c b/plug-ins/libart/dialibartrenderer.c
index cbf2009..b96c3b5 100644
--- a/plug-ins/libart/dialibartrenderer.c
+++ b/plug-ins/libart/dialibartrenderer.c
@@ -111,7 +111,7 @@ get_height_pixels (DiaRenderer *self)
 }
 
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
 #ifdef HAVE_FREETYPE
   /* pango_ft2_get_context API docs :
diff --git a/plug-ins/metapost/render_metapost.c b/plug-ins/metapost/render_metapost.c
index 6ca0d6b..15444a8 100644
--- a/plug-ins/metapost/render_metapost.c
+++ b/plug-ins/metapost/render_metapost.c
@@ -153,7 +153,7 @@ static _slant_lookup_entry SLANT_LOOKUP_TABLE[] =
 static void end_draw_op(MetapostRenderer *renderer);
 static void draw_with_linestyle(MetapostRenderer *renderer);
 
-static void begin_render(DiaRenderer *self);
+static void begin_render(DiaRenderer *self, const Rectangle *update);
 static void end_render(DiaRenderer *self);
 static void set_linewidth(DiaRenderer *self, real linewidth);
 static void set_linecaps(DiaRenderer *self, LineCaps mode);
@@ -346,7 +346,7 @@ set_fill_color(MetapostRenderer *renderer,Color *color)
 
 
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
 }
 
diff --git a/plug-ins/pgf/render_pgf.c b/plug-ins/pgf/render_pgf.c
index 6b1b6bb..f5c3618 100644
--- a/plug-ins/pgf/render_pgf.c
+++ b/plug-ins/pgf/render_pgf.c
@@ -79,7 +79,7 @@ TODO:
 #define pgf_itostr(buf,i) \
 	g_sprintf(buf,"%d",i)
 
-static void begin_render(DiaRenderer *self);
+static void begin_render(DiaRenderer *self, const Rectangle *update);
 static void end_render(DiaRenderer *self);
 static void set_linewidth(DiaRenderer *self, real linewidth);
 static void set_linecaps(DiaRenderer *self, LineCaps mode);
@@ -322,7 +322,7 @@ set_fill_color(PgfRenderer *renderer,Color *color)
 }
 
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
 }
 
diff --git a/plug-ins/postscript/diapsrenderer.c b/plug-ins/postscript/diapsrenderer.c
index f6bdb1a..f433491 100644
--- a/plug-ins/postscript/diapsrenderer.c
+++ b/plug-ins/postscript/diapsrenderer.c
@@ -68,7 +68,7 @@ lazy_setcolor(DiaPsRenderer *renderer,
 }
 
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
   DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
   time_t time_now;
diff --git a/plug-ins/pstricks/render_pstricks.c b/plug-ins/pstricks/render_pstricks.c
index e6d85df..2b5745a 100644
--- a/plug-ins/pstricks/render_pstricks.c
+++ b/plug-ins/pstricks/render_pstricks.c
@@ -64,7 +64,7 @@ NOT WORKING (exporting macros):
 #define pstricks_dtostr(buf,d) \
 	g_ascii_formatd(buf,sizeof(buf),"%f",d)
 
-static void begin_render(DiaRenderer *self);
+static void begin_render(DiaRenderer *self, const Rectangle *update);
 static void end_render(DiaRenderer *self);
 static void set_linewidth(DiaRenderer *self, real linewidth);
 static void set_linecaps(DiaRenderer *self, LineCaps mode);
@@ -238,7 +238,7 @@ set_fill_color(PstricksRenderer *renderer,Color *color)
 }
 
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
 }
 
diff --git a/plug-ins/python/pydia-render.c b/plug-ins/python/pydia-render.c
index c094c6d..ac7b39c 100644
--- a/plug-ins/python/pydia-render.c
+++ b/plug-ins/python/pydia-render.c
@@ -82,7 +82,7 @@ struct _DiaPyRendererClass
  * Members overwritable by Python scripts
  */
 static void
-begin_render(DiaRenderer *renderer)
+begin_render(DiaRenderer *renderer, const Rectangle *update)
 {
   PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);
 
diff --git a/plug-ins/svg/render_svg.c b/plug-ins/svg/render_svg.c
index 744b048..003a447 100644
--- a/plug-ins/svg/render_svg.c
+++ b/plug-ins/svg/render_svg.c
@@ -136,11 +136,11 @@ svg_renderer_get_type (void)
 }
 
 static void
-begin_render (DiaRenderer *self)
+begin_render (DiaRenderer *self, const Rectangle *update)
 {
   SvgRenderer *renderer = SVG_RENDERER (self);
   g_assert (g_queue_is_empty (renderer->parents));
-  DIA_RENDERER_CLASS (parent_class)->begin_render (DIA_RENDERER (self));
+  DIA_RENDERER_CLASS (parent_class)->begin_render (DIA_RENDERER (self), NULL);
 }
 
 static void
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index 10328ae..a95caf0 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -184,6 +184,58 @@ static PropDescription svg_text_prop_descs[] = {
     { "text", PROP_TYPE_TEXT },
     PROP_DESC_END};
 
+
+/* <use/> has x and y attributes, use to position */
+static void
+use_position (DiaObject *obj, xmlNodePtr node)
+{
+    Point pos = {0, 0};
+    xmlChar *str;
+
+    str = xmlGetProp(node, (const xmlChar *)"x");
+    if (str) {
+        pos.x = get_value_as_cm((char *) str, NULL);
+        xmlFree(str);
+    }
+
+    str = xmlGetProp(node, (const xmlChar *)"y");
+    if (str) {
+        pos.y = get_value_as_cm((char *) str, NULL);
+        xmlFree(str);
+    }
+    /* assuming the original is at 0,0 */
+    obj->ops->move(obj, &pos);
+
+    str = xmlGetProp(node, (const xmlChar *)"transform");
+    if (str) {
+        DiaMatrix *m = dia_svg_parse_transform ((const gchar *)str, user_scale);
+
+	if (m) {
+	    GPtrArray *props = g_ptr_array_new ();
+	    PointProperty *pp;
+	    RealProperty  *pr;
+
+	    prop_list_add_point (props, "obj_pos", &pos); 
+	    prop_list_add_real (props, "width", 1.0);
+	    prop_list_add_real (props, "height", 1.0);
+	    obj->ops->get_props (obj, props);
+	    /* try to transform the object without the full matrix  */
+	    pp = g_ptr_array_index (props, 0);
+	    pp->point_data.x +=  m->x0;
+	    pp->point_data.y +=  m->x0;
+	    pr = g_ptr_array_index (props, 1);
+	    pr->real_data *= m->xx;
+	    pr = g_ptr_array_index (props, 2);
+	    pr->real_data *= m->yy;
+	    obj->ops->set_props (obj, props);
+
+	    prop_list_free (props);
+	    g_free (m);
+	}
+        xmlFree(str);
+    }
+}
+
 /* apply SVG style to object */
 static void
 apply_style(DiaObject *obj, xmlNodePtr node, DiaSvgStyle *parent_style) 
@@ -741,6 +793,19 @@ read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, const gc
   return g_list_append (list, new_obj);
 }
 
+/* GFunc for foreach */
+static void
+add_def (gpointer       data,
+         gpointer       user_data)
+{
+  DiaObject  *obj = (DiaObject *)data;
+  GHashTable *defs_ht = (GHashTable *)user_data;
+  gchar *id = dia_object_get_meta (obj, "id");
+  if (id) /* pass ownership of name and object */
+    g_hash_table_insert (defs_ht, id, obj);
+  else
+    obj->ops->destroy (obj);
+}
 
 /*!
  * Fill a GList* with objects which is to be put in a
@@ -804,6 +869,15 @@ read_items (xmlNodePtr   startnode,
         dia_font_unref (group_gs->font);
       g_free (group_gs);
       g_free (matrix);
+    } else if (!xmlStrcmp(node->name, (const xmlChar *)"symbol")) {
+      /* ignore ‘viewBox’ and ‘preserveAspectRatio’ */
+      GList *moreitems = read_items (node->xmlChildrenNode, parent_gs, defs_ht, filename_svg);
+
+      /* only one object or create a group */
+      if (g_list_length (moreitems))
+	obj = group_create (moreitems);
+      else
+	obj = g_list_last(items)->data;
     } else if (!xmlStrcmp(node->name, (const xmlChar *)"rect")) {
       items = read_rect_svg(node, parent_gs, items);
       if (items)
@@ -844,6 +918,7 @@ read_items (xmlNodePtr   startnode,
       GList *list, *defs = read_items (node->xmlChildrenNode, parent_gs, defs_ht, filename_svg);
 
       for (list = defs; list != NULL; list = g_list_next (list)) {
+#if 0
 	gchar *id;
 
 	otemp = list->data;
@@ -851,11 +926,18 @@ read_items (xmlNodePtr   startnode,
 	if (id) {
 	  /* pass ownership of name and object */
 	  g_hash_table_insert (defs_ht, id, otemp);
+	} else if (IS_GROUP (otemp)) {
+	  /* defs in groups, I don't get the benefit */
+	  GList *moredefs = group_objects (otemp);
+
+	  g_list_foreach (moredefs, add_def, defs_ht);
+	  group_destroy_shallow (otemp);
 	} else {
 	  /* just loose the object */
 	  otemp->ops->destroy (otemp);
 	  list->data = NULL;
 	}
+#endif
       }
     } else if(!xmlStrcmp(node->name, (const xmlChar *)"use")) {
       xmlChar *key = xmlGetProp (node, (const xmlChar *)"xlink:href");
@@ -869,6 +951,7 @@ read_items (xmlNodePtr   startnode,
 	if (otemp) {
 	  DiaObject *onew = otemp->ops->copy (otemp);
 
+	  use_position (onew, node);
 	  apply_style (onew, node, parent_gs);
 	  items = g_list_append (items, onew);
 	}
@@ -905,6 +988,8 @@ read_items (xmlNodePtr   startnode,
       xmlChar *val = xmlGetProp (node, (const xmlChar *)"id");
       if (val) {
 	dia_object_set_meta (obj, "id", val);
+	if (defs_ht) /* FIXME: adding everything with id */
+	  g_hash_table_insert (defs_ht, g_strdup ((char *)val), obj);
 	xmlFree (val);
       }
     }
diff --git a/plug-ins/vdx/vdx-export.c b/plug-ins/vdx/vdx-export.c
index 5dc1998..59a4d46 100644
--- a/plug-ins/vdx/vdx-export.c
+++ b/plug-ins/vdx/vdx-export.c
@@ -98,7 +98,7 @@ struct _VDXRenderer
 };
 
 
-static void begin_render(DiaRenderer *self);
+static void begin_render(DiaRenderer *self, const Rectangle *update);
 static void end_render(DiaRenderer *renderer);
 static void set_linewidth(DiaRenderer *self, real linewidth);
 static void set_linecaps(DiaRenderer *self, LineCaps mode);
@@ -268,7 +268,7 @@ vdx_renderer_class_init (VDXRendererClass *klass)
  */
 
 static void 
-begin_render(DiaRenderer *self) 
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
     VDXRenderer *renderer = VDX_RENDERER(self);
     Color c;
@@ -1814,7 +1814,7 @@ export_vdx(DiagramData *data, const gchar *filename,
     
     renderer->version = 2002;   /* For now */
 
-    DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer));
+    DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer), NULL);
   
     /* First run through without drawing to setup tables */
     for (i=0; i<data->layers->len; i++) 
@@ -1830,7 +1830,7 @@ export_vdx(DiagramData *data, const gchar *filename,
 
     renderer->first_pass = FALSE;
 
-    DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer));
+    DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer), NULL);
 
     /* Now render */
 
diff --git a/plug-ins/wmf/wmf.cpp b/plug-ins/wmf/wmf.cpp
index c59883d..6524b0e 100644
--- a/plug-ins/wmf/wmf.cpp
+++ b/plug-ins/wmf/wmf.cpp
@@ -255,7 +255,7 @@ my_log(WmfRenderer* renderer, const char* format, ...)
  * renderer interface implementation
  */
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *)
 {
     WmfRenderer *renderer = WMF_RENDERER (self);
 
diff --git a/plug-ins/wpg/wpg.c b/plug-ins/wpg/wpg.c
index 24c2343..9ea56b3 100644
--- a/plug-ins/wpg/wpg.c
+++ b/plug-ins/wpg/wpg.c
@@ -259,7 +259,7 @@ WriteFillAttr(WpgRenderer *renderer, Color* colour, gboolean bFill)
  * render functions 
  */ 
 static void
-begin_render(DiaRenderer *self)
+begin_render(DiaRenderer *self, const Rectangle *update)
 {
   WpgRenderer *renderer = WPG_RENDERER (self);
 #if 0
diff --git a/plug-ins/xfig/xfig-export.c b/plug-ins/xfig/xfig-export.c
index f8a9806..32c580e 100644
--- a/plug-ins/xfig/xfig-export.c
+++ b/plug-ins/xfig/xfig-export.c
@@ -82,7 +82,7 @@ static int hasArrow(Arrow *arrow)
   return (!arrow || ARROW_NONE==arrow->type) ? 0 : 1;
 }
 
-static void begin_render(DiaRenderer *self);
+static void begin_render(DiaRenderer *self, const Rectangle *update);
 static void end_render(DiaRenderer *renderer);
 static void set_linewidth(DiaRenderer *self, real linewidth);
 static void set_linecaps(DiaRenderer *self, LineCaps mode);
@@ -477,7 +477,7 @@ figArrow(XfigRenderer *renderer, Arrow *arrow, real line_width)
 }
 
 static void 
-begin_render(DiaRenderer *self) 
+begin_render(DiaRenderer *self, const Rectangle *update) 
 {
   XfigRenderer *renderer = XFIG_RENDERER(self);
 
@@ -1175,7 +1175,7 @@ export_fig(DiagramData *data, const gchar *filename,
 
   renderer->color_pass = TRUE;
 
-  DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer));
+  DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer), NULL);
   
   for (i=0; i<data->layers->len; i++) {
     layer = (Layer *) g_ptr_array_index(data->layers, i);
@@ -1189,7 +1189,7 @@ export_fig(DiagramData *data, const gchar *filename,
 
   renderer->color_pass = FALSE;
 
-  DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer));
+  DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer), NULL);
   
   for (i=0; i<data->layers->len; i++) {
     layer = (Layer *) g_ptr_array_index(data->layers, i);



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