#include "ffb.h"
#include "ffb_regs.h"
#include "ffb_rcache.h"
#include "ffb_fifo.h"
#include "ffb_loops.h"
#include "pixmapstr.h"
#include "scrnintstr.h"
#include "fontstruct.h"
#include "dixfontstr.h"
#define PSZ 8
#include "cfb.h"
#undef PSZ
#include "cfb32.h"
void
CreatorPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase)
{
FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
ffb_fbcPtr ffb = pFfb->regs;
FontPtr pfont = pGC->font;
RegionPtr clip = cfbGetCompositeClip(pGC);
BoxPtr pbox = REGION_RECTS(clip);
int nbox = REGION_NUM_RECTS(clip);
int skippix, skipglyph, width, n, i;
int Left, Right, Top, Bottom, LeftEdge, RightEdge;
FFBLOG(("CreatorPolyGlyphBlt: xy[%08x:%08x] nglyph(%d)\n", x, y, nglyph));
x += pDrawable->x;
y += pDrawable->y;
width = 0;
for(i = 0; i < (nglyph - 1); i++)
width += (ppci[i])->metrics.characterWidth;
Left = x + (ppci[0])->metrics.leftSideBearing;
Right = x + (width + (ppci[nglyph - 1])->metrics.rightSideBearing);
Top = y - FONTMAXBOUNDS(pfont, ascent);
Bottom = y + FONTMAXBOUNDS(pfont, descent);
while(nbox && (Top >= pbox->y2)) {
pbox++;
nbox--;
}
if(!nbox || Bottom < pbox->y1)
return;
{
unsigned int ppc = (FFB_PPC_APE_DISABLE | FFB_PPC_TBE_TRANSPARENT |
FFB_PPC_CS_CONST);
unsigned int ppc_mask = (FFB_PPC_APE_MASK | FFB_PPC_TBE_MASK |
FFB_PPC_CS_MASK);
unsigned int pmask = pGC->planemask;
unsigned int rop = (FFB_ROP_EDIT_BIT | pGC->alu) | (FFB_ROP_NEW << 8);
unsigned int fg = pGC->fgPixel;
WindowPtr pWin = (WindowPtr) pDrawable;
unsigned int fbc = FFB_FBC_WIN(pWin);
fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
if((pFfb->ppc_cache & ppc_mask) != ppc ||
pFfb->fg_cache != fg ||
pFfb->fbc_cache != fbc ||
pFfb->rop_cache != rop ||
pFfb->pmask_cache != pmask ||
pFfb->fontinc_cache != ((1<<16) | 0)) {
pFfb->ppc_cache &= ~ppc_mask;
pFfb->ppc_cache |= ppc;
pFfb->fg_cache = fg;
pFfb->fbc_cache = fbc;
pFfb->rop_cache = rop;
pFfb->pmask_cache = pmask;
pFfb->fontinc_cache = ((1<<16) | 0);
pFfb->rp_active = 1;
FFBFifo(pFfb, 6);
ffb->ppc = ppc;
ffb->fg = fg;
ffb->fbc = fbc;
ffb->rop = rop;
ffb->pmask = pmask;
ffb->fontinc = ((1 << 16) | 0);
}
}
while(nbox && (Bottom >= pbox->y1)) {
LeftEdge = max(Left, pbox->x1);
RightEdge = min(Right, pbox->x2);
if(RightEdge > LeftEdge) {
int walk, x_start;
skippix = LeftEdge - x;
skipglyph = walk = 0;
while(skippix >= (walk + (ppci[skipglyph])->metrics.rightSideBearing)) {
walk += (ppci[skipglyph])->metrics.characterWidth;
skipglyph++;
}
x_start = x + walk;
skippix = RightEdge - x;
n = 0;
i = skipglyph;
while((i < nglyph) &&
(skippix > (walk + (ppci[i])->metrics.leftSideBearing))) {
walk += (ppci[i])->metrics.characterWidth;
i++;
n++;
}
if(n) {
CharInfoPtr *ppci_iter = ppci + skipglyph;
CharInfoPtr pci;
unsigned int *bits;
int w, h, x0, y0, xskip, yskip;
while(n--) {
pci = *ppci_iter++;
w = GLYPHWIDTHPIXELS(pci);
h = GLYPHHEIGHTPIXELS(pci);
if(!w || !h)
goto next_glyph;
x0 = x_start + pci->metrics.leftSideBearing;
y0 = y - pci->metrics.ascent;
bits = (unsigned int *) pci->bits;
xskip = yskip = 0;
if(pbox->x1 > x0) {
xskip = pbox->x1 - x0;
w -= xskip;
x0 = pbox->x1;
if(w <= 0)
goto next_glyph;
}
if(pbox->y1 > y0) {
yskip = pbox->y1 - y0;
h -= yskip;
y0 = pbox->y1;
if(h <= 0)
goto next_glyph;
}
if(pbox->x2 < (x0 + w)) {
w = pbox->x2 - x0;
if(w <= 0)
goto next_glyph;
}
if(pbox->y2 < (y0 + h)) {
h = pbox->y2 - y0;
if(h <= 0)
goto next_glyph;
}
FFB_WRITE_FONTW(pFfb, ffb, w);
FFBFifo(pFfb, 1 + h);
ffb->fontxy = ((y0 << 16) | x0);
for(i = 0; i < h; i++)
ffb->font = bits[yskip + i] << xskip;
next_glyph:
x_start += pci->metrics.characterWidth;
}
}
}
nbox--;
pbox++;
}
pFfb->rp_active = 1;
FFBSync(pFfb, ffb);
}
void
CreatorTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase)
{
FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
ffb_fbcPtr ffb = pFfb->regs;
RegionPtr clip = cfbGetCompositeClip(pGC);
int nbox = REGION_NUM_RECTS(clip);
BoxPtr pbox = REGION_RECTS(clip);
FontPtr pfont = pGC->font;
int glyphWidth = FONTMAXBOUNDS(pfont, characterWidth);
int skippix, skipglyphs, Left, Right, Top, Bottom;
int LeftEdge, RightEdge, ytop, ybot, h, w;
FFBLOG(("CreatorTEGlyphBlt: xy[%08x:%08x] nglyph(%d) pgbase(%p)\n",
x, y, nglyph, pGlyphBase));
Left = x + pDrawable->x;
Right = Left + (glyphWidth * nglyph);
y += pDrawable->y;
Top = y - FONTASCENT(pfont);
Bottom = y + FONTDESCENT(pfont);
while(nbox && (Top >= pbox->y2)) {
pbox++;
nbox--;
}
if(!nbox || Bottom <= pbox->y1)
return;
{
unsigned int ppc = FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
unsigned int ppc_mask = FFB_PPC_APE_MASK|FFB_PPC_TBE_MASK|FFB_PPC_CS_MASK;
unsigned int pmask = pGC->planemask;
unsigned int rop;
unsigned int fg = pGC->fgPixel;
unsigned int bg = pGC->bgPixel;
WindowPtr pWin = (WindowPtr) pDrawable;
unsigned int fbc = FFB_FBC_WIN(pWin);
fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
if(pGlyphBase) {
ppc |= FFB_PPC_TBE_TRANSPARENT;
rop = FFB_ROP_EDIT_BIT | pGC->alu;
} else {
ppc |= FFB_PPC_TBE_OPAQUE;
rop = FFB_ROP_EDIT_BIT | GXcopy;
}
rop |= (FFB_ROP_NEW << 8);
if((pFfb->ppc_cache & ppc_mask) != ppc ||
pFfb->fg_cache != fg ||
pFfb->fbc_cache != fbc ||
pFfb->rop_cache != rop ||
pFfb->pmask_cache != pmask ||
pFfb->fontinc_cache != ((1<<16) | 0) ||
(!pGlyphBase && pFfb->bg_cache != bg)) {
pFfb->ppc_cache &= ~ppc_mask;
pFfb->ppc_cache |= ppc;
pFfb->fg_cache = fg;
pFfb->fbc_cache = fbc;
pFfb->rop_cache = rop;
pFfb->pmask_cache = pmask;
pFfb->fontinc_cache = ((1<<16) | 0);
if(!pGlyphBase)
pFfb->bg_cache = bg;
FFBFifo(pFfb, (!pGlyphBase ? 7 : 6));
ffb->ppc = ppc;
ffb->fg = fg;
ffb->fbc = fbc;
ffb->rop = rop;
ffb->pmask = pmask;
ffb->fontinc = ((1 << 16) | 0);
if(!pGlyphBase)
ffb->bg = bg;
}
}
while(nbox && (Bottom > pbox->y1)) {
LeftEdge = max(Left, pbox->x1);
RightEdge = min(Right, pbox->x2);
if(RightEdge > LeftEdge) {
ytop = max(Top, pbox->y1);
ybot = min(Bottom, pbox->y2);
if((skippix = LeftEdge - Left)) {
skipglyphs = skippix / glyphWidth;
skippix %= glyphWidth;
} else
skipglyphs = 0;
w = RightEdge - LeftEdge;
if(skippix) {
unsigned int *gbits = (unsigned int *) ppci[skipglyphs++]->bits;
int chunk_size = (glyphWidth - skippix);
if (chunk_size > w)
chunk_size = w;
FFB_WRITE_FONTW(pFfb, ffb, chunk_size);
FFBFifo(pFfb, 1 + (ybot - ytop));
ffb->fontxy = ((ytop << 16) | LeftEdge);
for(h = (ytop - Top); h < (ybot - Top); h++)
ffb->font = gbits[h] << skippix;
LeftEdge += chunk_size;
w -= chunk_size;
}
#define LoopIt(chunkW, loadup, fetch) \
FFB_WRITE_FONTW(pFfb, ffb, chunkW); \
while (w >= chunkW) { \
loadup \
FFBFifo(pFfb, 1 + (ybot - ytop)); \
ffb->fontxy = ((ytop << 16) | LeftEdge); \
for(h = (ytop - Top); h < (ybot - Top); h++) \
ffb->font = fetch; \
LeftEdge += chunkW; \
w -= chunkW; \
}
if(glyphWidth <= 8) {
int chunk_size = glyphWidth << 2;
LoopIt(chunk_size,
unsigned int *char1 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
unsigned int *char2 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
unsigned int *char3 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
unsigned int *char4 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);,
(*char1++ | ((*char2++ | ((*char3++ | (*char4++ >> glyphWidth))
>> glyphWidth))
>> glyphWidth)))
} else if(glyphWidth <= 10) {
int chunk_size = (glyphWidth << 1) + glyphWidth;
LoopIt(chunk_size,
unsigned int *char1 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
unsigned int *char2 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
unsigned int *char3 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);,
(*char1++ | ((*char2++ | (*char3++ >> glyphWidth)) >> glyphWidth)));
} else if(glyphWidth <= 16) {
int chunk_size = glyphWidth << 1;
LoopIt(chunk_size,
unsigned int *char1 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
unsigned int *char2 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);,
(*char1++ | (*char2++ >> glyphWidth)));
}
#undef LoopIt
while(w > 0) {
unsigned int *gbits = (unsigned int *) ppci[skipglyphs++]->bits;
int pix = glyphWidth;
if(w < pix)
pix = w;
FFB_WRITE_FONTW(pFfb, ffb, pix);
FFBFifo(pFfb, 1 + (ybot - ytop));
ffb->fontxy = ((ytop << 16) | LeftEdge);
for(h = (ytop - Top); h < (ybot - Top); h++)
ffb->font = gbits[h];
LeftEdge += pix;
w -= pix;
}
}
nbox--;
pbox++;
}
pFfb->rp_active = 1;
FFBSync(pFfb, ffb);
}
void
CreatorPolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase)
{
CreatorTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (char *) 1);
}