home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
progm
/
pcgraphc.zip
/
GRAPHX.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-26
|
46KB
|
1,540 lines
/* graphics library for the C language:
This set of routines is designed to replicate the Hewlett-Packard
9845 BASIC graphics routine. The current implimentation uses naming
conventions from the HP9845 series computers (i.e., LOCATE and SCALE),
but incorporates some of the features of HP Technical BASIC 5.0 (such as
PIVOT, RMOVE, RPLOT, RDRAW). This is not a complete implimentation, as
several functions (such as CURSOR, DIGITIZE, POINTER, PLOTTER IS, AXES,
LINETYPE, and GRID are either not completely implimented for hardware
reasons, or are not implimented at all. */
/*
Copyright 1988, Lantern Systems
*/
/* to start debugging, enter this line: #define debug 1 */
/* headers and definitions for this code */
#include "gr_lib.h"
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <dos.h>
#define MAX(x,y) (((x) < (y)) ? (y) : (x))
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#define isprint(x) ((*char_$_p[x]) == -1) ? 0 : 1
union REGS regs; /* register definitions for DOS interrupts */
static char copyright[] = "copyright 1988, Lantern Systems";
extern int *char_$_v[];
extern char *char_$_p[];
static int xpos, ypos, max_x_dot, max_y_dot, clp[4][2], locat[4],
units, clip_type, clip_store, pivot_x, pivot_y;
int degree, pendown;
static int x_inc, y_inc, l_org, l_type, rpos_x, rpos_y;
static unsigned char video_mode;
double X_mm, Y_mm;
static double tilt, a_ratio, c_size, l_cos, l_sin, x_gdu, y_gdu,
p_cos, p_sin, x_factor, y_factor, x_offset, y_offset, ratio_,
c_scale, ar_scale, def_csize, pivot_sin, pivot_cos;
static double gdu_limit_mms, x_ppm, y_ppm, limit_xmin, limit_ymin;
static double pix_p_gdu_x, pix_p_gdu_y, gdu_inc, l_rpt;
static double l_1[] = { 0 }; /* solid line */
static int l_1p[] = { 0 };
static double l_2[] = { 0 }; /* dot at end points, only */
static int l_2p[] = { 0 };
static double l_3[] = { 0, 0, 5.0 }; /* dot every 5 gdu's */
static int l_3p[] = { 1, -1, 0 };
static double l_4[] = { 0, 0, 2 }; /* dot every 2 gdu's */
static int l_4p[] = { 1, -1, 0 };
static double l_5[] = { 3, 5 };
static int l_5p[] = { 1, 0 }; /* 3 gdu dash, 2 gdu space */
static double l_6[] = { 3.4, 4.1, 4.3, 5 };
static int l_6p[] = { 1, 0, 1, 0 }; /* 3.4 gdu dash, .7 gdu space, .2 gdu dash, .7 gdu space */
static double l_7[] = { 2.9, 3.6, 4.3, 5 };
static int l_7p[] = { 1, 0, 1, 0 }; /* 2.9 gdu dash, .7 gdu space, .7 gdu dash, .7 gdu space */
static double l_8[] = { 0.5, 1.0, 1.5, 2, 4.5, 5.0 };
static int l_8p[] = { 1, 0, 1, 0, 1, 0 };
static double l_9[] = { 5 }; /* solid w/ 1 gdu tick at end of segment */
static int l_9p[] = { 1 };
static double l_10[] = { 5 }; /* solid w/ 2 gdu tick at end of segment */
static int l_10p[] = { 1 };
static double *line_types[] = { l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8,
l_9, l_10 };
static int *line_penc[] = { l_1p, l_2p, l_3p, l_4p, l_5p, l_6p, l_7p, l_8p,
l_9p, l_10p };
static int line_pat[] = { 0, 0, 3, 3, 2, 4, 4, 6, 1, 1 };
static int pat_ptr, pix_cnt, pen_c[10], pen_px[10], pen_py[10], pat_length;
static int pix_max, pen_stat, Pen;
va_list arg_ptr;
/*__________________________________________________*/
/* variable usage:
pendown: Used to record the current pen status (up or down). 1 => pen is down
xpos, ypos: Current x & y position on screen (pixel coordinates)
max_x_dot, max_y_dot: maximum pixel position for selected video mode
locat[0]: xmin \
locat[1]: xmax | define a viewport within the hardclip limits (in mm's)
locat[2]: ymin |
locat[3]: ymax /
Ordinarily, the locate size would be kept in pixels. However, because of
the unequal pixel density in the x- and y-directions of the PC screens, it
is necessary to keep the locate area size in mm's so that the aspect ratio
of the viewing area is preserved and isotropic scaling (show) functions
correctly.
clp[0][0]: xmin \
clp[1][0]: xmax | define the hard clip boundary (in pixel coordinates).
clp[2][0]: ymin | default is the physical screen size in pixels.
clp[3][0]: ymax /
clp[0][1]: xmin \
clp[1][1]: xmax | define the soft clip boundary (in pixel coordinates).
clp[2][1]: ymin | default is the locate viewport size in pixels whenever
clp[3][1]: ymax / locate () is issued. Same as hard clip at g_init ().
degree: select degree or radian mode. degree = 1 => degree mode.
Pen: Select the pen # (various colors on a color crt or plotter)
x_inc, y_inc: x & y basic sizes of stroke characters (in gdu's)
l_org: label origin (0 - 9)
l_type: line type (1 - 10)
l_rpt: repeat length (in gdu's) for non-solid line patterns
rpos_x, rpos_y: reference x, y position (in pixel coordinates) for relative
motion plotting, moving, and drawing.
X_mm, Y_mm: CRT plotting area in mm. User must set these in gpr.h for his
particular screen size.
tilt: tan(tilt) used to tilt stroke characters (in current angle units)
a_ratio: aspect ratio of label characters.
c_size: scale factor for label char's.
l_cos, l_sin: cosine and sine of label direction (for rotation of labels)
p_cos, p_sin: cosine and sine of plotting direction (for relative and
incremental motion)
x_factor, y_factor: scale factors for x-axis and y-axis plotting (in
pixels/user_unit). Set by scale (), show (), and mscale ().
x_offset, y_offset: x-value and y-value for left edge and bottom edge,
respectively, of locate viewport. Set by scale (), show (), and
mscale ().
ratio_: aspect ratio of hardclip area (pixels/pixel)
c_scale: scale factor for external csize () to internal c_size.
ar_scale: scale factor for external char aspect ratio to internal
character a_ratio.
def_csize: default c_size if externally specified value is 0.
clip_type: current clipping limits (0 = hardclip, 1 = softclip)
clip_store: storage for current clipping type (used when drawing
characters which only obey the hardclip limits)
x_ppm, y_ppm: # pixels/mm of the selected screen mode
gdu_limit_mms: # mm's along the longest axis of the limit area
limit_xmin, limit_ymin: the lower left corner coordinates of the limit
area in mm's. This location is required in order to calculate
the locat[] coordinates in mm's from the user supplied input
which is in gdu's
*/
/*__________________________________________________*/
void labelf (fmt) char *fmt;
{
/* this routine accepts strings and formatted output for labeling. It
controls centering and positioning of the string exactly as does the
HP labeling software on the 9845 and series 200 and 300 computers.
Due to the embedding of control characters (i.e., <cr><lf> pairs in
the text, labelf() will have to scan for and capture them to get the
correct string length for centering and justifying.
tan(slant), aspect ratio, character size, cos(label_dir), sin(label_dir),
x_pos, y_pos mark the starting point for the string
x_inc, y_inc are the x-step between characters and the
y-step between lines. They are scaled by c_size and a_ratio.
labelf() and draw_c() routines.
labelf() functions exactly as printf except for drawing onto the graphics
screen with graphic characters.
draw_c() is the routine which calls drawline() and actually draws the
graphic characters.
draw_c() calls drawline(); drawline() calls putdot(). */
int save_clip, p_char, t_char, xp, yp;
char *start, *idx, pr_str[512], cur_char;
save_clip = clip_type; /* save current clipping type */
clip_type = 0; /* turn off soft clipping */
va_start (arg_ptr, fmt);
t_char = vsprintf ( pr_str, fmt, arg_ptr ); /* print to string */
if ((t_char > 512) || (t_char < 0)) /* check for overflow or error */
{
fprintf (stderr,"?(label) - string length violation\n");
exit(1);
}
va_end (arg_ptr);
#ifdef debug
printf ("(labelf): pr_str = %s\n", pr_str);
#endif
start = idx = pr_str; /* initialize string pointers */
t_char = p_char = 0; /* t_char = total # chars, p_char = # printing chars */
xp = xpos; /* save starting position for after a <cr> if any */
yp = ypos;
pendown = 1; /* drop pen to draw */
while ((cur_char = *idx) != '\0') /* scan string for <cr>'s */
{
++t_char;
if (isprint (cur_char)) ++p_char;
++idx; /* point to next char */
if (cur_char == '\n')
{
#ifdef debug
printf ("(labelf): # char = %d, # printing chars = %d\n", t_char, p_char);
#endif
write_char (start, t_char, p_char); /* label substring */
start = idx; /* skip '\n' for next line (if any) */
p_char = 0; /* reset printing char count */
t_char = 0; /* reset total # of chars in substring */
/* return to start of label */
xpos = xp += (int) ((double) y_inc * c_size * x_gdu * l_sin * x_ppm);
ypos = yp -= (int) ((double) y_inc * c_size * x_gdu * l_cos * y_ppm);
/* new pen position after \n with l_dir rotation */
}
}
/* catch strings which don't end with a <cr> */
if (p_char > 0) write_char (start, t_char, p_char);
clip_type = save_clip; /* resume previous clipping after labeling */
pendown = 0; /* lift pen at end of label */
return;
}
/*____________________________________________________*/
/* routine for labeling strings */
void write_char (start, t_char, p_char) char *start; int t_char, p_char;
{
int i;
double l_str;
l_str = p_char * ((double) (x_inc) * x_gdu * c_size * a_ratio);
/* length of char string in pixels */
/* left justified requires no action */
if ((l_org < 7) && (l_org > 3))
{
xpos = xpos - (int) (l_str * x_ppm * l_cos / 2); /* centered */
ypos = ypos - (int) (l_str * y_ppm * l_sin / 2);
}
else if (l_org>=7)
{
xpos = xpos - (int) (l_str * x_ppm * l_cos); /* right justified */
ypos = ypos - (int) (l_str * y_ppm * l_sin);
}
switch ( l_org )
{
case 0:
case 1:
case 4:
case 7:break; /* bottom justified */
case 2:
case 5:
case 8: ypos = ypos - (int) ((double)(y_inc) * c_size * y_gdu * y_ppm * l_cos / 2); /* centered */
xpos = xpos + (int) ((double)(y_inc) * c_size * x_gdu * x_ppm * l_sin / 2);
break;
case 3:
case 6:
case 9: ypos = ypos - (int) ((double)(y_inc) * c_size * y_gdu * y_ppm * l_cos); /* top justified */
xpos = xpos + (int) ((double)(y_inc) * c_size * y_gdu * x_ppm * l_sin);
default:break;
}
for (i = 0; i < t_char; ++i)
{
if (isprint (*start)) draw_c (*start);
++start;
}
return;
}
/*____________________________________________________*/
void draw_c (c) char c;
{
/* graphics_tbl[] is a table of pointers the the (x,y) pairs which
make up the characters. pen_tbl[] is a table of pointer to the
pen control character. 0xff is the end of the table for a particular
character. */
/* xpos,ypos are screen pixel coordinates (integer). */
int *start_char, x1, y1, x3, y3, x4, y4;
double x2, y2, ival_x, ival_y;
char pen_c, *start_pen;
double x_f, y_f;
#ifdef debug
printf ("(draw_c):char code: %xh, char = %c\n",c,c);
#endif
start_char = char_$_v[c]; /* pointer to first (x,y) (in pixels) */
start_pen = char_$_p[c]; /* pointer to first pen control */
x_f = c_size * a_ratio * gdu_limit_mms / 100; /* units are mm's/gdu */
y_f = c_size * gdu_limit_mms / 100;
/* # mm's / gdu:100 gdu's = y-size of limit area */
/* (x,y) are origin of character */
x3 = xpos;
y3 = ypos; /* all characters start at relative origin (0,0) */
do
{
/* rotate starting coordinates to ldir() angle */
x1 = x3;
y1 = y3; /* start (x,y) for line */
#ifdef debug
printf ("(draw_c): x1 = %d y1 = %d\n", x1, y1);
#endif
pen_c = *(start_pen++);
/* scale size of char and aspect ratio to gdu's */
/* the order of these statements is important!!! */
x2 = ((double) (*(start_char ++))) * x_f;
#ifdef debug
printf ("(draw_c): char_y_pos = %d\n", *start_char);
#endif
y2 = ((double) (*(start_char++))) * y_f;
x2 = x2 + y2 * tilt; /* add tilt to characters */
/* stop (x,y) for character after rotation: scale for different
X and Y pixel densities */
ival_x = (x2 * l_cos - y2 * l_sin) * x_ppm;
ival_y = (y2 * l_cos + x2 * l_sin) * y_ppm;
/* rotation of coordinates for ldir() */
x4 = (ival_x > 0) ? (int) (ival_x + 0.5) : (int) (ival_x -0.5);
y4 = (ival_y > 0) ? (int) (ival_y + 0.5) : (int) (ival_y -0.5);
x3 = x4 + xpos;
y3 = y4 + ypos;
#ifdef debug
printf ("(draw_c): x3: %d, y3: %d\n", x3, y3 );
#endif
if ((pen_c & 1) != 0) drawline ( x1, y1, x3, y3 );
}
while (pen_c >= 0);
/* calculate new pen position based upon c_size, a_ratio, and ldir */
/* new position for lateral x-motion only */
xpos = xpos + (int) ((double) (x_inc) * a_ratio * l_cos * y_f * x_ppm);
ypos = ypos + (int) ((double) (x_inc) * a_ratio * l_sin * y_f * y_ppm);
return;
}
/*---------------------------------------------------*/
void csize (height, a_r, slant) double height, a_r, slant;
{
/* csize (size (default = 4), aspect ratio (default = 0.6), slant (default = 0)) */
a_ratio = ((a_r != 0.0) ? fabs (a_r * ar_scale) : 0.6 * ar_scale );
tilt = tan ( ((degree != 0) ? slant / 57.2958 : slant) );
c_size = ((height != 0) ? fabs (height / c_scale) : def_csize );
/* units are GDU's: default is 4.0 c_scale changes the height
to reflect higher res screens. */
return;
}
/*---------------------------------------------------*/
void lorg (x) int x;
{
/* select label origin (0 - 9) */
l_org = MAX (MIN(9,abs(x)), 1);
return;
}
/*---------------------------------------------------*/
double ratio()
{
/* get hardclip aspect ratio */
return ((double) (clp[1][0] - clp[0][0]) / (double) (clp[3][0] - clp[2][0]));
}
/*---------------------------------------------------*/
void ldir (angle) double angle;
{
if (degree == 1) angle = angle / 57.2958; /* convert to radians */
l_cos = cos (angle);
l_sin = sin (angle); /* rotation of labels */
return;
}
/*---------------------------------------------------*/
void line_type (type, repeat) int type; double repeat;
{
/* line_type (type, repeat (default = 5 GDU's)) */
int i;
l_type = MIN (MAX (abs (type), 1),10);
l_rpt = MAX ( (fabs ( repeat ) / 5),1);
pat_ptr = 0; /* reset pattern pointer */
pix_cnt = 0; /* reset pixel counter */
pen_c[0] = 1; /* pen control for zero length patterns */
pen_px[0] = 32767; /* make pattern length arbritrarily long for solid lines */
pen_py[0] = 32767;
pat_length = line_pat [ l_type -1 ];
#ifdef debug
printf ("(line_type): pat_length = %d\n",pat_length);
#endif
for (i = 0; i < pat_length; ++i)
{
switch ( line_penc[ l_type - 1 ][i])
{
case -1: /* dot at pattern count */
pen_c[i] = 1; /* pen down */
pen_px[i] = pen_px[i - 1] + 1;
pen_py[i] = pen_py[i - 1] + 1;
break;
case 0: /* pen up */
pen_c[i] = 0;
pen_px[i] = (int) line_types[ l_type - 1][ i ] * x_gdu * x_ppm * l_rpt;
pen_py[i] = (int) line_types[ l_type - 1][ i ] * x_gdu * y_ppm * l_rpt;
break;
case 1: /* pen down */
pen_c[i] = 1;
pen_px[i] = (int) line_types[ l_type - 1][ i ] * x_gdu * x_ppm * l_rpt;
pen_py[i] = (int) line_types[ l_type - 1][ i ] * x_gdu * y_ppm * l_rpt;
break;
}
#ifdef debug
printf ("(line_type): line_penc[ l_type - 1 ][i] = %d\n", line_penc[l_type - 1][i]);
printf ("(line_type): i = %d, pen_c[i] = %d, pen_py[i] = %d\n",i, pen_c[i], pen_py[i]);
#endif
}
return;
}
/*---------------------------------------------------*/
void pen (p) int p;
{
Pen = p;
return;
}
/*---------------------------------------------------*/
void penup ()
{
pendown = 0; /* mark pen as up */
return;
}
/*---------------------------------------------------*/
void deg ()
{
degree = 1;
return;
}
/*---------------------------------------------------*/
void rad ()
{
degree = 0;
return;
}
/*---------------------------------------------------*/
/* only graphics_off () is implimented. Switching from alpha to graphics
screens clears the graphics screen */
void graphics_off ()
{
regs.h.ah = SET_MODE;
regs.h.al = video_mode; /* return to original video mode */
int86 (VIDEO, ®s, ®s);
}
/*---------------------------------------------------*/
void g_init (mode) int mode;
{
/* select graphics mode for drawing.
modes are
1: 320x200 CGA 4 color; 2: 640x200 CGA 2 color; 3: 640x400 AT&T 2 color;
4: 320x200 EGA 16 color; 5: 640x200 EGA 16 color;
6: 640x350 EGA 16 color; 7: 640x480 VGA 16 color;
8: 320x200 VGS 256 color */
clp[0][0] = 0; /* set hard clip lower limits */
clp[2][0] = 0; /* to the same boundary */
def_csize = c_size = 0.5; /* scale & size char's for */
c_scale = 8.0; /* Initial internal c_size. Default external csize = 4 */
a_ratio = 1.0; /* initial internal aspect ratio for characters is 1.0 */
ar_scale = 1.666; /* aspect ratio scaling for char's */
regs.h.ah = VIDEO_STATE; /* Read current video mode */
int86 (VIDEO, ®s, ®s);
video_mode = regs.h.al; /* current video mode */
switch (mode)
{
case 1:
clp[1][0] = 319; /* low res screen */
clp[3][0] = 199;
regs.h.ah = SET_MODE;
regs.h.al = CGA_MED;
int86 (VIDEO, ®s, ®s);
break;
case 2:
clp[1][0] = 639; /* med res screen */
clp[3][0] = 199;
regs.h.ah = SET_MODE;
regs.h.al = CGA_HIGH;
int86 (VIDEO, ®s, ®s);
break;
case 3:
clp[1][0] = 639; /* high res screen */
clp[3][0] = 399;
regs.h.ah = SET_MODE;
regs.h.al = ATT_HIRES;
int86 (VIDEO, ®s, ®s);
/* mode 72 also available (tiny text) */
break;
case 4:
clp[1][0] = 319; /* 16 color EGA screen */
clp[3][0] = 199;
regs.h.ah = SET_MODE;
regs.h.al = EGA_LORES;
int86 (VIDEO, ®s, ®s);
break;
case 5:
clp[1][0] = 639; /* 16 color EGA screen */
clp[3][0] = 199;
regs.h.ah = SET_MODE;
regs.h.al = EGA_MEDRES;
int86 (VIDEO, ®s, ®s);
break;
case 6:
clp[1][0] = 639; /* 16 color EGA screen */
clp[3][0] = 349;
regs.h.ah = SET_MODE;
regs.h.al = EGA_HIRES;
int86 (VIDEO, ®s, ®s);
break;
case 7:
clp[1][0] = 639; /* 16 color VGA screen */
clp[3][0] = 479;
regs.h.ah = SET_MODE;
regs.h.al = VGA_HIRES;
int86 (VIDEO, ®s, ®s);
break;
case 8:
clp[1][0] = 319; /* 256 color VGA screen */
clp[3][0] = 199;
regs.h.ah = SET_MODE;
regs.h.al = VGA_LORES;
int86 (VIDEO, ®s, ®s);
break;
default:
printf ("\nIllegal graphics mode\n");
exit(1);
}
deg (); /* set mode to degrees */
clip_store = 0; /* set clipping save buffer to hard clipping */
clip_type = 0; /* hard clipping on */
units = 0; /* select GDU's */
x_inc = 9; /* basic char. x-size is 9 gdu's */
y_inc = 15; /* basic char. y-size is 15 gdu's */
l_org = 1; /* label origin is 1 */
line_type (1,0);/* set initial line type to 1 */
l_cos = 1.0; /* label direction rotation */
l_sin = 0;
tilt = 0.0; /* tilt of characters */
rpos_x = xpos = 0; /* initial x,y position on screen */
rpos_y = ypos = 0; /* (in pixels) */
p_cos = 1.0; /* plotting direction rotation */
p_sin = 0.0;
Pen = 1; /* select pen #1 as the default pen. */
pendown = 0; /* mark pen as up */
limit_xmin = 0;
limit_ymin = 0; /* hardclip limit lower left corner (in pixels) */
/* set soft clip limits to hard clip limits and default locate limits
to hard clip limits. Adjust max_dot to reflect current mode.
max_x_dot and max_y_dot are max screen size in pixels. */
locat[0] = limit_xmin;
locat[2] = limit_ymin;
locat[1] = X_mm;
locat[3] = Y_mm; /* set locate limits to screen limits */
clp[0][1] = clp[0][0];
max_x_dot = clp[1][1] = clp[1][0];
clp[2][1] = clp[2][0];
max_y_dot = clp[3][1] = clp[3][0];
x_ppm = max_x_dot / X_mm;
y_ppm = max_y_dot / Y_mm; /* pixels / mm */
ratio_ = X_mm / Y_mm;
if (ratio_ >= 1.0) /* y gdu's = 100 */
gdu_limit_mms = Y_mm;
else /* x gdu's = 100 */
gdu_limit_mms = X_mm;
/* set the startup x_gdu and y_gdu values. These change when the hard
clip limits are changed. Normally, the screen aspect ratio is defined
as (max_x - min_x) / (max_y - min_y). */
x_gdu = y_gdu = gdu_limit_mms / 100; /* mm's / gdu */
x_factor = x_gdu * x_ppm;
y_factor = y_gdu * y_ppm; /* default scaling (needed by clip() */
x_offset = y_offset = 0; /* mscale, scale, and show change these */
#ifdef debug
printf ("x_gdu = %lf, y_gdu = %lf\nx_factor = %lf, x_offset = %lf\n", x_gdu, y_gdu, x_factor, x_offset );
#endif
return;
}
/*----------------------------------------------------*/
void limit (xmin, xmax, ymin, ymax) double xmin, xmax, ymin, ymax;
{
/* The limits are defined to be in mm from the origin of the plotting
device. These are hard clip limits which are used to redefine the
size of the screen. */
/* units are in mm's from the lower left corner of the crt */
if (xmin < 0 || xmax < 0 || ymin < 0 || ymax < 0)
{
fprintf (stderr, "? (limit) - parameter out of range.");
exit (1);
}
locat[0] = limit_xmin = xmin;
locat[1] = xmax;
locat[2] = limit_ymin = ymin; /* new lower left corner in mm's */
locat[3] = ymax;
pivot_x = locat[0];
pivot_y = locat[2];
pivot_cos = 1.0;
pivot_sin = 0.0; /* clear existing pivot (if any) */
clp[0][1] = clp[0][0] = MIN (((int) (xmin * (double) (max_x_dot) / X_mm)), max_x_dot);
clp[1][1] = clp[1][0] = MIN (((int) (xmax * (double) (max_x_dot) / X_mm)), max_x_dot);
clp[2][1] = clp[2][0] = MIN (((int) (ymin * (double) (max_y_dot) / Y_mm)), max_y_dot);
clp[3][1] = clp[3][0] = MIN (((int) (ymax * (double) (max_y_dot) / Y_mm)), max_y_dot);
/* set the screen aspect ratio for the new hard clip limits
and set the soft clip limits to the new hard clip limits */
#ifdef debug
printf ("(limit): screen size X_mm = %lf, Y_mm = %lf\n", X_mm, Y_mm);
printf ("(limit): clip (min) (X,Y) = (%d, %d), (max) (X,Y) = (%d, %d)\n", clp[0][0], clp[2][0], clp[1][0], clp[3][0] );
#endif
ratio_ = (xmax - xmin) / (ymax - ymin); /* set ratio by screen size */
if (ratio_ >= 1.0) /* y gdu's = 100 */
gdu_limit_mms = ymax - ymin;
else /* x gdu's = 100 */
gdu_limit_mms = xmax - xmin;
x_gdu = y_gdu = gdu_limit_mms / 100; /* mm's / gdu */
#ifdef debug
printf ("(limit): ratio = %lf, x_gdu = %lf mm/gdu, y_gdu = %lf mm/gdu\n", ratio_, x_gdu, y_gdu);
#endif
return;
}
/*------------------------------------------------------*/
void locate (xmin, xmax, ymin, ymax) double xmin, xmax, ymin, ymax;
{
/* units are in gdu's; locate is defined in terms of offsets from
the lower right limit coordinate. clip[][] is in screen coordinates
(pixels), and locate is in mm's. locate() sets the softclip limits
to the locate parameters when called. The locate coordinates are
kept in mm's because of the varying anisotropic pixel density of
the various screen modes of the PC */
locat[0] = limit_xmin + xmin * x_gdu;
locat[1] = limit_xmin + xmax * x_gdu;
locat[2] = limit_ymin + ymin * y_gdu;
locat[3] = limit_ymin + ymax * y_gdu; /* new locate window in mm's */
pivot_x = locat[0];
pivot_y = locat[2];
pivot_cos = 1.0;
pivot_sin = 0.0; /* clear existing pivot (if any) */
clp[0][1] = clp[0][0] + (int) (xmin * x_gdu * x_ppm); /* xmin */
clp[1][1] = clp[0][0] + (int) (xmax * x_gdu * x_ppm); /* xmax */
clp[2][1] = clp[2][0] + (int) (ymin * y_gdu * y_ppm); /* ymin */
clp[3][1] = clp[2][0] + (int) (ymax * y_gdu * y_ppm); /* ymax */
#ifdef debug
printf ("(locate): (x,y) min = (%d,%d), (x,y) max = (%d,%d)\n", locat[0], locat[2], locat[1], locat[3]);
#endif
clip_type = clip_store = 1; /* select soft clipping */
return;
}
/*------------------------------------------------------*/
/* routine to set new softclip limits using current units */
void clip (xmin, xmax, ymin, ymax) double xmin, xmax, ymin, ymax;
{
/* define softclip area within scaled locate area*/
/* (x, y) are in user units (udu's, mm's), or gdu's at g_init */
clp[0][1] = (int) ((xmin - x_offset) * x_factor + locat[0] * x_ppm);
clp[1][1] = (int) ((xmax - x_offset) * x_factor + locat[0] * x_ppm);
clp[2][1] = (int) ((ymin - y_offset) * y_factor + locat[2] * y_ppm);
clp[3][1] = (int) ((ymax - y_offset) * y_factor + locat[2] * y_ppm);
clip_type = clip_store = 1; /* select soft clipping */
return;
}
/*------------------------------------------------------*/
/* anisotropic scaling routine */
void scale (x1, x2, y1, y2) double x1, x2, y1, y2; /* coordinates are in udu's */
{
/* x_factor, y_factor are pixels/user_unit; x_offset, y_offset are in udu's */
x_factor = x_ppm * (locat[1] - locat[0])/(x2 - x1);
y_factor = y_ppm * (locat[3] - locat[2])/(y2 - y1);
x_offset = x1;
y_offset = y1; /* offset in udu's */
#ifdef debug
printf ("(scale): x_factor: %f, y_factor: %f, x_offset: %f, y_offset: %f\n", x_factor, y_factor, x_offset, y_offset);
#endif
units = 1; /* set to user units */
pivot_x = locat[0];
pivot_y = locat[2];
pivot_cos = 1.0;
pivot_sin = 0.0; /* clear existing pivot (if any) */
clip_type = clip_store = 1; /* select soft clipping */
return;
}
/*--------------------------------------------------------*/
/* isotropic scaling routine */
void show (xmin, xmax, ymin, ymax) double xmin, xmax, ymin, ymax;
{
double xf, yf;
/* calculate number of mm / user_unit */
xf = (locat[1] - locat[0]) / (xmax - xmin);
yf = (locat[3] - locat[2]) / (ymax - ymin);
/* scale window isotropically using the scale factor (xf or yf)
of the axis with the fewer mm / user_unit. Then calculate
a new offset for the remaining axis so that the specified
scale (ymax - ymin or xmax - xmin) will be centered in the new
window. */
if (xf < yf)
{
/* use xf mm / user_unit and center ymin and ymax in
the new scale. */
x_factor = xf * x_ppm;
y_factor = xf * y_ppm;
x_offset = xmin;
y_offset = (ymax + ymin - (locat[3] - locat[2]) / xf) / 2;
}
else
{
/* use yf mm / user_unit and center xmin and xmax in
the new scale. */
x_factor = yf * x_ppm;
y_factor = yf * y_ppm;
y_offset = ymin;
x_offset = (xmax + xmin - (locat[1] - locat[0]) / yf) / 2;
}
units = 1; /* set to user units */
pivot_x = locat[0];
pivot_y = locat[2];
pivot_cos = 1.0;
pivot_sin = 0.0; /* clear existing pivot (if any) */
#ifdef debug
printf ("(show): x_factor: %f, y_factor: %f, x_offset: %f, y_offset: %f\n", x_factor, y_factor, x_offset, y_offset);
#endif
clip_type = clip_store = 1; /* select soft clipping */
return;
}
/*-------------------------------------------------------------*/
/* mm scaling routine */
void mscale (x, y) double x, y;
{
/* x,y = displacement of origin (in mm's) from lower left corner of locate window */
x_factor = x_ppm; /* pixels/mm for full screen */
y_factor = y_ppm; /* invariant w/ hardclip limits */
x_offset = - x;
y_offset = - y; /* offset of mscale (0,0) in mm */
units = 1; /* set to user units */
pivot_x = locat[0];
pivot_y = locat[2];
pivot_cos = 1.0;
pivot_sin = 0.0; /* clear existing pivot (if any) */
clip_type = clip_store = 1; /* select soft clipping */
return;
}
/*-------------------------------------------------------------*/
void frame ()
{
int x1, y1, x2, y2;
/* frame the current clipping window. The soft clip limits never
exceed the hard clip limits. drawline() is called with pixel units */
pendown = 1; /* Drop pen to draw */
x1 = clp[0][clip_type]; /* draw frame around current clipping area */
x2 = clp[1][clip_type];
y1 = clp[2][clip_type];
y2 = clp[3][clip_type];
drawline (x1, y1, x1, y2);
drawline (x1, y2, x2, y2);
drawline (x2, y2, x2, y1);
drawline (x2, y1, x1, y1);
rpos_x = xpos = x1;
rpos_y = ypos = y1; /* move pen to lower left corner */
pendown = 0; /* mark pen as up */
return;
}
/*-------------------------------------------------------------*/
void pdir (angle) double angle;
{
/* set plotting direction for relative & incremental plotting,
drawing, and moving */
if (degree == 1) angle = angle / 57.2958; /* convert to radians */
p_cos = cos (angle);
p_sin = sin (angle);
#ifdef debug
printf ("(pdir): p_cos = %12.9lf, p_sin = %12.9lf\n", p_cos, p_sin);
#endif
return;
}
/*-------------------------------------------------------------*/
void move (x, y) double x, y;
{
/* direct screen move */
pendown = 0; /* mark pen as up */
if (units) /* udu's */
{
xpos = (int) ((x - x_offset) * x_factor) + locat[0] * x_ppm ;
ypos = (int) ((y - y_offset) * y_factor) + locat[2] * y_ppm;
}
else /* gdu's: (gdu's) * (mm/gdu) * (pixels/mm) + offset of hardclip origin */
{
xpos = (int) (x * x_gdu * x_ppm) + clp[0][0];
ypos = (int) (y * y_gdu * y_ppm) + clp[2][0];
}
rpos_x = xpos;
rpos_y = ypos; /* update relative plot origin coordinates */
#ifdef debug
printf ("move to (pixel) (%d,%d)\n", xpos, ypos);
#endif
return;
}
/*-----------------------------------------------------------*/
void draw (x,y) double x,y;
{
/* draw from current (x,y) to new (x.y) */
/* passed parameters may be either gdu's or udu's */
int x_1, x_2, y_1, y_2;
pendown = 1; /* mark pen as down */
if (units) /* udu's */
{
rpos_x = (int) ((x - x_offset) * x_factor) + locat[0] * x_ppm;
rpos_y = (int) ((y - y_offset) * y_factor) + locat[2] * y_ppm;
}
else /* gdu's: (gdu's) * (mm/gdu) * (pixels/mm) + offset of hardclip origin */
{
rpos_x = (int) (x * x_gdu * x_ppm) + clp[0][0];
rpos_y = (int) (y * y_gdu * y_ppm) + clp[2][0];
}
x_1 = (int)( ((double) (xpos - pivot_x)) * pivot_cos - ((double) (ypos - pivot_y)) * pivot_sin) + pivot_x;
y_1 = (int)( ((double) (ypos - pivot_y)) * pivot_cos + ((double) (xpos - pivot_x)) * pivot_sin) + pivot_y;
x_2 = (int)( ((double) (rpos_x - pivot_x)) * pivot_cos - ((double) (rpos_y - pivot_y)) * pivot_sin) + pivot_x;
y_2 = (int)( ((double) (rpos_y - pivot_y)) * pivot_cos + ((double) (rpos_x - pivot_x)) * pivot_sin) + pivot_y;
drawline ( x_1, y_1, x_2, y_2 ); /* passed coordinates are pixel locations */
#ifdef debug
printf ("draw from (pixel) (%d,%d) to (%d,%d)\n", xpos, ypos, rpos_x, rpos_y);
#endif
xpos = rpos_x;
ypos = rpos_y; /* update logical pen position */
return;
}
/*------------------------------------------------------*/
void plot (x, y, penc) double x, y; int penc;
{
/* plot from current (x,y) to new (x,y) */
switch ((( abs (penc) & 1) << 1) + (penc < 0))
{
case 0: /* even, penc >0 */
if (pendown) draw (x,y);
else move (x, y);
pendown = 0;
break;
case 1: /* even, penc < 0 */
pendown = 0;
move (x, y);
break;
case 2: /* odd, penc >= 0 */
if (pendown) draw (x, y);
else move (x, y);
pendown = 1;
break;
case 3: /* odd, penc < 0 */
draw (x, y);
pendown = 1;
default:break;
}
return; /* call to draw() updates pen position */
}
/*-------------------------------------------------------------*/
void rplot (x, y, penc) double x, y; int penc;
{
/* plot relative to (rpos_x, rpos_y) */
switch ((( abs (penc) & 1) << 1) + (penc < 0))
{
case 0: /* even, penc >0 */
if (pendown) rdraw (x,y);
else rmove (x, y);
pendown = 0;
break;
case 1: /* even, penc < 0 */
pendown = 0;
rmove (x, y);
break;
case 2: /* odd, penc >= 0 */
if (pendown) rdraw (x, y);
else rmove (x, y);
pendown = 1;
break;
case 3: /* odd, penc < 0 */
rdraw (x, y);
pendown = 1;
default:break;
}
return; /* call to rdraw() updates pen position */
}
/*-------------------------------------------------------------*/
void rdraw (x,y) double x,y;
{
/* draw relative to (rpos_x, rpos_y) */
double xp, yp;
int xpix, ypix, x_1, y_1, x_2, y_2;
pendown = 1; /* mark pen as down */
xp = x * p_cos - y * p_sin;
yp = y * p_cos + x * p_sin; /* relative rotation */
/* get pixel coordinates of (x, y) relative to (rpos_x, rpos_y) */
xpix = rpos_x + ( units ) ? ((int) (xp * x_factor)): ((int) (xp * x_gdu * x_ppm));
ypix = rpos_y + ( units ) ? ((int) (yp * y_factor)): ((int) (yp * y_gdu * y_ppm));
x_1 = (int)( ((double) (xpos - pivot_x)) * pivot_cos - ((double) (ypos - pivot_y)) * pivot_sin) + pivot_x;
y_1 = (int)( ((double) (ypos - pivot_y)) * pivot_cos + ((double) (xpos - pivot_x)) * pivot_sin) + pivot_y;
x_2 = (int)( ((double) (xpix - pivot_x)) * pivot_cos - ((double) (ypix - pivot_y)) * pivot_sin) + pivot_x;
y_2 = (int)( ((double) (ypix - pivot_y)) * pivot_cos + ((double) (xpix - pivot_x)) * pivot_sin) + pivot_y;
drawline (x_1, y_1, x_2, y_2); /* draw line */
#ifdef debug
printf ("rdraw from (pixel) (%d,%d) to (%d,%d)\n", xpos, ypos, xpix, ypix);
#endif
xpos = xpix;
ypos = ypix; /* update pen position */
return;
}
/*-------------------------------------------------------------*/
void rmove (x, y) double x, y;
{
/* move relative to rpos_x, rpos_y */
double xp, yp;
xp = x * p_cos - y * p_sin;
yp = y * p_cos + x * p_sin; /* relative rotation */
if (units) /* udu's */
{
xpos = rpos_x + (int) ( xp * x_factor);
ypos = rpos_y + (int) ( yp * y_factor);
}
else /* gdu's * */
{
xpos = rpos_x + (int) (xp * x_gdu * x_ppm);
ypos = rpos_y + (int) (yp * y_gdu * y_ppm);
}
#ifdef debug
printf ("rmove to (pixel) (%d,%d)\n", xpos, ypos);
#endif
return;
}
/*-------------------------------------------------------------*/
void iplot (x, y, penc) double x, y; int penc;
{
/* plot incrementally to (x, y) */
switch ((( abs (penc) & 1) << 1) + (penc < 0))
{
case 0: /* even, penc >0 */
if (pendown) idraw (x,y);
else imove (x, y);
pendown = 0;
break;
case 1: /* even, penc < 0 */
pendown = 0;
imove (x, y);
break;
case 2: /* odd, penc >= 0 */
if (pendown) idraw (x, y);
else imove (x, y);
pendown = 1;
break;
case 3: /* odd, penc < 0 */
idraw (x, y);
pendown = 1;
default:break;
}
return; /* call to idraw() updates pen position */
}
/*-------------------------------------------------------------*/
void idraw (x, y) double x, y;
{
/* incremental draw from (x,y) to (x + x',y + y') */
int x_1, x_2, y_1, y_2;
double xp, yp;
#ifdef debug
printf ("(idraw): x = %12.9lf, y = %12.9lf\n", x, y);
#endif
pendown = 1;
xp = x * p_cos - y * p_sin;
yp = y * p_cos + x * p_sin; /* rotate coordinates to p_dir() */
if (units) /* udu's */
{
rpos_x = xpos + (int) (xp * x_factor);
rpos_y = ypos + (int) (yp * y_factor);
}
else
{
rpos_x = xpos + (int) (xp * x_gdu * x_ppm);
rpos_y = ypos + (int) (yp * y_gdu * y_ppm);
}
#ifdef debug
printf ("(idraw): rpos_x = %d, rpos_y = %d\n", rpos_x, rpos_y);
#endif
x_1 = (int)( ((double) (xpos - pivot_x)) * pivot_cos - ((double) (ypos - pivot_y)) * pivot_sin) + pivot_x;
y_1 = (int)( ((double) (ypos - pivot_y)) * pivot_cos + ((double) (xpos - pivot_x)) * pivot_sin) + pivot_y;
x_2 = (int)( ((double) (rpos_x - pivot_x)) * pivot_cos - ((double) (rpos_y - pivot_y)) * pivot_sin) + pivot_x;
y_2 = (int)( ((double) (rpos_y - pivot_y)) * pivot_cos + ((double) (rpos_x - pivot_x)) * pivot_sin) + pivot_y;
drawline (xpos, ypos, rpos_x, rpos_y);
xpos = rpos_x;
ypos = rpos_y; /* update relative pen position */
return;
}
/*-------------------------------------------------------------*/
void imove (x, y) double x, y;
{
/* move incrementally to x, y */
double xp, yp;
xp = x * p_cos - y * p_sin;
yp = y * p_cos + x * p_sin; /* rotate coordinates to p_dir() */
if (units) /* udu's */
{
rpos_x = xpos = xpos + (int) ( xp * x_factor);
rpos_y = ypos = ypos + (int) ( yp * y_factor);
}
else /* gdu's: (gdu's) * (mm/gdu) * (pixels/mm) + offset of hardclip origin */
{
rpos_x = xpos = xpos + (int) (x * x_gdu * x_ppm) + clp[0][0];
rpos_y = ypos = ypos + (int) (y * y_gdu * y_ppm) + clp[2][0];
}
return;
}
/*-------------------------------------------------------------*/
void setgu ()
{
/* select graphics units for display */
units = 0;
clip_store = clip_type; /* save last clipping type */
clip_type = 0; /* use hardclip limits for gdu's */
return;
}
/*-------------------------------------------------------------*/
void setuu ()
{
/* select user units for display */
units = 1;
clip_type = clip_store; /* retrieve last clipping type (if any) */
return;
}
/*-------------------------------------------------------------*/
void unclip ()
{
clip_store = clip_type = 0; /* set clip window to the hard clip limits */
return;
}
/*-------------------------------------------------------------*/
void pivot (angle) double angle;
{
if (degree) angle /= 57.2958;
pivot_cos = cos (angle);
pivot_sin = sin (angle);
pivot_x = xpos;
pivot_y = ypos;
#ifdef debug
printf ("pivot_x = %d, pivot_y = %d\n", pivot_x, pivot_y);
printf ("pivot_cos = %12.9lf, pivot_sin = %12.9lf\n", pivot_cos, pivot_sin);
#endif
return;
}
/*-------------------------------------------------------------*/
/* drawline -- a graphics function
calling:
void drawline (x1, y1, x2, y2) int x1, y1, x2, y2;
draws a line from (x1,y1) to (x2,y2) using Bresenham's algorithm. The
line is drawn using the pen chosen unless no pen is chosen. The previous
pen is then used. Pen 0 is no pen, and pen < 0 undraws a line.
The cartesian coordinate system is divided into 8 sectors.
^y
\ 3 | 2 /
4 \ | / 1
_______\|/_________ x
/|\
5 / | \ 8
/ 6 | 7 \
v
This division is necessary because Bresenham's algorithm works only for slopes
up to 1. Above 1, it is necessary to change to the next octant. The same is
true for slopes below -1. */
static void drawline (x1, y1, x2, y2) int x1, y1, x2, y2;
{
/* passed parameters are screen pixel coordinates */
int x_inc, y_inc, dx, dy, dir, err, ct, i, tick;
if ( (Pen == 0) || (pendown == 0) ) return;
/* no point in drawing with no pen or pen up */
err = 0;
ct = clip_type;
#ifdef debug
printf ("drawline from (pixel) (%d,%d) to (%d,%d)\n", x1, y1, x2, y2);
#endif
if (l_type == 2) /* dot only at endpoint */
{
putdot (x2, y2);
return;
}
dx = abs (x2 - x1);
dy = abs (y2 - y1);
x_inc = 2 * dx;
y_inc = 2 * dy;
if (dy > dx) /* |slope| >1 */
{
tick = (int) (x_gdu * x_ppm / 2 + 0.5);
if (l_type == 10) tick = (int) (x_gdu * x_ppm + 0.5);
pix_max = pen_py[pat_ptr];
pen_stat = pen_c[pat_ptr];
dir = (x2 > x1) ? 1: -1; /* set direction to draw */
if (y2 >= y1) /* sector 2,3 */
{
while (y1 <= y2) /* draw vector */
{ /* test clip limits */
if ( (!(x1 < clp[0][ct] || x1 > clp[1][ct]
|| y1 < clp[2][ct] || y1 > clp[3][ct])) &&
(pen_stat > 0) ) putdot (x1, y1);
++pix_cnt;
++y1; /* next y-incr */
err = err + x_inc;
if (err >= dy) /* control x-increments */
{
err = err - y_inc;
x1 = x1 + dir;
++pix_cnt;
}
if (pix_cnt >= pix_max )
{
++pat_ptr;
if (pat_ptr >= pat_length)
{
pat_ptr = 0;
pix_cnt = 0;
}
if ( (l_type == 9) || (l_type == 10) )
{
for (i = -tick; i <= tick; ++i)
if (!(x1 + i < clp[0][ct] || x1 + i > clp[1][ct]
|| y1 < clp[2][ct] || y1 > clp[3][ct]))
putdot ( x1 + i , y1);
}
pix_max = pen_py[pat_ptr];
pen_stat = pen_c[pat_ptr];
#ifdef debug
printf ("(draw_line): pat_ptr = %d\n", pat_ptr);
printf ("(draw_line): pix_max = %d, pen_stat = %d\n", pix_max, pen_stat);
#endif
}
}
}
else /* sector 6,7 */
{
while (y2 <= y1) /* draw vector */
{ /* test clip limits */
if ( (!(x1 < clp[0][ct] || x1 > clp[1][ct]
|| y1 < clp[2][ct] || y1 > clp[3][ct])) &&
(pen_stat > 0) ) putdot (x1, y1);
--y1; /* next y-incr */
++pix_cnt;
err = err + x_inc;
if ( err >= dy) /* control x-increments */
{
err = err - y_inc;
x1 = x1 + dir;
++pix_cnt;
}
if (pix_cnt >= pix_max )
{
++pat_ptr;
if (pat_ptr >= pat_length)
{
pat_ptr = 0;
pix_cnt = 0;
}
if ( (l_type == 9) || (l_type == 10) )
{
for (i = -tick; i <= tick; ++i)
if (!(x1 + i < clp[0][ct] || x1 + i > clp[1][ct]
|| y1 < clp[2][ct] || y1 > clp[3][ct]))
putdot ( x1 + i , y1);
}
pix_max = pen_py[pat_ptr];
pen_stat = pen_c[pat_ptr];
#ifdef debug
printf ("(draw_line): pat_ptr = %d\n", pat_ptr);
printf ("(draw_line): pix_max = %d, pen_stat = %d\n", pix_max, pen_stat);
#endif
}
}
}
return;
}
else /* |slope| <= 1 */
{
tick = (int) (x_gdu * x_ppm / 2 + 0.5);
if (l_type == 10) tick = (int) (x_gdu * x_ppm + 0.5);
pix_max = pen_px[pat_ptr];
pen_stat = pen_c[pat_ptr];
dir = (y2 > y1) ? 1: -1; /* set y direction */
if (x2 >= x1) /* sector 1,8 */
{
while (x1 <= x2) /* draw vector */
{ /* test clip limits */
if ( (!(x1 < clp[0][ct] || x1 > clp[1][ct]
|| y1 < clp[2][ct] || y1 > clp[3][ct])) &&
(pen_stat > 0) ) putdot (x1, y1);
++x1; /* next x-incr */
++pix_cnt;
err = err + y_inc;
if (err >= dx) /* controls y-increments */
{
err = err - x_inc;
y1 = y1 + dir;
++pix_cnt;
}
if (pix_cnt >= pix_max )
{
++pat_ptr;
if (pat_ptr >= pat_length)
{
pat_ptr = 0;
pix_cnt = 0;
}
if ( (l_type == 9) || (l_type == 10) )
{
for (i = -tick; i <= tick; ++i)
if (!(x1 < clp[0][ct] || x1 > clp[1][ct]
|| y1 + i < clp[2][ct] || y1 + i > clp[3][ct]))
putdot ( x1 , y1 + i );
}
pix_max = pen_px[pat_ptr];
pen_stat = pen_c[pat_ptr];
#ifdef debug
printf ("(draw_line): pat_ptr = %d\n", pat_ptr);
printf ("(draw_line): pix_max = %d, pen_stat = %d\n", pix_max, pen_stat);
#endif
}
}
}
else /* sector 4,5 */
{
while (x1 >= x2) /* draw vector */
{ /* test clip limits */
if ( (!(x1 < clp[0][ct] || x1 > clp[1][ct]
|| y1 < clp[2][ct] || y1 > clp[3][ct])) &&
(pen_stat > 0) ) putdot (x1, y1);
--x1; /* next x-incr */
++pix_cnt;
err = err + y_inc;
if (err >= dx) /* controls y-increments */
{
err = err - x_inc;
y1 = y1 + dir;
++pix_cnt;
}
if (pix_cnt >= pix_max )
{
++pat_ptr;
if (pat_ptr >= pat_length)
{
pat_ptr = 0;
pix_cnt = 0;
}
if ( (l_type == 9) || (l_type == 10) )
{
for (i = -tick; i <= tick; ++i)
if (!(x1 < clp[0][ct] || x1 > clp[1][ct]
|| y1 + i < clp[2][ct] || y1 + i > clp[3][ct]))
putdot ( x1 , y1 + i );
}
pix_max = pen_px[pat_ptr];
pen_stat = pen_c[pat_ptr];
#ifdef debug
printf ("(draw_line): pat_ptr = %d\n", pat_ptr);
printf ("(draw_line): pix_max = %d, pen_stat = %d\n", pix_max, pen_stat);
#endif
}
}
}
return;
}
} /* end of line drawing algorithm */
/*-------------------------------------------------------------*/
/* putdot() */
/*
This routine places or removes a dot in the graphics crt at the
location it is told to place it. putdot() shifts the origin from the
upper left corner of the screen to the lower left corner. This makes
the display compatible with Hewlett-Packard's graphics display system.
putdot() expects the global variables max_x_dot and max_y_dot to be defined
in the screen setup routine for absolute screen limits. Putdot checks only
for absolute screen boundaries and the current hardclip limits. They are:
(clip[0][0],clip[2][0]), (clip[1][0],clip[3][0]) : (x1, y1), (x2, y2)
(lower left, upper right) screen boundaries.
*/
void putdot (x,y) int x,y;
{
/* can never exceed hard clip limits under program control. */
if ( (x < clp[0][0]) | (x > clp[1][0]) |
(y < clp[2][0]) | (y > clp[3][0]) )
return; /* outside hard clip limits: do nothing */
if (x > max_x_dot || y > max_y_dot || x < 0 || y < 0)
return; /* outside physical screen limits */
regs.x.dx = max_y_dot - y; /* invert y-coordinate: row # */
regs.x.cx = x; /* setup x-coordinate: col # */
regs.h.ah = WRT_PIX; /* mode for BIOS graphics write */
if (Pen > 0)
regs.h.al = (unsigned char) Pen; /* pixel color */
else
regs.h.al = (unsigned char) 0; /* erase pixel */
/* in order to clear pixels from the screen, it is necessary to
read the screen first since the IBM PC will only XOR pixels. Thus,
to erase a pixel, one should first determine if it is on, and then
XOR the pixel with the same data. NOTE!!! if you change the pen
color between write and erase, it will erase in the color chosen
and this may NOT erase the line. */
int86 ( VIDEO, ®s, ®s);
return;
}