Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/***************************************************************************/
2
/*                                                                         */
3
/*  cffload.c                                                              */
4
/*                                                                         */
5
/*    OpenType and CFF data/program tables loader (body).                  */
6
/*                                                                         */
7
/*  Copyright 1996-2013 by                                                 */
8
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9
/*                                                                         */
10
/*  This file is part of the FreeType project, and may only be used,       */
11
/*  modified, and distributed under the terms of the FreeType project      */
12
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13
/*  this file you indicate that you have read the license and              */
14
/*  understand and accept it fully.                                        */
15
/*                                                                         */
16
/***************************************************************************/
17
 
18
 
19
#include 
20
#include FT_INTERNAL_DEBUG_H
21
#include FT_INTERNAL_OBJECTS_H
22
#include FT_INTERNAL_STREAM_H
23
#include FT_TRUETYPE_TAGS_H
24
#include FT_TYPE1_TABLES_H
25
 
26
#include "cffload.h"
27
#include "cffparse.h"
28
 
29
#include "cfferrs.h"
30
 
31
 
32
#if 1
33
 
34
  static const FT_UShort  cff_isoadobe_charset[229] =
35
  {
36
      0,   1,   2,   3,   4,   5,   6,   7,
37
      8,   9,  10,  11,  12,  13,  14,  15,
38
     16,  17,  18,  19,  20,  21,  22,  23,
39
     24,  25,  26,  27,  28,  29,  30,  31,
40
     32,  33,  34,  35,  36,  37,  38,  39,
41
     40,  41,  42,  43,  44,  45,  46,  47,
42
     48,  49,  50,  51,  52,  53,  54,  55,
43
     56,  57,  58,  59,  60,  61,  62,  63,
44
     64,  65,  66,  67,  68,  69,  70,  71,
45
     72,  73,  74,  75,  76,  77,  78,  79,
46
     80,  81,  82,  83,  84,  85,  86,  87,
47
     88,  89,  90,  91,  92,  93,  94,  95,
48
     96,  97,  98,  99, 100, 101, 102, 103,
49
    104, 105, 106, 107, 108, 109, 110, 111,
50
    112, 113, 114, 115, 116, 117, 118, 119,
51
    120, 121, 122, 123, 124, 125, 126, 127,
52
    128, 129, 130, 131, 132, 133, 134, 135,
53
    136, 137, 138, 139, 140, 141, 142, 143,
54
    144, 145, 146, 147, 148, 149, 150, 151,
55
    152, 153, 154, 155, 156, 157, 158, 159,
56
    160, 161, 162, 163, 164, 165, 166, 167,
57
    168, 169, 170, 171, 172, 173, 174, 175,
58
    176, 177, 178, 179, 180, 181, 182, 183,
59
    184, 185, 186, 187, 188, 189, 190, 191,
60
    192, 193, 194, 195, 196, 197, 198, 199,
61
    200, 201, 202, 203, 204, 205, 206, 207,
62
    208, 209, 210, 211, 212, 213, 214, 215,
63
    216, 217, 218, 219, 220, 221, 222, 223,
64
    224, 225, 226, 227, 228
65
  };
66
 
67
  static const FT_UShort  cff_expert_charset[166] =
68
  {
69
      0,   1, 229, 230, 231, 232, 233, 234,
70
    235, 236, 237, 238,  13,  14,  15,  99,
71
    239, 240, 241, 242, 243, 244, 245, 246,
72
    247, 248,  27,  28, 249, 250, 251, 252,
73
    253, 254, 255, 256, 257, 258, 259, 260,
74
    261, 262, 263, 264, 265, 266, 109, 110,
75
    267, 268, 269, 270, 271, 272, 273, 274,
76
    275, 276, 277, 278, 279, 280, 281, 282,
77
    283, 284, 285, 286, 287, 288, 289, 290,
78
    291, 292, 293, 294, 295, 296, 297, 298,
79
    299, 300, 301, 302, 303, 304, 305, 306,
80
    307, 308, 309, 310, 311, 312, 313, 314,
81
    315, 316, 317, 318, 158, 155, 163, 319,
82
    320, 321, 322, 323, 324, 325, 326, 150,
83
    164, 169, 327, 328, 329, 330, 331, 332,
84
    333, 334, 335, 336, 337, 338, 339, 340,
85
    341, 342, 343, 344, 345, 346, 347, 348,
86
    349, 350, 351, 352, 353, 354, 355, 356,
87
    357, 358, 359, 360, 361, 362, 363, 364,
88
    365, 366, 367, 368, 369, 370, 371, 372,
89
    373, 374, 375, 376, 377, 378
90
  };
91
 
92
  static const FT_UShort  cff_expertsubset_charset[87] =
93
  {
94
      0,   1, 231, 232, 235, 236, 237, 238,
95
     13,  14,  15,  99, 239, 240, 241, 242,
96
    243, 244, 245, 246, 247, 248,  27,  28,
97
    249, 250, 251, 253, 254, 255, 256, 257,
98
    258, 259, 260, 261, 262, 263, 264, 265,
99
    266, 109, 110, 267, 268, 269, 270, 272,
100
    300, 301, 302, 305, 314, 315, 158, 155,
101
    163, 320, 321, 322, 323, 324, 325, 326,
102
    150, 164, 169, 327, 328, 329, 330, 331,
103
    332, 333, 334, 335, 336, 337, 338, 339,
104
    340, 341, 342, 343, 344, 345, 346
105
  };
106
 
107
  static const FT_UShort  cff_standard_encoding[256] =
108
  {
109
      0,   0,   0,   0,   0,   0,   0,   0,
110
      0,   0,   0,   0,   0,   0,   0,   0,
111
      0,   0,   0,   0,   0,   0,   0,   0,
112
      0,   0,   0,   0,   0,   0,   0,   0,
113
      1,   2,   3,   4,   5,   6,   7,   8,
114
      9,  10,  11,  12,  13,  14,  15,  16,
115
     17,  18,  19,  20,  21,  22,  23,  24,
116
     25,  26,  27,  28,  29,  30,  31,  32,
117
     33,  34,  35,  36,  37,  38,  39,  40,
118
     41,  42,  43,  44,  45,  46,  47,  48,
119
     49,  50,  51,  52,  53,  54,  55,  56,
120
     57,  58,  59,  60,  61,  62,  63,  64,
121
     65,  66,  67,  68,  69,  70,  71,  72,
122
     73,  74,  75,  76,  77,  78,  79,  80,
123
     81,  82,  83,  84,  85,  86,  87,  88,
124
     89,  90,  91,  92,  93,  94,  95,   0,
125
      0,   0,   0,   0,   0,   0,   0,   0,
126
      0,   0,   0,   0,   0,   0,   0,   0,
127
      0,   0,   0,   0,   0,   0,   0,   0,
128
      0,   0,   0,   0,   0,   0,   0,   0,
129
      0,  96,  97,  98,  99, 100, 101, 102,
130
    103, 104, 105, 106, 107, 108, 109, 110,
131
      0, 111, 112, 113, 114,   0, 115, 116,
132
    117, 118, 119, 120, 121, 122,   0, 123,
133
      0, 124, 125, 126, 127, 128, 129, 130,
134
    131,   0, 132, 133,   0, 134, 135, 136,
135
    137,   0,   0,   0,   0,   0,   0,   0,
136
      0,   0,   0,   0,   0,   0,   0,   0,
137
      0, 138,   0, 139,   0,   0,   0,   0,
138
    140, 141, 142, 143,   0,   0,   0,   0,
139
      0, 144,   0,   0,   0, 145,   0,   0,
140
    146, 147, 148, 149,   0,   0,   0,   0
141
  };
