Added GIFPlot example

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@219 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2000-02-11 05:37:31 +00:00
commit a59e9a4405
49 changed files with 8487 additions and 0 deletions

View file

@ -0,0 +1,21 @@
CC = @CC@
INCLUDE = -I../Include
CFLAGS = -O
SRCS = frame.c color.c plot2d.c plot3d.c font.c pixmap.c matrix.c gif.c
OBJS = $(SRCS:.c=.o)
AR = @AR@
RANLIB = @RANLIB@
TARGET = ../libgifplot.a
.c.o:
$(CC) $(INCLUDE) $(CFLAGS) -c -o $*.o $<
all: $(OBJS)
@rm -f ../libgifplot.a
$(AR) cr $(TARGET) $(OBJS)
$(RANLIB) $(TARGET)
clean:
rm -f *.o *~ $(TARGET)

View file

@ -0,0 +1,140 @@
/* -----------------------------------------------------------------------------
* color.c
*
* Colormaps
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
* Copyright (C) 1995-1996
*
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
#define COLORMAP
#include "gifplot.h"
#include <string.h>
/* ------------------------------------------------------------------------
ColorMap *new_ColorMap(char *filename)
Read a colormap from a file.
------------------------------------------------------------------------ */
ColorMap *new_ColorMap(char *filename) {
ColorMap *c;
FILE *cm;
void ColorMap_default(ColorMap *);
if (!filename) {
c = (ColorMap *) malloc(sizeof(ColorMap));
c->cmap = (unsigned char *) malloc(768*sizeof(char));
c->name = 0;
ColorMap_default(c);
return c;
}
if (strlen(filename) == 0) {
c = (ColorMap *) malloc(sizeof(ColorMap));
c->cmap = (unsigned char *) malloc(768*sizeof(char));
ColorMap_default(c);
return c;
}
if ((cm = fopen(filename,"rb")) == NULL) {
return (ColorMap *) 0;
}
c = (ColorMap *) malloc(sizeof(ColorMap));
c->cmap = (unsigned char *) malloc(768*sizeof(char));
if (fread(c->cmap, 768, 1, cm) != 1) {
free((char *)c->cmap);
free((char *)c);
fclose(cm);
return (ColorMap *) 0;
}
fclose(cm);
c->name = (char *) malloc(strlen(filename)+1);
strcpy(c->name, filename);
ColorMap_default(c);
return c;
}
/* --------------------------------------------------------------------------
delete_ColorMap(ColorMap *cm)
Destroy a ColorMap
-------------------------------------------------------------------------- */
void delete_ColorMap(ColorMap *cm) {
if (cm) {
free((char *)cm->cmap);
if (cm->name)
free((char *)cm->name);
free((char *)cm);
}
}
/* --------------------------------------------------------------------------
ColorMap_default(ColorMap *cm)
This function fills in default values for the first 8 entries of the
colormap. These are *fixed* values---used internally.
-------------------------------------------------------------------------- */
void ColorMap_default(ColorMap *cm) {
unsigned char *r,*g,*b;
if (cm) {
r = cm->cmap;
g = cm->cmap+256;
b = cm->cmap+512;
r[0] = 0; g[0] = 0; b[0] = 0; /* BLACK */
r[1] = 255; g[1] = 255; b[1] = 255; /* WHITE */
r[2] = 255; g[2] = 0; b[2] = 0; /* RED */
r[3] = 0; g[3] = 255; b[3] = 0; /* GREEN */
r[4] = 0; g[4] = 0; b[4] = 255; /* BLUE */
r[5] = 255; g[5] = 255; b[5] = 0; /* YELLOW */
r[6] = 0; g[6] = 255; b[6] = 255; /* CYAN */
r[7] = 255; g[7] = 0; b[7] = 255; /* MAGENTA */
}
}
void ColorMap_assign(ColorMap *cm, int index, int r, int g, int b) {
unsigned char *rb,*gb,*bb;
rb = cm->cmap;
gb = cm->cmap+256;
bb = cm->cmap+512;
rb[index] = r;
gb[index] = g;
bb[index] = b;
}
int ColorMap_getitem(ColorMap *cm, int index) {
if ((index < 0) && (index >= 768)) return -1;
return cm->cmap[index];
}
void ColorMap_setitem(ColorMap *cm, int index, int value) {
if ((index < 0) && (index >= 768)) return;
cm->cmap[index]=value;
}
/* --------------------------------------------------------------------
ColorMap_write(ColorMap *cm, char *filename)
Write out a colormap to disk.
-------------------------------------------------------------------- */
int ColorMap_write(ColorMap *cm, char *filename) {
FILE *f;
if (!cm) return -1;
if (!filename) return -1;
if (strlen(filename) == 0) return -1;
f = fopen(filename,"w");
fwrite(cm->cmap,768,1,f);
fclose(f);
return 0;
}
#undef COLORMAP

View file

