[comp.sources.misc] v03i088: HPGL to LaserJet translator, part 2 of 3

edf@ROCKEFELLER.ARPA (David MacKenzie) (07/16/88)

Posting-number: Volume 3, Issue 88
Submitted-by: "David MacKenzie" <edf@ROCKEFELLER.ARPA>
Archive-name: hpglplot/Part2

#! /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 2 (of 3)."
# Contents:  end_ref.c ep_map.c hpglfix.c hpglplot.doc ib_map.c
#   lj_map.c step.c
# Wrapped by dave@zedfdc  on Fri Jul  8 20:50:51 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'end_ref.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'end_ref.c'\"
else
echo shar: Extracting \"'end_ref.c'\" \(3894 characters\)
sed "s/^X//" >'end_ref.c' <<'END_OF_FILE'
X/*
X * end_ref.c
X *
X * Copyright (c) 1988 Environmental Defense Fund, Inc.
X */
X
X#include <stdio.h>
X#include <math.h>
X#include "const.h"
X#include "vars.h"
X#include "fillcnst.h"
X#include "fillvars.h"
X#ifdef TESTVER
X#include "dbgvars.h"
X#endif
X
X#ifdef __STDC__
Xint
Xend_ref(POINT A, POINT B, POINT C);
Xint
Xchoose_step(FPOINT *f_pt_s1p, double chg_x_s1, double chg_y_s1,
X    FPOINT *f_pt_s2p, double chg_x_s2, double chg_y_s2,
X    int status, int limit);
X
X#endif
X
X/* =========================== end_ref() =================================== */
Xend_ref(C, A, B)
X    POINT   C,
X            A,
X            B;
X{
X    /* endpt of hatch segment on CB, ... etc: coordinates are doubles */
X    FPOINT  f_pt_CB,
X            f_pt_CA,
X            f_pt_AB;
X
X    /* endpt of hatch segment on CB, ... etc: coordinates are integers */
X    POINT   endpt_CB,
X            endpt_CA,
X            endpt_AB;
X    double  xdiff,
X            ydiff;
X    int     limit;
X
X#ifdef TESTVER
X    if (debug4) {
X	fprintf(errfp, "A: ( %d, %d );  ", A.x, A.y);
X	fprintf(errfp, "B: ( %d, %d );  ", B.x, B.y);
X	fprintf(errfp, "C: ( %d, %d )\n", C.x, C.y);
X    }
X#endif
X
X    /* assign 1st set of hatch segment endpoints (along 1st side) */
X    endpt_CB = C;
X    f_pt_CB.xx = (double) endpt_CB.x;
X    f_pt_CB.yy = (double) endpt_CB.y;
X    if (C_A == PARL) {
X	endpt_CA = A;
X	f_pt_CA.xx = (double) endpt_CA.x;
X	f_pt_CA.yy = (double) endpt_CA.y;
X    } else {
X	endpt_CA = C;
X	f_pt_CA.xx = (double) endpt_CA.x;
X	f_pt_CA.yy = (double) endpt_CA.y;
X    }
X
X    /* plot hatch lines up to limiting point along 1st side of triangle */
X    limit = ((C_A == VERT) ? A.y : A.x);
X#ifdef TESTVER
X    if (debug4)
X	fprintf(errfp, "\nlimit: %d\n", limit);
X    if (debug1c) {
X	fprintf(stderr, "To: choose_step() - side 1;\n");
X    }
X    if (debug1f) {
X	fprintf(errfp, "\nTo: choose_step() - side 1;\n");
X    }
X#endif
X    choose_step(&f_pt_CA, chg_x_CA, chg_y_CA,
X	&f_pt_CB, chg_x_CB, chg_y_CB,
X	C_A, limit);
X
X
X    /* do second side ------------------------- */
X    if (A_B == PARL) {
X#ifdef TESTVER
X	if (debug4) {
X	    fprintf(errfp, "\nA_B parallel to hatch lines, side 2 skipped\n");
X	}
X#endif
X    } else {			/* A_B not parallel to hatch lines */
X
X	/* assign next set of hatch segment endpoints (along 2nd side, AB) */
X	/* fprintf( stderr, "\nStart side 2 -- chg_x_CB: %f\n", chg_x_CB ); */
X	if (chg_x_CB == 0.0) {
X	    ydiff = chg_y_AB * ((double) B.y - f_pt_CB.yy) / chg_y_CB;
X	    if (chg_y_AB == 0.0) {
X		xdiff = (f_pt_CB.yy - (double) B.y) / tan(hatch_rads);
X	    } else {
X		xdiff = ydiff * chg_x_AB / chg_y_AB;
X	    }
X	} else {
X	    xdiff = ((double) B.x - f_pt_CB.xx) * chg_x_AB / chg_x_CB;
X	    if (chg_y_CB == 0.0) {
X		if (chg_x_AB == 0.0) {
X		    ydiff = -(B.x - f_pt_CB.xx) * tan(hatch_rads);
X#ifdef TESTVER
X		    if (debug4) {
X			fprintf(errfp, "\nCase A - ydiff: %6.1f\n", ydiff);
X		    }
X#endif
X		} else {
X		    ydiff = xdiff * (B.y - A.y) / (B.x - A.x);
X#ifdef TESTVER
X		    if (debug4) {
X			fprintf(errfp, "\nCase B - ydiff: %6.1f\n", ydiff);
X		    }
X#endif
X		}
X	    } else {
X		ydiff = ((double) B.y - f_pt_CB.yy) * chg_y_AB / chg_y_CB;
X#ifdef TESTVER
X		if (debug4) {
X		    fprintf(errfp, "\nCase C - ydiff: %6.1f\n", ydiff);
X		}
X#endif
X	    }
X	}
X	f_pt_AB.xx = (double) B.x - xdiff;
X	f_pt_AB.yy = (double) B.y - ydiff;
X#ifdef TESTVER
X	if (debug4) {
X	    fprintf(errfp, "xdiff: %6.0f;  ydiff: %6.0f\n", xdiff, ydiff);
X	    fprintf(errfp,
X		"f_pt_CB: ( %6.0f, %6.0f );  f_pt_AB: ( %6.0f, %6.0f )\n",
X		f_pt_CB.xx, f_pt_CB.yy, f_pt_AB.xx, f_pt_AB.yy);
X	}
X#endif
X
X	/* plot hatch lines up to limiting point along 2nd side of triangle */
X	limit = ((C_B == VERT) ? B.y : B.x);
X#ifdef TESTVER
X	if (debug1c) {
X	    fprintf(stderr, "To: choose_step() - side 2;\n");
X	}
X	if (debug1f) {
X	    fprintf(errfp, "\nTo: choose_step() - side 2;\n");
X	}
X#endif
X	choose_step(&f_pt_CB, chg_x_CB, chg_y_CB,
X	    &f_pt_AB, chg_x_AB, chg_y_AB,
X	    C_B, limit);
X    }
X}
END_OF_FILE
if test 3894 -ne `wc -c <'end_ref.c'`; then
    echo shar: \"'end_ref.c'\" unpacked with wrong size!
