~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/freetype/src/pcf/pcfread.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  pcfread.c
 
2
 
 
3
    FreeType font driver for pcf fonts
 
4
 
 
5
  Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
 
6
            2010 by
 
7
  Francesco Zappa Nardelli
 
8
 
 
9
Permission is hereby granted, free of charge, to any person obtaining a copy
 
10
of this software and associated documentation files (the "Software"), to deal
 
11
in the Software without restriction, including without limitation the rights
 
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
13
copies of the Software, and to permit persons to whom the Software is
 
14
furnished to do so, subject to the following conditions:
 
15
 
 
16
The above copyright notice and this permission notice shall be included in
 
17
all copies or substantial portions of the Software.
 
18
 
 
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
25
THE SOFTWARE.
 
26
*/
 
27
 
 
28
 
 
29
#include <ft2build.h>
 
30
 
 
31
#include FT_INTERNAL_DEBUG_H
 
32
#include FT_INTERNAL_STREAM_H
 
33
#include FT_INTERNAL_OBJECTS_H
 
34
 
 
35
#include "pcf.h"
 
36
#include "pcfread.h"
 
37
 
 
38
#include "pcferror.h"
 
39
 
 
40
 
 
41
  /*************************************************************************/
 
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
#ifdef FT_DEBUG_LEVEL_TRACE
 
52
  static const char* const  tableNames[] =
 
53
  {
 
54
    "prop", "accl", "mtrcs", "bmps", "imtrcs",
 
55
    "enc", "swidth", "names", "accel"
 
56
  };
 
57
#endif
 
58
 
 
59
 
 
60
  static
 
61
  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
 
 
73
  static
 
74
  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
 
 
88
  static FT_Error
 
89
  pcf_read_TOC( FT_Stream  stream,
 
90
                PCF_Face   face )
 
91
  {
 
92
    FT_Error   error;
 
93
    PCF_Toc    toc = &face->toc;
 
94
    PCF_Table  tables;
 
95
 
 
96
    FT_Memory  memory = FT_FACE(face)->memory;
 
97
    FT_UInt    n;
 
98
 
 
99
 
 
100
    if ( FT_STREAM_SEEK ( 0 )                          ||
 
101
         FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) )
 
102
      return PCF_Err_Cannot_Open_Resource;
 
103
 
 
104
    if ( toc->version != PCF_FILE_VERSION                 ||
 
105
         toc->count   >  FT_ARRAY_MAX( face->toc.tables ) ||
 
106
         toc->count   == 0                                )
 
107
      return PCF_Err_Invalid_File_Format;
 
108
 
 
109
    if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
 
110
      return PCF_Err_Out_Of_Memory;
 
111
 
 
112
    tables = face->toc.tables;
 
113
    for ( n = 0; n < toc->count; n++ )
 
114
    {
 
115
      if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) )
 
116
        goto Exit;
 
117
      tables++;
 
118
    }
 
119
 
 
120
    /* 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
 
 
155
#ifdef FT_DEBUG_LEVEL_TRACE
 
156
 
 
157
    {
 
158
      FT_UInt      i, j;
 
159
      const char*  name = "?";
 
160
 
 
161
 
 
162
      FT_TRACE4(( "pcf_read_TOC:\n" ));
 
163
 
 
164
      FT_TRACE4(( "  number of tables: %ld\n", face->toc.count ));
 
165
 
 
166
      tables = face->toc.tables;
 
167
      for ( i = 0; i < toc->count; i++ )
 
168
      {
 
169
        for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] );
 
170
              j++ )
 
171
          if ( tables[i].type == (FT_UInt)( 1 << j ) )
 
172
            name = tableNames[j];
 
173
 
 
174
        FT_TRACE4(( "  %d: type=%s, format=0x%X, "
 
175
                    "size=%ld (0x%lX), offset=%ld (0x%lX)\n",
 
176
                    i, name,
 
177
                    tables[i].format,
 
178
                    tables[i].size, tables[i].size,
 
179
                    tables[i].offset, tables[i].offset ));
 
180
      }
 
181
    }
 
182
 
 
183
#endif
 
184
 
 
185
    return PCF_Err_Ok;
 
186
 
 
187
  Exit:
 
188
    FT_FREE( face->toc.tables );
 
189
    return error;
 
190
  }
 
191
 
 
192
 
 
193
#define PCF_METRIC_SIZE  12
 
194
 
 
195
  static
 
196
  const FT_Frame_Field  pcf_metric_header[] =
 
197
  {
 
198
#undef  FT_STRUCTURE
 
199
#define FT_STRUCTURE  PCF_MetricRec
 
200
 
 
201
    FT_FRAME_START( PCF_METRIC_SIZE ),
 
202
      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
 
 
212
  static
 
213
  const FT_Frame_Field  pcf_metric_msb_header[] =
 
214
  {
 
215
#undef  FT_STRUCTURE
 
216
#define FT_STRUCTURE  PCF_MetricRec
 
217
 
 
218
    FT_FRAME_START( PCF_METRIC_SIZE ),
 
219
      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
 
 
229
#define PCF_COMPRESSED_METRIC_SIZE  5
 
230
 
 
231
  static
 
232
  const FT_Frame_Field  pcf_compressed_metric_header[] =
 
233
  {
 
234
#undef  FT_STRUCTURE
 
235
#define FT_STRUCTURE  PCF_Compressed_MetricRec
 
236
 
 
237
    FT_FRAME_START( PCF_COMPRESSED_METRIC_SIZE ),
 
238
      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
 
 
247
  static FT_Error
 
248
  pcf_get_metric( FT_Stream   stream,
 
249
                  FT_ULong    format,
 
250
                  PCF_Metric  metric )
 
251
  {
 
252
    FT_Error  error = PCF_Err_Ok;
 
253
 
 
254
 
 
255
    if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
 
256
    {
 
257
      const FT_Frame_Field*  fields;
 
258
 
 
259
 
 
260
      /* parsing normal metrics */
 