@ -0,0 +1,705 @@
/* -----------------------------------------------------------------------------
* font.c
*
* Some basic fonts.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
* Copyright (C) 1995-1996
*
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
#define FONT
#include "gifplot.h"
static char Char_A[80] = "\
...x....\
...x....\
..x.x...\
..x.x...\
.x...x..\
.xxxxx..\
x.....x.\
x.....x.\
x.....x.\
........";
static char Char_B[80] = "\
xxxxxx..\
x.....x.\
x.....x.\
x.....x.\
xxxxxx..\
x.....x.\
x.....x.\
x.....x.\
xxxxxx..\
........";
static char Char_C[80] = "\
..xxxx..\
.x....x.\
x.......\
x.......\
x.......\
x.......\
x.......\
.x....x.\
..xxxx..\
........";
static char Char_D[80] = "\
xxxxx...\
x....x..\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x....x..\
xxxxx...\
........";
static char Char_E[80] = "\
xxxxxxx.\
x.......\
x.......\
x.......\
xxxxx...\
x.......\
x.......\
x.......\
xxxxxxx.\
........";
static char Char_F[80] = "\
xxxxxxx.\
x.......\
x.......\
x.......\
xxxxx...\
x.......\
x.......\
x.......\
x.......\
........";
static char Char_G[80] = "\
.xxxxx..\
x.....x.\
x.......\
x.......\
x...xxx.\
x.....x.\
x.....x.\
x.....x.\
.xxxxx..\
........";
static char Char_H[80] = "\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
xxxxxxx.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
........";
static char Char_I[80] = "\
xxxxxxx.\
...x....\
...x....\
...x....\
...x....\
...x....\
...x....\
...x....\
xxxxxxx.\
........";
static char Char_J[80] = "\
......x.\
......x.\
......x.\
......x.\
......x.\
......x.\
x.....x.\
.x...x..\
..xxx...\
........";
static char Char_K[80] = "\
x.....x.\
x....x..\
x...x...\
x..x....\
xxx.....\
x..x....\
x...x...\
x....x..\
x.....x.\
........";
static char Char_L[80] = "\
x.......\
x.......\
x.......\
x.......\
x.......\
x.......\
x.......\
x.......\
xxxxxxx.\
........";
static char Char_M[80] = "\
x.....x.\
xx...xx.\
xx...xx.\
x.x.x.x.\
x.x.x.x.\
x..x..x.\
x..x..x.\
x.....x.\
x.....x.\
........";
static char Char_N[80] = "\
x.....x.\
xx....x.\
x.x...x.\
x.x...x.\
x..x..x.\
x...x.x.\
x...x.x.\
x....xx.\
x.....x.\
........";
static char Char_O[80] = "\
.xxxxx..\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
.xxxxx..\
........";
static char Char_P[80] = "\
xxxxxx..\
x.....x.\
x.....x.\
x.....x.\
xxxxxx..\
x.......\
x.......\
x.......\
x.......\
........";
static char Char_Q[80] = "\
.xxxxx..\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x...x.x.\
x....x..\
.xxxx.x.\
........";
static char Char_R[80] = "\
xxxxxx..\
x.....x.\
x.....x.\
x.....x.\
xxxxxx..\
x..x....\
x...x...\
x....x..\
x.....x.\
........";
static char Char_S[80] = "\
.xxxxx..\
x.....x.\
x.......\
x.......\
.xxxxx..\
......x.\
......x.\
x.....x.\
.xxxxx..\
........";
static char Char_T[80] = "\
xxxxxxx.\
...x....\
...x....\
...x....\
...x....\
...x....\
...x....\
...x....\
...x....\
........";
static char Char_U[80] = "\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
.xxxxx..\
........";
static char Char_V[80] = "\
x.....x.\
x.....x.\
.x...x..\
.x...x..\
..x.x...\
..x.x...\
...x....\
...x....\
...x....\
........";
static char Char_W[80] = "\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x.....x.\
x..x..x.\
x..x..x.\
x.x.x.x.\
.x...x..\
........";
static char Char_X[80] = "\
x.....x.\
x.....x.\
.x...x..\
..x.x...\
...x....\
..x.x...\
.x...x..\
x.....x.\
x.....x.\
........";
static char Char_Y[80] = "\
x.....x.\
x.....x.\
.x...x..\
..x.x...\
...x....\
...x....\
...x....\
...x....\
...x....\
........";
static char Char_Z[80] = "\
xxxxxxx.\
......x.\
.....x..\
....x...\
...x....\
..x.....\
.x......\
x.......\
xxxxxxx.\
........";
static char Char_0[80] = "\
.xxxxx..\
x....xx.\
x...x.x.\
x..x..x.\
x..x..x.\
x.x...x.\
x.x...x.\
xx....x.\
.xxxxx..\
........";
static char Char_1[80] = "\
...x....\
..xx....\
...x....\
...x....\
...x....\
...x....\
...x....\
...x....\
..xxx...\
........";
static char Char_2[80] = "\
..xxxx..\
.x....x.\
x.....x.\
.....x..\
....x...\
...x....\
..x.....\
.x......\
xxxxxxx.\
........";
static char Char_3[80] = "\
.xxxxx..\
x.....x.\
......x.\
......x.\
...xxx..\
......x.\
......x.\
x.....x.\
.xxxxx..\
........";
static char Char_4[80] = "\
....xx..\
...x.x..\
..x..x..\
.x...x..\
xxxxxxx.\
.....x..\
.....x..\
.....x..\
.....x..\
........";
static char Char_5[80] = "\
xxxxxxx.\
x.......\
x.......\
x.......\
xxxxxx..\
......x.\
......x.\
x.....x.\
.xxxxx..\
........";
static char Char_6[80] = "\
....xxx.\
..xx....\
.x......\
x.......\
x.xxx...\
xx...x..\
x.....x.\
.x...x..\
..xxx...\
........";
static char Char_7[80] = "\
xxxxxxx.\
x.....x.\
.....x..\
....x...\
...x....\
..x.....\
.x......\
x.......\
x.......\
........";
static char Char_8[80] = "\
.xxxxx..\
x.....x.\
x.....x.\
x.....x.\
.xxxxx..\
x.....x.\
x.....x.\
x.....x.\
.xxxxx..\
........";
static char Char_9[80] = "\
..xxxx..\
.x....x.\
x.....x.\
x....xx.\
.xxxx.x.\
......x.\
......x.\
....xx..\
.xxx....\
........";
static char Char_MINUS[80] = "\
........\
........\
........\
........\
.xxxxxx.\
........\
........\
........\
........\
........";
static char Char_PLUS[80] = "\
........\
........\
...x....\
...x....\
.xxxxx..\
...x....\
...x....\
........\
........\
........";
static char Char_EQUAL[80] = "\
........\
........\
........\
.xxxxx..\
........\
.xxxxx..\
........\
........\
........\
........";
static char Char_LPAREN[80] = "\
....x...\
...x....\
..x.....\
.x......\
.x......\
.x......\
..x.....\
...x....\
....x...\
........";
static char Char_RPAREN[80] = "\
...x....\
....x...\
.....x..\
......x.\
......x.\
......x.\
.....x..\
....x...\
...x....\
........";
static char Char_QUOTE[80] = "\
..x.x...\
..x.x...\
........\
........\
........\
........\
........\
........\
........\
........";
static char Char_COLON[80] = "\
........\
........\
...xx...\
...xx...\
........\
...xx...\
...xx...\
........\
........\
........";
static char Char_PERIOD[80] = "\
........\
........\
........\
........\
........\
........\
........\
...xx...\
...xx...\
........";
static char Char_COMMA[80] = "\
........\
........\
........\
........\
........\
........\
...xx...\
...xx...\
....x...\
...x....";
static char Char_SLASH[80] = "\
........\
......x.\
.....x..\
....x...\
...x....\
..x.....\
.x......\
x.......\
........\
........";
static char Char_SPACE[80] = "\
........\
........\
........\
........\
........\
........\
........\
........\
........\
........";
static char *GP_Font[128];
static int InitGP_Font = 0;
static void initGP_Fonts(void) {
int i;
for (i = 0; i < 128; i++)
GP_Font[i] = (char *) 0;
GP_Font['A'] = GP_Font['a'] = Char_A;
GP_Font['B'] = GP_Font['b'] = Char_B;
GP_Font['C'] = GP_Font['c'] = Char_C;
GP_Font['D'] = GP_Font['d'] = Char_D;
GP_Font['E'] = GP_Font['e'] = Char_E;
GP_Font['F'] = GP_Font['f'] = Char_F;
GP_Font['G'] = GP_Font['g'] = Char_G;
GP_Font['H'] = GP_Font['h'] = Char_H;
GP_Font['I'] = GP_Font['i'] = Char_I;
GP_Font['J'] = GP_Font['j'] = Char_J;
GP_Font['K'] = GP_Font['k'] = Char_K;
GP_Font['L'] = GP_Font['l'] = Char_L;
GP_Font['M'] = GP_Font['m'] = Char_M;
GP_Font['N'] = GP_Font['n'] = Char_N;
GP_Font['O'] = GP_Font['o'] = Char_O;
GP_Font['P'] = GP_Font['p'] = Char_P;
GP_Font['Q'] = GP_Font['q'] = Char_Q;
GP_Font['R'] = GP_Font['r'] = Char_R;
GP_Font['S'] = GP_Font['s'] = Char_S;
GP_Font['T'] = GP_Font['t'] = Char_T;
GP_Font['U'] = GP_Font['u'] = Char_U;
GP_Font['V'] = GP_Font['v'] = Char_V;
GP_Font['W'] = GP_Font['w'] = Char_W;
GP_Font['X'] = GP_Font['x'] = Char_X;
GP_Font['Y'] = GP_Font['y'] = Char_Y;
GP_Font['Z'] = GP_Font['z'] = Char_Z;
GP_Font['0'] = Char_0;
GP_Font['1'] = Char_1;
GP_Font['2'] = Char_2;
GP_Font['3'] = Char_3;
GP_Font['4'] = Char_4;
GP_Font['5'] = Char_5;
GP_Font['6'] = Char_6;
GP_Font['7'] = Char_7;
GP_Font['8'] = Char_8;
GP_Font['9'] = Char_9;
GP_Font['.'] = Char_PERIOD;
GP_Font[','] = Char_COMMA;
GP_Font['='] = Char_EQUAL;
GP_Font['-'] = Char_MINUS;
GP_Font['+'] = Char_PLUS;
GP_Font['\"'] = Char_QUOTE;
GP_Font['('] = Char_LPAREN;
GP_Font[')'] = Char_RPAREN;
GP_Font[':'] = Char_COLON;
GP_Font['/'] = Char_SLASH;
GP_Font[' '] = Char_SPACE;
InitGP_Font = 1;
}
/* -----------------------------------------------------------------------
void FrameBuffer_drawchar(FrameBuffer *f, int x, int y, Pixel fgcolor, Pixel bgcolor, char chr, int orientation)
Draws a character at location x, y with given color and orientation parameters.
Orientation can either be HORIZONTAL or VERTICAL
----------------------------------------------------------------------- */
void FrameBuffer_drawchar(FrameBuffer *f, int x, int y, int fgcolor,
int bgcolor, char chr, int orientation) {
Pixel c, bc,*p,*p1;
char *ch;
int i,j;
int xpixels,ypixels;
if (!InitGP_Font) initGP_Fonts();
c = (Pixel) fgcolor;
bc = (Pixel) bgcolor;
xpixels = f->width;
ypixels = f->height;
if (orientation == HORIZONTAL) {
if ((x < f->xmin) || (x > f->xmax-8) ||
(y < f->ymin) || (y > f->ymax-10)) return;
ch = GP_Font[(int) chr];
if (!ch) return;
p = &f->pixels[y+9][x];
for (i = 0; i < 10; i++) {
p1 = p;
for (j = 0; j< 8; j++) {
if (*(ch++) == 'x') *p= c;
else if (bgcolor >= 0)
*p = bc;
p++;
}
p = (p1 - xpixels);
}
} else {
if ((x < f->xmin+10) || (x >= f->xmax) ||
(y < f->ymin) || (y > f->ymax-8)) return;
ch = GP_Font[(int) chr];
if (!ch) return;
p = &f->pixels[y][x-9];
for (i = 0; i < 10; i++) {
p1 = p;
for (j = 0; j< 8; j++) {
if (*(ch++) == 'x') *p= c;
else if (bgcolor >= 0)
*p = bc;
p+=xpixels;
}
p = p1 + 1;
}
}
}
/* ----------------------------------------------------------------------
void FrameBuffer_drawstring(FrameBuffer *f, int x, int y, int fgcolor,
int bgcolor, char *text, int orientation)
Draws an ASCII string on the framebuffer. Can be oriented either horizontally
or vertically.
---------------------------------------------------------------------- */
void FrameBuffer_drawstring(FrameBuffer *f, int x, int y, int fgcolor, int bgcolor, char *text, int orientation) {
char *c;
int x1, y1;
int xpixels, ypixels;
x1 = x;
y1 = y;
xpixels = f->width;
ypixels = f->height;
c = text;
while (*c) {
if (*c == '\n') {
if (orientation == HORIZONTAL) {
x1 = x; y1= y1- 10*xpixels;
} else {
y1 = y; x1= x1 + 10*ypixels;
}
} else {
FrameBuffer_drawchar(f, x1,y1,fgcolor, bgcolor,*c, orientation);
if (orientation == HORIZONTAL) {
x1+=8;
if (x1 >= (xpixels-8)) {
x1 = x; y1= y1- 10;}
if (y1 < 0) return;
} else {
y1 += 8;
if (y1 >= (ypixels-8)) {
y1 = y; x1 = x1 + 10;}
if (x1 > (xpixels-10)) return;
}
}
c++;
}
}

View file

