#include <X11/X.h>
#include <X11/Xtrans.h>
#include <X11/Xpoll.h>
#include "FS.h"
#include "FSproto.h"
#include "fontmisc.h"
#include "fontstruct.h"
#include "fservestr.h"
#include "fontutil.h"
#include "fslibos.h"
extern char _fs_glyph_undefined;
extern char _fs_glyph_requested;
extern char _fs_glyph_zero_length;
void
_fs_convert_char_info(fsXCharInfo *src, xCharInfo *dst)
{
dst->ascent = src->ascent;
dst->descent = src->descent;
dst->leftSideBearing = src->left;
dst->rightSideBearing = src->right;
dst->characterWidth = src->width;
dst->attributes = src->attributes;
}
void
_fs_init_fontinfo(FSFpePtr conn, FontInfoPtr pfi)
{
if (conn->fsMajorVersion == 1) {
unsigned short n;
n = pfi->firstCol;
pfi->firstCol = pfi->firstRow;
pfi->firstRow = n;
n = pfi->lastCol;
pfi->lastCol = pfi->lastRow;
pfi->lastRow = n;
pfi->defaultCh = ((pfi->defaultCh >> 8) & 0xff)
+ ((pfi->defaultCh & 0xff) << 8);
}
if (FontCouldBeTerminal (pfi))
{
pfi->terminalFont = TRUE;
pfi->minbounds.ascent = pfi->fontAscent;
pfi->minbounds.descent = pfi->fontDescent;
pfi->minbounds.leftSideBearing = 0;
pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth;
pfi->maxbounds = pfi->minbounds;
}
FontComputeInfoAccelerators (pfi);
}
int
_fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd,
FontInfoPtr pfi)
{
FontPropPtr dprop;
int i,
nprops;
char *is_str;
fsPropOffset local_off;
char *off_adr;
char *pdc = pd;
#define BAD_RESOURCE 0xe0000000
nprops = pfi->nprops = pi->num_offsets;
if (nprops < 0
|| nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char)))
return -1;
dprop = (FontPropPtr) xalloc(sizeof(FontPropRec) * nprops +
sizeof (char) * nprops);
if (!dprop)
return -1;
is_str = (char *) (dprop + nprops);
pfi->props = dprop;
pfi->isStringProp = is_str;
off_adr = (char *)po;
for (i = 0; i < nprops; i++, dprop++, is_str++)
{
memcpy(&local_off, off_adr, SIZEOF(fsPropOffset));
dprop->name = MakeAtom(&pdc[local_off.name.position],
local_off.name.length, 1);
if (local_off.type != PropTypeString) {
*is_str = FALSE;
dprop->value = local_off.value.position;
} else {
*is_str = TRUE;
dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position],
local_off.value.length, 1);
if (dprop->value == BAD_RESOURCE)
{
xfree (pfi->props);
pfi->nprops = 0;
pfi->props = 0;
pfi->isStringProp = 0;
return -1;
}
}
off_adr += SIZEOF(fsPropOffset);
}
return nprops;
}
void
_fs_free_props (FontInfoPtr pfi)
{
if (pfi->props)
{
xfree (pfi->props);
pfi->nprops = 0;
pfi->props = 0;
}
}
int
_fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi,
fsListFontsWithXInfoReply *fsrep,
fsPropInfo *pi, fsPropOffset *po, pointer pd)
{
fsUnpack_XFontInfoHeader(fsrep, pfi);
_fs_init_fontinfo(conn, pfi);
if (_fs_convert_props(pi, po, pd, pfi) == -1)
return AllocError;
return Successful;
}
#define ENCODING_UNDEFINED(enc) \
((enc)->bits == &_fs_glyph_undefined ? \
TRUE : \
(access_done = access_done && (enc)->bits != &_fs_glyph_requested, \
FALSE))
#define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc))
int
fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count,
int item_size, unsigned char *data, int *nranges,
fsRange **ranges)
{
FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate);
register CharInfoPtr encoding = fsfont->encoding;
FontInfoPtr pfi = &(pfont->info);
fsRange range;
int access_done = TRUE;
int err;
register unsigned long firstrow, lastrow, firstcol, lastcol;
register unsigned long row;
register unsigned long col;
register unsigned long loc;
if (!fsd->glyphs_to_get)
return AccessDone;
firstrow = pfi->firstRow;
lastrow = pfi->lastRow;
firstcol = pfi->firstCol;
lastcol = pfi->lastCol;
if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault))
{
loc = fsfont->pDefault - encoding;
row = loc / (lastcol - firstcol + 1) + firstrow;
col = loc % (lastcol - firstcol + 1) + firstcol;
range.min_char_low = range.max_char_low = col;
range.min_char_high = range.max_char_high = row;
if ((err = add_range(&range, nranges, ranges, FALSE)) !=
Successful) return err;
encoding[loc].bits = &_fs_glyph_requested;
access_done = FALSE;
}
if (!range_flag && item_size == 1)
{
if (firstrow != 0) return AccessDone;
while (count--)
{
col = *data++;
if (col >= firstcol && col <= lastcol &&
GLYPH_UNDEFINED(col - firstcol))
{
int col1, col2;
col1 = col & 0xf0;
col2 = col1 + 15;
if (col1 < firstcol) col1 = firstcol;
if (col2 > lastcol) col2 = lastcol;
for (col = col1; col <= col2; col++)
{
if (!GLYPH_UNDEFINED(col - firstcol)) continue;
range.min_char_low = range.max_char_low = col;
range.min_char_high = range.max_char_high = 0;
if ((err = add_range(&range, nranges, ranges, FALSE)) !=
Successful) return err;
encoding[col - firstcol].bits = &_fs_glyph_requested;
access_done = FALSE;
}
}
}
}
else
{
fsRange fullrange[1];
if (range_flag && count == 0)
{
count = 2;
data = (unsigned char *)fullrange;
fullrange[0].min_char_high = firstrow;
fullrange[0].min_char_low = firstcol;
fullrange[0].max_char_high = lastrow;
fullrange[0].max_char_low = lastcol;
}
while (count--)
{
int row1, col1, row2, col2;
row1 = row2 = *data++;
col1 = col2 = *data++;
if (range_flag)
{
if (count)
{
row2 = *data++;
col2 = *data++;
count--;
}
else
{
row2 = lastrow;
col2 = lastcol;
}
if (row1 < firstrow) row1 = firstrow;
if (row2 > lastrow) row2 = lastrow;
if (col1 < firstcol) col1 = firstcol;
if (col2 > lastcol) col2 = lastcol;
}
else
{
if (row1 < firstrow || row1 > lastrow ||
col1 < firstcol || col1 > lastcol)
continue;
}
for (row = row1; row <= row2; row++)
{
expand_glyph_range: ;
loc = (row - firstrow) * (lastcol + 1 - firstcol) +
(col1 - firstcol);
for (col = col1; col <= col2; col++, loc++)
{
if (GLYPH_UNDEFINED(loc))
{
if (row1 == row2 &&
(((col1 & 0xf) && col1 > firstcol) ||
(col2 & 0xf) != 0xf) && (col2 < lastcol))
{
col1 &= 0xf0;
col2 = (col2 & 0xf0) + 15;
if (col1 < firstcol) col1 = firstcol;
if (col2 > lastcol) col2 = lastcol;
goto expand_glyph_range;
}
range.min_char_low = range.max_char_low = col;
range.min_char_high = range.max_char_high = row;
if ((err = add_range(&range, nranges, ranges, FALSE)) !=
Successful) return err;
encoding[loc].bits = &_fs_glyph_requested;
access_done = FALSE;
}
}
}
}
}
return access_done ?
AccessDone :
Successful;
}
#undef GLYPH_UNDEFINED
#undef ENCODING_UNDEFINED
void
_fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges,
fsRange *expected_ranges)
{
register FSFontPtr fsfont;
register int i;
fsfont = (FSFontPtr) pfont->fontPrivate;
if (fsfont->encoding)
{
fsRange full_range[1];
if (!num_expected_ranges)
{
full_range[0].min_char_low = pfont->info.firstCol;
full_range[0].min_char_high = pfont->info.firstRow;
full_range[0].max_char_low = pfont->info.lastCol;
full_range[0].max_char_high = pfont->info.lastRow;
num_expected_ranges = 1;
expected_ranges = full_range;
}
for (i = 0; i < num_expected_ranges; i++)
{
int row, col;
for (row = expected_ranges[i].min_char_high;
row <= expected_ranges[i].max_char_high;
row++)
{
register CharInfoPtr encoding = fsfont->encoding +
((row - pfont->info.firstRow) *
(pfont->info.lastCol -
pfont->info.firstCol + 1) +
expected_ranges[i].min_char_low -
pfont->info.firstCol);
for (col = expected_ranges[i].min_char_low;
col <= expected_ranges[i].max_char_low;
encoding++, col++)
{
if (encoding->bits == &_fs_glyph_requested)
encoding->bits = &_fs_glyph_undefined;
}
}
}
}
}
int
_fs_check_extents(FontPtr pfont, Mask flags, int nranges, fsRange *range,
FSBlockDataPtr blockrec)
{
return Successful;
}
int
_fs_check_bitmaps(FontPtr pfont, fsBitmapFormat format,
Mask flags, int nranges, fsRange *range,
FSBlockDataPtr blockrec)
{
return Successful;
}
int
_fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
FontEncoding charEncoding,
unsigned long *glyphCount,
CharInfoPtr *glyphs)
{
FSFontPtr fsdata;
unsigned int firstCol;
register unsigned int numCols;
unsigned int firstRow;
unsigned int numRows;
CharInfoPtr *glyphsBase;
register unsigned int c;
register CharInfoPtr pci;
unsigned int r;
CharInfoPtr encoding;
CharInfoPtr pDefault;
FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate;
int err = Successful;
fsdata = (FSFontPtr) pFont->fontPrivate;
encoding = fsdata->encoding;
pDefault = fsdata->pDefault;
firstCol = pFont->info.firstCol;
numCols = pFont->info.lastCol - firstCol + 1;
glyphsBase = glyphs;
#define CHECK_ENCODING(cnum) \
( pci = encoding + (cnum), \
fsd->glyphs_to_get ? \
( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \
((err = fs_load_all_glyphs(pFont)), pci) : \
pci ) : \
pci )
switch (charEncoding) {
case Linear8Bit:
case TwoD8Bit:
if (pFont->info.firstRow > 0)
break;
if (pFont->info.allExist && pDefault) {
while (err == Successful && count--) {
c = (*chars++) - firstCol;
if (c < numCols)
*glyphs++ = CHECK_ENCODING(c);
else
*glyphs++ = pDefault;
}
} else {
while (err == Successful && count--) {
c = (*chars++) - firstCol;
if (c < numCols && CHECK_ENCODING(c)->bits)
*glyphs++ = pci;
else if (pDefault)
*glyphs++ = pDefault;
}
}
break;
case Linear16Bit:
if (pFont->info.allExist && pDefault) {
while (err == Successful && count--) {
c = *chars++ << 8;
c = (c | *chars++) - firstCol;
if (c < numCols)
*glyphs++ = CHECK_ENCODING(c);
else
*glyphs++ = pDefault;
}
} else {
while (err == Successful && count--) {
c = *chars++ << 8;
c = (c | *chars++) - firstCol;
if (c < numCols && CHECK_ENCODING(c)->bits)
*glyphs++ = pci;
else if (pDefault)
*glyphs++ = pDefault;
}
}
break;
case TwoD16Bit:
firstRow = pFont->info.firstRow;
numRows = pFont->info.lastRow - firstRow + 1;
while (err == Successful && count--) {
r = (*chars++) - firstRow;
c = (*chars++) - firstCol;
if (r < numRows && c < numCols &&
CHECK_ENCODING(r * numCols + c)->bits)
*glyphs++ = pci;
else if (pDefault)
*glyphs++ = pDefault;
}
break;
}
*glyphCount = glyphs - glyphsBase;
return err;
}
static int
_fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars,
FontEncoding charEncoding,
unsigned long *glyphCount,
xCharInfo **glyphs)
{
FSFontPtr fsdata;
unsigned int firstCol;
register unsigned int numCols;
unsigned int firstRow;
unsigned int numRows;
xCharInfo **glyphsBase;
register unsigned int c;
unsigned int r;
CharInfoPtr encoding;
CharInfoPtr pDefault;
fsdata = (FSFontPtr) pFont->fontPrivate;
encoding = fsdata->inkMetrics;
pDefault = fsdata->pDefault;
if (pDefault)
pDefault = encoding + (pDefault - fsdata->encoding);
firstCol = pFont->info.firstCol;
numCols = pFont->info.lastCol - firstCol + 1;
glyphsBase = glyphs;
switch (charEncoding) {
case Linear8Bit:
case TwoD8Bit:
if (pFont->info.firstRow > 0)
break;
if (pFont->info.allExist && pDefault) {
while (count--) {
c = (*chars++) - firstCol;
if (c < numCols)
*glyphs++ = (xCharInfo *)&encoding[c];
else
*glyphs++ = (xCharInfo *)pDefault;
}
} else {
while (count--) {
c = (*chars++) - firstCol;
if (c < numCols)
*glyphs++ = (xCharInfo *)(encoding + c);
else if (pDefault)
*glyphs++ = (xCharInfo *)pDefault;
}
}
break;
case Linear16Bit:
if (pFont->info.allExist && pDefault) {
while (count--) {
c = *chars++ << 8;
c = (c | *chars++) - firstCol;
if (c < numCols)
*glyphs++ = (xCharInfo *)(encoding + c);
else
*glyphs++ = (xCharInfo *)pDefault;
}
} else {
while (count--) {
c = *chars++ << 8;
c = (c | *chars++) - firstCol;
if (c < numCols)
*glyphs++ = (xCharInfo *)(encoding + c);
else if (pDefault)
*glyphs++ = (xCharInfo *)pDefault;
}
}
break;
case TwoD16Bit:
firstRow = pFont->info.firstRow;
numRows = pFont->info.lastRow - firstRow + 1;
while (count--) {
r = (*chars++) - firstRow;
c = (*chars++) - firstCol;
if (r < numRows && c < numCols)
*glyphs++ = (xCharInfo *)(encoding + (r * numCols + c));
else if (pDefault)
*glyphs++ = (xCharInfo *)pDefault;
}
break;
}
*glyphCount = glyphs - glyphsBase;
return Successful;
}
void
_fs_unload_font(FontPtr pfont)
{
FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate;
FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate;
CharInfoPtr encoding = fsdata->encoding;
FSGlyphPtr glyphs;
if (encoding)
xfree(encoding);
while ((glyphs = fsdata->glyphs))
{
fsdata->glyphs = glyphs->next;
xfree (glyphs);
}
if (find_old_font(fsd->fontid))
DeleteFontClientID (fsd->fontid);
_fs_free_props (&pfont->info);
xfree(fsdata);
DestroyFontRec(pfont);
}
FontPtr
fs_create_font (FontPathElementPtr fpe,
char *name,
int namelen,
fsBitmapFormat format,
fsBitmapFormatMask fmask)
{
FontPtr pfont;
FSFontPtr fsfont;
FSFontDataPtr fsd;
int bit, byte, scan, glyph;
pfont = CreateFontRec ();
if (!pfont)
return 0;
fsfont = (FSFontPtr) xalloc (sizeof (FSFontRec) +
sizeof (FSFontDataRec) +
namelen + 1);
if (!fsfont)
{
DestroyFontRec (pfont);
return 0;
}
fsd = (FSFontDataPtr) (fsfont + 1);
bzero((char *) fsfont, sizeof(FSFontRec));
bzero((char *) fsd, sizeof(FSFontDataRec));
pfont->fpe = fpe;
pfont->fontPrivate = (pointer) fsfont;
pfont->fpePrivate = (pointer) fsd;
CheckFSFormat(format, BitmapFormatMaskBit |
BitmapFormatMaskByte |
BitmapFormatMaskScanLineUnit |
BitmapFormatMaskScanLinePad,
&bit,
&byte,
&scan,
&glyph,
NULL);
pfont->format = format;
pfont->bit = bit;
pfont->byte = byte;
pfont->scan = scan;
pfont->glyph = glyph;
pfont->info.nprops = 0;
pfont->info.props = 0;
pfont->info.isStringProp = 0;
pfont->get_glyphs = _fs_get_glyphs;
pfont->get_metrics = _fs_get_metrics;
pfont->unload_font = _fs_unload_font;
pfont->unload_glyphs = NULL;
fsd->format = format;
fsd->fmask = fmask;
fsd->name = (char *) (fsd + 1);
memcpy (fsd->name, name, namelen);
fsd->name[namelen] = '\0';
fsd->fontid = GetNewFontClientID ();
if (!StoreFontClientFont(pfont, fsd->fontid))
{
xfree (fsfont);
DestroyFontRec (pfont);
return 0;
}
return pfont;
}
pointer
fs_alloc_glyphs (FontPtr pFont, int size)
{
FSGlyphPtr glyphs;
FSFontPtr fsfont = (FSFontPtr) pFont->fontPrivate;
glyphs = xalloc (sizeof (FSGlyphRec) + size);
glyphs->next = fsfont->glyphs;
fsfont->glyphs = glyphs;
return (pointer) (glyphs + 1);
}