142
 
143
  static const FT_UShort  cff_expert_encoding[256] =
144
  {
145
      0,   0,   0,   0,   0,   0,   0,   0,
146
      0,   0,   0,   0,   0,   0,   0,   0,
147
      0,   0,   0,   0,   0,   0,   0,   0,
148
      0,   0,   0,   0,   0,   0,   0,   0,
149
      1, 229, 230,   0, 231, 232, 233, 234,
150
    235, 236, 237, 238,  13,  14,  15,  99,
151
    239, 240, 241, 242, 243, 244, 245, 246,
152
    247, 248,  27,  28, 249, 250, 251, 252,
153
      0, 253, 254, 255, 256, 257,   0,   0,
154
      0, 258,   0,   0, 259, 260, 261, 262,
155
      0,   0, 263, 264, 265,   0, 266, 109,
156
    110, 267, 268, 269,   0, 270, 271, 272,
157
    273, 274, 275, 276, 277, 278, 279, 280,
158
    281, 282, 283, 284, 285, 286, 287, 288,
159
    289, 290, 291, 292, 293, 294, 295, 296,
160
    297, 298, 299, 300, 301, 302, 303,   0,
161
      0,   0,   0,   0,   0,   0,   0,   0,
162
      0,   0,   0,   0,   0,   0,   0,   0,
163
      0,   0,   0,   0,   0,   0,   0,   0,
164
      0,   0,   0,   0,   0,   0,   0,   0,
165
      0, 304, 305, 306,   0,   0, 307, 308,
166
    309, 310, 311,   0, 312,   0,   0, 312,
167
      0,   0, 314, 315,   0,   0, 316, 317,
168
    318,   0,   0,   0, 158, 155, 163, 319,
169
    320, 321, 322, 323, 324, 325,   0,   0,
170
    326, 150, 164, 169, 327, 328, 329, 330,
171
    331, 332, 333, 334, 335, 336, 337, 338,
172
    339, 340, 341, 342, 343, 344, 345, 346,
173
    347, 348, 349, 350, 351, 352, 353, 354,
174
    355, 356, 357, 358, 359, 360, 361, 362,
175
    363, 364, 365, 366, 367, 368, 369, 370,
176
    371, 372, 373, 374, 375, 376, 377, 378
177
  };
178
 
179
#endif /* 1 */
180
 
181
 
182
  FT_LOCAL_DEF( FT_UShort )
183
  cff_get_standard_encoding( FT_UInt  charcode )
184
  {
185
    return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode]
186
                                       : 0 );
187
  }
188
 
189
 
190
  /*************************************************************************/
191
  /*                                                                       */
192
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
193
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
194
  /* messages during execution.                                            */
195
  /*                                                                       */
196
#undef  FT_COMPONENT
197
#define FT_COMPONENT  trace_cffload
198
 
199
 
200
  /* read an offset from the index's stream current position */
201
  static FT_ULong
202
  cff_index_read_offset( CFF_Index  idx,
203
                         FT_Error  *errorp )
204
  {
205
    FT_Error   error;
206
    FT_Stream  stream = idx->stream;
207
    FT_Byte    tmp[4];
208
    FT_ULong   result = 0;
209
 
210
 
211
    if ( !FT_STREAM_READ( tmp, idx->off_size ) )
212
    {
213
      FT_Int  nn;
214
 
215
 
216
      for ( nn = 0; nn < idx->off_size; nn++ )
217
        result = ( result << 8 ) | tmp[nn];
218
    }
219
 
220
    *errorp = error;
221
    return result;
222
  }
223
 
224
 
225
  static FT_Error
226
  cff_index_init( CFF_Index  idx,
227
                  FT_Stream  stream,
228
                  FT_Bool    load )
229
  {
230
    FT_Error   error;
231
    FT_Memory  memory = stream->memory;
232
    FT_UShort  count;
233
 
234
 
235
    FT_MEM_ZERO( idx, sizeof ( *idx ) );
236
 
237
    idx->stream = stream;
238
    idx->start  = FT_STREAM_POS();
239
    if ( !FT_READ_USHORT( count ) &&
240
         count > 0                )
241
    {
242
      FT_Byte   offsize;
243
      FT_ULong  size;
244
 
245
 
246
      /* there is at least one element; read the offset size,           */
247
      /* then access the offset table to compute the index's total size */
248
      if ( FT_READ_BYTE( offsize ) )
249
        goto Exit;
250
 
251
      if ( offsize < 1 || offsize > 4 )
252
      {
253
        error = FT_THROW( Invalid_Table );
254
        goto Exit;
255
      }
256
 
257
      idx->count    = count;
258
      idx->off_size = offsize;
259
      size          = (FT_ULong)( count + 1 ) * offsize;
260
 
261
      idx->data_offset = idx->start + 3 + size;
262
 
263
      if ( FT_STREAM_SKIP( size - offsize ) )
264
        goto Exit;
265
 
266
      size = cff_index_read_offset( idx, &error );
267
      if ( error )
268
        goto Exit;
269
 
270
      if ( size == 0 )
271
      {
272
        error = FT_THROW( Invalid_Table );
273
        goto Exit;
274
      }
275
 
276
      idx->data_size = --size;
277
 
278
      if ( load )
279
      {
280
        /* load the data */
281
        if ( FT_FRAME_EXTRACT( size, idx->bytes ) )
282
          goto Exit;
283
      }
284
      else
285
      {
286
        /* skip the data */
287
        if ( FT_STREAM_SKIP( size ) )
288
          goto Exit;
289
      }
290
    }
291
 
292
  Exit:
293
    if ( error )
294
      FT_FREE( idx->offsets );
295
 
296
    return error;
297
  }
298
 
299
 
300
  static void
301
  cff_index_done( CFF_Index  idx )
302
  {
303
    if ( idx->stream )
304
    {
305
      FT_Stream  stream = idx->stream;
306
      FT_Memory  memory = stream->memory;
307
 
308
 
309
      if ( idx->bytes )
310
        FT_FRAME_RELEASE( idx->bytes );
311
 
312
      FT_FREE( idx->offsets );
313
      FT_MEM_ZERO( idx, sizeof ( *idx ) );
314
    }
315
  }
316
 
317
 
318
  static FT_Error
319
  cff_index_load_offsets( CFF_Index  idx )
