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