home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
PROGRAM
/
CBGRX100.ZIP
/
CONTRIB
/
LIBGRX
/
SRC
/
P4BITBLT.C
< prev
next >
Wrap
Text File
|
1992-04-10
|
8KB
|
292 lines
/**
** P4BITBLT.C
**
** Copyright (C) 1992, Csaba Biegl
** 820 Stirrup Dr, Nashville, TN, 37221
** csaba@vuse.vanderbilt.edu
**
** This file is distributed under the terms listed in the document
** "copying.cb", available from the author at the address above.
** A copy of "copying.cb" should accompany this file; if not, a copy
** should be available from where this file was obtained. This file
** may not be distributed without a verbatim copy of "copying.cb".
** You should also have received a copy of the GNU General Public
** License along with this program (it is in the file "copying");
** if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
** Cambridge, MA 02139, USA.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**/
#include "p4.h"
#include "memcopy.h"
#include "bitcopy.h"
#include "gmalloc.h"
#define SHIFT 8 /* need to shift pixels */
#define EDGEONLY 4 /* copy masked edge only (when no shift) */
#define REVERSE 4 /* do reverse shift */
#define SFT_INIT 0x100 /* more bits in 1st byte of dst than in src */
#define SFT_NOLAST 0x200 /* do not read last byte when shifting */
void _GrP4PixCopy(GC *dst,long da,GC *src,long sa,int width,int height,int op)
{
pixptr dp1,ddp,sp1,ssp,temp;
long dpoff = dst->gc_planeoffset;
long spoff = src->gc_planeoffset;
int doff = dst->gc_lineoffset;
int soff = src->gc_lineoffset;
char vdst = dst->gc_onscreen;
char vsrc = src->gc_onscreen;
char usetemp = FALSE;
char reverse = FALSE;
char edgeonly = FALSE;
char readdst = FALSE;
int plane,maskwdt;
int shift,shftwdt;
int cmode,linewdt;
int doff2,soff2;
int mask;
if((width <= 0) || (height <= 0)) return;
cmode = op = C_OPER(op);
mask = 0;
maskwdt = 0;
shftwdt = 0;
if((src->gc_baseaddr != dst->gc_baseaddr) || (da < sa)) {
if((shift = P_OFFSET((int)da + width)) != 0) {
width -= shift;
R_MASK(mask) = (unsigned char)(0xff00 >> shift);
maskwdt++;
}
if((shift = P_OFFSET(da)) != 0) {
width -= (8 - shift);
L_MASK(mask) = (unsigned char)(0xff >> shift);
maskwdt++;
}
if((width >>= 3) < 0) {
L_MASK(mask) &= R_MASK(mask);
R_MASK(mask) = 0;
maskwdt--;
width = 0;
}
if((shift -= P_OFFSET(sa)) != 0) {
cmode |= SHIFT;
if(shift < 0) { shift += (8 + SFT_INIT); shftwdt++; }
if((P_XPOS(sa) + width + maskwdt + shftwdt) > soff) {
if(R_MASK(mask) != 0) {
shift |= SFT_NOLAST;
shftwdt--;
}
else if(width > 0) {
R_MASK(mask) = 0xff;
shift |= SFT_NOLAST;
shftwdt--;
maskwdt++;
width--;
}
else if(shftwdt > 0) {
shftwdt = 0;
shift = 8 + SFT_INIT - shift;
cmode |= REVERSE;
}
else return;
}
}
ddp = P_ADDRESS(dst,da);
ssp = P_ADDRESS(src,sa);
_ClrDir();
}
else {
linewdt = width - 1;
if((shift = P_OFFSET((int)da + width)) != 0) {
width -= shift;
L_MASK(mask) = (unsigned char)(0xff00 >> shift);
maskwdt++;
}
if((shift = P_OFFSET(da)) != 0) {
width -= (8 - shift);
R_MASK(mask) = (unsigned char)(0xff >> shift);
maskwdt++;
}
if((width >>= 3) < 0) {
L_MASK(mask) &= R_MASK(mask);
R_MASK(mask) = 0;
maskwdt--;
width = 0;
}
sa += linewdt;
da += linewdt;
if((shift = P_OFFSET(sa) - P_OFFSET(da)) != 0) {
if(shift < 0) { shift += (8 + SFT_INIT); shftwdt++; }
cmode |= (SHIFT | REVERSE);
if((width + maskwdt + shftwdt) > (P_XPOS(sa) + 1)) {
if(R_MASK(mask) != 0) {
shift |= SFT_NOLAST;
shftwdt--;
}
else if(width > 0) {
R_MASK(mask) = 0xff;
shift |= SFT_NOLAST;
shftwdt--;
maskwdt++;
width--;
}
else if(shftwdt > 0) {
shftwdt = 0;
shift = 8 + SFT_INIT - shift;
cmode &= ~REVERSE;
}
else return;
}
}
ddp = (pixptr)dst->gc_baseaddr +
((COORD_Y(da) + height - 1) * doff) +
P_XPOS(da);
ssp = (pixptr)src->gc_baseaddr +
((COORD_Y(sa) + height - 1) * soff) +
P_XPOS(sa);
soff = (-soff);
doff = (-doff);
reverse = TRUE;
_SetDir();
}
if(vdst) {
_SetVGASetResetPlanes(0);
_SetVGAWriteMask(0xff);
_SetVGAColorFunction(VGA_FUNC_SET);
if(maskwdt || (op != C_SET)) readdst = TRUE;
if(vsrc) {
if(!shift && width && (op == C_SET) && _GrCanBcopyInBlit) {
_SetVGAWriteMode(1);
linewdt = L_MASK(mask) ? (reverse ? -1 : 1) : 0;
dp1 = ddp + linewdt + _GrWrOnlyOffset;
sp1 = ssp + linewdt + _GrRdOnlyOffset;
linewdt = reverse ? (-width) : width;
doff2 = doff - linewdt;
soff2 = soff - linewdt;
_SaveDS();
_BlkCpyB(FAST,dp1,doff2,sp1,soff2,width,height);
_RestoreDS();
_SetVGAWriteMode(0);
if(!maskwdt) goto done;
edgeonly = TRUE;
}
if(_GrBigFrameBuffer) {
if(_GrCanBcopyInBlit && !readdst) {
ssp += _GrRdOnlyOffset;
ddp += _GrWrOnlyOffset;
}
else {
linewdt = width + maskwdt + shftwdt;
temp = (pixptr)_GrGetTempBuffer(linewdt << 2);
if(temp == (pixptr)NULL) goto done;
spoff = (long)linewdt;
if(reverse) temp += (linewdt - 1);
usetemp = TRUE;
vsrc = readdst;
}
}
}
vsrc |= readdst;
}
if((shift == 0) && ((width == 0) || edgeonly)) {
linewdt = width + maskwdt - 1;
if(reverse) {
linewdt = (-linewdt);
width = (-width);
}
edgeonly = TRUE;
cmode |= EDGEONLY;
}
_SaveDS();
while(--height >= 0) {
dp1 = ddp;
sp1 = ssp;
if(usetemp) {
sp1 = temp;
for(plane = 0; plane < 4; plane++) {
_SetVGAReadPlane(plane);
if(!edgeonly)
_RowCpyB(TEMPBUFFER,sp1,ssp,linewdt);
else {
sp1[0] = ssp[0];
sp1[linewdt] = ssp[linewdt];
}
sp1 += (int)spoff;
}
sp1 = temp;
}
for(plane = 0; plane < 4; plane++) {
if(vdst) _SetVGAWritePlane(plane);
if(vsrc) _SetVGAReadPlane(plane);
switch(cmode) {
case C_SET:
_CopyMskLine(dp1,sp1,mask,width);
break;
case C_XOR:
_CopyMskLineXor(dp1,sp1,mask,width);
break;
case C_OR:
_CopyMskLineOr(dp1,sp1,mask,width);
break;
case C_AND:
_CopyMskLineAnd(dp1,sp1,mask,width);
break;
case (C_SET | EDGEONLY):
_CopyMskEdge(dp1,sp1,mask,width);
break;
case (C_XOR | EDGEONLY):
_CopyMskEdgeXor(dp1,sp1,mask,width);
break;
case (C_OR | EDGEONLY):
_CopyMskEdgeOr(dp1,sp1,mask,width);
break;
case (C_AND | EDGEONLY):
_CopyMskEdgeAnd(dp1,sp1,mask,width);
break;
case (C_SET | SHIFT):
_FwdShiftLine(dp1,sp1,shift,mask,width);
break;
case (C_XOR | SHIFT):
_FwdShiftLineXor(dp1,sp1,shift,mask,width);
break;
case (C_OR | SHIFT):
_FwdShiftLineOr(dp1,sp1,shift,mask,width);
break;
case (C_AND | SHIFT):
_FwdShiftLineAnd(dp1,sp1,shift,mask,width);
break;
case (C_SET | SHIFT | REVERSE):
_RevShiftLine(dp1,sp1,shift,mask,width);
break;
case (C_XOR | SHIFT | REVERSE):
_RevShiftLineXor(dp1,sp1,shift,mask,width);
break;
case (C_OR | SHIFT | REVERSE):
_RevShiftLineOr(dp1,sp1,shift,mask,width);
break;
case (C_AND | SHIFT | REVERSE):
_RevShiftLineAnd(dp1,sp1,shift,mask,width);
break;
}
*((long *)&dp1) += dpoff;
*((long *)&sp1) += spoff;
}
ddp += doff;
ssp += soff;
}
_RestoreDS();
done:
_ClrDir();
if(vdst) {
_SetVGASetResetPlanes(0x0f);
_SetVGAWriteAllPlanes();
}
}