320
  {
321
    FT_Error   error  = FT_Err_Ok;
322
    FT_Stream  stream = idx->stream;
323
    FT_Memory  memory = stream->memory;
324
 
325
 
326
    if ( idx->count > 0 && idx->offsets == NULL )
327
    {
328
      FT_Byte    offsize = idx->off_size;
329
      FT_ULong   data_size;
330
      FT_Byte*   p;
331
      FT_Byte*   p_end;
332
      FT_ULong*  poff;
333
 
334
 
335
      data_size = (FT_ULong)( idx->count + 1 ) * offsize;
336
 
337
      if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
338
           FT_STREAM_SEEK( idx->start + 3 )             ||
339
           FT_FRAME_ENTER( data_size )                  )
340
        goto Exit;
341
 
342
      poff   = idx->offsets;
343
      p      = (FT_Byte*)stream->cursor;
344
      p_end  = p + data_size;
345
 
346
      switch ( offsize )
347
      {
348
      case 1:
349
        for ( ; p < p_end; p++, poff++ )
350
          poff[0] = p[0];
351
        break;
352
 
353
      case 2:
354
        for ( ; p < p_end; p += 2, poff++ )
355
          poff[0] = FT_PEEK_USHORT( p );
356
        break;
357
 
358
      case 3:
359
        for ( ; p < p_end; p += 3, poff++ )
360
          poff[0] = FT_PEEK_OFF3( p );
361
        break;
362
 
363
      default:
364
        for ( ; p < p_end; p += 4, poff++ )
365
          poff[0] = FT_PEEK_ULONG( p );
366
      }
367
 
368
      FT_FRAME_EXIT();
369
    }
370
 
371
  Exit:
372
    if ( error )
373
      FT_FREE( idx->offsets );
374
 
375
    return error;
376
  }
377
 
378
 
379
  /* Allocate a table containing pointers to an index's elements. */
380
  /* The `pool' argument makes this function convert the index    */
381
  /* entries to C-style strings (this is, NULL-terminated).       */
382
  static FT_Error
383
  cff_index_get_pointers( CFF_Index   idx,
384
                          FT_Byte***  table,
385
                          FT_Byte**   pool )
386
  {
387
    FT_Error   error     = FT_Err_Ok;
388
    FT_Memory  memory    = idx->stream->memory;
389
 
390
    FT_Byte**  t         = NULL;
391
    FT_Byte*   new_bytes = NULL;
392
 
393
 
394
    *table = NULL;
395
 
396
    if ( idx->offsets == NULL )
397
    {
398
      error = cff_index_load_offsets( idx );
399
      if ( error )
400
        goto Exit;
401
    }
402
 
403
    if ( idx->count > 0                                        &&
404
         !FT_NEW_ARRAY( t, idx->count + 1 )                    &&
405
         ( !pool || !FT_ALLOC( new_bytes,
406
                               idx->data_size + idx->count ) ) )
407
    {
408
      FT_ULong  n, cur_offset;
409
      FT_ULong  extra = 0;
410
      FT_Byte*  org_bytes = idx->bytes;
411
 
412
 
413
      /* at this point, `idx->offsets' can't be NULL */
414
      cur_offset = idx->offsets[0] - 1;
415
 
416
      /* sanity check */
417
      if ( cur_offset >= idx->data_size )
418
      {
419
        FT_TRACE0(( "cff_index_get_pointers:"
420
                    " invalid first offset value %d set to zero\n",
421
                    cur_offset ));
422
        cur_offset = 0;
423
      }
424
 
425
      if ( !pool )
426
        t[0] = org_bytes + cur_offset;
427
      else
428
        t[0] = new_bytes + cur_offset;
429
 
430
      for ( n = 1; n <= idx->count; n++ )
431
      {
432
        FT_ULong  next_offset = idx->offsets[n] - 1;
433
 
434
 
435
        /* empty slot + two sanity checks for invalid offset tables */
436
        if ( next_offset == 0                                    ||
437
             next_offset < cur_offset                            ||
438
             ( next_offset >= idx->data_size && n < idx->count ) )
439
          next_offset = cur_offset;
440
 
441
        if ( !pool )
442
          t[n] = org_bytes + next_offset;
443
        else
444
        {
445
          t[n] = new_bytes + next_offset + extra;
446
 
447
          if ( next_offset != cur_offset )
448
          {
449
            FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] );
450
            t[n][0] = '\0';
451
            t[n]   += 1;
452
            extra++;
453
          }
454
        }
455
 
456
        cur_offset = next_offset;
457
      }
458
      *table = t;
459
 
460
      if ( pool )
461
        *pool = new_bytes;
462
    }
463
 
464
  Exit:
465
    return error;
466
  }
467
 
468
 
469
  FT_LOCAL_DEF( FT_Error )
470
  cff_index_access_element( CFF_Index  idx,
471
                            FT_UInt    element,
472
                            FT_Byte**  pbytes,
473
                            FT_ULong*  pbyte_len )
474
  {
475
    FT_Error  error = FT_Err_Ok;
476
 
477
 
478
    if ( idx && idx->count > element )
479
    {
480
      /* compute start and end offsets */
481
      FT_Stream  stream = idx->stream;
482
      FT_ULong   off1, off2 = 0;
483
 
484
 
485
      /* load offsets from file or the offset table */
486
      if ( !idx->offsets )
487
      {
488
        FT_ULong  pos = element * idx->off_size;
489
 
490
 
491
        if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
492
          goto Exit;
493
 
494
        off1 = cff_index_read_offset( idx, &error );
495
        if ( error )
496
          goto Exit;
497
 
498
        if ( off1 != 0 )
499
        {
500
          do
501
          {
502
            element++;
503
            off2 = cff_index_read_offset( idx, &error );
504
          }
505
          while ( off2 == 0 && element < idx->count );
506
        }
507
      }
508
      else   /* use offsets table */
509
      {
510
        off1 = idx->offsets[element];
511
        if ( off1 )
512
        {
513
          do
514
          {
515
            element++;
516
            off2 = idx->offsets[element];
517
 
518
          } while ( off2 == 0 && element < idx->count );
519
        }
520
      }
521
 
522
      /* XXX: should check off2 does not exceed the end of this entry; */
523
      /*      at present, only truncate off2 at the end of this stream */
524
      if ( off2 > stream->size + 1                    ||
525
           idx->data_offset > stream->size - off2 + 1 )
526
      {
527
        FT_ERROR(( "cff_index_access_element:"
528
                   " offset to next entry (%d)"
529
                   " exceeds the end of stream (%d)\n",
530
                   off2, stream->size - idx->data_offset + 1 ));
531
        off2 = stream->size - idx->data_offset + 1;
532
      }
533
 
534
      /* access element */
535
      if ( off1 && off2 > off1 )
536
      {
537
        *pbyte_len = off2 - off1;
538
 
539
        if ( idx->bytes )
540
        {
541
          /* this index was completely loaded in memory, that's easy */
542
          *pbytes = idx->bytes + off1 - 1;
543
        }
544
        else
545
        {
546
          /* this index is still on disk/file, access it through a frame */
547
          if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||
548
               FT_FRAME_EXTRACT( off2 - off1, *pbytes )      )
549
            goto Exit;
550
        }
551
      }
552
      else
553
      {
554
        /* empty index element */
555
        *pbytes    = 0;
556
        *pbyte_len = 0;
557
      }
558
    }
559
    else
560
      error = FT_THROW( Invalid_Argument );
561
 
562
  Exit:
563
    return error;
564
  }
565
 
566
 
567
  FT_LOCAL_DEF( void )
568
  cff_index_forget_element( CFF_Index  idx,
569
                            FT_Byte**  pbytes )
570
  {
571
    if ( idx->bytes == 0 )
572
    {
573
      FT_Stream  stream = idx->stream;
574
 
575
 
576
      FT_FRAME_RELEASE( *pbytes );
577
    }
578
  }
579
 
580
 
581
  /* get an entry from Name INDEX */
582
  FT_LOCAL_DEF( FT_String* )
583
  cff_index_get_name( CFF_Font  font,
584
                      FT_UInt   element )
