blob: 2a142fca41c70ea77dfc70167a8fc3fabb3284ec [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 Lemberg8c4120d2007-01-15 06:42:40 +00005 Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 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"
Werner Lemberg499053c2003-06-07 04:02:21 +000035#include "pcfdrivr.h"
David Turner2f709652003-01-22 22:45:28 +000036#include "pcfread.h"
Werner Lembergf28b7bf2001-01-01 17:24:31 +000037
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000038#include "pcferror.h"
39
Werner Lemberg93616ec2001-06-27 19:46:12 +000040
Werner Lembergf28b7bf2001-01-01 17:24:31 +000041 /*************************************************************************/
42 /* */
43 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
44 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
45 /* messages during execution. */
46 /* */
47#undef FT_COMPONENT
48#define FT_COMPONENT trace_pcfread
49
50
51#if defined( FT_DEBUG_LEVEL_TRACE )
David Turner10bf05a2004-04-21 14:30:37 +000052 static const char* const tableNames[] =
Werner Lembergf28b7bf2001-01-01 17:24:31 +000053 {
54 "prop", "accl", "mtrcs", "bmps", "imtrcs",
55 "enc", "swidth", "names", "accel"
56 };
57#endif
58
59
Werner Lemberg93616ec2001-06-27 19:46:12 +000060 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +000061 const FT_Frame_Field pcf_toc_header[] =
62 {
63#undef FT_STRUCTURE
64#define FT_STRUCTURE PCF_TocRec
65
66 FT_FRAME_START( 8 ),
67 FT_FRAME_ULONG_LE( version ),
68 FT_FRAME_ULONG_LE( count ),
69 FT_FRAME_END
70 };
71
72
Werner Lemberg93616ec2001-06-27 19:46:12 +000073 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +000074 const FT_Frame_Field pcf_table_header[] =
75 {
76#undef FT_STRUCTURE
77#define FT_STRUCTURE PCF_TableRec
78
79 FT_FRAME_START( 16 ),
80 FT_FRAME_ULONG_LE( type ),
81 FT_FRAME_ULONG_LE( format ),
82 FT_FRAME_ULONG_LE( size ),
83 FT_FRAME_ULONG_LE( offset ),
84 FT_FRAME_END
85 };
86
87
Werner Lemberg93616ec2001-06-27 19:46:12 +000088 static FT_Error
89 pcf_read_TOC( FT_Stream stream,
90 PCF_Face face )
Werner Lembergf28b7bf2001-01-01 17:24:31 +000091 {
92 FT_Error error;
93 PCF_Toc toc = &face->toc;
94 PCF_Table tables;
95
David Turner04893282002-02-06 11:22:56 +000096 FT_Memory memory = FT_FACE(face)->memory;
97 FT_UInt n;
Werner Lembergf28b7bf2001-01-01 17:24:31 +000098
99
Werner Lemberg1987fb22002-03-31 06:56:56 +0000100 if ( FT_STREAM_SEEK ( 0 ) ||
David Turner7d3a2642002-03-20 10:49:31 +0000101 FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000102 return PCF_Err_Cannot_Open_Resource;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000103
David Turner58609c42005-03-15 23:31:48 +0000104 if ( toc->version != PCF_FILE_VERSION ||
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000105 toc->count > FT_ARRAY_MAX( face->toc.tables ) ||
106 toc->count == 0 )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000107 return PCF_Err_Invalid_File_Format;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000108
David Turnere459d742002-03-22 13:52:37 +0000109 if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000110 return PCF_Err_Out_Of_Memory;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000111
112 tables = face->toc.tables;
Werner Lembergc3b21602001-12-05 01:22:05 +0000113 for ( n = 0; n < toc->count; n++ )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000114 {
David Turner7d3a2642002-03-20 10:49:31 +0000115 if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000116 goto Exit;
117 tables++;
118 }
119
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000120 /* Sort tables and check for overlaps. Because they are almost */
121 /* always ordered already, an in-place bubble sort with simultaneous */
122 /* boundary checking seems appropriate. */
123 tables = face->toc.tables;
124
125 for ( n = 0; n < toc->count - 1; n++ )
126 {
127 FT_UInt i, have_change;
128
129
130 have_change = 0;
131
132 for ( i = 0; i < toc->count - 1 - n; i++ )
133 {
134 PCF_TableRec tmp;
135
136
137 if ( tables[i].offset > tables[i + 1].offset )
138 {
139 tmp = tables[i];
140 tables[i] = tables[i + 1];
141 tables[i + 1] = tmp;
142
143 have_change = 1;
144 }
145
146 if ( ( tables[i].size > tables[i + 1].offset ) ||
147 ( tables[i].offset > tables[i + 1].offset - tables[i].size ) )
148 return PCF_Err_Invalid_Offset;
149 }
150
151 if ( !have_change )
152 break;
153 }
154
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000155#if defined( FT_DEBUG_LEVEL_TRACE )
156
157 {
David Turner04893282002-02-06 11:22:56 +0000158 FT_UInt i, j;
159 const char* name = "?";
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000160
161
Werner Lemberg83efe772004-06-22 06:24:09 +0000162 FT_TRACE4(( "pcf_read_TOC:\n" ));
163
164 FT_TRACE4(( " number of tables: %ld\n", face->toc.count ));
165
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000166 tables = face->toc.tables;
167 for ( i = 0; i < toc->count; i++ )
168 {
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000169 for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] );
170 j++ )
David Turner04893282002-02-06 11:22:56 +0000171 if ( tables[i].type == (FT_UInt)( 1 << j ) )
Werner Lembergc3b21602001-12-05 01:22:05 +0000172 name = tableNames[j];
Werner Lemberg1987fb22002-03-31 06:56:56 +0000173
Werner Lemberg83efe772004-06-22 06:24:09 +0000174 FT_TRACE4(( " %d: type=%s, format=0x%X, "
175 "size=%ld (0x%lX), offset=%ld (0x%lX)\n",
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000176 i, name,
177 tables[i].format,
Werner Lemberg93616ec2001-06-27 19:46:12 +0000178 tables[i].size, tables[i].size,
Werner Lemberg83efe772004-06-22 06:24:09 +0000179 tables[i].offset, tables[i].offset ));
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000180 }
181 }
182
183#endif
184
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000185 return PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000186
187 Exit:
David Turnere459d742002-03-22 13:52:37 +0000188 FT_FREE( face->toc.tables );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000189 return error;
190 }
191
192
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000193#define PCF_METRIC_SIZE 12
194
Werner Lemberg93616ec2001-06-27 19:46:12 +0000195 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000196 const FT_Frame_Field pcf_metric_header[] =
197 {
198#undef FT_STRUCTURE
199#define FT_STRUCTURE PCF_MetricRec
200
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000201 FT_FRAME_START( PCF_METRIC_SIZE ),
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000202 FT_FRAME_SHORT_LE( leftSideBearing ),
203 FT_FRAME_SHORT_LE( rightSideBearing ),
204 FT_FRAME_SHORT_LE( characterWidth ),
205 FT_FRAME_SHORT_LE( ascent ),
206 FT_FRAME_SHORT_LE( descent ),
207 FT_FRAME_SHORT_LE( attributes ),
208 FT_FRAME_END
209 };
210
211
Werner Lemberg93616ec2001-06-27 19:46:12 +0000212 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000213 const FT_Frame_Field pcf_metric_msb_header[] =
214 {
215#undef FT_STRUCTURE
216#define FT_STRUCTURE PCF_MetricRec
217
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000218 FT_FRAME_START( PCF_METRIC_SIZE ),
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000219 FT_FRAME_SHORT( leftSideBearing ),
220 FT_FRAME_SHORT( rightSideBearing ),
221 FT_FRAME_SHORT( characterWidth ),
222 FT_FRAME_SHORT( ascent ),
223 FT_FRAME_SHORT( descent ),
224 FT_FRAME_SHORT( attributes ),
225 FT_FRAME_END
226 };
227
228
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000229#define PCF_COMPRESSED_METRIC_SIZE 5
230
Werner Lemberg93616ec2001-06-27 19:46:12 +0000231 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000232 const FT_Frame_Field pcf_compressed_metric_header[] =
233 {
234#undef FT_STRUCTURE
235#define FT_STRUCTURE PCF_Compressed_MetricRec
236
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000237 FT_FRAME_START( PCF_COMPRESSED_METRIC_SIZE ),
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000238 FT_FRAME_BYTE( leftSideBearing ),
239 FT_FRAME_BYTE( rightSideBearing ),
240 FT_FRAME_BYTE( characterWidth ),
241 FT_FRAME_BYTE( ascent ),
242 FT_FRAME_BYTE( descent ),
243 FT_FRAME_END
244 };
245
246
Werner Lemberg93616ec2001-06-27 19:46:12 +0000247 static FT_Error
248 pcf_get_metric( FT_Stream stream,
249 FT_ULong format,
250 PCF_Metric metric )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000251 {
Werner Lemberg60a1fab2002-02-08 06:23:50 +0000252 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000253
254
255 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
256 {
Werner Lemberg1987fb22002-03-31 06:56:56 +0000257 const FT_Frame_Field* fields;
258
259
David Turner04893282002-02-06 11:22:56 +0000260 /* parsing normal metrics */
261 fields = PCF_BYTE_ORDER( format ) == MSBFirst
Werner Lemberg1987fb22002-03-31 06:56:56 +0000262 ? pcf_metric_msb_header
263 : pcf_metric_header;
David Turner04893282002-02-06 11:22:56 +0000264
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000265 /* the following sets `error' but doesn't return in case of failure */
Werner Lemberg1987fb22002-03-31 06:56:56 +0000266 (void)FT_STREAM_READ_FIELDS( fields, metric );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000267 }
268 else
David Turner04893282002-02-06 11:22:56 +0000269 {
270 PCF_Compressed_MetricRec compr;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000271
David Turner04893282002-02-06 11:22:56 +0000272
273 /* parsing compressed metrics */
David Turner7d3a2642002-03-20 10:49:31 +0000274 if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) )
David Turner04893282002-02-06 11:22:56 +0000275 goto Exit;
276
277 metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 );
278 metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 );
279 metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 );
280 metric->ascent = (FT_Short)( compr.ascent - 0x80 );
281 metric->descent = (FT_Short)( compr.descent - 0x80 );
282 metric->attributes = 0;
283 }
284
285 Exit:
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000286 return error;
287 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000288
Werner Lemberg93616ec2001-06-27 19:46:12 +0000289
290 static FT_Error
David Turner04893282002-02-06 11:22:56 +0000291 pcf_seek_to_table_type( FT_Stream stream,
292 PCF_Table tables,
293 FT_Int ntables,
294 FT_ULong type,
295 FT_ULong *aformat,
296 FT_ULong *asize )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000297 {
Werner Lemberg319c00d2003-04-23 19:48:24 +0000298 FT_Error error = PCF_Err_Invalid_File_Format;
Werner Lembergb5349a92002-02-19 16:30:15 +0000299 FT_Int i;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000300
301
302 for ( i = 0; i < ntables; i++ )
303 if ( tables[i].type == type )
304 {
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000305 if ( stream->pos > tables[i].offset )
306 {
Werner Lemberg319c00d2003-04-23 19:48:24 +0000307 error = PCF_Err_Invalid_Stream_Skip;
308 goto Fail;
309 }
David Turner04893282002-02-06 11:22:56 +0000310
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000311 if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) )
312 {
Werner Lemberg319c00d2003-04-23 19:48:24 +0000313 error = PCF_Err_Invalid_Stream_Skip;
314 goto Fail;
315 }
David Turner04893282002-02-06 11:22:56 +0000316
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000317 *asize = tables[i].size;
David Turner04893282002-02-06 11:22:56 +0000318 *aformat = tables[i].format;
Werner Lemberg1987fb22002-03-31 06:56:56 +0000319
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000320 return PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000321 }
322
Werner Lemberg319c00d2003-04-23 19:48:24 +0000323 Fail:
Werner Lemberg8c4120d2007-01-15 06:42:40 +0000324 *asize = 0;
Werner Lemberg319c00d2003-04-23 19:48:24 +0000325 return error;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000326 }
327
328
Werner Lemberg93616ec2001-06-27 19:46:12 +0000329 static FT_Bool
David Turner04893282002-02-06 11:22:56 +0000330 pcf_has_table_type( PCF_Table tables,
331 FT_Int ntables,
332 FT_ULong type )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000333 {
David Turner04893282002-02-06 11:22:56 +0000334 FT_Int i;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000335
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000336
337 for ( i = 0; i < ntables; i++ )
338 if ( tables[i].type == type )
339 return TRUE;
340
341 return FALSE;
342 }
343
344
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000345#define PCF_PROPERTY_SIZE 9
346
Werner Lemberg93616ec2001-06-27 19:46:12 +0000347 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000348 const FT_Frame_Field pcf_property_header[] =
349 {
350#undef FT_STRUCTURE
351#define FT_STRUCTURE PCF_ParsePropertyRec
352
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000353 FT_FRAME_START( PCF_PROPERTY_SIZE ),
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000354 FT_FRAME_LONG_LE( name ),
355 FT_FRAME_BYTE ( isString ),
356 FT_FRAME_LONG_LE( value ),
357 FT_FRAME_END
358 };
359
360
Werner Lemberg93616ec2001-06-27 19:46:12 +0000361 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000362 const FT_Frame_Field pcf_property_msb_header[] =
363 {
364#undef FT_STRUCTURE
365#define FT_STRUCTURE PCF_ParsePropertyRec
366
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000367 FT_FRAME_START( PCF_PROPERTY_SIZE ),
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000368 FT_FRAME_LONG( name ),
369 FT_FRAME_BYTE( isString ),
370 FT_FRAME_LONG( value ),
371 FT_FRAME_END
372 };
373
374
David Turner2f709652003-01-22 22:45:28 +0000375 FT_LOCAL_DEF( PCF_Property )
David Turner04893282002-02-06 11:22:56 +0000376 pcf_find_property( PCF_Face face,
377 const FT_String* prop )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000378 {
379 PCF_Property properties = face->properties;
380 FT_Bool found = 0;
381 int i;
382
383
384 for ( i = 0 ; i < face->nprops && !found; i++ )
385 {
David Turnerd15bc0d2002-04-12 09:31:48 +0000386 if ( !ft_strcmp( properties[i].name, prop ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000387 found = 1;
388 }
Werner Lemberg93616ec2001-06-27 19:46:12 +0000389
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000390 if ( found )
391 return properties + i - 1;
392 else
393 return NULL;
394 }
395
396
Werner Lemberg93616ec2001-06-27 19:46:12 +0000397 static FT_Error
398 pcf_get_properties( FT_Stream stream,
399 PCF_Face face )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000400 {
401 PCF_ParseProperty props = 0;
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000402 PCF_Property properties;
403 FT_UInt nprops, i;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000404 FT_ULong format, size;
405 FT_Error error;
406 FT_Memory memory = FT_FACE(face)->memory;
407 FT_ULong string_size;
408 FT_String* strings = 0;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000409
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000410
David Turner04893282002-02-06 11:22:56 +0000411 error = pcf_seek_to_table_type( stream,
412 face->toc.tables,
413 face->toc.count,
414 PCF_PROPERTIES,
415 &format,
416 &size );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000417 if ( error )
418 goto Bail;
419
David Turnera890c292002-03-22 12:55:23 +0000420 if ( FT_READ_ULONG_LE( format ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000421 goto Bail;
422
Werner Lemberg83efe772004-06-22 06:24:09 +0000423 FT_TRACE4(( "pcf_get_properties:\n" ));
424
425 FT_TRACE4(( " format = %ld\n", format ));
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000426
427 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
428 goto Bail;
429
430 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
David Turnera890c292002-03-22 12:55:23 +0000431 (void)FT_READ_ULONG( nprops );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000432 else
David Turnera890c292002-03-22 12:55:23 +0000433 (void)FT_READ_ULONG_LE( nprops );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000434 if ( error )
435 goto Bail;
436
Werner Lemberg83efe772004-06-22 06:24:09 +0000437 FT_TRACE4(( " nprop = %d\n", nprops ));
Werner Lemberg93616ec2001-06-27 19:46:12 +0000438
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000439 /* rough estimate */
440 if ( nprops > size / PCF_PROPERTY_SIZE )
441 {
442 error = PCF_Err_Invalid_Table;
443 goto Bail;
444 }
445
446 face->nprops = nprops;
447
David Turnere459d742002-03-22 13:52:37 +0000448 if ( FT_NEW_ARRAY( props, nprops ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000449 goto Bail;
450
451 for ( i = 0; i < nprops; i++ )
452 {
453 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
Werner Lemberg22e812a2001-03-11 13:11:43 +0000454 {
David Turner7d3a2642002-03-20 10:49:31 +0000455 if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) )
Werner Lemberg22e812a2001-03-11 13:11:43 +0000456 goto Bail;
457 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000458 else
Werner Lemberg22e812a2001-03-11 13:11:43 +0000459 {
David Turner7d3a2642002-03-20 10:49:31 +0000460 if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) )
Werner Lemberg22e812a2001-03-11 13:11:43 +0000461 goto Bail;
462 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000463 }
464
465 /* pad the property array */
466 /* */
467 /* clever here - nprops is the same as the number of odd-units read, */
468 /* as only isStringProp are odd length (Keith Packard) */
469 /* */
470 if ( nprops & 3 )
471 {
472 i = 4 - ( nprops & 3 );
David Turner53b3fa12002-02-24 05:26:57 +0000473 FT_Stream_Skip( stream, i );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000474 }
475
476 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
David Turnera890c292002-03-22 12:55:23 +0000477 (void)FT_READ_ULONG( string_size );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000478 else
David Turnera890c292002-03-22 12:55:23 +0000479 (void)FT_READ_ULONG_LE( string_size );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000480 if ( error )
481 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000482
Werner Lemberg83efe772004-06-22 06:24:09 +0000483 FT_TRACE4(( " string_size = %ld\n", string_size ));
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000484
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000485 /* rough estimate */
486 if ( string_size > size - nprops * PCF_PROPERTY_SIZE )
487 {
488 error = PCF_Err_Invalid_Table;
489 goto Bail;
490 }
491
David Turnere459d742002-03-22 13:52:37 +0000492 if ( FT_NEW_ARRAY( strings, string_size ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000493 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000494
David Turner53b3fa12002-02-24 05:26:57 +0000495 error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000496 if ( error )
497 goto Bail;
498
David Turnere459d742002-03-22 13:52:37 +0000499 if ( FT_NEW_ARRAY( properties, nprops ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000500 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000501
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000502 face->properties = properties;
503
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000504 for ( i = 0; i < nprops; i++ )
505 {
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000506 FT_Long name_offset = props[i].name;
507
508
509 if ( ( name_offset < 0 ) ||
510 ( (FT_ULong)name_offset > string_size ) )
511 {
512 error = PCF_Err_Invalid_Offset;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000513 goto Bail;
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000514 }
515
David Turnerc0f9c4a2007-02-12 14:55:03 +0000516 if ( FT_STRDUP( properties[i].name, strings + name_offset ) )
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000517 goto Bail;
Werner Lemberg83efe772004-06-22 06:24:09 +0000518
519 FT_TRACE4(( " %s:", properties[i].name ));
Werner Lemberg93616ec2001-06-27 19:46:12 +0000520
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000521 properties[i].isString = props[i].isString;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000522
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000523 if ( props[i].isString )
524 {
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000525 FT_Long value_offset = props[i].value;
526
527
528 if ( ( value_offset < 0 ) ||
529 ( (FT_ULong)value_offset > string_size ) )
530 {
531 error = PCF_Err_Invalid_Offset;
532 goto Bail;
533 }
534
David Turnerc0f9c4a2007-02-12 14:55:03 +0000535 if ( FT_STRDUP( properties[i].value.atom, strings + value_offset ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000536 goto Bail;
Werner Lemberg83efe772004-06-22 06:24:09 +0000537
538 FT_TRACE4(( " `%s'\n", properties[i].value.atom ));
Werner Lemberg93616ec2001-06-27 19:46:12 +0000539 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000540 else
Werner Lemberg83efe772004-06-22 06:24:09 +0000541 {
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000542 properties[i].value.integer = props[i].value;
Werner Lemberg83efe772004-06-22 06:24:09 +0000543
544 FT_TRACE4(( " %d\n", properties[i].value.integer ));
545 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000546 }
Werner Lemberg93616ec2001-06-27 19:46:12 +0000547
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000548 error = PCF_Err_Ok;
Werner Lemberg9b774e22007-01-16 06:11:27 +0000549
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000550 Bail:
David Turnere459d742002-03-22 13:52:37 +0000551 FT_FREE( props );
552 FT_FREE( strings );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000553
554 return error;
555 }
556
557
Werner Lemberg93616ec2001-06-27 19:46:12 +0000558 static FT_Error
559 pcf_get_metrics( FT_Stream stream,
560 PCF_Face face )
561 {
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000562 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000563 FT_Memory memory = FT_FACE(face)->memory;
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000564 FT_ULong format, size;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000565 PCF_Metric metrics = 0;
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000566 FT_ULong nmetrics, i;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000567
568
David Turner04893282002-02-06 11:22:56 +0000569 error = pcf_seek_to_table_type( stream,
Werner Lemberg60a1fab2002-02-08 06:23:50 +0000570 face->toc.tables,
571 face->toc.count,
572 PCF_METRICS,
573 &format,
574 &size );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000575 if ( error )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000576 return error;
577
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000578 if ( FT_READ_ULONG_LE( format ) )
579 goto Bail;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000580
Werner Lemberg1987fb22002-03-31 06:56:56 +0000581 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000582 !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000583 return PCF_Err_Invalid_File_Format;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000584
585 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
586 {
587 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
David Turnera890c292002-03-22 12:55:23 +0000588 (void)FT_READ_ULONG( nmetrics );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000589 else
David Turnera890c292002-03-22 12:55:23 +0000590 (void)FT_READ_ULONG_LE( nmetrics );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000591 }
592 else
593 {
594 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
David Turnera890c292002-03-22 12:55:23 +0000595 (void)FT_READ_USHORT( nmetrics );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000596 else
David Turnera890c292002-03-22 12:55:23 +0000597 (void)FT_READ_USHORT_LE( nmetrics );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000598 }
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000599 if ( error )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000600 return PCF_Err_Invalid_File_Format;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000601
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000602 face->nmetrics = nmetrics;
603
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000604 FT_TRACE4(( "pcf_get_metrics:\n" ));
605
606 FT_TRACE4(( " number of metrics: %d\n", nmetrics ));
607
608 /* rough estimate */
609 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
610 {
611 if ( nmetrics > size / PCF_METRIC_SIZE )
612 return PCF_Err_Invalid_Table;
613 }
614 else
615 {
616 if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
617 return PCF_Err_Invalid_Table;
618 }
619
David Turnere459d742002-03-22 13:52:37 +0000620 if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000621 return PCF_Err_Out_Of_Memory;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000622
623 metrics = face->metrics;
624 for ( i = 0; i < nmetrics; i++ )
625 {
626 pcf_get_metric( stream, format, metrics + i );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000627
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000628 metrics[i].bits = 0;
629
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000630 FT_TRACE5(( " idx %d: width=%d, "
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000631 "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
632 i,
633 ( metrics + i )->characterWidth,
634 ( metrics + i )->leftSideBearing,
635 ( metrics + i )->rightSideBearing,
636 ( metrics + i )->ascent,
637 ( metrics + i )->descent,
638 ( metrics + i )->attributes ));
Werner Lemberg93616ec2001-06-27 19:46:12 +0000639
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000640 if ( error )
641 break;
642 }
643
644 if ( error )
David Turnere459d742002-03-22 13:52:37 +0000645 FT_FREE( face->metrics );
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000646
647 Bail:
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000648 return error;
649 }
650
651
Werner Lemberg93616ec2001-06-27 19:46:12 +0000652 static FT_Error
653 pcf_get_bitmaps( FT_Stream stream,
654 PCF_Face face )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000655 {
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000656 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000657 FT_Memory memory = FT_FACE(face)->memory;
658 FT_Long* offsets;
659 FT_Long bitmapSizes[GLYPHPADOPTIONS];
660 FT_ULong format, size;
David Turner0b3a9912001-06-19 15:45:48 +0000661 int nbitmaps, i, sizebitmaps = 0;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000662
663
David Turner04893282002-02-06 11:22:56 +0000664 error = pcf_seek_to_table_type( stream,
665 face->toc.tables,
666 face->toc.count,
667 PCF_BITMAPS,
668 &format,
669 &size );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000670 if ( error )
671 return error;
672
David Turner7d3a2642002-03-20 10:49:31 +0000673 error = FT_Stream_EnterFrame( stream, 8 );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000674 if ( error )
675 return error;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000676
David Turnera890c292002-03-22 12:55:23 +0000677 format = FT_GET_ULONG_LE();
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000678 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
David Turnera890c292002-03-22 12:55:23 +0000679 nbitmaps = FT_GET_ULONG();
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000680 else
David Turnera890c292002-03-22 12:55:23 +0000681 nbitmaps = FT_GET_ULONG_LE();
David Turner04893282002-02-06 11:22:56 +0000682
David Turner7d3a2642002-03-20 10:49:31 +0000683 FT_Stream_ExitFrame( stream );
David Turner04893282002-02-06 11:22:56 +0000684
685 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
686 return PCF_Err_Invalid_File_Format;
687
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000688 FT_TRACE4(( "pcf_get_bitmaps:\n" ));
689
690 FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps ));
691
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000692 if ( nbitmaps != face->nmetrics )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000693 return PCF_Err_Invalid_File_Format;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000694
David Turnere459d742002-03-22 13:52:37 +0000695 if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000696 return error;
697
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000698 for ( i = 0; i < nbitmaps; i++ )
Werner Lemberg93616ec2001-06-27 19:46:12 +0000699 {
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000700 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
David Turnera890c292002-03-22 12:55:23 +0000701 (void)FT_READ_LONG( offsets[i] );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000702 else
David Turnera890c292002-03-22 12:55:23 +0000703 (void)FT_READ_LONG_LE( offsets[i] );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000704
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000705 FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n",
Werner Lemberg83efe772004-06-22 06:24:09 +0000706 i, offsets[i], offsets[i] ));
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000707 }
708 if ( error )
709 goto Bail;
710
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000711 for ( i = 0; i < GLYPHPADOPTIONS; i++ )
Werner Lemberg93616ec2001-06-27 19:46:12 +0000712 {
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000713 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
David Turnera890c292002-03-22 12:55:23 +0000714 (void)FT_READ_LONG( bitmapSizes[i] );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000715 else
David Turnera890c292002-03-22 12:55:23 +0000716 (void)FT_READ_LONG_LE( bitmapSizes[i] );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000717 if ( error )
718 goto Bail;
719
720 sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
721
Werner Lemberg83efe772004-06-22 06:24:09 +0000722 FT_TRACE4(( " padding %d implies a size of %ld\n", i, bitmapSizes[i] ));
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000723 }
724
725 FT_TRACE4(( " %d bitmaps, padding index %ld\n",
726 nbitmaps,
727 PCF_GLYPH_PAD_INDEX( format ) ));
Werner Lemberg83efe772004-06-22 06:24:09 +0000728 FT_TRACE4(( " bitmap size = %d\n", sizebitmaps ));
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000729
Werner Lembergb5349a92002-02-19 16:30:15 +0000730 FT_UNUSED( sizebitmaps ); /* only used for debugging */
731
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000732 for ( i = 0; i < nbitmaps; i++ )
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000733 {
734 /* rough estimate */
735 if ( ( offsets[i] < 0 ) ||
736 ( (FT_ULong)offsets[i] > size ) )
737 {
738 FT_ERROR(( "pcf_get_bitmaps:"));
739 FT_ERROR(( " invalid offset to bitmap data of glyph %d\n", i ));
740 }
741 else
742 face->metrics[i].bits = stream->pos + offsets[i];
743 }
Werner Lemberg93616ec2001-06-27 19:46:12 +0000744
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000745 face->bitmapsFormat = format;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000746
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000747 Bail:
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000748 FT_FREE( offsets );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000749 return error;
750 }
751
752
Werner Lemberg93616ec2001-06-27 19:46:12 +0000753 static FT_Error
754 pcf_get_encodings( FT_Stream stream,
755 PCF_Face face )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000756 {
Werner Lemberg83efe772004-06-22 06:24:09 +0000757 FT_Error error = PCF_Err_Ok;
758 FT_Memory memory = FT_FACE(face)->memory;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000759 FT_ULong format, size;
760 int firstCol, lastCol;
761 int firstRow, lastRow;
762 int nencoding, encodingOffset;
763 int i, j;
764 PCF_Encoding tmpEncoding, encoding = 0;
765
766
David Turner04893282002-02-06 11:22:56 +0000767 error = pcf_seek_to_table_type( stream,
Werner Lemberg1987fb22002-03-31 06:56:56 +0000768 face->toc.tables,
769 face->toc.count,
770 PCF_BDF_ENCODINGS,
771 &format,
772 &size );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000773 if ( error )
774 return error;
775
David Turner7d3a2642002-03-20 10:49:31 +0000776 error = FT_Stream_EnterFrame( stream, 14 );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000777 if ( error )
778 return error;
David Turner04893282002-02-06 11:22:56 +0000779
David Turnera890c292002-03-22 12:55:23 +0000780 format = FT_GET_ULONG_LE();
Werner Lemberg93616ec2001-06-27 19:46:12 +0000781
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000782 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
783 {
David Turnera890c292002-03-22 12:55:23 +0000784 firstCol = FT_GET_SHORT();
785 lastCol = FT_GET_SHORT();
786 firstRow = FT_GET_SHORT();
787 lastRow = FT_GET_SHORT();
788 face->defaultChar = FT_GET_SHORT();
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000789 }
790 else
791 {
David Turnera890c292002-03-22 12:55:23 +0000792 firstCol = FT_GET_SHORT_LE();
793 lastCol = FT_GET_SHORT_LE();
794 firstRow = FT_GET_SHORT_LE();
795 lastRow = FT_GET_SHORT_LE();
796 face->defaultChar = FT_GET_SHORT_LE();
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000797 }
798
David Turner7d3a2642002-03-20 10:49:31 +0000799 FT_Stream_ExitFrame( stream );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000800
David Turner04893282002-02-06 11:22:56 +0000801 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
802 return PCF_Err_Invalid_File_Format;
803
Werner Lemberg83efe772004-06-22 06:24:09 +0000804 FT_TRACE4(( "pdf_get_encodings:\n" ));
805
806 FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000807 firstCol, lastCol, firstRow, lastRow ));
808
809 nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );
810
David Turnere459d742002-03-22 13:52:37 +0000811 if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) )
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000812 return PCF_Err_Out_Of_Memory;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000813
David Turner7d3a2642002-03-20 10:49:31 +0000814 error = FT_Stream_EnterFrame( stream, 2 * nencoding );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000815 if ( error )
816 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000817
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000818 for ( i = 0, j = 0 ; i < nencoding; i++ )
819 {
820 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
David Turnera890c292002-03-22 12:55:23 +0000821 encodingOffset = FT_GET_SHORT();
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000822 else
David Turnera890c292002-03-22 12:55:23 +0000823 encodingOffset = FT_GET_SHORT_LE();
Werner Lemberg93616ec2001-06-27 19:46:12 +0000824
David Turner3b7049f2001-07-07 16:12:14 +0000825 if ( encodingOffset != -1 )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000826 {
827 tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
828 firstRow ) * 256 ) +
829 ( ( i % ( lastCol - firstCol + 1 ) ) +
830 firstCol );
831
David Turner8edbcab2001-06-19 08:28:24 +0000832 tmpEncoding[j].glyph = (FT_Short)encodingOffset;
Werner Lemberg83efe772004-06-22 06:24:09 +0000833
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000834 FT_TRACE5(( " code %d (0x%04X): idx %d\n",
Werner Lemberg83efe772004-06-22 06:24:09 +0000835 tmpEncoding[j].enc, tmpEncoding[j].enc,
836 tmpEncoding[j].glyph ));
837
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000838 j++;
839 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000840 }
David Turner7d3a2642002-03-20 10:49:31 +0000841 FT_Stream_ExitFrame( stream );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000842
David Turnere459d742002-03-22 13:52:37 +0000843 if ( FT_NEW_ARRAY( encoding, j ) )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000844 goto Bail;
845
846 for ( i = 0; i < j; i++ )
847 {
848 encoding[i].enc = tmpEncoding[i].enc;
849 encoding[i].glyph = tmpEncoding[i].glyph;
850 }
851
852 face->nencodings = j;
853 face->encodings = encoding;
David Turnere459d742002-03-22 13:52:37 +0000854 FT_FREE( tmpEncoding );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000855
856 return error;
857
858 Bail:
David Turnere459d742002-03-22 13:52:37 +0000859 FT_FREE( encoding );
860 FT_FREE( tmpEncoding );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000861 return error;
862 }
863
864
Werner Lemberg93616ec2001-06-27 19:46:12 +0000865 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000866 const FT_Frame_Field pcf_accel_header[] =
867 {
868#undef FT_STRUCTURE
869#define FT_STRUCTURE PCF_AccelRec
870
871 FT_FRAME_START( 20 ),
872 FT_FRAME_BYTE ( noOverlap ),
873 FT_FRAME_BYTE ( constantMetrics ),
874 FT_FRAME_BYTE ( terminalFont ),
875 FT_FRAME_BYTE ( constantWidth ),
876 FT_FRAME_BYTE ( inkInside ),
877 FT_FRAME_BYTE ( inkMetrics ),
878 FT_FRAME_BYTE ( drawDirection ),
879 FT_FRAME_SKIP_BYTES( 1 ),
880 FT_FRAME_LONG_LE ( fontAscent ),
881 FT_FRAME_LONG_LE ( fontDescent ),
882 FT_FRAME_LONG_LE ( maxOverlap ),
883 FT_FRAME_END
884 };
885
886
Werner Lemberg93616ec2001-06-27 19:46:12 +0000887 static
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000888 const FT_Frame_Field pcf_accel_msb_header[] =
889 {
890#undef FT_STRUCTURE
891#define FT_STRUCTURE PCF_AccelRec
892
893 FT_FRAME_START( 20 ),
894 FT_FRAME_BYTE ( noOverlap ),
895 FT_FRAME_BYTE ( constantMetrics ),
896 FT_FRAME_BYTE ( terminalFont ),
897 FT_FRAME_BYTE ( constantWidth ),
898 FT_FRAME_BYTE ( inkInside ),
899 FT_FRAME_BYTE ( inkMetrics ),
900 FT_FRAME_BYTE ( drawDirection ),
901 FT_FRAME_SKIP_BYTES( 1 ),
902 FT_FRAME_LONG ( fontAscent ),
903 FT_FRAME_LONG ( fontDescent ),
904 FT_FRAME_LONG ( maxOverlap ),
905 FT_FRAME_END
906 };
907
908
Werner Lemberg93616ec2001-06-27 19:46:12 +0000909 static FT_Error
910 pcf_get_accel( FT_Stream stream,
911 PCF_Face face,
912 FT_ULong type )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000913 {
914 FT_ULong format, size;
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000915 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000916 PCF_Accel accel = &face->accel;
917
918
David Turner04893282002-02-06 11:22:56 +0000919 error = pcf_seek_to_table_type( stream,
920 face->toc.tables,
921 face->toc.count,
922 type,
923 &format,
924 &size );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000925 if ( error )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000926 goto Bail;
927
Werner Lemberg4af3c4d2006-07-08 21:31:24 +0000928 if ( FT_READ_ULONG_LE( format ) )
929 goto Bail;
David Turner04893282002-02-06 11:22:56 +0000930
Werner Lemberg1987fb22002-03-31 06:56:56 +0000931 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000932 !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
933 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000934
Werner Lemberg22e812a2001-03-11 13:11:43 +0000935 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
936 {
David Turner7d3a2642002-03-20 10:49:31 +0000937 if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) )
Werner Lemberg22e812a2001-03-11 13:11:43 +0000938 goto Bail;
939 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000940 else
Werner Lemberg22e812a2001-03-11 13:11:43 +0000941 {
David Turner7d3a2642002-03-20 10:49:31 +0000942 if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) )
Werner Lemberg22e812a2001-03-11 13:11:43 +0000943 goto Bail;
944 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000945
Werner Lemberg9928df82002-04-16 13:39:17 +0000946 error = pcf_get_metric( stream,
947 format & ( ~PCF_FORMAT_MASK ),
948 &(accel->minbounds) );
Werner Lemberg93616ec2001-06-27 19:46:12 +0000949 if ( error )
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000950 goto Bail;
David Turner04893282002-02-06 11:22:56 +0000951
Werner Lemberg9928df82002-04-16 13:39:17 +0000952 error = pcf_get_metric( stream,
953 format & ( ~PCF_FORMAT_MASK ),
954 &(accel->maxbounds) );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000955 if ( error )
956 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000957
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000958 if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
959 {
Werner Lemberg9928df82002-04-16 13:39:17 +0000960 error = pcf_get_metric( stream,
961 format & ( ~PCF_FORMAT_MASK ),
962 &(accel->ink_minbounds) );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000963 if ( error )
964 goto Bail;
David Turner04893282002-02-06 11:22:56 +0000965
Werner Lemberg9928df82002-04-16 13:39:17 +0000966 error = pcf_get_metric( stream,
967 format & ( ~PCF_FORMAT_MASK ),
968 &(accel->ink_maxbounds) );
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000969 if ( error )
970 goto Bail;
Werner Lemberg93616ec2001-06-27 19:46:12 +0000971 }
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000972 else
973 {
974 accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */
975 accel->ink_maxbounds = accel->maxbounds;
976 }
Werner Lemberg93616ec2001-06-27 19:46:12 +0000977
Werner Lembergf28b7bf2001-01-01 17:24:31 +0000978 Bail:
979 return error;
980 }
981
982
Werner Lemberg51ecb692003-11-13 10:19:27 +0000983 static FT_Error
984 pcf_interpret_style( PCF_Face pcf )
985 {
986 FT_Error error = PCF_Err_Ok;
987 FT_Face face = FT_FACE( pcf );
988 FT_Memory memory = face->memory;
989
990 PCF_Property prop;
991
David Turnerc0f9c4a2007-02-12 14:55:03 +0000992 int nn, len;
993 char* strings[4] = { NULL, NULL, NULL, NULL };
994 int lengths[4];
Werner Lemberg51ecb692003-11-13 10:19:27 +0000995
996
997 face->style_flags = 0;
998
999 prop = pcf_find_property( pcf, "SLANT" );
1000 if ( prop && prop->isString &&
1001 ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
1002 *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
1003 {
1004 face->style_flags |= FT_STYLE_FLAG_ITALIC;
Werner Lemberg442bfb82007-02-12 21:44:10 +00001005 strings[2] = ( *(prop->value.atom) == 'O' ||
1006 *(prop->value.atom) == 'o' ) ? (char *)"Oblique"
1007 : (char *)"Italic";
Werner Lemberg51ecb692003-11-13 10:19:27 +00001008 }
1009
1010 prop = pcf_find_property( pcf, "WEIGHT_NAME" );
1011 if ( prop && prop->isString &&
1012 ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
1013 {
1014 face->style_flags |= FT_STYLE_FLAG_BOLD;
David Turnerc0f9c4a2007-02-12 14:55:03 +00001015 strings[1] = (char *)"Bold";
Werner Lemberg51ecb692003-11-13 10:19:27 +00001016 }
1017
1018 prop = pcf_find_property( pcf, "SETWIDTH_NAME" );
1019 if ( prop && prop->isString &&
1020 *(prop->value.atom) &&
1021 !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
David Turnerc0f9c4a2007-02-12 14:55:03 +00001022 strings[3] = (char *)(prop->value.atom);
Werner Lemberg51ecb692003-11-13 10:19:27 +00001023
1024 prop = pcf_find_property( pcf, "ADD_STYLE_NAME" );
1025 if ( prop && prop->isString &&
1026 *(prop->value.atom) &&
1027 !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
David Turnerc0f9c4a2007-02-12 14:55:03 +00001028 strings[0] = (char *)(prop->value.atom);
Werner Lemberg51ecb692003-11-13 10:19:27 +00001029
Werner Lemberg442bfb82007-02-12 21:44:10 +00001030 for ( len = 0, nn = 0; nn < 4; nn++ )
Werner Lemberg004f3da2004-07-28 00:09:02 +00001031 {
David Turnerc0f9c4a2007-02-12 14:55:03 +00001032 lengths[nn] = 0;
Werner Lemberg442bfb82007-02-12 21:44:10 +00001033 if ( strings[nn] )
David Turnerc0f9c4a2007-02-12 14:55:03 +00001034 {
Werner Lemberg442bfb82007-02-12 21:44:10 +00001035 lengths[nn] = ft_strlen( strings[nn] );
1036 len += lengths[nn] + 1;
David Turnerc0f9c4a2007-02-12 14:55:03 +00001037 }
Werner Lemberg004f3da2004-07-28 00:09:02 +00001038 }
David Turnerc0f9c4a2007-02-12 14:55:03 +00001039
1040 if ( len == 0 )
Werner Lemberg51ecb692003-11-13 10:19:27 +00001041 {
David Turnerc0f9c4a2007-02-12 14:55:03 +00001042 strings[0] = "Regular";
Werner Lemberg442bfb82007-02-12 21:44:10 +00001043 lengths[0] = ft_strlen( strings[0] );
1044 len = lengths[0] + 1;
David Turnerc0f9c4a2007-02-12 14:55:03 +00001045 }
1046
1047 {
1048 char* s;
Werner Lemberg51ecb692003-11-13 10:19:27 +00001049
1050
David Turnerc0f9c4a2007-02-12 14:55:03 +00001051 if ( FT_ALLOC( face->style_name, len ) )
Werner Lemberg51ecb692003-11-13 10:19:27 +00001052 return error;
1053
David Turnerc0f9c4a2007-02-12 14:55:03 +00001054 s = face->style_name;
Werner Lemberg51ecb692003-11-13 10:19:27 +00001055
Werner Lemberg442bfb82007-02-12 21:44:10 +00001056 for ( nn = 0; nn < 4; nn++ )
Werner Lemberg51ecb692003-11-13 10:19:27 +00001057 {
David Turnerc0f9c4a2007-02-12 14:55:03 +00001058 char* src = strings[nn];
1059 int len = lengths[nn];
Werner Lemberg51ecb692003-11-13 10:19:27 +00001060
Werner Lemberg442bfb82007-02-12 21:44:10 +00001061
David Turnerc0f9c4a2007-02-12 14:55:03 +00001062 if ( src == NULL )
1063 continue;
1064
1065 /* separate elements with a space */
Werner Lemberg442bfb82007-02-12 21:44:10 +00001066 if ( s != face->style_name )
David Turnerc0f9c4a2007-02-12 14:55:03 +00001067 *s++ = ' ';
1068
Werner Lemberg442bfb82007-02-12 21:44:10 +00001069 ft_memcpy( s, src, len );
David Turnerc0f9c4a2007-02-12 14:55:03 +00001070
Werner Lemberg442bfb82007-02-12 21:44:10 +00001071 /* need to convert spaces to dashes for */
1072 /* add_style_name and setwidth_name */
1073 if ( nn == 0 || nn == 3 )
David Turnerc0f9c4a2007-02-12 14:55:03 +00001074 {
1075 int mm;
1076
Werner Lemberg442bfb82007-02-12 21:44:10 +00001077
1078 for ( mm = 0; mm < len; mm++ )
David Turnerc0f9c4a2007-02-12 14:55:03 +00001079 if (s[mm] == ' ')
1080 s[mm] = '-';
1081 }
1082
1083 s += len;
1084 }
1085 *s = 0;
Werner Lemberg51ecb692003-11-13 10:19:27 +00001086 }
1087
1088 return error;
1089 }
1090
1091
David Turnerbc82f1b2002-03-01 02:26:22 +00001092 FT_LOCAL_DEF( FT_Error )
Werner Lemberg93616ec2001-06-27 19:46:12 +00001093 pcf_load_font( FT_Stream stream,
1094 PCF_Face face )
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001095 {
Werner Lemberg1f7f0e82001-06-06 17:30:41 +00001096 FT_Error error = PCF_Err_Ok;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001097 FT_Memory memory = FT_FACE(face)->memory;
1098 FT_Bool hasBDFAccelerators;
1099
1100
1101 error = pcf_read_TOC( stream, face );
1102 if ( error )
David Turner42372fd2002-03-21 15:02:54 +00001103 goto Exit;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001104
1105 error = pcf_get_properties( stream, face );
1106 if ( error )
David Turner42372fd2002-03-21 15:02:54 +00001107 goto Exit;
Werner Lemberg93616ec2001-06-27 19:46:12 +00001108
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001109 /* Use the old accelerators if no BDF accelerators are in the file. */
David Turner04893282002-02-06 11:22:56 +00001110 hasBDFAccelerators = pcf_has_table_type( face->toc.tables,
Werner Lemberg60a1fab2002-02-08 06:23:50 +00001111 face->toc.count,
1112 PCF_BDF_ACCELERATORS );
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001113 if ( !hasBDFAccelerators )
1114 {
1115 error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
Werner Lemberg93616ec2001-06-27 19:46:12 +00001116 if ( error )
David Turner42372fd2002-03-21 15:02:54 +00001117 goto Exit;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001118 }
Werner Lemberg93616ec2001-06-27 19:46:12 +00001119
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001120 /* metrics */
1121 error = pcf_get_metrics( stream, face );
1122 if ( error )
David Turner42372fd2002-03-21 15:02:54 +00001123 goto Exit;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001124
1125 /* bitmaps */
1126 error = pcf_get_bitmaps( stream, face );
1127 if ( error )
David Turner42372fd2002-03-21 15:02:54 +00001128 goto Exit;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001129
1130 /* encodings */
1131 error = pcf_get_encodings( stream, face );
1132 if ( error )
David Turner42372fd2002-03-21 15:02:54 +00001133 goto Exit;
Werner Lemberg93616ec2001-06-27 19:46:12 +00001134
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001135 /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
1136 if ( hasBDFAccelerators )
1137 {
1138 error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
1139 if ( error )
David Turner42372fd2002-03-21 15:02:54 +00001140 goto Exit;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001141 }
1142
1143 /* XXX: TO DO: inkmetrics and glyph_names are missing */
1144
1145 /* now construct the face object */
1146 {
1147 FT_Face root = FT_FACE( face );
1148 PCF_Property prop;
1149
1150
Werner Lemberg6d798992003-07-01 07:28:55 +00001151 root->num_faces = 1;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001152 root->face_index = 0;
1153 root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
1154 FT_FACE_FLAG_HORIZONTAL |
1155 FT_FACE_FLAG_FAST_GLYPHS;
Werner Lemberg93616ec2001-06-27 19:46:12 +00001156
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001157 if ( face->accel.constantWidth )
1158 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
1159
David Turner9e185f32003-12-19 20:25:14 +00001160 if ( ( error = pcf_interpret_style( face ) ) != 0 )
Werner Lemberg51ecb692003-11-13 10:19:27 +00001161 goto Exit;
Werner Lemberg93616ec2001-06-27 19:46:12 +00001162
David Turner04893282002-02-06 11:22:56 +00001163 prop = pcf_find_property( face, "FAMILY_NAME" );
Werner Lemberg51ecb692003-11-13 10:19:27 +00001164 if ( prop && prop->isString )
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001165 {
David Turnerc0f9c4a2007-02-12 14:55:03 +00001166 if ( FT_STRDUP( root->family_name, prop->value.atom ) )
Werner Lemberg51ecb692003-11-13 10:19:27 +00001167 goto Exit;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001168 }
1169 else
Werner Lemberg51ecb692003-11-13 10:19:27 +00001170 root->family_name = NULL;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001171
Werner Lemberg9b774e22007-01-16 06:11:27 +00001172 /*
Werner Lemberg4af3c4d2006-07-08 21:31:24 +00001173 * Note: We shift all glyph indices by +1 since we must
Werner Lemberg428c2e42003-04-25 05:35:04 +00001174 * respect the convention that glyph 0 always corresponds
Werner Lemberg4af3c4d2006-07-08 21:31:24 +00001175 * to the `missing glyph'.
Werner Lemberg428c2e42003-04-25 05:35:04 +00001176 *
Werner Lemberg4af3c4d2006-07-08 21:31:24 +00001177 * This implies bumping the number of `available' glyphs by 1.
Werner Lemberg428c2e42003-04-25 05:35:04 +00001178 */
David Turner2dd1e652003-04-24 21:12:18 +00001179 root->num_glyphs = face->nmetrics + 1;
Werner Lemberg93616ec2001-06-27 19:46:12 +00001180
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001181 root->num_fixed_sizes = 1;
David Turnere459d742002-03-22 13:52:37 +00001182 if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
David Turner42372fd2002-03-21 15:02:54 +00001183 goto Exit;
Werner Lemberg93616ec2001-06-27 19:46:12 +00001184
Werner Lembergf891f912001-12-23 01:38:53 +00001185 {
Werner Lemberg6d798992003-07-01 07:28:55 +00001186 FT_Bitmap_Size* bsize = root->available_sizes;
Werner Lemberge0c50442004-02-08 16:30:37 +00001187 FT_Short resolution_x = 0, resolution_y = 0;
Werner Lemberg6d798992003-07-01 07:28:55 +00001188
1189
1190 FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
1191
Wu, Chia-I (吳佳一)bcc438b2006-01-23 14:12:40 +00001192#if 0
1193 bsize->height = face->accel.maxbounds.ascent << 6;
1194#endif
Werner Lemberg3273a992004-07-31 23:04:23 +00001195 bsize->height = (FT_Short)( face->accel.fontAscent +
1196 face->accel.fontDescent );
Werner Lemberg6d798992003-07-01 07:28:55 +00001197
1198 prop = pcf_find_property( face, "AVERAGE_WIDTH" );
Werner Lemberg51ecb692003-11-13 10:19:27 +00001199 if ( prop )
Werner Lemberg6d798992003-07-01 07:28:55 +00001200 bsize->width = (FT_Short)( ( prop->value.integer + 5 ) / 10 );
Werner Lemberge0c50442004-02-08 16:30:37 +00001201 else
David Turner750fa962005-05-01 10:11:32 +00001202 bsize->width = (FT_Short)( bsize->height * 2/3 );
Werner Lemberg6d798992003-07-01 07:28:55 +00001203
David Turner04893282002-02-06 11:22:56 +00001204 prop = pcf_find_property( face, "POINT_SIZE" );
Werner Lemberg51ecb692003-11-13 10:19:27 +00001205 if ( prop )
Werner Lemberge0c50442004-02-08 16:30:37 +00001206 /* convert from 722.7 decipoints to 72 points per inch */
Werner Lemberg6d798992003-07-01 07:28:55 +00001207 bsize->size =
1208 (FT_Pos)( ( prop->value.integer * 64 * 7200 + 36135L ) / 72270L );
Werner Lembergf891f912001-12-23 01:38:53 +00001209
Werner Lemberge0c50442004-02-08 16:30:37 +00001210 prop = pcf_find_property( face, "PIXEL_SIZE" );
1211 if ( prop )
1212 bsize->y_ppem = (FT_Short)prop->value.integer << 6;
1213
Werner Lemberg6d798992003-07-01 07:28:55 +00001214 prop = pcf_find_property( face, "RESOLUTION_X" );
Werner Lemberg51ecb692003-11-13 10:19:27 +00001215 if ( prop )
Werner Lemberge0c50442004-02-08 16:30:37 +00001216 resolution_x = (FT_Short)prop->value.integer;
Werner Lembergf891f912001-12-23 01:38:53 +00001217
Werner Lemberg6d798992003-07-01 07:28:55 +00001218 prop = pcf_find_property( face, "RESOLUTION_Y" );
Werner Lemberg51ecb692003-11-13 10:19:27 +00001219 if ( prop )
Werner Lemberge0c50442004-02-08 16:30:37 +00001220 resolution_y = (FT_Short)prop->value.integer;
Werner Lemberg6d798992003-07-01 07:28:55 +00001221
Werner Lemberge0c50442004-02-08 16:30:37 +00001222 if ( bsize->y_ppem == 0 )
1223 {
1224 bsize->y_ppem = bsize->size;
1225 if ( resolution_y )
1226 bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
1227 }
1228 if ( resolution_x && resolution_y )
1229 bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
1230 else
1231 bsize->x_ppem = bsize->y_ppem;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001232 }
Werner Lembergf891f912001-12-23 01:38:53 +00001233
Werner Lemberg779afe42003-06-22 15:33:53 +00001234 /* set up charset */
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001235 {
1236 PCF_Property charset_registry = 0, charset_encoding = 0;
Werner Lemberg1987fb22002-03-31 06:56:56 +00001237
1238
David Turner04893282002-02-06 11:22:56 +00001239 charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" );
1240 charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" );
Werner Lemberg1987fb22002-03-31 06:56:56 +00001241
Werner Lemberg51ecb692003-11-13 10:19:27 +00001242 if ( charset_registry && charset_registry->isString &&
1243 charset_encoding && charset_encoding->isString )
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001244 {
Werner Lemberg442bfb82007-02-12 21:44:10 +00001245 if ( FT_STRDUP( face->charset_encoding,
1246 charset_encoding->value.atom ) ||
1247 FT_STRDUP( face->charset_registry,
1248 charset_registry->value.atom ) )
Werner Lemberg51ecb692003-11-13 10:19:27 +00001249 goto Exit;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001250 }
1251 }
Werner Lemberg93616ec2001-06-27 19:46:12 +00001252 }
Werner Lemberg1987fb22002-03-31 06:56:56 +00001253
David Turner42372fd2002-03-21 15:02:54 +00001254 Exit:
Werner Lemberg1987fb22002-03-31 06:56:56 +00001255 if ( error )
David Turner42372fd2002-03-21 15:02:54 +00001256 {
Werner Lemberg4af3c4d2006-07-08 21:31:24 +00001257 /* This is done to respect the behaviour of the original */
Werner Lemberg1987fb22002-03-31 06:56:56 +00001258 /* PCF font driver. */
David Turner42372fd2002-03-21 15:02:54 +00001259 error = PCF_Err_Invalid_File_Format;
1260 }
Werner Lemberg1987fb22002-03-31 06:56:56 +00001261
David Turner42372fd2002-03-21 15:02:54 +00001262 return error;
Werner Lembergf28b7bf2001-01-01 17:24:31 +00001263 }
1264
1265
1266/* END */