home *** CD-ROM | disk | FTP | other *** search
- /**
- ** 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();
- }
- }
-