2014-11-06 13:19:51 +01:00

331 lines
9.1 KiB
C

/* $XConsortium: xf86fcache.c,v 1.4 95/01/05 20:25:04 kaleb Exp $ */
/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/cache/xf86fcache.c,v 3.8 1995/07/07 15:38:25 dawes Exp $ */
/*
* Copyright 1992 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 DISCLAIMS 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.
*
*/
/*
* Extracted from s3fcach.c and adapted to XFree86 in X11R6 by
* Hans Nasten. ( nasten@everyware.se ).
*/
/*
* Modified for the CyberVision 64 by Michael Teske
*/
#include "amiga.h"
#include "X.h"
#include "Xmd.h"
#include "Xproto.h"
#include "cfb.h"
#include "misc.h"
#include "windowstr.h"
#include "gcstruct.h"
#include "fontstruct.h"
#include "dixfontstr.h"
#include "xf86bcache.h"
#include "xf86fcache.h"
#include "amigaCV.h"
static CacheFont8Ptr xf86HeadFont = NULL;
static CachePool xf86FontPool = NULL;
static int xf86MaxWidth;
static int xf86MaxHeight;
static void (*xf86FontOpStippleFunc)(
#if NeedFunctionPrototypes
int, int, int, int, unsigned char *, int, Pixel
#endif
);
/*
* Init the font cache.
* The Cache Pool pointer is stored together with various other information
*/
void
xf86InitFontCache(
CachePool FontCache,
int MaxWidth,
int MaxHeight,
void (*FontOpStippleFunc)(
int, int, int, int, unsigned char *, int, Pixel
)
)
{
xf86FontPool = FontCache;
xf86MaxWidth = MaxWidth / 32;
xf86MaxHeight = MaxHeight;
xf86HeadFont = (CacheFont8Ptr) Xcalloc(sizeof(CacheFont8Rec));
xf86FontOpStippleFunc = FontOpStippleFunc;
}
/*
* Release all cache blocks to the block allocator.
*/
void xf86ReleaseFontCache(void)
{
CacheFont8Ptr CFptr;
int i;
/*
* The screen has been destroyed so we must go through
* all cached font blocks and return them to the cache
*/
ERROR_F(("Releasing font cache.\n"));
for (CFptr = xf86HeadFont; CFptr != NULL; CFptr=CFptr->next) {
if (CFptr->font) {
for (i = 0; i < 8; i++) {
if (CFptr->fblock[i] != NULL)
xf86ReleaseToCachePool( xf86FontPool, CFptr->fblock[i] );
}
}
}
}
/*
* Remove a font from the font cache.
*/
void
xf86UnCacheFont8(FontPtr font)
{
int i;
CacheFont8Ptr ptr, last;
ERROR_F(("UnCach %d\n", font));
last = xf86HeadFont;
for (ptr = xf86HeadFont; ptr != NULL; ptr = ptr->next) {
if (ptr->font == font) {
for (i = 0; i < 8; i++)
if (ptr->fblock[i] != NULL)
xf86ReleaseToCachePool( xf86FontPool, ptr->fblock[i] );
if (ptr != xf86HeadFont) {
last->next = ptr->next;
xfree(ptr);
} else {
if (ptr->next != NULL) { /* move the head down */
xf86HeadFont=ptr->next;
xfree(ptr);
} else { /* one and only entry */
xf86HeadFont->font = NULL;
}
}
#ifdef DEBUG_FCACHE
for (ptr = xf86HeadFont; ptr != NULL; ptr = ptr->next)
__dolog("fonts %d\n", ptr->font);
#endif
return;
}
last=ptr;
}
}
/*
* Add a new font to the font cache.
*/
CacheFont8Ptr
xf86CacheFont8(FontPtr font)
{
int c;
unsigned long n;
unsigned char chr;
int width, height;
CharInfoPtr pci;
CacheFont8Ptr last, ret = xf86HeadFont;
if( !xf86FontPool ) /* No font cache available */
return( NULL );
/* XXX*/
/* font->refcnt++;*/
while (ret != NULL) {
if (ret->font == font) {
return ret;
}
last = ret;
ret = ret->next;
}
width = FONTMAXBOUNDS(font, rightSideBearing) -
FONTMINBOUNDS(font, leftSideBearing);
height = FONTMAXBOUNDS(font, ascent) + FONTMAXBOUNDS(font, descent);
if ((width > xf86MaxWidth) || (height > xf86MaxHeight) ||
(FONTFIRSTROW(font) != 0) || (FONTLASTROW(font) != 0) ||
(FONTLASTCOL(font) > 255))
return NULL;
if (xf86HeadFont->font == NULL)
ret = xf86HeadFont;
else
ret = (CacheFont8Ptr) Xcalloc(sizeof(CacheFont8Rec));
if (ret == NULL) {
return NULL;
}
ret->w = width;
ret->h = height;
ret->font = font;
/*
* We load all the font infos now, and the fonts themselves are demand
* loaded into the cache as 32 font bitmaps. This way we can load alot
* more things into cache at the expense of the cache management.
*/
for (c = 0; c < 256; c++) {
chr = (unsigned char)c;
GetGlyphs(font, 1, &chr, Linear8Bit, &n, &pci);
if (n == 0) {
ret->pci[c] = NULL;
} else {
ret->pci[c] = pci;
}
}
if (ret != xf86HeadFont)
last->next = ret;
/* test: */
ret->next = NULL;
return ret;
}
/*
* Load a block of 32 glyphs into a cache block requested
* from the block allocator.
*/
void
xf86loadFontBlock(CacheFont8Ptr fentry, int block)
{
int i, j, c;
unsigned char chr;
int nbyLine;
unsigned char *pb, *pbits;
unsigned char *pglyph;
int gWidth, gHeight;
int nbyGlyphWidth;
int nbyPadGlyph;
nbyLine = PixmapBytePad(fentry->w, 1);
__dolog("loading %d (%d) %d\n", fentry->font, block, fentry->fblock[block]);
pbits = (unsigned char *)ALLOCATE_LOCAL(nbyLine * fentry->h);
if (pbits != NULL &&
(fentry->fblock[block] = xf86AllocFromCachePool( xf86FontPool,
32 * fentry->w,
fentry->h )) != NULL) {
fentry->fblock[block]->reference = (pointer *) &(fentry->fblock[block]);
fentry->fblock[block]->lru = 0x7fffffff;
for (c = block * 32; c < (block * 32) + 32; c++) {
if (fentry->pci[c] != NULL) {
chr = (unsigned char)c;
pglyph = FONTGLYPHBITS(pglyphBase, fentry->pci[c]);
gWidth = GLYPHWIDTHPIXELS(fentry->pci[c]);
gHeight = GLYPHHEIGHTPIXELS(fentry->pci[c]);
if (gWidth && gHeight) {
nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(fentry->pci[c]);
nbyPadGlyph = PixmapBytePad(gWidth, 1);
if (nbyGlyphWidth == nbyPadGlyph
#if GLYPHPADBYTES != 4
&& (((int)pglyph) & 3) == 0
#endif
)
pb = pglyph;
else {
for (i = 0, pb = pbits;
i < gHeight;
i++, pb = pbits + (i * nbyPadGlyph))
for (j = 0; j < nbyGlyphWidth; j++)
*pb++ = *pglyph++;
pb = pbits;
}
(xf86FontOpStippleFunc)( fentry->fblock[block]->x +
(c % 32) * fentry->w,
fentry->fblock[block]->y,
gWidth, gHeight,
pb, nbyGlyphWidth,
fentry->fblock[block]->id);
}
}
}
DEALLOCATE_LOCAL(pbits);
} else {
CacheFont8Ptr fptr;
Bool found = FALSE;
/*
* If we get here we are in deep trouble, half way through printing a
* string we have been unable to load a font block into the cache, the
* get Block function found no block of the right size, this is probably
* impossible but just to stop potential core dumps we shall do something
* stupid about it anyway we just throw away the font blocks of another
* font. Or even ourselves in desperate times!
* Unfortunatly this doesn't work if we use the preload code so the
* demand load makes more sense.
*/
if (pbits) DEALLOCATE_LOCAL(pbits);
__dolog("Time to write new font cache management\n");
for (fptr = xf86HeadFont; fptr != NULL; fptr= fptr->next)
if (fptr != fentry) {
for (i = 0; i < 8; i++)
if (fptr->fblock[i] != NULL) {
xf86ReleaseToCachePool( xf86FontPool, fptr->fblock[i] );
fptr->fblock[i] = NULL;
found = TRUE;
}
if (found)
break;
}
/* getting real desperate - this doesn't work with pre-loading */
if (!found) {
for (i = 0; i < 8; i++)
if (fentry->fblock[i] != NULL) {
xf86ReleaseToCachePool( xf86FontPool, fentry->fblock[i] );
fentry->fblock[i] = NULL;
}
}
xf86loadFontBlock(fentry, block);
return;
}
#ifdef DEBUG_FCACHE
for(fentry=xf86HeadFont;fentry != NULL;fentry=fentry->next)
if( fentry->font != NULL )
for (i = 0; i < 8; i++)
__dolog(("got %d (%d) %d x=%d y=%d w=%d h=%d\n",
fentry->font, i, fentry->fblock[i],
fentry->fblock[i] != NULL ? fentry->fblock[i]->x : 0,
fentry->fblock[i] != NULL ? fentry->fblock[i]->y : 0,
fentry->fblock[i] != NULL ? fentry->fblock[i]->w : 0,
fentry->fblock[i] != NULL ? fentry->fblock[i]->h : 0));
#endif
}