@ -0,0 +1,924 @@
/* -----------------------------------------------------------------------------
* frame.c
*
* Frame buffer management
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
* Copyright (C) 1995-1996
*
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
#define FRAME
#include "gifplot.h"
#include <float.h>
/* ------------------------------------------------------------------------
FrameBuffer *new_FrameBuffer(int width, int height)
Creates a new framebuffer for storing data.
------------------------------------------------------------------------ */
FrameBuffer *new_FrameBuffer(unsigned int width, unsigned int height) {
FrameBuffer *f;
int FrameBuffer_resize(FrameBuffer *f, int width, int height);
/* Create a new frame buffer */
f = (FrameBuffer *) malloc(sizeof(FrameBuffer));
f->pixels = (Pixel **) 0;
f->zbuffer = (Zvalue **) 0;
/* Set its size */
if (FrameBuffer_resize(f, width, height) == -1) {
free((char *) f);
return (FrameBuffer *) 0;
}
f->xmin = 0;
f->ymin = 0;
f->xmax = width;
f->ymax = height;
return f;
}
/* ------------------------------------------------------------------------
void delete_FrameBuffer(FrameBuffer *f)
Destroys the given framebuffer
------------------------------------------------------------------------ */
void delete_FrameBuffer(FrameBuffer *f) {
if (f) {
if (f->pixels) {
free((char *) f->pixels[0]);
free((char *) f->pixels);
}
if (f->zbuffer) {
free((char *) f->zbuffer[0]);
free((char *) f->zbuffer);
}
free((char *)f);
}
}
/* ------------------------------------------------------------------------
int *FrameBuffer_resize(FrameBuffer *f, int width, int height)
Resize the given framebuffer. Returns 0 on success, -1 on failure.
------------------------------------------------------------------------ */
int FrameBuffer_resize(FrameBuffer *f, int width, int height) {
int i;
if ((f) && (width > 0) && (height > 0)) {
if (f->pixels) {
free((char *)f->pixels[0]);
free((char *)f->pixels);
}
f->pixels = (Pixel **) malloc (height*sizeof(Pixel *));
if (!f->pixels) return -1;
f->pixels[0] = (Pixel *) malloc(height*width*sizeof(Pixel));
if (!f->pixels[0]) {
free((char *)f->pixels);
return -1;
}
for (i = 0; i < height; i++)
f->pixels[i] = f->pixels[0] + i*width;
f->width = width;
f->height = height;
if (f->zbuffer) {
FrameBuffer_zresize(f,width,height);
}
return 0;
} else {
return -1;
}
}
/* ------------------------------------------------------------------------
void FrameBuffer_clear(FrameBuffer *f, Pixel color)
Clears the current FrameBuffer
------------------------------------------------------------------------ */
void FrameBuffer_clear(FrameBuffer *f, Pixel color) {
Pixel *p;
unsigned int i;
p = &f->pixels[0][0];
for (i = 0; i < f->width*f->height; i++, p++)
*p = color;
}
/* ------------------------------------------------------------------------
void FrameBuffer_plot(FrameBuffer *f, int x1, int y1, Pixel color)
Plots a point and does a bounds check.
------------------------------------------------------------------------ */
void FrameBuffer_plot(FrameBuffer *f, int x1, int y1, Pixel color) {
if ((x1 < f->xmin) || (x1 >= f->xmax) || (y1 < f->ymin) || (y1 >= f->ymax))
return;
f->pixels[y1][x1] = color;
}
/* ------------------------------------------------------------------------
FrameBuffer_horizontal(Framebuffer *f, int xmin, int xmax, int y, Pixel color)
Draw a horizontal line (clipped)
------------------------------------------------------------------------ */
void FrameBuffer_horizontal(FrameBuffer *f, int xmin, int xmax, int y, Pixel color) {
Pixel *p;
int i;
if ((y < f->ymin) || (y >= f->ymax)) return;
if (xmin < f->xmin) xmin = f->xmin;
if (xmax >= f->xmax) xmax = f->xmax - 1;
p = &f->pixels[y][xmin];
for (i = xmin; i <= xmax; i++, p++)
*p = color;
}
/* ------------------------------------------------------------------------
FrameBuffer_horizontalinterp(Framebuffer *f, int xmin, int xmax, int y,
Pixel c1, Pixel c2)
Draw a horizontal line (clipped) with color interpolation.
------------------------------------------------------------------------ */
void FrameBuffer_horizontalinterp(FrameBuffer *f, int xmin, int xmax, int y,
Pixel c1, Pixel c2) {
Pixel *p;
int i;
double mc;
int x1;
if ((y < f->ymin) || (y >= f->ymax)) return;
x1 = xmin;
if (xmin < f->xmin) xmin = f->xmin;
if (xmax >= f->xmax) xmax = f->xmax - 1;
if (xmax < f->xmin) return;
if (xmin >= f->xmax) return;
if (xmin != xmax)
mc = (double)(c2 - c1)/(double) (xmax - xmin);
else
mc = 0.0;
p = &f->pixels[y][xmin];
for (i = xmin; i <= xmax; i++, p++)
*p = (Pixel) (mc*(i-x1) + c1);
}
/* ------------------------------------------------------------------------
FrameBuffer_vertical(Framebuffer *f, int xmin, int xmax, int y, Pixel color)
Draw a Vertical line (clipped)
------------------------------------------------------------------------ */
void FrameBuffer_vertical(FrameBuffer *f, int ymin, int ymax, int x, Pixel color) {
Pixel *p;
int i;
if ((x < f->xmin) || (x >= f->xmax)) return;
if (ymax < f->ymin) return;
if (ymin > f->ymax) return;
if (ymin < f->ymin) ymin = f->ymin;
if (ymax >= f->ymax) ymax = f->ymax - 1;
p = &f->pixels[ymin][x];
for (i = 0; i <= (ymax - ymin); i++, p+=f->width)
*p = color;
}
/* ------------------------------------------------------------------------
void FrameBuffer_box(FrameBuffer *f, int x1, int y1, int x2, int y2, Pixel color)
Makes an outline box.
------------------------------------------------------------------------ */
void FrameBuffer_box(FrameBuffer *f, int x1, int y1, int x2, int y2, Pixel color) {
int xt, yt;
/* Make sure points are in correct order */
if (x2 < x1) {
xt = x2;
x2 = x1;
x1 = xt;
}
if (y2 < y1) {
yt = y2;
y2 = y1;
y1 = yt;
}
/* Draw lower edge */
FrameBuffer_horizontal(f,x1,x2,y1,color);
/* Draw upper edge */
FrameBuffer_horizontal(f,x1,x2,y2,color);
/* Draw left side */
FrameBuffer_vertical(f,y1,y2,x1,color);
/* Draw right side */
FrameBuffer_vertical(f,y1,y2,x2,color);
}
/* ------------------------------------------------------------------------
void FrameBuffer_solidbox(FrameBuffer *f, int x1, int y1, int x2, int y2, Pixel color)
Makes an solid box.
------------------------------------------------------------------------ */
void FrameBuffer_solidbox(FrameBuffer *f, int x1, int y1, int x2, int y2, Pixel color) {
int xt, yt;
/* Make sure points are in correct order */
if (x2 < x1) {
xt = x2;
x2 = x1;
x1 = xt;
}
if (y2 < y1) {
yt = y2;
y2 = y1;
y1 = yt;
}
/* Now perform some clipping */
if (y1 < f->ymin) y1 = f->ymin;
if (y2 >= f->ymax) y2 = f->ymax - 1;
/* Fill it in using horizontal lines */
for (yt = y1; yt <= y2; yt++)
FrameBuffer_horizontal(f,x1,x2,yt,color);
}
/* ------------------------------------------------------------------------
void FrameBuffer_interpbox(FrameBuffer *f, int x1, int y1, int x2, int y2
Pixel c1, Pixel c2, Pixel c3, Pixel c4)
Makes a box with interpolated color. Colors are assigned as follows :
(x1,y1) = c1
(x1,y2) = c2
(x2,y1) = c3
(x2,y2) = c4
------------------------------------------------------------------------ */
void FrameBuffer_interpbox(FrameBuffer *f, int x1, int y1, int x2, int y2,
Pixel c1, Pixel c2, Pixel c3, Pixel c4) {
int xt, yt;
Pixel ct;
double mc1,mc2;
int ystart;
/* Make sure points are in correct order */
if (x2 < x1) {
xt = x2;
x2 = x1;
x1 = xt;
ct = c1;
c1 = c3;
c3 = ct;
ct = c2;
c2 = c4;
c4 = ct;
}
if (y2 < y1) {
yt = y2;
y2 = y1;
y1 = yt;
ct = c1;
c1 = c2;
c2 = ct;
ct = c3;
c3 = c4;
c4 = ct;
}
/* Now perform some clipping */
ystart = y1;
mc1 = (double) (c2 - c1)/(double) (y2 - y1);
mc2 = (double) (c4 - c3)/(double) (y2 - y1);
if (y1 < f->ymin) y1 = f->ymin;
if (y2 >= f->ymax) y2 = f->ymax - 1;
/* Fill it in using horizontal lines */
for (yt = y1; yt <= y2; yt++)
FrameBuffer_horizontalinterp(f,x1,x2,yt,(Pixel) ((mc1*(yt - ystart)) + c1),
(Pixel) ((mc2*(yt-ystart))+c3));
}
/* ---------------------------------------------------------------------------
FrameBuffer_line(FrameBuffer *f, int x1, int y1, int x2, int y2, color)
Draws a line on the framebuffer using the Bresenham line algorithm. The
line is clipped to fit within the current view window.
---------------------------------------------------------------------------- */
void FrameBuffer_line(FrameBuffer *f, int x1, int y1, int x2, int y2, Pixel c) {
int dx,dy,dxneg,dyneg, inc1,inc2,di;
int x, y, xpixels, ypixels, xt, yt;
Pixel *p;
double m;
int end1 = 0, end2 = 0;
/* Need to figure out where in the heck this line is */
dx = x2 - x1;
dy = y2 - y1;
if (dx == 0) {
/* Draw a Vertical Line */
if (y1 < y2)
FrameBuffer_vertical(f,y1,y2,x1,c);
else
FrameBuffer_vertical(f,y2,y1,x1,c);
return;
}
if (dy == 0) {
/* Draw a Horizontal Line */
if (x1 < x2)
FrameBuffer_horizontal(f,x1,x2,y1,c);
else
FrameBuffer_horizontal(f,x2,x1,y1,c);
return;
}
/* Figure out where in the heck these lines are using the
Cohen-Sutherland Line Clipping Scheme. */
end1 = ((x1 - f->xmin) < 0) |
(((f->xmax- 1 - x1) < 0) << 1) |
(((y1 - f->ymin) < 0) << 2) |
(((f->ymax-1 - y1) < 0) << 3);
end2 = ((x2 - f->xmin) < 0) |
(((f->xmax-1 - x2) < 0) << 1) |
(((y2 - f->ymin) < 0) << 2) |
(((f->ymax-1 - y2) < 0) << 3);
if (end1 & end2) return; /* Nope : Not visible */
/* Make sure points have a favorable orientation */
if (x1 > x2) {
xt = x1;
x1 = x2;
x2 = xt;
yt = y1;
y1 = y2;
y2 = yt;
}
/* Clip against the boundaries */
m = (y2 - y1)/(double) (x2-x1);
if (x1 < f->xmin) {
y1 = (int) ((f->xmin - x1)*m + y1);
x1 = (int) f->xmin;
}
if (x2 >= f->xmax) {
y2 = (int) ((f->xmax -1 -x1)*m + y1);
x2 = (int) (f->xmax - 1);
}
if (y1 > y2) {
xt = x1;
x1 = x2;
x2 = xt;
yt = y1;
y1 = y2;
y2 = yt;
}
m = 1/m;
if (y1 < f->ymin) {
x1 = (int) ((f->ymin - y1)*m + x1);
y1 = (int) f->ymin;
}
if (y2 >= f->ymax) {
x2 = (int) ((f->ymax-1-y1)*m + x1);
y2 = (int) (f->ymax-1);
}
if ((x1 < f->xmin) || (x1 >= f->xmax) || (y1 < f->ymin) || (y1 >= f->ymax) ||
(x2 < f->xmin) || (x2 >= f->xmax) || (y2 < f->ymin) || (y2 >= f->ymax)) return;
dx = x2 - x1;
dy = y2 - y1;
xpixels = f->width;
ypixels = f->height;
dxneg = (dx < 0) ? 1 : 0;
dyneg = (dy < 0) ? 1 : 0;
dx = abs(dx);
dy = abs(dy);
if (dx >= dy) {
/* Slope between -1 and 1. */
if (dxneg) {
x = x1;
y = y1;
x1 = x2;
y1 = y2;
x2 = x;
y2 = y;
dyneg = !dyneg;
}
inc1 = 2*dy;
inc2 = 2*(dy-dx);
di = 2*dy-dx;
/* Draw a line using x as independent variable */
p = &f->pixels[y1][x1];
x = x1;
while (x <= x2) {
*(p++) = c;
if (di < 0) {
di = di + inc1;
} else {
if (dyneg) {
p = p - xpixels;
di = di + inc2;
} else {
p = p + xpixels;
di = di + inc2;
}
}
x++;
}
} else {
/* Slope < -1 or > 1 */
if (dyneg) {
x = x1;
y = y1;
x1 = x2;
y1 = y2;
x2 = x;
y2 = y;
dxneg = !dxneg;
}
inc1 = 2*dx;
inc2 = 2*(dx-dy);
di = 2*dx-dy;
/* Draw a line using y as independent variable */
p = &f->pixels[y1][x1];
y = y1;
while (y <= y2) {
*p = c;
p = p + xpixels;
if (di < 0) {
di = di + inc1;
} else {
if (dxneg) {
p = p - 1;
di = di + inc2;
} else {
p = p + 1;
di = di + inc2;
}
}
y++;
}
}
}
/* -------------------------------------------------------------------------
FrameBuffer_circle(FrameBuffer f, int xc, int yc, int radius, Pixel c)
Create an outline circle
------------------------------------------------------------------------- */
#define plot_circle(x,y,c) \
if ((x >= xmin) && (x < xmax) && \
(y >= ymin) && (y < ymax)) \
pixels[y][x] = c;
void FrameBuffer_circle(FrameBuffer *f, int xc, int yc, int radius, Pixel c) {
int xpixels, ypixels, x, y, p;
int xmin, ymin, xmax, ymax;
Pixel **pixels;
if (radius <= 0) return;
xpixels = f->width;
ypixels = f->height;
pixels = f->pixels;
xmin = f->xmin;
ymin = f->ymin;
xmax = f->xmax;
ymax = f->ymax;
x = 0;
y = radius;
p = 3-2*radius;
while (x <= y) {
plot_circle(xc+x,yc+y,c);
plot_circle(xc-x,yc+y,c);
plot_circle(xc+x,yc-y,c);
plot_circle(xc-x,yc-y,c);
plot_circle(xc+y,yc+x,c);
plot_circle(xc-y,yc+x,c);
plot_circle(xc+y,yc-x,c);
plot_circle(xc-y,yc-x,c);
if (p < 0) p = p + 4*x + 6;
else {
p = p + 4*(x-y) + 10;
y = y -1;
}
x++;
}
}
/* -------------------------------------------------------------------------
FrameBuffer_solidcircle(FrameBuffer f, int xc, int yc, int radius, Pixel c)
Create an filled circle
------------------------------------------------------------------------- */
#define fill_circle(x,y,c) \
x1 = xc - x; \
x2 = xc + x; \
FrameBuffer_horizontal(f,x1,x2,y,c);
void FrameBuffer_solidcircle(FrameBuffer *f, int xc, int yc, int radius, Pixel c) {
int xpixels, ypixels, x, y, p;
int x1,x2;
int xmin, ymin, xmax, ymax;
Pixel **pixels;
if (radius <= 0) return;
xpixels = f->width;
ypixels = f->height;
pixels = f->pixels;
xmin = f->xmin;
ymin = f->ymin;
xmax = f->xmax;
ymax = f->ymax;
x = 0;
y = radius;
p = 3-2*radius;
while (x <= y) {
fill_circle(x,yc+y,c);
fill_circle(x,yc-y,c);
fill_circle(y,yc+x,c);
fill_circle(y,yc-x,c);
if (p < 0) p = p + 4*x + 6;
else {
p = p + 4*(x-y) + 10;
y = y -1;
}
x++;
}
}
/* ------------------------------------------------------------------------
void FrameBuffer_setclip(f,xmin,ymin,xmax,ymax)
Set clipping region for plotting
------------------------------------------------------------------------ */
void FrameBuffer_setclip(FrameBuffer *f, int xmin, int ymin, int xmax, int ymax) {
if (xmin >= xmax) return;
if (ymin >= ymax) return;
if (xmin < 0) xmin = 0;
if (ymin < 0) ymin = 0;
if (xmax > (int) f->width) xmax = f->width;
if (ymax > (int) f->height) ymax = f->height;
f->xmin = xmin;
f->ymin = ymin;
f->xmax = xmax;
f->ymax = ymax;
}
/* ------------------------------------------------------------------------
void FrameBuffer_noclip(f)
Disable clipping region
------------------------------------------------------------------------ */
void FrameBuffer_noclip(FrameBuffer *f) {
f->xmin = 0;
f->ymin = 0;
f->xmax = f->width;
f->ymax = f->height;
}
/* ------------------------------------------------------------------------
FrameBuffer_zresize(FrameBuffer *f, int width, int height)
This function resizes the framebuffer's zbuffer. If none exist, it
creates a new one.
------------------------------------------------------------------------ */
void FrameBuffer_zresize(FrameBuffer *f, int width, int height) {
int i;
if (f->zbuffer) {
free((char *)f->zbuffer[0]);
free((char *)f->zbuffer);
}
f->zbuffer = (Zvalue **) malloc(height*sizeof(Zvalue *));
f->zbuffer[0] = (Zvalue *) malloc(height*width*sizeof(Zvalue));
for (i = 0; i < height; i++)
f->zbuffer[i] = f->zbuffer[0]+i*width;
}
/* ------------------------------------------------------------------------
FrameBuffer_zclear(FrameBuffer *f)
Clears the z-buffer for a particular frame. Sets all of the z-values to
ZMIN.
------------------------------------------------------------------------- */
void FrameBuffer_zclear(FrameBuffer *f) {
unsigned int i,j;
if (f) {
if (f->zbuffer) {
for (i = 0; i < f->width; i++)
for (j = 0; j < f->height; j++)
f->zbuffer[j][i] = ZMIN;
}
}
}
/* -------------------------------------------------------------------------
FrameBuffer_solidtriangle(FrameBuffer *f, int tx1, int ty2,
int tx2, int ty2,
int tx3, int ty3, Pixel color)
This function draws a 2D filled triangle.
General idea :
1. Transform the three points into screen coordinates
2. Order three points vertically on screen.
3. Check for degenerate cases (where 3 points are colinear).
4. Fill in the resulting triangle using horizontal lines.
-------------------------------------------------------------------------- */
void FrameBuffer_solidtriangle(FrameBuffer *f, int tx1, int ty1,
int tx2, int ty2,
int tx3, int ty3, Pixel color) {
int tempx, tempy;
double m1,m2,m3;
int y;
int ix1, ix2;
/* Figure out which point has the greatest "y" value */
if (ty2 > ty1) { /* Swap points 1 and 2 if 2 is higher */
tempx = tx1;
tempy = ty1;
tx1 = tx2;
ty1 = ty2;
tx2 = tempx;
ty2 = tempy;
}
if (ty3 > ty1) { /* Swap points 1 and 3 if 3 is higher */
tempx = tx1;
tempy = ty1;
tx1 = tx3;
ty1 = ty3;
tx3 = tempx;
ty3 = tempy;
}
if (ty3 > ty2) { /* Swap points 2 and 3 if 3 is higher */
tempx = tx2;
tempy = ty2;
tx2 = tx3;
ty2 = ty3;
tx3 = tempx;
ty3 = tempy;
}
/* Points are now order so that t_1 is the highest point, t_2 is the
middle point, and t_3 is the lowest point */
/* Check for degenerate cases here */
if ((ty1 == ty2) && (ty2 == ty3)) {
/* Points are aligned horizontally. Handle as a special case */
/* Just draw three lines using the outline color */
FrameBuffer_line(f,tx1,ty1,tx2,ty2,color);
FrameBuffer_line(f,tx1,ty1,tx3,ty3,color);
FrameBuffer_line(f,tx2,ty2,tx3,ty3,color);
} else {
if (ty2 < ty1) {
/* First process line segments between (x1,y1)-(x2,y2)
And between (x1,y1),(x3,y3) */
m1 = (double) (tx2 - tx1)/(double) (ty2 - ty1);
m2 = (double) (tx3 - tx1)/(double) (ty3 - ty1);
y = ty1;
while (y >= ty2) {
/* Calculate x values from slope */
ix1 = (int) (m1*(y-ty1)+0.5) + tx1;
ix2 = (int) (m2*(y-ty1)+0.5) + tx1;
if (ix1 > ix2)
FrameBuffer_horizontal(f,ix2,ix1,y,color);
else
FrameBuffer_horizontal(f,ix1,ix2,y,color);
y--;
}
}
if (ty3 < ty2) {
/* Draw lower half of the triangle */
m2 = (double) (tx3 - tx1)/(double) (ty3 - ty1);
m3 = (double) (tx3 - tx2)/(double)(ty3 - ty2);
y = ty2;
while (y >= ty3) {
ix1 = (int) (m3*(y-ty2)+0.5)+tx2;
ix2 = (int) (m2*(y-ty1)+0.5)+tx1;
if (ix1 > ix2)
FrameBuffer_horizontal(f,ix2,ix1,y,color);
else
FrameBuffer_horizontal(f,ix1,ix2,y,color);
y--;
}
}
}
}
/* -------------------------------------------------------------------------
FrameBuffer_interptriangle(FrameBuffer *f,
int tx1, int ty2, Pixel c1,
int tx2, int ty2, Pixel c2,
int tx3, int ty3, Pixel c3)
This function draws a filled triangle with color
interpolation.
General idea :
1. Transform the three points into screen coordinates
2. Order three points vertically on screen.
3. Check for degenerate cases (where 3 points are colinear).
4. Fill in the resulting triangle using horizontal lines.
5. Colors are interpolated between end points
-------------------------------------------------------------------------- */
void FrameBuffer_interptriangle(FrameBuffer *f,
int tx1, int ty1, Pixel c1,
int tx2, int ty2, Pixel c2,
int tx3, int ty3, Pixel c3) {
int tempx, tempy;
double m1,m2,m3;
double mc1,mc2,mc3;
Pixel ic1,ic2,tempc;
int y;
int ix1, ix2;
/* Figure out which point has the greatest "y" value */
if (ty2 > ty1) { /* Swap points 1 and 2 if 2 is higher */
tempx = tx1;
tempy = ty1;
tempc = c1;
tx1 = tx2;
ty1 = ty2;
c1 = c2;
tx2 = tempx;
ty2 = tempy;
c2 = tempc;
}
if (ty3 > ty1) { /* Swap points 1 and 3 if 3 is higher */
tempx = tx1;
tempy = ty1;
tempc = c1;
tx1 = tx3;
ty1 = ty3;
c1 = c3;
tx3 = tempx;
ty3 = tempy;
c3 = tempc;
}
if (ty3 > ty2) { /* Swap points 2 and 3 if 3 is higher */
tempx = tx2;
tempy = ty2;
tempc = c2;
tx2 = tx3;
ty2 = ty3;
c2 = c3;
tx3 = tempx;
ty3 = tempy;
c3 = tempc;
}
/* Points are now order so that t_1 is the highest point, t_2 is the
middle point, and t_3 is the lowest point */
/* Check for degenerate cases here */
if ((ty1 == ty2) && (ty2 == ty3)) {
/* Points are aligned horizontally. Handle as a special case */
/* Just draw three lines using the outline color */
if (tx2 > tx1)
FrameBuffer_horizontalinterp(f,tx1,tx2,ty1,c1,c2);
else
FrameBuffer_horizontalinterp(f,tx2,tx1,ty1,c2,c1);
if (tx3 > tx1)
FrameBuffer_horizontalinterp(f,tx1,tx3,ty1,c1,c3);
else
FrameBuffer_horizontalinterp(f,tx3,tx1,ty1,c3,c1);
if (tx3 > tx2)
FrameBuffer_horizontalinterp(f,tx2,tx3,ty2,c2,c3);
else
FrameBuffer_horizontalinterp(f,tx3,tx2,ty2,c3,c2);
} else {
/* First process line segments between (x1,y1)-(x2,y2)
And between (x1,y1),(x3,y3) */
if (ty2 < ty1) {
m1 = (double) (tx2 - tx1)/(double) (ty2 - ty1);
m2 = (double) (tx3 - tx1)/(double) (ty3 - ty1);
mc1 = (c2 - c1)/(double) (ty2 - ty1);
mc2 = (c3 - c1)/(double) (ty3 - ty1);
y = ty1;
while (y >= ty2) {
/* Calculate x values from slope */
ix1 = (int) (m1*(y-ty1)+0.5) + tx1;
ix2 = (int) (m2*(y-ty1)+0.5) + tx1;
ic1 = (int) (mc1*(y-ty1) + c1);
ic2 = (int) (mc2*(y-ty1) + c1);
if (ix1 > ix2)
FrameBuffer_horizontalinterp(f,ix2,ix1,y,ic2,ic1);
else
FrameBuffer_horizontalinterp(f,ix1,ix2,y,ic1,ic2);
y--;
}
}
if (ty3 < ty2) {
/* Draw lower half of the triangle */
m2 = (double) (tx3 - tx1)/(double) (ty3 - ty1);
mc2 = (c3 - c1)/(double) (ty3 - ty1);
m3 = (double) (tx3 - tx2)/(double)(ty3 - ty2);
mc3 = (c3 - c2)/(double) (ty3 - ty2);
y = ty2;
while (y >= ty3) {
ix1 = (int) (m3*(y-ty2)+0.5)+tx2;
ix2 = (int) (m2*(y-ty1)+0.5)+tx1;
ic1 = (int) (mc3*(y-ty2)+c2);
ic2 = (int) (mc2*(y-ty1)+c1);
if (ix1 > ix2)
FrameBuffer_horizontalinterp(f,ix2,ix1,y,ic2,ic1);
else
FrameBuffer_horizontalinterp(f,ix1,ix2,y,ic1,ic2);
y--;
}
}
}
}

