Okay, here we are, sooner than I expected =)

I attached two files to this post and hopefully, I did not edit any other that I forgot to attach.

In pydia-render.c, I added draw_rounded_rect and fill_rounded_rect and declared them at the bottom of the file. I needed that to get pretty clean SVG code that's rendered correctly in Firefox. Before that, other functions like ellipse or arc were used to achieve this and that ended up in strange results.

The other file I added is my diasvgcss.py file. It's based on Hans' diasvg.py with the following modifications:

- scale all coordinates and line widths with 20 (as in the C renderer)
- corrected SVG viewBox (width must be width-x, height must be height-x, that thing made me nearly crazy *g*)
- put all objects in group tags
- added meta id as group class
- added object name as group name
- if an item has a meta id, the fill or stroke value is saved in a separate CSS file (<svgname>.css), if not it's saved in the tag itself

I hope that my modifications are useful to someone else than me so that they find their way to the default Dia version. Please be kind if there are any C or Python mistakes, I did not have much contact to either before that ;-)

As I mentioned in an earlier post, I'm using this to extend Concordion tests with diagrams. I'm about to write a blog entry for our company's blog and I'll post the link to it once it's finished.

If anyone's interested in, I could also merge my modifications to the original diasvg.py, except the export of the CSS attributes. I'm always interested in feedback, so if you've got any questions or suggestions, feel free to drop me a line. Let me know what you think about it!

Regards

Max



Am 25.01.11 21:27, schrieb Max Wahler:
Hi CGodefroy,

as Steffen already mentioned, I'm currently also working on customizing
the Python SVG exporter. Actually there _is_ a draw_object method! It's
in line 50 of the current GIT version. I hope that I'm ready to commit
my code for review to this mailing list this week.

A few words about what I'm doing: It groups the tags for objects and
sets the object's id as class argument. I use this to style the objects
afterwards via CSS.

Regards

Max


Am 25.01.2011 15:06, schrieb Cgodefroy:

Hello,
I would like to customize the Dia SVG export. I need to insert into my
SVG
document, informations about the objets (like their id). I have found the
diasvg.py file which seems to be the simplest way to customize my export.
Unfortunately, in this file there is no "draw_object" function. Do you
know
if there is a simple way to do my export? Has some people insert the
draw_object function in the diasvg.py file ?
Thanks for your help.
Regards
CGodefroy

_______________________________________________
dia-list mailing list
dia-list@gnome.org
http://mail.gnome.org/mailman/listinfo/dia-list
FAQ at http://live.gnome.org/Dia/Faq
Main page at http://live.gnome.org/Dia



--
All those, who believe in telekinesis, raise my hand.
/* Python plug-in for dia
 * Copyright (C) 1999  James Henstridge
 * Copyright (C) 2000,2002  Hans Breuer
 *
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <config.h>

#include <Python.h>
#include <glib.h>
#include <glib/gstdio.h>

#include <locale.h>

#include "intl.h"
#include "message.h"
#include "geometry.h"

#include "pydia-object.h" /* for PyObject_HEAD_INIT */
#include "pydia-export.h"
#include "pydia-diagramdata.h"
#include "pydia-geometry.h"
#include "pydia-color.h"
#include "pydia-font.h"
#include "pydia-image.h"
#include "pydia-error.h"
#include "pydia-render.h"

/*
 * The PyDiaRenderer is currently defined in Python only. The
 * DiaPyRenderer is using it's interface to map the gobject
 * DiaRenderer to it. A next step could be to let Python code
 * directly inherit from DiaPyRenderer.
 * To do that probably some code from pygtk.gobject needs to
 * be borrowed/shared
 */
#include "diarenderer.h"

#define DIA_TYPE_PY_RENDERER           (dia_py_renderer_get_type ())
#define DIA_PY_RENDERER(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
DIA_TYPE_PY_RENDERER, DiaPyRenderer))
#define DIA_PY_RENDERER_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), 
DIA_TYPE_PY_RENDERER, DiaPyRendererClass))
#define DIA_IS_PY_RENDERER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
DIA_TYPE_PY_RENDERER))
#define DIA_PY_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
DIA_TYPE_PY_RENDERER, DiaPyRendererClass))

GType dia_py_renderer_get_type (void) G_GNUC_CONST;

typedef struct _DiaPyRenderer DiaPyRenderer;
typedef struct _DiaPyRendererClass DiaPyRendererClass;

struct _DiaPyRenderer
{
  DiaRenderer parent_instance;

  char*     filename;
  PyObject* self; 
  PyObject* diagram_data;
  char*     old_locale;
};

struct _DiaPyRendererClass
{
  DiaRendererClass parent_class;
};

#define PYDIA_RENDERER(renderer) \
        (DIA_PY_RENDERER(renderer)->self)

