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