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