585
  {
586
    CFF_Index   idx = &font->name_index;
587
    FT_Memory   memory = idx->stream->memory;
588
    FT_Byte*    bytes;
589
    FT_ULong    byte_len;
590
    FT_Error    error;
591
    FT_String*  name = 0;
592
 
593
 
594
    error = cff_index_access_element( idx, element, &bytes, &byte_len );
595
    if ( error )
596
      goto Exit;
597
 
598
    if ( !FT_ALLOC( name, byte_len + 1 ) )
599
    {
600
      FT_MEM_COPY( name, bytes, byte_len );
601
      name[byte_len] = 0;
602
    }
603
    cff_index_forget_element( idx, &bytes );
604
 
605
  Exit:
606
    return name;
607
  }
608
 
609
 
610
  /* get an entry from String INDEX */
611
  FT_LOCAL_DEF( FT_String* )
612
  cff_index_get_string( CFF_Font  font,
613
                        FT_UInt   element )
614
  {
615
    return ( element < font->num_strings )
616
             ? (FT_String*)font->strings[element]
617
             : NULL;
618
  }
619
 
620
 
621
  FT_LOCAL_DEF( FT_String* )
622
  cff_index_get_sid_string( CFF_Font  font,
623
                            FT_UInt   sid )
624
  {
625
    /* value 0xFFFFU indicates a missing dictionary entry */
626
    if ( sid == 0xFFFFU )
627
      return NULL;
628
 
629
    /* if it is not a standard string, return it */
630
    if ( sid > 390 )
631
      return cff_index_get_string( font, sid - 391 );
632
 
633
    /* CID-keyed CFF fonts don't have glyph names */
634
    if ( !font->psnames )
635
      return NULL;
636
 
637
    /* this is a standard string */
638
    return (FT_String *)font->psnames->adobe_std_strings( sid );
639
  }
640
 
641
 
642
  /*************************************************************************/
643
  /*************************************************************************/
644
  /***                                                                   ***/
645
  /***   FD Select table support                                         ***/
646
  /***                                                                   ***/
647
  /*************************************************************************/
648
  /*************************************************************************/
649
 
650
 
651
  static void
652
  CFF_Done_FD_Select( CFF_FDSelect  fdselect,
653
                      FT_Stream     stream )
654
  {
655
    if ( fdselect->data )
656
      FT_FRAME_RELEASE( fdselect->data );
657
 
658
    fdselect->data_size   = 0;
659
    fdselect->format      = 0;
660
    fdselect->range_count = 0;
661
  }
662
 
663
 
664
  static FT_Error
665
  CFF_Load_FD_Select( CFF_FDSelect  fdselect,
666
                      FT_UInt       num_glyphs,
667
                      FT_Stream     stream,
668
                      FT_ULong      offset )
669
  {
670
    FT_Error  error;
671
    FT_Byte   format;
672
    FT_UInt   num_ranges;
673
 
674
 
675
    /* read format */
676
    if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) )
677
      goto Exit;
678
 
679
    fdselect->format      = format;
680
    fdselect->cache_count = 0;   /* clear cache */
681
 
682
    switch ( format )
683
    {
684
    case 0:     /* format 0, that's simple */
685
      fdselect->data_size = num_glyphs;
686
      goto Load_Data;
687
 
688
    case 3:     /* format 3, a tad more complex */
689
      if ( FT_READ_USHORT( num_ranges ) )
690
        goto Exit;
691
 
692
      fdselect->data_size = num_ranges * 3 + 2;
693
 
694
    Load_Data:
695
      if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) )
696
        goto Exit;
697
      break;
698
 
699
    default:    /* hmm... that's wrong */
700
      error = FT_THROW( Invalid_File_Format );
701
    }
702
 
703
  Exit:
704
    return error;
705
  }
706
 
707
 
708
  FT_LOCAL_DEF( FT_Byte )
709
  cff_fd_select_get( CFF_FDSelect  fdselect,
710
                     FT_UInt       glyph_index )
711
  {
712
    FT_Byte  fd = 0;
713
 
714
 
715
    switch ( fdselect->format )
716
    {
717
    case 0:
718
      fd = fdselect->data[glyph_index];
719
      break;
720
 
721
    case 3:
722
      /* first, compare to cache */
723
      if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
724
                        fdselect->cache_count )
725
      {
726
        fd = fdselect->cache_fd;
727
        break;
728
      }
729
 
730
      /* then, lookup the ranges array */
731
      {
732
        FT_Byte*  p       = fdselect->data;
733
        FT_Byte*  p_limit = p + fdselect->data_size;
734
        FT_Byte   fd2;
735
        FT_UInt   first, limit;
736
 
737
 
738
        first = FT_NEXT_USHORT( p );
739
        do
740
        {
741
          if ( glyph_index < first )
742
            break;
743
 
744
          fd2   = *p++;
745
          limit = FT_NEXT_USHORT( p );
746
 
747
          if ( glyph_index < limit )
748
          {
749
            fd = fd2;
750
 
751
            /* update cache */
752
            fdselect->cache_first = first;
753
            fdselect->cache_count = limit-first;
754
            fdselect->cache_fd    = fd2;
755
            break;
756
          }
757
          first = limit;
758
 
759
        } while ( p < p_limit );
760
      }
761
      break;
762
 
763
    default:
764
      ;
765
    }
766
 
767
    return fd;
768
  }
769
 
770
 
771
  /*************************************************************************/
772
  /*************************************************************************/
773
  /***                                                                   ***/
774
  /***   CFF font support                                                ***/
775
  /***                                                                   ***/
776
  /*************************************************************************/
777
  /*************************************************************************/
778
 
779
  static FT_Error
780
  cff_charset_compute_cids( CFF_Charset  charset,
781
                            FT_UInt      num_glyphs,
782
                            FT_Memory    memory )
783
  {
784
    FT_Error   error   = FT_Err_Ok;
785
    FT_UInt    i;
786
    FT_Long    j;
787
    FT_UShort  max_cid = 0;
788
 
789
 
790
    if ( charset->max_cid > 0 )
791
      goto Exit;
792
 
793
    for ( i = 0; i < num_glyphs; i++ )
794
    {
795
      if ( charset->sids[i] > max_cid )
796
        max_cid = charset->sids[i];
797
    }
798
 
799
    if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )
800
      goto Exit;
801
 
802
    /* When multiple GIDs map to the same CID, we choose the lowest */
803
    /* GID.  This is not described in any spec, but it matches the  */
804
    /* behaviour of recent Acroread versions.                       */
805
    for ( j = num_glyphs - 1; j >= 0 ; j-- )
806
      charset->cids[charset->sids[j]] = (FT_UShort)j;
807
 
808
    charset->max_cid    = max_cid;
809
    charset->num_glyphs = num_glyphs;
810
 
811
  Exit:
812
    return error;
813
  }
814
 
815
 
816
  FT_LOCAL_DEF( FT_UInt )
817
  cff_charset_cid_to_gindex( CFF_Charset  charset,
818
                             FT_UInt      cid )
819
  {
820
    FT_UInt  result = 0;
821
 
822
 
823
    if ( cid <= charset->max_cid )
824
      result = charset->cids[cid];
825
 
826
    return result;
827
  }
828
 
829
 
830
  static void
831
  cff_charset_free_cids( CFF_Charset  charset,
832
                         FT_Memory    memory )
