/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/p9000/p9000text.c,v 3.3.2.1 1998/10/21 10:44:38 dawes Exp $ */ /* * Copyright 1992,1993 by Kevin E. Martin, Chapel Hill, North Carolina. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Kevin E. Martin not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Kevin E. Martin makes no * representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. * * KEVIN E. MARTIN AND RICKARD E. FAITH DISCLAIM ALL WARRANTIES WITH REGARD * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL KEVIN E. MARTIN BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Modified for the Mach-8 by Rickard E. Faith (faith@cs.unc.edu) * Modified for the Mach32 by Kevin E. Martin (martin@cs.unc.edu) * Modified for Mach32 By Mike Bernson (mike@mbsun.mlb.org) from mach8 version * Modified for the p9000 by chris mason (clmtch@osfmail.isc.rit.edu) */ /* $XConsortium: p9000text.c /main/4 1996/02/21 17:33:15 kaleb $ */ #include "X.h" #include "Xmd.h" #include "Xproto.h" #include "cfb.h" #include "misc.h" #include "xf86.h" #include "gcstruct.h" #include "windowstr.h" #include "fontstruct.h" #include "dixfontstr.h" #include "mi.h" #include "p9000.h" #include "p9000reg.h" __inline__ static int p9000NoCPolyText() ; __inline__ static int p9000NoCImageText() ; /* * The guts of this should possibly be tidied up and put in mach32im.c. * The generic Stipple functions in mach32im.c have quite a large unnecessary * overhead for bitmap copies in the case that we are doing an exacy copy * with no tiling and starting from (0,0) in the source bitmap. - Jon. */ __inline__ static void p9000PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) DrawablePtr pDrawable; GC *pGC; int x, y; unsigned int nglyph; CharInfoPtr *ppci; /* array of character info */ unsigned char *pglyphBase; /* start of array of glyphs */ { int width, height; int nbyLine; /* bytes per line of padded pixmap */ FontPtr pfont; register int i; register int j; unsigned char *pbits; /* buffer for PutImage */ register unsigned char *pb; /* temp pointer into buffer */ register CharInfoPtr pci; /* currect char info */ register unsigned char *pglyph; /* pointer bits in glyph */ int gWidth, gHeight; /* width and height of glyph */ register int nbyGlyphWidth; /* bytes per scanline of glyph */ int nbyPadGlyph; /* server padded line of glyph */ pfont = pGC->font; width = FONTMAXBOUNDS(pfont,rightSideBearing) - FONTMINBOUNDS(pfont,leftSideBearing); height = FONTMAXBOUNDS(pfont,ascent) + FONTMAXBOUNDS(pfont,descent); nbyLine = PixmapBytePad(width, 1); pbits = (unsigned char *)ALLOCATE_LOCAL(height*nbyLine); if (!pbits) { return; } while(nglyph--) { pci = *ppci++ ; pglyph = FONTGLYPHBITS(pglyphBase, pci); gWidth = GLYPHWIDTHPIXELS(pci); gHeight = GLYPHHEIGHTPIXELS(pci); if (gWidth && gHeight) { nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(pci); nbyPadGlyph = PixmapBytePad(gWidth, 1); if (nbyGlyphWidth == nbyPadGlyph #if GLYPHPADBYTES != 4 && (((int) pglyph) & 3) == 0 #endif ) { pb = pglyph; } else { for (i=0, pb = pbits; imetrics.leftSideBearing) ; p9000Store(DEVICE_COORD | DC_1 | DC_X, CtlBase, x + pci->metrics.leftSideBearing) ; p9000Store(DEVICE_COORD | DC_1 | DC_Y, CtlBase, y - pci->metrics.ascent) ; p9000Store(DEVICE_COORD | DC_2 | DC_X, CtlBase, x + pci->metrics.leftSideBearing + gWidth) ; p9000Store(DEVICE_COORD | DC_3 | DC_Y, CtlBase, 1) ; { register unsigned char *pix ; for (i = 0 ; i < gHeight; ) { j = gWidth ; pix = pb + i * nbyPadGlyph ; i++ ; while (j > 32) { p9000Store(CMD_PIXEL1_32 | HBBSWAP, CtlBase, *(int *)pix) ; pix += 4 ; j -= 32 ; } if (j > 0) { p9000Store(CMD_PIXEL1(j) | HBBSWAP, CtlBase, *(int *)pix) ; } } } } x += pci->metrics.characterWidth; } DEALLOCATE_LOCAL(pbits); } static __inline__ int p9000NoCPolyText(pDraw, pGC, x, y, count, chars, is8bit) DrawablePtr pDraw; GCPtr pGC; int x; int y; int count; char *chars; Bool is8bit; { int i; BoxPtr pBox; int numRects; RegionPtr pRegion; int yBand; int maxAscent, maxDescent; int minLeftBearing; int old_w_min, old_w_max ; FontPtr pfont = pGC->font; int ret_x; unsigned long n; CharInfoPtr *charinfo; if (!OnScreenDrawable(pDraw->type) || !xf86VTSema || (pGC->fillStyle != FillSolid) ) { if (is8bit) return miPolyText8(pDraw, pGC, x, y, count, chars) ; else return miPolyText16(pDraw, pGC, x,y,count, (unsigned short *)chars) ; } old_w_min = p9000Fetch(W_MIN, CtlBase) ; old_w_max = p9000Fetch(W_MAX, CtlBase) ; if(!(charinfo = (CharInfoPtr *)ALLOCATE_LOCAL(count*sizeof(CharInfoPtr )))) return x ; if (is8bit) GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, Linear8Bit, &n, charinfo); else GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, &n, charinfo); /* * If miPolyText8() is to be believed, the returned new X value is * completely independent of what happens during rendering. */ ret_x = x; for (i = 0; i < n; i++) { ret_x += charinfo[i]->metrics.characterWidth; } if (n == 0) { DEALLOCATE_LOCAL(charinfo); return ret_x; } x += pDraw->x; y += pDraw->y; maxAscent = FONTMAXBOUNDS(pfont, ascent); maxDescent = FONTMAXBOUNDS(pfont, descent); minLeftBearing = FONTMINBOUNDS(pfont, leftSideBearing); pRegion = ((cfbPrivGC *) (pGC->devPrivates[cfbGCPrivateIndex].ptr))->pCompositeClip; pBox = REGION_RECTS(pRegion); numRects = REGION_NUM_RECTS(pRegion); while (numRects && pBox->y2 <= y - maxAscent) { ++pBox; --numRects; } if (!numRects || pBox->y1 >= y + maxDescent) { DEALLOCATE_LOCAL(charinfo); return ret_x; } yBand = pBox->y1; while (numRects && pBox->y1 == yBand && pBox->x2 <= x + minLeftBearing) { ++pBox; --numRects; } if (!numRects) { DEALLOCATE_LOCAL(charinfo); return ret_x; } p9000NotBusy() ; p9000Store(RASTER, CtlBase, p9000PixAlu[pGC->alu]) ; p9000Store(FGROUND, CtlBase, pGC->fgPixel) ; p9000Store(PMASK, CtlBase, pGC->planemask) ; for (; --numRects >= 0; ++pBox) { p9000NotBusy() ; p9000Store(W_MIN, CtlBase, YX_PACK(pBox->x1, pBox->y1)) ; p9000Store(W_MAX, CtlBase, YX_PACK(pBox->x2-1, pBox->y2-1)) ; p9000PolyGlyphBlt(pDraw, pGC, x, y, (unsigned int)n, charinfo, FONTGLYPHS(pGC->font)); } DEALLOCATE_LOCAL(charinfo); p9000NotBusy() ; p9000Store(W_MIN, CtlBase, old_w_min) ; p9000Store(W_MAX, CtlBase, old_w_max) ; return ret_x; } /* * Imagetext is all in one function to avoid calling GetGlyphs() twice. * - Jon. */ static __inline__ int p9000NoCImageText(pDraw, pGC, x, y, count, chars, is8bit) DrawablePtr pDraw; GCPtr pGC; int x; int y; int count; char *chars; Bool is8bit; { ExtentInfoRec info; /* used by QueryGlyphExtents() */ XID gcvals[3]; int oldAlu, oldFS; unsigned long oldFG; xRectangle backrect; register CharInfoPtr *charinfo; unsigned long n; int old_w_min, old_w_max ; if (!OnScreenDrawable(pDraw->type) || !xf86VTSema || (pGC->fillStyle != FillSolid) ) { if (is8bit) miImageText8(pDraw, pGC, x, y, count, chars) ; else miImageText16(pDraw, pGC, x, y, count, (unsigned short *)chars) ; return 1 ; } old_w_min = p9000Fetch(W_MIN, CtlBase) ; old_w_max = p9000Fetch(W_MAX, CtlBase) ; if (!(charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr)))) return 0; if (is8bit) GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, Linear8Bit, &n, charinfo); else GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, &n, charinfo); QueryGlyphExtents(pGC->font, charinfo, n, &info); if (info.overallWidth >= 0) { backrect.x = x; backrect.width = info.overallWidth; } else { backrect.x = x + info.overallWidth; backrect.width = -info.overallWidth; } backrect.y = y - FONTASCENT(pGC->font); backrect.height = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); oldAlu = pGC->alu; oldFG = pGC->fgPixel; oldFS = pGC->fillStyle; gcvals[0] = GXcopy; gcvals[1] = pGC->bgPixel; gcvals[2] = FillSolid; DoChangeGC(pGC, GCFunction | GCForeground | GCFillStyle, gcvals, 0); ValidateGC(pDraw, pGC); (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &backrect); /* put down the glyphs */ gcvals[0] = oldAlu; gcvals[1] = oldFG; gcvals[2] = oldFS; DoChangeGC(pGC, GCFunction | GCForeground | GCFillStyle, gcvals, 0); ValidateGC(pDraw, pGC); /* begin the font blitting */ { register BoxPtr pBox; register int numRects; register RegionPtr pRegion; int maxAscent, maxDescent; int yBand; int minLeftBearing; register FontPtr pfont = pGC->font; x += pDraw->x; y += pDraw->y; maxAscent = FONTMAXBOUNDS(pfont, ascent); maxDescent = FONTMAXBOUNDS(pfont, descent); minLeftBearing = FONTMINBOUNDS(pfont, leftSideBearing); pRegion = ((cfbPrivGC *) (pGC->devPrivates[cfbGCPrivateIndex].ptr))->pCompositeClip; pBox = REGION_RECTS(pRegion); numRects = REGION_NUM_RECTS(pRegion); while (numRects && pBox->y2 <= y - maxAscent) { ++pBox; --numRects; } if (!numRects || pBox->y1 >= y + maxDescent) { DEALLOCATE_LOCAL(charinfo); return 0; } yBand = pBox->y1; while (numRects && pBox->y1 == yBand && pBox->x2 <= x + minLeftBearing) { ++pBox; --numRects; } if (!numRects) { DEALLOCATE_LOCAL(charinfo); return 0; } p9000NotBusy() ; p9000Store(FGROUND, CtlBase, pGC->fgPixel) ; p9000Store(BGROUND, CtlBase, pGC->bgPixel) ; p9000Store(PMASK, CtlBase, pGC->planemask) ; p9000Store(RASTER, CtlBase, (IGM_S_MASK & IGM_F_MASK) | (~IGM_S_MASK & IGM_D_MASK)); for (; --numRects >= 0; ++pBox) { p9000NotBusy() ; p9000Store(W_MIN, CtlBase, YX_PACK(pBox->x1, pBox->y1)) ; p9000Store(W_MAX, CtlBase, YX_PACK(pBox->x2-1, pBox->y2-1)) ; p9000PolyGlyphBlt(pDraw, pGC, x, y, (unsigned int)n, charinfo, FONTGLYPHS(pGC->font)); } } /* end font blitting */ /* put all the toys away when done playing */ /* note the GC was changed back previously */ DEALLOCATE_LOCAL(charinfo); p9000NotBusy() ; p9000Store(W_MIN, CtlBase, old_w_min) ; p9000Store(W_MAX, CtlBase, old_w_max) ; return 0; } int p9000PolyText8(pDraw, pGC, x, y, count, chars) DrawablePtr pDraw; GCPtr pGC; int x; int y; int count; char *chars; { return p9000NoCPolyText(pDraw, pGC, x, y, count, chars, 1) ; } int p9000PolyText16(pDraw, pGC, x, y, count, chars) DrawablePtr pDraw; GCPtr pGC; int x; int y; int count; unsigned short *chars; { return p9000NoCPolyText(pDraw, pGC, x, y, count, chars, 0) ; } int p9000ImageText8(pDraw, pGC, x, y, count, chars) DrawablePtr pDraw; GCPtr pGC; int x; int y; int count; char *chars; { return p9000NoCImageText(pDraw, pGC, x, y, count, chars, 1) ; } int p9000ImageText16(pDraw, pGC, x, y, count, chars) DrawablePtr pDraw; GCPtr pGC; int x; int y; int count; unsigned short *chars; { return p9000NoCImageText(pDraw, pGC, x, y, count, chars, 0) ; }