#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdlib.h>
#include <X11/X.h>
#include "regionstr.h"
#include "pixmapstr.h"
#include "scrnintstr.h"
#include "regionstr.h"
#include "gc.h"
#include "maskbits.h"
#include "mi.h"
#include "mfb.h"
#define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2) \
if (((rx1) < (rx2)) && ((ry1) < (ry2)) && \
(!((reg)->data->numRects && \
((r-1)->y1 == (ry1)) && \
((r-1)->y2 == (ry2)) && \
((r-1)->x1 <= (rx1)) && \
((r-1)->x2 >= (rx2))))) \
{ \
if ((reg)->data->numRects == (reg)->data->size) \
{ \
miRectAlloc(reg, 1); \
fr = REGION_BOXPTR(reg); \
r = fr + (reg)->data->numRects; \
} \
r->x1 = (rx1); \
r->y1 = (ry1); \
r->x2 = (rx2); \
r->y2 = (ry2); \
(reg)->data->numRects++; \
if(r->x1 < (reg)->extents.x1) \
(reg)->extents.x1 = r->x1; \
if(r->x2 > (reg)->extents.x2) \
(reg)->extents.x2 = r->x2; \
r++; \
}
RegionPtr
mfbPixmapToRegion(pPix)
PixmapPtr pPix;
{
register RegionPtr pReg;
register PixelType *pw, w;
register int ib;
int width, h, base, rx1 = 0, crects;
PixelType *pwLineEnd;
int irectPrevStart, irectLineStart;
register BoxPtr prectO, prectN;
BoxPtr FirstRect, rects, prectLineStart;
Bool fInBox, fSame;
register PixelType mask0 = mask[0];
PixelType *pwLine;
int nWidth;
pReg = REGION_CREATE(pPix->drawable.pScreen, NULL, 1);
if(!pReg)
return NullRegion;
FirstRect = REGION_BOXPTR(pReg);
rects = FirstRect;
pwLine = (PixelType *) pPix->devPrivate.ptr;
nWidth = pPix->devKind / PGSZB;
width = pPix->drawable.width;
pReg->extents.x1 = width - 1;
pReg->extents.x2 = 0;
irectPrevStart = -1;
for(h = 0; h < pPix->drawable.height; h++)
{
pw = pwLine;
pwLine += nWidth;
irectLineStart = rects - FirstRect;
if(*pw & mask0)
{
fInBox = TRUE;
rx1 = 0;
}
else
fInBox = FALSE;
pwLineEnd = pw + (width >> PWSH);
for (base = 0; pw < pwLineEnd; base += PPW)
{
w = *pw++;
if (fInBox)
{
if (!~w)
continue;
}
else
{
if (!w)
continue;
}
for(ib = 0; ib < PPW; ib++)
{
if(w & mask0)
{
if(!fInBox)
{
rx1 = base + ib;
fInBox = TRUE;
}
}
else
{
if(fInBox)
{
ADDRECT(pReg, rects, FirstRect,
rx1, h, base + ib, h + 1);
fInBox = FALSE;
}
}
w = SCRLEFT(w, 1);
}
}
if(width & PIM)
{
w = *pw++;
for(ib = 0; ib < (width & PIM); ib++)
{
if(w & mask0)
{
if(!fInBox)
{
rx1 = base + ib;
fInBox = TRUE;
}
}
else
{
if(fInBox)
{
ADDRECT(pReg, rects, FirstRect,
rx1, h, base + ib, h + 1);
fInBox = FALSE;
}
}
w = SCRLEFT(w, 1);
}
}
if(fInBox)
{
ADDRECT(pReg, rects, FirstRect,
rx1, h, base + (width & PIM), h + 1);
}
fSame = FALSE;
if(irectPrevStart != -1)
{
crects = irectLineStart - irectPrevStart;
if(crects == ((rects - FirstRect) - irectLineStart))
{
prectO = FirstRect + irectPrevStart;
prectN = prectLineStart = FirstRect + irectLineStart;
fSame = TRUE;
while(prectO < prectLineStart)
{
if((prectO->x1 != prectN->x1) || (prectO->x2 != prectN->x2))
{
fSame = FALSE;
break;
}
prectO++;
prectN++;
}
if (fSame)
{
prectO = FirstRect + irectPrevStart;
while(prectO < prectLineStart)
{
prectO->y2 += 1;
prectO++;
}
rects -= crects;
pReg->data->numRects -= crects;
}
}
}
if(!fSame)
irectPrevStart = irectLineStart;
}
if (!pReg->data->numRects)
pReg->extents.x1 = pReg->extents.x2 = 0;
else
{
pReg->extents.y1 = REGION_BOXPTR(pReg)->y1;
pReg->extents.y2 = REGION_END(pReg)->y2;
if (pReg->data->numRects == 1)
{
xfree(pReg->data);
pReg->data = (RegDataPtr)NULL;
}
}
#ifdef DEBUG
if (!miValidRegion(pReg))
FatalError("Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__);
#endif
return(pReg);
}
mfbPixmapToRegionProc *
mfbPixmapToRegionWeak(void)
{
return mfbPixmapToRegion;
}