833
  {
834
    FT_FREE( charset->cids );
835
    charset->max_cid = 0;
836
  }
837
 
838
 
839
  static void
840
  cff_charset_done( CFF_Charset  charset,
841
                    FT_Stream    stream )
842
  {
843
    FT_Memory  memory = stream->memory;
844
 
845
 
846
    cff_charset_free_cids( charset, memory );
847
 
848
    FT_FREE( charset->sids );
849
    charset->format = 0;
850
    charset->offset = 0;
851
  }
852
 
853
 
854
  static FT_Error
855
  cff_charset_load( CFF_Charset  charset,
856
                    FT_UInt      num_glyphs,
857
                    FT_Stream    stream,
858
                    FT_ULong     base_offset,
859
                    FT_ULong     offset,
860
                    FT_Bool      invert )
861
  {
862
    FT_Memory  memory = stream->memory;
863
    FT_Error   error  = FT_Err_Ok;
864
    FT_UShort  glyph_sid;
865
 
866
 
867
    /* If the the offset is greater than 2, we have to parse the */
868
    /* charset table.                                            */
869
    if ( offset > 2 )
870
    {
871
      FT_UInt  j;
872
 
873
 
874
      charset->offset = base_offset + offset;
875
 
876
      /* Get the format of the table. */
877
      if ( FT_STREAM_SEEK( charset->offset ) ||
878
           FT_READ_BYTE( charset->format )   )
879
        goto Exit;
880
 
881
      /* Allocate memory for sids. */
882
      if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
883
        goto Exit;
884
 
885
      /* assign the .notdef glyph */
886
      charset->sids[0] = 0;
887
 
888
      switch ( charset->format )
889
      {
890
      case 0:
891
        if ( num_glyphs > 0 )
892
        {
893
          if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) )
894
            goto Exit;
895
 
896
          for ( j = 1; j < num_glyphs; j++ )
897
            charset->sids[j] = FT_GET_USHORT();
898
 
899
          FT_FRAME_EXIT();
900
        }
901
        break;
902
 
903
      case 1:
904
      case 2:
905
        {
906
          FT_UInt  nleft;
907
          FT_UInt  i;
908
 
909
 
910
          j = 1;
911
 
912
          while ( j < num_glyphs )
913
          {
914
            /* Read the first glyph sid of the range. */
915
            if ( FT_READ_USHORT( glyph_sid ) )
916
              goto Exit;
917
 
918
            /* Read the number of glyphs in the range.  */
919
            if ( charset->format == 2 )
920
            {
921
              if ( FT_READ_USHORT( nleft ) )
922
                goto Exit;
923
            }
924
            else
925
            {
926
              if ( FT_READ_BYTE( nleft ) )
927
                goto Exit;
928
            }
929
 
930
            /* try to rescue some of the SIDs if `nleft' is too large */
931
            if ( glyph_sid > 0xFFFFL - nleft )
932
            {
933
              FT_ERROR(( "cff_charset_load: invalid SID range trimmed"
934
                         " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));
935
              nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );
936
            }
937
 
938
            /* Fill in the range of sids -- `nleft + 1' glyphs. */
939
            for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )
940
              charset->sids[j] = glyph_sid;
941
          }
942
        }
943
        break;
944
 
945
      default:
946
        FT_ERROR(( "cff_charset_load: invalid table format\n" ));
947
        error = FT_THROW( Invalid_File_Format );
948
        goto Exit;
949
      }
950
    }
951
    else
952
    {
953
      /* Parse default tables corresponding to offset == 0, 1, or 2.  */
954
      /* CFF specification intimates the following:                   */
955
      /*                                                              */
956
      /* In order to use a predefined charset, the following must be  */
957
      /* true: The charset constructed for the glyphs in the font's   */
958
      /* charstrings dictionary must match the predefined charset in  */
959
      /* the first num_glyphs.                                        */
960
 
961
      charset->offset = offset;  /* record charset type */
962
 
963
      switch ( (FT_UInt)offset )
964
      {
965
      case 0:
966
        if ( num_glyphs > 229 )
967
        {
968
          FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
969
                     "predefined charset (Adobe ISO-Latin)\n" ));
970
          error = FT_THROW( Invalid_File_Format );
971
          goto Exit;
972
        }
973
 
974
        /* Allocate memory for sids. */
975
        if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
976
          goto Exit;
977
 
978
        /* Copy the predefined charset into the allocated memory. */
979
        FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs );
980
 
981
        break;
982
 
983
      case 1:
984
        if ( num_glyphs > 166 )
985
        {
986
          FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
987
                     "predefined charset (Adobe Expert)\n" ));
988
          error = FT_THROW( Invalid_File_Format );
989
          goto Exit;
990
        }
991
 
992
        /* Allocate memory for sids. */
993
        if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
994
          goto Exit;
995
 
996
        /* Copy the predefined charset into the allocated memory.     */
997
        FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs );
998
 
999
        break;
1000
 
1001
      case 2:
1002
        if ( num_glyphs > 87 )
1003
        {
1004
          FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
1005
                     "predefined charset (Adobe Expert Subset)\n" ));
1006
          error = FT_THROW( Invalid_File_Format );
1007
          goto Exit;
1008
        }
1009
 
1010
        /* Allocate memory for sids. */
1011
        if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
1012
          goto Exit;
1013
 
1014
        /* Copy the predefined charset into the allocated memory.     */
1015
        FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs );
1016
 
1017
        break;
1018
 
1019
      default:
1020
        error = FT_THROW( Invalid_File_Format );
1021
        goto Exit;
1022
      }
1023
    }
1024
 
1025
    /* we have to invert the `sids' array for subsetted CID-keyed fonts */
1026
    if ( invert )
1027
      error = cff_charset_compute_cids( charset, num_glyphs, memory );
1028
 
1029
  Exit:
1030
    /* Clean up if there was an error. */
1031
    if ( error )
1032
    {
1033
      FT_FREE( charset->sids );
1034
      FT_FREE( charset->cids );
1035
      charset->format = 0;
1036
      charset->offset = 0;
1037
      charset->sids   = 0;
1038
    }
1039
 
1040
    return error;
1041
  }
1042
 
1043
 
1044
  static void
1045
  cff_encoding_done( CFF_Encoding  encoding )
1046
  {
1047
    encoding->format = 0;
1048
    encoding->offset = 0;
1049
    encoding->count  = 0;
1050
  }
1051
 
1052
 
1053
  static FT_Error
1054
  cff_encoding_load( CFF_Encoding  encoding,
1055
                     CFF_Charset   charset,
1056
                     FT_UInt       num_glyphs,
1057
                     FT_Stream     stream,
1058
                     FT_ULong      base_offset,
1059
                     FT_ULong      offset )
