1 /* gtkplotps - postscript driver
2  * Copyright 1999-2001  Adrian E. Feiguin <feiguin@ifir.edu.ar>
3  *
4  * Some few lines of code borrowed from
5  * DiaCanvas -- a technical canvas widget
6  * Copyright (C) 1999 Arjan Molenaar
7  * Dia -- an diagram creation/manipulation program
8  * Copyright (C) 1998 Alexander Larsson
9  * ISO Latin encoding by
10  * Przemek Klosowski
11  * przemek@rrdbartok.nist.gov
12  * (borrowed from XMGR)
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27  * Boston, MA 02111-1307, USA.
28  */
29 
30 /**
31  * SECTION: gtkplotps
32  * @short_description: postscript driver
33  *
34  * Subclass of #GtkPlotPC used to generate PostScript output.
35  */
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <math.h>
41 #include <ctype.h>
42 #include <time.h>
43 #include <gtk/gtk.h>
44 #include <locale.h>
45 
46 #include "gtkplot.h"
47 #include "gtkpsfont.h"
48 #include "gtkplotpc.h"
49 #include "gtkplotps.h"
50 
51 
52 static void gtk_plot_ps_class_init 		(GtkPlotPSClass *klass);
53 static void gtk_plot_ps_init 			(GtkPlotPS *ps);
54 static void gtk_plot_ps_destroy 		(GtkObject *object);
55 /*********************************************************************/
56 /* Postscript specific functions */
57 static gboolean psinit				(GtkPlotPC *pc);
58 static void pssetviewport			(GtkPlotPC *pc,
59 						 gdouble w, gdouble h);
60 static void psleave				(GtkPlotPC *pc);
61 static void psgsave				(GtkPlotPC *pc);
62 static void psgrestore				(GtkPlotPC *pc);
63 static void psclip				(GtkPlotPC *pc,
64 						 const GdkRectangle *area);
65 static void psclipmask				(GtkPlotPC *pc,
66 						 gdouble x, gdouble y,
67 						 const GdkBitmap *mask);
68 static void psdrawlines				(GtkPlotPC *pc,
69 						 GtkPlotPoint *points,
70 						 gint numpoints);
71 static void psdrawpoint				(GtkPlotPC *pc,
72                 				 gdouble x, gdouble y);
73 static void psdrawline				(GtkPlotPC *pc,
74 						 gdouble x0, gdouble y0,
75 						 gdouble xf, gdouble yf);
76 static void psdrawpolygon			(GtkPlotPC *pc,
77 						 gboolean filled,
78 						 GtkPlotPoint *points,
79 						 gint numpoints);
80 static void psdrawrectangle			(GtkPlotPC *pc,
81 						 gboolean filled,
82                 				 gdouble x, gdouble y,
83 						 gdouble width, gdouble height);
84 static void psdrawcircle			(GtkPlotPC *pc,
85 						 gboolean filled,
86                                                  gdouble x, gdouble y,
87 						 gdouble size);
88 static void psdrawellipse			(GtkPlotPC *pc,
89               					 gboolean filled,
90 						 gdouble x, gdouble y,
91 						 gdouble width, gdouble height);
92 static void pssetcolor				(GtkPlotPC *pc,
93 						 const GdkColor *color);
94 static void pssetlineattr			(GtkPlotPC *pc,
95                                                  gfloat line_width,
96                                                  GdkLineStyle line_style,
97                                                  GdkCapStyle cap_style,
98                                                  GdkJoinStyle join_style);
99 static void psdrawstring			(GtkPlotPC *pc,
100              					 gint x, gint y,
101                                                  gint angle,
102                                                  const GdkColor *fg,
103                                                  const GdkColor *bg,
104                                                  gboolean transparent,
105                                                  gint border,
106                                                  gint border_space,
107                                                  gint border_width,
108                                                  gint shadow_width,
109                                                  const gchar *font,
110                                                  gint height,
111                                                  GtkJustification just,
112                                                  const gchar *text);
113 static void pssetfont				(GtkPlotPC *pc,
114 						 GtkPSFont *psfont,
115 						 gint height);
116 static void pssetdash				(GtkPlotPC *pc,
117 						 gdouble offset,
118 						 gdouble *values,
119 						 gint num_values);
120 static void psdrawpixmap                        (GtkPlotPC *pc,
121                                                  GdkPixmap *pixmap,
122                                                  GdkBitmap *mask,
123                                                  gint xsrc, gint ysrc,
124                                                  gint xdest, gint ydest,
125                                                  gint width, gint height,
126                                                  gdouble sx, gdouble sy);
127 
128 static void ps_reencode_font			(FILE *file, char *fontname);
129 static void color_to_hex                        (GdkColor color,
130                                                  gchar string[7]);
131 
132 /*********************************************************************/
133 static GtkPlotPCClass *parent_class = NULL;
134 static gchar *locale = NULL;
135 
136 GType
gtk_plot_ps_get_type(void)137 gtk_plot_ps_get_type (void)
138 {
139   static GType pc_type = 0;
140 
141   if (!pc_type)
142     {
143       pc_type = g_type_register_static_simple (
144 		GTK_TYPE_PLOT_PC,
145 		"GtkPlotPS",
146 		sizeof (GtkPlotPSClass),
147 		(GClassInitFunc) gtk_plot_ps_class_init,
148 		sizeof (GtkPlotPS),
149 		(GInstanceInitFunc) gtk_plot_ps_init,
150 		0);
151     }
152   return pc_type;
153 }
154 
155 static void
gtk_plot_ps_init(GtkPlotPS * ps)156 gtk_plot_ps_init (GtkPlotPS *ps)
157 {
158   ps->psname = NULL;
159   ps->gsaved = FALSE;
160   GTK_PLOT_PC(ps)->use_pixmap = FALSE;
161 }
162 
163 
164 static void
gtk_plot_ps_class_init(GtkPlotPSClass * klass)165 gtk_plot_ps_class_init (GtkPlotPSClass *klass)
166 {
167   GtkObjectClass *object_class;
168   GObjectClass *gobject_class;
169   GtkPlotPCClass *pc_class;
170 
171   parent_class = g_type_class_ref (gtk_plot_pc_get_type ());
172 
173   object_class = (GtkObjectClass *) klass;
174   gobject_class = (GObjectClass *) klass;
175   pc_class = (GtkPlotPCClass *) klass;
176 
177   pc_class->init = psinit;
178   pc_class->leave = psleave;
179   pc_class->set_viewport = pssetviewport;
180   pc_class->gsave = psgsave;
181   pc_class->grestore = psgrestore;
182   pc_class->clip = psclip;
183   pc_class->clip_mask = psclipmask;
184   pc_class->set_color = pssetcolor;
185   pc_class->set_dash = pssetdash;
186   pc_class->set_lineattr = pssetlineattr;
187   pc_class->draw_point = psdrawpoint;
188   pc_class->draw_line = psdrawline;
189   pc_class->draw_lines = psdrawlines;
190   pc_class->draw_rectangle = psdrawrectangle;
191   pc_class->draw_polygon = psdrawpolygon;
192   pc_class->draw_circle = psdrawcircle;
193   pc_class->draw_ellipse = psdrawellipse;
194   pc_class->set_font = pssetfont;
195   pc_class->draw_string = psdrawstring;
196   pc_class->draw_pixmap = psdrawpixmap;
197 
198   object_class->destroy = gtk_plot_ps_destroy;
199 }
200 
201 static void
gtk_plot_ps_destroy(GtkObject * object)202 gtk_plot_ps_destroy(GtkObject *object)
203 {
204   GtkPlotPS *ps;
205 
206   ps = GTK_PLOT_PS(object);
207 
208   if(ps->psname){
209     g_free(ps->psname);
210     ps->psname = NULL;
211   }
212 }
213 
214 
215 /**
216  * gtk_plot_ps_new:
217  * @psname:
218  * @orientation:
219  * @epsflag:
220  * @page_size:
221  * @scalex:
222  * @scaley:
223  *
224  *
225  *
226  * Return value: a new GtkObject.
227  */
228 GtkObject *
gtk_plot_ps_new(const gchar * psname,gint orientation,gint epsflag,gint page_size,gdouble scalex,gdouble scaley)229 gtk_plot_ps_new                         (const gchar *psname,
230                                          gint orientation,
231                                          gint epsflag,
232                                          gint page_size,
233                                          gdouble scalex,
234 					 gdouble scaley)
235 {
236   GtkObject *object;
237   GtkPlotPS *ps;
238 
239   object = g_object_new(gtk_plot_ps_get_type(), NULL);
240 
241   ps = GTK_PLOT_PS(object);
242 
243   gtk_plot_ps_construct(ps, psname, orientation, epsflag, page_size, scalex, scaley);
244 
245   return (object);
246 }
247 
248 /**
249  * gtk_plot_ps_construct:
250  * @ps: a #GtkPlotPS
251  * @orientation:
252  * @epsflag:
253  * @page_size:
254  * @scalex:
255  * @scaley:
256  *
257  *
258  */
259 void
gtk_plot_ps_construct(GtkPlotPS * ps,const gchar * psname,gint orientation,gint epsflag,gint page_size,gdouble scalex,gdouble scaley)260 gtk_plot_ps_construct                   (GtkPlotPS *ps,
261 					 const gchar *psname,
262                                          gint orientation,
263                                          gint epsflag,
264                                          gint page_size,
265                                          gdouble scalex,
266 					 gdouble scaley)
267 {
268   gint width, height;
269 
270   ps->psname = g_strdup(psname);
271   ps->orientation = orientation;
272   ps->epsflag = epsflag;
273   ps->page_size = page_size;
274   ps->scalex = scalex;
275   ps->scaley = scaley;
276 
277   switch (page_size){
278    case GTK_PLOT_LEGAL:
279         width = GTK_PLOT_LEGAL_W;
280         height = GTK_PLOT_LEGAL_H;
281         break;
282    case GTK_PLOT_A4:
283         width = GTK_PLOT_A4_W;
284         height = GTK_PLOT_A4_H;
285         break;
286    case GTK_PLOT_EXECUTIVE:
287         width = GTK_PLOT_EXECUTIVE_W;
288         height = GTK_PLOT_EXECUTIVE_H;
289         break;
290    case GTK_PLOT_LETTER:
291    default:
292         width = GTK_PLOT_LETTER_W;
293         height = GTK_PLOT_LETTER_H;
294   }
295 
296   gtk_plot_ps_set_size(ps, GTK_PLOT_PSPOINTS, width, height);
297 }
298 
299 /**
300  * gtk_plot_ps_new_with_size:
301  * @psname:
302  * @orientation:
303  * @epsflag:
304  * @units:
305  * @width:
306  * @height:
307  * @scalex:
308  * @scaley:
309  *
310  *
311  *
312  * Return value: a new GtkObject.
313  */
314 GtkObject *
gtk_plot_ps_new_with_size(const gchar * psname,gint orientation,gint epsflag,gint units,gdouble width,gdouble height,gdouble scalex,gdouble scaley)315 gtk_plot_ps_new_with_size                       (const gchar *psname,
316                                                  gint orientation,
317                                                  gint epsflag,
318                                                  gint units,
319                                                  gdouble width, gdouble height,
320 						 gdouble scalex, gdouble scaley)
321 {
322   GtkObject *object;
323   GtkPlotPS *ps;
324 
325   object = g_object_new(gtk_plot_ps_get_type(), NULL);
326 
327   ps = GTK_PLOT_PS(object);
328 
329   gtk_plot_ps_construct_with_size (ps, psname, orientation, epsflag, units, width, height, scalex, scaley);
330 
331   return object;
332 }
333 
334 /**
335  * gtk_plot_ps_construct_with_size:
336  * @ps: a #GtkPlotPS
337  * @psname:
338  * @orientation:
339  * @epsflag:
340  * @units:
341  * @width:
342  * @height:
343  * @scalex:
344  * @scaley:
345  *
346  *
347  */
348 void
gtk_plot_ps_construct_with_size(GtkPlotPS * ps,const gchar * psname,gint orientation,gint epsflag,gint units,gdouble width,gdouble height,gdouble scalex,gdouble scaley)349 gtk_plot_ps_construct_with_size                 (GtkPlotPS *ps,
350 						 const gchar *psname,
351                                                  gint orientation,
352                                                  gint epsflag,
353                                                  gint units,
354                                                  gdouble width, gdouble height,
355 						 gdouble scalex, gdouble scaley)
356 {
357   gtk_plot_ps_construct(ps, psname, orientation, epsflag, GTK_PLOT_CUSTOM, scalex, scaley);
358 
359   gtk_plot_ps_set_size(ps, units, width, height);
360 }
361 
362 /**
363  * gtk_plot_ps_set_size:
364  * @ps: a #GtkPlotPS
365  * @units:
366  * @width:
367  * @height:
368  *
369  *
370  */
371 void
gtk_plot_ps_set_size(GtkPlotPS * ps,gint units,gdouble width,gdouble height)372 gtk_plot_ps_set_size                            (GtkPlotPS *ps,
373                                                  gint units,
374                                                  gdouble width,
375                                                  gdouble height)
376 {
377   ps->units = units;
378   ps->width = width;
379   ps->height = height;
380 
381   switch(units){
382    case GTK_PLOT_MM:
383         ps->page_width = (gdouble)width * 2.835;
384         ps->page_height = (gdouble)height * 2.835;
385         break;
386    case GTK_PLOT_CM:
387         ps->page_width = width * 28.35;
388         ps->page_height = height * 28.35;
389         break;
390    case GTK_PLOT_INCHES:
391         ps->page_width = width * 72;
392         ps->page_height = height * 72;
393         break;
394    case GTK_PLOT_PSPOINTS:
395    default:
396         ps->page_width = width;
397         ps->page_height = height;
398    }
399 
400    if(ps->orientation == GTK_PLOT_PORTRAIT)
401      gtk_plot_pc_set_viewport(GTK_PLOT_PC(ps), ps->page_width, ps->page_height);
402    else
403      gtk_plot_pc_set_viewport(GTK_PLOT_PC(ps), ps->page_height, ps->page_width);
404 }
405 
406 /**
407  * gtk_plot_ps_set_scale:
408  * @ps: a #GtkPlotPS
409  * @scalex:
410  * @scaley:
411  *
412  *
413  */
414 void
gtk_plot_ps_set_scale(GtkPlotPS * ps,gdouble scalex,gdouble scaley)415 gtk_plot_ps_set_scale                           (GtkPlotPS *ps,
416                                                  gdouble scalex,
417                                                  gdouble scaley)
418 {
419   ps->scalex = scalex;
420   ps->scaley = scaley;
421 }
422 
pssetviewport(GtkPlotPC * pc,gdouble w,gdouble h)423 static void pssetviewport			(GtkPlotPC *pc,
424 						 gdouble w, gdouble h)
425 {
426 
427 }
428 
pssetlineattr(GtkPlotPC * pc,gfloat line_width,GdkLineStyle line_style,GdkCapStyle cap_style,GdkJoinStyle join_style)429 static void pssetlineattr			(GtkPlotPC *pc,
430                                                  gfloat line_width,
431                                                  GdkLineStyle line_style,
432                                                  GdkCapStyle cap_style,
433                                                  GdkJoinStyle join_style)
434 {
435     FILE *psout = GTK_PLOT_PS(pc)->psfile;
436 
437     fprintf(psout, "%g slw\n", line_width);
438     fprintf(psout, "%d slc\n", abs(cap_style - 1));
439     fprintf(psout, "%d slj\n", join_style);
440 
441     if(line_style == 0)
442             fprintf(psout,"[] 0 sd\n");  /* solid line */
443 }
444 
445 static void
pssetdash(GtkPlotPC * pc,gdouble offset,gdouble * values,gint num_values)446 pssetdash(GtkPlotPC *pc,
447           gdouble offset,
448           gdouble *values,
449           gint num_values)
450 {
451     FILE *psout = GTK_PLOT_PS(pc)->psfile;
452 
453     switch(num_values){
454       case 0:
455         fprintf(psout,"[] 0 sd\n");
456         break;
457       case 2:
458         fprintf(psout, "[%g %g] %g sd\n", values[0], values[1], offset);
459         break;
460       case 4:
461         fprintf(psout, "[%g %g %g %g] %g sd\n", values[0], values[1],
462                                                 values[2], values[3],
463                                                 offset);
464         break;
465       case 6:
466         fprintf(psout, "[%g %g %g %g %g %g] %g sd\n",  values[0], values[1],
467                                                        values[2], values[3],
468                                                        values[4], values[5],
469                                                        offset);
470         break;
471       default:
472         break;
473     }
474 }
475 
476 static void
psleave(GtkPlotPC * pc)477 psleave(GtkPlotPC *pc)
478 {
479     fprintf(GTK_PLOT_PS(pc)->psfile, "showpage\n");
480     fprintf(GTK_PLOT_PS(pc)->psfile, "%%%%Trailer\n");
481     fprintf(GTK_PLOT_PS(pc)->psfile, "%%%%EOF\n");
482     fclose(GTK_PLOT_PS(pc)->psfile);
483     setlocale(LC_NUMERIC, locale);
484     g_free(locale);
485 }
486 
487 static gboolean
psinit(GtkPlotPC * pc)488 psinit						(GtkPlotPC *pc)
489 {
490     time_t now;
491     FILE *psout;
492     GtkPlotPS *ps;
493 
494     now = time(NULL);
495 
496     locale = g_strdup(setlocale(LC_NUMERIC, NULL));
497     setlocale(LC_NUMERIC, "C");
498 
499     ps = GTK_PLOT_PS(pc);
500     psout = ps->psfile;
501 
502     if ((psout = fopen(ps->psname, "w")) == NULL){
503        g_warning("ERROR: Cannot open file: %s", ps->psname);
504        return FALSE;
505     }
506 
507     ps->psfile = psout;
508 
509     if(ps->epsflag)
510        fprintf (psout, "%%!PS-Adobe-2.0 PCF-2.0\n");
511     else
512        fprintf (psout, "%%!PS-Adobe-2.0\n");
513 
514     fprintf (psout,
515              "%%%%Title: %s\n"
516              "%%%%Creator: %s v%s Copyright (c) 1999 Adrian E. Feiguin\n"
517              "%%%%CreationDate: %s"
518              "%%%%Magnification: 1.0000\n",
519              ps->psname,
520              "GtkPlot", "3.x",
521              ctime (&now));
522 
523     if(ps->orientation == GTK_PLOT_PORTRAIT)
524              fprintf(psout,"%%%%Orientation: Portrait\n");
525     else
526              fprintf(psout,"%%%%Orientation: Landscape\n");
527 
528 /*
529     if(ps->epsflag)
530 */
531           fprintf (psout,
532                    "%%%%BoundingBox: 0 0 %d %d\n"
533                    "%%%%Pages: 1\n"
534                    "%%%%EndComments\n",
535                    ps->page_width,
536                    ps->page_height);
537 
538 
539     fprintf (psout,
540              "/cp {closepath} bind def\n"
541              "/c {curveto} bind def\n"
542              "/f {fill} bind def\n"
543              "/a {arc} bind def\n"
544              "/ef {eofill} bind def\n"
545              "/ex {exch} bind def\n"
546              "/gr {grestore} bind def\n"
547              "/gs {gsave} bind def\n"
548              "/sa {save} bind def\n"
549              "/rs {restore} bind def\n"
550              "/l {lineto} bind def\n"
551              "/m {moveto} bind def\n"
552              "/rm {rmoveto} bind def\n"
553              "/n {newpath} bind def\n"
554              "/s {stroke} bind def\n"
555              "/sh {show} bind def\n"
556              "/slc {setlinecap} bind def\n"
557              "/slj {setlinejoin} bind def\n"
558              "/slw {setlinewidth} bind def\n"
559              "/srgb {setrgbcolor} bind def\n"
560              "/rot {rotate} bind def\n"
561              "/sc {scale} bind def\n"
562              "/sd {setdash} bind def\n"
563              "/ff {findfont} bind def\n"
564              "/sf {setfont} bind def\n"
565              "/scf {scalefont} bind def\n"
566              "/sw {stringwidth pop} bind def\n"
567              "/tr {translate} bind def\n"
568 
569              "/JR {\n"
570              " neg 0\n"
571              " rmoveto\n"
572              "} bind def\n"
573 
574              "/JC {\n"
575              " 2 div neg 0\n"
576              " rmoveto\n"
577              "} bind def\n"
578 
579              "\n/ellipsedict 8 dict def\n"
580              "ellipsedict /mtrx matrix put\n"
581              "/ellipse\n"
582              "{ ellipsedict begin\n"
583              "   /endangle exch def\n"
584              "   /startangle exch def\n"
585              "   /yrad exch def\n"
586              "   /xrad exch def\n"
587              "   /y exch def\n"
588              "   /x exch def"
589              "   /savematrix mtrx currentmatrix def\n"
590              "   x y tr xrad yrad sc\n"
591              "   0 0 1 startangle endangle arc\n"
592              "   savematrix setmatrix\n"
593              "   end\n"
594              "} def\n\n"
595     );
596 
597     fprintf(psout,
598           "[ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
599           "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
600           "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
601           "/.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright\n"
602           "/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one\n"
603           "/two /three /four /five /six /seven /eight /nine /colon /semicolon\n"          "/less /equal /greater /question /at /A /B /C /D /E\n"
604           "/F /G /H /I /J /K /L /M /N /O\n"
605           "/P /Q /R /S /T /U /V /W /X /Y\n"
606           "/Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c\n"
607           "/d /e /f /g /h /i /j /k /l /m\n"
608           "/n /o /p /q /r /s /t /u /v /w\n"
609           "/x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef\n"
610           "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
611           "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
612           "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
613           "/space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright\n"
614           "/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior\n"
615           "/acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf\n"
616           "/threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n"
617           "/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde\n"
618           "/Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex\n"
619           "/Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring\n"
620           "/ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis\n"
621           "/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave\n"
622           "/uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def\n");
623 
624     ps_reencode_font(psout, "Times-Roman");
625     ps_reencode_font(psout, "Times-Italic");
626     ps_reencode_font(psout, "Times-Bold");
627     ps_reencode_font(psout, "Times-BoldItalic");
628     ps_reencode_font(psout, "AvantGarde-Book");
629     ps_reencode_font(psout, "AvantGarde-BookOblique");
630     ps_reencode_font(psout, "AvantGarde-Demi");
631     ps_reencode_font(psout, "AvantGarde-DemiOblique");
632     ps_reencode_font(psout, "Bookman-Light");
633     ps_reencode_font(psout, "Bookman-LightItalic");
634     ps_reencode_font(psout, "Bookman-Demi");
635     ps_reencode_font(psout, "Bookman-DemiItalic");
636     ps_reencode_font(psout, "Courier");
637     ps_reencode_font(psout, "Courier-Oblique");
638     ps_reencode_font(psout, "Courier-Bold");
639     ps_reencode_font(psout, "Courier-BoldOblique");
640     ps_reencode_font(psout, "Helvetica");
641     ps_reencode_font(psout, "Helvetica-Oblique");
642     ps_reencode_font(psout, "Helvetica-Bold");
643     ps_reencode_font(psout, "Helvetica-BoldOblique");
644     ps_reencode_font(psout, "Helvetica-Narrow");
645     ps_reencode_font(psout, "Helvetica-Narrow-Oblique");
646     ps_reencode_font(psout, "Helvetica-Narrow-Bold");
647     ps_reencode_font(psout, "Helvetica-Narrow-BoldOblique");
648     ps_reencode_font(psout, "NewCenturySchoolbook-Roman");
649     ps_reencode_font(psout, "NewCenturySchoolbook-Italic");
650     ps_reencode_font(psout, "NewCenturySchoolbook-Bold");
651     ps_reencode_font(psout, "NewCenturySchoolbook-BoldItalic");
652     ps_reencode_font(psout, "Palatino-Roman");
653     ps_reencode_font(psout, "Palatino-Italic");
654     ps_reencode_font(psout, "Palatino-Bold");
655     ps_reencode_font(psout, "Palatino-BoldItalic");
656     ps_reencode_font(psout, "Symbol");
657     ps_reencode_font(psout, "ZapfChancery-MediumItalic");
658     ps_reencode_font(psout, "ZapfDingbats");
659 
660     fprintf(psout,"%%%%EndProlog\n%%%%BeginSetup\n"
661                 "%%%%PageBoundingBox: 0 0 %d %d\n"
662                 "%%%%PageOrientation: %s\n"
663                 "%%%%PaperSize: %d %d\n",
664                  ps->page_width,
665                  ps->page_height,
666                 (ps->orientation == GTK_PLOT_PORTRAIT) ? "Portrait":"Landscape",
667                  ps->page_width,
668                  ps->page_height);
669 
670     if(ps->orientation == GTK_PLOT_PORTRAIT)
671              fprintf(psout, "%g %g scale\n",
672                             ps->scalex, ps->scaley);
673 
674     if(ps->orientation == GTK_PLOT_LANDSCAPE)
675              fprintf(psout, "%g %g scale\n"
676                             "90 rotate \n"
677                             "0 %d translate\n",
678                             ps->scalex, ps->scaley,
679                             -ps->page_height);
680 
681     fprintf(psout,"%%%%EndSetup\n\n\n");
682 
683     return TRUE;
684 }
685 
ps_reencode_font(FILE * file,char * fontname)686 static void ps_reencode_font(FILE *file, char *fontname)
687 {
688   /* Don't reencode the Symbol font, as it doesn't work in latin1 encoding.
689    * Instead, just define Symbol-latin1 to be the same as Symbol. */
690   if (!strcmp(fontname, "Symbol"))
691     fprintf(file,
692             "/%s-latin1\n"
693             "    /%s findfont\n"
694             "definefont pop\n", fontname, fontname);
695   else
696     fprintf(file,
697             "/%s-latin1\n"
698             "    /%s findfont\n"
699             "    dup length dict begin\n"
700             "   {1 index /FID ne {def} {pop pop} ifelse} forall\n"
701             "   /Encoding isolatin1encoding def\n"
702             "    currentdict end\n"
703             "definefont pop\n", fontname, fontname);
704 }
705 
pssetcolor(GtkPlotPC * pc,const GdkColor * color)706 static void pssetcolor(GtkPlotPC *pc, const GdkColor *color)
707 {
708     FILE *psout = GTK_PLOT_PS(pc)->psfile;
709 
710     fprintf(psout, "%g %g %g setrgbcolor\n",
711 	    (gdouble) color->red / 65535.0,
712 	    (gdouble) color->green / 65535.0,
713 	    (gdouble) color->blue / 65535.0);
714 }
715 
716 static void
psdrawpoint(GtkPlotPC * pc,gdouble x,gdouble y)717 psdrawpoint(GtkPlotPC *pc, gdouble x, gdouble y)
718 {
719   FILE *psout = GTK_PLOT_PS(pc)->psfile;
720 
721   y = GTK_PLOT_PS(pc)->page_height - y;
722   fprintf(psout, "n\n");
723   fprintf(psout, "%g %g m\n", x, y);
724   fprintf(psout, "%g %g l\n", x, y);
725   fprintf(psout, "s\n");
726 }
727 
728 static void
psdrawlines(GtkPlotPC * pc,GtkPlotPoint * points,gint numpoints)729 psdrawlines(GtkPlotPC *pc, GtkPlotPoint *points, gint numpoints)
730 {
731   gint i, page_height = GTK_PLOT_PS(pc)->page_height;
732   FILE *psout = GTK_PLOT_PS(pc)->psfile;
733 
734   fprintf(psout,"n\n");
735   fprintf(psout,"%g %g m\n", points[0].x, page_height - points[0].y);
736   for(i = 1; i < numpoints; i++)
737         fprintf(psout,"%g %g l\n", points[i].x, page_height - points[i].y);
738 
739   fprintf(psout,"s\n");
740 }
741 
742 static void
psdrawpolygon(GtkPlotPC * pc,gboolean filled,GtkPlotPoint * points,gint numpoints)743 psdrawpolygon(GtkPlotPC *pc, gboolean filled, GtkPlotPoint *points, gint numpoints)
744 {
745   gint i, page_height = GTK_PLOT_PS(pc)->page_height;
746   FILE *psout = GTK_PLOT_PS(pc)->psfile;
747 
748   fprintf(psout,"n\n");
749   fprintf(psout,"%g %g m\n", points[0].x, page_height - points[0].y);
750   for(i = 1; i < numpoints; i++)
751       fprintf(psout,"%g %g l\n", points[i].x, page_height - points[i].y);
752 
753   if(filled)
754      fprintf(psout,"f\n");
755   else
756      fprintf(psout,"cp\n");
757 
758   fprintf(psout,"s\n");
759 }
760 
psdrawline(GtkPlotPC * pc,gdouble x0,gdouble y0,gdouble xf,gdouble yf)761 static void psdrawline(GtkPlotPC *pc, gdouble x0, gdouble y0, gdouble xf, gdouble yf)
762 {
763   FILE *psout = GTK_PLOT_PS(pc)->psfile;
764 
765   fprintf(psout, "%g %g m\n", x0, GTK_PLOT_PS(pc)->page_height - y0);
766   fprintf(psout, "%g %g l\n", xf, GTK_PLOT_PS(pc)->page_height - yf);
767   fprintf(psout, "s\n");
768 }
769 
770 static void
psdrawrectangle(GtkPlotPC * pc,gboolean filled,gdouble x,gdouble y,gdouble width,gdouble height)771 psdrawrectangle(GtkPlotPC *pc, gboolean filled,
772                 gdouble x, gdouble y, gdouble width, gdouble height)
773 {
774   GtkPlotPoint point[4];
775 
776   point[0].x = x;
777   point[0].y = y;
778   point[1].x = x + width;
779   point[1].y = y;
780   point[2].x = x + width;
781   point[2].y = y + height;
782   point[3].x = x;
783   point[3].y = y + height;
784 
785   psdrawpolygon(pc, filled, point, 4);
786 }
787 
788 static void
psdrawcircle(GtkPlotPC * pc,gboolean filled,gdouble x,gdouble y,gdouble size)789 psdrawcircle(GtkPlotPC *pc, gboolean filled, gdouble x, gdouble y, gdouble size)
790 {
791   FILE *psout = GTK_PLOT_PS(pc)->psfile;
792 
793   y = GTK_PLOT_PS(pc)->page_height - y;
794   fprintf(psout,"n %g %g %g %g 0 360 ellipse\n",
795           x, y, size / 2., size / 2.);
796 
797   if(filled)
798      fprintf(psout,"f\n");
799 
800   fprintf(psout,"s\n");
801 }
802 
803 static void
psdrawellipse(GtkPlotPC * pc,gboolean filled,gdouble x,gdouble y,gdouble width,gdouble height)804 psdrawellipse(GtkPlotPC *pc,
805               gboolean filled,
806               gdouble x, gdouble y,
807               gdouble width, gdouble height)
808 {
809   FILE *psout = GTK_PLOT_PS(pc)->psfile;
810 
811   y = GTK_PLOT_PS(pc)->page_height - y;
812   fprintf(psout,"n %g %g %g %g 0 360 ellipse\n",
813           x+width/2., y-height/2.,
814           width/2., height/2.);
815 
816   if(filled)
817      fprintf(psout,"f\n");
818 
819   fprintf(psout,"s\n");
820 }
821 
822 static void
psoutputstring(GtkPlotPC * pc,GtkPSFont * psfont,GtkPSFont * latin_psfont,gint height,const gchar * wstring,const gchar * addstring)823 psoutputstring (GtkPlotPC *pc,
824 		GtkPSFont *psfont,
825 		GtkPSFont *latin_psfont,
826 		gint height,
827 		const gchar *wstring,
828 		const gchar *addstring)
829 {
830   const gchar *p;
831   gint curcode = 0;
832   gchar begin[] = { 0, '(', '<' };
833   gchar end[] = { 0, ')', '>' };
834   GtkPSFont *fonts[3];
835   FILE *out = GTK_PLOT_PS(pc)->psfile;
836   const gchar *c = NULL;
837 
838   fonts[0] = NULL;
839   fonts[1] = latin_psfont;
840   fonts[2] = psfont;
841 
842   p = wstring;
843 
844   if (psfont->i18n_latinfamily) {
845     gint code;  /* 0..neither 1..latin 2..i18n */
846     gchar wcs[2];
847     while (*p) {
848       code = (*p >= 0 && *p <= 0x7f) ? 1 : 2;
849       if (curcode && curcode != code)
850 	fprintf(out, "%c %s\n", end[curcode], addstring);
851       if (curcode != code) {
852 	pssetfont(pc, fonts[code], height);
853 	fputc(begin[code], out);
854       }
855 
856       curcode = code;
857 
858       wcs[0] = *p++;
859       wcs[1] = 0;
860       c = wcs;
861 
862       if (code == 2) {
863 	while (*c)
864 	  fprintf(out, "%02x", (unsigned char)(*c++));
865       } else {
866 	if (*c == '(' || *c == ')')
867 	  fputc('\\', out);
868 	fputc(*c, out);
869       }
870     }
871   } else {
872     c = wstring;
873 
874     pssetfont(pc, psfont, height);
875     fputc(begin[1], out);
876     curcode = 1;
877 
878     while (*c) {
879       const gchar *aux2 = c;
880       if (*c == '(' || *c == ')')
881 	fputc('\\', out);
882 
883       if(++aux2 != g_utf8_next_char(c)){
884         fprintf(out, ") show <%02x> show (", (unsigned char)(*++c));
885         c++;
886       } else {
887         fputc(*c, out);
888         c = g_utf8_next_char(c);
889       }
890     }
891   }
892 
893   if (curcode)
894     fprintf(out, "%c %s\n", end[curcode], addstring);
895 }
896 
897 static void
psdrawstring(GtkPlotPC * pc,gint x,gint y,gint angle,const GdkColor * fg,const GdkColor * bg,gboolean transparent,gint border,gint border_space,gint border_width,gint shadow_width,const gchar * font,gint font_height,GtkJustification justification,const gchar * text)898 psdrawstring	(GtkPlotPC *pc,
899              	 gint x, gint y,
900                  gint angle,
901                  const GdkColor *fg,
902                  const GdkColor *bg,
903                  gboolean transparent,
904                  gint border,
905                  gint border_space,
906                  gint border_width,
907                  gint shadow_width,
908                  const gchar *font,
909                  gint font_height,
910                  GtkJustification justification,
911                  const gchar *text)
912 
913 {
914   gchar *currfont;
915   const gchar *c;
916   GtkPSFont *psfont, *base_psfont, *latin_psfont = NULL;
917   gint curcnt = 0, offset = 0;
918   gint numf;
919   gdouble scale;
920   gboolean italic, bold;
921   gboolean special = FALSE;
922   GList *family;
923   FILE *psout;
924   gint twidth, theight, tdescent, tascent;
925   gint tx, ty, width, height;
926   gint i;
927   const gchar *aux, *xaux, *wtext, *lastchar = NULL;
928   gchar *curstr, bkspchar[3];
929   gchar num[4];
930 
931   if (text == NULL || strlen(text) == 0) return;
932 
933   psout = GTK_PLOT_PS(pc)->psfile;
934 
935   gtk_psfont_get_families(&family, &numf);
936   base_psfont = psfont = gtk_psfont_get_by_name(font);
937   italic = psfont->italic;
938   bold = psfont->bold;
939 
940   currfont = psfont->psname;
941 
942   if (psfont->i18n_latinfamily) {
943     latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic,
944 					    bold);
945   }
946 
947   gtk_plot_text_get_area(text, angle, justification, font, font_height,
948                          &tx, &ty, &width, &height);
949 
950   tx += x;
951   ty += y;
952 
953   if(!transparent){
954     pssetcolor(pc, bg);
955     gtk_plot_pc_draw_rectangle(pc,
956                          TRUE,
957                          tx - border_space, ty - border_space,
958                          width + 2*border_space, height + 2*border_space);
959   }
960 /* border */
961 
962   pssetcolor(pc, fg);
963   pssetdash(pc, 0, NULL, 0);
964   pssetlineattr(pc, border_width, 0, 0, 0);
965 
966   switch(border){
967     case GTK_PLOT_BORDER_SHADOW:
968       psdrawrectangle(pc,
969                          TRUE,
970                          tx - border_space + shadow_width,
971                          ty + height + border_space,
972                          width + 2 * border_space, shadow_width);
973       psdrawrectangle(pc,
974                          TRUE,
975                          tx + width + border_space,
976                          ty - border_space + shadow_width,
977                          shadow_width, height + 2 * border_space);
978     case GTK_PLOT_BORDER_LINE:
979       psdrawrectangle(pc,
980                          FALSE,
981                          tx - border_space, ty - border_space,
982                          width + 2*border_space, height + 2*border_space);
983     case GTK_PLOT_BORDER_NONE:
984     default:
985         break;
986   }
987 
988 
989   gtk_plot_text_get_size(text, angle, psfont->psname, font_height,
990                          &twidth, &theight, &tascent, &tdescent);
991 
992   psgsave(pc);
993   fprintf(psout, "%d %d translate\n", x, GTK_PLOT_PS(pc)->page_height - y);
994   fprintf(psout, "%d rotate\n", angle);
995 
996   fprintf(psout, "0 0 m\n");
997 
998   if (psfont->i18n_latinfamily)
999     special = TRUE;
1000 
1001   c = text;
1002   while(c && *c != '\0' && *c != '\n') {
1003      if(*c == '\\'){
1004          c = g_utf8_next_char(c);
1005          switch(*c){
1006            case '0': case '1': case '2': case '3':
1007            case '4': case '5': case '6': case '7': case '9':
1008            case '8': case'g': case 'B': case 'b': case 'x': case 'N':
1009            case 's': case 'S': case 'i': case '-': case '+': case '^':
1010              special = TRUE;
1011              break;
1012            default:
1013              break;
1014          }
1015      } else {
1016          c = g_utf8_next_char(c);
1017      }
1018   }
1019 
1020   if(special){
1021     switch (justification) {
1022       case GTK_JUSTIFY_LEFT:
1023         break;
1024       case GTK_JUSTIFY_RIGHT:
1025         if(angle == 0 || angle == 180)
1026                fprintf(psout, "%d JR\n", twidth);
1027         else
1028                fprintf(psout, "%d JR\n", theight);
1029         break;
1030       case GTK_JUSTIFY_CENTER:
1031       default:
1032         if(angle == 0 || angle == 180)
1033                fprintf(psout, "%d JC\n", twidth);
1034         else
1035                fprintf(psout, "%d JC\n", theight);
1036         break;
1037     }
1038   } else {
1039     pssetfont(pc, psfont, font_height);
1040 
1041     switch (justification) {
1042       case GTK_JUSTIFY_LEFT:
1043         break;
1044       case GTK_JUSTIFY_RIGHT:
1045         fprintf(psout, "(%s) sw JR\n", text);
1046         break;
1047       case GTK_JUSTIFY_CENTER:
1048       default:
1049         fprintf(psout, "(%s) sw JC\n", text);
1050         break;
1051     }
1052     fprintf(psout, "(%s) show\n", text);
1053 
1054     psgrestore(pc);
1055     fprintf(psout, "n\n");
1056     return;
1057   }
1058 
1059   i = g_utf8_strlen(text, -1) + 2;
1060   curstr = g_malloc0(sizeof(gchar) * i);
1061   aux = wtext = text;
1062 
1063   scale = font_height;
1064   curcnt = 0;
1065 
1066   while(aux && *aux != '\0' && *aux != '\n') {
1067      if(*aux == '\\'){
1068          aux = g_utf8_next_char(aux);
1069          switch(*aux){
1070            case '0': case '1': case '2': case '3':
1071            case '4': case '5': case '6': case '7': case '9':
1072                   curstr[curcnt] = 0;
1073 		  psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1074 				 curstr, "show");
1075                   curcnt = 0;
1076                   psfont = gtk_psfont_get_by_family((gchar *)g_list_nth_data(family, *aux-'0'), italic, bold);
1077 		  aux = g_utf8_next_char(aux);
1078                   break;
1079            case '8':case 'g':
1080                   curstr[curcnt] = 0;
1081                   psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1082 				 curstr, "show");
1083                   curcnt = 0;
1084                   psfont = gtk_psfont_get_by_family("Symbol", italic, bold);
1085                   aux = g_utf8_next_char(aux);
1086                   break;
1087            case 'B':
1088                   curstr[curcnt] = 0;
1089                   psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1090 				 curstr, "show");
1091                   curcnt = 0;
1092   		  bold = TRUE;
1093                   psfont = gtk_psfont_get_by_family(psfont->family, italic, bold);
1094 		  if (psfont->i18n_latinfamily)
1095 		    latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic, bold);
1096 		  aux = g_utf8_next_char(aux);
1097                   break;
1098            case 'x':
1099                   xaux = aux + 1;
1100                   for (i=0; i<3; i++){
1101 		    if (xaux[i] >= '0' && xaux[i] <= '9')
1102 		      num[i] = xaux[i];
1103 		    else
1104 		      break;
1105                   }
1106                   if (i < 3){
1107                      aux = g_utf8_next_char(aux);
1108                      break;
1109                   }
1110                   num[3] = '\0';
1111 
1112 		  i = atoi(num);
1113 		  g_snprintf(num, 4, "%o", i % (64 * 8));
1114 
1115 		  curstr[curcnt++] = '\\';
1116 		  i = 0;
1117 		  while (num[i]) {
1118 		    curstr[curcnt++] = num[i++];
1119 		  }
1120 
1121                   aux += 4;
1122                   break;
1123            case 'i':
1124 	          curstr[curcnt] = 0;
1125                   psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1126 				 curstr, "show");
1127                   curcnt = 0;
1128 		  italic = TRUE;
1129                   psfont = gtk_psfont_get_by_family(psfont->family, italic, bold);
1130 		  if (psfont->i18n_latinfamily)
1131 		    latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic, bold);
1132 		  aux = g_utf8_next_char(aux);
1133                   break;
1134            case 's':case '_':
1135                   curstr[curcnt] = 0;
1136                   psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1137 				 curstr, "show");
1138                   curcnt = 0;
1139                   scale = 0.6 * font_height;
1140 		  offset -= (gint)scale / 2;
1141                   fprintf(psout, "0 %d rmoveto\n", -((gint)scale / 2));
1142                   aux = g_utf8_next_char(aux);
1143                   break;
1144            case 'S':case '^':
1145                   curstr[curcnt] = 0;
1146                   psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1147 				 curstr, "show");
1148                   curcnt = 0;
1149                   scale = 0.6 * font_height;
1150 		  offset += 0.5*font_height;
1151                   fprintf(psout, "0 %d rmoveto\n", (gint)(0.5*font_height));
1152                   aux = g_utf8_next_char(aux);
1153                   break;
1154            case 'N':
1155                   curstr[curcnt] = 0;
1156                   psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1157 				 curstr, "show");
1158                   curcnt = 0;
1159 		  psfont = base_psfont;
1160 		  italic = psfont->italic;
1161 		  bold = psfont->bold;
1162 		  if (psfont->i18n_latinfamily) {
1163 		    latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily,
1164 							     italic, bold);
1165 		  }
1166                   scale = font_height;
1167                   fprintf(psout, "0 %d rmoveto\n", -offset);
1168                   offset = 0;
1169                   aux = g_utf8_next_char(aux);
1170                   break;
1171            case 'b':
1172                   curstr[curcnt] = '\0';
1173                   psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1174 				 curstr, "show");
1175                   curcnt = 0;
1176                   if (lastchar) {
1177                       const gchar *aux2 = lastchar;
1178                       bkspchar[0] = *lastchar;
1179                       lastchar = g_utf8_prev_char(lastchar);
1180 		      bkspchar[1] = 0;
1181                       if(--aux2 != lastchar){
1182                         bkspchar[1] = *lastchar;
1183                         lastchar = g_utf8_prev_char(lastchar);
1184 		        bkspchar[2] = 0;
1185                       }
1186                   } else {
1187                       bkspchar[0] = 'X';
1188                       lastchar = NULL;
1189                   }
1190 		  psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1191 				 bkspchar,
1192 				 "stringwidth pop 0 exch neg exch rmoveto");
1193                   aux = g_utf8_next_char(aux);
1194                   break;
1195            case '-':
1196                   curstr[curcnt] = 0;
1197 		  psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1198 				 curstr, "show");
1199                   curcnt = 0;
1200                   scale -= 3;
1201                   if (scale < 6) {
1202                       scale = 6;
1203                   }
1204                   aux = g_utf8_next_char(aux);
1205                   break;
1206            case '+':
1207                   curstr[curcnt] = 0;
1208 		  psoutputstring(pc, psfont, latin_psfont, (gint)scale,
1209 				 curstr, "show");
1210                   curcnt = 0;
1211                   scale += 3;
1212                   aux = g_utf8_next_char(aux);
1213                   break;
1214            default:
1215                   if(aux && *aux != '\0' && *aux != '\n'){
1216                     curstr[curcnt++] = *aux;
1217                     aux = g_utf8_next_char(aux);
1218                   }
1219                   break;
1220          }
1221      } else {
1222        if(aux && *aux != '\0' && *aux != '\n'){
1223                 const gchar *aux2 = aux;
1224                 if(g_utf8_next_char(aux) != ++aux2){
1225                   curstr[curcnt++] = *aux++;
1226 //                  aux = g_utf8_next_char(aux);
1227                   curstr[curcnt++] = *aux++;
1228                 } else {
1229                   curstr[curcnt++] = *aux;
1230 		  lastchar = aux;
1231                   aux = g_utf8_next_char(aux);
1232                 }
1233        }
1234      }
1235   }
1236   curstr[curcnt] = 0;
1237   psoutputstring(pc, psfont, latin_psfont, (gint)scale, curstr, "show");
1238 
1239   psgrestore(pc);
1240   fprintf(psout, "n\n");
1241 
1242   g_free(curstr);
1243 }
1244 
1245 static void
pssetfont(GtkPlotPC * pc,GtkPSFont * psfont,gint height)1246 pssetfont(GtkPlotPC *pc, GtkPSFont *psfont, gint height)
1247 {
1248   FILE *psout = GTK_PLOT_PS(pc)->psfile;
1249 
1250   if (psfont->i18n_latinfamily && psfont->vertical)
1251     fprintf(psout,
1252 	    "/%s ff [0 1 -1 0 0 0.3] makefont [%d 0 0 %d 0 0] makefont sf\n",
1253 	    psfont->psname, height, height);
1254   else
1255     fprintf(psout, "/%s-latin1 ff %g scf sf\n", psfont->psname, (double)height);
1256 
1257 }
1258 
1259 
1260 static void
psgsave(GtkPlotPC * pc)1261 psgsave(GtkPlotPC *pc)
1262 {
1263   GtkPlotPS *ps;
1264   FILE *psout;
1265 
1266   ps = GTK_PLOT_PS(pc);
1267 
1268   psout = ps->psfile;
1269 
1270   fprintf(psout,"gsave\n");
1271   ps->gsaved = TRUE;
1272 }
1273 
1274 static void
psgrestore(GtkPlotPC * pc)1275 psgrestore(GtkPlotPC *pc)
1276 {
1277   GtkPlotPS *ps;
1278   FILE *psout;
1279 
1280   ps = GTK_PLOT_PS(pc);
1281 
1282   psout = ps->psfile;
1283 
1284 /*
1285   if(!ps->gsaved) return;
1286 */
1287 
1288   fprintf(psout,"grestore\n");
1289   ps->gsaved = FALSE;
1290 }
1291 
1292 static void
psclipmask(GtkPlotPC * pc,gdouble x,gdouble y,const GdkBitmap * mask)1293 psclipmask(GtkPlotPC *pc, gdouble x, gdouble y, const GdkBitmap *mask)
1294 {
1295   FILE *psout = GTK_PLOT_PS(pc)->psfile;
1296   gint width, height;
1297   gint px, py;
1298   gint npoints = 0;
1299   gint i, page_height = GTK_PLOT_PS(pc)->page_height;
1300   GtkPlotVector *points;
1301   GdkImage *image;
1302 
1303   if(!mask){
1304     fprintf(psout,"grestore\n");
1305     return;
1306   }
1307 
1308   gdk_window_get_size((GdkWindow *)mask, &width, &height);
1309   image = gdk_image_get((GdkWindow *)mask, 0, 0, width, height);
1310 
1311   points = (GtkPlotVector *)g_malloc(width*height*sizeof(GtkPlotVector));
1312 
1313   for(px = 0; px < width; px++){
1314     for(py = 0; py < height; py++){
1315       if(gdk_image_get_pixel(image, px, py)){
1316         points[npoints].x = px;
1317         points[npoints].y = py;
1318         npoints++;
1319         break;
1320       }
1321     }
1322   }
1323   for(py = points[npoints-1].y; py < height; py++){
1324     for(px = width - 1; px >= 0; px--){
1325       if(gdk_image_get_pixel(image, px, py)){
1326         points[npoints].x = px;
1327         points[npoints].y = py;
1328         npoints++;
1329         break;
1330       }
1331     }
1332   }
1333   for(px = points[npoints-1].x; px >= 0; px--){
1334     for(py = height - 1; py >= 0; py--){
1335       if(gdk_image_get_pixel(image, px, py)){
1336         points[npoints].x = px;
1337         points[npoints].y = py;
1338         npoints++;
1339         break;
1340       }
1341     }
1342   }
1343   for(py = points[npoints-1].y; py >= 0; py--){
1344     for(px = 0; px < width; px++){
1345       if(gdk_image_get_pixel(image, px, py)){
1346         points[npoints].x = px;
1347         points[npoints].y = py;
1348         npoints++;
1349         break;
1350       }
1351     }
1352   }
1353 
1354   fprintf(psout,"gsave\n");
1355 
1356   fprintf(psout,"n\n");
1357   fprintf(psout,"%g %g m\n", x + points[0].x, page_height - y - points[0].y);
1358   for(i = 1; i < npoints; i++)
1359       fprintf(psout,"%g %g l\n", x + points[i].x, page_height - y - points[i].y);
1360 
1361   fprintf(psout,"cp\n");
1362 
1363   fprintf(psout,"clip\n");
1364 
1365   g_free(points);
1366   gdk_image_destroy(image);
1367 }
1368 
1369 static void
psclip(GtkPlotPC * pc,const GdkRectangle * clip)1370 psclip(GtkPlotPC *pc, const GdkRectangle *clip)
1371 {
1372   FILE *psout = GTK_PLOT_PS(pc)->psfile;
1373 
1374   if(!clip){
1375     fprintf(psout,"grestore\n");
1376     return;
1377   }
1378 
1379   fprintf(psout,"gsave\n");
1380   fprintf(psout,"%d %d %d %d rectclip\n",
1381                   clip->x,
1382                   GTK_PLOT_PS(pc)->page_height - clip->y - clip->height,
1383                   clip->width,
1384                   clip->height);
1385 }
1386 
1387 /* TODO: FIXME */
1388 
1389 static void
psdrawpixmap(GtkPlotPC * pc,GdkPixmap * pixmap,GdkBitmap * mask,gint xsrc,gint ysrc,gint xdest,gint ydest,gint width,gint height,gdouble scale_x,gdouble scale_y)1390 psdrawpixmap  (GtkPlotPC *pc,
1391                GdkPixmap *pixmap,
1392                GdkBitmap *mask,
1393                gint xsrc, gint ysrc,
1394                gint xdest, gint ydest,
1395                gint width, gint height,
1396                gdouble scale_x, gdouble scale_y)
1397 {
1398   FILE *psout = GTK_PLOT_PS(pc)->psfile;
1399   GdkColormap *colormap;
1400 
1401   colormap = gdk_colormap_get_system ();
1402 
1403   fprintf(psout, "gsave\n");
1404   if(pixmap){
1405     GdkImage *image;
1406     gint x, y;
1407 
1408     image = gdk_image_get(pixmap,
1409                           xsrc, ysrc,
1410                           width, height);
1411 
1412     if(mask) gtk_plot_pc_clip_mask(pc, xdest, ydest, mask);
1413     ydest = GTK_PLOT_PS(pc)->page_height - ydest - height * scale_y;
1414 
1415     fprintf(psout, "%d %g translate\n", xdest, ydest + height * scale_y);
1416     fprintf(psout, "%g %g scale\n",width * scale_x, height * scale_y);
1417     fprintf(psout, "%d %d 8 [%d 0 0 %d 0 %d]\n",width, height, width, height, height);
1418     fprintf(psout, "/scanline %d 3 mul string def\n", width);
1419     fprintf(psout, "{ currentfile scanline readhexstring pop } false 3\n");
1420     fprintf(psout, "colorimage\n");
1421 
1422     for(y = height - 1; y >= 0; y--){
1423       for(x = 0; x < width; x++){
1424         GdkColor color;
1425         gchar string[7];
1426 
1427         color.pixel = gdk_image_get_pixel(image, x, y);
1428 	gdk_colormap_query_color(colormap, color.pixel, &color);
1429         color_to_hex(color, string);
1430         fprintf(psout,"%s",string);
1431         if(fmod(x + 1, 13) == 0) fprintf(psout, "\n");
1432       }
1433       fprintf(psout,"\n");
1434     }
1435 
1436     gdk_image_destroy(image);
1437     if(mask) gtk_plot_pc_clip_mask(pc, xdest, ydest, NULL);
1438   }
1439 
1440   fprintf(psout, "grestore\n");
1441 }
1442 
1443 static void
color_to_hex(GdkColor color,gchar string[7])1444 color_to_hex(GdkColor color, gchar string[7])
1445 {
1446   gint n;
1447   gint aux;
1448 
1449   aux = color.red / 256;
1450   n=aux/16;
1451   aux-=n*16;
1452   if(n < 10)
1453     string[0]='0'+n;
1454   else
1455     string[0]='A'+n-10;
1456   n = aux;
1457   if(n < 10)
1458     string[1]='0'+n;
1459   else
1460     string[1]='A'+n-10;
1461 
1462   aux = color.green / 256;
1463   n=aux/16;
1464   aux-=n*16;
1465   if(n < 10)
1466     string[2]='0'+n;
1467   else
1468     string[2]='A'+n-10;
1469   n = aux;
1470   if(n < 10)
1471     string[3]='0'+n;
1472   else
1473     string[3]='A'+n-10;
1474 
1475   aux = color.blue / 256;
1476   n=aux/16;
1477   aux-=n*16;
1478   if(n < 10)
1479     string[4]='0'+n;
1480   else
1481     string[4]='A'+n-10;
1482   n = aux;
1483   if(n < 10)
1484     string[5]='0'+n;
1485   else
1486     string[5]='A'+n-10;
1487 
1488   string[6]='\0';
1489 }
1490 
1491 
1492