source: tags/initial/fig2dev/dev/genepic.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.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 * genepic.c: (E)EPIC driver for fig2dev
26 *
27 * Converted from fig2epic 5/89 by Micah Beck
28 */
29/*==================================================================*/
30/*      fig2epic (Fig to EPIC converter)                            */
31/*           Version 1.1d <March 30, 1988>                          */
32/*                                                                  */
33/*      Written by Conrad Kwok, Division of Computer Science, UCD   */
34/*                                                                  */
35/*      Permission is granted for freely distribution of this file  */
36/*              provided that this message is included.             */
37/*==================================================================*/
38
39/*====================================================================
40  Changes:
41
42  Version 1.0d:<September 18, 1988>
43  1. Add the option -P for Page mode. Two more configurable parameter---
44     Preamble and Postamble.
45
46  Version 1.1a: <January 18, 1989>
47  1. Fix the bug in closed control splines. The routine convertCS(p) is being
48     called once too often.
49
50  2. Add supports to Variable line width
51  3. Add supports to black, white or shaded area fill.
52
53  Version 1.1b: <Febrary 2, 1989>
54  1. Draw outline for area-filled figures when using dvips.
55
56  Version 1.1c: <Febrary 7, 1989>
57  1. Supports all 5 gray level in area fill.
58
59  Version 1.1d: <March 30, 1989>
60  1. Add supports for Gould NP1 (Bsd4.3) (Recieve the changes from
61                mcvax!presto.irisa.fr!hleroy@uunet.uu.net. Sorry
62                I don't have his/her name)
63  2. Add exit(0) before exit in the main.
64====================================================================*/
65
66 
67#include <stdio.h>
68#include <math.h>
69//#include <varargs.h>
70#include <ctype.h>
71#include "object.h"
72#include "fig2dev.h"
73#include "texfonts.h"
74#include "pi.h"
75
76#ifdef MSDOS
77#define getopt egetopt
78#define M_PI 3.14159265358979324
79#endif
80
81#define DrawOutLine
82#ifdef DrawOutLine
83int OutLine=0;
84#endif
85
86#define TopCoord 840            /* 10.5 in * 80 (DPI)            */
87                                /* Actually, it can be any value */
88#define PtPerLine 3
89#define ThinLines 0
90#define ThickLines 1
91#define FALSE 0
92#define TRUE 1
93#define Epic 0
94#define EEpic_emu 1
95#define EEpic 2
96#define None 0
97#define SolidLineBox 1
98#define DashLineBox 2
99#define BothBoxType 3
100#define Normal 0
101#define Economic 1
102#define DottedDash 2
103
104void genepic_ctl_spline(), genepic_int_spline(); 
105static void genepic_open_spline(), genepic_closed_spline(); 
106
107/* Structure for Point with "double" values */
108struct fp_struct {
109    double x,y;
110};
111
112typedef struct fp_struct FPoint;
113
114/* Local to the file only */
115static int coord_system;
116static int CoordSys = 2;
117static double Threshold;
118static int DPI;
119static int CurWidth = 0;
120static int LineStyle = SOLID_LINE;
121static int LLX = 0, LLY = 0;
122static char *LnCmd;
123static int MaxCircleRadius;
124static double DashLen;
125static int PageMode = FALSE;
126static int PatternType=UNFILLED;
127static struct {
128    double mag;
129    int size;
130} ScaleTbl[5] = {
131    { 0.6667, 8 },
132    { 0.75  , 9 },
133    { 0.8333, 10 },
134    { 0.9167, 11 },
135    { 1.0   , 12 }
136};
137
138/* Definition of Keywords for some of the configurable parameter */
139char *Tlangkw[] = { /* The order must match the definition of corr. constants */
140    "Epic", "EEpicemu", "EEpic", NULL
141};
142
143char *EllCmdkw[] = {
144    "ellipse", "oval", NULL
145};
146
147char *EllCmdstr[] = {
148    "\\%s%s{%d}{%d}}\n", "\\%s%s(%d,%d)}\n"
149};
150
151char *FillCommands[] = {
152    "", "\\whiten",
153    "\\shade", "\\shade", "\\shade",
154    "\\shade", "\\shade", "\\shade",
155    "\\shade", "\\shade", "\\shade",
156    "\\shade", "\\shade", "\\shade",
157    "\\shade", "\\shade", "\\shade",
158    "\\shade", "\\shade", "\\shade",
159    "\\shade", "\\blacken"
160};
161
162#define TEXT_LINE_SEP '\n'
163/* The following two arrays are used to translate characters which
164   are special to LaTeX into characters that print as one would expect.
165   Note that the <> characters aren't really special LaTeX characters
166   but they will not print as themselves unless one is using a font
167   like tt. */
168char latex_text_specials[] = "\\{}><^~$&#_%";
169char *latex_text_mappings[] = {
170  "$\\backslash$",
171  "$\\{$",
172  "$\\}$",
173  "$>$",
174  "$<$",
175  "\\^{}",
176  "\\~{}",
177  "\\$",
178  "\\&",
179  "\\#",
180  "\\_",
181  "\\%"};
182
183
184/* Configurable parameters */
185int LowerLeftX=0, LowerLeftY=0;
186double SegLen = 0.0625; /* inch */
187int Verbose = FALSE;
188int TopMargin = 5;
189int BottomMargin = 10;
190int DotDist = 5;
191int LineThick = 2;
192int TeXLang = EEpic;
193double DashScale=1;
194int EllipseCmd=0;
195int UseBox=None;
196int DashType=Normal;
197char *Preamble="\\documentstyle[epic,eepic]{article}\n\\begin{document}\n\\begin{center}\n";
198char *Postamble="\\end{center}\n\\end{document}\n";
199int VarWidth=FALSE;
200
201void genepic_option(opt, optarg)
202char opt, *optarg;
203{
204        int loop, i;
205
206        switch (opt) {
207        case 'a':
208            fprintf(stderr, "warning: genepic option -a obsolete");
209            break;
210
211        case 'f':
212            for ( i = 1; i <= MAX_FONT; i++ )
213                if ( !strcmp(optarg, texfontnames[i]) ) break;
214
215            if ( i > MAX_FONT)
216                fprintf(stderr,
217                        "warning: non-standard font name %s\n", optarg);
218       
219            texfontnames[0] = texfontnames[1] = optarg;
220            break;
221
222        case 'l':
223            LineThick = atoi(optarg);
224            break;
225
226        case 'L':
227            for (loop=0; loop < 3; loop++) {
228                if (stricmp(optarg, Tlangkw[loop]) == 0) break;
229            }
230            TeXLang = loop;
231            break;
232
233
234        case 'm':
235            break;
236
237        case 'P':
238            PageMode = 1;
239            break;
240
241        case 's':
242            font_size = atoi(optarg);
243            if (font_size <= 0 || font_size > MAXFONTSIZE) {
244                fprintf(stderr,
245                        "warning: font size %d out of bounds\n", font_size);
246            }
247            break;
248
249        case 'S':
250            loop = atoi(optarg);
251            if (loop < 8 || loop > 12) {
252                put_msg("Scale must be between 8 and 12 inclusively\n");
253                exit(1);
254            }
255            loop -= 8;
256            mag = ScaleTbl[loop].mag;
257            font_size = ScaleTbl[loop].size;
258            break;
259
260        case 'v':
261            Verbose = TRUE;
262            break;
263
264        case 'w':
265        case 'W':
266            VarWidth = opt=='W';
267            break;
268
269        default:
270            put_msg(Err_badarg, opt, "epic");
271            exit(1);
272            break;
273        }
274}
275
276static fconvertCS(fpt)
277FPoint *fpt;
278{
279    if (CoordSys) {
280        fpt->y = TopCoord - fpt->y;
281    }
282    fpt->x -= LLX;
283    fpt->y -= LLY;
284}
285
286convertCS(pt)
287F_point *pt;
288{
289    if (CoordSys) {
290        pt->y = TopCoord - pt->y;
291    }
292    pt->x -= LLX;
293    pt->y -= LLY;
294}
295
296void genepic_start(objects)
297F_compound *objects;
298{
299    int temp;
300    F_point pt1, pt2;
301    F_arc *arc;
302    F_compound *comp;
303    F_ellipse *ell;
304    F_line *line;
305    F_spline *spl;
306    F_text *text;
307
308    texfontsizes[0] = texfontsizes[1] = TEXFONTSIZE(font_size);
309
310    switch (TeXLang) {
311    case Epic:
312        EllipseCmd = 1; /* Oval */
313        LnCmd = "drawline";
314        break;
315    case EEpic_emu:
316    case EEpic:
317        LnCmd = "path";
318        break;
319    default:
320        put_msg("Program error in main\n");
321        break;
322    }
323    if (PageMode) {
324        fputs(Preamble, stdout);
325    }
326
327    DPI = objects->nwcorner.x;
328    if (DPI <= 0) {
329        put_msg("Resolution has to be positive. Default to 80!\n");
330        DPI = 80;
331    }
332    coord_system = objects->nwcorner.y;
333    switch (coord_system) {
334    case 1:
335        CoordSys = 0;
336        break;
337    case 2:
338        CoordSys = 1;
339        break;
340    default:
341        put_msg("Unknown Coordinate system -- %d\n", coord_system);
342        exit(1);
343    }
344    pt1.x = llx;
345    pt1.y = lly;
346    pt2.x = urx;
347    pt2.y = ury;
348    convertCS(&pt1);
349    convertCS(&pt2);
350    if (pt1.x > pt2.x) {
351        temp = pt1.x;
352        pt1.x = pt2.x;
353        pt2.x = temp;
354    }
355    if (pt1.y > pt2.y) {
356        temp = pt1.y;
357        pt1.y = pt2.y;
358        pt2.y = temp;
359    }
360    LLX = pt1.x - LowerLeftX;
361    LLY = pt1.y - LowerLeftY;
362    if (Verbose) {
363        fprintf(tfp, "%%\n%% Language in use is %s\n%%\n", Tlangkw[TeXLang]);
364    }
365    Threshold = 1.0 / DPI * mag;
366    fprintf(tfp, "\\setlength{\\unitlength}{%.4fin}\n", Threshold);
367    MaxCircleRadius = (int) (40 / 72.27 / Threshold);
368    Threshold = SegLen / Threshold;
369    define_setfigfont(tfp);
370    fprintf(tfp, "\\begin{picture}(%d,%d)(%d,%d)\n",
371           pt2.x-pt1.x, pt2.y-pt1.y + TopMargin + BottomMargin,
372           LowerLeftX, LowerLeftY-BottomMargin);
373}
374
375void genepic_end()
376{
377    fprintf(tfp, "\\end{picture}\n");
378    if (PageMode)
379        fputs(Postamble, stdout);
380}
381
382static set_linewidth(w)
383int w;
384{
385    int old_width;
386
387    if (w < 0) return;
388    old_width=CurWidth;
389    CurWidth = (w >= LineThick) ? (VarWidth ? w : ThickLines) : ThinLines;
390    if (old_width != CurWidth) {
391        if (CurWidth==ThinLines) {
392            fprintf(tfp, "\\thinlines\n");
393        } else if (VarWidth) {
394            fprintf(tfp, "\\allinethickness{%d}%%\n",w);
395        } else {
396            fprintf(tfp, "\\thicklines\n");
397        }
398    }
399}
400
401set_pattern(type)
402int type;
403{
404    static unsigned long patterns[3][32] = {
405        { 0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0,
406          0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0,
407          0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0,
408          0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0},
409        { 0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0,
410          0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0,
411          0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0,
412          0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0},
413        { 0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0,
414          0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0,
415          0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0,
416          0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0}};
417    int count, loop1, loop2, i;
418
419    if (type <= WHITE_FILL || type >= BLACK_FILL) return;
420    if (type != PatternType) {
421        PatternType=type;
422        i = ((int) PatternType - WHITE_FILL - 1) / 6;
423        fprintf(tfp, "\\texture{");
424        count=0;
425        for (loop1=4; loop1>0;) {
426            for (loop2=8; loop2>0; loop2--) 
427                fprintf(tfp, "%lx ", patterns[i][count++]);
428            if (--loop1 > 0)
429                fprintf(tfp, "\n\t");
430            else
431                fprintf(tfp, "}%\n");
432        }
433    }
434}
435
436void genepic_line(line)
437F_line *line;
438{
439    F_point *p, *q;
440    int pt_count = 0, temp;
441    int boxflag = FALSE, llx, lly, urx, ury;
442    double dtemp;
443
444    set_linewidth(line->thickness);
445    set_style(line->style, line->style_val);
446    p = line->points;
447    q = p->next;
448    convertCS(p);
449    if (q == NULL) {
450        fprintf(tfp, "\\drawline(%d,%d)(%d,%d)\n", p->x, p->y, p->x, p->y);
451        return;
452    }
453    if (line->type == T_ARC_BOX) { /* A box with rounded corners */
454          fprintf(stderr, "Arc box not implemented; substituting box.\n");
455          line->type = T_BOX;
456    }
457    if (line->type == T_BOX) {
458        if (Verbose) {
459            fprintf(tfp, "%%\n%% A box\n%%\n");
460        }
461        switch (LineStyle) {
462        case SOLID_LINE:
463            if (UseBox == BothBoxType || UseBox == SolidLineBox) {
464                boxflag = TRUE;
465            }
466            break;
467        case DASH_LINE:
468            if (UseBox == BothBoxType || UseBox == DashLineBox) {
469                boxflag = TRUE;
470            }
471            break;
472        }
473        if (boxflag) {
474            llx = urx = p->x;
475            lly = ury = p->y;
476            while (q != NULL) {
477                convertCS(q);
478                if (q->x < llx) {
479                    llx = q->x;
480                } else if (q->x > urx) {
481                    urx = q->x;
482                }
483                if (q->y < lly) {
484                    lly = q->y;
485                } else if (q->y > ury) {
486                    ury = q->y;
487                }
488                q = q->next;
489            }
490            switch(LineStyle) {
491            case SOLID_LINE:
492                fprintf(tfp, "\\put(%d,%d){\\framebox(%d,%d){}}\n",
493                    llx, lly, urx-llx, ury-lly);
494                break;
495            case DASH_LINE:
496                temp = (int) ((urx-llx) / DashLen);
497                dtemp = (double) (urx-llx) / temp;
498                fprintf(tfp, "\\put(%d,%d){\\dashbox{%4.3f}(%d,%d){}}\n",
499                    llx, lly, dtemp , urx-llx, ury-lly);
500                break;
501            default:
502                put_msg("Program Error! No other line styles allowed.\n");
503                break;
504            }
505            return;
506          }
507    }
508    set_pattern(line->area_fill);
509    convertCS(q);
510    if (line->back_arrow) {
511        draw_arrow_head(q, p, line->back_arrow->ht, line->back_arrow->wid);
512        if (Verbose) fprintf(tfp, "%%\n");
513    }
514    switch (LineStyle) {
515    case SOLID_LINE:
516        if (q->next != NULL && strcmp(LnCmd,"path")==0) {
517            if (line->area_fill < UNFILLED) line->area_fill = UNFILLED;
518            fprintf(tfp, "%s", FillCommands[line->area_fill]);
519        }
520        fprintf(tfp, "\\%s", LnCmd);
521#ifdef DrawOutLine
522        if (line->area_fill != UNFILLED && OutLine == 0) OutLine=1;
523#endif
524        break;
525    case DASH_LINE:
526        if ((TeXLang==Epic || TeXLang ==EEpic_emu) && DashType == Economic) {
527            fprintf(tfp, "\\drawline[-50]");
528        } else {
529            fprintf(tfp, "\\dashline{%4.3f}", DashLen);
530        }
531        break;
532    case DOTTED_LINE:
533        fprintf(tfp, "\\dottedline{%d}", DotDist);
534        break;
535    default:
536        fprintf(stderr,"Unknown Style\n");
537        exit(1);
538    }
539    fprintf(tfp, "(%d,%d)", p->x, p->y);
540    pt_count++;
541    while(q->next != NULL) {
542        if (++pt_count > PtPerLine) {
543            pt_count=1;
544            fprintf(tfp, "\n\t");
545        }
546        fprintf(tfp, "(%d,%d)", q->x, q->y);
547        p=q;
548        q = q->next;
549        convertCS(q);
550    }
551    fprintf(tfp, "(%d,%d)\n", q->x, q->y);
552#ifdef DrawOutLine
553    if (OutLine == 1) {
554        OutLine=0;
555        fprintf(tfp, "\\%s", LnCmd);
556        p=line->points;
557        pt_count=0;
558        q=p->next;
559        fprintf(tfp, "(%d,%d)", p->x, p->y);
560        pt_count++;
561        while(q->next != NULL) {
562            if (++pt_count > PtPerLine) {
563                pt_count=1;
564                fprintf(tfp, "\n\t");
565            }
566            fprintf(tfp, "(%d,%d)", q->x, q->y);
567            p=q;
568            q = q->next;
569        }
570        fprintf(tfp, "(%d,%d)\n", q->x, q->y);
571    }
572#endif
573    if (line->for_arrow) {
574        draw_arrow_head(p, q, line->for_arrow->ht, line->for_arrow->wid);
575        if (Verbose) fprintf(tfp, "%%\n");
576    }
577}
578
579set_style(style, dash_len)
580int style;
581float dash_len;
582{
583    LineStyle = style;
584    if (LineStyle == DASH_LINE) {
585        switch (DashType) {
586        case DottedDash:
587            LineStyle = DOTTED_LINE;
588            break;
589        default:
590            DashLen = dash_len * DashScale;
591            break;
592        }
593    }
594}
595
596
597void genepic_spline(spl)
598F_spline *spl;
599{
600    set_linewidth(spl->thickness);
601    set_style(SOLID_LINE, 0.0);
602    if (int_spline(spl)) {
603        genepic_itp_spline(spl);
604    } else {
605        genepic_ctl_spline(spl);
606    }
607}
608
609void genepic_ctl_spline(spl)
610F_spline *spl;
611{
612    if (closed_spline(spl)) {
613        genepic_closed_spline(spl);
614    } else {
615        genepic_open_spline(spl);
616    }
617}
618
619static void genepic_open_spline(spl)
620F_spline *spl;
621{
622    F_point *p, *q, *r;
623    FPoint first, mid;
624    int pt_count = 0;
625
626    p = spl->points;
627    q = p->next;
628    convertCS(p);
629    convertCS(q);
630    if (spl->back_arrow) {
631        draw_arrow_head(q, p, spl->back_arrow->ht, spl->back_arrow->wid);
632        if (Verbose) fprintf(tfp, "%%\n");
633    }
634    if (q->next == NULL) {
635        fprintf(tfp, "\\%s(%d,%d)(%d,%d)\n", LnCmd,
636               p->x, p->y, q->x, q->y);
637        return;
638    }
639    if (TeXLang == EEpic || TeXLang == EEpic_emu) {
640        fprintf(tfp, "\\spline(%d,%d)\n", p->x, p->y);
641        pt_count++;
642        while(q->next != NULL) {
643             if (++pt_count > PtPerLine) {
644                 pt_count=1;
645                 fprintf(tfp, "\n\t");
646             }
647             fprintf(tfp, "(%d,%d)", q->x, q->y);
648             p=q;
649             q = q->next;
650             convertCS(q);
651        }
652        fprintf(tfp, "(%d,%d)\n", q->x, q->y);
653    } else {
654        fprintf(tfp, "\\%s(%d,%d)\n", LnCmd, p->x, p->y);
655        r = q->next;
656        convertCS(r);
657        first.x = p->x;
658        first.y = p->y;
659        while (r->next != NULL) {
660            mid.x = (q->x + r->x) / 2.0;
661            mid.y = (q->y + r->y) / 2.0;
662            chaikin_curve(first.x, first.y, (double) q->x, (double) q->y,
663                            mid.x, mid.y);
664            first = mid;
665            q=r;
666            r = r->next;
667            convertCS(r);
668        }
669        chaikin_curve(first.x, first.y, (double) q->x, (double) q->y,
670                        (double) r->x, (double) r->y);
671        p=q;
672        q=r;
673        fprintf(tfp, "\n");
674    }
675    if (spl->for_arrow) {
676        draw_arrow_head(p, q, spl->for_arrow->ht, spl->for_arrow->wid);
677        if (Verbose) fprintf(tfp, "%%\n");
678    }
679}
680
681static void genepic_closed_spline(spl)
682F_spline *spl;
683{
684    F_point *p;
685    double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
686    double x1, y1, x2, y2;
687
688    p = spl->points;
689    convertCS(p);
690    x1 = p->x;  y1 = p->y;
691    p = p->next;
692    convertCS(p);
693    x2 = p->x;  y2 = p->y;
694    cx1 = (x1 + x2) / 2;      cy1 = (y1 + y2) / 2;
695    cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
696    for (p = p->next; p != NULL; p = p->next) {
697        fprintf(tfp, "\\%s(%.3f,%.3f)", LnCmd, cx1, cy1);
698        x1 = x2;  y1 = y2;
699        convertCS(p);
700        x2 = p->x;  y2 = p->y;
701        cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
702        cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
703        quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
704        fprintf(tfp, "\n");
705        cx1 = cx4;  cy1 = cy4;
706        cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
707    }
708    x1 = x2;  y1 = y2;
709    p = spl->points->next;
710    x2 = p->x;  y2 = p->y;
711    cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
712    cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
713    fprintf(tfp, "\\%s(%.3f,%.3f)", LnCmd, cx1, cy1);
714    quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
715    fprintf(tfp, "\n");
716}
717
718chaikin_curve(a1, b1, a2, b2, a3, b3)
719double a1, b1, a2, b2, a3, b3;
720{
721    double xm1, xmid, xm2, ym1, ymid, ym2;
722
723    if (fabs(a1-a3) < Threshold && fabs(b1-b3) < Threshold) {
724        fprintf(tfp, "\t(%.3f,%.3f)\n", a3, b3);
725    } else {
726        xm1 = (a1 + a2) / 2;
727        ym1 = (b1 + b2) / 2;
728        xm2 = (a2 + a3) / 2;
729        ym2 = (b2 + b3) / 2;
730        xmid = (xm1 + xm2) / 2;
731        ymid = (ym1 + ym2) / 2;
732        chaikin_curve(a1, b1, xm1, ym1, xmid, ymid);
733        chaikin_curve(xmid, ymid, xm2, ym2, a3, b3);
734    }
735}
736
737static quadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4)
738double  a1, b1, a2, b2, a3, b3, a4, b4;
739{
740    double      x1, y1, x4, y4;
741    double      xmid, ymid;
742
743    x1 = a1; y1 = b1;
744    x4 = a4; y4 = b4;
745
746    xmid = (a2 + a3) / 2;
747    ymid = (b2 + b3) / 2;
748    if (fabs(x1 - xmid) < Threshold && fabs(y1 - ymid) < Threshold) {
749        fprintf(tfp, "\t(%.3f,%.3f)\n", xmid, ymid);
750    } else {
751        quadratic_spline(x1, y1, ((x1+a2)/2), ((y1+b2)/2),
752                         ((3*a2+a3)/4), ((3*b2+b3)/4), xmid, ymid);
753    }
754
755    if (fabs(xmid - x4) < Threshold && fabs(ymid - y4) < Threshold) {
756        fprintf(tfp, "\t(%.3f,%.3f)\n", x4, y4);
757    } else {
758        quadratic_spline(xmid, ymid, ((a2+3*a3)/4), ((b2+3*b3)/4),
759                         ((a3+x4)/2), ((b3+y4)/2), x4, y4);
760    }
761}
762
763genepic_itp_spline(spl)
764F_spline *spl;
765{
766    F_point *p1, *p2;
767    FPoint pt1l, pt1r, pt2l, pt2r, tmpfpt;
768    F_control *cp1, *cp2;
769
770    p1 = spl->points;
771    convertCS(p1);
772    cp1 = spl->controls;
773    pt1l.x = cp1->lx;
774    pt1l.y = cp1->ly;
775    pt1r.x = cp1->rx;
776    pt1r.y = cp1->ry;
777    fconvertCS(&pt1l);
778    fconvertCS(&pt1r);
779
780    if (spl->back_arrow) {
781        tmpfpt.x = p1->x;
782        tmpfpt.y = p1->y;
783        fdraw_arrow_head(&pt1r, &tmpfpt, 
784                spl->back_arrow->ht, spl->back_arrow->wid);
785        if (Verbose) fprintf(tfp, "%%\n");
786    }
787
788    for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
789         p1 = p2, pt1r = pt2r, p2 = p2->next, cp2 = cp2->next) {
790        fprintf(tfp, "\\%s(%d,%d)", LnCmd, p1->x, p1->y);
791        convertCS(p2);
792        pt2l.x = cp2->lx;
793        pt2l.y = cp2->ly;
794        pt2r.x = cp2->rx;
795        pt2r.y = cp2->ry;
796        fconvertCS(&pt2l);
797        fconvertCS(&pt2r);
798        bezier_spline((double) p1->x, (double) p1->y,
799                      pt1r.x, pt1r.y,
800                      pt2l.x, pt2l.y,
801                      (double) p2->x, (double) p2->y);
802        fprintf(tfp, "\n");
803    }
804
805    if (spl->for_arrow) {
806        tmpfpt.x = p1->x;
807        tmpfpt.y = p1->y;
808        fdraw_arrow_head(&pt2l, &tmpfpt, 
809                         spl->for_arrow->ht, spl->for_arrow->wid);
810        if (Verbose) fprintf(tfp, "%%\n");
811    }
812}
813
814static bezier_spline(a0, b0, a1, b1, a2, b2, a3, b3)
815double  a0, b0, a1, b1, a2, b2, a3, b3;
816{
817    double      x0, y0, x3, y3;
818    double      sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid;
819
820    x0 = a0; y0 = b0;
821    x3 = a3; y3 = b3;
822    if (fabs(x0 - x3) < Threshold && fabs(y0 - y3) < Threshold) {
823        fprintf(tfp, "\t(%.3f,%.3f)\n", x3, y3);
824    } else {
825        tx = (a1 + a2) / 2;             ty = (b1 + b2) / 2;
826        sx1 = (x0 + a1) / 2;    sy1 = (y0 + b1) / 2;
827        sx2 = (sx1 + tx) / 2;   sy2 = (sy1 + ty) / 2;
828        tx2 = (a2 + x3) / 2;    ty2 = (b2 + y3) / 2;
829        tx1 = (tx2 + tx) / 2;   ty1 = (ty2 + ty) / 2;
830        xmid = (sx2 + tx1) / 2; ymid = (sy2 + ty1) / 2;
831
832        bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
833        bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
834    }
835}
836
837void genepic_ellipse(ell)
838F_ellipse *ell;
839{
840    F_point pt;
841
842    set_linewidth(ell->thickness);
843    pt.x = ell->center.x;
844    pt.y = ell->center.y;
845    convertCS(&pt);
846    if (TeXLang == EEpic || TeXLang == EEpic_emu ||
847          ell->radiuses.x != ell->radiuses.y ||
848          ell->radiuses.x > MaxCircleRadius) {
849        set_pattern(ell->area_fill);
850        fprintf(tfp, "\\put(%d,%d){", pt.x, pt.y );
851#ifndef OLDCODE
852        if (EllipseCmd == 0) {
853            if (ell->area_fill < UNFILLED) ell->area_fill = UNFILLED;
854            fprintf(tfp, "%s", FillCommands[ell->area_fill]);
855#  ifdef DrawOutLine
856            if (ell->area_fill != UNFILLED && OutLine == 0) OutLine = 1;
857#  endif
858        }
859        fprintf(tfp, EllCmdstr[EllipseCmd],EllCmdkw[EllipseCmd], "",
860               2 * ell->radiuses.x, 2 * ell->radiuses.y);
861#  ifdef DrawOutLine
862        if (OutLine == 1) {
863            OutLine=0;
864            fprintf(tfp, "\\put(%d,%d){", pt.x, pt.y );
865            fprintf(tfp, EllCmdstr[EllipseCmd],EllCmdkw[EllipseCmd], "",
866                   2 * ell->radiuses.x, 2 * ell->radiuses.y);
867        }
868#  endif
869#else
870        fprintf(tfp, EllCmdstr[EllipseCmd], EllCmdkw[EllipseCmd],
871               (EllipseCmd==0 && ell->area_fill==BLACK_FILL ? "*" : ""),
872               2 * ell->radiuses.x, 2 * ell->radiuses.y);
873#endif
874    } else {
875        fprintf(tfp, "\\put(%d,%d){\\circle", pt.x, pt.y);
876        if (ell->area_fill == BLACK_FILL) {
877            fputc('*', tfp);
878        }
879        fprintf(tfp, "{%d}}\n", 2*ell->radiuses.x);
880    }
881}
882
883extern char *ISOtoTeX[];
884void genepic_text(text)
885F_text *text;
886{
887    F_point pt;
888    char *tpos, *esc_cp, *special_index;
889    unsigned char   *cp;
890
891    pt.x=text->base_x;
892    pt.y=text->base_y;
893    convertCS(&pt);
894    switch (text->type) {
895    case T_LEFT_JUSTIFIED:
896    case DEFAULT:
897        tpos = "[lb]";
898        break;
899    case T_CENTER_JUSTIFIED:
900        tpos = "[b]";
901        break;
902    case T_RIGHT_JUSTIFIED:
903        tpos = "[rb]";
904        break;
905    default:
906        fprintf(stderr, "unknown text position type\n");
907        exit(1);
908    }
909    fprintf(tfp, "\\put(%d,%d){\\makebox(0,0)%s{\\smash{",
910           pt.x, pt.y, tpos);
911    /* Output a shortstack in case there are multiple lines. */
912    for(cp = (unsigned char*)text->cstring; *cp; cp++) {
913      if (*cp == TEXT_LINE_SEP) {
914    fprintf(tfp, "\\shortstack" );
915    /* Output the justification for the shortstack. */
916    switch (text->type) {
917    case T_LEFT_JUSTIFIED:
918    case DEFAULT:
919        fprintf(tfp, "[l]");
920        break;
921    case T_CENTER_JUSTIFIED:
922        break;
923    case T_RIGHT_JUSTIFIED:
924        fprintf(tfp, "[r]");
925        break;
926    default:
927        fprintf(stderr, "unknown text position type\n");
928        exit(1);
929        }
930        break;
931      }
932    }
933
934    unpsfont(text);
935    { int texsize;
936      double baselineskip;
937
938      texsize = TEXFONTMAG(text);
939      baselineskip = (texsize * 1.2);
940
941      fprintf(tfp, "{{\\SetFigFont{%d}{%.1f}{%s}",
942              texsize, baselineskip, TEXFONT(text->font));
943    }
944
945    if (!special_text(text))
946        /* This loop escapes special LaTeX characters. */
947        for(cp = (unsigned char*)text->cstring; *cp; cp++) {
948            if (special_index=strchr(latex_text_specials, *cp)) {
949              /* Write out the replacement.  Implementation note: we can't
950                 use puts since that will output an additional newline. */
951              esc_cp=latex_text_mappings[special_index-latex_text_specials];
952              while (*esc_cp)
953                fputc(*esc_cp++, tfp);
954            }
955            else if (*cp == TEXT_LINE_SEP) {
956              /* Handle multi-line text strings. The problem being addressed here
957                 is a LaTeX bug where LaTeX is unable to handle a font which
958                 spans multiple lines.  What we are doing here is closing off
959                 the current font, starting a new line, and then resuming with
960                 the current font. */
961              fprintf(tfp, "} \\\\\n");
962
963              { int texsize;
964                double baselineskip;
965 
966                texsize = TEXFONTMAG(text);
967                baselineskip = (texsize * 1.2);
968               
969                fprintf(tfp, "{\\SetFigFont{%d}{%.1f}{%s}",
970                        texsize, baselineskip, TEXFONT(text->font));
971              }
972            }
973            else
974                fputc(*cp, tfp);
975        }
976    else 
977        for(cp = (unsigned char*)text->cstring; *cp; cp++) {
978          if (*cp == TEXT_LINE_SEP) {
979              /* Handle multi-line text strings. */
980              fprintf(tfp, "} \\\\\n");
981
982              { int texsize;
983                double baselineskip;
984
985                texsize = TEXFONTMAG(text);
986                baselineskip = (texsize * 1.2);
987               
988                fprintf(tfp, "{\\SetFigFont{%d}{%.1f}{%s}",
989                        texsize, baselineskip, TEXFONT(text->font));
990              }
991            }
992            else
993                if (*cp >= 0xa0)        /* we escape 8-bit char */
994                        fprintf(tfp, "%s", ISOtoTeX[(int)*cp-0xa0]);
995                else
996                        fputc(*cp, tfp);
997          }
998    fprintf(tfp, "}}}}}\n");
999}
1000
1001void genepic_arc(arc)
1002F_arc *arc;
1003{
1004    FPoint pt1, pt2, ctr, tmp;
1005    double r1, r2, th1, th2, theta;
1006    double dx1, dy1, dx2, dy2;
1007    double arrowfactor;
1008
1009    ctr.x = arc->center.x;
1010    ctr.y = arc->center.y;
1011    pt1.x = arc->point[0].x;
1012    pt1.y = arc->point[0].y;
1013    pt2.x = arc->point[2].x;
1014    pt2.y = arc->point[2].y;
1015    fconvertCS(&ctr);
1016    fconvertCS(&pt1);
1017    fconvertCS(&pt2);
1018
1019    dx1 = pt1.x - ctr.x;
1020    dy1 = pt1.y - ctr.y;
1021    dx2 = pt2.x - ctr.x;
1022    dy2 = pt2.y - ctr.y;
1023
1024    rtop(dx1, dy1, &r1, &th1);
1025    rtop(dx2, dy2, &r2, &th2);
1026    arrowfactor = (r1+r2) / 30.0;
1027    if (arrowfactor > 1) arrowfactor = 1;
1028    set_linewidth(arc->thickness);
1029    if (arc->for_arrow) {
1030        arc_tangent(&ctr, &pt2, arc->direction, &tmp);
1031        fdraw_arrow_head(&tmp, &pt2,
1032                         arc->for_arrow->ht*arrowfactor,
1033                         arc->for_arrow->wid*arrowfactor);
1034        if (Verbose) fprintf(tfp, "%%\n");
1035    }
1036    if (arc->back_arrow) {
1037        arc_tangent(&ctr, &pt1, !arc->direction, &tmp);
1038        fdraw_arrow_head(&tmp, &pt1,
1039                         arc->back_arrow->ht*arrowfactor,
1040                         arc->back_arrow->wid*arrowfactor);
1041        if (Verbose) fprintf(tfp, "%%\n");
1042    }
1043    if (TeXLang == EEpic) {
1044        set_pattern(arc->area_fill);
1045        fprintf(tfp, "\\put(%4.3lf,%4.3lf){", ctr.x, ctr.y);
1046    } else {
1047        fprintf(tfp, "\\drawline");
1048    }
1049    if (TeXLang == EEpic) {
1050        if (arc->area_fill < UNFILLED) arc->area_fill = UNFILLED;
1051        fprintf(tfp, "%s", FillCommands[arc->area_fill]);
1052#ifdef DrawOutLine
1053        if (arc->area_fill != UNFILLED && OutLine==0) OutLine=1;
1054#endif
1055    }
1056    if (arc->direction) {
1057        theta = th2 - th1;
1058        if (theta < 0) theta += 2 * M_PI;
1059        th2 = 2*M_PI-th2;
1060        if (TeXLang == EEpic) {
1061            fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r1, th2, th2+theta);
1062#ifdef DrawOutLine
1063            if (OutLine==1) {
1064                OutLine=0;
1065                fprintf(tfp, "\\put(%4.3lf,%4.3lf){", ctr.x, ctr.y);
1066                fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r1, th2, th2+theta);
1067            }
1068#endif
1069        } else {
1070            drawarc(&ctr, r1, 2*M_PI - th2 - theta, theta);
1071        }
1072    } else {
1073        theta = th1 - th2;
1074        if (theta < 0) theta += 2 * M_PI;
1075        th1 = 2*M_PI-th1;
1076        if (TeXLang == EEpic) {
1077            fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r2, th1, th1+theta);
1078#ifdef DrawOutLine
1079            if (OutLine==1) {
1080                OutLine=0;
1081                fprintf(tfp, "\\put(%4.3lf,%4.3lf){", ctr.x, ctr.y);
1082                fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r2, th1, th1+theta);
1083            }
1084#endif
1085        } else {
1086            drawarc(&ctr, r2, 2*M_PI - th1 - theta, theta);
1087        }
1088    }
1089}
1090
1091drawarc(ctr, r, th1, angle)
1092FPoint *ctr;
1093double r, th1, angle;
1094{
1095    double arclength, delta;
1096    int division, pt_count = 0;
1097
1098
1099    division = angle * r / Threshold;
1100    delta = angle / division;
1101    division++;
1102    while (division-- > 0) {
1103        if (++pt_count > PtPerLine) {
1104            fprintf(tfp, "\n\t");
1105            pt_count = 1;
1106        }
1107        fprintf(tfp, "(%.3lf,%.3lf)", ctr->x + cos(th1) * r,
1108                                ctr->y + sin(th1) * r);
1109        th1 += delta;
1110    }
1111    fprintf(tfp, "\n");
1112}
1113
1114static arc_tangent(pt1, pt2, direction, pt3)
1115FPoint *pt1, *pt2, *pt3;
1116int direction;
1117{
1118    if (direction) {
1119        pt3->x = pt2->x + (pt2->y - pt1->y);
1120        pt3->y = pt2->y - (pt2->x - pt1->x);
1121    } else {
1122        pt3->x = pt2->x - (pt2->y - pt1->y);
1123        pt3->y = pt2->y + (pt2->x - pt1->x);
1124    }
1125}
1126
1127rtop(x, y, r, th)
1128double x, y, *r, *th;
1129{
1130    *r = sqrt(x*x+y*y);
1131    *th = acos(x/(*r));
1132    if (*th < 0) *th = M_PI + *th;
1133    if (y < 0) *th = 2*M_PI - *th;
1134}
1135
1136static draw_arrow_head(pt1, pt2, arrowht, arrowwid)
1137F_point *pt1, *pt2;
1138double arrowht, arrowwid;
1139{
1140    FPoint fpt1, fpt2;
1141
1142    fpt1.x = pt1->x;
1143    fpt1.y = pt1->y;
1144    fpt2.x = pt2->x;
1145    fpt2.y = pt2->y;
1146    fdraw_arrow_head(&fpt1, &fpt2, arrowht, arrowwid);
1147}
1148
1149fdraw_arrow_head(pt1, pt2, arrowht, arrowwid)
1150FPoint *pt1, *pt2;
1151double arrowht, arrowwid;
1152{
1153    double x1, y1, x2, y2;
1154    double x,y, xb,yb,dx,dy,l,sina,cosa;
1155    double xc, yc, xd, yd;
1156
1157    x1 = pt1->x;
1158    y1 = pt1->y;
1159    x2 = pt2->x;
1160    y2 = pt2->y;
1161
1162    dx = x2 - x1;  dy = y1 - y2;
1163    l = sqrt(dx*dx+dy*dy);
1164    if (l == 0) {
1165         return;
1166    }
1167    else {
1168         sina = dy / l;  cosa = dx / l;
1169    }
1170    xb = x2*cosa - y2*sina;
1171    yb = x2*sina + y2*cosa;
1172    x = xb - arrowht;
1173    y = yb - arrowwid / 2;
1174    xc = x*cosa + y*sina;
1175    yc = -x*sina + y*cosa;
1176    y = yb + arrowwid / 2;
1177    xd = x*cosa + y*sina;
1178    yd = -x*sina + y*cosa;
1179
1180    if (Verbose) fprintf(tfp, "%%\n%% arrow head\n%%\n");
1181
1182    fprintf(tfp, "\\%s(%4.3f,%4.3f)(%4.3f,%4.3f)(%4.3f,%4.3f)\n", LnCmd,
1183                xc, yc, x2, y2, xd, yd);
1184}
1185
1186#ifndef MSDOS
1187stricmp(s, t)
1188char *s, *t;
1189{
1190    char a, b;
1191
1192    for (;;) {
1193        a= *s++; b= *t++;
1194        a = islower(a) ? toupper(a) : a;
1195        b = islower(b) ? toupper(b) : b;
1196        if (a != b) break;
1197        if (a == '\0') return(0);
1198    }
1199    return(a - b);
1200}
1201#endif
1202
1203struct driver dev_epic = {
1204        genepic_option,
1205        genepic_start,
1206        genepic_arc,
1207        genepic_ellipse,
1208        genepic_line,
1209        genepic_spline,
1210        genepic_text,
1211        genepic_end,
1212        INCLUDE_TEXT
1213};
Note: See TracBrowser for help on using the repository browser.