1060
  {
1061
    FT_Error   error = FT_Err_Ok;
1062
    FT_UInt    count;
1063
    FT_UInt    j;
1064
    FT_UShort  glyph_sid;
1065
    FT_UInt    glyph_code;
1066
 
1067
 
1068
    /* Check for charset->sids.  If we do not have this, we fail. */
1069
    if ( !charset->sids )
1070
    {
1071
      error = FT_THROW( Invalid_File_Format );
1072
      goto Exit;
1073
    }
1074
 
1075
    /* Zero out the code to gid/sid mappings. */
1076
    for ( j = 0; j < 256; j++ )
1077
    {
1078
      encoding->sids [j] = 0;
1079
      encoding->codes[j] = 0;
1080
    }
1081
 
1082
    /* Note: The encoding table in a CFF font is indexed by glyph index;  */
1083
    /* the first encoded glyph index is 1.  Hence, we read the character  */
1084
    /* code (`glyph_code') at index j and make the assignment:            */
1085
    /*                                                                    */
1086
    /*    encoding->codes[glyph_code] = j + 1                             */
1087
    /*                                                                    */
1088
    /* We also make the assignment:                                       */
1089
    /*                                                                    */
1090
    /*    encoding->sids[glyph_code] = charset->sids[j + 1]               */
1091
    /*                                                                    */
1092
    /* This gives us both a code to GID and a code to SID mapping.        */
1093
 
1094
    if ( offset > 1 )
1095
    {
1096
      encoding->offset = base_offset + offset;
1097
 
1098
      /* we need to parse the table to determine its size */
1099
      if ( FT_STREAM_SEEK( encoding->offset ) ||
1100
           FT_READ_BYTE( encoding->format )   ||
1101
           FT_READ_BYTE( count )              )
1102
        goto Exit;
1103
 
1104
      switch ( encoding->format & 0x7F )
1105
      {
1106
      case 0:
1107
        {
1108
          FT_Byte*  p;
1109
 
1110
 
1111
          /* By convention, GID 0 is always ".notdef" and is never */
1112
          /* coded in the font.  Hence, the number of codes found  */
1113
          /* in the table is `count+1'.                            */
1114
          /*                                                       */
1115
          encoding->count = count + 1;
1116
 
1117
          if ( FT_FRAME_ENTER( count ) )
1118
            goto Exit;
1119
 
1120
          p = (FT_Byte*)stream->cursor;
1121
 
1122
          for ( j = 1; j <= count; j++ )
1123
          {
1124
            glyph_code = *p++;
1125
 
1126
            /* Make sure j is not too big. */
1127
            if ( j < num_glyphs )
1128
            {
1129
              /* Assign code to GID mapping. */
1130
              encoding->codes[glyph_code] = (FT_UShort)j;
1131
 
1132
              /* Assign code to SID mapping. */
1133
              encoding->sids[glyph_code] = charset->sids[j];
1134
            }
1135
          }
1136
 
1137
          FT_FRAME_EXIT();
1138
        }
1139
        break;
1140
 
1141
      case 1:
1142
        {
1143
          FT_UInt  nleft;
1144
          FT_UInt  i = 1;
1145
          FT_UInt  k;
1146
 
1147
 
1148
          encoding->count = 0;
1149
 
1150
          /* Parse the Format1 ranges. */
1151
          for ( j = 0;  j < count; j++, i += nleft )
1152
          {
1153
            /* Read the first glyph code of the range. */
1154
            if ( FT_READ_BYTE( glyph_code ) )
1155
              goto Exit;
1156
 
1157
            /* Read the number of codes in the range. */
1158
            if ( FT_READ_BYTE( nleft ) )
1159
              goto Exit;
1160
 
1161
            /* Increment nleft, so we read `nleft + 1' codes/sids. */
1162
            nleft++;
1163
 
1164
            /* compute max number of character codes */
1165
            if ( (FT_UInt)nleft > encoding->count )
1166
              encoding->count = nleft;
1167
 
1168
            /* Fill in the range of codes/sids. */
1169
            for ( k = i; k < nleft + i; k++, glyph_code++ )
1170
            {
1171
              /* Make sure k is not too big. */
1172
              if ( k < num_glyphs && glyph_code < 256 )
1173
              {
1174
                /* Assign code to GID mapping. */
1175
                encoding->codes[glyph_code] = (FT_UShort)k;
1176
 
1177
                /* Assign code to SID mapping. */
1178
                encoding->sids[glyph_code] = charset->sids[k];
1179
              }
1180
            }
1181
          }
1182
 
1183
          /* simple check; one never knows what can be found in a font */
1184
          if ( encoding->count > 256 )
1185
            encoding->count = 256;
1186
        }
1187
        break;
1188
 
1189
      default:
1190
        FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
1191
        error = FT_THROW( Invalid_File_Format );
1192
        goto Exit;
1193
      }
1194
 
1195
      /* Parse supplemental encodings, if any. */
1196
      if ( encoding->format & 0x80 )
1197
      {
1198
        FT_UInt  gindex;
1199
 
1200
 
1201
        /* count supplements */
1202
        if ( FT_READ_BYTE( count ) )
1203
          goto Exit;
1204
 
1205
        for ( j = 0; j < count; j++ )
1206
        {
1207
          /* Read supplemental glyph code. */
1208
          if ( FT_READ_BYTE( glyph_code ) )
1209
            goto Exit;
1210
 
1211
          /* Read the SID associated with this glyph code. */
1212
          if ( FT_READ_USHORT( glyph_sid ) )
1213
            goto Exit;
1214
 
1215
          /* Assign code to SID mapping. */
1216
          encoding->sids[glyph_code] = glyph_sid;
1217
 
1218
          /* First, look up GID which has been assigned to */
1219
          /* SID glyph_sid.                                */
1220
          for ( gindex = 0; gindex < num_glyphs; gindex++ )
1221
          {
1222
            if ( charset->sids[gindex] == glyph_sid )
1223
            {
1224
              encoding->codes[glyph_code] = (FT_UShort)gindex;
1225
              break;
1226
            }
1227
          }
1228
        }
1229
      }
1230
    }
1231
    else
1232
    {
1233
      /* We take into account the fact a CFF font can use a predefined */
1234
      /* encoding without containing all of the glyphs encoded by this */
1235
      /* encoding (see the note at the end of section 12 in the CFF    */
1236
      /* specification).                                               */
1237
 
1238
      switch ( (FT_UInt)offset )
1239
      {
1240
      case 0:
1241
        /* First, copy the code to SID mapping. */
1242
        FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 );
1243
        goto Populate;
1244
 
1245
      case 1:
1246
        /* First, copy the code to SID mapping. */
1247
        FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 );
1248
 
1249
      Populate:
1250
        /* Construct code to GID mapping from code to SID mapping */
1251
        /* and charset.                                           */
1252
 
1253
        encoding->count = 0;
1254
 
1255
        error = cff_charset_compute_cids( charset, num_glyphs,
1256
                                          stream->memory );
1257
        if ( error )
1258
          goto Exit;
1259
 
1260
        for ( j = 0; j < 256; j++ )
1261
        {
1262
          FT_UInt  sid = encoding->sids[j];
1263
          FT_UInt  gid = 0;
1264
 
1265
 
1266
          if ( sid )
1267
            gid = cff_charset_cid_to_gindex( charset, sid );
1268
 
1269
          if ( gid != 0 )
1270
          {
1271
            encoding->codes[j] = (FT_UShort)gid;
1272
            encoding->count    = j + 1;
1273
          }
1274
          else
1275
          {
1276
            encoding->codes[j] = 0;
1277
            encoding->sids [j] = 0;
1278
          }
1279
        }
1280
        break;
1281
 
1282
      default:
1283
        FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
1284
        error = FT_THROW( Invalid_File_Format );
1285
        goto Exit;
1286
      }
1287
    }
1288
 
1289
  Exit:
1290
 
1291
    /* Clean up if there was an error. */
1292
    return error;
