1 /* -*- Mode: C; c-basic-offset: 4 -*- */
2 /* Dia -- an diagram creation/manipulation program
3  * Copyright (C) 1998 Alexander Larsson
4  *
5  * render_metapost.c: Exporting module/plug-in to TeX Metapost
6  * Copyright (C) 2001 Chris Sperandio
7  * Originally derived from render_pstricks.c (pstricks plug-in)
8  * Copyright (C) 2000 Jacek Pliszka <pliszka@fuw.edu.pl>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  */
24 
25 
26 
27 /*
28  * This was basically borrowed from the pstricks plug-in.
29  *
30  * TODO:
31  * 1. Include file support.
32  * 2. Linestyles really need tweaking.
33  */
34 
35 
36 #include <config.h>
37 
38 #include <string.h>
39 #include <time.h>
40 #include <math.h>
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #include <errno.h>
45 
46 #include <glib/gstdio.h>
47 
48 #include "intl.h"
49 #include "render_metapost.h"
50 #include "message.h"
51 #include "diagramdata.h"
52 #include "filter.h"
53 #include "dia_image.h"
54 #include "font.h"
55 #include "text.h"
56 #include "textline.h"
57 
58 #define POINTS_in_INCH 28.346
59 #define DTOSTR_BUF_SIZE G_ASCII_DTOSTR_BUF_SIZE
60 #define mp_dtostr(buf,d) \
61 	g_ascii_formatd(buf, sizeof(buf), "%f", d)
62 
63 /* An entry in the font-mapping lookup table. */
64 typedef struct _font_lookup_entry {
65     char            *dia_name;
66         /* Dia's name for the font. */
67 
68     char            *mp_name;
69         /* Second argument for the \usefont command in the embedded TeX
70          * we'll pass to MetaPost. */
71 
72     real            size_mult;
73         /* Converts from a Dia font size to a MetaPost font "scaling factor".
74          * If x is the size of your Dia font, then the size of your MetaPost
75          * font will be (x * size_mult) / (10 pts), and you'll have to use
76          * (x * size_mult) as the "scale" argument to the label() command. */
77 
78 } _font_lookup_entry;
79 
80 #define DEFAULT_MP_FONT "cmr"
81 #define DEFAULT_MP_WEIGHT "m"
82 #define DEFAULT_MP_SLANT "n"
83 
84 #define DEFAULT_SIZE_MULT (1.9F)
85 
86 #define MAX_FONT_NAME_LEN 256
87 
88 /* A lookup table for converting Dia fonts into MetaPost fonts. */
89 /* TODO: Make the fonts in this table map more closely. */
90 static _font_lookup_entry FONT_LOOKUP_TABLE[] =
91 {
92     /* Since Dia doesn't usually have a "computer modern" font, we map Century
93      * Schoolbook to that font. */
94     {"century schoolbook l", DEFAULT_MP_FONT, DEFAULT_SIZE_MULT},
95 
96     /* Sans serif fonts go to phv. */
97     {"arial",       "phv", 2.05F},
98     {"helvetica",   "phv", 2.05F},
99     {"sans",        "phv", 2.05F},
100 
101     /* Monospace fonts map to Computer Modern Typewriter. */
102     {"courier",         "cmtt", 2.3F},
103     {"courier new",     "cmtt", 2.3F},
104     {"monospace",       "cmtt", 2.3F},
105     {NULL, NULL, 0.0F}
106         /* Terminator. */
107 };
108 
109 
110 /* An entry in the font weight lookup table. */
111 typedef struct _weight_lookup_entry {
112     DiaFontStyle    weight;
113         /* Mask your style with DIA_FONT_STYLE_GET_WEIGHT() and compare
114          * to this... */
115 
116     char            *mp_weight;
117         /* Third argument for the \usefont command in the embedded TeX
118          * we'll pass to MetaPost. */
119 } _weight_lookup_entry;
120 
121 #define STYLE_TERMINATOR ((DiaFontStyle)0xffffffff)
122 static _weight_lookup_entry WEIGHT_LOOKUP_TABLE[] =
123 {
124     {DIA_FONT_ULTRALIGHT,       "m"},
125     {DIA_FONT_LIGHT,            "m"},
126     {DIA_FONT_WEIGHT_NORMAL,    "m"},
127     {DIA_FONT_MEDIUM,           "m"},
128     {DIA_FONT_DEMIBOLD,         "b"},
129     {DIA_FONT_BOLD,             "b"},
130     {DIA_FONT_ULTRABOLD,        "b"},
131     {DIA_FONT_HEAVY,            "b"},
132     {STYLE_TERMINATOR, NULL}
133         /* Terminator */
134 };
135 
136 /* An entry in the font slant lookup table. */
137 typedef struct _slant_lookup_entry {
138     DiaFontStyle    slant;
139     char            *mp_slant;
140 } _slant_lookup_entry;
141 
142 static _slant_lookup_entry SLANT_LOOKUP_TABLE[] =
143 {
144     {DIA_FONT_NORMAL,   "n"},
145     {DIA_FONT_OBLIQUE,  "sl"},
146     {DIA_FONT_ITALIC,   "it"},
147     {STYLE_TERMINATOR, NULL}
148         /* Terminator */
149 };
150 
151 
152 
153 static void end_draw_op(MetapostRenderer *renderer);
154 static void draw_with_linestyle(MetapostRenderer *renderer);
155 
156 static void begin_render(DiaRenderer *self);
157 static void end_render(DiaRenderer *self);
158 static void set_linewidth(DiaRenderer *self, real linewidth);
159 static void set_linecaps(DiaRenderer *self, LineCaps mode);
160 static void set_linejoin(DiaRenderer *self, LineJoin mode);
161 static void set_linestyle(DiaRenderer *self, LineStyle mode);
162 static void set_dashlength(DiaRenderer *self, real length);
163 static void set_fillstyle(DiaRenderer *self, FillStyle mode);
164 static void set_font(DiaRenderer *self, DiaFont *font, real height);
165 static void draw_line(DiaRenderer *self,
166 		      Point *start, Point *end,
167 		      Color *line_color);
168 static void draw_polyline(DiaRenderer *self,
169 			  Point *points, int num_points,
170 			  Color *line_color);
171 static void draw_polygon(DiaRenderer *self,
172 			 Point *points, int num_points,
173 			 Color *line_color);
174 static void fill_polygon(DiaRenderer *self,
175 			 Point *points, int num_points,
176 			 Color *line_color);
177 static void draw_rect(DiaRenderer *self,
178 		      Point *ul_corner, Point *lr_corner,
179 		      Color *color);
180 static void fill_rect(DiaRenderer *self,
181 		      Point *ul_corner, Point *lr_corner,
182 		      Color *color);
183 static void draw_arc(DiaRenderer *self,
184 		     Point *center,
185 		     real width, real height,
186 		     real angle1, real angle2,
187 		     Color *color);
188 static void fill_arc(DiaRenderer *self,
189 		     Point *center,
190 		     real width, real height,
191 		     real angle1, real angle2,
192 		     Color *color);
193 static void draw_ellipse(DiaRenderer *self,
194 			 Point *center,
195 			 real width, real height,
196 			 Color *color);
197 static void fill_ellipse(DiaRenderer *self,
198 			 Point *center,
199 			 real width, real height,
200 			 Color *color);
201 static void draw_bezier(DiaRenderer *self,
202 			BezPoint *points,
203 			int numpoints,
204 			Color *color);
205 static void fill_bezier(DiaRenderer *self,
206 			BezPoint *points, /* Last point must be same as first point */
207 			int numpoints,
208 			Color *color);
209 static void draw_string(DiaRenderer *self,
210 			const char *text,
211 			Point *pos, Alignment alignment,
212 			Color *color);
213 static void draw_text  (DiaRenderer *self,
214 			Text *text);
215 static void draw_image(DiaRenderer *self,
216 		       Point *point,
217 		       real width, real height,
218 		       DiaImage *image);
219 
220 /* GObject stuff */
221 static void metapost_renderer_class_init (MetapostRendererClass *klass);
222 
223 static gpointer parent_class = NULL;
224 
225 GType
metapost_renderer_get_type(void)226 metapost_renderer_get_type (void)
227 {
228   static GType object_type = 0;
229 
230   if (!object_type)
231     {
232       static const GTypeInfo object_info =
233       {
234         sizeof (MetapostRendererClass),
235         (GBaseInitFunc) NULL,
236         (GBaseFinalizeFunc) NULL,
237         (GClassInitFunc) metapost_renderer_class_init,
238         NULL,           /* class_finalize */
239         NULL,           /* class_data */
240         sizeof (MetapostRenderer),
241         0,              /* n_preallocs */
242 	NULL            /* init */
243       };
244 
245       object_type = g_type_register_static (DIA_TYPE_RENDERER,
246                                             "MetapostRenderer",
247                                             &object_info, 0);
248     }
249 
250   return object_type;
251 }
252 
253 static void
metapost_renderer_finalize(GObject * object)254 metapost_renderer_finalize (GObject *object)
255 {
256 /*  MetapostRenderer *metapost_renderer = METAPOST_RENDERER (object); */
257 
258   G_OBJECT_CLASS (parent_class)->finalize (object);
259 }
260 
261 static void
metapost_renderer_class_init(MetapostRendererClass * klass)262 metapost_renderer_class_init (MetapostRendererClass *klass)
263 {
264   GObjectClass *object_class = G_OBJECT_CLASS (klass);
265   DiaRendererClass *renderer_class = DIA_RENDERER_CLASS (klass);
266 
267   parent_class = g_type_class_peek_parent (klass);
268 
269   object_class->finalize = metapost_renderer_finalize;
270 
271   renderer_class->begin_render = begin_render;
272   renderer_class->end_render = end_render;
273 
274   renderer_class->set_linewidth = set_linewidth;
275   renderer_class->set_linecaps = set_linecaps;
276   renderer_class->set_linejoin = set_linejoin;
277   renderer_class->set_linestyle = set_linestyle;
278   renderer_class->set_dashlength = set_dashlength;
279   renderer_class->set_fillstyle = set_fillstyle;
280   renderer_class->set_font = set_font;
281 
282   renderer_class->draw_line = draw_line;
283   renderer_class->draw_polyline = draw_polyline;
284 
285   renderer_class->draw_polygon = draw_polygon;
286   renderer_class->fill_polygon = fill_polygon;
287 
288   renderer_class->draw_rect = draw_rect;
289   renderer_class->fill_rect = fill_rect;
290 
291   renderer_class->draw_arc = draw_arc;
292   renderer_class->fill_arc = fill_arc;
293 
294   renderer_class->draw_ellipse = draw_ellipse;
295   renderer_class->fill_ellipse = fill_ellipse;
296 
297   renderer_class->draw_bezier = draw_bezier;
298   renderer_class->fill_bezier = fill_bezier;
299 
300   renderer_class->draw_string = draw_string;
301   renderer_class->draw_text = draw_text;
302 
303   renderer_class->draw_image = draw_image;
304 }
305 
306 
307 static void
end_draw_op(MetapostRenderer * renderer)308 end_draw_op(MetapostRenderer *renderer)
309 {
310     gchar d1_buf[DTOSTR_BUF_SIZE];
311     gchar d2_buf[DTOSTR_BUF_SIZE];
312     gchar d3_buf[DTOSTR_BUF_SIZE];
313 
314     fprintf(renderer->file, "\n    withpen pencircle scaled %sx",
315             g_ascii_formatd(d1_buf, sizeof(d1_buf), "%5.4f", (gdouble) renderer->line_width) );
316 
317     if (!color_equals(&renderer->color, &color_black))
318         fprintf(renderer->file, "\n    withcolor (%s, %s, %s)",
319                 g_ascii_formatd(d1_buf, sizeof(d1_buf), "%5.4f", (gdouble) renderer->color.red),
320                 g_ascii_formatd(d2_buf, sizeof(d2_buf), "%5.4f", (gdouble) renderer->color.green),
321                 g_ascii_formatd(d3_buf, sizeof(d3_buf), "%5.4f", (gdouble) renderer->color.blue) );
322 
323     draw_with_linestyle(renderer);
324     fprintf(renderer->file, ";\n");
325 }
326 
327 static void
set_line_color(MetapostRenderer * renderer,Color * color)328 set_line_color(MetapostRenderer *renderer,Color *color)
329 {
330     gchar red_buf[DTOSTR_BUF_SIZE];
331     gchar green_buf[DTOSTR_BUF_SIZE];
332     gchar blue_buf[DTOSTR_BUF_SIZE];
333 
334     renderer->color = *color;
335     fprintf(renderer->file, "%% set_line_color %s, %s, %s\n",
336             mp_dtostr(red_buf, (gdouble)color->red),
337 	    mp_dtostr(green_buf, (gdouble)color->green),
338 	    mp_dtostr(blue_buf, (gdouble)color->blue) );
339 }
340 
341 static void
set_fill_color(MetapostRenderer * renderer,Color * color)342 set_fill_color(MetapostRenderer *renderer,Color *color)
343 {
344     set_line_color(renderer,color);
345 }
346 
347 
348 static void
begin_render(DiaRenderer * self)349 begin_render(DiaRenderer *self)
350 {
351 }
352 
353 static void
end_render(DiaRenderer * self)354 end_render(DiaRenderer *self)
355 {
356     MetapostRenderer *renderer = METAPOST_RENDERER (self);
357 
358     fprintf(renderer->file,"endfig;\n");
359     fprintf(renderer->file,"end;\n");
360     fclose(renderer->file);
361 }
362 
363 static void
set_linewidth(DiaRenderer * self,real linewidth)364 set_linewidth(DiaRenderer *self, real linewidth)
365 {  /* 0 == hairline **/
366     gchar buf[DTOSTR_BUF_SIZE];
367     MetapostRenderer *renderer = METAPOST_RENDERER (self);
368 
369     fprintf(renderer->file, "%% set_linewidth %s\n", mp_dtostr(buf,linewidth) );
370     renderer->line_width = linewidth;
371 }
372 
373 static void
set_linecaps(DiaRenderer * self,LineCaps mode)374 set_linecaps(DiaRenderer *self, LineCaps mode)
375 {
376     MetapostRenderer *renderer = METAPOST_RENDERER (self);
377 
378     if(mode == renderer->saved_line_cap)
379 	return;
380 
381     switch(mode) {
382     case LINECAPS_BUTT:
383 	fprintf(renderer->file, "linecap:=butt;\n");
384 	break;
385     case LINECAPS_ROUND:
386 	fprintf(renderer->file, "linecap:=rounded;\n");
387 	break;
388     case LINECAPS_PROJECTING:
389 	/* is this right? */
390 	fprintf(renderer->file, "linecap:=squared;\n");
391 	break;
392     default:
393 	fprintf(renderer->file, "linecap:=squared;\n");
394     }
395 
396     renderer->saved_line_cap = mode;
397 }
398 
399 static void
set_linejoin(DiaRenderer * self,LineJoin mode)400 set_linejoin(DiaRenderer *self, LineJoin mode)
401 {
402     MetapostRenderer *renderer = METAPOST_RENDERER (self);
403 
404     if(mode == renderer->saved_line_join)
405 	return;
406 
407     switch(mode) {
408     case LINEJOIN_MITER:
409 	fprintf(renderer->file, "linejoin:=mitered;\n");
410 	break;
411     case LINEJOIN_ROUND:
412 	fprintf(renderer->file, "linejoin:=rounded;\n");
413 	break;
414     case LINEJOIN_BEVEL:
415 	fprintf(renderer->file, "linejoin:=beveled;\n");
416 	break;
417     default:
418 	/* noop; required at least for msvc */;
419     }
420 
421     renderer->saved_line_join = mode;
422 }
423 
424 static void
set_linestyle(DiaRenderer * self,LineStyle mode)425 set_linestyle(DiaRenderer *self, LineStyle mode)
426 {
427     MetapostRenderer *renderer = METAPOST_RENDERER (self);
428     renderer->saved_line_style = mode;
429 }
430 
431 static void
draw_with_linestyle(MetapostRenderer * renderer)432 draw_with_linestyle(MetapostRenderer *renderer)
433 {
434     real hole_width;
435     gchar dash_length_buf[DTOSTR_BUF_SIZE];
436     gchar dot_lenght_buf[DTOSTR_BUF_SIZE];
437     gchar hole_width_buf[DTOSTR_BUF_SIZE];
438 
439     switch(renderer->saved_line_style) {
440     case LINESTYLE_SOLID:
441 	break;
442     case LINESTYLE_DASHED:
443 	mp_dtostr(dash_length_buf, renderer->dash_length);
444 	fprintf(renderer->file, "\n    dashed dashpattern (on %sx off %sx)",
445 		dash_length_buf, dash_length_buf);
446 	break;
447     case LINESTYLE_DASH_DOT:
448 	hole_width = (renderer->dash_length - renderer->dot_length) / 2.0;
449 
450 	mp_dtostr(dash_length_buf, renderer->dash_length);
451 	mp_dtostr(dot_lenght_buf, renderer->dot_length);
452 	mp_dtostr(hole_width_buf, hole_width);
453 
454 	fprintf(renderer->file, "\n    dashed dashpattern (on %sx off %sx on %sx off %sx)",
455 		dash_length_buf, hole_width_buf,
456 		dot_lenght_buf, hole_width_buf);
457 	break;
458     case LINESTYLE_DASH_DOT_DOT:
459 	hole_width = (renderer->dash_length - 2.0*renderer->dot_length) / 3.0;
460 
461 	mp_dtostr(dash_length_buf, renderer->dash_length);
462 	mp_dtostr(dot_lenght_buf, renderer->dot_length);
463 	mp_dtostr(hole_width_buf, hole_width);
464 
465 	fprintf(renderer->file, "\n    dashed dashpattern (on %sx off %sx on %sx off %sx on %sx off %sx)",
466 		dash_length_buf, hole_width_buf,
467 		dot_lenght_buf, hole_width_buf,
468 		dot_lenght_buf, hole_width_buf );
469 	break;
470     case LINESTYLE_DOTTED:
471 	mp_dtostr(dot_lenght_buf, renderer->dot_length);
472 
473 	fprintf(renderer->file, "\n    dashed dashpattern (on %sx off %sx)",
474 		dot_lenght_buf, dot_lenght_buf);
475 	break;
476     }
477 }
478 
479 static void
set_dashlength(DiaRenderer * self,real length)480 set_dashlength(DiaRenderer *self, real length)
481 {  /* dot = 20% of len */
482     MetapostRenderer *renderer = METAPOST_RENDERER (self);
483 
484     if (length<0.001)
485 	length = 0.001;
486 
487     renderer->dash_length = length;
488     renderer->dot_length = length*0.05;
489 
490     set_linestyle(self, renderer->saved_line_style);
491 }
492 
493 static void
set_fillstyle(DiaRenderer * self,FillStyle mode)494 set_fillstyle(DiaRenderer *self, FillStyle mode)
495 {
496     /*MetapostRenderer *renderer = METAPOST_RENDERER (self);*/
497 
498     switch(mode) {
499     case FILLSTYLE_SOLID:
500 	break;
501     default:
502 	message_error("metapost_renderer: Unsupported fill mode specified!\n");
503     }
504 }
505 
506 static void
set_font(DiaRenderer * self,DiaFont * font,real height)507 set_font(DiaRenderer *self, DiaFont *font, real height)
508 {
509     MetapostRenderer *renderer = METAPOST_RENDERER (self);
510     int i = -1;
511 
512     /* Determine what font Dia is using, so we can convert to the closest
513      * matching MetaPost font. */
514     char *dia_font_name = (char*)dia_font_get_family(font);
515     const DiaFontStyle dia_font_style = dia_font_get_style(font);
516     const real dia_font_height = height;
517 
518     /* Catch default Dia fonts. */
519     if (DIA_FONT_STYLE_GET_FAMILY(dia_font_style) == DIA_FONT_SANS) {
520         dia_font_name = "sans";
521     } else if (DIA_FONT_STYLE_GET_FAMILY(dia_font_style) == DIA_FONT_SERIF) {
522         dia_font_name = "serif";
523     } else if (DIA_FONT_STYLE_GET_FAMILY(dia_font_style)
524             == DIA_FONT_MONOSPACE)
525     {
526         dia_font_name = "monospace";
527     }
528 
529     /* Start out with some sensible defaults. */
530     renderer->mp_font = DEFAULT_MP_FONT;
531     renderer->mp_weight = DEFAULT_MP_WEIGHT;
532     renderer->mp_slant = DEFAULT_MP_SLANT;
533     renderer->mp_font_height = DEFAULT_SIZE_MULT * dia_font_height;
534 
535     /* Try to find a better match for the Dia font by checking our lookup
536      * table. */
537     for (i = 0; FONT_LOOKUP_TABLE[i].dia_name != NULL; i++) {
538         if (0 == strncmp(FONT_LOOKUP_TABLE[i].dia_name, dia_font_name,
539                             MAX_FONT_NAME_LEN))
540         {
541             /* Found a match. */
542             renderer->mp_font = FONT_LOOKUP_TABLE[i].mp_name;
543             renderer->mp_font_height = FONT_LOOKUP_TABLE[i].size_mult
544                                         * dia_font_height;
545             break;
546         }
547     }
548 
549     /* Do the same for the weight and size. */
550     for (i = 0; WEIGHT_LOOKUP_TABLE[i].weight != STYLE_TERMINATOR; i++) {
551         if (DIA_FONT_STYLE_GET_WEIGHT(dia_font_style)
552                 == WEIGHT_LOOKUP_TABLE[i].weight) {
553             renderer->mp_weight = WEIGHT_LOOKUP_TABLE[i].mp_weight;
554         }
555     }
556     for (i = 0; SLANT_LOOKUP_TABLE[i].slant != STYLE_TERMINATOR; i++) {
557         if (DIA_FONT_STYLE_GET_SLANT(dia_font_style)
558                 == SLANT_LOOKUP_TABLE[i].slant) {
559             renderer->mp_slant = SLANT_LOOKUP_TABLE[i].mp_slant;
560         }
561     }
562 
563 #if 0
564     fprintf(renderer->file, "defaultfont:=\"%s\";\n", font_get_psfontname(font));
565 #endif
566 }
567 
568 static void
draw_line(DiaRenderer * self,Point * start,Point * end,Color * line_color)569 draw_line(DiaRenderer *self,
570 	  Point *start, Point *end,
571 	  Color *line_color)
572 {
573     MetapostRenderer *renderer = METAPOST_RENDERER (self);
574     gchar sx_buf[DTOSTR_BUF_SIZE];
575     gchar sy_buf[DTOSTR_BUF_SIZE];
576     gchar ex_buf[DTOSTR_BUF_SIZE];
577     gchar ey_buf[DTOSTR_BUF_SIZE];
578 
579     set_line_color(renderer,line_color);
580 
581     fprintf(renderer->file, "  draw (%sx,%sy)--(%sx,%sy)",
582 	    mp_dtostr(sx_buf, start->x), mp_dtostr(sy_buf, start->y),
583 	    mp_dtostr(ex_buf, end->x), mp_dtostr(ey_buf, end->y) );
584     end_draw_op(renderer);
585 }
586 
587 static void
draw_polyline(DiaRenderer * self,Point * points,int num_points,Color * line_color)588 draw_polyline(DiaRenderer *self,
589 	      Point *points, int num_points,
590 	      Color *line_color)
591 {
592     MetapostRenderer *renderer = METAPOST_RENDERER (self);
593     int i;
594     gchar px_buf[DTOSTR_BUF_SIZE];
595     gchar py_buf[DTOSTR_BUF_SIZE];
596 
597     set_line_color(renderer,line_color);
598 
599     fprintf(renderer->file,
600 	    "  draw (%sx,%sy)",
601 	    mp_dtostr(px_buf, points[0].x),
602 	    mp_dtostr(py_buf, points[0].y) );
603 
604     for (i=1;i<num_points;i++) {
605 	fprintf(renderer->file, "--(%sx,%sy)",
606 		mp_dtostr(px_buf, points[i].x),
607 		mp_dtostr(py_buf, points[i].y) );
608     }
609     end_draw_op(renderer);
610 }
611 
612 static void
draw_polygon(DiaRenderer * self,Point * points,int num_points,Color * line_color)613 draw_polygon(DiaRenderer *self,
614 	     Point *points, int num_points,
615 	     Color *line_color)
616 {
617     MetapostRenderer *renderer = METAPOST_RENDERER (self);
618     int i;
619     gchar px_buf[DTOSTR_BUF_SIZE];
620     gchar py_buf[DTOSTR_BUF_SIZE];
621 
622     set_line_color(renderer,line_color);
623 
624     fprintf(renderer->file,
625 	    "  draw (%sx,%sy)",
626 	    mp_dtostr(px_buf, points[0].x),
627 	    mp_dtostr(py_buf, points[0].y) );
628 
629     for (i=1;i<num_points;i++) {
630 	fprintf(renderer->file, "--(%sx,%sy)",
631 		mp_dtostr(px_buf, points[i].x),
632 		mp_dtostr(py_buf, points[i].y) );
633     }
634     fprintf(renderer->file,"--cycle");
635     end_draw_op(renderer);
636 }
637 
638 static void
fill_polygon(DiaRenderer * self,Point * points,int num_points,Color * line_color)639 fill_polygon(DiaRenderer *self,
640 	     Point *points, int num_points,
641 	     Color *line_color)
642 {
643     MetapostRenderer *renderer = METAPOST_RENDERER (self);
644     int i;
645     gchar px_buf[DTOSTR_BUF_SIZE];
646     gchar py_buf[DTOSTR_BUF_SIZE];
647 
648     set_line_color(renderer,line_color);
649 
650     fprintf(renderer->file, "%% fill_polygon\n");
651     fprintf(renderer->file,
652 	    "  path p;\n"
653 	    "  p = (%sx,%sy)",
654 	    mp_dtostr(px_buf, points[0].x),
655 	    mp_dtostr(py_buf, points[0].y) );
656 
657     for (i=1;i<num_points;i++) {
658 	fprintf(renderer->file, "--(%sx,%sy)",
659 		mp_dtostr(px_buf, points[i].x),
660 		mp_dtostr(py_buf, points[i].y) );
661     }
662     fprintf(renderer->file,"--cycle;\n");
663     fprintf(renderer->file,"  fill p ");
664     end_draw_op(renderer);
665 }
666 
667 static void
draw_rect(DiaRenderer * self,Point * ul_corner,Point * lr_corner,Color * color)668 draw_rect(DiaRenderer *self,
669 	  Point *ul_corner, Point *lr_corner,
670 	  Color *color)
671 {
672     MetapostRenderer *renderer = METAPOST_RENDERER (self);
673     gchar ulx_buf[DTOSTR_BUF_SIZE];
674     gchar uly_buf[DTOSTR_BUF_SIZE];
675     gchar lrx_buf[DTOSTR_BUF_SIZE];
676     gchar lry_buf[DTOSTR_BUF_SIZE];
677 
678     mp_dtostr(ulx_buf, (gdouble) ul_corner->x);
679     mp_dtostr(uly_buf, (gdouble) ul_corner->y);
680     mp_dtostr(lrx_buf, (gdouble) lr_corner->x);
681     mp_dtostr(lry_buf, (gdouble) lr_corner->y);
682 
683     set_line_color(renderer,color);
684 
685     fprintf(renderer->file,
686 	    "  draw (%sx,%sy)--(%sx,%sy)--(%sx,%sy)--(%sx,%sy)--cycle",
687 	    ulx_buf, uly_buf,
688 	    ulx_buf, lry_buf,
689 	    lrx_buf, lry_buf,
690 	    lrx_buf, uly_buf );
691     end_draw_op(renderer);
692 }
693 
694 static void
fill_rect(DiaRenderer * self,Point * ul_corner,Point * lr_corner,Color * color)695 fill_rect(DiaRenderer *self,
696 	  Point *ul_corner, Point *lr_corner,
697 	  Color *color)
698 {
699     MetapostRenderer *renderer = METAPOST_RENDERER (self);
700     gchar ulx_buf[DTOSTR_BUF_SIZE];
701     gchar uly_buf[DTOSTR_BUF_SIZE];
702     gchar lrx_buf[DTOSTR_BUF_SIZE];
703     gchar lry_buf[DTOSTR_BUF_SIZE];
704     gchar red_buf[DTOSTR_BUF_SIZE];
705     gchar green_buf[DTOSTR_BUF_SIZE];
706     gchar blue_buf[DTOSTR_BUF_SIZE];
707 
708     mp_dtostr(ulx_buf, (gdouble) ul_corner->x);
709     mp_dtostr(uly_buf, (gdouble) ul_corner->y);
710     mp_dtostr(lrx_buf, (gdouble) lr_corner->x);
711     mp_dtostr(lry_buf, (gdouble) lr_corner->y);
712 
713     fprintf(renderer->file,
714 	    "  path p;\n"
715 	    "  p = (%sx,%sy)--(%sx,%sy)--(%sx,%sy)--(%sx,%sy)--cycle;\n",
716 	    ulx_buf, uly_buf,
717 	    ulx_buf, lry_buf,
718 	    lrx_buf, lry_buf,
719 	    lrx_buf, uly_buf );
720     fprintf(renderer->file,
721 	    "  fill p withcolor (%s,%s,%s);\n",
722 	    mp_dtostr(red_buf, (gdouble) color->red),
723 	    mp_dtostr(green_buf, (gdouble) color->green),
724 	    mp_dtostr(blue_buf, (gdouble) color->blue) );
725 }
726 
727 static void
metapost_arc(MetapostRenderer * renderer,Point * center,real width,real height,real angle1,real angle2,Color * color,int filled)728 metapost_arc(MetapostRenderer *renderer,
729 	     Point *center,
730 	     real width, real height,
731 	     real angle1, real angle2,
732 	     Color *color, int filled)
733 {
734     double radius1,radius2;
735     double angle3;
736     double cx = (double) center->x;
737     double cy = (double) center->y;
738     gchar d1_buf[DTOSTR_BUF_SIZE];
739     gchar d2_buf[DTOSTR_BUF_SIZE];
740 
741     radius1=(double) width/2.0;
742     radius2=(double) height/2.0;
743 
744     fprintf(renderer->file,"%%metapost_arc\n");
745     fprintf(renderer->file, "%% %s = %s", "center->x", mp_dtostr(d1_buf, center->x));
746     fprintf(renderer->file, "%% %s = %s", "center->y", mp_dtostr(d1_buf, center->y));
747     fprintf(renderer->file, "%% %s = %s", "width", mp_dtostr(d1_buf, width));
748     fprintf(renderer->file, "%% %s = %s", "height", mp_dtostr(d1_buf, height));
749     fprintf(renderer->file, "%% %s = %s", "angle1", mp_dtostr(d1_buf, angle1));
750     fprintf(renderer->file, "%% %s = %s", "angle2", mp_dtostr(d1_buf, angle2));
751 
752 
753     angle1 = angle1*M_PI/180;
754     angle2 = angle2*M_PI/180;
755     angle3 = (double) (angle1+angle2)/2;
756     if (angle1 > angle2)
757         angle3 += M_PI;
758 
759     set_line_color(renderer,color);
760 
761     fprintf(renderer->file, "  draw (%sx,%sy)..",
762 	    mp_dtostr(d1_buf, cx + radius1*cos(angle1)),
763 	    mp_dtostr(d2_buf, cy - radius2*sin(angle1)) );
764     fprintf(renderer->file, "(%sx,%sy)..",
765 	    mp_dtostr(d1_buf, cx + radius1*cos(angle3)),
766 	    mp_dtostr(d2_buf, cy - radius2*sin(angle3)) );
767     fprintf(renderer->file, "(%sx,%sy)",
768 	    mp_dtostr(d1_buf, cx + radius1*cos(angle2)),
769 	    mp_dtostr(d2_buf, cy - radius2*sin(angle2)) );
770     end_draw_op(renderer);
771 }
772 
773 static void
draw_arc(DiaRenderer * self,Point * center,real width,real height,real angle1,real angle2,Color * color)774 draw_arc(DiaRenderer *self,
775 	 Point *center,
776 	 real width, real height,
777 	 real angle1, real angle2,
778 	 Color *color)
779 {
780     MetapostRenderer *renderer = METAPOST_RENDERER (self);
781 
782     metapost_arc(renderer,center,width,height,angle1,angle2,color,0);
783 }
784 
785 static void
fill_arc(DiaRenderer * self,Point * center,real width,real height,real angle1,real angle2,Color * color)786 fill_arc(DiaRenderer *self,
787 	 Point *center,
788 	 real width, real height,
789 	 real angle1, real angle2,
790 	 Color *color)
791 {
792     MetapostRenderer *renderer = METAPOST_RENDERER (self);
793 
794     metapost_arc(renderer,center,width,height,angle1,angle2,color,1);
795 }
796 
797 static void
draw_ellipse(DiaRenderer * self,Point * center,real width,real height,Color * color)798 draw_ellipse(DiaRenderer *self,
799 	     Point *center,
800 	     real width, real height,
801 	     Color *color)
802 {
803     MetapostRenderer *renderer = METAPOST_RENDERER (self);
804     gchar d1_buf[DTOSTR_BUF_SIZE];
805     gchar d2_buf[DTOSTR_BUF_SIZE];
806 
807     set_line_color(renderer,color);
808 
809     fprintf(renderer->file, "  draw (%sx,%sy)..",
810 	    mp_dtostr(d1_buf, (gdouble) center->x+width/2.0),
811 	    mp_dtostr(d2_buf, (gdouble) center->y) );
812     fprintf(renderer->file, "(%sx,%sy)..",
813 	    mp_dtostr(d1_buf, (gdouble) center->x),
814 	    mp_dtostr(d2_buf, (gdouble) center->y+height/2.0) );
815     fprintf(renderer->file, "(%sx,%sy)..",
816 	    mp_dtostr(d1_buf, (gdouble) center->x-width/2.0),
817 	    mp_dtostr(d2_buf, (gdouble) center->y) );
818     fprintf(renderer->file, "(%sx,%sy)..cycle",
819 	    mp_dtostr(d1_buf, (gdouble) center->x),
820 	    mp_dtostr(d2_buf, (gdouble) center->y-height/2.0) );
821     end_draw_op(renderer);
822 }
823 
824 static void
fill_ellipse(DiaRenderer * self,Point * center,real width,real height,Color * color)825 fill_ellipse(DiaRenderer *self,
826 	     Point *center,
827 	     real width, real height,
828 	     Color *color)
829 {
830     MetapostRenderer *renderer = METAPOST_RENDERER (self);
831     gchar d1_buf[DTOSTR_BUF_SIZE];
832     gchar d2_buf[DTOSTR_BUF_SIZE];
833     gchar red_buf[DTOSTR_BUF_SIZE];
834     gchar green_buf[DTOSTR_BUF_SIZE];
835     gchar blue_buf[DTOSTR_BUF_SIZE];
836 
837     fprintf(renderer->file,
838 	    "  path p;\n"
839 	    "  p = (%sx,%sy)..",
840 	    mp_dtostr(d1_buf, (gdouble) center->x+width/2.0),
841 	    mp_dtostr(d2_buf, (gdouble) center->y) );
842     fprintf(renderer->file, "(%sx,%sy)..",
843 	    mp_dtostr(d1_buf, (gdouble) center->x),
844 	    mp_dtostr(d2_buf, (gdouble) center->y+height/2.0) );
845     fprintf(renderer->file, "(%sx,%sy)..",
846 	    mp_dtostr(d1_buf, (gdouble) center->x-width/2.0),
847 	    mp_dtostr(d2_buf, (gdouble) center->y) );
848     fprintf(renderer->file, "(%sx,%sy)..cycle;\n",
849 	    mp_dtostr(d1_buf, (gdouble) center->x),
850 	    mp_dtostr(d2_buf, (gdouble) center->y-height/2.0) );
851 
852     fprintf(renderer->file,
853 	    "  fill p withcolor (%s,%s,%s);\n",
854 	    mp_dtostr(red_buf, (gdouble) color->red),
855 	    mp_dtostr(green_buf, (gdouble) color->green),
856 	    mp_dtostr(blue_buf, (gdouble) color->blue) );
857 }
858 
859 
860 
861 static void
draw_bezier(DiaRenderer * self,BezPoint * points,int numpoints,Color * color)862 draw_bezier(DiaRenderer *self,
863 	    BezPoint *points,
864 	    int numpoints, /* numpoints = 4+3*n, n=>0 */
865 	    Color *color)
866 {
867     MetapostRenderer *renderer = METAPOST_RENDERER (self);
868     gint i;
869     gchar p1x_buf[DTOSTR_BUF_SIZE];
870     gchar p1y_buf[DTOSTR_BUF_SIZE];
871     gchar p2x_buf[DTOSTR_BUF_SIZE];
872     gchar p2y_buf[DTOSTR_BUF_SIZE];
873     gchar p3x_buf[DTOSTR_BUF_SIZE];
874     gchar p3y_buf[DTOSTR_BUF_SIZE];
875 
876     set_line_color(renderer,color);
877 
878     if (points[0].type != BEZ_MOVE_TO)
879 	g_warning("first BezPoint must be a BEZ_MOVE_TO");
880 
881     fprintf(renderer->file, "  draw (%sx,%sy)",
882 	    mp_dtostr(p1x_buf, (gdouble) points[0].p1.x),
883 	    mp_dtostr(p1y_buf, (gdouble) points[0].p1.y) );
884 
885     for (i = 1; i < numpoints; i++)
886 	switch (points[i].type) {
887 	case BEZ_MOVE_TO:
888 	    g_warning("only first BezPoint can be a BEZ_MOVE_TO");
889 	    break;
890 	case BEZ_LINE_TO:
891 	    fprintf(renderer->file, "--(%sx,%sy)",
892 		    mp_dtostr(p1x_buf, (gdouble) points[i].p1.x),
893 		    mp_dtostr(p1y_buf, (gdouble) points[i].p1.y) );
894 	    break;
895 	case BEZ_CURVE_TO:
896 	    fprintf(renderer->file, "..controls (%sx,%sy) and (%sx,%sy)\n    ..(%sx,%sy)",
897 		    mp_dtostr(p1x_buf, (gdouble) points[i].p1.x),
898 		    mp_dtostr(p1y_buf, (gdouble) points[i].p1.y),
899 		    mp_dtostr(p2x_buf, (gdouble) points[i].p2.x),
900 		    mp_dtostr(p2y_buf, (gdouble) points[i].p2.y),
901 		    mp_dtostr(p3x_buf, (gdouble) points[i].p3.x),
902 		    mp_dtostr(p3y_buf, (gdouble) points[i].p3.y) );
903 	    break;
904 	}
905     end_draw_op(renderer);
906 }
907 
908 
909 
910 static void
fill_bezier(DiaRenderer * self,BezPoint * points,int numpoints,Color * color)911 fill_bezier(DiaRenderer *self,
912 	    BezPoint *points, /* Last point must be same as first point */
913 	    int numpoints,
914 	    Color *color)
915 {
916     MetapostRenderer *renderer = METAPOST_RENDERER (self);
917     gint i;
918     gchar p1x_buf[DTOSTR_BUF_SIZE];
919     gchar p1y_buf[DTOSTR_BUF_SIZE];
920     gchar p2x_buf[DTOSTR_BUF_SIZE];
921     gchar p2y_buf[DTOSTR_BUF_SIZE];
922     gchar p3x_buf[DTOSTR_BUF_SIZE];
923     gchar p3y_buf[DTOSTR_BUF_SIZE];
924     gchar red_buf[DTOSTR_BUF_SIZE];
925     gchar green_buf[DTOSTR_BUF_SIZE];
926     gchar blue_buf[DTOSTR_BUF_SIZE];
927 
928     if (points[0].type != BEZ_MOVE_TO)
929 	g_warning("first BezPoint must be a BEZ_MOVE_TO");
930 
931     fprintf(renderer->file, "  path p;\n");
932     fprintf(renderer->file, "  p = (%sx,%sy)",
933 	    mp_dtostr(p1x_buf, (gdouble) points[0].p1.x),
934 	    mp_dtostr(p1y_buf, (gdouble) points[0].p1.y) );
935 
936     for (i = 1; i < numpoints; i++)
937 	switch (points[i].type) {
938 	case BEZ_MOVE_TO:
939 	    g_warning("only first BezPoint can be a BEZ_MOVE_TO");
940 	    break;
941 	case BEZ_LINE_TO:
942 	    fprintf(renderer->file, "--(%sx,%sy)",
943 		    mp_dtostr(p1x_buf, (gdouble) points[i].p1.x),
944 		    mp_dtostr(p1y_buf, (gdouble) points[i].p1.y) );
945 	    break;
946 	case BEZ_CURVE_TO:
947 	    fprintf(renderer->file, "..controls (%sx,%sy) and (%sx,%sy)\n    ..(%sx,%sy)",
948 		    mp_dtostr(p1x_buf, (gdouble) points[i].p1.x),
949 		    mp_dtostr(p1y_buf, (gdouble) points[i].p1.y),
950 		    mp_dtostr(p2x_buf, (gdouble) points[i].p2.x),
951 		    mp_dtostr(p2y_buf, (gdouble) points[i].p2.y),
952 		    mp_dtostr(p3x_buf, (gdouble) points[i].p3.x),
953 		    mp_dtostr(p3y_buf, (gdouble) points[i].p3.y) );
954 	    break;
955 	}
956     fprintf(renderer->file, "\n    ..cycle;\n");
957 
958     fprintf(renderer->file,
959 	    "  fill p withcolor (%s,%s,%s);\n",
960 	    mp_dtostr(red_buf, (gdouble) color->red),
961 	    mp_dtostr(green_buf, (gdouble) color->green),
962 	    mp_dtostr(blue_buf, (gdouble) color->blue) );
963 }
964 
965 static void
draw_string(DiaRenderer * self,const char * text,Point * pos,Alignment alignment,Color * color)966 draw_string(DiaRenderer *self,
967 	    const char *text,
968 	    Point *pos, Alignment alignment,
969 	    Color *color)
970 {
971     MetapostRenderer *renderer = METAPOST_RENDERER (self);
972     gchar height_buf[DTOSTR_BUF_SIZE];
973     gchar px_buf[DTOSTR_BUF_SIZE];
974     gchar py_buf[DTOSTR_BUF_SIZE];
975     gchar red_buf[DTOSTR_BUF_SIZE];
976     gchar green_buf[DTOSTR_BUF_SIZE];
977     gchar blue_buf[DTOSTR_BUF_SIZE];
978 
979     set_line_color(renderer,color);
980 
981     /* text position is correct for baseline. Uses macros defined
982 	 * at top of MetaPost file (see export_metapost) to correctly
983 	 * align text. See bug # 332554 */
984     switch (alignment) {
985     case ALIGN_LEFT:
986 	fprintf(renderer->file,"  draw");
987 	break;
988     case ALIGN_CENTER:
989 	fprintf(renderer->file,"  draw hcentered");
990 	break;
991     case ALIGN_RIGHT:
992 	fprintf(renderer->file,"  draw rjust");
993 	break;
994     }
995 
996     /* Ideally, we would be able to use the "infont" macro to print this label
997      * in the proper font.  Unfortunately, though, metapost is in the habit of
998      * converting spaces into visible spaces, which looks rather yucky.  So we
999      * embed some TeX with \usefont commands instead. */
1000 	/* Scale text by multiplying text by variable t in metapost */
1001     fprintf(renderer->file,
1002             " btex {\\usefont{OT1}{%s}{%s}{%s} %s} etex scaled %st shifted (%sx,%sy)",
1003             renderer->mp_font, renderer->mp_weight, renderer->mp_slant,
1004             text,
1005 	    g_ascii_formatd(height_buf, sizeof(height_buf), "%g", renderer->mp_font_height),
1006 	    mp_dtostr(px_buf, pos->x),
1007 	    mp_dtostr(py_buf, pos->y) );
1008 
1009     if (!color_equals(&renderer->color, &color_black))
1010         fprintf(renderer->file, "\n    withcolor (%s, %s, %s)",
1011                 g_ascii_formatd(red_buf, sizeof(red_buf), "%5.4f", (gdouble) renderer->color.red),
1012                 g_ascii_formatd(green_buf, sizeof(green_buf), "%5.4f", (gdouble) renderer->color.green),
1013                 g_ascii_formatd(blue_buf, sizeof(blue_buf), "%5.4f", (gdouble) renderer->color.blue) );
1014 
1015     fprintf(renderer->file,";\n");
1016 }
1017 
1018 static void
draw_text(DiaRenderer * self,Text * text)1019 draw_text(DiaRenderer *self,
1020 		  Text *text) {
1021   Point pos;
1022   int i;
1023   pos = text->position;
1024 
1025 
1026   set_font(self, text->font, text->height);
1027 
1028   for (i=0;i<text->numlines;i++) {
1029     TextLine *text_line = text->lines[i];
1030 
1031     draw_string(self,
1032 				text_line_get_string(text_line),
1033 				&pos,
1034 				text->alignment,
1035 				&text->color);
1036     pos.y += text->height;
1037   }
1038 }
1039 
1040 static void
draw_text_line(DiaRenderer * self,TextLine * text_line,Point * pos,Alignment alignment,Color * color)1041 draw_text_line(DiaRenderer *self, TextLine *text_line,
1042 		Point *pos, Alignment alignment, Color *color)
1043 {
1044     MetapostRenderer *renderer = METAPOST_RENDERER (self);
1045     gchar height_buf[DTOSTR_BUF_SIZE];
1046     gchar px_buf[DTOSTR_BUF_SIZE];
1047     gchar py_buf[DTOSTR_BUF_SIZE];
1048     gchar red_buf[DTOSTR_BUF_SIZE];
1049     gchar green_buf[DTOSTR_BUF_SIZE];
1050     gchar blue_buf[DTOSTR_BUF_SIZE];
1051 
1052     /* real width = text_line_get_width(text_line); */
1053 
1054     set_line_color(renderer,color);
1055 
1056     /* Ideally, we would be able to use the "infont" macro to print this label
1057      * in the proper font.  Unfortunately, though, metapost is in the habit of
1058      * converting spaces into visible spaces, which looks rather yucky.  So we
1059      * embed some TeX with \usefont commands instead. */
1060 	/* Scale text by multiplying text by variable t in metapost */
1061     fprintf(renderer->file,
1062             "draw btex {\\usefont{OT1}{%s}{%s}{%s} %s} etex scaled %st,(%sx,%sy)",
1063             renderer->mp_font, renderer->mp_weight, renderer->mp_slant,
1064             text_line_get_string(text_line),
1065 	    g_ascii_formatd(height_buf, sizeof(height_buf), "%g", renderer->mp_font_height),
1066 	    mp_dtostr(px_buf, pos->x - text_line_get_alignment_adjustment (text_line, alignment)),
1067 	    mp_dtostr(py_buf, pos->y) );
1068 
1069     if (!color_equals(&renderer->color, &color_black))
1070         fprintf(renderer->file, "\n    withcolor (%s, %s, %s)",
1071                 g_ascii_formatd(red_buf, sizeof(red_buf), "%5.4f", (gdouble) renderer->color.red),
1072                 g_ascii_formatd(green_buf, sizeof(green_buf), "%5.4f", (gdouble) renderer->color.green),
1073                 g_ascii_formatd(blue_buf, sizeof(blue_buf), "%5.4f", (gdouble) renderer->color.blue) );
1074 
1075     fprintf(renderer->file,";\n");
1076 }
1077 
1078 
1079 static void
draw_image(DiaRenderer * self,Point * point,real width,real height,DiaImage * image)1080 draw_image(DiaRenderer *self,
1081 	   Point *point,
1082 	   real width, real height,
1083 	   DiaImage *image)
1084 {
1085     /* images have a banding problem */
1086     int img_width, img_height, img_rowstride;
1087     int x, y;
1088     real xstep, ystep;
1089     guint8 *rgb_data;
1090     guint8 *mask_data;
1091     double ix, iy;
1092     gchar d1_buf[DTOSTR_BUF_SIZE];
1093     gchar d2_buf[DTOSTR_BUF_SIZE];
1094     gchar d3_buf[DTOSTR_BUF_SIZE];
1095 
1096     MetapostRenderer *renderer = METAPOST_RENDERER (self);
1097 
1098     fprintf(renderer->file, "  %% draw_image: %s\n", dia_image_filename(image));
1099 
1100 
1101     img_width = dia_image_width(image);
1102     img_rowstride = dia_image_rowstride(image);
1103     img_height = dia_image_height(image);
1104 
1105     xstep = width/img_width;
1106     ystep = height/img_height;
1107 
1108     rgb_data = dia_image_rgb_data(image);
1109     mask_data = dia_image_mask_data(image);
1110 
1111     fprintf(renderer->file, "  pickup pensquare scaled %sx scaled %s;\n",
1112             mp_dtostr(d1_buf, (gdouble) xstep),
1113             mp_dtostr(d2_buf, (gdouble) (ystep/xstep)) );
1114 
1115 
1116     if (mask_data) {
1117         fprintf(renderer->file, "  %% have mask\n");
1118         for (y = 0, iy = point->y; y < img_height; y++, iy += ystep) {
1119             for (x = 0, ix = point->x; x < img_width; x++, ix += xstep) {
1120                 int i = y*img_rowstride+x*3;
1121                 int m = y*img_width+x;
1122 		fprintf(renderer->file, "  draw (%sx, %sy) ",
1123 			mp_dtostr(d1_buf, ix), mp_dtostr(d2_buf, iy) );
1124                 fprintf(renderer->file, "withcolor (%s, %s, %s);\n",
1125                         g_ascii_formatd(d1_buf, sizeof(d1_buf), "%5.4f",
1126 					(255-(mask_data[m]*(255-rgb_data[i])/255)/255.0)),
1127                         g_ascii_formatd(d2_buf, sizeof(d2_buf), "%5.4f",
1128 					(255-(mask_data[m]*(255-rgb_data[i+1])/255))/255.0),
1129                         g_ascii_formatd(d3_buf, sizeof(d3_buf), "%5.4f",
1130 					(255-(mask_data[m]*(255-rgb_data[i+2])/255))/255.0) );
1131             }
1132             fprintf(renderer->file, "\n");
1133         }
1134     } else {
1135         for (y = 0, iy = point->y; y < img_height; y++, iy += ystep) {
1136             for (x = 0, ix = point->x; x < img_width; x++, ix += xstep) {
1137                 int i = y*img_rowstride+x*3;
1138 		fprintf(renderer->file, "  draw (%sx, %sy) ",
1139 			mp_dtostr(d1_buf, ix), mp_dtostr(d2_buf, iy) );
1140                 fprintf(renderer->file, "withcolor (%s, %s, %s);\n",
1141                         g_ascii_formatd(d1_buf, sizeof(d1_buf), "%5.4f",
1142 					(gdouble) (rgb_data[i])/255.0),
1143                         g_ascii_formatd(d2_buf, sizeof(d2_buf), "%5.4f",
1144 					(gdouble) (rgb_data[i+1])/255.0),
1145                         g_ascii_formatd(d3_buf, sizeof(d3_buf), "%5.4f",
1146 					(gdouble) (rgb_data[i+2])/255.0) );
1147             }
1148             fprintf(renderer->file, "\n");
1149         }
1150     }
1151 
1152     g_free(mask_data);
1153     g_free(rgb_data);
1154 }
1155 
1156 /* --- export filter interface --- */
1157 static void
export_metapost(DiagramData * data,const gchar * filename,const gchar * diafilename,void * user_data)1158 export_metapost(DiagramData *data, const gchar *filename,
1159                 const gchar *diafilename, void* user_data)
1160 {
1161     MetapostRenderer *renderer;
1162     FILE *file;
1163     time_t time_now;
1164     double scale;
1165     Rectangle *extent;
1166     const char *name;
1167     gchar d1_buf[DTOSTR_BUF_SIZE];
1168     gchar d2_buf[DTOSTR_BUF_SIZE];
1169     gchar d3_buf[DTOSTR_BUF_SIZE];
1170     gchar d4_buf[DTOSTR_BUF_SIZE];
1171 
1172     Color initial_color;
1173 
1174     file = g_fopen(filename, "wb");
1175 
1176     if (file==NULL) {
1177 	message_error(_("Can't open output file %s: %s\n"),
1178 		      dia_message_filename(filename), strerror(errno));
1179         return;
1180     }
1181 
1182     renderer = g_object_new(METAPOST_TYPE_RENDERER, NULL);
1183 
1184     renderer->file = file;
1185 
1186     renderer->dash_length = 1.0;
1187     renderer->dot_length = 0.2;
1188     renderer->saved_line_style = LINESTYLE_SOLID;
1189 
1190     time_now  = time(NULL);
1191     extent = &data->extents;
1192 
1193     scale = POINTS_in_INCH * data->paper.scaling;
1194 
1195     name = g_get_user_name();
1196 
1197     fprintf(file,
1198 	    "%% Metapost TeX macro\n"
1199 	    "%% Title: %s\n"
1200 	    "%% Creator: Dia v%s\n"
1201 	    "%% CreationDate: %s"
1202 	    "%% For: %s\n"
1203 	    "\n\n"
1204 	    "beginfig(1);\n",
1205 	    diafilename,
1206 	    VERSION,
1207 	    ctime(&time_now),
1208 	    name);
1209 
1210     /* LaTeX header so that our font stuff works properly. */
1211     fprintf(renderer->file,
1212              "verbatimtex\n"
1213              "%%&latex\n"
1214              "\\documentclass{minimal}\n"
1215              "\\begin{document}\n"
1216              "etex\n");
1217 
1218 	/* Define Macros for Text Positioning */
1219     fprintf(renderer->file,
1220 			"%% Define macro for horizontal centering.\n"
1221 			"vardef hcentered primary P =\n"
1222 			"  P shifted -(xpart center P, 0)\n"
1223 			"enddef;\n");
1224 
1225     fprintf(renderer->file,
1226 			"%% Define macro for right justification.\n"
1227 			"vardef rjust primary P =\n"
1228 			"  P shifted -(xpart (lrcorner P - llcorner P), 0)\n"
1229 			"enddef;\n");
1230 
1231 
1232     fprintf(renderer->file,"  %% picture(%s,%s)(%s,%s)\n",
1233 	    mp_dtostr(d1_buf, extent->left * data->paper.scaling),
1234 	    mp_dtostr(d2_buf, -extent->bottom * data->paper.scaling),
1235 	    mp_dtostr(d3_buf, extent->right * data->paper.scaling),
1236 	    mp_dtostr(d4_buf, -extent->top * data->paper.scaling) );
1237     fprintf(renderer->file,"  x = %scm; y = %scm;\n\n",
1238 	    mp_dtostr(d1_buf, data->paper.scaling),
1239 	    mp_dtostr(d2_buf, -data->paper.scaling) );
1240 
1241 	/* Create a variable for Text Scaling  't' */
1242     fprintf(renderer->file,"  t = %s;\n\n",
1243 	    mp_dtostr(d1_buf, data->paper.scaling));
1244 
1245     initial_color.red=0.;
1246     initial_color.green=0.;
1247     initial_color.blue=0.;
1248     set_line_color(renderer,&initial_color);
1249 
1250     initial_color.red=1.;
1251     initial_color.green=1.;
1252     initial_color.blue=1.;
1253     set_fill_color(renderer,&initial_color);
1254 
1255     data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL);
1256 
1257     g_object_unref(renderer);
1258 }
1259 
1260 static const gchar *extensions[] = { "mp", NULL };
1261 DiaExportFilter metapost_export_filter = {
1262     N_("TeX Metapost macros"),
1263     extensions,
1264     export_metapost
1265 };
1266