xref: /inferno-os/libfreetype/pcfread.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /*  pcfread.c
2*37da2899SCharles.Forsyth 
3*37da2899SCharles.Forsyth     FreeType font driver for pcf fonts
4*37da2899SCharles.Forsyth 
5*37da2899SCharles.Forsyth   Copyright 2000-2001, 2002 by
6*37da2899SCharles.Forsyth   Francesco Zappa Nardelli
7*37da2899SCharles.Forsyth 
8*37da2899SCharles.Forsyth Permission is hereby granted, free of charge, to any person obtaining a copy
9*37da2899SCharles.Forsyth of this software and associated documentation files (the "Software"), to deal
10*37da2899SCharles.Forsyth in the Software without restriction, including without limitation the rights
11*37da2899SCharles.Forsyth to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12*37da2899SCharles.Forsyth copies of the Software, and to permit persons to whom the Software is
13*37da2899SCharles.Forsyth furnished to do so, subject to the following conditions:
14*37da2899SCharles.Forsyth 
15*37da2899SCharles.Forsyth The above copyright notice and this permission notice shall be included in
16*37da2899SCharles.Forsyth all copies or substantial portions of the Software.
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*37da2899SCharles.Forsyth IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*37da2899SCharles.Forsyth FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21*37da2899SCharles.Forsyth AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*37da2899SCharles.Forsyth LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*37da2899SCharles.Forsyth OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24*37da2899SCharles.Forsyth THE SOFTWARE.
25*37da2899SCharles.Forsyth */
26*37da2899SCharles.Forsyth 
27*37da2899SCharles.Forsyth 
28*37da2899SCharles.Forsyth #include <ft2build.h>
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
31*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H
32*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
33*37da2899SCharles.Forsyth 
34*37da2899SCharles.Forsyth #include "pcf.h"
35*37da2899SCharles.Forsyth #include "pcfdriver.h"
36*37da2899SCharles.Forsyth 
37*37da2899SCharles.Forsyth #include "pcferror.h"
38*37da2899SCharles.Forsyth 
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth   /*************************************************************************/
41*37da2899SCharles.Forsyth   /*                                                                       */
42*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
43*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
44*37da2899SCharles.Forsyth   /* messages during execution.                                            */
45*37da2899SCharles.Forsyth   /*                                                                       */
46*37da2899SCharles.Forsyth #undef  FT_COMPONENT
47*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_pcfread
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth 
50*37da2899SCharles.Forsyth #if defined( FT_DEBUG_LEVEL_TRACE )
51*37da2899SCharles.Forsyth   static const char*  tableNames[] =
52*37da2899SCharles.Forsyth   {
53*37da2899SCharles.Forsyth     "prop", "accl", "mtrcs", "bmps", "imtrcs",
54*37da2899SCharles.Forsyth     "enc", "swidth", "names", "accel"
55*37da2899SCharles.Forsyth   };
56*37da2899SCharles.Forsyth #endif
57*37da2899SCharles.Forsyth 
58*37da2899SCharles.Forsyth 
59*37da2899SCharles.Forsyth   static
60*37da2899SCharles.Forsyth   const FT_Frame_Field  pcf_toc_header[] =
61*37da2899SCharles.Forsyth   {
62*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
63*37da2899SCharles.Forsyth #define FT_STRUCTURE  PCF_TocRec
64*37da2899SCharles.Forsyth 
65*37da2899SCharles.Forsyth     FT_FRAME_START( 8 ),
66*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE( version ),
67*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE( count ),
68*37da2899SCharles.Forsyth     FT_FRAME_END
69*37da2899SCharles.Forsyth   };
70*37da2899SCharles.Forsyth 
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth   static
73*37da2899SCharles.Forsyth   const FT_Frame_Field  pcf_table_header[] =
74*37da2899SCharles.Forsyth   {
75*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
76*37da2899SCharles.Forsyth #define FT_STRUCTURE  PCF_TableRec
77*37da2899SCharles.Forsyth 
78*37da2899SCharles.Forsyth     FT_FRAME_START( 16  ),
79*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE( type ),
80*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE( format ),
81*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE( size ),
82*37da2899SCharles.Forsyth       FT_FRAME_ULONG_LE( offset ),
83*37da2899SCharles.Forsyth     FT_FRAME_END
84*37da2899SCharles.Forsyth   };
85*37da2899SCharles.Forsyth 
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth   static FT_Error
pcf_read_TOC(FT_Stream stream,PCF_Face face)88*37da2899SCharles.Forsyth   pcf_read_TOC( FT_Stream  stream,
89*37da2899SCharles.Forsyth                 PCF_Face   face )
90*37da2899SCharles.Forsyth   {
91*37da2899SCharles.Forsyth     FT_Error   error;
92*37da2899SCharles.Forsyth     PCF_Toc    toc = &face->toc;
93*37da2899SCharles.Forsyth     PCF_Table  tables;
94*37da2899SCharles.Forsyth 
95*37da2899SCharles.Forsyth     FT_Memory  memory = FT_FACE(face)->memory;
96*37da2899SCharles.Forsyth     FT_UInt    n;
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth     if ( FT_STREAM_SEEK ( 0 )                          ||
100*37da2899SCharles.Forsyth          FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) )
101*37da2899SCharles.Forsyth       return PCF_Err_Cannot_Open_Resource;
102*37da2899SCharles.Forsyth 
103*37da2899SCharles.Forsyth     if ( toc->version != PCF_FILE_VERSION )
104*37da2899SCharles.Forsyth       return PCF_Err_Invalid_File_Format;
105*37da2899SCharles.Forsyth 
106*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
107*37da2899SCharles.Forsyth       return PCF_Err_Out_Of_Memory;
108*37da2899SCharles.Forsyth 
109*37da2899SCharles.Forsyth     tables = face->toc.tables;
110*37da2899SCharles.Forsyth     for ( n = 0; n < toc->count; n++ )
111*37da2899SCharles.Forsyth     {
112*37da2899SCharles.Forsyth       if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) )
113*37da2899SCharles.Forsyth         goto Exit;
114*37da2899SCharles.Forsyth       tables++;
115*37da2899SCharles.Forsyth     }
116*37da2899SCharles.Forsyth 
117*37da2899SCharles.Forsyth #if defined( FT_DEBUG_LEVEL_TRACE )
118*37da2899SCharles.Forsyth 
119*37da2899SCharles.Forsyth     {
120*37da2899SCharles.Forsyth       FT_UInt      i, j;
121*37da2899SCharles.Forsyth       const char*  name = "?";
122*37da2899SCharles.Forsyth 
123*37da2899SCharles.Forsyth 
124*37da2899SCharles.Forsyth       FT_TRACE4(( "Tables count: %ld\n", face->toc.count ));
125*37da2899SCharles.Forsyth       tables = face->toc.tables;
126*37da2899SCharles.Forsyth       for ( i = 0; i < toc->count; i++ )
127*37da2899SCharles.Forsyth       {
128*37da2899SCharles.Forsyth         for( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ )
129*37da2899SCharles.Forsyth           if ( tables[i].type == (FT_UInt)( 1 << j ) )
130*37da2899SCharles.Forsyth             name = tableNames[j];
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth         FT_TRACE4(( "Table %d: type=%-6s format=0x%04lX "
133*37da2899SCharles.Forsyth                     "size=0x%06lX (%8ld) offset=0x%04lX\n",
134*37da2899SCharles.Forsyth                     i, name,
135*37da2899SCharles.Forsyth                     tables[i].format,
136*37da2899SCharles.Forsyth                     tables[i].size, tables[i].size,
137*37da2899SCharles.Forsyth                     tables[i].offset ));
138*37da2899SCharles.Forsyth       }
139*37da2899SCharles.Forsyth     }
140*37da2899SCharles.Forsyth 
141*37da2899SCharles.Forsyth #endif
142*37da2899SCharles.Forsyth 
143*37da2899SCharles.Forsyth     return PCF_Err_Ok;
144*37da2899SCharles.Forsyth 
145*37da2899SCharles.Forsyth   Exit:
146*37da2899SCharles.Forsyth     FT_FREE( face->toc.tables );
147*37da2899SCharles.Forsyth     return error;
148*37da2899SCharles.Forsyth   }
149*37da2899SCharles.Forsyth 
150*37da2899SCharles.Forsyth 
151*37da2899SCharles.Forsyth   static
152*37da2899SCharles.Forsyth   const FT_Frame_Field  pcf_metric_header[] =
153*37da2899SCharles.Forsyth   {
154*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
155*37da2899SCharles.Forsyth #define FT_STRUCTURE  PCF_MetricRec
156*37da2899SCharles.Forsyth 
157*37da2899SCharles.Forsyth     FT_FRAME_START( 12 ),
158*37da2899SCharles.Forsyth       FT_FRAME_SHORT_LE( leftSideBearing ),
159*37da2899SCharles.Forsyth       FT_FRAME_SHORT_LE( rightSideBearing ),
160*37da2899SCharles.Forsyth       FT_FRAME_SHORT_LE( characterWidth ),
161*37da2899SCharles.Forsyth       FT_FRAME_SHORT_LE( ascent ),
162*37da2899SCharles.Forsyth       FT_FRAME_SHORT_LE( descent ),
163*37da2899SCharles.Forsyth       FT_FRAME_SHORT_LE( attributes ),
164*37da2899SCharles.Forsyth     FT_FRAME_END
165*37da2899SCharles.Forsyth   };
166*37da2899SCharles.Forsyth 
167*37da2899SCharles.Forsyth 
168*37da2899SCharles.Forsyth   static
169*37da2899SCharles.Forsyth   const FT_Frame_Field  pcf_metric_msb_header[] =
170*37da2899SCharles.Forsyth   {
171*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
172*37da2899SCharles.Forsyth #define FT_STRUCTURE  PCF_MetricRec
173*37da2899SCharles.Forsyth 
174*37da2899SCharles.Forsyth     FT_FRAME_START( 12 ),
175*37da2899SCharles.Forsyth       FT_FRAME_SHORT( leftSideBearing ),
176*37da2899SCharles.Forsyth       FT_FRAME_SHORT( rightSideBearing ),
177*37da2899SCharles.Forsyth       FT_FRAME_SHORT( characterWidth ),
178*37da2899SCharles.Forsyth       FT_FRAME_SHORT( ascent ),
179*37da2899SCharles.Forsyth       FT_FRAME_SHORT( descent ),
180*37da2899SCharles.Forsyth       FT_FRAME_SHORT( attributes ),
181*37da2899SCharles.Forsyth     FT_FRAME_END
182*37da2899SCharles.Forsyth   };
183*37da2899SCharles.Forsyth 
184*37da2899SCharles.Forsyth 
185*37da2899SCharles.Forsyth   static
186*37da2899SCharles.Forsyth   const FT_Frame_Field  pcf_compressed_metric_header[] =
187*37da2899SCharles.Forsyth   {
188*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
189*37da2899SCharles.Forsyth #define FT_STRUCTURE  PCF_Compressed_MetricRec
190*37da2899SCharles.Forsyth 
191*37da2899SCharles.Forsyth     FT_FRAME_START( 5 ),
192*37da2899SCharles.Forsyth       FT_FRAME_BYTE( leftSideBearing ),
193*37da2899SCharles.Forsyth       FT_FRAME_BYTE( rightSideBearing ),
194*37da2899SCharles.Forsyth       FT_FRAME_BYTE( characterWidth ),
195*37da2899SCharles.Forsyth       FT_FRAME_BYTE( ascent ),
196*37da2899SCharles.Forsyth       FT_FRAME_BYTE( descent ),
197*37da2899SCharles.Forsyth     FT_FRAME_END
198*37da2899SCharles.Forsyth   };
199*37da2899SCharles.Forsyth 
200*37da2899SCharles.Forsyth 
201*37da2899SCharles.Forsyth   static FT_Error
pcf_get_metric(FT_Stream stream,FT_ULong format,PCF_Metric metric)202*37da2899SCharles.Forsyth   pcf_get_metric( FT_Stream   stream,
203*37da2899SCharles.Forsyth                   FT_ULong    format,
204*37da2899SCharles.Forsyth                   PCF_Metric  metric )
205*37da2899SCharles.Forsyth   {
206*37da2899SCharles.Forsyth     FT_Error  error = PCF_Err_Ok;
207*37da2899SCharles.Forsyth 
208*37da2899SCharles.Forsyth 
209*37da2899SCharles.Forsyth     if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
210*37da2899SCharles.Forsyth     {
211*37da2899SCharles.Forsyth       const FT_Frame_Field*  fields;
212*37da2899SCharles.Forsyth 
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth       /* parsing normal metrics */
215*37da2899SCharles.Forsyth       fields = PCF_BYTE_ORDER( format ) == MSBFirst
216*37da2899SCharles.Forsyth                ? pcf_metric_msb_header
217*37da2899SCharles.Forsyth                : pcf_metric_header;
218*37da2899SCharles.Forsyth 
219*37da2899SCharles.Forsyth       /* the following sets 'error' but doesn't return in case of failure */
220*37da2899SCharles.Forsyth       (void)FT_STREAM_READ_FIELDS( fields, metric );
221*37da2899SCharles.Forsyth     }
222*37da2899SCharles.Forsyth     else
223*37da2899SCharles.Forsyth     {
224*37da2899SCharles.Forsyth       PCF_Compressed_MetricRec  compr;
225*37da2899SCharles.Forsyth 
226*37da2899SCharles.Forsyth 
227*37da2899SCharles.Forsyth       /* parsing compressed metrics */
228*37da2899SCharles.Forsyth       if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) )
229*37da2899SCharles.Forsyth         goto Exit;
230*37da2899SCharles.Forsyth 
231*37da2899SCharles.Forsyth       metric->leftSideBearing  = (FT_Short)( compr.leftSideBearing  - 0x80 );
232*37da2899SCharles.Forsyth       metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 );
233*37da2899SCharles.Forsyth       metric->characterWidth   = (FT_Short)( compr.characterWidth   - 0x80 );
234*37da2899SCharles.Forsyth       metric->ascent           = (FT_Short)( compr.ascent           - 0x80 );
235*37da2899SCharles.Forsyth       metric->descent          = (FT_Short)( compr.descent          - 0x80 );
236*37da2899SCharles.Forsyth       metric->attributes       = 0;
237*37da2899SCharles.Forsyth     }
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
pcf_seek_to_table_type(FT_Stream stream,PCF_Table tables,FT_Int ntables,FT_ULong type,FT_ULong * aformat,FT_ULong * asize)245*37da2899SCharles.Forsyth   pcf_seek_to_table_type( FT_Stream  stream,
246*37da2899SCharles.Forsyth                           PCF_Table  tables,
247*37da2899SCharles.Forsyth                           FT_Int     ntables,
248*37da2899SCharles.Forsyth                           FT_ULong   type,
249*37da2899SCharles.Forsyth                           FT_ULong  *aformat,
250*37da2899SCharles.Forsyth                           FT_ULong  *asize )
251*37da2899SCharles.Forsyth   {
252*37da2899SCharles.Forsyth     FT_Error  error = 0;
253*37da2899SCharles.Forsyth     FT_Int    i;
254*37da2899SCharles.Forsyth 
255*37da2899SCharles.Forsyth 
256*37da2899SCharles.Forsyth     for ( i = 0; i < ntables; i++ )
257*37da2899SCharles.Forsyth       if ( tables[i].type == type )
258*37da2899SCharles.Forsyth       {
259*37da2899SCharles.Forsyth         if ( stream->pos > tables[i].offset )
260*37da2899SCharles.Forsyth           return PCF_Err_Invalid_Stream_Skip;
261*37da2899SCharles.Forsyth 
262*37da2899SCharles.Forsyth         if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) )
263*37da2899SCharles.Forsyth           return PCF_Err_Invalid_Stream_Skip;
264*37da2899SCharles.Forsyth 
265*37da2899SCharles.Forsyth         *asize   = tables[i].size;  /* unused - to be removed */
266*37da2899SCharles.Forsyth         *aformat = tables[i].format;
267*37da2899SCharles.Forsyth 
268*37da2899SCharles.Forsyth         return PCF_Err_Ok;
269*37da2899SCharles.Forsyth       }
270*37da2899SCharles.Forsyth 
271*37da2899SCharles.Forsyth     return PCF_Err_Invalid_File_Format;
272*37da2899SCharles.Forsyth   }
273*37da2899SCharles.Forsyth 
274*37da2899SCharles.Forsyth 
275*37da2899SCharles.Forsyth   static FT_Bool
pcf_has_table_type(PCF_Table tables,FT_Int ntables,FT_ULong type)276*37da2899SCharles.Forsyth   pcf_has_table_type( PCF_Table  tables,
277*37da2899SCharles.Forsyth                       FT_Int     ntables,
278*37da2899SCharles.Forsyth                       FT_ULong   type )
279*37da2899SCharles.Forsyth   {
280*37da2899SCharles.Forsyth     FT_Int  i;
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth 
283*37da2899SCharles.Forsyth     for ( i = 0; i < ntables; i++ )
284*37da2899SCharles.Forsyth       if ( tables[i].type == type )
285*37da2899SCharles.Forsyth         return TRUE;
286*37da2899SCharles.Forsyth 
287*37da2899SCharles.Forsyth     return FALSE;
288*37da2899SCharles.Forsyth   }
289*37da2899SCharles.Forsyth 
290*37da2899SCharles.Forsyth 
291*37da2899SCharles.Forsyth   static
292*37da2899SCharles.Forsyth   const FT_Frame_Field  pcf_property_header[] =
293*37da2899SCharles.Forsyth   {
294*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
295*37da2899SCharles.Forsyth #define FT_STRUCTURE  PCF_ParsePropertyRec
296*37da2899SCharles.Forsyth 
297*37da2899SCharles.Forsyth     FT_FRAME_START( 9 ),
298*37da2899SCharles.Forsyth       FT_FRAME_LONG_LE( name ),
299*37da2899SCharles.Forsyth       FT_FRAME_BYTE   ( isString ),
300*37da2899SCharles.Forsyth       FT_FRAME_LONG_LE( value ),
301*37da2899SCharles.Forsyth     FT_FRAME_END
302*37da2899SCharles.Forsyth   };
303*37da2899SCharles.Forsyth 
304*37da2899SCharles.Forsyth 
305*37da2899SCharles.Forsyth   static
306*37da2899SCharles.Forsyth   const FT_Frame_Field  pcf_property_msb_header[] =
307*37da2899SCharles.Forsyth   {
308*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
309*37da2899SCharles.Forsyth #define FT_STRUCTURE  PCF_ParsePropertyRec
310*37da2899SCharles.Forsyth 
311*37da2899SCharles.Forsyth     FT_FRAME_START( 9 ),
312*37da2899SCharles.Forsyth       FT_FRAME_LONG( name ),
313*37da2899SCharles.Forsyth       FT_FRAME_BYTE( isString ),
314*37da2899SCharles.Forsyth       FT_FRAME_LONG( value ),
315*37da2899SCharles.Forsyth     FT_FRAME_END
316*37da2899SCharles.Forsyth   };
317*37da2899SCharles.Forsyth 
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth   static PCF_Property
pcf_find_property(PCF_Face face,const FT_String * prop)320*37da2899SCharles.Forsyth   pcf_find_property( PCF_Face          face,
321*37da2899SCharles.Forsyth                      const FT_String*  prop )
322*37da2899SCharles.Forsyth   {
323*37da2899SCharles.Forsyth     PCF_Property  properties = face->properties;
324*37da2899SCharles.Forsyth     FT_Bool       found      = 0;
325*37da2899SCharles.Forsyth     int           i;
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth 
328*37da2899SCharles.Forsyth     for ( i = 0 ; i < face->nprops && !found; i++ )
329*37da2899SCharles.Forsyth     {
330*37da2899SCharles.Forsyth       if ( !ft_strcmp( properties[i].name, prop ) )
331*37da2899SCharles.Forsyth         found = 1;
332*37da2899SCharles.Forsyth     }
333*37da2899SCharles.Forsyth 
334*37da2899SCharles.Forsyth     if ( found )
335*37da2899SCharles.Forsyth       return properties + i - 1;
336*37da2899SCharles.Forsyth     else
337*37da2899SCharles.Forsyth       return NULL;
338*37da2899SCharles.Forsyth   }
339*37da2899SCharles.Forsyth 
340*37da2899SCharles.Forsyth 
341*37da2899SCharles.Forsyth   static FT_Error
pcf_get_properties(FT_Stream stream,PCF_Face face)342*37da2899SCharles.Forsyth   pcf_get_properties( FT_Stream  stream,
343*37da2899SCharles.Forsyth                       PCF_Face   face )
344*37da2899SCharles.Forsyth   {
345*37da2899SCharles.Forsyth     PCF_ParseProperty  props      = 0;
346*37da2899SCharles.Forsyth     PCF_Property       properties = 0;
347*37da2899SCharles.Forsyth     FT_Int             nprops, i;
348*37da2899SCharles.Forsyth     FT_ULong           format, size;
349*37da2899SCharles.Forsyth     FT_Error           error;
350*37da2899SCharles.Forsyth     FT_Memory          memory     = FT_FACE(face)->memory;
351*37da2899SCharles.Forsyth     FT_ULong           string_size;
352*37da2899SCharles.Forsyth     FT_String*         strings    = 0;
353*37da2899SCharles.Forsyth 
354*37da2899SCharles.Forsyth 
355*37da2899SCharles.Forsyth     error = pcf_seek_to_table_type( stream,
356*37da2899SCharles.Forsyth                                     face->toc.tables,
357*37da2899SCharles.Forsyth                                     face->toc.count,
358*37da2899SCharles.Forsyth                                     PCF_PROPERTIES,
359*37da2899SCharles.Forsyth                                     &format,
360*37da2899SCharles.Forsyth                                     &size );
361*37da2899SCharles.Forsyth     if ( error )
362*37da2899SCharles.Forsyth       goto Bail;
363*37da2899SCharles.Forsyth 
364*37da2899SCharles.Forsyth     if ( FT_READ_ULONG_LE( format ) )
365*37da2899SCharles.Forsyth       goto Bail;
366*37da2899SCharles.Forsyth 
367*37da2899SCharles.Forsyth     FT_TRACE4(( "get_prop: format = %ld\n", format ));
368*37da2899SCharles.Forsyth 
369*37da2899SCharles.Forsyth     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
370*37da2899SCharles.Forsyth       goto Bail;
371*37da2899SCharles.Forsyth 
372*37da2899SCharles.Forsyth     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
373*37da2899SCharles.Forsyth       (void)FT_READ_ULONG( nprops );
374*37da2899SCharles.Forsyth     else
375*37da2899SCharles.Forsyth       (void)FT_READ_ULONG_LE( nprops );
376*37da2899SCharles.Forsyth     if ( error )
377*37da2899SCharles.Forsyth       goto Bail;
378*37da2899SCharles.Forsyth 
379*37da2899SCharles.Forsyth     FT_TRACE4(( "get_prop: nprop = %d\n", nprops ));
380*37da2899SCharles.Forsyth 
381*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( props, nprops ) )
382*37da2899SCharles.Forsyth       goto Bail;
383*37da2899SCharles.Forsyth 
384*37da2899SCharles.Forsyth     for ( i = 0; i < nprops; i++ )
385*37da2899SCharles.Forsyth     {
386*37da2899SCharles.Forsyth       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
387*37da2899SCharles.Forsyth       {
388*37da2899SCharles.Forsyth         if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) )
389*37da2899SCharles.Forsyth           goto Bail;
390*37da2899SCharles.Forsyth       }
391*37da2899SCharles.Forsyth       else
392*37da2899SCharles.Forsyth       {
393*37da2899SCharles.Forsyth         if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) )
394*37da2899SCharles.Forsyth           goto Bail;
395*37da2899SCharles.Forsyth       }
396*37da2899SCharles.Forsyth     }
397*37da2899SCharles.Forsyth 
398*37da2899SCharles.Forsyth     /* pad the property array                                            */
399*37da2899SCharles.Forsyth     /*                                                                   */
400*37da2899SCharles.Forsyth     /* clever here - nprops is the same as the number of odd-units read, */
401*37da2899SCharles.Forsyth     /* as only isStringProp are odd length   (Keith Packard)             */
402*37da2899SCharles.Forsyth     /*                                                                   */
403*37da2899SCharles.Forsyth     if ( nprops & 3 )
404*37da2899SCharles.Forsyth     {
405*37da2899SCharles.Forsyth       i = 4 - ( nprops & 3 );
406*37da2899SCharles.Forsyth       FT_Stream_Skip( stream, i );
407*37da2899SCharles.Forsyth     }
408*37da2899SCharles.Forsyth 
409*37da2899SCharles.Forsyth     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
410*37da2899SCharles.Forsyth       (void)FT_READ_ULONG( string_size );
411*37da2899SCharles.Forsyth     else
412*37da2899SCharles.Forsyth       (void)FT_READ_ULONG_LE( string_size );
413*37da2899SCharles.Forsyth     if ( error )
414*37da2899SCharles.Forsyth       goto Bail;
415*37da2899SCharles.Forsyth 
416*37da2899SCharles.Forsyth     FT_TRACE4(( "get_prop: string_size = %ld\n", string_size ));
417*37da2899SCharles.Forsyth 
418*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( strings, string_size ) )
419*37da2899SCharles.Forsyth       goto Bail;
420*37da2899SCharles.Forsyth 
421*37da2899SCharles.Forsyth     error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );
422*37da2899SCharles.Forsyth     if ( error )
423*37da2899SCharles.Forsyth       goto Bail;
424*37da2899SCharles.Forsyth 
425*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( properties, nprops ) )
426*37da2899SCharles.Forsyth       goto Bail;
427*37da2899SCharles.Forsyth 
428*37da2899SCharles.Forsyth     for ( i = 0; i < nprops; i++ )
429*37da2899SCharles.Forsyth     {
430*37da2899SCharles.Forsyth       /* XXX: make atom */
431*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( properties[i].name,
432*37da2899SCharles.Forsyth                          ft_strlen( strings + props[i].name ) + 1 ) )
433*37da2899SCharles.Forsyth         goto Bail;
434*37da2899SCharles.Forsyth       ft_strcpy( properties[i].name,strings + props[i].name );
435*37da2899SCharles.Forsyth 
436*37da2899SCharles.Forsyth       properties[i].isString = props[i].isString;
437*37da2899SCharles.Forsyth 
438*37da2899SCharles.Forsyth       if ( props[i].isString )
439*37da2899SCharles.Forsyth       {
440*37da2899SCharles.Forsyth         if ( FT_NEW_ARRAY( properties[i].value.atom,
441*37da2899SCharles.Forsyth                            ft_strlen( strings + props[i].value ) + 1 ) )
442*37da2899SCharles.Forsyth           goto Bail;
443*37da2899SCharles.Forsyth         ft_strcpy( properties[i].value.atom, strings + props[i].value );
444*37da2899SCharles.Forsyth       }
445*37da2899SCharles.Forsyth       else
446*37da2899SCharles.Forsyth         properties[i].value.integer = props[i].value;
447*37da2899SCharles.Forsyth     }
448*37da2899SCharles.Forsyth 
449*37da2899SCharles.Forsyth     face->properties = properties;
450*37da2899SCharles.Forsyth     face->nprops = nprops;
451*37da2899SCharles.Forsyth 
452*37da2899SCharles.Forsyth     FT_FREE( props );
453*37da2899SCharles.Forsyth     FT_FREE( strings );
454*37da2899SCharles.Forsyth 
455*37da2899SCharles.Forsyth     return PCF_Err_Ok;
456*37da2899SCharles.Forsyth 
457*37da2899SCharles.Forsyth   Bail:
458*37da2899SCharles.Forsyth     FT_FREE( props );
459*37da2899SCharles.Forsyth     FT_FREE( strings );
460*37da2899SCharles.Forsyth 
461*37da2899SCharles.Forsyth     return error;
462*37da2899SCharles.Forsyth   }
463*37da2899SCharles.Forsyth 
464*37da2899SCharles.Forsyth 
465*37da2899SCharles.Forsyth   static FT_Error
pcf_get_metrics(FT_Stream stream,PCF_Face face)466*37da2899SCharles.Forsyth   pcf_get_metrics( FT_Stream  stream,
467*37da2899SCharles.Forsyth                    PCF_Face   face )
468*37da2899SCharles.Forsyth   {
469*37da2899SCharles.Forsyth     FT_Error    error    = PCF_Err_Ok;
470*37da2899SCharles.Forsyth     FT_Memory   memory   = FT_FACE(face)->memory;
471*37da2899SCharles.Forsyth     FT_ULong    format   = 0;
472*37da2899SCharles.Forsyth     FT_ULong    size     = 0;
473*37da2899SCharles.Forsyth     PCF_Metric  metrics  = 0;
474*37da2899SCharles.Forsyth     int         i;
475*37da2899SCharles.Forsyth     int         nmetrics = -1;
476*37da2899SCharles.Forsyth 
477*37da2899SCharles.Forsyth 
478*37da2899SCharles.Forsyth     error = pcf_seek_to_table_type( stream,
479*37da2899SCharles.Forsyth                                     face->toc.tables,
480*37da2899SCharles.Forsyth                                     face->toc.count,
481*37da2899SCharles.Forsyth                                     PCF_METRICS,
482*37da2899SCharles.Forsyth                                     &format,
483*37da2899SCharles.Forsyth                                     &size );
484*37da2899SCharles.Forsyth     if ( error )
485*37da2899SCharles.Forsyth       return error;
486*37da2899SCharles.Forsyth 
487*37da2899SCharles.Forsyth     error = FT_READ_ULONG_LE( format );
488*37da2899SCharles.Forsyth 
489*37da2899SCharles.Forsyth     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT )     &&
490*37da2899SCharles.Forsyth          !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
491*37da2899SCharles.Forsyth       return PCF_Err_Invalid_File_Format;
492*37da2899SCharles.Forsyth 
493*37da2899SCharles.Forsyth     if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
494*37da2899SCharles.Forsyth     {
495*37da2899SCharles.Forsyth       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
496*37da2899SCharles.Forsyth         (void)FT_READ_ULONG( nmetrics );
497*37da2899SCharles.Forsyth       else
498*37da2899SCharles.Forsyth         (void)FT_READ_ULONG_LE( nmetrics );
499*37da2899SCharles.Forsyth     }
500*37da2899SCharles.Forsyth     else
501*37da2899SCharles.Forsyth     {
502*37da2899SCharles.Forsyth       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
503*37da2899SCharles.Forsyth         (void)FT_READ_USHORT( nmetrics );
504*37da2899SCharles.Forsyth       else
505*37da2899SCharles.Forsyth         (void)FT_READ_USHORT_LE( nmetrics );
506*37da2899SCharles.Forsyth     }
507*37da2899SCharles.Forsyth     if ( error || nmetrics == -1 )
508*37da2899SCharles.Forsyth       return PCF_Err_Invalid_File_Format;
509*37da2899SCharles.Forsyth 
510*37da2899SCharles.Forsyth     face->nmetrics = nmetrics;
511*37da2899SCharles.Forsyth 
512*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )
513*37da2899SCharles.Forsyth       return PCF_Err_Out_Of_Memory;
514*37da2899SCharles.Forsyth 
515*37da2899SCharles.Forsyth     metrics = face->metrics;
516*37da2899SCharles.Forsyth     for ( i = 0; i < nmetrics; i++ )
517*37da2899SCharles.Forsyth     {
518*37da2899SCharles.Forsyth       pcf_get_metric( stream, format, metrics + i );
519*37da2899SCharles.Forsyth 
520*37da2899SCharles.Forsyth       metrics[i].bits = 0;
521*37da2899SCharles.Forsyth 
522*37da2899SCharles.Forsyth       FT_TRACE4(( "%d : width=%d, "
523*37da2899SCharles.Forsyth                   "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
524*37da2899SCharles.Forsyth                   i,
525*37da2899SCharles.Forsyth                   ( metrics + i )->characterWidth,
526*37da2899SCharles.Forsyth                   ( metrics + i )->leftSideBearing,
527*37da2899SCharles.Forsyth                   ( metrics + i )->rightSideBearing,
528*37da2899SCharles.Forsyth                   ( metrics + i )->ascent,
529*37da2899SCharles.Forsyth                   ( metrics + i )->descent,
530*37da2899SCharles.Forsyth                   ( metrics + i )->attributes ));
531*37da2899SCharles.Forsyth 
532*37da2899SCharles.Forsyth       if ( error )
533*37da2899SCharles.Forsyth         break;
534*37da2899SCharles.Forsyth     }
535*37da2899SCharles.Forsyth 
536*37da2899SCharles.Forsyth     if ( error )
537*37da2899SCharles.Forsyth       FT_FREE( face->metrics );
538*37da2899SCharles.Forsyth     return error;
539*37da2899SCharles.Forsyth   }
540*37da2899SCharles.Forsyth 
541*37da2899SCharles.Forsyth 
542*37da2899SCharles.Forsyth   static FT_Error
pcf_get_bitmaps(FT_Stream stream,PCF_Face face)543*37da2899SCharles.Forsyth   pcf_get_bitmaps( FT_Stream  stream,
544*37da2899SCharles.Forsyth                    PCF_Face   face )
545*37da2899SCharles.Forsyth   {
546*37da2899SCharles.Forsyth     FT_Error   error  = PCF_Err_Ok;
547*37da2899SCharles.Forsyth     FT_Memory  memory = FT_FACE(face)->memory;
548*37da2899SCharles.Forsyth     FT_Long*   offsets;
549*37da2899SCharles.Forsyth     FT_Long    bitmapSizes[GLYPHPADOPTIONS];
550*37da2899SCharles.Forsyth     FT_ULong   format, size;
551*37da2899SCharles.Forsyth     int        nbitmaps, i, sizebitmaps = 0;
552*37da2899SCharles.Forsyth     char*      bitmaps;
553*37da2899SCharles.Forsyth 
554*37da2899SCharles.Forsyth 
555*37da2899SCharles.Forsyth     error = pcf_seek_to_table_type( stream,
556*37da2899SCharles.Forsyth                                     face->toc.tables,
557*37da2899SCharles.Forsyth                                     face->toc.count,
558*37da2899SCharles.Forsyth                                     PCF_BITMAPS,
559*37da2899SCharles.Forsyth                                     &format,
560*37da2899SCharles.Forsyth                                     &size );
561*37da2899SCharles.Forsyth     if ( error )
562*37da2899SCharles.Forsyth       return error;
563*37da2899SCharles.Forsyth 
564*37da2899SCharles.Forsyth     error = FT_Stream_EnterFrame( stream, 8 );
565*37da2899SCharles.Forsyth     if ( error )
566*37da2899SCharles.Forsyth       return error;
567*37da2899SCharles.Forsyth 
568*37da2899SCharles.Forsyth     format = FT_GET_ULONG_LE();
569*37da2899SCharles.Forsyth     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
570*37da2899SCharles.Forsyth       nbitmaps  = FT_GET_ULONG();
571*37da2899SCharles.Forsyth     else
572*37da2899SCharles.Forsyth       nbitmaps  = FT_GET_ULONG_LE();
573*37da2899SCharles.Forsyth 
574*37da2899SCharles.Forsyth     FT_Stream_ExitFrame( stream );
575*37da2899SCharles.Forsyth 
576*37da2899SCharles.Forsyth     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
577*37da2899SCharles.Forsyth       return PCF_Err_Invalid_File_Format;
578*37da2899SCharles.Forsyth 
579*37da2899SCharles.Forsyth     if ( nbitmaps != face->nmetrics )
580*37da2899SCharles.Forsyth       return PCF_Err_Invalid_File_Format;
581*37da2899SCharles.Forsyth 
582*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
583*37da2899SCharles.Forsyth       return error;
584*37da2899SCharles.Forsyth 
585*37da2899SCharles.Forsyth     for ( i = 0; i < nbitmaps; i++ )
586*37da2899SCharles.Forsyth     {
587*37da2899SCharles.Forsyth       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
588*37da2899SCharles.Forsyth         (void)FT_READ_LONG( offsets[i] );
589*37da2899SCharles.Forsyth       else
590*37da2899SCharles.Forsyth         (void)FT_READ_LONG_LE( offsets[i] );
591*37da2899SCharles.Forsyth 
592*37da2899SCharles.Forsyth       FT_TRACE4(( "bitmap %d is at offset %ld\n", i, offsets[i] ));
593*37da2899SCharles.Forsyth     }
594*37da2899SCharles.Forsyth     if ( error )
595*37da2899SCharles.Forsyth       goto Bail;
596*37da2899SCharles.Forsyth 
597*37da2899SCharles.Forsyth     for ( i = 0; i < GLYPHPADOPTIONS; i++ )
598*37da2899SCharles.Forsyth     {
599*37da2899SCharles.Forsyth       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
600*37da2899SCharles.Forsyth         (void)FT_READ_LONG( bitmapSizes[i] );
601*37da2899SCharles.Forsyth       else
602*37da2899SCharles.Forsyth         (void)FT_READ_LONG_LE( bitmapSizes[i] );
603*37da2899SCharles.Forsyth       if ( error )
604*37da2899SCharles.Forsyth         goto Bail;
605*37da2899SCharles.Forsyth 
606*37da2899SCharles.Forsyth       sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
607*37da2899SCharles.Forsyth 
608*37da2899SCharles.Forsyth       FT_TRACE4(( "padding %d implies a size of %ld\n", i, bitmapSizes[i] ));
609*37da2899SCharles.Forsyth     }
610*37da2899SCharles.Forsyth 
611*37da2899SCharles.Forsyth     FT_TRACE4(( "  %d bitmaps, padding index %ld\n",
612*37da2899SCharles.Forsyth                 nbitmaps,
613*37da2899SCharles.Forsyth                 PCF_GLYPH_PAD_INDEX( format ) ));
614*37da2899SCharles.Forsyth     FT_TRACE4(( "bitmap size = %d\n", sizebitmaps ));
615*37da2899SCharles.Forsyth 
616*37da2899SCharles.Forsyth     FT_UNUSED( sizebitmaps );       /* only used for debugging */
617*37da2899SCharles.Forsyth 
618*37da2899SCharles.Forsyth     for ( i = 0; i < nbitmaps; i++ )
619*37da2899SCharles.Forsyth       face->metrics[i].bits = stream->pos + offsets[i];
620*37da2899SCharles.Forsyth 
621*37da2899SCharles.Forsyth     face->bitmapsFormat = format;
622*37da2899SCharles.Forsyth 
623*37da2899SCharles.Forsyth     FT_FREE ( offsets );
624*37da2899SCharles.Forsyth     return error;
625*37da2899SCharles.Forsyth 
626*37da2899SCharles.Forsyth   Bail:
627*37da2899SCharles.Forsyth     FT_FREE ( offsets );
628*37da2899SCharles.Forsyth     FT_FREE ( bitmaps );
629*37da2899SCharles.Forsyth     return error;
630*37da2899SCharles.Forsyth   }
631*37da2899SCharles.Forsyth 
632*37da2899SCharles.Forsyth 
633*37da2899SCharles.Forsyth   static FT_Error
pcf_get_encodings(FT_Stream stream,PCF_Face face)634*37da2899SCharles.Forsyth   pcf_get_encodings( FT_Stream  stream,
635*37da2899SCharles.Forsyth                      PCF_Face   face )
636*37da2899SCharles.Forsyth   {
637*37da2899SCharles.Forsyth     FT_Error      error   = PCF_Err_Ok;
638*37da2899SCharles.Forsyth     FT_Memory     memory  = FT_FACE(face)->memory;
639*37da2899SCharles.Forsyth     FT_ULong      format, size;
640*37da2899SCharles.Forsyth     int           firstCol, lastCol;
641*37da2899SCharles.Forsyth     int           firstRow, lastRow;
642*37da2899SCharles.Forsyth     int           nencoding, encodingOffset;
643*37da2899SCharles.Forsyth     int           i, j;
644*37da2899SCharles.Forsyth     PCF_Encoding  tmpEncoding, encoding = 0;
645*37da2899SCharles.Forsyth 
646*37da2899SCharles.Forsyth 
647*37da2899SCharles.Forsyth     error = pcf_seek_to_table_type( stream,
648*37da2899SCharles.Forsyth                                     face->toc.tables,
649*37da2899SCharles.Forsyth                                     face->toc.count,
650*37da2899SCharles.Forsyth                                     PCF_BDF_ENCODINGS,
651*37da2899SCharles.Forsyth                                     &format,
652*37da2899SCharles.Forsyth                                     &size );
653*37da2899SCharles.Forsyth     if ( error )
654*37da2899SCharles.Forsyth       return error;
655*37da2899SCharles.Forsyth 
656*37da2899SCharles.Forsyth     error = FT_Stream_EnterFrame( stream, 14 );
657*37da2899SCharles.Forsyth     if ( error )
658*37da2899SCharles.Forsyth       return error;
659*37da2899SCharles.Forsyth 
660*37da2899SCharles.Forsyth     format = FT_GET_ULONG_LE();
661*37da2899SCharles.Forsyth 
662*37da2899SCharles.Forsyth     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
663*37da2899SCharles.Forsyth     {
664*37da2899SCharles.Forsyth       firstCol          = FT_GET_SHORT();
665*37da2899SCharles.Forsyth       lastCol           = FT_GET_SHORT();
666*37da2899SCharles.Forsyth       firstRow          = FT_GET_SHORT();
667*37da2899SCharles.Forsyth       lastRow           = FT_GET_SHORT();
668*37da2899SCharles.Forsyth       face->defaultChar = FT_GET_SHORT();
669*37da2899SCharles.Forsyth     }
670*37da2899SCharles.Forsyth     else
671*37da2899SCharles.Forsyth     {
672*37da2899SCharles.Forsyth       firstCol          = FT_GET_SHORT_LE();
673*37da2899SCharles.Forsyth       lastCol           = FT_GET_SHORT_LE();
674*37da2899SCharles.Forsyth       firstRow          = FT_GET_SHORT_LE();
675*37da2899SCharles.Forsyth       lastRow           = FT_GET_SHORT_LE();
676*37da2899SCharles.Forsyth       face->defaultChar = FT_GET_SHORT_LE();
677*37da2899SCharles.Forsyth     }
678*37da2899SCharles.Forsyth 
679*37da2899SCharles.Forsyth     FT_Stream_ExitFrame( stream );
680*37da2899SCharles.Forsyth 
681*37da2899SCharles.Forsyth     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
682*37da2899SCharles.Forsyth       return PCF_Err_Invalid_File_Format;
683*37da2899SCharles.Forsyth 
684*37da2899SCharles.Forsyth     FT_TRACE4(( "enc: firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
685*37da2899SCharles.Forsyth                 firstCol, lastCol, firstRow, lastRow ));
686*37da2899SCharles.Forsyth 
687*37da2899SCharles.Forsyth     nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );
688*37da2899SCharles.Forsyth 
689*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) )
690*37da2899SCharles.Forsyth       return PCF_Err_Out_Of_Memory;
691*37da2899SCharles.Forsyth 
692*37da2899SCharles.Forsyth     error = FT_Stream_EnterFrame( stream, 2 * nencoding );
693*37da2899SCharles.Forsyth     if ( error )
694*37da2899SCharles.Forsyth       goto Bail;
695*37da2899SCharles.Forsyth 
696*37da2899SCharles.Forsyth     for ( i = 0, j = 0 ; i < nencoding; i++ )
697*37da2899SCharles.Forsyth     {
698*37da2899SCharles.Forsyth       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
699*37da2899SCharles.Forsyth         encodingOffset = FT_GET_SHORT();
700*37da2899SCharles.Forsyth       else
701*37da2899SCharles.Forsyth         encodingOffset = FT_GET_SHORT_LE();
702*37da2899SCharles.Forsyth 
703*37da2899SCharles.Forsyth       if ( encodingOffset != -1 )
704*37da2899SCharles.Forsyth       {
705*37da2899SCharles.Forsyth         tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
706*37da2899SCharles.Forsyth                                  firstRow ) * 256 ) +
707*37da2899SCharles.Forsyth                                ( ( i % ( lastCol - firstCol + 1 ) ) +
708*37da2899SCharles.Forsyth                                  firstCol );
709*37da2899SCharles.Forsyth 
710*37da2899SCharles.Forsyth         tmpEncoding[j].glyph = (FT_Short)encodingOffset;
711*37da2899SCharles.Forsyth         j++;
712*37da2899SCharles.Forsyth       }
713*37da2899SCharles.Forsyth 
714*37da2899SCharles.Forsyth       FT_TRACE4(( "enc n. %d ; Uni %ld ; Glyph %d\n",
715*37da2899SCharles.Forsyth                   i, tmpEncoding[j - 1].enc, encodingOffset ));
716*37da2899SCharles.Forsyth     }
717*37da2899SCharles.Forsyth     FT_Stream_ExitFrame( stream );
718*37da2899SCharles.Forsyth 
719*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( encoding, j ) )
720*37da2899SCharles.Forsyth       goto Bail;
721*37da2899SCharles.Forsyth 
722*37da2899SCharles.Forsyth     for ( i = 0; i < j; i++ )
723*37da2899SCharles.Forsyth     {
724*37da2899SCharles.Forsyth       encoding[i].enc   = tmpEncoding[i].enc;
725*37da2899SCharles.Forsyth       encoding[i].glyph = tmpEncoding[i].glyph;
726*37da2899SCharles.Forsyth     }
727*37da2899SCharles.Forsyth 
728*37da2899SCharles.Forsyth     face->nencodings = j;
729*37da2899SCharles.Forsyth     face->encodings  = encoding;
730*37da2899SCharles.Forsyth     FT_FREE( tmpEncoding );
731*37da2899SCharles.Forsyth 
732*37da2899SCharles.Forsyth     return error;
733*37da2899SCharles.Forsyth 
734*37da2899SCharles.Forsyth   Bail:
735*37da2899SCharles.Forsyth     FT_FREE( encoding );
736*37da2899SCharles.Forsyth     FT_FREE( tmpEncoding );
737*37da2899SCharles.Forsyth     return error;
738*37da2899SCharles.Forsyth   }
739*37da2899SCharles.Forsyth 
740*37da2899SCharles.Forsyth 
741*37da2899SCharles.Forsyth   static
742*37da2899SCharles.Forsyth   const FT_Frame_Field  pcf_accel_header[] =
743*37da2899SCharles.Forsyth   {
744*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
745*37da2899SCharles.Forsyth #define FT_STRUCTURE  PCF_AccelRec
746*37da2899SCharles.Forsyth 
747*37da2899SCharles.Forsyth     FT_FRAME_START( 20 ),
748*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( noOverlap ),
749*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( constantMetrics ),
750*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( terminalFont ),
751*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( constantWidth ),
752*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( inkInside ),
753*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( inkMetrics ),
754*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( drawDirection ),
755*37da2899SCharles.Forsyth       FT_FRAME_SKIP_BYTES( 1 ),
756*37da2899SCharles.Forsyth       FT_FRAME_LONG_LE   ( fontAscent ),
757*37da2899SCharles.Forsyth       FT_FRAME_LONG_LE   ( fontDescent ),
758*37da2899SCharles.Forsyth       FT_FRAME_LONG_LE   ( maxOverlap ),
759*37da2899SCharles.Forsyth     FT_FRAME_END
760*37da2899SCharles.Forsyth   };
761*37da2899SCharles.Forsyth 
762*37da2899SCharles.Forsyth 
763*37da2899SCharles.Forsyth   static
764*37da2899SCharles.Forsyth   const FT_Frame_Field  pcf_accel_msb_header[] =
765*37da2899SCharles.Forsyth   {
766*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
767*37da2899SCharles.Forsyth #define FT_STRUCTURE  PCF_AccelRec
768*37da2899SCharles.Forsyth 
769*37da2899SCharles.Forsyth     FT_FRAME_START( 20 ),
770*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( noOverlap ),
771*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( constantMetrics ),
772*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( terminalFont ),
773*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( constantWidth ),
774*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( inkInside ),
775*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( inkMetrics ),
776*37da2899SCharles.Forsyth       FT_FRAME_BYTE      ( drawDirection ),
777*37da2899SCharles.Forsyth       FT_FRAME_SKIP_BYTES( 1 ),
778*37da2899SCharles.Forsyth       FT_FRAME_LONG      ( fontAscent ),
779*37da2899SCharles.Forsyth       FT_FRAME_LONG      ( fontDescent ),
780*37da2899SCharles.Forsyth       FT_FRAME_LONG      ( maxOverlap ),
781*37da2899SCharles.Forsyth     FT_FRAME_END
782*37da2899SCharles.Forsyth   };
783*37da2899SCharles.Forsyth 
784*37da2899SCharles.Forsyth 
785*37da2899SCharles.Forsyth   static FT_Error
pcf_get_accel(FT_Stream stream,PCF_Face face,FT_ULong type)786*37da2899SCharles.Forsyth   pcf_get_accel( FT_Stream  stream,
787*37da2899SCharles.Forsyth                  PCF_Face   face,
788*37da2899SCharles.Forsyth                  FT_ULong   type )
789*37da2899SCharles.Forsyth   {
790*37da2899SCharles.Forsyth     FT_ULong   format, size;
791*37da2899SCharles.Forsyth     FT_Error   error = PCF_Err_Ok;
792*37da2899SCharles.Forsyth     PCF_Accel  accel = &face->accel;
793*37da2899SCharles.Forsyth 
794*37da2899SCharles.Forsyth 
795*37da2899SCharles.Forsyth     error = pcf_seek_to_table_type( stream,
796*37da2899SCharles.Forsyth                                     face->toc.tables,
797*37da2899SCharles.Forsyth                                     face->toc.count,
798*37da2899SCharles.Forsyth                                     type,
799*37da2899SCharles.Forsyth                                     &format,
800*37da2899SCharles.Forsyth                                     &size );
801*37da2899SCharles.Forsyth     if ( error )
802*37da2899SCharles.Forsyth       goto Bail;
803*37da2899SCharles.Forsyth 
804*37da2899SCharles.Forsyth     error = FT_READ_ULONG_LE( format );
805*37da2899SCharles.Forsyth 
806*37da2899SCharles.Forsyth     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT )    &&
807*37da2899SCharles.Forsyth          !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
808*37da2899SCharles.Forsyth       goto Bail;
809*37da2899SCharles.Forsyth 
810*37da2899SCharles.Forsyth     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
811*37da2899SCharles.Forsyth     {
812*37da2899SCharles.Forsyth       if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) )
813*37da2899SCharles.Forsyth         goto Bail;
814*37da2899SCharles.Forsyth     }
815*37da2899SCharles.Forsyth     else
816*37da2899SCharles.Forsyth     {
817*37da2899SCharles.Forsyth       if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) )
818*37da2899SCharles.Forsyth         goto Bail;
819*37da2899SCharles.Forsyth     }
820*37da2899SCharles.Forsyth 
821*37da2899SCharles.Forsyth     error = pcf_get_metric( stream,
822*37da2899SCharles.Forsyth                             format & ( ~PCF_FORMAT_MASK ),
823*37da2899SCharles.Forsyth                             &(accel->minbounds) );
824*37da2899SCharles.Forsyth     if ( error )
825*37da2899SCharles.Forsyth       goto Bail;
826*37da2899SCharles.Forsyth 
827*37da2899SCharles.Forsyth     error = pcf_get_metric( stream,
828*37da2899SCharles.Forsyth                             format & ( ~PCF_FORMAT_MASK ),
829*37da2899SCharles.Forsyth                             &(accel->maxbounds) );
830*37da2899SCharles.Forsyth     if ( error )
831*37da2899SCharles.Forsyth       goto Bail;
832*37da2899SCharles.Forsyth 
833*37da2899SCharles.Forsyth     if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
834*37da2899SCharles.Forsyth     {
835*37da2899SCharles.Forsyth       error = pcf_get_metric( stream,
836*37da2899SCharles.Forsyth                               format & ( ~PCF_FORMAT_MASK ),
837*37da2899SCharles.Forsyth                               &(accel->ink_minbounds) );
838*37da2899SCharles.Forsyth       if ( error )
839*37da2899SCharles.Forsyth         goto Bail;
840*37da2899SCharles.Forsyth 
841*37da2899SCharles.Forsyth       error = pcf_get_metric( stream,
842*37da2899SCharles.Forsyth                               format & ( ~PCF_FORMAT_MASK ),
843*37da2899SCharles.Forsyth                               &(accel->ink_maxbounds) );
844*37da2899SCharles.Forsyth       if ( error )
845*37da2899SCharles.Forsyth         goto Bail;
846*37da2899SCharles.Forsyth     }
847*37da2899SCharles.Forsyth     else
848*37da2899SCharles.Forsyth     {
849*37da2899SCharles.Forsyth       accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */
850*37da2899SCharles.Forsyth       accel->ink_maxbounds = accel->maxbounds;
851*37da2899SCharles.Forsyth     }
852*37da2899SCharles.Forsyth     return error;
853*37da2899SCharles.Forsyth 
854*37da2899SCharles.Forsyth   Bail:
855*37da2899SCharles.Forsyth     return error;
856*37da2899SCharles.Forsyth   }
857*37da2899SCharles.Forsyth 
858*37da2899SCharles.Forsyth 
859*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
pcf_load_font(FT_Stream stream,PCF_Face face)860*37da2899SCharles.Forsyth   pcf_load_font( FT_Stream  stream,
861*37da2899SCharles.Forsyth                  PCF_Face   face )
862*37da2899SCharles.Forsyth   {
863*37da2899SCharles.Forsyth     FT_Error   error  = PCF_Err_Ok;
864*37da2899SCharles.Forsyth     FT_Memory  memory = FT_FACE(face)->memory;
865*37da2899SCharles.Forsyth     FT_Bool    hasBDFAccelerators;
866*37da2899SCharles.Forsyth 
867*37da2899SCharles.Forsyth 
868*37da2899SCharles.Forsyth     error = pcf_read_TOC( stream, face );
869*37da2899SCharles.Forsyth     if ( error )
870*37da2899SCharles.Forsyth       goto Exit;
871*37da2899SCharles.Forsyth 
872*37da2899SCharles.Forsyth     error = pcf_get_properties( stream, face );
873*37da2899SCharles.Forsyth     if ( error )
874*37da2899SCharles.Forsyth       goto Exit;
875*37da2899SCharles.Forsyth 
876*37da2899SCharles.Forsyth     /* Use the old accelerators if no BDF accelerators are in the file. */
877*37da2899SCharles.Forsyth     hasBDFAccelerators = pcf_has_table_type( face->toc.tables,
878*37da2899SCharles.Forsyth                                              face->toc.count,
879*37da2899SCharles.Forsyth                                              PCF_BDF_ACCELERATORS );
880*37da2899SCharles.Forsyth     if ( !hasBDFAccelerators )
881*37da2899SCharles.Forsyth     {
882*37da2899SCharles.Forsyth       error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
883*37da2899SCharles.Forsyth       if ( error )
884*37da2899SCharles.Forsyth         goto Exit;
885*37da2899SCharles.Forsyth     }
886*37da2899SCharles.Forsyth 
887*37da2899SCharles.Forsyth     /* metrics */
888*37da2899SCharles.Forsyth     error = pcf_get_metrics( stream, face );
889*37da2899SCharles.Forsyth     if ( error )
890*37da2899SCharles.Forsyth       goto Exit;
891*37da2899SCharles.Forsyth 
892*37da2899SCharles.Forsyth     /* bitmaps */
893*37da2899SCharles.Forsyth     error = pcf_get_bitmaps( stream, face );
894*37da2899SCharles.Forsyth     if ( error )
895*37da2899SCharles.Forsyth       goto Exit;
896*37da2899SCharles.Forsyth 
897*37da2899SCharles.Forsyth     /* encodings */
898*37da2899SCharles.Forsyth     error = pcf_get_encodings( stream, face );
899*37da2899SCharles.Forsyth     if ( error )
900*37da2899SCharles.Forsyth       goto Exit;
901*37da2899SCharles.Forsyth 
902*37da2899SCharles.Forsyth     /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
903*37da2899SCharles.Forsyth     if ( hasBDFAccelerators )
904*37da2899SCharles.Forsyth     {
905*37da2899SCharles.Forsyth       error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
906*37da2899SCharles.Forsyth       if ( error )
907*37da2899SCharles.Forsyth         goto Exit;
908*37da2899SCharles.Forsyth     }
909*37da2899SCharles.Forsyth 
910*37da2899SCharles.Forsyth     /* XXX: TO DO: inkmetrics and glyph_names are missing */
911*37da2899SCharles.Forsyth 
912*37da2899SCharles.Forsyth     /* now construct the face object */
913*37da2899SCharles.Forsyth     {
914*37da2899SCharles.Forsyth       FT_Face       root = FT_FACE( face );
915*37da2899SCharles.Forsyth       PCF_Property  prop;
916*37da2899SCharles.Forsyth       int           size_set = 0;
917*37da2899SCharles.Forsyth 
918*37da2899SCharles.Forsyth 
919*37da2899SCharles.Forsyth       root->num_faces = 1;
920*37da2899SCharles.Forsyth       root->face_index = 0;
921*37da2899SCharles.Forsyth       root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
922*37da2899SCharles.Forsyth                          FT_FACE_FLAG_HORIZONTAL  |
923*37da2899SCharles.Forsyth                          FT_FACE_FLAG_FAST_GLYPHS;
924*37da2899SCharles.Forsyth 
925*37da2899SCharles.Forsyth       if ( face->accel.constantWidth )
926*37da2899SCharles.Forsyth         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
927*37da2899SCharles.Forsyth 
928*37da2899SCharles.Forsyth       root->style_flags = 0;
929*37da2899SCharles.Forsyth       prop = pcf_find_property( face, "SLANT" );
930*37da2899SCharles.Forsyth       if ( prop != NULL )
931*37da2899SCharles.Forsyth         if ( prop->isString )
932*37da2899SCharles.Forsyth           if ( ( *(prop->value.atom) == 'O' ) ||
933*37da2899SCharles.Forsyth                ( *(prop->value.atom) == 'I' ) )
934*37da2899SCharles.Forsyth             root->style_flags |= FT_STYLE_FLAG_ITALIC;
935*37da2899SCharles.Forsyth 
936*37da2899SCharles.Forsyth       prop = pcf_find_property( face, "WEIGHT_NAME" );
937*37da2899SCharles.Forsyth       if ( prop != NULL )
938*37da2899SCharles.Forsyth         if ( prop->isString )
939*37da2899SCharles.Forsyth           if ( *(prop->value.atom) == 'B' )
940*37da2899SCharles.Forsyth             root->style_flags |= FT_STYLE_FLAG_BOLD;
941*37da2899SCharles.Forsyth 
942*37da2899SCharles.Forsyth       root->style_name = (char *)"Regular";
943*37da2899SCharles.Forsyth 
944*37da2899SCharles.Forsyth       if ( root->style_flags & FT_STYLE_FLAG_BOLD ) {
945*37da2899SCharles.Forsyth         if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
946*37da2899SCharles.Forsyth           root->style_name = (char *)"Bold Italic";
947*37da2899SCharles.Forsyth         else
948*37da2899SCharles.Forsyth           root->style_name = (char *)"Bold";
949*37da2899SCharles.Forsyth       }
950*37da2899SCharles.Forsyth       else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
951*37da2899SCharles.Forsyth         root->style_name = (char *)"Italic";
952*37da2899SCharles.Forsyth 
953*37da2899SCharles.Forsyth       prop = pcf_find_property( face, "FAMILY_NAME" );
954*37da2899SCharles.Forsyth       if ( prop != NULL )
955*37da2899SCharles.Forsyth       {
956*37da2899SCharles.Forsyth         if ( prop->isString )
957*37da2899SCharles.Forsyth         {
958*37da2899SCharles.Forsyth           int  l = ft_strlen( prop->value.atom ) + 1;
959*37da2899SCharles.Forsyth 
960*37da2899SCharles.Forsyth 
961*37da2899SCharles.Forsyth           if ( FT_NEW_ARRAY( root->family_name, l ) )
962*37da2899SCharles.Forsyth             goto Exit;
963*37da2899SCharles.Forsyth           ft_strcpy( root->family_name, prop->value.atom );
964*37da2899SCharles.Forsyth         }
965*37da2899SCharles.Forsyth       }
966*37da2899SCharles.Forsyth       else
967*37da2899SCharles.Forsyth         root->family_name = 0;
968*37da2899SCharles.Forsyth 
969*37da2899SCharles.Forsyth       root->num_glyphs = face->nmetrics;
970*37da2899SCharles.Forsyth 
971*37da2899SCharles.Forsyth       root->num_fixed_sizes = 1;
972*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
973*37da2899SCharles.Forsyth         goto Exit;
974*37da2899SCharles.Forsyth 
975*37da2899SCharles.Forsyth       prop = pcf_find_property( face, "PIXEL_SIZE" );
976*37da2899SCharles.Forsyth       if ( prop != NULL )
977*37da2899SCharles.Forsyth       {
978*37da2899SCharles.Forsyth         root->available_sizes->height =
979*37da2899SCharles.Forsyth         root->available_sizes->width  = (FT_Short)( prop->value.integer );
980*37da2899SCharles.Forsyth 
981*37da2899SCharles.Forsyth         size_set = 1;
982*37da2899SCharles.Forsyth       }
983*37da2899SCharles.Forsyth       else
984*37da2899SCharles.Forsyth       {
985*37da2899SCharles.Forsyth         prop = pcf_find_property( face, "POINT_SIZE" );
986*37da2899SCharles.Forsyth         if ( prop != NULL )
987*37da2899SCharles.Forsyth         {
988*37da2899SCharles.Forsyth           PCF_Property  xres, yres, avgw;
989*37da2899SCharles.Forsyth 
990*37da2899SCharles.Forsyth 
991*37da2899SCharles.Forsyth           xres = pcf_find_property( face, "RESOLUTION_X" );
992*37da2899SCharles.Forsyth           yres = pcf_find_property( face, "RESOLUTION_Y" );
993*37da2899SCharles.Forsyth           avgw = pcf_find_property( face, "AVERAGE_WIDTH" );
994*37da2899SCharles.Forsyth 
995*37da2899SCharles.Forsyth           if ( ( yres != NULL ) && ( xres != NULL ) )
996*37da2899SCharles.Forsyth           {
997*37da2899SCharles.Forsyth             root->available_sizes->height =
998*37da2899SCharles.Forsyth               (FT_Short)( prop->value.integer *
999*37da2899SCharles.Forsyth                           yres->value.integer / 720 );
1000*37da2899SCharles.Forsyth 
1001*37da2899SCharles.Forsyth               root->available_sizes->width =
1002*37da2899SCharles.Forsyth                 (FT_Short)( prop->value.integer *
1003*37da2899SCharles.Forsyth                             xres->value.integer / 720 );
1004*37da2899SCharles.Forsyth 
1005*37da2899SCharles.Forsyth             size_set = 1;
1006*37da2899SCharles.Forsyth           }
1007*37da2899SCharles.Forsyth         }
1008*37da2899SCharles.Forsyth       }
1009*37da2899SCharles.Forsyth 
1010*37da2899SCharles.Forsyth       if (size_set == 0 )
1011*37da2899SCharles.Forsyth       {
1012*37da2899SCharles.Forsyth         root->available_sizes->width  = 12;
1013*37da2899SCharles.Forsyth         root->available_sizes->height = 12;
1014*37da2899SCharles.Forsyth       }
1015*37da2899SCharles.Forsyth 
1016*37da2899SCharles.Forsyth       /* set-up charset */
1017*37da2899SCharles.Forsyth       {
1018*37da2899SCharles.Forsyth         PCF_Property  charset_registry = 0, charset_encoding = 0;
1019*37da2899SCharles.Forsyth 
1020*37da2899SCharles.Forsyth 
1021*37da2899SCharles.Forsyth         charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" );
1022*37da2899SCharles.Forsyth         charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" );
1023*37da2899SCharles.Forsyth 
1024*37da2899SCharles.Forsyth         if ( ( charset_registry != NULL ) &&
1025*37da2899SCharles.Forsyth              ( charset_encoding != NULL ) )
1026*37da2899SCharles.Forsyth         {
1027*37da2899SCharles.Forsyth           if ( ( charset_registry->isString ) &&
1028*37da2899SCharles.Forsyth                ( charset_encoding->isString ) )
1029*37da2899SCharles.Forsyth           {
1030*37da2899SCharles.Forsyth             if ( FT_NEW_ARRAY( face->charset_encoding,
1031*37da2899SCharles.Forsyth                                ft_strlen( charset_encoding->value.atom ) + 1 ) )
1032*37da2899SCharles.Forsyth               goto Exit;
1033*37da2899SCharles.Forsyth 
1034*37da2899SCharles.Forsyth             if ( FT_NEW_ARRAY( face->charset_registry,
1035*37da2899SCharles.Forsyth                                ft_strlen( charset_registry->value.atom ) + 1 ) )
1036*37da2899SCharles.Forsyth               goto Exit;
1037*37da2899SCharles.Forsyth 
1038*37da2899SCharles.Forsyth             ft_strcpy( face->charset_registry, charset_registry->value.atom );
1039*37da2899SCharles.Forsyth             ft_strcpy( face->charset_encoding, charset_encoding->value.atom );
1040*37da2899SCharles.Forsyth           }
1041*37da2899SCharles.Forsyth         }
1042*37da2899SCharles.Forsyth       }
1043*37da2899SCharles.Forsyth     }
1044*37da2899SCharles.Forsyth 
1045*37da2899SCharles.Forsyth   Exit:
1046*37da2899SCharles.Forsyth     if ( error )
1047*37da2899SCharles.Forsyth     {
1048*37da2899SCharles.Forsyth       /* this is done to respect the behaviour of the original */
1049*37da2899SCharles.Forsyth       /* PCF font driver.                                      */
1050*37da2899SCharles.Forsyth       error = PCF_Err_Invalid_File_Format;
1051*37da2899SCharles.Forsyth     }
1052*37da2899SCharles.Forsyth 
1053*37da2899SCharles.Forsyth     return error;
1054*37da2899SCharles.Forsyth   }
1055*37da2899SCharles.Forsyth 
1056*37da2899SCharles.Forsyth 
1057*37da2899SCharles.Forsyth /* END */
1058