source: tags/initial/fig2dev/dev/genps.c

Last change on this file was 2, checked in by oldcode, 24 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.2 KB
Line 
1/*
2 * TransFig: Facility for Translating Fig code
3 * Copyright (c) 1985 Supoj Sutantavibul
4 * Copyright (c) 1991 Micah Beck
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation. The authors make no representations about the suitability
11 * of this software for any purpose.  It is provided "as is" without express
12 * or implied warranty.
13 *
14 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 */
23
24/*
25 *      genps.c: PostScript driver for fig2dev
26 *
27 *      Modified by Herbert Bauer to support ISO-Characters,
28 *      multiple page output, color mode etc.
29 *      heb@regent.e-technik.tu-muenchen.de
30 *
31 *      Modified by Eric Picheral to support the whole set of ISO-Latin-1
32 *      Modified by Herve Soulard to allow non-iso coding on special fonts
33 *      Herve.Soulard@inria.fr (8 Apr 1993)
34
35*/
36
37#include <sys/param.h>
38#if defined(hpux) || defined(SYSV) || defined(BSD4_3)
39#include <sys/types.h>
40#endif
41#include <sys/file.h>
42#include <stdio.h>
43#include <math.h>
44#include <pwd.h>
45#include <errno.h>
46
47#if !defined(LINUX) && !defined(linux)
48extern char *sys_errlist[]; 
49#endif
50
51#include "pi.h"
52#include "object.h"
53#include "fig2dev.h"
54#include "psfonts.h"
55//#include <string.h>
56#include <time.h>
57
58/* for the version nubmer */
59#include "../patchlevel.h"
60
61#ifdef A4
62#define         PAGE_WIDTH              595     /* points; 21cm */
63#define         PAGE_HEIGHT             842     /* points; 29.7cm */
64#else
65#define         PAGE_WIDTH              612     /* points; 8.5" */
66#define         PAGE_HEIGHT             792     /* points; 11" */
67#endif
68#define         TRUE                    1
69#define         FALSE                   0
70#define         POINT_PER_INCH          72
71#define         ULIMIT_FONT_SIZE        300
72#define         MAXCOLORS               16
73
74int             pagewidth = PAGE_WIDTH;
75int             pageheight = PAGE_HEIGHT;
76static int      coord_system;
77int             show_page = 0;
78static int      cur_thickness;
79int             center = 0;
80int             landscape = 0;
81int             pages;
82int             no_obj = 0;
83int             multi_page = FALSE;
84
85extern  int     v2_flag, v21_flag;
86
87static  arc_tangent();
88static  draw_arrow_head();
89static  fill_area();
90static  iso_text_exist();
91static  encode_all_fonts();
92static  ellipse_exist();
93static  normal_spline_exist();
94
95#define GRAYVAL(F)      ((F) <= 21 ? ((F)-1)/20.0 : 1.0)
96
97#define         BEGIN_PROLOG    "\
98/$F2psDict 200 dict def \n\
99$F2psDict begin\n\
100$F2psDict /mtrx matrix put\n\
101/l {lineto} bind def\n\
102/m {moveto} bind def\n\
103/s {stroke} bind def\n\
104/n {newpath} bind def\n\
105/gs {gsave} bind def\n\
106/gr {grestore} bind def\n\
107/clp {closepath} bind def\n\
108/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul\n\
1094 -2 roll mul setrgbcolor} bind def\n\
110/col-1 {} def\n\
111/col0 {0 0 0 setrgbcolor} bind def\n\
112/col1 {0 0 1 setrgbcolor} bind def\n\
113/col2 {0 1 0 setrgbcolor} bind def\n\
114/col3 {0 1 1 setrgbcolor} bind def\n\
115/col4 {1 0 0 setrgbcolor} bind def\n\
116/col5 {1 0 1 setrgbcolor} bind def\n\
117/col6 {1 1 0 setrgbcolor} bind def\n\
118/col7 {1 1 1 setrgbcolor} bind def\n\
119/col8 {.68 .85 .9 setrgbcolor} bind def\n\
120/col9 {0 .39 0 setrgbcolor} bind def\n\
121/col10 {.65 .17 .17 setrgbcolor} bind def\n\
122/col11 {1 .51 0 setrgbcolor} bind def\n\
123/col12 {.63 .13 .94 setrgbcolor} bind def\n\
124/col13 {1 .75 .8 setrgbcolor} bind def\n\
125/col14 {.7 .13 .13 setrgbcolor} bind def\n\
126/col15 {1 .84 0 setrgbcolor} bind def\n\
127"
128
129#define         SPECIAL_CHAR_1  "\
130/reencdict 12 dict def /ReEncode { reencdict begin\n\
131/newcodesandnames exch def /newfontname exch def /basefontname exch def\n\
132/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def\n\
133basefontdict { exch dup /FID ne { dup /Encoding eq\n\
134{ exch dup length array copy newfont 3 1 roll put }\n\
135{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall\n\
136newfont /FontName newfontname put newcodesandnames aload pop\n\
137128 1 255 { newfont /Encoding get exch /.notdef put } for\n\
138newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat\n\
139newfontname newfont definefont pop end } def\n\
140/isovec [ \n\
141"
142#define         SPECIAL_CHAR_2  "\
1438#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde\n\
1448#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis\n\
1458#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron\n\
1468#220 /dotlessi 8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling\n\
1478#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis\n\
1488#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot\n\
1498#255 /endash 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus\n\
1508#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph\n\
1518#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine\n\
1528#273 /guillemotright 8#274 /onequarter 8#275 /onehalf \n\
1538#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute\n\
1548#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring\n\
155"
156#define         SPECIAL_CHAR_3  "\
1578#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute\n\
1588#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute\n\
1598#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve\n\
1608#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply\n\
1618#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex\n\
1628#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave\n\
1638#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring\n\
1648#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute\n\
1658#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute\n\
1668#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve\n\
1678#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide\n\
1688#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex\n\
1698#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis \
170] def\n\
171"
172
173#define         ELLIPSE_PS      " \
174/DrawEllipse {\n\
175        /endangle exch def\n\
176        /startangle exch def\n\
177        /yrad exch def\n\
178        /xrad exch def\n\
179        /y exch def\n\
180        /x exch def\n\
181        /savematrix mtrx currentmatrix def\n\
182        x y translate xrad yrad scale 0 0 1 startangle endangle arc\n\
183        savematrix setmatrix\n\
184        } def\n\
185"
186/* The original PostScript definition for adding a spline section to the
187 * current path uses recursive bisection.  The following definition using the
188 * curveto operator is more efficient since it executes at compiled rather
189 * than interpreted code speed.  The Bezier control points are 2/3 of the way
190 * from z1 (and z3) to z2.
191 *
192 * ---Rene Llames, 21 July 1988.
193 */
194#define         SPLINE_PS       " \
195/DrawSplineSection {\n\
196        /y3 exch def\n\
197        /x3 exch def\n\
198        /y2 exch def\n\
199        /x2 exch def\n\
200        /y1 exch def\n\
201        /x1 exch def\n\
202        /xa x1 x2 x1 sub 0.666667 mul add def\n\
203        /ya y1 y2 y1 sub 0.666667 mul add def\n\
204        /xb x3 x2 x3 sub 0.666667 mul add def\n\
205        /yb y3 y2 y3 sub 0.666667 mul add def\n\
206        x1 y1 lineto\n\
207        xa ya xb yb x3 y3 curveto\n\
208        } def\n\
209"
210#define         END_PROLOG      "\
211        end\n\
212/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def\n\
213/$F2psEnd {$F2psEnteredState restore end} def\n\
214%%EndProlog\n\
215"
216
217static double           tx, scalex, scaley;
218static double           dx, dy, origx, origy;
219
220void genps_option(opt, optarg)
221char opt;
222char *optarg;
223{
224        int i;
225
226        extern char *getenv();
227        char *papersize;
228
229        if (papersize = getenv("FIG2DEV_SIZE"))
230        {
231                if (strcmp(papersize, "A4") == 0)
232                {
233                        pagewidth  = 595;
234                        pageheight = 842;
235                }
236                else if (strcmp(papersize, "A3") == 0)
237                {
238                        pagewidth  = 842;
239                        pageheight = 1190;
240                }
241                else if (strcmp(papersize, "A2") == 0)
242                {
243                        pagewidth  = 1190;
244                        pageheight = 1684;
245                }
246                else if (strcmp(papersize, "A1") == 0)
247                {
248                        pagewidth  = 1684;
249                        pageheight = 2380;
250                }
251                else if (strcmp(papersize, "A0") == 0)
252                {
253                        pagewidth  = 2380;
254                        pageheight = 3368;
255                }
256                else if (strcmp(papersize, "A0_LONG") == 0)
257                {
258                        pagewidth  = 2380;
259                        pageheight = 99999;
260                }
261        }
262
263        switch (opt) {
264
265        case 'f':
266                for ( i = 1; i <= MAX_PSFONT + 1; i++ )
267                        if ( !strcmp(optarg, PSfontnames[i]) ) break;
268
269                if ( i > MAX_PSFONT + 1 )
270                        fprintf(stderr,
271                            "warning: non-standard font name %s\n", optarg);
272
273                psfontnames[0] = psfontnames[1] = optarg;
274                PSfontnames[0] = PSfontnames[1] = optarg;
275                break;
276
277        case 'c':
278                center = 1;
279                break;
280
281        case 's':
282                if (font_size <= 0 || font_size > ULIMIT_FONT_SIZE) {
283                        fprintf(stderr,
284                                "warning: font size %d out of bounds\n", font_size);
285                }
286                break;
287
288        case 'P':
289                show_page = 1;
290                break;
291
292        case 'm':
293        case 'L':
294                break;
295
296        case 'l':
297                landscape = 1;
298                break;
299
300        default:
301                put_msg(Err_badarg, opt, "ps");
302                exit(1);
303                break;
304        }
305}
306
307void genps_start(objects)
308F_compound      *objects;
309{
310        char            host[256];
311        struct passwd   *who;
312        time_t          when;
313        int             itmp;
314        int             resolution;
315
316        resolution = objects->nwcorner.x;
317        coord_system = objects->nwcorner.y;
318        scalex = scaley = mag * POINT_PER_INCH / (double)resolution;
319        /* convert to point unit */
320        llx = (int)ceil(llx * scalex); lly = (int)ceil(lly * scaley);
321        urx = (int)ceil(urx * scalex); ury = (int)ceil(ury * scaley);
322
323
324        if (landscape)
325        {
326           itmp = pageheight; pageheight = pagewidth; pagewidth = itmp;
327           itmp = llx; llx = lly; lly = itmp;
328           itmp = urx; urx = ury; ury = itmp;
329        }
330        if (show_page)
331        {
332           if (center)
333           {
334              if (landscape)
335              {
336                 origx = (pageheight - urx - llx)/2.0;
337                 origy = (pagewidth - ury - lly)/2.0;
338              }
339              else
340              {
341                 origx = (pagewidth - urx - llx)/2.0;
342                 origy = (pageheight + ury + lly)/2.0;
343              }
344           }
345           else
346           {
347              origx = 0.0;
348              origy = landscape ? 0.0 : pageheight;
349           }
350        }
351        else
352        {
353           origx = -llx;
354           origy = landscape ? -lly : ury;
355        }
356
357        if (coord_system == 2) scaley = -scaley;
358
359        if (show_page)
360            fprintf(tfp, "%%!PS-Adobe-2.0\n");          /* PostScript magic strings */
361        else
362            fprintf(tfp, "%%!PS-Adobe-2.0 EPSF-2.0\n"); /* Encapsulated PostScript */
363        who = getpwuid(getuid());
364        if (-1 == gethostname(host, sizeof(host)))
365            (void)strcpy(host, "unknown-host!?!?");
366        (void) time(&when);
367        fprintf(tfp, "%%%%Title: %s\n", ((from) ? from : "stdin"));
368        fprintf(tfp, "%%%%Creator: %s Version %s Patchlevel %s\n", 
369                prog, VERSION, PATCHLEVEL);
370        fprintf(tfp, "%%%%CreationDate: %s", ctime(&when));
371        if (who)
372           fprintf(tfp, "%%%%For: %s@%s (%s)\n",
373                        who->pw_name, host, who->pw_gecos);
374
375        if (!center)
376           if (landscape)
377                pages = (urx/pageheight+1)*(ury/pagewidth+1);
378           else
379                pages = (urx/pagewidth+1)*(ury/pageheight+1);
380        else
381           pages = 1;
382        if (landscape) {
383           fprintf(tfp, "%%%%Orientation: Landscape\n");
384           fprintf(tfp, "%%%%BoundingBox: %d %d %d %d\n", 
385              (int)origx+llx, (int)origy+lly, (int)origx+urx, (int)origy+ury);
386        } else {
387           fprintf(tfp, "%%%%Orientation: Portrait\n");
388           fprintf(tfp, "%%%%BoundingBox: %d %d %d %d\n", 
389              (int)origx+llx, (int)origy-ury, (int)origx+urx, (int)origy-lly);
390        }
391        fprintf(tfp, "%%%%Pages: %d\n", show_page ? pages : 0 );
392
393        fprintf(tfp, "%%%%EndComments\n");
394        fprintf(tfp, "%s", BEGIN_PROLOG);
395        if (iso_text_exist(objects))
396        {
397           fprintf(tfp, "%s%s%s", SPECIAL_CHAR_1,SPECIAL_CHAR_2,SPECIAL_CHAR_3);
398           encode_all_fonts(objects);
399        }
400        if (ellipse_exist(objects)) fprintf(tfp, "%s\n", ELLIPSE_PS);
401        if (normal_spline_exist(objects)) fprintf(tfp, "%s\n", SPLINE_PS);
402        fprintf(tfp, "%s\n", END_PROLOG);
403        fprintf(tfp, "$F2psBegin\n");
404        fprintf(tfp, "0 setlinecap 0 setlinejoin\n");
405 
406        if ( pages > 1 && show_page && !center )
407            multi_page = TRUE;
408        else
409        {
410            fprintf (tfp, "%.1f %.1f translate", origx, origy);
411            if (landscape)
412            {
413               fprintf (tfp, " 90 rotate");
414            }
415            fprintf (tfp, " %.3f %.3f scale\n", scalex, scaley );
416        }
417}
418
419void genps_end()
420{
421    double dx,dy;
422    int i, page;
423    int h,w;
424 
425    if (multi_page)
426    {
427       page = 1;
428       h = (landscape? pagewidth: pageheight);
429       w = (landscape? pageheight: pagewidth);
430       for (dy=0; dy < (ury-h*0.1); dy += h*0.9)
431       {
432         for (dx=0; dx < (urx-w*0.1); dx += w*0.9)
433         {
434            fprintf (tfp, "%%%%Page: %d %d\n%.1f %.1f translate", 
435                page,page,
436                -(origx+dx), (origy+(landscape?-dy:dy)));
437            if (landscape)
438            {
439               fprintf(tfp, " 90 rotate");
440            }
441            fprintf (tfp, " %.3f %.3f scale\n", scalex, scaley);
442            for (i=0; i<no_obj; i++)
443            {
444               fprintf(tfp, "o%d ", i);
445               if (!(i%20)) fprintf(tfp, "\n", i);
446            }
447            fprintf(tfp, "showpage\n");
448            page++;
449         }
450       }
451    }
452    else
453       if (show_page) fprintf(tfp, "showpage\n");
454    fprintf(tfp, "$F2psEnd\n");
455}
456 
457static set_style(s, v)
458int     s;
459double  v;
460{
461        if (s == DASH_LINE) {
462            if (v > 0.0) fprintf(tfp, "\t[%f] 0 setdash\n", v);
463            }
464        else if (s == DOTTED_LINE) {
465            if (v > 0.0) fprintf(tfp, "\t1 setlinecap [1 %f] %f setdash\n", v, v);
466            }
467        }
468
469static reset_style(s, v)
470int     s;
471double  v;
472{
473        if (s == DASH_LINE) {
474            if (v > 0.0) fprintf(tfp, "\t[] 0 setdash\n");
475            }
476        else if (s == DOTTED_LINE) {
477            if (v > 0.0) fprintf(tfp, "\t[] 0 setdash 0 setlinecap\n");
478            }
479        }
480
481static set_linewidth(w)
482int     w;
483{
484        extern int      cur_thickness;
485
486        if (w != cur_thickness) {
487            cur_thickness = w;
488            fprintf(tfp, "%.3f setlinewidth\n", cur_thickness <= 1 ? 0.5* cur_thickness : cur_thickness -1.0);
489            }
490        }
491
492void genps_line(l)
493F_line  *l;
494{
495        F_point         *p, *q;
496        /* JNT */
497        int             radius, i = 0;
498        FILE            *epsf;
499        char            buf[512];
500        char            *cp;
501        int             xmin,xmax,ymin,ymax;
502        int             eps_w, eps_h;
503        double          fllx, flly, furx, fury;
504       
505        if (multi_page)
506           fprintf(tfp, "/o%d {", no_obj++);
507        if (l->type != T_EPS_BOX)  /* eps object has no line thickness */
508                set_linewidth(l->thickness);
509        radius = l->radius;             /* radius of rounded-corner boxes */
510        p = l->points;
511        q = p->next;
512        if (q == NULL) { /* A single point line */
513            fprintf(tfp, "n %d %d m %d %d l gs col%d s gr\n",
514                        p->x, p->y, p->x, p->y, l->color > MAXCOLORS ? -1 : l->color);
515            if (multi_page)
516               fprintf(tfp, "} bind def\n");
517            return;
518            }
519        if (l->back_arrow && l->thickness > 0)
520            draw_arrow_head((double)q->x, (double)q->y, (double)p->x,
521                        (double)p->y, l->back_arrow->ht, l->back_arrow->wid,
522                        l->color);
523        if (l->type != T_EPS_BOX)  /* eps object has no line style */
524                set_style(l->style, l->style_val);
525        fprintf(tfp, "%% Polyline\n");
526
527        xmin = xmax = p->x;
528        ymin = ymax = p->y;
529        while (p->next != NULL) /* find lower left and upper right corne
530rs */
531        {
532                p=p->next;
533                if (xmin > p->x)
534                        xmin = p->x;
535                else if (xmax < p->x)
536                        xmax = p->x;
537                if (ymin > p->y)
538                        ymin = p->y;
539                else if (ymax < p->y)
540                        ymax = p->y;
541                }
542
543        if (l->type == T_ARC_BOX)
544        {
545            fprintf(tfp, "n %d %d m",xmin+radius, ymin);
546            fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat",
547                                xmin, ymin, xmin, ymax-radius, radius);
548            fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc through bl to br */
549                                xmin, ymax, xmax-radius, ymax, radius);
550            fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc through br to tr */
551                                xmax, ymax, xmax, ymin+radius, radius);
552            fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc through tr to tl */
553                                xmax, ymin, xmin+radius, ymin, radius);
554        }
555        else if (l->type == T_EPS_BOX)  /* encapsulated postscript (eps) file */
556        {
557                int             dx, dy, rotation;
558                int             llx, lly, urx, ury;
559                double          fllx, flly, furx, fury;
560
561                dx = l->points->next->next->x - l->points->x;
562                dy = l->points->next->next->y - l->points->y;
563                rotation = 0;
564                if (dx < 0 && dy < 0)
565                           rotation = 180;
566                else if (dx < 0 && dy >= 0)
567                           rotation = 270;
568                else if (dy < 0 && dx >= 0)
569                           rotation = 90;
570
571                fprintf(tfp, "%%\n");
572                fprintf(tfp, "%% Begin Imported EPS File: %s\n", l->eps->file);
573                fprintf(tfp, "%%\n");
574                epsf = fopen(l->eps->file, "r");
575                if (epsf == NULL) {
576                        fprintf (stderr, "Unable to open eps file: %s, error: (%d)\n",
577                                l->eps->file, sys_errlist[errno],errno);
578                        return;
579                }
580                while (fgets(buf, 512, epsf) != NULL) {
581                  lower(buf);
582                  if (!strncmp(buf, "%%boundingbox", 13)) {
583                        if (sscanf(buf, "%%%%boundingbox: %lf %lf %lf %lf",
584                                           &fllx, &flly, &furx, &fury) < 4) {
585                          fprintf(stderr,"Bad EPS bitmap file: %s", l->eps->file);
586                          fclose(epsf);
587                          return;
588                        }
589                        llx= floor(fllx);
590                        lly= floor(flly);
591                        urx= ceil(furx);
592                        ury= ceil(fury);
593                        break;
594                  }
595                }
596                fclose(epsf);
597
598                fprintf(tfp, "n gs\n");
599                if (((rotation == 90 || rotation == 270) && !l->eps->flipped) ||
600                    (rotation != 90 && rotation != 270 && l->eps->flipped)) {
601                        eps_h = urx - llx;
602                        eps_w = ury - lly;
603                } else {
604                        eps_w = urx - llx;
605                        eps_h = ury - lly;
606                }
607
608                /* translate the eps stuff to the right spot on the page */
609                fprintf(tfp, "%d %d translate\n", xmin, ymin);
610
611                /* scale the eps stuff to fit into the bounding box */
612                /* Note: the origin for fig is in the upper-right corner;
613                 *       for postscript its in the lower right hand corner.
614                 *       To fix it, we use a "negative"-y scale factor, then
615                 *       translate the image up on the page */
616                fprintf(tfp, "%f %f scale\n",
617                        fabs((double)(xmax-xmin)/eps_w), -1.0*(double)(ymax-ymin)/eps_h);
618                fprintf(tfp, "0 %d translate\n", -eps_h);
619
620                /* flip the eps stuff */
621                /* always translate it back so that the lower-left corner is at the origin */
622                if (l->eps->flipped && rotation==90) {
623                        fprintf(tfp, "0 %d translate\n", eps_h);
624                        fprintf(tfp, "1 -1 scale\n");
625                }
626                if (l->eps->flipped && rotation==270) {
627                        fprintf(tfp, "%d 0 translate\n", eps_w);
628                        fprintf(tfp, "-1 1 scale\n");
629                }
630
631                /* note: fig measures rotation clockwise; postscript is counter-clockwise */
632                /* always translate it back so that the lower-left corner is at the origin */
633                switch (rotation) {
634                   case 0:
635                        break;
636                   case 90:
637                        if (l->eps->flipped) break;
638                        fprintf(tfp, "%d %d translate\n", 0, eps_h);
639                        fprintf(tfp, "%d rotate\n", 270);
640                        break;
641                   case 180:
642                        fprintf(tfp, "%d %d translate\n", eps_w, eps_h);
643                        fprintf(tfp, "%d rotate\n", 180);
644                        break;
645                   case 270:
646                        if (l->eps->flipped) break;
647                        fprintf(tfp, "%d %d translate\n", eps_w, 0);
648                        fprintf(tfp, "%d rotate\n", 90);
649                        break;
650                }
651
652                /* translate the eps stuff so that the lower-left corner is at the origin */
653                fprintf(tfp, "%d %d translate\n", -llx, -lly);
654                /* save vm so eps file won't change anything */
655                fprintf(tfp, "save\n");
656                fprintf(tfp, "%% EPS file follows:\n");
657                epsf = fopen(l->eps->file, "r");
658                if (epsf == NULL) {
659                        fprintf (stderr, "Unable to open eps file: %s, error: (%d)\n",
660                                l->eps->file, sys_errlist[errno],errno);
661                        fprintf(tfp, "gr\n");
662                        return;
663                }
664                while (fgets(buf, sizeof(buf), epsf) != NULL) {
665                        if (*buf == '%')                /* skip comment lines */
666                                continue;
667                        if ((cp=strstr(buf, "showpage")) != NULL)
668                                strcpy (cp, cp+8);      /* remove showpage */
669                        fputs(buf, tfp);
670                }
671                fclose (epsf);
672                /* restore vm and gsave */
673                fprintf(tfp, "restore gr\n");
674                fprintf(tfp, "%%\n");
675                fprintf(tfp, "%% End Imported EPS File: %s\n", l->eps->file);
676                fprintf(tfp, "%%\n");
677        }
678        else
679        {
680                p = l->points;
681                q = p->next;
682                fprintf(tfp, "n %d %d m", p->x, p->y);
683                while (q->next != NULL) {
684                    p = q;
685                    q = q->next;
686                    fprintf(tfp, " %d %d l ", p->x, p->y);
687                    if (!((++i)%5)) 
688                        fprintf(tfp, "\n");
689                }
690        }
691        if (l->type != T_EPS_BOX) {
692                if (l->type == T_POLYLINE)
693                    fprintf(tfp, " %d %d l ", q->x, q->y);
694                else 
695                    fprintf(tfp, " clp ");
696                if (l->area_fill && (int)l->area_fill != DEFAULT)
697                    fill_area(l->area_fill, l->color);
698                if (l->thickness > 0)
699                     fprintf(tfp, "gs col%d s gr\n",
700                                l->color > MAXCOLORS ? -1 : l->color);
701
702                reset_style(l->style, l->style_val);
703                if (l->for_arrow && l->thickness > 0)
704                    draw_arrow_head((double)p->x, (double)p->y, (double)q->x,
705                                (double)q->y, l->for_arrow->ht, l->for_arrow->wid,
706                                l->color);
707        }
708        if (multi_page)
709           fprintf(tfp, "} bind def\n");
710        }
711
712void genps_spline(s)
713F_spline        *s;
714{
715        if (multi_page)
716           fprintf(tfp, "/o%d {", no_obj++);
717        if (int_spline(s))
718            genps_itp_spline(s);
719        else
720            genps_ctl_spline(s);
721        if (multi_page)
722           fprintf(tfp, "} bind def\n");
723        }
724
725genps_itp_spline(s)
726F_spline        *s;
727{
728        F_point         *p, *q;
729        F_control       *a, *b;
730
731        set_linewidth(s->thickness);
732        a = s->controls;
733        p = s->points;
734        if (s->back_arrow && s->thickness > 0)
735            draw_arrow_head(a->rx, a->ry, (double)p->x,
736                        (double)p->y, s->back_arrow->ht, s->back_arrow->wid,
737                        s->color);
738
739        set_style(s->style, s->style_val);
740        fprintf(tfp, "%% Interpolated spline\n");
741        fprintf(tfp, "n %d %d m\n", p->x, p->y);
742        for (q = p->next; q != NULL; p = q, q = q->next) {
743            b = a->next;
744            fprintf(tfp, "\t%.3f %.3f %.3f %.3f %d %d curveto\n",
745                        a->rx, a->ry, b->lx, b->ly, q->x, q->y);
746            a = b;
747            }
748        if (closed_spline(s)) fprintf(tfp, " clp ");
749        if (s->area_fill && (int)s->area_fill != DEFAULT)
750            fill_area(s->area_fill, s->color);
751        if (s->thickness > 0)
752            fprintf(tfp, "gs col%d s gr\n", s->color > MAXCOLORS ? -1 : s->color);
753        reset_style(s->style, s->style_val);
754
755        if (s->for_arrow && s->thickness > 0)
756            draw_arrow_head(a->lx, a->ly, (double)p->x,
757                        (double)p->y, s->for_arrow->ht, s->for_arrow->wid,
758                        s->color);
759        }
760
761genps_ctl_spline(s)
762F_spline        *s;
763{
764        double          a, b, c, d, x1, y1, x2, y2, x3, y3;
765        F_point         *p, *q;
766
767        /*
768        if (first) {
769            first = FALSE;
770            fprintf(tfp, "%s\n", SPLINE_PS);
771            }
772        */
773
774        p = s->points;
775        x1 = p->x; y1 = p->y;
776        p = p->next;
777        c = p->x; d = p->y;
778        set_linewidth(s->thickness);
779        x3 = a = (x1 + c) / 2;
780        y3 = b = (y1 + d) / 2;
781        if (s->back_arrow && s->thickness > 0) {
782            draw_arrow_head(c, d, x1, y1, s->back_arrow->ht, s->back_arrow->wid,
783                            s->color);
784            }
785        set_style(s->style, s->style_val);
786        if (! closed_spline(s)) {
787            fprintf(tfp, "%% Open spline\n");
788            fprintf(tfp, "n %.3f %.3f m %.3f %.3f l\n",
789                        x1, y1, x3, y3);
790            }
791        else {
792            fprintf(tfp, "%% Closed spline\n");
793            fprintf(tfp, "n %.3f %.3f m\n", a, b);
794            }
795        for (q = p->next; q != NULL; p = q, q = q->next) {
796            x1 = x3; y1 = y3;
797            x2 = c;  y2 = d;
798            c = q->x; d = q->y;
799            x3 = (x2 + c) / 2;
800            y3 = (y2 + d) / 2;
801            fprintf(tfp, "\t%.3f %.3f %.3f %.3f %.3f %.3f DrawSplineSection\n",
802                        x1, y1, x2, y2, x3, y3);
803            }
804        /*
805        * At this point, (x2,y2) and (c,d) are the position of the
806        * next-to-last and last point respectively, in the point list
807        */
808        if (closed_spline(s)) {
809            fprintf(tfp, "\t%.3f %.3f %.3f %.3f %.3f %.3f DrawSplineSection closepath ",
810                        x3, y3, c, d, a, b);
811            }
812        else {
813            fprintf(tfp, "\t%.3f %.3f l ", c, d);
814            }
815        if (s->area_fill && (int)s->area_fill != DEFAULT)
816            fill_area(s->area_fill, s->color);
817        if (s->thickness > 0)
818            fprintf(tfp, "gs col%d s gr\n", s->color > MAXCOLORS ? -1 : s->color);
819        reset_style(s->style, s->style_val);
820        if (s->for_arrow && s->thickness > 0) {
821            draw_arrow_head(x2, y2, c, d, s->for_arrow->ht,
822                                s->for_arrow->wid, s->color);
823            }
824        }
825
826void genps_ellipse(e)
827F_ellipse       *e;
828{
829        if (multi_page)
830           fprintf(tfp, "/o%d {", no_obj++);
831        set_linewidth(e->thickness);
832        set_style(e->style, e->style_val);
833        if (e->angle == 0)
834        {
835            fprintf(tfp, "%% Ellipse\n");
836            fprintf(tfp, "n %d %d %d %d 0 360 DrawEllipse ",
837                  e->center.x, e->center.y, e->radiuses.x, e->radiuses.y);
838        }
839        else
840        {
841            fprintf(tfp, "%% Rotated Ellipse\n");
842            fprintf(tfp, "gs\n");
843            fprintf(tfp, "%d %d translate\n",e->center.x, e->center.y);
844            fprintf(tfp, "%6.3f rotate\n",-e->angle*180/M_PI);
845            fprintf(tfp, "n 0 0 %d %d 0 360 DrawEllipse ",
846                 e->radiuses.x, e->radiuses.y);
847        }
848        if (e->area_fill && (int)e->area_fill != DEFAULT)
849            fill_area(e->area_fill, e->color);
850        if (e->thickness > 0)
851            fprintf(tfp, "gs col%d s gr\n", e->color > MAXCOLORS ? -1 : e->color);
852        if (e->angle != 0)
853            fprintf(tfp, "gr\n");
854        reset_style(e->style, e->style_val);
855        if (multi_page)
856           fprintf(tfp, "} bind def\n");
857        }
858
859#define TEXT_PS         "\
860/%s%s findfont %.2f scalefont setfont\n\
861"
862void genps_text(t)
863F_text  *t;
864{
865        unsigned char           *cp;
866
867        if (multi_page)
868           fprintf(tfp, "/o%d {", no_obj++);
869        if (PSisomap[t->font+1] == TRUE)
870           fprintf(tfp, TEXT_PS, PSFONT(t), "-iso", PSFONTMAG(t));
871        else
872           fprintf(tfp, TEXT_PS, PSFONT(t), "", PSFONTMAG(t));
873
874        fprintf(tfp, "%d %d m \ngs ", t->base_x,  t->base_y);
875        if (coord_system == 2) fprintf(tfp, "1 -1 scale ");
876
877        if (t->angle != 0)
878           fprintf(tfp, " %.1f rotate ", t->angle*180/M_PI);
879        /* this loop escapes characters '(', ')', and '\' */
880        fputc('(', tfp);
881        for(cp = (unsigned char *)t->cstring; *cp; cp++) {
882            if (strchr("()\\", *cp)) 
883                fputc('\\', tfp);
884            if (*cp>=0x80)
885                fprintf(tfp,"\\%o", *cp);
886            else
887                fputc(*cp, tfp);
888                }
889        fputc(')', tfp);
890
891        if ((t->type == T_CENTER_JUSTIFIED) || (t->type == T_RIGHT_JUSTIFIED)){
892
893                fprintf(tfp, " dup stringwidth pop ");
894                if (t->type == T_CENTER_JUSTIFIED) fprintf(tfp, "2 div ");
895                fprintf(tfp, "neg 0 rmoveto ");
896                }
897
898        else if ((t->type != T_LEFT_JUSTIFIED) && (t->type != DEFAULT))
899                fprintf(stderr, "Text incorrectly positioned\n");
900
901        fprintf(tfp, " col%d show gr\n", t->color > MAXCOLORS ? -1 : t->color);
902
903        if (multi_page)
904           fprintf(tfp, "} bind def\n");
905        }
906
907void genps_arc(a)
908F_arc   *a;
909{
910        double          angle1, angle2, dx, dy, radius, x, y;
911        double          cx, cy, sx, sy, ex, ey;
912        int             direction;
913
914        if (multi_page)
915           fprintf(tfp, "/o%d {", no_obj++);
916        cx = a->center.x; cy = a->center.y;
917        sx = a->point[0].x; sy = a->point[0].y;
918        ex = a->point[2].x; ey = a->point[2].y;
919
920        if (coord_system == 2)
921            direction = !a->direction;
922        else
923            direction = a->direction;
924        set_linewidth(a->thickness);
925        if (a->for_arrow && a->thickness > 0) {
926            arc_tangent(cx, cy, ex, ey, direction, &x, &y);
927            draw_arrow_head(x, y, ex, ey, a->for_arrow->ht, a->for_arrow->wid, a->color);
928            }
929        if (a->back_arrow && a->thickness > 0) {
930            arc_tangent(cx, cy, sx, sy, !direction, &x, &y);
931            draw_arrow_head(x, y, sx, sy, a->back_arrow->ht, a->back_arrow->wid, a->color);
932            }
933        dx = cx - sx;
934        dy = cy - sy;
935        radius = sqrt(dx*dx+dy*dy);
936        angle1 = atan2(sy-cy, sx-cx) * 180 / M_PI;
937        angle2 = atan2(ey-cy, ex-cx) * 180 / M_PI;
938        /* direction = 1 -> Counterclockwise */
939        set_style(a->style, a->style_val);
940        fprintf(tfp, "n %.3f %.3f %.3f %.3f %.3f %s\n",
941                cx, cy, radius, angle1, angle2,
942                ((direction == 1) ? "arc" : "arcn"));
943        if (a->area_fill && (int)a->area_fill != DEFAULT)
944            fill_area(a->area_fill, a->color);
945        if (a->thickness > 0)
946            fprintf(tfp, "gs col%d s gr\n", a->color > MAXCOLORS ? -1 : a->color);
947        reset_style(a->style, a->style_val);
948        if (multi_page)
949           fprintf(tfp, "} bind def\n");
950        }
951
952static arc_tangent(x1, y1, x2, y2, direction, x, y)
953double  x1, y1, x2, y2, *x, *y;
954int     direction;
955{
956        if (direction) { /* counter clockwise  */
957            *x = x2 + (y2 - y1);
958            *y = y2 - (x2 - x1);
959            }
960        else {
961            *x = x2 - (y2 - y1);
962            *y = y2 + (x2 - x1);
963            }
964        }
965
966/*      draw arrow heading from (x1, y1) to (x2, y2)    */
967
968static draw_arrow_head(x1, y1, x2, y2, arrowht, arrowwid, col)
969double  x1, y1, x2, y2, arrowht, arrowwid;
970int col;
971{
972        double  x, y, xb, yb, dx, dy, l, sina, cosa;
973        double  xc, yc, xd, yd;
974
975        dx = x2 - x1;  dy = y1 - y2;
976        l = sqrt(dx*dx+dy*dy);
977        if (l == 0) {
978             return;
979        }
980        else {
981             sina = dy / l;  cosa = dx / l;
982        }
983        xb = x2*cosa - y2*sina;
984        yb = x2*sina + y2*cosa;
985        x = xb - arrowht;
986        y = yb - arrowwid / 2;
987        xc = x*cosa + y*sina;
988        yc = -x*sina + y*cosa;
989        y = yb + arrowwid / 2;
990        xd = x*cosa + y*sina;
991        yd = -x*sina + y*cosa;
992        fprintf(tfp, "n %.3f %.3f m %.3f %.3f l %.3f %.3f l gs 2 setlinejoin col%d s gr\n", xc, yc, x2, y2, xd, yd, col > MAXCOLORS ? -1 : col);
993        }
994
995static fill_area(fill, color)
996int fill, color;
997{
998   if (color < 1)   /* use gray levels for default and black */
999        fprintf(tfp, "gs %.2f setgray fill gr\n", 1.0 - GRAYVAL(fill));
1000   else
1001        fprintf(tfp, "gs col%d %.2f graycol fill gr ",
1002                color > MAXCOLORS ? -1 : color, GRAYVAL(fill));
1003}
1004
1005static iso_text_exist(ob)
1006F_compound      *ob;
1007{
1008   F_compound   *c;
1009   F_text          *t;
1010   unsigned char   *s;
1011
1012   if (ob->texts != NULL)
1013   {
1014      for (t = ob->texts; t != NULL; t = t->next)
1015      {
1016         for (s = (unsigned char*)t->cstring; *s != '\0'; s++)
1017         {
1018            /* look for characters >= 128 */
1019            if (*s>127) return(1);
1020         }
1021      }
1022   }
1023
1024   for (c = ob->compounds; c != NULL; c = c->next) {
1025       if (iso_text_exist(c)) return(1);
1026       }
1027   return(0);
1028}
1029
1030static encode_all_fonts(ob)
1031F_compound      *ob;
1032{
1033   F_compound *c;
1034   F_text     *t;
1035
1036   if (ob->texts != NULL)
1037   {
1038        for (t = ob->texts; t != NULL; t = t->next)
1039            if (PSisomap[t->font+1] == FALSE)
1040            {
1041                fprintf(tfp, "/%s /%s-iso isovec ReEncode\n", PSFONT(t), PSFONT(t));
1042                PSisomap[t->font+1] = TRUE;
1043            }
1044   }
1045
1046   for (c = ob->compounds; c != NULL; c = c->next) 
1047   {
1048        encode_all_fonts(c);
1049   }
1050}
1051
1052static ellipse_exist(ob)
1053F_compound      *ob;
1054{
1055        F_compound      *c;
1056
1057        if (NULL != ob->ellipses) return(1);
1058
1059        for (c = ob->compounds; c != NULL; c = c->next) {
1060            if (ellipse_exist(c)) return(1);
1061            }
1062
1063        return(0);
1064        }
1065
1066static normal_spline_exist(ob)
1067F_compound      *ob;
1068{
1069        F_spline        *s;
1070        F_compound      *c;
1071
1072        for (s = ob->splines; s != NULL; s = s->next) {
1073            if (normal_spline(s)) return(1);
1074            }
1075
1076        for (c = ob->compounds; c != NULL; c = c->next) {
1077            if (normal_spline_exist(c)) return(1);
1078            }
1079
1080        return(0);
1081        }
1082
1083struct driver dev_ps = {
1084        genps_option,
1085        genps_start,
1086        genps_arc,
1087        genps_ellipse,
1088        genps_line,
1089        genps_spline,
1090        genps_text,
1091        genps_end,
1092        INCLUDE_TEXT
1093};
Note: See TracBrowser for help on using the repository browser.