blob: 9fc6ca52922330e08e466a2c9dd44cde388d5016 [file] [log] [blame]
David Turner19ed8af2000-12-08 02:42:29 +00001/***************************************************************************/
2/* */
3/* cffload.c */
4/* */
5/* OpenType and CFF data/program tables loader (body) */
6/* */
7/* Copyright 1996-2000 by */
8/* 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
23#include FT_INTERNAL_POSTSCRIPT_NAMES_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 Turner19ed8af2000-12-08 02:42:29 +000032 /*************************************************************************/
33 /* */
34 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
35 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
36 /* messages during execution. */
37 /* */
38#undef FT_COMPONENT
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +000039#define FT_COMPONENT trace_cffload
David Turner19ed8af2000-12-08 02:42:29 +000040
Werner Lemberg6b766632000-12-30 22:14:58 +000041
Werner Lemberg6b766632000-12-30 22:14:58 +000042 const FT_UShort cff_isoadobe_charset[229] =
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +000043 {
44 0,
45 1,
46 2,
47 3,
48 4,
49 5,
50 6,
51 7,
52 8,
53 9,
54 10,
55 11,
56 12,
57 13,
58 14,
59 15,
60 16,
61 17,
62 18,
63 19,
64 20,
65 21,
66 22,
67 23,
68 24,
69 25,
70 26,
71 27,
72 28,
73 29,
74 30,
75 31,
76 32,
77 33,
78 34,
79 35,
80 36,
81 37,
82 38,
83 39,
84 40,
85 41,
86 42,
87 43,
88 44,
89 45,
90 46,
91 47,
92 48,
93 49,
94 50,
95 51,
96 52,
97 53,
98 54,
99 55,
100 56,
101 57,
102 58,
103 59,
104 60,
105 61,
106 62,
107 63,
108 64,
109 65,
110 66,
111 67,
112 68,
113 69,
114 70,
115 71,
116 72,
117 73,
118 74,
119 75,
120 76,
121 77,
122 78,
123 79,
124 80,
125 81,
126 82,
127 83,
128 84,
129 85,
130 86,
131 87,
132 88,
133 89,
134 90,
135 91,
136 92,
137 93,
138 94,
139 95,
140 96,
141 97,
142 98,
143 99,
144 100,
145 101,
146 102,
147 103,
148 104,
149 105,
150 106,
151 107,
152 108,
153 109,
154 110,
155 111,
156 112,
157 113,
158 114,
159 115,
160 116,
161 117,
162 118,
163 119,
164 120,
165 121,
166 122,
167 123,
168 124,
169 125,
170 126,
171 127,
172 128,
173 129,
174 130,
175 131,
176 132,
177 133,
178 134,
179 135,
180 136,
181 137,
182 138,
183 139,
184 140,
185 141,
186 142,
187 143,
188 144,
189 145,
190 146,
191 147,
192 148,
193 149,
194 150,
195 151,
196 152,
197 153,
198 154,
199 155,
200 156,
201 157,
202 158,
203 159,
204 160,
205 161,
206 162,
207 163,
208 164,
209 165,
210 166,
211 167,
212 168,
213 169,
214 170,
215 171,
216 172,
217 173,
218 174,
219 175,
220 176,
221 177,
222 178,
223 179,
224 180,
225 181,
226 182,
227 183,
228 184,
229 185,
230 186,
231 187,
232 188,
233 189,
234 190,
235 191,
236 192,
237 193,
238 194,
239 195,
240 196,
241 197,
242 198,
243 199,
244 200,
245 201,
246 202,
247 203,
248 204,
249 205,
250 206,
251 207,
252 208,
253 209,
254 210,
255 211,
256 212,
257 213,
258 214,
259 215,
260 216,
261 217,
262 218,
263 219,
264 220,
265 221,
266 222,
267 223,
268 224,
269 225,
270 226,
271 227,
272 228
273 };
274
Werner Lemberg6b766632000-12-30 22:14:58 +0000275 const FT_UShort cff_expert_charset[166] =
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +0000276 {
277 0,
278 1,
279 229,
280 230,
281 231,
282 232,
283 233,
284 234,
285 235,
286 236,
287 237,
288 238,
289 13,
290 14,
291 15,
292 99,
293 239,
294 240,
295 241,
296 242,
297 243,
298 244,
299 245,
300 246,
301 247,
302 248,
303 27,
304 28,
305 249,
306 250,
307 251,
308 252,
309 253,
310 254,
311 255,
312 256,
313 257,
314 258,
315 259,
316 260,
317 261,
318 262,
319 263,
320 264,
321 265,
322 266,
323 109,
324 110,
325 267,
326 268,
327 269,
328 270,
329 271,
330 272,
331 273,
332 274,
333 275,
334 276,
335 277,
336 278,
337 279,
338 280,
339 281,
340 282,
341 283,
342 284,
343 285,
344 286,
345 287,
346 288,
347 289,
348 290,
349 291,
350 292,
351 293,
352 294,
353 295,
354 296,
355 297,
356 298,
357 299,
358 300,
359 301,
360 302,
361 303,
362 304,
363 305,
364 306,
365 307,
366 308,
367 309,
368 310,
369 311,
370 312,
371 313,
372 314,
373 315,
374 316,
375 317,
376 318,
377 158,
378 155,
379 163,
380 319,
381 320,
382 321,
383 322,
384 323,
385 324,
386 325,
387 326,
388 150,
389 164,
390 169,
391 327,
392 328,
393 329,
394 330,
395 331,
396 332,
397 333,
398 334,
399 335,
400 336,
401 337,
402 338,
403 339,
404 340,
405 341,
406 342,
407 343,
408 344,
409 345,
410 346,
411 347,
412 348,
413 349,
414 350,
415 351,
416 352,
417 353,
418 354,
419 355,
420 356,
421 357,
422 358,
423 359,
424 360,
425 361,
426 362,
427 363,
428 364,
429 365,
430 366,
431 367,
432 368,
433 369,
434 370,
435 371,
436 372,
437 373,
438 374,
439 375,
440 376,
441 377,
442 378
443 };
444
Werner Lemberg6b766632000-12-30 22:14:58 +0000445 const FT_UShort cff_expertsubset_charset[87] =
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +0000446 {
447 0,
448 1,
449 231,
450 232,
451 235,
452 236,
453 237,
454 238,
455 13,
456 14,
457 15,
458 99,
459 239,
460 240,
461 241,
462 242,
463 243,
464 244,
465 245,
466 246,
467 247,
468 248,
469 27,
470 28,
471 249,
472 250,
473 251,
474 253,
475 254,
476 255,
477 256,
478 257,
479 258,
480 259,
481 260,
482 261,
483 262,
484 263,
485 264,
486 265,
487 266,
488 109,
489 110,
490 267,
491 268,
492 269,
493 270,
494 272,
495 300,
496 301,
497 302,
498 305,
499 314,
500 315,
501 158,
502 155,
503 163,
504 320,
505 321,
506 322,
507 323,
508 324,
509 325,
510 326,
511 150,
512 164,
513 169,
514 327,
515 328,
516 329,
517 330,
518 331,
519 332,
520 333,
521 334,
522 335,
523 336,
524 337,
525 338,
526 339,
527 340,
528 341,
529 342,
530 343,
531 344,
532 345,
533 346
534 };
535
Werner Lemberg6b766632000-12-30 22:14:58 +0000536 const FT_UShort cff_standard_encoding[256] =
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +0000537 {
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 0,
562 0,
563 0,
564 0,
565 0,
566 0,
567 0,
568 0,
569 0,
570 1,
571 2,
572 3,
573 4,
574 5,
575 6,
576 7,
577 8,
578 9,
579 10,
580 11,
581 12,
582 13,
583 14,
584 15,
585 16,
586 17,
587 18,
588 19,
589 20,
590 21,
591 22,
592 23,
593 24,
594 25,
595 26,
596 27,
597 28,
598 29,
599 30,
600 31,
601 32,
602 33,
603 34,
604 35,
605 36,
606 37,
607 38,
608 39,
609 40,
610 41,
611 42,
612 43,
613 44,
614 45,
615 46,
616 47,
617 48,
618 49,
619 50,
620 51,
621 52,
622 53,
623 54,
624 55,
625 56,
626 57,
627 58,
628 59,
629 60,
630 61,
631 62,
632 63,
633 64,
634 65,
635 66,
636 67,
637 68,
638 69,
639 70,
640 71,
641 72,
642 73,
643 74,
644 75,
645 76,
646 77,
647 78,
648 79,
649 80,
650 81,
651 82,
652 83,
653 84,
654 85,
655 86,
656 87,
657 88,
658 89,
659 90,
660 91,
661 92,
662 93,
663 94,
664 95,
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 0,
691 0,
692 0,
693 0,
694 0,
695 0,
696 0,
697 0,
698 0,
699 96,
700 97,
701 98,
702 99,
703 100,
704 101,
705 102,
706 103,
707 104,
708 105,
709 106,
710 107,
711 108,
712 109,
713 110,
714 0,
715 111,
716 112,
717 113,
718 114,
719 0,
720 115,
721 116,
722 117,
723 118,
724 119,
725 120,
726 121,
727 122,
728 0,
729 123,
730 0,
731 124,
732 125,
733 126,
734 127,
735 128,
736 129,
737 130,
738 131,
739 0,
740 132,
741 133,
742 0,
743 134,
744 135,
745 136,
746 137,
747 0,
748 0,
749 0,
750 0,
751 0,
752 0,
753 0,
754 0,
755 0,
756 0,
757 0,
758 0,
759 0,
760 0,
761 0,
762 0,
763 138,
764 0,
765 139,
766 0,
767 0,
768 0,
769 0,
770 140,
771 141,
772 142,
773 143,
774 0,
775 0,
776 0,
777 0,
778 0,
779 144,
780 0,
781 0,
782 0,
783 145,
784 0,
785 0,
786 146,
787 147,
788 148,
789 149,
790 0,
791 0,
792 0,
793 0
794 };
795
Werner Lemberg6b766632000-12-30 22:14:58 +0000796 const FT_UShort cff_expert_encoding[256] =
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +0000797 {
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 0,
822 0,
823 0,
824 0,
825 0,
826 0,
827 0,
828 0,
829 0,
830 1,
831 229,
832 230,
833 0,
834 231,
835 232,
836 233,
837 234,
838 235,
839 236,
840 237,
841 238,
842 13,
843 14,
844 15,
845 99,
846 239,
847 240,
848 241,
849 242,
850 243,
851 244,
852 245,
853 246,
854 247,
855 248,
856 27,
857 28,
858 249,
859 250,
860 251,
861 252,
862 0,
863 253,
864 254,
865 255,
866 256,
867 257,
868 0,
869 0,
870 0,
871 258,
872 0,
873 0,
874 259,
875 260,
876 261,
877 262,
878 0,
879 0,
880 263,
881 264,
882 265,
883 0,
884 266,
885 109,
886 110,
887 267,
888 268,
889 269,
890 0,
891 270,
892 271,
893 272,
894 273,
895 274,
896 275,
897 276,
898 277,
899 278,
900 279,
901 280,
902 281,
903 282,
904 283,
905 284,
906 285,
907 286,
908 287,
909 288,
910 289,
911 290,
912 291,
913 292,
914 293,
915 294,
916 295,
917 296,
918 297,
919 298,
920 299,
921 300,
922 301,
923 302,
924 303,
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 0,
951 0,
952 0,
953 0,
954 0,
955 0,
956 0,
957 0,
958 0,
959 304,
960 305,
961 306,
962 0,
963 0,
964 307,
965 308,
966 309,
967 310,
968 311,
969 0,
970 312,
971 0,
972 0,
973 312,
974 0,
975 0,
976 314,
977 315,
978 0,
979 0,
980 316,
981 317,
982 318,
983 0,
984 0,
985 0,
986 158,
987 155,
988 163,
989 319,
990 320,
991 321,
992 322,
993 323,
994 324,
995 325,
996 0,
997 0,
998 326,
999 150,
1000 164,
1001 169,
1002 327,
1003 328,
1004 329,
1005 330,
1006 331,
1007 332,
1008 333,
1009 334,
1010 335,
1011 336,
1012 337,
1013 338,
1014 339,
1015 340,
1016 341,
1017 342,
1018 343,
1019 344,
1020 345,
1021 346,
1022 347,
1023 348,
1024 349,
1025 350,
1026 351,
1027 352,
1028 353,
1029 354,
1030 355,
1031 356,
1032 357,
1033 358,
1034 359,
1035 360,
1036 361,
1037 362,
1038 363,
1039 364,
1040 365,
1041 366,
1042 367,
1043 368,
1044 369,
1045 370,
1046 371,
1047 372,
1048 373,
1049 374,
1050 375,
1051 376,
1052 377,
1053 378
1054 };
1055
David Turner19ed8af2000-12-08 02:42:29 +00001056
1057 /* read a CFF offset from memory */
Werner Lembergcc069be2000-12-08 16:17:16 +00001058 static
1059 FT_ULong cff_get_offset( FT_Byte* p,
1060 FT_Byte off_size )
David Turner19ed8af2000-12-08 02:42:29 +00001061 {
1062 FT_ULong result;
1063
1064
1065 for ( result = 0; off_size > 0; off_size-- )
1066 {
1067 result <<= 8;
1068 result |= *p++;
1069 }
1070
1071 return result;
1072 }
1073
1074
Werner Lembergcc069be2000-12-08 16:17:16 +00001075 static
1076 FT_Error cff_new_index( CFF_Index* index,
1077 FT_Stream stream,
1078 FT_Bool load )
David Turner19ed8af2000-12-08 02:42:29 +00001079 {
Werner Lembergcc069be2000-12-08 16:17:16 +00001080 FT_Error error;
1081 FT_Memory memory = stream->memory;
1082 FT_UShort count;
David Turner19ed8af2000-12-08 02:42:29 +00001083
1084
1085 MEM_Set( index, 0, sizeof ( *index ) );
1086
1087 index->stream = stream;
1088 if ( !READ_UShort( count ) &&
1089 count > 0 )
1090 {
1091 FT_Byte* p;
1092 FT_Byte offsize;
1093 FT_ULong data_size;
1094 FT_ULong* poff;
1095
1096
1097 /* there is at least one element; read the offset size, */
1098 /* then access the offset table to compute the index's total size */
1099 if ( READ_Byte( offsize ) )
1100 goto Exit;
1101
1102 index->stream = stream;
1103 index->count = count;
1104 index->off_size = offsize;
1105 data_size = (FT_ULong)( count + 1 ) * offsize;
1106
1107 if ( ALLOC_ARRAY( index->offsets, count + 1, FT_ULong ) ||
1108 ACCESS_Frame( data_size ) )
1109 goto Exit;
1110
1111 poff = index->offsets;
1112 p = (FT_Byte*)stream->cursor;
1113
1114 for ( ; (FT_Short)count >= 0; count-- )
1115 {
1116 poff[0] = cff_get_offset( p, offsize );
1117 poff++;
1118 p += offsize;
1119 }
1120
1121 FORGET_Frame();
1122
1123 index->data_offset = FILE_Pos();
1124 data_size = poff[-1] - 1;
1125
1126 if ( load )
1127 {
1128 /* load the data */
1129 if ( EXTRACT_Frame( data_size, index->bytes ) )
1130 goto Exit;
1131 }
1132 else
1133 {
1134 /* skip the data */
1135 if ( FILE_Skip( data_size ) )
1136 goto Exit;
1137 }
1138 }
1139
1140 Exit:
1141 if ( error )
1142 FREE( index->offsets );
1143
1144 return error;
1145 }
1146
1147
Werner Lembergcc069be2000-12-08 16:17:16 +00001148 static
1149 void cff_done_index( CFF_Index* index )
David Turner19ed8af2000-12-08 02:42:29 +00001150 {
1151 if ( index->stream )
1152 {
1153 FT_Stream stream = index->stream;
1154 FT_Memory memory = stream->memory;
1155
1156
1157 if ( index->bytes )
1158 RELEASE_Frame( index->bytes );
1159
1160 FREE( index->offsets );
1161 MEM_Set( index, 0, sizeof ( *index ) );
1162 }
1163 }
1164
1165
Werner Lembergcc069be2000-12-08 16:17:16 +00001166 static
1167 FT_Error cff_explicit_index( CFF_Index* index,
1168 FT_Byte*** table )
David Turner19ed8af2000-12-08 02:42:29 +00001169 {
1170 FT_Error error = 0;
1171 FT_Memory memory = index->stream->memory;
1172 FT_UInt n, offset, old_offset;
1173 FT_Byte** t;
1174
1175
1176 *table = 0;
1177
1178 if ( index->count > 0 && !ALLOC_ARRAY( t, index->count + 1, FT_Byte* ) )
1179 {
1180 old_offset = 1;
1181 for ( n = 0; n <= index->count; n++ )
1182 {
1183 offset = index->offsets[n];
1184 if ( !offset )
1185 offset = old_offset;
1186
1187 t[n] = index->bytes + offset - 1;
1188
1189 old_offset = offset;
1190 }
1191 *table = t;
1192 }
1193
1194 return error;
1195 }
1196
1197
Werner Lembergcc069be2000-12-08 16:17:16 +00001198 FT_LOCAL_DEF
1199 FT_Error CFF_Access_Element( CFF_Index* index,
1200 FT_UInt element,
1201 FT_Byte** pbytes,
1202 FT_ULong* pbyte_len )
David Turner19ed8af2000-12-08 02:42:29 +00001203 {
1204 FT_Error error = 0;
1205
1206
1207 if ( index && index->count > element )
1208 {
1209 /* compute start and end offsets */
1210 FT_ULong off1, off2 = 0;
1211
1212
1213 off1 = index->offsets[element];
1214 if ( off1 )
1215 {
1216 do
1217 {
1218 element++;
1219 off2 = index->offsets[element];
1220
1221 } while ( off2 == 0 && element < index->count );
1222
1223 if ( !off2 )
1224 off1 = 0;
1225 }
1226
1227 /* access element */
1228 if ( off1 )
1229 {
1230 *pbyte_len = off2 - off1;
1231
1232 if ( index->bytes )
1233 {
1234 /* this index was completely loaded in memory, that's easy */
1235 *pbytes = index->bytes + off1 - 1;
1236 }
1237 else
1238 {
1239 /* this index is still on disk/file, access it through a frame */
1240 FT_Stream stream = index->stream;
1241
1242
1243 if ( FILE_Seek( index->data_offset + off1 - 1 ) ||
1244 EXTRACT_Frame( off2 - off1, *pbytes ) )
1245 goto Exit;
1246 }
1247 }
1248 else
1249 {
1250 /* empty index element */
1251 *pbytes = 0;
1252 *pbyte_len = 0;
1253 }
1254 }
1255 else
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +00001256 error = CFF_Err_Invalid_Argument;
David Turner19ed8af2000-12-08 02:42:29 +00001257
1258 Exit:
1259 return error;
1260 }
1261
1262
Werner Lembergcc069be2000-12-08 16:17:16 +00001263 FT_LOCAL_DEF
1264 void CFF_Forget_Element( CFF_Index* index,
1265 FT_Byte** pbytes )
David Turner19ed8af2000-12-08 02:42:29 +00001266 {
1267 if ( index->bytes == 0 )
1268 {
1269 FT_Stream stream = index->stream;
1270
1271
1272 RELEASE_Frame( *pbytes );
1273 }
1274 }
1275
1276
Werner Lembergcc069be2000-12-08 16:17:16 +00001277 FT_LOCAL_DEF
1278 FT_String* CFF_Get_Name( CFF_Index* index,
1279 FT_UInt element )
David Turner19ed8af2000-12-08 02:42:29 +00001280 {
1281 FT_Memory memory = index->stream->memory;
1282 FT_Byte* bytes;
1283 FT_ULong byte_len;
1284 FT_Error error;
1285 FT_String* name = 0;
1286
1287
1288 error = CFF_Access_Element( index, element, &bytes, &byte_len );
1289 if ( error )
1290 goto Exit;
1291
1292 if ( !ALLOC( name, byte_len + 1 ) )
1293 {
1294 MEM_Copy( name, bytes, byte_len );
1295 name[byte_len] = 0;
1296 }
1297 CFF_Forget_Element( index, &bytes );
1298
1299 Exit:
1300 return name;
1301 }
1302
1303
Werner Lembergcc069be2000-12-08 16:17:16 +00001304 FT_LOCAL_DEF
1305 FT_String* CFF_Get_String( CFF_Index* index,
1306 FT_UInt sid,
1307 PSNames_Interface* interface )
David Turner19ed8af2000-12-08 02:42:29 +00001308 {
1309 /* if it is not a standard string, return it */
1310 if ( sid > 390 )
1311 return CFF_Get_Name( index, sid - 391 );
1312
1313 /* that's a standard string, fetch a copy from the PSName module */
1314 {
1315 FT_String* name = 0;
1316 const char* adobe_name = interface->adobe_std_strings( sid );
1317 FT_UInt len;
1318
1319
1320 if ( adobe_name )
1321 {
1322 FT_Memory memory = index->stream->memory;
1323 FT_Error error;
1324
1325
1326 len = (FT_UInt)strlen( adobe_name );
1327 if ( !ALLOC( name, len + 1 ) )
1328 {
1329 MEM_Copy( name, adobe_name, len );
1330 name[len] = 0;
1331 }
1332 }
1333
1334 return name;
1335 }
1336 }
1337
1338
1339 /*************************************************************************/
1340 /*************************************************************************/
1341 /*** ***/
1342 /*** FD Select table support ***/
1343 /*** ***/
1344 /*************************************************************************/
1345 /*************************************************************************/
1346
1347
Werner Lembergcc069be2000-12-08 16:17:16 +00001348 static
1349 void CFF_Done_FD_Select( CFF_FD_Select* select,
1350 FT_Stream stream )
David Turner19ed8af2000-12-08 02:42:29 +00001351 {
1352 if ( select->data )
1353 RELEASE_Frame( select->data );
1354
1355 select->data_size = 0;
1356 select->format = 0;
1357 select->range_count = 0;
1358 }
1359
1360
Werner Lembergcc069be2000-12-08 16:17:16 +00001361 static
1362 FT_Error CFF_Load_FD_Select( CFF_FD_Select* select,
1363 FT_UInt num_glyphs,
1364 FT_Stream stream,
1365 FT_ULong offset )
David Turner19ed8af2000-12-08 02:42:29 +00001366 {
Werner Lembergcc069be2000-12-08 16:17:16 +00001367 FT_Error error;
1368 FT_Byte format;
1369 FT_UInt num_ranges;
David Turner19ed8af2000-12-08 02:42:29 +00001370
1371
1372 /* read format */
1373 if ( FILE_Seek( offset ) || READ_Byte( format ) )
1374 goto Exit;
1375
1376 select->format = format;
1377 select->cache_count = 0; /* clear cache */
1378
1379 switch ( format )
1380 {
1381 case 0: /* format 0, that's simple */
1382 select->data_size = num_glyphs;
1383 goto Load_Data;
1384
1385 case 3: /* format 3, a tad more complex */
1386 if ( READ_UShort( num_ranges ) )
1387 goto Exit;
1388
1389 select->data_size = num_ranges * 3 + 2;
1390
1391 Load_Data:
1392 if ( EXTRACT_Frame( select->data_size, select->data ) )
1393 goto Exit;
1394 break;
1395
1396 default: /* hmm... that's wrong */
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +00001397 error = CFF_Err_Invalid_File_Format;
David Turner19ed8af2000-12-08 02:42:29 +00001398 }
1399
1400 Exit:
1401 return error;
1402 }
1403
1404
Werner Lembergcc069be2000-12-08 16:17:16 +00001405 FT_LOCAL_DEF
1406 FT_Byte CFF_Get_FD( CFF_FD_Select* select,
1407 FT_UInt glyph_index )
David Turner19ed8af2000-12-08 02:42:29 +00001408 {
1409 FT_Byte fd = 0;
1410
1411
1412 switch ( select->format )
1413 {
1414 case 0:
1415 fd = select->data[glyph_index];
1416 break;
1417
1418 case 3:
1419 /* first, compare to cache */
1420 if ( (FT_UInt)(glyph_index-select->cache_first) < select->cache_count )
1421 {
1422 fd = select->cache_fd;
1423 break;
1424 }
1425
1426 /* then, lookup the ranges array */
1427 {
1428 FT_Byte* p = select->data;
1429 FT_Byte* p_limit = p + select->data_size;
1430 FT_Byte fd2;
1431 FT_UInt first, limit;
1432
1433
1434 first = NEXT_UShort( p );
1435 do
1436 {
1437 if ( glyph_index < first )
1438 break;
1439
1440 fd2 = *p++;
1441 limit = NEXT_UShort( p );
1442
1443 if ( glyph_index < limit )
1444 {
1445 fd = fd2;
1446
1447 /* update cache */
1448 select->cache_first = first;
1449 select->cache_count = limit-first;
1450 select->cache_fd = fd2;
1451 break;
1452 }
1453 first = limit;
1454
1455 } while ( p < p_limit );
1456 }
1457 break;
1458
1459 default:
1460 ;
1461 }
1462
1463 return fd;
1464 }
1465
1466
1467 /*************************************************************************/
1468 /*************************************************************************/
1469 /*** ***/
1470 /*** CFF font support ***/
1471 /*** ***/
1472 /*************************************************************************/
1473 /*************************************************************************/
1474
Werner Lembergcc069be2000-12-08 16:17:16 +00001475 static
1476 void CFF_Done_Encoding( CFF_Encoding* encoding,
1477 FT_Stream stream )
David Turner19ed8af2000-12-08 02:42:29 +00001478 {
1479 FT_Memory memory = stream->memory;
1480
Werner Lembergcc069be2000-12-08 16:17:16 +00001481
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001482 FREE( encoding->codes );
1483 FREE( encoding->sids );
David Turner19ed8af2000-12-08 02:42:29 +00001484 encoding->format = 0;
David Turner19ed8af2000-12-08 02:42:29 +00001485 encoding->offset = 0;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001486 encoding->codes = 0;
1487 encoding->sids = 0;
David Turner19ed8af2000-12-08 02:42:29 +00001488 }
1489
1490
Werner Lembergcc069be2000-12-08 16:17:16 +00001491 static
1492 void CFF_Done_Charset( CFF_Charset* charset,
1493 FT_Stream stream )
David Turner19ed8af2000-12-08 02:42:29 +00001494 {
1495 FT_Memory memory = stream->memory;
1496
Werner Lemberg6b766632000-12-30 22:14:58 +00001497
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001498 FREE( charset->sids );
David Turner19ed8af2000-12-08 02:42:29 +00001499 charset->format = 0;
1500 charset->offset = 0;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001501 charset->sids = 0;
David Turner19ed8af2000-12-08 02:42:29 +00001502 }
1503
Werner Lemberg6b766632000-12-30 22:14:58 +00001504
Werner Lembergcc069be2000-12-08 16:17:16 +00001505 static
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001506 FT_Error CFF_Load_Charset( CFF_Charset* charset,
1507 FT_UInt num_glyphs,
1508 FT_Stream stream,
1509 FT_ULong base_offset,
1510 FT_ULong offset )
David Turner19ed8af2000-12-08 02:42:29 +00001511 {
Werner Lemberg6b766632000-12-30 22:14:58 +00001512 FT_Memory memory = stream->memory;
1513 FT_Error error = 0;
1514 FT_UShort glyph_sid;
1515
Werner Lembergcc069be2000-12-08 16:17:16 +00001516
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001517 charset->offset = base_offset + offset;
David Turner19ed8af2000-12-08 02:42:29 +00001518
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001519 /* Get the format of the table. */
1520 if ( FILE_Seek( charset->offset ) ||
1521 READ_Byte( charset->format ) )
1522 goto Exit;
1523
1524 /* If the the offset is greater than 2, we have to parse the */
1525 /* charset table. */
David Turner19ed8af2000-12-08 02:42:29 +00001526 if ( offset > 2 )
1527 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001528 FT_UInt j;
David Turner19ed8af2000-12-08 02:42:29 +00001529
Werner Lemberg6b766632000-12-30 22:14:58 +00001530
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001531 /* Allocate memory for sids. */
Werner Lemberg6b766632000-12-30 22:14:58 +00001532 if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
David Turner19ed8af2000-12-08 02:42:29 +00001533 goto Exit;
1534
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001535 /* assign the .notdef glyph */
1536 charset->sids[0] = 0;
1537
Werner Lembergcc069be2000-12-08 16:17:16 +00001538 switch ( charset->format )
David Turner19ed8af2000-12-08 02:42:29 +00001539 {
Werner Lembergcc069be2000-12-08 16:17:16 +00001540 case 0:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001541 for ( j = 1; j < num_glyphs; j++ )
1542 {
1543 if ( READ_UShort( glyph_sid ) )
1544 goto Exit;
1545
1546 charset->sids[j] = glyph_sid;
1547 }
Werner Lembergcc069be2000-12-08 16:17:16 +00001548 break;
1549
1550 case 1:
Werner Lembergcc069be2000-12-08 16:17:16 +00001551 case 2:
1552 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001553 FT_UInt nleft;
1554 FT_UInt i;
Werner Lembergcc069be2000-12-08 16:17:16 +00001555
Werner Lemberg6b766632000-12-30 22:14:58 +00001556
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001557 j = 1;
Werner Lembergcc069be2000-12-08 16:17:16 +00001558
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001559 while ( j < num_glyphs )
David Turner19ed8af2000-12-08 02:42:29 +00001560 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001561
1562 /* Read the first glyph sid of the range. */
1563 if ( READ_UShort( glyph_sid ) )
Werner Lembergcc069be2000-12-08 16:17:16 +00001564 goto Exit;
David Turner19ed8af2000-12-08 02:42:29 +00001565
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001566 /* Read the number of glyphs in the range. */
1567 if ( charset->format == 2 )
1568 {
1569 if ( READ_UShort( nleft ) )
1570 goto Exit;
1571 }
1572 else
1573 {
1574 if ( READ_Byte( nleft ) )
1575 goto Exit;
1576 }
1577
1578 /* Fill in the range of sids -- `nleft + 1' glyphs. */
1579 for ( i = 0; i <= nleft; i++, j++, glyph_sid++ )
1580 charset->sids[j] = glyph_sid;
David Turner19ed8af2000-12-08 02:42:29 +00001581 }
Werner Lembergcc069be2000-12-08 16:17:16 +00001582 }
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001583 break;
David Turner19ed8af2000-12-08 02:42:29 +00001584
Werner Lembergcc069be2000-12-08 16:17:16 +00001585 default:
1586 FT_ERROR(( "CFF_Load_Charset: invalid table format!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001587 error = CFF_Err_Invalid_File_Format;
Werner Lembergcc069be2000-12-08 16:17:16 +00001588 goto Exit;
David Turner19ed8af2000-12-08 02:42:29 +00001589 }
David Turner19ed8af2000-12-08 02:42:29 +00001590 }
1591 else
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001592 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001593 /* Parse default tables corresponding to offset == 0, 1, or 2. */
1594 /* CFF specification intimates the following: */
1595 /* */
1596 /* In order to use a predefined charset, the following must be */
Werner Lemberg6b766632000-12-30 22:14:58 +00001597 /* true: The charset constructed for the glyphs in the font's */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001598 /* charstrings dictionary must match the predefined charset in */
1599 /* the first num_glyphs, and hence must match the predefined */
1600 /* charset *exactly*. */
1601
1602 switch ( offset )
1603 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001604 case 0:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001605 if ( num_glyphs != 229 )
1606 {
Werner Lemberg6b766632000-12-30 22:14:58 +00001607 FT_ERROR(("CFF_Load_Charset: implicit charset not equal to\n"
1608 "predefined charset (Adobe ISO-Latin)!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001609 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001610 goto Exit;
1611 }
1612
1613 /* Allocate memory for sids. */
Werner Lemberg6b766632000-12-30 22:14:58 +00001614 if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001615 goto Exit;
1616
Werner Lemberg6b766632000-12-30 22:14:58 +00001617 /* Copy the predefined charset into the allocated memory. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001618 MEM_Copy( charset->sids, cff_isoadobe_charset,
Werner Lemberg6b766632000-12-30 22:14:58 +00001619 num_glyphs * sizeof ( FT_UShort ) );
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001620
1621 break;
1622
1623 case 1:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001624 if ( num_glyphs != 166 )
1625 {
Werner Lemberg6b766632000-12-30 22:14:58 +00001626 FT_ERROR(( "CFF_Load_Charset: implicit charset not equal to\n"
1627 "predefined charset (Adobe Expert)!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001628 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001629 goto Exit;
1630 }
1631
1632 /* Allocate memory for sids. */
Werner Lemberg6b766632000-12-30 22:14:58 +00001633 if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001634 goto Exit;
1635
1636 /* Copy the predefined charset into the allocated memory. */
1637 MEM_Copy( charset->sids, cff_expert_charset,
Werner Lemberg6b766632000-12-30 22:14:58 +00001638 num_glyphs * sizeof ( FT_UShort ) );
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001639
1640 break;
1641
1642 case 2:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001643 if ( num_glyphs != 87 )
1644 {
Werner Lemberg6b766632000-12-30 22:14:58 +00001645 FT_ERROR(( "CFF_Load_Charset: implicit charset not equal to\n"
1646 "predefined charset (Adobe Expert Subset)!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001647 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001648 goto Exit;
1649 }
1650
1651 /* Allocate memory for sids. */
Werner Lemberg6b766632000-12-30 22:14:58 +00001652 if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001653 goto Exit;
1654
1655 /* Copy the predefined charset into the allocated memory. */
1656 MEM_Copy( charset->sids, cff_expertsubset_charset,
Werner Lemberg6b766632000-12-30 22:14:58 +00001657 num_glyphs * sizeof ( FT_UShort ) );
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001658
1659 break;
1660
1661 default:
Werner Lemberg1429db62001-04-02 23:54:01 +00001662 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001663 goto Exit;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001664 }
1665 }
David Turner19ed8af2000-12-08 02:42:29 +00001666
1667 Exit:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001668
1669 /* Clean up if there was an error. */
1670 if ( error )
1671 if ( charset->sids )
1672 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001673 if ( charset->sids )
1674 FREE( charset->sids );
1675 charset->format = 0;
1676 charset->offset = 0;
1677 charset->sids = 0;
1678 }
1679
David Turner19ed8af2000-12-08 02:42:29 +00001680 return error;
1681 }
1682
Werner Lemberg6b766632000-12-30 22:14:58 +00001683
Werner Lembergcc069be2000-12-08 16:17:16 +00001684 static
1685 FT_Error CFF_Load_Encoding( CFF_Encoding* encoding,
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001686 CFF_Charset* charset,
Werner Lembergcc069be2000-12-08 16:17:16 +00001687 FT_UInt num_glyphs,
1688 FT_Stream stream,
1689 FT_ULong base_offset,
1690 FT_ULong offset )
David Turner19ed8af2000-12-08 02:42:29 +00001691 {
Werner Lemberg6b766632000-12-30 22:14:58 +00001692 FT_Memory memory = stream->memory;
1693 FT_Error error = 0;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001694 FT_UInt count;
1695 FT_UInt j;
1696 FT_UShort glyph_sid;
1697 FT_Byte glyph_code;
David Turner19ed8af2000-12-08 02:42:29 +00001698
Werner Lemberg6b766632000-12-30 22:14:58 +00001699
1700 /* Check for charset->sids. If we do not have this, we fail. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001701 if ( !charset->sids )
David Turner19ed8af2000-12-08 02:42:29 +00001702 {
Werner Lemberg1429db62001-04-02 23:54:01 +00001703 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001704 goto Exit;
1705 }
David Turner19ed8af2000-12-08 02:42:29 +00001706
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001707 /* Allocate memory for sids/codes -- there are at most 256 sids/codes */
1708 /* for an encoding. */
Werner Lemberg6b766632000-12-30 22:14:58 +00001709 if ( ALLOC( encoding->sids, 256 * sizeof ( FT_UShort ) ) ||
1710 ALLOC( encoding->codes, 256 * sizeof ( FT_UShort ) ) )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001711 goto Exit;
1712
Werner Lemberg6b766632000-12-30 22:14:58 +00001713 /* Zero out the code to gid/sid mappings. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001714 for ( j = 0; j < 255; j++ )
1715 {
1716 encoding->sids [j] = 0;
1717 encoding->codes[j] = 0;
1718 }
1719
Werner Lemberg6b766632000-12-30 22:14:58 +00001720 /* Note: The encoding table in a CFF font is indexed by glyph index, */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001721 /* where the first encoded glyph index is 1. Hence, we read the char */
1722 /* code (`glyph_code') at index j and make the assignment: */
1723 /* */
1724 /* encoding->codes[glyph_code] = j + 1 */
1725 /* */
1726 /* We also make the assignment: */
1727 /* */
1728 /* encoding->sids[glyph_code] = charset->sids[j + 1] */
1729 /* */
1730 /* This gives us both a code to GID and a code to SID mapping. */
1731
1732 if ( offset > 1 )
1733 {
Werner Lembergcc069be2000-12-08 16:17:16 +00001734
David Turner19ed8af2000-12-08 02:42:29 +00001735 encoding->offset = base_offset + offset;
1736
1737 /* we need to parse the table to determine its size */
1738 if ( FILE_Seek( encoding->offset ) ||
1739 READ_Byte( encoding->format ) ||
1740 READ_Byte( count ) )
1741 goto Exit;
1742
Werner Lembergcc069be2000-12-08 16:17:16 +00001743 switch ( encoding->format & 0x7F )
David Turner19ed8af2000-12-08 02:42:29 +00001744 {
Werner Lembergcc069be2000-12-08 16:17:16 +00001745 case 0:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001746 for ( j = 1; j <= count; j++ )
1747 {
1748 if ( READ_Byte( glyph_code ) )
1749 goto Exit;
1750
1751 /* Make sure j is not too big. */
1752 if ( j > num_glyphs )
1753 goto Exit;
1754
1755 /* Assign code to GID mapping. */
David Turner8edbcab2001-06-19 08:28:24 +00001756 encoding->codes[glyph_code] = (FT_UShort)j;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001757
1758 /* Assign code to SID mapping. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001759 encoding->sids[glyph_code] = charset->sids[j];
1760 }
1761
Werner Lembergcc069be2000-12-08 16:17:16 +00001762 break;
David Turner19ed8af2000-12-08 02:42:29 +00001763
Werner Lembergcc069be2000-12-08 16:17:16 +00001764 case 1:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001765 {
1766 FT_Byte nleft;
David Turner8edbcab2001-06-19 08:28:24 +00001767 FT_UInt i = 1;
1768 FT_UInt k;
David Turner19ed8af2000-12-08 02:42:29 +00001769
Werner Lemberg6b766632000-12-30 22:14:58 +00001770
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001771 /* Parse the Format1 ranges. */
1772 for ( j = 0; j < count; j++, i += nleft )
1773 {
Werner Lemberg6b766632000-12-30 22:14:58 +00001774 /* Read the first glyph code of the range. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001775 if ( READ_Byte( glyph_code ) )
1776 goto Exit;
1777
Werner Lemberg6b766632000-12-30 22:14:58 +00001778 /* Read the number of codes in the range. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001779 if ( READ_Byte( nleft ) )
1780 goto Exit;
1781
1782 /* Increment nleft, so we read `nleft + 1' codes/sids. */
1783 nleft++;
1784
Werner Lemberg6b766632000-12-30 22:14:58 +00001785 /* Fill in the range of codes/sids. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001786 for ( k = i; k < nleft + i; k++, glyph_code++ )
1787 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001788 /* Make sure k is not too big. */
David Turner8edbcab2001-06-19 08:28:24 +00001789 if ( k > num_glyphs )
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001790 goto Exit;
1791
1792 /* Assign code to GID mapping. */
David Turner8edbcab2001-06-19 08:28:24 +00001793 encoding->codes[glyph_code] = (FT_UShort)k;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001794
1795 /* Assign code to SID mapping. */
1796 encoding->sids[glyph_code] = charset->sids[k];
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001797 }
1798 }
1799 }
Werner Lembergcc069be2000-12-08 16:17:16 +00001800 break;
David Turner19ed8af2000-12-08 02:42:29 +00001801
Werner Lembergcc069be2000-12-08 16:17:16 +00001802 default:
Werner Lemberg6b766632000-12-30 22:14:58 +00001803 FT_ERROR(( "CFF_Load_Encoding: invalid table format!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001804 error = CFF_Err_Invalid_File_Format;
Werner Lembergcc069be2000-12-08 16:17:16 +00001805 goto Exit;
David Turner19ed8af2000-12-08 02:42:29 +00001806 }
1807
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001808 /* Parse supplemental encodings, if any. */
Werner Lembergcc069be2000-12-08 16:17:16 +00001809 if ( encoding->format & 0x80 )
David Turner19ed8af2000-12-08 02:42:29 +00001810 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001811 FT_UInt glyph_id;
David Turner19ed8af2000-12-08 02:42:29 +00001812
Werner Lemberg6b766632000-12-30 22:14:58 +00001813
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001814 /* count supplements */
1815 if ( READ_Byte( count ) )
1816 goto Exit;
1817
1818 for ( j = 0; j < count; j++ )
1819 {
Werner Lemberg6b766632000-12-30 22:14:58 +00001820 /* Read supplemental glyph code. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001821 if ( READ_Byte( glyph_code ) )
1822 goto Exit;
1823
Werner Lemberg6b766632000-12-30 22:14:58 +00001824 /* Read the SID associated with this glyph code. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001825 if ( READ_UShort( glyph_sid ) )
1826 goto Exit;
1827
Werner Lemberg6b766632000-12-30 22:14:58 +00001828 /* Assign code to SID mapping. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001829 encoding->sids[glyph_code] = glyph_sid;
1830
Werner Lemberg6b766632000-12-30 22:14:58 +00001831 /* First, lookup GID which has been assigned to */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001832 /* SID glyph_sid. */
1833 for ( glyph_id = 0; glyph_id < num_glyphs; glyph_id++ )
1834 {
1835 if ( charset->sids[glyph_id] == glyph_sid )
1836 break;
1837 }
1838
Werner Lemberg6b766632000-12-30 22:14:58 +00001839 /* Now, make the assignment. */
David Turner8edbcab2001-06-19 08:28:24 +00001840 encoding->codes[glyph_code] = (FT_UShort)glyph_id;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001841 }
1842 }
David Turner19ed8af2000-12-08 02:42:29 +00001843 }
1844 else
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001845 {
1846 FT_UInt i;
1847
Werner Lemberg6b766632000-12-30 22:14:58 +00001848
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001849 /* We take into account the fact a CFF font can use a predefined */
1850 /* encoding without containing all of the glyphs encoded by this */
1851 /* encoding (see the note at the end of section 12 in the CFF */
1852 /* specification). */
1853
1854 switch ( offset )
1855 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001856 case 0:
Werner Lemberg6b766632000-12-30 22:14:58 +00001857 /* First, copy the code to SID mapping. */
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001858 MEM_Copy( encoding->sids, cff_standard_encoding,
Werner Lemberg6b766632000-12-30 22:14:58 +00001859 256 * sizeof ( FT_UShort ) );
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001860
1861 /* Construct code to GID mapping from code */
1862 /* to SID mapping and charset. */
1863 for ( j = 0; j < 256; j++ )
1864 {
1865 /* If j is encoded, find the GID for it. */
1866 if ( encoding->sids[j] )
1867 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001868 for ( i = 1; i < num_glyphs; i++ )
1869 /* We matched, so break. */
1870 if ( charset->sids[i] == encoding->sids[j] )
1871 break;
1872
1873 /* i will be equal to num_glyphs if we exited the above */
1874 /* loop without a match. In this case, we also have to */
1875 /* fix the code to SID mapping. */
1876 if ( i == num_glyphs )
1877 {
1878 encoding->codes[j] = 0;
1879 encoding->sids [j] = 0;
1880 }
1881 else
David Turner8edbcab2001-06-19 08:28:24 +00001882 encoding->codes[j] = (FT_UShort)i;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001883 }
1884 }
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001885 break;
1886
1887 case 1:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001888 /* First, copy the code to SID mapping. */
1889 MEM_Copy( encoding->sids, cff_expert_encoding,
Werner Lemberg6b766632000-12-30 22:14:58 +00001890 256 * sizeof ( FT_UShort ) );
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001891
1892 /* Construct code to GID mapping from code to SID mapping */
1893 /* and charset. */
1894 for ( j = 0; j < 256; j++ )
1895 {
1896 /* If j is encoded, find the GID for it. */
1897 if ( encoding->sids[j] )
1898 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001899 for ( i = 1; i < num_glyphs; i++ )
1900 /* We matched, so break. */
1901 if ( charset->sids[i] == encoding->sids[j] )
1902 break;
1903
1904 /* i will be equal to num_glyphs if we exited the above */
1905 /* loop without a match. In this case, we also have to */
1906 /* fix the code to SID mapping. */
1907 if ( i == num_glyphs )
1908 {
1909 encoding->codes[j] = 0;
1910 encoding->sids [j] = 0;
1911 }
1912 else
David Turner8edbcab2001-06-19 08:28:24 +00001913 encoding->codes[j] = (FT_UShort)i;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001914 }
1915 }
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001916 break;
1917
1918 default:
Werner Lemberg6b766632000-12-30 22:14:58 +00001919 FT_ERROR(( "CFF_Load_Encoding: invalid table format!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00001920 error = CFF_Err_Invalid_File_Format;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001921 goto Exit;
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001922 }
1923 }
David Turner19ed8af2000-12-08 02:42:29 +00001924
1925 Exit:
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001926
1927 /* Clean up if there was an error. */
1928 if ( error )
1929 {
1930 if ( encoding->sids || encoding->codes )
1931 {
Tom Kacvinsky4ba1c0a2000-12-30 00:37:14 +00001932 if ( encoding->sids )
1933 FREE( encoding->sids );
1934
1935 if ( encoding->codes )
1936 FREE( encoding->codes );
1937
1938 charset->format = 0;
1939 charset->offset = 0;
1940 charset->sids = 0;
1941 }
1942 }
1943
David Turner19ed8af2000-12-08 02:42:29 +00001944 return error;
1945 }
1946
1947
Werner Lembergcc069be2000-12-08 16:17:16 +00001948 static
1949 FT_Error CFF_Load_SubFont( CFF_SubFont* font,
1950 CFF_Index* index,
1951 FT_UInt font_index,
1952 FT_Stream stream,
1953 FT_ULong base_offset )
David Turner19ed8af2000-12-08 02:42:29 +00001954 {
1955 FT_Error error;
Werner Lembergcc069be2000-12-08 16:17:16 +00001956 CFF_Parser parser;
David Turner19ed8af2000-12-08 02:42:29 +00001957 FT_Byte* dict;
1958 FT_ULong dict_len;
1959 CFF_Font_Dict* top = &font->font_dict;
1960 CFF_Private* priv = &font->private_dict;
1961
1962
1963 CFF_Parser_Init( &parser, CFF_CODE_TOPDICT, &font->font_dict );
1964
1965 /* set defaults */
1966 MEM_Set( top, 0, sizeof ( *top ) );
1967
1968 top->underline_position = -100;
1969 top->underline_thickness = 50;
1970 top->charstring_type = 2;
1971 top->font_matrix.xx = 0x10000L;
1972 top->font_matrix.yy = 0x10000L;
1973 top->cid_count = 8720;
1974
1975 error = CFF_Access_Element( index, font_index, &dict, &dict_len ) ||
1976 CFF_Parser_Run( &parser, dict, dict + dict_len );
1977
1978 CFF_Forget_Element( index, &dict );
1979
1980 if ( error )
1981 goto Exit;
1982
1983 /* if it is a CID font, we stop there */
1984 if ( top->cid_registry )
1985 goto Exit;
1986
1987 /* parse the private dictionary, if any */
1988 if ( top->private_offset && top->private_size )
1989 {
1990 /* set defaults */
1991 MEM_Set( priv, 0, sizeof ( *priv ) );
1992
1993 priv->blue_shift = 7;
1994 priv->blue_fuzz = 1;
1995 priv->lenIV = -1;
1996 priv->expansion_factor = (FT_Fixed)0.06 * 0x10000L;
1997 priv->blue_scale = (FT_Fixed)0.039625 * 0x10000L;
1998
1999 CFF_Parser_Init( &parser, CFF_CODE_PRIVATE, priv );
2000
2001 if ( FILE_Seek( base_offset + font->font_dict.private_offset ) ||
2002 ACCESS_Frame( font->font_dict.private_size ) )
2003 goto Exit;
2004
2005 error = CFF_Parser_Run( &parser,
2006 (FT_Byte*)stream->cursor,
2007 (FT_Byte*)stream->limit );
2008 FORGET_Frame();
2009 if ( error )
2010 goto Exit;
2011 }
2012
2013 /* read the local subrs, if any */
2014 if ( priv->local_subrs_offset )
2015 {
2016 if ( FILE_Seek( base_offset + top->private_offset +
2017 priv->local_subrs_offset ) )
2018 goto Exit;
2019
2020 error = cff_new_index( &font->local_subrs_index, stream, 1 );
2021 if ( error )
2022 goto Exit;
2023
2024 font->num_local_subrs = font->local_subrs_index.count;
2025 error = cff_explicit_index( &font->local_subrs_index,
2026 &font->local_subrs );
Werner Lembergcc069be2000-12-08 16:17:16 +00002027 if ( error )
David Turner19ed8af2000-12-08 02:42:29 +00002028 goto Exit;
2029 }
2030
2031 Exit:
2032 return error;
2033 }
2034
2035
Werner Lembergcc069be2000-12-08 16:17:16 +00002036 static
2037 void CFF_Done_SubFont( FT_Memory memory,
2038 CFF_SubFont* subfont )
David Turner19ed8af2000-12-08 02:42:29 +00002039 {
2040 if ( subfont )
2041 {
2042 cff_done_index( &subfont->local_subrs_index );
2043 FREE( subfont->local_subrs );
2044 }
2045 }
2046
2047
Werner Lembergcc069be2000-12-08 16:17:16 +00002048 FT_LOCAL_DEF
2049 FT_Error CFF_Load_Font( FT_Stream stream,
2050 FT_Int face_index,
2051 CFF_Font* font )
David Turner19ed8af2000-12-08 02:42:29 +00002052 {
2053 static const FT_Frame_Field cff_header_fields[] =
2054 {
2055#undef FT_STRUCTURE
2056#define FT_STRUCTURE CFF_Font
2057
2058 FT_FRAME_START( 4 ),
2059 FT_FRAME_BYTE( version_major ),
2060 FT_FRAME_BYTE( version_minor ),
2061 FT_FRAME_BYTE( header_size ),
2062 FT_FRAME_BYTE( absolute_offsize ),
2063 FT_FRAME_END
2064 };
2065
2066 FT_Error error;
2067 FT_Memory memory = stream->memory;
2068 FT_ULong base_offset;
2069 CFF_Font_Dict* dict;
2070
2071
2072 MEM_Set( font, 0, sizeof ( *font ) );
2073
2074 font->stream = stream;
2075 font->memory = memory;
2076 dict = &font->top_font.font_dict;
2077 base_offset = FILE_Pos();
2078
2079 /* read CFF font header */
2080 if ( READ_Fields( cff_header_fields, font ) )
2081 goto Exit;
2082
2083 /* check format */
2084 if ( font->version_major != 1 ||
2085 font->header_size < 4 ||
2086 font->absolute_offsize > 4 )
2087 {
2088 FT_TRACE2(( "[not a CFF font header!]\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00002089 error = CFF_Err_Unknown_File_Format;
David Turner19ed8af2000-12-08 02:42:29 +00002090 goto Exit;
2091 }
2092
2093 /* skip the rest of the header */
2094 if ( FILE_Skip( font->header_size - 4 ) )
2095 goto Exit;
2096
2097 /* read the name, top dict, string and global subrs index */
Werner Lembergcc069be2000-12-08 16:17:16 +00002098 if ( FT_SET_ERROR( cff_new_index( &font->name_index, stream, 0 )) ||
2099 FT_SET_ERROR( cff_new_index( &font->font_dict_index, stream, 0 )) ||
2100 FT_SET_ERROR( cff_new_index( &font->string_index, stream, 0 )) ||
2101 FT_SET_ERROR( cff_new_index( &font->global_subrs_index, stream, 1 )) )
David Turner19ed8af2000-12-08 02:42:29 +00002102 goto Exit;
2103
2104 /* well, we don't really forget the `disabled' fonts... */
2105 font->num_faces = font->name_index.count;
2106 if ( face_index >= (FT_Int)font->num_faces )
2107 {
2108 FT_ERROR(( "CFF_Load_Font: incorrect face index = %d\n",
2109 face_index ));
Tom Kacvinsky8d1f6042001-01-03 00:21:59 +00002110 error = CFF_Err_Invalid_Argument;
David Turner19ed8af2000-12-08 02:42:29 +00002111 }
2112
2113 /* in case of a font format check, simply exit now */
2114 if ( face_index < 0 )
2115 goto Exit;
2116
2117 /* now, parse the top-level font dictionary */
2118 error = CFF_Load_SubFont( &font->top_font,
2119 &font->font_dict_index,
2120 face_index,
2121 stream,
2122 base_offset );
2123 if ( error )
2124 goto Exit;
2125
2126 /* now, check for a CID font */
2127 if ( dict->cid_registry )
2128 {
2129 CFF_Index fd_index;
2130 CFF_SubFont* sub;
2131 FT_UInt index;
2132
2133
2134 /* this is a CID-keyed font, we must now allocate a table of */
2135 /* sub-fonts, then load each of them separately */
2136 if ( FILE_Seek( base_offset + dict->cid_fd_array_offset ) )
2137 goto Exit;
2138
2139 error = cff_new_index( &fd_index, stream, 0 );
2140 if ( error )
2141 goto Exit;
2142
2143 if ( fd_index.count > CFF_MAX_CID_FONTS )
2144 {
2145 FT_ERROR(( "CFF_Load_Font: FD array too large in CID font\n" ));
2146 goto Fail_CID;
2147 }
2148
2149 /* allocate & read each font dict independently */
2150 font->num_subfonts = fd_index.count;
2151 if ( ALLOC_ARRAY( sub, fd_index.count, CFF_SubFont ) )
2152 goto Fail_CID;
2153
2154 /* setup pointer table */
2155 for ( index = 0; index < fd_index.count; index++ )
2156 font->subfonts[index] = sub + index;
2157
2158 /* now load each sub font independently */
2159 for ( index = 0; index < fd_index.count; index++ )
2160 {
2161 sub = font->subfonts[index];
2162 error = CFF_Load_SubFont( sub, &fd_index, index,
2163 stream, base_offset );
2164 if ( error )
2165 goto Fail_CID;
2166 }
2167
2168 /* now load the FD Select array */
2169 error = CFF_Load_FD_Select( &font->fd_select,
2170 dict->cid_count,
2171 stream,
2172 base_offset + dict->cid_fd_select_offset );
2173
Werner Lembergcc069be2000-12-08 16:17:16 +00002174 Fail_CID:
David Turner19ed8af2000-12-08 02:42:29 +00002175 cff_done_index( &fd_index );
2176
2177 if ( error )
2178 goto Exit;
2179 }
2180 else
2181 font->num_subfonts = 0;
2182
2183 /* read the charstrings index now */
2184 if ( dict->charstrings_offset == 0 )
2185 {
2186 FT_ERROR(( "CFF_Load_Font: no charstrings offset!\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +00002187 error = CFF_Err_Unknown_File_Format;
David Turner19ed8af2000-12-08 02:42:29 +00002188 goto Exit;
2189 }
2190
2191 if ( FILE_Seek( base_offset + dict->charstrings_offset ) )
2192 goto Exit;
2193
2194 error = cff_new_index( &font->charstrings_index, stream, 0 );
2195 if ( error )
2196 goto Exit;
2197
2198 /* explicit the global subrs */
2199 font->num_global_subrs = font->global_subrs_index.count;
2200 font->num_glyphs = font->charstrings_index.count;
2201
2202 error = cff_explicit_index( &font->global_subrs_index,
2203 &font->global_subrs ) ;
2204
2205 if ( error )
2206 goto Exit;
2207
2208 /* read the Charset and Encoding tables when available */
2209 error = CFF_Load_Charset( &font->charset, font->num_glyphs, stream,
2210 base_offset, dict->charset_offset );
Werner Lembergcc069be2000-12-08 16:17:16 +00002211 if ( error )
David Turner19ed8af2000-12-08 02:42:29 +00002212 goto Exit;
2213
Werner Lemberg6b766632000-12-30 22:14:58 +00002214 error = CFF_Load_Encoding( &font->encoding,
2215 &font->charset,
2216 font->num_glyphs,
2217 stream,
2218 base_offset,
2219 dict->encoding_offset );
Werner Lembergcc069be2000-12-08 16:17:16 +00002220 if ( error )
David Turner19ed8af2000-12-08 02:42:29 +00002221 goto Exit;
2222
2223 /* get the font name */
2224 font->font_name = CFF_Get_Name( &font->name_index, face_index );
2225
2226 Exit:
2227 return error;
2228 }
2229
2230
Werner Lembergcc069be2000-12-08 16:17:16 +00002231 FT_LOCAL_DEF
2232 void CFF_Done_Font( CFF_Font* font )
David Turner19ed8af2000-12-08 02:42:29 +00002233 {
2234 FT_Memory memory = font->memory;
2235 FT_UInt index;
2236
2237
2238 cff_done_index( &font->global_subrs_index );
2239 cff_done_index( &font->string_index );
2240 cff_done_index( &font->font_dict_index );
2241 cff_done_index( &font->name_index );
2242 cff_done_index( &font->charstrings_index );
2243
2244 /* release font dictionaries */
2245 for ( index = 0; index < font->num_subfonts; index++ )
2246 CFF_Done_SubFont( memory, font->subfonts[index] );
2247
2248 CFF_Done_Encoding( &font->encoding, font->stream );
2249 CFF_Done_Charset( &font->charset, font->stream );
2250
2251 CFF_Done_SubFont( memory, &font->top_font );
2252
2253 CFF_Done_FD_Select( &font->fd_select, font->stream );
2254
2255 FREE( font->global_subrs );
2256 FREE( font->font_name );
2257 }
2258
2259
2260/* END */