261
      fields = PCF_BYTE_ORDER( format ) == MSBFirst
 
262
               ? pcf_metric_msb_header
 
263
               : pcf_metric_header;
 
264
 
 
265
      /* the following sets `error' but doesn't return in case of failure */
 
266
      (void)FT_STREAM_READ_FIELDS( fields, metric );
 
267
    }
 
268
    else
 
269
    {
 
270
      PCF_Compressed_MetricRec  compr;
 
271
 
 
272
 
 
273
      /* parsing compressed metrics */
 
274
      if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) )
 
275
        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:
 
286
    return error;
 
287
  }
 
288
 
 
289
 
 
290
  static FT_Error
 
291
  pcf_seek_to_table_type( FT_Stream  stream,
 
292
                          PCF_Table  tables,
 
293
                          FT_ULong   ntables, /* same as PCF_Toc->count */
 
294
                          FT_ULong   type,
 
295
                          FT_ULong  *aformat,
 
296
                          FT_ULong  *asize )
 
297
  {
 
298
    FT_Error  error = PCF_Err_Invalid_File_Format;
 
299
    FT_ULong  i;
 
300
 
 
301
 
 
302
    for ( i = 0; i < ntables; i++ )
 
303
      if ( tables[i].type == type )
 
304
      {
 
305
        if ( stream->pos > tables[i].offset )
 
306
        {
 
307
          error = PCF_Err_Invalid_Stream_Skip;
 
308
          goto Fail;
 
309
        }
 
310
 
 
311
        if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) )
 
312
        {
 
313
          error = PCF_Err_Invalid_Stream_Skip;
 
314
          goto Fail;
 
315
        }
 
316
 
 
317
        *asize   = tables[i].size;
 
318
        *aformat = tables[i].format;
 
319
 
 
320
        return PCF_Err_Ok;
 
321
      }
 
322
 
 
323
  Fail:
 
324
    *asize = 0;
 
325
    return error;
 
326
  }
 
327
 
 
328
 
 
329
  static FT_Bool
 
330
  pcf_has_table_type( PCF_Table  tables,
 
331
                      FT_ULong   ntables, /* same as PCF_Toc->count */
 
332
                      FT_ULong   type )
 
333
  {
 
334
    FT_ULong  i;
 
335
 
 
336
 
 
337
    for ( i = 0; i < ntables; i++ )
 
338
      if ( tables[i].type == type )
 
339
        return TRUE;
 
340
 
 
341
    return FALSE;
 
342
  }
 
343
 
 
344
 
 
345
#define PCF_PROPERTY_SIZE  9
 
346
 
 
347
  static
 
348
  const FT_Frame_Field  pcf_property_header[] =
 
349
  {
 
350
#undef  FT_STRUCTURE
 
351
#define FT_STRUCTURE  PCF_ParsePropertyRec
 
352
 
 
353
    FT_FRAME_START( PCF_PROPERTY_SIZE ),
 
354
      FT_FRAME_LONG_LE( name ),
 
355
      FT_FRAME_BYTE   ( isString ),
 
356
      FT_FRAME_LONG_LE( value ),
 
357
    FT_FRAME_END
 
358
  };
 
359
 
 
360
 
 
361
  static
 
362
  const FT_Frame_Field  pcf_property_msb_header[] =
 
363
  {
 
364
#undef  FT_STRUCTURE
 
365
#define FT_STRUCTURE  PCF_ParsePropertyRec
 
366
 
 
367
    FT_FRAME_START( PCF_PROPERTY_SIZE ),
 
368
      FT_FRAME_LONG( name ),
 
369
      FT_FRAME_BYTE( isString ),
 
370
      FT_FRAME_LONG( value ),
 
371
    FT_FRAME_END
 
372
  };
 
373
 
 
374
 
 
375
  FT_LOCAL_DEF( PCF_Property )
 
376
  pcf_find_property( PCF_Face          face,
 
377
                     const FT_String*  prop )
 
378
  {
 
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
    {
 
386
      if ( !ft_strcmp( properties[i].name, prop ) )
 
387
        found = 1;
 
388
    }
 
389
 
 
390
    if ( found )
 
391
      return properties + i - 1;
 
392
    else
 
393
      return NULL;
 
394
  }
 
395
 
 
396
 
 
397
  static FT_Error
 
398
  pcf_get_properties( FT_Stream  stream,
 
399
                      PCF_Face   face )
 