View file

@ -0,0 +1,572 @@
/* -----------------------------------------------------------------------------
* gif.c
*
* GIF encoding with broken compression algorithm to avoid LZW.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
* Copyright (C) 1995-1996
*
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
/*
* xvgifwr.c - handles writing of GIF files. based on flgife.c and
* flgifc.c from the FBM Library, by Michael Maudlin
*
* Contains:
* WriteGIF(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
* comment)
*
* Note: slightly brain-damaged, in that it'll only write non-interlaced
* GIF files (in the interests of speed, or something)
*
*/
/*****************************************************************
* Portions of this code Copyright (C) 1989 by Michael Mauldin.
* Permission is granted to use this file in whole or in
* part for any purpose, educational, recreational or commercial,
* provided that this copyright notice is retained unchanged.
* This software is available to all free of charge by anonymous
* FTP and in the UUNET archives.
*
*
* Authors: Michael Mauldin (mlm@cs.cmu.edu)
* David Rowley (mgardi@watdcsu.waterloo.edu)
*
* Based on: compress.c - File compression ala IEEE Computer, June 1984.
*
* Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
* Jim McKie (decvax!mcvax!jim)
* Steve Davies (decvax!vax135!petsd!peora!srd)
* Ken Turkowski (decvax!decwrl!turtlevax!ken)
* James A. Woods (decvax!ihnp4!ames!jaw)
* Joe Orost (decvax!vax135!petsd!joe)
*****************************************************************/
#include "gifplot.h"
#include <string.h>
typedef long int count_int;
typedef unsigned char byte;
static int gif_error;
static unsigned char *op;
static int Width, Height;
static int curx, cury;
static int Interlace;
static void putgifword(int);
static void compress(int, byte **, int);
static void output_GIF(int);
static void cl_block(void);
static void cl_hash(count_int);
static void char_init(void);
static void char_out(int);
static void flush_char(void);
static void *OutBuffer;
static int OutBufSize;
static FrameBuffer *GIF_frame;
static unsigned char pc2nc[256],r1[256],g1[256],b1[256];
/*************************************************************/
int FrameBuffer_makeGIF(FrameBuffer *f, ColorMap *c, void *outbuffer, unsigned int outbufsize)
{
int RWidth, RHeight;
int LeftOfs, TopOfs;
int ColorMapSize, InitCodeSize, Background, BitsPerPixel;
int i,j,nc;
char *rmap, *gmap, *bmap;
char *cmap;
int count;
Interlace = 0;
Background = 0;
OutBuffer = outbuffer;
OutBufSize = outbufsize;
GIF_frame = f;
cmap = (char *) c->cmap;
op = (unsigned char *) outbuffer;
gif_error = 0;
for (i=0; i<256; i++) { pc2nc[i] = r1[i] = g1[i] = b1[i] = 0; }
/* compute number of unique colors */
nc = 0;
rmap = &cmap[0];
gmap = &cmap[256];
bmap = &cmap[512];
for (i=0; i<256; i++) {
/* see if color #i is already used */
for (j=0; j<i; j++) {
if (rmap[i] == rmap[j] && gmap[i] == gmap[j] &&
bmap[i] == bmap[j]) break;
}
if (j==i) { /* wasn't found */
pc2nc[i] = nc;
r1[nc] = rmap[i];
g1[nc] = gmap[i];
b1[nc] = bmap[i];
nc++;
}
else pc2nc[i] = pc2nc[j];
}
/* figure out 'BitsPerPixel' */
for (i=1; i<8; i++)
if ( (1<<i) >= nc) break;
BitsPerPixel = i;
ColorMapSize = 1 << BitsPerPixel;
RWidth = Width = f->width;
RHeight = Height = f->height;
LeftOfs = TopOfs = 0;
if (BitsPerPixel <= 1) InitCodeSize = 2;
else InitCodeSize = BitsPerPixel;
curx = 0;
cury = f->height - 1;
strcpy((char *) op,"GIF89a"); /* Put in GIF magic number */
op+=6;
putgifword(RWidth); /* screen descriptor */
putgifword(RHeight);
i = 0x80; /* Yes, there is a color map */
i |= (8-1)<<4; /* OR in the color resolution (hardwired 8) */
i |= (BitsPerPixel - 1); /* OR in the # of bits per pixel */
*(op++) = i;
*(op++) = Background; /* background color */
*(op++) = 0;
for (i=0; i<ColorMapSize; i++) { /* write out Global colormap */
*(op++) = r1[i];
*(op++) = g1[i];
*(op++) = b1[i];
}
*(op++) = ','; /* image separator */
/* Write the Image header */
putgifword(LeftOfs);
putgifword(TopOfs);
putgifword(Width);
putgifword(Height);
*(op++) = 0;
*(op++) = InitCodeSize;
compress(InitCodeSize+1, f->pixels, f->width*f->height);
*(op++) = 0;
*(op++) = ';';
count = (op - (unsigned char *) OutBuffer);
if (gif_error) return -1;
else return count;
}
/******************************/
static void putgifword(w)
int w;
{
/* writes a 16-bit integer in GIF order (LSB first) */
*(op++) = w & 0xff;
*(op++) = (w>>8)&0xff;
}
/***********************************************************************/
static unsigned long cur_accum = 0;
static int cur_bits = 0;
#define GP_BITS 12 /* BITS was already defined on some systems */
#define HSIZE 5003 /* 80% occupancy */
typedef unsigned char char_type;
static int n_bits; /* number of bits/code */
static int maxbits = GP_BITS; /* user settable max # bits/code */
static int maxcode; /* maximum code, given n_bits */
static int maxmaxcode = 1 << GP_BITS; /* NEVER generate this */
#define MAXCODE(n_bits) ( (1 << (n_bits)) - 1)
static count_int *htab;
static unsigned short *codetab;
static GIFOutBufSize;
/* static count_int htab [HSIZE];
static unsigned short codetab [HSIZE]; */
#define HashTabOf(i) htab[i]
#define CodeTabOf(i) codetab[i]
static int hsize = HSIZE; /* for dynamic table sizing */
/*
* To save much memory, we overlay the table used by compress() with those
* used by decompress(). The tab_prefix table is the same size and type
* as the codetab. The tab_suffix table needs 2**BITS characters. We
* get this from the beginning of htab. The output stack uses the rest
* of htab, and contains characters. There is plenty of room for any
* possible stack (stack used to be 8000 characters).
*/
#define tab_prefixof(i) CodeTabOf(i)
#define tab_suffixof(i) ((char_type *)(htab))[i]
#define de_stack ((char_type *)&tab_suffixof(1<<GP_BITS))
static int free_ent = 0; /* first unused entry */
/*
* block compression parameters -- after all codes are used up,
* and compression rate changes, start over.
*/
static int clear_flg = 0;
static long int out_count = 0; /* # of codes output (for debugging) */
/*
* compress stdin to stdout
*
* Algorithm: use open addressing double hashing (no chaining) on the
* prefix code / next character combination. We do a variant of Knuth's
* algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
* secondary probe. Here, the modular division first probe is gives way
* to a faster exclusive-or manipulation. Also do block compression with
* an adaptive reset, whereby the code table is cleared when the compression
* ratio decreases, but after the table fills. The variable-length output
* codes are re-sized at this point, and a special CLEAR code is generated
* for the decompressor. Late addition: construct the table according to
* file size for noticeable speed improvement on small files. Please direct
* questions about this implementation to ames!jaw.
*/
static int g_init_bits;
static int ClearCode;
static int EOFCode;
/********************************************************/
static void compress(init_bits, data, len)
int init_bits;
unsigned char **data;
int len;
{
register long fcode;
register int i = 0;
register int c;
register int ent;
register int disp;
register int hsize_reg;
register int hshift;
int code_count = 0;
/* Use the output buffer as temporary storage for GIF data */
if (OutBufSize < HSIZE*(sizeof(count_int) + sizeof(unsigned short))) {
gif_error =1;
return;
}
/* Put htab and codetab arrays into the output buffer */
GIFOutBufSize = OutBufSize - HSIZE*(sizeof(count_int) + sizeof(unsigned short)) - 16;
GIFOutBufSize = GIFOutBufSize & (~0x3); /* Make sure it's double word alligned */
htab = (count_int *) ((char *) OutBuffer + GIFOutBufSize);
codetab = (unsigned short *) ((char *) OutBuffer + GIFOutBufSize + HSIZE*sizeof(count_int));
/*
* Set up the globals: g_init_bits - initial number of bits
* g_outfile - pointer to output file
*/
g_init_bits = init_bits;
/* initialize 'compress' globals */
maxbits = GP_BITS;
maxmaxcode = 1<<GP_BITS;
memset(htab,0,sizeof(htab));
memset(codetab,0,sizeof(codetab));
hsize = HSIZE;
free_ent = 0;
clear_flg = 0;
out_count = 0;
cur_accum = 0;
cur_bits = 0;
/*
* Set up the necessary values
*/
out_count = 0;
clear_flg = 0;
maxcode = MAXCODE(n_bits = g_init_bits);
ClearCode = (1 << (init_bits - 1));
EOFCode = ClearCode + 1;
free_ent = ClearCode + 2;
char_init();
ent = pc2nc[data[cury][curx]];
curx++;
if (curx >= GIF_frame->width) {
curx = 0;
cury--;
}
len--;
hshift = 0;
for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
hshift++;
hshift = 8 - hshift; /* set hash code range bound */
hsize_reg = hsize;
cl_hash( (count_int) hsize_reg); /* clear hash table */
output_GIF(ClearCode);
while (len) {
c = pc2nc[data[cury][curx]];
curx++;
if (curx >= GIF_frame->width) {
curx = 0;
cury--;
}
len--;
/* Uncompressed GIF */
output_GIF(ent);
code_count++;
if (code_count >= ClearCode-2) {
output_GIF(ClearCode);
code_count = 0;
}
ent = c;
}
/* Put out the final code */
output_GIF(ent);
output_GIF(EOFCode);
}
/*****************************************************************
* TAG( output_GIF )
*
* Output the given code.
* Inputs:
* code: A n_bits-bit integer. If == -1, then EOF. This assumes
* that n_bits =< (long)wordsize - 1.
* Outputs:
* Outputs code to the file.
* Assumptions:
* Chars are 8 bits long.
* Algorithm:
* Maintain a BITS character long buffer (so that 8 codes will
* fit in it exactly). Use the VAX insv instruction to insert each
* code in turn. When the buffer fills up empty it and start over.
*/
static
unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
0x001F, 0x003F, 0x007F, 0x00FF,
0x01FF, 0x03FF, 0x07FF, 0x0FFF,
0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
static void output_GIF(code)
int code;
{
cur_accum &= masks[cur_bits];
if (cur_bits > 0)
cur_accum |= ((long)code << cur_bits);
else
cur_accum = code;
cur_bits += n_bits;
while( cur_bits >= 8 ) {
char_out( (int) (cur_accum & 0xff) );
cur_accum >>= 8;
cur_bits -= 8;
}
/*
* If the next entry is going to be too big for the code size,
* then increase it, if possible.
*/
if (free_ent > maxcode || clear_flg) {
if( clear_flg ) {
maxcode = MAXCODE (n_bits = g_init_bits);
clear_flg = 0;
}
else {
n_bits++;
if ( n_bits == maxbits )
maxcode = maxmaxcode;
else
maxcode = MAXCODE(n_bits);
}
}
if( code == EOFCode ) {
/* At EOF, write the rest of the buffer */
while( cur_bits > 0 ) {
char_out( (int)(cur_accum & 0xff) );
cur_accum >>= 8;
cur_bits -= 8;
}
flush_char();
}
}
/********************************/
static void cl_block () /* table clear for block compress */
{
/* Clear out the hash table */
cl_hash ( (count_int) hsize );
free_ent = ClearCode + 2;
clear_flg = 1;
output_GIF(ClearCode);
}
/********************************/
static void cl_hash(hsize) /* reset code table */
register count_int hsize;
{
register count_int *htab_p = htab+hsize;
register long i;
register long m1 = -1;
i = hsize - 16;
do { /* might use Sys V memset(3) here */
*(htab_p-16) = m1;
*(htab_p-15) = m1;
*(htab_p-14) = m1;
*(htab_p-13) = m1;
*(htab_p-12) = m1;
*(htab_p-11) = m1;
*(htab_p-10) = m1;
*(htab_p-9) = m1;
*(htab_p-8) = m1;
*(htab_p-7) = m1;
*(htab_p-6) = m1;
*(htab_p-5) = m1;
*(htab_p-4) = m1;
*(htab_p-3) = m1;
*(htab_p-2) = m1;
*(htab_p-1) = m1;
htab_p -= 16;
} while ((i -= 16) >= 0);
for ( i += 16; i > 0; i-- )
*--htab_p = m1;
}
/******************************************************************************
*
* GIF Specific routines
*
******************************************************************************/
/*
* Number of characters so far in this 'packet'
*/
static int a_count;
/*
* Set up the 'byte output' routine
*/
static void char_init()
{
a_count = 0;
}
/*
* Define the storage for the packet accumulator
*/
static char accum[ 256 ];
/*
* Add a character to the end of the current packet, and if it is 254
* characters, flush the packet to disk.
*/
static void char_out(c)
int c;
{
accum[ a_count++ ] = c;
if( a_count >= 254 )
flush_char();
}
/*
* Flush the packet to disk, and reset the accumulator
*/
static void flush_char()
{
if (gif_error) return;
if( a_count > 0 ) {
*(op++) = a_count;
memcpy(op,accum,a_count);
op+=a_count;
a_count = 0;
if (op > (unsigned char *) ((char *) OutBuffer + (GIFOutBufSize - 2048))) {
gif_error = 1;
}
}
}
/* ----------------------------------------------------------------------
int FrameBuffer_writeGIF(char *filename)
Write a GIF file to filename
----------------------------------------------------------------------- */
int FrameBuffer_writeGIF(FrameBuffer *f, ColorMap *c, char *filename) {
FILE *file;
void *buffer;
int nbytes;
int bufsize;
file = fopen(filename,"wb");
if (file == NULL) return -1;
bufsize = (f->width*f->height*3)/2;
buffer = (void *) malloc(bufsize);
nbytes = FrameBuffer_makeGIF(f,c,buffer,bufsize);
if (nbytes == -1) {
free(buffer);
fclose(file);
return -1;
}
fwrite(buffer,nbytes,1,file);
fclose(file);
free(buffer);
return 0;
}

