• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************/
2 /*                                                                         */
3 /*  cffload.c                                                              */
4 /*                                                                         */
5 /*    OpenType and CFF data/program tables loader (body).                  */
6 /*                                                                         */
7 /*  Copyright 1996-2017 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 <ft2build.h>
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 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
27 #include FT_MULTIPLE_MASTERS_H
28 #include FT_SERVICE_MULTIPLE_MASTERS_H
29 #endif
30 
31 #include "cffload.h"
32 #include "cffparse.h"
33 
34 #include "cfferrs.h"
35 
36 
37 #define FT_FIXED_ONE  ( (FT_Fixed)0x10000 )
38 
39 
40 #if 1
41 
42   static const FT_UShort  cff_isoadobe_charset[229] =
43   {
44       0,   1,   2,   3,   4,   5,   6,   7,
45       8,   9,  10,  11,  12,  13,  14,  15,
46      16,  17,  18,  19,  20,  21,  22,  23,
47      24,  25,  26,  27,  28,  29,  30,  31,
48      32,  33,  34,  35,  36,  37,  38,  39,
49      40,  41,  42,  43,  44,  45,  46,  47,
50      48,  49,  50,  51,  52,  53,  54,  55,
51      56,  57,  58,  59,  60,  61,  62,  63,
52      64,  65,  66,  67,  68,  69,  70,  71,
53      72,  73,  74,  75,  76,  77,  78,  79,
54      80,  81,  82,  83,  84,  85,  86,  87,
55      88,  89,  90,  91,  92,  93,  94,  95,
56      96,  97,  98,  99, 100, 101, 102, 103,
57     104, 105, 106, 107, 108, 109, 110, 111,
58     112, 113, 114, 115, 116, 117, 118, 119,
59     120, 121, 122, 123, 124, 125, 126, 127,
60     128, 129, 130, 131, 132, 133, 134, 135,
61     136, 137, 138, 139, 140, 141, 142, 143,
62     144, 145, 146, 147, 148, 149, 150, 151,
63     152, 153, 154, 155, 156, 157, 158, 159,
64     160, 161, 162, 163, 164, 165, 166, 167,
65     168, 169, 170, 171, 172, 173, 174, 175,
66     176, 177, 178, 179, 180, 181, 182, 183,
67     184, 185, 186, 187, 188, 189, 190, 191,
68     192, 193, 194, 195, 196, 197, 198, 199,
69     200, 201, 202, 203, 204, 205, 206, 207,
70     208, 209, 210, 211, 212, 213, 214, 215,
71     216, 217, 218, 219, 220, 221, 222, 223,
72     224, 225, 226, 227, 228
73   };
74 
75   static const FT_UShort  cff_expert_charset[166] =
76   {
77       0,   1, 229, 230, 231, 232, 233, 234,
78     235, 236, 237, 238,  13,  14,  15,  99,
79     239, 240, 241, 242, 243, 244, 245, 246,
80     247, 248,  27,  28, 249, 250, 251, 252,
81     253, 254, 255, 256, 257, 258, 259, 260,
82     261, 262, 263, 264, 265, 266, 109, 110,
83     267, 268, 269, 270, 271, 272, 273, 274,
84     275, 276, 277, 278, 279, 280, 281, 282,
85     283, 284, 285, 286, 287, 288, 289, 290,
86     291, 292, 293, 294, 295, 296, 297, 298,
87     299, 300, 301, 302, 303, 304, 305, 306,
88     307, 308, 309, 310, 311, 312, 313, 314,
89     315, 316, 317, 318, 158, 155, 163, 319,
90     320, 321, 322, 323, 324, 325, 326, 150,
91     164, 169, 327, 328, 329, 330, 331, 332,
92     333, 334, 335, 336, 337, 338, 339, 340,
93     341, 342, 343, 344, 345, 346, 347, 348,
94     349, 350, 351, 352, 353, 354, 355, 356,
95     357, 358, 359, 360, 361, 362, 363, 364,
96     365, 366, 367, 368, 369, 370, 371, 372,
97     373, 374, 375, 376, 377, 378
98   };
99 
100   static const FT_UShort  cff_expertsubset_charset[87] =
101   {
102       0,   1, 231, 232, 235, 236, 237, 238,
103      13,  14,  15,  99, 239, 240, 241, 242,
104     243, 244, 245, 246, 247, 248,  27,  28,
105     249, 250, 251, 253, 254, 255, 256, 257,
106     258, 259, 260, 261, 262, 263, 264, 265,
107     266, 109, 110, 267, 268, 269, 270, 272,
108     300, 301, 302, 305, 314, 315, 158, 155,
109     163, 320, 321, 322, 323, 324, 325, 326,
110     150, 164, 169, 327, 328, 329, 330, 331,
111     332, 333, 334, 335, 336, 337, 338, 339,
112     340, 341, 342, 343, 344, 345, 346
113   };
114 
115   static const FT_UShort  cff_standard_encoding[256] =
116   {
117       0,   0,   0,   0,   0,   0,   0,   0,
118       0,   0,   0,   0,   0,   0,   0,   0,
119       0,   0,   0,   0,   0,   0,   0,   0,
120       0,   0,   0,   0,   0,   0,   0,   0,
121       1,   2,   3,   4,   5,   6,   7,   8,
122       9,  10,  11,  12,  13,  14,  15,  16,
123      17,  18,  19,  20,  21,  22,  23,  24,
124      25,  26,  27,  28,  29,  30,  31,  32,
125      33,  34,  35,  36,  37,  38,  39,  40,
126      41,  42,  43,  44,  45,  46,  47,  48,
127      49,  50,  51,  52,  53,  54,  55,  56,
128      57,  58,  59,  60,  61,  62,  63,  64,
129      65,  66,  67,  68,  69,  70,  71,  72,
130      73,  74,  75,  76,  77,  78,  79,  80,
131      81,  82,  83,  84,  85,  86,  87,  88,
132      89,  90,  91,  92,  93,  94,  95,   0,
133       0,   0,   0,   0,   0,   0,   0,   0,
134       0,   0,   0,   0,   0,   0,   0,   0,
135       0,   0,   0,   0,   0,   0,   0,   0,
136       0,   0,   0,   0,   0,   0,   0,   0,
137       0,  96,  97,  98,  99, 100, 101, 102,
138     103, 104, 105, 106, 107, 108, 109, 110,
139       0, 111, 112, 113, 114,   0, 115, 116,
140     117, 118, 119, 120, 121, 122,   0, 123,
141       0, 124, 125, 126, 127, 128, 129, 130,
142     131,   0, 132, 133,   0, 134, 135, 136,
143     137,   0,   0,   0,   0,   0,   0,   0,
144       0,   0,   0,   0,   0,   0,   0,   0,
145       0, 138,   0, 139,   0,   0,   0,   0,
146     140, 141, 142, 143,   0,   0,   0,   0,
147       0, 144,   0,   0,   0, 145,   0,   0,
148     146, 147, 148, 149,   0,   0,   0,   0
149   };
150 
151   static const FT_UShort  cff_expert_encoding[256] =
152   {
153       0,   0,   0,   0,   0,   0,   0,   0,
154       0,   0,   0,   0,   0,   0,   0,   0,
155       0,   0,   0,   0,   0,   0,   0,   0,
156       0,   0,   0,   0,   0,   0,   0,   0,
157       1, 229, 230,   0, 231, 232, 233, 234,
158     235, 236, 237, 238,  13,  14,  15,  99,
159     239, 240, 241, 242, 243, 244, 245, 246,
160     247, 248,  27,  28, 249, 250, 251, 252,
161       0, 253, 254, 255, 256, 257,   0,   0,
162       0, 258,   0,   0, 259, 260, 261, 262,
163       0,   0, 263, 264, 265,   0, 266, 109,
164     110, 267, 268, 269,   0, 270, 271, 272,
165     273, 274, 275, 276, 277, 278, 279, 280,
166     281, 282, 283, 284, 285, 286, 287, 288,
167     289, 290, 291, 292, 293, 294, 295, 296,
168     297, 298, 299, 300, 301, 302, 303,   0,
169       0,   0,   0,   0,   0,   0,   0,   0,
170       0,   0,   0,   0,   0,   0,   0,   0,
171       0,   0,   0,   0,   0,   0,   0,   0,
172       0,   0,   0,   0,   0,   0,   0,   0,
173       0, 304, 305, 306,   0,   0, 307, 308,
174     309, 310, 311,   0, 312,   0,   0, 312,
175       0,   0, 314, 315,   0,   0, 316, 317,
176     318,   0,   0,   0, 158, 155, 163, 319,
177     320, 321, 322, 323, 324, 325,   0,   0,
178     326, 150, 164, 169, 327, 328, 329, 330,
179     331, 332, 333, 334, 335, 336, 337, 338,
180     339, 340, 341, 342, 343, 344, 345, 346,
181     347, 348, 349, 350, 351, 352, 353, 354,
182     355, 356, 357, 358, 359, 360, 361, 362,
183     363, 364, 365, 366, 367, 368, 369, 370,
184     371, 372, 373, 374, 375, 376, 377, 378
185   };
186 
187 #endif /* 1 */
188 
189 
190   FT_LOCAL_DEF( FT_UShort )
cff_get_standard_encoding(FT_UInt charcode)191   cff_get_standard_encoding( FT_UInt  charcode )
192   {
193     return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode]
194                                        : 0 );
195   }
196 
197 
198   /*************************************************************************/
199   /*                                                                       */
200   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
201   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
202   /* messages during execution.                                            */
203   /*                                                                       */
204 #undef  FT_COMPONENT
205 #define FT_COMPONENT  trace_cffload
206 
207 
208   /* read an offset from the index's stream current position */
209   static FT_ULong
cff_index_read_offset(CFF_Index idx,FT_Error * errorp)210   cff_index_read_offset( CFF_Index  idx,
211                          FT_Error  *errorp )
212   {
213     FT_Error   error;
214     FT_Stream  stream = idx->stream;
215     FT_Byte    tmp[4];
216     FT_ULong   result = 0;
217 
218 
219     if ( !FT_STREAM_READ( tmp, idx->off_size ) )
220     {
221       FT_Int  nn;
222 
223 
224       for ( nn = 0; nn < idx->off_size; nn++ )
225         result = ( result << 8 ) | tmp[nn];
226     }
227 
228     *errorp = error;
229     return result;
230   }
231 
232 
233   static FT_Error
cff_index_init(CFF_Index idx,FT_Stream stream,FT_Bool load,FT_Bool cff2)234   cff_index_init( CFF_Index  idx,
235                   FT_Stream  stream,
236                   FT_Bool    load,
237                   FT_Bool    cff2 )
238   {
239     FT_Error   error;
240     FT_Memory  memory = stream->memory;
241     FT_UInt    count;
242 
243 
244     FT_ZERO( idx );
245 
246     idx->stream = stream;
247     idx->start  = FT_STREAM_POS();
248 
249     if ( cff2 )
250     {
251       if ( FT_READ_ULONG( count ) )
252         goto Exit;
253       idx->hdr_size = 5;
254     }
255     else
256     {
257       if ( FT_READ_USHORT( count ) )
258         goto Exit;
259       idx->hdr_size = 3;
260     }
261 
262     if ( count > 0 )
263     {
264       FT_Byte   offsize;
265       FT_ULong  size;
266 
267 
268       /* there is at least one element; read the offset size,           */
269       /* then access the offset table to compute the index's total size */
270       if ( FT_READ_BYTE( offsize ) )
271         goto Exit;
272 
273       if ( offsize < 1 || offsize > 4 )
274       {
275         error = FT_THROW( Invalid_Table );
276         goto Exit;
277       }
278 
279       idx->count    = count;
280       idx->off_size = offsize;
281       size          = (FT_ULong)( count + 1 ) * offsize;
282 
283       idx->data_offset = idx->start + idx->hdr_size + size;
284 
285       if ( FT_STREAM_SKIP( size - offsize ) )
286         goto Exit;
287 
288       size = cff_index_read_offset( idx, &error );
289       if ( error )
290         goto Exit;
291 
292       if ( size == 0 )
293       {
294         error = FT_THROW( Invalid_Table );
295         goto Exit;
296       }
297 
298       idx->data_size = --size;
299 
300       if ( load )
301       {
302         /* load the data */
303         if ( FT_FRAME_EXTRACT( size, idx->bytes ) )
304           goto Exit;
305       }
306       else
307       {
308         /* skip the data */
309         if ( FT_STREAM_SKIP( size ) )
310           goto Exit;
311       }
312     }
313 
314   Exit:
315     if ( error )
316       FT_FREE( idx->offsets );
317 
318     return error;
319   }
320 
321 
322   static void
cff_index_done(CFF_Index idx)323   cff_index_done( CFF_Index  idx )
324   {
325     if ( idx->stream )
326     {
327       FT_Stream  stream = idx->stream;
328       FT_Memory  memory = stream->memory;
329 
330 
331       if ( idx->bytes )
332         FT_FRAME_RELEASE( idx->bytes );
333 
334       FT_FREE( idx->offsets );
335       FT_ZERO( idx );
336     }
337   }
338 
339 
340   static FT_Error
cff_index_load_offsets(CFF_Index idx)341   cff_index_load_offsets( CFF_Index  idx )
342   {
343     FT_Error   error  = FT_Err_Ok;
344     FT_Stream  stream = idx->stream;
345     FT_Memory  memory = stream->memory;
346 
347 
348     if ( idx->count > 0 && !idx->offsets )
349     {
350       FT_Byte    offsize = idx->off_size;
351       FT_ULong   data_size;
352       FT_Byte*   p;
353       FT_Byte*   p_end;
354       FT_ULong*  poff;
355 
356 
357       data_size = (FT_ULong)( idx->count + 1 ) * offsize;
358 
359       if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
360            FT_STREAM_SEEK( idx->start + idx->hdr_size ) ||
361            FT_FRAME_ENTER( data_size )                  )
362         goto Exit;
363 
364       poff   = idx->offsets;
365       p      = (FT_Byte*)stream->cursor;
366       p_end  = p + data_size;
367 
368       switch ( offsize )
369       {
370       case 1:
371         for ( ; p < p_end; p++, poff++ )
372           poff[0] = p[0];
373         break;
374 
375       case 2:
376         for ( ; p < p_end; p += 2, poff++ )
377           poff[0] = FT_PEEK_USHORT( p );
378         break;
379 
380       case 3:
381         for ( ; p < p_end; p += 3, poff++ )
382           poff[0] = FT_PEEK_UOFF3( p );
383         break;
384 
385       default:
386         for ( ; p < p_end; p += 4, poff++ )
387           poff[0] = FT_PEEK_ULONG( p );
388       }
389 
390       FT_FRAME_EXIT();
391     }
392 
393   Exit:
394     if ( error )
395       FT_FREE( idx->offsets );
396 
397     return error;
398   }
399 
400 
401   /* Allocate a table containing pointers to an index's elements. */
402   /* The `pool' argument makes this function convert the index    */
403   /* entries to C-style strings (this is, NULL-terminated).       */
404   static FT_Error
cff_index_get_pointers(CFF_Index idx,FT_Byte *** table,FT_Byte ** pool,FT_ULong * pool_size)405   cff_index_get_pointers( CFF_Index   idx,
406                           FT_Byte***  table,
407                           FT_Byte**   pool,
408                           FT_ULong*   pool_size )
409   {
410     FT_Error   error     = FT_Err_Ok;
411     FT_Memory  memory    = idx->stream->memory;
412 
413     FT_Byte**  t         = NULL;
414     FT_Byte*   new_bytes = NULL;
415     FT_ULong   new_size;
416 
417 
418     *table = NULL;
419 
420     if ( !idx->offsets )
421     {
422       error = cff_index_load_offsets( idx );
423       if ( error )
424         goto Exit;
425     }
426 
427     new_size = idx->data_size + idx->count;
428 
429     if ( idx->count > 0                                &&
430          !FT_NEW_ARRAY( t, idx->count + 1 )            &&
431          ( !pool || !FT_ALLOC( new_bytes, new_size ) ) )
432     {
433       FT_ULong  n, cur_offset;
434       FT_ULong  extra = 0;
435       FT_Byte*  org_bytes = idx->bytes;
436 
437 
438       /* at this point, `idx->offsets' can't be NULL */
439       cur_offset = idx->offsets[0] - 1;
440 
441       /* sanity check */
442       if ( cur_offset != 0 )
443       {
444         FT_TRACE0(( "cff_index_get_pointers:"
445                     " invalid first offset value %d set to zero\n",
446                     cur_offset ));
447         cur_offset = 0;
448       }
449 
450       if ( !pool )
451         t[0] = org_bytes + cur_offset;
452       else
453         t[0] = new_bytes + cur_offset;
454 
455       for ( n = 1; n <= idx->count; n++ )
456       {
457         FT_ULong  next_offset = idx->offsets[n] - 1;
458 
459 
460         /* two sanity checks for invalid offset tables */
461         if ( next_offset < cur_offset )
462           next_offset = cur_offset;
463         else if ( next_offset > idx->data_size )
464           next_offset = idx->data_size;
465 
466         if ( !pool )
467           t[n] = org_bytes + next_offset;
468         else
469         {
470           t[n] = new_bytes + next_offset + extra;
471 
472           if ( next_offset != cur_offset )
473           {
474             FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] );
475             t[n][0] = '\0';
476             t[n]   += 1;
477             extra++;
478           }
479         }
480 
481         cur_offset = next_offset;
482       }
483       *table = t;
484 
485       if ( pool )
486         *pool = new_bytes;
487       if ( pool_size )
488         *pool_size = new_size;
489     }
490 
491   Exit:
492     return error;
493   }
494 
495 
496   FT_LOCAL_DEF( FT_Error )
cff_index_access_element(CFF_Index idx,FT_UInt element,FT_Byte ** pbytes,FT_ULong * pbyte_len)497   cff_index_access_element( CFF_Index  idx,
498                             FT_UInt    element,
499                             FT_Byte**  pbytes,
500                             FT_ULong*  pbyte_len )
501   {
502     FT_Error  error = FT_Err_Ok;
503 
504 
505     if ( idx && idx->count > element )
506     {
507       /* compute start and end offsets */
508       FT_Stream  stream = idx->stream;
509       FT_ULong   off1, off2 = 0;
510 
511 
512       /* load offsets from file or the offset table */
513       if ( !idx->offsets )
514       {
515         FT_ULong  pos = element * idx->off_size;
516 
517 
518         if ( FT_STREAM_SEEK( idx->start + idx->hdr_size + pos ) )
519           goto Exit;
520 
521         off1 = cff_index_read_offset( idx, &error );
522         if ( error )
523           goto Exit;
524 
525         if ( off1 != 0 )
526         {
527           do
528           {
529             element++;
530             off2 = cff_index_read_offset( idx, &error );
531 
532           } while ( off2 == 0 && element < idx->count );
533         }
534       }
535       else   /* use offsets table */
536       {
537         off1 = idx->offsets[element];
538         if ( off1 )
539         {
540           do
541           {
542             element++;
543             off2 = idx->offsets[element];
544 
545           } while ( off2 == 0 && element < idx->count );
546         }
547       }
548 
549       /* XXX: should check off2 does not exceed the end of this entry; */
550       /*      at present, only truncate off2 at the end of this stream */
551       if ( off2 > stream->size + 1                    ||
552            idx->data_offset > stream->size - off2 + 1 )
553       {
554         FT_ERROR(( "cff_index_access_element:"
555                    " offset to next entry (%d)"
556                    " exceeds the end of stream (%d)\n",
557                    off2, stream->size - idx->data_offset + 1 ));
558         off2 = stream->size - idx->data_offset + 1;
559       }
560 
561       /* access element */
562       if ( off1 && off2 > off1 )
563       {
564         *pbyte_len = off2 - off1;
565 
566         if ( idx->bytes )
567         {
568           /* this index was completely loaded in memory, that's easy */
569           *pbytes = idx->bytes + off1 - 1;
570         }
571         else
572         {
573           /* this index is still on disk/file, access it through a frame */
574           if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||
575                FT_FRAME_EXTRACT( off2 - off1, *pbytes )      )
576             goto Exit;
577         }
578       }
579       else
580       {
581         /* empty index element */
582         *pbytes    = 0;
583         *pbyte_len = 0;
584       }
585     }
586     else
587       error = FT_THROW( Invalid_Argument );
588 
589   Exit:
590     return error;
591   }
592 
593 
594   FT_LOCAL_DEF( void )
cff_index_forget_element(CFF_Index idx,FT_Byte ** pbytes)595   cff_index_forget_element( CFF_Index  idx,
596                             FT_Byte**  pbytes )
597   {
598     if ( idx->bytes == 0 )
599     {
600       FT_Stream  stream = idx->stream;
601 
602 
603       FT_FRAME_RELEASE( *pbytes );
604     }
605   }
606 
607 
608   /* get an entry from Name INDEX */
609   FT_LOCAL_DEF( FT_String* )
cff_index_get_name(CFF_Font font,FT_UInt element)610   cff_index_get_name( CFF_Font  font,
611                       FT_UInt   element )
612   {
613     CFF_Index   idx = &font->name_index;
614     FT_Memory   memory;
615     FT_Byte*    bytes;
616     FT_ULong    byte_len;
617     FT_Error    error;
618     FT_String*  name = 0;
619 
620 
621     if ( !idx->stream )  /* CFF2 does not include a name index */
622       goto Exit;
623 
624     memory = idx->stream->memory;
625 
626     error = cff_index_access_element( idx, element, &bytes, &byte_len );
627     if ( error )
628       goto Exit;
629 
630     if ( !FT_ALLOC( name, byte_len + 1 ) )
631     {
632       if ( byte_len )
633         FT_MEM_COPY( name, bytes, byte_len );
634       name[byte_len] = 0;
635     }
636     cff_index_forget_element( idx, &bytes );
637 
638   Exit:
639     return name;
640   }
641 
642 
643   /* get an entry from String INDEX */
644   FT_LOCAL_DEF( FT_String* )
cff_index_get_string(CFF_Font font,FT_UInt element)645   cff_index_get_string( CFF_Font  font,
646                         FT_UInt   element )
647   {
648     return ( element < font->num_strings )
649              ? (FT_String*)font->strings[element]
650              : NULL;
651   }
652 
653 
654   FT_LOCAL_DEF( FT_String* )
cff_index_get_sid_string(CFF_Font font,FT_UInt sid)655   cff_index_get_sid_string( CFF_Font  font,
656                             FT_UInt   sid )
657   {
658     /* value 0xFFFFU indicates a missing dictionary entry */
659     if ( sid == 0xFFFFU )
660       return NULL;
661 
662     /* if it is not a standard string, return it */
663     if ( sid > 390 )
664       return cff_index_get_string( font, sid - 391 );
665 
666     /* CID-keyed CFF fonts don't have glyph names */
667     if ( !font->psnames )
668       return NULL;
669 
670     /* this is a standard string */
671     return (FT_String *)font->psnames->adobe_std_strings( sid );
672   }
673 
674 
675   /*************************************************************************/
676   /*************************************************************************/
677   /***                                                                   ***/
678   /***   FD Select table support                                         ***/
679   /***                                                                   ***/
680   /*************************************************************************/
681   /*************************************************************************/
682 
683 
684   static void
CFF_Done_FD_Select(CFF_FDSelect fdselect,FT_Stream stream)685   CFF_Done_FD_Select( CFF_FDSelect  fdselect,
686                       FT_Stream     stream )
687   {
688     if ( fdselect->data )
689       FT_FRAME_RELEASE( fdselect->data );
690 
691     fdselect->data_size   = 0;
692     fdselect->format      = 0;
693     fdselect->range_count = 0;
694   }
695 
696 
697   static FT_Error
CFF_Load_FD_Select(CFF_FDSelect fdselect,FT_UInt num_glyphs,FT_Stream stream,FT_ULong offset)698   CFF_Load_FD_Select( CFF_FDSelect  fdselect,
699                       FT_UInt       num_glyphs,
700                       FT_Stream     stream,
701                       FT_ULong      offset )
702   {
703     FT_Error  error;
704     FT_Byte   format;
705     FT_UInt   num_ranges;
706 
707 
708     /* read format */
709     if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) )
710       goto Exit;
711 
712     fdselect->format      = format;
713     fdselect->cache_count = 0;   /* clear cache */
714 
715     switch ( format )
716     {
717     case 0:     /* format 0, that's simple */
718       fdselect->data_size = num_glyphs;
719       goto Load_Data;
720 
721     case 3:     /* format 3, a tad more complex */
722       if ( FT_READ_USHORT( num_ranges ) )
723         goto Exit;
724 
725       if ( !num_ranges )
726       {
727         FT_TRACE0(( "CFF_Load_FD_Select: empty FDSelect array\n" ));
728         error = FT_THROW( Invalid_File_Format );
729         goto Exit;
730       }
731 
732       fdselect->data_size = num_ranges * 3 + 2;
733 
734     Load_Data:
735       if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) )
736         goto Exit;
737       break;
738 
739     default:    /* hmm... that's wrong */
740       error = FT_THROW( Invalid_File_Format );
741     }
742 
743   Exit:
744     return error;
745   }
746 
747 
748   FT_LOCAL_DEF( FT_Byte )
cff_fd_select_get(CFF_FDSelect fdselect,FT_UInt glyph_index)749   cff_fd_select_get( CFF_FDSelect  fdselect,
750                      FT_UInt       glyph_index )
751   {
752     FT_Byte  fd = 0;
753 
754 
755     /* if there is no FDSelect, return zero               */
756     /* Note: CFF2 with just one Font Dict has no FDSelect */
757     if ( !fdselect->data )
758       goto Exit;
759 
760     switch ( fdselect->format )
761     {
762     case 0:
763       fd = fdselect->data[glyph_index];
764       break;
765 
766     case 3:
767       /* first, compare to the cache */
768       if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
769                         fdselect->cache_count )
770       {
771         fd = fdselect->cache_fd;
772         break;
773       }
774 
775       /* then, look up the ranges array */
776       {
777         FT_Byte*  p       = fdselect->data;
778         FT_Byte*  p_limit = p + fdselect->data_size;
779         FT_Byte   fd2;
780         FT_UInt   first, limit;
781 
782 
783         first = FT_NEXT_USHORT( p );
784         do
785         {
786           if ( glyph_index < first )
787             break;
788 
789           fd2   = *p++;
790           limit = FT_NEXT_USHORT( p );
791 
792           if ( glyph_index < limit )
793           {
794             fd = fd2;
795 
796             /* update cache */
797             fdselect->cache_first = first;
798             fdselect->cache_count = limit - first;
799             fdselect->cache_fd    = fd2;
800             break;
801           }
802           first = limit;
803 
804         } while ( p < p_limit );
805       }
806       break;
807 
808     default:
809       ;
810     }
811 
812   Exit:
813     return fd;
814   }
815 
816 
817   /*************************************************************************/
818   /*************************************************************************/
819   /***                                                                   ***/
820   /***   CFF font support                                                ***/
821   /***                                                                   ***/
822   /*************************************************************************/
823   /*************************************************************************/
824 
825   static FT_Error
cff_charset_compute_cids(CFF_Charset charset,FT_UInt num_glyphs,FT_Memory memory)826   cff_charset_compute_cids( CFF_Charset  charset,
827                             FT_UInt      num_glyphs,
828                             FT_Memory    memory )
829   {
830     FT_Error   error   = FT_Err_Ok;
831     FT_UInt    i;
832     FT_Long    j;
833     FT_UShort  max_cid = 0;
834 
835 
836     if ( charset->max_cid > 0 )
837       goto Exit;
838 
839     for ( i = 0; i < num_glyphs; i++ )
840     {
841       if ( charset->sids[i] > max_cid )
842         max_cid = charset->sids[i];
843     }
844 
845     if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )
846       goto Exit;
847 
848     /* When multiple GIDs map to the same CID, we choose the lowest */
849     /* GID.  This is not described in any spec, but it matches the  */
850     /* behaviour of recent Acroread versions.                       */
851     for ( j = (FT_Long)num_glyphs - 1; j >= 0; j-- )
852       charset->cids[charset->sids[j]] = (FT_UShort)j;
853 
854     charset->max_cid    = max_cid;
855     charset->num_glyphs = num_glyphs;
856 
857   Exit:
858     return error;
859   }
860 
861 
862   FT_LOCAL_DEF( FT_UInt )
cff_charset_cid_to_gindex(CFF_Charset charset,FT_UInt cid)863   cff_charset_cid_to_gindex( CFF_Charset  charset,
864                              FT_UInt      cid )
865   {
866     FT_UInt  result = 0;
867 
868 
869     if ( cid <= charset->max_cid )
870       result = charset->cids[cid];
871 
872     return result;
873   }
874 
875 
876   static void
cff_charset_free_cids(CFF_Charset charset,FT_Memory memory)877   cff_charset_free_cids( CFF_Charset  charset,
878                          FT_Memory    memory )
879   {
880     FT_FREE( charset->cids );
881     charset->max_cid = 0;
882   }
883 
884 
885   static void
cff_charset_done(CFF_Charset charset,FT_Stream stream)886   cff_charset_done( CFF_Charset  charset,
887                     FT_Stream    stream )
888   {
889     FT_Memory  memory = stream->memory;
890 
891 
892     cff_charset_free_cids( charset, memory );
893 
894     FT_FREE( charset->sids );
895     charset->format = 0;
896     charset->offset = 0;
897   }
898 
899 
900   static FT_Error
cff_charset_load(CFF_Charset charset,FT_UInt num_glyphs,FT_Stream stream,FT_ULong base_offset,FT_ULong offset,FT_Bool invert)901   cff_charset_load( CFF_Charset  charset,
902                     FT_UInt      num_glyphs,
903                     FT_Stream    stream,
904                     FT_ULong     base_offset,
905                     FT_ULong     offset,
906                     FT_Bool      invert )
907   {
908     FT_Memory  memory = stream->memory;
909     FT_Error   error  = FT_Err_Ok;
910     FT_UShort  glyph_sid;
911 
912 
913     /* If the offset is greater than 2, we have to parse the charset */
914     /* table.                                                        */
915     if ( offset > 2 )
916     {
917       FT_UInt  j;
918 
919 
920       charset->offset = base_offset + offset;
921 
922       /* Get the format of the table. */
923       if ( FT_STREAM_SEEK( charset->offset ) ||
924            FT_READ_BYTE( charset->format )   )
925         goto Exit;
926 
927       /* Allocate memory for sids. */
928       if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
929         goto Exit;
930 
931       /* assign the .notdef glyph */
932       charset->sids[0] = 0;
933 
934       switch ( charset->format )
935       {
936       case 0:
937         if ( num_glyphs > 0 )
938         {
939           if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) )
940             goto Exit;
941 
942           for ( j = 1; j < num_glyphs; j++ )
943             charset->sids[j] = FT_GET_USHORT();
944 
945           FT_FRAME_EXIT();
946         }
947         break;
948 
949       case 1:
950       case 2:
951         {
952           FT_UInt  nleft;
953           FT_UInt  i;
954 
955 
956           j = 1;
957 
958           while ( j < num_glyphs )
959           {
960             /* Read the first glyph sid of the range. */
961             if ( FT_READ_USHORT( glyph_sid ) )
962               goto Exit;
963 
964             /* Read the number of glyphs in the range.  */
965             if ( charset->format == 2 )
966             {
967               if ( FT_READ_USHORT( nleft ) )
968                 goto Exit;
969             }
970             else
971             {
972               if ( FT_READ_BYTE( nleft ) )
973                 goto Exit;
974             }
975 
976             /* try to rescue some of the SIDs if `nleft' is too large */
977             if ( glyph_sid > 0xFFFFL - nleft )
978             {
979               FT_ERROR(( "cff_charset_load: invalid SID range trimmed"
980                          " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));
981               nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );
982             }
983 
984             /* Fill in the range of sids -- `nleft + 1' glyphs. */
985             for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )
986               charset->sids[j] = glyph_sid;
987           }
988         }
989         break;
990 
991       default:
992         FT_ERROR(( "cff_charset_load: invalid table format\n" ));
993         error = FT_THROW( Invalid_File_Format );
994         goto Exit;
995       }
996     }
997     else
998     {
999       /* Parse default tables corresponding to offset == 0, 1, or 2.  */
1000       /* CFF specification intimates the following:                   */
1001       /*                                                              */
1002       /* In order to use a predefined charset, the following must be  */
1003       /* true: The charset constructed for the glyphs in the font's   */
1004       /* charstrings dictionary must match the predefined charset in  */
1005       /* the first num_glyphs.                                        */
1006 
1007       charset->offset = offset;  /* record charset type */
1008 
1009       switch ( (FT_UInt)offset )
1010       {
1011       case 0:
1012         if ( num_glyphs > 229 )
1013         {
1014           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
1015                      "predefined charset (Adobe ISO-Latin)\n" ));
1016           error = FT_THROW( Invalid_File_Format );
1017           goto Exit;
1018         }
1019 
1020         /* Allocate memory for sids. */
1021         if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
1022           goto Exit;
1023 
1024         /* Copy the predefined charset into the allocated memory. */
1025         FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs );
1026 
1027         break;
1028 
1029       case 1:
1030         if ( num_glyphs > 166 )
1031         {
1032           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
1033                      "predefined charset (Adobe Expert)\n" ));
1034           error = FT_THROW( Invalid_File_Format );
1035           goto Exit;
1036         }
1037 
1038         /* Allocate memory for sids. */
1039         if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
1040           goto Exit;
1041 
1042         /* Copy the predefined charset into the allocated memory.     */
1043         FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs );
1044 
1045         break;
1046 
1047       case 2:
1048         if ( num_glyphs > 87 )
1049         {
1050           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
1051                      "predefined charset (Adobe Expert Subset)\n" ));
1052           error = FT_THROW( Invalid_File_Format );
1053           goto Exit;
1054         }
1055 
1056         /* Allocate memory for sids. */
1057         if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
1058           goto Exit;
1059 
1060         /* Copy the predefined charset into the allocated memory.     */
1061         FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs );
1062 
1063         break;
1064 
1065       default:
1066         error = FT_THROW( Invalid_File_Format );
1067         goto Exit;
1068       }
1069     }
1070 
1071     /* we have to invert the `sids' array for subsetted CID-keyed fonts */
1072     if ( invert )
1073       error = cff_charset_compute_cids( charset, num_glyphs, memory );
1074 
1075   Exit:
1076     /* Clean up if there was an error. */
1077     if ( error )
1078     {
1079       FT_FREE( charset->sids );
1080       FT_FREE( charset->cids );
1081       charset->format = 0;
1082       charset->offset = 0;
1083       charset->sids   = 0;
1084     }
1085 
1086     return error;
1087   }
1088 
1089 
1090   static void
cff_vstore_done(CFF_VStoreRec * vstore,FT_Memory memory)1091   cff_vstore_done( CFF_VStoreRec*  vstore,
1092                    FT_Memory       memory )
1093   {
1094     FT_UInt  i;
1095 
1096 
1097     /* free regionList and axisLists */
1098     if ( vstore->varRegionList )
1099     {
1100       for ( i = 0; i < vstore->regionCount; i++ )
1101         FT_FREE( vstore->varRegionList[i].axisList );
1102     }
1103     FT_FREE( vstore->varRegionList );
1104 
1105     /* free varData and indices */
1106     if ( vstore->varData )
1107     {
1108       for ( i = 0; i < vstore->dataCount; i++ )
1109         FT_FREE( vstore->varData[i].regionIndices );
1110     }
1111     FT_FREE( vstore->varData );
1112   }
1113 
1114 
1115   /* convert 2.14 to Fixed */
1116   #define FT_fdot14ToFixed( x )  ( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
1117 
1118 
1119   static FT_Error
cff_vstore_load(CFF_VStoreRec * vstore,FT_Stream stream,FT_ULong base_offset,FT_ULong offset)1120   cff_vstore_load( CFF_VStoreRec*  vstore,
1121                    FT_Stream       stream,
1122                    FT_ULong        base_offset,
1123                    FT_ULong        offset )
1124   {
1125     FT_Memory  memory = stream->memory;
1126     FT_Error   error  = FT_ERR( Invalid_File_Format );
1127 
1128     FT_ULong*  dataOffsetArray = NULL;
1129     FT_UInt    i, j;
1130 
1131 
1132     /* no offset means no vstore to parse */
1133     if ( offset )
1134     {
1135       FT_UInt   vsOffset;
1136       FT_UInt   format;
1137       FT_ULong  regionListOffset;
1138 
1139 
1140       /* we need to parse the table to determine its size; */
1141       /* skip table length                                 */
1142       if ( FT_STREAM_SEEK( base_offset + offset ) ||
1143            FT_STREAM_SKIP( 2 )                    )
1144         goto Exit;
1145 
1146       /* actual variation store begins after the length */
1147       vsOffset = FT_STREAM_POS();
1148 
1149       /* check the header */
1150       if ( FT_READ_USHORT( format ) )
1151         goto Exit;
1152       if ( format != 1 )
1153       {
1154         error = FT_THROW( Invalid_File_Format );
1155         goto Exit;
1156       }
1157 
1158       /* read top level fields */
1159       if ( FT_READ_ULONG( regionListOffset )   ||
1160            FT_READ_USHORT( vstore->dataCount ) )
1161         goto Exit;
1162 
1163       /* make temporary copy of item variation data offsets; */
1164       /* we'll parse region list first, then come back       */
1165       if ( FT_NEW_ARRAY( dataOffsetArray, vstore->dataCount ) )
1166         goto Exit;
1167 
1168       for ( i = 0; i < vstore->dataCount; i++ )
1169       {
1170         if ( FT_READ_ULONG( dataOffsetArray[i] ) )
1171           goto Exit;
1172       }
1173 
1174       /* parse regionList and axisLists */
1175       if ( FT_STREAM_SEEK( vsOffset + regionListOffset ) ||
1176            FT_READ_USHORT( vstore->axisCount )           ||
1177            FT_READ_USHORT( vstore->regionCount )         )
1178         goto Exit;
1179 
1180       if ( FT_NEW_ARRAY( vstore->varRegionList, vstore->regionCount ) )
1181         goto Exit;
1182 
1183       for ( i = 0; i < vstore->regionCount; i++ )
1184       {
1185         CFF_VarRegion*  region = &vstore->varRegionList[i];
1186 
1187 
1188         if ( FT_NEW_ARRAY( region->axisList, vstore->axisCount ) )
1189           goto Exit;
1190 
1191         for ( j = 0; j < vstore->axisCount; j++ )
1192         {
1193           CFF_AxisCoords*  axis = &region->axisList[j];
1194 
1195           FT_Int16  start14, peak14, end14;
1196 
1197 
1198           if ( FT_READ_SHORT( start14 ) ||
1199                FT_READ_SHORT( peak14 )  ||
1200                FT_READ_SHORT( end14 )   )
1201             goto Exit;
1202 
1203           axis->startCoord = FT_fdot14ToFixed( start14 );
1204           axis->peakCoord  = FT_fdot14ToFixed( peak14 );
1205           axis->endCoord   = FT_fdot14ToFixed( end14 );
1206         }
1207       }
1208 
1209       /* use dataOffsetArray now to parse varData items */
1210       if ( FT_NEW_ARRAY( vstore->varData, vstore->dataCount ) )
1211         goto Exit;
1212 
1213       for ( i = 0; i < vstore->dataCount; i++ )
1214       {
1215         CFF_VarData*  data = &vstore->varData[i];
1216 
1217 
1218         if ( FT_STREAM_SEEK( vsOffset + dataOffsetArray[i] ) )
1219           goto Exit;
1220 
1221         /* ignore `itemCount' and `shortDeltaCount' */
1222         /* because CFF2 has no delta sets           */
1223         if ( FT_STREAM_SKIP( 4 ) )
1224           goto Exit;
1225 
1226         /* Note: just record values; consistency is checked later    */
1227         /*       by cff_blend_build_vector when it consumes `vstore' */
1228 
1229         if ( FT_READ_USHORT( data->regionIdxCount ) )
1230           goto Exit;
1231 
1232         if ( FT_NEW_ARRAY( data->regionIndices, data->regionIdxCount ) )
1233           goto Exit;
1234 
1235         for ( j = 0; j < data->regionIdxCount; j++ )
1236         {
1237           if ( FT_READ_USHORT( data->regionIndices[j] ) )
1238             goto Exit;
1239         }
1240       }
1241     }
1242 
1243     error = FT_Err_Ok;
1244 
1245   Exit:
1246     FT_FREE( dataOffsetArray );
1247     if ( error )
1248       cff_vstore_done( vstore, memory );
1249 
1250     return error;
1251   }
1252 
1253 
1254   /* Clear blend stack (after blend values are consumed). */
1255   /*                                                      */
1256   /* TODO: Should do this in cff_run_parse, but subFont   */
1257   /*       ref is not available there.                    */
1258   /*                                                      */
1259   /* Allocation is not changed when stack is cleared.     */
1260   FT_LOCAL_DEF( void )
cff_blend_clear(CFF_SubFont subFont)1261   cff_blend_clear( CFF_SubFont  subFont )
1262   {
1263     subFont->blend_top  = subFont->blend_stack;
1264     subFont->blend_used = 0;
1265   }
1266 
1267 
1268   /* Blend numOperands on the stack,                       */
1269   /* store results into the first numBlends values,        */
1270   /* then pop remaining arguments.                         */
1271   /*                                                       */
1272   /* This is comparable to `cf2_doBlend' but               */
1273   /* the cffparse stack is different and can't be written. */
1274   /* Blended values are written to a different buffer,     */
1275   /* using reserved operator 255.                          */
1276   /*                                                       */
1277   /* Blend calculation is done in 16.16 fixed point.       */
1278   FT_LOCAL_DEF( FT_Error )
cff_blend_doBlend(CFF_SubFont subFont,CFF_Parser parser,FT_UInt numBlends)1279   cff_blend_doBlend( CFF_SubFont  subFont,
1280                      CFF_Parser   parser,
1281                      FT_UInt      numBlends )
1282   {
1283     FT_UInt  delta;
1284     FT_UInt  base;
1285     FT_UInt  i, j;
1286     FT_UInt  size;
1287 
1288     CFF_Blend  blend = &subFont->blend;
1289 
1290     FT_Memory  memory = subFont->blend.font->memory; /* for FT_REALLOC */
1291     FT_Error   error  = FT_Err_Ok;                   /* for FT_REALLOC */
1292 
1293     /* compute expected number of operands for this blend */
1294     FT_UInt  numOperands = (FT_UInt)( numBlends * blend->lenBV );
1295     FT_UInt  count       = (FT_UInt)( parser->top - 1 - parser->stack );
1296 
1297 
1298     if ( numOperands > count )
1299     {
1300       FT_TRACE4(( " cff_blend_doBlend: Stack underflow %d args\n", count ));
1301 
1302       error = FT_THROW( Stack_Underflow );
1303       goto Exit;
1304     }
1305 
1306     /* check whether we have room for `numBlends' values at `blend_top' */
1307     size = 5 * numBlends;           /* add 5 bytes per entry    */
1308     if ( subFont->blend_used + size > subFont->blend_alloc )
1309     {
1310       FT_Byte*  blend_stack_old = subFont->blend_stack;
1311       FT_Byte*  blend_top_old   = subFont->blend_top;
1312 
1313 
1314       /* increase or allocate `blend_stack' and reset `blend_top'; */
1315       /* prepare to append `numBlends' values to the buffer        */
1316       if ( FT_REALLOC( subFont->blend_stack,
1317                        subFont->blend_alloc,
1318                        subFont->blend_alloc + size ) )
1319         goto Exit;
1320 
1321       subFont->blend_top    = subFont->blend_stack + subFont->blend_used;
1322       subFont->blend_alloc += size;
1323 
1324       /* iterate over the parser stack and adjust pointers */
1325       /* if the reallocated buffer has a different address */
1326       if ( blend_stack_old                         &&
1327            subFont->blend_stack != blend_stack_old )
1328       {
1329         FT_PtrDist  offset = subFont->blend_stack - blend_stack_old;
1330         FT_Byte**   p;
1331 
1332 
1333         for ( p = parser->stack; p < parser->top; p++ )
1334         {
1335           if ( *p >= blend_stack_old && *p < blend_top_old )
1336             *p += offset;
1337         }
1338       }
1339     }
1340     subFont->blend_used += size;
1341 
1342     base  = count - numOperands;     /* index of first blend arg */
1343     delta = base + numBlends;        /* index of first delta arg */
1344 
1345     for ( i = 0; i < numBlends; i++ )
1346     {
1347       const FT_Int32*  weight = &blend->BV[1];
1348       FT_Int32         sum;
1349 
1350 
1351       /* convert inputs to 16.16 fixed point */
1352       sum = cff_parse_num( parser, &parser->stack[i + base] ) * 65536;
1353 
1354       for ( j = 1; j < blend->lenBV; j++ )
1355         sum += FT_MulFix( *weight++,
1356                           cff_parse_num( parser,
1357                                          &parser->stack[delta++] ) * 65536 );
1358 
1359       /* point parser stack to new value on blend_stack */
1360       parser->stack[i + base] = subFont->blend_top;
1361 
1362       /* Push blended result as Type 2 5-byte fixed point number.  This */
1363       /* will not conflict with actual DICTs because 255 is a reserved  */
1364       /* opcode in both CFF and CFF2 DICTs.  See `cff_parse_num' for    */
1365       /* decode of this, which rounds to an integer.                    */
1366       *subFont->blend_top++ = 255;
1367       *subFont->blend_top++ = ( (FT_UInt32)sum & 0xFF000000U ) >> 24;
1368       *subFont->blend_top++ = ( (FT_UInt32)sum & 0x00FF0000U ) >> 16;
1369       *subFont->blend_top++ = ( (FT_UInt32)sum & 0x0000FF00U ) >>  8;
1370       *subFont->blend_top++ =   (FT_UInt32)sum & 0x000000FFU;
1371     }
1372 
1373     /* leave only numBlends results on parser stack */
1374     parser->top = &parser->stack[base + numBlends];
1375 
1376   Exit:
1377     return error;
1378   }
1379 
1380 
1381   /* Compute a blend vector from variation store index and normalized  */
1382   /* vector based on pseudo-code in OpenType Font Variations Overview. */
1383   /*                                                                   */
1384   /* Note: lenNDV == 0 produces a default blend vector, (1,0,0,...).   */
1385   FT_LOCAL_DEF( FT_Error )
cff_blend_build_vector(CFF_Blend blend,FT_UInt vsindex,FT_UInt lenNDV,FT_Fixed * NDV)1386   cff_blend_build_vector( CFF_Blend  blend,
1387                           FT_UInt    vsindex,
1388                           FT_UInt    lenNDV,
1389                           FT_Fixed*  NDV )
1390   {
1391     FT_Error   error  = FT_Err_Ok;            /* for FT_REALLOC */
1392     FT_Memory  memory = blend->font->memory;  /* for FT_REALLOC */
1393 
1394     FT_UInt       len;
1395     CFF_VStore    vs;
1396     CFF_VarData*  varData;
1397     FT_UInt       master;
1398 
1399 
1400     FT_ASSERT( lenNDV == 0 || NDV );
1401 
1402     blend->builtBV = FALSE;
1403 
1404     vs = &blend->font->vstore;
1405 
1406     /* VStore and fvar must be consistent */
1407     if ( lenNDV != 0 && lenNDV != vs->axisCount )
1408     {
1409       FT_TRACE4(( " cff_blend_build_vector: Axis count mismatch\n" ));
1410       error = FT_THROW( Invalid_File_Format );
1411       goto Exit;
1412     }
1413 
1414     if ( vsindex >= vs->dataCount )
1415     {
1416       FT_TRACE4(( " cff_blend_build_vector: vsindex out of range\n" ));
1417       error = FT_THROW( Invalid_File_Format );
1418       goto Exit;
1419     }
1420 
1421     /* select the item variation data structure */
1422     varData = &vs->varData[vsindex];
1423 
1424     /* prepare buffer for the blend vector */
1425     len = varData->regionIdxCount + 1;    /* add 1 for default component */
1426     if ( FT_REALLOC( blend->BV,
1427                      blend->lenBV * sizeof( *blend->BV ),
1428                      len * sizeof( *blend->BV ) ) )
1429       goto Exit;
1430 
1431     blend->lenBV = len;
1432 
1433     /* outer loop steps through master designs to be blended */
1434     for ( master = 0; master < len; master++ )
1435     {
1436       FT_UInt         j;
1437       FT_UInt         idx;
1438       CFF_VarRegion*  varRegion;
1439 
1440 
1441       /* default factor is always one */
1442       if ( master == 0 )
1443       {
1444         blend->BV[master] = FT_FIXED_ONE;
1445         FT_TRACE4(( "   build blend vector len %d\n"
1446                     "   [ %f ",
1447                     len,
1448                     blend->BV[master] / 65536.0 ));
1449         continue;
1450       }
1451 
1452       /* VStore array does not include default master, so subtract one */
1453       idx       = varData->regionIndices[master - 1];
1454       varRegion = &vs->varRegionList[idx];
1455 
1456       if ( idx >= vs->regionCount )
1457       {
1458         FT_TRACE4(( " cff_blend_build_vector:"
1459                     " region index out of range\n" ));
1460         error = FT_THROW( Invalid_File_Format );
1461         goto Exit;
1462       }
1463 
1464       /* Note: `lenNDV' could be zero.                              */
1465       /*       In that case, build default blend vector (1,0,0...). */
1466       /*       In the normal case, initialize each component to 1   */
1467       /*       before inner loop.                                   */
1468       if ( lenNDV != 0 )
1469         blend->BV[master] = FT_FIXED_ONE; /* default */
1470 
1471       /* inner loop steps through axes in this region */
1472       for ( j = 0; j < lenNDV; j++ )
1473       {
1474         CFF_AxisCoords*  axis = &varRegion->axisList[j];
1475         FT_Fixed         axisScalar;
1476 
1477 
1478         /* compute the scalar contribution of this axis; */
1479         /* ignore invalid ranges                         */
1480         if ( axis->startCoord > axis->peakCoord ||
1481              axis->peakCoord > axis->endCoord   )
1482           axisScalar = FT_FIXED_ONE;
1483 
1484         else if ( axis->startCoord < 0 &&
1485                   axis->endCoord > 0   &&
1486                   axis->peakCoord != 0 )
1487           axisScalar = FT_FIXED_ONE;
1488 
1489         /* peak of 0 means ignore this axis */
1490         else if ( axis->peakCoord == 0 )
1491           axisScalar = FT_FIXED_ONE;
1492 
1493         /* ignore this region if coords are out of range */
1494         else if ( NDV[j] < axis->startCoord ||
1495                   NDV[j] > axis->endCoord   )
1496           axisScalar = 0;
1497 
1498         /* calculate a proportional factor */
1499         else
1500         {
1501           if ( NDV[j] == axis->peakCoord )
1502             axisScalar = FT_FIXED_ONE;
1503           else if ( NDV[j] < axis->peakCoord )
1504             axisScalar = FT_DivFix( NDV[j] - axis->startCoord,
1505                                     axis->peakCoord - axis->startCoord );
1506           else
1507             axisScalar = FT_DivFix( axis->endCoord - NDV[j],
1508                                     axis->endCoord - axis->peakCoord );
1509         }
1510 
1511         /* take product of all the axis scalars */
1512         blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar );
1513       }
1514 
1515       FT_TRACE4(( ", %f ",
1516                   blend->BV[master] / 65536.0 ));
1517     }
1518 
1519     FT_TRACE4(( "]\n" ));
1520 
1521     /* record the parameters used to build the blend vector */
1522     blend->lastVsindex = vsindex;
1523 
1524     if ( lenNDV != 0 )
1525     {
1526       /* user has set a normalized vector */
1527       if ( FT_REALLOC( blend->lastNDV,
1528                        blend->lenNDV * sizeof ( *NDV ),
1529                        lenNDV * sizeof ( *NDV ) ) )
1530         goto Exit;
1531 
1532       blend->lenNDV = lenNDV;
1533       FT_MEM_COPY( blend->lastNDV,
1534                    NDV,
1535                    lenNDV * sizeof ( *NDV ) );
1536     }
1537 
1538     blend->builtBV = TRUE;
1539 
1540   Exit:
1541     return error;
1542   }
1543 
1544 
1545   /* `lenNDV' is zero for default vector;           */
1546   /* return TRUE if blend vector needs to be built. */
1547   FT_LOCAL_DEF( FT_Bool )
cff_blend_check_vector(CFF_Blend blend,FT_UInt vsindex,FT_UInt lenNDV,FT_Fixed * NDV)1548   cff_blend_check_vector( CFF_Blend  blend,
1549                           FT_UInt    vsindex,
1550                           FT_UInt    lenNDV,
1551                           FT_Fixed*  NDV )
1552   {
1553     if ( !blend->builtBV                             ||
1554          blend->lastVsindex != vsindex               ||
1555          blend->lenNDV != lenNDV                     ||
1556          ( lenNDV                                  &&
1557            memcmp( NDV,
1558                    blend->lastNDV,
1559                    lenNDV * sizeof ( *NDV ) ) != 0 ) )
1560     {
1561       /* need to build blend vector */
1562       return TRUE;
1563     }
1564 
1565     return FALSE;
1566   }
1567 
1568 
1569 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1570 
1571   FT_LOCAL_DEF( FT_Error )
cff_get_var_blend(CFF_Face face,FT_UInt * num_coords,FT_Fixed ** coords,FT_MM_Var ** mm_var)1572   cff_get_var_blend( CFF_Face     face,
1573                      FT_UInt     *num_coords,
1574                      FT_Fixed*   *coords,
1575                      FT_MM_Var*  *mm_var )
1576   {
1577     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
1578 
1579 
1580     return mm->get_var_blend( FT_FACE( face ), num_coords, coords, mm_var );
1581   }
1582 
1583 
1584   FT_LOCAL_DEF( void )
cff_done_blend(CFF_Face face)1585   cff_done_blend( CFF_Face  face )
1586   {
1587     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
1588 
1589 
1590     mm->done_blend( FT_FACE( face ) );
1591   }
1592 
1593 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1594 
1595 
1596   static void
cff_encoding_done(CFF_Encoding encoding)1597   cff_encoding_done( CFF_Encoding  encoding )
1598   {
1599     encoding->format = 0;
1600     encoding->offset = 0;
1601     encoding->count  = 0;
1602   }
1603 
1604 
1605   static FT_Error
cff_encoding_load(CFF_Encoding encoding,CFF_Charset charset,FT_UInt num_glyphs,FT_Stream stream,FT_ULong base_offset,FT_ULong offset)1606   cff_encoding_load( CFF_Encoding  encoding,
1607                      CFF_Charset   charset,
1608                      FT_UInt       num_glyphs,
1609                      FT_Stream     stream,
1610                      FT_ULong      base_offset,
1611                      FT_ULong      offset )
1612   {
1613     FT_Error   error = FT_Err_Ok;
1614     FT_UInt    count;
1615     FT_UInt    j;
1616     FT_UShort  glyph_sid;
1617     FT_UInt    glyph_code;
1618 
1619 
1620     /* Check for charset->sids.  If we do not have this, we fail. */
1621     if ( !charset->sids )
1622     {
1623       error = FT_THROW( Invalid_File_Format );
1624       goto Exit;
1625     }
1626 
1627     /* Zero out the code to gid/sid mappings. */
1628     for ( j = 0; j < 256; j++ )
1629     {
1630       encoding->sids [j] = 0;
1631       encoding->codes[j] = 0;
1632     }
1633 
1634     /* Note: The encoding table in a CFF font is indexed by glyph index;  */
1635     /* the first encoded glyph index is 1.  Hence, we read the character  */
1636     /* code (`glyph_code') at index j and make the assignment:            */
1637     /*                                                                    */
1638     /*    encoding->codes[glyph_code] = j + 1                             */
1639     /*                                                                    */
1640     /* We also make the assignment:                                       */
1641     /*                                                                    */
1642     /*    encoding->sids[glyph_code] = charset->sids[j + 1]               */
1643     /*                                                                    */
1644     /* This gives us both a code to GID and a code to SID mapping.        */
1645 
1646     if ( offset > 1 )
1647     {
1648       encoding->offset = base_offset + offset;
1649 
1650       /* we need to parse the table to determine its size */
1651       if ( FT_STREAM_SEEK( encoding->offset ) ||
1652            FT_READ_BYTE( encoding->format )   ||
1653            FT_READ_BYTE( count )              )
1654         goto Exit;
1655 
1656       switch ( encoding->format & 0x7F )
1657       {
1658       case 0:
1659         {
1660           FT_Byte*  p;
1661 
1662 
1663           /* By convention, GID 0 is always ".notdef" and is never */
1664           /* coded in the font.  Hence, the number of codes found  */
1665           /* in the table is `count+1'.                            */
1666           /*                                                       */
1667           encoding->count = count + 1;
1668 
1669           if ( FT_FRAME_ENTER( count ) )
1670             goto Exit;
1671 
1672           p = (FT_Byte*)stream->cursor;
1673 
1674           for ( j = 1; j <= count; j++ )
1675           {
1676             glyph_code = *p++;
1677 
1678             /* Make sure j is not too big. */
1679             if ( j < num_glyphs )
1680             {
1681               /* Assign code to GID mapping. */
1682               encoding->codes[glyph_code] = (FT_UShort)j;
1683 
1684               /* Assign code to SID mapping. */
1685               encoding->sids[glyph_code] = charset->sids[j];
1686             }
1687           }
1688 
1689           FT_FRAME_EXIT();
1690         }
1691         break;
1692 
1693       case 1:
1694         {
1695           FT_UInt  nleft;
1696           FT_UInt  i = 1;
1697           FT_UInt  k;
1698 
1699 
1700           encoding->count = 0;
1701 
1702           /* Parse the Format1 ranges. */
1703           for ( j = 0;  j < count; j++, i += nleft )
1704           {
1705             /* Read the first glyph code of the range. */
1706             if ( FT_READ_BYTE( glyph_code ) )
1707               goto Exit;
1708 
1709             /* Read the number of codes in the range. */
1710             if ( FT_READ_BYTE( nleft ) )
1711               goto Exit;
1712 
1713             /* Increment nleft, so we read `nleft + 1' codes/sids. */
1714             nleft++;
1715 
1716             /* compute max number of character codes */
1717             if ( (FT_UInt)nleft > encoding->count )
1718               encoding->count = nleft;
1719 
1720             /* Fill in the range of codes/sids. */
1721             for ( k = i; k < nleft + i; k++, glyph_code++ )
1722             {
1723               /* Make sure k is not too big. */
1724               if ( k < num_glyphs && glyph_code < 256 )
1725               {
1726                 /* Assign code to GID mapping. */
1727                 encoding->codes[glyph_code] = (FT_UShort)k;
1728 
1729                 /* Assign code to SID mapping. */
1730                 encoding->sids[glyph_code] = charset->sids[k];
1731               }
1732             }
1733           }
1734 
1735           /* simple check; one never knows what can be found in a font */
1736           if ( encoding->count > 256 )
1737             encoding->count = 256;
1738         }
1739         break;
1740 
1741       default:
1742         FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
1743         error = FT_THROW( Invalid_File_Format );
1744         goto Exit;
1745       }
1746 
1747       /* Parse supplemental encodings, if any. */
1748       if ( encoding->format & 0x80 )
1749       {
1750         FT_UInt  gindex;
1751 
1752 
1753         /* count supplements */
1754         if ( FT_READ_BYTE( count ) )
1755           goto Exit;
1756 
1757         for ( j = 0; j < count; j++ )
1758         {
1759           /* Read supplemental glyph code. */
1760           if ( FT_READ_BYTE( glyph_code ) )
1761             goto Exit;
1762 
1763           /* Read the SID associated with this glyph code. */
1764           if ( FT_READ_USHORT( glyph_sid ) )
1765             goto Exit;
1766 
1767           /* Assign code to SID mapping. */
1768           encoding->sids[glyph_code] = glyph_sid;
1769 
1770           /* First, look up GID which has been assigned to */
1771           /* SID glyph_sid.                                */
1772           for ( gindex = 0; gindex < num_glyphs; gindex++ )
1773           {
1774             if ( charset->sids[gindex] == glyph_sid )
1775             {
1776               encoding->codes[glyph_code] = (FT_UShort)gindex;
1777               break;
1778             }
1779           }
1780         }
1781       }
1782     }
1783     else
1784     {
1785       /* We take into account the fact a CFF font can use a predefined */
1786       /* encoding without containing all of the glyphs encoded by this */
1787       /* encoding (see the note at the end of section 12 in the CFF    */
1788       /* specification).                                               */
1789 
1790       switch ( (FT_UInt)offset )
1791       {
1792       case 0:
1793         /* First, copy the code to SID mapping. */
1794         FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 );
1795         goto Populate;
1796 
1797       case 1:
1798         /* First, copy the code to SID mapping. */
1799         FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 );
1800 
1801       Populate:
1802         /* Construct code to GID mapping from code to SID mapping */
1803         /* and charset.                                           */
1804 
1805         encoding->count = 0;
1806 
1807         error = cff_charset_compute_cids( charset, num_glyphs,
1808                                           stream->memory );
1809         if ( error )
1810           goto Exit;
1811 
1812         for ( j = 0; j < 256; j++ )
1813         {
1814           FT_UInt  sid = encoding->sids[j];
1815           FT_UInt  gid = 0;
1816 
1817 
1818           if ( sid )
1819             gid = cff_charset_cid_to_gindex( charset, sid );
1820 
1821           if ( gid != 0 )
1822           {
1823             encoding->codes[j] = (FT_UShort)gid;
1824             encoding->count    = j + 1;
1825           }
1826           else
1827           {
1828             encoding->codes[j] = 0;
1829             encoding->sids [j] = 0;
1830           }
1831         }
1832         break;
1833 
1834       default:
1835         FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
1836         error = FT_THROW( Invalid_File_Format );
1837         goto Exit;
1838       }
1839     }
1840 
1841   Exit:
1842 
1843     /* Clean up if there was an error. */
1844     return error;
1845   }
1846 
1847 
1848   /* Parse private dictionary; first call is always from `cff_face_init', */
1849   /* so NDV has not been set for CFF2 variation.                          */
1850   /*                                                                      */
1851   /* `cff_slot_load' must call this function each time NDV changes.       */
1852   FT_LOCAL_DEF( FT_Error )
cff_load_private_dict(CFF_Font font,CFF_SubFont subfont,FT_UInt lenNDV,FT_Fixed * NDV)1853   cff_load_private_dict( CFF_Font     font,
1854                          CFF_SubFont  subfont,
1855                          FT_UInt      lenNDV,
1856                          FT_Fixed*    NDV )
1857   {
1858     FT_Error         error  = FT_Err_Ok;
1859     CFF_ParserRec    parser;
1860     CFF_FontRecDict  top    = &subfont->font_dict;
1861     CFF_Private      priv   = &subfont->private_dict;
1862     FT_Stream        stream = font->stream;
1863     FT_UInt          stackSize;
1864 
1865 
1866     /* store handle needed to access memory, vstore for blend;    */
1867     /* we need this for clean-up even if there is no private DICT */
1868     subfont->blend.font   = font;
1869     subfont->blend.usedBV = FALSE;  /* clear state */
1870 
1871     if ( !top->private_offset || !top->private_size )
1872       goto Exit2;       /* no private DICT, do nothing */
1873 
1874     /* set defaults */
1875     FT_ZERO( priv );
1876 
1877     priv->blue_shift       = 7;
1878     priv->blue_fuzz        = 1;
1879     priv->lenIV            = -1;
1880     priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
1881     priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
1882 
1883     /* provide inputs for blend calculations */
1884     priv->subfont   = subfont;
1885     subfont->lenNDV = lenNDV;
1886     subfont->NDV    = NDV;
1887 
1888     stackSize = font->cff2 ? font->top_font.font_dict.maxstack
1889                            : CFF_MAX_STACK_DEPTH + 1;
1890 
1891     if ( cff_parser_init( &parser,
1892                           font->cff2 ? CFF2_CODE_PRIVATE : CFF_CODE_PRIVATE,
1893                           priv,
1894                           font->library,
1895                           stackSize,
1896                           top->num_designs,
1897                           top->num_axes ) )
1898       goto Exit;
1899 
1900     if ( FT_STREAM_SEEK( font->base_offset + top->private_offset ) ||
1901          FT_FRAME_ENTER( top->private_size )                       )
1902       goto Exit;
1903 
1904     FT_TRACE4(( " private dictionary:\n" ));
1905     error = cff_parser_run( &parser,
1906                             (FT_Byte*)stream->cursor,
1907                             (FT_Byte*)stream->limit );
1908     FT_FRAME_EXIT();
1909 
1910     if ( error )
1911       goto Exit;
1912 
1913     /* ensure that `num_blue_values' is even */
1914     priv->num_blue_values &= ~1;
1915 
1916   Exit:
1917     /* clean up */
1918     cff_blend_clear( subfont ); /* clear blend stack */
1919     cff_parser_done( &parser ); /* free parser stack */
1920 
1921   Exit2:
1922     /* no clean up (parser not initialized) */
1923     return error;
1924   }
1925 
1926 
1927   /* There are 3 ways to call this function, distinguished by code.  */
1928   /*                                                                 */
1929   /* . CFF_CODE_TOPDICT for either a CFF Top DICT or a CFF Font DICT */
1930   /* . CFF2_CODE_TOPDICT for CFF2 Top DICT                           */
1931   /* . CFF2_CODE_FONTDICT for CFF2 Font DICT                         */
1932 
1933   static FT_Error
cff_subfont_load(CFF_SubFont subfont,CFF_Index idx,FT_UInt font_index,FT_Stream stream,FT_ULong base_offset,FT_UInt code,CFF_Font font)1934   cff_subfont_load( CFF_SubFont  subfont,
1935                     CFF_Index    idx,
1936                     FT_UInt      font_index,
1937                     FT_Stream    stream,
1938                     FT_ULong     base_offset,
1939                     FT_UInt      code,
1940                     CFF_Font     font )
1941   {
1942     FT_Error         error;
1943     CFF_ParserRec    parser;
1944     FT_Byte*         dict = NULL;
1945     FT_ULong         dict_len;
1946     CFF_FontRecDict  top  = &subfont->font_dict;
1947     CFF_Private      priv = &subfont->private_dict;
1948 
1949     FT_Bool  cff2      = FT_BOOL( code == CFF2_CODE_TOPDICT  ||
1950                                   code == CFF2_CODE_FONTDICT );
1951     FT_UInt  stackSize = cff2 ? CFF2_DEFAULT_STACK
1952                               : CFF_MAX_STACK_DEPTH;
1953 
1954 
1955     /* Note: We use default stack size for CFF2 Font DICT because        */
1956     /*       Top and Font DICTs are not allowed to have blend operators. */
1957     error = cff_parser_init( &parser,
1958                              code,
1959                              &subfont->font_dict,
1960                              font->library,
1961                              stackSize,
1962                              0,
1963                              0 );
1964     if ( error )
1965       goto Exit;
1966 
1967     /* set defaults */
1968     FT_ZERO( top );
1969 
1970     top->underline_position  = -( 100L << 16 );
1971     top->underline_thickness = 50L << 16;
1972     top->charstring_type     = 2;
1973     top->font_matrix.xx      = 0x10000L;
1974     top->font_matrix.yy      = 0x10000L;
1975     top->cid_count           = 8720;
1976 
1977     /* we use the implementation specific SID value 0xFFFF to indicate */
1978     /* missing entries                                                 */
1979     top->version             = 0xFFFFU;
1980     top->notice              = 0xFFFFU;
1981     top->copyright           = 0xFFFFU;
1982     top->full_name           = 0xFFFFU;
1983     top->family_name         = 0xFFFFU;
1984     top->weight              = 0xFFFFU;
1985     top->embedded_postscript = 0xFFFFU;
1986 
1987     top->cid_registry        = 0xFFFFU;
1988     top->cid_ordering        = 0xFFFFU;
1989     top->cid_font_name       = 0xFFFFU;
1990 
1991     /* set default stack size */
1992     top->maxstack            = cff2 ? CFF2_DEFAULT_STACK : 48;
1993 
1994     if ( idx->count )   /* count is nonzero for a real index */
1995       error = cff_index_access_element( idx, font_index, &dict, &dict_len );
1996     else
1997     {
1998       /* CFF2 has a fake top dict index;     */
1999       /* simulate `cff_index_access_element' */
2000 
2001       /* Note: macros implicitly use `stream' and set `error' */
2002       if ( FT_STREAM_SEEK( idx->data_offset )       ||
2003            FT_FRAME_EXTRACT( idx->data_size, dict ) )
2004         goto Exit;
2005 
2006       dict_len = idx->data_size;
2007     }
2008 
2009     if ( !error )
2010     {
2011       FT_TRACE4(( " top dictionary:\n" ));
2012       error = cff_parser_run( &parser, dict, dict + dict_len );
2013     }
2014 
2015     /* clean up regardless of error */
2016     if ( idx->count )
2017       cff_index_forget_element( idx, &dict );
2018     else
2019       FT_FRAME_RELEASE( dict );
2020 
2021     if ( error )
2022       goto Exit;
2023 
2024     /* if it is a CID font, we stop there */
2025     if ( top->cid_registry != 0xFFFFU )
2026       goto Exit;
2027 
2028     /* Parse the private dictionary, if any.                   */
2029     /*                                                         */
2030     /* CFF2 does not have a private dictionary in the Top DICT */
2031     /* but may have one in a Font DICT.  We need to parse      */
2032     /* the latter here in order to load any local subrs.       */
2033     error = cff_load_private_dict( font, subfont, 0, 0 );
2034     if ( error )
2035       goto Exit;
2036 
2037     /* read the local subrs, if any */
2038     if ( priv->local_subrs_offset )
2039     {
2040       if ( FT_STREAM_SEEK( base_offset + top->private_offset +
2041                            priv->local_subrs_offset ) )
2042         goto Exit;
2043 
2044       error = cff_index_init( &subfont->local_subrs_index, stream, 1, cff2 );
2045       if ( error )
2046         goto Exit;
2047 
2048       error = cff_index_get_pointers( &subfont->local_subrs_index,
2049                                       &subfont->local_subrs, NULL, NULL );
2050       if ( error )
2051         goto Exit;
2052     }
2053 
2054   Exit:
2055     cff_parser_done( &parser ); /* free parser stack */
2056 
2057     return error;
2058   }
2059 
2060 
2061   static void
cff_subfont_done(FT_Memory memory,CFF_SubFont subfont)2062   cff_subfont_done( FT_Memory    memory,
2063                     CFF_SubFont  subfont )
2064   {
2065     if ( subfont )
2066     {
2067       cff_index_done( &subfont->local_subrs_index );
2068       FT_FREE( subfont->local_subrs );
2069 
2070       FT_FREE( subfont->blend.lastNDV );
2071       FT_FREE( subfont->blend.BV );
2072       FT_FREE( subfont->blend_stack );
2073     }
2074   }
2075 
2076 
2077   FT_LOCAL_DEF( FT_Error )
cff_font_load(FT_Library library,FT_Stream stream,FT_Int face_index,CFF_Font font,FT_Bool pure_cff,FT_Bool cff2)2078   cff_font_load( FT_Library library,
2079                  FT_Stream  stream,
2080                  FT_Int     face_index,
2081                  CFF_Font   font,
2082                  FT_Bool    pure_cff,
2083                  FT_Bool    cff2 )
2084   {
2085     static const FT_Frame_Field  cff_header_fields[] =
2086     {
2087 #undef  FT_STRUCTURE
2088 #define FT_STRUCTURE  CFF_FontRec
2089 
2090       FT_FRAME_START( 3 ),
2091         FT_FRAME_BYTE( version_major ),
2092         FT_FRAME_BYTE( version_minor ),
2093         FT_FRAME_BYTE( header_size ),
2094       FT_FRAME_END
2095     };
2096 
2097     FT_Error         error;
2098     FT_Memory        memory = stream->memory;
2099     FT_ULong         base_offset;
2100     CFF_FontRecDict  dict;
2101     CFF_IndexRec     string_index;
2102     FT_UInt          subfont_index;
2103 
2104 
2105     FT_ZERO( font );
2106     FT_ZERO( &string_index );
2107 
2108     dict        = &font->top_font.font_dict;
2109     base_offset = FT_STREAM_POS();
2110 
2111     font->library     = library;
2112     font->stream      = stream;
2113     font->memory      = memory;
2114     font->cff2        = cff2;
2115     font->base_offset = base_offset;
2116 
2117     /* read CFF font header */
2118     if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
2119       goto Exit;
2120 
2121     if ( cff2 )
2122     {
2123       if ( font->version_major != 2 ||
2124            font->header_size < 5    )
2125       {
2126         FT_TRACE2(( "  not a CFF2 font header\n" ));
2127         error = FT_THROW( Unknown_File_Format );
2128         goto Exit;
2129       }
2130 
2131       if ( FT_READ_USHORT( font->top_dict_length ) )
2132         goto Exit;
2133     }
2134     else
2135     {
2136       FT_Byte  absolute_offset;
2137 
2138 
2139       if ( FT_READ_BYTE( absolute_offset ) )
2140         goto Exit;
2141 
2142       if ( font->version_major != 1 ||
2143            font->header_size < 4    ||
2144            absolute_offset > 4      )
2145       {
2146         FT_TRACE2(( "  not a CFF font header\n" ));
2147         error = FT_THROW( Unknown_File_Format );
2148         goto Exit;
2149       }
2150     }
2151 
2152     /* skip the rest of the header */
2153     if ( FT_STREAM_SEEK( base_offset + font->header_size ) )
2154     {
2155       /* For pure CFFs we have read only four bytes so far.  Contrary to */
2156       /* other formats like SFNT those bytes doesn't define a signature; */
2157       /* it is thus possible that the font isn't a CFF at all.           */
2158       if ( pure_cff )
2159       {
2160         FT_TRACE2(( "  not a CFF file\n" ));
2161         error = FT_THROW( Unknown_File_Format );
2162       }
2163       goto Exit;
2164     }
2165 
2166     if ( cff2 )
2167     {
2168       /* For CFF2, the top dict data immediately follow the header    */
2169       /* and the length is stored in the header `offSize' field;      */
2170       /* there is no index for it.                                    */
2171       /*                                                              */
2172       /* Use the `font_dict_index' to save the current position       */
2173       /* and length of data, but leave count at zero as an indicator. */
2174       FT_ZERO( &font->font_dict_index );
2175 
2176       font->font_dict_index.data_offset = FT_STREAM_POS();
2177       font->font_dict_index.data_size   = font->top_dict_length;
2178 
2179       /* skip the top dict data for now, we will parse it later */
2180       if ( FT_STREAM_SKIP( font->top_dict_length ) )
2181         goto Exit;
2182 
2183       /* next, read the global subrs index */
2184       if ( FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
2185                                          stream, 1, cff2 ) ) )
2186         goto Exit;
2187     }
2188     else
2189     {
2190       /* for CFF, read the name, top dict, string and global subrs index */
2191       if ( FT_SET_ERROR( cff_index_init( &font->name_index,
2192                                          stream, 0, cff2 ) ) )
2193       {
2194         if ( pure_cff )
2195         {
2196           FT_TRACE2(( "  not a CFF file\n" ));
2197           error = FT_THROW( Unknown_File_Format );
2198         }
2199         goto Exit;
2200       }
2201 
2202       /* font names must not be empty */
2203       if ( font->name_index.data_size < font->name_index.count )
2204       {
2205         /* for pure CFFs, we still haven't checked enough bytes */
2206         /* to be sure that it is a CFF at all                   */
2207         error = pure_cff ? FT_THROW( Unknown_File_Format )
2208                          : FT_THROW( Invalid_File_Format );
2209         goto Exit;
2210       }
2211 
2212       if ( FT_SET_ERROR( cff_index_init( &font->font_dict_index,
2213                                          stream, 0, cff2 ) )                 ||
2214            FT_SET_ERROR( cff_index_init( &string_index,
2215                                          stream, 1, cff2 ) )                 ||
2216            FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
2217                                          stream, 1, cff2 ) )                 ||
2218            FT_SET_ERROR( cff_index_get_pointers( &string_index,
2219                                                  &font->strings,
2220                                                  &font->string_pool,
2221                                                  &font->string_pool_size ) ) )
2222         goto Exit;
2223 
2224       /* there must be a Top DICT index entry for each name index entry */
2225       if ( font->name_index.count > font->font_dict_index.count )
2226       {
2227         FT_ERROR(( "cff_font_load:"
2228                    " not enough entries in Top DICT index\n" ));
2229         error = FT_THROW( Invalid_File_Format );
2230         goto Exit;
2231       }
2232     }
2233 
2234     font->num_strings = string_index.count;
2235 
2236     if ( pure_cff )
2237     {
2238       /* well, we don't really forget the `disabled' fonts... */
2239       subfont_index = (FT_UInt)( face_index & 0xFFFF );
2240 
2241       if ( face_index > 0 && subfont_index >= font->name_index.count )
2242       {
2243         FT_ERROR(( "cff_font_load:"
2244                    " invalid subfont index for pure CFF font (%d)\n",
2245                    subfont_index ));
2246         error = FT_THROW( Invalid_Argument );
2247         goto Exit;
2248       }
2249 
2250       font->num_faces = font->name_index.count;
2251     }
2252     else
2253     {
2254       subfont_index = 0;
2255 
2256       if ( font->name_index.count > 1 )
2257       {
2258         FT_ERROR(( "cff_font_load:"
2259                    " invalid CFF font with multiple subfonts\n"
2260                    "              "
2261                    " in SFNT wrapper\n" ));
2262         error = FT_THROW( Invalid_File_Format );
2263         goto Exit;
2264       }
2265     }
2266 
2267     /* in case of a font format check, simply exit now */
2268     if ( face_index < 0 )
2269       goto Exit;
2270 
2271     /* now, parse the top-level font dictionary */
2272     FT_TRACE4(( "parsing top-level\n" ));
2273     error = cff_subfont_load( &font->top_font,
2274                               &font->font_dict_index,
2275                               subfont_index,
2276                               stream,
2277                               base_offset,
2278                               cff2 ? CFF2_CODE_TOPDICT : CFF_CODE_TOPDICT,
2279                               font );
2280     if ( error )
2281       goto Exit;
2282 
2283     if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
2284       goto Exit;
2285 
2286     error = cff_index_init( &font->charstrings_index, stream, 0, cff2 );
2287     if ( error )
2288       goto Exit;
2289 
2290     /* now, check for a CID or CFF2 font */
2291     if ( dict->cid_registry != 0xFFFFU ||
2292          cff2                          )
2293     {
2294       CFF_IndexRec  fd_index;
2295       CFF_SubFont   sub = NULL;
2296       FT_UInt       idx;
2297 
2298 
2299       /* for CFF2, read the Variation Store if available;                 */
2300       /* this must follow the Top DICT parse and precede any Private DICT */
2301       error = cff_vstore_load( &font->vstore,
2302                                stream,
2303                                base_offset,
2304                                dict->vstore_offset );
2305       if ( error )
2306         goto Exit;
2307 
2308       /* this is a CID-keyed font, we must now allocate a table of */
2309       /* sub-fonts, then load each of them separately              */
2310       if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
2311         goto Exit;
2312 
2313       error = cff_index_init( &fd_index, stream, 0, cff2 );
2314       if ( error )
2315         goto Exit;
2316 
2317       /* Font Dicts are not limited to 256 for CFF2. */
2318       /* TODO: support this for CFF2                 */
2319       if ( fd_index.count > CFF_MAX_CID_FONTS )
2320       {
2321         FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
2322         goto Fail_CID;
2323       }
2324 
2325       /* allocate & read each font dict independently */
2326       font->num_subfonts = fd_index.count;
2327       if ( FT_NEW_ARRAY( sub, fd_index.count ) )
2328         goto Fail_CID;
2329 
2330       /* set up pointer table */
2331       for ( idx = 0; idx < fd_index.count; idx++ )
2332         font->subfonts[idx] = sub + idx;
2333 
2334       /* now load each subfont independently */
2335       for ( idx = 0; idx < fd_index.count; idx++ )
2336       {
2337         sub = font->subfonts[idx];
2338         FT_TRACE4(( "parsing subfont %u\n", idx ));
2339         error = cff_subfont_load( sub,
2340                                   &fd_index,
2341                                   idx,
2342                                   stream,
2343                                   base_offset,
2344                                   cff2 ? CFF2_CODE_FONTDICT
2345                                        : CFF_CODE_TOPDICT,
2346                                   font );
2347         if ( error )
2348           goto Fail_CID;
2349       }
2350 
2351       /* now load the FD Select array;               */
2352       /* CFF2 omits FDSelect if there is only one FD */
2353       if ( !cff2 || fd_index.count > 1 )
2354         error = CFF_Load_FD_Select( &font->fd_select,
2355                                     font->charstrings_index.count,
2356                                     stream,
2357                                     base_offset + dict->cid_fd_select_offset );
2358 
2359     Fail_CID:
2360       cff_index_done( &fd_index );
2361 
2362       if ( error )
2363         goto Exit;
2364     }
2365     else
2366       font->num_subfonts = 0;
2367 
2368     /* read the charstrings index now */
2369     if ( dict->charstrings_offset == 0 )
2370     {
2371       FT_ERROR(( "cff_font_load: no charstrings offset\n" ));
2372       error = FT_THROW( Invalid_File_Format );
2373       goto Exit;
2374     }
2375 
2376     font->num_glyphs = font->charstrings_index.count;
2377 
2378     error = cff_index_get_pointers( &font->global_subrs_index,
2379                                     &font->global_subrs, NULL, NULL );
2380 
2381     if ( error )
2382       goto Exit;
2383 
2384     /* read the Charset and Encoding tables if available */
2385     if ( !cff2 && font->num_glyphs > 0 )
2386     {
2387       FT_Bool  invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
2388 
2389 
2390       error = cff_charset_load( &font->charset, font->num_glyphs, stream,
2391                                 base_offset, dict->charset_offset, invert );
2392       if ( error )
2393         goto Exit;
2394 
2395       /* CID-keyed CFFs don't have an encoding */
2396       if ( dict->cid_registry == 0xFFFFU )
2397       {
2398         error = cff_encoding_load( &font->encoding,
2399                                    &font->charset,
2400                                    font->num_glyphs,
2401                                    stream,
2402                                    base_offset,
2403                                    dict->encoding_offset );
2404         if ( error )
2405           goto Exit;
2406       }
2407     }
2408 
2409     /* get the font name (/CIDFontName for CID-keyed fonts, */
2410     /* /FontName otherwise)                                 */
2411     font->font_name = cff_index_get_name( font, subfont_index );
2412 
2413   Exit:
2414     cff_index_done( &string_index );
2415 
2416     return error;
2417   }
2418 
2419 
2420   FT_LOCAL_DEF( void )
cff_font_done(CFF_Font font)2421   cff_font_done( CFF_Font  font )
2422   {
2423     FT_Memory  memory = font->memory;
2424     FT_UInt    idx;
2425 
2426 
2427     cff_index_done( &font->global_subrs_index );
2428     cff_index_done( &font->font_dict_index );
2429     cff_index_done( &font->name_index );
2430     cff_index_done( &font->charstrings_index );
2431 
2432     /* release font dictionaries, but only if working with */
2433     /* a CID keyed CFF font or a CFF2 font                 */
2434     if ( font->num_subfonts > 0 )
2435     {
2436       for ( idx = 0; idx < font->num_subfonts; idx++ )
2437         cff_subfont_done( memory, font->subfonts[idx] );
2438 
2439       /* the subfonts array has been allocated as a single block */
2440       FT_FREE( font->subfonts[0] );
2441     }
2442 
2443     cff_encoding_done( &font->encoding );
2444     cff_charset_done( &font->charset, font->stream );
2445     cff_vstore_done( &font->vstore, memory );
2446 
2447     cff_subfont_done( memory, &font->top_font );
2448 
2449     CFF_Done_FD_Select( &font->fd_select, font->stream );
2450 
2451     FT_FREE( font->font_info );
2452 
2453     FT_FREE( font->font_name );
2454     FT_FREE( font->global_subrs );
2455     FT_FREE( font->strings );
2456     FT_FREE( font->string_pool );
2457 
2458     if ( font->cf2_instance.finalizer )
2459     {
2460       font->cf2_instance.finalizer( font->cf2_instance.data );
2461       FT_FREE( font->cf2_instance.data );
2462     }
2463   }
2464 
2465 
2466 /* END */
2467