/*
 * Members overwritable by Python scripts
 */
static void
begin_render(DiaRenderer *renderer)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  DIA_PY_RENDERER(renderer)->old_locale = setlocale(LC_NUMERIC, "C");

  func = PyObject_GetAttrString (self, "begin_render");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(Os)", 
                         DIA_PY_RENDERER(renderer)->diagram_data, 
                         DIA_PY_RENDERER(renderer)->filename);
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF (func);
    Py_DECREF (self);
  }
}

static void
end_render(DiaRenderer *renderer)
{
  PyObject *func, *res, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "end_render");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    res = PyEval_CallObject (func, (PyObject *)NULL);
    ON_RES(res, FALSE);
    Py_DECREF(func);
    Py_DECREF(self);
  }

  Py_DECREF (DIA_PY_RENDERER(renderer)->diagram_data);
  g_free (DIA_PY_RENDERER(renderer)->filename);
  DIA_PY_RENDERER(renderer)->filename = NULL;

  setlocale(LC_NUMERIC, DIA_PY_RENDERER(renderer)->old_locale);
}

static void
set_linewidth(DiaRenderer *renderer, real linewidth)
{  
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "set_linewidth");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(d)", linewidth);
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else /* member optional */
    PyErr_Clear();
}

static void
set_linecaps(DiaRenderer *renderer, LineCaps mode)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  switch(mode) {
  case LINECAPS_BUTT:
    break;
  case LINECAPS_ROUND:
    break;
  case LINECAPS_PROJECTING:
    break;
  default:
    PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode 
specified!\n");
  }

  func = PyObject_GetAttrString (self, "set_linecaps");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(i)", mode);
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else /* member optional */
    PyErr_Clear();
}

static void
set_linejoin(DiaRenderer *renderer, LineJoin mode)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  switch(mode) {
    case LINEJOIN_MITER:
    break;
  case LINEJOIN_ROUND:
    break;
  case LINEJOIN_BEVEL:
    break;
  default:
    PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode 
specified!\n");
  }

  func = PyObject_GetAttrString (self, "set_linejoin");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(i)", mode);
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else /* member optional */
    PyErr_Clear();
}

static void
set_linestyle(DiaRenderer *renderer, LineStyle mode)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  /* line type */
  switch (mode) {
  case LINESTYLE_SOLID:
    break;
  case LINESTYLE_DASHED:
    break;
  case LINESTYLE_DASH_DOT:
    break;
  case LINESTYLE_DASH_DOT_DOT:
    break;
  case LINESTYLE_DOTTED:
    break;
  default:
    PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode 
specified!\n");
  }

  func = PyObject_GetAttrString (self, "set_linestyle");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(i)", mode);
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else /* member optional */
    PyErr_Clear();
}

static void
set_dashlength(DiaRenderer *renderer, real length)
{  
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "set_dashlength");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(d)", length);
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else /* member optional */
    PyErr_Clear();
}

static void
set_fillstyle(DiaRenderer *renderer, FillStyle mode)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  switch(mode) {
  case FILLSTYLE_SOLID:
    break;
  default:
    PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode 
specified!\n");
  }

  func = PyObject_GetAttrString (self, "set_fillstyle");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(i)", mode);
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else /* member optional */
    PyErr_Clear();
}

static void
set_font(DiaRenderer *renderer, DiaFont *font, real height)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "set_font");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(Od)", PyDiaFont_New (font), height);
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else /* member optional */
    PyErr_Clear();
}

static gpointer parent_class = NULL;

static void
draw_object (DiaRenderer *renderer, DiaObject *object, DiaMatrix *matrix)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "draw_object");
  if (func && PyCallable_Check(func)) {
    PyObject *mat = NULL;

    Py_INCREF(self);
    Py_INCREF(func);
    if (matrix)
      mat = PyDiaMatrix_New (matrix);
    else {
      Py_INCREF(Py_None);
      mat = Py_None;
    }
    arg = Py_BuildValue ("(OO)", PyDiaObject_New (object), mat );
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_XDECREF (mat);
    Py_DECREF(func);
    Py_DECREF(self);
  } else { /* member optional */
    PyErr_Clear();
    /* but should still call the base class */
    DIA_RENDERER_CLASS (parent_class)->draw_object (renderer, object, matrix);
  }
}

static void
draw_line(DiaRenderer *renderer, 
          Point *start, Point *end, 
          Color *line_colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "draw_line");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OOO)", PyDiaPoint_New (start),
                                  PyDiaPoint_New (end),
                                  PyDiaColor_New (line_colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member not optional */
    gchar *msg = g_strdup_printf ("%s.draw_line() implmentation missing.",
                                  G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS 
(renderer)));
    PyErr_Clear();
    PyErr_Warn (PyExc_RuntimeWarning, msg);
    g_free (msg);
  }
}

