* freetype2/include/freetype/internal/psaux.h: New macros IS_PS_NEWLINE, IS_PS_SPACE, IS_PS_SPECIAL, IS_PS_DELIM, IS_PS_DIGIT, IS_PS_XDIGIT, and IS_PS_BASE85 (from freetype2/src/psaux/psconv.h). (T1_FieldLocation): Add T1_FIELD_LOCATION_LOADER, T1_FIELD_LOCATION_FACE, and T1_FIELD_LOCATION_BLEND. (T1_DecoderRec): New fields `buildchar' and `face'. (IS_PS_TOKEN): New macro. * freetype2/include/freetype/internal/t1types.h (T1_FaceRec): New fields `ndv_idx', `cdv_idx', and `len_buildchar'. * freetype2/include/freetype/t1tables.h (PS_BlendRec): New fields `default_design_vector' and `num_default_design_vector'. * freetype2/src/psaux/psconv.h: Move macros IS_PS_NEWLINE, IS_PS_SPACE, IS_PS_SPECIAL, IS_PS_DELIM, IS_PS_DIGIT, IS_PS_XDIGIT, and IS_PS_BASE85 to freetype2/include/freetype/internal/psaux.h. * freetype2/src/psaux/psobjs.c (ps_parser_to_token_array): Allow `token' argument to be NULL if we want only to count the number of tokens. (ps_tocoordarray): Allow `coords' argument to be NULL if we just want to skip the array. (ps_tofixedarray): Allow `values' argument to be NULL if we just want to skip the array. * freetype2/src/psaux/t1decode.c (t1_decoder_parse_charstrings): Add support for (partially commented out) othersubrs 19-25, 27, and 28. (t1_decoder_init): Initialize new fields `face' and `buildchar'. (t1_decoder_done): Release new field `buildchar'. * freetype2/src/type1/t1load.c (parse_buildchar, parse_private): New functions. (t1_keywords): Register them. (t1_allocate_blend): Updated. (t1_load_keyword): Handle field types T1_FIELD_LOCATION_LOADER, T1_FIELD_LOCATION_FACE and T1_FIELD_LOCATION_BLEND. (parse_dict): Remove `keyword_flags' argument. Use new macro IS_PS_TOKEN. Changed function so that later PostScript definitions override earlier ones. (t1_init_loader): Initialize new field `keywords_encountered'. (T1_Open_Face): Initialize new fields `ndv_idx', `cdv_idx', and `len_buildchar'. Remove `keywords_flags'. * freetype2/src/type1/t1load.h (T1_LoaderRect): New field `keywords_encountered'. (T1_PRIVATE, T1_FONTDIR_AFTER_PRIVATE): New macros. * freetype2/src/type1/t1tokens.h [!T1_CONFIG_OPTION_NO_MM_SUPPORT]: New entries for parsing /NDV, /CDV, and /DesignVector.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
diff --git a/ChangeLog b/ChangeLog
index 3e278f4..07a39f0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+2006-07-14 Jens Claudius <jens.claudius@yahoo.com>
+
+ * freetype2/include/freetype/internal/psaux.h: New macros
+ IS_PS_NEWLINE, IS_PS_SPACE, IS_PS_SPECIAL, IS_PS_DELIM, IS_PS_DIGIT,
+ IS_PS_XDIGIT, and IS_PS_BASE85 (from freetype2/src/psaux/psconv.h).
+ (T1_FieldLocation): Add T1_FIELD_LOCATION_LOADER,
+ T1_FIELD_LOCATION_FACE, and T1_FIELD_LOCATION_BLEND.
+ (T1_DecoderRec): New fields `buildchar' and `face'.
+ (IS_PS_TOKEN): New macro.
+
+ * freetype2/include/freetype/internal/t1types.h (T1_FaceRec): New
+ fields `ndv_idx', `cdv_idx', and `len_buildchar'.
+
+ * freetype2/include/freetype/t1tables.h (PS_BlendRec): New fields
+ `default_design_vector' and `num_default_design_vector'.
+
+ * freetype2/src/psaux/psconv.h: Move macros IS_PS_NEWLINE,
+ IS_PS_SPACE, IS_PS_SPECIAL, IS_PS_DELIM, IS_PS_DIGIT, IS_PS_XDIGIT,
+ and IS_PS_BASE85 to freetype2/include/freetype/internal/psaux.h.
+
+ * freetype2/src/psaux/psobjs.c (ps_parser_to_token_array): Allow
+ `token' argument to be NULL if we want only to count the number of
+ tokens.
+ (ps_tocoordarray): Allow `coords' argument to be NULL if we just
+ want to skip the array.
+ (ps_tofixedarray): Allow `values' argument to be NULL if we just
+ want to skip the array.
+
+ * freetype2/src/psaux/t1decode.c (t1_decoder_parse_charstrings): Add
+ support for (partially commented out) othersubrs 19-25, 27, and 28.
+ (t1_decoder_init): Initialize new fields `face' and `buildchar'.
+ (t1_decoder_done): Release new field `buildchar'.
+
+ * freetype2/src/type1/t1load.c (parse_buildchar, parse_private): New
+ functions.
+ (t1_keywords): Register them.
+ (t1_allocate_blend): Updated.
+ (t1_load_keyword): Handle field types T1_FIELD_LOCATION_LOADER,
+ T1_FIELD_LOCATION_FACE and T1_FIELD_LOCATION_BLEND.
+ (parse_dict): Remove `keyword_flags' argument.
+ Use new macro IS_PS_TOKEN.
+ Changed function so that later PostScript definitions override
+ earlier ones.
+ (t1_init_loader): Initialize new field `keywords_encountered'.
+ (T1_Open_Face): Initialize new fields `ndv_idx', `cdv_idx', and
+ `len_buildchar'.
+ Remove `keywords_flags'.
+
+ * freetype2/src/type1/t1load.h (T1_LoaderRect): New field
+ `keywords_encountered'.
+ (T1_PRIVATE, T1_FONTDIR_AFTER_PRIVATE): New macros.
+
+ * freetype2/src/type1/t1tokens.h [!T1_CONFIG_OPTION_NO_MM_SUPPORT]:
+ New entries for parsing /NDV, /CDV, and /DesignVector.
+
2006-07-07 Werner Lemberg <wl@gnu.org>
Add many checks to protect against malformed PCF files.
diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h
index d2e4910..4afd2b0 100644
--- a/include/freetype/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -199,6 +199,9 @@ FT_BEGIN_HEADER
T1_FIELD_LOCATION_FONT_INFO,
T1_FIELD_LOCATION_PRIVATE,
T1_FIELD_LOCATION_BBOX,
+ T1_FIELD_LOCATION_LOADER,
+ T1_FIELD_LOCATION_FACE,
+ T1_FIELD_LOCATION_BLEND,
/* do not remove */
T1_FIELD_LOCATION_MAX
@@ -683,6 +686,10 @@ FT_BEGIN_HEADER
T1_Decoder_Callback parse_callback;
T1_Decoder_FuncsRec funcs;
+ FT_Int* buildchar;
+
+ T1_Face face;
+
} T1_DecoderRec;
@@ -712,8 +719,10 @@ FT_BEGIN_HEADER
} AFM_Parser_FuncsRec;
+
typedef struct AFM_StreamRec_* AFM_Stream;
+
/*************************************************************************/
/* */
/* <Struct> */
@@ -801,6 +810,57 @@ FT_BEGIN_HEADER
/* backwards-compatible type definition */
typedef PSAux_ServiceRec PSAux_Interface;
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Some convenience functions *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define IS_PS_NEWLINE( ch ) \
+ ( (ch) == '\r' || \
+ (ch) == '\n' )
+
+#define IS_PS_SPACE( ch ) \
+ ( (ch) == ' ' || \
+ IS_PS_NEWLINE( ch ) || \
+ (ch) == '\t' || \
+ (ch) == '\f' || \
+ (ch) == '\0' )
+
+#define IS_PS_SPECIAL( ch ) \
+ ( (ch) == '/' || \
+ (ch) == '(' || (ch) == ')' || \
+ (ch) == '<' || (ch) == '>' || \
+ (ch) == '[' || (ch) == ']' || \
+ (ch) == '{' || (ch) == '}' || \
+ (ch) == '%' )
+
+#define IS_PS_DELIM( ch ) \
+ ( IS_PS_SPACE( ch ) || \
+ IS_PS_SPECIAL( ch ) )
+
+#define IS_PS_DIGIT( ch ) \
+ ( (ch) >= '0' && (ch) <= '9' )
+
+#define IS_PS_XDIGIT( ch ) \
+ ( IS_PS_DIGIT( ch ) || \
+ ( (ch) >= 'A' && (ch) <= 'F' ) || \
+ ( (ch) >= 'a' && (ch) <= 'f' ) )
+
+#define IS_PS_BASE85( ch ) \
+ ( (ch) >= '!' && (ch) <= 'u' )
+
+#define IS_PS_TOKEN( cur, limit, token ) \
+ ( (char)(cur)[0] == (token)[0] && \
+ ( (cur) + sizeof ( (token) ) == (limit) || \
+ ( (cur) + sizeof( (token) ) < (limit) && \
+ IS_PS_DELIM( (cur)[sizeof ( (token) ) - 1] ) ) ) && \
+ ft_strncmp( (char*)(cur), (token), sizeof ( (token) ) - 1 ) == 0 )
+
+
FT_END_HEADER
#endif /* __PSAUX_H__ */
diff --git a/include/freetype/internal/t1types.h b/include/freetype/internal/t1types.h
index 65d9ca9..eca91a7 100644
--- a/include/freetype/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
@@ -208,6 +208,16 @@ FT_BEGIN_HEADER
/* support for Multiple Masters fonts */
PS_Blend blend;
+ /* undocumented, optional: indices of subroutines that express */
+ /* the NormalizeDesignVector and the ConvertDesignVector procedure, */
+ /* respectively, as Type 2 charstrings; -1 if keywords not present */
+ FT_Int ndv_idx;
+ FT_Int cdv_idx;
+
+ /* undocumented, optional: has the same meaning as len_buildchar */
+ /* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */
+ FT_UInt len_buildchar;
+
/* since version 2.1 - interface to PostScript hinter */
const void* pshinter;
diff --git a/include/freetype/t1tables.h b/include/freetype/t1tables.h
index 1815250..7979ea5 100644
--- a/include/freetype/t1tables.h
+++ b/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
/* Basic Type 1/Type 2 tables definitions and interface (specification */
/* only). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004 by */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -256,6 +256,15 @@ FT_BEGIN_HEADER
FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1];
+ /* since 2.2.2 */
+
+ /* undocumented, optional: the default design instance; */
+ /* corresponds to default_weight_vector -- */
+ /* num_default_design_vector == 0 means it is not present */
+ /* in the font and associated metrics files */
+ FT_UInt default_design_vector[T1_MAX_MM_DESIGNS];
+ FT_UInt num_default_design_vector;
+
} PS_BlendRec, *PS_Blend;
diff --git a/src/psaux/psconv.h b/src/psaux/psconv.h
index 82c3707..e511241 100644
--- a/src/psaux/psconv.h
+++ b/src/psaux/psconv.h
@@ -63,42 +63,6 @@ FT_BEGIN_HEADER
FT_UShort* seed );
-#define IS_PS_NEWLINE( ch ) \
- ( ( ch ) == '\r' || \
- ( ch ) == '\n' )
-
-#define IS_PS_SPACE( ch ) \
- ( ( ch ) == ' ' || \
- IS_PS_NEWLINE( ch ) || \
- ( ch ) == '\t' || \
- ( ch ) == '\f' || \
- ( ch ) == '\0' )
-
-#define IS_PS_SPECIAL( ch ) \
- ( ( ch ) == '/' || \
- ( ch ) == '(' || \
- ( ch ) == ')' || \
- ( ch ) == '<' || \
- ( ch ) == '>' || \
- ( ch ) == '[' || \
- ( ch ) == ']' || \
- ( ch ) == '{' || \
- ( ch ) == '}' || \
- ( ch ) == '%' )
-
-#define IS_PS_DELIM( ch ) \
- ( IS_PS_SPACE( ch ) || \
- IS_PS_SPECIAL( ch ) )
-
-#define IS_PS_DIGIT( ch ) ( ( ch ) >= '0' && ( ch ) <= '9' )
-
-#define IS_PS_XDIGIT( ch ) \
- ( IS_PS_DIGIT( ( ch ) ) || \
- ( ( ch ) >= 'A' && ( ch ) <= 'F' ) || \
- ( ( ch ) >= 'a' && ( ch ) <= 'f' ) )
-
-#define IS_PS_BASE85( ch ) ( ( ch ) >= '!' && ( ch ) <= 'u' )
-
FT_END_HEADER
#endif /* __PSCONV_H__ */
diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c
index 25b0bc6..5f7037f 100644
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -698,6 +698,9 @@
}
+ /* NB: `tokens' can be NULL if we only want to count */
+ /* the number of array elements */
+
FT_LOCAL_DEF( void )
ps_parser_to_token_array( PS_Parser parser,
T1_Token tokens,
@@ -733,7 +736,7 @@
if ( !token.type )
break;
- if ( cur < limit )
+ if ( tokens != NULL && cur < limit )
*cur = token;
cur++;
@@ -748,6 +751,8 @@
/* first character must be a delimiter or a part of a number */
+ /* NB: `coords' can be NULL if we just want to skip the */
+ /* array; in this case we ignore `max_coords' */
static FT_Int
ps_tocoordarray( FT_Byte* *acur,
@@ -780,21 +785,26 @@
/* now, read the coordinates */
while ( cur < limit )
{
+ FT_Short dummy;
+
+
/* skip whitespace in front of data */
skip_spaces( &cur, limit );
if ( cur >= limit )
goto Exit;
- if ( count >= max_coords )
+ if ( coords != NULL && count >= max_coords )
break;
- if ( c == ender )
+ if ( *cur == ender )
{
cur++;
break;
}
- coords[count] =
+ /* call PS_Conv_ToFixed() even if coords == NULL */
+ /* to properly parse number at `cur' */
+ *( coords != NULL ? &coords[count] : &dummy ) =
(FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
count++;
@@ -809,6 +819,8 @@
/* first character must be a delimiter or a part of a number */
+ /* NB: `values' can be NULL if we just want to skip the */
+ /* array in this case we ignore `max_values' */
static FT_Int
ps_tofixedarray( FT_Byte* *acur,
@@ -842,21 +854,27 @@
/* now, read the values */
while ( cur < limit )
{
+ FT_Fixed dummy;
+
+
/* skip whitespace in front of data */
skip_spaces( &cur, limit );
if ( cur >= limit )
goto Exit;
- if ( count >= max_values )
+ if ( values != NULL && count >= max_values )
break;
- if ( c == ender )
+ if ( *cur == ender )
{
cur++;
break;
}
- values[count] = PS_Conv_ToFixed( &cur, limit, power_ten );
+ /* call PS_Conv_ToFixed() even if coords == NULL */
+ /* to properly parse number at `cur' */
+ *( values != NULL ? &values[count] : &dummy ) =
+ PS_Conv_ToFixed( &cur, limit, power_ten );
count++;
if ( !ender )
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index 574527c..bc799e4 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -348,6 +348,14 @@
hinter = (T1_Hints_Funcs)builder->hints_funcs;
+ /* a font that reads BuildCharArray without setting */
+ /* its values first is buggy, but ... */
+ if ( decoder->face->len_buildchar > 0 )
+ memset( &decoder->buildchar[0],
+ 0,
+ sizeof( decoder->buildchar[0] ) *
+ decoder->face->len_buildchar );
+
FT_TRACE4(( "\nStart charstring\n" ));
zone->base = charstring_base;
@@ -582,12 +590,9 @@
subr_no = (FT_Int)top[1];
arg_cnt = (FT_Int)top[0];
- if ( arg_cnt > top - decoder->stack )
- goto Stack_Underflow;
-
/***********************************************************/
/* */
- /* remove all operands to callsubr from the stack */
+ /* remove all operands to callothersubr from the stack */
/* */
/* for handled othersubrs, where we know the number of */
/* arguments, we increase the stack by the value of */
@@ -596,11 +601,30 @@
/* for unhandled othersubrs the following pops adjust the */
/* stack pointer as necessary */
+ if ( arg_cnt > top - decoder->stack )
+ goto Stack_Underflow;
+
top -= arg_cnt;
known_othersubr_result_cnt = 0;
unknown_othersubr_result_cnt = 0;
+ /* XXX TODO: The checks to `arg_count == <whatever>' */
+ /* might not be correct; an othersubr expects a certain */
+ /* number of operands on the PostScript stack (as opposed */
+ /* to the T1 stack) but it doesn't have to put them there */
+ /* by itself; previous othersubrs might have left the */
+ /* operands there if they were not followed by an */
+ /* appropriate number of pops */
+ /* */
+ /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */
+ /* accept a font that contains charstrings like */
+ /* */
+ /* 100 200 2 20 callothersubr */
+ /* 300 1 20 callothersubr pop */
+ /* */
+ /* Perhaps this is the reason why BuildCharArray exists. */
+
switch ( subr_no )
{
case 1: /* start flex feature */
@@ -726,6 +750,158 @@
break;
}
+#ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS
+
+ /* We cannot yet enable these since currently */
+ /* our T1 stack stores integers which lack the */
+ /* precision to express the values */
+
+ case 19:
+ /* <idx> 1 19 callothersubr */
+ /* => replace elements starting from index cvi( <idx> ) */
+ /* of BuildCharArray with WeightVector */
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+
+ if ( arg_cnt != 1 || blend == NULL )
+ goto Unexpected_OtherSubr;
+
+ idx = top[0];
+
+ if ( idx < 0 ||
+ idx + blend->num_designs > decoder->face->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ memcpy( &decoder->buildchar[idx],
+ blend->weight_vector,
+ blend->num_designs *
+ sizeof( blend->weight_vector[ 0 ] ) );
+ }
+ break;
+
+ case 20:
+ /* <arg1> <arg2> 2 20 callothersubr pop */
+ /* ==> push <arg1> + <arg2> onto T1 stack */
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ top[0] += top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 21:
+ /* <arg1> <arg2> 2 21 callothersubr pop */
+ /* ==> push <arg1> - <arg2> onto T1 stack */
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ top[0] -= top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 22:
+ /* <arg1> <arg2> 2 22 callothersubr pop */
+ /* ==> push <arg1> * <arg2> onto T1 stack */
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ top[0] *= top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 23:
+ /* <arg1> <arg2> 2 23 callothersubr pop */
+ /* ==> push <arg1> / <arg2> onto T1 stack */
+ if ( arg_cnt != 2 || top[1] == 0 )
+ goto Unexpected_OtherSubr;
+
+ top[0] /= top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+#endif /* CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS */
+
+ case 24:
+ /* <val> <idx> 2 24 callothersubr */
+ /* => set BuildCharArray[cvi( <idx> )] = <val> */
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+ if ( arg_cnt != 2 || blend == NULL )
+ goto Unexpected_OtherSubr;
+
+ idx = top[1];
+
+ if ( idx < 0 || (FT_UInt) idx >= decoder->face->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ decoder->buildchar[idx] = top[0];
+ }
+ break;
+
+ case 25:
+ /* <idx> 1 25 callothersubr pop */
+ /* => push BuildCharArray[cvi( idx )] */
+ /* onto T1 stack */
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+ if ( arg_cnt != 1 || blend == NULL )
+ goto Unexpected_OtherSubr;
+
+ idx = top[0];
+
+ if ( idx < 0 || (FT_UInt) idx >= decoder->face->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ top[0] = decoder->buildchar[idx];
+ }
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+#if 0
+ case 26:
+ /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */
+ /* leave mark on T1 stack */
+ /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */
+ XXX who has left his mark on the (PostScript) stack ?;
+ break;
+#endif
+
+ case 27:
+ /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
+ /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
+ /* otherwise push <res2> */
+ if ( arg_cnt != 4 )
+ goto Unexpected_OtherSubr;
+
+ if ( top[2] > top[3] )
+ top[0] = top[1];
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+#ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS
+ case 28:
+ /* 0 28 callothersubr pop */
+ /* => push random value from interval [0, 1) onto stack */
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ top[0] = FT_rand();
+ known_othersubr_result_cnt = 1;
+ break;
+#endif
+
default:
FT_ERROR(( "t1_decoder_parse_charstrings: "
"unknown othersubr [%d %d], wish me luck!\n",
@@ -805,8 +981,30 @@
/* add current outline to the glyph slot */
FT_GlyphLoader_Add( builder->loader );
+ FT_TRACE4(( "\n" ));
+
+ /* the compiler should optimize away this empty loop but ... */
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ if ( decoder->face->len_buildchar > 0 )
+ {
+ FT_UInt i;
+
+
+ FT_TRACE4(( "BuildCharArray = [ " ));
+
+ for ( i = 0; i < decoder->face->len_buildchar; ++i )
+ FT_TRACE4(( "%d ", decoder->buildchar[ i ] ));
+
+ FT_TRACE4(( "]\n" ));
+ }
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ FT_TRACE4(( "\n" ));
+
/* return now! */
- FT_TRACE4(( "\n\n" ));
return PSaux_Err_Ok;
case op_hsbw:
@@ -1225,6 +1423,10 @@
FT_Render_Mode hint_mode,
T1_Decoder_Callback parse_callback )
{
+ FT_Error error;
+ FT_Memory memory = face->memory;
+
+
FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
/* retrieve PSNames interface from list of current modules */
@@ -1243,6 +1445,18 @@
decoder->psnames = psnames;
}
+ decoder->face = (T1_Face) face;
+
+ if ( decoder->face->len_buildchar > 0 )
+ {
+ if ( FT_NEW_ARRAY( decoder->buildchar, decoder->face->len_buildchar ) )
+ {
+ FT_ERROR(( "t1_decoder_init: " ));
+ FT_ERROR(( "cannot allocate memory for BuildCharArray\n" ));
+ return error;
+ }
+ }
+
t1_builder_init( &decoder->builder, face, size, slot, hinting );
decoder->num_glyphs = (FT_UInt)face->num_glyphs;
@@ -1261,7 +1475,12 @@
FT_LOCAL_DEF( void )
t1_decoder_done( T1_Decoder decoder )
{
+ FT_Memory memory = decoder->face->root.memory;
+
+
t1_builder_done( &decoder->builder );
+
+ FT_FREE( decoder->buildchar );
}
diff --git a/src/type1/t1load.c b/src/type1/t1load.c
index 38d9055..635e16c 100644
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -107,6 +107,8 @@
if ( FT_NEW( blend ) )
goto Exit;
+ blend->num_default_design_vector = 0;
+
face->blend = blend;
}
@@ -877,6 +879,18 @@
}
+ /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */
+ /* we're only interested in the number of array elements */
+ static void
+ parse_buildchar( T1_Face face,
+ T1_Loader loader )
+ {
+ face->len_buildchar = T1_ToFixedArray( &loader->parser, 0, NULL, 0 );
+
+ return;
+ }
+
+
#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
@@ -950,6 +964,26 @@
}
break;
+ case T1_FIELD_LOCATION_LOADER:
+ dummy_object = loader;
+ objects = &dummy_object;
+ max_objects = 0;
+ break;
+
+ case T1_FIELD_LOCATION_FACE:
+ dummy_object = face;
+ objects = &dummy_object;
+ max_objects = 0;
+ break;
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ case T1_FIELD_LOCATION_BLEND:
+ dummy_object = face->blend;
+ objects = &dummy_object;
+ max_objects = 0;
+ break;
+#endif
+
default:
dummy_object = &face->type1;
objects = &dummy_object;
@@ -969,6 +1003,16 @@
}
+ static void
+ parse_private( T1_Face face,
+ T1_Loader loader )
+ {
+ FT_UNUSED( face );
+
+ loader->keywords_encountered |= T1_PRIVATE;
+ }
+
+
static int
is_space( FT_Byte c )
{
@@ -1681,12 +1725,14 @@
T1_FIELD_CALLBACK( "Encoding", parse_encoding )
T1_FIELD_CALLBACK( "Subrs", parse_subrs )
T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
+ T1_FIELD_CALLBACK( "Private", parse_private )
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions )
T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map )
T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types )
T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector )
+ T1_FIELD_CALLBACK( "BuildCharArray", parse_buildchar )
#endif
{ 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
@@ -1701,8 +1747,7 @@
parse_dict( T1_Face face,
T1_Loader loader,
FT_Byte* base,
- FT_Long size,
- FT_Byte* keyword_flags )
+ FT_Long size )
{
T1_Parser parser = &loader->parser;
FT_Byte *limit, *start_binary = NULL;
@@ -1724,31 +1769,23 @@
cur = parser->root.cursor;
- /* cur[5] must be a token delimiter; */
- /* eexec encryption is optional, so look for `eexec' */
- if ( *cur == 'e' && cur + 5 < limit &&
- ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
+ /* look for `eexec' */
+ if ( IS_PS_TOKEN( cur, limit, "eexec" ) )
break;
- /* cur[9] must be a token delimiter; */
/* look for `closefile' which ends the eexec section */
- else if ( *cur == 'c' && cur + 9 < limit &&
- ft_strncmp( (char*)cur, "closefile", 9 ) == 0 )
+ else if ( IS_PS_TOKEN( cur, limit, "closefile" ) )
break;
-#ifdef TO_BE_DONE
/* in a synthetic font the base font starts after a */
/* `FontDictionary' token that is placed after a Private dict */
-
- /* cur[13] must be a token delimiter */
- else if ( *cur == 'F' && cur + 13 < limit &&
- ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
+ else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) )
{
- if ( loader->private_encountered )
- loader->fontdir_after_private = 1;
+ if ( loader->keywords_encountered & T1_PRIVATE )
+ loader->keywords_encountered |=
+ T1_FONTDIR_AFTER_PRIVATE;
parser->root.cursor += 13;
}
-#endif
/* check whether we have an integer */
else if ( ft_isdigit( *cur ) )
@@ -1807,8 +1844,7 @@
if ( len > 0 && len < 22 && parser->root.cursor < limit )
{
/* now compare the immediate name to the keyword table */
- T1_Field keyword = (T1_Field)t1_keywords;
- FT_Byte* keyword_flag = keyword_flags;
+ T1_Field keyword = (T1_Field)t1_keywords;
for (;;)
@@ -1824,21 +1860,28 @@
len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
ft_memcmp( cur, name, len ) == 0 )
{
- /* We found it -- run the parsing callback! */
- /* We only record the first instance of any */
- /* field to deal adequately with synthetic */
- /* fonts; /Subrs and /CharStrings are */
- /* handled specially. */
- if ( keyword_flag[0] == 0 ||
- ft_strcmp( (const char*)name, "Subrs" ) == 0 ||
- ft_strcmp( (const char*)name, "CharStrings" ) == 0 )
+ /* We found it -- run the parsing callback! */
+ /* We record every instance of every field */
+ /* (until we reach the base font of a */
+ /* synthetic font) to deal adequately with */
+ /* multiple master fonts; this is also */
+ /* necessary because later PostScript */
+ /* definitions override earlier ones */
+
+ /* Once we encounter `FontDirectory' after */
+ /* `/Private', we know that this is a synthetic */
+ /* font; except for `/CharStrings' we are not */
+ /* interested in anything that follows this */
+ /* `FontDirectory' */
+
+ if ( !( loader->keywords_encountered &
+ T1_FONTDIR_AFTER_PRIVATE ) ||
+ ft_strcmp((const char*)name, "CharStrings") == 0 )
{
parser->root.error = t1_load_keyword( face,
loader,
keyword );
- if ( parser->root.error == T1_Err_Ok )
- keyword_flag[0] = 1;
- else
+ if ( parser->root.error != T1_Err_Ok )
{
if ( FT_ERROR_BASE( parser->root.error ) == FT_Err_Ignore )
parser->root.error = T1_Err_Ok;
@@ -1850,7 +1893,6 @@
}
keyword++;
- keyword_flag++;
}
}
@@ -1883,12 +1925,13 @@
loader->num_chars = 0;
/* initialize the tables -- simply set their `init' field to 0 */
- loader->encoding_table.init = 0;
- loader->charstrings.init = 0;
- loader->glyph_names.init = 0;
- loader->subrs.init = 0;
- loader->swap_table.init = 0;
- loader->fontdata = 0;
+ loader->encoding_table.init = 0;
+ loader->charstrings.init = 0;
+ loader->glyph_names.init = 0;
+ loader->subrs.init = 0;
+ loader->swap_table.init = 0;
+ loader->fontdata = 0;
+ loader->keywords_encountered = 0;
}
@@ -1918,7 +1961,6 @@
T1_Font type1 = &face->type1;
PS_Private priv = &type1->private_dict;
FT_Error error;
- FT_Byte keyword_flags[T1_FIELD_COUNT];
PSAux_Service psaux = (PSAux_Service)face->psaux;
@@ -1926,6 +1968,10 @@
t1_init_loader( &loader, face );
/* default values */
+ face->ndv_idx = -1;
+ face->cdv_idx = -1;
+ face->len_buildchar = 0;
+
priv->blue_shift = 7;
priv->blue_fuzz = 1;
priv->lenIV = 4;
@@ -1940,16 +1986,8 @@
if ( error )
goto Exit;
- {
- FT_UInt n;
-
-
- for ( n = 0; n < T1_FIELD_COUNT; n++ )
- keyword_flags[n] = 0;
- }
-
- error = parse_dict( face, &loader, parser->base_dict, parser->base_len,
- keyword_flags );
+ error = parse_dict( face, &loader,
+ parser->base_dict, parser->base_len );
if ( error )
goto Exit;
@@ -1957,9 +1995,8 @@
if ( error )
goto Exit;
- error = parse_dict( face, &loader, parser->private_dict,
- parser->private_len,
- keyword_flags );
+ error = parse_dict( face, &loader,
+ parser->private_dict, parser->private_len );
if ( error )
goto Exit;
@@ -1968,6 +2005,19 @@
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ if ( face->blend &&
+ face->blend->num_default_design_vector != 0 &&
+ face->blend->num_default_design_vector != face->blend->num_axis )
+ {
+ /* we don't use it currently so just warn, reset, and ignore */
+ FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries "
+ "while there are %u axes.\n",
+ face->blend->num_default_design_vector,
+ face->blend->num_axis ));
+
+ face->blend->num_default_design_vector = 0;
+ }
+
/* the following can happen for MM instances; we then treat the */
/* font as a normal PS font */
if ( face->blend &&
diff --git a/src/type1/t1load.h b/src/type1/t1load.h
index 9823f53..717ae61 100644
--- a/src/type1/t1load.h
+++ b/src/type1/t1load.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 font loader (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2004 by */
+/* Copyright 1996-2001, 2002, 2004, 2006 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -48,9 +48,18 @@ FT_BEGIN_HEADER
PS_TableRec subrs;
FT_Bool fontdata;
+ FT_UInt keywords_encountered; /* T1_LOADER_ENCOUNTERED_XXX */
+
} T1_LoaderRec, *T1_Loader;
+ /* treatment of some keywords differs depending on whether */
+ /* they preceed or follow certain other keywords */
+
+#define T1_PRIVATE ( 1 << 0 )
+#define T1_FONTDIR_AFTER_PRIVATE ( 1 << 1 )
+
+
FT_LOCAL( FT_Error )
T1_Open_Face( T1_Face face );
diff --git a/src/type1/t1tokens.h b/src/type1/t1tokens.h
index a3cc952..bd27361 100644
--- a/src/type1/t1tokens.h
+++ b/src/type1/t1tokens.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 tokenizer (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004 by */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -73,6 +73,7 @@
T1_FIELD_NUM ( "FontType", font_type )
T1_FIELD_FIXED( "StrokeWidth", stroke_width )
+
#undef FT_STRUCTURE
#define FT_STRUCTURE FT_BBox
#undef T1CODE
@@ -81,4 +82,26 @@
T1_FIELD_BBOX("FontBBox", xMin )
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE T1_FaceRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_FACE
+
+ T1_FIELD_NUM ( "NDV", ndv_idx )
+ T1_FIELD_NUM ( "CDV", cdv_idx )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PS_BlendRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_BLEND
+
+ T1_FIELD_NUM_TABLE( "DesignVector", default_design_vector, T1_MAX_MM_DESIGNS )
+
+
+#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
/* END */