#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include "xf4bpp.h"
#include "OScompiler.h"
#include "mfbmap.h"
#include "mfb.h"
#include "maskbits.h"
#include "mi.h"
#include "dixfontstr.h"
#include "ppcGCstr.h"
#include "wm3.h"
#include "xf86str.h"
extern ScrnInfoPtr *xf86Screens;
static void doImageGlyphBlt(
DrawablePtr,
GC *,
int,
int,
unsigned int,
CharInfoPtr *,
unsigned char *,
ExtentInfoRec *
);
void
xf4bppImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
DrawablePtr pDrawable;
GC *pGC;
int x, y;
unsigned int nglyph;
CharInfoPtr *ppci;
pointer pglyphBase;
{
ExtentInfoRec info;
xRectangle backrect;
if ( (pDrawable->type != DRAWABLE_WINDOW) || (pGC->alu != GXcopy) ||
!xf86Screens[pDrawable->pScreen->myNum]->vtSema ||
((pGC->font) &&
(FONTMAXBOUNDS(pGC->font,rightSideBearing) -
FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
FONTMINBOUNDS(pGC->font,characterWidth) < 0)) ) {
miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
} else {
ppcPrivGC *pPrivGC;
int oldfillStyle, oldfg, oldalu;
if (!(pGC->planemask & 0x0F))
return;
QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info);
backrect.x = x;
backrect.y = y - FONTASCENT(pGC->font);
backrect.width = info.overallWidth;
backrect.height = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
pPrivGC = pGC->devPrivates[mfbGetGCPrivateIndex()].ptr;
oldfillStyle = pPrivGC->colorRrop.fillStyle;
oldfg = pPrivGC->colorRrop.fgPixel;
oldalu = pPrivGC->colorRrop.alu;
pPrivGC->colorRrop.fillStyle = FillSolid;
pPrivGC->colorRrop.fgPixel = pGC->bgPixel;
pGC->fgPixel = pGC->bgPixel;
pPrivGC->colorRrop.alu = GXcopy;
pGC->alu = GXcopy;
xf4bppPolyFillRect(pDrawable, pGC, 1, &backrect);
pPrivGC->colorRrop.fgPixel = oldfg;
pGC->fgPixel = oldfg;
DO_WM3(pGC,doImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
pglyphBase,&info))
pPrivGC->colorRrop.fillStyle = oldfillStyle;
pPrivGC->colorRrop.alu = oldalu;
pGC->alu = oldalu;
}
}
static void
doImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase,infop)
DrawablePtr pDrawable;
GC *pGC;
int x, y;
unsigned int nglyph;
CharInfoPtr *ppci;
unsigned char *pglyphBase;
ExtentInfoRec* infop;
{
BoxRec bbox;
CharInfoPtr pci;
int xorg, yorg;
int widthDst;
CARD32 *pdstBase;
int xchar;
register int xoff;
register CARD32 *pdst;
int w;
int h;
int widthGlyph;
register unsigned char *pglyph;
register unsigned int tmpSrc;
register int startmask;
register int endmask;
register int nFirst;
xorg = pDrawable->x;
yorg = pDrawable->y;
if (pDrawable->type == DRAWABLE_WINDOW)
{
pdstBase = (CARD32 *)
(((PixmapPtr)(pDrawable->pScreen->devPrivate))->devPrivate.ptr);
widthDst = (int)
(((PixmapPtr)(pDrawable->pScreen->devPrivate))->devKind) >> 2;
}
else
{
pdstBase = (CARD32 *)(((PixmapPtr)pDrawable)->devPrivate.ptr);
widthDst = (int)(((PixmapPtr)pDrawable)->devKind) >> 2;
}
x += xorg;
y += yorg;
bbox.x1 = x + infop->overallLeft;
bbox.x2 = x + infop->overallRight;
bbox.y1 = y - infop->overallAscent;
bbox.y2 = y + infop->overallDescent;
switch (RECT_IN_REGION(pGC->pScreen, pGC->pCompositeClip, &bbox))
{
case rgnOUT:
break;
case rgnIN:
pdstBase = pdstBase + (widthDst * y) + (x >> PWSH);
xchar = x & PIM;
while(nglyph--)
{
pci = *ppci;
pglyph = FONTGLYPHBITS(pglyphBase, pci);
w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
h = pci->metrics.ascent + pci->metrics.descent;
widthGlyph = GLYPHWIDTHBYTESPADDED(pci);
pdst = pdstBase - (pci->metrics.ascent * widthDst);
xoff = xchar + pci->metrics.leftSideBearing;
if (xoff > PIM)
{
pdst++;
xoff &= PIM;
}
else if (xoff < 0)
{
xoff += PPW;
pdst--;
}
if ((xoff + w) <= PPW)
{
maskpartialbits(xoff, w, startmask);
while (h--)
{
getleftbits(pglyph, w, tmpSrc);
UPDRW(pdst,(SCRRIGHT(tmpSrc, xoff) & startmask));
pglyph += widthGlyph;
pdst += widthDst;
}
}
else
{
maskPPWbits(xoff, w, startmask, endmask);
nFirst = PPW - xoff;
while (h--)
{
getleftbits(pglyph, w, tmpSrc);
UPDRW(pdst,(SCRRIGHT(tmpSrc, xoff) & startmask));
UPDRW(&(pdst[1]),(SCRLEFT(tmpSrc, nFirst) & endmask));
pglyph += widthGlyph;
pdst += widthDst;
}
}
x += pci->metrics.characterWidth;
xchar += pci->metrics.characterWidth;
if (xchar > PLST)
{
xchar -= PPW;
pdstBase++;
}
else if (xchar < 0)
{
xchar += PPW;
pdstBase--;
}
ppci++;
}
break;
case rgnPART:
{
TEXTPOS *ppos;
int nbox;
BoxPtr pbox;
RegionPtr cclip;
int xpos;
unsigned int i;
BoxRec clip;
int leftEdge, rightEdge;
int topEdge, bottomEdge;
int glyphRow;
int glyphCol;
#if GETLEFTBITS_ALIGNMENT > 1
int getWidth;
#endif
if(!(ppos = (TEXTPOS *)ALLOCATE_LOCAL(nglyph * sizeof(TEXTPOS))))
return;
pdstBase = pdstBase + (widthDst * y) + (x >> PWSH);
xpos = x;
xchar = xpos & PIM;
for (i=0; i<nglyph; i++)
{
pci = ppci[i];
ppos[i].xpos = xpos;
ppos[i].xchar = xchar;
ppos[i].leftEdge = xpos + pci->metrics.leftSideBearing;
ppos[i].rightEdge = xpos + pci->metrics.rightSideBearing;
ppos[i].topEdge = y - pci->metrics.ascent;
ppos[i].bottomEdge = y + pci->metrics.descent;
ppos[i].pdstBase = pdstBase;
ppos[i].widthGlyph = GLYPHWIDTHBYTESPADDED(pci);
xpos += pci->metrics.characterWidth;
xchar += pci->metrics.characterWidth;
if (xchar > PLST)
{
xchar &= PIM;
pdstBase++;
}
else if (xchar < 0)
{
xchar += PPW;
pdstBase--;
}
}
cclip = pGC->pCompositeClip;
pbox = REGION_RECTS(cclip);
nbox = REGION_NUM_RECTS(cclip);
pbox--;
while(nbox--)
{
pbox++;
clip.x1 = max(bbox.x1, pbox->x1);
clip.y1 = max(bbox.y1, pbox->y1);
clip.x2 = min(bbox.x2, pbox->x2);
clip.y2 = min(bbox.y2, pbox->y2);
if ((clip.x2<=clip.x1) || (clip.y2<=clip.y1))
continue;
for(i=0; i<nglyph; i++)
{
pci = ppci[i];
xchar = ppos[i].xchar;
if (ppos[i].leftEdge < clip.x1)
leftEdge = clip.x1;
else
leftEdge = ppos[i].leftEdge;
if (ppos[i].rightEdge > clip.x2)
rightEdge = clip.x2;
else
rightEdge = ppos[i].rightEdge;
w = rightEdge - leftEdge;
if (w <= 0)
continue;
if (ppos[i].topEdge < clip.y1)
topEdge = clip.y1;
else
topEdge = ppos[i].topEdge;
if (ppos[i].bottomEdge > clip.y2)
bottomEdge = clip.y2;
else
bottomEdge = ppos[i].bottomEdge;
h = bottomEdge - topEdge;
if (h <= 0)
continue;
glyphRow = (topEdge - y) + pci->metrics.ascent;
widthGlyph = ppos[i].widthGlyph;
pglyph = FONTGLYPHBITS(pglyphBase, pci);
pglyph += (glyphRow * widthGlyph);
pdst = ppos[i].pdstBase - ((y-topEdge) * widthDst);
glyphCol = (leftEdge - ppos[i].xpos) -
(pci->metrics.leftSideBearing);
#if GETLEFTBITS_ALIGNMENT > 1
getWidth = w + glyphCol;
#endif
xoff = xchar + (leftEdge - ppos[i].xpos);
if (xoff > PLST)
{
xoff &= PIM;
pdst++;
}
else if (xoff < 0)
{
xoff += PPW;
pdst--;
}
if ((xoff + w) <= PPW)
{
maskpartialbits(xoff, w, startmask);
while (h--)
{
getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc);
UPDRW(pdst,(SCRRIGHT(tmpSrc, xoff) & startmask));
pglyph += widthGlyph;
pdst += widthDst;
}
}
else
{
maskPPWbits(xoff, w, startmask, endmask);
nFirst = PPW - xoff;
while (h--)
{
getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc);
UPDRW(pdst,(SCRRIGHT(tmpSrc, xoff) & startmask));
UPDRW(&(pdst[1]),(SCRLEFT(tmpSrc, nFirst) & endmask));
pglyph += widthGlyph;
pdst += widthDst;
}
}
}
}
DEALLOCATE_LOCAL(ppos);
break;
}
default:
break;
}
}