fsconvert.c revision a96d7823
1/*
2 * Copyright 1990 Network Computing Devices
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Network Computing Devices not be used
9 * in advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission.  Network Computing Devices
11 * makes no representations about the suitability of this software for any
12 * purpose.  It is provided "as is" without express or implied warranty.
13 *
14 * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
16 * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
17 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
19 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
20 * OR PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Author:  	Dave Lemke, Network Computing Devices, Inc
23 */
24/*
25 * FS data conversion
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "libxfontint.h"
32#include        <X11/X.h>
33#include 	<X11/Xtrans/Xtrans.h>
34#include	<X11/Xpoll.h>
35#include	<X11/fonts/FS.h>
36#include	<X11/fonts/FSproto.h>
37#include	<X11/fonts/fontmisc.h>
38#include	<X11/fonts/fontstruct.h>
39#include	"fservestr.h"
40#include	<X11/fonts/fontutil.h>
41#include	"fslibos.h"
42
43extern char _fs_glyph_undefined;
44extern char _fs_glyph_requested;
45
46/*
47 * converts data from font server form to X server form
48 */
49
50void
51_fs_convert_char_info(fsXCharInfo *src, xCharInfo *dst)
52{
53    dst->ascent = src->ascent;
54    dst->descent = src->descent;
55    dst->leftSideBearing = src->left;
56    dst->rightSideBearing = src->right;
57    dst->characterWidth = src->width;
58    dst->attributes = src->attributes;
59}
60
61void
62_fs_init_fontinfo(FSFpePtr conn, FontInfoPtr pfi)
63{
64    if (conn->fsMajorVersion == 1) {
65	unsigned short n;
66	n = pfi->firstCol;
67	pfi->firstCol = pfi->firstRow;
68	pfi->firstRow = n;
69	n = pfi->lastCol;
70	pfi->lastCol = pfi->lastRow;
71	pfi->lastRow = n;
72	pfi->defaultCh = ((pfi->defaultCh >> 8) & 0xff)
73	                   + ((pfi->defaultCh & 0xff) << 8);
74    }
75
76    if (FontCouldBeTerminal (pfi))
77    {
78	pfi->terminalFont = TRUE;
79	pfi->minbounds.ascent = pfi->fontAscent;
80	pfi->minbounds.descent = pfi->fontDescent;
81	pfi->minbounds.leftSideBearing = 0;
82	pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth;
83	pfi->maxbounds = pfi->minbounds;
84    }
85
86    FontComputeInfoAccelerators (pfi);
87}
88
89int
90_fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd,
91		  FontInfoPtr pfi)
92{
93    FontPropPtr dprop;
94    int         i,
95                nprops;
96    char       *is_str;
97    fsPropOffset local_off;
98    char *off_adr;
99    char *pdc = pd;
100
101/* stolen from server/include/resource.h */
102#define BAD_RESOURCE 0xe0000000
103
104    nprops = pfi->nprops = pi->num_offsets;
105
106    if (nprops < 0
107	|| nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char)))
108	return -1;
109
110    dprop = malloc(sizeof(FontPropRec) * nprops + sizeof (char) * nprops);
111    if (!dprop)
112	return -1;
113
114    is_str = (char *) (dprop + nprops);
115    pfi->props = dprop;
116    pfi->isStringProp = is_str;
117
118    off_adr = (char *)po;
119    for (i = 0; i < nprops; i++, dprop++, is_str++)
120    {
121	memcpy(&local_off, off_adr, SIZEOF(fsPropOffset));
122	if ((local_off.name.position >= pi->data_len) ||
123		(local_off.name.length >
124		 (pi->data_len - local_off.name.position)))
125	    goto bail;
126	dprop->name = MakeAtom(&pdc[local_off.name.position],
127			       local_off.name.length, 1);
128	if (local_off.type != PropTypeString) {
129	    *is_str = FALSE;
130	    dprop->value = local_off.value.position;
131	} else {
132	    *is_str = TRUE;
133	    if ((local_off.value.position >= pi->data_len) ||
134		(local_off.value.length >
135		 (pi->data_len - local_off.value.position)))
136		goto bail;
137	    dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position],
138					    local_off.value.length, 1);
139	    if (dprop->value == BAD_RESOURCE)
140	    {
141	      bail:
142		free (pfi->props);
143		pfi->nprops = 0;
144		pfi->props = 0;
145		pfi->isStringProp = 0;
146		return -1;
147	    }
148	}
149	off_adr += SIZEOF(fsPropOffset);
150    }
151
152    return nprops;
153}
154
155void
156_fs_free_props (FontInfoPtr pfi)
157{
158    if (pfi->props)
159    {
160	free (pfi->props);
161	pfi->nprops = 0;
162	pfi->props = 0;
163    }
164}
165
166int
167_fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi,
168		       fsListFontsWithXInfoReply *fsrep,
169		       fsPropInfo *pi, fsPropOffset *po, pointer pd)
170{
171    fsUnpack_XFontInfoHeader(fsrep, pfi);
172    _fs_init_fontinfo(conn, pfi);
173
174    if (_fs_convert_props(pi, po, pd, pfi) == -1)
175	return AllocError;
176
177    return Successful;
178}
179
180
181#define ENCODING_UNDEFINED(enc) \
182	((enc)->bits == &_fs_glyph_undefined ? \
183	 TRUE : \
184	 (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \
185	  FALSE))
186
187#define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc))
188
189/*
190 * figures out what glyphs to request
191 *
192 * Includes logic to attempt to reduce number of round trips to the font
193 * server:  when a glyph is requested, fs_build_range() requests a
194 * 16-glyph range of glyphs that contains the requested glyph.  This is
195 * predicated on the belief that using a glyph increases the chances
196 * that nearby glyphs will be used: a good assumption for phonetic
197 * alphabets, but a questionable one for ideographic/pictographic ones.
198 */
199/* ARGSUSED */
200int
201fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count,
202	       int item_size, unsigned char *data, int *nranges,
203	       fsRange **ranges)
204{
205    FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
206    FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate);
207    register CharInfoPtr encoding = fsfont->encoding;
208    FontInfoPtr pfi = &(pfont->info);
209    fsRange	range;
210    int		access_done = TRUE;
211    int		err;
212    register unsigned long firstrow, lastrow, firstcol, lastcol;
213    register unsigned long row;
214    register unsigned long col;
215    register unsigned long loc;
216
217    if (!fsd->glyphs_to_get)
218	return AccessDone;
219
220    firstrow = pfi->firstRow;
221    lastrow = pfi->lastRow;
222    firstcol = pfi->firstCol;
223    lastcol = pfi->lastCol;
224
225    /* Make sure we have default char */
226    if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault))
227    {
228	loc = fsfont->pDefault - encoding;
229	row = loc / (lastcol - firstcol + 1) + firstrow;
230	col = loc % (lastcol - firstcol + 1) + firstcol;
231
232	range.min_char_low = range.max_char_low = col;
233	range.min_char_high = range.max_char_high = row;
234
235	if ((err = add_range(&range, nranges, ranges, FALSE)) !=
236	    Successful) return err;
237	encoding[loc].bits = &_fs_glyph_requested;
238	access_done = FALSE;
239    }
240
241    if (!range_flag && item_size == 1)
242    {
243	if (firstrow != 0) return AccessDone;
244	while (count--)
245	{
246	    col = *data++;
247	    if (col >= firstcol && col <= lastcol &&
248		GLYPH_UNDEFINED(col - firstcol))
249	    {
250		int col1, col2;
251		col1 = col & 0xf0;
252		col2 = col1 + 15;
253		if (col1 < firstcol) col1 = firstcol;
254		if (col2 > lastcol) col2 = lastcol;
255		/* Collect a 16-glyph neighborhood containing the requested
256		   glyph... should in most cases reduce the number of round
257		   trips to the font server. */
258		for (col = col1; col <= col2; col++)
259		{
260		    if (!GLYPH_UNDEFINED(col - firstcol)) continue;
261		    range.min_char_low = range.max_char_low = col;
262		    range.min_char_high = range.max_char_high = 0;
263		    if ((err = add_range(&range, nranges, ranges, FALSE)) !=
264		        Successful) return err;
265		    encoding[col - firstcol].bits = &_fs_glyph_requested;
266		    access_done = FALSE;
267		}
268	    }
269	}
270    }
271    else
272    {
273	fsRange fullrange[1];
274
275	if (range_flag && count == 0)
276	{
277	    count = 2;
278	    data = (unsigned char *)fullrange;
279	    fullrange[0].min_char_high = firstrow;
280	    fullrange[0].min_char_low = firstcol;
281	    fullrange[0].max_char_high = lastrow;
282	    fullrange[0].max_char_low = lastcol;
283	}
284
285	while (count--)
286	{
287	    int row1, col1, row2, col2;
288	    row1 = row2 = *data++;
289	    col1 = col2 = *data++;
290	    if (range_flag)
291	    {
292		if (count)
293		{
294		    row2 = *data++;
295		    col2 = *data++;
296		    count--;
297		}
298		else
299		{
300		    row2 = lastrow;
301		    col2 = lastcol;
302		}
303		if (row1 < firstrow) row1 = firstrow;
304		if (row2 > lastrow) row2 = lastrow;
305		if (col1 < firstcol) col1 = firstcol;
306		if (col2 > lastcol) col2 = lastcol;
307	    }
308	    else
309	    {
310		if (row1 < firstrow || row1 > lastrow ||
311		    col1 < firstcol || col1 > lastcol)
312		    continue;
313	    }
314	    for (row = row1; row <= row2; row++)
315	    {
316	    expand_glyph_range: ;
317		loc = (row - firstrow) * (lastcol + 1 - firstcol) +
318		      (col1 - firstcol);
319		for (col = col1; col <= col2; col++, loc++)
320		{
321		    if (GLYPH_UNDEFINED(loc))
322		    {
323			if (row1 == row2 &&
324			    (((col1 & 0xf) && col1 > firstcol) ||
325			     (col2 & 0xf) != 0xf) && (col2 < lastcol))
326			{
327			    /* If we're loading from a single row, expand
328			       range of glyphs loaded to a multiple of
329			       a 16-glyph range -- attempt to reduce number
330			       of round trips to the font server. */
331			    col1 &= 0xf0;
332			    col2 = (col2 & 0xf0) + 15;
333			    if (col1 < firstcol) col1 = firstcol;
334			    if (col2 > lastcol) col2 = lastcol;
335			    goto expand_glyph_range;
336			}
337			range.min_char_low = range.max_char_low = col;
338			range.min_char_high = range.max_char_high = row;
339			if ((err = add_range(&range, nranges, ranges, FALSE)) !=
340			    Successful) return err;
341			encoding[loc].bits = &_fs_glyph_requested;
342			access_done = FALSE;
343		    }
344		}
345	    }
346	}
347    }
348
349    return access_done ?
350	   AccessDone :
351	   Successful;
352}
353
354#undef GLYPH_UNDEFINED
355#undef ENCODING_UNDEFINED
356
357
358/* _fs_clean_aborted_loadglyphs(): Undoes the changes to the encoding array
359   performed by fs_build_range(); for use if the associated LoadGlyphs
360   requests needs to be cancelled. */
361
362void
363_fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges,
364			     fsRange *expected_ranges)
365{
366    register FSFontPtr fsfont;
367    register int i;
368
369    fsfont = (FSFontPtr) pfont->fontPrivate;
370    if (fsfont->encoding)
371    {
372	fsRange full_range[1];
373	if (!num_expected_ranges)
374	{
375	    full_range[0].min_char_low = pfont->info.firstCol;
376	    full_range[0].min_char_high = pfont->info.firstRow;
377	    full_range[0].max_char_low = pfont->info.lastCol;
378	    full_range[0].max_char_high = pfont->info.lastRow;
379	    num_expected_ranges = 1;
380	    expected_ranges = full_range;
381	}
382
383	for (i = 0; i < num_expected_ranges; i++)
384	{
385	    int row, col;
386	    for (row = expected_ranges[i].min_char_high;
387		 row <= expected_ranges[i].max_char_high;
388		 row++)
389	    {
390		register CharInfoPtr encoding = fsfont->encoding +
391		    ((row - pfont->info.firstRow) *
392		     (pfont->info.lastCol -
393		      pfont->info.firstCol + 1) +
394		     expected_ranges[i].min_char_low -
395		     pfont->info.firstCol);
396		for (col = expected_ranges[i].min_char_low;
397		     col <= expected_ranges[i].max_char_low;
398		     encoding++, col++)
399		{
400		    if (encoding->bits == &_fs_glyph_requested)
401			encoding->bits = &_fs_glyph_undefined;
402		}
403	    }
404	}
405    }
406}
407
408static int
409_fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
410	       FontEncoding charEncoding,
411	       unsigned long *glyphCount, /* RETURN */
412	       CharInfoPtr *glyphs) 	  /* RETURN  */
413{
414    FSFontPtr   fsdata;
415    unsigned int firstCol;
416    register unsigned int numCols;
417    unsigned int firstRow;
418    unsigned int numRows;
419    CharInfoPtr *glyphsBase;
420    register unsigned int c;
421    register CharInfoPtr pci;
422    unsigned int r;
423    CharInfoPtr encoding;
424    CharInfoPtr pDefault;
425    FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate;
426    int         err = Successful;
427
428    fsdata = (FSFontPtr) pFont->fontPrivate;
429    encoding = fsdata->encoding;
430    pDefault = fsdata->pDefault;
431    firstCol = pFont->info.firstCol;
432    numCols = pFont->info.lastCol - firstCol + 1;
433    glyphsBase = glyphs;
434
435    /* In this age of glyph caching, any glyphs gotten through this
436       procedure should already be loaded.  If they are not, we are
437       dealing with someone (perhaps a ddx driver optimizing a font)
438       that doesn't understand the finer points of glyph caching.  The
439       CHECK_ENCODING macro checks for this condition...  if found, it
440       calls fs_load_all_glyphs(), which corrects it.  Since the caller
441       of this code will not know how to handle a return value of
442       Suspended, the fs_load_all_glyphs() procedure will block and
443       freeze the server until the load operation is done.  Moral: the
444       glyphCachingMode flag really must indicate the capabilities of
445       the ddx drivers.  */
446
447#define CHECK_ENCODING(cnum) \
448    ( pci = encoding + (cnum), \
449      fsd->glyphs_to_get ? \
450      ( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \
451	((err = fs_load_all_glyphs(pFont)), pci) : \
452	pci ) : \
453      pci )
454
455    switch (charEncoding) {
456
457    case Linear8Bit:
458    case TwoD8Bit:
459	if (pFont->info.firstRow > 0)
460	    break;
461	if (pFont->info.allExist && pDefault) {
462	    while (err == Successful && count--) {
463		c = (*chars++) - firstCol;
464		if (c < numCols)
465		    *glyphs++ = CHECK_ENCODING(c);
466		else
467		    *glyphs++ = pDefault;
468	    }
469	} else {
470	    while (err == Successful && count--) {
471		c = (*chars++) - firstCol;
472		if (c < numCols && CHECK_ENCODING(c)->bits)
473		    *glyphs++ = pci;
474		else if (pDefault)
475		    *glyphs++ = pDefault;
476	    }
477	}
478	break;
479    case Linear16Bit:
480	if (pFont->info.allExist && pDefault) {
481	    while (err == Successful && count--) {
482		c = *chars++ << 8;
483		c = (c | *chars++) - firstCol;
484		if (c < numCols)
485		    *glyphs++ = CHECK_ENCODING(c);
486		else
487		    *glyphs++ = pDefault;
488	    }
489	} else {
490	    while (err == Successful && count--) {
491		c = *chars++ << 8;
492		c = (c | *chars++) - firstCol;
493		if (c < numCols && CHECK_ENCODING(c)->bits)
494		    *glyphs++ = pci;
495		else if (pDefault)
496		    *glyphs++ = pDefault;
497	    }
498	}
499	break;
500
501    case TwoD16Bit:
502	firstRow = pFont->info.firstRow;
503	numRows = pFont->info.lastRow - firstRow + 1;
504	while (err == Successful && count--) {
505	    r = (*chars++) - firstRow;
506	    c = (*chars++) - firstCol;
507	    if (r < numRows && c < numCols &&
508		    CHECK_ENCODING(r * numCols + c)->bits)
509		*glyphs++ = pci;
510	    else if (pDefault)
511		*glyphs++ = pDefault;
512	}
513	break;
514    }
515    *glyphCount = glyphs - glyphsBase;
516    return err;
517}
518
519
520static int
521_fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars,
522		FontEncoding charEncoding,
523		unsigned long *glyphCount, /* RETURN */
524		xCharInfo **glyphs) 	   /* RETURN */
525{
526    FSFontPtr   fsdata;
527    unsigned int firstCol;
528    register unsigned int numCols;
529    unsigned int firstRow;
530    unsigned int numRows;
531    xCharInfo **glyphsBase;
532    register unsigned int c;
533    unsigned int r;
534    CharInfoPtr encoding;
535    CharInfoPtr pDefault;
536
537    fsdata = (FSFontPtr) pFont->fontPrivate;
538    encoding = fsdata->inkMetrics;
539    pDefault = fsdata->pDefault;
540    /* convert default bitmap metric to default ink metric */
541    if (pDefault)
542	pDefault = encoding + (pDefault - fsdata->encoding);
543    firstCol = pFont->info.firstCol;
544    numCols = pFont->info.lastCol - firstCol + 1;
545    glyphsBase = glyphs;
546
547
548    /* XXX - this should be much smarter */
549    /* make sure the glyphs are there */
550    switch (charEncoding) {
551
552    case Linear8Bit:
553    case TwoD8Bit:
554	if (pFont->info.firstRow > 0)
555	    break;
556	if (pFont->info.allExist && pDefault) {
557	    while (count--) {
558		c = (*chars++) - firstCol;
559		if (c < numCols)
560		    *glyphs++ = (xCharInfo *)&encoding[c];
561		else
562		    *glyphs++ = (xCharInfo *)pDefault;
563	    }
564	} else {
565	    while (count--) {
566		c = (*chars++) - firstCol;
567		if (c < numCols)
568		    *glyphs++ = (xCharInfo *)(encoding + c);
569		else if (pDefault)
570		    *glyphs++ = (xCharInfo *)pDefault;
571	    }
572	}
573	break;
574    case Linear16Bit:
575	if (pFont->info.allExist && pDefault) {
576	    while (count--) {
577		c = *chars++ << 8;
578		c = (c | *chars++) - firstCol;
579		if (c < numCols)
580		    *glyphs++ = (xCharInfo *)(encoding + c);
581		else
582		    *glyphs++ = (xCharInfo *)pDefault;
583	    }
584	} else {
585	    while (count--) {
586		c = *chars++ << 8;
587		c = (c | *chars++) - firstCol;
588		if (c < numCols)
589		    *glyphs++ = (xCharInfo *)(encoding + c);
590		else if (pDefault)
591		    *glyphs++ = (xCharInfo *)pDefault;
592	    }
593	}
594	break;
595
596    case TwoD16Bit:
597	firstRow = pFont->info.firstRow;
598	numRows = pFont->info.lastRow - firstRow + 1;
599	while (count--) {
600	    r = (*chars++) - firstRow;
601	    c = (*chars++) - firstCol;
602	    if (r < numRows && c < numCols)
603		*glyphs++ = (xCharInfo *)(encoding + (r * numCols + c));
604	    else if (pDefault)
605		*glyphs++ = (xCharInfo *)pDefault;
606	}
607	break;
608    }
609    *glyphCount = glyphs - glyphsBase;
610    return Successful;
611}
612
613
614static void
615_fs_unload_font(FontPtr pfont)
616{
617    FSFontPtr	    fsdata = (FSFontPtr) pfont->fontPrivate;
618    FSFontDataPtr   fsd = (FSFontDataPtr) pfont->fpePrivate;
619    CharInfoPtr	    encoding = fsdata->encoding;
620    FSGlyphPtr	    glyphs;
621
622    /*
623     * fsdata points at FSFontRec, FSFontDataRec and name
624     */
625    if (encoding)
626	free(encoding);
627
628    while ((glyphs = fsdata->glyphs))
629    {
630	fsdata->glyphs = glyphs->next;
631	free (glyphs);
632    }
633
634    /* XXX we may get called after the resource DB has been cleaned out */
635    if (find_old_font(fsd->fontid))
636	DeleteFontClientID (fsd->fontid);
637
638    _fs_free_props (&pfont->info);
639
640    free(fsdata);
641
642    DestroyFontRec(pfont);
643}
644
645FontPtr
646fs_create_font (FontPathElementPtr  fpe,
647		const char	    *name,
648		int		    namelen,
649		fsBitmapFormat	    format,
650		fsBitmapFormatMask  fmask)
651{
652    FontPtr	    pfont;
653    FSFontPtr	    fsfont;
654    FSFontDataPtr   fsd;
655    int		    bit, byte, scan, glyph;
656
657    pfont = CreateFontRec ();
658    if (!pfont)
659	return 0;
660    fsfont = malloc (sizeof (FSFontRec) + sizeof (FSFontDataRec) + namelen + 1);
661    if (!fsfont)
662    {
663	DestroyFontRec (pfont);
664	return 0;
665    }
666    fsd = (FSFontDataPtr) (fsfont + 1);
667    bzero((char *) fsfont, sizeof(FSFontRec));
668    bzero((char *) fsd, sizeof(FSFontDataRec));
669
670    pfont->fpe = fpe;
671    pfont->fontPrivate = (pointer) fsfont;
672    pfont->fpePrivate = (pointer) fsd;
673
674    /* These font components will be needed in packGlyphs */
675    CheckFSFormat(format, BitmapFormatMaskBit |
676		  BitmapFormatMaskByte |
677		  BitmapFormatMaskScanLineUnit |
678		  BitmapFormatMaskScanLinePad,
679		  &bit,
680		  &byte,
681		  &scan,
682		  &glyph,
683		  NULL);
684    pfont->format = format;
685    pfont->bit = bit;
686    pfont->byte = byte;
687    pfont->scan = scan;
688    pfont->glyph = glyph;
689
690    pfont->info.nprops = 0;
691    pfont->info.props = 0;
692    pfont->info.isStringProp = 0;
693
694    /* set font function pointers */
695    pfont->get_glyphs = _fs_get_glyphs;
696    pfont->get_metrics = _fs_get_metrics;
697    pfont->unload_font = _fs_unload_font;
698    pfont->unload_glyphs = NULL;
699
700    /* set the FPE private information */
701    fsd->format = format;
702    fsd->fmask = fmask;
703    fsd->name = (char *) (fsd + 1);
704    memcpy (fsd->name, name, namelen);
705    fsd->name[namelen] = '\0';
706    fsd->fontid = GetNewFontClientID ();
707
708    /* save the ID */
709    if (!StoreFontClientFont(pfont, fsd->fontid))
710    {
711	free (fsfont);
712	DestroyFontRec (pfont);
713	return 0;
714    }
715
716    return pfont;
717}
718
719pointer
720fs_alloc_glyphs (FontPtr pFont, int size)
721{
722    FSGlyphPtr	glyphs;
723    FSFontPtr	fsfont = (FSFontPtr) pFont->fontPrivate;
724
725    if (size < (INT_MAX - sizeof (FSGlyphRec)))
726	glyphs = malloc (sizeof (FSGlyphRec) + size);
727    else
728	glyphs = NULL;
729    if (glyphs == NULL)
730	return NULL;
731    glyphs->next = fsfont->glyphs;
732    fsfont->glyphs = glyphs;
733    return (pointer) (glyphs + 1);
734}
735