View file

@ -0,0 +1,343 @@
/* -----------------------------------------------------------------------------
* matrix.c
*
* Some 4x4 matrix operations
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
* Copyright (C) 1995-1996
*
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
#define MATRIX
#include "gifplot.h"
#include <math.h>
/* ------------------------------------------------------------------------
Matrix new_Matrix()
Create a new 4x4 matrix.
------------------------------------------------------------------------ */
Matrix
new_Matrix() {
Matrix m;
m = (Matrix) malloc(16*sizeof(double));
return m;
}
/* ------------------------------------------------------------------------
delete_Matrix(Matrix *m);
Destroy a matrix
------------------------------------------------------------------------ */
void
delete_Matrix(Matrix m) {
if (m)
free((char *) m);
}
/* ------------------------------------------------------------------------
Matrix Matrix_copy(Matrix a)
Makes a copy of matrix a and returns it.
------------------------------------------------------------------------ */
Matrix Matrix_copy(Matrix a) {
int i;
Matrix r = 0;
if (a) {
r = new_Matrix();
if (r) {
for (i = 0; i < 16; i++)
r[i] = a[i];
}
}
return r;
}
/* ------------------------------------------------------------------------
Matrix_multiply(Matrix a, Matrix b, Matrix c)
Multiplies a*b = c
c may be one of the source matrices
------------------------------------------------------------------------ */
void
Matrix_multiply(Matrix a, Matrix b, Matrix c) {
double temp[16];
int i,j,k;
for (i =0; i < 4; i++)
for (j = 0; j < 4; j++) {
temp[i*4+j] = 0.0;
for (k = 0; k < 4; k++)
temp[i*4+j] += a[i*4+k]*b[k*4+j];
}
for (i = 0; i < 16; i++)
c[i] = temp[i];
}
/* ------------------------------------------------------------------------
Matrix_identity(Matrix a)
Puts an identity matrix in matrix a
------------------------------------------------------------------------ */
void
Matrix_identity(Matrix a) {
int i;
for (i = 0; i < 16; i++) a[i] = 0;
a[0] = 1;
a[5] = 1;
a[10] = 1;
a[15] = 1;
}
/* ------------------------------------------------------------------------
Matrix_zero(Matrix a)
Puts a zero matrix in matrix a
------------------------------------------------------------------------ */
void
Matrix_zero(Matrix a) {
int i;
for (i = 0; i < 16; i++) a[i] = 0;
}
/* ------------------------------------------------------------------------
Matrix_transpose(Matrix a, Matrix result)
Transposes matrix a and puts it in result.
------------------------------------------------------------------------ */
void
Matrix_transpose(Matrix a, Matrix result) {
double temp[16];
int i,j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
temp[4*i+j] = a[4*j+i];
for (i = 0; i < 16; i++)
result[i] = temp[i];
}
/* ------------------------------------------------------------------------
Matrix_gauss(Matrix a, Matrix b)
Solves ax=b for x, using Gaussian elimination. Destroys a.
Really only used for calculating inverses of 4x4 transformation
matrices.
------------------------------------------------------------------------ */
void Matrix_gauss(Matrix a, Matrix b) {
int ipiv[4], indxr[4], indxc[4];
int i,j,k,l,ll;
int irow=0, icol=0;
double big, pivinv;
double dum;
for (j = 0; j < 4; j++)
ipiv[j] = 0;
for (i = 0; i < 4; i++) {
big = 0;
for (j = 0; j < 4; j++) {
if (ipiv[j] != 1) {
for (k = 0; k < 4; k++) {
if (ipiv[k] == 0) {
if (fabs(a[4*j+k]) >= big) {
big = fabs(a[4*j+k]);
irow = j;
icol = k;
}
} else if (ipiv[k] > 1)
return; /* Singular matrix */
}
}
}
ipiv[icol] = ipiv[icol]+1;
if (irow != icol) {
for (l = 0; l < 4; l++) {
dum = a[4*irow+l];
a[4*irow+l] = a[4*icol+l];
a[4*icol+l] = dum;
}
for (l = 0; l < 4; l++) {
dum = b[4*irow+l];
b[4*irow+l] = b[4*icol+l];
b[4*icol+l] = dum;
}
}
indxr[i] = irow;
indxc[i] = icol;
if (a[4*icol+icol] == 0) return;
pivinv = 1.0/a[4*icol+icol];
a[4*icol+icol] = 1.0;
for (l = 0; l < 4; l++)
a[4*icol+l] = a[4*icol+l]*pivinv;
for (l = 0; l < 4; l++)
b[4*icol+l] = b[4*icol+l]*pivinv;
for (ll = 0; ll < 4; ll++) {
if (ll != icol) {
dum = a[4*ll+icol];
a[4*ll+icol] = 0;
for (l = 0; l < 4; l++)
a[4*ll+l] = a[4*ll+l] - a[4*icol+l]*dum;
for (l = 0; l < 4; l++)
b[4*ll+l] = b[4*ll+l] - b[4*icol+l]*dum;
}
}
}
for (l = 3; l >= 0; l--) {
if (indxr[l] != indxc[l]) {
for (k = 0; k < 4; k++) {
dum = a[4*k+indxr[l]];
a[4*k+indxr[l]] = a[4*k+indxc[l]];
a[4*k+indxc[l]] = dum;
}
}
}
}
/* ------------------------------------------------------------------------
Matrix_invert(Matrix a, Matrix inva)
Inverts Matrix a and places the result in inva.
Relies on the Gaussian Elimination code above. (See Numerical recipes).
------------------------------------------------------------------------ */
void
Matrix_invert(Matrix a, Matrix inva) {
double temp[16];
int i;
for (i = 0; i < 16; i++)
temp[i] = a[i];
Matrix_identity(inva);
Matrix_gauss(temp,inva);
}
/* ------------------------------------------------------------------------
Matrix_transform(Matrix a, GL_Vector *r, GL_Vector *t)
Transform a vector. a*r ----> t
------------------------------------------------------------------------ */
void Matrix_transform(Matrix a, GL_Vector *r, GL_Vector *t) {
double rx, ry, rz, rw;
rx = r->x;
ry = r->y;
rz = r->z;
rw = r->w;
t->x = a[0]*rx + a[1]*ry + a[2]*rz + a[3]*rw;
t->y = a[4]*rx + a[5]*ry + a[6]*rz + a[7]*rw;
t->z = a[8]*rx + a[9]*ry + a[10]*rz + a[11]*rw;
t->w = a[12]*rx + a[13]*ry + a[14]*rz + a[15]*rw;
}
/* ------------------------------------------------------------------------
Matrix_transform4(Matrix a, double x, double y, double z, double w, GL_Vector *t)
Transform a vector from a point specified as 4 doubles
------------------------------------------------------------------------ */
void Matrix_transform4(Matrix a, double rx, double ry, double rz, double rw,
GL_Vector *t) {
t->x = a[0]*rx + a[1]*ry + a[2]*rz + a[3]*rw;
t->y = a[4]*rx + a[5]*ry + a[6]*rz + a[7]*rw;
t->z = a[8]*rx + a[9]*ry + a[10]*rz + a[11]*rw;
t->w = a[12]*rx + a[13]*ry + a[14]*rz + a[15]*rw;
}
/* ---------------------------------------------------------------------
Matrix_translate(Matrix a, double tx, double ty, double tz)
Put a translation matrix in Matrix a
---------------------------------------------------------------------- */
void Matrix_translate(Matrix a, double tx, double ty, double tz) {
Matrix_identity(a);
a[3] = tx;
a[7] = ty;
a[11] = tz;
a[15] = 1;
}
/* -----------------------------------------------------------------------
Matrix_rotatex(Matrix a, double deg)
Produce an x-rotation matrix for given angle in degrees.
----------------------------------------------------------------------- */
void
Matrix_rotatex(Matrix a, double deg) {
double r;
r = 3.1415926*deg/180.0;
Matrix_zero(a);
a[0] = 1.0;
a[5] = cos(r);
a[6] = -sin(r);
a[9] = sin(r);
a[10] = cos(r);
a[15] = 1.0;
}
/* -----------------------------------------------------------------------
Matrix_rotatey(Matrix a, double deg)
Produce an y-rotation matrix for given angle in degrees.
----------------------------------------------------------------------- */
void
Matrix_rotatey(Matrix a, double deg) {
double r;
r = 3.1415926*deg/180.0;
Matrix_zero(a);
a[0] = cos(r);
a[2] = sin(r);
a[5] = 1.0;
a[8] = -sin(r);
a[10] = cos(r);
a[15] = 1;
}
/* -----------------------------------------------------------------------
Matrix_RotateZ(Matrix a, double deg)
Produce an z-rotation matrix for given angle in degrees.
----------------------------------------------------------------------- */
void
Matrix_rotatez(Matrix a, double deg) {
double r;
r = 3.1415926*deg/180.0;
Matrix_zero(a);
a[0] = cos(r);
a[1] = -sin(r);
a[4] = sin(r);
a[5] = cos(r);
a[10] = 1.0;
a[15] = 1.0;
}
/* A debugging routine */
void Matrix_set(Matrix a, int i, int j, double val) {
a[4*j+i] = val;
}
void Matrix_print(Matrix a) {
int i,j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
fprintf(stdout,"%10f ",a[4*i+j]);
}
fprintf(stdout,"\n");
}
fprintf(stdout,"\n");
}

