dia r4329 - in trunk: . plug-ins/python samples



Author: hans
Date: Mon Mar 23 19:49:06 2009
New Revision: 4329
URL: http://svn.gnome.org/viewvc/dia?rev=4329&view=rev

Log:
2009-03-23  Hans Breuer  <hans breuer org>

	* plug-ins/python/diastddia.py : a new renderer implementation which 
	outputs Dia's native format, but restricted to "Standard - *"-objects.
	Initial version: buggy and incomplete (e.g. bug #576468).
	* plug-ins/python/Makefile.am : added to EXTRA_DIST
	* plug-ins/python/pydia-render.c : if the PyDia renderer does not
	implement an optional method just fall back to the base classes
	render implmentation. Also (try to) warn about missing, not optional
	methods with PyErr_Warn(), but can't find these messages yet.

	* plug-ins/python/diasvg.py : self.line_width was not initialized

	* samples/UML-demo.dia : converted to be readable, not a single line
	of uncpompresed XML.



Added:
   trunk/plug-ins/python/diastddia.py
Modified:
   trunk/ChangeLog
   trunk/plug-ins/python/Makefile.am
   trunk/plug-ins/python/diasvg.py
   trunk/plug-ins/python/pydia-render.c
   trunk/samples/UML-demo.dia

Modified: trunk/plug-ins/python/Makefile.am
==============================================================================
--- trunk/plug-ins/python/Makefile.am	(original)
+++ trunk/plug-ins/python/Makefile.am	Mon Mar 23 19:49:06 2009
@@ -88,6 +88,7 @@
 	group_props.py \
 	\
 	bbox.py \
+	diastddia.py \
 	debug_objects.py \
 	export-object.py \
 	export-render.py \

Added: trunk/plug-ins/python/diastddia.py
==============================================================================
--- (empty file)
+++ trunk/plug-ins/python/diastddia.py	Mon Mar 23 19:49:06 2009
@@ -0,0 +1,277 @@
+#  PyDia Standard Dia Renderer
+#  Copyright (c) 2009 Hans Breuer <hans breuer org>
+#
+#  A renderer which outputs Dia "Standard - *" Objects in Dia XML
+#  by implementing the renderer interface.
+
+#  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, os, dia
+
+class StandardDiaRenderer :
+	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
+		# every object should have a unique id - mainly for connections definition
+		self.oid = 0
+		self.filename = ""
+	def _open(self, filename) :
+		self.f = open(filename, "w")
+	def begin_render (self, data, filename) :
+		self.filename = filename
+		self._open (filename)
+		self.f.write('''<?xml version="1.0" encoding="UTF-8"?>
+<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/";>
+  <!-- Created by dia_standard_dia.py -->
+  <dia:diagramdata>
+    <!-- almost everything is optional here -->
+  </dia:diagramdata>
+  <dia:layer name="Background" visible="true" >
+''')
+	def end_render (self) :
+		self.f.write('''<!-- no connections in the renderer interface -->
+  </dia:layer>
+</dia:diagram>''')
+		self.f.close()
+	# some helpers
+	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
+	#FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=576468 makes this evem less desirable
+	def _tinting (self, color, fill=None) :
+		# maybe this is too smart: fill=0 != fill=None
+		if fill == None :
+			attrs = '''
+      <dia:attribute name="line_color">
+        <dia:color val="%s"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="%.3f"/>
+      </dia:attribute>
+'''  % (self._rgb(color), self.line_width)
+		elif fill :
+			attrs = '''
+      <dia:attribute name="border_color">
+        <dia:color val="%s"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <!-- FIXME: folding missing -->
+      <dia:attribute name="inner_color">
+        <dia:color val="%s"/>
+      </dia:attribute>
+      <dia:attribute name="border_width">
+        <dia:real val="0"/>
+      </dia:attribute>
+''' % (self._rgb(color), self._rgb(color))
+		else :
+			attrs = '''
+      <dia:attribute name="border_color">
+        <dia:color val="%s"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="border_width">
+        <dia:real val="%.3f"/>
+      </dia:attribute>
+''' % (self._rgb(color), self.line_width)
+		return attrs
+	def _stroke_style (self) :
+		return '''
+      <dia:attribute name="line_style">
+        <dia:enum val="%d"/>
+      </dia:attribute>
+      <dia:attribute name="dashlength">
+        <dia:real val="%.3f"/>
+      </dia:attribute>
+''' % (self.line_style, self.dash_length)
+	# just remember the given state to use it during object creation
+	def set_linewidth (self, width) :
+		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
+	# now to the actual object creation - it should be 'delayed' to fold draw&fill again, 
+	# split in the rendering process but the Dia's 'Standard' objects can do both in one
+	def _box (self, rect, color, fill) :
+		self.oid = self.oid + 1
+		self.f.write('''
+    <dia:object type="Standard - Box" version="0" id="O%d">
+      <dia:attribute name="elem_corner">
+        <dia:point val="%.3f,%.3f"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="%.3f"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="%.3f"/>
+      </dia:attribute>
+%s%s
+    </dia:object>''' % (self.oid, rect.left,rect.top, rect.right - rect.left, rect.bottom - rect.top, 
+			self._tinting(color, fill), self._stroke_style()))
+	def draw_rect (self, rect, color) :
+		self._box(rect, color, 0)
+	def fill_rect (self, rect, color) :
+		self._box(rect, color, 1)
+
+	def _ellipse (self, center, width, height, color, fill) :
+		self.oid = self.oid + 1
+		self.f.write('''
+    <dia:object type="Standard - Ellipse" version="0" id="O%d">
+      <dia:attribute name="elem_corner">
+        <dia:point val="%.3f,%.3f"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="%.3f"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="%.3f"/>
+      </dia:attribute>
+%s%s
+    </dia:object>''' % (self.oid, center.x-width/2, center.y-height/2, width, height, 
+			self._tinting(color, fill), self._stroke_style()))
+	def draw_ellipse (self, center, width, height, color) :
+		self._ellipse(center, width, height, color, 0)
+	def fill_ellipse (self, center, width, height, color) :
+		self._ellipse(center, width, height, color, 0)
+
+	def _arc(self, center, width, height, angle1, angle2, color, fill) :
+		pass #FIXME
+	def draw_arc (self, center, width, height, angle1, angle2, color) :
+		self._arc(center, width, height, angle1, angle2, color, 0)
+	def fill_arc (self, center, width, height, angle1, angle2, color) :
+		self._arc(center, width, height, angle1, angle2, color, 1)
+
+	def _poly (self, type_name, points, color, fill) :
+		self.oid = self.oid + 1
+		self.f.write('''
+    <dia:object type="Standard - %s" version="0" id="O%d">
+%s%s
+      <dia:attribute name="poly_points">''' % (type_name, self.oid, self._tinting(color, fill), self._stroke_style()))
+		for p in points :
+			self.f.write('''
+        <dia:point val="%.3f,%.3f"/>''' % (p.x, p.y))
+		self.f.write('''
+      </dia:attribute>
+    </dia:object>''')
+	def draw_polyline (self, points, color) :
+		self._poly("PolyLine", points, color, None)
+	def draw_polygon (self, points, color) :
+		self._poly("Polygon", points, color, 0)
+	def fill_polygon (self, points, color) :
+		self._poly("Polygon", points, color, 1)
+
+	def _bezier (self, type_name, points, color, fill) :
+		self.oid = self.oid + 1
+		self.f.write('''
+    <dia:object type="Standard - %s" version="0" id="O%d">
+%s%s
+      <dia:attribute name="bez_points">''' % (type_name, self.oid, self._tinting(color, fill), self._stroke_style()))
+		# first point is just move
+		for bp in points :
+			if bp.type == 0 : # BEZ_MOVE_TO
+				#FIXME: moveto must be first
+				self.f.write('''
+        <dia:point val="%.3f,%.3f"/>''' % (bp.p1.x, bp.p1.y))
+			elif bp.type == 1 : # BEZ_LINE_TO
+				# simulated by curveto
+				self.f.write('''
+        <dia:point val="%.3f,%.3f"/>
+        <dia:point val="%.3f,%.3f"/>
+        <dia:point val="%.3f,%.3f"/>''' % (last.x, last.y, bp.p1.x, bp.p1.y, bp.p1.x, bp.p1.y))
+			elif bp.type == 2 : # BEZ_CURVE_TO
+				self.f.write('''
+        <dia:point val="%.3f,%.3f"/>
+        <dia:point val="%.3f,%.3f"/>
+        <dia:point val="%.3f,%.3f"/>''' % (bp.p1.x, bp.p1.y, bp.p2.x, bp.p2.y, bp.p3.x, bp.p3.y))
+			last = bp.p1
+		self.f.write('''
+      </dia:attribute>
+    </dia:object>''')
+	def draw_bezier (self, points, color) :
+		self._bezier("BezierLine", points, color, None)
+	def fill_bezier (self, points, color) :
+		self._bezier("Beziergon", points, color, 1)
+
+	def draw_string (self, text, pos, alignment, color) :
+		pass #FIXME
+
+	def draw_image (self, point, width, height, image) :
+		fname = image.filename
+		# do something better than absolute pathes
+		common = os.path.commonprefix ([fname, self.filename])
+		if len(common) > 0 and string.find(self.filename[len(common):], os.path.pathsep) == -1 :
+			fname = fname[len(common):]
+		self.oid = self.oid + 1
+		if abs(width/height - image.width/image.height) < 0.001 :
+			keep_aspect = "true"
+		else :
+			keep_aspect = "false"
+		self.f.write('''
+    <dia:object type="Standard - Image" version="0" id="O%d">
+      <dia:attribute name="elem_corner">
+        <dia:point val="%.3f,%.3f"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="%.3f"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="%.3f"/>
+      </dia:attribute>
+      <dia:attribute name="file">
+        <dia:string>#%s#</dia:string>
+      </dia:attribute>
+      <dia:attribute name="draw_border">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="keep_aspect">
+        <dia:boolean val="%s"/>
+      </dia:attribute>
+    </dia:object>''' % (self.oid, point.x,point.y, width, height, fname, keep_aspect))
+
+	# defining only this line drawer makes almost everything interpolated
+	def draw_line (self, start, end, color) :
+		self.oid = self.oid + 1
+		self.f.write('''
+    <dia:object type="Standard - Line" version="0" id="O%d">
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="%.3f,%.3f"/>
+        <dia:point val="%.3f,%.3f"/>
+      </dia:attribute>
+%s%s
+    </dia:object>''' % (self.oid, start.x,start.y, end.x, end.y, 
+			self._tinting(color), self._stroke_style()))
+		
+# register the renderer
+dia.register_export ("Dia plain", "dia", StandardDiaRenderer())
+

Modified: trunk/plug-ins/python/diasvg.py
==============================================================================
--- trunk/plug-ins/python/diasvg.py	(original)
+++ trunk/plug-ins/python/diasvg.py	Mon Mar 23 19:49:06 2009
@@ -23,6 +23,7 @@
 class SvgRenderer :
 	def __init__ (self) :
 		self.f = None
+		self.line_width = 0.1
 		self.line_caps = 0
 		self.line_join = 0
 		self.line_style = 0

Modified: trunk/plug-ins/python/pydia-render.c
==============================================================================
--- trunk/plug-ins/python/pydia-render.c	(original)
+++ trunk/plug-ins/python/pydia-render.c	Mon Mar 23 19:49:06 2009
@@ -161,7 +161,7 @@
   case LINECAPS_PROJECTING:
     break;
   default:
-    message_error("DiaPyRenderer : Unsupported fill mode specified!\n");
+    PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode specified!\n");
   }
 
   func = PyObject_GetAttrString (self, "set_linecaps");
