home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gondwana.ecr.mu.oz.au/pub/
/
Graphics.tar
/
Graphics
/
VOGLE.ZIP
/
VOGLE
/
DRIVERS
/
GIF.C
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-11
|
12KB
|
357 lines
#include "gd.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "vogle.h"
extern FILE *_voutfile();
static FILE *fp;
static gdImagePtr im;
static int x_size, y_size; /* size of graphics array */
byte *graphics_rgb; /* the graphics data */
static int color = 0;
static int drawn = 0;
static int GLOBAL_rasters = 1; /* line thickness */
static int lastx, lasty; /* position of last draw */
int coltab[256];
static int
noop()
{
return(-1); /* do nothing but return-1 */
}
static int
GIF_color(col) /* change the current color */
int col;
{
color = coltab[col % 256];
return(0);
}
/******************************************************************************/
static int
GIF_mapcolor(indx, r, g, b)
int indx, r, g, b;
{
if (indx < 256 && indx >= 0) {
coltab[indx] = gdImageColorAllocate(im, r, g, b);
}
return(0);
}
/******************************************************************************/
static int
GIF_init()
{
int prefx, prefy, prefxs, prefys;
int i;
getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
if (prefxs != -1 ) {
if (prefys <= 0 ){
fprintf(stderr,"*GIF_init* y size of %d set to 400\n",prefys);
prefys = 400;
}
else{
vdevice.sizeSy = prefys;
}
if (prefxs <= 0 ){
fprintf(stderr,"*GIF_init* x size of %d set to 600\n",prefys);
prefxs = 600;
}
else{
vdevice.sizeSx = prefxs;
}
} else {
/* nice default value */
prefx = 0;
prefy = 0;
vdevice.sizeSy = 400;
vdevice.sizeSx = 600;
}
vdevice.sizeX = vdevice.sizeY = MIN(vdevice.sizeSy,vdevice.sizeSx);
x_size=vdevice.sizeSx;
y_size=vdevice.sizeSy;
vdevice.depth = 8;
im = gdImageCreate(x_size, y_size);
fp = _voutfile();
/* Cause scaling to be 0 to maxX maxY: prefx, vdevice.sizeSx+prefx, prefy, vdevice.sizeSy+prefy */
lastx = -1111111;
lasty = -1111111;
drawn = 0;
GIF_mapcolor(0, 0, 0, 0);
GIF_mapcolor(1, 255, 0, 0);
GIF_mapcolor(2, 0, 255, 0);
GIF_mapcolor(3, 255, 255, 0);
GIF_mapcolor(4, 0, 0, 255);
GIF_mapcolor(5, 255, 0, 255);
GIF_mapcolor(6, 0, 255, 255);
GIF_mapcolor(7, 255, 255, 255);
for(i=8; i<256; i++){
GIF_mapcolor(i, 255, 255, 255);
}
return(1);
}
/******************************************************************************/
static
PPM_fill(n, x, y) /* "fill" a polygon */
int n, x[], y[];
{
int i;
PROTOTYPE static void PPM_SOLID_FILL( int n, int x[], int y[]);
/* update current position if needed */
GLOBAL_lastx=x[0];
GLOBAL_lasty=y[0];
for (i = 1; i < n; i++){
PPM_DRAW_LINE(x[i],y[i]); /* draw outline across graphics array */
}
if ( x[n-1] != x[0] || y[n-1] != y[0] ) /* close the polygon if it is not closed */
PPM_DRAW_LINE(x[0],y[0]);
PPM_SOLID_FILL(n, x, y);
/* update current position */
GLOBAL_lastx = vdevice.cpVx = x[n - 1];
GLOBAL_lasty = vdevice.cpVy = y[n - 1];
GLOBAL_drawn = DRAWN;
}
/******************************************************************************/
static
GIF_draw(x, y)
int x, y;
{
int holdx, holdy;
int xwide[4], ywide[4];
float cosa, sina;
double angle;
if (lastx != x || lasty != y) {
gdImageLine(im, lastx, lasty, x, y, color);
lastx = vdevice.cpVx
lasty = vdevice.cpVy
drawn = 1;
}
}
static
GIF_exit()
{
gdImageGif(im, fp);
if (fp != stdout){
fclose(fp);
}
}
static
GIF_setlw(w)
int w;
{
GLOBAL_rasters = MAX(1,w);
}
static
GIF_clear()
{
gdImageGif(im, fp);
memset(im->pixels, 0, x_size * y_size);
}
/******************************************************************************/
static int GIF_font(font) /* load in large or small */
char *font;
{
if (strcmp(font, "small") == 0) {
vdevice.hwidth = 97.01; /* Size in plotter resolution units */
vdevice.hheight = vdevice.hwidth * 2.0;
} else if (strcmp(font, "large") == 0) {
vdevice.hwidth = 145.5;
vdevice.hheight = vdevice.hwidth * 2.0;
} else
return(0);
return(1);
}
/******************************************************************************/
static PPM_string(s) /* output a string. */
char *s;
{
int dy, dx;
if (GLOBAL_lastx != vdevice.cpVx || GLOBAL_lasty != vdevice.cpVy){
GLOBAL_lastx=vdevice.cpVx;
GLOBAL_lasty=vdevice.cpVy;
}
fputs(s, fp);
GLOBAL_lastx = GLOBAL_lasty = -1111111; /* undefine current position because used hardware text ?*/
GLOBAL_drawn = DRAWN;
}
/******************************************************************************/
static PPM_char(c) /* output a character */
char c;
{
char s[2];
s[0] = c; s[1]='\0';
PPM_string(s);
}
/******************************************************************************/
static DevEntry PPMdev = {
"ppm", /* name of device */
"large", /* name of large font */
"small", /* name of small font */
noop, /* Set drawing in back buffer */
PPM_char, /* Draw a hardware character */
noop, /* Check if a key was hit */
PPM_clear, /* Clear the screen to current color */
PPM_color, /* Set current color */
PPM_draw, /* Draw a line */
PPM_exit, /* Exit graphics */
PPM_fill, /* Fill a polygon */
PPM_font, /* Set hardware font */
noop, /* Set drawing in front buffer */
noop, /* Wait for and get the next key hit */
PPM_init, /* Initialize the device */
noop, /* Get mouse/cross hair position */
PPM_mapcolor,/* Set color indices */
PPM_setlw, /* Set line width */
PPM_string, /* Draw a hardware string */
noop, /* Swap front and back buffers */
noop /* Syncronize the display */
};
/******************************************************************************/
_P3_devcpy()
{
vdevice.dev = PPMdev;
vdevice.dev.Vinit = PPM_init;
GLOBAL_driver = P3;
}
/******************************************************************************/
_P6_devcpy()
{
vdevice.dev = PPMdev;
vdevice.dev.Vinit = PPM_init;
GLOBAL_driver = P6;
}
/*******************************************************************************/
static PPM_YINTERCEPT(yscan, x1, y1, x2, y2, xintercept,yprev)
/*
Determine if scan line intercepts the line segment. If it does, return the x intercept.
*/
int yscan, x1, y1, x2, y2, *xintercept, *yprev;
{
int deltay, yprevious;
float t;
yprevious = *yprev; /* the value we need to use in this pass */
*yprev = y1; /* store the value for the next call to (probably) use */
deltay = y2 - y1;
if ( deltay == 0 ){
/* horizontal lines do not contribute to scan line intercepts */
*yprev=yprevious;
return(0);
}
t = (float)(yscan - y1) / deltay;
if (t > 0.0 && t <= 1.0) {
/* scan line and line segment intersect but not at leading vertex */
*xintercept = x1 + t*(x2 - x1) + 0.5;
return (1);
} else if ( t == 0.0 ){
/* scan line and line segment intersect at leading vertex */
*xintercept = x1 + t*(x2 - x1) + 0.5;
if(yprevious <= y1 && y2 <= y1 ){
/* local maximum */
return (1);
} else if(yprevious >= y1 && y2 >= y1 ){
/* local minimum */
return (1);
} else{
/* ignore duplicate at vertex that is not a local maximum or minimum */
return (0);
}
}
/* scan line and line segment did not intersect */
return (0);
}
/*******************************************************************************/
static void PPM_SOLID_FILL(n, x, y) /* fill polygon of n points drawn by polyline <x,y>. */
int n, x[], y[];
{
int i, j, sorted, yhorizontal, xint, tmp, xmin, xmax, ymax, ymin, xi[MAXVERTS], yprev;
if ( n > MAXVERTS) {
fprintf(stderr,"*PPM_SOLID_FILL* more than %d vertices in a polygon\n",MAXVERTS);
return;
}
/* find clip range */
ymin = ymax = y[0];
xmin = xmax = y[0];
for (i = 0; i < n; i++) {
ymax = MAX(ymax, y[i]);
ymin = MIN(ymin, y[i]);
xmax = MAX(xmax, x[i]);
xmin = MIN(xmin, x[i]);
}
/* ensure scan lines are generated that do not cause out-of-bound problems in the y direction */
ymin=MAX(ymin,0);
ymax=MIN(ymax,Y_SIZE);
/* For each y value, get a list of X intersections... */
yhorizontal = ymax ;
while (yhorizontal >= ymin) {
j = 0;
yprev = y[n-1];
for (i = 0; i < n-1; i++)
if (PPM_YINTERCEPT(yhorizontal, x[i], y[i], x[i+1], y[i+1], &xint, &yprev))
xi[j++] = xint;
/* Last one. */
if (PPM_YINTERCEPT(yhorizontal, x[n-1], y[n-1], x[0], y[0], &xint, &yprev))
xi[j++] = xint;
/* odd pairs means something went wrong in figuring out whether to count vertices or not */
if( 2 * (j/2) != j){
fprintf(stderr,"*PPM_SOLID_FILL* Internal error: odd number of intersection points (%d) \n",j);
}
/* Sort the X intersections... */
sorted = 0;
while (!sorted) {
sorted = 1;
for (i = 0; i < j-1; i++)
if (xi[i] > xi[i+1]) {
tmp = xi[i];
xi[i] = xi[i+1];
xi[i+1] = tmp;
sorted = 0;
}
}
/* Draw the horizontal lines */
/* should make sure within X clipping range */
for (i = 0; i < j-1; i += 2) {
GLOBAL_lastx=MAX(0,MIN(xi[i],X_SIZE));
GLOBAL_lasty=yhorizontal;
PPM_DRAW_LINE(MAX(0,MIN(xi[i+1],X_SIZE)), yhorizontal);
}
yhorizontal -= 1;
}
}
/*******************************************************************************/