1293
  }
1294
 
1295
 
1296
  static FT_Error
1297
  cff_subfont_load( CFF_SubFont  font,
1298
                    CFF_Index    idx,
1299
                    FT_UInt      font_index,
1300
                    FT_Stream    stream,
1301
                    FT_ULong     base_offset,
1302
                    FT_Library   library )
1303
  {
1304
    FT_Error         error;
1305
    CFF_ParserRec    parser;
1306
    FT_Byte*         dict = NULL;
1307
    FT_ULong         dict_len;
1308
    CFF_FontRecDict  top  = &font->font_dict;
1309
    CFF_Private      priv = &font->private_dict;
1310
 
1311
 
1312
    cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );
1313
 
1314
    /* set defaults */
1315
    FT_MEM_ZERO( top, sizeof ( *top ) );
1316
 
1317
    top->underline_position  = -( 100L << 16 );
1318
    top->underline_thickness = 50L << 16;
1319
    top->charstring_type     = 2;
1320
    top->font_matrix.xx      = 0x10000L;
1321
    top->font_matrix.yy      = 0x10000L;
1322
    top->cid_count           = 8720;
1323
 
1324
    /* we use the implementation specific SID value 0xFFFF to indicate */
1325
    /* missing entries                                                 */
1326
    top->version             = 0xFFFFU;
1327
    top->notice              = 0xFFFFU;
1328
    top->copyright           = 0xFFFFU;
1329
    top->full_name           = 0xFFFFU;
1330
    top->family_name         = 0xFFFFU;
1331
    top->weight              = 0xFFFFU;
1332
    top->embedded_postscript = 0xFFFFU;
1333
 
1334
    top->cid_registry        = 0xFFFFU;
1335
    top->cid_ordering        = 0xFFFFU;
1336
    top->cid_font_name       = 0xFFFFU;
1337
 
1338
    error = cff_index_access_element( idx, font_index, &dict, &dict_len );
1339
    if ( !error )
1340
    {
1341
      FT_TRACE4(( " top dictionary:\n" ));
1342
      error = cff_parser_run( &parser, dict, dict + dict_len );
1343
    }
1344
 
1345
    cff_index_forget_element( idx, &dict );
1346
 
1347
    if ( error )
1348
      goto Exit;
1349
 
1350
    /* if it is a CID font, we stop there */
1351
    if ( top->cid_registry != 0xFFFFU )
1352
      goto Exit;
1353
 
1354
    /* parse the private dictionary, if any */
1355
    if ( top->private_offset && top->private_size )
1356
    {
1357
      /* set defaults */
1358
      FT_MEM_ZERO( priv, sizeof ( *priv ) );
1359
 
1360
      priv->blue_shift       = 7;
1361
      priv->blue_fuzz        = 1;
1362
      priv->lenIV            = -1;
1363
      priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
1364
      priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
1365
 
1366
      cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );
1367
 
1368
      if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
1369
           FT_FRAME_ENTER( font->font_dict.private_size )                 )
1370
        goto Exit;
1371
 
1372
      FT_TRACE4(( " private dictionary:\n" ));
1373
      error = cff_parser_run( &parser,
1374
                              (FT_Byte*)stream->cursor,
1375
                              (FT_Byte*)stream->limit );
1376
      FT_FRAME_EXIT();
1377
      if ( error )
1378
        goto Exit;
1379
 
1380
      /* ensure that `num_blue_values' is even */
1381
      priv->num_blue_values &= ~1;
1382
    }
1383
 
1384
    /* read the local subrs, if any */
1385
    if ( priv->local_subrs_offset )
1386
    {
1387
      if ( FT_STREAM_SEEK( base_offset + top->private_offset +
1388
                           priv->local_subrs_offset ) )
1389
        goto Exit;
1390
 
1391
      error = cff_index_init( &font->local_subrs_index, stream, 1 );
1392
      if ( error )
1393
        goto Exit;
1394
 
1395
      error = cff_index_get_pointers( &font->local_subrs_index,
1396
                                      &font->local_subrs, NULL );
1397
      if ( error )
1398
        goto Exit;
1399
    }
1400
 
1401
  Exit:
1402
    return error;
1403
  }
1404
 
1405
 
1406
  static void
1407
  cff_subfont_done( FT_Memory    memory,
1408
                    CFF_SubFont  subfont )
1409
  {
1410
    if ( subfont )
1411
    {
1412
      cff_index_done( &subfont->local_subrs_index );
1413
      FT_FREE( subfont->local_subrs );
1414
    }
1415
  }
1416
 
1417
 
1418
  FT_LOCAL_DEF( FT_Error )
1419
  cff_font_load( FT_Library library,
1420
                 FT_Stream  stream,
1421
                 FT_Int     face_index,
1422
                 CFF_Font   font,
1423
                 FT_Bool    pure_cff )
1424
  {
1425
    static const FT_Frame_Field  cff_header_fields[] =
1426
    {
1427
#undef  FT_STRUCTURE
1428
#define FT_STRUCTURE  CFF_FontRec
1429
 
1430
      FT_FRAME_START( 4 ),
1431
        FT_FRAME_BYTE( version_major ),
1432
        FT_FRAME_BYTE( version_minor ),
1433
        FT_FRAME_BYTE( header_size ),
1434
        FT_FRAME_BYTE( absolute_offsize ),
1435
      FT_FRAME_END
1436
    };
1437
 
1438
    FT_Error         error;
1439
    FT_Memory        memory = stream->memory;
1440
    FT_ULong         base_offset;
1441
    CFF_FontRecDict  dict;
1442
    CFF_IndexRec     string_index;
1443
    FT_Int           subfont_index;
1444
 
1445
 
1446
    FT_ZERO( font );
1447
    FT_ZERO( &string_index );
1448
 
1449
    font->stream = stream;
1450
    font->memory = memory;
1451
    dict         = &font->top_font.font_dict;
1452
    base_offset  = FT_STREAM_POS();
1453
 
1454
    /* read CFF font header */
1455
    if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
1456
      goto Exit;
1457
 
1458
    /* check format */
1459
    if ( font->version_major   != 1 ||
1460
         font->header_size      < 4 ||
1461
         font->absolute_offsize > 4 )
1462
    {
1463
      FT_TRACE2(( "  not a CFF font header\n" ));
1464
      error = FT_THROW( Unknown_File_Format );
1465
      goto Exit;
1466
    }
1467
 
1468
    /* skip the rest of the header */
1469
    if ( FT_STREAM_SKIP( font->header_size - 4 ) )
1470
      goto Exit;
1471
 
1472
    /* read the name, top dict, string and global subrs index */
1473
    if ( FT_SET_ERROR( cff_index_init( &font->name_index,
1474
                                       stream, 0 ) )                  ||
1475
         FT_SET_ERROR( cff_index_init( &font->font_dict_index,
1476
                                       stream, 0 ) )                  ||
1477
         FT_SET_ERROR( cff_index_init( &string_index,
1478
                                       stream, 1 ) )                  ||
1479
         FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
1480
                                       stream, 1 ) )                  ||
1481
         FT_SET_ERROR( cff_index_get_pointers( &string_index,
1482
                                               &font->strings,
1483
                                               &font->string_pool ) ) )
1484
      goto Exit;
1485
 
1486
    font->num_strings = string_index.count;
1487
 
1488
    if ( pure_cff )