fi
# end of 'end_ref.c'
fi
if test -f 'ep_map.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ep_map.c'\"
else
echo shar: Extracting \"'ep_map.c'\" \(5595 characters\)
sed "s/^X//" >'ep_map.c' <<'END_OF_FILE'
X/*
X * ep_map.c
X *
X * Copyright (c) 1988 Environmental Defense Fund, Inc.
X */
X
X#include <stdio.h>
X#include "const.h"
X#include "fillcnst.h"
X
X#ifdef TESTVER
X#include <signal.h>
X#include "dbgvars.h"
X#endif
X
X/* Constants */
X/* SCALEX = 10.15 (inches) / 10366 (plotter units) * 180 (dots/inch) */
X#define SCALEX 0.1762492
X/* SCALEY = 7.8 (inches) / 7963 (plotter units) * 180 (dots/inch) */
X#define SCALEY 0.1763154
X
X#define YLIM 1404
X#define XLIM 231
X
X#define ROUNDER 0.0
X
X#ifdef TESTVER
X#define PUT_BIT(x, y) map[(tempindex = (tempy = y) + YLIM * ((tempx = x) >> 3))] |= BITS[x & 7];
X#else
X#define PUT_BIT(x, y) map[y + YLIM * (x >> 3)] |= BITS[x & 7]
X#endif
X
X#define ABS(x) ( (x) > 0.0 ? (x) : -(x) )
X
Xstatic char BITS[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
X
X/* move bit map to maps.c for combined printer version --- */
X/* char   map[XLIM * YLIM]; */
Xextern char map[];
X
X#ifdef TESTVER
Xstatic int tempindex,
X        tempx,
X        tempy;
Xstatic POINT tempp1,
X        tempp2;
X
Xep_catch()
X{
X    fprintf(stderr, "Segmentation violation\n");
X    fprintf(stderr, "tempindex = %d x = %d y = %d p1 = %d,%d p2 = %d,%d\n", tempindex, tempx, tempy, tempp1.x, tempp1.y, tempp2.x, tempp2.y);
X    ep_dump_map(FALSE);
X    exit(1);
X}
X
Xepcatchi()
X{
X    ep_dump_map(FALSE);
X    exit(1);
X}
X
X#endif
X
X
Xep_put_seg(p1, p2)
X    POINT   p1,
X            p2;
X{
X    double  diffx,
X            diffy,
X            change_ratio;
X    register int x,
X            y;
X    register int inc;
X
X#ifdef TESTVER
X    if (debug2 || debug2x) {
X	fprintf(errfp, "p1 ( %d, %d );   p2 ( %d, %d )\n",
X	    p1.x, p1.y, p2.x, p2.y);
X    }
X#if 0
X    signal(SIGSEGV, ep_catch);
X    signal(SIGINT, epcatchi);
X#endif
X    tempp1 = p1;
X    tempp2 = p2;
X#endif
X
X    p1.x = SCALEX * (double) p1.x + ROUNDER;
X    p2.x = SCALEX * (double) p2.x + ROUNDER;
X    p1.y = SCALEY * (double) p1.y + ROUNDER;
X    p2.y = SCALEY * (double) p2.y + ROUNDER;
X
X    diffx = p2.x - p1.x;
X    diffy = p2.y - p1.y;
X
X    if (diffx != 0.0 && diffy != 0.0) {
X	if (ABS(diffx) > ABS(diffy)) {
X	    inc = (diffx < 0) ? -1 : 1;
X	    change_ratio = diffy / diffx;
X	    for (x = p1.x; x != p2.x; x += inc) {
X		y = (x - p1.x) * change_ratio + p1.y + ROUNDER;
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(p2.x, p2.y);
X	} else {
X	    inc = (diffy < 0) ? -1 : 1;
X	    change_ratio = diffx / diffy;
X	    for (y = p1.y; y != p2.y; y += inc) {
X		x = (y - p1.y) * change_ratio + p1.x + ROUNDER;
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(p2.x, p2.y);
X	}
X    } else {
X	if (diffx) {		/* horizontal line */
X	    y = p1.y;
X	    inc = (diffx < 0) ? -1 : 1;
X	    for (x = p1.x; x != p2.x; x += inc) {
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(p2.x, y);
X	} else {
X	    x = p1.x;
X	    inc = (diffy < 0) ? -1 : 1;
X	    for (y = p1.y; y != p2.y; y += inc) {
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(x, p2.y);
X	}
X    }
X}
X
X
X/* LEFT_CUTOFF is the number of dot rows along left edge of page to skip over.
X *    shifts image to the left by that many dot rows on the hardcopy page */
X#define LEFT_CUTOFF  72
X
Xep_dump_map(to_printer)
X    int     to_printer;
X{
X    register int k;
X    int     map_max = XLIM * YLIM;
X    int     i,
X            j;
X    char    hdr[5];
X    register char *pm0,
X           *pm1,
X           *pm2,
X           *pb;
X    char    buf[180];
X    int     non_blank;
X    short int lim;
X
X#ifndef TESTVER
X    to_printer = TRUE;
X#endif
X
X    if (to_printer) {
X	hdr[0] = ESC;
X	hdr[1] = '3';
X	hdr[2] = 24;		/* Spacing at 24/180 inch per line */
X	write(1, hdr, 3);
X	hdr[1] = '*';
X	hdr[2] = 39;		/* Triple density, 24 pins */
X	hdr[3] = (YLIM - LEFT_CUTOFF) & 0x0ff;
X	hdr[4] = ((YLIM - LEFT_CUTOFF) >> 8) & 0x0ff;
X	for (k = 0; k < map_max; k += 3 * YLIM) {
X	    write(1, hdr, 5);
X	    pm0 = &map[k + LEFT_CUTOFF];
X	    pm1 = &map[k + YLIM + LEFT_CUTOFF];
X	    pm2 = &map[k + (2 * YLIM) + LEFT_CUTOFF];
X	    lim = YLIM - LEFT_CUTOFF;
X	    while ((lim -= 60) >= 0) {
X		pb = buf;
X		for (i = 0; i < 60; i++) {
X		    *pb++ = *pm0++;
X		    *pb++ = *pm1++;
X		    *pb++ = *pm2++;
X		}
X		write(1, buf, 180);
X		fflush(stdout);
X	    }
X
X	    if (lim < 0)
X		for (lim += 60; lim > 0; lim--) {
X		    pb = buf;
X		    *pb++ = *pm0++;
X		    *pb++ = *pm1++;
X		    *pb++ = *pm2++;
X		    write(1, buf, 3);
X		    fflush(stdout);
X		}
X	    write(1, "\n\r", 2);/* LF and CR to end line */
X	}
X	hdr[0] = '\f';		/* Initialize the printer */
X	write(1, hdr, 1);
X	fflush(stdout);
X	hdr[0] = ESC;		/* Initialize the printer */
X	hdr[1] = '@';
X	write(1, hdr, 2);
X	fflush(stdout);
X#ifdef TESTVER
X	fclose(errfp);
X#endif
X
X    }
X#ifdef TESTVER
X    else {
X	FILE   *tty,
X	       *ttyout;
X	int     dump_start,
X	        dump_stop;
X
X	if ((tty = fopen(TTY, "r")) == NULL) {
X	    perror(TTY);
X	    exit(10);
X	}
X	if ((ttyout = fopen(TTY, "w")) == NULL) {
X	    perror(TTY);
X	    exit(10);
X	}
X	fprintf(ttyout, "Enter start bit:");
X	fflush(ttyout);
X	fscanf(tty, "%d", &dump_start);
X	dump_stop = dump_start + 79;
X	non_blank = 0;
X	pb = buf;
X	for (k = 0; k < XLIM * YLIM; k += YLIM) {
X	    for (i = 0; i < 8; i++) {
X		for (j = k + dump_start; j < k + dump_stop; j++) {
X		    if (map[j] & BITS[i]) {
X			sprintf(pb, ".");
X			non_blank = 1;
X		    } else {
X			sprintf(pb, " ");
X		    }
X		    pb++;
X		}
X		if (non_blank) {
X		    sprintf(pb, "\n\000");
X		    printf("%s", buf);
X		}
X		non_blank = 0;
X		pb = buf;
X	    }
X	}
X    }
X#endif
X
X}
X
X
Xep_init_map()
X{
X    register int k;
X    int     map_max = XLIM * YLIM;
X    register char *mp;
X
X#ifdef TRUESOLID
X    extern double PUs_per_dot;	/* declared in file filltype.c */
X
X    PUs_per_dot = 1.0 / SCALEX;	/* used by fix_fill() in file filltype.c */
X#endif
X
X    mp = map;
X    for (k = 0; k < map_max; k++) {
X	*mp++ = 0;
X    }
X}
END_OF_FILE
if test 5595 -ne `wc -c <'ep_map.c'`; then
    echo shar: \"'ep_map.c'\" unpacked with wrong size!
fi
# end of 'ep_map.c'
fi
if test -f 'hpglfix.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hpglfix.c'\"
else
echo shar: Extracting \"'hpglfix.c'\" \(7097 characters\)
sed "s/^X//" >'hpglfix.c' <<'END_OF_FILE'
X/*
X * hpglfix
X *
X * Copyright (c) 1988 Environmental Defense Fund, Inc.
X *
X * For use with HPGL files generated by the 20/20 spreadsheet.
X * Takes HPGL input file from stdin and writes fixed HPGL file to stdout.
X *
X * Currently fixes two problems: piecharts and multi-line line charts.
X *
X * A 20/20 rounding error bug generates HPGL pie charts whose sector angles
X * may add up to less than 360 degrees.  The current solution is to use the
X * starting angles for the sectors, and re-compute the sweep angles based on 
X * the values of the adjacent start angles.  This does NOT necessarily correct
X * the rounding errors, which are present in both the starting angles and the
X * sweep angles, but it produces a good looking graph, with angles off by no
X * more than 1 degree.  This process is duplicated for both the EW and WG 
X * commands.  EW = 'edge wedge' -- outline a pie sector.  WG = 'wedge' -- fill 
X * a pie sector.
X *
X * A 20/20 bug generates HPGL multi-line graphs with the last point on one line
X * connected to the 1st point of the next line.  The current solution is to 
X * insert a PU (pen up) command after each occurrence of an LT (line type) 
X * command.  This may need to be revised.
X *
X * Usage:  hpglfix < hpglfile | hpglplot
X */
X
X#include <stdio.h>
X
X#define FILEMAX     20000	/* max hpgl filesize that can be processed */
X#define SECTORMAX   200		/* max # of pie sectors that can be processed */
X#define EW_MARKER   23
X#define WG_MARKER   24
X#define INFILE      0
X#define ANGLES      1
X
Xchar    nextchar();
Xchar    c;
Xchar    hpgl[FILEMAX];		/* ram storage for hpgl file */
Xint     offset;			/* offset from start of hpgl[] */
Xint     is_piechart = 0;
Xint     EW_start[SECTORMAX],
X        EW_sweep[SECTORMAX];	/* start and sweep angles */
Xint     WG_start[SECTORMAX],
X        WG_sweep[SECTORMAX];	/* start and sweep angles */
Xint     EW_cnt;			/* count of number of pie sectors processed */
Xint     WG_cnt;			/* count of number of pie sectors processed */
Xint     EW_sweep_sum = 0;	/* sum of sweep angles processed */
Xint     WG_sweep_sum = 0;	/* sum of sweep angles processed */
X
X
X/* ============================ main() ============================ */
Xmain()
X{
X    input();
X    if (is_piechart) {
X	piefix(EW_start, EW_sweep, EW_cnt, EW_sweep_sum);
X	piefix(WG_start, WG_sweep, WG_cnt, WG_sweep_sum);
X    }
X    output();
X}
X
X
X/* ============================ input() ============================ */
Xinput()
X{
X    char    label_terminator = 3;
X
X    EW_cnt = 0;
X    WG_cnt = 0;
X    offset = 0;
X
X    while ((c = nextchar()) != EOF) {	/* Read from stdin until EOF */
X	switch (c) {
X	case 'D':
X	    if ((c = nextchar()) == 'T') {
X		label_terminator = nextchar();
X	    }
X	    break;
X	case 'L':
X	    c = nextchar();
X	    if (c == 'B') {	/* skip over chars in labels */
X		while (nextchar() != label_terminator);
X	    } else {
X		if (c == 'T') {
X		    linefix();
X		}
X	    }
X	    break;
X	case 'E':
X	    if ((c = nextchar()) == 'W') {
X		prep_pie(EW_start, EW_sweep, &EW_cnt,
X		    EW_MARKER, &EW_sweep_sum);
X	    }
X	    break;
X	case 'W':
X	    if ((c = nextchar()) == 'G') {
X		prep_pie(WG_start, WG_sweep, &WG_cnt,
X		    WG_MARKER, &WG_sweep_sum);
X	    }
X	    break;
X	}
X    }
X    check(INFILE, offset);
X    *(hpgl + offset) = NULL;
X}
X
X
X/* ============================ nextchar() ============================ */
X/*
X * read next char from stdin, check to see that there is room for it in 
X * array hpgl[], and if so store it in hpgl[]
X */
X
Xchar 
Xnextchar()
X{
X    char    ch;
X
X    ch = getchar();
X    check(INFILE, offset);
X    *(hpgl + offset++) = ch;	/* put ch in hpgl[] */
X    return ch;
X}
X
X
X/* ============================ prep_pie() ========================= */
Xprep_pie(start, sweep, cntp, marker, sum_p)
X    int     start[],
X            sweep[],
X           *sum_p;
X    int    *cntp;
X    char    marker;
X{
X    int     cnt;
X
X    cnt = *cntp;
X    is_piechart = 1;
X    while ((c = nextchar()) != ',');	/* put radius & ',' in hpgl[] */
X
X    /*
X     * on output, marker will be replaced by corrected start_angle, the
X     * intervening ',', and the corrected sweep_angle 
X     */
X    check(INFILE, offset);
X    *(hpgl + offset++) = marker;
X
X    check(ANGLES, cnt);
X    scanf("%d,%d", &start[cnt], &sweep[cnt]);
X    *sum_p += sweep[cnt];
X    (*cntp)++;
X}
X
X
X/* ============================ linefix() ============================ */
Xlinefix()
X{
X    while ((c = nextchar()) != ';');	/* put LT params & ';' in hpgl[] */
X    check(INFILE, offset + 3);
X    *(hpgl + offset++) = 'P';	/* insert the PU command */
X    *(hpgl + offset++) = 'U';
X    *(hpgl + offset++) = ';';
X}
X
X
X/* ============================ check() ============================ */
X/*
X * exit with error msg if array for storage of input file or angle arrays
X * are about to overflow.
X */
X
Xcheck(type, size)
X    int     type,
X            size;
X{
X    if (type == INFILE) {
X	if (size >= FILEMAX) {
X	    fprintf(stderr,
X		"Hpglfix fatal error.  Input file exceeds %d bytes.\n", FILEMAX);
X	    exit(1);
X	}
X    } else {
X	if (size >= SECTORMAX) {
X	    fprintf(stderr,
X		"Hpglfix fatal error.  Number of pie sectors exceeds %d.\n",
X		SECTORMAX);
X	    exit(1);
X	}
X    }
X}
X
X
X/* ============================ piefix() ============================ */
Xpiefix(start, sweep, cnt, sweep_sum)
X    int     start[],
X            sweep[],
X            cnt,
X            sweep_sum;
X{
X    int     i;
X    int     max_chg = 0;
X
X    if (sweep_sum > 380) {
X	fprintf(stderr, "Hpglfix warning: ");
X	fprintf(stderr,
X	    "More than one pie, or input file error.  No fix was made.\n");
X    } else {
X	if (start[cnt - 1] == 89) {
X	    start[cnt - 1] = 90;
X	    max_chg = 1;
X	}
X	sweep[0] = new_sweep(cnt - 1, 0, &max_chg, start, sweep);
X	for (i = 1; i < cnt; i++) {
X	    sweep[i] = new_sweep(i - 1, i, &max_chg, start, sweep);
X	}
X
X	if (max_chg > 1) {
X	    fprintf(stderr, "Hpglfix warning: ");
X	    fprintf(stderr,
X		"At least one angle of pie was changed by %d degrees.\n",
X		max_chg);
X	}
X    }
X}
X
X
X/* ======================== new_sweep() ===================== */
X/*
X * return new value for current sweep angle, based on prev start angle and 
X * current start angle.  Reset max_chg if it increases.  max_chg is the 
X * largest change made to any sweep angle
X */
X
Xint 
Xnew_sweep(prev, curr, maxchg_p, start, sweep)
X    int     prev,
X            curr,
X           *maxchg_p;
X    int     start[],
X            sweep[];
X{
X    int     sw_angle,
X            change;
X
X    if (start[prev] >= start[curr]) {
X	sw_angle = start[prev] - start[curr];
X    } else {
X	sw_angle = (start[prev] + 360) - start[curr];
X    }
X    change = abs(sw_angle - sweep[curr]);
X    if (change > *maxchg_p)
X	*maxchg_p = change;
X    return sw_angle;
X}
X
X
X/* ============================ output() ============================ */
Xoutput()
X{
X    char    c;
X    char   *hp;
X
X    hp = hpgl;
X    EW_cnt = 0;
X    WG_cnt = 0;
X
X    while ((c = *hp++) != NULL) {
X	if (c == EW_MARKER) {
X	    printf("%d,%d", EW_start[EW_cnt], EW_sweep[EW_cnt]);
X	    EW_cnt++;
X	} else if (c == WG_MARKER) {
X	    printf("%d,%d", WG_start[WG_cnt], WG_sweep[WG_cnt]);
X	    WG_cnt++;
X	} else {
X	    putchar(c);
X	}
X    }
X    putchar(NULL);
X}
END_OF_FILE
if test 7097 -ne `wc -c <'hpglfix.c'`; then
    echo shar: \"'hpglfix.c'\" unpacked with wrong size!
fi
# end of 'hpglfix.c'
fi
if test -f 'hpglplot.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hpglplot.doc'\"
else
echo shar: Extracting \"'hpglplot.doc'\" \(9035 characters\)
sed "s/^X//" >'hpglplot.doc' <<'END_OF_FILE'
XHPGLPLOT
X
XAl Chase
X
XCopyright (c) 1988 Environmental Defense Fund, Inc.
X
X
XHpglplot is a filter to read HPGL commands (Hewlett-Packard Graphics
XLanguage, used by HP7475A 6-pen plotter, among others) and produce bit
Xmap graphics commands for various printers.
X
XAuthors:
X Mel Brooks
X  (415) 530-0300
X Al Chase
X  (916) 273-7047
X David MacKenzie
X  (202) 387-3500
X
XCOMMAND LINE OPTIONS
X
X-e	produce output for Epson LQ-1500
X-i	produce output for IBM Proprinter
X-l	produce output for HP LaserJet+
X-n	disable area fill routines (bug-prone)
X
X           *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
X
XThe following information is intended to ease the task of modifying the
Xcode of the hpglplot program.
X
X
XPREPROCESSOR CONSTANTS
X
XTESTVER enables lines of code used for debugging.  The test version
Xmakes a wealth of debugging output available, and does some range
Xchecking to prevent setting bits which are outside the bounds of the
Xbit map.
X
XTRUESOLID enables true solid fill versus a triple cross- hatch
Xsubstitute for solid fill.  See more below.
X
XIn ep_map.c, LEFT_CUTOFF controls the displacement of the graphics
Ximage to the left on the Epson hardcopy.  There are 180 dots/in, so a
Xvalue of 180 for LEFT_CUTOFF will displace the image 1 inch to the left
Xon the paper.  Adjust the value of LEFT_CUTOFF to suit.
X
X
XPRINTERS
X
XHpglplot can produce output for the HP LaserJet+, the Epson LQ-1500,
Xand the IBM Proprinter.  In the production version, use a command line
Xflag -l for the LaserJet, -e for the Epson, or -i for the IBM
XProprinter.  In the test version (#define TESTVER), use flag -e for
Xoutput to the Epson, -i for output to an IBM Proprinter, and no flag
Xfor output to the screen.  Screen output was created by Mel Brooks, the
Xinitial programmer of hpglplot.  I haven't succeeded in getting useful
Xinformation from it.  The test version will not output to the LaserJet.
X
X
XINTERNAL CONTROL OF MULTIPLE PRINTERS
X
XThe original function map_bits() is replaced with maps(), ep_map(),
Xlj_map(), and ib_map().  maps() dispatches map-related function calls
Xto either ep_map(), ib_map(), or lj_map(), depending on how the
Xvariable 'printer' was set by the command line flag.  maps.c also
Xdeclares a single bit map array which is accessed by whichever set of
Xmap-related functions is active.  The bit maps which had been declared
Xin ep_map(), ib_map(), and lj_map() have been commented out in those
Xfiles.  Each function in the respective version of map_bits() was given
Xa prefix of ep_, ib_, or lj_.  Otherwise, the three files are quite
Xindependent of each other, so that they could easily be pulled apart
Xinto single-printer versions; and a new working single-printer version
Xcould be added very quickly.
X
X
XDOS ENVIRONMENT
X
XAs it stands, the bit map array, map(), is too large for C
Ximplementations (Turbo C, anyhow) in the DOS environment.  A quick fix
Xis to reduce each dimension of the Proprinter output to one half of
Xnormal (see XLIM and YLIM at the top of file ib_map.c), and declare
Xarray map() in file map.c to be of size 25000.  The quarter page images
Xare cute, anyhow.  A longer fix would be to convert from array to
Xpointer.
X
X
XNON-STANDARD EXTENSIONS
X
XInstructions PG, polygon area fill, and EP, edge a polygon, are
Xdocumented in their respective files, do_pg.c and do_ep.c.
X
XComments in an HPGL file may be placed in curly braces, {}.  Comments
Xmay be nested, and are guarded against the occurence of a closing brace
Xin a label instruction.  Useful for writing or elucidating HPGL files.
XIndispensable for isolating problem instructions in a larger file, when
Xdebugging the hpglplot program.  A DT instruction, define label
Xterminator, should not be commented out.
X
XSpaces may be embedded between instructions, and between instructions
Xand comments.
X
XTwo other instructions which serve as debugging aids: ESC.! will
Xterminate the program without dumping the bit map (see main.c); and an
Xexclamation point  !  can be used to call any user defined test routine
Xnamed in that case of the switch statement.  Depending on the test
Xroutine, the ! may be followed by parameters.
X
X
XSOLID FILL
X
XThere are two solid fill routines; one gives a true solid fill, the
Xother is a triple cross hatch with angles of 30, 90, and 150.  Since
Xthe algorithm used to plot a line segment (the edge of a figure) is
Xdifferent from the one used to locate the limits of the true solid
Xfilling, a figure which is true solid- filled and edged shows a few
Xopen dots just inside the edging.  This effect is extremely noticeable
Xat the lowest resolutions that I use, and very slightly noticeable at
Xthe finest resolution that I can get (120 dots per inch by 72).  It
Xshould be scarcely noticeable at all with the Epson and LaserJet
Xresolutions.  I've left both solid fills in place, under the control of
Xthe preprocessor constant TRUESOLID.  If the hardcopy output of the
Xtrue solid fill doesn't look ok, don't define TRUESOLID.  Try it both
Xways.  The true solid fill is a matter of plotting vertical hatch lines
Xat a spacing equal to the spacing of the dots.
X
X#ifdef TRUESOLID structures are found in fix_fill() in file fill.c, and
Xat the top of file fill.c;  in hatch() in file hatch.c;  and in
Xep/lj_init_map(), towards the bottom of file ep/lj_map.c.
X
X
XOVERVIEW OF AREA-FILL ROUTINES
X
XThe approach taken to the area fill is to divide each area into a set
Xof triangles, all of which share a common vertex (the center of the
Xcircle, in the case of a pie sector).  In each triangle, the first
Xhatch segment is drawn through the common vertex, so that the hatch
Xsegments of the adjoining triangles that make up the figure are all in
Xalignment with each other.  (The common vertex serves as a reference
Xpoint for the alignment.)  The common vertex is referred to as:
X   points[0] in do_Rx(), do_WG(), and do_PG()
X   pts[0] in hatch(), and fill_figure()
X   P[0] in fill_figure(), and fill_triangle()
X   (vertex) C in fill_triangle(), get_3_chgs(), end_ref(), and mid_ref()
X
XHorizontal hatch lines have not been implemented.  See (*) below.
X
XIn any of the component triangles, call the x-intercept of the hatch
Xline containing vertex C x_int_C, and likewise for x_int_A and x_int_B.
XIf  x_int_C <= x_int_A  and  x_int_C <= x_int_B, the reference point C
Xis considered to be at the 'left' end of the triangle.  Note that
Xdepending on the hatch line angle, C may not actually be the leftmost
Xvertex, but it is the first (or ties for first with A or B) vertex that
Xwould be intersected by a succession of hatch lines moving from left to
Xright.
X
XIn this case, where C is at the 'left', the next vertex intersected by
Xthe succession of hatch lines is named A and the last vertex is named
XB.  Starting with the hatch line through C, successive hatch segments
Xare plotted from left to right, with one endpoint on side CA and one
Xendpoint on side CB, until the next hatch line would no longer
Xintersect CA.  From there, the hatch lines are plotted with one
Xendpoint on AB and one on CB until the next hatch line would no longer
Xintersect CB.
X
XIf C is at the 'right' of the triangle, the succession of hatch lines
Xstarts at C and moves from right to left, encountering A before (or at
Xthe same time as) B.
X
XThe above scenarios are handled by function end_ref() -- the reference
Xpoint is at one 'end' of the triangle or the other.
X
XIf x_int_C is between x_int_A and x_int_B, the vertex to the 'left' of
XC is named A, and that to the 'right' of C is named B.  The first hatch
Xsegment is plotted with one endpoint at C and the other on side AB.
XThen hatch segments proceed to the right with endpoints on AB and CB,
Xand finally hatch segments are plotted to the left, starting with the
Xfirst one to the left of the segment containing C.  This scenario is
Xhandled by function mid_ref() -- the reference point is in the 'middle'
Xof the triangle.
X
Xfix_fill() is used to compensate for the lack of distinct pens.  A
Xformula is used to change the appearance of the fill when only the pen
Xnumber is changed in the HPGL file.  If pen 1 is selected, the fill
Xtype and fill angle(*) set by the last FT instruction are used.  If a
Xdifferent pen is selected, pen number, fill type, fill angle, and fill
Xspacing are combined in the fix_fill() formula to give a different
Xfill.
X
X(*) Horizontal lines have not been implemented because the x-intercept
Xof the hatch lines is the basis for the approach taken, and horizontal
Xlines don't have x-intercepts.  A second set of routines, based on the
Xy-intercepts of the hatch lines, could be written for horizontal hatch
Xlines, (and in that case, for all hatch lines inclined closer to
Xhorizontal than vertical).
X
XBecause horizontal lines have not been implemented, actual fill angles
Xnamed by the FT instruction have been altered as follows:
Xfor parallel hatching:
X0 degrees -> 25 degrees
X45        -> 65
X90        -> 90
X135       -> 115
Xand for cross-hatching:
X0/90      -> 20/160
X45/135    -> 70/110
XHowever, any hatch angle other than 0, 45, or 135 will plot exactly.
XIt's not advisable to name hatch angles very close to 0 degrees.
END_OF_FILE
if test 9035 -ne `wc -c <'hpglplot.doc'`; then
    echo shar: \"'hpglplot.doc'\" unpacked with wrong size!
fi
# end of 'hpglplot.doc'
fi
if test -f 'ib_map.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ib_map.c'\"
else
echo shar: Extracting \"'ib_map.c'\" \(4583 characters\)
sed "s/^X//" >'ib_map.c' <<'END_OF_FILE'
X/*
X * ib_map.c
X *
X * Copyright (c) 1988 Environmental Defense Fund, Inc.
X */
X
X#include <stdio.h>
X#include "const.h"
X#include "fillcnst.h"
X
X#ifdef TESTVER
X#include <signal.h>
X#include "dbgvars.h"
X#endif
X
X#define XLIM 32			/* 47 for 1/2 pg output, 94 for full page
X				 * output */
X#define YLIM 320		/* 240/480 for half/full pg output, mode K... */
X /* ...480/960 for half/full pg output, mode L */
X#define MODE 'L'		/* 'K' / 'L': 60 dots per in / 120 dots per
X				 * in */
X
X#define LEFT_CUTOFF  0
X
X/*
X * Constants
X * SCALEX and SCALEY have been changed to vars, set in init_map,
X * to simplify quick changes of scale, depending on XLIM, YLIM
X */
X
X#define ROUNDER 0.0
X
X#ifndef TESTVER
X#define PUT_BIT(x,y)    map[(x >> 3) + (XLIM * y)] |= BITS[x & 7]
X#endif
X
X#define ABS(x) ((x) > 0.0 ? (x) : -(x))
X
Xlong    MAP_MAX;
Xdouble  SCALEX,
X        SCALEY;			/* <<<<<<<<<<<< */
Xchar    BITS[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
Xextern char map[];		/* in maps.c */
X
X
X/*******************************
X * catch(), catchi() were here *
X *******************************/
X
X#ifdef TESTVER
XPUT_BIT(x, y)
X    int     x,
X            y;
X{
X    int     offset;
X
X    offset = ((x >> 3) + (XLIM * y));
X    if ((offset >= (MAP_MAX)) || (offset < 0)) {
X	fprintf(stderr,
X	    "PUTBIT offset overflow: %d;  x: %d;  y: %d\n", offset, x, y);
X	fprintf(errfp,
X	    "PUTBIT offset overflow: %d;  x: %d;  y: %d\n", offset, x, y);
X	fclose(errfp);
X	dump_map(TRUE);
X	exit(1);
X    }
X    map[offset] |= BITS[x & 7];
X}
X
X#endif
X
X
Xib_put_seg(p1, p2)
X    POINT   p1,
X            p2;
X{
X    double  diffx,
X            diffy,
X            change_ratio;
X    register int x,
X            y;
X    register int inc;
X
X#if 0
X    signal(SIGSEGV, catch);
X    signal(SIGINT, catchi);
X#endif
X
X#ifdef TESTVER
X    if (debug2 || debug2x) {
X	fprintf(errfp, "p1 ( %d, %d );   p2 ( %d, %d )\n",
X	    p1.x, p1.y, p2.x, p2.y);
X    }
X#endif
X
X    p1.x = SCALEX * (double) p1.x + ROUNDER;
X    p2.x = SCALEX * (double) p2.x + ROUNDER;
X    p1.y = SCALEY * (double) p1.y + ROUNDER;
X    p2.y = SCALEY * (double) p2.y + ROUNDER;
X
X    diffx = p2.x - p1.x;
X    diffy = p2.y - p1.y;
X
X    if (diffx != 0.0 && diffy != 0.0) {	/* neither horiz nor vert */
X	if (ABS(diffx) > ABS(diffy)) {	/* closer to horizontal */
X	    inc = (diffx < 0) ? -1 : 1;
X	    change_ratio = diffy / diffx;
X	    for (x = p1.x; x != p2.x; x += inc) {
X		y = (x - p1.x) * change_ratio + p1.y + ROUNDER;
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(p2.x, p2.y);
X	} else {		/* closer to vertical */
X	    inc = (diffy < 0) ? -1 : 1;
X	    change_ratio = diffx / diffy;
X	    for (y = p1.y; y != p2.y; y += inc) {
X		x = (y - p1.y) * change_ratio + p1.x + ROUNDER;
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(p2.x, p2.y);
X	}
X    } else {
X	if (diffx) {		/* horizontal line */
X	    y = p1.y;
X	    inc = (diffx < 0) ? -1 : 1;
X	    for (x = p1.x; x != p2.x; x += inc) {
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(p2.x, y);
X	} else {		/* vert. line */
X	    x = p1.x;
X	    inc = (diffy < 0) ? -1 : 1;
X	    for (y = p1.y; y != p2.y; y += inc) {
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(x, p2.y);
X	}
X    }
X}
X
X
Xib_dump_map(to_printer)
X    int     to_printer;
X{
X    int     i;
X    register int j;
X    char    ch;
X    char    hdr[5];
X
X    if (to_printer) {
X	hdr[0] = ESC;
X	hdr[1] = '3';
X	hdr[2] = 24;		/* Line spacing for graphics: 24/216 inch */
X	write(1, hdr, 3);
X	hdr[1] = MODE;		/* 'K'/'L': 480/960 bit image graphics */
X	hdr[2] = (YLIM - LEFT_CUTOFF) & 0xff;	/* n1 = YLIM mod 256 */
X	hdr[3] = ((YLIM - LEFT_CUTOFF) >> 8) & 0xff;	/* n2 = YLIM / 256 */
X
X	for (i = 0; i < XLIM; i++) {
X	    write(1, hdr, 4);
X	    for (j = LEFT_CUTOFF * XLIM; j < MAP_MAX; j += XLIM) {
X		ch = map[i + j];
X		if (ch == 26)
X		    ch = 18;	/* bug in proprinter graphics */
X		if (ch == '\n')
X		    ch = 8;	/* prevent add'n of \r to \n */
X		write(1, &ch, 1);
X#ifdef TESTVER
X		if (debug5)
X		    fprintf(errfp, "%4d", ch);
X#endif
X	    }
X#ifdef TESTVER
X	    if (debug5)
X		fprintf(errfp, "%3d*\n", i);
X#endif
X	    putchar('\n');	/* LF and CR to end line */
X	    putchar('\r');
X	    fflush(stdout);
X	}
X
X	/* putchar( '\f' ); *//* form feed */
X#ifdef TESTVER
X	fclose(errfp);
X#endif
X
X    }				/* end if ( to_printer )... */
X}
X
X
Xib_init_map()
X{
X#ifdef TRUESOLID
X    extern double PUs_per_dot;	/* declared in file filltype.c */
X
X#endif
X    register int k;
X    register char *mp;
X
X    MAP_MAX = XLIM * YLIM;
X    SCALEX = (double) (XLIM * 8) / 10366;
X    SCALEY = (double) (YLIM) / 7963;
X
X#ifdef TRUESOLID
X    PUs_per_dot = 1.0 / SCALEX;	/* used by fix_fill() in file filltype.c */
X#endif
X
X    mp = map;
X    for (k = 0; k < MAP_MAX; k++)
X	*mp++ = 0;
X}
END_OF_FILE
if test 4583 -ne `wc -c <'ib_map.c'`; then
    echo shar: \"'ib_map.c'\" unpacked with wrong size!
fi
# end of 'ib_map.c'
fi
if test -f 'lj_map.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lj_map.c'\"
else
echo shar: Extracting \"'lj_map.c'\" \(5523 characters\)
sed "s/^X//" >'lj_map.c' <<'END_OF_FILE'
X/*
X * lj_map.c
X *
X * Copyright (c) 1988 Environmental Defense Fund, Inc.
X */
X
X#include <stdio.h>
X#include "const.h"
X#include "fillcnst.h"
X
X#ifdef TESTVER
X#include <signal.h>
X#endif
X
X/*
X * Origin is at lower left corner.
X * Bytes of raster data are oriented along the x-axis, hi bit at left:
X *       (0,0) is bit 7 of byte 0;
X *       (7,0) is bit 0 of byte 0;
X *       (16,0) is bit 7 of byte 2;
X *       (16,3) is bit 7 of byte (2 + XLIM*3)
X */
X
X/*
X * Constants
X * YLIM = 1440 dot rows, plus a couple extra for rounding error
X */
X#define YLIM 1442
X#define XLIM  235
X
X/* SCALEX = SCALEY = number of dots per plotter unit
X                   = 1440 dot rows in y-direction / 7962 PU's in y-dir */
X#define SCALEX  0.180859
X#define SCALEY  0.180859
X#define ROUNDER 0.0
X
X#ifdef TESTVER
X#define PUT_BIT(x, y)  map[(tempindex = (tempx = (x >> 3)) + ((tempy = y) * XLIM))] |= BITS[x & 7];
X#else
X#define PUT_BIT(x, y)  map[(x >> 3) + (y * XLIM)] |= BITS[x & 7];
X#endif
X
X#define ABS(x) ((x) > 0.0 ? (x) : -(x))
X
X/* move bit map to maps.c for combined printer version --- */
X#if 0
Xchar    map[XLIM * YLIM];
X
X#endif
Xextern char map[];
X
Xstatic char BITS[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
X
X#ifdef TESTVER
Xstatic int tempindex,
X        tempx,
X        tempy;
Xstatic POINT tempp1,
X        tempp2;
X
Xlj_catch()
X{
X    fprintf(stderr, "Segmentation violation\n");
X    fprintf(stderr, "tempindex = %d x = %d y = %d p1 = %d,%d p2 = %d,%d\n",
X	tempindex, tempx, tempy, tempp1.x, tempp1.y, tempp2.x, tempp2.y);
X    lj_dump_map(FALSE);
X    exit(1);
X}
X
Xljcatchi()
X{
X    lj_dump_map(FALSE);
X    exit(1);
X}
X
X#endif
X
Xlj_put_seg(p1, p2)
X    POINT   p1,
X            p2;
X{
X    double  diffx,
X            diffy,
X            change_ratio;
X    register int x,
X            y;
X    register int inc;
X
X#ifdef TESTVER
X#if 0
X    signal(SIGSEGV, lj_catch);
X    signal(SIGINT, ljcatchi);
X#endif
X    tempp1 = p1;
X    tempp2 = p2;
X#endif
X
X    p1.x = SCALEX * (double) p1.x + ROUNDER;
X    p2.x = SCALEX * (double) p2.x + ROUNDER;
X    p1.y = SCALEY * (double) p1.y + ROUNDER;
X    p2.y = SCALEY * (double) p2.y + ROUNDER;
X
X    diffx = p2.x - p1.x;
X    diffy = p2.y - p1.y;
X
X    if (diffx != 0.0 && diffy != 0.0) {
X	if (ABS(diffx) > ABS(diffy)) {
X	    inc = (diffx < 0) ? -1 : 1;
X	    change_ratio = diffy / diffx;
X	    for (x = p1.x; x != p2.x; x += inc) {
X		y = (x - p1.x) * change_ratio + p1.y + ROUNDER;
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(p2.x, p2.y);
X	} else {
X	    inc = (diffy < 0) ? -1 : 1;
X	    change_ratio = diffx / diffy;
X	    for (y = p1.y; y != p2.y; y += inc) {
X		x = (y - p1.y) * change_ratio + p1.x + ROUNDER;
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(p2.x, p2.y);
X	}
X    } else {
X	if (diffx) {		/* horizontal line */
X	    y = p1.y;
X	    inc = (diffx < 0) ? -1 : 1;
X	    for (x = p1.x; x != p2.x; x += inc) {
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(p2.x, y);
X	} else {
X	    x = p1.x;
X	    inc = (diffy < 0) ? -1 : 1;
X	    for (y = p1.y; y != p2.y; y += inc) {
X		PUT_BIT(x, y);
X	    }
X	    PUT_BIT(x, p2.y);
X	}
X    }
X}
X
X
Xlj_dump_map(to_printer)
X    int     to_printer;
X{
X    register int r;
X    char    hdr[7];
X    char   *mp = map;
X    char   *p,
X           *maxp;		/* for LF-char test */
X    short int hdr_length;
X
X    if (to_printer) {
X	hdr[0] = ESC;
X
X	/* reset printer */
X	hdr_length = 1 + n_strcpy(&hdr[1], "E");
X	write(1, hdr, hdr_length);
X
X	/* set printer to interpret a '\n' char to a '\r\n' pair */
X	hdr_length = 1 + n_strcpy(&hdr[1], "&k2G");
X	write(1, hdr, hdr_length);
X
X	/* raster graphics resolution: 300 dots/in */
X	hdr_length = 1 + n_strcpy(&hdr[1], "*t300R");
X	write(1, hdr, hdr_length);
X
X	/* set cursor to col 11 */
X	hdr_length = 1 + n_strcpy(&hdr[1], "&a11C");
X	write(1, hdr, hdr_length);
X
X	/* set cursor to row 10 */
X	hdr_length = 1 + n_strcpy(&hdr[1], "&a10R");
X	write(1, hdr, hdr_length);
X
X	/* start graphics at current cursor posn */
X	hdr_length = 1 + n_strcpy(&hdr[1], "*r1A");
X	write(1, hdr, hdr_length);
X
X	/* transfer-line-of-graphics escape sequence -- 235 is XLIM */
X	hdr_length = 1 + n_strcpy(&hdr[1], "*b235W");
X
X	/*
X	 * write YLIM rows, each row is XLIM bytes starting at offset r from
X	 * map[0] 
X	 */
X	for (r = (YLIM - 1) * XLIM; r >= 0; r -= XLIM) {
X	    /* check this row for LF-chars; replace with byte value of 8 */
X	    p = mp + r;
X	    maxp = p + XLIM;
X	    while (p < maxp) {
X		if (*p == '\n') {
X		    *p = 8;
X		}
X		p++;
X	    }
X	    write(1, hdr, hdr_length);
X	    write(1, mp + r, XLIM);
X	    fflush(stdout);
X	}
X
X	/* end raster graphics */
X	hdr_length = 1 + n_strcpy(&hdr[1], "*rB");
X	write(1, hdr, hdr_length);
X
X	/* reset printer and eject the page */
X	hdr_length = 1 + n_strcpy(&hdr[1], "E");
X	write(1, hdr, hdr_length);
X
X	/*
X	 * set printer to interpret a '\n' char to a '\r\n' pair. this works
X	 * in combo with the plot script, which also controls interpretation
X	 * of \n's at the port 
X	 */
X	hdr_length = 1 + n_strcpy(&hdr[1], "&k2G");
X	write(1, hdr, hdr_length);
X
X	fflush(stdout);
X    }
X}
X
X
X/*
X * copy string from src to dst, including terminating \0.
X * return number of chars copied, excluding terminating \0
X */
Xint
Xn_strcpy(dst, src)
X    char   *dst,
X           *src;
X{
X    char   *p;
X
X    p = src;
X    while (*dst++ = *src++);
X    return ((--src) - p);
X}
X
X
Xlj_init_map()
X{
X    register int k;
X    register char *mp;
X    int     map_max = YLIM * XLIM;
X
X#ifdef TRUESOLID
X    extern double PUs_per_dot;	/* declared in file filltype.c */
X
X    PUs_per_dot = 1.0 / SCALEX;	/* used by fix_fill() in file filltype.c */
X#endif
X
X    mp = map;
X    for (k = 0; k < map_max; k++) {
X	*mp++ = 0;
X    }
X}
END_OF_FILE
if test 5523 -ne `wc -c <'lj_map.c'`; then
    echo shar: \"'lj_map.c'\" unpacked with wrong size!
fi
# end of 'lj_map.c'
fi
if test -f 'step.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'step.c'\"
else
echo shar: Extracting \"'step.c'\" \(6760 characters\)
sed "s/^X//" >'step.c' <<'END_OF_FILE'
X/*
X * step.c
X *
X * Copyright (c) 1988 Environmental Defense Fund, Inc.
X */
X
X#include <stdio.h>
X#include <math.h>
X#include <string.h>		/* for debug4 in get_chgs() */
X#include "const.h"
X#include "vars.h"
X#include "fillcnst.h"
X#include "fillvars.h"
X#ifdef TESTVER
X#include "dbgvars.h"
X#endif
X
X#ifdef __STDC__
X/* function prototypes */
Xint
Xchoose_step(FPOINT *f_pt_s1p, double chg_x_s1, double chg_y_s1,
X    FPOINT *f_pt_s2p, double chg_x_s2, double chg_y_s2,
X    int status, int limit);
Xint
Xstep(FPOINT *f_pt_s1p, double chg_x_s1, double chg_y_s1,
X    FPOINT *f_pt_s2p, double chg_x_s2, double chg_y_s2,
X    POINT *endpt_s1p, POINT *endpt_s2p);
Xint
Xcvt_pt(POINT *pt, FPOINT *f_pt);
Xint
Xget_chgs(double *chg_xp, double *chg_yp, POINT p1, POINT p2);
Xdouble
Xreduce_rads(double angle);
X
X#else
Xdouble  reduce_rads();
X
X#endif
X
X/* 1 dot in 10 inches at 300 dots/in; in radians */
X#define APPROX      0.0003
X
X
X/* =========================== choose_step() =============================== */
X/*
X * while the current hatch segment 
X * intersects both side s1 and side s2 of the triangle, 
X *    call step():
X *                  write the segment to the map[] array, 
X *                  and calculate the endpts for the next hatch segment.
X * Side s1 is the side used to determine the limit of the hatching.
X */
X
Xchoose_step(f_pt_s1p, chg_x_s1, chg_y_s1,
X    f_pt_s2p, chg_x_s2, chg_y_s2,
X    status, limit)
X    FPOINT *f_pt_s1p,
X           *f_pt_s2p;
X    double  chg_x_s1,
X            chg_y_s1,
X            chg_x_s2,
X            chg_y_s2;
X    int     status,
X            limit;
X{
X    POINT   endpt_s1,
X            endpt_s2;
X
X#ifdef TESTVER
X    if (debug4) {
X	fprintf(errfp,
X	    "f_pt_s1: ( %6.1f, %6.1f );  f_pt_s2: ( %6.1f, %6.1f )\n",
X	    f_pt_s1p->xx, f_pt_s1p->yy, f_pt_s2p->xx, f_pt_s2p->yy);
X	fprintf(errfp,
X	    "status: %d;  limit: %d\n", status, limit);
X	fprintf(errfp,
X	    "chg_x_s1: %6.1f;  chg_y_s1: %6.1f;  chg_x_s2: %6.1f;  chg_y_s2: %6.1f\n",
X	    chg_x_s1, chg_y_s1, chg_x_s2, chg_y_s2);
X	fflush(errfp);
X    }
X#endif
X
X    cvt_pt(&endpt_s1, f_pt_s1p);
X    cvt_pt(&endpt_s2, f_pt_s2p);
X
X    if (status == VERT) {
X	if (chg_y_s1 > 0.0) {
X	    while (endpt_s1.y <= limit) {
X		step(f_pt_s1p, chg_x_s1, chg_y_s1,
X		    f_pt_s2p, chg_x_s2, chg_y_s2,
X		    &endpt_s1, &endpt_s2);
X	    }
X	} else {
X	    while (endpt_s1.y >= limit) {
X		step(f_pt_s1p, chg_x_s1, chg_y_s1,
X		    f_pt_s2p, chg_x_s2, chg_y_s2,
X		    &endpt_s1, &endpt_s2);
X	    }
X	}
X    } else {			/* non-vertical, use x-values for reference */
X	if (chg_x_s1 > 0.0) {
X	    while (endpt_s1.x <= limit) {
X		step(f_pt_s1p, chg_x_s1, chg_y_s1,
X		    f_pt_s2p, chg_x_s2, chg_y_s2,
X		    &endpt_s1, &endpt_s2);
X	    }
X	} else {
X	    while (endpt_s1.x >= limit) {
X		step(f_pt_s1p, chg_x_s1, chg_y_s1,
X		    f_pt_s2p, chg_x_s2, chg_y_s2,
X		    &endpt_s1, &endpt_s2);
X	    }
X	}
X    }
X}
X
X
X/* =========================== step() ====================================== */
X/*
X * write the current hatch segment to the map[] array, 
X * and calculate the endpts for the succeeding hatch segment.
X */
X
Xstep(f_pt_s1p, chg_x_s1, chg_y_s1,
X    f_pt_s2p, chg_x_s2, chg_y_s2,
X    endpt_s1p, endpt_s2p)
X    FPOINT *f_pt_s1p,
X           *f_pt_s2p;
X    double  chg_x_s1,
X            chg_y_s1,
X            chg_x_s2,
X            chg_y_s2;
X    POINT  *endpt_s1p,
X           *endpt_s2p;
X{
X    put_seg(*endpt_s1p, *endpt_s2p);
X
X    f_pt_s1p->xx += chg_x_s1;
X    f_pt_s1p->yy += chg_y_s1;
X    f_pt_s2p->xx += chg_x_s2;
X    f_pt_s2p->yy += chg_y_s2;
X
X    cvt_pt(endpt_s1p, f_pt_s1p);
X    cvt_pt(endpt_s2p, f_pt_s2p);
X}
X
X
X/* =========================== cvt_pt() ==================================== */
Xcvt_pt(pt, f_pt)
X    POINT  *pt;
X    FPOINT *f_pt;
X{
X    pt->x = (int) floor(f_pt->xx + 0.5);
X    pt->y = (int) floor(f_pt->yy + 0.5);
X}
X
X
X/* =========================== get_chgs() ================================== */
Xint
Xget_chgs(chg_xp, chg_yp, p1, p2)
X    double *chg_xp,
X           *chg_yp;
X    POINT   p1,
X            p2;
X{
X    double  seg_shift;
X    int     diffx,
X            diffy;
X    double  seg_rads;		/* angle of segment p1-p2 in radians */
X    int     status;		/* local var status */
X
X#ifdef TESTVER
X    static char *stat_type[] = {"GENERIC",
X	"PARALLEL",
X	"VERTICAL",
X	"HORIZONTAL"};
X
X#endif
X
X
X#ifdef TESTVER
X    if (debug7) {
X	fprintf(errfp, "\nIn: get_chgs();\n");
X    }
X    if (debug7) {
X	fprintf(errfp, "p1: ( %d, %d );  p2: ( %d, %d )\n",
X	    p1.x, p1.y, p2.x, p2.y);
X	fflush(errfp);
X    }
X#endif
X
X    /* find the angle of inclination of segment p1-p2 */
X    diffy = p2.y - p1.y;
X    diffx = p2.x - p1.x;
X    if (diffx != 0) {
X	seg_rads = atan2((double) diffy, (double) diffx);
X    } else {
X	seg_rads = (double) PI_2;
X    }
X
X    /*
X     * find the x- and y- increments for successive hatch line intersections
X     * along segment p1-p2 
X     */
X    hatch_rads = reduce_rads(hatch_rads);
X    seg_rads = reduce_rads(seg_rads);
X
X#ifdef TESTVER
X    if (debug7) {
X	fprintf(errfp, "diffy: %6d;  diffx: %6d\n", diffy, diffx);
X	fprintf(errfp, "seg_rads: %6.4f;  hatch_rads: %6.4f;  abs diff: %6.4f\n",
X	    seg_rads, hatch_rads, fabs(hatch_rads - seg_rads));
X    }
X#endif
X
X    if (fabs(hatch_rads - seg_rads) < APPROX) {	/* parallel */
X	status = PARL;
X	*chg_xp = x_shift;
X	*chg_yp = 0.0;
X    } else if (fabs(seg_rads) < APPROX) {	/* horizontal */
X	status = HORZ;
X	*chg_xp = x_shift;
X	*chg_yp = 0.0;
X    } else if (fabs(seg_rads - PI_2) < APPROX) {	/* vertical */
X	status = VERT;
X	*chg_xp = 0.0;
X	*chg_yp = -tan(hatch_rads) * x_shift;
X    } else {
X	/*
X	 * spacing of intercepts of adjacent hatch lines along segment p1-p2
X	 * uses law of sines 
X	 */
X	status = GENR;
X	seg_shift = (x_shift * sin(PI - hatch_rads)) /
X	    sin(hatch_rads - seg_rads);
X	*chg_xp = seg_shift * cos(seg_rads);
X	*chg_yp = seg_shift * sin(seg_rads);
X    }
X    /* remove error due to digital storage, for tests for equality later */
X    if (fabs(*chg_xp) < 0.001)
X	*chg_xp = 0.0;
X    if (fabs(*chg_yp) < 0.001)
X	*chg_yp = 0.0;
X
X#ifdef TESTVER
X    if (debug7) {
X	fprintf(errfp, "seg_rads (deg): %6.1f; seg_rads (rads): %6.4f\n",
X	    (seg_rads / DEG_TO_RAD), seg_rads);
X	fprintf(errfp, "sin(PI-hatch_rads): %6.4f;  sin(hatch-seg): %6.4f\n",
X	    sin(PI - hatch_rads), sin(hatch_rads - seg_rads));
X	fprintf(errfp, "x_shift: %6.1f;  seg_shift: %6.1f\n",
X	    x_shift, seg_shift);
X	fprintf(errfp, "Angle relationship: %s\n", stat_type[status]);
X	fprintf(errfp, "chg_x: %6.1f;  chg_y: %6.1f\n", *chg_xp, *chg_yp);
X	fflush(errfp);
X    }
X#endif
X
X    return (status);
X}
X
X
X/* =========================== reduce_rads() =============================== */
X/* modify angle so that  0 <= angle <= PI */
Xdouble
Xreduce_rads(angle)
X    double  angle;
X{
X    while (angle > PI) {
X	angle -= PI;
X    }
X    while (angle < 0.0) {
X	angle += PI;
X    }
X    return (angle);
X}
END_OF_FILE
if test 6760 -ne `wc -c <'step.c'`; then
    echo shar: \"'step.c'\" unpacked with wrong size!
fi
# end of 'step.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 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