• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

作図ソフト dia の改良版


Commit MetaInfo

修订版3ec25448ae14f38c59b2ec504d45f02836b74ab9 (tree)
时间2014-04-26 22:31:46
作者Hans Breuer <hans@breu...>
CommiterHans Breuer

Log Message

[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.

更改概述

差异

--- a/lib/diapathrenderer.c
+++ b/lib/diapathrenderer.c
@@ -27,6 +27,11 @@
2727
2828 #include "attributes.h" /* attributes_get_foreground() */
2929
30+typedef enum {
31+ PATH_STROKE = (1<<0),
32+ PATH_FILL = (1<<1)
33+} PathLastOp;
34+
3035 /*!
3136 * \brief Renderer which turns everything into a path (or a list thereof)
3237 *
@@ -44,6 +49,8 @@ struct _DiaPathRenderer
4449
4550 Color stroke;
4651 Color fill;
52+
53+ PathLastOp last_op;
4754 };
4855
4956 struct _DiaPathRendererClass
@@ -94,7 +101,7 @@ dia_path_renderer_finalize (GObject *object)
94101 * @param self explicit this pointer
95102 * @param stroke line color or NULL
96103 * @param fill fill color or NULL
97- * \private \memeberof _DiaPathRenderer
104+ * \private \memberof _DiaPathRenderer
98105 */
99106 static GArray *
100107 _get_current_path (DiaPathRenderer *self,
@@ -113,6 +120,11 @@ _get_current_path (DiaPathRenderer *self,
113120 memcpy (&self->fill, fill, sizeof(*fill));
114121 new_path = TRUE;
115122 }
123+ /* also create a new path if the last op was a fill and we now stroke */
124+ if ( stroke && self->last_op == PATH_FILL
125+ || fill && self->last_op == PATH_STROKE)
126+ new_path = TRUE;
127+ self->last_op = stroke ? PATH_STROKE : PATH_FILL;
116128
117129 if (!self->pathes || new_path) {
118130 if (!self->pathes)
@@ -123,6 +135,40 @@ _get_current_path (DiaPathRenderer *self,
123135 return path;
124136 }
125137 /*!
138+ * \brief Optimize away potential duplicated path
139+ * Dia's object rendering often consists of identical consecutive fill and stroke
140+ * operations. This function check if two identical pathes are at the end of our
141+ * list and just removes the second one.
142+ * \private \memberof _DiaPathRenderer
143+ */
144+static void
145+_remove_duplicated_path (DiaPathRenderer *self)
146+{
147+ if (self->pathes && self->pathes->len >= 2) {
148+ GArray *p1 = g_ptr_array_index (self->pathes, self->pathes->len - 2);
149+ GArray *p2 = g_ptr_array_index (self->pathes, self->pathes->len - 1);
150+ if (p1->len == p2->len) {
151+ gboolean same = TRUE;
152+ guint i;
153+ for (i = 0; i < p1->len; ++i) {
154+ const BezPoint *bp1 = &g_array_index (p1, BezPoint, i);
155+ const BezPoint *bp2 = &g_array_index (p2, BezPoint, i);
156+
157+ same &= (bp1->type == bp2->type);
158+ same &= (memcmp (&bp1->p1, &bp2->p1, sizeof(Point)) == 0);
159+ if (bp1->type == BEZ_CURVE_TO) {
160+ same &= (memcmp (&bp1->p2, &bp2->p2, sizeof(Point)) == 0);
161+ same &= (memcmp (&bp1->p3, &bp2->p3, sizeof(Point)) == 0);
162+ }
163+ }
164+ if (same) {
165+ g_array_free (p2, TRUE);
166+ g_ptr_array_set_size (self->pathes, self->pathes->len - 1);
167+ }
168+ }
169+ }
170+}
171+/*!
126172 * \brief Starting a new rendering run
127173 * Could be used to clean the path leftovers from a previous run.
128174 * Typical export renderers flush here.
@@ -188,7 +234,7 @@ _path_append (GArray *points, const Point *pt)
188234 const BezPoint *prev = (points->len > 0) ? &g_array_index (points, BezPoint, points->len - 1) : NULL;
189235 const Point *last = prev ? (prev->type == BEZ_CURVE_TO ? &prev->p3 : &prev->p1) : NULL;
190236
191- if (!last || last->x != pt->x || last->y != pt->y) {
237+ if (!last || distance_point_point(last, pt) > 0.001) {
192238 BezPoint bp;
193239 bp.type = BEZ_MOVE_TO;
194240 bp.p1 = *pt;
@@ -282,6 +328,7 @@ draw_polyline(DiaRenderer *self,
282328 Color *line_colour)
283329 {
284330 _polyline (self, points, num_points, line_colour, NULL);
331+ _remove_duplicated_path (DIA_PATH_RENDERER (self));
285332 }
286333 static void
287334 draw_polygon(DiaRenderer *self,
@@ -294,6 +341,7 @@ draw_polygon(DiaRenderer *self,
294341 /* FIXME: can't be that simple ;) */
295342 _polyline (self, points, num_points, line_colour, NULL);
296343 _path_lineto (path, &points[0]);
344+ _remove_duplicated_path (renderer);
297345 }
298346 static void
299347 fill_polygon(DiaRenderer *self,
@@ -336,6 +384,7 @@ draw_rect (DiaRenderer *self,
336384 Color *color)
337385 {
338386 _rect (self, ul_corner, lr_corner, color, NULL);
387+ _remove_duplicated_path (DIA_PATH_RENDERER (self));
339388 }
340389 static void
341390 fill_rect (DiaRenderer *self,
@@ -423,6 +472,7 @@ draw_arc (DiaRenderer *self,
423472 Color *color)
424473 {
425474 _arc (self, center, width, height, angle1, angle2, color, NULL);
475+ _remove_duplicated_path (DIA_PATH_RENDERER (self));
426476 }
427477 static void
428478 fill_arc (DiaRenderer *self,
@@ -508,6 +558,7 @@ draw_ellipse (DiaRenderer *self,
508558 Color *color)
509559 {
510560 _ellipse (self, center, width, height, color, NULL);
561+ _remove_duplicated_path (DIA_PATH_RENDERER (self));
511562 }
512563 static void
513564 fill_ellipse (DiaRenderer *self,
@@ -545,6 +596,7 @@ draw_bezier (DiaRenderer *self,
545596 Color *color)
546597 {
547598 _bezier(self, points, numpoints, color, NULL);
599+ _remove_duplicated_path (DIA_PATH_RENDERER (self));
548600 }
549601 static void
550602 fill_bezier(DiaRenderer *self,
Binary files /dev/null and b/samples/convert-to-path.dia differ