400
  {
 
401
    PCF_ParseProperty  props      = 0;
 
402
    PCF_Property       properties;
 
403
    FT_ULong           nprops, i;
 
404
    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;
 
409
 
 
410
 
 
411
    error = pcf_seek_to_table_type( stream,
 
412
                                    face->toc.tables,
 
413
                                    face->toc.count,
 
414
                                    PCF_PROPERTIES,
 
415
                                    &format,
 
416
                                    &size );
 
417
    if ( error )
 
418
      goto Bail;
 
419
 
 
420
    if ( FT_READ_ULONG_LE( format ) )
 
421
      goto Bail;
 
422
 
 
423
    FT_TRACE4(( "pcf_get_properties:\n" ));
 
424
 
 
425
    FT_TRACE4(( "  format = %ld\n", format ));
 
426
 
 
427
    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
 
428
      goto Bail;
 
429
 
 
430
    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
431
      (void)FT_READ_ULONG( nprops );
 
432
    else
 
433
      (void)FT_READ_ULONG_LE( nprops );
 
434
    if ( error )
 
435
      goto Bail;
 
436
 
 
437
    FT_TRACE4(( "  nprop = %d (truncate %d props)\n",
 
438
                (int)nprops, nprops - (int)nprops ));
 
439
 
 
440
    nprops = (int)nprops;
 
441
 
 
442
    /* rough estimate */
 
443
    if ( nprops > size / PCF_PROPERTY_SIZE )
 
444
    {
 
445
      error = PCF_Err_Invalid_Table;
 
446
      goto Bail;
 
447
    }
 
448
 
 
449
    face->nprops = (int)nprops;
 
450
 
 
451
    if ( FT_NEW_ARRAY( props, nprops ) )
 
452
      goto Bail;
 
453
 
 
454
    for ( i = 0; i < nprops; i++ )
 
455
    {
 
456
      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
457
      {
 
458
        if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) )
 
459
          goto Bail;
 
460
      }
 
461
      else
 
462
      {
 
463
        if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) )
 
464
          goto Bail;
 
465
      }
 
466
    }
 
467
 
 
468
    /* pad the property array                                            */
 
469
    /*                                                                   */
 
470
    /* clever here - nprops is the same as the number of odd-units read, */
 
471
    /* as only isStringProp are odd length   (Keith Packard)             */
 
472
    /*                                                                   */
 
473
    if ( nprops & 3 )
 
474
    {
 
475
      i = 4 - ( nprops & 3 );
 
476
      if ( FT_STREAM_SKIP( i ) )
 
477
      {
 
478
        error = PCF_Err_Invalid_Stream_Skip;
 
479
        goto Bail;
 
480
      }
 
481
    }
 
482
 
 
483
    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
484
      (void)FT_READ_ULONG( string_size );
 
485
    else
 
486
      (void)FT_READ_ULONG_LE( string_size );
 
487
    if ( error )
 
488
      goto Bail;
 
489
 
 
490
    FT_TRACE4(( "  string_size = %ld\n", string_size ));
 
491
 
 
492
    /* rough estimate */
 
493
    if ( string_size > size - nprops * PCF_PROPERTY_SIZE )
 
494
    {
 
495
      error = PCF_Err_Invalid_Table;
 
496
      goto Bail;
 
497
    }
 
498
 
 
499
    if ( FT_NEW_ARRAY( strings, string_size ) )
 
500
      goto Bail;
 
501
 
 
502
    error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );
 
503
    if ( error )
 
504
      goto Bail;
 
505
 
 
506
    if ( FT_NEW_ARRAY( properties, nprops ) )
 
507
      goto Bail;
 
508
 
 
509
    face->properties = properties;
 
510
 
 
511
    for ( i = 0; i < nprops; i++ )
 
512
    {
 
513
      FT_Long  name_offset = props[i].name;
 
514
 
 
515
 
 
516
      if ( ( name_offset < 0 )                     ||
 
517
           ( (FT_ULong)name_offset > string_size ) )
 
518
      {
 
519
        error = PCF_Err_Invalid_Offset;
 
520
        goto Bail;
 
521
      }
 
522
 
 
523
      if ( FT_STRDUP( properties[i].name, strings + name_offset ) )
 
524
        goto Bail;
 
525
 
 
526
      FT_TRACE4(( "  %s:", properties[i].name ));
 
527
 
 
528
      properties[i].isString = props[i].isString;
 
529
 
 
530
      if ( props[i].isString )
 
531
      {
 
532
        FT_Long  value_offset = props[i].value;
 
533
 
 
534
 
 
535
        if ( ( value_offset < 0 )                     ||
 
536
             ( (FT_ULong)value_offset > string_size ) )
 
537
        {
 
538
          error = PCF_Err_Invalid_Offset;
 
539
          goto Bail;
 
540
        }
 
541
 
 
542
        if ( FT_STRDUP( properties[i].value.atom, strings + value_offset ) )
 
543
          goto Bail;
 
544
 
 
545
        FT_TRACE4(( " `%s'\n", properties[i].value.atom ));
 
546
      }
 
547
      else
 
548
      {
 
549
        properties[i].value.l = props[i].value;
 
550
 
 
551
        FT_TRACE4(( " %d\n", properties[i].value.l ));
 
552
      }
 
553
    }
 
554
 
 
555
    error = PCF_Err_Ok;
 
556
 
 
557
  Bail:
 
558
    FT_FREE( props );
 
559
    FT_FREE( strings );
 
560
 
 
561
    return error;
 
562
  }
 
563
 
 
564
 
 
565
  static FT_Error
 
566
  pcf_get_metrics( FT_Stream  stream,
 
567
                   PCF_Face   face )
 
