source: tags/initial/fig2dev/dev/genlatex.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: 22.8 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 *      genlatex.c : LaTeX driver for fig2dev
26 *
27 *      Author: Frank Schmuck, Cornell University 6/88
28 *      Converted from fig2latex 5/89 by Micah Beck
29 *      Color, rotated text and ISO-chars added by Herbert Bauer 11/91
30 *
31 */
32#if defined(hpux) || defined(SYSV)
33#include <sys/types.h>
34#endif
35#include <sys/file.h>
36#include <stdio.h>
37#include <math.h>
38#include "object.h"
39#include "fig2dev.h"
40#include "texfonts.h"
41#include "pi.h"
42
43#ifndef fabs
44extern double fabs();
45#endif
46#ifndef sin
47extern double sin();
48#endif
49#ifndef cos
50extern double cos();
51#endif
52#ifndef acos
53extern double acos();
54#endif
55#ifndef atan
56extern double atan();
57#endif
58extern double rad2deg;
59extern void unpsfont();
60
61#define rint(a) floor((a)+0.5)     /* close enough? */
62
63/*
64 *  Installation dependent constants:
65 *
66 *  THINDOT     latex command for generating a dot if line width = \thinlines
67 *  THICKDOT    latex command for generating a dot if line width = \thicklines
68 *  MIN_LEN     shortest slanted line that latex can produce; shorter lines will
69 *              we translated into a sequence of dots generated by \multiput.
70 *  THICK_LDOT  latex command for generating the dot for making short slanted
71 *              lines if line width = \thinlines
72 *  THIN_LDOT   ...  if line width = \thicklines
73 */
74#define THICKDOT        "\\SetFigFont{10}{12}{rm}."
75#define THINDOT         "\\SetFigFont{7}{8.4}{rm}."
76double  THIN_XOFF =     (0.1/72.0);
77double  THIN_YOFF =     (0.7/72.0);
78double  THICK_XOFF =    (0.4/72.0);
79double  THICK_YOFF =    (0.6/72.0);
80#define THICK_LDOT      "\\SetFigFont{7}{8.4}{rm}."
81#define THIN_LDOT       "\\SetFigFont{5}{6}{rm}."
82double  THIN_LXOFF =    (0.1/72.0);
83double  THIN_LYOFF =    (0.7/72.0);
84double  THICK_LXOFF =   (0.4/72.0);
85double  THICK_LYOFF =   (0.6/72.0);
86#define MIN_LEN         (13.0/72.0)     /* 13  points */
87
88/*
89 *  other constants and macros
90 */
91#define TOP             840
92#define THINLINES       1
93#define THICKLINES      2
94
95#define MAXCIRCLEDIA    80
96#define MAXCIRCLERAD    ((MAXCIRCLEDIA-0.5)/(2*72.27))
97
98#define SWAP(x,y)       {tmp=x; x=y; y=tmp;}
99#define TRANS(x,y)              (*translate_coordinates)(&x,&y)
100#define TRANS2(x1,y1,x2,y2)     (*translate_coordinates)(&x1,&y1); \
101                                (*translate_coordinates)(&x2,&y2)
102#define TRANSD(x,y)             (*translate_coordinates_d)(&x,&y)
103#ifndef MIN
104#define MIN(x,y)        (((x) <= (y))? (x): (y))
105#endif
106#ifndef MAX
107#define MAX(x,y)        (((x) >= (y))? (x): (y))
108#endif
109#define ABS(x)          (((x) >= 0)? (x): -(x))
110#define round4(x)       ((round(10000.0*(x))/10000.0))
111#define round6(x)       ((round(1000000.0*(x))/1000000.0))
112
113char            thindot [] = THINDOT;
114char            thickdot[] = THICKDOT;
115char            thin_ldot [] = THIN_LDOT;
116char            thick_ldot[] = THICK_LDOT;
117
118static  int     coord_system;
119int             verbose = 0;
120double          dash_mag = 1.0;
121int             thick_width = 2;
122double          tolerance = 2.0;
123double          arc_tolerance = 1.0;
124int             (*translate_coordinates)() = NULL;
125int             (*translate_coordinates_d)() = NULL;
126double          unitlength;
127static int      cur_thickness = -1;
128double          ldot_diameter = 1.0/72.0;
129char            *dot_cmd = thindot;
130char            *ldot_cmd = thin_ldot;
131double          dot_xoffset;
132double          dot_yoffset;
133double          ldot_xoffset;
134double          ldot_yoffset;
135
136extern char *ISOtoTeX[];
137
138static translate1(xp, yp)
139int     *xp, *yp;
140{
141        *xp = *xp + 1;
142        *yp = *yp + 1;
143        }
144
145static translate2(xp, yp)
146int     *xp, *yp;
147{
148        *xp = *xp + 1;
149        *yp = TOP - *yp -1;
150        }
151
152static translate1_d(xp, yp)
153double  *xp, *yp;
154{
155        *xp = *xp + 1.0;
156        *yp = *yp + 1.0;
157        }
158
159static translate2_d(xp, yp)
160double  *xp, *yp;
161{
162        *xp = *xp + 1.0;
163        *yp = (double)TOP - *yp -1.0;
164        }
165
166void genlatex_option(opt, optarg)
167char opt, *optarg;
168{
169    int i;
170
171    switch (opt) {
172        case 'a':
173            fprintf(stderr, "warning: latex option -a obsolete");
174            break;
175
176        case 'd':
177            dash_mag = atof(optarg);    /* set dash magnification */
178            break;
179
180
181        case 'f':               /* set default text font */
182            for ( i = 1; i <= MAX_FONT; i++ )
183                if ( !strcmp(optarg, texfontnames[i]) ) break;
184
185            if ( i > MAX_FONT)
186                fprintf(stderr,
187                        "warning: non-standard font name %s\n", optarg);
188               
189            texfontnames[0] = texfontnames[1] = optarg;
190            break;
191
192        case 'l':               /* set thin/thick line threshold */
193            thick_width = atoi(optarg);
194            break;
195
196        case 's':
197            if (font_size <= 0 || font_size > MAXFONTSIZE) {
198                fprintf(stderr,
199                        "warning: font size %d out of bounds\n", font_size);
200            }
201            break;
202
203        case 'v':
204            verbose = 1;                /* verbose mode */
205            break;
206
207        case 'm':
208        case 'L':
209            break;
210
211        default:
212            put_msg(Err_badarg, opt, "latex");
213            exit(1);
214            break;
215        }
216}
217
218void genlatex_start(objects)
219F_compound      *objects;
220{
221        int tmp;
222
223        texfontsizes[0] = texfontsizes[1] = TEXFONTSIZE(font_size);
224
225        coord_system = objects->nwcorner.y;
226        unitlength = mag/objects->nwcorner.x;
227
228        switch (coord_system) {
229            case 1:
230                translate_coordinates = translate1;
231                translate_coordinates_d = translate1_d;
232                break;
233            case 2:
234                translate_coordinates = translate2;
235                translate_coordinates_d = translate2_d;
236                break;
237            default:
238                fprintf(stderr, "Wrong coordinate system; cannot continue\n");
239                return;
240            }
241
242        TRANS2(llx, lly, urx, ury);
243        if (llx > urx) SWAP(llx, urx)
244        if (lly > ury) SWAP(lly, ury)
245
246        /* LaTeX start */
247        fprintf(tfp, "\\setlength{\\unitlength}{%.6fin}%%\n",
248                                                round6(unitlength));
249        /* define the SetFigFont macro */
250        define_setfigfont(tfp);
251        fprintf(tfp, "\\begin{picture}(%d,%d)(%d,%d)\n",
252                                         urx-llx, ury-lly, llx, lly);
253}
254
255void genlatex_end()
256{
257        /* LaTeX ending */
258        fprintf(tfp, "\\end{picture}\n");
259}
260
261static set_linewidth(w)
262int     w;
263{
264        int             latex_w;
265
266        if (w == 0) return;
267        /* latex only knows thin lines or thick lines */
268        latex_w = (w >= thick_width)? THICKLINES: THINLINES;
269        if (latex_w != cur_thickness) {
270            cur_thickness = latex_w;
271            if (cur_thickness == THICKLINES) {
272                fprintf(tfp, "\\thicklines\n");
273                dot_cmd = thickdot;
274                dot_xoffset = round4(THICK_XOFF/unitlength);
275                dot_yoffset = round4(THICK_YOFF/unitlength);
276                ldot_cmd = thick_ldot;
277                ldot_xoffset = round4(THICK_LXOFF/unitlength);
278                ldot_yoffset = round4(THICK_LYOFF/unitlength);
279                }
280            else {
281                fprintf(tfp, "\\thinlines\n");
282                dot_cmd = thin_ldot;
283                dot_xoffset = round4(THIN_XOFF/unitlength);
284                dot_yoffset = round4(THIN_YOFF/unitlength);
285                ldot_cmd = thin_ldot;
286                ldot_xoffset = round4(THIN_LXOFF/unitlength);
287                ldot_yoffset = round4(THIN_LYOFF/unitlength);
288                }
289            }
290        }
291
292void genlatex_line(l)
293F_line  *l;
294{
295        F_point         *p, *q;
296        int             x, y, llx, lly, urx, ury, arrow;
297
298        if (verbose) fprintf(tfp, "%%\n%% Fig POLYLINE object\n%%\n");
299
300        set_linewidth(l->thickness);
301        set_color(l->color);
302
303        p = l->points;
304        q = p->next;
305
306        if (q == NULL) { /* A single point line */
307            x = p->x; y = p->y;
308            TRANS(x, y);
309            fprintf(tfp, "\\put(%3d,%3d){\\makebox(%.4f,%.4f){%s}}\n",
310              x, y, dot_xoffset, dot_yoffset, dot_cmd);
311            return;
312            }
313
314        if (l->type == T_ARC_BOX) { /* A box with rounded corners */
315          fprintf(stderr, "Arc box not implemented; substituting box.\n");
316          l->type = T_BOX;
317        }
318
319        if (l->type == T_BOX) { /* A box */
320            x = p->x; y = p->y;
321            TRANS(x, y);
322            llx = urx = x;
323            lly = ury = y;
324            while (q != NULL) {
325                x = q->x; y = q->y;
326                TRANS(x, y);
327                if (x < llx) llx = x;
328                if (y < lly) lly = y;
329                if (x > urx) urx = x;
330                if (y > ury) ury = y;
331                q = q->next;
332                }
333            put_box (llx, lly, urx, ury, l->style, l->style_val);
334            return;
335            }
336
337        while (q != NULL) {
338            arrow = 0;
339            if (l->for_arrow  &&  q->next == NULL)
340                arrow = 1;
341            if (l->back_arrow  &&  p == l->points)
342                arrow = (arrow)? 2: -1;
343            single_line(p->x, p->y, q->x, q->y, arrow, l->style, l->style_val);
344            p = q;
345            q = q->next;
346            }
347
348        if (l->area_fill && (int)l->area_fill != DEFAULT)
349                fprintf(stderr, "Line area fill not implemented\n");
350        reset_color(l->color);
351        }
352
353static single_line (x1, y1, x2, y2, arrow, style, val)
354int     x1, y1, x2, y2, arrow, style;
355double  val;
356{
357        int    dx, dy, sx, sy;
358        double l, m, deviation;
359
360        TRANS2(x1, y1, x2, y2);
361        dx = x2-x1;
362        dy = y2-y1;
363        /*** compute direction vector ***/
364        get_slope(dx, dy, &sx, &sy, arrow);
365        /*** compute line length in x-direction ***/
366        if (sx == 0) {
367            l = (double)abs(dy);
368        } else {
369            m = (double)abs(sy) / (double)abs(sx);
370            l = ((double)abs(dx) + m*(double)abs(dy)) / (1.0 + m*m);
371            deviation = fabs(l-abs(dx)) + fabs(m*l-abs(dy));
372            if (deviation > tolerance)
373                fprintf(stderr,
374                  "Not a LaTeX slope (%d, %d), deviation %.1f pixels\n",
375                  dx, dy, deviation);
376        }
377        l = round4(l);
378        /*** output letex command ***/
379        switch (style) {
380            case SOLID_LINE:
381                put_solidline(x1, y1, sx, sy, l, arrow);
382                break;
383            case DASH_LINE:
384                put_dashline(x1, y1, sx, sy, l, arrow, val);
385                break;
386            case DOTTED_LINE:
387                put_dotline(x1, y1, sx, sy, l, arrow, val);
388                break;
389            }
390        }
391
392
393/*
394 * draw box
395 */
396static put_box (llx, lly, urx, ury, style, val)
397int     llx, lly, urx, ury, style;
398double  val;
399{
400        int     dlen;
401
402        switch (style) {
403            case SOLID_LINE:
404                fprintf(tfp, "\\put(%3d,%3d){\\framebox(%d,%d){}}\n",
405                  llx, lly, urx-llx, ury-lly);
406                break;
407            case DASH_LINE:
408                dlen = round(val*dash_mag);
409                fprintf(tfp, "\\put(%3d,%3d){\\dashbox{%d}(%d,%d){}}\n",
410                  llx, lly, dlen, urx-llx, ury-lly);
411                break;
412            case DOTTED_LINE:
413                put_dotline (llx, lly, 1, 0, (double)(urx-llx), 0, val);
414                put_dotline (llx, ury, 1, 0, (double)(urx-llx), 0, val);
415                put_dotline (llx, lly, 0, 1, (double)(ury-lly), 0, val);
416                put_dotline (urx, lly, 0, 1, (double)(ury-lly), 0, val);
417                break;
418            }
419        return;
420        }
421
422/*
423 * draw a solid line given latex slope
424 */
425static put_solidline (x, y, sx, sy, l, arrow)
426int     x, y, sx, sy, arrow;
427double  l;
428{
429        double  cosine;         /* cosine of line angle */
430        double  dx, dy;
431        int     x2, y2, n;
432
433        if (sx) {
434            cosine = (double)abs(sx) / sqrt((double)(sx*sx)+(double)(sy*sy));
435            x2 = (sx >= 0)? x + round(l): x - round(l);
436            y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx);
437            }
438        else {
439            cosine = 1.0;
440            x2 = x;
441            y2 = (sy >= 0)? y + round(l): y - round(l);
442            }
443        if (sx == 0  ||  sy == 0  ||  (l/cosine)*unitlength >= MIN_LEN) {
444            switch (arrow) {
445            case 0:  /* simple line */
446                fprintf(tfp, "\\put(%3d,%3d){\\line(%2d,%2d)", x, y, sx,sy);
447                break;
448            case 1:  /* forward arrow */
449                fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx,sy);
450                break;
451            case -1: /* backward arrow */
452                fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x2, y2, -sx,-sy);
453                break;
454            case 2:  /* double arrow */
455                fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){  0}}\n", x,y,-sx,-sy);
456                fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx, sy);
457                break;
458                }
459            if (l == floor(l))
460                fprintf(tfp, "{%3.0f}}\n", l);
461            else
462                fprintf(tfp, "{%7.3f}}\n", l);
463            }
464        else {
465            n = 2 * (l/cosine) / (ldot_diameter/unitlength);
466            fprintf(stderr, "Line too short; will do %d dots\n", n);
467            dx = l / (double)n;
468            if (sx < 0) dx = -dx;
469            dy = dx * (double)sy / (double)sx;
470            fprintf(tfp, 
471              "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\makebox(%.4f,%.4f){%s}}\n",
472              x, y, dx, dy, n+1, ldot_xoffset, ldot_yoffset, ldot_cmd);
473            if (arrow == 1  ||  arrow == 2)  /* forward arrow */
474                fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2,y2, sx,sy);
475            if (arrow == -1  ||  arrow == 2) /* backward arrow */
476                fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x,y, -sx,-sy);
477            }
478        }
479
480/*
481 * draw a dashed line given latex slope
482 */
483static put_dashline (x, y, sx, sy, l, arrow, val)
484int     x, y, sx, sy, arrow;
485double  l;
486double  val;
487{
488        double  cosine;         /* cosine of line angle */
489        double  nd;             /* number of dashes and gaps fitting on line */
490        int     n;              /* nd rounded to the nearest odd integer */
491        double  dl;             /* actual x-length of each dash */
492        double  dg;             /* actual x-length of each gap */
493        double  dx, dy;         /* step between dashes */
494        int     x2, y2;
495
496        if (sx) {
497            cosine = (double)abs(sx) / sqrt((double)(sx*sx)+(double)(sy*sy));
498            x2 = (sx >= 0)? x + round(l): x - round(l);
499            y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx );
500            }
501        else {
502            cosine = 1.0;
503            x2 = x;
504            y2 = (sy >= 0)? y + round(l): y - round(l);
505            }
506        /*** compute number of dashes, length of dashes and gaps ***/
507        nd = l / (val*dash_mag*cosine);
508        n = (int) (rint((nd + 1.0)/2.0)*2 - 1);
509        dl = l / (double)n;
510        if (sx  &&  sy  &&  (dl/cosine)*unitlength < MIN_LEN) {
511            fprintf(stderr, "Dash too small; using larger dash\n");
512            dl = MIN_LEN/unitlength * cosine;
513            nd = l / dl;
514            n = (int) (rint((nd + 1.0)/2.0)*2 - 1);
515            }
516        if (2*dl >= l  ||  (sx  &&  sy  &&  (l/cosine)*unitlength < MIN_LEN)) {
517            fprintf(stderr, "Dashed line too short; drawing solid line\n");
518            put_solidline (x, y, sx, sy, l, arrow);
519            return;
520            }
521        dg = (l - (n/2+1)*dl) / (double)(n/2);
522        if (sx) {
523            dx = dl+dg;
524            if (sx < 0) dx = -dx;
525            dy = dx * (double)sy / (double)sx;
526            }
527        else {
528            dx = 0.0;
529            dy = dl+dg;
530            if (sy < 0) dy = -dy;
531            }
532        /*** draw dashed line ***/
533        fprintf(tfp, "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\line(%2d,%2d){%7.3f}}\n",
534            x, y, dx, dy, n/2+1, sx, sy, dl);
535        /*** draw arrow heads ***/
536        if (arrow == 1  ||  arrow == 2)
537            fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy);
538        if (arrow == -1  ||  arrow == 2)
539            fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy);
540        }
541
542/*
543 * draw a dotted line given latex slope
544 */
545static put_dotline (x, y, sx, sy, l, arrow, val)
546int     x, y, sx, sy, arrow;
547double  l;
548double  val;
549{
550        double  cosine;         /* cosine of line angle */
551        double  nd;             /* number of dots fitting on line */
552        int     n;              /* nd rounded to the nearest integer */
553        double  dx, dy;         /* step between dashes */
554        int     x2, y2;
555
556
557        cosine = (sx)? (double)abs(sx) / sqrt((double)(sx*sx)+(double)(sy*sy)): 1.0;
558        /*** compute step width ***/
559        nd = l / (3*val*cosine);
560        n = rint(nd);
561        dx = l / (double)n;
562        if (sx) {
563            dx = l / (double)n;
564            if (sx < 0) dx = -dx;
565            dy = dx * (double)sy / (double)sx;
566            }
567        else {
568            dx = 0.0;
569            dy = l / (double)n;
570            if (sy < 0) dy = -dy;
571            }
572        /*** draw arrow heads ***/
573        if (arrow == 1  ||  arrow == 2) {
574            /* forward arrow */
575            if (sx) {
576                x2 = (sx >= 0)? x + round(l): x - round(l);
577                y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx );
578                }
579            else {
580                x2 = x;
581                y2 = (sy >= 0)? y + round(l): y - round(l);
582                }
583            fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy);
584            n--;
585            }
586        if (arrow == -1  ||  arrow == 2) {
587            fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy);
588            x = round(x + dx);
589            y = round(y + dy);
590            n--;
591            }
592        /*** draw dotted line ***/
593        fprintf(tfp, "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\makebox(%.4f,%.4f){%s}}\n",
594            x, y, dx, dy, n+1, dot_xoffset, dot_yoffset, dot_cmd);
595        }
596
597void genlatex_spline(s)
598F_spline        *s;
599{
600        fprintf(stderr, "Can't generate spline; omitting object\n");
601        }
602
603void genlatex_ellipse(e)
604F_ellipse       *e;
605{
606        int  x, y, d, dx, dy;
607
608        if (verbose) fprintf(tfp, "%%\n%% Fig ELLIPSE\n%%\n");
609
610        set_linewidth(e->thickness);
611        switch (e->style) {
612            case SOLID_LINE:
613                break;
614            case DASH_LINE:
615                fprintf(stderr, "Dashed circles and elipses not supported\n");
616                break;
617            case DOTTED_LINE:
618                fprintf(stderr, "Dotted circles and elipses not supported\n");
619                break;
620            }
621
622        x = e->center.x;
623        y = e->center.y;
624        TRANS(x, y);
625        if ((e->type == T_CIRCLE_BY_RAD || e->type == T_CIRCLE_BY_DIA)
626                        && e->radiuses.x*unitlength <= MAXCIRCLERAD) {
627
628            d = 2 * e->radiuses.x;
629            if (e->area_fill == BLACK_FILL)
630                fprintf(tfp, "\\put(%3d,%3d){\\circle*{%d}}\n", x, y, d);
631            else {
632                fprintf(tfp, "\\put(%3d,%3d){\\circle{%d}}\n", x, y, d);
633                if (e->area_fill && (int)e->area_fill != DEFAULT)
634                        fprintf(stderr, "Circle area fill not implemented\n");
635            }
636
637        } else {           
638            dx = 2 * e->radiuses.x;
639            dy = 2 * e->radiuses.y;
640            fprintf(tfp, "\\put(%3d,%3d){\\oval(%d,%d)}\n", x, y, dx, dy);
641            if (e->area_fill && (int)e->area_fill != DEFAULT)
642                fprintf(stderr, "Ellipse area fill not implemented\n");
643        }
644      }
645
646void genlatex_text(t)
647F_text  *t;
648{
649        int     x, y;
650        char    *tpos;
651        unsigned char   *cp;
652
653        if (verbose) fprintf(tfp, "%%\n%% Fig TEXT object\n%%\n");
654
655        x = t->base_x;
656        y = t->base_y;
657        TRANS(x, y);
658
659        switch (t->type) {
660
661            case T_LEFT_JUSTIFIED:
662            case DEFAULT:
663                tpos = "[lb]";
664                break;
665
666            case T_CENTER_JUSTIFIED:
667                tpos = "[b]";
668                break;
669
670            case T_RIGHT_JUSTIFIED:
671                tpos = "[rb]";
672                break;
673
674            default:
675                fprintf(stderr, "Text incorrectly positioned\n");
676            }
677
678        /* smash is used to position text at baseline */
679        unpsfont(t);
680        fprintf(tfp, 
681          "\\put(%3d,%3d){\\makebox(0,0)%s{\\smash{",
682          x, y, tpos);
683
684#ifdef DVIPS
685        if(t->angle && t->type == T_LEFT_JUSTIFIED)
686          fprintf(tfp, "\\special{ps:gsave currentpoint currentpoint translate\n%.1f rotate neg exch neg exch translate}", -t->angle*180/M_PI);
687#endif
688
689        { int texsize;
690          double baselineskip;
691
692          texsize = TEXFONTMAG(t);
693          baselineskip = (texsize * 1.2);
694
695          fprintf(tfp, "\\SetFigFont{%d}{%.1f}{%s}",
696                texsize, baselineskip, TEXFONT(t->font));
697        }
698
699        set_color(t->color);
700
701        if (!special_text(t))
702
703                /* this loop escapes characters "$&%#_{}" */
704                /* and deleted characters "~^\" */
705                for(cp = (unsigned char*)t->cstring; *cp; cp++) {
706                    if (strchr("$&%#_{}", *cp)) (void)fputc('\\', tfp);
707                    if (strchr("~^\\", *cp))
708                        fprintf(stderr,
709                                "Bad character in text object '%c'\n" ,*cp);
710                    else
711                        (void)fputc(*cp, tfp);
712                }
713        else 
714                for(cp = (unsigned char*)t->cstring; *cp; cp++) {
715                    if (*cp >= 0xa0)
716                         fprintf(tfp, "%s", ISOtoTeX[(int)*cp-0xa0]);
717                else
718                    fputc(*cp, tfp);
719                }
720
721        reset_color(t->color);
722
723#ifdef DVIPS
724        if(t->angle)
725        {
726          if (t->type == T_LEFT_JUSTIFIED)
727             fprintf(tfp, "\\special{ps:currentpoint grestore moveto}");
728          else
729             fprintf(stderr, "Rotated Text only for left justified text\n");
730        }
731#endif
732        fprintf(tfp, "}}}\n");
733        }
734
735void genlatex_arc(a)
736F_arc   *a;
737/*
738 *  Approximates an arc by a sequence of quarter ovals.
739 *
740 *  Example:
741 *
742 *      Arc with center at (0,0) and radius 10 from +45 degree to +225 degree
743 *      (arc from p1 = (7.07, 7.07) to p2 = (-7.07, -7.07) counterclockwise).
744 *      This arc is approximated by three quarter ovals, one for each quadrant
745 *      through which the arc goes:
746 *
747 *       1. quarter oval from p1 to the intersection of arc and y-axis,
748 *          i.e., from (7.07, 7.07) to (0, 10) in quadrant 0
749 *
750 *              \put(0, 7.07){\oval(14.14, 5.86)[tr]}
751 *
752 *       2. quarter oval from intersection arc/y-axis to intersection arc/x-axis
753 *          i.e., from (0, 10) to (-10, 0) in quadrant 1
754 *
755 *              \put(0, 0){\oval(20,20)[tl]}
756 *
757 *       3. quarter oval from p1 to the intersection of arc and y-axis,
758 *          i.e., from (-10, 0) to (-7.07, -7.07) in quadrant 2
759 *
760 *              \put(-7.07, 0){\oval(5.86, 14.14)[bl]}
761 */
762{
763        F_pos           p1, p2, pq[4];
764        double          cx, cy;
765        double          v1x, v1y, v2x, v2y;
766        double          r, angle1, angle2;
767        int             q1, q2;
768        int             p1_arrow, p2_arrow;
769        static char     *ad1[4] = { " 0,-1", " 1, 0", " 0, 1", "-1, 0" };
770        static char     *ad2[4] = { "-1, 0", " 0,-1", " 1, 0", " 0, 1" };
771
772        set_linewidth(a->thickness);
773        set_color(a->color);
774        switch (a->style) {
775            case SOLID_LINE:
776                break;
777            case DASH_LINE:
778                fprintf(stderr, "Dashed arcs not supported\n");
779                break;
780            case DOTTED_LINE:
781                fprintf(stderr, "Dotted arcs not supported\n");
782                break;
783            }
784        if (a->direction == 1) {
785            p1 = a->point[0];
786            p2 = a->point[2];
787            p1_arrow = (a->back_arrow != NULL);
788            p2_arrow = (a->for_arrow != NULL);
789            }
790        else {
791            p1 = a->point[2];
792            p2 = a->point[0];
793            p1_arrow = (a->for_arrow != NULL);
794            p2_arrow = (a->back_arrow != NULL);
795            }
796        cx = a->center.x;
797        cy = a->center.y;
798        TRANS2(p1.x, p1.y, p2.x, p2.y);
799        TRANSD(cx, cy);
800        /*** compute vectors and angles from arc center to p1, p2 ***/
801        v1x = (double)p1.x - cx;
802        v1y = (double)p1.y - cy;
803        v2x = (double)p2.x - cx;
804        v2y = (double)p2.y - cy;
805        angle1 = atan2(v1y, v1x) * rad2deg;
806        angle2 = atan2(v2y, v2x) * rad2deg;
807        if (angle1 < 0.0)
808            angle1 += 360.0; 
809        if (angle2 < 0.0)
810            angle2 += 360.0; 
811        /* compute arc radius */
812        r = sqrt(v1x*v1x+v1y*v1y);
813        /*** compute intersection of arc with x and y axis (origin at cx, cy) */
814        pq[0].x = round(cx);
815        pq[0].y = round(cy + r);
816        pq[1].x = round(cx - r);
817        pq[1].y = round(cy);
818        pq[2].x = round(cx);
819        pq[2].y = round(cy - r);
820        pq[3].x = round(cx + r);
821        pq[3].y = round(cy);
822        /*** compute in which quadrants p1 and p2 are located ***/
823        q1 = (int)(angle1/90.0);
824        q2 = (int)(angle2/90.0);
825        if (fabs(angle1 - 90.0*q1) > arc_tolerance
826         || fabs(angle2 - 90.0*q2) > arc_tolerance)
827            fprintf(stderr, "Approximating arc by ovals\n");
828        /*** Draw arc ***/
829        if (p1_arrow)
830            fprintf(tfp, "\\put(%3d,%3d){\\vector(%s){0}}\n", p1.x, p1.y, ad1[q1]);
831        while (q1 != q2) {
832            put_quarter(p1, pq[q1], q1);
833            p1 = pq[q1];
834            q1 = (q1 + 1) % 4;
835            }
836        put_quarter(p1, p2, q1);
837        if (p2_arrow)
838            fprintf(tfp, "\\put(%3d,%3d){\\vector(%s){0}}\n", p2.x, p2.y, ad2[q2]);
839
840        if (a->area_fill && (int)a->area_fill != DEFAULT)
841                fprintf(stderr, "Arc area fill not implemented\n");
842        reset_color(a->color);
843        }
844
845static put_quarter(p1, p2, q)
846F_pos   p1, p2;
847int     q;
848/*
849 *  Draw quarter oval from p1 to p2 in quadrant q
850 */
851{
852        char    *opt;
853        int     px, py, dx, dy;
854
855        dx = 2*ABS(p1.x - p2.x);
856        dy = 2*ABS(p1.y - p2.y);
857        if (dx == 0  &&  dy == 0)
858            return;
859        switch (q) {
860            case 0:
861                px = MIN(p1.x, p2.x);
862                py = MIN(p1.y, p2.y);
863                opt = "tr";
864                break;
865            case 1:
866                px = MAX(p1.x, p2.x);
867                py = MIN(p1.y, p2.y);
868                opt = "tl";
869                break;
870            case 2:
871                px = MAX(p1.x, p2.x);
872                py = MAX(p1.y, p2.y);
873                opt = "bl";
874                break;
875            case 3:
876                px = MIN(p1.x, p2.x);
877                py = MAX(p1.y, p2.y);
878                opt = "br";
879                break;
880            }
881        fprintf(tfp, "\\put(%3d,%3d){\\oval(%3d,%3d)[%s]}\n", px, py, dx, dy, opt);
882        }
883
884#define  MAXCOLORS 8
885
886set_color(col)
887int col;
888{
889   static char *colors[] = {
890   "0 0 0",    /* black */
891   "0 0 1",    /* blue */
892   "0 1 0",    /* green */
893   "0 1 1",    /* cyan */
894   "1 0 0",    /* red */
895   "1 0 1",    /* magenta */
896   "1 1 0",    /* yellow */
897   "1 1 1",    /* white */
898   };
899   
900#ifdef DVIPS
901   if (col != -1 && col < MAXCOLORS)
902      fprintf(tfp, "\\special{ps: gsave %s setrgbcolor}", colors[col]);
903#endif
904   return;
905}
906
907reset_color(col)
908int col;
909{
910#ifdef DVIPS
911   if (col != -1 && col < MAXCOLORS)
912      fprintf(tfp, "\\special{ps: grestore}");
913#endif
914   return;
915}
916
917
918struct driver dev_latex = {
919        genlatex_option,
920        genlatex_start,
921        genlatex_arc,
922        genlatex_ellipse,
923        genlatex_line,
924        genlatex_spline,
925        genlatex_text,
926        genlatex_end,
927        EXCLUDE_TEXT
928};
Note: See TracBrowser for help on using the repository browser.