1489
    {
1490
      /* well, we don't really forget the `disabled' fonts... */
1491
      subfont_index = face_index;
1492
 
1493
      if ( subfont_index >= (FT_Int)font->name_index.count )
1494
      {
1495
        FT_ERROR(( "cff_font_load:"
1496
                   " invalid subfont index for pure CFF font (%d)\n",
1497
                   subfont_index ));
1498
        error = FT_THROW( Invalid_Argument );
1499
        goto Exit;
1500
      }
1501
 
1502
      font->num_faces = font->name_index.count;
1503
    }
1504
    else
1505
    {
1506
      subfont_index = 0;
1507
 
1508
      if ( font->name_index.count > 1 )
1509
      {
1510
        FT_ERROR(( "cff_font_load:"
1511
                   " invalid CFF font with multiple subfonts\n"
1512
                   "              "
1513
                   " in SFNT wrapper\n" ));
1514
        error = FT_THROW( Invalid_File_Format );
1515
        goto Exit;
1516
      }
1517
    }
1518
 
1519
    /* in case of a font format check, simply exit now */
1520
    if ( face_index < 0 )
1521
      goto Exit;
1522
 
1523
    /* now, parse the top-level font dictionary */
1524
    FT_TRACE4(( "parsing top-level\n" ));
1525
    error = cff_subfont_load( &font->top_font,
1526
                              &font->font_dict_index,
1527
                              subfont_index,
1528
                              stream,
1529
                              base_offset,
1530
                              library );
1531
    if ( error )
1532
      goto Exit;
1533
 
1534
    if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
1535
      goto Exit;
1536
 
1537
    error = cff_index_init( &font->charstrings_index, stream, 0 );
1538
    if ( error )
1539
      goto Exit;
1540
 
1541
    /* now, check for a CID font */
1542
    if ( dict->cid_registry != 0xFFFFU )
1543
    {
1544
      CFF_IndexRec  fd_index;
1545
      CFF_SubFont   sub = NULL;
1546
      FT_UInt       idx;
1547
 
1548
 
1549
      /* this is a CID-keyed font, we must now allocate a table of */
1550
      /* sub-fonts, then load each of them separately              */
1551
      if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
1552
        goto Exit;
1553
 
1554
      error = cff_index_init( &fd_index, stream, 0 );
1555
      if ( error )
1556
        goto Exit;
1557
 
1558
      if ( fd_index.count > CFF_MAX_CID_FONTS )
1559
      {
1560
        FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
1561
        goto Fail_CID;
1562
      }
1563
 
1564
      /* allocate & read each font dict independently */
1565
      font->num_subfonts = fd_index.count;
1566
      if ( FT_NEW_ARRAY( sub, fd_index.count ) )
1567
        goto Fail_CID;
1568
 
1569
      /* set up pointer table */
1570
      for ( idx = 0; idx < fd_index.count; idx++ )
1571
        font->subfonts[idx] = sub + idx;
1572
 
1573
      /* now load each subfont independently */
1574
      for ( idx = 0; idx < fd_index.count; idx++ )
1575
      {
1576
        sub = font->subfonts[idx];
1577
        FT_TRACE4(( "parsing subfont %u\n", idx ));
1578
        error = cff_subfont_load( sub, &fd_index, idx,
1579
                                  stream, base_offset, library );
1580
        if ( error )
1581
          goto Fail_CID;
1582
      }
1583
 
1584
      /* now load the FD Select array */
1585
      error = CFF_Load_FD_Select( &font->fd_select,
1586
                                  font->charstrings_index.count,
1587
                                  stream,
1588
                                  base_offset + dict->cid_fd_select_offset );
1589
 
1590
    Fail_CID:
1591
      cff_index_done( &fd_index );
1592
 
1593
      if ( error )
1594
        goto Exit;
1595
    }
1596
    else
1597
      font->num_subfonts = 0;
1598
 
1599
    /* read the charstrings index now */
1600
    if ( dict->charstrings_offset == 0 )
1601
    {
1602
      FT_ERROR(( "cff_font_load: no charstrings offset\n" ));
1603
      error = FT_THROW( Invalid_File_Format );
1604
      goto Exit;
1605
    }
1606
 
1607
    font->num_glyphs = font->charstrings_index.count;
1608
 
1609
    error = cff_index_get_pointers( &font->global_subrs_index,
1610
                                    &font->global_subrs, NULL );
1611
 
1612
    if ( error )
1613
      goto Exit;
1614
 
1615
    /* read the Charset and Encoding tables if available */
1616
    if ( font->num_glyphs > 0 )
1617
    {
1618
      FT_Bool  invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
1619
 
1620
 
1621
      error = cff_charset_load( &font->charset, font->num_glyphs, stream,
1622
                                base_offset, dict->charset_offset, invert );
1623
      if ( error )
1624
        goto Exit;
1625
 
1626
      /* CID-keyed CFFs don't have an encoding */
1627
      if ( dict->cid_registry == 0xFFFFU )
1628
      {
1629
        error = cff_encoding_load( &font->encoding,
1630
                                   &font->charset,
1631
                                   font->num_glyphs,
1632
                                   stream,
1633
                                   base_offset,
1634
                                   dict->encoding_offset );
1635
        if ( error )
1636
          goto Exit;
1637
      }
1638
    }
1639
 
1640
    /* get the font name (/CIDFontName for CID-keyed fonts, */
1641
    /* /FontName otherwise)                                 */
1642
    font->font_name = cff_index_get_name( font, subfont_index );
1643
 
1644
  Exit:
1645
    cff_index_done( &string_index );
1646
 
1647
    return error;
1648
  }
1649
 
1650
 
1651
  FT_LOCAL_DEF( void )
1652
  cff_font_done( CFF_Font  font )
1653
  {
1654
    FT_Memory  memory = font->memory;
1655
    FT_UInt    idx;
1656
 
1657
 
1658
    cff_index_done( &font->global_subrs_index );
1659
    cff_index_done( &font->font_dict_index );
1660
    cff_index_done( &font->name_index );
1661
    cff_index_done( &font->charstrings_index );
1662
 
1663
    /* release font dictionaries, but only if working with */
1664
    /* a CID keyed CFF font                                */
1665
    if ( font->num_subfonts > 0 )
1666
    {
1667
      for ( idx = 0; idx < font->num_subfonts; idx++ )
1668
        cff_subfont_done( memory, font->subfonts[idx] );
1669
 
1670
      /* the subfonts array has been allocated as a single block */
1671
      FT_FREE( font->subfonts[0] );
1672
    }
1673
 
1674
    cff_encoding_done( &font->encoding );
1675
    cff_charset_done( &font->charset, font->stream );
1676
 
1677
    cff_subfont_done( memory, &font->top_font );
1678
 
1679
    CFF_Done_FD_Select( &font->fd_select, font->stream );
1680
 
1681
    FT_FREE( font->font_info );
1682
 
1683
    FT_FREE( font->font_name );
1684
    FT_FREE( font->global_subrs );
1685
    FT_FREE( font->strings );
1686
    FT_FREE( font->string_pool );
1687
 
1688
    if ( font->cf2_instance.finalizer )
1689
    {
1690
      font->cf2_instance.finalizer( font->cf2_instance.data );
1691
      FT_FREE( font->cf2_instance.data );
1692
    }
1693
  }
1694
 
1695
 
1696
/* END */