568
  {
 
569
    FT_Error    error    = PCF_Err_Ok;
 
570
    FT_Memory   memory   = FT_FACE(face)->memory;
 
571
    FT_ULong    format, size;
 
572
    PCF_Metric  metrics  = 0;
 
573
    FT_ULong    nmetrics, i;
 
574
 
 
575
 
 
576
    error = pcf_seek_to_table_type( stream,
 
577
                                    face->toc.tables,
 
578
                                    face->toc.count,
 
579
                                    PCF_METRICS,
 
580
                                    &format,
 
581
                                    &size );
 
582
    if ( error )
 
583
      return error;
 
584
 
 
585
    if ( FT_READ_ULONG_LE( format ) )
 
586
      goto Bail;
 
587
 
 
588
    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT )     &&
 
589
         !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
 
590
      return PCF_Err_Invalid_File_Format;
 
591
 
 
592
    if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
 
593
    {
 
594
      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
595
        (void)FT_READ_ULONG( nmetrics );
 
596
      else
 
597
        (void)FT_READ_ULONG_LE( nmetrics );
 
598
    }
 
599
    else
 
600
    {
 
601
      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
602
        (void)FT_READ_USHORT( nmetrics );
 
603
      else
 
604
        (void)FT_READ_USHORT_LE( nmetrics );
 
605
    }
 
606
    if ( error )
 
607
      return PCF_Err_Invalid_File_Format;
 
608
 
 
609
    face->nmetrics = nmetrics;
 
610
 
 
611
    if ( !nmetrics )
 
612
      return PCF_Err_Invalid_Table;
 
613
 
 
614
    FT_TRACE4(( "pcf_get_metrics:\n" ));
 
615
 
 
616
    FT_TRACE4(( "  number of metrics: %d\n", nmetrics ));
 
617
 
 
618
    /* rough estimate */
 
619
    if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
 
620
    {
 
621
      if ( nmetrics > size / PCF_METRIC_SIZE )
 
622
        return PCF_Err_Invalid_Table;
 
623
    }
 
624
    else
 
625
    {
 
626
      if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
 
627
        return PCF_Err_Invalid_Table;
 
628
    }
 
629
 
 
630
    if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )
 
631
      return PCF_Err_Out_Of_Memory;
 
632
 
 
633
    metrics = face->metrics;
 
634
    for ( i = 0; i < nmetrics; i++ )
 
635
    {
 
636
      error = pcf_get_metric( stream, format, metrics + i );
 
637
 
 
638
      metrics[i].bits = 0;
 
639
 
 
640
      FT_TRACE5(( "  idx %d: width=%d, "
 
641
                  "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
 
642
                  i,
 
643
                  ( metrics + i )->characterWidth,
 
644
                  ( metrics + i )->leftSideBearing,
 
645
                  ( metrics + i )->rightSideBearing,
 
646
                  ( metrics + i )->ascent,
 
647
                  ( metrics + i )->descent,
 
648
                  ( metrics + i )->attributes ));
 
649
 
 
650
      if ( error )
 
651
        break;
 
652
    }
 
653
 
 
654
    if ( error )
 
655
      FT_FREE( face->metrics );
 
656
 
 
657
  Bail:
 
658
    return error;
 
659
  }
 
660
 
 
661
 
 
662
  static FT_Error
 
663
  pcf_get_bitmaps( FT_Stream  stream,
 
664
                   PCF_Face   face )
 
665
  {
 
666
    FT_Error   error  = PCF_Err_Ok;
 
667
    FT_Memory  memory = FT_FACE(face)->memory;
 
668
    FT_Long*   offsets;
 
669
    FT_Long    bitmapSizes[GLYPHPADOPTIONS];
 
670
    FT_ULong   format, size;
 
671
    FT_ULong   nbitmaps, i, sizebitmaps = 0;
 
672
 
 
673
 
 
674
    error = pcf_seek_to_table_type( stream,
 
675
                                    face->toc.tables,
 
676
                                    face->toc.count,
 
677
                                    PCF_BITMAPS,
 
678
                                    &format,
 
679
                                    &size );
 
680
    if ( error )
 
681
      return error;
 
682
 
 
683
    error = FT_Stream_EnterFrame( stream, 8 );
 
684
    if ( error )
 
685
      return error;
 
686
 
 
687
    format = FT_GET_ULONG_LE();
 
688
    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
689
      nbitmaps  = FT_GET_ULONG();
 
690
    else
 
691
      nbitmaps  = FT_GET_ULONG_LE();
 
692
 
 
693
    FT_Stream_ExitFrame( stream );
 
694
 
 
695
    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
 
696
      return PCF_Err_Invalid_File_Format;
 
697
 
 
698
    FT_TRACE4(( "pcf_get_bitmaps:\n" ));
 
699
 
 
700
    FT_TRACE4(( "  number of bitmaps: %d\n", nbitmaps ));
 
701
 
 
702
    /* XXX: PCF_Face->nmetrics is singed FT_Long, see pcf.h */
 
703
    if ( face->nmetrics < 0 || nbitmaps != ( FT_ULong )face->nmetrics )
 
704
      return PCF_Err_Invalid_File_Format;
 
705
 
 
706
    if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
 
707
      return error;
 
708
 
 
709
    for ( i = 0; i < nbitmaps; i++ )
 
710
    {
 
711
      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
712
        (void)FT_READ_LONG( offsets[i] );
 
713
      else
 
714
        (void)FT_READ_LONG_LE( offsets[i] );
 
715
 
 
716
      FT_TRACE5(( "  bitmap %d: offset %ld (0x%lX)\n",
 
717
                  i, offsets[i], offsets[i] ));
 
718
    }
 
719
    if ( error )
 
720
      goto Bail;
 
721
 
 
722
    for ( i = 0; i < GLYPHPADOPTIONS; i++ )
 
723
    {
 
724
      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
725
        (void)FT_READ_LONG( bitmapSizes[i] );
 
726
      else
 
727
        (void)FT_READ_LONG_LE( bitmapSizes[i] );
 
728
      if ( error )
 
729
        goto Bail;
 
730
 
 
731
      sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
 
732
 
 
733
      FT_TRACE4(( "  padding %d implies a size of %ld\n", i, bitmapSizes[i] ));
 
734
    }
 
735
 
 
736
    FT_TRACE4(( "  %d bitmaps, padding index %ld\n",
 
737
                nbitmaps,
 
738
                PCF_GLYPH_PAD_INDEX( format ) ));
 
739
    FT_TRACE4(( "  bitmap size = %d\n", sizebitmaps ));
 
740
 
 
741
    FT_UNUSED( sizebitmaps );       /* only used for debugging */
 
742
 
 
743
    for ( i = 0; i < nbitmaps; i++ )
 
744
    {
 
745
      /* rough estimate */
 
746
      if ( ( offsets[i] < 0 )              ||
 
747
           ( (FT_ULong)offsets[i] > size ) )
 
748
      {
 
749
        FT_TRACE0(( "pcf_get_bitmaps:"
 
750
                    " invalid offset to bitmap data of glyph %d\n", i ));
 
751
      }
 
752
      else
 
753
        face->metrics[i].bits = stream->pos + offsets[i];
 
754
    }
 
755
 
 
756
    face->bitmapsFormat = format;
 
757
 
 
758
  Bail:
 
759
    FT_FREE( offsets );
 
760
    return error;
 
761
  }
 