@@ -194,7 +194,7 @@
   case LINEJOIN_BEVEL:
     break;
   default:
-    message_error("DiaPyRenderer : Unsupported fill mode specified!\n");
+    PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode specified!\n");
   }
 
   func = PyObject_GetAttrString (self, "set_linejoin");
@@ -232,7 +232,7 @@
   case LINESTYLE_DOTTED:
     break;
   default:
-    message_error("DiaPyRenderer : Unsupported fill mode specified!\n");
+    PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode specified!\n");
   }
 
   func = PyObject_GetAttrString (self, "set_linestyle");
@@ -283,7 +283,7 @@
   case FILLSTYLE_SOLID:
     break;
   default:
-    message_error("DiaPyRenderer : Unsupported fill mode specified!\n");
+    PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode specified!\n");
   }
 
   func = PyObject_GetAttrString (self, "set_fillstyle");
@@ -325,6 +325,8 @@
     PyErr_Clear();
 }
 
+static gpointer parent_class = NULL;
+
 static void
 draw_line(DiaRenderer *renderer, 
           Point *start, Point *end, 
@@ -347,8 +349,13 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -372,8 +379,11 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -397,8 +407,11 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -422,8 +435,13 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -447,8 +465,11 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -472,8 +493,13 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -500,8 +526,13 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -528,8 +559,13 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -555,8 +591,13 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -582,8 +623,13 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -608,8 +654,11 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -634,8 +683,11 @@
     Py_DECREF(func);
     Py_DECREF(self);
   }
-  else /* member optional */
+  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
@@ -673,9 +725,13 @@
     Py_XDECREF (arg);
     Py_DECREF(func);
     Py_DECREF(self);
-  }
-  else /* member optional */
+  } 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
@@ -700,9 +756,13 @@
     Py_XDECREF (arg);
     Py_DECREF(func);
     Py_DECREF(self);
-  }
-  else /* member optional */
+  } 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
@@ -743,8 +803,6 @@
  */
 static void dia_py_renderer_class_init (DiaPyRendererClass *klass);
 
-static gpointer parent_class = NULL;
-
 GType
 dia_py_renderer_get_type (void)
 {

Modified: trunk/samples/UML-demo.dia
==============================================================================
Binary files. No diff available.



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