2004-05-17 Hans Breuer <hans@breuer.org>
[dia.git] / app / diapsrenderer.c
blob4e6a4cd836c44f7b8aac23dd826843c47976f3a1
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 /* Returns TRUE if this file is an encapsulated postscript file
36 * (including e.g. epsi).
38 static gboolean renderer_is_eps(DiaPsRenderer *renderer) {
39 return renderer->pstype == PSTYPE_EPS ||
40 renderer->pstype == PSTYPE_EPSI;
43 /** Returns TRUE if this file is an EPSI file */
44 static gboolean renderer_is_epsi(DiaPsRenderer *renderer) {
45 return renderer->pstype == PSTYPE_EPSI;
48 void
49 lazy_setcolor(DiaPsRenderer *renderer,
50 Color *color)
52 if (!color_equals(color, &(renderer->lcolor))) {
53 renderer->lcolor = *color;
54 fprintf(renderer->file, "%f %f %f srgb\n",
55 (double) color->red,
56 (double) color->green,
57 (double) color->blue);
61 static void
62 begin_render(DiaRenderer *self)
64 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
65 time_t time_now;
67 g_assert (renderer->file != NULL);
69 time_now = time(NULL);
71 if (renderer_is_eps(renderer))
72 fprintf(renderer->file,
73 "%%!PS-Adobe-2.0 EPSF-2.0\n");
74 else
75 fprintf(renderer->file,
76 "%%!PS-Adobe-2.0\n");
77 fprintf(renderer->file,
78 "%%%%Title: %s\n"
79 "%%%%Creator: Dia v%s\n"
80 "%%%%CreationDate: %s"
81 "%%%%For: %s\n"
82 "%%%%Orientation: %s\n",
83 renderer->title ? renderer->title : "(NULL)" ,
84 VERSION,
85 ctime(&time_now),
86 g_get_user_name(),
87 renderer->is_portrait ? "Portrait" : "Landscape");
89 if (renderer_is_eps(renderer))
90 fprintf(renderer->file,
91 "%%%%Magnification: 1.0000\n"
92 "%%%%BoundingBox: 0 0 %d %d\n",
93 (int) ceil( (renderer->extent.right - renderer->extent.left)
94 * renderer->scale),
95 (int) ceil( (renderer->extent.bottom - renderer->extent.top)
96 * renderer->scale) );
98 else
99 fprintf(renderer->file,
100 "%%%%DocumentPaperSizes: %s\n",
101 renderer->paper ? renderer->paper : "(NULL)");
103 fprintf(renderer->file,
104 "%%%%BeginSetup\n");
105 fprintf(renderer->file,
106 "%%%%EndSetup\n"
107 "%%%%EndComments\n");
109 DIA_PS_RENDERER_GET_CLASS(self)->begin_prolog(renderer);
110 /* get our font definitions */
111 DIA_PS_RENDERER_GET_CLASS(self)->dump_fonts(renderer);
112 /* done it */
113 DIA_PS_RENDERER_GET_CLASS(self)->end_prolog(renderer);
116 static void
117 end_render(DiaRenderer *self)
119 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
121 if (renderer_is_eps(renderer))
122 fprintf(renderer->file, "showpage\n");
125 static void
126 set_linewidth(DiaRenderer *self, real linewidth)
127 { /* 0 == hairline **/
128 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
130 /* Adobe's advice: Set to very small but fixed size, to avoid changes
131 * due to different resolution output. */
132 /* .01 cm becomes <5 dots on 1200 DPI */
133 if (linewidth == 0.0) linewidth=.01;
134 fprintf(renderer->file, "%f slw\n", (double) linewidth);
137 static void
138 set_linecaps(DiaRenderer *self, LineCaps mode)
140 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
141 int ps_mode;
143 switch(mode) {
144 case LINECAPS_BUTT:
145 ps_mode = 0;
146 break;
147 case LINECAPS_ROUND:
148 ps_mode = 1;
149 break;
150 case LINECAPS_PROJECTING:
151 ps_mode = 2;
152 break;
153 default:
154 ps_mode = 0;
157 fprintf(renderer->file, "%d slc\n", ps_mode);
160 static void
161 set_linejoin(DiaRenderer *self, LineJoin mode)
163 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
164 int ps_mode;
166 switch(mode) {
167 case LINEJOIN_MITER:
168 ps_mode = 0;
169 break;
170 case LINEJOIN_ROUND:
171 ps_mode = 1;
172 break;
173 case LINEJOIN_BEVEL:
174 ps_mode = 2;
175 break;
176 default:
177 ps_mode = 0;
180 fprintf(renderer->file, "%d slj\n", ps_mode);
183 static void
184 set_linestyle(DiaRenderer *self, LineStyle mode)
186 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
187 real hole_width;
189 renderer->saved_line_style = mode;
191 switch(mode) {
192 case LINESTYLE_SOLID:
193 fprintf(renderer->file, "[] 0 sd\n");
194 break;
195 case LINESTYLE_DASHED:
196 fprintf(renderer->file, "[%f] 0 sd\n", renderer->dash_length);
197 break;
198 case LINESTYLE_DASH_DOT:
199 hole_width = (renderer->dash_length - renderer->dot_length) / 2.0;
200 fprintf(renderer->file, "[%f %f %f %f] 0 sd\n",
201 renderer->dash_length,
202 hole_width,
203 renderer->dot_length,
204 hole_width );
205 break;
206 case LINESTYLE_DASH_DOT_DOT:
207 hole_width = (renderer->dash_length - 2.0*renderer->dot_length) / 3.0;
208 fprintf(renderer->file, "[%f %f %f %f %f %f] 0 sd\n",
209 renderer->dash_length,
210 hole_width,
211 renderer->dot_length,
212 hole_width,
213 renderer->dot_length,
214 hole_width );
215 break;
216 case LINESTYLE_DOTTED:
217 fprintf(renderer->file, "[%f] 0 sd\n", renderer->dot_length);
218 break;
222 static void
223 set_dashlength(DiaRenderer *self, real length)
224 { /* dot = 20% of len */
225 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
227 if (length<0.001)
228 length = 0.001;
230 renderer->dash_length = length;
231 renderer->dot_length = length*0.2;
233 set_linestyle(self, renderer->saved_line_style);
236 static void
237 set_fillstyle(DiaRenderer *self, FillStyle mode)
239 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
241 switch(mode) {
242 case FILLSTYLE_SOLID:
243 break;
244 default:
245 message_error("%s : Unsupported fill mode specified!\n",
246 G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (self)));
250 static void
251 set_font(DiaRenderer *self, DiaFont *font, real height)
253 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
255 fprintf(renderer->file, "/%s-latin1 ff %f scf sf\n",
256 dia_font_get_psfontname(font), (double)height*0.7);
259 static void
260 draw_line(DiaRenderer *self,
261 Point *start, Point *end,
262 Color *line_color)
264 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
266 lazy_setcolor(renderer,line_color);
268 fprintf(renderer->file, "n %f %f m %f %f l s\n",
269 start->x, start->y, end->x, end->y);
272 static void
273 draw_polyline(DiaRenderer *self,
274 Point *points, int num_points,
275 Color *line_color)
277 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
278 int i;
280 lazy_setcolor(renderer,line_color);
282 fprintf(renderer->file, "n %f %f m ",
283 points[0].x, points[0].y);
285 for (i=1;i<num_points;i++) {
286 fprintf(renderer->file, "%f %f l ",
287 points[i].x, points[i].y);
290 fprintf(renderer->file, "s\n");
293 static void
294 draw_polygon(DiaRenderer *self,
295 Point *points, int num_points,
296 Color *line_color)
298 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
299 int i;
301 lazy_setcolor(renderer,line_color);
303 fprintf(renderer->file, "n %f %f m ",
304 points[0].x, points[0].y);
306 for (i=1;i<num_points;i++) {
307 fprintf(renderer->file, "%f %f l ",
308 points[i].x, points[i].y);
311 fprintf(renderer->file, "cp s\n");
314 static void
315 fill_polygon(DiaRenderer *self,
316 Point *points, int num_points,
317 Color *fill_color)
319 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
320 int i;
322 lazy_setcolor(renderer,fill_color);
324 fprintf(renderer->file, "n %f %f m ",
325 points[0].x, points[0].y);
327 for (i=1;i<num_points;i++) {
328 fprintf(renderer->file, "%f %f l ",
329 points[i].x, points[i].y);
332 fprintf(renderer->file, "f\n");
335 static void
336 draw_rect(DiaRenderer *self,
337 Point *ul_corner, Point *lr_corner,
338 Color *color)
340 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
342 lazy_setcolor(renderer,color);
344 fprintf(renderer->file, "n %f %f m %f %f l %f %f l %f %f l cp s\n",
345 (double) ul_corner->x, (double) ul_corner->y,
346 (double) ul_corner->x, (double) lr_corner->y,
347 (double) lr_corner->x, (double) lr_corner->y,
348 (double) lr_corner->x, (double) ul_corner->y );
351 static void
352 fill_rect(DiaRenderer *self,
353 Point *ul_corner, Point *lr_corner,
354 Color *color)
356 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
358 lazy_setcolor(renderer,color);
360 fprintf(renderer->file, "n %f %f m %f %f l %f %f l %f %f l f\n",
361 (double) ul_corner->x, (double) ul_corner->y,
362 (double) ul_corner->x, (double) lr_corner->y,
363 (double) lr_corner->x, (double) lr_corner->y,
364 (double) lr_corner->x, (double) ul_corner->y );
367 static void
368 draw_arc(DiaRenderer *self,
369 Point *center,
370 real width, real height,
371 real angle1, real angle2,
372 Color *color)
374 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
376 lazy_setcolor(renderer,color);
378 fprintf(renderer->file, "n %f %f %f %f %f %f ellipse s\n",
379 (double) center->x, (double) center->y,
380 (double) width/2.0, (double) height/2.0,
381 (double) 360.0 - angle2, (double) 360.0 - angle1 );
384 static void
385 fill_arc(DiaRenderer *self,
386 Point *center,
387 real width, real height,
388 real angle1, real angle2,
389 Color *color)
391 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
393 lazy_setcolor(renderer,color);
395 fprintf(renderer->file, "n %f %f m %f %f %f %f %f %f ellipse f\n",
396 (double) center->x, (double) center->y,
397 (double) center->x, (double) center->y,
398 (double) width/2.0, (double) height/2.0,
399 (double) 360.0 - angle2, (double) 360.0 - angle1 );
402 static void
403 draw_ellipse(DiaRenderer *self,
404 Point *center,
405 real width, real height,
406 Color *color)
408 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
410 lazy_setcolor(renderer,color);
412 fprintf(renderer->file, "n %f %f %f %f 0 360 ellipse cp s\n",
413 (double) center->x, (double) center->y,
414 (double) width/2.0, (double) height/2.0 );
417 static void
418 fill_ellipse(DiaRenderer *self,
419 Point *center,
420 real width, real height,
421 Color *color)
423 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
425 lazy_setcolor(renderer,color);
427 fprintf(renderer->file, "n %f %f %f %f 0 360 ellipse f\n",
428 (double) center->x, (double) center->y,
429 (double) width/2.0, (double) height/2.0 );
432 static void
433 draw_bezier(DiaRenderer *self,
434 BezPoint *points,
435 int numpoints, /* numpoints = 4+3*n, n=>0 */
436 Color *color)
438 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
439 int i;
441 lazy_setcolor(renderer,color);
443 if (points[0].type != BEZ_MOVE_TO)
444 g_warning("first BezPoint must be a BEZ_MOVE_TO");
446 fprintf(renderer->file, "n %f %f m",
447 (double) points[0].p1.x, (double) points[0].p1.y);
449 for (i = 1; i < numpoints; i++)
450 switch (points[i].type) {
451 case BEZ_MOVE_TO:
452 g_warning("only first BezPoint can be a BEZ_MOVE_TO");
453 break;
454 case BEZ_LINE_TO:
455 fprintf(renderer->file, " %f %f l",
456 (double) points[i].p1.x, (double) points[i].p1.y);
457 break;
458 case BEZ_CURVE_TO:
459 fprintf(renderer->file, " %f %f %f %f %f %f c",
460 (double) points[i].p1.x, (double) points[i].p1.y,
461 (double) points[i].p2.x, (double) points[i].p2.y,
462 (double) points[i].p3.x, (double) points[i].p3.y );
463 break;
466 fprintf(renderer->file, " s\n");
469 static void
470 fill_bezier(DiaRenderer *self,
471 BezPoint *points, /* Last point must be same as first point */
472 int numpoints,
473 Color *color)
475 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
476 int i;
478 lazy_setcolor(renderer,color);
480 if (points[0].type != BEZ_MOVE_TO)
481 g_warning("first BezPoint must be a BEZ_MOVE_TO");
483 fprintf(renderer->file, "n %f %f m",
484 (double) points[0].p1.x, (double) points[0].p1.y);
486 for (i = 1; i < numpoints; i++)
487 switch (points[i].type) {
488 case BEZ_MOVE_TO:
489 g_warning("only first BezPoint can be a BEZ_MOVE_TO");
490 break;
491 case BEZ_LINE_TO:
492 fprintf(renderer->file, " %f %f l",
493 (double) points[i].p1.x, (double) points[i].p1.y);
494 break;
495 case BEZ_CURVE_TO:
496 fprintf(renderer->file, " %f %f %f %f %f %f c",
497 (double) points[i].p1.x, (double) points[i].p1.y,
498 (double) points[i].p2.x, (double) points[i].p2.y,
499 (double) points[i].p3.x, (double) points[i].p3.y );
500 break;
503 fprintf(renderer->file, " f\n");
506 static void
507 draw_string(DiaRenderer *self,
508 const char *text,
509 Point *pos, Alignment alignment,
510 Color *color)
512 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
513 char *buffer;
514 const char *str;
515 int len;
516 gchar *localestr;
517 GError * error = NULL;
519 if (1 > strlen(text))
520 return;
522 lazy_setcolor(renderer,color);
524 /* TODO: Use latin-1 encoding */
526 localestr = g_locale_from_utf8(text, -1, NULL, NULL, &error);
528 if (localestr == NULL) {
529 message_error("Can't convert string %s: %s\n", text, error->message);
530 localestr = g_strdup(text);
533 /* Escape all '(' and ')': */
534 buffer = g_malloc(2*strlen(localestr)+1);
535 *buffer = 0;
536 str = localestr;
537 while (*str != 0) {
538 len = strcspn(str,"()\\");
539 strncat(buffer, str, len);
540 str += len;
541 if (*str != 0) {
542 strcat(buffer,"\\");
543 strncat(buffer, str, 1);
544 str++;
547 fprintf(renderer->file, "(%s) ", buffer);
548 g_free(buffer);
549 g_free(localestr);
551 switch (alignment) {
552 case ALIGN_LEFT:
553 fprintf(renderer->file, "%f %f m", pos->x, pos->y);
554 break;
555 case ALIGN_CENTER:
556 fprintf(renderer->file, "dup sw 2 div %f ex sub %f m",
557 pos->x, pos->y);
558 break;
559 case ALIGN_RIGHT:
560 fprintf(renderer->file, "dup sw %f ex sub %f m",
561 pos->x, pos->y);
562 break;
565 fprintf(renderer->file, " gs 1 -1 sc sh gr\n");
568 static void
569 draw_image(DiaRenderer *self,
570 Point *point,
571 real width, real height,
572 DiaImage image)
574 DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
575 int img_width, img_height, img_rowstride;
576 int v;
577 int x, y;
578 real ratio;
579 guint8 *rgb_data;
580 guint8 *mask_data;
582 img_width = dia_image_width(image);
583 img_rowstride = dia_image_rowstride(image);
584 img_height = dia_image_height(image);
586 rgb_data = dia_image_rgb_data(image);
587 mask_data = dia_image_mask_data(image);
589 ratio = height/width;
591 fprintf(renderer->file, "gs\n");
593 /* color output only */
594 fprintf(renderer->file, "/pix %i string def\n", img_width * 3);
595 fprintf(renderer->file, "%i %i 8\n", img_width, img_height);
596 fprintf(renderer->file, "%f %f tr\n", point->x, point->y);
597 fprintf(renderer->file, "%f %f sc\n", width, height);
598 fprintf(renderer->file, "[%i 0 0 %i 0 0]\n", img_width, img_height);
600 fprintf(renderer->file, "{currentfile pix readhexstring pop}\n");
601 fprintf(renderer->file, "false 3 colorimage\n");
602 fprintf(renderer->file, "\n");
604 if (mask_data) {
605 for (y = 0; y < img_height; y++) {
606 for (x = 0; x < img_width; x++) {
607 int i = y*img_rowstride+x*3;
608 int m = y*img_width+x;
609 fprintf(renderer->file, "%02x", 255-(mask_data[m]*(255-rgb_data[i])/255));
610 fprintf(renderer->file, "%02x", 255-(mask_data[m]*(255-rgb_data[i+1])/255));
611 fprintf(renderer->file, "%02x", 255-(mask_data[m]*(255-rgb_data[i+2])/255));
613 fprintf(renderer->file, "\n");
615 } else {
616 guint8 *ptr = rgb_data;
617 for (y = 0; y < img_height; y++) {
618 for (x = 0; x < img_width; x++) {
619 int i = y*img_rowstride+x*3;
620 fprintf(renderer->file, "%02x", (int)(rgb_data[i]));
621 fprintf(renderer->file, "%02x", (int)(rgb_data[i+1]));
622 fprintf(renderer->file, "%02x", (int)(rgb_data[i+2]));
624 fprintf(renderer->file, "\n");
627 fprintf(renderer->file, "gr\n");
628 fprintf(renderer->file, "\n");
630 g_free(rgb_data);
631 g_free(mask_data);
634 static void
635 begin_prolog (DiaPsRenderer *renderer)
637 g_assert(renderer->file != NULL);
639 fprintf(renderer->file, "%%%%BeginProlog\n");
640 fprintf(renderer->file,
641 "[ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
642 "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
643 "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
644 "/.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright\n"
645 "/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one\n"
646 "/two /three /four /five /six /seven /eight /nine /colon /semicolon\n"
647 "/less /equal /greater /question /at /A /B /C /D /E\n"
648 "/F /G /H /I /J /K /L /M /N /O\n"
649 "/P /Q /R /S /T /U /V /W /X /Y\n"
650 "/Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c\n"
651 "/d /e /f /g /h /i /j /k /l /m\n"
652 "/n /o /p /q /r /s /t /u /v /w\n"
653 "/x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef\n"
654 "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
655 "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
656 "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
657 "/space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright\n"
658 "/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior\n"
659 "/acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf\n"
660 "/threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n"
661 "/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde\n"
662 "/Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex\n"
663 "/Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring\n"
664 "/ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis\n"
665 "/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave\n"
666 "/uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def\n");
668 fprintf(renderer->file,
669 "/cp {closepath} bind def\n"
670 "/c {curveto} bind def\n"
671 "/f {fill} bind def\n"
672 "/a {arc} bind def\n"
673 "/ef {eofill} bind def\n"
674 "/ex {exch} bind def\n"
675 "/gr {grestore} bind def\n"
676 "/gs {gsave} bind def\n"
677 "/sa {save} bind def\n"
678 "/rs {restore} bind def\n"
679 "/l {lineto} bind def\n"
680 "/m {moveto} bind def\n"
681 "/rm {rmoveto} bind def\n"
682 "/n {newpath} bind def\n"
683 "/s {stroke} bind def\n"
684 "/sh {show} bind def\n"
685 "/slc {setlinecap} bind def\n"
686 "/slj {setlinejoin} bind def\n"
687 "/slw {setlinewidth} bind def\n"
688 "/srgb {setrgbcolor} bind def\n"
689 "/rot {rotate} bind def\n"
690 "/sc {scale} bind def\n"
691 "/sd {setdash} bind def\n"
692 "/ff {findfont} bind def\n"
693 "/sf {setfont} bind def\n"
694 "/scf {scalefont} bind def\n"
695 "/sw {stringwidth pop} bind def\n"
696 "/tr {translate} bind def\n"
698 "\n/ellipsedict 8 dict def\n"
699 "ellipsedict /mtrx matrix put\n"
700 "/ellipse\n"
701 "{ ellipsedict begin\n"
702 " /endangle exch def\n"
703 " /startangle exch def\n"
704 " /yrad exch def\n"
705 " /xrad exch def\n"
706 " /y exch def\n"
707 " /x exch def"
708 " /savematrix mtrx currentmatrix def\n"
709 " x y tr xrad yrad sc\n"
710 " 0 0 1 startangle endangle arc\n"
711 " savematrix setmatrix\n"
712 " end\n"
713 "} def\n\n"
714 "/mergeprocs {\n"
715 "dup length\n"
716 "3 -1 roll\n"
717 "dup\n"
718 "length\n"
719 "dup\n"
720 "5 1 roll\n"
721 "3 -1 roll\n"
722 "add\n"
723 "array cvx\n"
724 "dup\n"
725 "3 -1 roll\n"
726 "0 exch\n"
727 "putinterval\n"
728 "dup\n"
729 "4 2 roll\n"
730 "putinterval\n"
731 "} bind def\n");
735 /* helper function */
736 static void
737 print_reencode_font(FILE *file, char *fontname)
739 /* Don't reencode the Symbol font, as it doesn't work in latin1 encoding.
740 * Instead, just define Symbol-latin1 to be the same as Symbol. */
741 if (!strcmp(fontname, "Symbol"))
742 fprintf(file,
743 "/%s-latin1\n"
744 " /%s findfont\n"
745 "definefont pop\n", fontname, fontname);
746 else
747 fprintf(file,
748 "/%s-latin1\n"
749 " /%s findfont\n"
750 " dup length dict begin\n"
751 " {1 index /FID ne {def} {pop pop} ifelse} forall\n"
752 " /Encoding isolatin1encoding def\n"
753 " currentdict end\n"
754 "definefont pop\n", fontname, fontname);
757 static void
758 dump_fonts (DiaPsRenderer *renderer)
760 print_reencode_font(renderer->file, "Times-Roman");
761 print_reencode_font(renderer->file, "Times-Italic");
762 print_reencode_font(renderer->file, "Times-Bold");
763 print_reencode_font(renderer->file, "Times-BoldItalic");
764 print_reencode_font(renderer->file, "AvantGarde-Book");
765 print_reencode_font(renderer->file, "AvantGarde-BookOblique");
766 print_reencode_font(renderer->file, "AvantGarde-Demi");
767 print_reencode_font(renderer->file, "AvantGarde-DemiOblique");
768 print_reencode_font(renderer->file, "Bookman-Light");
769 print_reencode_font(renderer->file, "Bookman-LightItalic");
770 print_reencode_font(renderer->file, "Bookman-Demi");
771 print_reencode_font(renderer->file, "Bookman-DemiItalic");
772 print_reencode_font(renderer->file, "Courier");
773 print_reencode_font(renderer->file, "Courier-Oblique");
774 print_reencode_font(renderer->file, "Courier-Bold");
775 print_reencode_font(renderer->file, "Courier-BoldOblique");
776 print_reencode_font(renderer->file, "Helvetica");
777 print_reencode_font(renderer->file, "Helvetica-Oblique");
778 print_reencode_font(renderer->file, "Helvetica-Bold");
779 print_reencode_font(renderer->file, "Helvetica-BoldOblique");
780 print_reencode_font(renderer->file, "Helvetica-Narrow");
781 print_reencode_font(renderer->file, "Helvetica-Narrow-Oblique");
782 print_reencode_font(renderer->file, "Helvetica-Narrow-Bold");
783 print_reencode_font(renderer->file, "Helvetica-Narrow-BoldOblique");
784 print_reencode_font(renderer->file, "NewCenturySchoolbook-Roman");
785 print_reencode_font(renderer->file, "NewCenturySchoolbook-Italic");
786 print_reencode_font(renderer->file, "NewCenturySchoolbook-Bold");
787 print_reencode_font(renderer->file, "NewCenturySchoolbook-BoldItalic");
788 print_reencode_font(renderer->file, "Palatino-Roman");
789 print_reencode_font(renderer->file, "Palatino-Italic");
790 print_reencode_font(renderer->file, "Palatino-Bold");
791 print_reencode_font(renderer->file, "Palatino-BoldItalic");
792 print_reencode_font(renderer->file, "Symbol");
793 print_reencode_font(renderer->file, "ZapfChancery-MediumItalic");
794 print_reencode_font(renderer->file, "ZapfDingbats");
797 static void
798 end_prolog (DiaPsRenderer *renderer)
800 if (renderer_is_eps(renderer)) {
801 fprintf(renderer->file,
802 "%f %f scale\n", renderer->scale, -renderer->scale);
803 fprintf(renderer->file,
804 "%f %f translate\n", -renderer->extent.left, -renderer->extent.bottom);
805 } else {
806 /* done by BoundingBox above */
809 fprintf(renderer->file,
810 "%%%%EndProlog\n\n\n");
813 /* constructor */
814 static void
815 ps_renderer_init (GTypeInstance *instance, gpointer g_class)
817 DiaPsRenderer *renderer = DIA_PS_RENDERER (instance);
819 renderer->file = NULL;
821 renderer->lcolor.red = -1.0;
823 renderer->dash_length = 1.0;
824 renderer->dot_length = 0.2;
825 renderer->saved_line_style = LINESTYLE_SOLID;
826 renderer->is_portrait = TRUE;
828 renderer->scale = 28.346;
831 /* GObject stuff */
832 static void dia_ps_renderer_class_init (DiaPsRendererClass *klass);
834 static gpointer parent_class = NULL;
836 GType
837 dia_ps_renderer_get_type (void)
839 static GType object_type = 0;
841 if (!object_type)
843 static const GTypeInfo object_info =
845 sizeof (DiaPsRendererClass),
846 (GBaseInitFunc) NULL,
847 (GBaseFinalizeFunc) NULL,
848 (GClassInitFunc) dia_ps_renderer_class_init,
849 NULL, /* class_finalize */
850 NULL, /* class_data */
851 sizeof (DiaPsRenderer),
852 0, /* n_preallocs */
853 ps_renderer_init /* init */
856 object_type = g_type_register_static (DIA_TYPE_RENDERER,
857 "DiaPsRenderer",
858 &object_info, 0);
861 return object_type;
864 static void
865 dia_ps_renderer_finalize (GObject *object)
867 DiaPsRenderer *renderer = DIA_PS_RENDERER (object);
869 g_free(renderer->title);
870 /* fclose(renderer->file);*/
872 G_OBJECT_CLASS (parent_class)->finalize (object);
875 static void
876 dia_ps_renderer_class_init (DiaPsRendererClass *klass)
878 GObjectClass *object_class = G_OBJECT_CLASS (klass);
879 DiaRendererClass *renderer_class = DIA_RENDERER_CLASS (klass);
880 DiaPsRendererClass *ps_renderer_class = DIA_PS_RENDERER_CLASS (klass);
882 parent_class = g_type_class_peek_parent (klass);
884 object_class->finalize = dia_ps_renderer_finalize;
886 renderer_class->begin_render = begin_render;
887 renderer_class->end_render = end_render;
889 renderer_class->set_linewidth = set_linewidth;
890 renderer_class->set_linecaps = set_linecaps;
891 renderer_class->set_linejoin = set_linejoin;
892 renderer_class->set_linestyle = set_linestyle;
893 renderer_class->set_dashlength = set_dashlength;
894 renderer_class->set_fillstyle = set_fillstyle;
895 renderer_class->set_font = set_font;
897 renderer_class->draw_line = draw_line;
898 renderer_class->fill_polygon = fill_polygon;
899 renderer_class->draw_arc = draw_arc;
900 renderer_class->fill_arc = fill_arc;
901 renderer_class->draw_ellipse = draw_ellipse;
902 renderer_class->fill_ellipse = fill_ellipse;
903 renderer_class->draw_string = draw_string;
904 renderer_class->draw_image = draw_image;
906 /* medium level functions */
907 renderer_class->draw_bezier = draw_bezier;
908 renderer_class->fill_bezier = fill_bezier;
909 renderer_class->draw_rect = draw_rect;
910 renderer_class->fill_rect = fill_rect;
911 renderer_class->draw_polyline = draw_polyline;
912 renderer_class->draw_polygon = draw_polygon;
914 /* ps specific */
915 ps_renderer_class->begin_prolog = begin_prolog;
916 ps_renderer_class->dump_fonts = dump_fonts;
917 ps_renderer_class->end_prolog = end_prolog;