762
 
 
763
 
 
764
  static FT_Error
 
765
  pcf_get_encodings( FT_Stream  stream,
 
766
                     PCF_Face   face )
 
767
  {
 
768
    FT_Error      error  = PCF_Err_Ok;
 
769
    FT_Memory     memory = FT_FACE(face)->memory;
 
770
    FT_ULong      format, size;
 
771
    int           firstCol, lastCol;
 
772
    int           firstRow, lastRow;
 
773
    int           nencoding, encodingOffset;
 
774
    int           i, j;
 
775
    PCF_Encoding  tmpEncoding, encoding = 0;
 
776
 
 
777
 
 
778
    error = pcf_seek_to_table_type( stream,
 
779
                                    face->toc.tables,
 
780
                                    face->toc.count,
 
781
                                    PCF_BDF_ENCODINGS,
 
782
                                    &format,
 
783
                                    &size );
 
784
    if ( error )
 
785
      return error;
 
786
 
 
787
    error = FT_Stream_EnterFrame( stream, 14 );
 
788
    if ( error )
 
789
      return error;
 
790
 
 
791
    format = FT_GET_ULONG_LE();
 
792
 
 
793
    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
794
    {
 
795
      firstCol          = FT_GET_SHORT();
 
796
      lastCol           = FT_GET_SHORT();
 
797
      firstRow          = FT_GET_SHORT();
 
798
      lastRow           = FT_GET_SHORT();
 
799
      face->defaultChar = FT_GET_SHORT();
 
800
    }
 
801
    else
 
802
    {
 
803
      firstCol          = FT_GET_SHORT_LE();
 
804
      lastCol           = FT_GET_SHORT_LE();
 
805
      firstRow          = FT_GET_SHORT_LE();
 
806
      lastRow           = FT_GET_SHORT_LE();
 
807
      face->defaultChar = FT_GET_SHORT_LE();
 
808
    }
 
809
 
 
810
    FT_Stream_ExitFrame( stream );
 
811
 
 
812
    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
 
813
      return PCF_Err_Invalid_File_Format;
 
814
 
 
815
    FT_TRACE4(( "pdf_get_encodings:\n" ));
 
816
 
 
817
    FT_TRACE4(( "  firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
 
818
                firstCol, lastCol, firstRow, lastRow ));
 
819
 
 
820
    nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );
 
821
 
 
822
    if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) )
 
823
      return PCF_Err_Out_Of_Memory;
 
824
 
 
825
    error = FT_Stream_EnterFrame( stream, 2 * nencoding );
 
826
    if ( error )
 
827
      goto Bail;
 
828
 
 
829
    for ( i = 0, j = 0 ; i < nencoding; i++ )
 
830
    {
 
831
      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
832
        encodingOffset = FT_GET_SHORT();
 
833
      else
 
834
        encodingOffset = FT_GET_SHORT_LE();
 
835
 
 
836
      if ( encodingOffset != -1 )
 
837
      {
 
838
        tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
 
839
                                 firstRow ) * 256 ) +
 
840
                               ( ( i % ( lastCol - firstCol + 1 ) ) +
 
841
                                 firstCol );
 
842
 
 
843
        tmpEncoding[j].glyph = (FT_Short)encodingOffset;
 
844
 
 
845
        FT_TRACE5(( "  code %d (0x%04X): idx %d\n",
 
846
                    tmpEncoding[j].enc, tmpEncoding[j].enc,
 
847
                    tmpEncoding[j].glyph ));
 
848
 
 
849
        j++;
 
850
      }
 
851
    }
 
852
    FT_Stream_ExitFrame( stream );
 
853
 
 
854
    if ( FT_NEW_ARRAY( encoding, j ) )
 
855
      goto Bail;
 
856
 
 
857
    for ( i = 0; i < j; i++ )
 
