xref: /inferno-os/libfreetype/bdflib.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /*
2*37da2899SCharles.Forsyth  * Copyright 2000 Computing Research Labs, New Mexico State University
3*37da2899SCharles.Forsyth  * Copyright 2001, 2002 Francesco Zappa Nardelli
4*37da2899SCharles.Forsyth  *
5*37da2899SCharles.Forsyth  * Permission is hereby granted, free of charge, to any person obtaining a
6*37da2899SCharles.Forsyth  * copy of this software and associated documentation files (the "Software"),
7*37da2899SCharles.Forsyth  * to deal in the Software without restriction, including without limitation
8*37da2899SCharles.Forsyth  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*37da2899SCharles.Forsyth  * and/or sell copies of the Software, and to permit persons to whom the
10*37da2899SCharles.Forsyth  * Software is furnished to do so, subject to the following conditions:
11*37da2899SCharles.Forsyth  *
12*37da2899SCharles.Forsyth  * The above copyright notice and this permission notice shall be included in
13*37da2899SCharles.Forsyth  * all copies or substantial portions of the Software.
14*37da2899SCharles.Forsyth  *
15*37da2899SCharles.Forsyth  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*37da2899SCharles.Forsyth  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*37da2899SCharles.Forsyth  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*37da2899SCharles.Forsyth  * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
19*37da2899SCharles.Forsyth  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
20*37da2899SCharles.Forsyth  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
21*37da2899SCharles.Forsyth  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*37da2899SCharles.Forsyth  */
23*37da2899SCharles.Forsyth 
24*37da2899SCharles.Forsyth   /*************************************************************************/
25*37da2899SCharles.Forsyth   /*                                                                       */
26*37da2899SCharles.Forsyth   /*  This file is based on bdf.c,v 1.22 2000/03/16 20:08:50               */
27*37da2899SCharles.Forsyth   /*                                                                       */
28*37da2899SCharles.Forsyth   /*  taken from Mark Leisher's xmbdfed package                            */
29*37da2899SCharles.Forsyth   /*                                                                       */
30*37da2899SCharles.Forsyth   /*************************************************************************/
31*37da2899SCharles.Forsyth 
32*37da2899SCharles.Forsyth 
33*37da2899SCharles.Forsyth #include <ft2build.h>
34*37da2899SCharles.Forsyth 
35*37da2899SCharles.Forsyth #include FT_FREETYPE_H
36*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
37*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H
38*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth #include "bdf.h"
41*37da2899SCharles.Forsyth #include "bdferror.h"
42*37da2899SCharles.Forsyth 
43*37da2899SCharles.Forsyth 
44*37da2899SCharles.Forsyth   /*************************************************************************/
45*37da2899SCharles.Forsyth   /*                                                                       */
46*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
47*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
48*37da2899SCharles.Forsyth   /* messages during execution.                                            */
49*37da2899SCharles.Forsyth   /*                                                                       */
50*37da2899SCharles.Forsyth #undef  FT_COMPONENT
51*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_bdflib
52*37da2899SCharles.Forsyth 
53*37da2899SCharles.Forsyth 
54*37da2899SCharles.Forsyth   /*************************************************************************/
55*37da2899SCharles.Forsyth   /*                                                                       */
56*37da2899SCharles.Forsyth   /* Default BDF font options.                                             */
57*37da2899SCharles.Forsyth   /*                                                                       */
58*37da2899SCharles.Forsyth   /*************************************************************************/
59*37da2899SCharles.Forsyth 
60*37da2899SCharles.Forsyth 
61*37da2899SCharles.Forsyth   static const bdf_options_t  _bdf_opts =
62*37da2899SCharles.Forsyth   {
63*37da2899SCharles.Forsyth     1,                /* Correct metrics.               */
64*37da2899SCharles.Forsyth     1,                /* Preserve unencoded glyphs.     */
65*37da2899SCharles.Forsyth     0,                /* Preserve comments.             */
66*37da2899SCharles.Forsyth     BDF_PROPORTIONAL  /* Default spacing.               */
67*37da2899SCharles.Forsyth   };
68*37da2899SCharles.Forsyth 
69*37da2899SCharles.Forsyth 
70*37da2899SCharles.Forsyth   /*************************************************************************/
71*37da2899SCharles.Forsyth   /*                                                                       */
72*37da2899SCharles.Forsyth   /* Builtin BDF font properties.                                          */
73*37da2899SCharles.Forsyth   /*                                                                       */
74*37da2899SCharles.Forsyth   /*************************************************************************/
75*37da2899SCharles.Forsyth 
76*37da2899SCharles.Forsyth   /* List of most properties that might appear in a font.  Doesn't include */
77*37da2899SCharles.Forsyth   /* the RAW_* and AXIS_* properties in X11R6 polymorphic fonts.           */
78*37da2899SCharles.Forsyth 
79*37da2899SCharles.Forsyth   static const bdf_property_t  _bdf_properties[] =
80*37da2899SCharles.Forsyth   {
81*37da2899SCharles.Forsyth     { (char *)"ADD_STYLE_NAME",          BDF_ATOM,     1, { 0 } },
82*37da2899SCharles.Forsyth     { (char *)"AVERAGE_WIDTH",           BDF_INTEGER,  1, { 0 } },
83*37da2899SCharles.Forsyth     { (char *)"AVG_CAPITAL_WIDTH",       BDF_INTEGER,  1, { 0 } },
84*37da2899SCharles.Forsyth     { (char *)"AVG_LOWERCASE_WIDTH",     BDF_INTEGER,  1, { 0 } },
85*37da2899SCharles.Forsyth     { (char *)"CAP_HEIGHT",              BDF_INTEGER,  1, { 0 } },
86*37da2899SCharles.Forsyth     { (char *)"CHARSET_COLLECTIONS",     BDF_ATOM,     1, { 0 } },
87*37da2899SCharles.Forsyth     { (char *)"CHARSET_ENCODING",        BDF_ATOM,     1, { 0 } },
88*37da2899SCharles.Forsyth     { (char *)"CHARSET_REGISTRY",        BDF_ATOM,     1, { 0 } },
89*37da2899SCharles.Forsyth     { (char *)"COMMENT",                 BDF_ATOM,     1, { 0 } },
90*37da2899SCharles.Forsyth     { (char *)"COPYRIGHT",               BDF_ATOM,     1, { 0 } },
91*37da2899SCharles.Forsyth     { (char *)"DEFAULT_CHAR",            BDF_CARDINAL, 1, { 0 } },
92*37da2899SCharles.Forsyth     { (char *)"DESTINATION",             BDF_CARDINAL, 1, { 0 } },
93*37da2899SCharles.Forsyth     { (char *)"DEVICE_FONT_NAME",        BDF_ATOM,     1, { 0 } },
94*37da2899SCharles.Forsyth     { (char *)"END_SPACE",               BDF_INTEGER,  1, { 0 } },
95*37da2899SCharles.Forsyth     { (char *)"FACE_NAME",               BDF_ATOM,     1, { 0 } },
96*37da2899SCharles.Forsyth     { (char *)"FAMILY_NAME",             BDF_ATOM,     1, { 0 } },
97*37da2899SCharles.Forsyth     { (char *)"FIGURE_WIDTH",            BDF_INTEGER,  1, { 0 } },
98*37da2899SCharles.Forsyth     { (char *)"FONT",                    BDF_ATOM,     1, { 0 } },
99*37da2899SCharles.Forsyth     { (char *)"FONTNAME_REGISTRY",       BDF_ATOM,     1, { 0 } },
100*37da2899SCharles.Forsyth     { (char *)"FONT_ASCENT",             BDF_INTEGER,  1, { 0 } },
101*37da2899SCharles.Forsyth     { (char *)"FONT_DESCENT",            BDF_INTEGER,  1, { 0 } },
102*37da2899SCharles.Forsyth     { (char *)"FOUNDRY",                 BDF_ATOM,     1, { 0 } },
103*37da2899SCharles.Forsyth     { (char *)"FULL_NAME",               BDF_ATOM,     1, { 0 } },
104*37da2899SCharles.Forsyth     { (char *)"ITALIC_ANGLE",            BDF_INTEGER,  1, { 0 } },
105*37da2899SCharles.Forsyth     { (char *)"MAX_SPACE",               BDF_INTEGER,  1, { 0 } },
106*37da2899SCharles.Forsyth     { (char *)"MIN_SPACE",               BDF_INTEGER,  1, { 0 } },
107*37da2899SCharles.Forsyth     { (char *)"NORM_SPACE",              BDF_INTEGER,  1, { 0 } },
108*37da2899SCharles.Forsyth     { (char *)"NOTICE",                  BDF_ATOM,     1, { 0 } },
109*37da2899SCharles.Forsyth     { (char *)"PIXEL_SIZE",              BDF_INTEGER,  1, { 0 } },
110*37da2899SCharles.Forsyth     { (char *)"POINT_SIZE",              BDF_INTEGER,  1, { 0 } },
111*37da2899SCharles.Forsyth     { (char *)"QUAD_WIDTH",              BDF_INTEGER,  1, { 0 } },
112*37da2899SCharles.Forsyth     { (char *)"RAW_ASCENT",              BDF_INTEGER,  1, { 0 } },
113*37da2899SCharles.Forsyth     { (char *)"RAW_AVERAGE_WIDTH",       BDF_INTEGER,  1, { 0 } },
114*37da2899SCharles.Forsyth     { (char *)"RAW_AVG_CAPITAL_WIDTH",   BDF_INTEGER,  1, { 0 } },
115*37da2899SCharles.Forsyth     { (char *)"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER,  1, { 0 } },
116*37da2899SCharles.Forsyth     { (char *)"RAW_CAP_HEIGHT",          BDF_INTEGER,  1, { 0 } },
117*37da2899SCharles.Forsyth     { (char *)"RAW_DESCENT",             BDF_INTEGER,  1, { 0 } },
118*37da2899SCharles.Forsyth     { (char *)"RAW_END_SPACE",           BDF_INTEGER,  1, { 0 } },
119*37da2899SCharles.Forsyth     { (char *)"RAW_FIGURE_WIDTH",        BDF_INTEGER,  1, { 0 } },
120*37da2899SCharles.Forsyth     { (char *)"RAW_MAX_SPACE",           BDF_INTEGER,  1, { 0 } },
121*37da2899SCharles.Forsyth     { (char *)"RAW_MIN_SPACE",           BDF_INTEGER,  1, { 0 } },
122*37da2899SCharles.Forsyth     { (char *)"RAW_NORM_SPACE",          BDF_INTEGER,  1, { 0 } },
123*37da2899SCharles.Forsyth     { (char *)"RAW_PIXEL_SIZE",          BDF_INTEGER,  1, { 0 } },
124*37da2899SCharles.Forsyth     { (char *)"RAW_POINT_SIZE",          BDF_INTEGER,  1, { 0 } },
125*37da2899SCharles.Forsyth     { (char *)"RAW_PIXELSIZE",           BDF_INTEGER,  1, { 0 } },
126*37da2899SCharles.Forsyth     { (char *)"RAW_POINTSIZE",           BDF_INTEGER,  1, { 0 } },
127*37da2899SCharles.Forsyth     { (char *)"RAW_QUAD_WIDTH",          BDF_INTEGER,  1, { 0 } },
128*37da2899SCharles.Forsyth     { (char *)"RAW_SMALL_CAP_SIZE",      BDF_INTEGER,  1, { 0 } },
129*37da2899SCharles.Forsyth     { (char *)"RAW_STRIKEOUT_ASCENT",    BDF_INTEGER,  1, { 0 } },
130*37da2899SCharles.Forsyth     { (char *)"RAW_STRIKEOUT_DESCENT",   BDF_INTEGER,  1, { 0 } },
131*37da2899SCharles.Forsyth     { (char *)"RAW_SUBSCRIPT_SIZE",      BDF_INTEGER,  1, { 0 } },
132*37da2899SCharles.Forsyth     { (char *)"RAW_SUBSCRIPT_X",         BDF_INTEGER,  1, { 0 } },
133*37da2899SCharles.Forsyth     { (char *)"RAW_SUBSCRIPT_Y",         BDF_INTEGER,  1, { 0 } },
134*37da2899SCharles.Forsyth     { (char *)"RAW_SUPERSCRIPT_SIZE",    BDF_INTEGER,  1, { 0 } },
135*37da2899SCharles.Forsyth     { (char *)"RAW_SUPERSCRIPT_X",       BDF_INTEGER,  1, { 0 } },
136*37da2899SCharles.Forsyth     { (char *)"RAW_SUPERSCRIPT_Y",       BDF_INTEGER,  1, { 0 } },
137*37da2899SCharles.Forsyth     { (char *)"RAW_UNDERLINE_POSITION",  BDF_INTEGER,  1, { 0 } },
138*37da2899SCharles.Forsyth     { (char *)"RAW_UNDERLINE_THICKNESS", BDF_INTEGER,  1, { 0 } },
139*37da2899SCharles.Forsyth     { (char *)"RAW_X_HEIGHT",            BDF_INTEGER,  1, { 0 } },
140*37da2899SCharles.Forsyth     { (char *)"RELATIVE_SETWIDTH",       BDF_CARDINAL, 1, { 0 } },
141*37da2899SCharles.Forsyth     { (char *)"RELATIVE_WEIGHT",         BDF_CARDINAL, 1, { 0 } },
142*37da2899SCharles.Forsyth     { (char *)"RESOLUTION",              BDF_INTEGER,  1, { 0 } },
143*37da2899SCharles.Forsyth     { (char *)"RESOLUTION_X",            BDF_CARDINAL, 1, { 0 } },
144*37da2899SCharles.Forsyth     { (char *)"RESOLUTION_Y",            BDF_CARDINAL, 1, { 0 } },
145*37da2899SCharles.Forsyth     { (char *)"SETWIDTH_NAME",           BDF_ATOM,     1, { 0 } },
146*37da2899SCharles.Forsyth     { (char *)"SLANT",                   BDF_ATOM,     1, { 0 } },
147*37da2899SCharles.Forsyth     { (char *)"SMALL_CAP_SIZE",          BDF_INTEGER,  1, { 0 } },
148*37da2899SCharles.Forsyth     { (char *)"SPACING",                 BDF_ATOM,     1, { 0 } },
149*37da2899SCharles.Forsyth     { (char *)"STRIKEOUT_ASCENT",        BDF_INTEGER,  1, { 0 } },
150*37da2899SCharles.Forsyth     { (char *)"STRIKEOUT_DESCENT",       BDF_INTEGER,  1, { 0 } },
151*37da2899SCharles.Forsyth     { (char *)"SUBSCRIPT_SIZE",          BDF_INTEGER,  1, { 0 } },
152*37da2899SCharles.Forsyth     { (char *)"SUBSCRIPT_X",             BDF_INTEGER,  1, { 0 } },
153*37da2899SCharles.Forsyth     { (char *)"SUBSCRIPT_Y",             BDF_INTEGER,  1, { 0 } },
154*37da2899SCharles.Forsyth     { (char *)"SUPERSCRIPT_SIZE",        BDF_INTEGER,  1, { 0 } },
155*37da2899SCharles.Forsyth     { (char *)"SUPERSCRIPT_X",           BDF_INTEGER,  1, { 0 } },
156*37da2899SCharles.Forsyth     { (char *)"SUPERSCRIPT_Y",           BDF_INTEGER,  1, { 0 } },
157*37da2899SCharles.Forsyth     { (char *)"UNDERLINE_POSITION",      BDF_INTEGER,  1, { 0 } },
158*37da2899SCharles.Forsyth     { (char *)"UNDERLINE_THICKNESS",     BDF_INTEGER,  1, { 0 } },
159*37da2899SCharles.Forsyth     { (char *)"WEIGHT",                  BDF_CARDINAL, 1, { 0 } },
160*37da2899SCharles.Forsyth     { (char *)"WEIGHT_NAME",             BDF_ATOM,     1, { 0 } },
161*37da2899SCharles.Forsyth     { (char *)"X_HEIGHT",                BDF_INTEGER,  1, { 0 } },
162*37da2899SCharles.Forsyth     { (char *)"_MULE_BASELINE_OFFSET",   BDF_INTEGER,  1, { 0 } },
163*37da2899SCharles.Forsyth     { (char *)"_MULE_RELATIVE_COMPOSE",  BDF_INTEGER,  1, { 0 } },
164*37da2899SCharles.Forsyth   };
165*37da2899SCharles.Forsyth 
166*37da2899SCharles.Forsyth   static unsigned long
167*37da2899SCharles.Forsyth   _num_bdf_properties = sizeof ( _bdf_properties ) /
168*37da2899SCharles.Forsyth                         sizeof ( _bdf_properties[0] );
169*37da2899SCharles.Forsyth 
170*37da2899SCharles.Forsyth 
171*37da2899SCharles.Forsyth   /*************************************************************************/
172*37da2899SCharles.Forsyth   /*                                                                       */
173*37da2899SCharles.Forsyth   /* Hash table utilities for the properties.                              */
174*37da2899SCharles.Forsyth   /*                                                                       */
175*37da2899SCharles.Forsyth   /*************************************************************************/
176*37da2899SCharles.Forsyth 
177*37da2899SCharles.Forsyth   /* XXX: Replace this with FreeType's hash functions */
178*37da2899SCharles.Forsyth 
179*37da2899SCharles.Forsyth 
180*37da2899SCharles.Forsyth #define INITIAL_HT_SIZE  241
181*37da2899SCharles.Forsyth 
182*37da2899SCharles.Forsyth   typedef void
183*37da2899SCharles.Forsyth   (*hash_free_func)( hashnode  node );
184*37da2899SCharles.Forsyth 
185*37da2899SCharles.Forsyth   static hashnode*
hash_bucket(char * key,hashtable * ht)186*37da2899SCharles.Forsyth   hash_bucket( char*       key,
187*37da2899SCharles.Forsyth                hashtable*  ht )
188*37da2899SCharles.Forsyth   {
189*37da2899SCharles.Forsyth     char*          kp  = key;
190*37da2899SCharles.Forsyth     unsigned long  res = 0;
191*37da2899SCharles.Forsyth     hashnode*      bp  = ht->table, *ndp;
192*37da2899SCharles.Forsyth 
193*37da2899SCharles.Forsyth 
194*37da2899SCharles.Forsyth     /* Mocklisp hash function. */
195*37da2899SCharles.Forsyth     while ( *kp )
196*37da2899SCharles.Forsyth       res = ( res << 5 ) - res + *kp++;
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth     ndp = bp + ( res % ht->size );
199*37da2899SCharles.Forsyth     while ( *ndp )
200*37da2899SCharles.Forsyth     {
201*37da2899SCharles.Forsyth       kp = (*ndp)->key;
202*37da2899SCharles.Forsyth       if ( kp[0] == key[0] && ft_strcmp( kp, key ) == 0 )
203*37da2899SCharles.Forsyth         break;
204*37da2899SCharles.Forsyth       ndp--;
205*37da2899SCharles.Forsyth       if ( ndp < bp )
206*37da2899SCharles.Forsyth         ndp = bp + ( ht->size - 1 );
207*37da2899SCharles.Forsyth     }
208*37da2899SCharles.Forsyth 
209*37da2899SCharles.Forsyth     return ndp;
210*37da2899SCharles.Forsyth   }
211*37da2899SCharles.Forsyth 
212*37da2899SCharles.Forsyth 
213*37da2899SCharles.Forsyth   static FT_Error
hash_rehash(hashtable * ht,FT_Memory memory)214*37da2899SCharles.Forsyth   hash_rehash( hashtable*  ht,
215*37da2899SCharles.Forsyth                FT_Memory   memory )
216*37da2899SCharles.Forsyth   {
217*37da2899SCharles.Forsyth     hashnode*  obp = ht->table, *bp, *nbp;
218*37da2899SCharles.Forsyth     int        i, sz = ht->size;
219*37da2899SCharles.Forsyth     FT_Error   error = BDF_Err_Ok;
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth 
222*37da2899SCharles.Forsyth     ht->size <<= 1;
223*37da2899SCharles.Forsyth     ht->limit  = ht->size / 3;
224*37da2899SCharles.Forsyth 
225*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( ht->table, ht->size ) )
226*37da2899SCharles.Forsyth       goto Exit;
227*37da2899SCharles.Forsyth     FT_MEM_ZERO( ht->table, sizeof ( hashnode ) * ht->size );
228*37da2899SCharles.Forsyth 
229*37da2899SCharles.Forsyth     for ( i = 0, bp = obp; i < sz; i++, bp++ )
230*37da2899SCharles.Forsyth     {
231*37da2899SCharles.Forsyth       if ( *bp )
232*37da2899SCharles.Forsyth       {
233*37da2899SCharles.Forsyth         nbp = hash_bucket( (*bp)->key, ht );
234*37da2899SCharles.Forsyth         *nbp = *bp;
235*37da2899SCharles.Forsyth       }
236*37da2899SCharles.Forsyth     }
237*37da2899SCharles.Forsyth     FT_FREE( obp );
238*37da2899SCharles.Forsyth 
239*37da2899SCharles.Forsyth   Exit:
240*37da2899SCharles.Forsyth     return error;
241*37da2899SCharles.Forsyth   }
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth 
244*37da2899SCharles.Forsyth   static FT_Error
hash_init(hashtable * ht,FT_Memory memory)245*37da2899SCharles.Forsyth   hash_init( hashtable*  ht,
246*37da2899SCharles.Forsyth              FT_Memory   memory )
247*37da2899SCharles.Forsyth   {
248*37da2899SCharles.Forsyth     int       sz = INITIAL_HT_SIZE;
249*37da2899SCharles.Forsyth     FT_Error  error = BDF_Err_Ok;
250*37da2899SCharles.Forsyth 
251*37da2899SCharles.Forsyth 
252*37da2899SCharles.Forsyth     ht->size  = sz;
253*37da2899SCharles.Forsyth     ht->limit = sz / 3;
254*37da2899SCharles.Forsyth     ht->used  = 0;
255*37da2899SCharles.Forsyth 
256*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( ht->table, sz ) )
257*37da2899SCharles.Forsyth       goto Exit;
258*37da2899SCharles.Forsyth     FT_MEM_ZERO( ht->table, sizeof ( hashnode ) * sz );
259*37da2899SCharles.Forsyth 
260*37da2899SCharles.Forsyth   Exit:
261*37da2899SCharles.Forsyth     return error;
262*37da2899SCharles.Forsyth   }
263*37da2899SCharles.Forsyth 
264*37da2899SCharles.Forsyth 
265*37da2899SCharles.Forsyth   static void
hash_free(hashtable * ht,FT_Memory memory)266*37da2899SCharles.Forsyth   hash_free( hashtable*  ht,
267*37da2899SCharles.Forsyth              FT_Memory   memory )
268*37da2899SCharles.Forsyth   {
269*37da2899SCharles.Forsyth     if ( ht != 0 )
270*37da2899SCharles.Forsyth     {
271*37da2899SCharles.Forsyth       int        i, sz = ht->size;
272*37da2899SCharles.Forsyth       hashnode*  bp = ht->table;
273*37da2899SCharles.Forsyth 
274*37da2899SCharles.Forsyth 
275*37da2899SCharles.Forsyth       for ( i = 0; i < sz; i++, bp++ )
276*37da2899SCharles.Forsyth         FT_FREE( *bp );
277*37da2899SCharles.Forsyth 
278*37da2899SCharles.Forsyth       FT_FREE( ht->table );
279*37da2899SCharles.Forsyth     }
280*37da2899SCharles.Forsyth   }
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth 
283*37da2899SCharles.Forsyth   static FT_Error
hash_insert(char * key,void * data,hashtable * ht,FT_Memory memory)284*37da2899SCharles.Forsyth   hash_insert( char*       key,
285*37da2899SCharles.Forsyth                void*       data,
286*37da2899SCharles.Forsyth                hashtable*  ht,
287*37da2899SCharles.Forsyth                FT_Memory   memory )
288*37da2899SCharles.Forsyth   {
289*37da2899SCharles.Forsyth     hashnode  nn, *bp = hash_bucket( key, ht );
290*37da2899SCharles.Forsyth     FT_Error  error = BDF_Err_Ok;
291*37da2899SCharles.Forsyth 
292*37da2899SCharles.Forsyth 
293*37da2899SCharles.Forsyth     nn = *bp;
294*37da2899SCharles.Forsyth     if ( !nn )
295*37da2899SCharles.Forsyth     {
296*37da2899SCharles.Forsyth       if ( FT_NEW( nn ) )
297*37da2899SCharles.Forsyth         goto Exit;
298*37da2899SCharles.Forsyth       *bp = nn;
299*37da2899SCharles.Forsyth 
300*37da2899SCharles.Forsyth       nn->key  = key;
301*37da2899SCharles.Forsyth       nn->data = data;
302*37da2899SCharles.Forsyth 
303*37da2899SCharles.Forsyth       if ( ht->used >= ht->limit )
304*37da2899SCharles.Forsyth       {
305*37da2899SCharles.Forsyth         error = hash_rehash( ht, memory );
306*37da2899SCharles.Forsyth         if ( error )
307*37da2899SCharles.Forsyth           goto Exit;
308*37da2899SCharles.Forsyth       }
309*37da2899SCharles.Forsyth       ht->used++;
310*37da2899SCharles.Forsyth     }
311*37da2899SCharles.Forsyth     else
312*37da2899SCharles.Forsyth       nn->data = data;
313*37da2899SCharles.Forsyth 
314*37da2899SCharles.Forsyth   Exit:
315*37da2899SCharles.Forsyth     return error;
316*37da2899SCharles.Forsyth   }
317*37da2899SCharles.Forsyth 
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth   static hashnode
hash_lookup(char * key,hashtable * ht)320*37da2899SCharles.Forsyth   hash_lookup( char*       key,
321*37da2899SCharles.Forsyth                hashtable*  ht )
322*37da2899SCharles.Forsyth   {
323*37da2899SCharles.Forsyth     hashnode *np = hash_bucket( key, ht );
324*37da2899SCharles.Forsyth 
325*37da2899SCharles.Forsyth 
326*37da2899SCharles.Forsyth     return *np;
327*37da2899SCharles.Forsyth   }
328*37da2899SCharles.Forsyth 
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth   /*************************************************************************/
331*37da2899SCharles.Forsyth   /*                                                                       */
332*37da2899SCharles.Forsyth   /* Utility types and functions.                                          */
333*37da2899SCharles.Forsyth   /*                                                                       */
334*37da2899SCharles.Forsyth   /*************************************************************************/
335*37da2899SCharles.Forsyth 
336*37da2899SCharles.Forsyth 
337*37da2899SCharles.Forsyth   /* Function type for parsing lines of a BDF font. */
338*37da2899SCharles.Forsyth 
339*37da2899SCharles.Forsyth   typedef FT_Error
340*37da2899SCharles.Forsyth   (*_bdf_line_func_t)( char*          line,
341*37da2899SCharles.Forsyth                        unsigned long  linelen,
342*37da2899SCharles.Forsyth                        unsigned long  lineno,
343*37da2899SCharles.Forsyth                        void*          call_data,
344*37da2899SCharles.Forsyth                        void*          client_data );
345*37da2899SCharles.Forsyth 
346*37da2899SCharles.Forsyth 
347*37da2899SCharles.Forsyth   /* List structure for splitting lines into fields. */
348*37da2899SCharles.Forsyth 
349*37da2899SCharles.Forsyth   typedef struct  _bdf_list_t_
350*37da2899SCharles.Forsyth   {
351*37da2899SCharles.Forsyth     char**         field;
352*37da2899SCharles.Forsyth     unsigned long  size;
353*37da2899SCharles.Forsyth     unsigned long  used;
354*37da2899SCharles.Forsyth 
355*37da2899SCharles.Forsyth   } _bdf_list_t;
356*37da2899SCharles.Forsyth 
357*37da2899SCharles.Forsyth 
358*37da2899SCharles.Forsyth   /* Structure used while loading BDF fonts. */
359*37da2899SCharles.Forsyth 
360*37da2899SCharles.Forsyth   typedef struct  _bdf_parse_t_
361*37da2899SCharles.Forsyth   {
362*37da2899SCharles.Forsyth     unsigned long   flags;
363*37da2899SCharles.Forsyth     unsigned long   cnt;
364*37da2899SCharles.Forsyth     unsigned long   row;
365*37da2899SCharles.Forsyth 
366*37da2899SCharles.Forsyth     short           minlb;
367*37da2899SCharles.Forsyth     short           maxlb;
368*37da2899SCharles.Forsyth     short           maxrb;
369*37da2899SCharles.Forsyth     short           maxas;
370*37da2899SCharles.Forsyth     short           maxds;
371*37da2899SCharles.Forsyth 
372*37da2899SCharles.Forsyth     short           rbearing;
373*37da2899SCharles.Forsyth 
374*37da2899SCharles.Forsyth     char*           glyph_name;
375*37da2899SCharles.Forsyth     long            glyph_enc;
376*37da2899SCharles.Forsyth 
377*37da2899SCharles.Forsyth     bdf_font_t*     font;
378*37da2899SCharles.Forsyth     bdf_options_t*  opts;
379*37da2899SCharles.Forsyth 
380*37da2899SCharles.Forsyth     unsigned long   have[2048];
381*37da2899SCharles.Forsyth     _bdf_list_t     list;
382*37da2899SCharles.Forsyth 
383*37da2899SCharles.Forsyth     FT_Memory       memory;
384*37da2899SCharles.Forsyth 
385*37da2899SCharles.Forsyth   } _bdf_parse_t;
386*37da2899SCharles.Forsyth 
387*37da2899SCharles.Forsyth 
388*37da2899SCharles.Forsyth #define setsbit( m, cc )  ( m[(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) )
389*37da2899SCharles.Forsyth #define sbitset( m, cc )  ( m[(cc) >> 3]  & ( 1 << ( (cc) & 7 ) ) )
390*37da2899SCharles.Forsyth 
391*37da2899SCharles.Forsyth 
392*37da2899SCharles.Forsyth   /* An empty string for empty fields. */
393*37da2899SCharles.Forsyth 
394*37da2899SCharles.Forsyth   static char  empty[1] = { 0 };   /* XXX eliminate this */
395*37da2899SCharles.Forsyth 
396*37da2899SCharles.Forsyth 
397*37da2899SCharles.Forsyth   /* Assume the line is NULL-terminated and that the `list' parameter */
398*37da2899SCharles.Forsyth   /* was initialized the first time it was used.                      */
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth   static FT_Error
_bdf_split(char * separators,char * line,unsigned long linelen,_bdf_list_t * list,FT_Memory memory)401*37da2899SCharles.Forsyth   _bdf_split( char*          separators,
402*37da2899SCharles.Forsyth               char*          line,
403*37da2899SCharles.Forsyth               unsigned long  linelen,
404*37da2899SCharles.Forsyth               _bdf_list_t*   list,
405*37da2899SCharles.Forsyth               FT_Memory      memory )
406*37da2899SCharles.Forsyth   {
407*37da2899SCharles.Forsyth     int       mult, final_empty;
408*37da2899SCharles.Forsyth     char      *sp, *ep, *end;
409*37da2899SCharles.Forsyth     char      seps[32];
410*37da2899SCharles.Forsyth     FT_Error  error = BDF_Err_Ok;
411*37da2899SCharles.Forsyth 
412*37da2899SCharles.Forsyth 
413*37da2899SCharles.Forsyth     /* Initialize the list. */
414*37da2899SCharles.Forsyth     list->used = 0;
415*37da2899SCharles.Forsyth 
416*37da2899SCharles.Forsyth     /* If the line is empty, then simply return. */
417*37da2899SCharles.Forsyth     if ( linelen == 0 || line[0] == 0 )
418*37da2899SCharles.Forsyth       goto Exit;
419*37da2899SCharles.Forsyth 
420*37da2899SCharles.Forsyth     /* In the original code, if the `separators' parameter is NULL or */
421*37da2899SCharles.Forsyth     /* empty, the list is split into individual bytes.  We don't need */
422*37da2899SCharles.Forsyth     /* this, so an error is signaled.                                 */
423*37da2899SCharles.Forsyth     if ( separators == 0 || *separators == 0 )
424*37da2899SCharles.Forsyth     {
425*37da2899SCharles.Forsyth       error = BDF_Err_Invalid_Argument;
426*37da2899SCharles.Forsyth       goto Exit;
427*37da2899SCharles.Forsyth     }
428*37da2899SCharles.Forsyth 
429*37da2899SCharles.Forsyth     /* Prepare the separator bitmap. */
430*37da2899SCharles.Forsyth     FT_MEM_ZERO( seps, 32 );
431*37da2899SCharles.Forsyth 
432*37da2899SCharles.Forsyth     /* If the very last character of the separator string is a plus, then */
433*37da2899SCharles.Forsyth     /* set the `mult' flag to indicate that multiple separators should be */
434*37da2899SCharles.Forsyth     /* collapsed into one.                                                */
435*37da2899SCharles.Forsyth     for ( mult = 0, sp = separators; sp && *sp; sp++ )
436*37da2899SCharles.Forsyth     {
437*37da2899SCharles.Forsyth       if ( *sp == '+' && *( sp + 1 ) == 0 )
438*37da2899SCharles.Forsyth         mult = 1;
439*37da2899SCharles.Forsyth       else
440*37da2899SCharles.Forsyth         setsbit( seps, *sp );
441*37da2899SCharles.Forsyth     }
442*37da2899SCharles.Forsyth 
443*37da2899SCharles.Forsyth     /* Break the line up into fields. */
444*37da2899SCharles.Forsyth     for ( final_empty = 0, sp = ep = line, end = sp + linelen;
445*37da2899SCharles.Forsyth           sp < end && *sp; )
446*37da2899SCharles.Forsyth     {
447*37da2899SCharles.Forsyth       /* Collect everything that is not a separator. */
448*37da2899SCharles.Forsyth       for ( ; *ep && !sbitset( seps, *ep ); ep++ )
449*37da2899SCharles.Forsyth         ;
450*37da2899SCharles.Forsyth 
451*37da2899SCharles.Forsyth       /* Resize the list if necessary. */
452*37da2899SCharles.Forsyth       if ( list->used == list->size )
453*37da2899SCharles.Forsyth       {
454*37da2899SCharles.Forsyth         if ( list->size == 0 )
455*37da2899SCharles.Forsyth         {
456*37da2899SCharles.Forsyth           if ( FT_NEW_ARRAY( list->field, 5 ) )
457*37da2899SCharles.Forsyth             goto Exit;
458*37da2899SCharles.Forsyth         }
459*37da2899SCharles.Forsyth         else
460*37da2899SCharles.Forsyth         {
461*37da2899SCharles.Forsyth           if ( FT_RENEW_ARRAY ( list->field ,
462*37da2899SCharles.Forsyth                                 list->size,
463*37da2899SCharles.Forsyth                                 list->size + 5 ) )
464*37da2899SCharles.Forsyth             goto Exit;
465*37da2899SCharles.Forsyth         }
466*37da2899SCharles.Forsyth 
467*37da2899SCharles.Forsyth         list->size += 5;
468*37da2899SCharles.Forsyth       }
469*37da2899SCharles.Forsyth 
470*37da2899SCharles.Forsyth       /* Assign the field appropriately. */
471*37da2899SCharles.Forsyth       list->field[list->used++] = ( ep > sp ) ? sp : empty;
472*37da2899SCharles.Forsyth 
473*37da2899SCharles.Forsyth       sp = ep;
474*37da2899SCharles.Forsyth 
475*37da2899SCharles.Forsyth       if ( mult )
476*37da2899SCharles.Forsyth       {
477*37da2899SCharles.Forsyth         /* If multiple separators should be collapsed, do it now by */
478*37da2899SCharles.Forsyth         /* setting all the separator characters to 0.               */
479*37da2899SCharles.Forsyth         for ( ; *ep && sbitset( seps, *ep ); ep++ )
480*37da2899SCharles.Forsyth           *ep = 0;
481*37da2899SCharles.Forsyth       }
482*37da2899SCharles.Forsyth       else if ( *ep != 0 )
483*37da2899SCharles.Forsyth         /* Don't collapse multiple separators by making them 0, so just */
484*37da2899SCharles.Forsyth         /* make the one encountered 0.                                  */
485*37da2899SCharles.Forsyth         *ep++ = 0;
486*37da2899SCharles.Forsyth 
487*37da2899SCharles.Forsyth       final_empty = ( ep > sp && *ep == 0 );
488*37da2899SCharles.Forsyth       sp = ep;
489*37da2899SCharles.Forsyth     }
490*37da2899SCharles.Forsyth 
491*37da2899SCharles.Forsyth     /* Finally, NULL-terminate the list. */
492*37da2899SCharles.Forsyth     if ( list->used + final_empty + 1 >= list->size )
493*37da2899SCharles.Forsyth     {
494*37da2899SCharles.Forsyth       if ( list->used == list->size )
495*37da2899SCharles.Forsyth       {
496*37da2899SCharles.Forsyth         if ( list->size == 0 )
497*37da2899SCharles.Forsyth         {
498*37da2899SCharles.Forsyth           if ( FT_NEW_ARRAY( list->field, 5 ) )
499*37da2899SCharles.Forsyth             goto Exit;
500*37da2899SCharles.Forsyth         }
501*37da2899SCharles.Forsyth         else
502*37da2899SCharles.Forsyth         {
503*37da2899SCharles.Forsyth           if ( FT_RENEW_ARRAY( list->field,
504*37da2899SCharles.Forsyth                                list->size,
505*37da2899SCharles.Forsyth                                list->size + 5 ) )
506*37da2899SCharles.Forsyth             goto Exit;
507*37da2899SCharles.Forsyth         }
508*37da2899SCharles.Forsyth 
509*37da2899SCharles.Forsyth         list->size += 5;
510*37da2899SCharles.Forsyth       }
511*37da2899SCharles.Forsyth     }
512*37da2899SCharles.Forsyth 
513*37da2899SCharles.Forsyth     if ( final_empty )
514*37da2899SCharles.Forsyth       list->field[list->used++] = empty;
515*37da2899SCharles.Forsyth 
516*37da2899SCharles.Forsyth     if ( list->used == list->size )
517*37da2899SCharles.Forsyth     {
518*37da2899SCharles.Forsyth       if ( list->size == 0 )
519*37da2899SCharles.Forsyth       {
520*37da2899SCharles.Forsyth         if ( FT_NEW_ARRAY( list->field, 5 ) )
521*37da2899SCharles.Forsyth           goto Exit;
522*37da2899SCharles.Forsyth       }
523*37da2899SCharles.Forsyth       else
524*37da2899SCharles.Forsyth       {
525*37da2899SCharles.Forsyth         if ( FT_RENEW_ARRAY( list->field,
526*37da2899SCharles.Forsyth                              list->size,
527*37da2899SCharles.Forsyth                              list->size + 5 ) )
528*37da2899SCharles.Forsyth           goto Exit;
529*37da2899SCharles.Forsyth       }
530*37da2899SCharles.Forsyth 
531*37da2899SCharles.Forsyth       list->size += 5;
532*37da2899SCharles.Forsyth     }
533*37da2899SCharles.Forsyth 
534*37da2899SCharles.Forsyth     list->field[list->used] = 0;
535*37da2899SCharles.Forsyth 
536*37da2899SCharles.Forsyth   Exit:
537*37da2899SCharles.Forsyth     return error;
538*37da2899SCharles.Forsyth   }
539*37da2899SCharles.Forsyth 
540*37da2899SCharles.Forsyth 
541*37da2899SCharles.Forsyth   static void
_bdf_shift(unsigned long n,_bdf_list_t * list)542*37da2899SCharles.Forsyth   _bdf_shift( unsigned long  n,
543*37da2899SCharles.Forsyth               _bdf_list_t*   list )
544*37da2899SCharles.Forsyth   {
545*37da2899SCharles.Forsyth     unsigned long  i, u;
546*37da2899SCharles.Forsyth 
547*37da2899SCharles.Forsyth 
548*37da2899SCharles.Forsyth     if ( list == 0 || list->used == 0 || n == 0 )
549*37da2899SCharles.Forsyth       return;
550*37da2899SCharles.Forsyth 
551*37da2899SCharles.Forsyth     if ( n >= list->used )
552*37da2899SCharles.Forsyth     {
553*37da2899SCharles.Forsyth       list->used = 0;
554*37da2899SCharles.Forsyth       return;
555*37da2899SCharles.Forsyth     }
556*37da2899SCharles.Forsyth 
557*37da2899SCharles.Forsyth     for ( u = n, i = 0; u < list->used; i++, u++ )
558*37da2899SCharles.Forsyth       list->field[i] = list->field[u];
559*37da2899SCharles.Forsyth     list->used -= n;
560*37da2899SCharles.Forsyth   }
561*37da2899SCharles.Forsyth 
562*37da2899SCharles.Forsyth 
563*37da2899SCharles.Forsyth   static char *
_bdf_join(int c,unsigned long * len,_bdf_list_t * list)564*37da2899SCharles.Forsyth   _bdf_join( int             c,
565*37da2899SCharles.Forsyth              unsigned long*  len,
566*37da2899SCharles.Forsyth              _bdf_list_t*    list )
567*37da2899SCharles.Forsyth   {
568*37da2899SCharles.Forsyth     unsigned long  i, j;
569*37da2899SCharles.Forsyth     char           *fp, *dp;
570*37da2899SCharles.Forsyth 
571*37da2899SCharles.Forsyth 
572*37da2899SCharles.Forsyth     if ( list == 0 || list->used == 0 )
573*37da2899SCharles.Forsyth       return 0;
574*37da2899SCharles.Forsyth 
575*37da2899SCharles.Forsyth     *len = 0;
576*37da2899SCharles.Forsyth 
577*37da2899SCharles.Forsyth     dp = list->field[0];
578*37da2899SCharles.Forsyth     for ( i = j = 0; i < list->used; i++ )
579*37da2899SCharles.Forsyth     {
580*37da2899SCharles.Forsyth       fp = list->field[i];
581*37da2899SCharles.Forsyth       while ( *fp )
582*37da2899SCharles.Forsyth         dp[j++] = *fp++;
583*37da2899SCharles.Forsyth 
584*37da2899SCharles.Forsyth       if ( i + 1 < list->used )
585*37da2899SCharles.Forsyth         dp[j++] = (char)c;
586*37da2899SCharles.Forsyth     }
587*37da2899SCharles.Forsyth     dp[j] = 0;
588*37da2899SCharles.Forsyth 
589*37da2899SCharles.Forsyth     *len = j;
590*37da2899SCharles.Forsyth     return dp;
591*37da2899SCharles.Forsyth   }
592*37da2899SCharles.Forsyth 
593*37da2899SCharles.Forsyth 
594*37da2899SCharles.Forsyth   /* High speed file reader that passes each line to a callback. */
595*37da2899SCharles.Forsyth   static FT_Error
bdf_internal_readstream(FT_Stream stream,char * buffer,int count,int * read_bytes)596*37da2899SCharles.Forsyth   bdf_internal_readstream( FT_Stream  stream,
597*37da2899SCharles.Forsyth                            char*      buffer,
598*37da2899SCharles.Forsyth                            int        count,
599*37da2899SCharles.Forsyth                            int       *read_bytes )
600*37da2899SCharles.Forsyth   {
601*37da2899SCharles.Forsyth     int            rbytes;
602*37da2899SCharles.Forsyth     unsigned long  pos   = stream->pos;
603*37da2899SCharles.Forsyth     FT_Error       error = BDF_Err_Ok;
604*37da2899SCharles.Forsyth 
605*37da2899SCharles.Forsyth 
606*37da2899SCharles.Forsyth     if ( pos > stream->size )
607*37da2899SCharles.Forsyth     {
608*37da2899SCharles.Forsyth       FT_ERROR(( "bdf_internal_readstream:" ));
609*37da2899SCharles.Forsyth       FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
610*37da2899SCharles.Forsyth                  pos, stream->size ));
611*37da2899SCharles.Forsyth       error = BDF_Err_Invalid_Stream_Operation;
612*37da2899SCharles.Forsyth       goto Exit;
613*37da2899SCharles.Forsyth     }
614*37da2899SCharles.Forsyth 
615*37da2899SCharles.Forsyth     if ( stream->read )
616*37da2899SCharles.Forsyth       rbytes = stream->read( stream, pos,
617*37da2899SCharles.Forsyth                              (unsigned char *)buffer, count );
618*37da2899SCharles.Forsyth     else
619*37da2899SCharles.Forsyth     {
620*37da2899SCharles.Forsyth       rbytes = stream->size - pos;
621*37da2899SCharles.Forsyth       if ( rbytes > count )
622*37da2899SCharles.Forsyth         rbytes = count;
623*37da2899SCharles.Forsyth 
624*37da2899SCharles.Forsyth       FT_MEM_COPY( buffer, stream->base + pos, rbytes );
625*37da2899SCharles.Forsyth     }
626*37da2899SCharles.Forsyth 
627*37da2899SCharles.Forsyth     stream->pos = pos + rbytes;
628*37da2899SCharles.Forsyth 
629*37da2899SCharles.Forsyth     *read_bytes = rbytes;
630*37da2899SCharles.Forsyth 
631*37da2899SCharles.Forsyth   Exit:
632*37da2899SCharles.Forsyth     return error;
633*37da2899SCharles.Forsyth   }
634*37da2899SCharles.Forsyth 
635*37da2899SCharles.Forsyth 
636*37da2899SCharles.Forsyth   static FT_Error
_bdf_readstream(FT_Stream stream,_bdf_line_func_t callback,void * client_data,unsigned long * lno)637*37da2899SCharles.Forsyth   _bdf_readstream( FT_Stream         stream,
638*37da2899SCharles.Forsyth                    _bdf_line_func_t  callback,
639*37da2899SCharles.Forsyth                    void*             client_data,
640*37da2899SCharles.Forsyth                    unsigned long    *lno )
641*37da2899SCharles.Forsyth   {
642*37da2899SCharles.Forsyth     _bdf_line_func_t  cb;
643*37da2899SCharles.Forsyth     unsigned long     lineno;
644*37da2899SCharles.Forsyth     int               n, res, done, refill, bytes, hold;
645*37da2899SCharles.Forsyth     char              *ls, *le, *pp, *pe, *hp;
646*37da2899SCharles.Forsyth     char              *buf = 0;
647*37da2899SCharles.Forsyth     FT_Memory         memory = stream->memory;
648*37da2899SCharles.Forsyth     FT_Error          error = BDF_Err_Ok;
649*37da2899SCharles.Forsyth 
650*37da2899SCharles.Forsyth 
651*37da2899SCharles.Forsyth     if ( callback == 0 )
652*37da2899SCharles.Forsyth     {
653*37da2899SCharles.Forsyth       error = BDF_Err_Invalid_Argument;
654*37da2899SCharles.Forsyth       goto Exit;
655*37da2899SCharles.Forsyth     }
656*37da2899SCharles.Forsyth 
657*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( buf, 65536L ) )
658*37da2899SCharles.Forsyth       goto Exit;
659*37da2899SCharles.Forsyth 
660*37da2899SCharles.Forsyth     cb     = callback;
661*37da2899SCharles.Forsyth     lineno = 1;
662*37da2899SCharles.Forsyth     buf[0] = 0;
663*37da2899SCharles.Forsyth 
664*37da2899SCharles.Forsyth     res = done = 0;
665*37da2899SCharles.Forsyth     pp = ls = le = buf;
666*37da2899SCharles.Forsyth 
667*37da2899SCharles.Forsyth     bytes = 65536L;
668*37da2899SCharles.Forsyth 
669*37da2899SCharles.Forsyth     while ( !done )
670*37da2899SCharles.Forsyth     {
671*37da2899SCharles.Forsyth       error = bdf_internal_readstream( stream, pp, bytes, &n );
672*37da2899SCharles.Forsyth       if ( error )
673*37da2899SCharles.Forsyth         goto Exit;
674*37da2899SCharles.Forsyth 
675*37da2899SCharles.Forsyth       if ( n == 0 )
676*37da2899SCharles.Forsyth         break;
677*37da2899SCharles.Forsyth 
678*37da2899SCharles.Forsyth       /* Determine the new end of the buffer pages. */
679*37da2899SCharles.Forsyth       pe = pp + n;
680*37da2899SCharles.Forsyth 
681*37da2899SCharles.Forsyth       for ( refill = 0; done == 0 && refill == 0; )
682*37da2899SCharles.Forsyth       {
683*37da2899SCharles.Forsyth         while ( le < pe && *le != '\n' && *le != '\r' )
684*37da2899SCharles.Forsyth           le++;
685*37da2899SCharles.Forsyth 
686*37da2899SCharles.Forsyth         if ( le == pe )
687*37da2899SCharles.Forsyth         {
688*37da2899SCharles.Forsyth           /* Hit the end of the last page in the buffer.  Need to find */
689*37da2899SCharles.Forsyth           /* out how many pages to shift and how many pages need to be */
690*37da2899SCharles.Forsyth           /* read in.  Adjust the line start and end pointers down to  */
691*37da2899SCharles.Forsyth           /* point to the right places in the pages.                   */
692*37da2899SCharles.Forsyth 
693*37da2899SCharles.Forsyth           pp  = buf + ( ( ( ls - buf ) >> 13 ) << 13 );
694*37da2899SCharles.Forsyth           n   = pp - buf;
695*37da2899SCharles.Forsyth           ls -= n;
696*37da2899SCharles.Forsyth           le -= n;
697*37da2899SCharles.Forsyth           n   = pe - pp;
698*37da2899SCharles.Forsyth 
699*37da2899SCharles.Forsyth           FT_MEM_COPY( buf, pp, n );
700*37da2899SCharles.Forsyth 
701*37da2899SCharles.Forsyth           pp     = buf + n;
702*37da2899SCharles.Forsyth           bytes  = 65536L - n;
703*37da2899SCharles.Forsyth           refill = 1;
704*37da2899SCharles.Forsyth         }
705*37da2899SCharles.Forsyth         else
706*37da2899SCharles.Forsyth         {
707*37da2899SCharles.Forsyth           /* Temporarily NULL-terminate the line. */
708*37da2899SCharles.Forsyth           hp   = le;
709*37da2899SCharles.Forsyth           hold = *le;
710*37da2899SCharles.Forsyth           *le  = 0;
711*37da2899SCharles.Forsyth 
712*37da2899SCharles.Forsyth           /* XXX: Use encoding independent value for 0x1a */
713*37da2899SCharles.Forsyth           if ( *ls != '#' && *ls != 0x1a                          &&
714*37da2899SCharles.Forsyth                le > ls                                            &&
715*37da2899SCharles.Forsyth                ( error = (*cb)( ls, le - ls, lineno, (void *)&cb,
716*37da2899SCharles.Forsyth                                 client_data ) ) != BDF_Err_Ok     )
717*37da2899SCharles.Forsyth             done = 1;
718*37da2899SCharles.Forsyth           else
719*37da2899SCharles.Forsyth           {
720*37da2899SCharles.Forsyth             ls = ++le;
721*37da2899SCharles.Forsyth             /* Handle the case of DOS crlf sequences. */
722*37da2899SCharles.Forsyth             if ( le < pe && hold == '\n' && *le =='\r' )
723*37da2899SCharles.Forsyth               ls = ++le;
724*37da2899SCharles.Forsyth           }
725*37da2899SCharles.Forsyth 
726*37da2899SCharles.Forsyth           /* Increment the line number. */
727*37da2899SCharles.Forsyth           lineno++;
728*37da2899SCharles.Forsyth 
729*37da2899SCharles.Forsyth           /* Restore the character at the end of the line. */
730*37da2899SCharles.Forsyth           *hp = (char)hold;
731*37da2899SCharles.Forsyth         }
732*37da2899SCharles.Forsyth       }
733*37da2899SCharles.Forsyth     }
734*37da2899SCharles.Forsyth 
735*37da2899SCharles.Forsyth     *lno             = lineno;
736*37da2899SCharles.Forsyth 
737*37da2899SCharles.Forsyth   Exit:
738*37da2899SCharles.Forsyth     FT_FREE( buf );
739*37da2899SCharles.Forsyth     return error;
740*37da2899SCharles.Forsyth   }
741*37da2899SCharles.Forsyth 
742*37da2899SCharles.Forsyth 
743*37da2899SCharles.Forsyth   /* XXX: make this work with EBCDIC also */
744*37da2899SCharles.Forsyth 
745*37da2899SCharles.Forsyth   static const unsigned char  a2i[128] =
746*37da2899SCharles.Forsyth   {
747*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
748*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
750*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
751*37da2899SCharles.Forsyth     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
752*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
753*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
754*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
755*37da2899SCharles.Forsyth     0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
756*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
758*37da2899SCharles.Forsyth   };
759*37da2899SCharles.Forsyth 
760*37da2899SCharles.Forsyth   static const unsigned char  odigits[32] =
761*37da2899SCharles.Forsyth   {
762*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
763*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766*37da2899SCharles.Forsyth   };
767*37da2899SCharles.Forsyth 
768*37da2899SCharles.Forsyth   static const unsigned char  ddigits[32] =
769*37da2899SCharles.Forsyth   {
770*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
771*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774*37da2899SCharles.Forsyth   };
775*37da2899SCharles.Forsyth 
776*37da2899SCharles.Forsyth   static const unsigned char  hdigits[32] =
777*37da2899SCharles.Forsyth   {
778*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
779*37da2899SCharles.Forsyth     0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
780*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
781*37da2899SCharles.Forsyth     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
782*37da2899SCharles.Forsyth   };
783*37da2899SCharles.Forsyth 
784*37da2899SCharles.Forsyth 
785*37da2899SCharles.Forsyth #define isdigok( m, d )  (m[(d) >> 3] & ( 1 << ( (d) & 7 ) ) )
786*37da2899SCharles.Forsyth 
787*37da2899SCharles.Forsyth 
788*37da2899SCharles.Forsyth   /* Routine to convert an ASCII string into an unsigned long integer. */
789*37da2899SCharles.Forsyth   static unsigned long
_bdf_atoul(char * s,char ** end,int base)790*37da2899SCharles.Forsyth   _bdf_atoul( char*   s,
791*37da2899SCharles.Forsyth               char**  end,
792*37da2899SCharles.Forsyth               int     base )
793*37da2899SCharles.Forsyth   {
794*37da2899SCharles.Forsyth     unsigned long         v;
795*37da2899SCharles.Forsyth     const unsigned char*  dmap;
796*37da2899SCharles.Forsyth 
797*37da2899SCharles.Forsyth 
798*37da2899SCharles.Forsyth     if ( s == 0 || *s == 0 )
799*37da2899SCharles.Forsyth       return 0;
800*37da2899SCharles.Forsyth 
801*37da2899SCharles.Forsyth     /* Make sure the radix is something recognizable.  Default to 10. */
802*37da2899SCharles.Forsyth     switch ( base )
803*37da2899SCharles.Forsyth     {
804*37da2899SCharles.Forsyth     case 8:
805*37da2899SCharles.Forsyth       dmap = odigits;
806*37da2899SCharles.Forsyth       break;
807*37da2899SCharles.Forsyth     case 16:
808*37da2899SCharles.Forsyth       dmap = hdigits;
809*37da2899SCharles.Forsyth       break;
810*37da2899SCharles.Forsyth     default:
811*37da2899SCharles.Forsyth       base = 10;
812*37da2899SCharles.Forsyth       dmap = ddigits;
813*37da2899SCharles.Forsyth       break;
814*37da2899SCharles.Forsyth     }
815*37da2899SCharles.Forsyth 
816*37da2899SCharles.Forsyth     /* Check for the special hex prefix. */
817*37da2899SCharles.Forsyth     if ( *s == '0'                                  &&
818*37da2899SCharles.Forsyth          ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
819*37da2899SCharles.Forsyth     {
820*37da2899SCharles.Forsyth       base = 16;
821*37da2899SCharles.Forsyth       dmap = hdigits;
822*37da2899SCharles.Forsyth       s   += 2;
823*37da2899SCharles.Forsyth     }
824*37da2899SCharles.Forsyth 
825*37da2899SCharles.Forsyth     for ( v = 0; isdigok( dmap, *s ); s++ )
826*37da2899SCharles.Forsyth       v = v * base + a2i[(int)*s];
827*37da2899SCharles.Forsyth 
828*37da2899SCharles.Forsyth     if ( end != 0 )
829*37da2899SCharles.Forsyth       *end = s;
830*37da2899SCharles.Forsyth 
831*37da2899SCharles.Forsyth     return v;
832*37da2899SCharles.Forsyth   }
833*37da2899SCharles.Forsyth 
834*37da2899SCharles.Forsyth 
835*37da2899SCharles.Forsyth   /* Routine to convert an ASCII string into an signed long integer. */
836*37da2899SCharles.Forsyth   static long
_bdf_atol(char * s,char ** end,int base)837*37da2899SCharles.Forsyth   _bdf_atol( char*   s,
838*37da2899SCharles.Forsyth              char**  end,
839*37da2899SCharles.Forsyth              int     base )
840*37da2899SCharles.Forsyth   {
841*37da2899SCharles.Forsyth     long                  v, neg;
842*37da2899SCharles.Forsyth     const unsigned char*  dmap;
843*37da2899SCharles.Forsyth 
844*37da2899SCharles.Forsyth 
845*37da2899SCharles.Forsyth     if ( s == 0 || *s == 0 )
846*37da2899SCharles.Forsyth       return 0;
847*37da2899SCharles.Forsyth 
848*37da2899SCharles.Forsyth     /* Make sure the radix is something recognizable.  Default to 10. */
849*37da2899SCharles.Forsyth     switch ( base )
850*37da2899SCharles.Forsyth     {
851*37da2899SCharles.Forsyth     case 8:
852*37da2899SCharles.Forsyth       dmap = odigits;
853*37da2899SCharles.Forsyth       break;
854*37da2899SCharles.Forsyth     case 16:
855*37da2899SCharles.Forsyth       dmap = hdigits;
856*37da2899SCharles.Forsyth       break;
857*37da2899SCharles.Forsyth     default:
858*37da2899SCharles.Forsyth       base = 10;
859*37da2899SCharles.Forsyth       dmap = ddigits;
860*37da2899SCharles.Forsyth       break;
861*37da2899SCharles.Forsyth     }
862*37da2899SCharles.Forsyth 
863*37da2899SCharles.Forsyth     /* Check for a minus sign. */
864*37da2899SCharles.Forsyth     neg = 0;
865*37da2899SCharles.Forsyth     if ( *s == '-' )
866*37da2899SCharles.Forsyth     {
867*37da2899SCharles.Forsyth       s++;
868*37da2899SCharles.Forsyth       neg = 1;
869*37da2899SCharles.Forsyth     }
870*37da2899SCharles.Forsyth 
871*37da2899SCharles.Forsyth     /* Check for the special hex prefix. */
872*37da2899SCharles.Forsyth     if ( *s == '0'                                  &&
873*37da2899SCharles.Forsyth          ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
874*37da2899SCharles.Forsyth     {
875*37da2899SCharles.Forsyth       base = 16;
876*37da2899SCharles.Forsyth       dmap = hdigits;
877*37da2899SCharles.Forsyth       s   += 2;
878*37da2899SCharles.Forsyth     }
879*37da2899SCharles.Forsyth 
880*37da2899SCharles.Forsyth     for ( v = 0; isdigok( dmap, *s ); s++ )
881*37da2899SCharles.Forsyth       v = v * base + a2i[(int)*s];
882*37da2899SCharles.Forsyth 
883*37da2899SCharles.Forsyth     if ( end != 0 )
884*37da2899SCharles.Forsyth       *end = s;
885*37da2899SCharles.Forsyth 
886*37da2899SCharles.Forsyth     return ( !neg ) ? v : -v;
887*37da2899SCharles.Forsyth   }
888*37da2899SCharles.Forsyth 
889*37da2899SCharles.Forsyth 
890*37da2899SCharles.Forsyth   /* Routine to convert an ASCII string into an signed short integer. */
891*37da2899SCharles.Forsyth   static short
_bdf_atos(char * s,char ** end,int base)892*37da2899SCharles.Forsyth   _bdf_atos( char*   s,
893*37da2899SCharles.Forsyth              char**  end,
894*37da2899SCharles.Forsyth              int     base )
895*37da2899SCharles.Forsyth   {
896*37da2899SCharles.Forsyth     short                 v, neg;
897*37da2899SCharles.Forsyth     const unsigned char*  dmap;
898*37da2899SCharles.Forsyth 
899*37da2899SCharles.Forsyth 
900*37da2899SCharles.Forsyth     if ( s == 0 || *s == 0 )
901*37da2899SCharles.Forsyth       return 0;
902*37da2899SCharles.Forsyth 
903*37da2899SCharles.Forsyth     /* Make sure the radix is something recognizable.  Default to 10. */
904*37da2899SCharles.Forsyth     switch ( base )
905*37da2899SCharles.Forsyth     {
906*37da2899SCharles.Forsyth     case 8:
907*37da2899SCharles.Forsyth       dmap = odigits;
908*37da2899SCharles.Forsyth       break;
909*37da2899SCharles.Forsyth     case 16:
910*37da2899SCharles.Forsyth       dmap = hdigits;
911*37da2899SCharles.Forsyth       break;
912*37da2899SCharles.Forsyth     default:
913*37da2899SCharles.Forsyth       base = 10;
914*37da2899SCharles.Forsyth       dmap = ddigits;
915*37da2899SCharles.Forsyth       break;
916*37da2899SCharles.Forsyth     }
917*37da2899SCharles.Forsyth 
918*37da2899SCharles.Forsyth     /* Check for a minus. */
919*37da2899SCharles.Forsyth     neg = 0;
920*37da2899SCharles.Forsyth     if ( *s == '-' )
921*37da2899SCharles.Forsyth     {
922*37da2899SCharles.Forsyth       s++;
923*37da2899SCharles.Forsyth       neg = 1;
924*37da2899SCharles.Forsyth     }
925*37da2899SCharles.Forsyth 
926*37da2899SCharles.Forsyth     /* Check for the special hex prefix. */
927*37da2899SCharles.Forsyth     if ( *s == '0'                                  &&
928*37da2899SCharles.Forsyth          ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
929*37da2899SCharles.Forsyth     {
930*37da2899SCharles.Forsyth       base = 16;
931*37da2899SCharles.Forsyth       dmap = hdigits;
932*37da2899SCharles.Forsyth       s   += 2;
933*37da2899SCharles.Forsyth     }
934*37da2899SCharles.Forsyth 
935*37da2899SCharles.Forsyth     for ( v = 0; isdigok( dmap, *s ); s++ )
936*37da2899SCharles.Forsyth       v = (short)( v * base + a2i[(int)*s] );
937*37da2899SCharles.Forsyth 
938*37da2899SCharles.Forsyth     if ( end != 0 )
939*37da2899SCharles.Forsyth       *end = s;
940*37da2899SCharles.Forsyth 
941*37da2899SCharles.Forsyth     return (short)( ( !neg ) ? v : -v );
942*37da2899SCharles.Forsyth   }
943*37da2899SCharles.Forsyth 
944*37da2899SCharles.Forsyth 
945*37da2899SCharles.Forsyth   /* Routine to compare two glyphs by encoding so they can be sorted. */
946*37da2899SCharles.Forsyth   static int
by_encoding(const void * a,const void * b)947*37da2899SCharles.Forsyth   by_encoding( const void*  a,
948*37da2899SCharles.Forsyth                const void*  b )
949*37da2899SCharles.Forsyth   {
950*37da2899SCharles.Forsyth     bdf_glyph_t  *c1, *c2;
951*37da2899SCharles.Forsyth 
952*37da2899SCharles.Forsyth 
953*37da2899SCharles.Forsyth     c1 = (bdf_glyph_t *)a;
954*37da2899SCharles.Forsyth     c2 = (bdf_glyph_t *)b;
955*37da2899SCharles.Forsyth 
956*37da2899SCharles.Forsyth     if ( c1->encoding < c2->encoding )
957*37da2899SCharles.Forsyth       return -1;
958*37da2899SCharles.Forsyth     else if ( c1->encoding > c2->encoding )
959*37da2899SCharles.Forsyth       return 1;
960*37da2899SCharles.Forsyth 
961*37da2899SCharles.Forsyth     return 0;
962*37da2899SCharles.Forsyth   }
963*37da2899SCharles.Forsyth 
964*37da2899SCharles.Forsyth 
965*37da2899SCharles.Forsyth   static FT_Error
bdf_create_property(char * name,int format,bdf_font_t * font)966*37da2899SCharles.Forsyth   bdf_create_property( char*        name,
967*37da2899SCharles.Forsyth                        int          format,
968*37da2899SCharles.Forsyth                        bdf_font_t*  font )
969*37da2899SCharles.Forsyth   {
970*37da2899SCharles.Forsyth     unsigned long    n;
971*37da2899SCharles.Forsyth     bdf_property_t*  p;
972*37da2899SCharles.Forsyth     FT_Memory        memory = font->memory;
973*37da2899SCharles.Forsyth     FT_Error         error = BDF_Err_Ok;
974*37da2899SCharles.Forsyth 
975*37da2899SCharles.Forsyth 
976*37da2899SCharles.Forsyth     /* First check to see if the property has      */
977*37da2899SCharles.Forsyth     /* already been added or not.  If it has, then */
978*37da2899SCharles.Forsyth     /* simply ignore it.                           */
979*37da2899SCharles.Forsyth     if ( hash_lookup( name, &(font->proptbl) ) )
980*37da2899SCharles.Forsyth       goto Exit;
981*37da2899SCharles.Forsyth 
982*37da2899SCharles.Forsyth     if ( font->nuser_props == 0 )
983*37da2899SCharles.Forsyth     {
984*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( font->user_props, 1 ) )
985*37da2899SCharles.Forsyth         goto Exit;
986*37da2899SCharles.Forsyth     }
987*37da2899SCharles.Forsyth     else
988*37da2899SCharles.Forsyth     {
989*37da2899SCharles.Forsyth       if ( FT_RENEW_ARRAY( font->user_props,
990*37da2899SCharles.Forsyth                            font->nuser_props,
991*37da2899SCharles.Forsyth                            font->nuser_props + 1 ) )
992*37da2899SCharles.Forsyth         goto Exit;
993*37da2899SCharles.Forsyth     }
994*37da2899SCharles.Forsyth 
995*37da2899SCharles.Forsyth     p = font->user_props + font->nuser_props;
996*37da2899SCharles.Forsyth     FT_MEM_ZERO( p, sizeof ( bdf_property_t ) );
997*37da2899SCharles.Forsyth 
998*37da2899SCharles.Forsyth     n = (unsigned long)( ft_strlen( name ) + 1 );
999*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( p->name, n ) )
1000*37da2899SCharles.Forsyth       goto Exit;
1001*37da2899SCharles.Forsyth 
1002*37da2899SCharles.Forsyth     FT_MEM_COPY( (char *)p->name, name, n );
1003*37da2899SCharles.Forsyth 
1004*37da2899SCharles.Forsyth     p->format  = format;
1005*37da2899SCharles.Forsyth     p->builtin = 0;
1006*37da2899SCharles.Forsyth 
1007*37da2899SCharles.Forsyth     n = _num_bdf_properties + font->nuser_props;
1008*37da2899SCharles.Forsyth 
1009*37da2899SCharles.Forsyth     error = hash_insert( p->name, (void *)n, &(font->proptbl), memory );
1010*37da2899SCharles.Forsyth     if ( error )
1011*37da2899SCharles.Forsyth       goto Exit;
1012*37da2899SCharles.Forsyth 
1013*37da2899SCharles.Forsyth     font->nuser_props++;
1014*37da2899SCharles.Forsyth 
1015*37da2899SCharles.Forsyth   Exit:
1016*37da2899SCharles.Forsyth     return error;
1017*37da2899SCharles.Forsyth   }
1018*37da2899SCharles.Forsyth 
1019*37da2899SCharles.Forsyth 
1020*37da2899SCharles.Forsyth   FT_LOCAL_DEF( bdf_property_t * )
bdf_get_property(char * name,bdf_font_t * font)1021*37da2899SCharles.Forsyth   bdf_get_property( char*        name,
1022*37da2899SCharles.Forsyth                     bdf_font_t*  font )
1023*37da2899SCharles.Forsyth   {
1024*37da2899SCharles.Forsyth     hashnode       hn;
1025*37da2899SCharles.Forsyth     unsigned long  propid;
1026*37da2899SCharles.Forsyth 
1027*37da2899SCharles.Forsyth 
1028*37da2899SCharles.Forsyth     if ( name == 0 || *name == 0 )
1029*37da2899SCharles.Forsyth       return 0;
1030*37da2899SCharles.Forsyth 
1031*37da2899SCharles.Forsyth     if ( ( hn = hash_lookup( name, &(font->proptbl) ) ) == 0 )
1032*37da2899SCharles.Forsyth       return 0;
1033*37da2899SCharles.Forsyth 
1034*37da2899SCharles.Forsyth     propid = (unsigned long)hn->data;
1035*37da2899SCharles.Forsyth     if ( propid >= _num_bdf_properties )
1036*37da2899SCharles.Forsyth       return font->user_props + ( propid - _num_bdf_properties );
1037*37da2899SCharles.Forsyth 
1038*37da2899SCharles.Forsyth     return (bdf_property_t*)_bdf_properties + propid;
1039*37da2899SCharles.Forsyth   }
1040*37da2899SCharles.Forsyth 
1041*37da2899SCharles.Forsyth 
1042*37da2899SCharles.Forsyth   /*************************************************************************/
1043*37da2899SCharles.Forsyth   /*                                                                       */
1044*37da2899SCharles.Forsyth   /* BDF font file parsing flags and functions.                            */
1045*37da2899SCharles.Forsyth   /*                                                                       */
1046*37da2899SCharles.Forsyth   /*************************************************************************/
1047*37da2899SCharles.Forsyth 
1048*37da2899SCharles.Forsyth 
1049*37da2899SCharles.Forsyth   /* Parse flags. */
1050*37da2899SCharles.Forsyth 
1051*37da2899SCharles.Forsyth #define _BDF_START      0x0001
1052*37da2899SCharles.Forsyth #define _BDF_FONT_NAME  0x0002
1053*37da2899SCharles.Forsyth #define _BDF_SIZE       0x0004
1054*37da2899SCharles.Forsyth #define _BDF_FONT_BBX   0x0008
1055*37da2899SCharles.Forsyth #define _BDF_PROPS      0x0010
1056*37da2899SCharles.Forsyth #define _BDF_GLYPHS     0x0020
1057*37da2899SCharles.Forsyth #define _BDF_GLYPH      0x0040
1058*37da2899SCharles.Forsyth #define _BDF_ENCODING   0x0080
1059*37da2899SCharles.Forsyth #define _BDF_SWIDTH     0x0100
1060*37da2899SCharles.Forsyth #define _BDF_DWIDTH     0x0200
1061*37da2899SCharles.Forsyth #define _BDF_BBX        0x0400
1062*37da2899SCharles.Forsyth #define _BDF_BITMAP     0x0800
1063*37da2899SCharles.Forsyth 
1064*37da2899SCharles.Forsyth #define _BDF_SWIDTH_ADJ  0x1000
1065*37da2899SCharles.Forsyth 
1066*37da2899SCharles.Forsyth #define _BDF_GLYPH_BITS ( _BDF_GLYPH    | \
1067*37da2899SCharles.Forsyth                           _BDF_ENCODING | \
1068*37da2899SCharles.Forsyth                           _BDF_SWIDTH   | \
1069*37da2899SCharles.Forsyth                           _BDF_DWIDTH   | \
1070*37da2899SCharles.Forsyth                           _BDF_BBX      | \
1071*37da2899SCharles.Forsyth                           _BDF_BITMAP   )
1072*37da2899SCharles.Forsyth 
1073*37da2899SCharles.Forsyth #define _BDF_GLYPH_WIDTH_CHECK   0x40000000L
1074*37da2899SCharles.Forsyth #define _BDF_GLYPH_HEIGHT_CHECK  0x80000000L
1075*37da2899SCharles.Forsyth 
1076*37da2899SCharles.Forsyth 
1077*37da2899SCharles.Forsyth   /* Auto correction messages. */
1078*37da2899SCharles.Forsyth #define ACMSG1   "FONT_ASCENT property missing.  " \
1079*37da2899SCharles.Forsyth                  "Added \"FONT_ASCENT %hd\".\n"
1080*37da2899SCharles.Forsyth #define ACMSG2   "FONT_DESCENT property missing.  " \
1081*37da2899SCharles.Forsyth                  "Added \"FONT_DESCENT %hd\".\n"
1082*37da2899SCharles.Forsyth #define ACMSG3   "Font width != actual width.  Old: %hd New: %hd.\n"
1083*37da2899SCharles.Forsyth #define ACMSG4   "Font left bearing != actual left bearing.  " \
1084*37da2899SCharles.Forsyth                  "Old: %hd New: %hd.\n"
1085*37da2899SCharles.Forsyth #define ACMSG5   "Font ascent != actual ascent.  Old: %hd New: %hd.\n"
1086*37da2899SCharles.Forsyth #define ACMSG6   "Font descent != actual descent.  Old: %hd New: %hd.\n"
1087*37da2899SCharles.Forsyth #define ACMSG7   "Font height != actual height. Old: %hd New: %hd.\n"
1088*37da2899SCharles.Forsyth #define ACMSG8   "Glyph scalable width (SWIDTH) adjustments made.\n"
1089*37da2899SCharles.Forsyth #define ACMSG9   "SWIDTH field missing at line %ld.  Set automatically.\n"
1090*37da2899SCharles.Forsyth #define ACMSG10  "DWIDTH field missing at line %ld.  Set to glyph width.\n"
1091*37da2899SCharles.Forsyth #define ACMSG11  "SIZE bits per pixel field adjusted to %hd.\n"
1092*37da2899SCharles.Forsyth #define ACMSG12  "Duplicate encoding %ld (%s) changed to unencoded.\n"
1093*37da2899SCharles.Forsyth #define ACMSG13  "Glyph %ld extra rows removed.\n"
1094*37da2899SCharles.Forsyth #define ACMSG14  "Glyph %ld extra columns removed.\n"
1095*37da2899SCharles.Forsyth #define ACMSG15  "Incorrect glyph count: %ld indicated but %ld found.\n"
1096*37da2899SCharles.Forsyth 
1097*37da2899SCharles.Forsyth   /* Error messages. */
1098*37da2899SCharles.Forsyth #define ERRMSG1  "[line %ld] Missing \"%s\" line.\n"
1099*37da2899SCharles.Forsyth #define ERRMSG2  "[line %ld] Font header corrupted or missing fields.\n"
1100*37da2899SCharles.Forsyth #define ERRMSG3  "[line %ld] Font glyphs corrupted or missing fields.\n"
1101*37da2899SCharles.Forsyth 
1102*37da2899SCharles.Forsyth 
1103*37da2899SCharles.Forsyth   static FT_Error
_bdf_add_comment(bdf_font_t * font,char * comment,unsigned long len)1104*37da2899SCharles.Forsyth   _bdf_add_comment( bdf_font_t*    font,
1105*37da2899SCharles.Forsyth                     char*          comment,
1106*37da2899SCharles.Forsyth                     unsigned long  len )
1107*37da2899SCharles.Forsyth   {
1108*37da2899SCharles.Forsyth     char*      cp;
1109*37da2899SCharles.Forsyth     FT_Memory  memory = font->memory;
1110*37da2899SCharles.Forsyth     FT_Error   error = BDF_Err_Ok;
1111*37da2899SCharles.Forsyth 
1112*37da2899SCharles.Forsyth 
1113*37da2899SCharles.Forsyth     if ( font->comments_len == 0 )
1114*37da2899SCharles.Forsyth     {
1115*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( font->comments, len + 1 ) )
1116*37da2899SCharles.Forsyth         goto Exit;
1117*37da2899SCharles.Forsyth     }
1118*37da2899SCharles.Forsyth     else
1119*37da2899SCharles.Forsyth     {
1120*37da2899SCharles.Forsyth       if ( FT_RENEW_ARRAY( font->comments,
1121*37da2899SCharles.Forsyth                            font->comments_len,
1122*37da2899SCharles.Forsyth                            font->comments_len + len + 1 ) )
1123*37da2899SCharles.Forsyth         goto Exit;
1124*37da2899SCharles.Forsyth     }
1125*37da2899SCharles.Forsyth 
1126*37da2899SCharles.Forsyth     cp = font->comments + font->comments_len;
1127*37da2899SCharles.Forsyth     FT_MEM_COPY( cp, comment, len );
1128*37da2899SCharles.Forsyth     cp   += len;
1129*37da2899SCharles.Forsyth     *cp++ = '\n';
1130*37da2899SCharles.Forsyth     font->comments_len += len + 1;
1131*37da2899SCharles.Forsyth 
1132*37da2899SCharles.Forsyth   Exit:
1133*37da2899SCharles.Forsyth     return error;
1134*37da2899SCharles.Forsyth   }
1135*37da2899SCharles.Forsyth 
1136*37da2899SCharles.Forsyth 
1137*37da2899SCharles.Forsyth   /* Set the spacing from the font name if it exists, or set it to the */
1138*37da2899SCharles.Forsyth   /* default specified in the options.                                 */
1139*37da2899SCharles.Forsyth   static FT_Error
_bdf_set_default_spacing(bdf_font_t * font,bdf_options_t * opts)1140*37da2899SCharles.Forsyth   _bdf_set_default_spacing( bdf_font_t*     font,
1141*37da2899SCharles.Forsyth                             bdf_options_t*  opts )
1142*37da2899SCharles.Forsyth   {
1143*37da2899SCharles.Forsyth     unsigned long  len;
1144*37da2899SCharles.Forsyth     char           name[128];
1145*37da2899SCharles.Forsyth     _bdf_list_t    list;
1146*37da2899SCharles.Forsyth     FT_Memory      memory;
1147*37da2899SCharles.Forsyth     FT_Error       error = BDF_Err_Ok;
1148*37da2899SCharles.Forsyth 
1149*37da2899SCharles.Forsyth 
1150*37da2899SCharles.Forsyth     if ( font == 0 || font->name == 0 || font->name[0] == 0 )
1151*37da2899SCharles.Forsyth     {
1152*37da2899SCharles.Forsyth       error = BDF_Err_Invalid_Argument;
1153*37da2899SCharles.Forsyth       goto Exit;
1154*37da2899SCharles.Forsyth     }
1155*37da2899SCharles.Forsyth 
1156*37da2899SCharles.Forsyth     memory = font->memory;
1157*37da2899SCharles.Forsyth 
1158*37da2899SCharles.Forsyth     font->spacing = opts->font_spacing;
1159*37da2899SCharles.Forsyth 
1160*37da2899SCharles.Forsyth     len = (unsigned long)( ft_strlen( font->name ) + 1 );
1161*37da2899SCharles.Forsyth     FT_MEM_COPY( name, font->name, len );
1162*37da2899SCharles.Forsyth 
1163*37da2899SCharles.Forsyth     list.size = list.used = 0;
1164*37da2899SCharles.Forsyth 
1165*37da2899SCharles.Forsyth     error = _bdf_split( (char *)"-", name, len, &list, memory );
1166*37da2899SCharles.Forsyth     if ( error )
1167*37da2899SCharles.Forsyth       goto Exit;
1168*37da2899SCharles.Forsyth 
1169*37da2899SCharles.Forsyth     if ( list.used == 15 )
1170*37da2899SCharles.Forsyth     {
1171*37da2899SCharles.Forsyth       switch ( list.field[11][0] )
1172*37da2899SCharles.Forsyth       {
1173*37da2899SCharles.Forsyth       case 'C':
1174*37da2899SCharles.Forsyth       case 'c':
1175*37da2899SCharles.Forsyth         font->spacing = BDF_CHARCELL;
1176*37da2899SCharles.Forsyth         break;
1177*37da2899SCharles.Forsyth       case 'M':
1178*37da2899SCharles.Forsyth       case 'm':
1179*37da2899SCharles.Forsyth         font->spacing = BDF_MONOWIDTH;
1180*37da2899SCharles.Forsyth         break;
1181*37da2899SCharles.Forsyth       case 'P':
1182*37da2899SCharles.Forsyth       case 'p':
1183*37da2899SCharles.Forsyth         font->spacing = BDF_PROPORTIONAL;
1184*37da2899SCharles.Forsyth         break;
1185*37da2899SCharles.Forsyth       }
1186*37da2899SCharles.Forsyth     }
1187*37da2899SCharles.Forsyth 
1188*37da2899SCharles.Forsyth     FT_FREE( list.field );
1189*37da2899SCharles.Forsyth 
1190*37da2899SCharles.Forsyth   Exit:
1191*37da2899SCharles.Forsyth     return error;
1192*37da2899SCharles.Forsyth   }
1193*37da2899SCharles.Forsyth 
1194*37da2899SCharles.Forsyth 
1195*37da2899SCharles.Forsyth   /* Determine whether the property is an atom or not.  If it is, then */
1196*37da2899SCharles.Forsyth   /* clean it up so the double quotes are removed if they exist.       */
1197*37da2899SCharles.Forsyth   static int
_bdf_is_atom(char * line,unsigned long linelen,char ** name,char ** value,bdf_font_t * font)1198*37da2899SCharles.Forsyth   _bdf_is_atom( char*          line,
1199*37da2899SCharles.Forsyth                 unsigned long  linelen,
1200*37da2899SCharles.Forsyth                 char**         name,
1201*37da2899SCharles.Forsyth                 char**         value,
1202*37da2899SCharles.Forsyth                 bdf_font_t*    font )
1203*37da2899SCharles.Forsyth   {
1204*37da2899SCharles.Forsyth     int              hold;
1205*37da2899SCharles.Forsyth     char             *sp, *ep;
1206*37da2899SCharles.Forsyth     bdf_property_t*  p;
1207*37da2899SCharles.Forsyth 
1208*37da2899SCharles.Forsyth 
1209*37da2899SCharles.Forsyth     *name = sp = ep = line;
1210*37da2899SCharles.Forsyth 
1211*37da2899SCharles.Forsyth     while ( *ep && *ep != ' ' && *ep != '\t' )
1212*37da2899SCharles.Forsyth       ep++;
1213*37da2899SCharles.Forsyth 
1214*37da2899SCharles.Forsyth     hold = -1;
1215*37da2899SCharles.Forsyth     if ( *ep )
1216*37da2899SCharles.Forsyth     {
1217*37da2899SCharles.Forsyth       hold = *ep;
1218*37da2899SCharles.Forsyth       *ep  = 0;
1219*37da2899SCharles.Forsyth     }
1220*37da2899SCharles.Forsyth 
1221*37da2899SCharles.Forsyth     p = bdf_get_property( sp, font );
1222*37da2899SCharles.Forsyth 
1223*37da2899SCharles.Forsyth     /* Restore the character that was saved before any return can happen. */
1224*37da2899SCharles.Forsyth     if ( hold != -1 )
1225*37da2899SCharles.Forsyth       *ep = (char)hold;
1226*37da2899SCharles.Forsyth 
1227*37da2899SCharles.Forsyth     /* If the property exists and is not an atom, just return here. */
1228*37da2899SCharles.Forsyth     if ( p && p->format != BDF_ATOM )
1229*37da2899SCharles.Forsyth       return 0;
1230*37da2899SCharles.Forsyth 
1231*37da2899SCharles.Forsyth     /* The property is an atom.  Trim all leading and trailing whitespace */
1232*37da2899SCharles.Forsyth     /* and double quotes for the atom value.                              */
1233*37da2899SCharles.Forsyth     sp = ep;
1234*37da2899SCharles.Forsyth     ep = line + linelen;
1235*37da2899SCharles.Forsyth 
1236*37da2899SCharles.Forsyth     /* Trim the leading whitespace if it exists. */
1237*37da2899SCharles.Forsyth     *sp++ = 0;
1238*37da2899SCharles.Forsyth     while ( *sp                           &&
1239*37da2899SCharles.Forsyth             ( *sp == ' ' || *sp == '\t' ) )
1240*37da2899SCharles.Forsyth       sp++;
1241*37da2899SCharles.Forsyth 
1242*37da2899SCharles.Forsyth     /* Trim the leading double quote if it exists. */
1243*37da2899SCharles.Forsyth     if ( *sp == '"' )
1244*37da2899SCharles.Forsyth       sp++;
1245*37da2899SCharles.Forsyth     *value = sp;
1246*37da2899SCharles.Forsyth 
1247*37da2899SCharles.Forsyth     /* Trim the trailing whitespace if it exists. */
1248*37da2899SCharles.Forsyth     while ( ep > sp                                       &&
1249*37da2899SCharles.Forsyth             ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) )
1250*37da2899SCharles.Forsyth       *--ep = 0;
1251*37da2899SCharles.Forsyth 
1252*37da2899SCharles.Forsyth     /* Trim the trailing double quote if it exists. */
1253*37da2899SCharles.Forsyth     if ( ep > sp && *( ep - 1 ) == '"' )
1254*37da2899SCharles.Forsyth       *--ep = 0;
1255*37da2899SCharles.Forsyth 
1256*37da2899SCharles.Forsyth     return 1;
1257*37da2899SCharles.Forsyth   }
1258*37da2899SCharles.Forsyth 
1259*37da2899SCharles.Forsyth 
1260*37da2899SCharles.Forsyth   static FT_Error
_bdf_add_property(bdf_font_t * font,char * name,char * value)1261*37da2899SCharles.Forsyth   _bdf_add_property( bdf_font_t*  font,
1262*37da2899SCharles.Forsyth                      char*        name,
1263*37da2899SCharles.Forsyth                      char*        value )
1264*37da2899SCharles.Forsyth   {
1265*37da2899SCharles.Forsyth     unsigned long   propid;
1266*37da2899SCharles.Forsyth     hashnode        hn;
1267*37da2899SCharles.Forsyth     int             len;
1268*37da2899SCharles.Forsyth     bdf_property_t  *prop, *fp;
1269*37da2899SCharles.Forsyth     FT_Memory       memory = font->memory;
1270*37da2899SCharles.Forsyth     FT_Error        error = BDF_Err_Ok;
1271*37da2899SCharles.Forsyth 
1272*37da2899SCharles.Forsyth 
1273*37da2899SCharles.Forsyth     /* First, check to see if the property already exists in the font. */
1274*37da2899SCharles.Forsyth     if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 )
1275*37da2899SCharles.Forsyth     {
1276*37da2899SCharles.Forsyth       /* The property already exists in the font, so simply replace */
1277*37da2899SCharles.Forsyth       /* the value of the property with the current value.          */
1278*37da2899SCharles.Forsyth       fp = font->props + (unsigned long)hn->data;
1279*37da2899SCharles.Forsyth 
1280*37da2899SCharles.Forsyth       switch ( fp->format )
1281*37da2899SCharles.Forsyth       {
1282*37da2899SCharles.Forsyth       case BDF_ATOM:
1283*37da2899SCharles.Forsyth         /* Delete the current atom if it exists. */
1284*37da2899SCharles.Forsyth         FT_FREE( fp->value.atom );
1285*37da2899SCharles.Forsyth 
1286*37da2899SCharles.Forsyth         if ( value == 0 )
1287*37da2899SCharles.Forsyth           len = 1;
1288*37da2899SCharles.Forsyth         else
1289*37da2899SCharles.Forsyth           len = ft_strlen( value ) + 1;
1290*37da2899SCharles.Forsyth 
1291*37da2899SCharles.Forsyth         if ( len > 1 )
1292*37da2899SCharles.Forsyth         {
1293*37da2899SCharles.Forsyth           if ( FT_NEW_ARRAY( fp->value.atom, len ) )
1294*37da2899SCharles.Forsyth             goto Exit;
1295*37da2899SCharles.Forsyth           FT_MEM_COPY( fp->value.atom, value, len );
1296*37da2899SCharles.Forsyth         }
1297*37da2899SCharles.Forsyth         else
1298*37da2899SCharles.Forsyth           fp->value.atom = 0;
1299*37da2899SCharles.Forsyth         break;
1300*37da2899SCharles.Forsyth 
1301*37da2899SCharles.Forsyth       case BDF_INTEGER:
1302*37da2899SCharles.Forsyth         fp->value.int32 = _bdf_atol( value, 0, 10 );
1303*37da2899SCharles.Forsyth         break;
1304*37da2899SCharles.Forsyth 
1305*37da2899SCharles.Forsyth       case BDF_CARDINAL:
1306*37da2899SCharles.Forsyth         fp->value.card32 = _bdf_atoul( value, 0, 10 );
1307*37da2899SCharles.Forsyth         break;
1308*37da2899SCharles.Forsyth 
1309*37da2899SCharles.Forsyth       default:
1310*37da2899SCharles.Forsyth         ;
1311*37da2899SCharles.Forsyth       }
1312*37da2899SCharles.Forsyth 
1313*37da2899SCharles.Forsyth       goto Exit;
1314*37da2899SCharles.Forsyth     }
1315*37da2899SCharles.Forsyth 
1316*37da2899SCharles.Forsyth     /* See whether this property type exists yet or not. */
1317*37da2899SCharles.Forsyth     /* If not, create it.                                */
1318*37da2899SCharles.Forsyth     hn = hash_lookup( name, &(font->proptbl) );
1319*37da2899SCharles.Forsyth     if ( hn == 0 )
1320*37da2899SCharles.Forsyth     {
1321*37da2899SCharles.Forsyth       error = bdf_create_property( name, BDF_ATOM, font );
1322*37da2899SCharles.Forsyth       if ( error )
1323*37da2899SCharles.Forsyth         goto Exit;
1324*37da2899SCharles.Forsyth       hn = hash_lookup( name, &(font->proptbl) );
1325*37da2899SCharles.Forsyth     }
1326*37da2899SCharles.Forsyth 
1327*37da2899SCharles.Forsyth     /* Allocate another property if this is overflow. */
1328*37da2899SCharles.Forsyth     if ( font->props_used == font->props_size )
1329*37da2899SCharles.Forsyth     {
1330*37da2899SCharles.Forsyth       if ( font->props_size == 0 )
1331*37da2899SCharles.Forsyth       {
1332*37da2899SCharles.Forsyth         if ( FT_NEW_ARRAY( font->props, 1 ) )
1333*37da2899SCharles.Forsyth           goto Exit;
1334*37da2899SCharles.Forsyth       }
1335*37da2899SCharles.Forsyth       else
1336*37da2899SCharles.Forsyth       {
1337*37da2899SCharles.Forsyth         if ( FT_RENEW_ARRAY( font->props,
1338*37da2899SCharles.Forsyth                              font->props_size,
1339*37da2899SCharles.Forsyth                              font->props_size + 1 ) )
1340*37da2899SCharles.Forsyth           goto Exit;
1341*37da2899SCharles.Forsyth       }
1342*37da2899SCharles.Forsyth 
1343*37da2899SCharles.Forsyth       fp = font->props + font->props_size;
1344*37da2899SCharles.Forsyth       FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) );
1345*37da2899SCharles.Forsyth       font->props_size++;
1346*37da2899SCharles.Forsyth     }
1347*37da2899SCharles.Forsyth 
1348*37da2899SCharles.Forsyth     propid = (unsigned long)hn->data;
1349*37da2899SCharles.Forsyth     if ( propid >= _num_bdf_properties )
1350*37da2899SCharles.Forsyth       prop = font->user_props + ( propid - _num_bdf_properties );
1351*37da2899SCharles.Forsyth     else
1352*37da2899SCharles.Forsyth       prop = (bdf_property_t*)_bdf_properties + propid;
1353*37da2899SCharles.Forsyth 
1354*37da2899SCharles.Forsyth     fp = font->props + font->props_used;
1355*37da2899SCharles.Forsyth 
1356*37da2899SCharles.Forsyth     fp->name    = prop->name;
1357*37da2899SCharles.Forsyth     fp->format  = prop->format;
1358*37da2899SCharles.Forsyth     fp->builtin = prop->builtin;
1359*37da2899SCharles.Forsyth 
1360*37da2899SCharles.Forsyth     switch ( prop->format )
1361*37da2899SCharles.Forsyth     {
1362*37da2899SCharles.Forsyth     case BDF_ATOM:
1363*37da2899SCharles.Forsyth       if ( value == 0 )
1364*37da2899SCharles.Forsyth         len = 1;
1365*37da2899SCharles.Forsyth       else
1366*37da2899SCharles.Forsyth         len = ft_strlen( value ) + 1;
1367*37da2899SCharles.Forsyth 
1368*37da2899SCharles.Forsyth       if ( len > 1 )
1369*37da2899SCharles.Forsyth       {
1370*37da2899SCharles.Forsyth         if ( FT_NEW_ARRAY( fp->value.atom, len ) )
1371*37da2899SCharles.Forsyth           goto Exit;
1372*37da2899SCharles.Forsyth         FT_MEM_COPY( fp->value.atom, value, len );
1373*37da2899SCharles.Forsyth       }
1374*37da2899SCharles.Forsyth       else
1375*37da2899SCharles.Forsyth         fp->value.atom = 0;
1376*37da2899SCharles.Forsyth       break;
1377*37da2899SCharles.Forsyth 
1378*37da2899SCharles.Forsyth     case BDF_INTEGER:
1379*37da2899SCharles.Forsyth       fp->value.int32 = _bdf_atol( value, 0, 10 );
1380*37da2899SCharles.Forsyth       break;
1381*37da2899SCharles.Forsyth 
1382*37da2899SCharles.Forsyth     case BDF_CARDINAL:
1383*37da2899SCharles.Forsyth       fp->value.card32 = _bdf_atoul( value, 0, 10 );
1384*37da2899SCharles.Forsyth       break;
1385*37da2899SCharles.Forsyth     }
1386*37da2899SCharles.Forsyth 
1387*37da2899SCharles.Forsyth     /* If the property happens to be a comment, then it doesn't need */
1388*37da2899SCharles.Forsyth     /* to be added to the internal hash table.                       */
1389*37da2899SCharles.Forsyth     if ( ft_memcmp( name, "COMMENT", 7 ) != 0 ) {
1390*37da2899SCharles.Forsyth       /* Add the property to the font property table. */
1391*37da2899SCharles.Forsyth       error = hash_insert( fp->name,
1392*37da2899SCharles.Forsyth                            (void *)font->props_used,
1393*37da2899SCharles.Forsyth                            (hashtable *)font->internal,
1394*37da2899SCharles.Forsyth                            memory );
1395*37da2899SCharles.Forsyth       if ( error )
1396*37da2899SCharles.Forsyth         goto Exit;
1397*37da2899SCharles.Forsyth     }
1398*37da2899SCharles.Forsyth 
1399*37da2899SCharles.Forsyth     font->props_used++;
1400*37da2899SCharles.Forsyth 
1401*37da2899SCharles.Forsyth     /* Some special cases need to be handled here.  The DEFAULT_CHAR       */
1402*37da2899SCharles.Forsyth     /* property needs to be located if it exists in the property list, the */
1403*37da2899SCharles.Forsyth     /* FONT_ASCENT and FONT_DESCENT need to be assigned if they are        */
1404*37da2899SCharles.Forsyth     /* present, and the SPACING property should override the default       */
1405*37da2899SCharles.Forsyth     /* spacing.                                                            */
1406*37da2899SCharles.Forsyth     if ( ft_memcmp( name, "DEFAULT_CHAR", 12 ) == 0 )
1407*37da2899SCharles.Forsyth       font->default_glyph = fp->value.int32;
1408*37da2899SCharles.Forsyth     else if ( ft_memcmp( name, "FONT_ASCENT", 11 ) == 0 )
1409*37da2899SCharles.Forsyth       font->font_ascent = fp->value.int32;
1410*37da2899SCharles.Forsyth     else if ( ft_memcmp( name, "FONT_DESCENT", 12 ) == 0 )
1411*37da2899SCharles.Forsyth       font->font_descent = fp->value.int32;
1412*37da2899SCharles.Forsyth     else if ( ft_memcmp( name, "SPACING", 7 ) == 0 )
1413*37da2899SCharles.Forsyth     {
1414*37da2899SCharles.Forsyth       if ( fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P' )
1415*37da2899SCharles.Forsyth         font->spacing = BDF_PROPORTIONAL;
1416*37da2899SCharles.Forsyth       else if ( fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M' )
1417*37da2899SCharles.Forsyth         font->spacing = BDF_MONOWIDTH;
1418*37da2899SCharles.Forsyth       else if ( fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C' )
1419*37da2899SCharles.Forsyth         font->spacing = BDF_CHARCELL;
1420*37da2899SCharles.Forsyth     }
1421*37da2899SCharles.Forsyth 
1422*37da2899SCharles.Forsyth   Exit:
1423*37da2899SCharles.Forsyth     return error;
1424*37da2899SCharles.Forsyth   }
1425*37da2899SCharles.Forsyth 
1426*37da2899SCharles.Forsyth 
1427*37da2899SCharles.Forsyth   static const unsigned char nibble_mask[8] =
1428*37da2899SCharles.Forsyth   {
1429*37da2899SCharles.Forsyth     0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE
1430*37da2899SCharles.Forsyth   };
1431*37da2899SCharles.Forsyth 
1432*37da2899SCharles.Forsyth 
1433*37da2899SCharles.Forsyth   /* Actually parse the glyph info and bitmaps. */
1434*37da2899SCharles.Forsyth   static FT_Error
_bdf_parse_glyphs(char * line,unsigned long linelen,unsigned long lineno,void * call_data,void * client_data)1435*37da2899SCharles.Forsyth   _bdf_parse_glyphs( char*          line,
1436*37da2899SCharles.Forsyth                      unsigned long  linelen,
1437*37da2899SCharles.Forsyth                      unsigned long  lineno,
1438*37da2899SCharles.Forsyth                      void*          call_data,
1439*37da2899SCharles.Forsyth                      void*          client_data )
1440*37da2899SCharles.Forsyth   {
1441*37da2899SCharles.Forsyth     int                c, mask_index;
1442*37da2899SCharles.Forsyth     char*              s;
1443*37da2899SCharles.Forsyth     unsigned char*     bp;
1444*37da2899SCharles.Forsyth     unsigned long      i, slen, nibbles;
1445*37da2899SCharles.Forsyth 
1446*37da2899SCharles.Forsyth     _bdf_line_func_t*  next;
1447*37da2899SCharles.Forsyth     _bdf_parse_t*      p;
1448*37da2899SCharles.Forsyth     bdf_glyph_t*       glyph;
1449*37da2899SCharles.Forsyth     bdf_font_t*        font;
1450*37da2899SCharles.Forsyth 
1451*37da2899SCharles.Forsyth     FT_Memory          memory;
1452*37da2899SCharles.Forsyth     FT_Error           error = BDF_Err_Ok;
1453*37da2899SCharles.Forsyth 
1454*37da2899SCharles.Forsyth     FT_UNUSED( lineno );        /* only used in debug mode */
1455*37da2899SCharles.Forsyth 
1456*37da2899SCharles.Forsyth 
1457*37da2899SCharles.Forsyth     next = (_bdf_line_func_t *)call_data;
1458*37da2899SCharles.Forsyth     p    = (_bdf_parse_t *)    client_data;
1459*37da2899SCharles.Forsyth 
1460*37da2899SCharles.Forsyth     font   = p->font;
1461*37da2899SCharles.Forsyth     memory = font->memory;
1462*37da2899SCharles.Forsyth 
1463*37da2899SCharles.Forsyth     /* Check for a comment. */
1464*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
1465*37da2899SCharles.Forsyth     {
1466*37da2899SCharles.Forsyth       linelen -= 7;
1467*37da2899SCharles.Forsyth 
1468*37da2899SCharles.Forsyth       s = line + 7;
1469*37da2899SCharles.Forsyth       if ( *s != 0 )
1470*37da2899SCharles.Forsyth       {
1471*37da2899SCharles.Forsyth         s++;
1472*37da2899SCharles.Forsyth         linelen--;
1473*37da2899SCharles.Forsyth       }
1474*37da2899SCharles.Forsyth       error = _bdf_add_comment( p->font, s, linelen );
1475*37da2899SCharles.Forsyth       goto Exit;
1476*37da2899SCharles.Forsyth     }
1477*37da2899SCharles.Forsyth 
1478*37da2899SCharles.Forsyth     /* The very first thing expected is the number of glyphs. */
1479*37da2899SCharles.Forsyth     if ( !( p->flags & _BDF_GLYPHS ) )
1480*37da2899SCharles.Forsyth     {
1481*37da2899SCharles.Forsyth       if ( ft_memcmp( line, "CHARS", 5 ) != 0 )
1482*37da2899SCharles.Forsyth       {
1483*37da2899SCharles.Forsyth         FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" ));
1484*37da2899SCharles.Forsyth         error = BDF_Err_Missing_Chars_Field;
1485*37da2899SCharles.Forsyth         goto Exit;
1486*37da2899SCharles.Forsyth       }
1487*37da2899SCharles.Forsyth 
1488*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
1489*37da2899SCharles.Forsyth       if ( error )
1490*37da2899SCharles.Forsyth         goto Exit;
1491*37da2899SCharles.Forsyth       p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 );
1492*37da2899SCharles.Forsyth 
1493*37da2899SCharles.Forsyth       /* Make sure the number of glyphs is non-zero. */
1494*37da2899SCharles.Forsyth       if ( p->cnt == 0 )
1495*37da2899SCharles.Forsyth         font->glyphs_size = 64;
1496*37da2899SCharles.Forsyth 
1497*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) )
1498*37da2899SCharles.Forsyth         goto Exit;
1499*37da2899SCharles.Forsyth 
1500*37da2899SCharles.Forsyth       p->flags |= _BDF_GLYPHS;
1501*37da2899SCharles.Forsyth 
1502*37da2899SCharles.Forsyth       goto Exit;
1503*37da2899SCharles.Forsyth     }
1504*37da2899SCharles.Forsyth 
1505*37da2899SCharles.Forsyth     /* Check for the ENDFONT field. */
1506*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "ENDFONT", 7 ) == 0 )
1507*37da2899SCharles.Forsyth     {
1508*37da2899SCharles.Forsyth       /* Sort the glyphs by encoding. */
1509*37da2899SCharles.Forsyth       ft_qsort( (char *)font->glyphs,
1510*37da2899SCharles.Forsyth                 font->glyphs_used,
1511*37da2899SCharles.Forsyth                 sizeof ( bdf_glyph_t ),
1512*37da2899SCharles.Forsyth                 by_encoding );
1513*37da2899SCharles.Forsyth 
1514*37da2899SCharles.Forsyth       p->flags &= ~_BDF_START;
1515*37da2899SCharles.Forsyth 
1516*37da2899SCharles.Forsyth       goto Exit;
1517*37da2899SCharles.Forsyth     }
1518*37da2899SCharles.Forsyth 
1519*37da2899SCharles.Forsyth     /* Check for the ENDCHAR field. */
1520*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "ENDCHAR", 7 ) == 0 )
1521*37da2899SCharles.Forsyth     {
1522*37da2899SCharles.Forsyth       p->glyph_enc = 0;
1523*37da2899SCharles.Forsyth       p->flags    &= ~_BDF_GLYPH_BITS;
1524*37da2899SCharles.Forsyth 
1525*37da2899SCharles.Forsyth       goto Exit;
1526*37da2899SCharles.Forsyth     }
1527*37da2899SCharles.Forsyth 
1528*37da2899SCharles.Forsyth     /* Check to see whether a glyph is being scanned but should be */
1529*37da2899SCharles.Forsyth     /* ignored because it is an unencoded glyph.                   */
1530*37da2899SCharles.Forsyth     if ( ( p->flags & _BDF_GLYPH )     &&
1531*37da2899SCharles.Forsyth          p->glyph_enc            == -1 &&
1532*37da2899SCharles.Forsyth          p->opts->keep_unencoded == 0  )
1533*37da2899SCharles.Forsyth       goto Exit;
1534*37da2899SCharles.Forsyth 
1535*37da2899SCharles.Forsyth     /* Check for the STARTCHAR field. */
1536*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "STARTCHAR", 9 ) == 0 )
1537*37da2899SCharles.Forsyth     {
1538*37da2899SCharles.Forsyth       /* Set the character name in the parse info first until the */
1539*37da2899SCharles.Forsyth       /* encoding can be checked for an unencoded character.      */
1540*37da2899SCharles.Forsyth       FT_FREE( p->glyph_name );
1541*37da2899SCharles.Forsyth 
1542*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list,memory );
1543*37da2899SCharles.Forsyth       if ( error )
1544*37da2899SCharles.Forsyth         goto Exit;
1545*37da2899SCharles.Forsyth       _bdf_shift( 1, &p->list );
1546*37da2899SCharles.Forsyth 
1547*37da2899SCharles.Forsyth       s = _bdf_join( ' ', &slen, &p->list );
1548*37da2899SCharles.Forsyth 
1549*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) )
1550*37da2899SCharles.Forsyth         goto Exit;
1551*37da2899SCharles.Forsyth       FT_MEM_COPY( p->glyph_name, s, slen + 1 );
1552*37da2899SCharles.Forsyth 
1553*37da2899SCharles.Forsyth       p->flags |= _BDF_GLYPH;
1554*37da2899SCharles.Forsyth 
1555*37da2899SCharles.Forsyth       goto Exit;
1556*37da2899SCharles.Forsyth     }
1557*37da2899SCharles.Forsyth 
1558*37da2899SCharles.Forsyth     /* Check for the ENCODING field. */
1559*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "ENCODING", 8 ) == 0 )
1560*37da2899SCharles.Forsyth     {
1561*37da2899SCharles.Forsyth       if ( !( p->flags & _BDF_GLYPH ) )
1562*37da2899SCharles.Forsyth       {
1563*37da2899SCharles.Forsyth         /* Missing STARTCHAR field. */
1564*37da2899SCharles.Forsyth         FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" ));
1565*37da2899SCharles.Forsyth         error = BDF_Err_Missing_Startchar_Field;
1566*37da2899SCharles.Forsyth         goto Exit;
1567*37da2899SCharles.Forsyth       }
1568*37da2899SCharles.Forsyth 
1569*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
1570*37da2899SCharles.Forsyth       if ( error )
1571*37da2899SCharles.Forsyth         goto Exit;
1572*37da2899SCharles.Forsyth       p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 );
1573*37da2899SCharles.Forsyth 
1574*37da2899SCharles.Forsyth       /* Check to see whether this encoding has already been encountered. */
1575*37da2899SCharles.Forsyth       /* If it has then change it to unencoded so it gets added if        */
1576*37da2899SCharles.Forsyth       /* indicated.                                                       */
1577*37da2899SCharles.Forsyth       if ( p->glyph_enc >= 0 )
1578*37da2899SCharles.Forsyth       {
1579*37da2899SCharles.Forsyth         if ( _bdf_glyph_modified( p->have, p->glyph_enc ) )
1580*37da2899SCharles.Forsyth         {
1581*37da2899SCharles.Forsyth           /* Emit a message saying a glyph has been moved to the */
1582*37da2899SCharles.Forsyth           /* unencoded area.                                     */
1583*37da2899SCharles.Forsyth           FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12,
1584*37da2899SCharles.Forsyth                       p->glyph_enc, p->glyph_name ));
1585*37da2899SCharles.Forsyth           p->glyph_enc = -1;
1586*37da2899SCharles.Forsyth           font->modified = 1;
1587*37da2899SCharles.Forsyth         }
1588*37da2899SCharles.Forsyth         else
1589*37da2899SCharles.Forsyth           _bdf_set_glyph_modified( p->have, p->glyph_enc );
1590*37da2899SCharles.Forsyth       }
1591*37da2899SCharles.Forsyth 
1592*37da2899SCharles.Forsyth       if ( p->glyph_enc >= 0 )
1593*37da2899SCharles.Forsyth       {
1594*37da2899SCharles.Forsyth         /* Make sure there are enough glyphs allocated in case the */
1595*37da2899SCharles.Forsyth         /* number of characters happen to be wrong.                */
1596*37da2899SCharles.Forsyth         if ( font->glyphs_used == font->glyphs_size )
1597*37da2899SCharles.Forsyth         {
1598*37da2899SCharles.Forsyth           if ( FT_RENEW_ARRAY( font->glyphs,
1599*37da2899SCharles.Forsyth                                font->glyphs_size,
1600*37da2899SCharles.Forsyth                                font->glyphs_size + 64 ) )
1601*37da2899SCharles.Forsyth             goto Exit;
1602*37da2899SCharles.Forsyth           FT_MEM_ZERO( font->glyphs + font->glyphs_size,
1603*37da2899SCharles.Forsyth                        sizeof ( bdf_glyph_t ) * 64 ); /* FZ inutile */
1604*37da2899SCharles.Forsyth           font->glyphs_size += 64;
1605*37da2899SCharles.Forsyth         }
1606*37da2899SCharles.Forsyth 
1607*37da2899SCharles.Forsyth         glyph           = font->glyphs + font->glyphs_used++;
1608*37da2899SCharles.Forsyth         glyph->name     = p->glyph_name;
1609*37da2899SCharles.Forsyth         glyph->encoding = p->glyph_enc;
1610*37da2899SCharles.Forsyth 
1611*37da2899SCharles.Forsyth         /* Reset the initial glyph info. */
1612*37da2899SCharles.Forsyth         p->glyph_name = 0;
1613*37da2899SCharles.Forsyth       }
1614*37da2899SCharles.Forsyth       else
1615*37da2899SCharles.Forsyth       {
1616*37da2899SCharles.Forsyth         /* Unencoded glyph.  Check to see whether it should */
1617*37da2899SCharles.Forsyth         /* be added or not.                                 */
1618*37da2899SCharles.Forsyth         if ( p->opts->keep_unencoded != 0 )
1619*37da2899SCharles.Forsyth         {
1620*37da2899SCharles.Forsyth           /* Allocate the next unencoded glyph. */
1621*37da2899SCharles.Forsyth           if ( font->unencoded_used == font->unencoded_size )
1622*37da2899SCharles.Forsyth           {
1623*37da2899SCharles.Forsyth             if ( font->unencoded_size == 0 )
1624*37da2899SCharles.Forsyth             {
1625*37da2899SCharles.Forsyth               if ( FT_NEW_ARRAY( font->unencoded, 4 ) )
1626*37da2899SCharles.Forsyth                 goto Exit;
1627*37da2899SCharles.Forsyth             }
1628*37da2899SCharles.Forsyth             else
1629*37da2899SCharles.Forsyth             {
1630*37da2899SCharles.Forsyth               if ( FT_RENEW_ARRAY( font->unencoded ,
1631*37da2899SCharles.Forsyth                                    font->unencoded_size,
1632*37da2899SCharles.Forsyth                                    font->unencoded_size + 4 ) )
1633*37da2899SCharles.Forsyth                 goto Exit;
1634*37da2899SCharles.Forsyth             }
1635*37da2899SCharles.Forsyth             font->unencoded_size += 4;
1636*37da2899SCharles.Forsyth           }
1637*37da2899SCharles.Forsyth 
1638*37da2899SCharles.Forsyth           glyph           = font->unencoded + font->unencoded_used;
1639*37da2899SCharles.Forsyth           glyph->name     = p->glyph_name;
1640*37da2899SCharles.Forsyth           glyph->encoding = font->unencoded_used++;
1641*37da2899SCharles.Forsyth         }
1642*37da2899SCharles.Forsyth         else
1643*37da2899SCharles.Forsyth           /* Free up the glyph name if the unencoded shouldn't be */
1644*37da2899SCharles.Forsyth           /* kept.                                                */
1645*37da2899SCharles.Forsyth           FT_FREE( p->glyph_name );
1646*37da2899SCharles.Forsyth 
1647*37da2899SCharles.Forsyth         p->glyph_name = 0;
1648*37da2899SCharles.Forsyth       }
1649*37da2899SCharles.Forsyth 
1650*37da2899SCharles.Forsyth       /* Clear the flags that might be added when width and height are */
1651*37da2899SCharles.Forsyth       /* checked for consistency.                                      */
1652*37da2899SCharles.Forsyth       p->flags &= ~( _BDF_GLYPH_WIDTH_CHECK | _BDF_GLYPH_HEIGHT_CHECK );
1653*37da2899SCharles.Forsyth 
1654*37da2899SCharles.Forsyth       p->flags |= _BDF_ENCODING;
1655*37da2899SCharles.Forsyth 
1656*37da2899SCharles.Forsyth       goto Exit;
1657*37da2899SCharles.Forsyth     }
1658*37da2899SCharles.Forsyth 
1659*37da2899SCharles.Forsyth     /* Point at the glyph being constructed. */
1660*37da2899SCharles.Forsyth     if ( p->glyph_enc == -1 )
1661*37da2899SCharles.Forsyth       glyph = font->unencoded + ( font->unencoded_used - 1 );
1662*37da2899SCharles.Forsyth     else
1663*37da2899SCharles.Forsyth       glyph = font->glyphs + ( font->glyphs_used - 1 );
1664*37da2899SCharles.Forsyth 
1665*37da2899SCharles.Forsyth     /* Check to see whether a bitmap is being constructed. */
1666*37da2899SCharles.Forsyth     if ( p->flags & _BDF_BITMAP )
1667*37da2899SCharles.Forsyth     {
1668*37da2899SCharles.Forsyth       /* If there are more rows than are specified in the glyph metrics, */
1669*37da2899SCharles.Forsyth       /* ignore the remaining lines.                                     */
1670*37da2899SCharles.Forsyth       if ( p->row >= (unsigned long)glyph->bbx.height )
1671*37da2899SCharles.Forsyth       {
1672*37da2899SCharles.Forsyth         if ( !( p->flags & _BDF_GLYPH_HEIGHT_CHECK ) )
1673*37da2899SCharles.Forsyth         {
1674*37da2899SCharles.Forsyth           FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding ));
1675*37da2899SCharles.Forsyth           p->flags |= _BDF_GLYPH_HEIGHT_CHECK;
1676*37da2899SCharles.Forsyth           font->modified = 1;
1677*37da2899SCharles.Forsyth         }
1678*37da2899SCharles.Forsyth 
1679*37da2899SCharles.Forsyth         goto Exit;
1680*37da2899SCharles.Forsyth       }
1681*37da2899SCharles.Forsyth 
1682*37da2899SCharles.Forsyth       /* Only collect the number of nibbles indicated by the glyph     */
1683*37da2899SCharles.Forsyth       /* metrics.  If there are more columns, they are simply ignored. */
1684*37da2899SCharles.Forsyth       nibbles = glyph->bpr << 1;
1685*37da2899SCharles.Forsyth       bp      = glyph->bitmap + p->row * glyph->bpr;
1686*37da2899SCharles.Forsyth 
1687*37da2899SCharles.Forsyth       for ( i = 0, *bp = 0; i < nibbles; i++ )
1688*37da2899SCharles.Forsyth       {
1689*37da2899SCharles.Forsyth         c = line[i];
1690*37da2899SCharles.Forsyth         *bp = (FT_Byte)( ( *bp << 4 ) + a2i[c] );
1691*37da2899SCharles.Forsyth         if ( i + 1 < nibbles && ( i & 1 ) )
1692*37da2899SCharles.Forsyth           *++bp = 0;
1693*37da2899SCharles.Forsyth       }
1694*37da2899SCharles.Forsyth 
1695*37da2899SCharles.Forsyth       /* Remove possible garbage at the right. */
1696*37da2899SCharles.Forsyth       mask_index = ( glyph->bbx.width * p->font->bpp ) & 7;
1697*37da2899SCharles.Forsyth       *bp &= nibble_mask[mask_index];
1698*37da2899SCharles.Forsyth 
1699*37da2899SCharles.Forsyth       /* If any line has extra columns, indicate they have been removed. */
1700*37da2899SCharles.Forsyth       if ( ( line[nibbles] == '0' || a2i[(int)line[nibbles]] != 0 ) &&
1701*37da2899SCharles.Forsyth            !( p->flags & _BDF_GLYPH_WIDTH_CHECK )                   )
1702*37da2899SCharles.Forsyth       {
1703*37da2899SCharles.Forsyth         FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding ));
1704*37da2899SCharles.Forsyth         p->flags       |= _BDF_GLYPH_WIDTH_CHECK;
1705*37da2899SCharles.Forsyth         font->modified  = 1;
1706*37da2899SCharles.Forsyth       }
1707*37da2899SCharles.Forsyth 
1708*37da2899SCharles.Forsyth       p->row++;
1709*37da2899SCharles.Forsyth       goto Exit;
1710*37da2899SCharles.Forsyth     }
1711*37da2899SCharles.Forsyth 
1712*37da2899SCharles.Forsyth     /* Expect the SWIDTH (scalable width) field next. */
1713*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "SWIDTH", 6 ) == 0 )
1714*37da2899SCharles.Forsyth     {
1715*37da2899SCharles.Forsyth       if ( !( p->flags & _BDF_ENCODING ) )
1716*37da2899SCharles.Forsyth       {
1717*37da2899SCharles.Forsyth         /* Missing ENCODING field. */
1718*37da2899SCharles.Forsyth         FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENCODING" ));
1719*37da2899SCharles.Forsyth         error = BDF_Err_Missing_Encoding_Field;
1720*37da2899SCharles.Forsyth         goto Exit;
1721*37da2899SCharles.Forsyth       }
1722*37da2899SCharles.Forsyth 
1723*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
1724*37da2899SCharles.Forsyth       if ( error )
1725*37da2899SCharles.Forsyth         goto Exit;
1726*37da2899SCharles.Forsyth       glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
1727*37da2899SCharles.Forsyth       p->flags |= _BDF_SWIDTH;
1728*37da2899SCharles.Forsyth 
1729*37da2899SCharles.Forsyth       goto Exit;
1730*37da2899SCharles.Forsyth     }
1731*37da2899SCharles.Forsyth 
1732*37da2899SCharles.Forsyth     /* Expect the DWIDTH (scalable width) field next. */
1733*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "DWIDTH", 6 ) == 0 )
1734*37da2899SCharles.Forsyth     {
1735*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list,memory );
1736*37da2899SCharles.Forsyth       if ( error )
1737*37da2899SCharles.Forsyth         goto Exit;
1738*37da2899SCharles.Forsyth       glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
1739*37da2899SCharles.Forsyth 
1740*37da2899SCharles.Forsyth       if ( !( p->flags & _BDF_SWIDTH ) )
1741*37da2899SCharles.Forsyth       {
1742*37da2899SCharles.Forsyth         /* Missing SWIDTH field.  Emit an auto correction message and set */
1743*37da2899SCharles.Forsyth         /* the scalable width from the device width.                      */
1744*37da2899SCharles.Forsyth         FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG9, lineno ));
1745*37da2899SCharles.Forsyth 
1746*37da2899SCharles.Forsyth         glyph->swidth = (unsigned short)FT_MulDiv(
1747*37da2899SCharles.Forsyth                           glyph->dwidth, 72000L,
1748*37da2899SCharles.Forsyth                           (FT_Long)( font->point_size *
1749*37da2899SCharles.Forsyth                                      font->resolution_x ) );
1750*37da2899SCharles.Forsyth       }
1751*37da2899SCharles.Forsyth 
1752*37da2899SCharles.Forsyth       p->flags |= _BDF_DWIDTH;
1753*37da2899SCharles.Forsyth       goto Exit;
1754*37da2899SCharles.Forsyth     }
1755*37da2899SCharles.Forsyth 
1756*37da2899SCharles.Forsyth     /* Expect the BBX field next. */
1757*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "BBX", 3 ) == 0 )
1758*37da2899SCharles.Forsyth     {
1759*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
1760*37da2899SCharles.Forsyth       if ( error )
1761*37da2899SCharles.Forsyth         goto Exit;
1762*37da2899SCharles.Forsyth 
1763*37da2899SCharles.Forsyth       glyph->bbx.width    = _bdf_atos( p->list.field[1], 0, 10 );
1764*37da2899SCharles.Forsyth       glyph->bbx.height   = _bdf_atos( p->list.field[2], 0, 10 );
1765*37da2899SCharles.Forsyth       glyph->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
1766*37da2899SCharles.Forsyth       glyph->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
1767*37da2899SCharles.Forsyth 
1768*37da2899SCharles.Forsyth       /* Generate the ascent and descent of the character. */
1769*37da2899SCharles.Forsyth       glyph->bbx.ascent  = (short)( glyph->bbx.height + glyph->bbx.y_offset );
1770*37da2899SCharles.Forsyth       glyph->bbx.descent = (short)( -glyph->bbx.y_offset );
1771*37da2899SCharles.Forsyth 
1772*37da2899SCharles.Forsyth       /* Determine the overall font bounding box as the characters are */
1773*37da2899SCharles.Forsyth       /* loaded so corrections can be done later if indicated.         */
1774*37da2899SCharles.Forsyth       p->maxas    = (short)MAX( glyph->bbx.ascent, p->maxas );
1775*37da2899SCharles.Forsyth       p->maxds    = (short)MAX( glyph->bbx.descent, p->maxds );
1776*37da2899SCharles.Forsyth 
1777*37da2899SCharles.Forsyth       p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset );
1778*37da2899SCharles.Forsyth 
1779*37da2899SCharles.Forsyth       p->maxrb    = (short)MAX( p->rbearing, p->maxrb );
1780*37da2899SCharles.Forsyth       p->minlb    = (short)MIN( glyph->bbx.x_offset, p->minlb );
1781*37da2899SCharles.Forsyth       p->maxlb    = (short)MAX( glyph->bbx.x_offset, p->maxlb );
1782*37da2899SCharles.Forsyth 
1783*37da2899SCharles.Forsyth       if ( !( p->flags & _BDF_DWIDTH ) )
1784*37da2899SCharles.Forsyth       {
1785*37da2899SCharles.Forsyth         /* Missing DWIDTH field.  Emit an auto correction message and set */
1786*37da2899SCharles.Forsyth         /* the device width to the glyph width.                           */
1787*37da2899SCharles.Forsyth         FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG10, lineno ));
1788*37da2899SCharles.Forsyth         glyph->dwidth = glyph->bbx.width;
1789*37da2899SCharles.Forsyth       }
1790*37da2899SCharles.Forsyth 
1791*37da2899SCharles.Forsyth       /* If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH */
1792*37da2899SCharles.Forsyth       /* value if necessary.                                            */
1793*37da2899SCharles.Forsyth       if ( p->opts->correct_metrics != 0 )
1794*37da2899SCharles.Forsyth       {
1795*37da2899SCharles.Forsyth         /* Determine the point size of the glyph. */
1796*37da2899SCharles.Forsyth         unsigned short  sw = (unsigned short)FT_MulDiv(
1797*37da2899SCharles.Forsyth                                glyph->dwidth, 72000L,
1798*37da2899SCharles.Forsyth                                (FT_Long)( font->point_size *
1799*37da2899SCharles.Forsyth                                           font->resolution_x ) );
1800*37da2899SCharles.Forsyth 
1801*37da2899SCharles.Forsyth 
1802*37da2899SCharles.Forsyth         if ( sw != glyph->swidth )
1803*37da2899SCharles.Forsyth         {
1804*37da2899SCharles.Forsyth           glyph->swidth = sw;
1805*37da2899SCharles.Forsyth 
1806*37da2899SCharles.Forsyth           if ( p->glyph_enc == -1 )
1807*37da2899SCharles.Forsyth             _bdf_set_glyph_modified( font->umod,
1808*37da2899SCharles.Forsyth                                      font->unencoded_used - 1 );
1809*37da2899SCharles.Forsyth           else
1810*37da2899SCharles.Forsyth             _bdf_set_glyph_modified( font->nmod, glyph->encoding );
1811*37da2899SCharles.Forsyth 
1812*37da2899SCharles.Forsyth           p->flags       |= _BDF_SWIDTH_ADJ;
1813*37da2899SCharles.Forsyth           font->modified  = 1;
1814*37da2899SCharles.Forsyth         }
1815*37da2899SCharles.Forsyth       }
1816*37da2899SCharles.Forsyth 
1817*37da2899SCharles.Forsyth       p->flags |= _BDF_BBX;
1818*37da2899SCharles.Forsyth       goto Exit;
1819*37da2899SCharles.Forsyth     }
1820*37da2899SCharles.Forsyth 
1821*37da2899SCharles.Forsyth     /* And finally, gather up the bitmap. */
1822*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "BITMAP", 6 ) == 0 )
1823*37da2899SCharles.Forsyth     {
1824*37da2899SCharles.Forsyth       if ( !( p->flags & _BDF_BBX ) )
1825*37da2899SCharles.Forsyth       {
1826*37da2899SCharles.Forsyth         /* Missing BBX field. */
1827*37da2899SCharles.Forsyth         FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "BBX" ));
1828*37da2899SCharles.Forsyth         error = BDF_Err_Missing_Bbx_Field;
1829*37da2899SCharles.Forsyth         goto Exit;
1830*37da2899SCharles.Forsyth       }
1831*37da2899SCharles.Forsyth 
1832*37da2899SCharles.Forsyth       /* Allocate enough space for the bitmap. */
1833*37da2899SCharles.Forsyth       glyph->bpr   = ( glyph->bbx.width * p->font->bpp + 7 ) >> 3;
1834*37da2899SCharles.Forsyth       glyph->bytes = (unsigned short)( glyph->bpr * glyph->bbx.height );
1835*37da2899SCharles.Forsyth 
1836*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) )
1837*37da2899SCharles.Forsyth         goto Exit;
1838*37da2899SCharles.Forsyth 
1839*37da2899SCharles.Forsyth       p->row    = 0;
1840*37da2899SCharles.Forsyth       p->flags |= _BDF_BITMAP;
1841*37da2899SCharles.Forsyth 
1842*37da2899SCharles.Forsyth       goto Exit;
1843*37da2899SCharles.Forsyth     }
1844*37da2899SCharles.Forsyth 
1845*37da2899SCharles.Forsyth     error = BDF_Err_Invalid_File_Format;
1846*37da2899SCharles.Forsyth 
1847*37da2899SCharles.Forsyth   Exit:
1848*37da2899SCharles.Forsyth     return error;
1849*37da2899SCharles.Forsyth   }
1850*37da2899SCharles.Forsyth 
1851*37da2899SCharles.Forsyth 
1852*37da2899SCharles.Forsyth   /* Load the font properties. */
1853*37da2899SCharles.Forsyth   static FT_Error
_bdf_parse_properties(char * line,unsigned long linelen,unsigned long lineno,void * call_data,void * client_data)1854*37da2899SCharles.Forsyth   _bdf_parse_properties( char*          line,
1855*37da2899SCharles.Forsyth                          unsigned long  linelen,
1856*37da2899SCharles.Forsyth                          unsigned long  lineno,
1857*37da2899SCharles.Forsyth                          void*          call_data,
1858*37da2899SCharles.Forsyth                          void*          client_data )
1859*37da2899SCharles.Forsyth   {
1860*37da2899SCharles.Forsyth     unsigned long      vlen;
1861*37da2899SCharles.Forsyth     _bdf_line_func_t*  next;
1862*37da2899SCharles.Forsyth     _bdf_parse_t*      p;
1863*37da2899SCharles.Forsyth     char*              name;
1864*37da2899SCharles.Forsyth     char*              value;
1865*37da2899SCharles.Forsyth     char               nbuf[128];
1866*37da2899SCharles.Forsyth     FT_Memory          memory;
1867*37da2899SCharles.Forsyth     FT_Error           error = BDF_Err_Ok;
1868*37da2899SCharles.Forsyth 
1869*37da2899SCharles.Forsyth     FT_UNUSED( lineno );
1870*37da2899SCharles.Forsyth 
1871*37da2899SCharles.Forsyth 
1872*37da2899SCharles.Forsyth     next = (_bdf_line_func_t *)call_data;
1873*37da2899SCharles.Forsyth     p    = (_bdf_parse_t *)    client_data;
1874*37da2899SCharles.Forsyth 
1875*37da2899SCharles.Forsyth     memory = p->font->memory;
1876*37da2899SCharles.Forsyth 
1877*37da2899SCharles.Forsyth     /* Check for the end of the properties. */
1878*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "ENDPROPERTIES", 13 ) == 0 )
1879*37da2899SCharles.Forsyth     {
1880*37da2899SCharles.Forsyth       /* If the FONT_ASCENT or FONT_DESCENT properties have not been      */
1881*37da2899SCharles.Forsyth       /* encountered yet, then make sure they are added as properties and */
1882*37da2899SCharles.Forsyth       /* make sure they are set from the font bounding box info.          */
1883*37da2899SCharles.Forsyth       /*                                                                  */
1884*37da2899SCharles.Forsyth       /* This is *always* done regardless of the options, because X11     */
1885*37da2899SCharles.Forsyth       /* requires these two fields to compile fonts.                      */
1886*37da2899SCharles.Forsyth       if ( bdf_get_font_property( p->font, (char *)"FONT_ASCENT" ) == 0 )
1887*37da2899SCharles.Forsyth       {
1888*37da2899SCharles.Forsyth         p->font->font_ascent = p->font->bbx.ascent;
1889*37da2899SCharles.Forsyth         ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );
1890*37da2899SCharles.Forsyth         error = _bdf_add_property( p->font, (char *)"FONT_ASCENT", nbuf );
1891*37da2899SCharles.Forsyth         if ( error )
1892*37da2899SCharles.Forsyth           goto Exit;
1893*37da2899SCharles.Forsyth 
1894*37da2899SCharles.Forsyth         FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));
1895*37da2899SCharles.Forsyth         p->font->modified = 1;
1896*37da2899SCharles.Forsyth       }
1897*37da2899SCharles.Forsyth 
1898*37da2899SCharles.Forsyth       if ( bdf_get_font_property( p->font, (char *)"FONT_DESCENT" ) == 0 )
1899*37da2899SCharles.Forsyth       {
1900*37da2899SCharles.Forsyth         p->font->font_descent = p->font->bbx.descent;
1901*37da2899SCharles.Forsyth         ft_sprintf( nbuf, "%hd", p->font->bbx.descent );
1902*37da2899SCharles.Forsyth         error = _bdf_add_property( p->font, (char *)"FONT_DESCENT", nbuf );
1903*37da2899SCharles.Forsyth         if ( error )
1904*37da2899SCharles.Forsyth           goto Exit;
1905*37da2899SCharles.Forsyth 
1906*37da2899SCharles.Forsyth         FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));
1907*37da2899SCharles.Forsyth         p->font->modified = 1;
1908*37da2899SCharles.Forsyth       }
1909*37da2899SCharles.Forsyth 
1910*37da2899SCharles.Forsyth       p->flags &= ~_BDF_PROPS;
1911*37da2899SCharles.Forsyth       *next     = _bdf_parse_glyphs;
1912*37da2899SCharles.Forsyth 
1913*37da2899SCharles.Forsyth       goto Exit;
1914*37da2899SCharles.Forsyth     }
1915*37da2899SCharles.Forsyth 
1916*37da2899SCharles.Forsyth     /* Ignore the _XFREE86_GLYPH_RANGES properties. */
1917*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 )
1918*37da2899SCharles.Forsyth       goto Exit;
1919*37da2899SCharles.Forsyth 
1920*37da2899SCharles.Forsyth     /* Handle COMMENT fields and properties in a special way to preserve */
1921*37da2899SCharles.Forsyth     /* the spacing.                                                      */
1922*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
1923*37da2899SCharles.Forsyth     {
1924*37da2899SCharles.Forsyth       name = value = line;
1925*37da2899SCharles.Forsyth       value += 7;
1926*37da2899SCharles.Forsyth       if ( *value )
1927*37da2899SCharles.Forsyth         *value++ = 0;
1928*37da2899SCharles.Forsyth       error = _bdf_add_property( p->font, name, value );
1929*37da2899SCharles.Forsyth       if ( error )
1930*37da2899SCharles.Forsyth         goto Exit;
1931*37da2899SCharles.Forsyth     }
1932*37da2899SCharles.Forsyth     else if ( _bdf_is_atom( line, linelen, &name, &value, p->font ) )
1933*37da2899SCharles.Forsyth     {
1934*37da2899SCharles.Forsyth       error = _bdf_add_property( p->font, name, value );
1935*37da2899SCharles.Forsyth       if ( error )
1936*37da2899SCharles.Forsyth         goto Exit;
1937*37da2899SCharles.Forsyth     }
1938*37da2899SCharles.Forsyth     else
1939*37da2899SCharles.Forsyth     {
1940*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
1941*37da2899SCharles.Forsyth       if ( error )
1942*37da2899SCharles.Forsyth         goto Exit;
1943*37da2899SCharles.Forsyth       name = p->list.field[0];
1944*37da2899SCharles.Forsyth 
1945*37da2899SCharles.Forsyth       _bdf_shift( 1, &p->list );
1946*37da2899SCharles.Forsyth       value = _bdf_join( ' ', &vlen, &p->list );
1947*37da2899SCharles.Forsyth 
1948*37da2899SCharles.Forsyth       error = _bdf_add_property( p->font, name, value );
1949*37da2899SCharles.Forsyth       if ( error )
1950*37da2899SCharles.Forsyth         goto Exit;
1951*37da2899SCharles.Forsyth     }
1952*37da2899SCharles.Forsyth 
1953*37da2899SCharles.Forsyth   Exit:
1954*37da2899SCharles.Forsyth     return error;
1955*37da2899SCharles.Forsyth   }
1956*37da2899SCharles.Forsyth 
1957*37da2899SCharles.Forsyth 
1958*37da2899SCharles.Forsyth   /* Load the font header. */
1959*37da2899SCharles.Forsyth   static FT_Error
_bdf_parse_start(char * line,unsigned long linelen,unsigned long lineno,void * call_data,void * client_data)1960*37da2899SCharles.Forsyth   _bdf_parse_start( char*          line,
1961*37da2899SCharles.Forsyth                     unsigned long  linelen,
1962*37da2899SCharles.Forsyth                     unsigned long  lineno,
1963*37da2899SCharles.Forsyth                     void*          call_data,
1964*37da2899SCharles.Forsyth                     void*          client_data )
1965*37da2899SCharles.Forsyth   {
1966*37da2899SCharles.Forsyth     unsigned long      slen;
1967*37da2899SCharles.Forsyth     _bdf_line_func_t*  next;
1968*37da2899SCharles.Forsyth     _bdf_parse_t*      p;
1969*37da2899SCharles.Forsyth     bdf_font_t*        font;
1970*37da2899SCharles.Forsyth     char               *s;
1971*37da2899SCharles.Forsyth 
1972*37da2899SCharles.Forsyth     FT_Memory          memory = NULL;
1973*37da2899SCharles.Forsyth     FT_Error           error  = BDF_Err_Ok;
1974*37da2899SCharles.Forsyth 
1975*37da2899SCharles.Forsyth     FT_UNUSED( lineno );            /* only used in debug mode */
1976*37da2899SCharles.Forsyth 
1977*37da2899SCharles.Forsyth 
1978*37da2899SCharles.Forsyth     next = (_bdf_line_func_t *)call_data;
1979*37da2899SCharles.Forsyth     p    = (_bdf_parse_t *)    client_data;
1980*37da2899SCharles.Forsyth 
1981*37da2899SCharles.Forsyth     if ( p->font )
1982*37da2899SCharles.Forsyth       memory = p->font->memory;
1983*37da2899SCharles.Forsyth 
1984*37da2899SCharles.Forsyth     /* Check for a comment.  This is done to handle those fonts that have */
1985*37da2899SCharles.Forsyth     /* comments before the STARTFONT line for some reason.                */
1986*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
1987*37da2899SCharles.Forsyth     {
1988*37da2899SCharles.Forsyth       if ( p->opts->keep_comments != 0 && p->font != 0 )
1989*37da2899SCharles.Forsyth       {
1990*37da2899SCharles.Forsyth         linelen -= 7;
1991*37da2899SCharles.Forsyth 
1992*37da2899SCharles.Forsyth         s = line + 7;
1993*37da2899SCharles.Forsyth         if ( *s != 0 )
1994*37da2899SCharles.Forsyth         {
1995*37da2899SCharles.Forsyth           s++;
1996*37da2899SCharles.Forsyth           linelen--;
1997*37da2899SCharles.Forsyth         }
1998*37da2899SCharles.Forsyth 
1999*37da2899SCharles.Forsyth         error = _bdf_add_comment( p->font, s, linelen );
2000*37da2899SCharles.Forsyth         if ( error )
2001*37da2899SCharles.Forsyth           goto Exit;
2002*37da2899SCharles.Forsyth         /* here font is not defined! */
2003*37da2899SCharles.Forsyth       }
2004*37da2899SCharles.Forsyth 
2005*37da2899SCharles.Forsyth       goto Exit;
2006*37da2899SCharles.Forsyth     }
2007*37da2899SCharles.Forsyth 
2008*37da2899SCharles.Forsyth     if ( !( p->flags & _BDF_START ) )
2009*37da2899SCharles.Forsyth     {
2010*37da2899SCharles.Forsyth       memory = p->memory;
2011*37da2899SCharles.Forsyth 
2012*37da2899SCharles.Forsyth       if ( ft_memcmp( line, "STARTFONT", 9 ) != 0 )
2013*37da2899SCharles.Forsyth       {
2014*37da2899SCharles.Forsyth         /* No STARTFONT field is a good indication of a problem. */
2015*37da2899SCharles.Forsyth         error = BDF_Err_Missing_Startfont_Field;
2016*37da2899SCharles.Forsyth         goto Exit;
2017*37da2899SCharles.Forsyth       }
2018*37da2899SCharles.Forsyth 
2019*37da2899SCharles.Forsyth       p->flags = _BDF_START;
2020*37da2899SCharles.Forsyth       font = p->font = 0;
2021*37da2899SCharles.Forsyth 
2022*37da2899SCharles.Forsyth       if ( FT_NEW( font ) )
2023*37da2899SCharles.Forsyth         goto Exit;
2024*37da2899SCharles.Forsyth       p->font = font;
2025*37da2899SCharles.Forsyth 
2026*37da2899SCharles.Forsyth       font->memory = p->memory;
2027*37da2899SCharles.Forsyth       p->memory    = 0;
2028*37da2899SCharles.Forsyth 
2029*37da2899SCharles.Forsyth       { /* setup */
2030*37da2899SCharles.Forsyth         unsigned long    i;
2031*37da2899SCharles.Forsyth         bdf_property_t*  prop;
2032*37da2899SCharles.Forsyth 
2033*37da2899SCharles.Forsyth 
2034*37da2899SCharles.Forsyth         error = hash_init( &(font->proptbl), memory );
2035*37da2899SCharles.Forsyth         if ( error )
2036*37da2899SCharles.Forsyth           goto Exit;
2037*37da2899SCharles.Forsyth         for ( i = 0, prop = (bdf_property_t*)_bdf_properties;
2038*37da2899SCharles.Forsyth               i < _num_bdf_properties; i++, prop++ )
2039*37da2899SCharles.Forsyth         {
2040*37da2899SCharles.Forsyth           error = hash_insert( prop->name, (void *)i,
2041*37da2899SCharles.Forsyth                                &(font->proptbl), memory );
2042*37da2899SCharles.Forsyth           if ( error )
2043*37da2899SCharles.Forsyth             goto Exit;
2044*37da2899SCharles.Forsyth         }
2045*37da2899SCharles.Forsyth       }
2046*37da2899SCharles.Forsyth 
2047*37da2899SCharles.Forsyth       if ( FT_ALLOC( p->font->internal, sizeof ( hashtable ) ) )
2048*37da2899SCharles.Forsyth         goto Exit;
2049*37da2899SCharles.Forsyth       error = hash_init( (hashtable *)p->font->internal,memory );
2050*37da2899SCharles.Forsyth       if ( error )
2051*37da2899SCharles.Forsyth         goto Exit;
2052*37da2899SCharles.Forsyth       p->font->spacing       = p->opts->font_spacing;
2053*37da2899SCharles.Forsyth       p->font->default_glyph = -1;
2054*37da2899SCharles.Forsyth 
2055*37da2899SCharles.Forsyth       goto Exit;
2056*37da2899SCharles.Forsyth     }
2057*37da2899SCharles.Forsyth 
2058*37da2899SCharles.Forsyth     /* Check for the start of the properties. */
2059*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "STARTPROPERTIES", 15 ) == 0 )
2060*37da2899SCharles.Forsyth     {
2061*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
2062*37da2899SCharles.Forsyth       if ( error )
2063*37da2899SCharles.Forsyth         goto Exit;
2064*37da2899SCharles.Forsyth       p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1], 0, 10 );
2065*37da2899SCharles.Forsyth 
2066*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( p->font->props, p->cnt ) )
2067*37da2899SCharles.Forsyth         goto Exit;
2068*37da2899SCharles.Forsyth 
2069*37da2899SCharles.Forsyth       p->flags |= _BDF_PROPS;
2070*37da2899SCharles.Forsyth       *next     = _bdf_parse_properties;
2071*37da2899SCharles.Forsyth 
2072*37da2899SCharles.Forsyth       goto Exit;
2073*37da2899SCharles.Forsyth     }
2074*37da2899SCharles.Forsyth 
2075*37da2899SCharles.Forsyth     /* Check for the FONTBOUNDINGBOX field. */
2076*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "FONTBOUNDINGBOX", 15 ) == 0 )
2077*37da2899SCharles.Forsyth     {
2078*37da2899SCharles.Forsyth       if ( !(p->flags & _BDF_SIZE ) )
2079*37da2899SCharles.Forsyth       {
2080*37da2899SCharles.Forsyth         /* Missing the SIZE field. */
2081*37da2899SCharles.Forsyth         FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "SIZE" ));
2082*37da2899SCharles.Forsyth         error = BDF_Err_Missing_Size_Field;
2083*37da2899SCharles.Forsyth         goto Exit;
2084*37da2899SCharles.Forsyth       }
2085*37da2899SCharles.Forsyth 
2086*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list , memory );
2087*37da2899SCharles.Forsyth       if ( error )
2088*37da2899SCharles.Forsyth         goto Exit;
2089*37da2899SCharles.Forsyth 
2090*37da2899SCharles.Forsyth       p->font->bbx.width  = _bdf_atos( p->list.field[1], 0, 10 );
2091*37da2899SCharles.Forsyth       p->font->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );
2092*37da2899SCharles.Forsyth 
2093*37da2899SCharles.Forsyth       p->font->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
2094*37da2899SCharles.Forsyth       p->font->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
2095*37da2899SCharles.Forsyth 
2096*37da2899SCharles.Forsyth       p->font->bbx.ascent  = (short)( p->font->bbx.height +
2097*37da2899SCharles.Forsyth                                       p->font->bbx.y_offset );
2098*37da2899SCharles.Forsyth 
2099*37da2899SCharles.Forsyth       p->font->bbx.descent = (short)( -p->font->bbx.y_offset );
2100*37da2899SCharles.Forsyth 
2101*37da2899SCharles.Forsyth       p->flags |= _BDF_FONT_BBX;
2102*37da2899SCharles.Forsyth 
2103*37da2899SCharles.Forsyth       goto Exit;
2104*37da2899SCharles.Forsyth     }
2105*37da2899SCharles.Forsyth 
2106*37da2899SCharles.Forsyth     /* The next thing to check for is the FONT field. */
2107*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "FONT", 4 ) == 0 )
2108*37da2899SCharles.Forsyth     {
2109*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list , memory );
2110*37da2899SCharles.Forsyth       if ( error )
2111*37da2899SCharles.Forsyth         goto Exit;
2112*37da2899SCharles.Forsyth       _bdf_shift( 1, &p->list );
2113*37da2899SCharles.Forsyth 
2114*37da2899SCharles.Forsyth       s = _bdf_join( ' ', &slen, &p->list );
2115*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) )
2116*37da2899SCharles.Forsyth         goto Exit;
2117*37da2899SCharles.Forsyth       FT_MEM_COPY( p->font->name, s, slen + 1 );
2118*37da2899SCharles.Forsyth 
2119*37da2899SCharles.Forsyth       /* If the font name is an XLFD name, set the spacing to the one in  */
2120*37da2899SCharles.Forsyth       /* the font name.  If there is no spacing fall back on the default. */
2121*37da2899SCharles.Forsyth       error = _bdf_set_default_spacing( p->font, p->opts );
2122*37da2899SCharles.Forsyth       if ( error )
2123*37da2899SCharles.Forsyth         goto Exit;
2124*37da2899SCharles.Forsyth 
2125*37da2899SCharles.Forsyth       p->flags |= _BDF_FONT_NAME;
2126*37da2899SCharles.Forsyth 
2127*37da2899SCharles.Forsyth       goto Exit;
2128*37da2899SCharles.Forsyth     }
2129*37da2899SCharles.Forsyth 
2130*37da2899SCharles.Forsyth     /* Check for the SIZE field. */
2131*37da2899SCharles.Forsyth     if ( ft_memcmp( line, "SIZE", 4 ) == 0 )
2132*37da2899SCharles.Forsyth     {
2133*37da2899SCharles.Forsyth       if ( !( p->flags & _BDF_FONT_NAME ) )
2134*37da2899SCharles.Forsyth       {
2135*37da2899SCharles.Forsyth         /* Missing the FONT field. */
2136*37da2899SCharles.Forsyth         FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONT" ));
2137*37da2899SCharles.Forsyth         error = BDF_Err_Missing_Font_Field;
2138*37da2899SCharles.Forsyth         goto Exit;
2139*37da2899SCharles.Forsyth       }
2140*37da2899SCharles.Forsyth 
2141*37da2899SCharles.Forsyth       error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
2142*37da2899SCharles.Forsyth       if ( error )
2143*37da2899SCharles.Forsyth         goto Exit;
2144*37da2899SCharles.Forsyth 
2145*37da2899SCharles.Forsyth       p->font->point_size   = _bdf_atoul( p->list.field[1], 0, 10 );
2146*37da2899SCharles.Forsyth       p->font->resolution_x = _bdf_atoul( p->list.field[2], 0, 10 );
2147*37da2899SCharles.Forsyth       p->font->resolution_y = _bdf_atoul( p->list.field[3], 0, 10 );
2148*37da2899SCharles.Forsyth 
2149*37da2899SCharles.Forsyth       /* Check for the bits per pixel field. */
2150*37da2899SCharles.Forsyth       if ( p->list.used == 5 )
2151*37da2899SCharles.Forsyth       {
2152*37da2899SCharles.Forsyth         unsigned short bitcount, i, shift;
2153*37da2899SCharles.Forsyth 
2154*37da2899SCharles.Forsyth 
2155*37da2899SCharles.Forsyth         p->font->bpp = (unsigned short)_bdf_atos( p->list.field[4], 0, 10 );
2156*37da2899SCharles.Forsyth 
2157*37da2899SCharles.Forsyth         /* Only values 1, 2, 4, 8 are allowed. */
2158*37da2899SCharles.Forsyth         shift = p->font->bpp;
2159*37da2899SCharles.Forsyth         bitcount = 0;
2160*37da2899SCharles.Forsyth         for ( i = 0; shift > 0; i++ )
2161*37da2899SCharles.Forsyth         {
2162*37da2899SCharles.Forsyth           if ( shift & 1 )
2163*37da2899SCharles.Forsyth             bitcount = i;
2164*37da2899SCharles.Forsyth           shift >>= 1;
2165*37da2899SCharles.Forsyth         }
2166*37da2899SCharles.Forsyth 
2167*37da2899SCharles.Forsyth         shift = (short)( ( bitcount > 3 ) ? 8 : ( 1 << bitcount ) );
2168*37da2899SCharles.Forsyth 
2169*37da2899SCharles.Forsyth         if ( p->font->bpp > shift || p->font->bpp != shift )
2170*37da2899SCharles.Forsyth         {
2171*37da2899SCharles.Forsyth           /* select next higher value */
2172*37da2899SCharles.Forsyth           p->font->bpp = (unsigned short)( shift << 1 );
2173*37da2899SCharles.Forsyth           FT_TRACE2(( "_bdf_parse_start: " ACMSG11, p->font->bpp ));
2174*37da2899SCharles.Forsyth         }
2175*37da2899SCharles.Forsyth       }
2176*37da2899SCharles.Forsyth       else
2177*37da2899SCharles.Forsyth         p->font->bpp = 1;
2178*37da2899SCharles.Forsyth 
2179*37da2899SCharles.Forsyth       p->flags |= _BDF_SIZE;
2180*37da2899SCharles.Forsyth 
2181*37da2899SCharles.Forsyth       goto Exit;
2182*37da2899SCharles.Forsyth     }
2183*37da2899SCharles.Forsyth 
2184*37da2899SCharles.Forsyth     error = BDF_Err_Invalid_File_Format;
2185*37da2899SCharles.Forsyth 
2186*37da2899SCharles.Forsyth   Exit:
2187*37da2899SCharles.Forsyth     return error;
2188*37da2899SCharles.Forsyth   }
2189*37da2899SCharles.Forsyth 
2190*37da2899SCharles.Forsyth 
2191*37da2899SCharles.Forsyth   /*************************************************************************/
2192*37da2899SCharles.Forsyth   /*                                                                       */
2193*37da2899SCharles.Forsyth   /* API.                                                                  */
2194*37da2899SCharles.Forsyth   /*                                                                       */
2195*37da2899SCharles.Forsyth   /*************************************************************************/
2196*37da2899SCharles.Forsyth 
2197*37da2899SCharles.Forsyth 
2198*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
bdf_load_font(FT_Stream stream,FT_Memory extmemory,bdf_options_t * opts,bdf_font_t ** font)2199*37da2899SCharles.Forsyth   bdf_load_font( FT_Stream       stream,
2200*37da2899SCharles.Forsyth                  FT_Memory       extmemory,
2201*37da2899SCharles.Forsyth                  bdf_options_t*  opts,
2202*37da2899SCharles.Forsyth                  bdf_font_t*    *font )
2203*37da2899SCharles.Forsyth   {
2204*37da2899SCharles.Forsyth     unsigned long  lineno;
2205*37da2899SCharles.Forsyth     _bdf_parse_t   *p;
2206*37da2899SCharles.Forsyth 
2207*37da2899SCharles.Forsyth     FT_Memory      memory = extmemory;
2208*37da2899SCharles.Forsyth     FT_Error       error  = BDF_Err_Ok;
2209*37da2899SCharles.Forsyth 
2210*37da2899SCharles.Forsyth 
2211*37da2899SCharles.Forsyth     if ( FT_ALLOC( p, sizeof ( _bdf_parse_t ) ) )
2212*37da2899SCharles.Forsyth       goto Exit;
2213*37da2899SCharles.Forsyth 
2214*37da2899SCharles.Forsyth     memory    = NULL;
2215*37da2899SCharles.Forsyth     p->opts   = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts );
2216*37da2899SCharles.Forsyth     p->minlb  = 32767;
2217*37da2899SCharles.Forsyth     p->memory = extmemory;  /* only during font creation */
2218*37da2899SCharles.Forsyth 
2219*37da2899SCharles.Forsyth     error = _bdf_readstream( stream, _bdf_parse_start,
2220*37da2899SCharles.Forsyth                              (void *)p, &lineno );
2221*37da2899SCharles.Forsyth     if ( error )
2222*37da2899SCharles.Forsyth       goto Exit;
2223*37da2899SCharles.Forsyth 
2224*37da2899SCharles.Forsyth     if ( p->font != 0 )
2225*37da2899SCharles.Forsyth     {
2226*37da2899SCharles.Forsyth       /* If the font is not proportional, set the font's monowidth */
2227*37da2899SCharles.Forsyth       /* field to the width of the font bounding box.              */
2228*37da2899SCharles.Forsyth       memory = p->font->memory;
2229*37da2899SCharles.Forsyth 
2230*37da2899SCharles.Forsyth       if ( p->font->spacing != BDF_PROPORTIONAL )
2231*37da2899SCharles.Forsyth         p->font->monowidth = p->font->bbx.width;
2232*37da2899SCharles.Forsyth 
2233*37da2899SCharles.Forsyth       /* If the number of glyphs loaded is not that of the original count, */
2234*37da2899SCharles.Forsyth       /* indicate the difference.                                          */
2235*37da2899SCharles.Forsyth       if ( p->cnt != p->font->glyphs_used + p->font->unencoded_used )
2236*37da2899SCharles.Forsyth       {
2237*37da2899SCharles.Forsyth         FT_TRACE2(( "bdf_load_font: " ACMSG15, p->cnt,
2238*37da2899SCharles.Forsyth                     p->font->glyphs_used + p->font->unencoded_used ));
2239*37da2899SCharles.Forsyth         p->font->modified = 1;
2240*37da2899SCharles.Forsyth       }
2241*37da2899SCharles.Forsyth 
2242*37da2899SCharles.Forsyth       /* Once the font has been loaded, adjust the overall font metrics if */
2243*37da2899SCharles.Forsyth       /* necessary.                                                        */
2244*37da2899SCharles.Forsyth       if ( p->opts->correct_metrics != 0 &&
2245*37da2899SCharles.Forsyth            ( p->font->glyphs_used > 0 || p->font->unencoded_used > 0 ) )
2246*37da2899SCharles.Forsyth       {
2247*37da2899SCharles.Forsyth         if ( p->maxrb - p->minlb != p->font->bbx.width )
2248*37da2899SCharles.Forsyth         {
2249*37da2899SCharles.Forsyth           FT_TRACE2(( "bdf_load_font: " ACMSG3,
2250*37da2899SCharles.Forsyth                       p->font->bbx.width, p->maxrb - p->minlb ));
2251*37da2899SCharles.Forsyth           p->font->bbx.width = (unsigned short)( p->maxrb - p->minlb );
2252*37da2899SCharles.Forsyth           p->font->modified  = 1;
2253*37da2899SCharles.Forsyth         }
2254*37da2899SCharles.Forsyth 
2255*37da2899SCharles.Forsyth         if ( p->font->bbx.x_offset != p->minlb )
2256*37da2899SCharles.Forsyth         {
2257*37da2899SCharles.Forsyth           FT_TRACE2(( "bdf_load_font: " ACMSG4,
2258*37da2899SCharles.Forsyth                       p->font->bbx.x_offset, p->minlb ));
2259*37da2899SCharles.Forsyth           p->font->bbx.x_offset = p->minlb;
2260*37da2899SCharles.Forsyth           p->font->modified     = 1;
2261*37da2899SCharles.Forsyth         }
2262*37da2899SCharles.Forsyth 
2263*37da2899SCharles.Forsyth         if ( p->font->bbx.ascent != p->maxas )
2264*37da2899SCharles.Forsyth         {
2265*37da2899SCharles.Forsyth           FT_TRACE2(( "bdf_load_font: " ACMSG5,
2266*37da2899SCharles.Forsyth                       p->font->bbx.ascent, p->maxas ));
2267*37da2899SCharles.Forsyth           p->font->bbx.ascent = p->maxas;
2268*37da2899SCharles.Forsyth           p->font->modified   = 1;
2269*37da2899SCharles.Forsyth         }
2270*37da2899SCharles.Forsyth 
2271*37da2899SCharles.Forsyth         if ( p->font->bbx.descent != p->maxds )
2272*37da2899SCharles.Forsyth         {
2273*37da2899SCharles.Forsyth           FT_TRACE2(( "bdf_load_font: " ACMSG6,
2274*37da2899SCharles.Forsyth                       p->font->bbx.descent, p->maxds ));
2275*37da2899SCharles.Forsyth           p->font->bbx.descent  = p->maxds;
2276*37da2899SCharles.Forsyth           p->font->bbx.y_offset = (short)( -p->maxds );
2277*37da2899SCharles.Forsyth           p->font->modified     = 1;
2278*37da2899SCharles.Forsyth         }
2279*37da2899SCharles.Forsyth 
2280*37da2899SCharles.Forsyth         if ( p->maxas + p->maxds != p->font->bbx.height )
2281*37da2899SCharles.Forsyth         {
2282*37da2899SCharles.Forsyth           FT_TRACE2(( "bdf_load_font: " ACMSG7,
2283*37da2899SCharles.Forsyth                       p->font->bbx.height, p->maxas + p->maxds ));
2284*37da2899SCharles.Forsyth           p->font->bbx.height = (unsigned short)( p->maxas + p->maxds );
2285*37da2899SCharles.Forsyth         }
2286*37da2899SCharles.Forsyth 
2287*37da2899SCharles.Forsyth         if ( p->flags & _BDF_SWIDTH_ADJ )
2288*37da2899SCharles.Forsyth           FT_TRACE2(( "bdf_load_font: " ACMSG8 ));
2289*37da2899SCharles.Forsyth       }
2290*37da2899SCharles.Forsyth     }
2291*37da2899SCharles.Forsyth 
2292*37da2899SCharles.Forsyth     if ( p->flags & _BDF_START )
2293*37da2899SCharles.Forsyth     {
2294*37da2899SCharles.Forsyth       {
2295*37da2899SCharles.Forsyth         /* The ENDFONT field was never reached or did not exist. */
2296*37da2899SCharles.Forsyth         if ( !( p->flags & _BDF_GLYPHS ) )
2297*37da2899SCharles.Forsyth           /* Error happened while parsing header. */
2298*37da2899SCharles.Forsyth           FT_ERROR(( "bdf_load_font: " ERRMSG2, lineno ));
2299*37da2899SCharles.Forsyth         else
2300*37da2899SCharles.Forsyth           /* Error happened when parsing glyphs. */
2301*37da2899SCharles.Forsyth           FT_ERROR(( "bdf_load_font: " ERRMSG3, lineno ));
2302*37da2899SCharles.Forsyth       }
2303*37da2899SCharles.Forsyth     }
2304*37da2899SCharles.Forsyth 
2305*37da2899SCharles.Forsyth     /* Free up the list used during the parsing. */
2306*37da2899SCharles.Forsyth     if ( memory != NULL )
2307*37da2899SCharles.Forsyth       FT_FREE( p->list.field );
2308*37da2899SCharles.Forsyth 
2309*37da2899SCharles.Forsyth     if ( p->font != 0 )
2310*37da2899SCharles.Forsyth     {
2311*37da2899SCharles.Forsyth       /* Make sure the comments are NULL terminated if they exist. */
2312*37da2899SCharles.Forsyth       memory = p->font->memory;
2313*37da2899SCharles.Forsyth 
2314*37da2899SCharles.Forsyth       if ( p->font->comments_len > 0 ) {
2315*37da2899SCharles.Forsyth         if ( FT_RENEW_ARRAY( p->font->comments,
2316*37da2899SCharles.Forsyth                              p->font->comments_len,
2317*37da2899SCharles.Forsyth                              p->font->comments_len + 1 ) )
2318*37da2899SCharles.Forsyth           goto Exit;
2319*37da2899SCharles.Forsyth 
2320*37da2899SCharles.Forsyth         p->font->comments[p->font->comments_len] = 0;
2321*37da2899SCharles.Forsyth       }
2322*37da2899SCharles.Forsyth     }
2323*37da2899SCharles.Forsyth     else if ( error == BDF_Err_Ok )
2324*37da2899SCharles.Forsyth       error = BDF_Err_Invalid_File_Format;
2325*37da2899SCharles.Forsyth 
2326*37da2899SCharles.Forsyth     *font = p->font;
2327*37da2899SCharles.Forsyth 
2328*37da2899SCharles.Forsyth   Exit:
2329*37da2899SCharles.Forsyth     if ( p )
2330*37da2899SCharles.Forsyth     {
2331*37da2899SCharles.Forsyth       memory = extmemory;
2332*37da2899SCharles.Forsyth       FT_FREE( p );
2333*37da2899SCharles.Forsyth     }
2334*37da2899SCharles.Forsyth 
2335*37da2899SCharles.Forsyth     return error;
2336*37da2899SCharles.Forsyth   }
2337*37da2899SCharles.Forsyth 
2338*37da2899SCharles.Forsyth 
2339*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
bdf_free_font(bdf_font_t * font)2340*37da2899SCharles.Forsyth   bdf_free_font( bdf_font_t*  font )
2341*37da2899SCharles.Forsyth   {
2342*37da2899SCharles.Forsyth     bdf_property_t*  prop;
2343*37da2899SCharles.Forsyth     unsigned long    i;
2344*37da2899SCharles.Forsyth     bdf_glyph_t*     glyphs;
2345*37da2899SCharles.Forsyth     FT_Memory        memory;
2346*37da2899SCharles.Forsyth 
2347*37da2899SCharles.Forsyth 
2348*37da2899SCharles.Forsyth     if ( font == 0 )
2349*37da2899SCharles.Forsyth       return;
2350*37da2899SCharles.Forsyth 
2351*37da2899SCharles.Forsyth     memory = font->memory;
2352*37da2899SCharles.Forsyth 
2353*37da2899SCharles.Forsyth     FT_FREE( font->name );
2354*37da2899SCharles.Forsyth 
2355*37da2899SCharles.Forsyth     /* Free up the internal hash table of property names. */
2356*37da2899SCharles.Forsyth     if ( font->internal )
2357*37da2899SCharles.Forsyth     {
2358*37da2899SCharles.Forsyth       hash_free( (hashtable *)font->internal, memory );
2359*37da2899SCharles.Forsyth       FT_FREE( font->internal );
2360*37da2899SCharles.Forsyth     }
2361*37da2899SCharles.Forsyth 
2362*37da2899SCharles.Forsyth     /* Free up the comment info. */
2363*37da2899SCharles.Forsyth     FT_FREE( font->comments );
2364*37da2899SCharles.Forsyth 
2365*37da2899SCharles.Forsyth     /* Free up the properties. */
2366*37da2899SCharles.Forsyth     for ( i = 0; i < font->props_size; i++ )
2367*37da2899SCharles.Forsyth     {
2368*37da2899SCharles.Forsyth       if ( font->props[i].format == BDF_ATOM )
2369*37da2899SCharles.Forsyth         FT_FREE( font->props[i].value.atom );
2370*37da2899SCharles.Forsyth     }
2371*37da2899SCharles.Forsyth 
2372*37da2899SCharles.Forsyth     FT_FREE( font->props );
2373*37da2899SCharles.Forsyth 
2374*37da2899SCharles.Forsyth     /* Free up the character info. */
2375*37da2899SCharles.Forsyth     for ( i = 0, glyphs = font->glyphs;
2376*37da2899SCharles.Forsyth           i < font->glyphs_used; i++, glyphs++ )
2377*37da2899SCharles.Forsyth     {
2378*37da2899SCharles.Forsyth       FT_FREE( glyphs->name );
2379*37da2899SCharles.Forsyth       FT_FREE( glyphs->bitmap );
2380*37da2899SCharles.Forsyth     }
2381*37da2899SCharles.Forsyth 
2382*37da2899SCharles.Forsyth     for ( i = 0, glyphs = font->unencoded; i < font->unencoded_used;
2383*37da2899SCharles.Forsyth           i++, glyphs++ )
2384*37da2899SCharles.Forsyth     {
2385*37da2899SCharles.Forsyth       FT_FREE( glyphs->name );
2386*37da2899SCharles.Forsyth       FT_FREE( glyphs->bitmap );
2387*37da2899SCharles.Forsyth     }
2388*37da2899SCharles.Forsyth 
2389*37da2899SCharles.Forsyth     FT_FREE( font->glyphs );
2390*37da2899SCharles.Forsyth     FT_FREE( font->unencoded );
2391*37da2899SCharles.Forsyth 
2392*37da2899SCharles.Forsyth     /* Free up the overflow storage if it was used. */
2393*37da2899SCharles.Forsyth     for ( i = 0, glyphs = font->overflow.glyphs;
2394*37da2899SCharles.Forsyth           i < font->overflow.glyphs_used; i++, glyphs++ )
2395*37da2899SCharles.Forsyth     {
2396*37da2899SCharles.Forsyth       FT_FREE( glyphs->name );
2397*37da2899SCharles.Forsyth       FT_FREE( glyphs->bitmap );
2398*37da2899SCharles.Forsyth     }
2399*37da2899SCharles.Forsyth 
2400*37da2899SCharles.Forsyth     FT_FREE( font->overflow.glyphs );
2401*37da2899SCharles.Forsyth 
2402*37da2899SCharles.Forsyth     /* bdf_cleanup */
2403*37da2899SCharles.Forsyth     hash_free( &(font->proptbl), memory );
2404*37da2899SCharles.Forsyth 
2405*37da2899SCharles.Forsyth     /* Free up the user defined properties. */
2406*37da2899SCharles.Forsyth     for (prop = font->user_props, i = 0;
2407*37da2899SCharles.Forsyth          i < font->nuser_props; i++, prop++ )
2408*37da2899SCharles.Forsyth     {
2409*37da2899SCharles.Forsyth       FT_FREE( prop->name );
2410*37da2899SCharles.Forsyth       if ( prop->format == BDF_ATOM )
2411*37da2899SCharles.Forsyth         FT_FREE( prop->value.atom );
2412*37da2899SCharles.Forsyth     }
2413*37da2899SCharles.Forsyth 
2414*37da2899SCharles.Forsyth     FT_FREE( font->user_props );
2415*37da2899SCharles.Forsyth 
2416*37da2899SCharles.Forsyth     /* FREE( font ); */ /* XXX Fixme */
2417*37da2899SCharles.Forsyth   }
2418*37da2899SCharles.Forsyth 
2419*37da2899SCharles.Forsyth 
2420*37da2899SCharles.Forsyth   FT_LOCAL_DEF( bdf_property_t * )
bdf_get_font_property(bdf_font_t * font,char * name)2421*37da2899SCharles.Forsyth   bdf_get_font_property( bdf_font_t*  font,
2422*37da2899SCharles.Forsyth                          char*        name )
2423*37da2899SCharles.Forsyth   {
2424*37da2899SCharles.Forsyth     hashnode  hn;
2425*37da2899SCharles.Forsyth 
2426*37da2899SCharles.Forsyth 
2427*37da2899SCharles.Forsyth     if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 )
2428*37da2899SCharles.Forsyth       return 0;
2429*37da2899SCharles.Forsyth 
2430*37da2899SCharles.Forsyth     hn = hash_lookup( name, (hashtable *)font->internal );
2431*37da2899SCharles.Forsyth 
2432*37da2899SCharles.Forsyth     return hn ? ( font->props + (unsigned long)hn->data ) : 0;
2433*37da2899SCharles.Forsyth   }
2434*37da2899SCharles.Forsyth 
2435*37da2899SCharles.Forsyth 
2436*37da2899SCharles.Forsyth /* END */
2437