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