[dia] Fix DiaRenderer::fill_bezier() call with just a single point
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] Fix DiaRenderer::fill_bezier() call with just a single point
- Date: Sat, 26 Apr 2014 17:17:22 +0000 (UTC)
commit 9d086480ba3d479a13196b5581b92b382bfb4298
Author: Hans Breuer <hans breuer org>
Date: Mon Apr 21 17:00:01 2014 +0200
Fix DiaRenderer::fill_bezier() call with just a single point
My recent renderer tests showed complaints about Beziergon creations
with just too few points. The root cause was identified by a new
DissectRenderer implemented with PyDia. Actually the bug was in
bezier_render_fill() - the emulation method for Bézier with holes.
lib/diarenderer.c | 5 +-
plug-ins/python/diadissect.py | 163 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 167 insertions(+), 1 deletions(-)
---
diff --git a/lib/diarenderer.c b/lib/diarenderer.c
index 11dcf07..877e0cf 100644
--- a/lib/diarenderer.c
+++ b/lib/diarenderer.c
@@ -1679,8 +1679,11 @@ bezier_render_fill (DiaRenderer *renderer, BezPoint *pts, int total, Color *colo
g_array_append_val(points, pts[i]);
}
}
- if (points->len)
+ if (points->len > 1) {
+ /* actually most renderers need at least three points, but having only one
+ * point is an artifact coming from the algorithm above: "new needs move-to" */
DIA_RENDERER_GET_CLASS (renderer)->fill_bezier (renderer, &g_array_index(points, BezPoint, 0),
points->len, color);
+ }
g_array_free (points, TRUE);
}
}
diff --git a/plug-ins/python/diadissect.py b/plug-ins/python/diadissect.py
new file mode 100644
index 0000000..c6b1912
--- /dev/null
+++ b/plug-ins/python/diadissect.py
@@ -0,0 +1,163 @@
+#
+# Dissect a diagram by rendering it and accumulating invalid
+# renderer calls to object selection.
+#
+# Copyright (c) 2014 Hans Breuer <hans breuer org>
+#
+# 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
+
+##
+# \brief A dissecting renderer for Dia
+#
+# Check the diagram by rendering it and report anomalies with their
+# call and the causing object.
+#
+# \extends _DiaPyRenderer
+# \ingroup ExportFilters
+class DissectRenderer :
+ def __init__ (self) :
+ self.f = None
+ self.current_objects = []
+ self.warnings = []
+ self.errors = []
+ self.font = None
+ def _open(self, filename) :
+ self.f = open(filename, "w")
+ def begin_render (self, data, filename) :
+ self._open (filename)
+ self.extents = data.extents
+ try :
+ # this can fail for two reason:
+ # 1) data.diagram is None, e.g. when running from pure bindings
+ # 2) there is no member data.diagram because Dia is just too old
+ self.f.write ("# Dissect %s\n" % (data.diagram.filename,))
+ except :
+ self.f.write ("# Dissect %s\n" % (filename,))
+ def end_render (self) :
+ self.f.write('%d error(s) %d warning(s)\n' % (len(self.errors), len(self.warnings)))
+ self.f.close ()
+ def Warning (self, msg) :
+ self.warnings.append ((self.current_objects[-1], msg))
+ if self.f :
+ self.f.write ("Warning: %s, %s\n" % (self.current_objects[-1], msg))
+ def Error (self, msg) :
+ self.errors.append ((self.current_objects[-1], msg))
+ if self.f :
+ self.f.write ("Error: %s, %s\n" % (self.current_objects[-1], msg))
+ def draw_object (self, object, matrix) :
+ self.current_objects.append (object)
+ # XXX: check matrix
+ # don't forget to render the object
+ object.draw (self)
+ del self.current_objects[-1]
+ def set_linewidth (self, width) :
+ # width==0 is hairline
+ if width < 0 or width > 10 :
+ self.Warning ("linewidth out of range")
+ def set_linecaps (self, mode) :
+ if mode < 0 or mode > 2 :
+ self.Error ("linecaps '%d' unknown" % (mode,))
+ def set_linejoin (self, mode) :
+ if mode < 0 or mode > 2 :
+ self.Error ("linejoin '%d' unknown" % (mode,))
+ def set_linestyle (self, style) :
+ if style < 0 or style > 4 :
+ self.Error ("linestyle '%d' unknown" % (style,))
+ def set_dashlength (self, length) :
+ if length < 0.001 or length > 1 :
+ self.Warning ("dashlength '%f' out of range" % (length,))
+ def set_fillstyle (self, style) :
+ # currently only 'solid' so not used anywhere else
+ if style != 0 :
+ self.Error ("fillstyle '%d' unknown" % (style,))
+ def set_font (self, font, size) :
+ self.font = font
+ self.font_size = size
+ def draw_line (self, start, end, color) :
+ pass # can anything go wrong here ?
+ def draw_polyline (self, points, color) :
+ if len(points) < 2 :
+ self.Error ("draw_polyline with too few points")
+ def _polygon (self, points, fun) :
+ if len(points) < 3 :
+ self.Error ("%s with too few points" % (fun,))
+ def draw_polygon (self, points, color) :
+ self._polygon(points, "draw_polygon")
+ def fill_polygon (self, points, color) :
+ self._polygon(points, "draw_polygon")
+ def _rect (self, rect, fun) :
+ if rect.top > rect.bottom :
+ self.Warning ("%s negative height" % (fun,))
+ if rect.left > rect.right :
+ self.Warning ("%s negative width" % (fun,))
+ def draw_rect (self, rect, color) :
+ self._rect (rect, "draw_rect")
+ def draw_rounded_rect (self, rect, color, rounding) :
+ # XXX: check rounding to be positive (smaller than half width, height?)
+ self._rect (rect, "draw_rect")
+ def fill_rect (self, rect, color) :
+ self._rect (rect, "draw_rect")
+ def fill_rounded_rect (self, rect, color, rounding) :
+ self._rect (rect, "draw_rect")
+ def _arc (self, center, width, height, angle1, angle2, fun) :
+ if width <= 0 :
+ self.Warning ("%s width too small" % (fun,))
+ if height <= 0 :
+ self.Warning ("%s height too small" % (fun,))
+ # XXX: angles?
+ def draw_arc (self, center, width, height, angle1, angle2, color) :
+ self._arc(center, width, height, angle1, angle2, "draw_arc")
+ def fill_arc (self, center, width, height, angle1, angle2, color) :
+ self._arc(center, width, height, angle1, angle2, "fill_arc")
+ def draw_ellipse (self, center, width, height, color) :
+ self._arc(center, width, height, 0, 360, "draw_ellipse")
+ def fill_ellipse (self, center, width, height, color) :
+ self._arc(center, width, height, 0, 360, "fill_elipse")
+ def _bezier (self, bezpoints, fun) :
+ nMoves = 0
+ for bp in bezpoints :
+ if bp.type == 0 : # BEZ_MOVE_TO
+ nMoves = nMoves + 1
+ if nMoves > 1 :
+ self.Warning ("%s move-to within", (fun,))
+ elif bp.type == 1 : # BEZ_LINE_TO
+ pass
+ elif bp.type == 2 : # BEZ_CURVE_TO
+ pass
+ else :
+ self.Error ("%s invalid BezPoint type='%d'" % (fun, bp.type,))
+ def draw_bezier (self, bezpoints, color) :
+ if len(bezpoints) < 2 :
+ self.Error ("draw_bezier too few points");
+ self._bezier (bezpoints, "draw_bezier")
+ def fill_bezier (self, bezpoints, color) :
+ if len(bezpoints) < 3 :
+ self.Error ("fill_bezier too few points");
+ self._bezier (bezpoints, "fill_bezier")
+ def draw_string (self, text, pos, alignment, color) :
+ if len(text) < 1 :
+ self.Warning ("draw_string empty text")
+ if alignment < 0 or alignment > 2 :
+ self.Error ("draw_string unknown alignmern '%d'" % (alignment,))
+ def draw_image (self, point, width, height, image) :
+ if width <= 0 :
+ self.Warning ("draw_image width too small")
+ if height <= 0 :
+ self.Warning ("draw_image height too small")
+ # XXX: check image, e.g. existing file name
+# dia-python keeps a reference to the renderer class and uses it on demand
+dia.register_export ("Dissect", "dissect", DissectRenderer())
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]