home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast.iso
/
dv_x
/
dvix.zip
/
BITMAP.C
next >
Wrap
C/C++ Source or Header
|
1992-10-02
|
10KB
|
429 lines
/* bitmap.c: bitmap manipulation code */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include "dvi.h"
#include "pxl.h"
#include "general.h"
#include "local.h"
#include "bitorder.h"
#ifdef MSBITFIRST
#define maskBits(n) (((1<<(n))-1)<<(BYTESIZE-(n)))
#define maskBits2(n) (((1<<(n))-1)<<(BYTESIZE*2-(n)))
#define shiftMask(m,n) ((m)>>(n))
#define shiftBack(m,n) ((m)<<(n))
#define catBits(b0,b1) (((b0)<<BYTESIZE)+(b1))
#define oneBit(n) ((1<<(BYTESIZE-1))>>(n))
#else
#define maskBits(n) ((1<<(n))-1)
#define maskBits2(n) ((1<<(n))-1)
#define shiftMask(m,n) ((m)<<(n))
#define shiftBack(m,n) ((m)>>(n))
#define catBits(b0,b1) (((b1)<<BYTESIZE)+(b0))
#define oneBit(n) (1<<(n))
#endif
extern unsigned char reverse_byte[];
char *malloc();
/*
** the following declarations are imported from gf.c
*/
#define int32 long /* used when at least 32 bits are required */
typedef struct bitmap *BitMap;
/* OR the src onto the dst (MSBit/MSByte first) */
bitOr(dstbm,x,y,w,h,srcbm,srcx,srcy)
BitMap dstbm,srcbm;
int x, y, w, h, srcx, srcy;
{
register BYTE *src, *dst;
register BYTE *sbp, *dbp;
register long sx, dx, width;
int dll, sll;
sx = srcx;
dx = x;
width = w;
/* do clipping first */
if (dx < 0) { width += dx; sx -= dx; dx = 0; }
if (sx < 0) { width += sx; dx -= sx; sx = 0; }
if (dx+width > dstbm->w) { width = dstbm->w - dx; }
if (sx+width > srcbm->w) { width = srcbm->w - sx; }
if (width <= 0) return;
if (y < 0) { h += y; srcy -= y; y = 0; }
if (srcy < 0) { h += srcy; y -= srcy; srcy = 0; }
if (y+h > dstbm->h) { h = dstbm->h - y; }
if (srcy+h > srcbm->h) { h = srcbm->h - srcy; }
if (h <= 0) return;
/* adjust dx and sx mod BYTESIZE */
dll = dstbm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
dst = (BYTE*)dstbm->bits + y*dll;
if (dx) { dst += dx>>BYTESHIFT; dx &= BYTEMASK; }
sll = srcbm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
src = (BYTE*)srcbm->bits + srcy*sll;
if (srcx) { src += sx>>BYTESHIFT; sx &= BYTEMASK; }
/* save some values for later use (in the loop) */
w = width;
dbp = dst;
sbp = src;
/* now, do the bit-or operations */
if (sx==0)
{
/* easier to do when the source is BYTE aligned */
if (dx+width<=BYTESIZE)
{
register unsigned long mask;
mask = maskBits(width);
while (--h>=0)
{
*dst |= shiftMask(mask & *src, dx);
dst += dll;
src += sll;
}
}
else if (width<=BYTESIZE)
{
register unsigned long mask;
mask = maskBits(width);
while (--h>=0)
{
dst[0] |= shiftMask(mask & *src, dx);
dst[1] |= shiftBack(mask & *src, BYTESIZE-dx);
dst += dll;
src += sll;
}
}
else
{
while (--h>=0)
{
register unsigned long bits;
while (width >= BYTESIZE)
{
bits = *src++;
*dst++ |= shiftMask(bits, dx);
if (dx) *dst |= shiftBack(bits, BYTESIZE-dx);
width -= BYTESIZE;
}
if (width)
{
bits = *src++ & maskBits(width);
*dst++ |= shiftMask(bits, dx);
if (width+dx>BYTESIZE)
*dst |= shiftBack(bits, BYTESIZE-dx);
}
dst = dbp += dll;
src = sbp += sll;
width = w;
}
}
}
else
{
while (--h>=0)
{
register unsigned long bits;
bits = 0L;
while (width >= BYTESIZE)
{
bits |= shiftBack(*src, sx);
*dst++ |= shiftMask(bits, dx);
if (dx) *dst |= shiftBack(bits, BYTESIZE-dx);
bits = shiftMask(*src++, BYTESIZE-sx);
width -= BYTESIZE;
}
if (width)
{
bits |= shiftMask(*src, sx);
bits &= maskBits(width);
*dst++ |= shiftMask( bits, dx);
if (width+dx>BYTESIZE)
*dst |= shiftBack( bits, BYTESIZE-dx);
}
dst = dbp += dll;
src = sbp += sll;
width = w;
}
}
}
#define bitClip(bm,x,y) (x>=0 && y>=0 && x<bm->w && y<bm->h)
#define bitSetOne(bp,x) (bp[(x)>>BYTESHIFT] |= oneBit((x)&BYTEMASK))
/* draw a line onto the bitmap as an OR operation */
bitLine(dstbm,x,y,x2,y2)
BitMap dstbm;
register int x, y;
int x2, y2;
{
register int w, h;
register BYTE *dst;
register BYTE *dbp;
int dll;
/* normalize the (x) direction first */
w = x2 - x;
h = y2 - y;
if (w<0) { x += w; w = -w; y += h; h = -h; }
if (x+w<0 || x>dstbm->w) return;
dll = dstbm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
dst = (BYTE*)dstbm->bits + y*dll;
if (h==0) {
/* horizontal */
bitFillBox(dstbm,x,y,w+1,1);
}
else if (w==0) {
/* vertical */
if (h<0) bitFillBox(dstbm,x,y+h,1,1-h);
else bitFillBox(dstbm,x,y,1,h+1);
}
else if (h>0) {
/* positive slope */
if (y+h<0 || y>dstbm->h) return;
if (w>=h) {
/* wider than high */
/* slope less than or equal to one */
register int err, i;
err = (h<<1) - w;
for (i=0; i<=w; i++) {
if (bitClip(dstbm,x,y)) bitSetOne(dst,x);
if (err>0) {
y++;
dst += dll;
err += (h-w)<<1;
}
else
err += h<<1;
x++;
}
}
else {
/* higher than wide */
/* slope greater than one */
register int err, i;
err = (w<<1) - h;
for (i=0; i<=h; i++) {
if (bitClip(dstbm,x,y)) bitSetOne(dst,x);
if (err>0) {
x++;
err += (w-h)<<1;
}
else
err += w<<1;
y++;
dst += dll;
}
}
}
else {
/* negative slope */
h = -h;
if (y+h<0 || y>dstbm->h) return;
if (w>=h) {
/* wider than high */
/* abs(slope) less than or equal to one */
register int err, i;
err = (h<<1) - w;
for (i=0; i<=w; i++) {
if (bitClip(dstbm,x,y)) bitSetOne(dst,x);
if (err>0) {
y--;
dst -= dll;
err += (h-w)<<1;
}
else
err += h<<1;
x++;
}
}
else {
/* higher than wide */
/* abs(slope) greater than one */
register int err, i;
err = (w<<1) - h;
for (i=0; i<=h; i++) {
if (bitClip(dstbm,x,y)) bitSetOne(dst,x);
if (err>0) {
x++;
err += (w-h)<<1;
}
else
err += w<<1;
y--;
dst -= dll;
}
}
}
}
/* draw a filled box of the given size */
bitFillBox(bm,x,y,width,height)
BitMap bm;
{
register int dx, dy, w, h;
register BYTE *dst;
dx = x;
dy = y;
w = width;
h = height;
/* do clipping first */
if (w<0) { dx += w; w = -w; }
if (dx < 0) { w += dx; dx = 0; }
if (dx+w > bm->w) { w = bm->w - dx; }
if (w <= 0) return;
if (h<0) { dy += h; h = -h; }
if (dy < 0) { h += dy; dy = 0; }
if (dy+h > bm->h) { h = bm->h - dy; }
if (h <= 0) return;
/* adjust dx and sx mod BYTESIZE */
dst = (BYTE*)bm->bits + dy*bm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
if (dx) { dst += dx>>BYTESHIFT; dx &= BYTEMASK; }
x = dx;
width = w;
dy = bm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
if (dx+width<=BYTESIZE)
{
register unsigned long mask;
mask = maskBits(width);
if (dx) mask = shiftMask(mask,dx);
while (--h>=0)
{
*dst |= mask;
dst += dy;
}
}
else
{
register BYTE *dbp = dst;
while (--h>=0)
{
if (dx)
{
*dst++ |= shiftMask(maskBits(BYTESIZE-dx),dx);
width -= BYTESIZE-dx;
}
while (width >= BYTESIZE)
{
*dst++ = ~0;
width -= BYTESIZE;
}
if (width)
*dst++ |= maskBits(width);
dst = dbp += dy;
width = w;
}
}
}
/* draw a dotted box of the given size */
bitGrayBox(bm,x,y,width,height,odd)
BitMap bm;
{
register int dx, dy, w, h;
register long gray = 0x55555555;
register BYTE *dst;
dx = x;
dy = y;
w = width;
h = height;
/* do clipping first */
if (dx < 0) { w += dx; dx = 0; }
if (dx+w > bm->w) { w = bm->w - dx; }
if (w <= 0) return;
if (dy < 0) { h += dy; dy = 0; }
if (dy+h > bm->h) { h = bm->h - dy; }
if (h <= 0) return;
/* keep the pattern aligned with the background */
if ((odd^dy)&1) gray = ~gray;
/* adjust dx and sx mod BYTESIZE */
dst = (BYTE*)bm->bits + dy*bm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
if (dx) { dst += dx>>BYTESHIFT; dx &= BYTEMASK; }
x = dx;
width = w;
dy = bm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
if (dx+width<=BYTESIZE)
{
register unsigned long mask;
mask = maskBits(width);
if (dx) mask = shiftMask(mask,dx);
while (--h>=0)
{
*dst |= mask & gray;
dst += dy;
gray = ~gray;
}
}
else
{
register BYTE *dbp = dst;
while (--h>=0)
{
if (dx)
{
*dst++ |= shiftMask(maskBits(BYTESIZE-dx),dx) & gray;
width -= BYTESIZE-dx;
}
while (width >= BYTESIZE)
{
*dst++ = gray;
width -= BYTESIZE;
}
if (width)
*dst++ |= maskBits(width) & gray;
dst = dbp += dy;
width = w;
gray = ~gray;
}
}
}
/* clear the contents of a BitMap */
bitClear(dst)
BitMap dst;
{
if (dst->bits)
bzero(dst->bits, dst->bytes_wide * dst->h);
}
struct bitmap *
bitCreate(width,height)
{
unsigned int rowbytes = (width+BYTEMASK)/BYTESIZE*(BYTESIZE/BITS_PER_BYTE);
struct bitmap *bm;
bm = (struct bitmap *) malloc(sizeof(struct bitmap));
bm->w = width;
bm->h = height;
bm->bytes_wide = rowbytes;
bm->bits = malloc(rowbytes*height);
return bm;
}