作図ソフト dia の改良版
修订版 | 11c3108a01a05ea1e3e249bc7be794b42ca7cdaf (tree) |
---|---|
时间 | 2014-09-06 21:37:08 |
作者 | Hans Breuer <hans@breu...> |
Commiter | Hans Breuer |
Bug 735430 - vdx: Box rounding support for export and import
VDX 'Rounding' is basically the same as Dia corner_radius, so
draw_rounded_rect() was really easy to implement. While at it
remove all superfluous prototypes instead of adding a new one.
The import has to be a little more elaborated, because corner_radius
can only be handled with "Standard - Box", but VDX has no rectangle.
So we check the polygon for being rectangular and if so apply the
rounding.
Checked with ellipse.dia round-trip as well as with Visio Viewer 2010.
Also included some minor line style/caps tweaking.
@@ -97,46 +97,6 @@ struct _VDXRenderer | ||
97 | 97 | }; |
98 | 98 | |
99 | 99 | |
100 | -static void begin_render(DiaRenderer *self, const Rectangle *update); | |
101 | -static void end_render(DiaRenderer *renderer); | |
102 | -static void set_linewidth(DiaRenderer *self, real linewidth); | |
103 | -static void set_linecaps(DiaRenderer *self, LineCaps mode); | |
104 | -static void set_linejoin(DiaRenderer *self, LineJoin mode); | |
105 | -static void set_linestyle(DiaRenderer *self, LineStyle mode, real dash_length); | |
106 | -static void set_fillstyle(DiaRenderer *self, FillStyle mode); | |
107 | -static void set_font(DiaRenderer *self, DiaFont *font, real height); | |
108 | -static void draw_line(DiaRenderer *self, | |
109 | - Point *start, Point *end, | |
110 | - Color *color); | |
111 | -static void draw_polyline(DiaRenderer *self, | |
112 | - Point *points, int num_points, | |
113 | - Color *color); | |
114 | -static void draw_polygon(DiaRenderer *self, | |
115 | - Point *points, int num_points, | |
116 | - Color *fill, Color *stroke); | |
117 | -static void draw_arc(DiaRenderer *self, | |
118 | - Point *center, | |
119 | - real width, real height, | |
120 | - real angle1, real angle2, | |
121 | - Color *color); | |
122 | -static void fill_arc(DiaRenderer *self, | |
123 | - Point *center, | |
124 | - real width, real height, | |
125 | - real angle1, real angle2, | |
126 | - Color *color); | |
127 | -static void draw_ellipse(DiaRenderer *self, | |
128 | - Point *center, | |
129 | - real width, real height, | |
130 | - Color *fill, Color *stroke); | |
131 | -static void draw_string(DiaRenderer *self, | |
132 | - const char *text, | |
133 | - Point *pos, Alignment alignment, | |
134 | - Color *color); | |
135 | -static void draw_image(DiaRenderer *self, | |
136 | - Point *point, | |
137 | - real width, real height, | |
138 | - DiaImage *image); | |
139 | - | |
140 | 100 | static void vdx_renderer_class_init (VDXRendererClass *klass); |
141 | 101 | |
142 | 102 | static gboolean export_vdx(DiagramData *data, DiaContext *ctx, |
@@ -191,52 +151,6 @@ vdx_renderer_finalize (GObject *object) | ||
191 | 151 | G_OBJECT_CLASS (parent_class)->finalize (object); |
192 | 152 | } |
193 | 153 | |
194 | -/** Class constructor for renderer | |
195 | - * @param klass a renderer | |
196 | - */ | |
197 | - | |
198 | -static void | |
199 | -vdx_renderer_class_init (VDXRendererClass *klass) | |
200 | -{ | |
201 | - GObjectClass *object_class = G_OBJECT_CLASS (klass); | |
202 | - DiaRendererClass *renderer_class = DIA_RENDERER_CLASS (klass); | |
203 | - | |
204 | - parent_class = g_type_class_peek_parent (klass); | |
205 | - | |
206 | - object_class->finalize = vdx_renderer_finalize; | |
207 | - | |
208 | - renderer_class->begin_render = begin_render; | |
209 | - renderer_class->end_render = end_render; | |
210 | - | |
211 | - renderer_class->set_linewidth = set_linewidth; | |
212 | - renderer_class->set_linecaps = set_linecaps; | |
213 | - renderer_class->set_linejoin = set_linejoin; | |
214 | - renderer_class->set_linestyle = set_linestyle; | |
215 | - renderer_class->set_fillstyle = set_fillstyle; | |
216 | - renderer_class->set_font = set_font; | |
217 | - | |
218 | - renderer_class->draw_line = draw_line; | |
219 | - renderer_class->draw_polyline = draw_polyline; | |
220 | - | |
221 | - renderer_class->draw_polygon = draw_polygon; | |
222 | - | |
223 | - renderer_class->draw_arc = draw_arc; | |
224 | - renderer_class->fill_arc = fill_arc; | |
225 | - | |
226 | - renderer_class->draw_ellipse = draw_ellipse; | |
227 | - | |
228 | - /* Until we have NURBS, let Dia use lines */ | |
229 | - /* renderer_class->draw_bezier = draw_bezier; */ | |
230 | - /* renderer_class->draw_beziergon = draw_beziergon; */ | |
231 | - /* renderer_class->draw_bezier_with_arrows = draw_bezier_with_arrows; */ | |
232 | - | |
233 | - renderer_class->draw_string = draw_string; | |
234 | - | |
235 | - renderer_class->draw_image = draw_image; | |
236 | - | |
237 | - /* Further high level methods not required (or desired) */ | |
238 | -} | |
239 | - | |
240 | 154 | /** Initialises VDXrenderer |
241 | 155 | * @param self a renderer |
242 | 156 | */ |
@@ -446,7 +360,6 @@ vdxCheckFont(VDXRenderer *renderer) | ||
446 | 360 | * @param end_arrow optional end arrow |
447 | 361 | * @todo join, caps, dashlength |
448 | 362 | */ |
449 | - | |
450 | 363 | static void |
451 | 364 | create_Line(VDXRenderer *renderer, Color *color, struct vdx_Line *Line, |
452 | 365 | Arrow *start_arrow, Arrow *end_arrow) |
@@ -476,6 +389,9 @@ create_Line(VDXRenderer *renderer, Color *color, struct vdx_Line *Line, | ||
476 | 389 | Line->LineColor = *color; |
477 | 390 | Line->LineColorTrans = 1.0 - color->alpha; |
478 | 391 | Line->LineWeight = renderer->linewidth / vdx_Line_Scale; |
392 | + /* VDX only has Rounded (0) or Square (1) ends */ | |
393 | + if (renderer->capsmode != LINECAPS_ROUND) | |
394 | + Line->LineCap = 1; /* Square */ | |
479 | 395 | if (start_arrow || end_arrow) |
480 | 396 | { |
481 | 397 | g_debug("create_Line (ARROWS)"); |
@@ -713,16 +629,11 @@ static void draw_polyline(DiaRenderer *self, Point *points, int num_points, | ||
713 | 629 | g_free(LineTo); |
714 | 630 | } |
715 | 631 | |
716 | -/** Render a Dia filled polygon | |
717 | - * @param self a renderer | |
718 | - * @param points corners of polygon | |
719 | - * @param num_points number of points | |
720 | - * @param color line colour | |
721 | - */ | |
722 | 632 | static void |
723 | -draw_polygon (DiaRenderer *self, | |
724 | - Point *points, int num_points, | |
725 | - Color *fill, Color *stroke) | |
633 | +_polygon (DiaRenderer *self, | |
634 | + Point *points, int num_points, | |
635 | + Color *fill, Color *stroke, | |
636 | + real radius) | |
726 | 637 | { |
727 | 638 | VDXRenderer *renderer = VDX_RENDERER(self); |
728 | 639 | Point a, b; |
@@ -812,6 +723,7 @@ draw_polygon (DiaRenderer *self, | ||
812 | 723 | create_Fill(renderer, fill, &Fill); |
813 | 724 | if (stroke) |
814 | 725 | create_Line(renderer, stroke, &Line, NULL, NULL); |
726 | + Line.Rounding = visio_length (radius); | |
815 | 727 | |
816 | 728 | Geom.NoFill = fill ? 0 : 1; |
817 | 729 | Geom.NoLine = stroke ? 0 : 1; |
@@ -825,7 +737,7 @@ draw_polygon (DiaRenderer *self, | ||
825 | 737 | Shape.any.children = g_slist_append(Shape.any.children, &XForm); |
826 | 738 | if (fill) |
827 | 739 | Shape.any.children = g_slist_append(Shape.any.children, &Fill); |
828 | - if (stroke) | |
740 | + if (stroke || radius > 0.0) | |
829 | 741 | Shape.any.children = g_slist_append(Shape.any.children, &Line); |
830 | 742 | Shape.any.children = g_slist_append(Shape.any.children, &Geom); |
831 | 743 |
@@ -838,6 +750,37 @@ draw_polygon (DiaRenderer *self, | ||
838 | 750 | g_free(LineTo); |
839 | 751 | } |
840 | 752 | |
753 | +/** Render a Dia filled polygon | |
754 | + * @param self a renderer | |
755 | + * @param points corners of polygon | |
756 | + * @param num_points number of points | |
757 | + * @param color line colour | |
758 | + */ | |
759 | +static void | |
760 | +draw_polygon (DiaRenderer *self, | |
761 | + Point *points, int num_points, | |
762 | + Color *fill, Color *stroke) | |
763 | +{ | |
764 | + _polygon (self, points, num_points, fill, stroke, 0.0); | |
765 | +} | |
766 | + | |
767 | +static void | |
768 | +draw_rounded_rect (DiaRenderer *self, | |
769 | + Point *ul_corner, Point *lr_corner, | |
770 | + Color *fill, Color *stroke, | |
771 | + real radius) | |
772 | +{ | |
773 | + Point points[4]; /* close path done by _polygon() */ | |
774 | + | |
775 | + g_debug("draw_rounded_rect((%f,%f), (%f,%f)) -> draw_polyline", | |
776 | + ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y); | |
777 | + points[0].x = ul_corner->x; points[0].y = lr_corner->y; | |
778 | + points[1] = *lr_corner; | |
779 | + points[2].x = lr_corner->x; points[2].y = ul_corner->y; | |
780 | + points[3] = *ul_corner; | |
781 | + | |
782 | + _polygon (self, points, 4, fill, stroke, radius); | |
783 | +} | |
841 | 784 | /** Render a Dia arc |
842 | 785 | * @param self a renderer |
843 | 786 | * @param center centre of arc |
@@ -2094,3 +2037,49 @@ draw_object (DiaRenderer *self, | ||
2094 | 2037 | |
2095 | 2038 | |
2096 | 2039 | #endif |
2040 | + | |
2041 | +/** Class constructor for renderer | |
2042 | + * @param klass a renderer | |
2043 | + */ | |
2044 | +static void | |
2045 | +vdx_renderer_class_init (VDXRendererClass *klass) | |
2046 | +{ | |
2047 | + GObjectClass *object_class = G_OBJECT_CLASS (klass); | |
2048 | + DiaRendererClass *renderer_class = DIA_RENDERER_CLASS (klass); | |
2049 | + | |
2050 | + parent_class = g_type_class_peek_parent (klass); | |
2051 | + | |
2052 | + object_class->finalize = vdx_renderer_finalize; | |
2053 | + | |
2054 | + renderer_class->begin_render = begin_render; | |
2055 | + renderer_class->end_render = end_render; | |
2056 | + | |
2057 | + renderer_class->set_linewidth = set_linewidth; | |
2058 | + renderer_class->set_linecaps = set_linecaps; | |
2059 | + renderer_class->set_linejoin = set_linejoin; | |
2060 | + renderer_class->set_linestyle = set_linestyle; | |
2061 | + renderer_class->set_fillstyle = set_fillstyle; | |
2062 | + renderer_class->set_font = set_font; | |
2063 | + | |
2064 | + renderer_class->draw_line = draw_line; | |
2065 | + renderer_class->draw_polyline = draw_polyline; | |
2066 | + | |
2067 | + renderer_class->draw_polygon = draw_polygon; | |
2068 | + | |
2069 | + renderer_class->draw_arc = draw_arc; | |
2070 | + renderer_class->fill_arc = fill_arc; | |
2071 | + | |
2072 | + renderer_class->draw_ellipse = draw_ellipse; | |
2073 | + | |
2074 | + /* Until we have NURBS, let Dia use lines */ | |
2075 | + /* renderer_class->draw_bezier = draw_bezier; */ | |
2076 | + /* renderer_class->draw_beziergon = draw_beziergon; */ | |
2077 | + /* renderer_class->draw_bezier_with_arrows = draw_bezier_with_arrows; */ | |
2078 | + | |
2079 | + renderer_class->draw_string = draw_string; | |
2080 | + | |
2081 | + renderer_class->draw_image = draw_image; | |
2082 | + | |
2083 | + renderer_class->draw_rounded_rect = draw_rounded_rect; | |
2084 | + /* Further high level methods not required (or desired?) */ | |
2085 | +} |
@@ -631,19 +631,25 @@ vdx_simple_properties(DiaObject *obj, | ||
631 | 631 | (LinestyleProperty *)make_new_prop("line_style", |
632 | 632 | PROP_TYPE_LINESTYLE, |
633 | 633 | PROP_FLAG_DONT_SAVE); |
634 | - lsprop->style = LINESTYLE_SOLID; | |
635 | - | |
636 | - if (Line->LinePattern > 1) | |
637 | - lsprop->style = LINESTYLE_DASHED; | |
638 | - if (Line->LinePattern == 4) | |
639 | - lsprop->style = LINESTYLE_DASH_DOT; | |
640 | - if (Line->LinePattern == 3) | |
641 | - lsprop->style = LINESTYLE_DOTTED; | |
634 | + if (Line->LinePattern == 2) | |
635 | + lsprop->style = LINESTYLE_DASHED; | |
636 | + else if (Line->LinePattern == 4) | |
637 | + lsprop->style = LINESTYLE_DASH_DOT; | |
638 | + else if (Line->LinePattern == 3) | |
639 | + lsprop->style = LINESTYLE_DOTTED; | |
640 | + else if (Line->LinePattern == 5) | |
641 | + lsprop->style = LINESTYLE_DASH_DOT_DOT; | |
642 | + else | |
643 | + lsprop->style = LINESTYLE_SOLID; | |
642 | 644 | |
643 | 645 | lsprop->dash = vdx_Dash_Length; |
644 | 646 | |
645 | 647 | g_ptr_array_add(props,lsprop); |
646 | 648 | } |
649 | + if (Line->Rounding > 0.0) | |
650 | + { | |
651 | + prop_list_add_real(props, "corner_radius", Line->Rounding * vdx_Line_Scale); | |
652 | + } | |
647 | 653 | } |
648 | 654 | |
649 | 655 | if (Fill && Fill->FillPattern) |
@@ -809,6 +815,46 @@ make_arrow(const struct vdx_Line *Line, char start_end, | ||
809 | 815 | return a; |
810 | 816 | } |
811 | 817 | |
818 | +/*! | |
819 | + * \brief Translate points to rectangle representation if possible | |
820 | + */ | |
821 | +static gboolean | |
822 | +_is_rect (int count, Point *points, real *x, real *y, real *w, real *h) | |
823 | +{ | |
824 | + int i; | |
825 | + real minx, miny, maxdx = 0.0, maxdy = 0.0, sumdx = 0.0, sumdy = 0.0; | |
826 | + | |
827 | + if (count != 5) | |
828 | + return FALSE; | |
829 | + minx = points[0].x; | |
830 | + miny = points[0].y; | |
831 | + for (i = 1; i< 5; ++i) | |
832 | + { | |
833 | + real dx = points[i-1].x - points[i].x; | |
834 | + real dy = points[i-1].y - points[i].y; | |
835 | + | |
836 | + /* must be both 0 for a real rectangle */ | |
837 | + sumdx += dx; | |
838 | + sumdy += dy; | |
839 | + | |
840 | + dx = fabs (dx); | |
841 | + dy = fabs (dy); | |
842 | + | |
843 | + if (dx > EPSILON && dy > EPSILON) | |
844 | + return FALSE; | |
845 | + minx = MIN(minx, points[i].x); | |
846 | + miny = MIN(miny, points[i].y); | |
847 | + maxdx = MAX(maxdx, dx); | |
848 | + maxdy = MAX(maxdy, dy); | |
849 | + } | |
850 | + if (fabs(sumdx) > EPSILON || fabs(sumdy) > EPSILON) | |
851 | + return FALSE; | |
852 | + *x = minx; | |
853 | + *y = miny; | |
854 | + *w = maxdx; | |
855 | + *h = maxdy; | |
856 | + return TRUE; | |
857 | +} | |
812 | 858 | |
813 | 859 | /* The following functions create the Dia standard objects */ |
814 | 860 |
@@ -942,7 +988,16 @@ plot_polyline(const struct vdx_Geom *Geom, const struct vdx_XForm *XForm, | ||
942 | 988 | } |
943 | 989 | else |
944 | 990 | { |
945 | - newobj = create_standard_polygon(count, points); | |
991 | + real x, y, w, h; | |
992 | + | |
993 | + if (_is_rect (count, points, &x, &y, &w, &h)) | |
994 | + { | |
995 | + newobj = create_standard_box(x, y, w, h); | |
996 | + } | |
997 | + else | |
998 | + { | |
999 | + newobj = create_standard_polygon(count, points); | |
1000 | + } | |
946 | 1001 | } |
947 | 1002 | } |
948 | 1003 | else |