blob: 6d73e985d25f8fb0c35d2050d1e73cbbe8ef0bbb [file] [log] [blame]
David Turner19ed8af2000-12-08 02:42:29 +00001/***************************************************************************/
2/* */
3/* cffload.c */
4/* */
Werner Lembergc3b21602001-12-05 01:22:05 +00005/* OpenType and CFF data/program tables loader (body). */
David Turner19ed8af2000-12-08 02:42:29 +00006/* */
Werner Lembergbe3c9812006-01-27 14:16:16 +00007/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
David Turner19ed8af2000-12-08 02:42:29 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used, */
Werner Lemberg521a2d72001-03-20 22:58:56 +000011/* modified, and distributed under the terms of the FreeType project */
David Turner19ed8af2000-12-08 02:42:29 +000012/* 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
Werner Lembergcc069be2000-12-08 16:17:16 +000018
David Turner19ed8af2000-12-08 02:42:29 +000019#include <ft2build.h>
20#include FT_INTERNAL_DEBUG_H
21#include FT_INTERNAL_OBJECTS_H
22#include FT_INTERNAL_STREAM_H
David Turner77605952003-10-29 21:43:52 +000023#include FT_SERVICE_POSTSCRIPT_CMAPS_H
David Turner19ed8af2000-12-08 02:42:29 +000024#include FT_TRUETYPE_TAGS_H
25
David Turner8d3a4012001-03-20 11:14:24 +000026#include "cffload.h"
27#include "cffparse.h"
David Turner19ed8af2000-12-08 02:42:29 +000028
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000029#include "cfferrs.h"
30
Werner Lemberg6b766632000-12-30 22:14:58 +000031
David Turnerc8087482001-12-20 13:14:18 +000032#if 1
33 static const FT_UShort cff_isoadobe_charset[229] =
34 {
35 0,
36 1,
37 2,
38 3,
39 4,
40 5,
41 6,
42 7,
43 8,
44 9,
45 10,
46 11,
47 12,
48 13,
49 14,
50 15,
51 16,
52 17,
53 18,
54 19,
55 20,
56 21,
57 22,
58 23,
59 24,
60 25,
61 26,
62 27,
63 28,
64 29,
65 30,
66 31,
67 32,
68 33,
69 34,
70 35,
71 36,
72 37,
73 38,
74 39,
75 40,
76 41,
77 42,
78 43,
79 44,
80 45,
81 46,
82 47,
83 48,
84 49,
85 50,
86 51,
87 52,
88 53,
89 54,
90 55,
91 56,
92 57,
93 58,
94 59,
95 60,
96 61,
97 62,
98 63,
99 64,
100 65,
101 66,
102 67,
103 68,
104 69,
105 70,
106 71,
107 72,
108 73,
109 74,
110 75,
111 76,
112 77,
113 78,
114 79,
115 80,
116 81,
117 82,
118 83,
119 84,
120 85,
121 86,
122 87,
123 88,
124 89,
125 90,
126 91,
127 92,
128 93,
129 94,
130 95,
131 96,
132 97,
133 98,
134 99,
135 100,
136 101,
137 102,
138 103,
139 104,
140 105,
141 106,
142 107,
143 108,
144 109,
145 110,
146 111,
147 112,
148 113,
149 114,
150 115,
151 116,
152 117,
153 118,
154 119,
155 120,
156 121,
157 122,
158 123,
159 124,
160 125,
161 126,
162 127,
163 128,
164 129,
165 130,
166 131,
167 132,
168 133,
169 134,
170 135,
171 136,
172 137,
173 138,
174 139,
175 140,
176 141,
177 142,
178 143,
179 144,
180 145,
181 146,
182 147,
183 148,
184 149,
185 150,
186 151,
187 152,
188 153,
189 154,
190 155,
191 156,
192 157,
193 158,
194 159,
195 160,
196 161,
197 162,
198 163,
199 164,
200 165,
201 166,
202 167,
203 168,
204 169,
205 170,
206 171,
207 172,
208 173,
209 174,
210 175,
211 176,
212 177,
213 178,
214 179,
215 180,
216 181,
217 182,
218 183,
219 184,
220 185,
221 186,
222 187,
223 188,
224 189,
225 190,
226 191,
227 192,
228 193,
229 194,
230 195,
231 196,
232 197,
233 198,
234 199,
235 200,
236 201,
237 202,
238 203,
239 204,
240 205,
241 206,
242 207,
243 208,
244 209,
245 210,
246 211,
247 212,
248 213,
249 214,
250 215,
251 216,
252 217,
253 218,
254 219,
255 220,
256 221,
257 222,
258 223,
259 224,
260 225,
261 226,
262 227,
263 228
264 };
265
266 static const FT_UShort cff_expert_charset[166] =
267 {
268 0,
269 1,
270 229,
271 230,
272 231,
273 232,
274 233,
275 234,
276 235,
277 236,
278 237,
279 238,
280 13,
281 14,
282 15,
283 99,
284 239,
285 240,
286 241,
287 242,
288 243,
289 244,
290 245,
291 246,
292 247,
293 248,
294 27,
295 28,
296 249,
297 250,
298 251,
299 252,
300 253,
301 254,
302 255,
303 256,
304 257,
305 258,
306 259,
307 260,
308 261,
309 262,
310 263,
311 264,
312 265,
313 266,
314 109,
315 110,
316 267,
317 268,
318 269,
319 270,
320 271,
321 272,
322 273,
323 274,
324 275,
325 276,
326 277,
327 278,
328 279,
329 280,
330 281,
331 282,
332 283,
333 284,
334 285,
335 286,
336 287,
337 288,
338 289,
339 290,
340 291,
341 292,
342 293,
343 294,
344 295,
345 296,
346 297,
347 298,
348 299,
349 300,
350 301,
351 302,
352 303,
353 304,
354 305,
355 306,
356 307,
357 308,
358 309,
359 310,
360 311,
361 312,
362 313,
363 314,
364 315,
365 316,
366 317,
367 318,
368 158,
369 155,
370 163,
371 319,
372 320,
373 321,
374 322,
375 323,
376 324,
377 325,
378 326,
379 150,
380 164,
381 169,
382 327,
383 328,
384 329,
385 330,
386 331,
387 332,
388 333,
389 334,
390 335,
391 336,
392 337,
393 338,
394 339,
395 340,
396 341,
397 342,
398 343,
399 344,
400 345,
401 346,
402 347,
403 348,
404 349,
405 350,
406 351,
407 352,
408 353,
409 354,
410 355,
411 356,
412 357,
413 358,
414 359,
415 360,
416 361,
417 362,
418 363,
419 364,
420 365,
421 366,
422 367,
423 368,
424 369,
425 370,
426 371,
427 372,
428 373,
429 374,
430 375,
431 376,
432 377,
433 378
434 };
435
436 static const FT_UShort cff_expertsubset_charset[87] =
437 {
438 0,
439 1,
440 231,
441 232,
442 235,
443 236,
444 237,
445 238,
446 13,
447 14,
448 15,
449 99,
450 239,
451 240,
452 241,
453 242,
454 243,
455 244,
456 245,
457 246,
458 247,
459 248,
460 27,
461 28,
462 249,
463 250,
464 251,
465 253,
466 254,
467 255,
468 256,
469 257,
470 258,
471 259,
472 260,
473 261,
474 262,
475 263,
476 264,
477 265,
478 266,
479 109,
480 110,
481 267,
482 268,
483 269,
484 270,
485 272,
486 300,
487 301,
488 302,
489 305,
490 314,
491 315,
492 158,
493 155,
494 163,
495 320,
496 321,
497 322,
498 323,
499 324,
500 325,
501 326,
502 150,
503 164,
504 169,
505 327,
506 328,
507 329,
508 330,
509 331,
510 332,
511 333,
512 334,
513 335,
514 336,
515 337,
516 338,
517 339,
518 340,
519 341,
520 342,
521 343,
522 344,
523 345,
524 346
525 };
526
527 static const FT_UShort cff_standard_encoding[256] =
528 {
529 0,
530 0,
531 0,
532 0,
533 0,
534 0,
535 0,
536 0,
537 0,
538 0,
539 0,
540 0,
541 0,
542 0,
543 0,
544 0,
545 0,
546 0,
547 0,
548 0,
549 0,
550 0,
551 0,
552 0,
553 0,
554 0,
555 0,
556 0,
557 0,
558 0,
559 0,
560 0,
561 1,
562 2,
563 3,
564 4,
565 5,
566 6,
567 7,
568 8,
569 9,
570 10,
571 11,
572 12,
573 13,
574 14,
575 15,
576 16,
577 17,
578 18,
579 19,
580 20,
581 21,
582 22,
583 23,
584 24,
585 25,
586 26,
587 27,
588 28,
589 29,
590 30,
591 31,
592 32,
593 33,
594 34,
595 35,
596 36,
597 37,
598 38,
599 39,
600 40,
601 41,
602 42,
603 43,
604 44,
605 45,
606 46,
607 47,
608 48,
609 49,
610 50,
611 51,
612 52,
613 53,
614 54,
615 55,
616 56,
617 57,
618 58,
619 59,
620 60,
621 61,
622 62,
623 63,
624 64,
625 65,
626 66,
627 67,
628 68,
629 69,
630 70,
631 71,
632 72,
633 73,
634 74,
635 75,
636 76,
637 77,
638 78,
639 79,
640 80,
641 81,
642 82,
643 83,
644 84,
645 85,
646 86,
647 87,
648 88,
649 89,
650 90,
651 91,
652 92,
653 93,
654 94,
655 95,
656 0,
657 0,
658 0,
659 0,
660 0,
661 0,
662 0,
663 0,
664 0,
665 0,
666 0,
667 0,
668 0,
669 0,
670 0,
671 0,
672 0,
673 0,
674 0,
675 0,
676 0,
677 0,
678 0,
679 0,
680 0,
681 0,
682 0,
683 0,
684 0,
685 0,
686 0,
687 0,
688 0,
689 0,
690 96,
691 97,
692 98,
693 99,
694 100,
695 101,
696 102,
697 103,
698 104,
699 105,
700 106,
701 107,
702 108,
703 109,
704 110,
705 0,
706 111,
707 112,
708 113,
709 114,
710 0,
711 115,
712 116,
713 117,
714 118,
715 119,
716 120,
717 121,
718 122,
719 0,
720 123,
721 0,
722 124,
723 125,
724 126,
725 127,
726 128,
727 129,
728 130,
729 131,
730 0,
731 132,
732 133,
733 0,
734 134,
735 135,
736 136,
737 137,
738 0,
739 0,
740 0,
741 0,
742 0,
743 0,
744 0,
745 0,
746 0,
747 0,
748 0,
749 0,
750 0,
751 0,
752 0,
753 0,
754 138,
755 0,
756 139,
757 0,
758 0,
759 0,
760 0,
761 140,
762 141,
763 142,
764 143,
765 0,
766 0,
767 0,
768 0,
769 0,
770 144,
771 0,
772 0,
773 0,
774 145,
775 0,
776 0,
777 146,
778 147,
779 148,
780 149,
781 0,
782 0,
783 0,
784 0
785 };
786
787 static const FT_UShort cff_expert_encoding[256] =
788 {
789 0,
790 0,
791 0,
792 0,
793 0,
794 0,
795 0,
796 0,
797 0,
798 0,
799 0,
800 0,
801 0,
802 0,
803 0,
804 0,
805 0,
806 0,
807 0,
808 0,
809 0,
810 0,
811 0,
812 0,
813 0,
814 0,
815 0,
816 0,
817 0,
818 0,
819 0,
820 0,
821 1,
822 229,
823 230,
824 0,
825 231,
826 232,
827 233,
828 234,
829 235,
830 236,
831 237,
832 238,
833 13,
834 14,
835 15,
836 99,
837 239,
838 240,
839 241,
840 242,
841 243,
842 244,
843 245,
844 246,
845 247,
846 248,
847 27,
848 28,
849 249,
850 250,
851 251,
852 252,
853 0,
854 253,
855 254,
856 255,
857 256,
858 257,
859 0,
860 0,
861 0,
862 258,
863 0,
864 0,
865 259,
866 260,
867 261,
868 262,
869 0,
870 0,
871 263,
872 264,
873 265,
874 0,
875 266,
876 109,
877 110,
878 267,
879 268,
880 269,
881 0,
882 270,
883 271,
884 272,
885 273,
886 274,
887 275,
888 276,
889 277,
890 278,
891 279,
892 280,
893 281,
894 282,
895 283,
896 284,
897 285,
898 286,
899 287,
900 288,
901 289,
902 290,
903 291,
904 292,
905 293,
906 294,
907 295,
908 296,
909 297,
910 298,
911 299,
912 300,
913 301,
914 302,
915 303,
916 0,
917 0,
918 0,
919 0,
920 0,
921 0,
922 0,
923 0,
924 0,
925 0,
926 0,
927 0,
928 0,
929 0,
930 0,
931 0,
932 0,
933 0,
934 0,
935 0,
936 0,
937 0,
938 0,
939 0,
940 0,
941 0,
942 0,
943 0,
944 0,
945 0,
946 0,
947 0,
948 0,
949 0,
950 304,
951 305,
952 306,
953 0,
954 0,
955 307,
956 308,
957 309,
958 310,
959 311,
960 0,
961 312,
962 0,
963 0,
964 312,
965 0,
966 0,
967 314,
968 315,
969 0,
970 0,
971 316,
972 317,
973 318,
974 0,
975 0,
976 0,
977 158,
978 155,
979 163,
980 319,
981 320,
982 321,
983 322,
984 323,
985 324,
986 325,
987 0,
988 0,
989 326,
990 150,
991 164,
992 169,
993 327,
994 328,
995 329,
996 330,
997 331,
998 332,
999 333,
1000 334,
1001 335,
1002 336,
1003 337,
1004 338,
1005 339,
1006 340,
1007 341,
1008 342,
1009 343,
1010 344,
1011 345,
1012 346,
1013 347,
1014 348,
1015 349,
1016 350,
1017 351,
1018 352,
1019 353,
1020 354,
1021 355,
1022 356,
1023 357,
1024 358,
1025 359,
1026 360,
1027 361,
1028 362,
1029 363,
1030 364,
1031 365,
1032 366,
1033 367,
1034 368,
1035 369,
1036 370,
1037 371,
1038 372,
1039 373,
1040 374,
1041 375,
1042 376,
1043 377,
1044 378
1045 };
1046#endif
1047
1048
David Turnerbc82f1b2002-03-01 02:26:22 +00001049 FT_LOCAL_DEF( FT_UShort )
David Turnerb9b2cac2002-07-10 16:52:06 +00001050 cff_get_standard_encoding( FT_UInt charcode )
David Turnerc8087482001-12-20 13:14:18 +00001051 {
David Turnerf86709a2002-01-07 10:04:09 +00001052 return (FT_UShort)(charcode < 256 ? cff_standard_encoding[charcode] : 0);
David Turnerc8087482001-12-20 13:14:18 +00001053 }
1054
1055
David Turner19ed8af2000-12-08 02:42:29 +00001056 /*************************************************************************/
1057 /* */
1058 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
1059 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
1060 /* messages during execution. */
1061 /* */
1062#undef FT_COMPONENT
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +00001063#define FT_COMPONENT trace_cffload
David Turner19ed8af2000-12-08 02:42:29 +00001064
David Turner12d40da2001-10-21 15:41:11 +00001065
David Turner19ed8af2000-12-08 02:42:29 +00001066 /* read a CFF offset from memory */
Werner Lemberg93616ec2001-06-27 19:46:12 +00001067 static FT_ULong
1068 cff_get_offset( FT_Byte* p,
1069 FT_Byte off_size )
David Turner19ed8af2000-12-08 02:42:29 +00001070 {
1071 FT_ULong result;
1072
1073
1074 for ( result = 0; off_size > 0; off_size-- )
1075 {
1076 result <<= 8;
1077 result |= *p++;
1078 }
1079
1080 return result;
1081 }
1082
1083
Werner Lemberg93616ec2001-06-27 19:46:12 +00001084 static FT_Error
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001085 cff_new_index( CFF_Index idx,
1086 FT_Stream stream,
1087 FT_Bool load )
David Turner19ed8af2000-12-08 02:42:29 +00001088 {
Werner Lembergcc069be2000-12-08 16:17:16 +00001089 FT_Error error;
1090 FT_Memory memory = stream->memory;
1091 FT_UShort count;
David Turner19ed8af2000-12-08 02:42:29 +00001092
1093
Werner Lembergb3d5e9c2002-07-28 05:05:24 +00001094 FT_MEM_ZERO( idx, sizeof ( *idx ) );
David Turner19ed8af2000-12-08 02:42:29 +00001095
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001096 idx->stream = stream;
David Turnera890c292002-03-22 12:55:23 +00001097 if ( !FT_READ_USHORT( count ) &&
Werner Lemberg3bcad432004-05-06 11:48:35 +00001098 count > 0 )
David Turner19ed8af2000-12-08 02:42:29 +00001099 {
1100 FT_Byte* p;
1101 FT_Byte offsize;
1102 FT_ULong data_size;
1103 FT_ULong* poff;
1104
1105
1106 /* there is at least one element; read the offset size, */
1107 /* then access the offset table to compute the index's total size */
David Turnera890c292002-03-22 12:55:23 +00001108 if ( FT_READ_BYTE( offsize ) )
David Turner19ed8af2000-12-08 02:42:29 +00001109 goto Exit;
1110
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001111 idx->stream = stream;
1112 idx->count = count;
1113 idx->off_size = offsize;
1114 data_size = (FT_ULong)( count + 1 ) * offsize;
David Turner19ed8af2000-12-08 02:42:29 +00001115
David Turnere459d742002-03-22 13:52:37 +00001116 if ( FT_NEW_ARRAY( idx->offsets, count + 1 ) ||
1117 FT_FRAME_ENTER( data_size ) )
David Turner19ed8af2000-12-08 02:42:29 +00001118 goto Exit;
1119
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001120 poff = idx->offsets;
David Turner19ed8af2000-12-08 02:42:29 +00001121 p = (FT_Byte*)stream->cursor;
1122
1123 for ( ; (FT_Short)count >= 0; count-- )
1124 {
1125 poff[0] = cff_get_offset( p, offsize );
1126 poff++;
1127 p += offsize;
1128 }
1129
David Turner7d3a2642002-03-20 10:49:31 +00001130 FT_FRAME_EXIT();
David Turner19ed8af2000-12-08 02:42:29 +00001131
David Turner7d3a2642002-03-20 10:49:31 +00001132 idx->data_offset = FT_STREAM_POS();
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001133 data_size = poff[-1] - 1;
David Turner19ed8af2000-12-08 02:42:29 +00001134
1135 if ( load )
1136 {
1137 /* load the data */
David Turner7d3a2642002-03-20 10:49:31 +00001138 if ( FT_FRAME_EXTRACT( data_size, idx->bytes ) )
David Turner19ed8af2000-12-08 02:42:29 +00001139 goto Exit;
1140 }
1141 else
1142 {
1143 /* skip the data */
David Turner7d3a2642002-03-20 10:49:31 +00001144 if ( FT_STREAM_SKIP( data_size ) )
David Turner19ed8af2000-12-08 02:42:29 +00001145 goto Exit;
1146 }
1147 }
1148
1149 Exit:
1150 if ( error )
David Turnere459d742002-03-22 13:52:37 +00001151 FT_FREE( idx->offsets );
David Turner19ed8af2000-12-08 02:42:29 +00001152
1153 return error;
1154 }
1155
1156
Werner Lemberg93616ec2001-06-27 19:46:12 +00001157 static void
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001158 cff_done_index( CFF_Index idx )
David Turner19ed8af2000-12-08 02:42:29 +00001159 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001160 if ( idx->stream )
David Turner19ed8af2000-12-08 02:42:29 +00001161 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001162 FT_Stream stream = idx->stream;
David Turner19ed8af2000-12-08 02:42:29 +00001163 FT_Memory memory = stream->memory;
1164
1165
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001166 if ( idx->bytes )
David Turner7d3a2642002-03-20 10:49:31 +00001167 FT_FRAME_RELEASE( idx->bytes );
David Turner19ed8af2000-12-08 02:42:29 +00001168
David Turnere459d742002-03-22 13:52:37 +00001169 FT_FREE( idx->offsets );
Werner Lembergb3d5e9c2002-07-28 05:05:24 +00001170 FT_MEM_ZERO( idx, sizeof ( *idx ) );
David Turner19ed8af2000-12-08 02:42:29 +00001171 }
1172 }
1173
1174
Werner Lemberg9b067fa2003-12-11 17:55:58 +00001175 /* allocate a table containing pointers to an index's elements */
Werner Lemberg93616ec2001-06-27 19:46:12 +00001176 static FT_Error
David Turnerb9b2cac2002-07-10 16:52:06 +00001177 cff_index_get_pointers( CFF_Index idx,
1178 FT_Byte*** table )
David Turner19ed8af2000-12-08 02:42:29 +00001179 {
Werner Lembergbfb712f2004-03-03 08:21:12 +00001180 FT_Error error = CFF_Err_Ok;
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001181 FT_Memory memory = idx->stream->memory;
Werner Lemberg68e9f922002-09-27 11:09:23 +00001182 FT_ULong n, offset, old_offset;
David Turner19ed8af2000-12-08 02:42:29 +00001183 FT_Byte** t;
1184
1185
1186 *table = 0;
1187
David Turnere459d742002-03-22 13:52:37 +00001188 if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) )
David Turner19ed8af2000-12-08 02:42:29 +00001189 {
1190 old_offset = 1;
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001191 for ( n = 0; n <= idx->count; n++ )
David Turner19ed8af2000-12-08 02:42:29 +00001192 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001193 offset = idx->offsets[n];
David Turner19ed8af2000-12-08 02:42:29 +00001194 if ( !offset )
1195 offset = old_offset;
1196
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001197 t[n] = idx->bytes + offset - 1;
David Turner19ed8af2000-12-08 02:42:29 +00001198
1199 old_offset = offset;
1200 }
1201 *table = t;
1202 }
1203
1204 return error;
1205 }
1206
1207
David Turnerbc82f1b2002-03-01 02:26:22 +00001208 FT_LOCAL_DEF( FT_Error )
David Turnerb9b2cac2002-07-10 16:52:06 +00001209 cff_index_access_element( CFF_Index idx,
1210 FT_UInt element,
1211 FT_Byte** pbytes,
1212 FT_ULong* pbyte_len )
David Turner19ed8af2000-12-08 02:42:29 +00001213 {
Werner Lemberg9b067fa2003-12-11 17:55:58 +00001214 FT_Error error = CFF_Err_Ok;
David Turner19ed8af2000-12-08 02:42:29 +00001215
1216
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001217 if ( idx && idx->count > element )
David Turner19ed8af2000-12-08 02:42:29 +00001218 {
1219 /* compute start and end offsets */
1220 FT_ULong off1, off2 = 0;
1221
1222
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001223 off1 = idx->offsets[element];
David Turner19ed8af2000-12-08 02:42:29 +00001224 if ( off1 )
1225 {
1226 do
1227 {
1228 element++;
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001229 off2 = idx->offsets[element];
David Turner19ed8af2000-12-08 02:42:29 +00001230
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001231 } while ( off2 == 0 && element < idx->count );
David Turner19ed8af2000-12-08 02:42:29 +00001232
1233 if ( !off2 )
1234 off1 = 0;
1235 }
1236
1237 /* access element */
1238 if ( off1 )
1239 {
1240 *pbyte_len = off2 - off1;
1241
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001242 if ( idx->bytes )
David Turner19ed8af2000-12-08 02:42:29 +00001243 {
1244 /* this index was completely loaded in memory, that's easy */
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001245 *pbytes = idx->bytes + off1 - 1;
David Turner19ed8af2000-12-08 02:42:29 +00001246 }
1247 else
1248 {
1249 /* this index is still on disk/file, access it through a frame */
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001250 FT_Stream stream = idx->stream;
David Turner19ed8af2000-12-08 02:42:29 +00001251
1252
David Turner7d3a2642002-03-20 10:49:31 +00001253 if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||
1254 FT_FRAME_EXTRACT( off2 - off1, *pbytes ) )
David Turner19ed8af2000-12-08 02:42:29 +00001255 goto Exit;
1256 }
1257 }
1258 else
1259 {
1260 /* empty index element */
1261 *pbytes = 0;
1262 *pbyte_len = 0;
1263 }
1264 }
1265 else
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +00001266 error = CFF_Err_Invalid_Argument;
David Turner19ed8af2000-12-08 02:42:29 +00001267
1268 Exit:
1269 return error;
1270 }
1271
1272
David Turnerbc82f1b2002-03-01 02:26:22 +00001273 FT_LOCAL_DEF( void )
David Turnerb9b2cac2002-07-10 16:52:06 +00001274 cff_index_forget_element( CFF_Index idx,
1275 FT_Byte** pbytes )
David Turner19ed8af2000-12-08 02:42:29 +00001276 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001277 if ( idx->bytes == 0 )
David Turner19ed8af2000-12-08 02:42:29 +00001278 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001279 FT_Stream stream = idx->stream;
David Turner19ed8af2000-12-08 02:42:29 +00001280
1281
David Turner7d3a2642002-03-20 10:49:31 +00001282 FT_FRAME_RELEASE( *pbytes );
David Turner19ed8af2000-12-08 02:42:29 +00001283 }
1284 }
1285
1286
David Turnerbc82f1b2002-03-01 02:26:22 +00001287 FT_LOCAL_DEF( FT_String* )
David Turnerb9b2cac2002-07-10 16:52:06 +00001288 cff_index_get_name( CFF_Index idx,
1289 FT_UInt element )
David Turner19ed8af2000-12-08 02:42:29 +00001290 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001291 FT_Memory memory = idx->stream->memory;
David Turner19ed8af2000-12-08 02:42:29 +00001292 FT_Byte* bytes;
1293 FT_ULong byte_len;
1294 FT_Error error;
1295 FT_String* name = 0;
1296
1297
David Turnerb9b2cac2002-07-10 16:52:06 +00001298 error = cff_index_access_element( idx, element, &bytes, &byte_len );
David Turner19ed8af2000-12-08 02:42:29 +00001299 if ( error )
1300 goto Exit;
1301
David Turnere459d742002-03-22 13:52:37 +00001302 if ( !FT_ALLOC( name, byte_len + 1 ) )
David Turner19ed8af2000-12-08 02:42:29 +00001303 {
David Turnere459d742002-03-22 13:52:37 +00001304 FT_MEM_COPY( name, bytes, byte_len );
David Turner19ed8af2000-12-08 02:42:29 +00001305 name[byte_len] = 0;
1306 }
David Turnerb9b2cac2002-07-10 16:52:06 +00001307 cff_index_forget_element( idx, &bytes );
David Turner19ed8af2000-12-08 02:42:29 +00001308
1309 Exit:
1310 return name;
1311 }
1312
1313
David Turnerbc82f1b2002-03-01 02:26:22 +00001314 FT_LOCAL_DEF( FT_String* )
David Turnerb72d8a82003-09-29 20:33:37 +00001315 cff_index_get_sid_string( CFF_Index idx,
1316 FT_UInt sid,
David Turner77605952003-10-29 21:43:52 +00001317 FT_Service_PsCMaps psnames )
David Turner19ed8af2000-12-08 02:42:29 +00001318 {
Werner Lemberg9b067fa2003-12-11 17:55:58 +00001319 /* value 0xFFFFU indicates a missing dictionary entry */
1320 if ( sid == 0xFFFFU )
1321 return 0;
1322
David Turner19ed8af2000-12-08 02:42:29 +00001323 /* if it is not a standard string, return it */
1324 if ( sid > 390 )
David Turnerb9b2cac2002-07-10 16:52:06 +00001325 return cff_index_get_name( idx, sid - 391 );
David Turner19ed8af2000-12-08 02:42:29 +00001326
Werner Lemberg9b067fa2003-12-11 17:55:58 +00001327 /* CID-keyed CFF fonts don't have glyph names */
1328 if ( !psnames )
1329 return 0;
1330
David Turner19ed8af2000-12-08 02:42:29 +00001331 /* that's a standard string, fetch a copy from the PSName module */
1332 {
1333 FT_String* name = 0;
David Turnerb72d8a82003-09-29 20:33:37 +00001334 const char* adobe_name = psnames->adobe_std_strings( sid );
David Turner19ed8af2000-12-08 02:42:29 +00001335 FT_UInt len;
1336
1337
1338 if ( adobe_name )
1339 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +00001340 FT_Memory memory = idx->stream->memory;
Werner Lembergb5349a92002-02-19 16:30:15 +00001341 FT_Error error;
David Turner19ed8af2000-12-08 02:42:29 +00001342
1343
David Turnerd15bc0d2002-04-12 09:31:48 +00001344 len = (FT_UInt)ft_strlen( adobe_name );
David Turnere459d742002-03-22 13:52:37 +00001345 if ( !FT_ALLOC( name, len + 1 ) )
David Turner19ed8af2000-12-08 02:42:29 +00001346 {
David Turnere459d742002-03-22 13:52:37 +00001347 FT_MEM_COPY( name, adobe_name, len );
David Turner19ed8af2000-12-08 02:42:29 +00001348 name[len] = 0;
1349 }
Werner Lembergb5349a92002-02-19 16:30:15 +00001350
1351 FT_UNUSED( error );
David Turner19ed8af2000-12-08 02:42:29 +00001352 }
1353
1354 return name;
1355 }
1356 }
1357
1358
1359 /*************************************************************************/
1360 /*************************************************************************/
1361 /*** ***/
1362 /*** FD Select table support ***/
1363 /*** ***/
1364 /*************************************************************************/
1365 /*************************************************************************/
1366
1367
Werner Lemberg93616ec2001-06-27 19:46:12 +00001368 static void
Werner Lemberg3c403e42002-08-06 21:47:40 +00001369 CFF_Done_FD_Select( CFF_FDSelect fdselect,
Werner Lemberg48c984b2002-03-30 16:41:09 +00001370 FT_Stream stream )
David Turner19ed8af2000-12-08 02:42:29 +00001371 {
Werner Lemberg3c403e42002-08-06 21:47:40 +00001372 if ( fdselect->data )
1373 FT_FRAME_RELEASE( fdselect->data );
David Turner19ed8af2000-12-08 02:42:29 +00001374
Werner Lemberg3c403e42002-08-06 21:47:40 +00001375 fdselect->data_size = 0;
1376 fdselect->format = 0;
1377 fdselect->range_count = 0;
David Turner19ed8af2000-12-08 02:42:29 +00001378 }
1379
1380
Werner Lemberg93616ec2001-06-27 19:46:12 +00001381 static FT_Error
Werner Lemberg3c403e42002-08-06 21:47:40 +00001382 CFF_Load_FD_Select( CFF_FDSelect fdselect,
Werner Lemberg48c984b2002-03-30 16:41:09 +00001383 FT_UInt num_glyphs,
1384 FT_Stream stream,
1385 FT_ULong offset )
David Turner19ed8af2000-12-08 02:42:29 +00001386 {
Werner Lembergcc069be2000-12-08 16:17:16 +00001387 FT_Error error;
1388 FT_Byte format;
1389 FT_UInt num_ranges;
David Turner19ed8af2000-12-08 02:42:29 +00001390
1391
1392 /* read format */
David Turnera890c292002-03-22 12:55:23 +00001393 if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) )
David Turner19ed8af2000-12-08 02:42:29 +00001394 goto Exit;
1395
Werner Lemberg3c403e42002-08-06 21:47:40 +00001396 fdselect->format = format;
1397 fdselect->cache_count = 0; /* clear cache */
David Turner19ed8af2000-12-08 02:42:29 +00001398
1399 switch ( format )
1400 {
1401 case 0: /* format 0, that's simple */
Werner Lemberg3c403e42002-08-06 21:47:40 +00001402 fdselect->data_size = num_glyphs;
David Turner19ed8af2000-12-08 02:42:29 +00001403 goto Load_Data;
1404
1405 case 3: /* format 3, a tad more complex */
David Turnera890c292002-03-22 12:55:23 +00001406 if ( FT_READ_USHORT( num_ranges ) )
David Turner19ed8af2000-12-08 02:42:29 +00001407 goto Exit;
1408
Werner Lemberg3c403e42002-08-06 21:47:40 +00001409 fdselect->data_size = num_ranges * 3 + 2;
David Turner19ed8af2000-12-08 02:42:29 +00001410
1411 Load_Data:
Werner Lemberg3c403e42002-08-06 21:47:40 +00001412 if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) )
David Turner19ed8af2000-12-08 02:42:29 +00001413 goto Exit;
1414 break;
1415
1416 default: /* hmm... that's wrong */
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +00001417 error = CFF_Err_Invalid_File_Format;
David Turner19ed8af2000-12-08 02:42:29 +00001418 }
1419
1420 Exit:
1421 return error;
1422 }
1423
1424
David Turnerbc82f1b2002-03-01 02:26:22 +00001425 FT_LOCAL_DEF( FT_Byte )
Werner Lemberg3c403e42002-08-06 21:47:40 +00001426 cff_fd_select_get( CFF_FDSelect fdselect,
David Turnerb9b2cac2002-07-10 16:52:06 +00001427 FT_UInt glyph_index )
David Turner19ed8af2000-12-08 02:42:29 +00001428 {
1429 FT_Byte fd = 0;
1430
1431
Werner Lemberg3c403e42002-08-06 21:47:40 +00001432 switch ( fdselect->format )
David Turner19ed8af2000-12-08 02:42:29 +00001433 {
1434 case 0:
Werner Lemberg3c403e42002-08-06 21:47:40 +00001435 fd = fdselect->data[glyph_index];
David Turner19ed8af2000-12-08 02:42:29 +00001436 break;
1437
1438 case 3:
1439 /* first, compare to cache */
Werner Lemberg3c403e42002-08-06 21:47:40 +00001440 if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
1441 fdselect->cache_count )
David Turner19ed8af2000-12-08 02:42:29 +00001442 {
Werner Lemberg3c403e42002-08-06 21:47:40 +00001443 fd = fdselect->cache_fd;
David Turner19ed8af2000-12-08 02:42:29 +00001444 break;
1445 }
1446
1447 /* then, lookup the ranges array */
1448 {
Werner Lemberg3c403e42002-08-06 21:47:40 +00001449 FT_Byte* p = fdselect->data;
1450 FT_Byte* p_limit = p + fdselect->data_size;
David Turner19ed8af2000-12-08 02:42:29 +00001451 FT_Byte fd2;
1452 FT_UInt first, limit;
1453
1454
David Turnera890c292002-03-22 12:55:23 +00001455 first = FT_NEXT_USHORT( p );
David Turner19ed8af2000-12-08 02:42:29 +00001456 do
1457 {
1458 if ( glyph_index < first )
1459 break;
1460
1461 fd2 = *p++;
David Turnera890c292002-03-22 12:55:23 +00001462 limit = FT_NEXT_USHORT( p );
David Turner19ed8af2000-12-08 02:42:29 +00001463
1464 if ( glyph_index < limit )
1465 {
1466 fd = fd2;
1467
1468 /* update cache */
Werner Lemberg3c403e42002-08-06 21:47:40 +00001469 fdselect->cache_first = first;
1470 fdselect->cache_count = limit-first;
1471 fdselect->cache_fd = fd2;
David Turner19ed8af2000-12-08 02:42:29 +00001472 break;
1473 }
1474 first = limit;
1475
1476 } while ( p < p_limit );
1477 }
1478 break;
1479
1480 default:
1481 ;
1482 }
1483
1484 return fd;
1485 }
1486
1487
1488 /*************************************************************************/
1489 /*************************************************************************/
1490 /*** ***/
1491 /*** CFF font support ***/
1492 /*** ***/
1493 /*************************************************************************/
1494 /*************************************************************************/
1495
Werner Lemberg93616ec2001-06-27 19:46:12 +00001496 static void
David Turnerb9b2cac2002-07-10 16:52:06 +00001497 cff_charset_done( CFF_Charset charset,
Werner Lemberg48c984b2002-03-30 16:41:09 +00001498 FT_Stream stream )
David Turner19ed8af2000-12-08 02:42:29 +00001499 {
1500 FT_Memory memory = stream->memory;
1501
Werner Lemberg6b766632000-12-30 22:14:58 +00001502
David Turnere459d742002-03-22 13:52:37 +00001503 FT_FREE( charset->sids );
Werner Lemberga9cd8562003-12-18 08:18:37 +00001504 FT_FREE( charset->cids );
David Turner19ed8af2000-12-08 02:42:29 +00001505 charset->format = 0;
1506 charset->offset = 0;
David Turner19ed8af2000-12-08 02:42:29 +00001507 }
1508
Werner Lemberg6b766632000-12-30 22:14:58 +00001509
Werner Lemberg93616ec2001-06-27 19:46:12 +00001510 static FT_Error
David Turnerb9b2cac2002-07-10 16:52:06 +00001511 cff_charset_load( CFF_Charset charset,
David Turner2bf2b9c2002-03-20 09:44:20 +00001512 FT_UInt num_glyphs,
1513 FT_Stream stream,
1514 FT_ULong base_offset,
Werner Lembergb36d4a52003-12-12 15:38:39 +00001515 FT_ULong offset,
1516 FT_Bool invert )
David Turner19ed8af2000-12-08 02:42:29 +00001517 {
Werner Lembergf35ff802003-06-02 21:58:05 +00001518 FT_Memory memory = stream->memory;
Werner Lembergbfb712f2004-03-03 08:21:12 +00001519 FT_Error error = CFF_Err_Ok;
Werner Lemberg6b766632000-12-30 22:14:58 +00001520 FT_UShort glyph_sid;
1521
Werner Lembergcc069be2000-12-08 16:17:16 +00001522
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001523 /* If the the offset is greater than 2, we have to parse the */
1524 /* charset table. */
David Turner19ed8af2000-12-08 02:42:29 +00001525 if ( offset > 2 )
1526 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001527 FT_UInt j;
David Turner19ed8af2000-12-08 02:42:29 +00001528
Werner Lemberg6b766632000-12-30 22:14:58 +00001529
David Turnerb9b2cac2002-07-10 16:52:06 +00001530 charset->offset = base_offset + offset;
1531
1532 /* Get the format of the table. */
1533 if ( FT_STREAM_SEEK( charset->offset ) ||
1534 FT_READ_BYTE( charset->format ) )
1535 goto Exit;
1536
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001537 /* Allocate memory for sids. */
David Turnere459d742002-03-22 13:52:37 +00001538 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
David Turner19ed8af2000-12-08 02:42:29 +00001539 goto Exit;
1540
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001541 /* assign the .notdef glyph */
1542 charset->sids[0] = 0;
1543
Werner Lembergcc069be2000-12-08 16:17:16 +00001544 switch ( charset->format )
David Turner19ed8af2000-12-08 02:42:29 +00001545 {
Werner Lembergcc069be2000-12-08 16:17:16 +00001546 case 0:
David Turnerb9b2cac2002-07-10 16:52:06 +00001547 if ( num_glyphs > 0 )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001548 {
Werner Lemberg7f74a522002-07-26 09:09:10 +00001549 if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001550 goto Exit;
David Turner4bdf4352003-01-30 23:24:18 +00001551
David Turnerb9b2cac2002-07-10 16:52:06 +00001552 for ( j = 1; j < num_glyphs; j++ )
1553 charset->sids[j] = FT_GET_USHORT();
David Turner4bdf4352003-01-30 23:24:18 +00001554
David Turnerb9b2cac2002-07-10 16:52:06 +00001555 FT_FRAME_EXIT();
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001556 }
Werner Lembergcc069be2000-12-08 16:17:16 +00001557 break;
1558
1559 case 1:
Werner Lembergcc069be2000-12-08 16:17:16 +00001560 case 2:
1561 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001562 FT_UInt nleft;
1563 FT_UInt i;
Werner Lembergcc069be2000-12-08 16:17:16 +00001564
Werner Lemberg6b766632000-12-30 22:14:58 +00001565
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001566 j = 1;
Werner Lembergcc069be2000-12-08 16:17:16 +00001567
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001568 while ( j < num_glyphs )
David Turner19ed8af2000-12-08 02:42:29 +00001569 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001570 /* Read the first glyph sid of the range. */
David Turnera890c292002-03-22 12:55:23 +00001571 if ( FT_READ_USHORT( glyph_sid ) )
Werner Lembergcc069be2000-12-08 16:17:16 +00001572 goto Exit;
David Turner19ed8af2000-12-08 02:42:29 +00001573
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001574 /* Read the number of glyphs in the range. */
1575 if ( charset->format == 2 )
1576 {
David Turnera890c292002-03-22 12:55:23 +00001577 if ( FT_READ_USHORT( nleft ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001578 goto Exit;
1579 }
1580 else
1581 {
David Turnera890c292002-03-22 12:55:23 +00001582 if ( FT_READ_BYTE( nleft ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001583 goto Exit;
1584 }
1585
1586 /* Fill in the range of sids -- `nleft + 1' glyphs. */
David Turnerb9b2cac2002-07-10 16:52:06 +00001587 for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001588 charset->sids[j] = glyph_sid;
David Turner19ed8af2000-12-08 02:42:29 +00001589 }
Werner Lembergcc069be2000-12-08 16:17:16 +00001590 }
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001591 break;
David Turner19ed8af2000-12-08 02:42:29 +00001592
Werner Lembergcc069be2000-12-08 16:17:16 +00001593 default:
David Turnerb9b2cac2002-07-10 16:52:06 +00001594 FT_ERROR(( "cff_charset_load: invalid table format!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001595 error = CFF_Err_Invalid_File_Format;
Werner Lembergcc069be2000-12-08 16:17:16 +00001596 goto Exit;
David Turner19ed8af2000-12-08 02:42:29 +00001597 }
David Turner19ed8af2000-12-08 02:42:29 +00001598 }
1599 else
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001600 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001601 /* Parse default tables corresponding to offset == 0, 1, or 2. */
1602 /* CFF specification intimates the following: */
1603 /* */
1604 /* In order to use a predefined charset, the following must be */
Werner Lemberg6b766632000-12-30 22:14:58 +00001605 /* true: The charset constructed for the glyphs in the font's */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001606 /* charstrings dictionary must match the predefined charset in */
Werner Lemberg2acb9632003-04-23 06:47:12 +00001607 /* the first num_glyphs. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001608
David Turnerb9b2cac2002-07-10 16:52:06 +00001609 charset->offset = offset; /* record charset type */
1610
Werner Lemberg68e9f922002-09-27 11:09:23 +00001611 switch ( (FT_UInt)offset )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001612 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001613 case 0:
David Turnerc2278682002-11-23 15:53:57 +00001614 if ( num_glyphs > 229 )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001615 {
Werner Lembergb36d4a52003-12-12 15:38:39 +00001616 FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
1617 "predefined charset (Adobe ISO-Latin)!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001618 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001619 goto Exit;
1620 }
1621
1622 /* Allocate memory for sids. */
David Turnere459d742002-03-22 13:52:37 +00001623 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001624 goto Exit;
1625
Werner Lemberg6b766632000-12-30 22:14:58 +00001626 /* Copy the predefined charset into the allocated memory. */
David Turner4632fcc2004-01-15 19:07:44 +00001627 FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs );
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001628
1629 break;
1630
1631 case 1:
David Turnerc2278682002-11-23 15:53:57 +00001632 if ( num_glyphs > 166 )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001633 {
David Turnerc2278682002-11-23 15:53:57 +00001634 FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
Werner Lemberg6b766632000-12-30 22:14:58 +00001635 "predefined charset (Adobe Expert)!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001636 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001637 goto Exit;
1638 }
1639
1640 /* Allocate memory for sids. */
David Turnere459d742002-03-22 13:52:37 +00001641 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001642 goto Exit;
1643
1644 /* Copy the predefined charset into the allocated memory. */
David Turner4632fcc2004-01-15 19:07:44 +00001645 FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs );
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001646
1647 break;
1648
1649 case 2:
David Turnerc2278682002-11-23 15:53:57 +00001650 if ( num_glyphs > 87 )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001651 {
David Turnerc2278682002-11-23 15:53:57 +00001652 FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
Werner Lemberg6b766632000-12-30 22:14:58 +00001653 "predefined charset (Adobe Expert Subset)!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001654 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001655 goto Exit;
1656 }
1657
1658 /* Allocate memory for sids. */
David Turnere459d742002-03-22 13:52:37 +00001659 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001660 goto Exit;
1661
1662 /* Copy the predefined charset into the allocated memory. */
David Turner4632fcc2004-01-15 19:07:44 +00001663 FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs );
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001664
1665 break;
1666
1667 default:
Werner Lemberg1429db62001-04-02 23:54:01 +00001668 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001669 goto Exit;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001670 }
1671 }
David Turner19ed8af2000-12-08 02:42:29 +00001672
Werner Lemberga9cd8562003-12-18 08:18:37 +00001673 /* we have to invert the `sids' array for subsetted CID-keyed fonts */
Werner Lembergb36d4a52003-12-12 15:38:39 +00001674 if ( invert )
1675 {
1676 FT_UInt i;
1677 FT_UShort max_cid = 0;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001678
Werner Lembergb36d4a52003-12-12 15:38:39 +00001679
1680 for ( i = 0; i < num_glyphs; i++ )
1681 if ( charset->sids[i] > max_cid )
1682 max_cid = charset->sids[i];
1683 max_cid++;
1684
1685 if ( FT_NEW_ARRAY( charset->cids, max_cid ) )
1686 goto Exit;
1687 FT_MEM_ZERO( charset->cids, sizeof ( FT_UShort ) * max_cid );
1688
1689 for ( i = 0; i < num_glyphs; i++ )
David Turner750fa962005-05-01 10:11:32 +00001690 charset->cids[charset->sids[i]] = (FT_UShort)i;
Werner Lembergb36d4a52003-12-12 15:38:39 +00001691 }
1692
1693 Exit:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001694 /* Clean up if there was an error. */
1695 if ( error )
Werner Lembergb36d4a52003-12-12 15:38:39 +00001696 {
1697 FT_FREE( charset->sids );
1698 FT_FREE( charset->cids );
1699 charset->format = 0;
1700 charset->offset = 0;
1701 charset->sids = 0;
1702 }
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001703
David Turner19ed8af2000-12-08 02:42:29 +00001704 return error;
1705 }
1706
Werner Lemberg6b766632000-12-30 22:14:58 +00001707
David Turnerb9b2cac2002-07-10 16:52:06 +00001708 static void
1709 cff_encoding_done( CFF_Encoding encoding )
1710 {
1711 encoding->format = 0;
1712 encoding->offset = 0;
1713 encoding->count = 0;
1714 }
1715
1716
Werner Lemberg93616ec2001-06-27 19:46:12 +00001717 static FT_Error
David Turnerb9b2cac2002-07-10 16:52:06 +00001718 cff_encoding_load( CFF_Encoding encoding,
David Turnerab4fc4d2002-03-14 08:57:10 +00001719 CFF_Charset charset,
Werner Lemberg48c984b2002-03-30 16:41:09 +00001720 FT_UInt num_glyphs,
1721 FT_Stream stream,
1722 FT_ULong base_offset,
1723 FT_ULong offset )
David Turner19ed8af2000-12-08 02:42:29 +00001724 {
Werner Lembergbfb712f2004-03-03 08:21:12 +00001725 FT_Error error = CFF_Err_Ok;
Werner Lembergf35ff802003-06-02 21:58:05 +00001726 FT_UInt count;
1727 FT_UInt j;
1728 FT_UShort glyph_sid;
1729 FT_UInt glyph_code;
David Turner19ed8af2000-12-08 02:42:29 +00001730
Werner Lemberg6b766632000-12-30 22:14:58 +00001731
1732 /* Check for charset->sids. If we do not have this, we fail. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001733 if ( !charset->sids )
David Turner19ed8af2000-12-08 02:42:29 +00001734 {
Werner Lemberg1429db62001-04-02 23:54:01 +00001735 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001736 goto Exit;
1737 }
David Turner19ed8af2000-12-08 02:42:29 +00001738
Werner Lemberg6b766632000-12-30 22:14:58 +00001739 /* Zero out the code to gid/sid mappings. */
David Turnerb9b2cac2002-07-10 16:52:06 +00001740 for ( j = 0; j < 256; j++ )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001741 {
1742 encoding->sids [j] = 0;
1743 encoding->codes[j] = 0;
1744 }
1745
Werner Lembergf35ff802003-06-02 21:58:05 +00001746 /* Note: The encoding table in a CFF font is indexed by glyph index; */
1747 /* the first encoded glyph index is 1. Hence, we read the character */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001748 /* code (`glyph_code') at index j and make the assignment: */
1749 /* */
1750 /* encoding->codes[glyph_code] = j + 1 */
1751 /* */
1752 /* We also make the assignment: */
1753 /* */
1754 /* encoding->sids[glyph_code] = charset->sids[j + 1] */
1755 /* */
1756 /* This gives us both a code to GID and a code to SID mapping. */
1757
1758 if ( offset > 1 )
1759 {
David Turner19ed8af2000-12-08 02:42:29 +00001760 encoding->offset = base_offset + offset;
1761
1762 /* we need to parse the table to determine its size */
David Turner7d3a2642002-03-20 10:49:31 +00001763 if ( FT_STREAM_SEEK( encoding->offset ) ||
Werner Lemberg48c984b2002-03-30 16:41:09 +00001764 FT_READ_BYTE( encoding->format ) ||
1765 FT_READ_BYTE( count ) )
David Turner19ed8af2000-12-08 02:42:29 +00001766 goto Exit;
1767
Werner Lembergcc069be2000-12-08 16:17:16 +00001768 switch ( encoding->format & 0x7F )
David Turner19ed8af2000-12-08 02:42:29 +00001769 {
Werner Lembergcc069be2000-12-08 16:17:16 +00001770 case 0:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001771 {
David Turnerb9b2cac2002-07-10 16:52:06 +00001772 FT_Byte* p;
David Turner4bdf4352003-01-30 23:24:18 +00001773
Werner Lemberg2acb9632003-04-23 06:47:12 +00001774
1775 /* By convention, GID 0 is always ".notdef" and is never */
1776 /* coded in the font. Hence, the number of codes found */
1777 /* in the table is `count+1'. */
David Turner9967dce2002-11-23 16:41:23 +00001778 /* */
1779 encoding->count = count + 1;
Werner Lemberg7f74a522002-07-26 09:09:10 +00001780
David Turnerb9b2cac2002-07-10 16:52:06 +00001781 if ( FT_FRAME_ENTER( count ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001782 goto Exit;
1783
Werner Lemberg7f74a522002-07-26 09:09:10 +00001784 p = (FT_Byte*)stream->cursor;
David Turner4bdf4352003-01-30 23:24:18 +00001785
David Turnerb9b2cac2002-07-10 16:52:06 +00001786 for ( j = 1; j <= count; j++ )
1787 {
1788 glyph_code = *p++;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001789
David Turnerb9b2cac2002-07-10 16:52:06 +00001790 /* Make sure j is not too big. */
David Turner9967dce2002-11-23 16:41:23 +00001791 if ( j < num_glyphs )
David Turnerb9b2cac2002-07-10 16:52:06 +00001792 {
1793 /* Assign code to GID mapping. */
1794 encoding->codes[glyph_code] = (FT_UShort)j;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001795
David Turnerb9b2cac2002-07-10 16:52:06 +00001796 /* Assign code to SID mapping. */
1797 encoding->sids[glyph_code] = charset->sids[j];
1798 }
1799 }
David Turner4bdf4352003-01-30 23:24:18 +00001800
David Turnerb9b2cac2002-07-10 16:52:06 +00001801 FT_FRAME_EXIT();
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001802 }
Werner Lembergcc069be2000-12-08 16:17:16 +00001803 break;
David Turner19ed8af2000-12-08 02:42:29 +00001804
Werner Lembergcc069be2000-12-08 16:17:16 +00001805 case 1:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001806 {
Werner Lembergdeb55102003-06-20 07:50:13 +00001807 FT_UInt nleft;
Werner Lemberg7f74a522002-07-26 09:09:10 +00001808 FT_UInt i = 1;
1809 FT_UInt k;
David Turner19ed8af2000-12-08 02:42:29 +00001810
Werner Lemberg6b766632000-12-30 22:14:58 +00001811
David Turner9967dce2002-11-23 16:41:23 +00001812 encoding->count = 0;
1813
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001814 /* Parse the Format1 ranges. */
1815 for ( j = 0; j < count; j++, i += nleft )
1816 {
Werner Lemberg6b766632000-12-30 22:14:58 +00001817 /* Read the first glyph code of the range. */
David Turnera890c292002-03-22 12:55:23 +00001818 if ( FT_READ_BYTE( glyph_code ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001819 goto Exit;
1820
Werner Lemberg6b766632000-12-30 22:14:58 +00001821 /* Read the number of codes in the range. */
David Turnera890c292002-03-22 12:55:23 +00001822 if ( FT_READ_BYTE( nleft ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001823 goto Exit;
1824
1825 /* Increment nleft, so we read `nleft + 1' codes/sids. */
1826 nleft++;
David Turner4bdf4352003-01-30 23:24:18 +00001827
David Turner9967dce2002-11-23 16:41:23 +00001828 /* compute max number of character codes */
David Turner4bdf4352003-01-30 23:24:18 +00001829 if ( (FT_UInt)nleft > encoding->count )
David Turner9967dce2002-11-23 16:41:23 +00001830 encoding->count = nleft;
David Turner4bdf4352003-01-30 23:24:18 +00001831
Werner Lemberg6b766632000-12-30 22:14:58 +00001832 /* Fill in the range of codes/sids. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001833 for ( k = i; k < nleft + i; k++, glyph_code++ )
1834 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001835 /* Make sure k is not too big. */
David Turnerb9b2cac2002-07-10 16:52:06 +00001836 if ( k < num_glyphs && glyph_code < 256 )
1837 {
1838 /* Assign code to GID mapping. */
1839 encoding->codes[glyph_code] = (FT_UShort)k;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001840
David Turnerb9b2cac2002-07-10 16:52:06 +00001841 /* Assign code to SID mapping. */
1842 encoding->sids[glyph_code] = charset->sids[k];
1843 }
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001844 }
1845 }
David Turner4bdf4352003-01-30 23:24:18 +00001846
Werner Lemberg2acb9632003-04-23 06:47:12 +00001847 /* simple check; one never knows what can be found in a font */
David Turner9967dce2002-11-23 16:41:23 +00001848 if ( encoding->count > 256 )
1849 encoding->count = 256;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001850 }
Werner Lembergcc069be2000-12-08 16:17:16 +00001851 break;
David Turner19ed8af2000-12-08 02:42:29 +00001852
Werner Lembergcc069be2000-12-08 16:17:16 +00001853 default:
David Turnerb9b2cac2002-07-10 16:52:06 +00001854 FT_ERROR(( "cff_encoding_load: invalid table format!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001855 error = CFF_Err_Invalid_File_Format;
Werner Lembergcc069be2000-12-08 16:17:16 +00001856 goto Exit;
David Turner19ed8af2000-12-08 02:42:29 +00001857 }
1858
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001859 /* Parse supplemental encodings, if any. */
Werner Lembergcc069be2000-12-08 16:17:16 +00001860 if ( encoding->format & 0x80 )
David Turner19ed8af2000-12-08 02:42:29 +00001861 {
David Turnerb9b2cac2002-07-10 16:52:06 +00001862 FT_UInt gindex;
David Turner19ed8af2000-12-08 02:42:29 +00001863
Werner Lemberg6b766632000-12-30 22:14:58 +00001864
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001865 /* count supplements */
David Turnera890c292002-03-22 12:55:23 +00001866 if ( FT_READ_BYTE( count ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001867 goto Exit;
1868
1869 for ( j = 0; j < count; j++ )
1870 {
Werner Lemberg6b766632000-12-30 22:14:58 +00001871 /* Read supplemental glyph code. */
David Turnera890c292002-03-22 12:55:23 +00001872 if ( FT_READ_BYTE( glyph_code ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001873 goto Exit;
1874
Werner Lemberg6b766632000-12-30 22:14:58 +00001875 /* Read the SID associated with this glyph code. */
David Turnera890c292002-03-22 12:55:23 +00001876 if ( FT_READ_USHORT( glyph_sid ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001877 goto Exit;
1878
Werner Lemberg6b766632000-12-30 22:14:58 +00001879 /* Assign code to SID mapping. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001880 encoding->sids[glyph_code] = glyph_sid;
1881
Werner Lembergf35ff802003-06-02 21:58:05 +00001882 /* First, look up GID which has been assigned to */
1883 /* SID glyph_sid. */
David Turnerb9b2cac2002-07-10 16:52:06 +00001884 for ( gindex = 0; gindex < num_glyphs; gindex++ )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001885 {
David Turnerb9b2cac2002-07-10 16:52:06 +00001886 if ( charset->sids[gindex] == glyph_sid )
1887 {
Werner Lembergf35ff802003-06-02 21:58:05 +00001888 encoding->codes[glyph_code] = (FT_UShort)gindex;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001889 break;
David Turnerb9b2cac2002-07-10 16:52:06 +00001890 }
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001891 }
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001892 }
1893 }
David Turner19ed8af2000-12-08 02:42:29 +00001894 }
1895 else
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001896 {
1897 FT_UInt i;
1898
Werner Lemberg6b766632000-12-30 22:14:58 +00001899
Werner Lembergf35ff802003-06-02 21:58:05 +00001900 /* We take into account the fact a CFF font can use a predefined */
1901 /* encoding without containing all of the glyphs encoded by this */
1902 /* encoding (see the note at the end of section 12 in the CFF */
1903 /* specification). */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001904
Werner Lemberg68e9f922002-09-27 11:09:23 +00001905 switch ( (FT_UInt)offset )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001906 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001907 case 0:
Werner Lemberg6b766632000-12-30 22:14:58 +00001908 /* First, copy the code to SID mapping. */
David Turner4632fcc2004-01-15 19:07:44 +00001909 FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 );
David Turnerb9b2cac2002-07-10 16:52:06 +00001910 goto Populate;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001911
1912 case 1:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001913 /* First, copy the code to SID mapping. */
David Turner4632fcc2004-01-15 19:07:44 +00001914 FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 );
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001915
David Turnerb9b2cac2002-07-10 16:52:06 +00001916 Populate:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001917 /* Construct code to GID mapping from code to SID mapping */
1918 /* and charset. */
David Turner4bdf4352003-01-30 23:24:18 +00001919
David Turner9967dce2002-11-23 16:41:23 +00001920 encoding->count = 0;
1921
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001922 for ( j = 0; j < 256; j++ )
1923 {
1924 /* If j is encoded, find the GID for it. */
1925 if ( encoding->sids[j] )
1926 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001927 for ( i = 1; i < num_glyphs; i++ )
1928 /* We matched, so break. */
1929 if ( charset->sids[i] == encoding->sids[j] )
1930 break;
1931
1932 /* i will be equal to num_glyphs if we exited the above */
1933 /* loop without a match. In this case, we also have to */
1934 /* fix the code to SID mapping. */
1935 if ( i == num_glyphs )
1936 {
1937 encoding->codes[j] = 0;
1938 encoding->sids [j] = 0;
1939 }
1940 else
David Turner9967dce2002-11-23 16:41:23 +00001941 {
David Turner8edbcab2001-06-19 08:28:24 +00001942 encoding->codes[j] = (FT_UShort)i;
David Turner4bdf4352003-01-30 23:24:18 +00001943
David Turner9967dce2002-11-23 16:41:23 +00001944 /* update encoding count */
Werner Lemberg2acb9632003-04-23 06:47:12 +00001945 if ( encoding->count < j + 1 )
1946 encoding->count = j + 1;
David Turner9967dce2002-11-23 16:41:23 +00001947 }
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001948 }
1949 }
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001950 break;
1951
1952 default:
David Turnerb9b2cac2002-07-10 16:52:06 +00001953 FT_ERROR(( "cff_encoding_load: invalid table format!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001954 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001955 goto Exit;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001956 }
1957 }
David Turner19ed8af2000-12-08 02:42:29 +00001958
1959 Exit:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001960
1961 /* Clean up if there was an error. */
David Turner19ed8af2000-12-08 02:42:29 +00001962 return error;
1963 }
1964
1965
Werner Lemberg93616ec2001-06-27 19:46:12 +00001966 static FT_Error
David Turnerb9b2cac2002-07-10 16:52:06 +00001967 cff_subfont_load( CFF_SubFont font,
Werner Lemberg48c984b2002-03-30 16:41:09 +00001968 CFF_Index idx,
1969 FT_UInt font_index,
1970 FT_Stream stream,
1971 FT_ULong base_offset )
David Turner19ed8af2000-12-08 02:42:29 +00001972 {
Werner Lemberg48c984b2002-03-30 16:41:09 +00001973 FT_Error error;
1974 CFF_ParserRec parser;
Werner Lemberg658f2632004-01-24 15:06:57 +00001975 FT_Byte* dict = NULL;
Werner Lemberg48c984b2002-03-30 16:41:09 +00001976 FT_ULong dict_len;
David Turnerab4fc4d2002-03-14 08:57:10 +00001977 CFF_FontRecDict top = &font->font_dict;
Werner Lemberg48c984b2002-03-30 16:41:09 +00001978 CFF_Private priv = &font->private_dict;
David Turner19ed8af2000-12-08 02:42:29 +00001979
1980
David Turnerb9b2cac2002-07-10 16:52:06 +00001981 cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict );
David Turner19ed8af2000-12-08 02:42:29 +00001982
1983 /* set defaults */
Werner Lembergb3d5e9c2002-07-28 05:05:24 +00001984 FT_MEM_ZERO( top, sizeof ( *top ) );
David Turner19ed8af2000-12-08 02:42:29 +00001985
Werner Lemberg65ba7242003-05-30 09:12:50 +00001986 top->underline_position = -100L << 16;
1987 top->underline_thickness = 50L << 16;
David Turner19ed8af2000-12-08 02:42:29 +00001988 top->charstring_type = 2;
1989 top->font_matrix.xx = 0x10000L;
1990 top->font_matrix.yy = 0x10000L;
1991 top->cid_count = 8720;
1992
Werner Lemberg9b067fa2003-12-11 17:55:58 +00001993 /* we use the implementation specific SID value 0xFFFF to indicate */
1994 /* missing entries */
1995 top->version = 0xFFFFU;
1996 top->notice = 0xFFFFU;
1997 top->copyright = 0xFFFFU;
1998 top->full_name = 0xFFFFU;
1999 top->family_name = 0xFFFFU;
2000 top->weight = 0xFFFFU;
2001 top->embedded_postscript = 0xFFFFU;
2002
2003 top->cid_registry = 0xFFFFU;
2004 top->cid_ordering = 0xFFFFU;
2005 top->cid_font_name = 0xFFFFU;
2006
David Turnerb9b2cac2002-07-10 16:52:06 +00002007 error = cff_index_access_element( idx, font_index, &dict, &dict_len ) ||
2008 cff_parser_run( &parser, dict, dict + dict_len );
David Turner19ed8af2000-12-08 02:42:29 +00002009
David Turnerb9b2cac2002-07-10 16:52:06 +00002010 cff_index_forget_element( idx, &dict );
David Turner19ed8af2000-12-08 02:42:29 +00002011
2012 if ( error )
2013 goto Exit;
2014
2015 /* if it is a CID font, we stop there */
Werner Lemberg9b067fa2003-12-11 17:55:58 +00002016 if ( top->cid_registry != 0xFFFFU )
David Turner19ed8af2000-12-08 02:42:29 +00002017 goto Exit;
2018
2019 /* parse the private dictionary, if any */
2020 if ( top->private_offset && top->private_size )
2021 {
2022 /* set defaults */
Werner Lembergb3d5e9c2002-07-28 05:05:24 +00002023 FT_MEM_ZERO( priv, sizeof ( *priv ) );
David Turner19ed8af2000-12-08 02:42:29 +00002024
2025 priv->blue_shift = 7;
2026 priv->blue_fuzz = 1;
2027 priv->lenIV = -1;
Werner Lembergbf7c8322003-06-06 05:07:53 +00002028 priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
2029 priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
David Turner19ed8af2000-12-08 02:42:29 +00002030
David Turnerb9b2cac2002-07-10 16:52:06 +00002031 cff_parser_init( &parser, CFF_CODE_PRIVATE, priv );
David Turner19ed8af2000-12-08 02:42:29 +00002032
David Turner7d3a2642002-03-20 10:49:31 +00002033 if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
Werner Lemberg48c984b2002-03-30 16:41:09 +00002034 FT_FRAME_ENTER( font->font_dict.private_size ) )
David Turner19ed8af2000-12-08 02:42:29 +00002035 goto Exit;
2036
David Turnerb9b2cac2002-07-10 16:52:06 +00002037 error = cff_parser_run( &parser,
Werner Lemberg7f74a522002-07-26 09:09:10 +00002038 (FT_Byte*)stream->cursor,
2039 (FT_Byte*)stream->limit );
David Turner7d3a2642002-03-20 10:49:31 +00002040 FT_FRAME_EXIT();
David Turner19ed8af2000-12-08 02:42:29 +00002041 if ( error )
2042 goto Exit;
2043 }
2044
2045 /* read the local subrs, if any */
2046 if ( priv->local_subrs_offset )
2047 {
David Turner7d3a2642002-03-20 10:49:31 +00002048 if ( FT_STREAM_SEEK( base_offset + top->private_offset +
Werner Lemberg48c984b2002-03-30 16:41:09 +00002049 priv->local_subrs_offset ) )
David Turner19ed8af2000-12-08 02:42:29 +00002050 goto Exit;
2051
2052 error = cff_new_index( &font->local_subrs_index, stream, 1 );
2053 if ( error )
2054 goto Exit;
2055
2056 font->num_local_subrs = font->local_subrs_index.count;
David Turnerb9b2cac2002-07-10 16:52:06 +00002057 error = cff_index_get_pointers( &font->local_subrs_index,
Werner Lemberg7f74a522002-07-26 09:09:10 +00002058 &font->local_subrs );
Werner Lembergcc069be2000-12-08 16:17:16 +00002059 if ( error )
David Turner19ed8af2000-12-08 02:42:29 +00002060 goto Exit;
2061 }
2062
2063 Exit:
2064 return error;
2065 }
2066
2067
Werner Lemberg93616ec2001-06-27 19:46:12 +00002068 static void
David Turnerb9b2cac2002-07-10 16:52:06 +00002069 cff_subfont_done( FT_Memory memory,
David Turnerab4fc4d2002-03-14 08:57:10 +00002070 CFF_SubFont subfont )
David Turner19ed8af2000-12-08 02:42:29 +00002071 {
2072 if ( subfont )
2073 {
2074 cff_done_index( &subfont->local_subrs_index );
David Turnere459d742002-03-22 13:52:37 +00002075 FT_FREE( subfont->local_subrs );
David Turner19ed8af2000-12-08 02:42:29 +00002076 }
2077 }
2078
2079
David Turnerbc82f1b2002-03-01 02:26:22 +00002080 FT_LOCAL_DEF( FT_Error )
David Turnerb9b2cac2002-07-10 16:52:06 +00002081 cff_font_load( FT_Stream stream,
Werner Lemberg93616ec2001-06-27 19:46:12 +00002082 FT_Int face_index,
Graham Asher9eefed12002-08-23 10:08:38 +00002083 CFF_Font font )
David Turner19ed8af2000-12-08 02:42:29 +00002084 {
2085 static const FT_Frame_Field cff_header_fields[] =
2086 {
2087#undef FT_STRUCTURE
David Turnerab4fc4d2002-03-14 08:57:10 +00002088#define FT_STRUCTURE CFF_FontRec
David Turner19ed8af2000-12-08 02:42:29 +00002089
2090 FT_FRAME_START( 4 ),
2091 FT_FRAME_BYTE( version_major ),
2092 FT_FRAME_BYTE( version_minor ),
2093 FT_FRAME_BYTE( header_size ),
2094 FT_FRAME_BYTE( absolute_offsize ),
2095 FT_FRAME_END
2096 };
2097
Werner Lemberg48c984b2002-03-30 16:41:09 +00002098 FT_Error error;
2099 FT_Memory memory = stream->memory;
2100 FT_ULong base_offset;
David Turnerab4fc4d2002-03-14 08:57:10 +00002101 CFF_FontRecDict dict;
David Turner19ed8af2000-12-08 02:42:29 +00002102
Werner Lemberg0f2a4152004-12-28 07:31:35 +00002103
David Turnerb9b2cac2002-07-10 16:52:06 +00002104 FT_ZERO( font );
David Turner19ed8af2000-12-08 02:42:29 +00002105
2106 font->stream = stream;
2107 font->memory = memory;
2108 dict = &font->top_font.font_dict;
David Turner7d3a2642002-03-20 10:49:31 +00002109 base_offset = FT_STREAM_POS();
David Turner19ed8af2000-12-08 02:42:29 +00002110
2111 /* read CFF font header */
David Turner7d3a2642002-03-20 10:49:31 +00002112 if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
David Turner19ed8af2000-12-08 02:42:29 +00002113 goto Exit;
2114
2115 /* check format */
2116 if ( font->version_major != 1 ||
2117 font->header_size < 4 ||
2118 font->absolute_offsize > 4 )
2119 {
2120 FT_TRACE2(( "[not a CFF font header!]\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00002121 error = CFF_Err_Unknown_File_Format;
David Turner19ed8af2000-12-08 02:42:29 +00002122 goto Exit;
2123 }
2124
2125 /* skip the rest of the header */
David Turner7d3a2642002-03-20 10:49:31 +00002126 if ( FT_STREAM_SKIP( font->header_size - 4 ) )
David Turner19ed8af2000-12-08 02:42:29 +00002127 goto Exit;
2128
2129 /* read the name, top dict, string and global subrs index */
Werner Lembergcc069be2000-12-08 16:17:16 +00002130 if ( FT_SET_ERROR( cff_new_index( &font->name_index, stream, 0 )) ||
2131 FT_SET_ERROR( cff_new_index( &font->font_dict_index, stream, 0 )) ||
2132 FT_SET_ERROR( cff_new_index( &font->string_index, stream, 0 )) ||
2133 FT_SET_ERROR( cff_new_index( &font->global_subrs_index, stream, 1 )) )
David Turner19ed8af2000-12-08 02:42:29 +00002134 goto Exit;
2135
2136 /* well, we don't really forget the `disabled' fonts... */
2137 font->num_faces = font->name_index.count;
2138 if ( face_index >= (FT_Int)font->num_faces )
2139 {
David Turnerb9b2cac2002-07-10 16:52:06 +00002140 FT_ERROR(( "cff_font_load: incorrect face index = %d\n",
David Turner19ed8af2000-12-08 02:42:29 +00002141 face_index ));
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +00002142 error = CFF_Err_Invalid_Argument;
David Turner19ed8af2000-12-08 02:42:29 +00002143 }
2144
2145 /* in case of a font format check, simply exit now */
2146 if ( face_index < 0 )
2147 goto Exit;
2148
2149 /* now, parse the top-level font dictionary */
David Turnerb9b2cac2002-07-10 16:52:06 +00002150 error = cff_subfont_load( &font->top_font,
David Turner19ed8af2000-12-08 02:42:29 +00002151 &font->font_dict_index,
2152 face_index,
2153 stream,
2154 base_offset );
2155 if ( error )
2156 goto Exit;
2157
Werner Lembergedeed6b2004-01-15 16:12:36 +00002158 if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
2159 goto Exit;
2160
2161 error = cff_new_index( &font->charstrings_index, stream, 0 );
2162 if ( error )
2163 goto Exit;
2164
David Turner19ed8af2000-12-08 02:42:29 +00002165 /* now, check for a CID font */
Werner Lemberg9b067fa2003-12-11 17:55:58 +00002166 if ( dict->cid_registry != 0xFFFFU )
David Turner19ed8af2000-12-08 02:42:29 +00002167 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +00002168 CFF_IndexRec fd_index;
Werner Lemberg48c984b2002-03-30 16:41:09 +00002169 CFF_SubFont sub;
Werner Lemberg0d9165e2002-03-07 21:59:59 +00002170 FT_UInt idx;
David Turner19ed8af2000-12-08 02:42:29 +00002171
2172
2173 /* this is a CID-keyed font, we must now allocate a table of */
2174 /* sub-fonts, then load each of them separately */
David Turner7d3a2642002-03-20 10:49:31 +00002175 if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
David Turner19ed8af2000-12-08 02:42:29 +00002176 goto Exit;
2177
2178 error = cff_new_index( &fd_index, stream, 0 );
2179 if ( error )
2180 goto Exit;
2181
2182 if ( fd_index.count > CFF_MAX_CID_FONTS )
2183 {
David Turnerb9b2cac2002-07-10 16:52:06 +00002184 FT_ERROR(( "cff_font_load: FD array too large in CID font\n" ));
David Turner19ed8af2000-12-08 02:42:29 +00002185 goto Fail_CID;
2186 }
2187
2188 /* allocate & read each font dict independently */
2189 font->num_subfonts = fd_index.count;
David Turnere459d742002-03-22 13:52:37 +00002190 if ( FT_NEW_ARRAY( sub, fd_index.count ) )
David Turner19ed8af2000-12-08 02:42:29 +00002191 goto Fail_CID;
2192
Werner Lemberga10a9f92005-12-04 12:48:57 +00002193 /* set up pointer table */
Werner Lemberg0d9165e2002-03-07 21:59:59 +00002194 for ( idx = 0; idx < fd_index.count; idx++ )
2195 font->subfonts[idx] = sub + idx;
David Turner19ed8af2000-12-08 02:42:29 +00002196
Werner Lemberga10a9f92005-12-04 12:48:57 +00002197 /* now load each subfont independently */
Werner Lemberg0d9165e2002-03-07 21:59:59 +00002198 for ( idx = 0; idx < fd_index.count; idx++ )
David Turner19ed8af2000-12-08 02:42:29 +00002199 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +00002200 sub = font->subfonts[idx];
David Turnerb9b2cac2002-07-10 16:52:06 +00002201 error = cff_subfont_load( sub, &fd_index, idx,
David Turner19ed8af2000-12-08 02:42:29 +00002202 stream, base_offset );
2203 if ( error )
2204 goto Fail_CID;
2205 }
2206
2207 /* now load the FD Select array */
2208 error = CFF_Load_FD_Select( &font->fd_select,
Werner Lembergedeed6b2004-01-15 16:12:36 +00002209 font->charstrings_index.count,
David Turner19ed8af2000-12-08 02:42:29 +00002210 stream,
2211 base_offset + dict->cid_fd_select_offset );
2212
Werner Lembergcc069be2000-12-08 16:17:16 +00002213 Fail_CID:
David Turner19ed8af2000-12-08 02:42:29 +00002214 cff_done_index( &fd_index );
2215
2216 if ( error )
2217 goto Exit;
2218 }
2219 else
2220 font->num_subfonts = 0;
2221
Graham Asher9eefed12002-08-23 10:08:38 +00002222 /* read the charstrings index now */
2223 if ( dict->charstrings_offset == 0 )
Werner Lembergf25ce9d2002-08-15 23:07:18 +00002224 {
Graham Asher9eefed12002-08-23 10:08:38 +00002225 FT_ERROR(( "cff_font_load: no charstrings offset!\n" ));
2226 error = CFF_Err_Unknown_File_Format;
2227 goto Exit;
Werner Lembergf25ce9d2002-08-15 23:07:18 +00002228 }
David Turner19ed8af2000-12-08 02:42:29 +00002229
2230 /* explicit the global subrs */
2231 font->num_global_subrs = font->global_subrs_index.count;
2232 font->num_glyphs = font->charstrings_index.count;
2233
David Turnerb9b2cac2002-07-10 16:52:06 +00002234 error = cff_index_get_pointers( &font->global_subrs_index,
Werner Lemberg7f74a522002-07-26 09:09:10 +00002235 &font->global_subrs ) ;
David Turner19ed8af2000-12-08 02:42:29 +00002236
2237 if ( error )
2238 goto Exit;
2239
Werner Lemberg9b067fa2003-12-11 17:55:58 +00002240 /* read the Charset and Encoding tables if available */
Graham Asher3fd12f12002-08-15 12:10:48 +00002241 if ( font->num_glyphs > 0 )
2242 {
David Turner750fa962005-05-01 10:11:32 +00002243 FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU );
Werner Lemberga9cd8562003-12-18 08:18:37 +00002244
2245
Graham Asher3fd12f12002-08-15 12:10:48 +00002246 error = cff_charset_load( &font->charset, font->num_glyphs, stream,
Werner Lemberga9cd8562003-12-18 08:18:37 +00002247 base_offset, dict->charset_offset, invert );
Graham Asher3fd12f12002-08-15 12:10:48 +00002248 if ( error )
2249 goto Exit;
Werner Lemberg415235d2001-06-28 17:49:10 +00002250
Werner Lemberg9b067fa2003-12-11 17:55:58 +00002251 /* CID-keyed CFFs don't have an encoding */
2252 if ( dict->cid_registry == 0xFFFFU )
2253 {
2254 error = cff_encoding_load( &font->encoding,
2255 &font->charset,
2256 font->num_glyphs,
2257 stream,
2258 base_offset,
2259 dict->encoding_offset );
2260 if ( error )
2261 goto Exit;
2262 }
Werner Lemberg83da52b2003-12-20 07:30:05 +00002263 else
2264 /* CID-keyed fonts only need CIDs */
2265 FT_FREE( font->charset.sids );
Graham Asher3fd12f12002-08-15 12:10:48 +00002266 }
Werner Lemberg415235d2001-06-28 17:49:10 +00002267
Werner Lemberg9b067fa2003-12-11 17:55:58 +00002268 /* get the font name (/CIDFontName for CID-keyed fonts, */
2269 /* /FontName otherwise) */
David Turnerb9b2cac2002-07-10 16:52:06 +00002270 font->font_name = cff_index_get_name( &font->name_index, face_index );
David Turner19ed8af2000-12-08 02:42:29 +00002271
2272 Exit:
2273 return error;
2274 }
2275
2276
David Turnerbc82f1b2002-03-01 02:26:22 +00002277 FT_LOCAL_DEF( void )
David Turnerb9b2cac2002-07-10 16:52:06 +00002278 cff_font_done( CFF_Font font )
David Turner19ed8af2000-12-08 02:42:29 +00002279 {
2280 FT_Memory memory = font->memory;
Werner Lemberg0d9165e2002-03-07 21:59:59 +00002281 FT_UInt idx;
David Turner19ed8af2000-12-08 02:42:29 +00002282
2283
2284 cff_done_index( &font->global_subrs_index );
2285 cff_done_index( &font->string_index );
2286 cff_done_index( &font->font_dict_index );
2287 cff_done_index( &font->name_index );
2288 cff_done_index( &font->charstrings_index );
2289
Werner Lembergc3b21602001-12-05 01:22:05 +00002290 /* release font dictionaries, but only if working with */
2291 /* a CID keyed CFF font */
Tom Kacvinskydfa45682001-10-21 20:26:59 +00002292 if ( font->num_subfonts > 0 )
2293 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +00002294 for ( idx = 0; idx < font->num_subfonts; idx++ )
David Turnerb9b2cac2002-07-10 16:52:06 +00002295 cff_subfont_done( memory, font->subfonts[idx] );
Tom Kacvinskydfa45682001-10-21 20:26:59 +00002296 }
Tom Kacvinsky98289a22001-10-21 16:29:16 +00002297
David Turnerb9b2cac2002-07-10 16:52:06 +00002298 cff_encoding_done( &font->encoding );
2299 cff_charset_done( &font->charset, font->stream );
David Turner19ed8af2000-12-08 02:42:29 +00002300
David Turnerb9b2cac2002-07-10 16:52:06 +00002301 cff_subfont_done( memory, &font->top_font );
David Turner19ed8af2000-12-08 02:42:29 +00002302
2303 CFF_Done_FD_Select( &font->fd_select, font->stream );
2304
David Turnere459d742002-03-22 13:52:37 +00002305 FT_FREE( font->global_subrs );
2306 FT_FREE( font->font_name );
David Turner19ed8af2000-12-08 02:42:29 +00002307 }
2308
2309
2310/* END */