858
    {
 
859
      encoding[i].enc   = tmpEncoding[i].enc;
 
860
      encoding[i].glyph = tmpEncoding[i].glyph;
 
861
    }
 
862
 
 
863
    face->nencodings = j;
 
864
    face->encodings  = encoding;
 
865
    FT_FREE( tmpEncoding );
 
866
 
 
867
    return error;
 
868
 
 
869
  Bail:
 
870
    FT_FREE( encoding );
 
871
    FT_FREE( tmpEncoding );
 
872
    return error;
 
873
  }
 
874
 
 
875
 
 
876
  static
 
877
  const FT_Frame_Field  pcf_accel_header[] =
 
878
  {
 
879
#undef  FT_STRUCTURE
 
880
#define FT_STRUCTURE  PCF_AccelRec
 
881
 
 
882
    FT_FRAME_START( 20 ),
 
883
      FT_FRAME_BYTE      ( noOverlap ),
 
884
      FT_FRAME_BYTE      ( constantMetrics ),
 
885
      FT_FRAME_BYTE      ( terminalFont ),
 
886
      FT_FRAME_BYTE      ( constantWidth ),
 
887
      FT_FRAME_BYTE      ( inkInside ),
 
888
      FT_FRAME_BYTE      ( inkMetrics ),
 
889
      FT_FRAME_BYTE      ( drawDirection ),
 
890
      FT_FRAME_SKIP_BYTES( 1 ),
 
891
      FT_FRAME_LONG_LE   ( fontAscent ),
 
892
      FT_FRAME_LONG_LE   ( fontDescent ),
 
893
      FT_FRAME_LONG_LE   ( maxOverlap ),
 
894
    FT_FRAME_END
 
895
  };
 
896
 
 
897
 
 
898
  static
 
899
  const FT_Frame_Field  pcf_accel_msb_header[] =
 
900
  {
 
901
#undef  FT_STRUCTURE
 
902
#define FT_STRUCTURE  PCF_AccelRec
 
903
 
 
904
    FT_FRAME_START( 20 ),
 
905
      FT_FRAME_BYTE      ( noOverlap ),
 
906
      FT_FRAME_BYTE      ( constantMetrics ),
 
907
      FT_FRAME_BYTE      ( terminalFont ),
 
908
      FT_FRAME_BYTE      ( constantWidth ),
 
909
      FT_FRAME_BYTE      ( inkInside ),
 
910
      FT_FRAME_BYTE      ( inkMetrics ),
 
911
      FT_FRAME_BYTE      ( drawDirection ),
 
912
      FT_FRAME_SKIP_BYTES( 1 ),
 
913
      FT_FRAME_LONG      ( fontAscent ),
 
914
      FT_FRAME_LONG      ( fontDescent ),
 
915
      FT_FRAME_LONG      ( maxOverlap ),
 
916
    FT_FRAME_END
 
917
  };
 
918
 
 
919
 
 
920
  static FT_Error
 
921
  pcf_get_accel( FT_Stream  stream,
 
922
                 PCF_Face   face,
 
923
                 FT_ULong   type )
 
924
  {
 
925
    FT_ULong   format, size;
 
926
    FT_Error   error = PCF_Err_Ok;
 
927
    PCF_Accel  accel = &face->accel;
 
928
 
 
929
 
 
930
    error = pcf_seek_to_table_type( stream,
 
931
                                    face->toc.tables,
 
932
                                    face->toc.count,
 
933
                                    type,
 
934
                                    &format,
 
935
                                    &size );
 
936
    if ( error )
 
937
      goto Bail;
 
938
 
 
939
    if ( FT_READ_ULONG_LE( format ) )
 
940
      goto Bail;
 
941
 
 
942
    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT )    &&
 
943
         !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
 
944
      goto Bail;
 
945
 
 
946
    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
 
947
    {
 
948
      if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) )
 
949
        goto Bail;
 
950
    }
 
951
    else
 
952
    {
 
953
      if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) )
 
954
        goto Bail;
 
955
    }
 
956
 
 
957
    error = pcf_get_metric( stream,
 
958
                            format & ( ~PCF_FORMAT_MASK ),
 
959
                            &(accel->minbounds) );
 
960
    if ( error )
 
961
      goto Bail;
 
962
 
 
963
    error = pcf_get_metric( stream,
 
964
                            format & ( ~PCF_FORMAT_MASK ),
 
965
                            &(accel->maxbounds) );
 
966
    if ( error )
 
967
      goto Bail;
 
968
 
 
969
    if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
 
970
    {
 
971
      error = pcf_get_metric( stream,
 
972
                              format & ( ~PCF_FORMAT_MASK ),
 
973
                              &(accel->ink_minbounds) );
 
974
      if ( error )
 
975
        goto Bail;
 
976
 
 
977
      error = pcf_get_metric( stream,
 
978
                              format & ( ~PCF_FORMAT_MASK ),
 
979
                              &(accel->ink_maxbounds) );
 
980
      if ( error )
 
981
        goto Bail;
 
982
    }
 
983
    else
 
984
    {
 
985
      accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */
 
986
      accel->ink_maxbounds = accel->maxbounds;
 
987
    }
 
988
 
 
989
  Bail:
 
990
    return error;
 
991
  }
 
992
 
 
993
 
 
994
  static FT_Error
 
995
  pcf_interpret_style( PCF_Face  pcf )
 