static void
draw_polyline(DiaRenderer *renderer, 
              Point *points, int num_points, 
              Color *line_colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "draw_polyline");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OO)", PyDiaPointTuple_New (points, num_points),
                                 PyDiaColor_New (line_colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member optional */
    PyErr_Clear();
    /* XXX: implementing the same fallback as DiaRenderer */
    DIA_RENDERER_CLASS (parent_class)->draw_polyline (renderer, points, 
num_points, line_colour);
  }
}

static void
draw_polygon(DiaRenderer *renderer, 
             Point *points, int num_points, 
             Color *line_colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "draw_polygon");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OO)", PyDiaPointTuple_New (points, num_points),
                                 PyDiaColor_New (line_colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member optional */
    PyErr_Clear();
    /* XXX: implementing the same fallback as DiaRenderer would do */
    DIA_RENDERER_CLASS (parent_class)->draw_polygon (renderer, points, 
num_points, line_colour);
  }
}

static void
fill_polygon(DiaRenderer *renderer, 
             Point *points, int num_points, 
             Color *colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "fill_polygon");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OO)", PyDiaPointTuple_New (points, num_points),
                                 PyDiaColor_New (colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member not optional */
    gchar *msg = g_strdup_printf ("%s.fill_polygon() implmentation missing.",
                                  G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS 
(renderer)));
    PyErr_Clear();
    PyErr_Warn (PyExc_RuntimeWarning, msg);
    g_free (msg);
  }
}

static void
draw_rect(DiaRenderer *renderer, 
          Point *ul_corner, Point *lr_corner,
          Color *colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "draw_rect");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OO)", PyDiaRectangle_New_FromPoints (ul_corner, 
lr_corner),
                                 PyDiaColor_New (colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member optional */
    PyErr_Clear();
    /* XXX: implementing the same fallback as DiaRenderer would do */
    DIA_RENDERER_CLASS (parent_class)->draw_rect (renderer, ul_corner, 
lr_corner, colour);
  }
}


static void
draw_rounded_rect(DiaRenderer *renderer, 
          Point *ul_corner, Point *lr_corner,
          Color *colour, real rounding)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "draw_rounded_rect");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OOd)", PyDiaRectangle_New_FromPoints (ul_corner, 
lr_corner),
                                 PyDiaColor_New (colour), rounding);
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member optional */
    PyErr_Clear();
    /* XXX: implementing the same fallback as DiaRenderer would do */
    DIA_RENDERER_CLASS (parent_class)->draw_rounded_rect (renderer, ul_corner, 
lr_corner, colour, rounding);
  }
}


static void
fill_rect(DiaRenderer *renderer, 
          Point *ul_corner, Point *lr_corner,
          Color *colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "fill_rect");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OO)", PyDiaRectangle_New_FromPoints (ul_corner, 
lr_corner),
                                 PyDiaColor_New (colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member not optional */
    gchar *msg = g_strdup_printf ("%s.fill_rect() implmentation missing.",
                                  G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS 
(renderer)));
    PyErr_Clear();
    PyErr_Warn (PyExc_RuntimeWarning, msg);
    g_free (msg);
  }
}

static void
fill_rounded_rect(DiaRenderer *renderer, 
          Point *ul_corner, Point *lr_corner,
          Color *colour, real rounding)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "fill_rounded_rect");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OOd)", PyDiaRectangle_New_FromPoints (ul_corner, 
lr_corner),
                                 PyDiaColor_New (colour), rounding);
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member optional */
    PyErr_Clear();
    /* XXX: implementing the same fallback as DiaRenderer would do */
    DIA_RENDERER_CLASS (parent_class)->fill_rounded_rect (renderer, ul_corner, 
lr_corner, colour, rounding);
  }
}

static void
draw_arc(DiaRenderer *renderer, 
         Point *center,
         real width, real height,
         real angle1, real angle2,
         Color *colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "draw_arc");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OddddO)", PyDiaPoint_New (center),
                                     width, height, angle1, angle2,
                                     PyDiaColor_New (colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member not optional */
    gchar *msg = g_strdup_printf ("%s.draw_arc() implmentation missing.",
                                  G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS 
(renderer)));
    PyErr_Clear();
    PyErr_Warn (PyExc_RuntimeWarning, msg);
    g_free (msg);
  }
}

static void
fill_arc(DiaRenderer *renderer, 
         Point *center,
         real width, real height,
         real angle1, real angle2,
         Color *colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "fill_arc");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OddddO)", PyDiaPoint_New (center),
                                     width, height, angle1, angle2,
                                     PyDiaColor_New (colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member not optional */
    gchar *msg = g_strdup_printf ("%s.fill_arc() implmentation missing.",
                                  G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS 
(renderer)));
    PyErr_Clear();
    PyErr_Warn (PyExc_RuntimeWarning, msg);
    g_free (msg);
  }
}

