home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Creative Computers
/
CreativeComputers.iso
/
shareware
/
text
/
dvi_3.62
/
source
/
dvisrc.lha
/
dviclip.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-26
|
8KB
|
420 lines
/*
** Datei: DVICLIP.C
** Autor: Ingo Eichenseher
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <string.h>
#include "dvi.h"
#include "dvisplin.h"
#include "dvidraw.h"
#define QSORT
int clip_active = 0;
int fill_mode;
int clip_nx, clip_ymin, clip_ymax;
int *clip_x, **clip_y;
int cmaxx = MAX_X;
int sw, *swp;
static struct clip_xy *path_coord = NULL;
static struct clip_xy *clip_coord = NULL;
static long clip_size, path_size, clip_x_size, clip_y_size;
static int path_points = 0, path_max_points=0, clip_max_points=0;
static int clip_xmax;
static int fill_s0, fill_sn, fill_start;
static int fill_error, fill_x1, fill_x2, fill_y1, fill_y2, path_start;
#ifdef QSORT
static int clip_compare(struct clip_xy const *a, struct clip_xy const *b)
{
if (a->y==b->y) return a->x - b->x;
return a->y - b->y;
}
typedef int (*cmpf)(const void *, const void*);
static struct clip_xy *path_ptr;
static void clip_newcoord(int x, int y)
{
if (path_points<path_max_points)
{
path_ptr->x = x;
path_ptr->y = y;
path_ptr++;
path_points++;
}
else fill_error = 2;
}
#define clip_rmcoord() path_points--, path_ptr--
#else
static int lp;
static void clip_newcoord(int x, int y)
{
if (path_points>=path_max_points)
{
fill_error = 2;
return;
}
if (path_points>0)
{
int c = y==path_coord[lp].y ? x-path_coord[lp].x : y-path_coord[lp].y;
while(c>0 && lp<path_points)
if (++lp<path_points)
c = y==path_coord[lp].y ? x-path_coord[lp].x : y-path_coord[lp].y;
while(lp>0)
{
c = y==path_coord[lp-1].y ? x-path_coord[lp-1].x : y-path_coord[lp-1].y;
if (c>=0) break;
lp--;
}
if (lp<path_points)
memmove(path_coord+lp+1,path_coord+lp,(path_points-lp)*sizeof(struct coord));
}
else lp = 0;
path_coord[lp].x = x;
path_coord[lp].y = y;
path_points++;
}
static void clip_rmcoord(void)
{
if (path_points>0 && lp<path_points-1)
memmove(path_coord+lp,path_coord+lp+1,(path_points-lp-1)*sizeof(struct coord));
if (path_points>0) path_points--;
}
#endif
static void clip_newpoint(int x, int y)
{
clip_newcoord(x,y);
clip_newcoord(x,y);
}
void clip_line(int x1, int y1, int x2, int y2)
{
register int dx, dy, e, i, sy, sx;
static int last_sy = 0;
int last_y = y1;
dx = iabs(x2-x1);
sx = isgn(x2-x1);
dy = iabs(y2-y1);
sy = isgn(y2-y1);
if (path_start)
{
fill_x1 = x1;
fill_y1 = y1;
path_start = 0;
}
else
{
if (fill_x2!=x1 || fill_y2!=y1)
{
fill_error = 1;
/* print("(%d!=%d,%d!=%d)",fill_x2,x1,fill_y2,y1); */
}
}
if (fill_error) return;
fill_x2 = x2;
fill_y2 = y2;
if (sy!=0)
{
if (fill_start)
{
clip_newcoord(x1,y1);
fill_s0 = sy;
fill_start=0;
}
else if (sy!=last_sy) clip_newcoord(x1,y1);
last_sy = sy;
fill_sn = sy;
}
if (dx==0 && dy==0)
{
clip_newpoint(x1,y1);
return;
}
if (dy>dx)
{
dx += dx;
i = dy;
e = dx-dy;
dy += dy;
while( i-- >= 0 )
{
if (y1!=last_y)
{
clip_newcoord(x1,y1);
last_y = y1;
}
else clip_newpoint(x1,y1);
while(e>=0)
{
x1 += sx;
e -= dy;
}
e += dx;
y1 += sy;
}
}
else
{
dy += dy;
i = dx;
e = dy-dx;
dx += dx;
while ( i-- >= 0)
{
if (y1!=last_y)
{
clip_newcoord(x1,y1);
last_y = y1;
}
else clip_newpoint(x1,y1);
while(e>=0)
{
y1 += sy;
e -= dx;
}
x1 += sx;
e += dy;
}
}
}
static void psize_init(long *size, int *points)
{
if (op.pathmem>0l)
{
long p;
*size = op.pathmem;
p = *size/sizeof(struct clip_xy);
if (p!=(int)p)
{
p = 32767;
*size = p*sizeof(struct clip_xy);
}
*points = (int)p;
}
else
{
*points = 2*(dvi_info.width+dvi_info.height);
*size = *points*sizeof(struct clip_xy);
}
}
void clip_init(void)
{
psize_init(&path_size,&path_max_points);
if (op.tracemem) xprint(0,"{DefClip:%ld",path_size);
path_coord = (struct clip_xy*)mem_alloc(path_size,"DefClip");
path_points = 0;
path_ptr = path_coord;
fill_start = 1;
fill_mode = 1;
path_start = 1;
fill_error = 0;
}
static int clip_cut(struct clip_xy *clip_coord, int clip_max_points)
{
int f, n = clip_max_points;
struct clip_xy *cp = clip_coord, *pp;
for (f=0, pp=path_coord; f<path_points-1; f+=2, pp+=2)
{
int y = pp->y;
if (y>=clip_ymin && y<=clip_ymax)
{
int *p;
for (p=clip_y[y-clip_ymin]; *p<MAX_X; p+=2)
{
int min_x = pp->x > *p ? pp->x : *p;
int max_x = pp[1].x < p[1] ? pp[1].x : p[1];
if (min_x<=max_x)
{
if ( 0==n-- ) return -1;
cp->x = min_x;
cp->y = y;
cp++;
if ( 0==n-- ) return -1;
cp->x = max_x;
cp->y = y;
cp++;
}
}
}
}
return clip_max_points-n;
}
static int clip1(unsigned char *clip_mask)
{
int i, clip_points, *cpx;
static struct clip_xy *cp;
if (!fill_mode) return fill_error = 1;
fill_mode = 0;
if (fill_start) return 0;
if (fill_x1!=fill_x2 || fill_y1!=fill_y2) return fill_error = 1;
if (fill_error) return fill_error;
if (fill_sn==fill_s0) clip_rmcoord();
#ifdef QSORT
qsort(path_coord,path_points,sizeof(*path_coord),(cmpf)clip_compare);
#endif
if (clip_active)
{
psize_init(&clip_size,&clip_max_points);
if (op.tracemem) xprint(0,"{ClipCut:%ld",clip_size);
clip_coord = (struct clip_xy*)mem_alloc(clip_size,"ClipCut");
clip_active = 0;
clip_points = clip_cut(clip_coord,clip_max_points);
mem_free(path_coord,path_size);
path_coord = NULL;
if (op.tracemem) xprint(-1,"}");
if (clip_points<0) return 2;
}
else
{
clip_points = path_points;
clip_coord = path_coord;
clip_size = path_size;
clip_max_points = path_max_points;
path_coord = NULL;
}
if (clip_x==NULL)
{
clip_xmax = clip_max_points;
clip_x_size = clip_xmax*sizeof(*clip_x);
clip_y_size = clip_max_points*sizeof(*clip_y);
if (op.tracemem) xprint(0,"{Clip:%ld",clip_x_size+clip_y_size);
clip_x = (int*)mem_alloc(clip_x_size,"ClipX");
clip_y = (int**)mem_alloc(clip_y_size,"ClipY");
}
if (clip_points>0)
{
clip_ymin = clip_coord[0].y;
clip_ymax = clip_coord[clip_points-1].y;
}
else
{
clip_ymin = 0;
clip_ymax = -1;
}
if (clip_ymax-clip_ymin>=clip_max_points) return 2;
for (i=0; i<=clip_ymax-clip_ymin; i++) clip_y[i] = &cmaxx;
clip_nx = clip_xmax;
cpx = clip_x;
for (i=0, cp=clip_coord; i<clip_points;)
{
int y = cp->y;
clip_y[y-clip_ymin] = cpx;
while(cp->y==y)
{
if (0==clip_nx--) return 2;
*cpx++ = (cp++)->x; i++;
if (cp->y!=y) return 3;
while(i<clip_points-2 && cp[1].y==y && cp->x>cp[1].x)
{
i += 2; cp += 2;
if (cp->y!=y) return 3;
}
if ( 0==clip_nx-- ) return 2;
*cpx++ = (cp++)->x; i++;
}
if ( 0==clip_nx-- ) return 2;
*cpx++ = MAX_X;
}
clip_nx = clip_xmax - clip_nx;
if (clip_mask)
{
for (i=0, cp=clip_coord; i<clip_points; i+=2, cp+=2)
hline(cp->x,cp->y,cp[1].x,clip_mask[cp->y&7]);
}
clip_active = 1;
return 0;
}
void clip_clean(int phase)
{
if (path_coord!=NULL)
{
mem_free(path_coord,path_size);
path_coord = NULL;
if (op.tracemem) xprint(-1,"}");
}
if (clip_coord!=NULL)
{
mem_free(clip_coord,clip_size);
clip_coord = NULL;
if (op.tracemem) xprint(-1,"}");
}
if (phase>0 && clip_x!=NULL)
{
mem_free(clip_x,clip_x_size);
mem_free(clip_y,clip_y_size);
clip_x = NULL;
clip_y = NULL;
if (op.tracemem) xprint(-1,"}");
}
}
int clip_exec(unsigned char *clip_mask)
{
int ret = clip1(clip_mask);
clip_clean(0);
return ret;
}
void clip_end(void)
{
clip_clean(1);
clip_active = 0;
}
int fill_with_pattern(int pattern)
{
int i;
if (!fill_mode) return fill_error = 1;
fill_mode = 0;
if (fill_start) return 0;
if (fill_x1!=fill_x2 || fill_y1!=fill_y2) return fill_error = 1;
if (fill_error) return fill_error;
if (fill_sn==fill_s0) clip_rmcoord();
#ifdef QSORT
qsort(path_coord,path_points,sizeof(*path_coord),(cmpf)clip_compare);
#endif
for (i=0; i<path_points-1; i+=2)
{
if (path_coord[i].y!=path_coord[i+1].y) return 3;
hline(path_coord[i].x,path_coord[i].y,path_coord[i+1].x,
pattern);
}
mem_free(path_coord,path_size);
path_coord = 0;
if (op.tracemem) xprint(-1,"}");
return 0;
}