[comp.sources.unix] v23i018: Tools for creating TeX documents with portable graphics, Part05/06

rsalz@bbn.com (Rich Salz) (08/31/90)

Submitted-by: Micah Beck <beck@cs.cornell.edu>
Posting-number: Volume 23, Issue 18
Archive-name: transfig/part05

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 6)."
# Contents:  transfig/fig2dev/dev/genepic.c
# Wrapped by beck@rocky on Thu May 17 15:56:13 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'transfig/fig2dev/dev/genepic.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'transfig/fig2dev/dev/genepic.c'\"
else
echo shar: Extracting \"'transfig/fig2dev/dev/genepic.c'\" \(28053 characters\)
sed "s/^X//" >'transfig/fig2dev/dev/genepic.c' <<'END_OF_FILE'
X/*
X * genepic.c: (E)EPIC driver for fig2dev
X *
X * Converted from fig2epic 5/89 by Micah Beck
X */
X/*==================================================================*/
X/*	fig2epic (Fig to EPIC converter) 			    */
X/*	     Version 1.1d <March 30, 1988>			    */
X/*								    */
X/*	Written by Conrad Kwok, Division of Computer Science, UCD   */
X/*								    */
X/*	Permission is granted for freely distribution of this file  */
X/*		provided that this message is included.		    */
X/*==================================================================*/
X
X/*====================================================================
X  Changes:
X
X  Version 1.0d:<September 18, 1988>
X  1. Add the option -P for Page mode. Two more configurable parameter---
X     Preamble and Postamble.
X
X  Version 1.1a: <January 18, 1989>
X  1. Fix the bug in closed control splines. The routine convertCS(p) is being
X     called once too often.
X
X  2. Add supports to Variable line width
X  3. Add supports to black, white or shaded area fill.
X
X  Version 1.1b: <Febrary 2, 1989>
X  1. Draw outline for area-filled figures when using dvips.
X
X  Version 1.1c: <Febrary 7, 1989>
X  1. Supports all 5 gray level in area fill.
X
X  Version 1.1d: <March 30, 1989>
X  1. Add supports for Gould NP1 (Bsd4.3) (Recieve the changes from
X		mcvax!presto.irisa.fr!hleroy@uunet.uu.net. Sorry
X		I don't have his/her name)
X  2. Add exit(0) before exit in the main.
X====================================================================*/
X
X  
X#include <stdio.h>
X#include <math.h>
X#include <string.h>
X#include <varargs.h>
X#include <ctype.h>
X#include "object.h"
X#include "fig2dev.h"
X#include "texfonts.h"
X#include "pi.h"
X
X#ifdef MSDOS
X#define getopt egetopt
X#define M_PI 3.14159265358979324
X#endif
X
X#define DrawOutLine
X#ifdef DrawOutLine
Xint OutLine=0;
X#endif
X
X#define TopCoord 840		/* 10.5 in * 80 (DPI)            */
X				/* Actually, it can be any value */
X#define PtPerLine 3
X#define ThinLines 0
X#define ThickLines 1
X#define FALSE 0
X#define TRUE 1
X#define Epic 0
X#define EEpic_emu 1
X#define EEpic 2
X#define None 0
X#define SolidLineBox 1
X#define DashLineBox 2
X#define BothBoxType 3
X#define Normal 0
X#define Economic 1
X#define DottedDash 2
X
Xvoid genepic_ctl_spline(), genepic_int_spline(); 
Xvoid genepic_open_spline(), genepic_closed_spline(); 
X
X/* Structure for Point with "double" values */
Xstruct fp_struct {
X    double x,y;
X};
X
Xtypedef struct fp_struct FPoint;
X
X/* Local to the file only */
Xstatic int CoordSys = 2;
Xstatic double Threshold;
Xstatic int DPI;
Xstatic int CurWidth = 0;
Xstatic int LineStyle = SOLID_LINE;
Xstatic int LLX = 0, LLY = 0;
Xstatic char *LnCmd;
Xstatic int MaxCircleRadius;
Xstatic double DashLen;
Xstatic int PageMode = FALSE;
Xstatic F_pattern *PatternType=UNFILLED;
Xstatic struct {
X    double mag;
X    int size;
X} ScaleTbl[5] = {
X    { 0.6667, 8 },
X    { 0.75  , 9 },
X    { 0.8333, 10 },
X    { 0.9167, 11 },
X    { 1.0   , 12 }
X};
X
X/* Definition of Keywords for some of the configurable parameter */
Xchar *Tlangkw[] = { /* The order must match the definition of corr. constants */
X    "Epic", "EEpicemu", "EEpic", NULL
X};
X
Xchar *EllCmdkw[] = {
X    "ellipse", "oval", NULL
X};
X
Xchar *EllCmdstr[] = {
X    "\\%s%s{%d}{%d}}\n", "\\%s%s(%d,%d)}\n"
X};
X
Xchar *FillCommands[] = {
X    "", "\\blacken", "\\shade", "\\shade", "\\shade", "\\whiten"
X};
X
X#define TEXT_LINE_SEP '\n'
X/* The following two arrays are used to translate characters which
X   are special to LaTeX into characters that print as one would expect.
X   Note that the <> characters aren't really special LaTeX characters
X   but they will not print as themselves unless one is using a font
X   like tt. */
Xchar latex_text_specials[] = "\\{}><^~$&#_%";
Xchar *latex_text_mappings[] = {
X  "$\\backslash$",
X  "$\\{$",
X  "$\\}$",
X  "$>$",
X  "$<$",
X  "\\^{}",
X  "\\~{}",
X  "\\$",
X  "\\&",
X  "\\#",
X  "\\_",
X  "\\%"};
X
X
X/* Configurable parameters */
Xint LowerLeftX=0, LowerLeftY=0;
Xdouble SegLen = 0.0625; /* inch */
Xint Verbose = FALSE;
Xint TopMargin = 5;
Xint BottomMargin = 10;
Xint DotDist = 5;
Xint LineThick = 2;
Xint TeXLang = EEpic;
Xdouble DashScale=1;
Xint EllipseCmd=0;
Xint UseBox=None;
Xint DashType=Normal;
Xchar *Preamble="\\documentstyle[epic,eepic]{article}\n\\begin{document}\n\\begin{center}\n";
Xchar *Postamble="\\end{center}\n\\end{document}\n";
Xint VarWidth=FALSE;
X
Xvoid genepic_option(opt, optarg)
Xchar opt, *optarg;
X{
X  	int loop;
X
X        switch (opt) {
X        case 'S':
X            loop = atoi(optarg);
X            if (loop < 8 || loop > 12) {
X            	put_msg("Scale must be between 8 and 12 inclusively\n");
X            	exit(1);
X            }
X            loop -= 8;
X            mag = ScaleTbl[loop].mag;
X            font_size = ScaleTbl[loop].size;
X            break;
X
X        case 'l':
X            LineThick = atoi(optarg);
X            break;
X
X        case 'v':
X            Verbose = TRUE;
X            break;
X
X	case 'L':
X	    for (loop=0; loop < 3; loop++) {
X	    	if (stricmp(optarg, Tlangkw[loop]) == 0) break;
X	    }
X	    TeXLang = loop;
X	    break;
X
X	case 'w':
X	case 'W':
X	    VarWidth = opt=='W';
X	    break;
X
X	case 'f':
X	{   int i;
X
X	    for ( i = 1; i <= MAXFONT + 1; i++ )
X		if ( !strcmp(optarg, fontnames[i]) ) break;
X
X	    if ( i > MAXFONT + 1 )
X		fprintf(stderr,
X			"warning: non-standard font name %s\n", optarg);
X	}
X	
X    	    fontnames[0] = fontnames[1] = optarg;
X	    break;
X
X	case 's':
X	    if (font_size <= 0 || font_size > MAXFONTSIZE) {
X		fprintf(stderr,
X			"warning: font size %d out of bounds\n", font_size);
X	    }
X	    break;
X
X	case 'm':
X	    break;
X
X	default:
X	    put_msg(Err_badarg, opt, "epic");
X	    exit(1);
X	    break;
X        }
X}
X
Xstatic fconvertCS(fpt)
XFPoint *fpt;
X{
X    if (CoordSys) {
X        fpt->y = TopCoord - fpt->y;
X    }
X    fpt->x -= LLX;
X    fpt->y -= LLY;
X}
X
XconvertCS(pt)
XF_point *pt;
X{
X    if (CoordSys) {
X        pt->y = TopCoord - pt->y;
X    }
X    pt->x -= LLX;
X    pt->y -= LLY;
X}
X
Xvoid genepic_start(objects)
XF_compound *objects;
X{
X    int temp;
X    F_point pt1, pt2;
X    F_arc *arc;
X    F_compound *comp;
X    F_ellipse *ell;
X    F_line *line;
X    F_spline *spl;
X    F_text *text;
X
X    fontsizes[0] = fontsizes[1] = TEXFONTSIZE(font_size);
X
X    switch (TeXLang) {
X    case Epic:
X        EllipseCmd = 1; /* Oval */
X        LnCmd = "drawline";
X        break;
X    case EEpic_emu:
X    case EEpic:
X        LnCmd = "path";
X        break;
X    default:
X        put_msg("Program error in main\n");
X        break;
X    }
X    if (PageMode) {
X        fputs(Preamble, stdout);
X    }
X
X    DPI = objects->nwcorner.x;
X    if (DPI <= 0) {
X        put_msg("Resolution has to be positive. Default to 80!\n");
X        DPI = 80;
X    }
X    coord_system = objects->nwcorner.y;
X    switch (coord_system) {
X    case 1:
X        CoordSys = 0;
X        break;
X    case 2:
X        CoordSys = 1;
X        break;
X    default:
X        put_msg("Unknown Coordinate system -- %d\n", coord_system);
X        exit(1);
X    }
X    pt1.x = llx;
X    pt1.y = lly;
X    pt2.x = urx;
X    pt2.y = ury;
X    convertCS(&pt1);
X    convertCS(&pt2);
X    if (pt1.x > pt2.x) {
X        temp = pt1.x;
X        pt1.x = pt2.x;
X        pt2.x = temp;
X    }
X    if (pt1.y > pt2.y) {
X        temp = pt1.y;
X        pt1.y = pt2.y;
X        pt2.y = temp;
X    }
X    LLX = pt1.x - LowerLeftX;
X    LLY = pt1.y - LowerLeftY;
X    if (Verbose) {
X        fprintf(tfp, "%%\n%% Language in use is %s\n%%\n", Tlangkw[TeXLang]);
X    }
X    Threshold = 1.0 / DPI * mag;
X    fprintf(tfp, "\\setlength{\\unitlength}{%.4fin}\n", Threshold);
X    MaxCircleRadius = (int) (40 / 72.27 / Threshold);
X    Threshold = SegLen / Threshold;
X    fprintf(tfp, "\\begin{picture}(%d,%d)(%d,%d)\n",
X           pt2.x-pt1.x, pt2.y-pt1.y + TopMargin + BottomMargin,
X           LowerLeftX, LowerLeftY-BottomMargin);
X}
X
Xvoid genepic_end()
X{
X    fprintf(tfp, "\\end{picture}\n");
X    if (PageMode)
X        fputs(Postamble, stdout);
X}
X
Xstatic set_linewidth(w)
Xint w;
X{
X    int old_width;
X
X    if (w < 0) return;
X    old_width=CurWidth;
X    CurWidth = (w >= LineThick) ? (VarWidth ? w : ThickLines) : ThinLines;
X    if (old_width != CurWidth) {
X	if (CurWidth==ThinLines) {
X	    fprintf(tfp, "\\thinlines\n");
X	} else if (VarWidth) {
X	    fprintf(tfp, "\\allinethickness{%d}%%\n",w);
X	} else {
X	    fprintf(tfp, "\\thicklines\n");
X	}
X    }
X}
X
Xset_pattern(type)
XF_pattern *type;
X{
X    static unsigned long patterns[3][32] = {
X	{ 0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0,
X	  0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0,
X	  0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0,
X	  0x55555555, 0, 0x55555555, 0, 0x55555555, 0, 0x55555555, 0},
X	{ 0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0,
X	  0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0,
X	  0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0,
X	  0xcccccccc, 0, 0, 0, 0xcccccccc, 0, 0, 0},
X	{ 0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0,
X	  0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0,
X	  0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0,
X	  0xc0c0c0c0, 0, 0, 0, 0, 0, 0, 0}};
X    int count, loop1, loop2, i;
X
X    if (type < DARK_GRAY_FILL || type > LIGHT_GRAY_FILL) return;
X    if (type != PatternType) {
X	PatternType=type;
X	i = (int) PatternType - (int) DARK_GRAY_FILL;
X	fprintf(tfp, "\\texture{");
X	count=0;
X	for (loop1=4; loop1>0;) {
X	    for (loop2=8; loop2>0; loop2--) 
X		fprintf(tfp, "%lx ", patterns[i][count++]);
X	    if (--loop1 > 0)
X		fprintf(tfp, "\n\t");
X	    else
X		fprintf(tfp, "}%\n");
X	}
X    }
X}
X
Xvoid genepic_line(line)
XF_line *line;
X{
X    F_point *p, *q;
X    int pt_count = 0, temp;
X    int boxflag = FALSE, llx, lly, urx, ury;
X    double dtemp;
X
X    set_linewidth(line->thickness);
X    set_style(line->style, line->style_val);
X    p = line->points;
X    q = p->next;
X    convertCS(p);
X    if (q == NULL) {
X	fprintf(tfp, "\\drawline(%d,%d)(%d,%d)\n", p->x, p->y, p->x, p->y);
X	return;
X    }
X    if (line->type == T_BOX) {
X	if (Verbose) {
X	    fprintf(tfp, "%%\n%% A box\n%%\n");
X	}
X	switch (LineStyle) {
X	case SOLID_LINE:
X	    if (UseBox == BothBoxType || UseBox == SolidLineBox) {
X	        boxflag = TRUE;
X	    }
X	    break;
X	case DASH_LINE:
X	    if (UseBox == BothBoxType || UseBox == DashLineBox) {
X	        boxflag = TRUE;
X	    }
X	    break;
X	}
X	if (boxflag) {
X	    llx = urx = p->x;
X	    lly = ury = p->y;
X	    while (q != NULL) {
X	        convertCS(q);
X	        if (q->x < llx) {
X	            llx = q->x;
X	        } else if (q->x > urx) {
X	            urx = q->x;
X	        }
X	        if (q->y < lly) {
X	            lly = q->y;
X	        } else if (q->y > ury) {
X	            ury = q->y;
X	        }
X	        q = q->next;
X	    }
X	    switch(LineStyle) {
X	    case SOLID_LINE:
X	        fprintf(tfp, "\\put(%d,%d){\\framebox(%d,%d){}}\n",
X	            llx, lly, urx-llx, ury-lly);
X	        break;
X	    case DASH_LINE:
X		temp = (int) ((urx-llx) / DashLen);
X		dtemp = (double) (urx-llx) / temp;
X	        fprintf(tfp, "\\put(%d,%d){\\dashbox{%4.3f}(%d,%d){}}\n",
X	            llx, lly, dtemp , urx-llx, ury-lly);
X	        break;
X	    default:
X	        put_msg("Program Error! No other line styles allowed.\n");
X	        break;
X	    }
X	    return;
X	  }
X    }
X    set_pattern(line->area_fill);
X    convertCS(q);
X    if (line->back_arrow) {
X	draw_arrow_head(q, p, line->back_arrow->ht, line->back_arrow->wid);
X    	if (Verbose) fprintf(tfp, "%%\n");
X    }
X    switch (LineStyle) {
X    case SOLID_LINE:
X	if (q->next != NULL && strcmp(LnCmd,"path")==0) {
X	    if (line->area_fill < UNFILLED) line->area_fill = UNFILLED;
X	    fprintf(tfp, "%s", FillCommands[(int) line->area_fill]);
X	}
X	fprintf(tfp, "\\%s", LnCmd);
X#ifdef DrawOutLine
X	if (line->area_fill != UNFILLED && OutLine == 0) OutLine=1;
X#endif
X	break;
X    case DASH_LINE:
X        if ((TeXLang==Epic || TeXLang ==EEpic_emu) && DashType == Economic) {
X            fprintf(tfp, "\\drawline[-50]");
X        } else {
X	    fprintf(tfp, "\\dashline{%4.3f}", DashLen);
X	}
X	break;
X    case DOTTED_LINE:
X	fprintf(tfp, "\\dottedline{%d}", DotDist);
X	break;
X    default:
X	fprintf(stderr,"Unknown Style\n");
X	exit(1);
X    }
X    fprintf(tfp, "(%d,%d)", p->x, p->y);
X    pt_count++;
X    while(q->next != NULL) {
X	if (++pt_count > PtPerLine) {
X	    pt_count=1;
X	    fprintf(tfp, "\n\t");
X	}
X	fprintf(tfp, "(%d,%d)", q->x, q->y);
X	p=q;
X	q = q->next;
X	convertCS(q);
X    }
X    fprintf(tfp, "(%d,%d)\n", q->x, q->y);
X#ifdef DrawOutLine
X    if (OutLine == 1) {
X	OutLine=0;
X	fprintf(tfp, "\\%s", LnCmd);
X	p=line->points;
X	pt_count=0;
X	q=p->next;
X	fprintf(tfp, "(%d,%d)", p->x, p->y);
X	pt_count++;
X	while(q->next != NULL) {
X	    if (++pt_count > PtPerLine) {
X		pt_count=1;
X		fprintf(tfp, "\n\t");
X	    }
X	    fprintf(tfp, "(%d,%d)", q->x, q->y);
X	    p=q;
X	    q = q->next;
X	}
X	fprintf(tfp, "(%d,%d)\n", q->x, q->y);
X    }
X#endif
X    if (line->for_arrow) {
X	draw_arrow_head(p, q, line->for_arrow->ht, line->for_arrow->wid);
X    	if (Verbose) fprintf(tfp, "%%\n");
X    }
X}
X
Xset_style(style, dash_len)
Xint style;
Xfloat dash_len;
X{
X    LineStyle = style;
X    if (LineStyle == DASH_LINE) {
X        switch (DashType) {
X        case DottedDash:
X            LineStyle = DOTTED_LINE;
X            break;
X        default:
X            DashLen = dash_len * DashScale;
X            break;
X        }
X    }
X}
X
X
Xvoid genepic_spline(spl)
XF_spline *spl;
X{
X    set_linewidth(spl->thickness);
X    set_style(SOLID_LINE, 0.0);
X    if (int_spline(spl)) {
X	genepic_itp_spline(spl);
X    } else {
X	genepic_ctl_spline(spl);
X    }
X}
X
Xvoid genepic_ctl_spline(spl)
XF_spline *spl;
X{
X    if (closed_spline(spl)) {
X	genepic_closed_spline(spl);
X    } else {
X	genepic_open_spline(spl);
X    }
X}
X
Xstatic void genepic_open_spline(spl)
XF_spline *spl;
X{
X    F_point *p, *q, *r;
X    FPoint first, mid;
X    int pt_count = 0;
X
X    p = spl->points;
X    q = p->next;
X    convertCS(p);
X    convertCS(q);
X    if (spl->back_arrow) {
X	draw_arrow_head(q, p, spl->back_arrow->ht, spl->back_arrow->wid);
X    	if (Verbose) fprintf(tfp, "%%\n");
X    }
X    if (q->next == NULL) {
X	fprintf(tfp, "\\%s(%d,%d)(%d,%d)\n", LnCmd,
X	       p->x, p->y, q->x, q->y);
X	return;
X    }
X    if (TeXLang == EEpic || TeXLang == EEpic_emu) {
X        fprintf(tfp, "\\spline(%d,%d)\n", p->x, p->y);
X        pt_count++;
X        while(q->next != NULL) {
X             if (++pt_count > PtPerLine) {
X                 pt_count=1;
X                 fprintf(tfp, "\n\t");
X             }
X             fprintf(tfp, "(%d,%d)", q->x, q->y);
X             p=q;
X             q = q->next;
X             convertCS(q);
X        }
X        fprintf(tfp, "(%d,%d)\n", q->x, q->y);
X    } else {
X        fprintf(tfp, "\\%s(%d,%d)\n", LnCmd, p->x, p->y);
X        r = q->next;
X        convertCS(r);
X        first.x = p->x;
X        first.y = p->y;
X        while (r->next != NULL) {
X            mid.x = (q->x + r->x) / 2.0;
X            mid.y = (q->y + r->y) / 2.0;
X            chaikin_curve(first.x, first.y, (double) q->x, (double) q->y,
X                            mid.x, mid.y);
X            first = mid;
X            q=r;
X            r = r->next;
X            convertCS(r);
X        }
X        chaikin_curve(first.x, first.y, (double) q->x, (double) q->y,
X                        (double) r->x, (double) r->y);
X        p=q;
X        q=r;
X	fprintf(tfp, "\n");
X    }
X    if (spl->for_arrow) {
X	draw_arrow_head(p, q, spl->for_arrow->ht, spl->for_arrow->wid);
X    	if (Verbose) fprintf(tfp, "%%\n");
X    }
X}
X
Xstatic void genepic_closed_spline(spl)
XF_spline *spl;
X{
X    F_point *p;
X    double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
X    double x1, y1, x2, y2;
X
X    p = spl->points;
X    convertCS(p);
X    x1 = p->x;  y1 = p->y;
X    p = p->next;
X    convertCS(p);
X    x2 = p->x;  y2 = p->y;
X    cx1 = (x1 + x2) / 2;      cy1 = (y1 + y2) / 2;
X    cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
X    for (p = p->next; p != NULL; p = p->next) {
X	fprintf(tfp, "\\%s(%.3f,%.3f)", LnCmd, cx1, cy1);
X	x1 = x2;  y1 = y2;
X	convertCS(p);
X	x2 = p->x;  y2 = p->y;
X	cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
X	cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
X	quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
X	fprintf(tfp, "\n");
X	cx1 = cx4;  cy1 = cy4;
X	cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
X    }
X    x1 = x2;  y1 = y2;
X    p = spl->points->next;
X    x2 = p->x;  y2 = p->y;
X    cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
X    cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
X    fprintf(tfp, "\\%s(%.3f,%.3f)", LnCmd, cx1, cy1);
X    quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
X    fprintf(tfp, "\n");
X}
X
Xchaikin_curve(a1, b1, a2, b2, a3, b3)
Xdouble a1, b1, a2, b2, a3, b3;
X{
X    double xm1, xmid, xm2, ym1, ymid, ym2;
X
X    if (fabs(a1-a3) < Threshold && fabs(b1-b3) < Threshold) {
X        fprintf(tfp, "\t(%.3f,%.3f)\n", a3, b3);
X    } else {
X        xm1 = (a1 + a2) / 2;
X        ym1 = (b1 + b2) / 2;
X        xm2 = (a2 + a3) / 2;
X        ym2 = (b2 + b3) / 2;
X        xmid = (xm1 + xm2) / 2;
X        ymid = (ym1 + ym2) / 2;
X        chaikin_curve(a1, b1, xm1, ym1, xmid, ymid);
X        chaikin_curve(xmid, ymid, xm2, ym2, a3, b3);
X    }
X}
X
Xstatic quadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4)
Xdouble	a1, b1, a2, b2, a3, b3, a4, b4;
X{
X    double	x1, y1, x4, y4;
X    double	xmid, ymid;
X
X    x1 = a1; y1 = b1;
X    x4 = a4; y4 = b4;
X
X    xmid = (a2 + a3) / 2;
X    ymid = (b2 + b3) / 2;
X    if (fabs(x1 - xmid) < Threshold && fabs(y1 - ymid) < Threshold) {
X	fprintf(tfp, "\t(%.3f,%.3f)\n", xmid, ymid);
X    } else {
X	quadratic_spline(x1, y1, ((x1+a2)/2), ((y1+b2)/2),
X			 ((3*a2+a3)/4), ((3*b2+b3)/4), xmid, ymid);
X    }
X
X    if (fabs(xmid - x4) < Threshold && fabs(ymid - y4) < Threshold) {
X	fprintf(tfp, "\t(%.3f,%.3f)\n", x4, y4);
X    } else {
X	quadratic_spline(xmid, ymid, ((a2+3*a3)/4), ((b2+3*b3)/4),
X			 ((a3+x4)/2), ((b3+y4)/2), x4, y4);
X    }
X}
X
Xgenepic_itp_spline(spl)
XF_spline *spl;
X{
X    F_point *p1, *p2;
X    FPoint pt1l, pt1r, pt2l, pt2r, tmpfpt;
X    F_control *cp1, *cp2;
X
X    p1 = spl->points;
X    convertCS(p1);
X    cp1 = spl->controls;
X    pt1l.x = cp1->lx;
X    pt1l.y = cp1->ly;
X    pt1r.x = cp1->rx;
X    pt1r.y = cp1->ry;
X    fconvertCS(&pt1l);
X    fconvertCS(&pt1r);
X
X    if (spl->back_arrow) {
X	tmpfpt.x = p1->x;
X	tmpfpt.y = p1->y;
X	fdraw_arrow_head(&pt1r, &tmpfpt, 
X		spl->back_arrow->ht, spl->back_arrow->wid);
X    	if (Verbose) fprintf(tfp, "%%\n");
X    }
X
X    for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
X	 p1 = p2, pt1r = pt2r, p2 = p2->next, cp2 = cp2->next) {
X	fprintf(tfp, "\\%s(%d,%d)", LnCmd, p1->x, p1->y);
X	convertCS(p2);
X	pt2l.x = cp2->lx;
X	pt2l.y = cp2->ly;
X	pt2r.x = cp2->rx;
X	pt2r.y = cp2->ry;
X	fconvertCS(&pt2l);
X	fconvertCS(&pt2r);
X	bezier_spline((double) p1->x, (double) p1->y,
X		      pt1r.x, pt1r.y,
X		      pt2l.x, pt2l.y,
X		      (double) p2->x, (double) p2->y);
X	fprintf(tfp, "\n");
X    }
X
X    if (spl->for_arrow) {
X	tmpfpt.x = p1->x;
X	tmpfpt.y = p1->y;
X	fdraw_arrow_head(&pt2l, &tmpfpt, 
X			 spl->for_arrow->ht, spl->for_arrow->wid);
X	if (Verbose) fprintf(tfp, "%%\n");
X    }
X}
X
Xstatic bezier_spline(a0, b0, a1, b1, a2, b2, a3, b3)
Xdouble	a0, b0, a1, b1, a2, b2, a3, b3;
X{
X    double	x0, y0, x3, y3;
X    double	sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid;
X
X    x0 = a0; y0 = b0;
X    x3 = a3; y3 = b3;
X    if (fabs(x0 - x3) < Threshold && fabs(y0 - y3) < Threshold) {
X	fprintf(tfp, "\t(%.3f,%.3f)\n", x3, y3);
X    } else {
X	tx = (a1 + a2) / 2;		ty = (b1 + b2) / 2;
X	sx1 = (x0 + a1) / 2;	sy1 = (y0 + b1) / 2;
X	sx2 = (sx1 + tx) / 2;	sy2 = (sy1 + ty) / 2;
X	tx2 = (a2 + x3) / 2;	ty2 = (b2 + y3) / 2;
X	tx1 = (tx2 + tx) / 2;	ty1 = (ty2 + ty) / 2;
X	xmid = (sx2 + tx1) / 2;	ymid = (sy2 + ty1) / 2;
X
X	bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
X	bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
X    }
X}
X
Xvoid genepic_ellipse(ell)
XF_ellipse *ell;
X{
X    F_point pt;
X
X    set_linewidth(ell->thickness);
X    pt.x = ell->center.x;
X    pt.y = ell->center.y;
X    convertCS(&pt);
X    if (TeXLang == EEpic || TeXLang == EEpic_emu ||
X	  ell->radiuses.x != ell->radiuses.y ||
X          ell->radiuses.x > MaxCircleRadius) {
X	set_pattern(ell->area_fill);
X        fprintf(tfp, "\\put(%d,%d){", pt.x, pt.y );
X#ifndef OLDCODE
X        if (EllipseCmd == 0) {
X	    if (ell->area_fill < UNFILLED) ell->area_fill = UNFILLED;
X	    fprintf(tfp, "%s", FillCommands[(int) ell->area_fill]);
X#  ifdef DrawOutLine
X	    if (ell->area_fill != UNFILLED && OutLine == 0) OutLine = 1;
X#  endif
X        }
X 	fprintf(tfp, EllCmdstr[EllipseCmd],EllCmdkw[EllipseCmd], "",
X	       2 * ell->radiuses.x, 2 * ell->radiuses.y);
X#  ifdef DrawOutLine
X	if (OutLine == 1) {
X	    OutLine=0;
X            fprintf(tfp, "\\put(%d,%d){", pt.x, pt.y );
X	    fprintf(tfp, EllCmdstr[EllipseCmd],EllCmdkw[EllipseCmd], "",
X		   2 * ell->radiuses.x, 2 * ell->radiuses.y);
X	}
X#  endif
X#else
X	fprintf(tfp, EllCmdstr[EllipseCmd], EllCmdkw[EllipseCmd],
X	       (EllipseCmd==0 && ell->area_fill==BLACK_FILL ? "*" : ""),
X	       2 * ell->radiuses.x, 2 * ell->radiuses.y);
X#endif
X    } else {
X        fprintf(tfp, "\\put(%d,%d){\\circle", pt.x, pt.y);
X        if (ell->area_fill == BLACK_FILL) {
X            fputc('*', tfp);
X        }
X        fprintf(tfp, "{%d}}\n", 2*ell->radiuses.x);
X    }
X}
X
Xvoid genepic_text(text)
XF_text *text;
X{
X    F_point pt;
X    char *tpos, *cp, *esc_cp, *special_index;
X
X    pt.x=text->base_x;
X    pt.y=text->base_y;
X    convertCS(&pt);
X    switch (text->type) {
X    case T_LEFT_JUSTIFIED:
X    case DEFAULT:
X	tpos = "[lb]";
X	break;
X    case T_CENTER_JUSTIFIED:
X	tpos = "[b]";
X	break;
X    case T_RIGHT_JUSTIFIED:
X	tpos = "[rb]";
X	break;
X    default:
X	fprintf(stderr, "unknown text position type\n");
X	exit(1);
X    }
X    fprintf(tfp, "\\put(%d,%d){\\makebox(0,0)%s{\\raisebox{0pt}[0pt][0pt]{",
X           pt.x, pt.y, tpos);
X    /* Output a shortstack in case there are multiple lines. */
X    fprintf(tfp, "\\shortstack" );
X    /* Output the justification for the shortstack. */
X    switch (text->type) {
X    case T_LEFT_JUSTIFIED:
X    case DEFAULT:
X	fprintf(tfp, "[l]");
X	break;
X    case T_CENTER_JUSTIFIED:
X	break;
X    case T_RIGHT_JUSTIFIED:
X	fprintf(tfp, "[r]");
X	break;
X    default:
X	fprintf(stderr, "unknown text position type\n");
X	exit(1);
X    }
X    fprintf(tfp, "{{\\%s%s ", TEXFONTSIZE(text->size), TEXFONT(text->font));
X    if (text->font && text->font != DEFAULT_FONT)
X	/* This loop escapes special LaTeX characters. */
X	for(cp = text->cstring; *cp; cp++) {
X      	    if (special_index=strchr(latex_text_specials, *cp)) {
X	      /* Write out the replacement.  Implementation note: we can't
X		 use puts since that will output an additional newline. */
X	      esc_cp=latex_text_mappings[special_index-latex_text_specials];
X	      while (*esc_cp)
X		fputc(*esc_cp++, tfp);
X	    }
X	    else if (*cp == TEXT_LINE_SEP) {
X	      /* Handle multi-line text strings. The problem being addressed here
X		 is a LaTeX bug where LaTeX is unable to handle a font which
X		 spans multiple lines.  What we are doing here is closing off
X		 the current font, starting a new line, and then resuming with
X		 the current font. */
X	      fprintf(tfp, "} \\\\\n");
X	      fprintf(tfp, "{\\%s%s ", TEXFONTSIZE(text->size), TEXFONT(text->font));
X	    }
X	    else
X		fputc(*cp, tfp);
X      	}
X    else 
X	for(cp = text->cstring; *cp; cp++) {
X	  if (*cp == TEXT_LINE_SEP) {
X	      /* Handle multi-line text strings. */
X	      fprintf(tfp, "} \\\\\n");
X	      fprintf(tfp, "{\\%s%s ", TEXFONTSIZE(text->size), TEXFONT(text->font));
X	    }
X	    else 
X	      fputc(*cp, tfp);
X	  }
X    fprintf(tfp, "}}}}}\n");
X}
X
Xvoid genepic_arc(arc)
XF_arc *arc;
X{
X    FPoint pt1, pt2, ctr, tmp;
X    double r1, r2, th1, th2, theta;
X    double dx1, dy1, dx2, dy2;
X    double arrowfactor;
X
X    ctr.x = arc->center.x;
X    ctr.y = arc->center.y;
X    pt1.x = arc->point[0].x;
X    pt1.y = arc->point[0].y;
X    pt2.x = arc->point[2].x;
X    pt2.y = arc->point[2].y;
X    fconvertCS(&ctr);
X    fconvertCS(&pt1);
X    fconvertCS(&pt2);
X
X    dx1 = pt1.x - ctr.x;
X    dy1 = pt1.y - ctr.y;
X    dx2 = pt2.x - ctr.x;
X    dy2 = pt2.y - ctr.y;
X
X    rtop(dx1, dy1, &r1, &th1);
X    rtop(dx2, dy2, &r2, &th2);
X    arrowfactor = (r1+r2) / 30.0;
X    if (arrowfactor > 1) arrowfactor = 1;
X    set_linewidth(arc->thickness);
X    if (arc->for_arrow) {
X	arc_tangent(&ctr, &pt2, arc->direction, &tmp);
X	fdraw_arrow_head(&tmp, &pt2,
X			 arc->for_arrow->ht*arrowfactor,
X			 arc->for_arrow->wid*arrowfactor);
X    	if (Verbose) fprintf(tfp, "%%\n");
X    }
X    if (arc->back_arrow) {
X	arc_tangent(&ctr, &pt1, !arc->direction, &tmp);
X	fdraw_arrow_head(&tmp, &pt1,
X			 arc->back_arrow->ht*arrowfactor,
X			 arc->back_arrow->wid*arrowfactor);
X    	if (Verbose) fprintf(tfp, "%%\n");
X    }
X    if (TeXLang == EEpic) {
X	set_pattern(arc->area_fill);
X        fprintf(tfp, "\\put(%4.3lf,%4.3lf){", ctr.x, ctr.y);
X    } else {
X	fprintf(tfp, "\\drawline");
X    }
X    if (TeXLang == EEpic) {
X	if (arc->area_fill < UNFILLED) arc->area_fill = UNFILLED;
X	fprintf(tfp, "%s", FillCommands[(int) arc->area_fill]);
X#ifdef DrawOutLine
X	if (arc->area_fill != UNFILLED && OutLine==0) OutLine=1;
X#endif
X    }
X    if (arc->direction) {
X	theta = th2 - th1;
X	if (theta < 0) theta += 2 * M_PI;
X	th2 = 2*M_PI-th2;
X	if (TeXLang == EEpic) {
X	    fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r1, th2, th2+theta);
X#ifdef DrawOutLine
X	    if (OutLine==1) {
X		OutLine=0;
X	        fprintf(tfp, "\\put(%4.3lf,%4.3lf){", ctr.x, ctr.y);
X		fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r1, th2, th2+theta);
X	    }
X#endif
X        } else {
X            drawarc(&ctr, r1, 2*M_PI - th2 - theta, theta);
X        }
X    } else {
X	theta = th1 - th2;
X	if (theta < 0) theta += 2 * M_PI;
X	th1 = 2*M_PI-th1;
X	if (TeXLang == EEpic) {
X	    fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r2, th1, th1+theta);
X#ifdef DrawOutLine
X	    if (OutLine==1) {
X		OutLine=0;
X		fprintf(tfp, "\\arc{%4.3f}{%2.4f}{%2.4f}}\n", 2*r2, th1, th1+theta);
X	    }
X#endif
X        } else {
X            drawarc(&ctr, r2, 2*M_PI - th1 - theta, theta);
X        }
X    }
X}
X
Xdrawarc(ctr, r, th1, angle)
XFPoint *ctr;
Xdouble r, th1, angle;
X{
X    double arclength, delta;
X    int division, pt_count = 0;
X
X
X    division = angle * r / Threshold;
X    delta = angle / division;
X    division++;
X    while (division-- > 0) {
X        if (++pt_count > PtPerLine) {
X            fprintf(tfp, "\n\t");
X            pt_count = 1;
X        }
X        fprintf(tfp, "(%.3lf,%.3lf)", ctr->x + cos(th1) * r,
X                                ctr->y + sin(th1) * r);
X        th1 += delta;
X    }
X    fprintf(tfp, "\n");
X}
X
Xstatic arc_tangent(pt1, pt2, direction, pt3)
XFPoint *pt1, *pt2, *pt3;
Xint direction;
X{
X    if (direction) {
X	pt3->x = pt2->x + (pt2->y - pt1->y);
X	pt3->y = pt2->y - (pt2->x - pt1->x);
X    } else {
X	pt3->x = pt2->x - (pt2->y - pt1->y);
X	pt3->y = pt2->y + (pt2->x - pt1->x);
X    }
X}
X
Xrtop(x, y, r, th)
Xdouble x, y, *r, *th;
X{
X    *r = hypot(x,y);
X    *th = acos(x/(*r));
X    if (*th < 0) *th = M_PI + *th;
X    if (y < 0) *th = 2*M_PI - *th;
X}
X
Xstatic draw_arrow_head(pt1, pt2, arrowht, arrowwid)
XF_point *pt1, *pt2;
Xdouble arrowht, arrowwid;
X{
X    FPoint fpt1, fpt2;
X
X    fpt1.x = pt1->x;
X    fpt1.y = pt1->y;
X    fpt2.x = pt2->x;
X    fpt2.y = pt2->y;
X    fdraw_arrow_head(&fpt1, &fpt2, arrowht, arrowwid);
X}
X
Xfdraw_arrow_head(pt1, pt2, arrowht, arrowwid)
XFPoint *pt1, *pt2;
Xdouble arrowht, arrowwid;
X{
X    double x1, y1, x2, y2;
X    double x,y, xb,yb,dx,dy,l,sina,cosa;
X    double xc, yc, xd, yd;
X
X    x1 = pt1->x;
X    y1 = pt1->y;
X    x2 = pt2->x;
X    y2 = pt2->y;
X
X    if (Verbose) fprintf(tfp, "%%\n%% arrow head\n%%\n");
X
X    dx = x2 - x1;  dy = y1 - y2;
X    l = hypot(dx,dy);
X    sina = dy / l;  cosa = dx / l;
X    xb = x2*cosa - y2*sina;
X    yb = x2*sina + y2*cosa;
X    x = xb - arrowht;
X    y = yb - arrowwid / 2;
X    xc = x*cosa + y*sina;
X    yc = -x*sina + y*cosa;
X    y = yb + arrowwid / 2;
X    xd = x*cosa + y*sina;
X    yd = -x*sina + y*cosa;
X
X    fprintf(tfp, "\\%s(%4.3f,%4.3f)(%4.3f,%4.3f)(%4.3f,%4.3f)\n", LnCmd,
X		xc, yc, x2, y2, xd, yd);
X}
X
X#ifndef MSDOS
Xstricmp(s, t)
Xchar *s, *t;
X{
X    char a, b;
X
X    for (;;) {
X        a= *s++; b= *t++;
X        a = islower(a) ? toupper(a) : a;
X        b = islower(b) ? toupper(b) : b;
X        if (a != b) break;
X        if (a == '\0') return(0);
X    }
X    return(a - b);
X}
X#endif
X
Xstruct driver dev_epic = {
X     	genepic_option,
X	genepic_start,
X	genepic_arc,
X	genepic_ellipse,
X	genepic_line,
X	genepic_spline,
X	genepic_text,
X	genepic_end,
X	INCLUDE_TEXT
X};
END_OF_FILE
if test 28053 -ne `wc -c <'transfig/fig2dev/dev/genepic.c'`; then
    echo shar: \"'transfig/fig2dev/dev/genepic.c'\" unpacked with wrong size!
fi
# end of 'transfig/fig2dev/dev/genepic.c'
fi
echo shar: End of archive 5 \(of 6\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.