home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
x
/
xibm.zip
/
apa16
/
apa16Font.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-03-23
|
13KB
|
486 lines
/***********************************************************
Copyright 1991 by the Massachusetts Institute of Technology
All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
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 the Massachusetts
Institute of Technology (M.I.T.) not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
M.I.T. 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.
******************************************************************/
#include "X.h"
#include "Xproto.h"
#include "region.h"
#include "misc.h"
#include "screenint.h"
#include "dixfontstr.h"
#include "OScompiler.h"
#include "apa16Decls.h"
#include "apa16Hdwr.h"
#include "apa16Font.h"
#include "ibmTrace.h"
/* apa16 font cache:
There are 4 areas of off-screen memory available for use as a font cache.
When a font is allocated, memory is allocated to hold the cache descriptor
but no off-screen memory is allocated. The first call to apa16ValidateGC
causes apa16CacheFont to be called. This allocates memory for the character
bitmap and metric pointers and calls get_glyphs to initialize them.
The first time the font is used, apa16CacheFontRow is called to allocate
offscreen memory. This may displace other fonts (there is a counter in
each font structure used for an LRU replacement). Individual characters
are copied in as needed.
There remains one problem: what to do if a the widths of the characters of
a font add to more than 1024. Currently the remaining characters are not
cached.
*/
#ifndef NO_FUNCTION_PROTOTYPES
static void apa16UncacheFontRow(apa16FontPtr, int);
#else
static void apa16UncacheFontRow();
#endif
/* This variable is used to determine the least recently used cached font.
Each user of a cached font should assign
font->afCache[row]->referenced = ++apa16_fontcache_counter;
*/
int apa16_fontcache_counter;
static struct apa16FontCache *cache_head[4], font_regions[4];
void apa16InitFontCache()
{
TRACE(("apa16InitFontCache"));
/* The code below never frees a font cache entry with a zero prev field;
it is easier to use the address of a static variable than to call
malloc and be prepared to handle failure. */
cache_head[0] = &font_regions[0];
cache_head[1] = &font_regions[1];
cache_head[2] = &font_regions[2];
cache_head[3] = &font_regions[3];
font_regions[0].xorg = 0;
font_regions[1].xorg = 0;
font_regions[2].xorg = 0;
font_regions[3].xorg = MAXCURSORS * 2 * CURSOR_WIDTH;
font_regions[0].yorg = 1009;
font_regions[1].yorg = 768;
font_regions[2].yorg = FONT_TOP;
font_regions[3].yorg = CURSOR_AREA_TOP;
font_regions[0].w = 1023;
font_regions[1].w = 1023;
font_regions[2].w = 1023;
font_regions[3].w = STAGE_X_OFFSET - MAXCURSORS * 2 * CURSOR_WIDTH;
font_regions[0].h = 15;
font_regions[1].h = 16;
font_regions[2].h = FONT_BOTTOM - FONT_TOP + 1; /* 48 */
font_regions[3].h = 64;
font_regions[0].prev = 0;
font_regions[1].prev = 0;
font_regions[2].prev = 0;
font_regions[3].prev = 0;
font_regions[0].next = 0;
font_regions[1].next = 0;
font_regions[2].next = 0;
font_regions[3].next = 0;
font_regions[0].used = 0;
font_regions[1].used = 0;
font_regions[2].used = 0;
font_regions[3].used = 0;
}
Bool
apa16RealizeFont(pScr, pFont)
ScreenPtr pScr;
register FontPtr pFont;
{
apa16FontPtr pAF;
TRACE(("apa16RealizeFont(%#x)", pFont));
if (pFont->info.maxbounds.characterWidth > 32 ||
FONTMAXBOUNDS(pFont,ascent) + FONTMAXBOUNDS(pFont,descent) + 1 > 24 ||
pFont->info.minbounds.characterWidth < 0 ||
pFont->info.drawDirection != FontLeftToRight ||
#ifndef ALLOW_16BIT
FONTLASTROW(pFont) > 1 || /* temporary restriction */
#endif
(pAF = (apa16FontPtr)Xalloc(sizeof(apa16Font))) == NULL)
{
return mfbRealizeFont(pScr, pFont);
}
if (!FontSetPrivate(pFont, apa16FontPrivateIndex, (pointer)pAF))
{
Xfree(pAF);
return mfbRealizeFont(pScr, pFont);
}
TRACE(("\tcached\n"));
pAF->afFont = pFont;
#if 1
pAF->afHeight = FONTMAXBOUNDS(pFont,ascent) + FONTMAXBOUNDS(pFont,descent);
#else
pAF->afHeight = FONTASCENT(pFont) + FONTDESCENT(pFont);
#endif
pAF->afNChars = FONTLASTCOL(pFont) - FONTFIRSTCOL(pFont) + 1;
pAF->afNrows = FONTLASTROW(pFont) + 1;
#ifdef ALLOW_16BIT
if (pAF->afNrows > 1)
pAF->afNChars *= ((pFont->info.lastRow - pFont->info.firstRow)+1);
#endif
pAF->afCache = NULL;
pAF->afDefChar = pFont->info.defaultCh + FONTFIRSTCOL(pFont);
if (pFont->info.constantWidth)
{
pAF->afDefWidth = pAF->afWidth = pFont->info.maxbounds.characterWidth;
}
else
{
pAF->afWidth = -1;
pAF->afDefWidth = -1; /* CacheFont will set this */
}
return TRUE;
}
Bool
apa16UnrealizeFont(pScr, pFont)
ScreenPtr pScr;
FontPtr pFont;
{
apa16FontPtr pAF = (apa16FontPtr)FontGetPrivate(pFont,apa16FontPrivateIndex);
TRACE(("apa16UnrealizeFont(%#x) cache %#x rows %d\n", pFont, pAF,
pAF ? pAF->afNrows : 0));
if (!pAF)
return mfbUnrealizeFont(pScr, pFont);
if (pAF->afCache)
{
int i;
for (i = pAF->afNrows - 1; i >= 0; i--)
apa16UncacheFontRow(pAF, i);
Xfree(pAF->afCache);
}
Xfree(pAF);
FontSetPrivate(pFont,apa16FontPrivateIndex,0);
return TRUE;
}
/* There is a design flaw in the font library: it is not possible
to find out where the holes in a font are except by querying each
individual character. */
static void apa16SlowGetGlyphs(xfont, nchars, chars, cip)
FontPtr xfont;
int nchars;
unsigned char *chars;
CharInfoPtr *cip;
{
int i;
for (i = 0; i < nchars; i++)
{
int n;
(*xfont->get_glyphs)(xfont, 1, chars++, Linear8Bit, &n, cip);
if (n != 1)
*cip = 0;
cip++;
}
}
Bool
apa16CacheFont(font)
apa16FontPtr font;
{
unsigned char allchars[256];
int i;
register apa16FontCache **fc;
register apa16FCCharInfo *ci;
FontPtr xfont = font->afFont;
int fontmin = FONTFIRSTCOL(xfont);
int fontmax = FONTLASTCOL(xfont);
int n;
#ifndef ALLOW_16BIT
if (font->afNrows > 1)
return FALSE;
#endif
/* If 16 bit fonts are allowed, multiply the malloc arg by the
number of rows. */
if ((fc = (apa16FontCache **)Xalloc(sizeof (apa16FontCache *))) == NULL)
return FALSE;
if ((ci = (apa16FCCharInfo *)Xalloc(sizeof (apa16FCCharInfo))) == NULL)
{
Xfree(fc);
return FALSE;
}
bzero(ci, sizeof(apa16FCCharInfo));
*fc = 0;
font->afCache = fc;
font->afChars = ci;
/* For now, assume 1 row (8 bit font). */
ci->cmin = fontmin;
ci->cmax = fontmax;
for (i = fontmin; i <= fontmax; i++)
allchars[i] = i;
(*xfont->get_glyphs)(xfont, fontmax - fontmin + 1,
allchars + fontmin, Linear8Bit,
&n, font->afChars[0].chars + fontmin);
if (n != fontmax - fontmin + 1)
apa16SlowGetGlyphs(xfont, fontmax - fontmin + 1, allchars + fontmin,
font->afChars[0].chars + fontmin);
font->afDefWidth = font->afChars[0].chars[font->afDefChar]->metrics.characterWidth;
TRACE(("apa16CacheFont(%x), default width = %d\n", font, font->afDefWidth));
return TRUE;
}
static apa16FontCache *
apa16FreeFontRow(h)
unsigned short h;
{
register apa16FontCache *fc;
unsigned int age = -1;
apa16FontCache *oldest = 0;
int i;
TRACE(("apa16FreeFontRow(%d)\n", h));
for (i = 0; i < 4; i++)
{
fc = cache_head[i];
do
if (fc->used && fc->h >= h && fc->referenced < age)
{
oldest = fc;
age = fc->referenced;
}
while (fc = fc->next);
}
if (oldest == 0)
return 0;
/* free oldest */
oldest->owner->afCache[oldest->row] = 0;
oldest->owner->afChars[oldest->row].cached = 0;
oldest->used = 0;
/* debug */
oldest->owner = 0;
fc = oldest->next;
if (fc && fc->used == 0 && fc->xorg == oldest->xorg && fc->w == oldest->w)
{
/* note: the permanent struct is always first on the chain,
therefore fc is not permanent */
oldest->h += fc->h;
oldest->next = fc->next;
if (fc->next)
fc->next->prev = oldest;
Xfree(fc);
}
return oldest;
}
static void
apa16UncacheFontRow(font, row)
apa16FontPtr font;
int row;
{
register apa16FontCache *fc = font->afCache[row], *tmpfc;
TRACE(("apa16UncacheFontRow(%x, %d) fc = %x\n", font, row, fc));
/* Even if a font is cached, a row of it may not be.
Check here to simplify callers. */
if (fc == 0)
return;
tmpfc = fc->next;
/* Because the first font cache in each region can't be freed (it
is staticly allocated), when there are two adjacent free regions
join them by freeing the second one. */
if (tmpfc && tmpfc->used == 0 &&
tmpfc->xorg == fc->xorg && tmpfc->w == fc->w)
{
fc->h += tmpfc->h;
fc->next = tmpfc->next;
if (fc->next)
fc->next->prev = fc;
Xfree(tmpfc);
}
tmpfc = fc->prev;
if (tmpfc && tmpfc->used == 0 &&
tmpfc->xorg == fc->xorg && tmpfc->w == fc->w)
{
tmpfc->h += fc->h;
tmpfc->next = fc->next;
if (tmpfc->next)
tmpfc->next->prev = tmpfc;
Xfree(fc);
fc = tmpfc;
}
fc->used = 0;
fc->row = 0;
fc->owner = 0;
font->afCache[row] = 0;
font->afChars[row].cached = 0;
return;
}
/* Allocate a band of offscreen memory for a font. */
Bool
apa16CacheFontRow(font, row)
apa16FontPtr font;
int row;
{
register apa16FontCache *fc;
apa16FontCache *tmp;
int i;
unsigned short cmd;
unsigned short h = font->afHeight;
TRACE(("apa16CacheFontRow(%x,%d)\n",font,row))
for (i = 0; i < 4; i++)
{
for (fc = cache_head[i]; fc; fc = fc->next)
if (!fc->used && fc->h >= h)
goto found;
}
/* Didn't find a free band. Free the least recently used font row. */
fc = apa16FreeFontRow(h);
found:
if (fc == 0)
return 0;
/* if band is more than 8 pixels larger than needed, split it */
if (fc->h > h + 8 &&
(tmp = (apa16FontCache *)Xalloc(sizeof(apa16FontCache))))
{
tmp->xorg = fc->xorg;
tmp->yorg = fc->yorg + h;
tmp->w = fc->w;
tmp->h = fc->h - h;
fc->h = h;
tmp->next = fc->next;
if (tmp->next)
tmp->next->prev = tmp;
fc->next = tmp;
tmp->prev = fc;
tmp->used = 0;
}
fc->row = row;
fc->used = 1;
fc->referenced = 0;
fc->owner = font;
font->afCache[row] = fc;
font->afChars[row].cached = 1;
font->afChars[row].x = fc->xorg;
font->afChars[row].xmax = fc->xorg + fc->w;
font->afChars[row].yorg = fc->yorg + h;
APA16_GET_CMD_FILL(RROP_BLACK,cmd);
FILL_RECT(cmd,fc->xorg + fc->w, fc->yorg + h, fc->w, h);
bzero(font->afChars[row].char_cached,
sizeof(font->afChars[row].char_cached));
return TRUE;
}
/* Given a list of characters, copy them to the cache.
Warning: this code only works for 8 bit fonts. */
Bool
apa16CacheChars(font, str, len)
apa16FontPtr font;
unsigned char *str;
unsigned int len;
{
TRACE(("apa16CacheChars(%x,%x,%d) %d x %d/%d range (%d,%d)\n",
font,str,len,*str,font->afChars->x, font->afChars->xmax,
font->afChars->cmin,font->afChars->cmax));
QUEUE_WAIT();
apa16Qmerge_mode_old = MERGE_WHITE;
MR = (MODE_SHADOW & MERGE_MODE_MASK) | MERGE_WHITE;
while(len-- > 0)
{
unsigned int ndx = *str;
apa16FCCharInfo *fci;
unsigned short w;
fci = font->afChars; /* change this for 16 bit fonts */
str++;
if (fci->chars[ndx] == 0)
fci->char_cached[ndx] = 1;
if (fci->char_cached[ndx])
continue;
w = GLYPHWIDTHPIXELS(fci->chars[ndx]);
if (fci->x + w > fci->xmax)
{
ErrorF("apa16CacheChars: out of space\n");
return FALSE;
}
fci->x += w;
fci->xorg[ndx] = fci->x;
fci->char_cached[ndx] = 1;
apa16PutGlyph(fci->xorg[ndx], fci->yorg, fci->chars[ndx],
FONTMAXBOUNDS(font->afFont,descent));
}
apa16Qmerge_mode_old = MERGE_COPY;
MR = MR_DEFAULT;
return TRUE;
}
#ifdef DEBUG
copy_font_area()
{
unsigned cmd;
APA16_GET_CMD(ROP_RECT_COPY,GXcopy,cmd);
COPY_RECT(cmd,1023,750,
1023,1023,1023,1023-768);
}
#endif