blob: e9979d82ed86d3bf4342e316244a1e0b58a2d0c6 [file] [log] [blame]
Werner Lemberg93616ec2001-06-27 19:46:12 +00001/* pcfread.c
Werner Lembergf28b7bf2001-01-01 17:24:31 +00002
3 FreeType font driver for pcf fonts
4
Werner Lemberg415235d2001-06-28 17:49:10 +00005 Copyright 2000-2001 by
Werner Lemberg93616ec2001-06-27 19:46:12 +00006 Francesco Zappa Nardelli
Werner Lembergf28b7bf2001-01-01 17:24:31 +00007
8Permission is hereby granted, free of charge, to any person obtaining a copy
9of this software and associated documentation files (the "Software"), to deal
10in the Software without restriction, including without limitation the rights
11to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12copies of the Software, and to permit persons to whom the Software is
13furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice shall be included in
16all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24THE SOFTWARE.
25*/
26
27
28#include <ft2build.h>
29
Werner Lembergf28b7bf2001-01-01 17:24:31 +000030#include FT_INTERNAL_DEBUG_H
31#include FT_INTERNAL_STREAM_H
32#include FT_INTERNAL_OBJECTS_H
33
David Turner8d3a4012001-03-20 11:14:24 +000034#include "pcf.h"
35#include "pcfdriver.h"
Werner Lembergf28b7bf2001-01-01 17:24:31 +000036
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000037#include "pcferror.h"
38
Werner Lembergf28b7bf2001-01-01 17:24:31 +000039#include <string.h> /* strlen(), strcpy() */
40
Werner Lemberg93616ec2001-06-27 19:46:12 +000041
Werner Lembergf28b7bf2001-01-01 17:24:31 +000042 /*************************************************************************/
43 /* */
44 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
45 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
46 /* messages during execution. */
47 /* */
48#undef FT_COMPONENT
49#define FT_COMPONENT trace_pcfread
50
51
52#if defined( FT_DEBUG_LEVEL_TRACE )
Werner Lembergc3b21602001-12-05 01:22:05 +000053 static const char* tableNames[] =
Werner Lembergf28b7bf2001-01-01 17:24:31 +000054 {
55 "prop", "accl", "mtrcs", "bmps", "imtrcs",
56 "enc", "swidth", "names", "accel"
57 };
58#endif
59
60
Werner Lemberg93616ec2001-06-27 19:46:12 +000061 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +000062 const FT_Frame_Field pcf_toc_header[] =
63 {
64#undef FT_STRUCTURE
65#define FT_STRUCTURE PCF_TocRec
66
67 FT_FRAME_START( 8 ),
68 FT_FRAME_ULONG_LE( version ),
69 FT_FRAME_ULONG_LE( count ),
70 FT_FRAME_END
71 };
72
73
Werner Lemberg93616ec2001-06-27 19:46:12 +000074 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +000075 const FT_Frame_Field pcf_table_header[] =
76 {
77#undef FT_STRUCTURE
78#define FT_STRUCTURE PCF_TableRec
79
80 FT_FRAME_START( 16 ),
81 FT_FRAME_ULONG_LE( type ),
82 FT_FRAME_ULONG_LE( format ),
83 FT_FRAME_ULONG_LE( size ),
84 FT_FRAME_ULONG_LE( offset ),
85 FT_FRAME_END
86 };
87
88
Werner Lemberg93616ec2001-06-27 19:46:12 +000089 static FT_Error
90 pcf_read_TOC( FT_Stream stream,
91 PCF_Face face )
Werner Lembergf28b7bf2001-01-01 17:24:31 +000092 {
93 FT_Error error;
94 PCF_Toc toc = &face->toc;
95 PCF_Table tables;
96
David Turner04893282002-02-06 11:22:56 +000097 FT_Memory memory = FT_FACE(face)->memory;
98 FT_UInt n;
Werner Lembergf28b7bf2001-01-01 17:24:31 +000099
100
101 if ( FILE_Seek ( 0 ) ||
102 READ_Fields ( pcf_toc_header, toc ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000103 return PCF_Err_Cannot_Open_Resource;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000104
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000105 if ( toc->version != PCF_FILE_VERSION )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000106 return PCF_Err_Invalid_File_Format;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000107
108 if ( ALLOC( face->toc.tables, toc->count * sizeof ( PCF_TableRec ) ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000109 return PCF_Err_Out_Of_Memory;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000110
111 tables = face->toc.tables;
Werner Lembergc3b21602001-12-05 01:22:05 +0000112 for ( n = 0; n < toc->count; n++ )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000113 {
114 if ( READ_Fields( pcf_table_header, tables ) )
115 goto Exit;
116 tables++;
117 }
118
119#if defined( FT_DEBUG_LEVEL_TRACE )
120
121 {
David Turner04893282002-02-06 11:22:56 +0000122 FT_UInt i, j;
123 const char* name = "?";
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000124
125
126 FT_TRACE4(( "Tables count: %ld\n", face->toc.count ));
127 tables = face->toc.tables;
128 for ( i = 0; i < toc->count; i++ )
129 {
130 for( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ )
David Turner04893282002-02-06 11:22:56 +0000131 if ( tables[i].type == (FT_UInt)( 1 << j ) )
Werner Lembergc3b21602001-12-05 01:22:05 +0000132 name = tableNames[j];
David Turner04893282002-02-06 11:22:56 +0000133
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000134 FT_TRACE4(( "Table %d: type=%-6s format=0x%04lX "
135 "size=0x%06lX (%8ld) offset=0x%04lX\n",
136 i, name,
137 tables[i].format,
Werner Lemberg93616ec2001-06-27 19:46:12 +0000138 tables[i].size, tables[i].size,
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000139 tables[i].offset ));
140 }
141 }
142
143#endif
144
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000145 return PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000146
147 Exit:
148 FREE( face->toc.tables );
149 return error;
150 }
151
152
Werner Lemberg93616ec2001-06-27 19:46:12 +0000153 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000154 const FT_Frame_Field pcf_metric_header[] =
155 {
156#undef FT_STRUCTURE
157#define FT_STRUCTURE PCF_MetricRec
158
159 FT_FRAME_START( 12 ),
160 FT_FRAME_SHORT_LE( leftSideBearing ),
161 FT_FRAME_SHORT_LE( rightSideBearing ),
162 FT_FRAME_SHORT_LE( characterWidth ),
163 FT_FRAME_SHORT_LE( ascent ),
164 FT_FRAME_SHORT_LE( descent ),
165 FT_FRAME_SHORT_LE( attributes ),
166 FT_FRAME_END
167 };
168
169
Werner Lemberg93616ec2001-06-27 19:46:12 +0000170 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000171 const FT_Frame_Field pcf_metric_msb_header[] =
172 {
173#undef FT_STRUCTURE
174#define FT_STRUCTURE PCF_MetricRec
175
176 FT_FRAME_START( 12 ),
177 FT_FRAME_SHORT( leftSideBearing ),
178 FT_FRAME_SHORT( rightSideBearing ),
179 FT_FRAME_SHORT( characterWidth ),
180 FT_FRAME_SHORT( ascent ),
181 FT_FRAME_SHORT( descent ),
182 FT_FRAME_SHORT( attributes ),
183 FT_FRAME_END
184 };
185
186
Werner Lemberg93616ec2001-06-27 19:46:12 +0000187 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000188 const FT_Frame_Field pcf_compressed_metric_header[] =
189 {
190#undef FT_STRUCTURE
191#define FT_STRUCTURE PCF_Compressed_MetricRec
192
193 FT_FRAME_START( 5 ),
194 FT_FRAME_BYTE( leftSideBearing ),
195 FT_FRAME_BYTE( rightSideBearing ),
196 FT_FRAME_BYTE( characterWidth ),
197 FT_FRAME_BYTE( ascent ),
198 FT_FRAME_BYTE( descent ),
199 FT_FRAME_END
200 };
201
202
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000203
204
Werner Lemberg93616ec2001-06-27 19:46:12 +0000205 static FT_Error
206 pcf_get_metric( FT_Stream stream,
207 FT_ULong format,
208 PCF_Metric metric )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000209 {
Werner Lemberg60a1fab2002-02-08 06:23:50 +0000210 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000211
212
213 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
214 {
David Turner04893282002-02-06 11:22:56 +0000215 const FT_Frame_Field* fields;
216
217 /* parsing normal metrics */
218 fields = PCF_BYTE_ORDER( format ) == MSBFirst
219 ? pcf_metric_msb_header
220 : pcf_metric_header;
221
222 /* the following sets 'error' but doesn't return in case of failure */
223 (void) READ_Fields( fields, metric );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000224 }
225 else
David Turner04893282002-02-06 11:22:56 +0000226 {
227 PCF_Compressed_MetricRec compr;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000228
David Turner04893282002-02-06 11:22:56 +0000229
230 /* parsing compressed metrics */
231 if ( READ_Fields( pcf_compressed_metric_header, &compr ) )
232 goto Exit;
233
234 metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 );
235 metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 );
236 metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 );
237 metric->ascent = (FT_Short)( compr.ascent - 0x80 );
238 metric->descent = (FT_Short)( compr.descent - 0x80 );
239 metric->attributes = 0;
240 }
241
242 Exit:
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000243 return error;
244 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000245
Werner Lemberg93616ec2001-06-27 19:46:12 +0000246
247 static FT_Error
David Turner04893282002-02-06 11:22:56 +0000248 pcf_seek_to_table_type( FT_Stream stream,
249 PCF_Table tables,
250 FT_Int ntables,
251 FT_ULong type,
252 FT_ULong *aformat,
253 FT_ULong *asize )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000254 {
Werner Lembergb5349a92002-02-19 16:30:15 +0000255 FT_Error error;
256 FT_Int i;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000257
258
259 for ( i = 0; i < ntables; i++ )
260 if ( tables[i].type == type )
261 {
262 if ( stream->pos > tables[i].offset )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000263 return PCF_Err_Invalid_Stream_Skip;
David Turner04893282002-02-06 11:22:56 +0000264
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000265 if ( FILE_Skip( tables[i].offset - stream->pos ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000266 return PCF_Err_Invalid_Stream_Skip;
David Turner04893282002-02-06 11:22:56 +0000267
268 *asize = tables[i].size; /* unused - to be removed */
269 *aformat = tables[i].format;
270
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000271 return PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000272 }
273
Werner Lembergb5349a92002-02-19 16:30:15 +0000274 FT_UNUSED( error );
275
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000276 return PCF_Err_Invalid_File_Format;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000277 }
278
279
Werner Lemberg93616ec2001-06-27 19:46:12 +0000280 static FT_Bool
David Turner04893282002-02-06 11:22:56 +0000281 pcf_has_table_type( PCF_Table tables,
282 FT_Int ntables,
283 FT_ULong type )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000284 {
David Turner04893282002-02-06 11:22:56 +0000285 FT_Int i;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000286
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000287
288 for ( i = 0; i < ntables; i++ )
289 if ( tables[i].type == type )
290 return TRUE;
291
292 return FALSE;
293 }
294
295
Werner Lemberg93616ec2001-06-27 19:46:12 +0000296 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000297 const FT_Frame_Field pcf_property_header[] =
298 {
299#undef FT_STRUCTURE
300#define FT_STRUCTURE PCF_ParsePropertyRec
301
302 FT_FRAME_START( 9 ),
303 FT_FRAME_LONG_LE( name ),
304 FT_FRAME_BYTE ( isString ),
305 FT_FRAME_LONG_LE( value ),
306 FT_FRAME_END
307 };
308
309
Werner Lemberg93616ec2001-06-27 19:46:12 +0000310 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000311 const FT_Frame_Field pcf_property_msb_header[] =
312 {
313#undef FT_STRUCTURE
314#define FT_STRUCTURE PCF_ParsePropertyRec
315
316 FT_FRAME_START( 9 ),
317 FT_FRAME_LONG( name ),
318 FT_FRAME_BYTE( isString ),
319 FT_FRAME_LONG( value ),
320 FT_FRAME_END
321 };
322
323
Werner Lemberg93616ec2001-06-27 19:46:12 +0000324 static PCF_Property
David Turner04893282002-02-06 11:22:56 +0000325 pcf_find_property( PCF_Face face,
326 const FT_String* prop )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000327 {
328 PCF_Property properties = face->properties;
329 FT_Bool found = 0;
330 int i;
331
332
333 for ( i = 0 ; i < face->nprops && !found; i++ )
334 {
335 if ( !strcmp( properties[i].name, prop ) )
336 found = 1;
337 }
Werner Lemberg93616ec2001-06-27 19:46:12 +0000338
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000339 if ( found )
340 return properties + i - 1;
341 else
342 return NULL;
343 }
344
345
Werner Lemberg93616ec2001-06-27 19:46:12 +0000346 static FT_Error
347 pcf_get_properties( FT_Stream stream,
348 PCF_Face face )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000349 {
350 PCF_ParseProperty props = 0;
351 PCF_Property properties = 0;
David Turner04893282002-02-06 11:22:56 +0000352 FT_Int nprops, i;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000353 FT_ULong format, size;
354 FT_Error error;
355 FT_Memory memory = FT_FACE(face)->memory;
356 FT_ULong string_size;
357 FT_String* strings = 0;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000358
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000359
David Turner04893282002-02-06 11:22:56 +0000360 error = pcf_seek_to_table_type( stream,
361 face->toc.tables,
362 face->toc.count,
363 PCF_PROPERTIES,
364 &format,
365 &size );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000366 if ( error )
367 goto Bail;
368
369 if ( READ_ULongLE( format ) )
370 goto Bail;
371
372 FT_TRACE4(( "get_prop: format = %ld\n", format ));
373
374 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
375 goto Bail;
376
377 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
378 (void)READ_ULong( nprops );
379 else
380 (void)READ_ULongLE( nprops );
381 if ( error )
382 goto Bail;
383
384 FT_TRACE4(( "get_prop: nprop = %d\n", nprops ));
Werner Lemberg93616ec2001-06-27 19:46:12 +0000385
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000386 if ( ALLOC( props, nprops * sizeof ( PCF_ParsePropertyRec ) ) )
387 goto Bail;
388
389 for ( i = 0; i < nprops; i++ )
390 {
391 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
Werner Lemberg22e812a2001-03-11 13:11:43 +0000392 {
393 if ( READ_Fields( pcf_property_msb_header, props + i ) )
394 goto Bail;
395 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000396 else
Werner Lemberg22e812a2001-03-11 13:11:43 +0000397 {
398 if ( READ_Fields( pcf_property_header, props + i ) )
399 goto Bail;
400 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000401 }
402
403 /* pad the property array */
404 /* */
405 /* clever here - nprops is the same as the number of odd-units read, */
406 /* as only isStringProp are odd length (Keith Packard) */
407 /* */
408 if ( nprops & 3 )
409 {
410 i = 4 - ( nprops & 3 );
David Turner53b3fa12002-02-24 05:26:57 +0000411 FT_Stream_Skip( stream, i );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000412 }
413
414 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
415 (void)READ_ULong( string_size );
416 else
417 (void)READ_ULongLE( string_size );
418 if ( error )
419 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000420
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000421 FT_TRACE4(( "get_prop: string_size = %ld\n", string_size ));
422
423 if ( ALLOC( strings, string_size * sizeof ( char ) ) )
424 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000425
David Turner53b3fa12002-02-24 05:26:57 +0000426 error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000427 if ( error )
428 goto Bail;
429
430 if ( ALLOC( properties, nprops * sizeof ( PCF_PropertyRec ) ) )
431 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000432
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000433 for ( i = 0; i < nprops; i++ )
434 {
Werner Lemberg93616ec2001-06-27 19:46:12 +0000435 /* XXX: make atom */
436 if ( ALLOC( properties[i].name,
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000437 ( strlen( strings + props[i].name ) + 1 ) *
Werner Lemberg3dac27d2001-01-18 04:00:12 +0000438 sizeof ( char ) ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000439 goto Bail;
440 strcpy( properties[i].name,strings + props[i].name );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000441
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000442 properties[i].isString = props[i].isString;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000443
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000444 if ( props[i].isString )
445 {
Werner Lemberg93616ec2001-06-27 19:46:12 +0000446 if ( ALLOC( properties[i].value.atom,
447 ( strlen( strings + props[i].value ) + 1 ) *
Werner Lemberg3dac27d2001-01-18 04:00:12 +0000448 sizeof ( char ) ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000449 goto Bail;
450 strcpy( properties[i].value.atom, strings + props[i].value );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000451 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000452 else
453 properties[i].value.integer = props[i].value;
454 }
Werner Lemberg93616ec2001-06-27 19:46:12 +0000455
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000456 face->properties = properties;
457 face->nprops = nprops;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000458
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000459 FREE( props );
460 FREE( strings );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000461
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000462 return PCF_Err_Ok;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000463
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000464 Bail:
465 FREE( props );
466 FREE( strings );
467
468 return error;
469 }
470
471
Werner Lemberg93616ec2001-06-27 19:46:12 +0000472 static FT_Error
473 pcf_get_metrics( FT_Stream stream,
474 PCF_Face face )
475 {
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000476 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000477 FT_Memory memory = FT_FACE(face)->memory;
478 FT_ULong format = 0;
479 FT_ULong size = 0;
480 PCF_Metric metrics = 0;
481 int i;
482 int nmetrics = -1;
483
484
David Turner04893282002-02-06 11:22:56 +0000485 error = pcf_seek_to_table_type( stream,
Werner Lemberg60a1fab2002-02-08 06:23:50 +0000486 face->toc.tables,
487 face->toc.count,
488 PCF_METRICS,
489 &format,
490 &size );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000491 if ( error )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000492 return error;
493
494 error = READ_ULongLE( format );
495
496 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
497 !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000498 return PCF_Err_Invalid_File_Format;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000499
500 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
501 {
502 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
503 (void)READ_ULong( nmetrics );
504 else
505 (void)READ_ULongLE( nmetrics );
506 }
507 else
508 {
509 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
510 (void)READ_UShort( nmetrics );
511 else
512 (void)READ_UShortLE( nmetrics );
513 }
514 if ( error || nmetrics == -1 )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000515 return PCF_Err_Invalid_File_Format;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000516
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000517 face->nmetrics = nmetrics;
518
Werner Lemberg3dac27d2001-01-18 04:00:12 +0000519 if ( ALLOC( face->metrics, nmetrics * sizeof ( PCF_MetricRec ) ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000520 return PCF_Err_Out_Of_Memory;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000521
522 metrics = face->metrics;
523 for ( i = 0; i < nmetrics; i++ )
524 {
525 pcf_get_metric( stream, format, metrics + i );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000526
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000527 metrics[i].bits = 0;
528
529 FT_TRACE4(( "%d : width=%d, "
530 "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
531 i,
532 ( metrics + i )->characterWidth,
533 ( metrics + i )->leftSideBearing,
534 ( metrics + i )->rightSideBearing,
535 ( metrics + i )->ascent,
536 ( metrics + i )->descent,
537 ( metrics + i )->attributes ));
Werner Lemberg93616ec2001-06-27 19:46:12 +0000538
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000539 if ( error )
540 break;
541 }
542
543 if ( error )
544 FREE( face->metrics );
545 return error;
546 }
547
548
Werner Lemberg93616ec2001-06-27 19:46:12 +0000549 static FT_Error
550 pcf_get_bitmaps( FT_Stream stream,
551 PCF_Face face )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000552 {
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000553 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000554 FT_Memory memory = FT_FACE(face)->memory;
555 FT_Long* offsets;
556 FT_Long bitmapSizes[GLYPHPADOPTIONS];
557 FT_ULong format, size;
David Turner0b3a9912001-06-19 15:45:48 +0000558 int nbitmaps, i, sizebitmaps = 0;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000559 char* bitmaps;
560
561
David Turner04893282002-02-06 11:22:56 +0000562 error = pcf_seek_to_table_type( stream,
563 face->toc.tables,
564 face->toc.count,
565 PCF_BITMAPS,
566 &format,
567 &size );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000568 if ( error )
569 return error;
570
David Turner53b3fa12002-02-24 05:26:57 +0000571 error = FT_Stream_Enter_Frame( stream, 8 );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000572 if ( error )
573 return error;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000574
David Turner04893282002-02-06 11:22:56 +0000575 format = GET_ULongLE();
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000576 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
577 nbitmaps = GET_ULong();
578 else
579 nbitmaps = GET_ULongLE();
David Turner04893282002-02-06 11:22:56 +0000580
David Turner53b3fa12002-02-24 05:26:57 +0000581 FT_Stream_Exit_Frame( stream );
David Turner04893282002-02-06 11:22:56 +0000582
583 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
584 return PCF_Err_Invalid_File_Format;
585
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000586 if ( nbitmaps != face->nmetrics )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000587 return PCF_Err_Invalid_File_Format;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000588
Werner Lemberg3dac27d2001-01-18 04:00:12 +0000589 if ( ALLOC( offsets, nbitmaps * sizeof ( FT_ULong ) ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000590 return error;
591
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000592 for ( i = 0; i < nbitmaps; i++ )
Werner Lemberg93616ec2001-06-27 19:46:12 +0000593 {
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000594 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
595 (void)READ_Long( offsets[i] );
596 else
597 (void)READ_LongLE( offsets[i] );
598
599 FT_TRACE4(( "bitmap %d is at offset %ld\n", i, offsets[i] ));
600 }
601 if ( error )
602 goto Bail;
603
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000604 for ( i = 0; i < GLYPHPADOPTIONS; i++ )
Werner Lemberg93616ec2001-06-27 19:46:12 +0000605 {
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000606 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
Werner Lemberg93616ec2001-06-27 19:46:12 +0000607 (void)READ_Long( bitmapSizes[i] );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000608 else
609 (void)READ_LongLE( bitmapSizes[i] );
610 if ( error )
611 goto Bail;
612
613 sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
614
615 FT_TRACE4(( "padding %d implies a size of %ld\n", i, bitmapSizes[i] ));
616 }
617
618 FT_TRACE4(( " %d bitmaps, padding index %ld\n",
619 nbitmaps,
620 PCF_GLYPH_PAD_INDEX( format ) ));
621 FT_TRACE4(( "bitmap size = %d\n", sizebitmaps ));
622
Werner Lembergb5349a92002-02-19 16:30:15 +0000623 FT_UNUSED( sizebitmaps ); /* only used for debugging */
624
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000625 for ( i = 0; i < nbitmaps; i++ )
Werner Lemberg93616ec2001-06-27 19:46:12 +0000626 face->metrics[i].bits = stream->pos + offsets[i];
627
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000628 face->bitmapsFormat = format;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000629
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000630 FREE ( offsets );
631 return error;
632
633 Bail:
634 FREE ( offsets );
635 FREE ( bitmaps );
636 return error;
637 }
638
639
Werner Lemberg93616ec2001-06-27 19:46:12 +0000640 static FT_Error
641 pcf_get_encodings( FT_Stream stream,
642 PCF_Face face )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000643 {
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000644 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000645 FT_Memory memory = FT_FACE(face)->memory;
646 FT_ULong format, size;
647 int firstCol, lastCol;
648 int firstRow, lastRow;
649 int nencoding, encodingOffset;
650 int i, j;
651 PCF_Encoding tmpEncoding, encoding = 0;
652
653
David Turner04893282002-02-06 11:22:56 +0000654 error = pcf_seek_to_table_type( stream,
Werner Lemberg93616ec2001-06-27 19:46:12 +0000655 face->toc.tables,
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000656 face->toc.count,
657 PCF_BDF_ENCODINGS,
658 &format,
659 &size );
660 if ( error )
661 return error;
662
David Turner53b3fa12002-02-24 05:26:57 +0000663 error = FT_Stream_Enter_Frame( stream, 14 );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000664 if ( error )
665 return error;
David Turner04893282002-02-06 11:22:56 +0000666
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000667 format = GET_ULongLE();
Werner Lemberg93616ec2001-06-27 19:46:12 +0000668
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000669 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
670 {
671 firstCol = GET_Short();
672 lastCol = GET_Short();
673 firstRow = GET_Short();
674 lastRow = GET_Short();
675 face->defaultChar = GET_Short();
676 }
677 else
678 {
679 firstCol = GET_ShortLE();
680 lastCol = GET_ShortLE();
681 firstRow = GET_ShortLE();
682 lastRow = GET_ShortLE();
683 face->defaultChar = GET_ShortLE();
684 }
685
David Turner53b3fa12002-02-24 05:26:57 +0000686 FT_Stream_Exit_Frame( stream );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000687
David Turner04893282002-02-06 11:22:56 +0000688 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
689 return PCF_Err_Invalid_File_Format;
690
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000691 FT_TRACE4(( "enc: firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
692 firstCol, lastCol, firstRow, lastRow ));
693
694 nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );
695
696 if ( ALLOC( tmpEncoding, nencoding * sizeof ( PCF_EncodingRec ) ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000697 return PCF_Err_Out_Of_Memory;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000698
David Turner53b3fa12002-02-24 05:26:57 +0000699 error = FT_Stream_Enter_Frame( stream, 2 * nencoding );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000700 if ( error )
701 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000702
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000703 for ( i = 0, j = 0 ; i < nencoding; i++ )
704 {
705 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
Werner Lemberg93616ec2001-06-27 19:46:12 +0000706 encodingOffset = GET_Short();
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000707 else
708 encodingOffset = GET_ShortLE();
Werner Lemberg93616ec2001-06-27 19:46:12 +0000709
David Turner3b7049f2001-07-07 16:12:14 +0000710 if ( encodingOffset != -1 )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000711 {
712 tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
713 firstRow ) * 256 ) +
714 ( ( i % ( lastCol - firstCol + 1 ) ) +
715 firstCol );
716
David Turner8edbcab2001-06-19 08:28:24 +0000717 tmpEncoding[j].glyph = (FT_Short)encodingOffset;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000718 j++;
719 }
720
721 FT_TRACE4(( "enc n. %d ; Uni %ld ; Glyph %d\n",
722 i, tmpEncoding[j - 1].enc, encodingOffset ));
723 }
David Turner53b3fa12002-02-24 05:26:57 +0000724 FT_Stream_Exit_Frame( stream );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000725
726 if ( ALLOC( encoding, (--j) * sizeof ( PCF_EncodingRec ) ) )
727 goto Bail;
728
729 for ( i = 0; i < j; i++ )
730 {
731 encoding[i].enc = tmpEncoding[i].enc;
732 encoding[i].glyph = tmpEncoding[i].glyph;
733 }
734
735 face->nencodings = j;
736 face->encodings = encoding;
737 FREE( tmpEncoding );
738
739 return error;
740
741 Bail:
742 FREE( encoding );
743 FREE( tmpEncoding );
744 return error;
745 }
746
747
Werner Lemberg93616ec2001-06-27 19:46:12 +0000748 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000749 const FT_Frame_Field pcf_accel_header[] =
750 {
751#undef FT_STRUCTURE
752#define FT_STRUCTURE PCF_AccelRec
753
754 FT_FRAME_START( 20 ),
755 FT_FRAME_BYTE ( noOverlap ),
756 FT_FRAME_BYTE ( constantMetrics ),
757 FT_FRAME_BYTE ( terminalFont ),
758 FT_FRAME_BYTE ( constantWidth ),
759 FT_FRAME_BYTE ( inkInside ),
760 FT_FRAME_BYTE ( inkMetrics ),
761 FT_FRAME_BYTE ( drawDirection ),
762 FT_FRAME_SKIP_BYTES( 1 ),
763 FT_FRAME_LONG_LE ( fontAscent ),
764 FT_FRAME_LONG_LE ( fontDescent ),
765 FT_FRAME_LONG_LE ( maxOverlap ),
766 FT_FRAME_END
767 };
768
769
Werner Lemberg93616ec2001-06-27 19:46:12 +0000770 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000771 const FT_Frame_Field pcf_accel_msb_header[] =
772 {
773#undef FT_STRUCTURE
774#define FT_STRUCTURE PCF_AccelRec
775
776 FT_FRAME_START( 20 ),
777 FT_FRAME_BYTE ( noOverlap ),
778 FT_FRAME_BYTE ( constantMetrics ),
779 FT_FRAME_BYTE ( terminalFont ),
780 FT_FRAME_BYTE ( constantWidth ),
781 FT_FRAME_BYTE ( inkInside ),
782 FT_FRAME_BYTE ( inkMetrics ),
783 FT_FRAME_BYTE ( drawDirection ),
784 FT_FRAME_SKIP_BYTES( 1 ),
785 FT_FRAME_LONG ( fontAscent ),
786 FT_FRAME_LONG ( fontDescent ),
787 FT_FRAME_LONG ( maxOverlap ),
788 FT_FRAME_END
789 };
790
791
Werner Lemberg93616ec2001-06-27 19:46:12 +0000792 static FT_Error
793 pcf_get_accel( FT_Stream stream,
794 PCF_Face face,
795 FT_ULong type )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000796 {
797 FT_ULong format, size;
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000798 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000799 PCF_Accel accel = &face->accel;
800
801
David Turner04893282002-02-06 11:22:56 +0000802 error = pcf_seek_to_table_type( stream,
803 face->toc.tables,
804 face->toc.count,
805 type,
806 &format,
807 &size );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000808 if ( error )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000809 goto Bail;
810
811 error = READ_ULongLE( format );
David Turner04893282002-02-06 11:22:56 +0000812
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000813 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
814 !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
815 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000816
Werner Lemberg22e812a2001-03-11 13:11:43 +0000817 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
818 {
819 if ( READ_Fields( pcf_accel_msb_header, accel ) )
820 goto Bail;
821 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000822 else
Werner Lemberg22e812a2001-03-11 13:11:43 +0000823 {
824 if ( READ_Fields( pcf_accel_header, accel ) )
825 goto Bail;
826 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000827
828 error = pcf_get_metric( stream, format, &(accel->minbounds) );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000829 if ( error )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000830 goto Bail;
David Turner04893282002-02-06 11:22:56 +0000831
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000832 error = pcf_get_metric( stream, format, &(accel->maxbounds) );
833 if ( error )
834 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000835
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000836 if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
837 {
838 error = pcf_get_metric( stream, format, &(accel->ink_minbounds) );
839 if ( error )
840 goto Bail;
David Turner04893282002-02-06 11:22:56 +0000841
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000842 error = pcf_get_metric( stream, format, &(accel->ink_maxbounds) );
843 if ( error )
844 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000845 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000846 else
847 {
848 accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */
849 accel->ink_maxbounds = accel->maxbounds;
850 }
851 return error;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000852
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000853 Bail:
854 return error;
855 }
856
857
Werner Lemberg93616ec2001-06-27 19:46:12 +0000858 FT_LOCAL_DEF FT_Error
859 pcf_load_font( FT_Stream stream,
860 PCF_Face face )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000861 {
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000862 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000863 FT_Memory memory = FT_FACE(face)->memory;
864 FT_Bool hasBDFAccelerators;
865
866
867 error = pcf_read_TOC( stream, face );
868 if ( error )
869 return error;
870
871 error = pcf_get_properties( stream, face );
872 if ( error )
873 return error;;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000874
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000875 /* Use the old accelerators if no BDF accelerators are in the file. */
David Turner04893282002-02-06 11:22:56 +0000876 hasBDFAccelerators = pcf_has_table_type( face->toc.tables,
Werner Lemberg60a1fab2002-02-08 06:23:50 +0000877 face->toc.count,
878 PCF_BDF_ACCELERATORS );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000879 if ( !hasBDFAccelerators )
880 {
881 error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000882 if ( error )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000883 goto Bail;
884 }
Werner Lemberg93616ec2001-06-27 19:46:12 +0000885
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000886 /* metrics */
887 error = pcf_get_metrics( stream, face );
888 if ( error )
889 goto Bail;
890
891 /* bitmaps */
892 error = pcf_get_bitmaps( stream, face );
893 if ( error )
894 goto Bail;
895
896 /* encodings */
897 error = pcf_get_encodings( stream, face );
898 if ( error )
899 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000900
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000901 /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
902 if ( hasBDFAccelerators )
903 {
904 error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
905 if ( error )
Werner Lemberg93616ec2001-06-27 19:46:12 +0000906 goto Bail;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000907 }
908
909 /* XXX: TO DO: inkmetrics and glyph_names are missing */
910
911 /* now construct the face object */
912 {
913 FT_Face root = FT_FACE( face );
914 PCF_Property prop;
Werner Lembergf891f912001-12-23 01:38:53 +0000915 int size_set = 0;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000916
917
918 root->num_faces = 1;
919 root->face_index = 0;
920 root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
921 FT_FACE_FLAG_HORIZONTAL |
922 FT_FACE_FLAG_FAST_GLYPHS;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000923
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000924 if ( face->accel.constantWidth )
925 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
926
927 root->style_flags = 0;
David Turner04893282002-02-06 11:22:56 +0000928 prop = pcf_find_property( face, "SLANT" );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000929 if ( prop != NULL )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000930 if ( prop->isString )
931 if ( ( *(prop->value.atom) == 'O' ) ||
932 ( *(prop->value.atom) == 'I' ) )
933 root->style_flags |= FT_STYLE_FLAG_ITALIC;
934
David Turner04893282002-02-06 11:22:56 +0000935 prop = pcf_find_property( face, "WEIGHT_NAME" );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000936 if ( prop != NULL )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000937 if ( prop->isString )
938 if ( *(prop->value.atom) == 'B' )
939 root->style_flags |= FT_STYLE_FLAG_BOLD;
940
941 root->style_name = (char *)"Regular";
942
943 if ( root->style_flags & FT_STYLE_FLAG_BOLD ) {
944 if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
945 root->style_name = (char *)"Bold Italic";
946 else
947 root->style_name = (char *)"Bold";
948 }
949 else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
950 root->style_name = (char *)"Italic";
Werner Lemberg93616ec2001-06-27 19:46:12 +0000951
David Turner04893282002-02-06 11:22:56 +0000952 prop = pcf_find_property( face, "FAMILY_NAME" );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000953 if ( prop != NULL )
954 {
955 if ( prop->isString )
956 {
957 int l = strlen( prop->value.atom ) + 1;
958
959
960 if ( ALLOC( root->family_name, l * sizeof ( char ) ) )
961 goto Bail;
962 strcpy( root->family_name, prop->value.atom );
963 }
964 }
965 else
966 root->family_name = 0;
967
968 root->num_glyphs = face->nmetrics;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000969
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000970 root->num_fixed_sizes = 1;
971 if ( ALLOC_ARRAY( root->available_sizes, 1, FT_Bitmap_Size ) )
972 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000973
David Turner04893282002-02-06 11:22:56 +0000974 prop = pcf_find_property( face, "PIXEL_SIZE" );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000975 if ( prop != NULL )
976 {
David Turner04893282002-02-06 11:22:56 +0000977 root->available_sizes->height =
Werner Lembergf891f912001-12-23 01:38:53 +0000978 root->available_sizes->width = (FT_Short)( prop->value.integer );
David Turner5a902ec2002-02-07 16:59:38 +0000979
980#if 0 /* average width property support removed until maturation */
David Turner04893282002-02-06 11:22:56 +0000981 prop = pcf_find_property( face, "AVERAGE_WIDTH" );
982 if ( prop != NULL )
983 root->available_sizes->width = (FT_Short)( prop->value.integer / 10 );
David Turner5a902ec2002-02-07 16:59:38 +0000984#endif
Werner Lembergf891f912001-12-23 01:38:53 +0000985
986 size_set = 1;
987 }
988 else
989 {
David Turner04893282002-02-06 11:22:56 +0000990 prop = pcf_find_property( face, "POINT_SIZE" );
Werner Lembergf891f912001-12-23 01:38:53 +0000991 if ( prop != NULL )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000992 {
David Turner04893282002-02-06 11:22:56 +0000993 PCF_Property xres, yres, avgw;
Werner Lembergf891f912001-12-23 01:38:53 +0000994
995
David Turner04893282002-02-06 11:22:56 +0000996 xres = pcf_find_property( face, "RESOLUTION_X" );
997 yres = pcf_find_property( face, "RESOLUTION_Y" );
998 avgw = pcf_find_property( face, "AVERAGE_WIDTH" );
999
David Turner5a902ec2002-02-07 16:59:38 +00001000 if ( ( yres != NULL ) && ( xres != NULL ) )
Werner Lembergf891f912001-12-23 01:38:53 +00001001 {
Werner Lembergf891f912001-12-23 01:38:53 +00001002 root->available_sizes->height =
1003 (FT_Short)( prop->value.integer *
1004 yres->value.integer / 720 );
David Turner04893282002-02-06 11:22:56 +00001005
David Turner5a902ec2002-02-07 16:59:38 +00001006#if 0 /* average width property support removed until maturation */
David Turner04893282002-02-06 11:22:56 +00001007 if ( avgw != NULL )
1008 root->available_sizes->width =
1009 (FT_Short)( avgw->value.integer / 10 );
1010 else
David Turner5a902ec2002-02-07 16:59:38 +00001011#endif
David Turner04893282002-02-06 11:22:56 +00001012 root->available_sizes->width =
1013 (FT_Short)( prop->value.integer *
1014 xres->value.integer / 720 );
Werner Lembergf891f912001-12-23 01:38:53 +00001015
1016 size_set = 1;
1017 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001018 }
1019 }
Werner Lembergf891f912001-12-23 01:38:53 +00001020
1021 if (size_set == 0 )
1022 {
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001023#if 0
1024 printf( "PCF Warning: Pixel Size undefined, assuming 12\n");
1025#endif
Werner Lembergf891f912001-12-23 01:38:53 +00001026 root->available_sizes->width = 12;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001027 root->available_sizes->height = 12;
Werner Lemberg93616ec2001-06-27 19:46:12 +00001028 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001029
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00001030 /* XXX: charmaps. For now, report unicode for Unicode and Latin 1 */
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001031 root->charmaps = &face->charmap_handle;
1032 root->num_charmaps = 1;
1033
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00001034 face->charmap.encoding = ft_encoding_none;
1035 face->charmap.platform_id = 0;
1036 face->charmap.encoding_id = 0;
1037
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001038 {
1039 PCF_Property charset_registry = 0, charset_encoding = 0;
Werner Lemberg93616ec2001-06-27 19:46:12 +00001040
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001041
David Turner04893282002-02-06 11:22:56 +00001042 charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" );
1043 charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" );
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001044
1045 if ( ( charset_registry != NULL ) &&
1046 ( charset_encoding != NULL ) )
1047 {
1048 if ( ( charset_registry->isString ) &&
1049 ( charset_encoding->isString ) )
1050 {
Werner Lemberg93616ec2001-06-27 19:46:12 +00001051 if ( ALLOC( face->charset_encoding,
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001052 ( strlen( charset_encoding->value.atom ) + 1 ) *
Werner Lemberg93616ec2001-06-27 19:46:12 +00001053 sizeof ( char ) ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001054 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +00001055 if ( ALLOC( face->charset_registry,
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001056 ( strlen( charset_registry->value.atom ) + 1 ) *
Werner Lemberg93616ec2001-06-27 19:46:12 +00001057 sizeof ( char ) ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001058 goto Bail;
1059 strcpy( face->charset_registry, charset_registry->value.atom );
1060 strcpy( face->charset_encoding, charset_encoding->value.atom );
1061
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00001062 if ( !strcmp( face->charset_registry, "ISO10646" ) ||
1063 ( !strcmp( face->charset_registry, "ISO8859" ) &&
1064 !strcmp( face->charset_encoding, "1" ) ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001065 {
1066 face->charmap.encoding = ft_encoding_unicode;
1067 face->charmap.platform_id = 3;
1068 face->charmap.encoding_id = 1;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001069 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001070 }
1071 }
1072 }
Werner Lemberg93616ec2001-06-27 19:46:12 +00001073
Werner Lemberg0f7c2f12002-02-04 20:55:58 +00001074 face->charmap.face = root;
1075 face->charmap_handle = &face->charmap;
1076 root->charmap = face->charmap_handle;
Werner Lemberg93616ec2001-06-27 19:46:12 +00001077 }
Werner Lemberg1f7f0e82001-06-06 17:30:41 +00001078 return PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001079
1080 Bail:
Werner Lemberg1f7f0e82001-06-06 17:30:41 +00001081 return PCF_Err_Invalid_File_Format;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001082 }
1083
1084
1085/* END */