#include "X.h"
#include "Xmd.h"
#include "Xproto.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "regionstr.h"
#include "ipl.h"
#include "fastblt.h"
#include "iplmergerop.h"
#include "iplmskbits.h"
void
INTER_MROP_NAME(iplDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask)
DrawablePtr pSrc, pDst;
int alu;
RegionPtr prgnDst;
DDXPointPtr pptSrc;
unsigned long planemask;
{
INTER_DECLAREG(*psrcBase);
INTER_DECLAREG(*pdstBase);
int widthSrc, widthDst;
BoxPtr pbox;
int nbox;
BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
DDXPointPtr pptTmp, pptNew1, pptNew2;
int w, h;
int xdir;
int ydir;
INTER_DECLAREG(*psrcLine);
INTER_DECLAREG(*pdstLine);
INTER_DECLAREG(*psrc);
INTER_DECLAREG(*pdst);
INTER_MROP_DECLARE_REG()
INTER_DECLAREG(startmask);
INTER_DECLAREG(endmask);
int ngMiddle;
int xoffSrc, xoffDst;
register int leftShift, rightShift;
INTER_DECLAREGP(bits);
INTER_DECLAREGP(bits1);
INTER_DECLAREGP(bits2);
register int ng;
int nstart;
int nend;
int srcStartOver;
int careful;
int tmpSrc;
INTER_MROP_INITIALIZE(alu,planemask);
iplGetGroupWidthAndPointer (pSrc, widthSrc, psrcBase)
iplGetGroupWidthAndPointer (pDst, widthDst, pdstBase)
careful = ((pSrc == pDst) ||
((pSrc->type == DRAWABLE_WINDOW) &&
(pDst->type == DRAWABLE_WINDOW)));
pbox = REGION_RECTS(prgnDst);
nbox = REGION_NUM_RECTS(prgnDst);
pboxNew1 = NULL;
pptNew1 = NULL;
pboxNew2 = NULL;
pptNew2 = NULL;
if (careful && (pptSrc->y < pbox->y1))
{
ydir = -1;
widthSrc = -widthSrc;
widthDst = -widthDst;
if (nbox > 1)
{
pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
if(!pboxNew1)
return;
pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
if(!pptNew1)
{
DEALLOCATE_LOCAL(pboxNew1);
return;
}
pboxBase = pboxNext = pbox+nbox-1;
while (pboxBase >= pbox)
{
while ((pboxNext >= pbox) &&
(pboxBase->y1 == pboxNext->y1))
pboxNext--;
pboxTmp = pboxNext+1;
pptTmp = pptSrc + (pboxTmp - pbox);
while (pboxTmp <= pboxBase)
{
*pboxNew1++ = *pboxTmp++;
*pptNew1++ = *pptTmp++;
}
pboxBase = pboxNext;
}
pboxNew1 -= nbox;
pbox = pboxNew1;
pptNew1 -= nbox;
pptSrc = pptNew1;
}
}
else
{
ydir = 1;
}
if (careful && (pptSrc->x < pbox->x1))
{
xdir = -1;
if (nbox > 1)
{
pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
if(!pboxNew2 || !pptNew2)
{
if (pptNew2) DEALLOCATE_LOCAL(pptNew2);
if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2);
if (pboxNew1)
{
DEALLOCATE_LOCAL(pptNew1);
DEALLOCATE_LOCAL(pboxNew1);
}
return;
}
pboxBase = pboxNext = pbox;
while (pboxBase < pbox+nbox)
{
while ((pboxNext < pbox+nbox) &&
(pboxNext->y1 == pboxBase->y1))
pboxNext++;
pboxTmp = pboxNext;
pptTmp = pptSrc + (pboxTmp - pbox);
while (pboxTmp != pboxBase)
{
*pboxNew2++ = *--pboxTmp;
*pptNew2++ = *--pptTmp;
}
pboxBase = pboxNext;
}
pboxNew2 -= nbox;
pbox = pboxNew2;
pptNew2 -= nbox;
pptSrc = pptNew2;
}
}
else
{
xdir = 1;
}
while(nbox--)
{
w = pbox->x2 - pbox->x1;
h = pbox->y2 - pbox->y1;
if (ydir == -1)
{
psrcLine = psrcBase + ((pptSrc->y+h-1) * -widthSrc);
pdstLine = pdstBase + ((pbox->y2-1) * -widthDst);
}
else
{
psrcLine = psrcBase + (pptSrc->y * widthSrc);
pdstLine = pdstBase + (pbox->y1 * widthDst);
}
if ((pbox->x1 & INTER_PIM) + w <= INTER_PPG)
{
INTER_maskpartialbits (pbox->x1, w, endmask);
startmask = 0;
ngMiddle = 0;
}
else
{
INTER_maskbits(pbox->x1, w, startmask, endmask, ngMiddle);
}
if (xdir == 1)
{
xoffSrc = pptSrc->x & INTER_PIM;
xoffDst = pbox->x1 & INTER_PIM;
pdstLine += (pbox->x1 >> INTER_PGSH) * INTER_PLANES;
psrcLine += (pptSrc->x >> INTER_PGSH) * INTER_PLANES;
ng = xoffSrc - xoffDst;
if (xoffSrc == xoffDst)
{
while (h--)
{
psrc = psrcLine;
pdst = pdstLine;
pdstLine += widthDst;
psrcLine += widthSrc;
if (startmask)
{
INTER_MROP_MASK(psrc, pdst, startmask, pdst);
INTER_NEXT_GROUP(psrc);
INTER_NEXT_GROUP(pdst);
}
ng = ngMiddle;
DuffL(ng, label1,
INTER_MROP_SOLID(psrc, pdst, pdst);
INTER_NEXT_GROUP(psrc);
INTER_NEXT_GROUP(pdst);
)
if (endmask)
INTER_MROP_MASK(psrc, pdst, endmask, pdst);
}
}
else
{
if (xoffSrc > xoffDst)
{
leftShift = xoffSrc - xoffDst;
rightShift = (INTER_PIM+1) - leftShift;
}
else
{
rightShift = xoffDst - xoffSrc;
leftShift = (INTER_PIM+1) - rightShift;
}
while (h--)
{
psrc = psrcLine;
pdst = pdstLine;
pdstLine += widthDst;
psrcLine += widthSrc;
INTER_CLR(bits);
if (xoffSrc > xoffDst) {
INTER_COPY(psrc, bits);
INTER_NEXT_GROUP(psrc);
}
if (startmask)
{
INTER_GETLRC(leftShift, rightShift, psrc, bits, bits1);
INTER_MROP_MASK(bits1, pdst, startmask, pdst);
INTER_NEXT_GROUP(psrc);
INTER_NEXT_GROUP(pdst);
}
ng = ngMiddle;
DuffL (ng,label2,
INTER_GETLRC(leftShift, rightShift, psrc, bits, bits1);
INTER_MROP_SOLID(bits1, pdst, pdst);
INTER_NEXT_GROUP(psrc);
INTER_NEXT_GROUP(pdst);
)
if (endmask)
{
if ((endmask << rightShift) & 0xffff) {
INTER_GETLRC(leftShift, rightShift, psrc, bits,
bits1);
}
else {
INTER_SCRLEFT(leftShift, bits, bits1);
}
INTER_MROP_MASK(bits1, pdst, endmask, pdst);
}
}
}
}
else
{
xoffSrc = (pptSrc->x + w - 1) & INTER_PIM;
xoffDst = (pbox->x2 - 1) & INTER_PIM;
pdstLine += (((pbox->x2-1) >> INTER_PGSH) + 1) * INTER_PLANES;
psrcLine += (((pptSrc->x+w - 1) >> INTER_PGSH) + 1) * INTER_PLANES;
if (xoffSrc == xoffDst)
{
while (h--)
{
psrc = psrcLine;
pdst = pdstLine;
pdstLine += widthDst;
psrcLine += widthSrc;
if (endmask)
{
INTER_PREV_GROUP(psrc);
INTER_PREV_GROUP(pdst);
INTER_MROP_MASK(psrc, pdst, endmask, pdst);
}
ng = ngMiddle;
DuffL(ng,label3,
INTER_PREV_GROUP(psrc);
INTER_PREV_GROUP(pdst);
INTER_MROP_SOLID(psrc, pdst, pdst);
)
if (startmask)
{
INTER_PREV_GROUP(psrc);
INTER_PREV_GROUP(pdst);
INTER_MROP_MASK(psrc, pdst, startmask, pdst);
}
}
}
else
{
if (xoffDst > xoffSrc)
{
rightShift = xoffDst - xoffSrc;
leftShift = (INTER_PIM + 1) - rightShift;
}
else
{
leftShift = xoffSrc - xoffDst;
rightShift = (INTER_PIM + 1) - leftShift;
}
while (h--)
{
psrc = psrcLine;
pdst = pdstLine;
pdstLine += widthDst;
psrcLine += widthSrc;
INTER_CLR(bits);
if (xoffDst > xoffSrc) {
INTER_PREV_GROUP(psrc);
INTER_COPY(psrc, bits);
}
if (endmask)
{
INTER_PREV_GROUP(psrc);
INTER_PREV_GROUP(pdst);
INTER_GETRLC(rightShift, leftShift, psrc, bits, bits1);
INTER_MROP_MASK(bits1, pdst, endmask, pdst);
}
ng = ngMiddle;
DuffL (ng, label4,
INTER_PREV_GROUP(psrc);
INTER_PREV_GROUP(pdst);
INTER_GETRLC(rightShift, leftShift, psrc, bits, bits1);
INTER_MROP_SOLID(bits1, pdst, pdst);
)
if (startmask)
{
INTER_PREV_GROUP(psrc);
INTER_PREV_GROUP(pdst);
if ((startmask >> leftShift) & 0xffff) {
INTER_GETRLC(rightShift, leftShift, psrc, bits,
bits1);
}
else {
INTER_SCRRIGHT(rightShift, bits, bits1);
}
INTER_MROP_MASK(bits1, pdst, startmask, pdst);
}
}
}
}
pbox++;
pptSrc++;
}
if (pboxNew2)
{
DEALLOCATE_LOCAL(pptNew2);
DEALLOCATE_LOCAL(pboxNew2);
}
if (pboxNew1)
{
DEALLOCATE_LOCAL(pptNew1);
DEALLOCATE_LOCAL(pboxNew1);
}
}