static void
draw_ellipse(DiaRenderer *renderer, 
             Point *center,
             real width, real height,
             Color *colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "draw_ellipse");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OddO)", PyDiaPoint_New (center),
                                   width, height,
                                   PyDiaColor_New (colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member not optional */
    gchar *msg = g_strdup_printf ("%s.draw_ellipse() implmentation missing.",
                                  G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS 
(renderer)));
    PyErr_Clear();
    PyErr_Warn (PyExc_RuntimeWarning, msg);
    g_free (msg);
  }
}

static void
fill_ellipse(DiaRenderer *renderer, 
             Point *center,
             real width, real height,
             Color *colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "fill_ellipse");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OddO)", PyDiaPoint_New (center),
                                   width, height,
                                   PyDiaColor_New (colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member not optional */
    gchar *msg = g_strdup_printf ("%s.fill_ellipse() implmentation missing.",
                                  G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS 
(renderer)));
    PyErr_Clear();
    PyErr_Warn (PyExc_RuntimeWarning, msg);
    g_free (msg);
  }
}

static void
draw_bezier(DiaRenderer *renderer, 
            BezPoint *points,
            int num_points,
            Color *colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "draw_bezier");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OO)", PyDiaBezPointTuple_New (points, num_points),
                                 PyDiaColor_New (colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member optional */
    PyErr_Clear();
    /* XXX: implementing the same fallback as DiaRenderer would do */
    DIA_RENDERER_CLASS (parent_class)->draw_bezier (renderer, points, 
num_points, colour);
  }
}

static void
fill_bezier(DiaRenderer *renderer, 
            BezPoint *points, /* Last point must be same as first point */
            int num_points,
            Color *colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "fill_bezier");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OO)", PyDiaBezPointTuple_New (points, num_points),
                                 PyDiaColor_New (colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  }
  else { /* member optional */
    PyErr_Clear();
    /* XXX: implementing the same fallback as DiaRenderer would do */
    DIA_RENDERER_CLASS (parent_class)->fill_bezier (renderer, points, 
num_points, colour);
  }
}

static void
draw_string(DiaRenderer *renderer,
            const char *text,
            Point *pos, Alignment alignment,
            Color *colour)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);
  int len;

  switch (alignment) {
  case ALIGN_LEFT:
    break;
  case ALIGN_CENTER:
    break;
  case ALIGN_RIGHT:
    break;
  }
  /* work out size of first chunk of text */
  len = strlen(text);

  func = PyObject_GetAttrString (self, "draw_string");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(sOiO)", text,
                                   PyDiaPoint_New (pos),
                                   alignment,
                                   PyDiaColor_New (colour));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  } else { /* member not optional */
    gchar *msg = g_strdup_printf ("%s.draw_string() implmentation missing.",
                                  G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS 
(renderer)));
    PyErr_Clear();
    PyErr_Warn (PyExc_RuntimeWarning, msg);
    g_free (msg);
  }
}

static void
draw_image(DiaRenderer *renderer,
           Point *point,
           real width, real height,
           DiaImage *image)
{
  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);

  func = PyObject_GetAttrString (self, "draw_image");
  if (func && PyCallable_Check(func)) {
    Py_INCREF(self);
    Py_INCREF(func);
    arg = Py_BuildValue ("(OddO)", PyDiaPoint_New (point),
                                   width, height,
                                   PyDiaImage_New (image));
    if (arg) {
      res = PyEval_CallObject (func, arg);
      ON_RES(res, FALSE);
    }
    Py_XDECREF (arg);
    Py_DECREF(func);
    Py_DECREF(self);
  } else { /* member not optional */
    gchar *msg = g_strdup_printf ("%s.draw_string() implmentation missing.",
                                  G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS 
(renderer)));
    PyErr_Clear();
    PyErr_Warn (PyExc_RuntimeWarning, msg);
    g_free (msg);
  }
}

void
PyDia_export_data(DiagramData *data, const gchar *filename, 
                  const gchar *diafilename, void* user_data)
{
  DiaPyRenderer *renderer;

  {
    FILE *file;
    file = g_fopen(filename, "w"); /* "wb" for binary! */

    if (file == NULL) {
      message_error(_("Couldn't open '%s' for writing.\n"), 
                    dia_message_filename(filename));
      return;
    }
    else
      fclose (file);
  }

  renderer = g_object_new (DIA_TYPE_PY_RENDERER, NULL);

  renderer->filename = g_strdup (filename);
  renderer->diagram_data = PyDiaDiagramData_New(data);

  /* The Python Renderer object was created at PyDia_Register */
  renderer->self = (PyObject*)user_data;

  /* this will call the required callback functions above */
  data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL);

  g_object_unref(renderer);
}

