1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
3 *
4 * hpgl.c -- HPGL export plugin for dia
5 * Copyright (C) 2000, Hans Breuer, <Hans@Breuer.Org>
6 * based on dummy.c
7 * based on CGM plug-in Copyright (C) 1999 James Henstridge.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24 /*
25 * ToDo:
26 * - move draw_ellipse_by_arc into libdia to make it available for other
27 * interested renderers ?
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <math.h>
37 #include <errno.h>
38
39 #include <glib.h>
40 #include <glib/gstdio.h>
41
42 #include "intl.h"
43 #include "message.h"
44 #include "geometry.h"
45 #include "diarenderer.h"
46 #include "filter.h"
47 #include "plug-ins.h"
48
49 /* #DEFINE DEBUG_HPGL */
50
51 /* format specific */
52 #define HPGL_MAX_PENS 8
53
54 #define PEN_HAS_COLOR (1 << 0)
55 #define PEN_HAS_WIDTH (1 << 1)
56
57 /* GObject boiler plate */
58 #define HPGL_TYPE_RENDERER (hpgl_renderer_get_type ())
59 #define HPGL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HPGL_TYPE_RENDERER, HpglRenderer))
60 #define HPGL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HPGL_TYPE_RENDERER, HpglRendererClass))
61 #define HPGL_IS_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HPGL_TYPE_RENDERER))
62 #define HPGL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HPGL_TYPE_RENDERER, HpglRendererClass))
63
64 GType hpgl_renderer_get_type (void) G_GNUC_CONST;
65
66 typedef struct _HpglRenderer HpglRenderer;
67 typedef struct _HpglRendererClass HpglRendererClass;
68
69 struct _HpglRenderer
70 {
71 DiaRenderer parent_instance;
72
73 FILE *file;
74
75 /*
76 * The number of pens is limited. This is used to select one.
77 */
78 struct {
79 Color color;
80 float width;
81 int has_it;
82 } pen[HPGL_MAX_PENS];
83 int last_pen;
84 real dash_length;
85 real font_height;
86
87 Point size; /* extent size */
88 real scale;
89 real offset; /* in dia units */
90 };
91
92 struct _HpglRendererClass
93 {
94 DiaRendererClass parent_class;
95 };
96
97 #ifdef DEBUG_HPGL
98 # define DIAG_NOTE(action) action
99 #else
100 # define DIAG_NOTE(action)
101 #endif
102
103 /* hpgl helpers */
104 static void
hpgl_select_pen(HpglRenderer * renderer,Color * color,real width)105 hpgl_select_pen(HpglRenderer* renderer, Color* color, real width)
106 {
107 int nPen = 0;
108 int i;
109 /* look if this pen is defined already */
110 if (0.0 != width) {
111 /* either width ... */
112 for (i = 0; i < HPGL_MAX_PENS; i++) {
113 if (!(renderer->pen[i].has_it & PEN_HAS_WIDTH)) {
114 nPen = i;
115 break;
116 }
117 if (width == renderer->pen[i].width) {
118 nPen = i;
119 break;
120 }
121 }
122 }
123
124 if (NULL != color) {
125 for (i = nPen; i < HPGL_MAX_PENS; i++) {
126 if (!(renderer->pen[i].has_it & PEN_HAS_COLOR)) {
127 nPen = i;
128 break;
129 }
130 if ( (color->red == renderer->pen[i].color.red)
131 && (color->green == renderer->pen[i].color.green)
132 && (color->blue == renderer->pen[i].color.blue)) {
133 nPen = i;
134 break;
135 }
136 }
137 }
138 /* "create" new pen ... */
139 if ((nPen < HPGL_MAX_PENS) && (-1 < nPen)) {
140 if (0.0 != width) {
141 renderer->pen[nPen].width = width;
142 renderer->pen[nPen].has_it |= PEN_HAS_WIDTH;
143 }
144 if (NULL != color) {
145 renderer->pen[nPen].color = *color;
146 renderer->pen[nPen].has_it |= PEN_HAS_COLOR;
147 }
148 }
149 /* ... or use best fitting one */
150 else if (-1 == nPen) {
151 nPen = 0; /* TODO: */
152 }
153
154 if (renderer->last_pen != nPen)
155 fprintf(renderer->file, "SP%d;\n", nPen+1);
156 renderer->last_pen = nPen;
157 }
158
159 static int
hpgl_scale(HpglRenderer * renderer,real val)160 hpgl_scale(HpglRenderer *renderer, real val)
161 {
162 return (int)((val + renderer->offset) * renderer->scale);
163 }
164
165 /* render functions */
166 static void
begin_render(DiaRenderer * object)167 begin_render(DiaRenderer *object)
168 {
169 HpglRenderer *renderer = HPGL_RENDERER (object);
170 int i;
171
172 DIAG_NOTE(g_message("begin_render"));
173
174 /* initialize pens */
175 for (i = 0; i < HPGL_MAX_PENS; i++) {
176 renderer->pen[i].color = color_black;
177 renderer->pen[i].width = 0.0;
178 renderer->pen[i].has_it = 0;
179 }
180 renderer->last_pen = -1;
181 renderer->dash_length = 0.0;
182 }
183
184 static void
end_render(DiaRenderer * object)185 end_render(DiaRenderer *object)
186 {
187 HpglRenderer *renderer = HPGL_RENDERER (object);
188
189 DIAG_NOTE(g_message("end_render"));
190 fclose(renderer->file);
191 }
192
193 static void
set_linewidth(DiaRenderer * object,real linewidth)194 set_linewidth(DiaRenderer *object, real linewidth)
195 {
196 HpglRenderer *renderer = HPGL_RENDERER (object);
197
198 DIAG_NOTE(g_message("set_linewidth %f", linewidth));
199
200 hpgl_select_pen(renderer, NULL, linewidth);
201 }
202
203 static void
set_linecaps(DiaRenderer * object,LineCaps mode)204 set_linecaps(DiaRenderer *object, LineCaps mode)
205 {
206 DIAG_NOTE(g_message("set_linecaps %d", mode));
207
208 switch(mode) {
209 case LINECAPS_BUTT:
210 break;
211 case LINECAPS_ROUND:
212 break;
213 case LINECAPS_PROJECTING:
214 break;
215 default:
216 message_error("HpglRenderer: Unsupported fill mode specified!\n");
217 }
218 }
219
220 static void
set_linejoin(DiaRenderer * object,LineJoin mode)221 set_linejoin(DiaRenderer *object, LineJoin mode)
222 {
223 DIAG_NOTE(g_message("set_join %d", mode));
224
225 switch(mode) {
226 case LINEJOIN_MITER:
227 break;
228 case LINEJOIN_ROUND:
229 break;
230 case LINEJOIN_BEVEL:
231 break;
232 default:
233 message_error("HpglRenderer : Unsupported fill mode specified!\n");
234 }
235 }
236
237 static void
set_linestyle(DiaRenderer * object,LineStyle mode)238 set_linestyle(DiaRenderer *object, LineStyle mode)
239 {
240 HpglRenderer *renderer = HPGL_RENDERER (object);
241
242 DIAG_NOTE(g_message("set_linestyle %d", mode));
243
244 /* line type */
245 switch (mode) {
246 case LINESTYLE_SOLID:
247 fprintf(renderer->file, "LT;\n");
248 break;
249 case LINESTYLE_DASHED:
250 if (renderer->dash_length > 0.5) /* ??? unit of dash_lenght ? */
251 fprintf(renderer->file, "LT2;\n"); /* short */
252 else
253 fprintf(renderer->file, "LT3;\n"); /* long */
254 break;
255 case LINESTYLE_DASH_DOT:
256 fprintf(renderer->file, "LT4;\n");
257 break;
258 case LINESTYLE_DASH_DOT_DOT:
259 fprintf(renderer->file, "LT5;\n"); /* ??? Mittellinie? */
260 break;
261 case LINESTYLE_DOTTED:
262 fprintf(renderer->file, "LT1;\n");
263 break;
264 default:
265 message_error("HpglRenderer : Unsupported fill mode specified!\n");
266 }
267 }
268
269 static void
set_dashlength(DiaRenderer * object,real length)270 set_dashlength(DiaRenderer *object, real length)
271 {
272 HpglRenderer *renderer = HPGL_RENDERER (object);
273
274 DIAG_NOTE(diag_note("set_dashlength %f", length));
275
276 /* dot = 20% of len */
277 renderer->dash_length = length;
278 }
279
280 static void
set_fillstyle(DiaRenderer * object,FillStyle mode)281 set_fillstyle(DiaRenderer *object, FillStyle mode)
282 {
283 DIAG_NOTE(g_message("set_fillstyle %d", mode));
284
285 switch(mode) {
286 case FILLSTYLE_SOLID:
287 break;
288 default:
289 message_error("HpglRenderer : Unsupported fill mode specified!\n");
290 }
291 }
292
293 static void
set_font(DiaRenderer * object,DiaFont * font,real height)294 set_font(DiaRenderer *object, DiaFont *font, real height)
295 {
296 HpglRenderer *renderer = HPGL_RENDERER (object);
297
298 DIAG_NOTE(g_message("set_font %f", height));
299 renderer->font_height = height;
300 }
301
302 /* Need to translate coord system:
303 *
304 * Dia x,y -> Hpgl x,-y
305 *
306 * doing it before scaling.
307 */
308 static void
draw_line(DiaRenderer * object,Point * start,Point * end,Color * line_colour)309 draw_line(DiaRenderer *object,
310 Point *start, Point *end,
311 Color *line_colour)
312 {
313 HpglRenderer *renderer = HPGL_RENDERER (object);
314
315 DIAG_NOTE(g_message("draw_line %f,%f -> %f, %f",
316 start->x, start->y, end->x, end->y));
317 hpgl_select_pen(renderer, line_colour, 0.0);
318 fprintf (renderer->file,
319 "PU%d,%d;PD%d,%d;\n",
320 hpgl_scale(renderer, start->x), hpgl_scale(renderer, -start->y),
321 hpgl_scale(renderer, end->x), hpgl_scale(renderer, -end->y));
322 }
323
324 static void
draw_polyline(DiaRenderer * object,Point * points,int num_points,Color * line_colour)325 draw_polyline(DiaRenderer *object,
326 Point *points, int num_points,
327 Color *line_colour)
328 {
329 HpglRenderer *renderer = HPGL_RENDERER (object);
330 int i;
331
332 DIAG_NOTE(g_message("draw_polyline n:%d %f,%f ...",
333 num_points, points->x, points->y));
334
335 g_return_if_fail(1 < num_points);
336
337 hpgl_select_pen(renderer, line_colour, 0.0);
338 fprintf (renderer->file, "PU%d,%d;PD;PA",
339 hpgl_scale(renderer, points[0].x),
340 hpgl_scale(renderer, -points[0].y));
341 /* absolute movement */
342 for (i = 1; i < num_points-1; i++)
343 fprintf(renderer->file, "%d,%d,",
344 hpgl_scale(renderer, points[i].x),
345 hpgl_scale(renderer, -points[i].y));
346 i = num_points - 1;
347 fprintf(renderer->file, "%d,%d;\n",
348 hpgl_scale(renderer, points[i].x),
349 hpgl_scale(renderer, -points[i].y));
350 }
351
352 static void
draw_polygon(DiaRenderer * object,Point * points,int num_points,Color * line_colour)353 draw_polygon(DiaRenderer *object,
354 Point *points, int num_points,
355 Color *line_colour)
356 {
357 DIAG_NOTE(g_message("draw_polygon n:%d %f,%f ...",
358 num_points, points->x, points->y));
359 draw_polyline(object,points,num_points,line_colour);
360 /* last to first */
361 draw_line(object, &points[num_points-1], &points[0], line_colour);
362 }
363
364 static void
fill_polygon(DiaRenderer * object,Point * points,int num_points,Color * colour)365 fill_polygon(DiaRenderer *object,
366 Point *points, int num_points,
367 Color *colour)
368 {
369 DIAG_NOTE(g_message("fill_polygon n:%d %f,%f ...",
370 num_points, points->x, points->y));
371 draw_polyline(object,points,num_points,colour);
372 }
373
374 static void
draw_rect(DiaRenderer * object,Point * ul_corner,Point * lr_corner,Color * colour)375 draw_rect(DiaRenderer *object,
376 Point *ul_corner, Point *lr_corner,
377 Color *colour)
378 {
379 HpglRenderer *renderer = HPGL_RENDERER (object);
380
381 DIAG_NOTE(g_message("draw_rect %f,%f -> %f,%f",
382 ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y));
383 hpgl_select_pen(renderer, colour, 0.0);
384 fprintf (renderer->file, "PU%d,%d;PD;EA%d,%d;\n",
385 hpgl_scale(renderer, ul_corner->x),
386 hpgl_scale(renderer, -ul_corner->y),
387 hpgl_scale(renderer, lr_corner->x),
388 hpgl_scale(renderer, -lr_corner->y));
389 }
390
391 static void
fill_rect(DiaRenderer * object,Point * ul_corner,Point * lr_corner,Color * colour)392 fill_rect(DiaRenderer *object,
393 Point *ul_corner, Point *lr_corner,
394 Color *colour)
395 {
396 DIAG_NOTE(g_message("fill_rect %f,%f -> %f,%f",
397 ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y));
398 #if 0
399 HpglRenderer *renderer = HPGL_RENDERER (object);
400
401 hpgl_select_pen(renderer, colour, 0.0);
402 fprintf (renderer->file, "PU%d,%d;PD;RA%d,%d;\n",
403 hpgl_scale(renderer, ul_corner->x),
404 hpgl_scale(renderer, -ul_corner->y),
405 hpgl_scale(renderer, lr_corner->x),
406 hpgl_scale(renderer, -lr_corner->y));
407 #else
408 /* the fill modes aren't really compatible ... */
409 draw_rect(object, ul_corner, lr_corner, colour);
410 #endif
411 }
412
413 static void
draw_arc(DiaRenderer * object,Point * center,real width,real height,real angle1,real angle2,Color * colour)414 draw_arc(DiaRenderer *object,
415 Point *center,
416 real width, real height,
417 real angle1, real angle2,
418 Color *colour)
419 {
420 HpglRenderer *renderer = HPGL_RENDERER (object);
421 Point start;
422
423 DIAG_NOTE(g_message("draw_arc %fx%f <%f,<%f",
424 width, height, angle1, angle2));
425 hpgl_select_pen(renderer, colour, 0.0);
426
427 /* move to start point */
428 start.x = center->x + (width / 2.0) * cos((M_PI / 180.0) * angle1);
429 start.y = - center->y + (height / 2.0) * sin((M_PI / 180.0) * angle1);
430 fprintf (renderer->file, "PU%d,%d;PD;",
431 hpgl_scale(renderer, start.x),
432 hpgl_scale(renderer, start.y));
433 /* Arc Absolute - around center */
434 fprintf (renderer->file, "AA%d,%d,%d;",
435 hpgl_scale(renderer, center->x),
436 hpgl_scale(renderer, - center->y),
437 (int)floor(360.0 - angle1 + angle2));
438 }
439
440 static void
fill_arc(DiaRenderer * object,Point * center,real width,real height,real angle1,real angle2,Color * colour)441 fill_arc(DiaRenderer *object,
442 Point *center,
443 real width, real height,
444 real angle1, real angle2,
445 Color *colour)
446 {
447 HpglRenderer *renderer = HPGL_RENDERER (object);
448
449 DIAG_NOTE(g_message("fill_arc %fx%f <%f,<%f",
450 width, height, angle1, angle2));
451 g_assert (width == height);
452
453 /* move to center */
454 fprintf (renderer->file, "PU%d,%d;PD;",
455 hpgl_scale(renderer, center->x),
456 hpgl_scale(renderer, -center->y));
457 /* Edge Wedge */
458 fprintf (renderer->file, "EW%d,%d,%d;",
459 hpgl_scale(renderer, width),
460 (int)angle1, (int)(angle2-angle1));
461 }
462
463 /* may go into lib/diarenderer.c if another renderer would be interested */
464 /* Draw an ellipse approximation consisting out of
465 * four arcs.
466 */
467 static void
draw_ellipse_by_arc(DiaRenderer * renderer,Point * center,real width,real height,Color * colour)468 draw_ellipse_by_arc (DiaRenderer *renderer,
469 Point *center,
470 real width, real height,
471 Color *colour)
472 {
473 real a, b, e, d, alpha, c, x, y;
474 real g, gamma, r;
475 Point pt;
476 real angle;
477
478 a = width / 2;
479 b = height / 2;
480 e = sqrt(a*a - b*b);
481
482 alpha = 0.25*M_PI - dia_asin((e/a) * sin(0.75*M_PI));
483 d = 2*a*sin(alpha);
484
485 c = (sin(0.25*M_PI) * (2*e + d)) / sin(0.75*M_PI - alpha);
486
487 y = c * sin (alpha);
488 x = c * cos (alpha) - e;
489
490 /* draw arcs */
491 g = sqrt((a-x)*(a-x) + y*y);
492 gamma = dia_acos((a-x)/g);
493 r = (sin(gamma) * g) / sin(M_PI-2*gamma);
494
495 pt.y = center->y;
496 angle = (180 * (M_PI-2*gamma)) / M_PI;
497 pt.x = center->x + a - r; /* right */
498 draw_arc(renderer, &pt, 2*r, 2*r, 360-angle, angle, colour);
499 pt.x = center->x - a + r; /* left */
500 draw_arc(renderer, &pt, 2*r, 2*r, 180-angle, 180+angle, colour);
501
502
503 g = sqrt((b-y)*(b-y) + x*x);
504 gamma = dia_acos((b-y)/g);
505 r = (sin(gamma) * g) / sin(M_PI-2*gamma);
506
507 pt.x = center->x;
508 angle = (180 * (M_PI-2*gamma)) / M_PI;
509 pt.y = center->y - b + r; /* top */
510 draw_arc(renderer, &pt, 2*r, 2*r, 90-angle, 90+angle, colour);
511 pt.y = center->y + b - r; /* bottom */
512 draw_arc(renderer, &pt, 2*r, 2*r, 270-angle, 270+angle, colour);
513 }
514
515 static void
draw_ellipse(DiaRenderer * object,Point * center,real width,real height,Color * colour)516 draw_ellipse(DiaRenderer *object,
517 Point *center,
518 real width, real height,
519 Color *colour)
520 {
521 HpglRenderer *renderer = HPGL_RENDERER (object);
522
523 DIAG_NOTE(g_message("draw_ellipse %fx%f center @ %f,%f",
524 width, height, center->x, center->y));
525
526 if (width != height)
527 {
528 draw_ellipse_by_arc(object, center, width, height, colour);
529 }
530 else
531 {
532 hpgl_select_pen(renderer, colour, 0.0);
533
534 fprintf (renderer->file, "PU%d,%d;CI%d;\n",
535 hpgl_scale(renderer, center->x),
536 hpgl_scale(renderer, -center->y),
537 hpgl_scale(renderer, width / 2.0));
538 }
539 }
540
541 static void
fill_ellipse(DiaRenderer * object,Point * center,real width,real height,Color * colour)542 fill_ellipse(DiaRenderer *object,
543 Point *center,
544 real width, real height,
545 Color *colour)
546 {
547 DIAG_NOTE(g_message("fill_ellipse %fx%f center @ %f,%f",
548 width, height, center->x, center->y));
549 }
550
551 static void
draw_string(DiaRenderer * object,const char * text,Point * pos,Alignment alignment,Color * colour)552 draw_string(DiaRenderer *object,
553 const char *text,
554 Point *pos, Alignment alignment,
555 Color *colour)
556 {
557 HpglRenderer *renderer = HPGL_RENDERER (object);
558 real width, height;
559
560 DIAG_NOTE(g_message("draw_string %f,%f %s",
561 pos->x, pos->y, text));
562
563 /* set position */
564 fprintf(renderer->file, "PU%d,%d;",
565 hpgl_scale(renderer, pos->x), hpgl_scale(renderer, -pos->y));
566
567 switch (alignment) {
568 case ALIGN_LEFT:
569 fprintf (renderer->file, "LO1;\n");
570 break;
571 case ALIGN_CENTER:
572 fprintf (renderer->file, "LO4;\n");
573 break;
574 case ALIGN_RIGHT:
575 fprintf (renderer->file, "LO7;\n");
576 break;
577 }
578 hpgl_select_pen(renderer,colour,0.0);
579
580 #if 0
581 /*
582 * SR - Relative Character Size >0.0 ... 127.999
583 * set the capital letter box width and height as a percentage of
584 * P2X-P1X and P2Y-P1Y
585 */
586 height = (127.999 * renderer->font_height * renderer->scale) / renderer->size.y;
587 width = 0.75 * height; /* FIXME: */
588 fprintf(renderer->file, "SR%d.%03d,%d.%03d;",
589 (int)width, (int)((width * 1000) % 1000),
590 (int)height, (int)((height * 1000) % 1000));
591 #else
592 /*
593 * SI - character size absolute
594 * size needed in centimeters
595 */
596 width = renderer->font_height * renderer->scale * 0.75 * 0.0025;
597 height = renderer->font_height * renderer->scale * 0.0025;
598 fprintf(renderer->file, "SI%d.%03d,%d.%03d;",
599 (int)width, ((int)(width * 1000) % 1000),
600 (int)height, ((int)(height * 1000) % 1000));
601 #endif
602 fprintf(renderer->file, "DT\003;" /* Terminator */
603 "LB%s\003;\n", text);
604 }
605
606 static void
draw_image(DiaRenderer * object,Point * point,real width,real height,DiaImage * image)607 draw_image(DiaRenderer *object,
608 Point *point,
609 real width, real height,
610 DiaImage *image)
611 {
612 DIAG_NOTE(g_message("draw_image %fx%f @%f,%f",
613 width, height, point->x, point->y));
614 g_warning("HPGL: images unsupported!");
615 }
616
617 /* overwrite vtable */
618 static void hpgl_renderer_class_init (HpglRendererClass *klass);
619
620 static gpointer parent_class = NULL;
621
622 GType
hpgl_renderer_get_type(void)623 hpgl_renderer_get_type (void)
624 {
625 static GType object_type = 0;
626
627 if (!object_type)
628 {
629 static const GTypeInfo object_info =
630 {
631 sizeof (HpglRendererClass),
632 (GBaseInitFunc) NULL,
633 (GBaseFinalizeFunc) NULL,
634 (GClassInitFunc) hpgl_renderer_class_init,
635 NULL, /* class_finalize */
636 NULL, /* class_data */
637 sizeof (HpglRenderer),
638 0, /* n_preallocs */
639 NULL /* init */
640 };
641
642 object_type = g_type_register_static (DIA_TYPE_RENDERER,
643 "HpglRenderer",
644 &object_info, 0);
645 }
646
647 return object_type;
648 }
649
650 static void
hpgl_renderer_finalize(GObject * object)651 hpgl_renderer_finalize (GObject *object)
652 {
653 G_OBJECT_CLASS (parent_class)->finalize (object);
654 }
655
656 static void
hpgl_renderer_class_init(HpglRendererClass * klass)657 hpgl_renderer_class_init (HpglRendererClass *klass)
658 {
659 GObjectClass *object_class = G_OBJECT_CLASS (klass);
660 DiaRendererClass *renderer_class = DIA_RENDERER_CLASS (klass);
661
662 parent_class = g_type_class_peek_parent (klass);
663
664 object_class->finalize = hpgl_renderer_finalize;
665
666 /* renderer members */
667 renderer_class->begin_render = begin_render;
668 renderer_class->end_render = end_render;
669
670 renderer_class->set_linewidth = set_linewidth;
671 renderer_class->set_linecaps = set_linecaps;
672 renderer_class->set_linejoin = set_linejoin;
673 renderer_class->set_linestyle = set_linestyle;
674 renderer_class->set_dashlength = set_dashlength;
675 renderer_class->set_fillstyle = set_fillstyle;
676
677 renderer_class->set_font = set_font;
678
679 renderer_class->draw_line = draw_line;
680 renderer_class->fill_polygon = fill_polygon;
681 renderer_class->draw_rect = draw_rect;
682 renderer_class->fill_rect = fill_rect;
683 renderer_class->draw_arc = draw_arc;
684 renderer_class->fill_arc = fill_arc;
685 renderer_class->draw_ellipse = draw_ellipse;
686 renderer_class->fill_ellipse = fill_ellipse;
687
688 renderer_class->draw_string = draw_string;
689 renderer_class->draw_image = draw_image;
690
691 /* medium level functions */
692 renderer_class->draw_rect = draw_rect;
693 renderer_class->draw_polyline = draw_polyline;
694 renderer_class->draw_polygon = draw_polygon;
695 }
696
697 /* plug-in interface : export function */
698 static void
export_data(DiagramData * data,const gchar * filename,const gchar * diafilename,void * user_data)699 export_data(DiagramData *data, const gchar *filename,
700 const gchar *diafilename, void* user_data)
701 {
702 HpglRenderer *renderer;
703 FILE *file;
704 Rectangle *extent;
705 real width, height;
706
707 file = g_fopen(filename, "w"); /* "wb" for binary! */
708
709 if (file == NULL) {
710 message_error(_("Can't open output file %s: %s\n"),
711 dia_message_filename(filename), strerror(errno));
712 return;
713 }
714
715 renderer = g_object_new(HPGL_TYPE_RENDERER, NULL);
716
717 renderer->file = file;
718
719 extent = &data->extents;
720
721 /* use extents */
722 DIAG_NOTE(g_message("export_data extents %f,%f -> %f,%f",
723 extent->left, extent->top, extent->right, extent->bottom));
724
725 width = extent->right - extent->left;
726 height = extent->bottom - extent->top;
727 renderer->scale = 0.001;
728 if (width > height)
729 while (renderer->scale * width < 3276.7) renderer->scale *= 10.0;
730 else
731 while (renderer->scale * height < 3276.7) renderer->scale *= 10.0;
732 renderer->offset = 0.0; /* just to have one */
733
734 renderer->size.x = width * renderer->scale;
735 renderer->size.y = height * renderer->scale;
736 #if 0
737 /* OR: set page size and scale */
738 fprintf(renderer->file, "PS0;SC%d,%d,%d,%d;\n",
739 hpgl_scale(renderer, extent->left),
740 hpgl_scale(renderer, extent->right),
741 hpgl_scale(renderer, extent->bottom),
742 hpgl_scale(renderer, extent->top));
743 #endif
744 data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL);
745
746 g_object_unref(renderer);
747 }
748
749 static const gchar *extensions[] = { "plt", "hpgl", NULL };
750 static DiaExportFilter my_export_filter = {
751 N_("HP Graphics Language"),
752 extensions,
753 export_data
754 };
755
756
757 /* --- dia plug-in interface --- */
758 static gboolean
_plugin_can_unload(PluginInfo * info)759 _plugin_can_unload (PluginInfo *info)
760 {
761 return TRUE;
762 }
763
764 static void
_plugin_unload(PluginInfo * info)765 _plugin_unload (PluginInfo *info)
766 {
767 filter_unregister_export(&my_export_filter);
768 }
769
770 DIA_PLUGIN_CHECK_INIT
771
772 PluginInitResult
dia_plugin_init(PluginInfo * info)773 dia_plugin_init(PluginInfo *info)
774 {
775 if (!dia_plugin_info_init(info, "HPGL",
776 _("HP Graphics Language export filter"),
777 _plugin_can_unload,
778 _plugin_unload))
779 return DIA_PLUGIN_INIT_ERROR;
780
781 filter_register_export(&my_export_filter);
782
783 return DIA_PLUGIN_INIT_OK;
784 }
785