~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/pcf/pcfread.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

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