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