1a96d7823Smrg/************************************************************************
2a96d7823SmrgCopyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
3a96d7823Smrg
4a96d7823Smrg                        All Rights Reserved
5a96d7823Smrg
6a96d7823SmrgPermission to use, copy, modify, and distribute this software and its
7a96d7823Smrgdocumentation for any purpose and without fee is hereby granted,
8a96d7823Smrgprovided that the above copyright notice appear in all copies and that
9a96d7823Smrgboth that copyright notice and this permission notice appear in
10a96d7823Smrgsupporting documentation, and that the name of Digital not be
11a96d7823Smrgused in advertising or publicity pertaining to distribution of the
12a96d7823Smrgsoftware without specific, written prior permission.
13a96d7823Smrg
14a96d7823SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15a96d7823SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16a96d7823SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17a96d7823SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18a96d7823SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19a96d7823SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20a96d7823SmrgSOFTWARE.
21a96d7823Smrg
22a96d7823Smrg************************************************************************/
23a96d7823Smrg
24a96d7823Smrg/*
25a96d7823Smrg
26a96d7823SmrgCopyright 1994, 1998  The Open Group
27a96d7823Smrg
28a96d7823SmrgPermission to use, copy, modify, distribute, and sell this software and its
29a96d7823Smrgdocumentation for any purpose is hereby granted without fee, provided that
30a96d7823Smrgthe above copyright notice appear in all copies and that both that
31a96d7823Smrgcopyright notice and this permission notice appear in supporting
32a96d7823Smrgdocumentation.
33a96d7823Smrg
34a96d7823SmrgThe above copyright notice and this permission notice shall be included
35a96d7823Smrgin all copies or substantial portions of the Software.
36a96d7823Smrg
37a96d7823SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
38a96d7823SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39a96d7823SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
40a96d7823SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
41a96d7823SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
42a96d7823SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
43a96d7823SmrgOTHER DEALINGS IN THE SOFTWARE.
44a96d7823Smrg
45a96d7823SmrgExcept as contained in this notice, the name of The Open Group shall
46a96d7823Smrgnot be used in advertising or otherwise to promote the sale, use or
47a96d7823Smrgother dealings in this Software without prior written authorization
48a96d7823Smrgfrom The Open Group.
49a96d7823Smrg
50a96d7823Smrg*/
51a96d7823Smrg
52a96d7823Smrg#ifdef HAVE_CONFIG_H
53a96d7823Smrg#include <config.h>
54a96d7823Smrg#endif
55a96d7823Smrg#include "libxfontint.h"
56c7b4381aSmrg#include "src/util/replace.h"
57a96d7823Smrg
58a96d7823Smrg#include <ctype.h>
59a96d7823Smrg#include <X11/fonts/fntfilst.h>
60a96d7823Smrg#include <X11/fonts/bitmap.h>
61a96d7823Smrg#include "snfstr.h"
62a96d7823Smrg
63a96d7823Smrg#include <stdarg.h>
64a96d7823Smrg
65a96d7823Smrgstatic void _X_ATTRIBUTE_PRINTF(1, 2)
66a96d7823SmrgsnfError(const char* message, ...)
67a96d7823Smrg{
68a96d7823Smrg    va_list args;
69a96d7823Smrg
70a96d7823Smrg    va_start(args, message);
71a96d7823Smrg
72a96d7823Smrg    fprintf(stderr, "SNF Error: ");
73a96d7823Smrg    vfprintf(stderr, message, args);
74a96d7823Smrg    va_end(args);
75a96d7823Smrg}
76a96d7823Smrg
77a96d7823Smrgstatic void snfUnloadFont(FontPtr pFont);
78a96d7823Smrg
79a96d7823Smrgstatic int
80a96d7823SmrgsnfReadCharInfo(FontFilePtr file, CharInfoPtr charInfo, char *base)
81a96d7823Smrg{
82a96d7823Smrg    snfCharInfoRec snfCharInfo;
83a96d7823Smrg
84a96d7823Smrg#define Width(m)    ((m).rightSideBearing - (m).leftSideBearing)
85a96d7823Smrg#define Height(m)   ((m).ascent + (m).descent)
86a96d7823Smrg
87a96d7823Smrg    if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) !=
88a96d7823Smrg	    sizeof(snfCharInfo)) {
89a96d7823Smrg	return BadFontName;
90a96d7823Smrg    }
91a96d7823Smrg    charInfo->metrics = snfCharInfo.metrics;
92a96d7823Smrg    if (snfCharInfo.exists)
93a96d7823Smrg	charInfo->bits = base + snfCharInfo.byteOffset;
94a96d7823Smrg    else
95a96d7823Smrg	charInfo->bits = 0;
96a96d7823Smrg    return Successful;
97a96d7823Smrg}
98a96d7823Smrg
99a96d7823Smrgstatic int
100a96d7823SmrgsnfReadxCharInfo(FontFilePtr file, xCharInfo *charInfo)
101a96d7823Smrg{
102a96d7823Smrg    snfCharInfoRec snfCharInfo;
103a96d7823Smrg
104a96d7823Smrg    if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) !=
105a96d7823Smrg	    sizeof(snfCharInfo)) {
106a96d7823Smrg	return BadFontName;
107a96d7823Smrg    }
108a96d7823Smrg    *charInfo = snfCharInfo.metrics;
109a96d7823Smrg    return Successful;
110a96d7823Smrg}
111a96d7823Smrg
112a96d7823Smrgstatic void
113a96d7823SmrgsnfCopyInfo(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo)
114a96d7823Smrg{
115a96d7823Smrg    pFontInfo->firstCol = snfInfo->firstCol;
116a96d7823Smrg    pFontInfo->lastCol = snfInfo->lastCol;
117a96d7823Smrg    pFontInfo->firstRow = snfInfo->firstRow;
118a96d7823Smrg    pFontInfo->lastRow = snfInfo->lastRow;
119a96d7823Smrg    pFontInfo->defaultCh = snfInfo->chDefault;
120a96d7823Smrg    pFontInfo->noOverlap = snfInfo->noOverlap;
121a96d7823Smrg    pFontInfo->terminalFont = snfInfo->terminalFont;
122a96d7823Smrg    pFontInfo->constantMetrics = snfInfo->constantMetrics;
123a96d7823Smrg    pFontInfo->constantWidth = snfInfo->constantWidth;
124a96d7823Smrg    pFontInfo->inkInside = snfInfo->inkInside;
125a96d7823Smrg    pFontInfo->inkMetrics = snfInfo->inkMetrics;
126a96d7823Smrg    pFontInfo->allExist = snfInfo->allExist;
127a96d7823Smrg    pFontInfo->drawDirection = snfInfo->drawDirection;
128a96d7823Smrg    pFontInfo->anamorphic = FALSE;
129a96d7823Smrg    pFontInfo->cachable = TRUE;
130a96d7823Smrg    pFontInfo->maxOverlap = 0;
131a96d7823Smrg    pFontInfo->minbounds = snfInfo->minbounds.metrics;
132a96d7823Smrg    pFontInfo->maxbounds = snfInfo->maxbounds.metrics;
133a96d7823Smrg    pFontInfo->fontAscent = snfInfo->fontAscent;
134a96d7823Smrg    pFontInfo->fontDescent = snfInfo->fontDescent;
135a96d7823Smrg    pFontInfo->nprops = snfInfo->nProps;
136a96d7823Smrg}
137a96d7823Smrg
138a96d7823Smrgstatic int
139a96d7823SmrgsnfReadProps(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo, FontFilePtr file)
140a96d7823Smrg{
141a96d7823Smrg    char       *strings;
142a96d7823Smrg    FontPropPtr pfp;
143a96d7823Smrg    snfFontPropPtr psnfp;
144a96d7823Smrg    char       *propspace;
145a96d7823Smrg    int         bytestoalloc;
146a96d7823Smrg    int         i;
147a96d7823Smrg
148a96d7823Smrg    bytestoalloc = snfInfo->nProps * sizeof(snfFontPropRec) +
149a96d7823Smrg	BYTESOFSTRINGINFO(snfInfo);
150a96d7823Smrg    propspace = malloc(bytestoalloc);
151a96d7823Smrg    if (!propspace) {
152a96d7823Smrg      snfError("snfReadProps(): Couldn't allocate propspace (%d)\n", bytestoalloc);
153a96d7823Smrg	return AllocError;
154a96d7823Smrg    }
155a96d7823Smrg
156a96d7823Smrg    if (FontFileRead(file, propspace, bytestoalloc) != bytestoalloc) {
157a96d7823Smrg	free(propspace);
158a96d7823Smrg	return BadFontName;
159a96d7823Smrg    }
160a96d7823Smrg    psnfp = (snfFontPropPtr) propspace;
161a96d7823Smrg
162a96d7823Smrg    strings = propspace + BYTESOFPROPINFO(snfInfo);
163a96d7823Smrg
164a96d7823Smrg    for (i = 0, pfp = pFontInfo->props; i < snfInfo->nProps; i++, pfp++, psnfp++) {
165a96d7823Smrg	pfp->name = MakeAtom(&strings[psnfp->name],
166a96d7823Smrg			     (unsigned) strlen(&strings[psnfp->name]), 1);
167a96d7823Smrg	pFontInfo->isStringProp[i] = psnfp->indirect;
168a96d7823Smrg	if (psnfp->indirect)
169a96d7823Smrg	    pfp->value = (INT32) MakeAtom(&strings[psnfp->value],
170a96d7823Smrg			       (unsigned) strlen(&strings[psnfp->value]), 1);
171a96d7823Smrg	else
172a96d7823Smrg	    pfp->value = psnfp->value;
173a96d7823Smrg    }
174a96d7823Smrg
175a96d7823Smrg    free(propspace);
176a96d7823Smrg    return Successful;
177a96d7823Smrg}
178a96d7823Smrg
179a96d7823Smrgstatic int
180a96d7823SmrgsnfReadHeader(snfFontInfoPtr snfInfo, FontFilePtr file)
181a96d7823Smrg{
182a96d7823Smrg    if (FontFileRead(file, (char *) snfInfo, sizeof *snfInfo) != sizeof *snfInfo)
183a96d7823Smrg	return BadFontName;
184a96d7823Smrg
185a96d7823Smrg    if (snfInfo->version1 != FONT_FILE_VERSION ||
186a96d7823Smrg	    snfInfo->version2 != FONT_FILE_VERSION)
187a96d7823Smrg	return BadFontName;
188a96d7823Smrg    return Successful;
189a96d7823Smrg}
190a96d7823Smrg
191a96d7823Smrgstatic int  snf_set;
192a96d7823Smrgstatic int  snf_bit, snf_byte, snf_glyph, snf_scan;
193a96d7823Smrg
194a96d7823Smrgvoid
195a96d7823SmrgSnfSetFormat (int bit, int byte, int glyph, int scan)
196a96d7823Smrg{
197a96d7823Smrg    snf_bit = bit;
198a96d7823Smrg    snf_byte = byte;
199a96d7823Smrg    snf_glyph = glyph;
200a96d7823Smrg    snf_scan = scan;
201a96d7823Smrg    snf_set = 1;
202a96d7823Smrg}
203a96d7823Smrg
204a96d7823Smrgstatic void
205a96d7823SmrgSnfGetFormat (int *bit, int *byte, int *glyph, int *scan)
206a96d7823Smrg{
207a96d7823Smrg    if (!snf_set)
208a96d7823Smrg	FontDefaultFormat (&snf_bit, &snf_byte, &snf_glyph, &snf_scan);
209a96d7823Smrg    *bit = snf_bit;
210a96d7823Smrg    *byte = snf_byte;
211a96d7823Smrg    *glyph = snf_glyph;
212a96d7823Smrg    *scan = snf_scan;
213a96d7823Smrg}
214a96d7823Smrg
215a96d7823Smrgint
216a96d7823SmrgsnfReadFont(FontPtr pFont, FontFilePtr file,
217a96d7823Smrg	    int bit, int byte, int glyph, int scan)
218a96d7823Smrg{
219a96d7823Smrg    snfFontInfoRec fi;
220a96d7823Smrg    unsigned    bytestoalloc;
221a96d7823Smrg    int         i, j;
222a96d7823Smrg    char       *fontspace;
223a96d7823Smrg    BitmapFontPtr  bitmapFont;
224a96d7823Smrg    int         num_chars;
225a96d7823Smrg    int         bitmapsSize;
226a96d7823Smrg    int         ret;
227a96d7823Smrg    int         metrics_off;
228a96d7823Smrg    int         encoding_off;
229a96d7823Smrg    int         props_off;
230a96d7823Smrg    int         isStringProp_off;
231a96d7823Smrg    int         ink_off;
232a96d7823Smrg    char	*bitmaps;
233a96d7823Smrg    int		def_bit, def_byte, def_glyph, def_scan;
234a96d7823Smrg
235a96d7823Smrg    ret = snfReadHeader(&fi, file);
236a96d7823Smrg    if (ret != Successful)
237a96d7823Smrg	return ret;
238a96d7823Smrg
239a96d7823Smrg    SnfGetFormat (&def_bit, &def_byte, &def_glyph, &def_scan);
240a96d7823Smrg
241a96d7823Smrg    /*
242a96d7823Smrg     * we'll allocate one chunk of memory and split it among the various parts
243a96d7823Smrg     * of the font:
244a96d7823Smrg     *
245a96d7823Smrg     * BitmapFontRec CharInfoRec's Glyphs Encoding DIX Properties Ink CharInfoRec's
246a96d7823Smrg     *
247a96d7823Smrg     * If the glyphpad is not the same as the font file, then the glyphs
248a96d7823Smrg     * are allocated separately, to be later realloc'ed when we know
249a96d7823Smrg     * how big to make them.
250a96d7823Smrg     */
251a96d7823Smrg
252a96d7823Smrg    bitmapsSize = BYTESOFGLYPHINFO(&fi);
253a96d7823Smrg    num_chars = n2dChars(&fi);
254a96d7823Smrg    bytestoalloc = sizeof(BitmapFontRec);	/* bitmapFont */
255a96d7823Smrg    metrics_off = bytestoalloc;
256a96d7823Smrg    bytestoalloc += num_chars * sizeof(CharInfoRec);	/* metrics */
257a96d7823Smrg    encoding_off = bytestoalloc;
258a96d7823Smrg    bytestoalloc += NUM_SEGMENTS(num_chars) * sizeof(CharInfoPtr**);
259a96d7823Smrg                                                /* encoding */
260a96d7823Smrg    props_off = bytestoalloc;
261a96d7823Smrg    bytestoalloc += fi.nProps * sizeof(FontPropRec);	/* props */
262a96d7823Smrg    isStringProp_off = bytestoalloc;
263a96d7823Smrg    bytestoalloc += fi.nProps * sizeof(char);	/* isStringProp */
264a96d7823Smrg    bytestoalloc = (bytestoalloc + 3) & ~3;
265a96d7823Smrg    ink_off = bytestoalloc;
266a96d7823Smrg    if (fi.inkMetrics)
267a96d7823Smrg	bytestoalloc += num_chars * sizeof(xCharInfo);	/* ink_metrics */
268a96d7823Smrg
269a96d7823Smrg    fontspace = malloc(bytestoalloc);
270a96d7823Smrg    if (!fontspace) {
271a96d7823Smrg      snfError("snfReadFont(): Couldn't allocate fontspace (%d)\n", bytestoalloc);
272a96d7823Smrg	return AllocError;
273a96d7823Smrg    }
274a96d7823Smrg    bitmaps = malloc (bitmapsSize);
275a96d7823Smrg    if (!bitmaps)
276a96d7823Smrg    {
277a96d7823Smrg      snfError("snfReadFont(): Couldn't allocate bitmaps (%d)\n", bitmapsSize);
278a96d7823Smrg	free (fontspace);
279a96d7823Smrg	return AllocError;
280a96d7823Smrg    }
281a96d7823Smrg    /*
282a96d7823Smrg     * now fix up pointers
283a96d7823Smrg     */
284a96d7823Smrg
285a96d7823Smrg    bitmapFont = (BitmapFontPtr) fontspace;
286a96d7823Smrg    bitmapFont->num_chars = num_chars;
287a96d7823Smrg    bitmapFont->metrics = (CharInfoPtr) (fontspace + metrics_off);
288a96d7823Smrg    bitmapFont->encoding = (CharInfoPtr **) (fontspace + encoding_off);
289a96d7823Smrg    bitmapFont->bitmaps = bitmaps;
290a96d7823Smrg    bitmapFont->pDefault = NULL;
291a96d7823Smrg    bitmapFont->bitmapExtra = NULL;
292a96d7823Smrg    pFont->info.props = (FontPropPtr) (fontspace + props_off);
293a96d7823Smrg    pFont->info.isStringProp = (char *) (fontspace + isStringProp_off);
294a96d7823Smrg    if (fi.inkMetrics)
295a96d7823Smrg	bitmapFont->ink_metrics = (xCharInfo *) (fontspace + ink_off);
296a96d7823Smrg    else
297a96d7823Smrg	bitmapFont->ink_metrics = 0;
298a96d7823Smrg
299a96d7823Smrg    /*
300a96d7823Smrg     * read the CharInfo
301a96d7823Smrg     */
302a96d7823Smrg
303a96d7823Smrg    ret = Successful;
304a96d7823Smrg    memset(bitmapFont->encoding, 0,
305a96d7823Smrg           NUM_SEGMENTS(num_chars)*sizeof(CharInfoPtr*));
306a96d7823Smrg    for (i = 0; ret == Successful && i < num_chars; i++) {
307a96d7823Smrg	ret = snfReadCharInfo(file, &bitmapFont->metrics[i], bitmaps);
308a96d7823Smrg	if (bitmapFont->metrics[i].bits) {
309a96d7823Smrg            if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) {
310a96d7823Smrg                bitmapFont->encoding[SEGMENT_MAJOR(i)]=
311a96d7823Smrg                    calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr));
312a96d7823Smrg                if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) {
313a96d7823Smrg                    ret = AllocError;
314a96d7823Smrg                    break;
315a96d7823Smrg                }
316a96d7823Smrg            }
317a96d7823Smrg            ACCESSENCODINGL(bitmapFont->encoding,i) = &bitmapFont->metrics[i];
318a96d7823Smrg        }
319a96d7823Smrg    }
320a96d7823Smrg
321a96d7823Smrg    if (ret != Successful) {
322a96d7823Smrg	free(bitmaps);
323a96d7823Smrg        if(bitmapFont->encoding) {
324a96d7823Smrg            for(j=0; j<SEGMENT_MAJOR(i); j++)
325a96d7823Smrg                free(bitmapFont->encoding[i]);
326a96d7823Smrg        }
327a96d7823Smrg	free(fontspace);
328a96d7823Smrg	return ret;
329a96d7823Smrg    }
330a96d7823Smrg    /*
331a96d7823Smrg     * read the glyphs
332a96d7823Smrg     */
333a96d7823Smrg
334a96d7823Smrg    if (FontFileRead(file, bitmaps, bitmapsSize) != bitmapsSize) {
335a96d7823Smrg	free(bitmaps);
336a96d7823Smrg	free(fontspace);
337a96d7823Smrg	return BadFontName;
338a96d7823Smrg    }
339a96d7823Smrg
340a96d7823Smrg    if (def_bit != bit)
341a96d7823Smrg	BitOrderInvert((unsigned char *)bitmaps, bitmapsSize);
342a96d7823Smrg    if ((def_byte == def_bit) != (bit == byte)) {
343a96d7823Smrg	switch (bit == byte ? def_scan : scan) {
344a96d7823Smrg	case 1:
345a96d7823Smrg	    break;
346a96d7823Smrg	case 2:
347a96d7823Smrg	    TwoByteSwap((unsigned char *)bitmaps, bitmapsSize);
348a96d7823Smrg	    break;
349a96d7823Smrg	case 4:
350a96d7823Smrg	    FourByteSwap((unsigned char *)bitmaps, bitmapsSize);
351a96d7823Smrg	    break;
352a96d7823Smrg	}
353a96d7823Smrg    }
354a96d7823Smrg    if (def_glyph != glyph) {
355a96d7823Smrg	char	    *padbitmaps;
356a96d7823Smrg	int         sizepadbitmaps;
357a96d7823Smrg	int	    sizechar;
358a96d7823Smrg	CharInfoPtr metric;
359a96d7823Smrg
360a96d7823Smrg	sizepadbitmaps = 0;
361a96d7823Smrg	metric = bitmapFont->metrics;
362a96d7823Smrg	for (i = 0; i < num_chars; i++)
363a96d7823Smrg	{
364a96d7823Smrg	    if (metric->bits)
365a96d7823Smrg		sizepadbitmaps += BYTES_FOR_GLYPH(metric,glyph);
366a96d7823Smrg	    metric++;
367a96d7823Smrg	}
368a96d7823Smrg	padbitmaps = malloc(sizepadbitmaps);
369a96d7823Smrg	if (!padbitmaps) {
370a96d7823Smrg	    snfError("snfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps);
371a96d7823Smrg	    free (bitmaps);
372a96d7823Smrg	    free (fontspace);
373a96d7823Smrg	    return AllocError;
374a96d7823Smrg	}
375a96d7823Smrg	metric = bitmapFont->metrics;
376a96d7823Smrg	bitmapFont->bitmaps = padbitmaps;
377a96d7823Smrg	for (i = 0; i < num_chars; i++) {
378a96d7823Smrg	    sizechar = RepadBitmap(metric->bits, padbitmaps,
379a96d7823Smrg			       def_glyph, glyph,
380a96d7823Smrg			       metric->metrics.rightSideBearing -
381a96d7823Smrg			       metric->metrics.leftSideBearing,
382a96d7823Smrg			       metric->metrics.ascent + metric->metrics.descent);
383a96d7823Smrg	    metric->bits = padbitmaps;
384a96d7823Smrg	    padbitmaps += sizechar;
385a96d7823Smrg	    metric++;
386a96d7823Smrg	}
387a96d7823Smrg	free(bitmaps);
388a96d7823Smrg    }
389a96d7823Smrg
390a96d7823Smrg    /* now read and atom'ize properties */
391a96d7823Smrg
392a96d7823Smrg    ret = snfReadProps(&fi, &pFont->info, file);
393a96d7823Smrg    if (ret != Successful) {
394a96d7823Smrg	free(fontspace);
395a96d7823Smrg	return ret;
396a96d7823Smrg    }
397a96d7823Smrg    snfCopyInfo(&fi, &pFont->info);
398a96d7823Smrg
399a96d7823Smrg    /* finally, read the ink metrics if the exist */
400a96d7823Smrg
401a96d7823Smrg    if (fi.inkMetrics) {
402a96d7823Smrg	ret = Successful;
403a96d7823Smrg	ret = snfReadxCharInfo(file, &pFont->info.ink_minbounds);
404a96d7823Smrg	ret = snfReadxCharInfo(file, &pFont->info.ink_maxbounds);
405a96d7823Smrg	for (i = 0; ret == Successful && i < num_chars; i++)
406a96d7823Smrg	    ret = snfReadxCharInfo(file, &bitmapFont->ink_metrics[i]);
407a96d7823Smrg	if (ret != Successful) {
408a96d7823Smrg	    free(fontspace);
409a96d7823Smrg	    return ret;
410a96d7823Smrg	}
411a96d7823Smrg    } else {
412a96d7823Smrg	pFont->info.ink_minbounds = pFont->info.minbounds;
413a96d7823Smrg	pFont->info.ink_maxbounds = pFont->info.maxbounds;
414a96d7823Smrg    }
415a96d7823Smrg
416a96d7823Smrg    if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) {
417a96d7823Smrg	unsigned int r,
418a96d7823Smrg	            c,
419a96d7823Smrg	            cols;
420a96d7823Smrg
421a96d7823Smrg	r = pFont->info.defaultCh >> 8;
422a96d7823Smrg	c = pFont->info.defaultCh & 0xFF;
423a96d7823Smrg	if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
424a96d7823Smrg		pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
425a96d7823Smrg	    cols = pFont->info.lastCol - pFont->info.firstCol + 1;
426a96d7823Smrg	    r = r - pFont->info.firstRow;
427a96d7823Smrg	    c = c - pFont->info.firstCol;
428a96d7823Smrg	    bitmapFont->pDefault = &bitmapFont->metrics[r * cols + c];
429a96d7823Smrg	}
430a96d7823Smrg    }
431a96d7823Smrg    bitmapFont->bitmapExtra = (BitmapExtraPtr) 0;
432a96d7823Smrg    pFont->fontPrivate = (pointer) bitmapFont;
433a96d7823Smrg    pFont->get_glyphs = bitmapGetGlyphs;
434a96d7823Smrg    pFont->get_metrics = bitmapGetMetrics;
435a96d7823Smrg    pFont->unload_font = snfUnloadFont;
436a96d7823Smrg    pFont->unload_glyphs = NULL;
437a96d7823Smrg    pFont->bit = bit;
438a96d7823Smrg    pFont->byte = byte;
439a96d7823Smrg    pFont->glyph = glyph;
440a96d7823Smrg    pFont->scan = scan;
441a96d7823Smrg    return Successful;
442a96d7823Smrg}
443a96d7823Smrg
444a96d7823Smrgint
445a96d7823SmrgsnfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file)
446a96d7823Smrg{
447a96d7823Smrg    int         ret;
448a96d7823Smrg    snfFontInfoRec fi;
449a96d7823Smrg    int         bytestoskip;
450a96d7823Smrg    int         num_chars;
451a96d7823Smrg
452a96d7823Smrg    ret = snfReadHeader(&fi, file);
453a96d7823Smrg    if (ret != Successful)
454a96d7823Smrg	return ret;
455a96d7823Smrg    snfCopyInfo(&fi, pFontInfo);
456a96d7823Smrg
457c7b4381aSmrg    pFontInfo->props = mallocarray(fi.nProps, sizeof(FontPropRec));
458a96d7823Smrg    if (!pFontInfo->props) {
459a96d7823Smrg	snfError("snfReadFontInfo(): Couldn't allocate props (%d*%d)\n",
460a96d7823Smrg		 fi.nProps, (int) sizeof(FontPropRec));
461a96d7823Smrg	return AllocError;
462a96d7823Smrg    }
463c7b4381aSmrg    pFontInfo->isStringProp = mallocarray(fi.nProps, sizeof(char));
464a96d7823Smrg    if (!pFontInfo->isStringProp) {
465a96d7823Smrg	snfError("snfReadFontInfo(): Couldn't allocate isStringProp (%d*%d)\n",
466a96d7823Smrg		 fi.nProps, (int) sizeof(char));
467a96d7823Smrg	free(pFontInfo->props);
468a96d7823Smrg	return AllocError;
469a96d7823Smrg    }
470a96d7823Smrg    num_chars = n2dChars(&fi);
471a96d7823Smrg    bytestoskip = num_chars * sizeof(snfCharInfoRec);	/* charinfos */
472a96d7823Smrg    bytestoskip += BYTESOFGLYPHINFO(&fi);
473a96d7823Smrg    (void)FontFileSkip(file, bytestoskip);
474a96d7823Smrg
475a96d7823Smrg    ret = snfReadProps(&fi, pFontInfo, file);
476a96d7823Smrg    if (ret != Successful) {
477a96d7823Smrg	free(pFontInfo->props);
478a96d7823Smrg	free(pFontInfo->isStringProp);
479a96d7823Smrg	return ret;
480a96d7823Smrg    }
481a96d7823Smrg    if (fi.inkMetrics) {
482a96d7823Smrg	ret = snfReadxCharInfo(file, &pFontInfo->ink_minbounds);
483a96d7823Smrg	if (ret != Successful) {
484a96d7823Smrg	    free(pFontInfo->props);
485a96d7823Smrg	    free(pFontInfo->isStringProp);
486a96d7823Smrg	    return ret;
487a96d7823Smrg	}
488a96d7823Smrg	ret = snfReadxCharInfo(file, &pFontInfo->ink_maxbounds);
489a96d7823Smrg	if (ret != Successful) {
490a96d7823Smrg	    free(pFontInfo->props);
491a96d7823Smrg	    free(pFontInfo->isStringProp);
492a96d7823Smrg	    return ret;
493a96d7823Smrg	}
494a96d7823Smrg    } else {
495a96d7823Smrg	pFontInfo->ink_minbounds = pFontInfo->minbounds;
496a96d7823Smrg	pFontInfo->ink_maxbounds = pFontInfo->maxbounds;
497a96d7823Smrg    }
498a96d7823Smrg    return Successful;
499a96d7823Smrg
500a96d7823Smrg}
501a96d7823Smrg
502a96d7823Smrgstatic void
503a96d7823SmrgsnfUnloadFont(FontPtr pFont)
504a96d7823Smrg{
505a96d7823Smrg    BitmapFontPtr   bitmapFont;
506a96d7823Smrg
507a96d7823Smrg    bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
508a96d7823Smrg    free (bitmapFont->bitmaps);
509a96d7823Smrg    free (bitmapFont);
510a96d7823Smrg    DestroyFontRec (pFont);
511a96d7823Smrg}
512a96d7823Smrg
513