996
  {
 
997
    FT_Error   error  = PCF_Err_Ok;
 
998
    FT_Face    face   = FT_FACE( pcf );
 
999
    FT_Memory  memory = face->memory;
 
1000
 
 
1001
    PCF_Property  prop;
 
1002
 
 
1003
    size_t  nn, len;
 
1004
    char*   strings[4] = { NULL, NULL, NULL, NULL };
 
1005
    size_t  lengths[4];
 
1006
 
 
1007
 
 
1008
    face->style_flags = 0;
 
1009
 
 
1010
    prop = pcf_find_property( pcf, "SLANT" );
 
1011
    if ( prop && prop->isString                                       &&
 
1012
         ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
 
1013
           *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
 
1014
    {
 
1015
      face->style_flags |= FT_STYLE_FLAG_ITALIC;
 
1016
      strings[2] = ( *(prop->value.atom) == 'O' ||
 
1017
                     *(prop->value.atom) == 'o' ) ? (char *)"Oblique"
 
1018
                                                  : (char *)"Italic";
 
1019
    }
 
1020
 
 
1021
    prop = pcf_find_property( pcf, "WEIGHT_NAME" );
 
1022
    if ( prop && prop->isString                                       &&
 
1023
         ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
 
1024
    {
 
1025
      face->style_flags |= FT_STYLE_FLAG_BOLD;
 
1026
      strings[1] = (char *)"Bold";
 
1027
    }
 
1028
 
 
1029
    prop = pcf_find_property( pcf, "SETWIDTH_NAME" );
 
1030
    if ( prop && prop->isString                                        &&
 
1031
         *(prop->value.atom)                                           &&
 
1032
         !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
 
1033
      strings[3] = (char *)(prop->value.atom);
 
1034
 
 
1035
    prop = pcf_find_property( pcf, "ADD_STYLE_NAME" );
 
1036
    if ( prop && prop->isString                                        &&
 
1037
         *(prop->value.atom)                                           &&
 
1038
         !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
 
1039
      strings[0] = (char *)(prop->value.atom);
 
1040
 
 
1041
    for ( len = 0, nn = 0; nn < 4; nn++ )
 
1042
    {
 
1043
      lengths[nn] = 0;
 
1044
      if ( strings[nn] )
 
1045
      {
 
1046
        lengths[nn] = ft_strlen( strings[nn] );
 
1047
        len        += lengths[nn] + 1;
 
1048
      }
 
1049
    }
 
1050
 
 
1051
    if ( len == 0 )
 
1052
    {
 
1053
      strings[0] = (char *)"Regular";
 
1054
      lengths[0] = ft_strlen( strings[0] );
 
1055
      len        = lengths[0] + 1;
 
1056
    }
 
1057
 
 
1058
    {
 
1059
      char*  s;
 
1060
 
 
1061
 
 
1062
      if ( FT_ALLOC( face->style_name, len ) )
 
1063
        return error;
 
1064
 
 
1065
      s = face->style_name;
 
1066
 
 
1067
      for ( nn = 0; nn < 4; nn++ )
 
1068
      {
 
1069
        char*  src = strings[nn];
 
1070
 
 
1071
 
 
1072
        len = lengths[nn];
 
1073
 
 
1074
        if ( src == NULL )
 
1075
          continue;
 
1076
 
 
1077
        /* separate elements with a space */
 
1078
        if ( s != face->style_name )
 
1079
          *s++ = ' ';
 
1080
 
 
1081
        ft_memcpy( s, src, len );
 
1082
 
 
1083
        /* need to convert spaces to dashes for */
 
1084
        /* add_style_name and setwidth_name     */
 
1085
        if ( nn == 0 || nn == 3 )
 
1086
        {
 
1087
          size_t  mm;
 
1088
 
 
1089
 
 
1090
          for ( mm = 0; mm < len; mm++ )
 
1091
            if (s[mm] == ' ')
 
1092
              s[mm] = '-';
 
1093
        }
 
1094
 
 
1095
        s += len;
 
1096
      }
 
1097
      *s = 0;
 
1098
    }
 
1099
 
 
1100
    return error;
 
1101
  }
 
1102
 
 
1103
 
 
1104
  FT_LOCAL_DEF( FT_Error )
 
1105
  pcf_load_font( FT_Stream  stream,
 
1106
                 PCF_Face   face )
 
1107
  {
 
1108
    FT_Error   error  = PCF_Err_Ok;
 
1109
    FT_Memory  memory = FT_FACE(face)->memory;
 
1110
    FT_Bool    hasBDFAccelerators;
 
1111
 
 
1112
 
 
1113
    error = pcf_read_TOC( stream, face );
 
1114
    if ( error )
 
1115
      goto Exit;
 
1116
 
 
1117
    error = pcf_get_properties( stream, face );
 
1118
    if ( error )
 
1119
      goto Exit;
 
1120
 
 
1121
    /* Use the old accelerators if no BDF accelerators are in the file. */
 
1122
    hasBDFAccelerators = pcf_has_table_type( face->toc.tables,
 
1123
                                             face->toc.count,
 
1124
                                             PCF_BDF_ACCELERATORS );
 
1125
    if ( !hasBDFAccelerators )
 
1126
    {
 
1127
      error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
 
1128
      if ( error )
 
1129
        goto Exit;
 
1130
    }
 
1131
 
 
1132
    /* metrics */
 
1133
    error = pcf_get_metrics( stream, face );
 
1134
    if ( error )
 
1135
      goto Exit;
 
1136
 
 
1137
    /* bitmaps */
 
1138
    error = pcf_get_bitmaps( stream, face );
 
1139
    if ( error )
 
1140
      goto Exit;
 
1141
 
 
1142
    /* encodings */
 
1143
    error = pcf_get_encodings( stream, face );
 
1144
    if ( error )
 
1145
      goto Exit;
 
1146
 
 
1147
    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
 
1148
    if ( hasBDFAccelerators )
 
1149
    {
 
1150
      error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
 
1151
      if ( error )
 
1152
        goto Exit;
 
1153
    }
 
1154
 
 
1155
    /* XXX: TO DO: inkmetrics and glyph_names are missing */
 
1156
 
 
1157
    /* now construct the face object */
 
1158
    {
 
1159
      FT_Face       root = FT_FACE( face );
 
1160
      PCF_Property  prop;
 
1161
 
 
1162
 
 
1163
      root->num_faces  = 1;
 
1164
      root->face_index = 0;
 
1165
      root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
 
1166
                         FT_FACE_FLAG_HORIZONTAL  |
 
1167
                         FT_FACE_FLAG_FAST_GLYPHS;
 
1168
 
 
1169
      if ( face->accel.constantWidth )
 
1170
        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
 
1171
 
 
1172
      if ( ( error = pcf_interpret_style( face ) ) != 0 )
 
1173
         goto Exit;
 
1174
 
 
1175
      prop = pcf_find_property( face, "FAMILY_NAME" );
 
1176
      if ( prop && prop->isString )
 
1177
      {
 
1178
        if ( FT_STRDUP( root->family_name, prop->value.atom ) )
 
1179
          goto Exit;
 
1180
      }
 
1181
      else
 
1182
        root->family_name = NULL;
 
1183
 
 
1184
      /*
 
1185
       * Note: We shift all glyph indices by +1 since we must
 
1186
       * respect the convention that glyph 0 always corresponds
 
1187
       * to the `missing glyph'.
 
1188
       *
 
1189
       * This implies bumping the number of `available' glyphs by 1.
 
1190
       */
 
1191
      root->num_glyphs = face->nmetrics + 1;
 
1192
 
 
1193
      root->num_fixed_sizes = 1;
 
1194
      if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
 
1195
        goto Exit;
 
1196
 
 
1197
      {
 
1198
        FT_Bitmap_Size*  bsize = root->available_sizes;
 
1199
        FT_Short         resolution_x = 0, resolution_y = 0;
 
1200
 
 
1201
 
 
1202
        FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
 
1203
 
 
1204
#if 0
 
1205
        bsize->height = face->accel.maxbounds.ascent << 6;
 
1206
#endif
 
1207
        bsize->height = (FT_Short)( face->accel.fontAscent +
 
1208
                                    face->accel.fontDescent );
 
1209
 
 
1210
        prop = pcf_find_property( face, "AVERAGE_WIDTH" );
 
1211
        if ( prop )
 
1212
          bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );
 
1213
        else
 
1214
          bsize->width = (FT_Short)( bsize->height * 2/3 );
 
1215
 
 
1216
        prop = pcf_find_property( face, "POINT_SIZE" );
 
1217
        if ( prop )
 
1218
          /* convert from 722.7 decipoints to 72 points per inch */
 
1219
          bsize->size =
 
1220
            (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );
 
1221
 
 
1222
        prop = pcf_find_property( face, "PIXEL_SIZE" );
 
1223
        if ( prop )
 
1224
          bsize->y_ppem = (FT_Short)prop->value.l << 6;
 
1225
 
 
1226
        prop = pcf_find_property( face, "RESOLUTION_X" );
 
1227
        if ( prop )
 
1228
          resolution_x = (FT_Short)prop->value.l;
 
1229
 
 
1230
        prop = pcf_find_property( face, "RESOLUTION_Y" );
 
1231
        if ( prop )
 
1232
          resolution_y = (FT_Short)prop->value.l;
 
1233
 
 
1234
        if ( bsize->y_ppem == 0 )
 
1235
        {
 
1236
          bsize->y_ppem = bsize->size;
 
1237
          if ( resolution_y )
 
1238
            bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
 
1239
        }
 
1240
        if ( resolution_x && resolution_y )
 
1241
          bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
 
1242
        else
 
1243
          bsize->x_ppem = bsize->y_ppem;
 
1244
      }
 
1245
 
 
1246
      /* set up charset */
 
1247
      {
 
1248
        PCF_Property  charset_registry = 0, charset_encoding = 0;
 
1249
 
 
1250
 
 
1251
        charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" );
 
1252
        charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" );
 
1253
 
 
1254
        if ( charset_registry && charset_registry->isString &&
 
1255
             charset_encoding && charset_encoding->isString )
 
1256
        {
 
1257
          if ( FT_STRDUP( face->charset_encoding,
 
1258
                          charset_encoding->value.atom ) ||
 
1259
               FT_STRDUP( face->charset_registry,
 
1260
                          charset_registry->value.atom ) )
 
1261
            goto Exit;
 
1262
        }
 
1263
      }
 
1264
    }
 
1265
 
 
1266
  Exit:
 
1267
    if ( error )
 
1268
    {
 
1269
      /* This is done to respect the behaviour of the original */
 
1270
      /* PCF font driver.                                      */
 
1271
      error = PCF_Err_Invalid_File_Format;
 
1272
    }
 
1273
 
 
1274
    return error;
 
1275
  }
 
1276
 
 
1277
 
 
1278
/* END */