View file

@ -0,0 +1,159 @@
/* -----------------------------------------------------------------------------
* pixmap.c
*
* Pixel maps (i.e., bitmaps)
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
* Copyright (C) 1995-1996
*
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
#define PIXMAP
#include "gifplot.h"
/* -----------------------------------------------------------------------
PixMap *new_PixMap(int width, int height, int centerx, int centery)
Create a new pixmap of given size
----------------------------------------------------------------------- */
PixMap *new_PixMap(int width, int height, int centerx, int centery) {
PixMap *pm;
if ((width > 0) && (height > 0)) {
pm = (PixMap *) malloc(sizeof(PixMap));
pm->width = width;
pm->height = height;
pm->centerx = centerx;
pm->centery = centery;
pm->map = (int *) malloc(height*width*sizeof(int));
return pm;
}
return (PixMap *) 0;
}
/* --------------------------------------------------------------------------
void delete_PixMap(PixMap *pm)
Destroy a pixmap
-------------------------------------------------------------------------- */
void delete_PixMap(PixMap *pm) {
if (pm) {
free((char *) pm->map);
free((char *) pm);
}
}
/* ---------------------------------------------------------------------------
void PixMap_set(PixMap *pm, int x, int y, int pix)
Set a pixel in the bitmap
--------------------------------------------------------------------------- */
void
PixMap_set(PixMap *pm, int x, int y, int pix) {
if ((x < 0) || (x>=pm->width)) return;
if ((y < 0) || (y>=pm->height)) return;
pm->map[pm->width*y + x] = pix;
}
/* -----------------------------------------------------------------------------
void FrameBuffer_drawpixmap(FrameBuffer *f, PixMap *pm, int x, int y, int fgcolor, int bgcolor)
Draw a pixmap onto the framebuffer. This is somewhat optimized for speed.
------------------------------------------------------------------------------ */
void
FrameBuffer_drawpixmap(FrameBuffer *f, PixMap *pm, int x, int y, int fgcolor, int bgcolor) {
int startx, starty; /* Starting location on framebuffer */
int startpixx = 0, startpixy = 0; /* Starting location in pixmap */
int endx, endy; /* Ending location on framebuffer */
int i,j, px, py;
int c;
startx = x - pm->centerx;
starty = y + pm->centery;
endx = startx + pm->width;
endy = starty - pm->height;
/* Figure out if we need to clip */
if (startx < f->xmin) {
startpixx = f->xmin - startx;
startx = f->xmin;
}
if (starty >= f->ymax) {
startpixy = starty - f->ymax;
starty = f->ymax-1;
}
if (endx >= f->xmax) {
endx = f->xmax-1;
}
if (endy < f->ymin) {
endy = f->ymin;
}
py = startpixy;
for (j = starty; j >= endy; j--) {
px = startpixx;
for (i = startx; i < endx; i++) {
c = pm->map[py*pm->width + px];
switch (c) {
case FOREGROUND:
f->pixels[j][i] = fgcolor;
break;
case BACKGROUND:
f->pixels[j][i] = bgcolor;
break;
default:
break;
}
px++;
}
py++;
}
}
/**************************************************************************
* Some common PixMaps (for plotting)
*
**************************************************************************/
int _SQUARE_MAP[] = {
0,1,1,1,1,1,1,1,
0,1,1,1,1,1,1,1,
0,1,1,1,1,1,1,1,
0,1,1,1,1,1,1,1,
0,1,1,1,1,1,1,1,
0,1,1,1,1,1,1,1,
0,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0 };
PixMap PixMap_SQUARE = { 8,8,4,4, _SQUARE_MAP};
int _TRIANGLE_MAP[] = {
0,0,0,1,0,0,0,0,
0,0,0,1,0,0,0,0,
0,0,1,1,1,0,0,0,
0,0,1,1,1,0,0,0,
0,1,1,1,1,1,0,0,
0,1,1,1,1,1,0,0,
1,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0 };
PixMap PixMap_TRIANGLE = { 8,8,4,4,_TRIANGLE_MAP};
int _CROSS_MAP[] = {
0,0,0,1,0,0,0,0,
0,0,0,1,0,0,0,0,
0,0,0,1,0,0,0,0,
1,1,1,1,1,1,1,0,
0,0,0,1,0,0,0,0,
0,0,0,1,0,0,0,0,
0,0,0,1,0,0,0,0,
0,0,0,0,0,0,0,0 };
PixMap PixMap_CROSS = { 8,8,4,4,_CROSS_MAP};

