[dia] [substitute] improve Convert to Path
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] [substitute] improve Convert to Path
- Date: Sat, 26 Apr 2014 17:17:27 +0000 (UTC)
commit 3ec25448ae14f38c59b2ec504d45f02836b74ab9
Author: Hans Breuer <hans breuer org>
Date: Fri Apr 25 12:00:29 2014 +0200
[substitute] improve Convert to Path
'Convert to Path' based on the DiaPathRenderer was not producing the
desired effect for some standard objects. Filled objects were not
necessarily filled anymore after conversion. Even simple objects were
producing a group of objects rather than a single path object. Now:
- start a new path when switching from fill to stroke color use
- optimize for duplicated path coming from Dia's current split to fill
and stroke in two steps (with the same path data)
- be more tolerant regarding path extending so that rounded rectangles
lead to a single path object
Also included a test/demo file convert-to-path.dia.
lib/diapathrenderer.c | 56 +++++++++++++++++++++++++++++++++++++++++-
samples/convert-to-path.dia | Bin 0 -> 3954 bytes
2 files changed, 54 insertions(+), 2 deletions(-)
---
diff --git a/lib/diapathrenderer.c b/lib/diapathrenderer.c
index 96ea988..b7ec40b 100644
--- a/lib/diapathrenderer.c
+++ b/lib/diapathrenderer.c
@@ -27,6 +27,11 @@
#include "attributes.h" /* attributes_get_foreground() */
+typedef enum {
+ PATH_STROKE = (1<<0),
+ PATH_FILL = (1<<1)
+} PathLastOp;
+
/*!
* \brief Renderer which turns everything into a path (or a list thereof)
*
@@ -44,6 +49,8 @@ struct _DiaPathRenderer
Color stroke;
Color fill;
+
+ PathLastOp last_op;
};
struct _DiaPathRendererClass
@@ -94,7 +101,7 @@ dia_path_renderer_finalize (GObject *object)
* @param self explicit this pointer
* @param stroke line color or NULL
* @param fill fill color or NULL
- * \private \memeberof _DiaPathRenderer
+ * \private \memberof _DiaPathRenderer
*/
static GArray *
_get_current_path (DiaPathRenderer *self,
@@ -113,6 +120,11 @@ _get_current_path (DiaPathRenderer *self,
memcpy (&self->fill, fill, sizeof(*fill));
new_path = TRUE;
}
+ /* also create a new path if the last op was a fill and we now stroke */
+ if ( stroke && self->last_op == PATH_FILL
+ || fill && self->last_op == PATH_STROKE)
+ new_path = TRUE;
+ self->last_op = stroke ? PATH_STROKE : PATH_FILL;
if (!self->pathes || new_path) {
if (!self->pathes)
@@ -123,6 +135,40 @@ _get_current_path (DiaPathRenderer *self,
return path;
}
/*!
+ * \brief Optimize away potential duplicated path
+ * Dia's object rendering often consists of identical consecutive fill and stroke
+ * operations. This function check if two identical pathes are at the end of our
+ * list and just removes the second one.
+ * \private \memberof _DiaPathRenderer
+ */
+static void
+_remove_duplicated_path (DiaPathRenderer *self)
+{
+ if (self->pathes && self->pathes->len >= 2) {
+ GArray *p1 = g_ptr_array_index (self->pathes, self->pathes->len - 2);
+ GArray *p2 = g_ptr_array_index (self->pathes, self->pathes->len - 1);
+ if (p1->len == p2->len) {
+ gboolean same = TRUE;
+ guint i;
+ for (i = 0; i < p1->len; ++i) {
+ const BezPoint *bp1 = &g_array_index (p1, BezPoint, i);
+ const BezPoint *bp2 = &g_array_index (p2, BezPoint, i);
+
+ same &= (bp1->type == bp2->type);
+ same &= (memcmp (&bp1->p1, &bp2->p1, sizeof(Point)) == 0);
+ if (bp1->type == BEZ_CURVE_TO) {
+ same &= (memcmp (&bp1->p2, &bp2->p2, sizeof(Point)) == 0);
+ same &= (memcmp (&bp1->p3, &bp2->p3, sizeof(Point)) == 0);
+ }
+ }
+ if (same) {
+ g_array_free (p2, TRUE);
+ g_ptr_array_set_size (self->pathes, self->pathes->len - 1);
+ }
+ }
+ }
+}
+/*!
* \brief Starting a new rendering run
* Could be used to clean the path leftovers from a previous run.
* Typical export renderers flush here.
@@ -188,7 +234,7 @@ _path_append (GArray *points, const Point *pt)
const BezPoint *prev = (points->len > 0) ? &g_array_index (points, BezPoint, points->len - 1) : NULL;
const Point *last = prev ? (prev->type == BEZ_CURVE_TO ? &prev->p3 : &prev->p1) : NULL;
- if (!last || last->x != pt->x || last->y != pt->y) {
+ if (!last || distance_point_point(last, pt) > 0.001) {
BezPoint bp;
bp.type = BEZ_MOVE_TO;
bp.p1 = *pt;
@@ -282,6 +328,7 @@ draw_polyline(DiaRenderer *self,
Color *line_colour)
{
_polyline (self, points, num_points, line_colour, NULL);
+ _remove_duplicated_path (DIA_PATH_RENDERER (self));
}
static void
draw_polygon(DiaRenderer *self,
@@ -294,6 +341,7 @@ draw_polygon(DiaRenderer *self,
/* FIXME: can't be that simple ;) */
_polyline (self, points, num_points, line_colour, NULL);
_path_lineto (path, &points[0]);
+ _remove_duplicated_path (renderer);
}
static void
fill_polygon(DiaRenderer *self,
@@ -336,6 +384,7 @@ draw_rect (DiaRenderer *self,
Color *color)
{
_rect (self, ul_corner, lr_corner, color, NULL);
+ _remove_duplicated_path (DIA_PATH_RENDERER (self));
}
static void
fill_rect (DiaRenderer *self,
@@ -423,6 +472,7 @@ draw_arc (DiaRenderer *self,
Color *color)
{
_arc (self, center, width, height, angle1, angle2, color, NULL);
+ _remove_duplicated_path (DIA_PATH_RENDERER (self));
}
static void
fill_arc (DiaRenderer *self,
@@ -508,6 +558,7 @@ draw_ellipse (DiaRenderer *self,
Color *color)
{
_ellipse (self, center, width, height, color, NULL);
+ _remove_duplicated_path (DIA_PATH_RENDERER (self));
}
static void
fill_ellipse (DiaRenderer *self,
@@ -545,6 +596,7 @@ draw_bezier (DiaRenderer *self,
Color *color)
{
_bezier(self, points, numpoints, color, NULL);
+ _remove_duplicated_path (DIA_PATH_RENDERER (self));
}
static void
fill_bezier(DiaRenderer *self,
diff --git a/samples/convert-to-path.dia b/samples/convert-to-path.dia
new file mode 100644
index 0000000..6ff7264
Binary files /dev/null and b/samples/convert-to-path.dia differ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]