New cisco icons, and a fix in element.h
[dia.git] / app / diapsrenderer.c
blob3300efeb8a0625c36ac0ff774f7333e8fa47f7ee
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * diapsrenderer.c -- implements the base class for Postscript rendering
5 * It is mostly refactoring of render_eps.c (some stuff not from the
6 * latest version but from 1.24) before PS rendering became multi-pass
7 * and text rendering became (necessary) complicated.
8 * Refatoring: Copyright (C) 2002 Hans Breuer
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.
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.
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.
25 #include <config.h>
27 #include <string.h>
28 #include <time.h>
30 #include "diapsrenderer.h"
31 #include "message.h"
32 #include "dia_image.h"
33 #include "font.h"
35 #define DTOSTR_BUF_SIZE G_ASCII_DTOSTR_BUF_SIZE
36 #define psrenderer_dtostr(buf,d) \
37 g_ascii_formatd(buf, sizeof(buf), "%f", d)
39 /* Returns TRUE if this file is an encapsulated postscript file
40 * (including e.g. epsi).
42 static gboolean renderer_is_eps(DiaPsRenderer *renderer) {
43 return renderer->pstype == PSTYPE_EPS ||
44 renderer->pstype == PSTYPE_EPSI;
47 /** Returns TRUE if this file is an EPSI file */
48 static gboolean renderer_is_epsi(DiaPsRenderer *renderer) {
49 return renderer->pstype == PSTYPE_EPSI;
52 void
53 lazy_setcolor(DiaPsRenderer *renderer,
54 Color *color)
56 gchar r_buf[DTOSTR_BUF_SIZE];
57 gchar g_buf[DTOSTR_BUF_SIZE];
58 gchar b_buf[DTOSTR_BUF_SIZE];
60 if (!color_equals(color, &(renderer->lcolor))) {
61 renderer->lcolor = *color;
62 fprintf(renderer->file, "%s %s %s srgb\n",
63 psrenderer_dtostr(r_buf, (gdouble) color->red),
64 psrenderer_dtostr(g_buf, (gdouble) color->green),
65 psrenderer_dtostr(b_buf, (gdouble) color->blue) );
69 static void
70 begin_render(DiaRenderer *self)
72 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
73 time_t time_now;
75 g_assert (renderer->file != NULL);
77 time_now = time(NULL);
79 if (renderer_is_eps(renderer))
80 fprintf(renderer->file,
81 "%%!PS-Adobe-2.0 EPSF-2.0\n");
82 else
83 fprintf(renderer->file,
84 "%%!PS-Adobe-2.0\n");
85 fprintf(renderer->file,
86 "%%%%Title: %s\n"
87 "%%%%Creator: Dia v%s\n"
88 "%%%%CreationDate: %s"
89 "%%%%For: %s\n"
90 "%%%%Orientation: %s\n",
91 renderer->title ? renderer->title : "(NULL)" ,
92 VERSION,
93 ctime(&time_now),
94 g_get_user_name(),
95 renderer->is_portrait ? "Portrait" : "Landscape");
97 if (renderer_is_epsi(renderer)) {
98 g_assert(!"Preview image not implmented");
99 /* but it *may* belong here ... */
101 if (renderer_is_eps(renderer))
102 fprintf(renderer->file,
103 "%%%%Magnification: 1.0000\n"
104 "%%%%BoundingBox: 0 0 %d %d\n",
105 (int) ceil( (renderer->extent.right - renderer->extent.left)
106 * renderer->scale),
107 (int) ceil( (renderer->extent.bottom - renderer->extent.top)
108 * renderer->scale) );
110 else
111 fprintf(renderer->file,
112 "%%%%DocumentPaperSizes: %s\n",
113 renderer->paper ? renderer->paper : "(NULL)");
115 fprintf(renderer->file,
116 "%%%%BeginSetup\n");
117 fprintf(renderer->file,
118 "%%%%EndSetup\n"
119 "%%%%EndComments\n");
121 DIA_PS_RENDERER_GET_CLASS(self)->begin_prolog(renderer);
122 /* get our font definitions */
123 DIA_PS_RENDERER_GET_CLASS(self)->dump_fonts(renderer);
124 /* done it */
125 DIA_PS_RENDERER_GET_CLASS(self)->end_prolog(renderer);
128 static void
129 end_render(DiaRenderer *self)
131 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
133 if (renderer_is_eps(renderer))
134 fprintf(renderer->file, "showpage\n");
137 static void
138 set_linewidth(DiaRenderer *self, real linewidth)
139 { /* 0 == hairline **/
140 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
141 gchar lw_buf[DTOSTR_BUF_SIZE];
143 /* Adobe's advice: Set to very small but fixed size, to avoid changes
144 * due to different resolution output. */
145 /* .01 cm becomes <5 dots on 1200 DPI */
146 if (linewidth == 0.0) linewidth=.01;
147 fprintf(renderer->file, "%s slw\n",
148 psrenderer_dtostr(lw_buf, (gdouble) linewidth) );
151 static void
152 set_linecaps(DiaRenderer *self, LineCaps mode)
154 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
155 int ps_mode;
157 switch(mode) {
158 case LINECAPS_BUTT:
159 ps_mode = 0;
160 break;
161 case LINECAPS_ROUND:
162 ps_mode = 1;
163 break;
164 case LINECAPS_PROJECTING:
165 ps_mode = 2;
166 break;
167 default:
168 ps_mode = 0;
171 fprintf(renderer->file, "%d slc\n", ps_mode);
174 static void
175 set_linejoin(DiaRenderer *self, LineJoin mode)
177 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
178 int ps_mode;
180 switch(mode) {
181 case LINEJOIN_MITER:
182 ps_mode = 0;
183 break;
184 case LINEJOIN_ROUND:
185 ps_mode = 1;
186 break;
187 case LINEJOIN_BEVEL:
188 ps_mode = 2;
189 break;
190 default:
191 ps_mode = 0;
194 fprintf(renderer->file, "%d slj\n", ps_mode);
197 static void
198 set_linestyle(DiaRenderer *self, LineStyle mode)
200 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
201 real hole_width;
202 gchar dashl_buf[DTOSTR_BUF_SIZE];
203 gchar dotl_buf[DTOSTR_BUF_SIZE];
204 gchar holew_buf[DTOSTR_BUF_SIZE];
206 renderer->saved_line_style = mode;
208 switch(mode) {
209 case LINESTYLE_SOLID:
210 fprintf(renderer->file, "[] 0 sd\n");
211 break;
212 case LINESTYLE_DASHED:
213 fprintf(renderer->file, "[%s] 0 sd\n",
214 psrenderer_dtostr(dashl_buf, renderer->dash_length) );
215 break;
216 case LINESTYLE_DASH_DOT:
217 hole_width = (renderer->dash_length - renderer->dot_length) / 2.0;
218 psrenderer_dtostr(holew_buf, hole_width);
219 psrenderer_dtostr(dashl_buf, renderer->dash_length);
220 psrenderer_dtostr(dotl_buf, renderer->dot_length);
221 fprintf(renderer->file, "[%s %s %s %s] 0 sd\n",
222 dashl_buf,
223 holew_buf,
224 dotl_buf,
225 holew_buf );
226 break;
227 case LINESTYLE_DASH_DOT_DOT:
228 hole_width = (renderer->dash_length - 2.0*renderer->dot_length) / 3.0;
229 psrenderer_dtostr(holew_buf, hole_width);
230 psrenderer_dtostr(dashl_buf, renderer->dash_length);
231 psrenderer_dtostr(dotl_buf, renderer->dot_length);
232 fprintf(renderer->file, "[%s %s %s %s %s %s] 0 sd\n",
233 dashl_buf,
234 holew_buf,
235 dotl_buf,
236 holew_buf,
237 dotl_buf,
238 holew_buf );
239 break;
240 case LINESTYLE_DOTTED:
241 fprintf(renderer->file, "[%s] 0 sd\n",
242 psrenderer_dtostr(dotl_buf, renderer->dot_length) );
243 break;
247 static void
248 set_dashlength(DiaRenderer *self, real length)
249 { /* dot = 20% of len */
250 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
252 if (length<0.001)
253 length = 0.001;
255 renderer->dash_length = length;
256 renderer->dot_length = length*0.2;
258 set_linestyle(self, renderer->saved_line_style);
261 static void
262 set_fillstyle(DiaRenderer *self, FillStyle mode)
264 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
266 switch(mode) {
267 case FILLSTYLE_SOLID:
268 break;
269 default:
270 message_error("%s : Unsupported fill mode specified!\n",
271 G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (renderer)));
275 static void
276 set_font(DiaRenderer *self, DiaFont *font, real height)
278 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
279 gchar h_buf[DTOSTR_BUF_SIZE];
281 fprintf(renderer->file, "/%s-latin1 ff %s scf sf\n",
282 dia_font_get_psfontname(font),
283 psrenderer_dtostr(h_buf, (gdouble) height*0.7) );
286 static void
287 draw_line(DiaRenderer *self,
288 Point *start, Point *end,
289 Color *line_color)
291 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
292 gchar sx_buf[DTOSTR_BUF_SIZE];
293 gchar sy_buf[DTOSTR_BUF_SIZE];
294 gchar ex_buf[DTOSTR_BUF_SIZE];
295 gchar ey_buf[DTOSTR_BUF_SIZE];
297 lazy_setcolor(renderer,line_color);
299 fprintf(renderer->file, "n %s %s m %s %s l s\n",
300 psrenderer_dtostr(sx_buf, start->x),
301 psrenderer_dtostr(sy_buf, start->y),
302 psrenderer_dtostr(ex_buf, end->x),
303 psrenderer_dtostr(ey_buf, end->y) );
306 static void
307 draw_polyline(DiaRenderer *self,
308 Point *points, int num_points,
309 Color *line_color)
311 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
312 int i;
313 gchar px_buf[DTOSTR_BUF_SIZE];
314 gchar py_buf[DTOSTR_BUF_SIZE];
316 lazy_setcolor(renderer,line_color);
318 fprintf(renderer->file, "n %s %s m ",
319 psrenderer_dtostr(px_buf, points[0].x),
320 psrenderer_dtostr(py_buf, points[0].y) );
322 for (i=1;i<num_points;i++) {
323 fprintf(renderer->file, "%s %s l ",
324 psrenderer_dtostr(px_buf, points[i].x),
325 psrenderer_dtostr(py_buf, points[i].y) );
328 fprintf(renderer->file, "s\n");
331 static void
332 psrenderer_polygon(DiaPsRenderer *renderer,
333 Point *points,
334 gint num_points,
335 Color *line_color,
336 gboolean filled)
338 gint i;
339 gchar px_buf[DTOSTR_BUF_SIZE];
340 gchar py_buf[DTOSTR_BUF_SIZE];
342 lazy_setcolor(renderer, line_color);
344 fprintf(renderer->file, "n %s %s m ",
345 psrenderer_dtostr(px_buf, points[0].x),
346 psrenderer_dtostr(py_buf, points[0].y) );
349 for (i=1;i<num_points;i++) {
350 fprintf(renderer->file, "%s %s l ",
351 psrenderer_dtostr(px_buf, points[i].x),
352 psrenderer_dtostr(py_buf, points[i].y) );
354 if (filled)
355 fprintf(renderer->file, "ef\n");
356 else
357 fprintf(renderer->file, "cp s\n");
360 static void
361 draw_polygon(DiaRenderer *self,
362 Point *points, int num_points,
363 Color *line_color)
365 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
366 psrenderer_polygon(renderer, points, num_points, line_color, FALSE);
369 static void
370 fill_polygon(DiaRenderer *self,
371 Point *points, int num_points,
372 Color *fill_color)
374 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
375 psrenderer_polygon(renderer, points, num_points, fill_color, TRUE);
378 static void
379 psrenderer_rect(DiaPsRenderer *renderer,
380 Point *ul_corner,
381 Point *lr_corner,
382 Color *color,
383 gboolean filled)
385 gchar ulx_buf[DTOSTR_BUF_SIZE];
386 gchar uly_buf[DTOSTR_BUF_SIZE];
387 gchar lrx_buf[DTOSTR_BUF_SIZE];
388 gchar lry_buf[DTOSTR_BUF_SIZE];
390 lazy_setcolor(renderer,color);
392 psrenderer_dtostr(ulx_buf, (gdouble) ul_corner->x);
393 psrenderer_dtostr(uly_buf, (gdouble) ul_corner->y);
394 psrenderer_dtostr(lrx_buf, (gdouble) lr_corner->x);
395 psrenderer_dtostr(lry_buf, (gdouble) lr_corner->y);
397 fprintf(renderer->file, "n %s %s m %s %s l %s %s l %s %s l %s\n",
398 ulx_buf, uly_buf,
399 ulx_buf, lry_buf,
400 lrx_buf, lry_buf,
401 lrx_buf, uly_buf,
402 filled ? "f" : "cp s" );
405 static void
406 draw_rect(DiaRenderer *self,
407 Point *ul_corner, Point *lr_corner,
408 Color *color)
410 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
411 psrenderer_rect(renderer, ul_corner, lr_corner, color, FALSE);
414 static void
415 fill_rect(DiaRenderer *self,
416 Point *ul_corner, Point *lr_corner,
417 Color *color)
419 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
420 psrenderer_rect(renderer, ul_corner, lr_corner, color, TRUE);
423 static void
424 psrenderer_arc(DiaPsRenderer *renderer,
425 Point *center,
426 real width, real height,
427 real angle1, real angle2,
428 Color *color,
429 gboolean filled)
431 gchar cx_buf[DTOSTR_BUF_SIZE];
432 gchar cy_buf[DTOSTR_BUF_SIZE];
433 gchar a1_buf[DTOSTR_BUF_SIZE];
434 gchar a2_buf[DTOSTR_BUF_SIZE];
435 gchar w_buf[DTOSTR_BUF_SIZE];
436 gchar h_buf[DTOSTR_BUF_SIZE];
438 lazy_setcolor(renderer, color);
440 psrenderer_dtostr(cx_buf, (gdouble) center->x);
441 psrenderer_dtostr(cy_buf, (gdouble) center->y);
442 psrenderer_dtostr(a1_buf, (gdouble) 360.0 - angle1);
443 psrenderer_dtostr(a2_buf, (gdouble) 360.0 - angle2);
444 psrenderer_dtostr(w_buf, (gdouble) width / 2.0);
445 psrenderer_dtostr(h_buf, (gdouble) height / 2.0);
447 fprintf(renderer->file, "n ");
449 if (filled)
450 fprintf(renderer->file, "%s %s m ", cx_buf, cy_buf);
452 fprintf(renderer->file, "%s %s %s %s %s %s ellipse %s\n",
453 cx_buf, cy_buf, w_buf, h_buf, a2_buf, a1_buf,
454 filled ? "f" : "s" );
458 static void
459 draw_arc(DiaRenderer *self,
460 Point *center,
461 real width, real height,
462 real angle1, real angle2,
463 Color *color)
465 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
466 psrenderer_arc(renderer, center, width, height, angle1, angle2, color, FALSE);
469 static void
470 fill_arc(DiaRenderer *self,
471 Point *center,
472 real width, real height,
473 real angle1, real angle2,
474 Color *color)
476 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
477 psrenderer_arc(renderer, center, width, height, angle1, angle2, color, TRUE);
480 static void
481 psrenderer_ellipse(DiaPsRenderer *renderer,
482 Point *center,
483 real width, real height,
484 Color *color,
485 gboolean filled)
487 gchar cx_buf[DTOSTR_BUF_SIZE];
488 gchar cy_buf[DTOSTR_BUF_SIZE];
489 gchar w_buf[DTOSTR_BUF_SIZE];
490 gchar h_buf[DTOSTR_BUF_SIZE];
492 lazy_setcolor(renderer,color);
494 fprintf(renderer->file, "n %s %s %s %s 0 360 ellipse %s\n",
495 psrenderer_dtostr(cx_buf, (gdouble) center->x),
496 psrenderer_dtostr(cy_buf, (gdouble) center->y),
497 psrenderer_dtostr(w_buf, (gdouble) width / 2.0),
498 psrenderer_dtostr(h_buf, (gdouble) height / 2.0),
499 filled ? "f" : "cp s" );
502 static void
503 draw_ellipse(DiaRenderer *self,
504 Point *center,
505 real width, real height,
506 Color *color)
508 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
509 psrenderer_ellipse(renderer, center, width, height, color, FALSE);
512 static void
513 fill_ellipse(DiaRenderer *self,
514 Point *center,
515 real width, real height,
516 Color *color)
518 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
519 psrenderer_ellipse(renderer, center, width, height, color, TRUE);
522 static void
523 psrenderer_bezier(DiaPsRenderer *renderer,
524 BezPoint *points,
525 gint numpoints,
526 Color *color,
527 gboolean filled)
529 gint i;
530 gchar p1x_buf[DTOSTR_BUF_SIZE];
531 gchar p1y_buf[DTOSTR_BUF_SIZE];
532 gchar p2x_buf[DTOSTR_BUF_SIZE];
533 gchar p2y_buf[DTOSTR_BUF_SIZE];
534 gchar p3x_buf[DTOSTR_BUF_SIZE];
535 gchar p3y_buf[DTOSTR_BUF_SIZE];
537 lazy_setcolor(renderer,color);
539 if (points[0].type != BEZ_MOVE_TO)
540 g_warning("first BezPoint must be a BEZ_MOVE_TO");
542 fprintf(renderer->file, "n %s %s m",
543 psrenderer_dtostr(p1x_buf, (gdouble) points[0].p1.x),
544 psrenderer_dtostr(p1y_buf, (gdouble) points[0].p1.y) );
546 for (i = 1; i < numpoints; i++)
547 switch (points[i].type) {
548 case BEZ_MOVE_TO:
549 g_warning("only first BezPoint can be a BEZ_MOVE_TO");
550 break;
551 case BEZ_LINE_TO:
552 fprintf(renderer->file, " %s %s l",
553 psrenderer_dtostr(p1x_buf, (gdouble) points[i].p1.x),
554 psrenderer_dtostr(p1y_buf, (gdouble) points[i].p1.y) );
555 break;
556 case BEZ_CURVE_TO:
557 fprintf(renderer->file, " %s %s %s %s %s %s c",
558 psrenderer_dtostr(p1x_buf, (gdouble) points[i].p1.x),
559 psrenderer_dtostr(p1y_buf, (gdouble) points[i].p1.y),
560 psrenderer_dtostr(p2x_buf, (gdouble) points[i].p2.x),
561 psrenderer_dtostr(p2y_buf, (gdouble) points[i].p2.y),
562 psrenderer_dtostr(p3x_buf, (gdouble) points[i].p3.x),
563 psrenderer_dtostr(p3y_buf, (gdouble) points[i].p3.y) );
564 break;
567 if (filled)
568 fprintf(renderer->file, " ef\n");
569 else
570 fprintf(renderer->file, " s\n");
573 static void
574 draw_bezier(DiaRenderer *self,
575 BezPoint *points,
576 int numpoints, /* numpoints = 4+3*n, n=>0 */
577 Color *color)
579 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
580 psrenderer_bezier(renderer, points, numpoints, color, FALSE);
583 static void
584 fill_bezier(DiaRenderer *self,
585 BezPoint *points, /* Last point must be same as first point */
586 int numpoints,
587 Color *color)
589 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
590 psrenderer_bezier(renderer, points, numpoints, color, TRUE);
593 static void
594 draw_string(DiaRenderer *self,
595 const char *text,
596 Point *pos, Alignment alignment,
597 Color *color)
599 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
600 gchar *buffer;
601 gchar *localestr;
602 gchar px_buf[DTOSTR_BUF_SIZE];
603 gchar py_buf[DTOSTR_BUF_SIZE];
604 const gchar *str;
605 gint len;
606 GError * error = NULL;
608 if (1 > strlen(text))
609 return;
611 lazy_setcolor(renderer,color);
613 localestr = g_convert(text, -1, "LATIN1", "UTF-8", NULL, NULL, &error);
615 if (localestr == NULL) {
616 message_error("Can't convert string %s: %s\n", text, error->message);
617 localestr = g_strdup(text);
620 /* Escape all '(' and ')': */
621 buffer = g_malloc(2*strlen(localestr)+1);
622 *buffer = 0;
623 str = localestr;
624 while (*str != 0) {
625 len = strcspn(str,"()\\");
626 strncat(buffer, str, len);
627 str += len;
628 if (*str != 0) {
629 strcat(buffer,"\\");
630 strncat(buffer, str, 1);
631 str++;
634 fprintf(renderer->file, "(%s) ", buffer);
635 g_free(buffer);
636 g_free(localestr);
638 switch (alignment) {
639 case ALIGN_LEFT:
640 fprintf(renderer->file, "%s %s m",
641 psrenderer_dtostr(px_buf, pos->x),
642 psrenderer_dtostr(py_buf, pos->y) );
643 break;
644 case ALIGN_CENTER:
645 fprintf(renderer->file, "dup sw 2 div %s ex sub %s m",
646 psrenderer_dtostr(px_buf, pos->x),
647 psrenderer_dtostr(py_buf, pos->y) );
648 break;
649 case ALIGN_RIGHT:
650 fprintf(renderer->file, "dup sw %s ex sub %s m",
651 psrenderer_dtostr(px_buf, pos->x),
652 psrenderer_dtostr(py_buf, pos->y) );
653 break;
656 fprintf(renderer->file, " gs 1 -1 sc sh gr\n");
659 static void
660 draw_image(DiaRenderer *self,
661 Point *point,
662 real width, real height,
663 DiaImage image)
665 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
666 int img_width, img_height, img_rowstride;
667 int x, y;
668 real ratio;
669 guint8 *rgb_data;
670 guint8 *mask_data;
671 gchar d1_buf[DTOSTR_BUF_SIZE];
672 gchar d2_buf[DTOSTR_BUF_SIZE];
674 img_width = dia_image_width(image);
675 img_rowstride = dia_image_rowstride(image);
676 img_height = dia_image_height(image);
678 rgb_data = dia_image_rgb_data(image);
679 mask_data = dia_image_mask_data(image);
681 ratio = height/width;
683 fprintf(renderer->file, "gs\n");
685 /* color output only */
686 fprintf(renderer->file, "/pix %i string def\n", img_width * 3);
687 fprintf(renderer->file, "%i %i 8\n", img_width, img_height);
688 fprintf(renderer->file, "%s %s tr\n",
689 psrenderer_dtostr(d1_buf, point->x),
690 psrenderer_dtostr(d2_buf, point->y) );
691 fprintf(renderer->file, "%s %s sc\n",
692 psrenderer_dtostr(d1_buf, width),
693 psrenderer_dtostr(d2_buf, height) );
694 fprintf(renderer->file, "[%i 0 0 %i 0 0]\n", img_width, img_height);
696 fprintf(renderer->file, "{currentfile pix readhexstring pop}\n");
697 fprintf(renderer->file, "false 3 colorimage\n");
698 fprintf(renderer->file, "\n");
700 if (mask_data) {
701 for (y = 0; y < img_height; y++) {
702 for (x = 0; x < img_width; x++) {
703 int i = y*img_rowstride+x*3;
704 int m = y*img_width+x;
705 fprintf(renderer->file, "%02x", 255-(mask_data[m]*(255-rgb_data[i])/255));
706 fprintf(renderer->file, "%02x", 255-(mask_data[m]*(255-rgb_data[i+1])/255));
707 fprintf(renderer->file, "%02x", 255-(mask_data[m]*(255-rgb_data[i+2])/255));
709 fprintf(renderer->file, "\n");
711 } else {
712 for (y = 0; y < img_height; y++) {
713 for (x = 0; x < img_width; x++) {
714 int i = y*img_rowstride+x*3;
715 fprintf(renderer->file, "%02x", (int)(rgb_data[i]));
716 fprintf(renderer->file, "%02x", (int)(rgb_data[i+1]));
717 fprintf(renderer->file, "%02x", (int)(rgb_data[i+2]));
719 fprintf(renderer->file, "\n");
722 fprintf(renderer->file, "gr\n");
723 fprintf(renderer->file, "\n");
725 g_free(rgb_data);
726 g_free(mask_data);
729 static void
730 begin_prolog (DiaPsRenderer *renderer)
732 g_assert(renderer->file != NULL);
734 fprintf(renderer->file, "%%%%BeginProlog\n");
735 fprintf(renderer->file,
736 "[ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
737 "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
738 "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
739 "/.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright\n"
740 "/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one\n"
741 "/two /three /four /five /six /seven /eight /nine /colon /semicolon\n"
742 "/less /equal /greater /question /at /A /B /C /D /E\n"
743 "/F /G /H /I /J /K /L /M /N /O\n"
744 "/P /Q /R /S /T /U /V /W /X /Y\n"
745 "/Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c\n"
746 "/d /e /f /g /h /i /j /k /l /m\n"
747 "/n /o /p /q /r /s /t /u /v /w\n"
748 "/x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef\n"
749 "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
750 "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
751 "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
752 "/space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright\n"
753 "/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior\n"
754 "/acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf\n"
755 "/threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n"
756 "/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde\n"
757 "/Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex\n"
758 "/Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring\n"
759 "/ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis\n"
760 "/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave\n"
761 "/uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def\n");
763 fprintf(renderer->file,
764 "/cp {closepath} bind def\n"
765 "/c {curveto} bind def\n"
766 "/f {fill} bind def\n"
767 "/a {arc} bind def\n"
768 "/ef {eofill} bind def\n"
769 "/ex {exch} bind def\n"
770 "/gr {grestore} bind def\n"
771 "/gs {gsave} bind def\n"
772 "/sa {save} bind def\n"
773 "/rs {restore} bind def\n"
774 "/l {lineto} bind def\n"
775 "/m {moveto} bind def\n"
776 "/rm {rmoveto} bind def\n"
777 "/n {newpath} bind def\n"
778 "/s {stroke} bind def\n"
779 "/sh {show} bind def\n"
780 "/slc {setlinecap} bind def\n"
781 "/slj {setlinejoin} bind def\n"
782 "/slw {setlinewidth} bind def\n"
783 "/srgb {setrgbcolor} bind def\n"
784 "/rot {rotate} bind def\n"
785 "/sc {scale} bind def\n"
786 "/sd {setdash} bind def\n"
787 "/ff {findfont} bind def\n"
788 "/sf {setfont} bind def\n"
789 "/scf {scalefont} bind def\n"
790 "/sw {stringwidth pop} bind def\n"
791 "/tr {translate} bind def\n"
793 "\n/ellipsedict 8 dict def\n"
794 "ellipsedict /mtrx matrix put\n"
795 "/ellipse\n"
796 "{ ellipsedict begin\n"
797 " /endangle exch def\n"
798 " /startangle exch def\n"
799 " /yrad exch def\n"
800 " /xrad exch def\n"
801 " /y exch def\n"
802 " /x exch def"
803 " /savematrix mtrx currentmatrix def\n"
804 " x y tr xrad yrad sc\n"
805 " 0 0 1 startangle endangle arc\n"
806 " savematrix setmatrix\n"
807 " end\n"
808 "} def\n\n"
809 "/mergeprocs {\n"
810 "dup length\n"
811 "3 -1 roll\n"
812 "dup\n"
813 "length\n"
814 "dup\n"
815 "5 1 roll\n"
816 "3 -1 roll\n"
817 "add\n"
818 "array cvx\n"
819 "dup\n"
820 "3 -1 roll\n"
821 "0 exch\n"
822 "putinterval\n"
823 "dup\n"
824 "4 2 roll\n"
825 "putinterval\n"
826 "} bind def\n");
830 /* helper function */
831 static void
832 print_reencode_font(FILE *file, char *fontname)
834 /* Don't reencode the Symbol font, as it doesn't work in latin1 encoding.
835 * Instead, just define Symbol-latin1 to be the same as Symbol. */
836 if (!strcmp(fontname, "Symbol"))
837 fprintf(file,
838 "/%s-latin1\n"
839 " /%s findfont\n"
840 "definefont pop\n", fontname, fontname);
841 else
842 fprintf(file,
843 "/%s-latin1\n"
844 " /%s findfont\n"
845 " dup length dict begin\n"
846 " {1 index /FID ne {def} {pop pop} ifelse} forall\n"
847 " /Encoding isolatin1encoding def\n"
848 " currentdict end\n"
849 "definefont pop\n", fontname, fontname);
852 static void
853 dump_fonts (DiaPsRenderer *renderer)
855 print_reencode_font(renderer->file, "Times-Roman");
856 print_reencode_font(renderer->file, "Times-Italic");
857 print_reencode_font(renderer->file, "Times-Bold");
858 print_reencode_font(renderer->file, "Times-BoldItalic");
859 print_reencode_font(renderer->file, "AvantGarde-Book");
860 print_reencode_font(renderer->file, "AvantGarde-BookOblique");
861 print_reencode_font(renderer->file, "AvantGarde-Demi");
862 print_reencode_font(renderer->file, "AvantGarde-DemiOblique");
863 print_reencode_font(renderer->file, "Bookman-Light");
864 print_reencode_font(renderer->file, "Bookman-LightItalic");
865 print_reencode_font(renderer->file, "Bookman-Demi");
866 print_reencode_font(renderer->file, "Bookman-DemiItalic");
867 print_reencode_font(renderer->file, "Courier");
868 print_reencode_font(renderer->file, "Courier-Oblique");
869 print_reencode_font(renderer->file, "Courier-Bold");
870 print_reencode_font(renderer->file, "Courier-BoldOblique");
871 print_reencode_font(renderer->file, "Helvetica");
872 print_reencode_font(renderer->file, "Helvetica-Oblique");
873 print_reencode_font(renderer->file, "Helvetica-Bold");
874 print_reencode_font(renderer->file, "Helvetica-BoldOblique");
875 print_reencode_font(renderer->file, "Helvetica-Narrow");
876 print_reencode_font(renderer->file, "Helvetica-Narrow-Oblique");
877 print_reencode_font(renderer->file, "Helvetica-Narrow-Bold");
878 print_reencode_font(renderer->file, "Helvetica-Narrow-BoldOblique");
879 print_reencode_font(renderer->file, "NewCenturySchoolbook-Roman");
880 print_reencode_font(renderer->file, "NewCenturySchoolbook-Italic");
881 print_reencode_font(renderer->file, "NewCenturySchoolbook-Bold");
882 print_reencode_font(renderer->file, "NewCenturySchoolbook-BoldItalic");
883 print_reencode_font(renderer->file, "Palatino-Roman");
884 print_reencode_font(renderer->file, "Palatino-Italic");
885 print_reencode_font(renderer->file, "Palatino-Bold");
886 print_reencode_font(renderer->file, "Palatino-BoldItalic");
887 print_reencode_font(renderer->file, "Symbol");
888 print_reencode_font(renderer->file, "ZapfChancery-MediumItalic");
889 print_reencode_font(renderer->file, "ZapfDingbats");
892 static void
893 end_prolog (DiaPsRenderer *renderer)
895 gchar d1_buf[DTOSTR_BUF_SIZE];
896 gchar d2_buf[DTOSTR_BUF_SIZE];
898 if (renderer_is_eps(renderer)) {
899 fprintf(renderer->file,
900 "%s %s scale\n",
901 psrenderer_dtostr(d1_buf, renderer->scale),
902 psrenderer_dtostr(d2_buf, -renderer->scale) );
903 fprintf(renderer->file,
904 "%s %s translate\n",
905 psrenderer_dtostr(d1_buf, -renderer->extent.left),
906 psrenderer_dtostr(d2_buf, -renderer->extent.bottom) );
907 } else {
908 /* done by BoundingBox above */
911 fprintf(renderer->file,
912 "%%%%EndProlog\n\n\n");
915 /* constructor */
916 static void
917 ps_renderer_init (GTypeInstance *instance, gpointer g_class)
919 DiaPsRenderer *renderer = DIA_PS_RENDERER (instance);
921 renderer->file = NULL;
923 renderer->lcolor.red = -1.0;
925 renderer->dash_length = 1.0;
926 renderer->dot_length = 0.2;
927 renderer->saved_line_style = LINESTYLE_SOLID;
928 renderer->is_portrait = TRUE;
930 renderer->scale = 28.346;
933 /* GObject stuff */
934 static void dia_ps_renderer_class_init (DiaPsRendererClass *klass);
936 static gpointer parent_class = NULL;
938 GType
939 dia_ps_renderer_get_type (void)
941 static GType object_type = 0;
943 if (!object_type)
945 static const GTypeInfo object_info =
947 sizeof (DiaPsRendererClass),
948 (GBaseInitFunc) NULL,
949 (GBaseFinalizeFunc) NULL,
950 (GClassInitFunc) dia_ps_renderer_class_init,
951 NULL, /* class_finalize */
952 NULL, /* class_data */
953 sizeof (DiaPsRenderer),
954 0, /* n_preallocs */
955 ps_renderer_init /* init */
958 object_type = g_type_register_static (DIA_TYPE_RENDERER,
959 "DiaPsRenderer",
960 &object_info, 0);
963 return object_type;
966 static void
967 dia_ps_renderer_finalize (GObject *object)
969 DiaPsRenderer *renderer = DIA_PS_RENDERER (object);
971 g_free(renderer->title);
972 /* fclose(renderer->file);*/
974 G_OBJECT_CLASS (parent_class)->finalize (object);
977 static void
978 dia_ps_renderer_class_init (DiaPsRendererClass *klass)
980 GObjectClass *object_class = G_OBJECT_CLASS (klass);
981 DiaRendererClass *renderer_class = DIA_RENDERER_CLASS (klass);
982 DiaPsRendererClass *ps_renderer_class = DIA_PS_RENDERER_CLASS (klass);
984 parent_class = g_type_class_peek_parent (klass);
986 object_class->finalize = dia_ps_renderer_finalize;
988 renderer_class->begin_render = begin_render;
989 renderer_class->end_render = end_render;
991 renderer_class->set_linewidth = set_linewidth;
992 renderer_class->set_linecaps = set_linecaps;
993 renderer_class->set_linejoin = set_linejoin;
994 renderer_class->set_linestyle = set_linestyle;
995 renderer_class->set_dashlength = set_dashlength;
996 renderer_class->set_fillstyle = set_fillstyle;
997 renderer_class->set_font = set_font;
999 renderer_class->draw_line = draw_line;
1000 renderer_class->fill_polygon = fill_polygon;
1001 renderer_class->draw_arc = draw_arc;
1002 renderer_class->fill_arc = fill_arc;
1003 renderer_class->draw_ellipse = draw_ellipse;
1004 renderer_class->fill_ellipse = fill_ellipse;
1005 renderer_class->draw_string = draw_string;
1006 renderer_class->draw_image = draw_image;
1008 /* medium level functions */
1009 renderer_class->draw_bezier = draw_bezier;
1010 renderer_class->fill_bezier = fill_bezier;
1011 renderer_class->draw_rect = draw_rect;
1012 renderer_class->fill_rect = fill_rect;
1013 renderer_class->draw_polyline = draw_polyline;
1014 renderer_class->draw_polygon = draw_polygon;
1016 /* ps specific */
1017 ps_renderer_class->begin_prolog = begin_prolog;
1018 ps_renderer_class->dump_fonts = dump_fonts;
1019 ps_renderer_class->end_prolog = end_prolog;