v14i029: Device-independant graphics system, with drivers
Rich Salz
rsalz at bbn.com
Thu Apr 7 08:04:13 AEST 1988
Submitted-by: Joe Dellinger <joe at hanauma.STANFORD.EDU>
Posting-number: Volume 14, Issue 29
Archive-name: vplot/part24
#! /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 24 (of 24)."
# Wrapped by rsalz at fig.bbn.com on Fri Mar 25 11:47:38 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Vplot_Kernel/filters/dovplot.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Vplot_Kernel/filters/dovplot.c'\"
else
echo shar: Extracting \"'Vplot_Kernel/filters/dovplot.c'\" \(51559 characters\)
sed "s/^X//" >'Vplot_Kernel/filters/dovplot.c' <<'END_OF_FILE'
X/*
X * Copyright 1987 the Board of Trustees of the Leland Stanford Junior
X * University. Official permission to use this software is included in
X * the documentation. It authorizes you to use this file for any
X * non-commercial purpose, provided that this copyright notice is not
X * removed and that any modifications made to this file are commented
X * and dated in the style of my example below.
X */
X
X/*
X *
X * source file: ./filters/dovplot.c
X *
X * Joe Dellinger (SEP), June 11 1987
X * Inserted this sample edit history entry.
X * Please log any further modifications made to this file:
X */
X/*
X * Joe Dellinger Oct 18 1987
X * Made text fatness scale with txscale and scale for GKS compatibility
X * Joe Dellinger Nov 9 1987
X * Changed "\n" to CRLF in MESG_TEXT calls, since newlines are
X * no longer mapped into Carriage-return linefeeds automatically.
X * (This was due to Stew's turning off of output translation.)
X * Joe Dellinger Dec 9 1987
X * Made the "bad color level" error message more verbose.
X * Joe Dellinger Dec 19 1987
X * Call dev.attributes(NEW_DASH,...) when the dash pattern has
X * been changed, call dev.attributes(NEW_PAT,...) when a new raster
X * pattern has been loaded, call dev.attributes(NEW_FONT,...)
X * when the txfont, txprec, or txovly has been changed,
X * dev.attributes(NEW_OVERLAY,...) when the overlay mode has
X * been changed, dev.attributes(NEW_ALIGN) when the text
X * alignment mode has been changed, dev.attributes(NEW_FAT) when
X * the fatness has been changed. Call dev.message(MESG_MESSAGE)
X * when a message is generated via the VP_MESSAGE vplot command.
X * Joe Dellinger Dec 20 1987
X * It's up to the device to turn around and call gentext if
X * txfont < NUMGENFONT.
X * Joe Dellinger Jan 8 1988
X * Added reset_parameters() to frontend and dovplot.
X * Turn off ALL polygon shading if shade=NO, even that generated
X * by raster, text, etc.
X * Joe Dellinger Jan 10 1988
X * Don't blindly scale up fatmult each time dovplot thinks it's
X * being called for the first time.
X * Joe Dellinger Jan 14 1988
X * The text alignment should also be reset between plots.
X * Joe Dellinger Jan 20 1988
X * Added VP_BEGIN_GROUP and VP_END_GROUP. Fixed nplots bug.
X * Joe Dellinger Jan 22 1988
X * Added xdim_orig and ydim_orig to pat.h.
X * Joe Dellinger Jan 26 1988
X * Fixed EOF bug in getvpstring(). Changed rule for mapping
X * colors to grey levels to match how B+W TV's do it.
X * Joe Dellinger Feb 10 1988
X * Weight color mismatches to tally with grey mapping method.
X * Joe Dellinger Feb 12 1988
X * Make sure that VP_WINDOW commands that specify an inverted
X * clipping rectangle cause everything to be clipped away.
X * Joe Dellinger Feb 16 1988
X * Make number of arguments passed to dev.attributes and dev.raster
X * constant to head off future catastrophe from Sun IV's.
X * Joe Dellinger Feb 22 1988
X * Created INT_PAUSE to be separate from INT_GET_STRING.
X * Joe Dellinger Feb 24 1988
X * Txfont, txprec, txovly, style, dash line style also reset
X * on erases.
X * Only the erase command is handled specially at the start
X * of the file. This was causing initial setstyle commands
X * to be left out of their groups!
X * Joe Dellinger Feb 26 1988
X * Allow vpattributes(END_GROUP,...) to signal dovplot whether it
X * should exit or not after the call.
X * Joe Dellinger Feb 28 1988
X * Fatness behaves like a geometric attribute.
X * Can't use the *= operator on the Sun!
X * if integer i = 10, then i *= .5 sets i to ZERO.
X * I wish Sun would get their act together.
X * This explains several mysterious bugs on the Suns.
X */
X
X/*
X * process a vplot file or stream
X * Keywords: vplot pen generic
X */
X
X#include <stdio.h>
X#include <math.h>
X#include <ctype.h>
X#include <strings.h>
X
X#include <vplot.h>
X
X#include "./include/params.h" /* for machine dependencies */
X#include "./include/enum.h"
X#include "./include/err.h"
X#include "./include/attrcom.h"
X#include "./include/intcom.h"
X#include "./include/mesgcom.h"
X#include "./include/erasecom.h"
X#include "./include/closestat.h"
X#include "./include/getxy.h"
X#include "./include/pat.h"
X#include "./include/vertex.h"
X#include "./include/extern.h"
X#include "./include/round.h"
X
X#define COLOR_MAP(A) color_set[A][MAP];
X#define GREY_MAP(A) color_set[A][_GREY];
X
X/*
X * Banished to an include file so that "indent" can't get its hands on it
X */
X#include "./include/readraster.h"
X
extern int wantras, smart_raster;
extern int allowecho;
extern int brake;
extern FILE *controltty;
extern int cur_color;
extern int pat_color;
extern int epause;
extern int erase;
extern int ever_called;
extern int fatbase;
extern int ifat;
extern int first_time;
extern int framewindows;
extern int next_color;
extern int ipat;
extern int nplots;
extern int overlay;
extern struct pat pat[];
extern FILE *pltout, *pltin, *temp;
extern char group_name[];
extern int group_number;
extern char *txbuffer;
extern int txbuflen;
extern struct vertex *vxbuffer;
extern int vxbuflen;
extern int window;
extern int xwmax, xwmin, ywmax, ywmin;
extern int xWmax, xWmin, yWmax, yWmin;
int xwmin_last, xwmax_last, ywmin_last, ywmax_last;
extern int xnew, ynew;
extern int xold, yold;
extern int xorigin, yorigin;
extern float scale;
extern float xscale;
extern float yscale;
extern int default_style;
extern int default_txfont, default_txprec, default_txovly;
extern int default_overlay;
extern int color_set[MAX_COL + 1][_NUM_PRIM];
extern int greycorr ();
extern int num_col_8;
extern int xret, yret;
extern int add_a_cor ();
extern char interact[];
extern float dashsum;
extern float dashpos;
extern float dashes[];
extern struct txalign txalign;
X
char *malloc ();
char *calloc ();
char *realloc ();
long int ftell ();
extern void dithline ();
extern void wlimit ();
X
int need_devcolor = NO;
X
dovplot ()
X{
int i, j, k, c;
int key, size, npts;
int nmul;
int nx, ny, nx_orig, ny_orig;
int orient, ras_orient;
register int *ptr;
int nx_mult, ny_mult;
int nx_temp, ny_temp;
int *tempbuf, *ptemp;
FILE *fopen ();
int new_style;
int starterase = 0;
int col_tab_no, red, green, blue, grey, dist, min_dist, best_col;
int hacol[NHATCH * 2], hafat[NHATCH * 2], haoff[NHATCH * 2], hasiz[NHATCH * 2], numhatch;
float angle, xrasmult, yrasmult;
int xpix, ypix, num_pat, num_byte;
int yrast, lastrast;
int xvr_min, xvr_max, yvr_min, yvr_max;
int xr_min, xr_max, yr_min, yr_max;
int xvru_min, xvru_max, yvru_min, yvru_max;
int xru_min, yru_max;
int xxx[4], yyy[4];
int pos, ii, jj, kk, num_rep, ras_offset, dither_it;
unsigned char *rasterline, *rasterline2, *outraster, *outraster2;
unsigned char ibyte;
int xnewer, ynewer;
int xtext0, xtext1, xtext2, ytext0, ytext1, ytext2;
int type;
int *marker_vec, *mvec;
int savefat;
float savefatmult;
char string[MAXFLEN + 1];
X
X /*
X * Check to make sure we really got anything before we claim we've made a
X * plot.
X */
X if ((c = getc (pltin)) == EOF)
X return;
X ungetc ((char) c, pltin);
X
X while (((c = getc (pltin)) == VP_ERASE) || ((c == VP_BREAK) && brake))
X {
X /*
X * This is a baby version of the main switch that takes up most of
X * this file.
X */
X switch (c)
X {
X case VP_ERASE:
X case VP_BREAK:
X starterase = 1;
X break;
X }
X }
X
X /*
X * Files that consist only of erase characters and nothing else are
X * ignored.
X */
X if (c == EOF)
X return;
X ungetc ((char) c, pltin);
X
X if (first_time)
X {
X dev.reset ();
X/*
X * Device is now officially open for orders.
X */
X if (dev_xmax <= dev_xmin ||
X dev_ymax <= dev_ymin ||
X pixels_per_inch == 0. ||
X aspect_ratio == 0. ||
X num_col == -1)
X ERR (FATAL, name, "Critical variables left unset by device!");
X
X/*
X * Set maximum clipping window for dev.attributes(SET_WINDOW)
X */
X xwmax_last = dev_xmax;
X xwmin_last = dev_xmin;
X ywmax_last = dev_ymax;
X ywmin_last = dev_ymin;
X
X/*
X * Set up color maps
X */
X init_colors ();
X
X ever_called = 1;
X }
X else
X {
X dev.close (CLOSE_FLUSH);
X if (epause > 0)
X {
X sleep ((unsigned) epause);
X }
X else
X if (epause < 0)
X {
X dev.close (CLOSE_FLUSH);
X message (MESG_ERASE);
X message (MESG_ON);
X message (MESG_HOME);
X message (MESG_READY);
X message (MESG_HIGHLIGHT_ON);
X message (MESG_TEXT, "Type Return to Continue... ");
X message (MESG_DONE);
X dev.interact (INT_PAUSE, controltty, string);
X message (MESG_HIGHLIGHT_OFF);
X if (!allowecho)
X {
X message (MESG_READY);
X message (MESG_TEXT, CRLF);
X }
X message (MESG_DONE);
X message (MESG_OFF);
X message (MESG_ERASE);
X }
X /*
X * Inquire point back from device
X */
X if (interact[0] != '\0')
X {
X getapoint ();
X }
X }
X
X /*
X * Erase the screen to background color
X */
X if (((erase & FORCE_INITIAL) && (first_time || (erase & DO_LITERALS)))
X || (starterase && (erase & DO_LITERALS)))
X {
X if (first_time)
X dev.erase (ERASE_START);
X else
X {
X dev.erase (ERASE_MIDDLE);
X nplots++;
X }
X dev.close (CLOSE_FLUSH);
X }
X
X first_time = NO;
X
X/*
X * Reset fatness, cur_color, etc.
X */
X new_style = default_style;
X setstyle (new_style);
X reset ();
X
X/*
X * Make SURE the color is what it's supposed to be, just to be safe.
X */
X dev.attributes (SET_COLOR, cur_color, 0, 0, 0);
X need_devcolor = NO;
X
X message (MESG_OFF);
X dev.close (CLOSE_FLUSH);
X
X/*
X * Start a group that will contain this frame (always group 0).
X */
X ii = ftell (pltin);
X sprintf (group_name, "%s.%d", pltname, nplots);
X dev.attributes (BEGIN_GROUP, group_number, ii, 0, 0);
X group_number++;
X
X if (framewindows)
X outline_window ();
X
X/*
X * Finally, here's the main loop that does the actual processing of vplot.
X * Notice that some tricky commands (VP_DRAW, VP_SET_COLOR_TABLE) look ahead
X * at the next command to try to anticipate often-occuring situations,
X * so things get a little complicated here.
X */
X while ((c = getc (pltin)) != EOF)
X {
X switch (c) /* command list */
X {
X case VP_SETSTYLE: /* set the style */
X c = getc (pltin);
X if ((c == 'r') || (c == 'R') || (c == 'm') || (c == 'M'))
X new_style = ROTATED;
X else
X if ((c == 'o') || (c == 'O'))
X new_style = OLD;
X else
X if ((c == 'a') || (c == 'A'))
X new_style = ABSOLUTE;
X else
X new_style = STANDARD;
X setstyle (new_style);
X
X if (framewindows)
X outline_window ();
X
X break;
X case VP_MOVE: /* move */
X /*
X * Reset position in dash pattern.
X */
X dashpos = 0.;
X
X GETXY (xold, yold);
X break;
X case VP_DRAW: /* draw */
X GETXY (xnew, ynew);
X update_color ();
X while ((c = getc (pltin)) == VP_DRAW)
X {
X GETXY (xnewer, ynewer);
X /*
X * Is it the same point?
X */
X if (xnewer == xnew && ynewer == ynew)
X continue;
X /*
X * Is it colinear and horizontal or vertical?
X */
X if ((ynewer == ynew && ynew == yold &&
X ((xnewer > xnew) == (xnew > xold))) ||
X (xnewer == xnew && xnew == xold &&
X ((ynewer > ynew) == (ynew > yold))))
X {
X ynew = ynewer;
X xnew = xnewer;
X continue;
X }
X dev.vector (xold, yold, xnew, ynew, fat, dashon);
X xold = xnew;
X yold = ynew;
X xnew = xnewer;
X ynew = ynewer;
X }
X dev.vector (xold, yold, xnew, ynew, fat, dashon);
X xold = xnew;
X yold = ynew;
X if (c == EOF)
X goto End_of_file;
X ungetc ((char) c, pltin);
X break;
X case VP_PLINE: /* polyline */
X /*
X * Reset position in dash pattern.
X */
X dashpos = 0.;
X
X npts = geth (pltin);
X if (npts == 0)
X break;
X GETXY (xold, yold);
X npts--;
X if (npts == 0)
X break;
X GETXY (xnew, ynew);
X npts--;
X update_color ();
X while (npts > 0)
X {
X GETXY (xnewer, ynewer);
X npts--;
X /*
X * Is it the same point?
X */
X if (xnewer == xnew && ynewer == ynew)
X continue;
X /*
X * Is it colinear and horizontal or vertical?
X */
X if ((ynewer == ynew && ynew == yold &&
X ((xnewer > xnew) == (xnew > xold))) ||
X (xnewer == xnew && xnew == xold &&
X ((ynewer > ynew) == (ynew > yold))))
X {
X ynew = ynewer;
X xnew = xnewer;
X continue;
X }
X dev.vector (xold, yold, xnew, ynew, fat, dashon);
X xold = xnew;
X yold = ynew;
X xnew = xnewer;
X ynew = ynewer;
X }
X dev.vector (xold, yold, xnew, ynew, fat, dashon);
X xold = xnew;
X yold = ynew;
X break;
X case VP_PMARK: /* polymarker */
X npts = geth (pltin);/* how many markers ? */
X type = geth (pltin);/* what symbol? (any positive integer) */
X size = geth (pltin);/* How big? */
X size = size * mkscale * vdevscale * RPERIN / TXPERIN;
X
X if (npts == 0)
X break;
X /* allocate space for the points */
X marker_vec = (int *) malloc ((unsigned) (npts * 2 * sizeof (int)));
X mvec = marker_vec;
X if (mvec == NULL)
X ERR (FATAL, name, "Can't malloc memory for markers!");
X
X /* read the locations, and transform them to device coordinates */
X for (ii = 0; ii < npts; ii++)
X {
X GETXY (xnewer, ynewer);
X *mvec = xnewer;
X ++mvec;
X *mvec = ynewer;
X ++mvec;
X }
X update_color ();
X /* call the device routine to display the markers */
X dev.marker (npts, type, size, marker_vec);
X /* release the storage used for the points */
X free ((char *) marker_vec);
X break;
X case VP_ORIGIN: /* set origin */
X xorigin = geth (pltin);
X yorigin = geth (pltin);
X break;
X case VP_BEGIN_GROUP:
X ii = ftell (pltin) - 1;
X getvpstring ();
X strncpy (group_name, txbuffer, MAXFLEN);
X dev.attributes (BEGIN_GROUP, group_number, ii, 0, 0);
X group_number++;
X break;
X case VP_END_GROUP:
X group_number--;
X if (group_number < 1)
X {
X ERR (WARN, name,
X "group invalidly nested");
X group_number = 1;
X }
X else
X {
X ii = dev.attributes (END_GROUP, group_number, 0, 0, 0);
X if (ii == DOVPLOT_EXIT)
X {
X dev.close (CLOSE_FLUSH);
X return;
X }
X if (ii != DOVPLOT_CONT)
X ERR (WARN, name, "dev.attributes(END_GROUP,...) returned junk.");
X }
X break;
X case VP_GTEXT: /* GKS-like text */
X xtext0 = 0;
X ytext0 = 0;
X vptodevxy (xtext0, ytext0, &xtext0, &ytext0);
X GETXY (xtext1, ytext1);
X GETXY (xtext2, ytext2);
X g_text:
X xtext1 -= xtext0;
X xtext2 -= xtext0;
X ytext1 -= ytext0;
X ytext2 -= ytext0;
X
X savefat = fat;
X savefatmult = fatmult;
X fatmult *= txscale;
X if (ifat >= 0)
X {
X fat = fatmult * (float) (ifat + fatbase);
X }
X else
X {
X fat = -1;
X }
X update_color ();
X getvpstring ();
X/*
X * Fonts less than NUMGENFONT reserved for gentext fonts:
X * up to the device to enforce that rule, though.
X */
X dev.text (txbuffer,
X (float) xtext1 / TEXTVECSCALE,
X (float) ytext1 / TEXTVECSCALE,
X (float) xtext2 / TEXTVECSCALE,
X (float) ytext2 / TEXTVECSCALE);
X fat = savefat;
X fatmult = savefatmult;
X break;
X case VP_TEXT: /* text */
X size = geth (pltin);
X size = size * txscale * (float) RPERIN / (float) TXPERIN;
X orient = (int) geth (pltin);
X new_text:
X xtext0 = 0;
X ytext0 = 0;
X /* Character path direction */
X xtext1 =
X ROUND (TEXTVECSCALE * size * cos (orient * 3.14159 / 180.));
X ytext1 =
X ROUND (TEXTVECSCALE * size * sin (orient * 3.14159 / 180.));
X /* Character up vector direction */
X orient += 90;
X xtext2 =
X ROUND (TEXTVECSCALE * size * cos (orient * 3.14159 / 180.));
X ytext2 =
X ROUND (TEXTVECSCALE * size * sin (orient * 3.14159 / 180.));
X vptodevxy (xtext0, ytext0, &xtext0, &ytext0);
X vptodevxy (xtext1, ytext1, &xtext1, &ytext1);
X vptodevxy (xtext2, ytext2, &xtext2, &ytext2);
X goto g_text;
X break;
X case VP_OLDTEXT: /* archaic format text */
X if ((key = geth (pltin)) < 0)
X ERR (FATAL, name, "invalid text key");
X size = (key & 037);
X size = size * txscale * (float) RPERIN / (float) TXPERIN;
X orient = (int) (((key & 0140) >> 5) * 90);
X goto new_text;
X break;
X case VP_OLDAREA: /* polygon */
X npts = geth (pltin);
X afat = geth (pltin);
X if (afat >= 0)
X {
X afat = fatmult * (fatbase + afat);
X }
X nx_temp = geth (pltin);
X ny_temp = geth (pltin);
X
X/*
X * If a monochrome device, then fill with dot pattern.
X * If a color device, fill with solid color.
X */
X nx = nx_temp * patternmult;
X if (nx_temp == 1 || (nx_temp > 0 && nx == 0))
X nx = 1;
X ny = ny_temp * patternmult;
X if (ny_temp == 1 || (ny_temp > 0 && ny == 0))
X ny = 1;
X
X nx_orig = nx;
X ny_orig = ny;
X
X if (!mono)
X {
X if (nx_temp == 0 || ny_temp == 0)
X {
X nx = 0;
X ny = 0;
X }
X else
X {
X nx = 1;
X ny = 1;
X }
X }
X /*
X * Create a temporary pattern
X */
X ipat = 0;
X if (nx * ny > 0)
X {
X if ((ptr = (int *) calloc ((unsigned) nx * ny, sizeof (int))) == NULL)
X ERR (FATAL, name, "cannot alloc memory to load pattern");
X pat[ipat] .patbits = ptr;
X ptr[(nx * ny) - 1] = cur_color;
X }
X else
X pat[ipat] .patbits = NULL;
X
X pat[ipat] .xdim = nx;
X pat[ipat] .ydim = ny;
X pat[ipat] .xdim_orig = nx_orig;
X pat[ipat] .ydim_orig = ny_orig;
X npts = getpolygon (npts);
X update_color ();
X if (afat >= 0)
X vecoutline (vxbuffer);
X if (npts > 2 && shade && nx > 0 && ny > 0)
X dev.area (npts, vxbuffer);
X if (nx * ny > 0)
X free ((char *) ptr);
X break;
X case VP_AREA: /* polygon fill */
X npts = geth (pltin);
X ipat = pat_color;
X
X if (pat[ipat] .patbits == NULL && shade)
X {
X /*
X * Create a default pattern (solid fill with this color) If
X * you don't like this default for a particular device, ie, a
X * black and white one, then the device itself can set up
X * defaults for colors 0 through 7 in dev.open
X */
X nx = 1;
X ny = 1;
X
X if ((ptr = (int *) calloc ((unsigned) nx * ny, sizeof (int))) == NULL)
X ERR (FATAL, name, "cannot alloc memory to load pattern");
X pat[ipat] .patbits = ptr;
X ptr[(nx * ny) - 1] = cur_color;
X pat[ipat] .xdim = nx;
X pat[ipat] .ydim = ny;
X pat[ipat] .xdim_orig = nx;
X pat[ipat] .ydim_orig = ny;
X }
X
X npts = getpolygon (npts);
X
X if (!shade)
X {
X /* At least draw the boundary to show where it is */
X afat = 0;
X update_color ();
X vecoutline (vxbuffer);
X }
X else
X {
X /* See whether raster or hatch area */
X if (pat[ipat] .xdim >= 0)
X {
X /* raster */
X if (npts > 2 && pat[ipat] .ydim > 0 && pat[ipat] .xdim > 0)
X {
X update_color ();
X dev.area (npts, vxbuffer);
X }
X }
X else
X {
X /* hatch */
X numhatch = -pat[ipat] .xdim;
X angle = 3.14159 * pat[ipat] .ydim / 180.;
X ptr = pat[ipat] .patbits;
X for (i = 0; i < numhatch * 2; i++)
X {
X hafat[i] = (*ptr++);
X hacol[i] = (*ptr++);
X haoff[i] = (*ptr++);
X hasiz[i] = (*ptr++);
X }
X if (npts > 2)
X {
X /*
X * Hatch patterns don't rotate. The polygon does, the
X * fill pattern doesn't.
X */
X genhatch (npts, numhatch, angle, hafat, hacol, haoff, hasiz, vxbuffer);
X }
X }
X }
X break;
X case VP_FAT: /* fat */
X /*
X * negative fat always means to not draw the line at all.
X */
X ifat = geth (pltin);
X if (ifat >= 0)
X {
X fat = fatmult * (float) (ifat + fatbase);
X }
X else
X {
X fat = -1;
X }
X dev.attributes (NEW_FAT, fat, 0, 0, 0);
X break;
X case VP_COLOR: /* change color */
X pat_color = geth (pltin);
X if (pat_color > MAX_COL || pat_color < 0)
X {
X ERR (WARN, name, "bad color number %d (max %d, min 0)",
X pat_color, MAX_COL);
X pat_color = DEFAULT_COLOR;
X }
X next_color = COLOR_MAP (pat_color);
X if (next_color != cur_color)
X {
X cur_color = next_color;
X need_devcolor = YES;
X }
X /*
X * Pattern zero reserved for the OLD_AREA command, so increment
X * the rest by one to make room.
X */
X pat_color++;
X break;
X case VP_SET_COLOR_TABLE: /* set color table entry */
X /*
X * The logic here is a bit tricky. Basically, it goes like this:
X * If the device actually has a settable color of that number,
X * then reset the device's color as asked. Otherwise, take the
X * closest color that we have and map to that. Color 0 is the
X * background color, and is special. Merely "close" colors are
X * not mapped to Color 0... it has to be exact. Even devices with
X * NO settable colors are still sent colors 0 through 7, and
X * these colors are then always left set to their original
X * defaults. In this way you can handle terminals like the GIGI
X * which have colors but not SETTABLE colors. Also remember that
X * the device itself will THEN have to permute colors 0 through 7
X * on top of all this to correspond with Vplot's definitions!
X */
X col_tab_no = geth (pltin);
X if (col_tab_no > MAX_COL || col_tab_no < 0)
X {
X ERR (FATAL, name, "Bad color table value %d (%d max)",
X col_tab_no, MAX_COL);
X }
X red = geth (pltin);
X green = geth (pltin);
X blue = geth (pltin);
X if (red > MAX_GUN || green > MAX_GUN || blue > MAX_GUN
X || red < 0 || green < 0 || blue < 0)
X {
X ERR (FATAL, name,
X "Bad color level in color %d (%d,%d,%d), %d max",
X col_tab_no, red, green, blue, MAX_GUN);
X }
X if (col_tab_no < num_col)
X {
X dev.attributes (SET_COLOR_TABLE, col_tab_no, red, green, blue);
X color_set[col_tab_no][STATUS] = SET;
X }
X else
X if (col_tab_no > 7)
X {
X color_set[col_tab_no][STATUS] = MAPPED;
X }
X else
X {
X if (col_tab_no > 0)
X {
X color_set[col_tab_no][STATUS] = MAP_SET;
X /*
X * Means that we need to map these but they are still set
X * to the original colors and can't be changed. Color 0
X * is always background, and any other color exactly the
X * same color as color 0 "wants to be", even if color 0
X * actually can't be and hasn't been reset, is mapped to
X * color zero if it can't be set.
X */
X }
X }
X /*
X * Save the color that this color table number wants to be
X */
X color_set[col_tab_no][_RED] = red;
X color_set[col_tab_no][_GREEN] = green;
X color_set[col_tab_no][_BLUE] = blue;
X /*
X * grey level is "Black and White TV style" mapped from color,
X * with corrections added by the subroutine greycorr.
X */
X grey = (blue * 1 + red * 2 + green * 4 + 6) / 7;
X color_set[col_tab_no][_GREY] = greycorr (grey);
X /*
X * If the next command is also a set color table command, we can
X * postpone doing this and kill 2 (or more) birds with one stone.
X */
X c = getc (pltin);
X if (c == EOF)
X goto End_of_file;
X ungetc ((char) c, pltin);
X if (c != VP_SET_COLOR_TABLE)
X {
X if (mono)
X {
X for (ii = 1; ii <= MAX_COL; ii++)
X {
X if (color_set[ii][_RED] == color_set[0][_RED] &&
X color_set[ii][_GREEN] == color_set[0][_GREEN] &&
X color_set[ii][_BLUE] == color_set[0][_BLUE])
X {
X color_set[ii][MAP] = 0;
X }
X else
X {
X color_set[ii][MAP] = 7;
X }
X }
X }
X else
X {
X /*
X * For all color table entries that aren't set, (because
X * we ran out of colors, for example) find the best color
X * that IS set and use that instead.
X */
X for (ii = num_col; ii <= MAX_COL; ii++)
X {
X if (color_set[ii][STATUS] & MAPPED)
X {
X min_dist = MAX_GUN * MAX_GUN * 8;
X for (i = num_col_8 - 1; i >= 0; i--)
X {
X /*
X * Colors 1 through 7 are guaranteed SET, So
X * we always get an answer. Color zero is
X * background and special. To map to it you
X * have to hit its color exactly, and no
X * other color matched exactly first.
X */
X if (color_set[i][STATUS] & SET)
X {
X if (color_set[i][STATUS] == SET)
X {
X k = color_set[i][_RED] - color_set[ii][_RED];
X dist = 2 * k * k;
X k = color_set[i][_GREEN] - color_set[ii][_GREEN];
X dist += 4 * k * k;
X k = color_set[i][_BLUE] - color_set[ii][_BLUE];
X dist += k * k;
X }
X else
X {
X k = MAX_GUN * ((i & 2) / 2) - color_set[ii][_RED];
X dist = 2 * k * k;
X k = MAX_GUN * ((i & 4) / 4) - color_set[ii][_GREEN];
X dist += 4 * k * k;
X k = MAX_GUN * ((i & 1) / 1) - color_set[ii][_BLUE];
X dist += k * k;
X }
X if (dist < min_dist && (i != 0 || dist == 0))
X {
X min_dist = dist;
X best_col = i;
X if (dist == 0)
X {
X /*
X * Might as well look no further
X */
X break;
X }
X }
X }
X }
X color_set[ii][MAP] = best_col;
X }
X }
X }
X }
X break;
X case VP_PURGE: /* purge pltout buffers */
X dev.close (CLOSE_FLUSH);
X break;
X case VP_BREAK: /* break */
X case VP_ERASE: /* erase */
X dev.close (CLOSE_FLUSH);
X
X if ((c == VP_ERASE) || brake)
X {
X group_number--;
X if (group_number != 0)
X {
X ERR (WARN, name,
X "group contains erase");
X group_number = 0;
X }
X else
X {
X ii = dev.attributes (END_GROUP, group_number, 0, 0, 0);
X if (ii == DOVPLOT_EXIT)
X return;
X if (ii != DOVPLOT_CONT)
X ERR (WARN, name, "dev.attributes(END_GROUP,...) returned junk.");
X }
X }
X
X if (epause < 0)
X {
X message (MESG_ERASE);
X message (MESG_ON);
X message (MESG_HOME);
X message (MESG_READY);
X message (MESG_HIGHLIGHT_ON);
X message (MESG_TEXT, "Type Return to Continue... ");
X message (MESG_DONE);
X dev.interact (INT_PAUSE, controltty, string);
X message (MESG_HIGHLIGHT_OFF);
X if (!allowecho)
X {
X message (MESG_READY);
X message (MESG_TEXT, CRLF);
X }
X message (MESG_DONE);
X message (MESG_OFF);
X message (MESG_ERASE);
X }
X else
X {
X if (epause > 0)
X sleep ((unsigned) epause);
X }
X /*
X * Inquire point back from device
X */
X if (interact[0] != '\0')
X {
X getapoint ();
X }
X
X if (erase & DO_LITERALS)
X if ((c == VP_ERASE) || brake)
X {
X dev.erase (ERASE_MIDDLE);
X nplots++;
X }
X else
X {
X dev.erase (ERASE_BREAK);
X nplots++;
X }
X
X new_style = default_style;
X setstyle (new_style);
X reset ();
X
X if ((c == VP_ERASE) || brake)
X {
X ii = ftell (pltin);
X sprintf (group_name, "%s.%d", pltname, nplots);
X dev.attributes (BEGIN_GROUP, group_number, ii, 0, 0);
X group_number++;
X }
X
X if (framewindows)
X outline_window ();
X
X break;
X case VP_WINDOW: /* window */
X if (window)
X {
X xwmin = geth (pltin);
X ywmin = geth (pltin);
X xwmax = geth (pltin);
X ywmax = geth (pltin);
X
X if (xwmin > xwmax || ywmin > ywmax)
X {
X/*
X * vptodevw will always return a window that is the "right way around",
X * even if the original window was inverted. So produce an inside-out
X * window which will clip everything away to nothing.
X */
X
X xwmin = xWmax + 1;
X xwmax = xWmin - 1;
X ywmin = yWmax + 1;
X ywmax = yWmin - 1;
X }
X else
X {
X
X vptodevw (xwmin, ywmin, xwmax, ywmax, &xwmin, &ywmin, &xwmax, &ywmax);
X
X wlimit (xWmin, xWmax, &xwmin, &xwmax);
X wlimit (yWmin, yWmax, &ywmin, &ywmax);
X }
X }
X else
X {
X geth (pltin);
X geth (pltin);
X geth (pltin);
X geth (pltin);
X }
X reset_windows ();
X if (framewindows)
X outline_window ();
X break;
X case VP_NOOP: /* no op */
X break;
X case VP_TXALIGN: /* set text alignment */
X /*
X * These are made available to the device text routine
X */
X txalign.hor = geth (pltin);
X txalign.ver = geth (pltin);
X dev.attributes (NEW_ALIGN, txalign.hor, txalign.ver, 0, 0);
X break;
X case VP_TXFONTPREC: /* set text font */
X /*
X * These are made available to the device text routine
X */
X ii = geth (pltin);
X if (ii >= 0)
X txfont = ii;
X else
X ii = -1;
X
X jj = geth (pltin);
X if (jj >= 0)
X txprec = jj;
X else
X jj = -1;
X
X kk = geth (pltin);
X if (kk >= 0)
X txovly = kk;
X else
X kk = -1;
X
X /*
X * Another way for the device to keep track of changes.
X */
X dev.attributes (NEW_FONT, ii, jj, kk, 0);
X break;
X case VP_OVERLAY: /* change overlay mode */
X /*
X * This is made available to the device dependent subroutines
X */
X overlay = geth (pltin);
X dev.attributes (NEW_OVERLAY, overlay, 0, 0, 0);
X break;
X case VP_PATLOAD: /* load a pattern */
X nmul = geth (pltin);
X ny = geth (pltin);
X
X /* See whether Raster or Hatch */
X if (ny >= 0)
X {
X /* Raster */
X /* nmul gives pixels_per_inch pattern is designed for */
X ny_mult = ny * (pixels_per_inch / nmul) * patternmult / aspect_ratio;
X if (ny_mult == 0 && ny > 0)
X ny_mult = 1;
X nx = geth (pltin);
X nx_mult = nx * (pixels_per_inch / nmul) * patternmult;
X if (nx_mult == 0 && nx > 0)
X nx_mult = 1;
X
X ipat = geth (pltin) + 1;
X if (ipat > NPAT || ipat < 1)
X ERR (FATAL, name, "bad pattern number %d (max %d, min 1)", ipat, NPAT);
X /*
X * Free up pattern that may already be there
X */
X if (pat[ipat] .patbits != NULL)
X {
X free ((char *) pat[ipat] .patbits);
X }
X
X if (nx_mult * ny_mult > 0)
X {
X if ((ptr = (int *) malloc ((unsigned) (nx_mult * ny_mult * sizeof (int)))) == NULL)
X ERR (FATAL, name, "cannot alloc memory to load pattern");
X pat[ipat] .patbits = ptr;
X }
X else
X {
X if ((ptr = (int *) malloc ((unsigned) (1 * sizeof (int)))) == NULL)
X ERR (FATAL, name, "cannot alloc memory to load dummy pattern");
X pat[ipat] .patbits = ptr;
X ptr[0] = 0;
X }
X
X if (nx * ny > 0)
X {
X if ((tempbuf = (int *) malloc ((unsigned) (nx * ny * sizeof (int)))) == NULL)
X ERR (FATAL, name,
X "cannot alloc memory to load pattern's temporary buffer");
X }
X else
X tempbuf = NULL;
X
X /*
X * read in pattern
X */
X ptemp = tempbuf;
X for (j = 0; j < nx * ny; j++)
X {
X k = geth (pltin);
X if (k > MAX_COL || k < 0)
X {
X ERR (WARN, name, "bad color number in pattern %d (max %d, min 0)",
X k, MAX_COL);
X k = DEFAULT_COLOR;
X }
X *ptemp++ = COLOR_MAP (k);
X }
X
X /*
X * copy into patbits, with "stretching"
X */
X for (i = 0; i < ny_mult; i++)
X {
X ny_temp = i * ny / ny_mult;
X for (j = 0; j < nx_mult; j++)
X {
X nx_temp = j * nx / nx_mult;
X ptr[j + nx_mult * i] = tempbuf[nx_temp + nx * ny_temp];
X }
X }
X /*
X * set dimensions of pattern
X */
X pat[ipat] .xdim = nx_mult;
X pat[ipat] .ydim = ny_mult;
X pat[ipat] .xdim_orig = nx_mult;
X pat[ipat] .ydim_orig = ny_mult;
X
X if (tempbuf != NULL)
X free ((char *) tempbuf);
X
X dev.attributes (NEW_PAT, ipat, 0, 0, 0);
X }
X else
X {
X /* Hatch Pattern */
X /* nmul gives angle, ny is merely a flag */
X nx = geth (pltin);
X if (nx <= 0 || nx * 2 > NHATCH)
X ERR (FATAL, name, "bad numhatch %d (max %d/2, min 1)", nx, NHATCH);
X ipat = geth (pltin) + 1;
X if (ipat > NPAT || ipat < 1)
X ERR (FATAL, name, "bad pattern number %d (max %d, min 1)", ipat, NPAT);
X /*
X * Free up pattern that may already be there
X */
X if (pat[ipat] .patbits != NULL)
X {
X free ((char *) pat[ipat] .patbits);
X }
X if ((ptr = (int *) malloc ((unsigned) (nx * 4 * 2 * sizeof (int)))) == NULL)
X ERR (FATAL, name, "cannot alloc memory to load pattern");
X pat[ipat] .patbits = ptr;
X
X for (i = 0; i < nx * 2; i++)
X {
X hafat[i] = geth (pltin);
X if (hafat[i] >= 0)
X {
X hafat[i] = fatmult * (fatbase + hafat[i]);
X }
X k = geth (pltin);
X if (k > MAX_COL || k < 0)
X {
X ERR (WARN, name, "bad color number in hatch %d (max %d, min 0)",
X k, MAX_COL);
X k = DEFAULT_COLOR;
X }
X hacol[i] = COLOR_MAP (k);
X haoff[i] = geth (pltin) * patternmult * pixels_per_inch / RPERIN;
X hasiz[i] = geth (pltin);
X }
X /*
X * Find the smallest hatch interval. 1/2 that, and then force
X * everything to be a multiple of that. If this were not
X * done, then hatch intervals that originally differed by
X * some simple fraction might end up slightly off, causing
X * very unsightly beats.
X */
X /*
X * Upper quantization limit of 1/10 inch
X */
X k = (RPERIN / 10) * 2;
X for (i = 0; i < nx * 2; i++)
X {
X if (hasiz[i] > 0 && hasiz[i] < k)
X k = hasiz[i];
X }
X j = k * (patternmult * pixels_per_inch / RPERIN) / 2.;
X if (j < 1)
X j = 1;
X for (i = 0; i < nx * 2; i++)
X {
X hasiz[i] = ((int) ((hasiz[i] * 2) / k)) * j;
X }
X /*
X * The above algorithm also means that you can't have a hatch
X * pattern come out on any device with a repetition rate of
X * faster than once per two pixels.
X */
X
X for (i = 0; i < nx * 2; i++)
X {
X/*
X * Make sure haoff < hasiz
X */
X if (haoff[i] >= hasiz[i])
X haoff[i] = 0;
X *ptr++ = hafat[i];
X *ptr++ = hacol[i];
X *ptr++ = haoff[i];
X *ptr++ = hasiz[i];
X }
X /*
X * set numhatch and angle... dimensions are 2 * numhatch by 4
X * . pat[ipat].xdim negative is a flag that this is a hatch
X * pattern, not raster, and so must be treated differently.
X */
X /*
X * numhatch, with neg as flag for hatch numhatch = 0 is OK,
X * because that means don't fill, same as nx = 0.
X */
X pat[ipat] .xdim = -nx;
X pat[ipat] .ydim = nmul; /* angle */
X }
X break;
X case VP_BIT_RASTER: /* bit raster data */
X case VP_BYTE_RASTER: /* byte raster data */
X ras_orient = geth (pltin);
X if (rotate % 90 != 0)
X {
X if (wantras)
X {
X ERR (WARN, name, "Raster only possible in 4 principal orientations");
X wantras = NO;
X }
X }
X else
X {
X ras_orient += rotate / 90;
X if (ras_orient >= 0)
X ras_orient = ras_orient % 4;
X else
X ras_orient = ((ras_orient % 4) + 4) % 4;
X }
X
X /*
X * They're on their honor to not go out of bounds. This check is
X * just for things that HAVE to go out of bounds.
X */
X ras_offset = geth (pltin);
X
X if (ras_offset + 0 > MAX_COL || ras_offset + 255 < 0)
X {
X ERR (FATAL, name, "Absurd raster offset %d", ras_offset);
X }
X
X xvr_min = geth (pltin);
X yvr_min = geth (pltin);
X xvr_max = geth (pltin);
X yvr_max = geth (pltin);
X vptodevw (xvr_min, yvr_min, xvr_max, yvr_max,
X &xvr_min, &yvr_min, &xvr_max, &yvr_max);
X xvru_min = xvr_min;
X yvru_min = yvr_min;
X xvru_max = xvr_max;
X yvru_max = yvr_max;
X
X xpix = geth (pltin);
X ypix = geth (pltin);
X
X switch (ras_orient)
X {
X case 0:
X xrasmult = (float) xpix / (float) (xvr_max - xvr_min);
X yrasmult = (float) ypix / (float) (yvr_max - yvr_min);
X xvr_max--;
X yvr_max--;
X break;
X case 1:
X yrasmult = (float) ypix / (float) (xvr_max - xvr_min);
X xrasmult = (float) xpix / (float) (yvr_max - yvr_min);
X xvr_max--;
X yvr_min++;
X break;
X case 2:
X xrasmult = (float) xpix / (float) (xvr_max - xvr_min);
X yrasmult = (float) ypix / (float) (yvr_max - yvr_min);
X xvr_min++;
X yvr_min++;
X break;
X case 3:
X yrasmult = (float) ypix / (float) (xvr_max - xvr_min);
X xrasmult = (float) xpix / (float) (yvr_max - yvr_min);
X xvr_min++;
X yvr_max--;
X break;
X }
X
X if (wantras && smart_raster)
X {
X rasterline = (unsigned char *) malloc ((unsigned) ((xpix + 7 + 2) * sizeof (unsigned char)));
X rasterline2 = (unsigned char *) malloc ((unsigned) ((xpix + 7 + 2) * sizeof (unsigned char)));
X if (rasterline == NULL || rasterline2 == NULL)
X ERR (FATAL, name, "cannot alloc memory to load raster line");
X
X outraster = (unsigned char *) malloc ((unsigned) (xpix * ypix) * sizeof (unsigned char));
X if (outraster == NULL)
X ERR (FATAL, name, "cannot alloc memory to load raster image");
X
X/*
X * See whether we want to dither or not.
X * Dither if monochrome device and dithering has been asked for.
X * It's up to the device to decide whether to actually do this.
X */
X dither_it = dither && mono;
X
X /*
X * Read in the Raster data for "Smart" devices, ie, those
X * which can stretch (and dither) their own raster.
X */
X num_rep = 0;
X for (yrast = 0; yrast < ypix; yrast++)
X {
X /*
X * Read in the next raster line, if we have a new one
X */
X if (num_rep <= 0)
X {
X num_rep = geth (pltin);
X if (num_rep <= 0)
X ERR (FATAL, name, "Bad Raster line multiplier");
X pos = 0;
X new_pat:num_pat = geth (pltin);
X num_byte = geth (pltin);
X if (num_pat <= 0 || num_byte <= 0 ||
X pos + num_pat * num_byte > xpix)
X ERR (FATAL, name, "Raster line not length promised");
X
X if (num_pat > 1)
X {
X if (dither_it)
X {
X READ_RASTER (
X rasterline2[j] = GREY_MAP (ras_offset + (int) fgetc (pltin)),
X rasterline2[j + jj] = GREY_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
X );
X }
X else
X {
X READ_RASTER (
X rasterline2[j] = COLOR_MAP (ras_offset + (int) fgetc (pltin)),
X rasterline2[j + jj] = COLOR_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
X );
X }
X for (j = 0; j < num_pat; j++)
X {
X for (k = 0; k < num_byte; k++)
X {
X rasterline[pos] = rasterline2[k];
X pos++;
X }
X }
X }
X else
X {
X if (dither_it)
X {
X READ_RASTER (
X rasterline[pos + j] = GREY_MAP (ras_offset + (int) fgetc (pltin)),
X rasterline[pos + j + jj] = GREY_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
X );
X }
X else
X {
X READ_RASTER (
X rasterline[pos + j] = COLOR_MAP (ras_offset + (int) fgetc (pltin)),
X rasterline[pos + j + jj] = COLOR_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
X );
X }
X pos += num_byte;
X }
X
X if (pos < xpix)
X goto new_pat;
X if (pos != xpix)
X ERR (FATAL, name, "Raster line not length promised");
X }
X num_rep--;
X for (ii = 0; ii < xpix; ii++)
X {
X outraster[ii + yrast * xpix] = rasterline[ii];
X }
X }
X
X /* Smart form */
X dev.raster (xpix, ypix, xvr_min, yvr_min, xvr_max, yvr_max,
X outraster, ras_orient, dither_it);
X
X free ((char *) rasterline);
X free ((char *) rasterline2);
X free ((char *) outraster);
X }
X else
X {
X wlimit (xwmin, xwmax, &xvr_min, &xvr_max);
X wlimit (ywmin, ywmax, &yvr_min, &yvr_max);
X
X switch (ras_orient)
X {
X case 0:
X xvr_max++;
X yvr_max++;
X xr_max = xvr_max - xvru_min;
X xr_min = xvr_min - xvru_min;
X yr_max = yvr_max - yvru_min;
X yr_min = yvr_min - yvru_min;
X yru_max = yvru_max - yvru_min;
X break;
X case 1:
X xvr_max++;
X yvr_min--;
X xr_max = yvru_max - yvr_min;
X xr_min = yvru_max - yvr_max;
X yr_max = xvr_max - xvru_min;
X yr_min = xvr_min - xvru_min;
X yru_max = xvru_max - xvru_min;
X break;
X case 2:
X xvr_min--;
X yvr_min--;
X xr_max = xvru_max - xvr_min;
X xr_min = xvru_max - xvr_max;
X yr_max = yvru_max - yvr_min;
X yr_min = yvru_max - yvr_max;
X yru_max = yvru_max - yvru_min;
X break;
X case 3:
X xvr_min--;
X yvr_max++;
X xr_max = yvr_max - yvru_min;
X xr_min = yvr_min - yvru_min;
X yr_max = xvru_max - xvr_min;
X yr_min = xvru_max - xvr_max;
X yru_max = xvru_max - xvru_min;
X break;
X }
X xru_min = 0;
X
X if (yr_max < yr_min || xr_max < xr_min || !wantras)
X {
X /*
X * We need to read through all the raster stuff, even if
X * we never use it.
X */
X yr_max = yr_min;
X xr_max = xr_min;
X }
X
X rasterline = (unsigned char *) malloc ((unsigned) ((xpix + 7 + 2) * sizeof (unsigned char)));
X rasterline2 = (unsigned char *) malloc ((unsigned) ((xpix + 7 + 2) * sizeof (unsigned char)));
X if (rasterline == NULL || rasterline2 == NULL)
X ERR (FATAL, name, "cannot alloc memory to load raster line");
X
X/*
X * See whether we need to dither or not.
X * Dither if monochrome device and dithering has been asked for,
X * Except if it is black-and-white bit raster already anyway.
X * For some reason putting "GREY_MAP" directly in the if makes a
X * syntax error. I think it is a compiler bug.
X */
X dither_it = dither && mono;
X if (dither_it && c == VP_BIT_RASTER)
X {
X j = GREY_MAP (0 * ras_offset);
X k = GREY_MAP (1 * ras_offset);
X if ((j == 0 || j == 255) && (k == 0 || k == 255))
X dither_it = NO;
X }
X
X if (xr_max > xr_min)
X {
X outraster2 = (unsigned char *) malloc ((unsigned) ((xr_max - xr_min) * sizeof (char)));
X if (dither_it)
X {
X outraster = (unsigned char *) malloc ((unsigned) ((xr_max - xr_min) * sizeof (char)));
X }
X else
X {
X outraster = outraster2;
X }
X if (outraster2 == NULL || outraster == NULL)
X ERR (FATAL, name, "cannot alloc memory to load raster line");
X }
X else
X {
X outraster2 = NULL;
X outraster = NULL;
X }
X
X /*
X * Read in the Raster data
X */
X lastrast = -1;
X num_rep = 0;
X for (i = yr_max - 1; i >= yr_min - 1; i--)
X {
X yrast = (yru_max - 1 - i) * yrasmult;
X if (i == yr_min - 1)
X {
X /*
X * Assure that the last bit of unused raster, if any,
X * is read. This last time through the loop is a
X * "dummy".
X */
X yrast = ypix - 1;
X }
X
X for (ii = 0; ii < (yrast - lastrast); ii++)
X {
X /*
X * Read in the next raster line, if we have a new one
X */
X if (num_rep <= 0)
X {
X num_rep = geth (pltin);
X if (num_rep <= 0)
X ERR (FATAL, name, "Bad Raster line multiplier");
X pos = 0;
X new_pat2:num_pat = geth (pltin);
X num_byte = geth (pltin);
X if (num_pat <= 0 || num_byte <= 0 ||
X pos + num_pat * num_byte > xpix)
X ERR (FATAL, name, "Raster line not length promised");
X
X/*
X * Only bother with it if we're actually going to use it
X */
X if (ii + num_rep >= yrast - lastrast
X && xr_max > xr_min && i >= yr_min)
X {
X if (num_pat > 1)
X {
X if (dither_it)
X {
X READ_RASTER (
X rasterline2[j] = GREY_MAP (ras_offset + (int) fgetc (pltin)),
X rasterline2[j + jj] = GREY_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
X );
X }
X else
X {
X READ_RASTER (
X rasterline2[j] = COLOR_MAP (ras_offset + (int) fgetc (pltin)),
X rasterline2[j + jj] = COLOR_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
X );
X }
X for (j = 0; j < num_pat; j++)
X {
X for (k = 0; k < num_byte; k++)
X {
X rasterline[pos] = rasterline2[k];
X pos++;
X }
X }
X }
X else
X {
X if (dither_it)
X {
X READ_RASTER (
X rasterline[pos + j] = GREY_MAP (ras_offset + (int) fgetc (pltin)),
X rasterline[pos + j + jj] = GREY_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
X );
X }
X else
X {
X READ_RASTER (
X rasterline[pos + j] = COLOR_MAP (ras_offset + (int) fgetc (pltin)),
X rasterline[pos + j + jj] = COLOR_MAP (ras_offset * ((ibyte & (001 << (7 - j))) != 0))
X );
X }
X pos += num_byte;
X }
X }
X else
X {
X/*
X * We're just going to turn right around and read another one,
X * So throw this away!
X */
X if (c == VP_BYTE_RASTER)
X {
X for (j = 0; j < num_byte; j++)
X {
X fgetc (pltin);
X }
X }
X else
X {
X for (j = 0; j < num_byte; j += 8)
X {
X fgetc (pltin);
X }
X }
X pos += num_pat * num_byte;
X }
X if (pos < xpix)
X goto new_pat2;
X if (pos != xpix)
X ERR (FATAL, name, "Raster line not length promised");
X
X if (wantras && xr_max > xr_min && i >= yr_min)
X {
X for (j = xr_min; j < xr_max; j++)
X {
X outraster2[j - xr_min] =
X rasterline[(int) ((j - xru_min) * xrasmult)];
X }
X }
X }
X num_rep--;
X }
X lastrast = yrast;
X
X if (xr_max > xr_min && i >= yr_min)
X {
X if (dither_it)
X {
X dithline (outraster2, outraster, xr_max - xr_min, yr_max - 1 - i, dither);
X }
X /* Dumb forms */
X switch (ras_orient)
X {
X case 0:
X dev.raster (yr_max - 1 - i, yr_max - yr_min,
X xvr_min, i + yvru_min,
X xr_max - xr_min, ras_orient, outraster,
X 0, 0);
X break;
X case 1:
X dev.raster (yr_max - 1 - i, yr_max - yr_min,
X xvru_min + i, yvr_max,
X xr_max - xr_min, ras_orient, outraster,
X 0, 0);
X break;
X case 2:
X dev.raster (yr_max - 1 - i, yr_max - yr_min,
X xvr_max, yvru_max - i,
X xr_max - xr_min, ras_orient, outraster,
X 0, 0);
X break;
X case 3:
X dev.raster (yr_max - 1 - i, yr_max - yr_min,
X xvru_max - i, yvr_min,
X xr_max - xr_min, ras_orient, outraster,
X 0, 0);
X break;
X }
X }
X }
X free ((char *) rasterline);
X free ((char *) rasterline2);
X if (outraster2 != NULL)
X {
X free ((char *) outraster2);
X if (dither_it)
X free ((char *) outraster);
X }
X if (!wantras)
X {
X xxx[0] = xvru_min;
X yyy[0] = yvru_min;
X xxx[1] = xvru_min;
X yyy[1] = yvru_max;
X xxx[2] = xvru_max;
X yyy[2] = yvru_max;
X xxx[3] = xvru_max;
X yyy[3] = yvru_min;
X drawpolygon (4, xxx, yyy);
X }
X }
X break;
X case VP_MESSAGE: /* Text message */
X getvpstring ();
X message (MESG_READY);
X message (MESG_MESSAGE);
X message (MESG_TEXT, txbuffer);
X message (MESG_TEXT, CRLF);
X message (MESG_DONE);
X break;
X case VP_SETDASH:
X npts = geth (pltin);
X if (npts > MAXDASH)
X {
X ERR (FATAL, name, "Too complicated a dash line pattern.");
X }
X dashon = npts;
X k = 0;
X dashsum = 0.;
X for (ii = 0; ii < npts * 2; ii++)
X {
X dashes[ii] = dashscale * (float) geth (pltin) / RPERIN;
X if (dashes[ii] < 0.)
X ERR (FATAL, name, "Negative dash distance.");
X
X if (dashes[ii] != 0.)
X k = 1;
X
X dashsum += dashes[ii];
X }
X if (!k)
X dashon = NO;
X dev.attributes (NEW_DASH, dashon, 0, 0, 0);
X break;
X default: /* error */
X ERR (FATAL, name,
X "invalid VPLOT command decimal %d character %c",
X (int) c, (char) c);
X break;
X }
X }
End_of_file:
X/*
X * End of main while loop. Either fall out here or jump here when you hit
X * the end of the file somewhere.
X */
X
X dev.close (CLOSE_FLUSH); /* force last vector out */
X
X/*
X * End the group for this frame
X */
X group_number--;
X if (group_number != 0)
X {
X ERR (WARN, name,
X "group left unclosed at end of file");
X group_number = 0;
X }
X else
X {
X ii = dev.attributes (END_GROUP, group_number, 0, 0, 0);
X if (ii == DOVPLOT_EXIT)
X return;
X if (ii != DOVPLOT_CONT)
X ERR (WARN, name, "dev.attributes(END_GROUP,...) returned junk.");
X }
X
X/*
X * Exit of dovplot
X */
X return;
X}
X
X/*
X * reset variables that can be affected by vplot commands when
X * processing multiple plots, and don't stay set across pages
X */
reset ()
X{
int ii, jj, kk;
X
X xwmin = xWmin; /* plot window parameters defaulted */
X xwmax = xWmax; /* to maximum size */
X ywmin = yWmin;
X ywmax = yWmax;
X
X reset_windows ();
X
X fat = fatmult * (float) (fatbase);
X dev.attributes (NEW_FAT, fat, 0, 0, 0);
X
X if (cur_color != DEFAULT_COLOR)
X {
X need_devcolor = YES;
X cur_color = DEFAULT_COLOR;
X }
X
X txalign.hor = TH_NORMAL;
X txalign.ver = TV_NORMAL;
X dev.attributes (NEW_ALIGN, txalign.hor, txalign.ver, 0, 0);
X
X ii = -1;
X jj = -1;
X kk = -1;
X if (txfont != default_txfont)
X {
X txfont = default_txfont;
X ii = txfont;
X }
X if (txprec != default_txprec)
X {
X txprec = default_txprec;
X jj = txprec;
X }
X if (txovly != default_txovly)
X {
X txovly = default_txovly;
X kk = txovly;
X }
X dev.attributes (NEW_FONT, ii, jj, kk, 0);
X
X dashon = NO;
X dev.attributes (NEW_DASH, dashon, 0, 0, 0);
X
X overlay = default_overlay;
X dev.attributes (NEW_OVERLAY, overlay, 0, 0, 0);
X}
X
reset_windows ()
X{
extern int xwmax_last, ywmax_last, xwmin_last, ywmin_last;
X
X if (xwmax != xwmax_last || ywmax != ywmax_last
X || xwmin != xwmin_last || ywmin != ywmin_last)
X dev.attributes (SET_WINDOW, xwmin, ywmin, xwmax, ywmax);
X
X xwmin_last = xwmin;
X ywmin_last = ywmin;
X xwmax_last = xwmax;
X ywmax_last = ywmax;
X}
X
outline_window ()
X{
X if (need_devcolor == YES || cur_color != DEFAULT_COLOR)
X {
X dev.attributes (SET_COLOR, DEFAULT_COLOR, 0, 0, 0);
X need_devcolor = NO;
X }
X dev.vector (xwmin, ywmin, xwmax, ywmin, 0, 0);
X dev.vector (xwmax, ywmin, xwmax, ywmax, 0, 0);
X dev.vector (xwmax, ywmax, xwmin, ywmax, 0, 0);
X dev.vector (xwmin, ywmax, xwmin, ywmin, 0, 0);
X if (cur_color != DEFAULT_COLOR)
X {
X dev.attributes (SET_COLOR, cur_color, 0, 0, 0);
X need_devcolor = NO;
X }
X}
X
getvpstring ()
X{
char *txptr;
int ii;
X
X txptr = txbuffer;
X
X while (1)
X {
X ii = getc (pltin);
X
X if (ii == EOF)
X {
X ERR (FATAL, name,
X "Unexpected EOF encountered in Text string");
X }
X
X *txptr = ii;
X txptr++;
X
X if (ii == 0)
X {
X break;
X }
X
X if ((txptr - txbuffer) == txbuflen)
X {
X txbuffer = realloc (txbuffer, (unsigned) (txbuflen + TXBUFLEN));
X txptr = txbuffer + txbuflen;
X txbuflen += TXBUFLEN;
X }
X }
X return;
X}
X
drawpolygon (npts, x, y)
X int npts, *x, *y;
X{
int i, j;
struct vertex *vertex;
static int point;
X
X j = 0;
X if (npts > (vxbuflen - 1))
X {
X free ((char *) vxbuffer);
X vxbuffer =
X (struct vertex *) malloc ((unsigned) ((npts + 1) * sizeof (struct vertex)));
X }
X vertex = vxbuffer;
X xnew = x[j];
X ynew = y[j];
X j++;
X vertex->x = xnew;
X vertex->y = ynew;
X vertex->next = vertex + 1;
X vertex++;
X i = npts - 1;
X while (i--)
X {
X vertex->x = x[j];
X vertex->y = y[j];
X j++;
X if ((vertex->x != xnew) || (vertex->y != ynew))
X {
X xnew = vertex->x;
X ynew = vertex->y;
X vertex->next = vertex + 1;
X vertex->last = vertex - 1;
X vertex++;
X continue;
X }
X npts--;
X }
X vertex--;
X vxbuffer->last = vertex;
X vertex->next = vxbuffer;
X
X ipat = 0;
X point = cur_color;
X pat[ipat] .patbits = &point;
X pat[ipat] .xdim = 1;
X pat[ipat] .ydim = 1;
X pat[ipat] .xdim_orig = 1;
X pat[ipat] .ydim_orig = 1;
X update_color ();
X if (npts > 2)
X {
X if (shade)
X dev.area (npts, vxbuffer);
X else
X vecoutline (vxbuffer);
X }
X}
X
getpolygon (npts)
X int npts;
X{
int i;
struct vertex *vertex;
X
X if (npts > (vxbuflen - 1))
X {
X free ((char *) vxbuffer);
X vxbuffer =
X (struct vertex *) malloc ((unsigned) ((npts + 1) * sizeof (struct vertex)));
X }
X vertex = vxbuffer;
X GETXY (xnew, ynew);
X vertex->x = xnew;
X vertex->y = ynew;
X vertex->next = vertex + 1;
X vertex++;
X i = npts - 1;
X while (i--)
X {
X GETXY (vertex->x, vertex->y);
X if ((vertex->x != xnew) || (vertex->y != ynew))
X {
X xnew = vertex->x;
X ynew = vertex->y;
X vertex->next = vertex + 1;
X vertex->last = vertex - 1;
X vertex++;
X continue;
X }
X npts--;
X }
X vertex--;
X vxbuffer->last = vertex;
X vertex->next = vxbuffer;
X return (npts);
X}
X
update_color ()
X{
X if (need_devcolor)
X {
X dev.attributes (SET_COLOR, cur_color, 0, 0, 0);
X need_devcolor = NO;
X }
X}
X
getapoint ()
X{
X while (1)
X {
X xret = dev_xmax + 1;
X yret = dev_ymax + 1;
X if ((int) dev.getpoint (controltty, &xret, &yret) ||
X (xret > dev_xmax - 5 && yret > dev_ymax - 5))
X break;
X devtovpxy (xret, yret, &xret, &yret);
X add_a_cor (interact, xret, yret);
X }
X}
END_OF_FILE
if test 51559 -ne `wc -c <'Vplot_Kernel/filters/dovplot.c'`; then
echo shar: \"'Vplot_Kernel/filters/dovplot.c'\" unpacked with wrong size!
fi
# end of 'Vplot_Kernel/filters/dovplot.c'
fi
echo shar: End of archive 24 \(of 24\).
cp /dev/null ark24isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 24 archives.
rm -f ark[1-9]isdone ark[1-9][0-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 at uunet.uu.net.
More information about the Comp.sources.unix
mailing list