View file

@ -0,0 +1,445 @@
/* -----------------------------------------------------------------------------
* plot2d.c
*
* 2-Dimensional plotting
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
* Copyright (C) 1995-1996
*
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
#define PLOT2D
#include "gifplot.h"
/* ------------------------------------------------------------------------
Plot2D *new_Plot2D(FrameBuffer *frame, xmin, ymin, xmax, ymax)
Create a new 2D plot with given minimum and maximum coordinates.
------------------------------------------------------------------------ */
Plot2D *new_Plot2D(FrameBuffer *frame,double xmin,double ymin,double xmax,double ymax) {
Plot2D *p2;
if (frame) {
if (xmax <= xmin) return (Plot2D *) 0;
if (ymax <= ymin) return (Plot2D *) 0;
p2 = (Plot2D *) malloc(sizeof(Plot2D));
p2->frame = frame;
p2->xmin = xmin;
p2->ymin = ymin;
p2->xmax = xmax;
p2->ymax = ymax;
p2->view_xmin = 0;
p2->view_xmax = frame->width;
p2->view_ymin = 0;
p2->view_ymax = frame->height;
p2->xscale = LINEAR;
p2->yscale = LINEAR;
p2->dx = (p2->view_xmax - p2->view_xmin)/(p2->xmax - p2->xmin);
p2->dy = (p2->view_ymax - p2->view_ymin)/(p2->ymax - p2->ymin);
return p2;
}
return (Plot2D *) 0;
}
/* ----------------------------------------------------------------------------
delete_Plot2D(Plot2D *p2)
Delete a 2D plot
---------------------------------------------------------------------------- */
void
delete_Plot2D(Plot2D *p2) {
if (p2)
free((char *) p2);
}
/* -----------------------------------------------------------------------------
Plot2D *Plot2D_copy(Plot2D *p2)
Makes a copy of the Plot2D data structure.
----------------------------------------------------------------------------- */
Plot2D *Plot2D_copy(Plot2D *p2) {
Plot2D *c2;
if (p2) {
c2 = (Plot2D *) malloc(sizeof(Plot2D));
if (c2) {
c2->frame = p2->frame;
c2->view_xmin = p2->view_xmin;
c2->view_ymin = p2->view_ymin;
c2->view_xmax = p2->view_xmax;
c2->view_ymax = p2->view_ymax;
c2->xmin = p2->xmin;
c2->ymin = p2->ymin;
c2->xmax = p2->xmax;
c2->ymax = p2->ymax;
c2->xscale = p2->xscale;
c2->yscale = p2->yscale;
c2->dx = p2->dx;
c2->dy = p2->dy;
}
return c2;
} else {
return (Plot2D *) 0;
}
}
/* -----------------------------------------------------------------------------
Plot2D_clear(Plot2D *p2, Pixel c)
Clear the region assigned to this plot to the given color.
-------------------------------------------------------------------------- */
void Plot2D_clear(Plot2D *p2, Pixel c) {
int i,j;
for (i = p2->view_xmin; i < p2->view_xmax; i++)
for (j = p2->view_ymin; j < p2->view_ymax; j++) {
p2->frame->pixels[j][i] = c;
}
}
/* ------------------------------------------------------------------------------
Plot2D_setview
Sets the plot region on the framebuffer
------------------------------------------------------------------------------ */
void
Plot2D_setview(Plot2D *p2, int vxmin, int vymin, int vxmax, int vymax) {
if (p2) {
p2->view_xmin = vxmin;
p2->view_ymin = vymin;
p2->view_xmax = vxmax;
p2->view_ymax = vymax;
p2->dx = (p2->view_xmax - p2->view_xmin)/(p2->xmax - p2->xmin);
p2->dy = (p2->view_ymax - p2->view_ymin)/(p2->ymax - p2->ymin);
FrameBuffer_setclip(p2->frame,vxmin,vymin,vxmax,vymax);
}
}
/* -------------------------------------------------------------------------------
Plot2D_setrange(Plot2D *p2, double xmin, double ymin, double xmax, double ymax)
Sets the plotting range.
------------------------------------------------------------------------------- */
void
Plot2D_setrange(Plot2D *p2, double xmin, double ymin, double xmax, double ymax) {
if (p2) {
p2->xmin = xmin;
p2->ymin = ymin;
p2->xmax = xmax;
p2->ymax = ymax;
p2->dx = (p2->view_xmax - p2->view_xmin)/(p2->xmax - p2->xmin);
p2->dy = (p2->view_ymax - p2->view_ymin)/(p2->ymax - p2->ymin);
}
}
/* -------------------------------------------------------------------------------
Plot2D_setscale(Plot2D *p2, int xscale, int yscale)
Sets the plotting scaling method
------------------------------------------------------------------------------- */
void
Plot2D_setscale(Plot2D *p2, int xscale, int yscale) {
if (p2) {
p2->xscale = xscale;
p2->yscale = yscale;
}
}
/* ----------------------------------------------------------------------------
Plot2D_transform(Plot2D *p2, double x, double y, int *px, int *py)
Transforms x,y into screen coordinates px and py. Result is returned
in px and py. Rounds to the nearest pixel instead of truncating.
----------------------------------------------------------------------------- */
void
Plot2D_transform(Plot2D *p2, double x, double y, int *px, int *py) {
if (p2) {
*px = p2->view_xmin + (int) (p2->dx*(x-p2->xmin) + 0.5);
*py = p2->view_ymin + (int) (p2->dy*(y-p2->ymin) + 0.5);
}
}
/* -------------------------------------------------------------------------------
Plot2D_plot(Plot2D *p2, double x, double y, Pixel color)
Plot a 2D Point of a given color
------------------------------------------------------------------------------- */
void
Plot2D_plot(Plot2D *p2, double x, double y, Pixel color) {
int px, py;
Plot2D_transform(p2,x,y,&px,&py);
FrameBuffer_plot(p2->frame, px, py, color);
}
/* -------------------------------------------------------------------------------
Plot2D_box(Plot2D *p2, double x1, double y1, double x2, double y2, Pixel Color)
Plot an outline box on the 2D plot
------------------------------------------------------------------------------- */
void
Plot2D_box(Plot2D *p2, double x1, double y1,double x2, double y2, Pixel color) {
int ix1, ix2,iy1, iy2;
Plot2D_transform(p2,x1,y1,&ix1,&iy1);
Plot2D_transform(p2,x2,y2,&ix2,&iy2);
FrameBuffer_box(p2->frame,ix1,iy1,ix2,iy2,color);
}
/* -------------------------------------------------------------------------------
Plot2D_solidbox(Plot2D *p2, double x1, double y1, double x2, double y2, Pixel Color)
Plot a solid box box on the 2D plot
------------------------------------------------------------------------------- */
void
Plot2D_solidbox(Plot2D *p2, double x1, double y1,double x2, double y2, Pixel color) {
int ix1, ix2,iy1, iy2;
Plot2D_transform(p2,x1,y1,&ix1,&iy1);
Plot2D_transform(p2,x2,y2,&ix2,&iy2);
FrameBuffer_solidbox(p2->frame,ix1,iy1,ix2,iy2,color);
}
/* -------------------------------------------------------------------------------
Plot2D_interpbox(Plot2D *p2, double x1, double y1, double x2, double y2,
Pixel c1, Pixel c2, Pixel c3, Pixel c4)
Plot a color-interpolated box on the 2D plot
------------------------------------------------------------------------------- */
void
Plot2D_interpbox(Plot2D *p2, double x1, double y1,double x2, double y2,
Pixel c1, Pixel c2, Pixel c3, Pixel c4) {
int ix1, ix2,iy1, iy2;
Plot2D_transform(p2,x1,y1,&ix1,&iy1);
Plot2D_transform(p2,x2,y2,&ix2,&iy2);
FrameBuffer_interpbox(p2->frame,ix1,iy1,ix2,iy2,c1,c2,c3,c4);
}
/* -------------------------------------------------------------------------------
Plot2D_circle(Plot2D *p2, double x, double y, double radius, Pixel color)
Make an outline circle on the 2D plot.
------------------------------------------------------------------------------- */
void
Plot2D_circle(Plot2D *p2, double x, double y, double radius, Pixel color) {
int ix, iy, ir;
Plot2D_transform(p2,x,y,&ix,&iy);
ir = p2->dx * radius; /* This is really incorrect. Will need ellipse */
if (ir > 1)
FrameBuffer_circle(p2->frame,ix,iy,ir,color);
else
FrameBuffer_plot(p2->frame,ix,iy,color);
}
/* -------------------------------------------------------------------------------
Plot2D_solidcircle(Plot2D *p2, double x, double y, double radius, Pixel color)
Make an solid circle on the 2D plot.
------------------------------------------------------------------------------- */
void
Plot2D_solidcircle(Plot2D *p2, double x, double y, double radius, Pixel color) {
int ix, iy, ir;
Plot2D_transform(p2,x,y,&ix,&iy);
ir = p2->dx * radius; /* This is really incorrect. Will need ellipse */
if (ir > 1)
FrameBuffer_solidcircle(p2->frame,ix,iy,ir,color);
else
FrameBuffer_plot(p2->frame,ix,iy,color);
}
/* -------------------------------------------------------------------------------
Plot2D_line(Plot2D *p2, double x1, double y1, double x2, double y2, Pixel color)
Draw a line
------------------------------------------------------------------------------- */
void
Plot2D_line(Plot2D *p2, double x1, double y1, double x2, double y2, Pixel color) {
int ix1, ix2, iy1, iy2;
Plot2D_transform(p2,x1,y1,&ix1,&iy1);
Plot2D_transform(p2,x2,y2,&ix2,&iy2);
FrameBuffer_line(p2->frame,ix1,iy1,ix2,iy2,color);
}
/* -------------------------------------------------------------------------------
Plot2D_start(Plot2D *p2)
This should be called before starting to make a 2D plot. It will change
the viewport coordinates for the framebuffer and do other stuff.
------------------------------------------------------------------------------- */
void Plot2D_start(Plot2D *p2) {
if (p2) {
FrameBuffer_setclip(p2->frame, p2->view_xmin,p2->view_ymin,p2->view_xmax, p2->view_ymax);
p2->dx = (p2->view_xmax - p2->view_xmin)/(p2->xmax - p2->xmin);
p2->dy = (p2->view_ymax - p2->view_ymin)/(p2->ymax - p2->ymin);
}
}
/* --------------------------------------------------------------------------
void Plot2D_drawpixmap(Plot2D *p2, PixMap *pm, double x, double y, Pixel color, Pixel bgcolor)
Draw a pixel map at the given coordinates. (Used for putting symbols on 2D
plots).
-------------------------------------------------------------------------- */
void
Plot2D_drawpixmap(Plot2D *p2, PixMap *pm, double x, double y, Pixel color, Pixel bgcolor) {
int ix, iy;
Plot2D_transform(p2,x,y,&ix,&iy);
FrameBuffer_drawpixmap(p2->frame,pm,ix,iy,color,bgcolor);
}
/* ----------------------------------------------------------------------------
void Plot2D_xaxis(Plot2D *p2, double x, double y, double xtick, int ticklength, Pixel color)
Draw an X axis bar at location x,y with ticks spaced every xtick units.
Ticks are spaced starting at "x"
----------------------------------------------------------------------------- */
void Plot2D_xaxis(Plot2D *p2, double x, double y, double xtick, int ticklength, Pixel color) {
int ix, iy,iy2;
double xt;
/* Draw a line fox the axis */
Plot2D_line(p2,p2->xmin,y,p2->xmax,y,color);
xt = x;
while (xt >= p2->xmin) {
Plot2D_transform(p2,xt,y,&ix,&iy);
iy2 = iy+ticklength;
iy = iy-ticklength;
FrameBuffer_line(p2->frame,ix,iy,ix,iy2,color);
xt = xt - xtick;
}
xt = x + xtick;
while (xt < p2->xmax) {
Plot2D_transform(p2,xt,y,&ix,&iy);
iy2 = iy+ticklength;
iy = iy-ticklength;
FrameBuffer_line(p2->frame,ix,iy,ix,iy2,color);
xt = xt + xtick;
}
}
/* ----------------------------------------------------------------------------
void Plot2D_yaxis(Plot2D *p2, double x, double y, double ytick, int ticklength, Pixel c)
Draw an Y axis bar at location x,y with ticks spaced every xtick units.
Ticks are spaced starting at "y"
----------------------------------------------------------------------------- */
void Plot2D_yaxis(Plot2D *p2, double x, double y, double ytick, int ticklength, Pixel color) {
int ix, iy, ix2;
double yt;
/* Draw a line fox the axis */
Plot2D_line(p2,x,p2->ymin,x,p2->ymax,color);
yt = y;
while (yt >= p2->ymin) {
Plot2D_transform(p2,x,yt,&ix,&iy);
ix2 = ix+ticklength;
ix = ix-ticklength;
FrameBuffer_line(p2->frame,ix,iy,ix2,iy,color);
yt = yt - ytick;
}
yt = y + ytick;
while (yt < p2->ymax) {
Plot2D_transform(p2,x,yt,&ix,&iy);
ix2 = ix+ticklength;
ix = ix-ticklength;
FrameBuffer_line(p2->frame,ix,iy,ix2,iy,color);
yt = yt + ytick;
}
}
/* -------------------------------------------------------------------------
Plot2D_triangle(Plot2D *p2, double x1, double y1,
double x2, double y2,
double x3, double y3,
Pixel fillcolor)
This function draws a 2D outline triangle.
-------------------------------------------------------------------------- */
void Plot2D_triangle(Plot2D *p2, double x1, double y1,
double x2, double y2,
double x3, double y3, Pixel color) {
Plot2D_line(p2,x1,y1,x2,y2,color);
Plot2D_line(p2,x2,y2,x3,y3,color);
Plot2D_line(p2,x3,y3,x1,y1,color);
}
/* -------------------------------------------------------------------------
Plot2D_solidtriangle(Plot2D *p2, double x1, double y1,
double x2, double y2,
double x3, double y3,
Pixel color)
This function draws a 2D filled triangle. Can be used to
draw other primitives such as quadralaterals, etc...
-------------------------------------------------------------------------- */
void Plot2D_solidtriangle(Plot2D *p2, double x1, double y1,
double x2, double y2,
double x3, double y3, Pixel color) {
int tx1, tx2, tx3, ty1, ty2, ty3;
/* Transform the three points into screen coordinates */
Plot2D_transform(p2,x1,y1,&tx1,&ty1);
Plot2D_transform(p2,x2,y2,&tx2,&ty2);
Plot2D_transform(p2,x3,y3,&tx3,&ty3);
FrameBuffer_solidtriangle(p2->frame,tx1,ty1,tx2,ty2,tx3,ty3,color);
}
/* -------------------------------------------------------------------------
Plot2D_interptriangle(Plot2D *p2, double x1, double y1, Pixel c1,
double x2, double y2, Pixel c2,
double x3, double y3, Pixel c3);
This function draws a 2D filled triangle with color interpolation.
Can be used to draw other primitives such as quadralaterals, etc...
-------------------------------------------------------------------------- */
void Plot2D_interptriangle(Plot2D *p2, double x1, double y1, Pixel c1,
double x2, double y2, Pixel c2,
double x3, double y3, Pixel c3) {
int tx1, tx2, tx3, ty1, ty2, ty3;
/* Transform the three points into screen coordinates */
Plot2D_transform(p2,x1,y1,&tx1,&ty1);
Plot2D_transform(p2,x2,y2,&tx2,&ty2);
Plot2D_transform(p2,x3,y3,&tx3,&ty3);
FrameBuffer_interptriangle(p2->frame,tx1,ty1,c1,tx2,ty2,c2,tx3,ty3,c3);
}

File diff suppressed because it is too large Load diff