DiaRenderer *
PyDia_new_renderer_wrapper (PyObject *self)
{
  DiaPyRenderer *wrapper;
  
  wrapper = g_object_new (DIA_TYPE_PY_RENDERER, NULL);
  wrapper->self = self;
  
  return DIA_RENDERER (wrapper);
}

/*
 * GObject boiler plate
 */
static void dia_py_renderer_class_init (DiaPyRendererClass *klass);

GType
dia_py_renderer_get_type (void)
{
  static GType object_type = 0;

  if (!object_type)
    {
      static const GTypeInfo object_info =
      {
        sizeof (DiaPyRendererClass),
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) dia_py_renderer_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data */
        sizeof (DiaPyRenderer),
        0,              /* n_preallocs */
        NULL            /* init */
      };

      object_type = g_type_register_static (DIA_TYPE_RENDERER,
                                            "DiaPyRenderer",
                                            &object_info, 0);
    }
  
  return object_type;
}

static void
dia_py_renderer_finalize (GObject *object)
{
  DiaPyRenderer *renderer = DIA_PY_RENDERER (object);

  if (renderer->filename)
    g_free (renderer->filename);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
dia_py_renderer_class_init (DiaPyRendererClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  DiaRendererClass *renderer_class = DIA_RENDERER_CLASS (klass);

  parent_class = g_type_class_peek_parent (klass);

  object_class->finalize = dia_py_renderer_finalize;

  /* all defined members from above */
  /* renderer members */
  renderer_class->begin_render = begin_render;
  renderer_class->end_render   = end_render;

  renderer_class->draw_object  = draw_object;

  renderer_class->set_linewidth  = set_linewidth;
  renderer_class->set_linecaps   = set_linecaps;
  renderer_class->set_linejoin   = set_linejoin;
  renderer_class->set_linestyle  = set_linestyle;
  renderer_class->set_dashlength = set_dashlength;
  renderer_class->set_fillstyle  = set_fillstyle;

  renderer_class->set_font  = set_font;

  renderer_class->draw_line    = draw_line;
  renderer_class->fill_polygon = fill_polygon;
  renderer_class->draw_rect    = draw_rect;
  renderer_class->fill_rect    = fill_rect;
  renderer_class->draw_arc     = draw_arc;
  renderer_class->fill_arc     = fill_arc;
  renderer_class->draw_ellipse = draw_ellipse;
  renderer_class->fill_ellipse = fill_ellipse;

  renderer_class->draw_string  = draw_string;
  renderer_class->draw_image   = draw_image;

  /* medium level functions */
  renderer_class->draw_rect = draw_rect;
  renderer_class->draw_polyline  = draw_polyline;
  renderer_class->draw_polygon   = draw_polygon;

  renderer_class->draw_bezier   = draw_bezier;
  renderer_class->fill_bezier   = fill_bezier;

  /* highest level functions */
  renderer_class->draw_rounded_rect = draw_rounded_rect;
  renderer_class->fill_rounded_rect = fill_rounded_rect;
}

#  PyDia SVG+CSS Renderer
#  Copyright (c) 2011 Max Wahler <m...@wwwahler.de>
#
#  This SVG(Z) renderer is based on the PyDia SVG renderer by Hans Breuer.
#  
#  Instead of writing all attributes inline, a separate CSS file is generated
#  which contain the color/stroke attributes of objects that have an id meta 
#  info field.
#
#  With this, it's possible to style objects differently after the diagram
#  was exported. This is useful for example when the SVG is embedded in a
#  HTML page and single elements should be highlighted on actions.

#   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
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

import sys, string, dia

class SvgCssRenderer :
	def __init__ (self) :
		self.f = None
		self.line_width = 0.1
		self.line_caps = 0
		self.line_join = 0
		self.line_style = 0
		self.dash_length = 0
		self.scale = 20.0
		self.css = None
		self.current_id = None
		self.current_attributes = None
	def _open(self, filename) :
		self.f = open(filename, "w")
		self.css = open(filename + ".css", "w")
	def begin_render (self, data, filename) :
		self._open (filename)
		r = data.extents
		xofs = - r[0]
		yofs = - r[1]
		self.f.write('''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created by diasvgcss.py -->
<svg width="%.3fcm" height="%.3fcm" viewBox="%.3f %.3f %.3f %.3f"
 xmlns="http://www.w3.org/2000/svg";
 xmlns:xlink="http://www.w3.org/1999/xlink";>
''' % (r.right - r.left, r.bottom - r.top, r[0] * self.scale, r[1] * self.scale, (r[2] - r[0]) * self.scale, (r[3] - r[1]) * self.scale))
		#self.f.write("<!-- %s -->\n" % (str(data.extents)))
		#self.f.write("<!-- %s -->\n" % (data.active_layer.name))
	def end_render (self) :
		self.f.write('</svg>')
		self.f.close()

		self.css.close()
	def draw_object (self, object, matrix) :

		self.f.write('<g')

		# write id (class) and name attributes
		self.current_attributes = {}
		meta = object.properties['meta'].value

		if meta is not None and meta.has_key('id') :
			self.f.write(' class="%s"' % meta['id'])
			self.current_id = meta['id']
		else :
			self.current_id = None

		if object.type.name != '' :
			self.f.write(' name="%s"' % object.type.name)

		self.f.write('>\n')

		# don't forget to render the object
		object.draw (self)
		self.f.write("</g>\n\n");

		# write css content
		if self.current_id is not None :
			self.css.write('.%s {\n' % self.current_id)
			for key in self.current_attributes.keys() :
				self.css.write('\t%s: %s;\n' % (key, self.current_attributes[key]))
			self.css.write('}\n\n')


	def set_linewidth (self, width) :
		if width < 0.001 : # zero line width is invisble ?
			self.line_width = 0.001
		else :
			self.line_width = width
	def set_linecaps (self, mode) :
		self.line_caps = mode
	def set_linejoin (self, mode) :
		self.line_join = mode
	def set_linestyle (self, style) :
		self.line_style = style
	def set_dashlength (self, length) :
		self.dash_length = length
	def set_fillstyle (self, style) :
		# currently only 'solid' so not used anywhere else
		self.fill_style = style
	def set_font (self, font, size) :
		self.font = font
		self.font_size = size
	def draw_rounded_rect (self, rect, color, rounding) :
		self.f.write('<rect x="%.3f" y="%.3f" width="%.3f" height="%.3f" fill="none" %s stroke-width="%.3f" %s rx="%.3f" ry="%.3f" />\n' \
					% (	rect.left * self.scale, rect.top * self.scale, 
						(rect.right - rect.left) * self.scale, (rect.bottom - rect.top) * self.scale,
				  		self._color_attr('stroke', color), self.line_width * self.scale, self._stroke_style(), rounding * self.scale, rounding * self.scale))

	def fill_rounded_rect (self, rect, color, rounding) :
		self.f.write('<rect x="%.3f" y="%.3f" width="%.3f" height="%.3f" stroke="none" %s rx="%.3f" ry="%.3f" />\n' \
					% (	rect.left * self.scale, rect.top * self.scale, 
						(rect.right - rect.left) * self.scale, (rect.bottom - rect.top) * self.scale,
				  		self._color_attr('fill', color), rounding * self.scale, rounding * self.scale))

	def draw_line (self, start, end, color) :
		self.f.write('<line x1="%.3f" y1="%.3f" x2="%.3f" y2="%.3f" %s stroke-width="%.3f" %s/>\n' \
					% (start.x * self.scale, start.y * self.scale, end.x * self.scale, end.y * self.scale, self._color_attr('stroke', color), self.line_width * self.scale, self._stroke_style()))
	def draw_polyline (self, points, color) :
		self.f.write('<polyline fill="none" %s stroke-width="%.3f" %s points="' \
					% (self._color_attr('stroke', color), self.line_width * self.scale, self._stroke_style()))
		for pt in points :
			self.f.write ('%.3f,%.3f ' % (pt.x * self.scale, pt.y * self.scale))
		self.f.write('"/>\n')
	def draw_polygon (self, points, color) :
		self.f.write('<polygon fill="none" %s stroke-width="%.3f" %s points="' \
					% (self._color_attr('stroke', color), self.line_width * self.scale, self._stroke_style()))
		for pt in points :
			self.f.write ('%.3f,%.3f ' % (pt.x * self.scale, pt.y * self.scale))
		self.f.write('"/>\n')
	def fill_polygon (self, points, color) :
		self.f.write('<polygon %s stroke="none" stroke-width="%.3f" points="' \
					% (self._color_attr('fill', color), self.line_width * self.scale))
		for pt in points :
			self.f.write ('%.3f,%.3f ' % (pt.x * self.scale, pt.y * self.scale))
		self.f.write('"/>\n')
	def draw_rect (self, rect, color) :
		self.f.write('<rect x="%.3f" y="%.3f" width="%.3f" height="%.3f" fill="none" %s stroke-width="%.3f" %s/>\n' \
					% (	rect.left * self.scale, rect.top * self.scale, 
						(rect.right - rect.left) * self.scale, (rect.bottom - rect.top) * self.scale,
				  		self._color_attr('stroke', color), self.line_width * self.scale, self._stroke_style()))
	def fill_rect (self, rect, color) :
		self.f.write('<rect x="%.3f" y="%.3f" width="%.3f" height="%.3f" %s stroke="none" stroke-width="0"/>\n' \
					% (	rect.left * self.scale, rect.top * self.scale, 
						(rect.right - rect.left) * self.scale, (rect.bottom - rect.top) * self.scale, self._color_attr('fill', color)))
	def _arc (self, center, width, height, angle1, angle2, color, fill=None) :
		# not in the renderer interface
		import math
		mPi180 = math.pi / 180.0
		rx = width / 2.0
		ry = height / 2.0
		sx = center.x + rx * math.cos(mPi180 * angle1)
		sy = center.y - ry * math.sin(mPi180 * angle1)
		ex = center.x + rx * math.cos(mPi180 * angle2)
		ey = center.y - ry * math.sin(mPi180 * angle2)
		largearc = (angle2 - angle1 >= 180)
		sweep = 0 # always draw in negative direction
		if not fill :
			self.f.write('<path %s fill="none" stroke-width="%.3f" %s' \
				% (self._color_attr('stroke', color), self.line_width * self.scale, self._stroke_style()))
		else :
			self.f.write('<path stroke="none" %s' % (self._color_attr('fill', color)))
		# moveto sx,sy arc rx,ry x-axis-rotation large-arc-flag,sweep-flag ex,ey 
		self.f.write(' d ="M %.3f,%.3f A %.3f,%.3f 0 %d,%d %.3f,%.3f ' % (sx * self.scale, sy * self.scale, rx * self.scale, ry * self.scale, largearc, sweep, ex * self.scale, ey * self.scale))
		self.f.write('"/>\n')
	def draw_arc (self, center, width, height, angle1, angle2, color) :
		self._arc(center, width, height, angle1, angle2, color)
	def fill_arc (self, center, width, height, angle1, angle2, color) :
		self._arc(center, width, height, angle1, angle2, color, 1)
	def draw_ellipse (self, center, width, height, color) :
		self.f.write('<ellipse cx="%.3f" cy="%.3f" rx="%.3f" ry="%.3f" fill="none" %s stroke-width="%.3f" %s/>\n' \
					% (center.x * self.scale, center.y * self.scale, (width / 2) * self.scale, (height / 2) * self.scale, self._color_attr('stroke', color), self.line_width * self.scale, self._stroke_style()))
	def fill_ellipse (self, center, width, height, color) :
		self.f.write('<ellipse cx="%.3f" cy="%.3f" rx="%.3f" ry="%.3f" %s stroke="none"  />\n' \
					% (center.x * self.scale, center.y * self.scale, (width / 2) * self.scale, (height / 2) * self.scale, self._color_attr('fill', color)))
	def draw_bezier (self, bezpoints, color) :
		self.f.write('<path %s fill="none" stroke-width="%.3f" %s d="' \
					% (self._color_attr('stroke', color), self.line_width * self.scale, self._stroke_style()))
		for bp in bezpoints :
			if bp.type == 0 : # BEZ_MOVE_TO
				self.f.write('M %.3f,%.3f ' % (bp.p1.x * self.scale, bp.p1.y * self.scale))
			elif bp.type == 1 : # BEZ_LINE_TO
				self.f.write('L %.3f,%.3f ' % (bp.p1.x * self.scale, bp.p1.y * self.scale))
			elif bp.type == 2 : # BEZ_CURVE_TO
				self.f.write ('C %.3f,%.3f %.3f,%.3f %.3f,%.3f ' \
					% (bp.p1.x * self.scale, bp.p1.y * self.scale, bp.p2.x * self.scale, bp.p2.y * self.scale, bp.p3.x * self.scale, bp.p3.y * self.scale))
			else :
				dia.message(2, "Invalid BezPoint type (%d)" * bp.type)
		self.f.write('"/>\n')
	def fill_bezier (self, bezpoints, color) :
		self.f.write('<path stroke="none" %s stroke-width="%.3f" d="' \
					% (self._color_attr('fill', color), self.line_width * self.scale))
		for bp in bezpoints :
			if bp.type == 0 : # BEZ_MOVE_TO
				self.f.write('M %.3f,%.3f ' % (bp.p1.x * self.scale, bp.p1.y * self.scale))
			elif bp.type == 1 : # BEZ_LINE_TO
				self.f.write('L %.3f,%.3f ' % (bp.p1.x * self.scale, bp.p1.y * self.scale))
			elif bp.type == 2 : # BEZ_CURVE_TO
				self.f.write ('C %.3f,%.3f %.3f,%.3f %.3f,%.3f ' \
					% (bp.p1.x * self.scale, bp.p1.y * self.scale, bp.p2.x * self.scale, bp.p2.y * self.scale, bp.p3.x * self.scale, bp.p3.y * self.scale))
			else :
				dia.message(2, "Invalid BezPoint type (%d)" * bp.type)
		self.f.write('"/>\n')
	def draw_string (self, text, pos, alignment, color) :
		if len(text) < 1 :
			return # shouldn'this be done at the higher level 
		talign = ('start', 'middle', 'end') [alignment]
		fstyle = ('normal', 'italic', 'oblique') [self.font.style & 0x03]
		fweight = (400, 200, 300, 500, 600, 700, 800, 900) [(self.font.style  >> 4)  & 0x7]
		self.f.write('<text x="%.3f" y="%.3f" stroke="none" %s text-anchor="%s" font-size="%.2f" font-family="%s" font-style="%s" font-weight="%d">\n' \
			% (pos.x * self.scale, pos.y * self.scale, self._color_attr('fill', color), talign, self.font_size * self.scale, self.font.family, fstyle,  fweight))
		# avoid writing XML special characters (ampersand must be first to not break the rest)
		for rep in [('&', '&amp;'), ('<', '&lt;'), ('>', '&gt;'), ('"', '&quot;'), ("'", '&apos;')] :
			text = string.replace (text, rep[0], rep[1])
		self.f.write(text)
		self.f.write('</text>\n')
	def draw_image (self, point, width, height, image) :
		#FIXME : do something better than absolute pathes ?
		self.f.write('<image x="%.3f" y="%.3f"  width="%.3f" height="%.3f" xlink:href="%s"/>\n' \
			% (point.x * self.scale, point.y * self.scale, width * self.scale, height * self.scale, image.uri))
	# Helpers, not in the DiaRenderer interface
	def _color_attr(self, attr_name, color) :
		if self.current_id is not None :
			insertion = ''
			self.current_attributes[attr_name] = self._rgb(color)
		else :
			insertion = '%s="%s"' % (attr_name, self._rgb(color))
		return insertion
	def _rgb(self, color) :
		# given a dia color convert to svg color string
		rgb = "#%02X%02X%02X" % (int(255 * color.red), int(color.green * 255), int(color.blue * 255))
		return rgb
	def _stroke_style(self) :
		# return the current line style as svg string
		dashlen =self.dash_length
		# dashlen/style interpretation like the DiaGdkRenderer
		dotlen = dashlen * 0.1
		caps = self.line_caps
		join = self.line_join
		style = self.line_style
		st = ""
		if style == 0 : # LINESTYLE_SOLID
			pass
		elif style == 1 : # DASHED
			st = 'stroke-dasharray="%.2f,%.2f"' % (dashlen * self.scale, dashlen * self.scale)
		elif style == 2 : # DASH_DOT,
			gaplen = (dashlen - dotlen) / 2.0
			st = 'stroke-dasharray="%.2f,%.2f,%.2f,%.2f"' % (dashlen * self.scale, gaplen * self.scale, dotlen * self.scale, gaplen * self.scale)
		elif style == 3 : # DASH_DOT_DOT,
			gaplen = (dashlen - dotlen) / 3.0
			st = 'stroke-dasharray="%.2f,%.2f,%.2f,%.2f,%.2f,%.2f"' % (dashlen * self.scale, gaplen * self.scale, dotlen * self.scale, gaplen * self.scale, dotlen * self.scale, gaplen * self.scale)
		elif style == 4 : # DOTTED
			st = 'stroke-dasharray="%.2f,%.2f"' % (dotlen * self.scale, dotlen * self.scale)

		if join == 0 : # MITER
			pass # st = st + ' stroke-linejoin="bevel"'
		elif join == 1 : # ROUND
			st = st + ' stroke-linejoin="round"'
		elif join == 2 : # BEVEL
			st = st + ' stroke-linejoin="bevel"'

		if caps == 0 : # BUTT
			pass # default stroke-linecap="butt"
		elif caps == 1 : # ROUND
			st = st + ' stroke-linecap="round"'
		elif caps == 2 : # PROJECTING
			st = st + ' stroke-linecap="square"' # is this the same ?

		return st

class SvgzCssRenderer(SvgCssRenderer) :
	def _open(self, filename) :
		# There is some (here) not wanted behaviour in gzip.open/GzipFile :
		# the filename with path is not only used to adress the file but also
		# completely stored in the file itself. Correct it here.
		import os, os.path, gzip
		path, name = os.path.split(filename)
		os.chdir(path)
		self.f = gzip.open (name, "wb")

# dia-python keeps a reference to the renderer class and uses it on demand
dia.register_export ("SVG+CSS plain", "svg", SvgCssRenderer())
dia.register_export ("SVG+CSS compressed", "svgz", SvgzCssRenderer())
_______________________________________________
dia-list mailing list
dia-list@gnome.org
http://mail.gnome.org/mailman/listinfo/dia-list
FAQ at http://live.gnome.org/Dia/Faq
Main page at http://live.gnome.org/Dia

Reply via email to