625 |
|
|
626 |
#ifdef TT_CONFIG_CMAP_FORMAT_4 |
#ifdef TT_CONFIG_CMAP_FORMAT_4 |
627 |
|
|
|
#define OPT_CMAP4 |
|
|
|
|
|
#ifdef OPT_CMAP4 |
|
|
|
|
628 |
typedef struct TT_CMap4Rec_ |
typedef struct TT_CMap4Rec_ |
629 |
{ |
{ |
630 |
TT_CMapRec cmap; |
TT_CMapRec cmap; |
|
FT_UInt32 old_charcode; /* old charcode */ |
|
631 |
FT_UInt32 cur_charcode; /* current charcode */ |
FT_UInt32 cur_charcode; /* current charcode */ |
632 |
FT_UInt cur_gindex; /* current glyph index */ |
FT_UInt cur_gindex; /* current glyph index */ |
633 |
|
|
|
FT_UInt table_length; |
|
634 |
FT_UInt num_ranges; |
FT_UInt num_ranges; |
635 |
FT_UInt cur_range; |
FT_UInt cur_range; |
636 |
FT_UInt cur_start; |
FT_UInt cur_start; |
650 |
|
|
651 |
cmap->cmap.data = table; |
cmap->cmap.data = table; |
652 |
|
|
|
p = table + 2; |
|
|
cmap->table_length = FT_PEEK_USHORT( p ); |
|
|
|
|
653 |
p = table + 6; |
p = table + 6; |
654 |
cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; |
cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; |
655 |
cmap->cur_range = cmap->num_ranges; |
cmap->cur_charcode = 0xFFFFFFFFUL; |
|
cmap->old_charcode = 0xFFFFFFFFUL; |
|
|
cmap->cur_charcode = 0; |
|
656 |
cmap->cur_gindex = 0; |
cmap->cur_gindex = 0; |
657 |
|
|
658 |
return SFNT_Err_Ok; |
return SFNT_Err_Ok; |
696 |
range_index++; |
range_index++; |
697 |
} |
} |
698 |
|
|
|
cmap->old_charcode = 0xFFFFFFFFUL; |
|
|
cmap->cur_charcode = 0; |
|
|
cmap->cur_gindex = 0; |
|
|
cmap->cur_range = num_ranges; |
|
699 |
return -1; |
return -1; |
700 |
} |
} |
701 |
|
|
702 |
|
|
703 |
|
/* find the index of the charcode next to cmap->cur_charcode; */ |
704 |
|
/* caller should call tt_cmap4_set_range with proper range */ |
705 |
|
/* before calling this function */ |
706 |
|
/* */ |
707 |
static void |
static void |
708 |
tt_cmap4_next( TT_CMap4 cmap ) |
tt_cmap4_next( TT_CMap4 cmap ) |
709 |
{ |
{ |
710 |
FT_UInt charcode = cmap->cur_charcode + 1; |
FT_UInt charcode; |
711 |
|
|
712 |
|
|
713 |
|
if ( cmap->cur_charcode >= 0xFFFFUL ) |
714 |
|
goto Fail; |
715 |
|
|
716 |
|
charcode = cmap->cur_charcode + 1; |
717 |
|
|
718 |
cmap->old_charcode = cmap->cur_charcode; |
if ( charcode < cmap->cur_start ) |
719 |
|
charcode = cmap->cur_start; |
720 |
|
|
721 |
for ( ;; ) |
for ( ;; ) |
722 |
{ |
{ |
770 |
if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 ) |
if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 ) |
771 |
break; |
break; |
772 |
|
|
773 |
charcode = cmap->cur_start; |
if ( charcode < cmap->cur_start ) |
774 |
|
charcode = cmap->cur_start; |
775 |
} |
} |
|
} |
|
776 |
|
|
777 |
|
Fail: |
778 |
static void |
cmap->cur_charcode = 0xFFFFFFFFUL; |
779 |
tt_cmap4_reset( TT_CMap4 cmap, |
cmap->cur_gindex = 0; |
|
FT_UInt code, |
|
|
FT_UInt range_index ) |
|
|
{ |
|
|
if ( tt_cmap4_set_range( cmap, range_index ) >= 0 ) |
|
|
{ |
|
|
cmap->cur_charcode = code; |
|
|
tt_cmap4_next( cmap ); |
|
|
} |
|
780 |
} |
} |
781 |
|
|
|
#endif /* OPT_CMAP4 */ |
|
|
|
|
|
|
|
782 |
|
|
783 |
FT_CALLBACK_DEF( FT_Error ) |
FT_CALLBACK_DEF( FT_Error ) |
784 |
tt_cmap4_validate( FT_Byte* table, |
tt_cmap4_validate( FT_Byte* table, |
791 |
FT_Error error = SFNT_Err_Ok; |
FT_Error error = SFNT_Err_Ok; |
792 |
|
|
793 |
|
|
|
/* in certain fonts, the `length' field is invalid and goes */ |
|
|
/* out of bound. We try to correct this here... */ |
|
794 |
if ( length < 16 ) |
if ( length < 16 ) |
795 |
FT_INVALID_TOO_SHORT; |
FT_INVALID_TOO_SHORT; |
796 |
|
|
797 |
|
/* in certain fonts, the `length' field is invalid and goes */ |
798 |
|
/* out of bound. We try to correct this here... */ |
799 |
if ( table + length > valid->limit ) |
if ( table + length > valid->limit ) |
800 |
{ |
{ |
801 |
if ( valid->level >= FT_VALIDATE_TIGHT ) |
if ( valid->level >= FT_VALIDATE_TIGHT ) |
816 |
|
|
817 |
num_segs /= 2; |
num_segs /= 2; |
818 |
|
|
819 |
|
if ( length < 16 + num_segs * 2 * 4 ) |
820 |
|
FT_INVALID_TOO_SHORT; |
821 |
|
|
822 |
/* check the search parameters - even though we never use them */ |
/* check the search parameters - even though we never use them */ |
823 |
/* */ |
/* */ |
824 |
if ( valid->level >= FT_VALIDATE_PARANOID ) |
if ( valid->level >= FT_VALIDATE_PARANOID ) |
850 |
offsets = deltas + num_segs * 2; |
offsets = deltas + num_segs * 2; |
851 |
glyph_ids = offsets + num_segs * 2; |
glyph_ids = offsets + num_segs * 2; |
852 |
|
|
|
if ( glyph_ids > table + length ) |
|
|
FT_INVALID_TOO_SHORT; |
|
|
|
|
853 |
/* check last segment, its end count must be FFFF */ |
/* check last segment, its end count must be FFFF */ |
854 |
if ( valid->level >= FT_VALIDATE_PARANOID ) |
if ( valid->level >= FT_VALIDATE_PARANOID ) |
855 |
{ |
{ |
858 |
FT_INVALID_DATA; |
FT_INVALID_DATA; |
859 |
} |
} |
860 |
|
|
|
/* check that segments are sorted in increasing order and do not */ |
|
|
/* overlap; check also the offsets */ |
|
861 |
{ |
{ |
862 |
FT_UInt start, end, last = 0, offset, n; |
FT_UInt start, end, offset, n; |
863 |
|
FT_UInt last_start = 0, last_end = 0; |
864 |
FT_Int delta; |
FT_Int delta; |
865 |
|
|
866 |
|
|
882 |
/* unfortunately, some popular Asian fonts present overlapping */ |
/* unfortunately, some popular Asian fonts present overlapping */ |
883 |
/* ranges in their charmaps */ |
/* ranges in their charmaps */ |
884 |
/* */ |
/* */ |
885 |
if ( n > 0 && start <= last ) |
if ( start <= last_end && n > 0 ) |
886 |
{ |
{ |
887 |
if ( valid->level >= FT_VALIDATE_TIGHT ) |
if ( valid->level >= FT_VALIDATE_TIGHT ) |
888 |
FT_INVALID_DATA; |
FT_INVALID_DATA; |
889 |
else |
else |
890 |
error = SFNT_Err_Invalid_CharMap_Format; |
{ |
891 |
|
/* allow overlapping segments, provided their start points */ |
892 |
|
/* and end points, respectively, are in ascending order. */ |
893 |
|
/* */ |
894 |
|
if ( last_start > start || last_end > end ) |
895 |
|
error |= TT_CMAP_FLAG_UNSORTED; |
896 |
|
else |
897 |
|
error |= TT_CMAP_FLAG_OVERLAPPED; |
898 |
|
} |
899 |
} |
} |
900 |
|
|
901 |
if ( offset && offset != 0xFFFFU ) |
if ( offset && offset != 0xFFFFU ) |
946 |
FT_INVALID_DATA; |
FT_INVALID_DATA; |
947 |
} |
} |
948 |
|
|
949 |
last = end; |
last_start = start; |
950 |
|
last_end = end; |
951 |
} |
} |
952 |
} |
} |
953 |
|
|
955 |
} |
} |
956 |
|
|
957 |
|
|
958 |
FT_CALLBACK_DEF( FT_UInt ) |
static FT_UInt |
959 |
tt_cmap4_char_index( TT_CMap cmap, |
tt_cmap4_char_map_linear( TT_CMap cmap, |
960 |
FT_UInt32 char_code ) |
FT_UInt* pcharcode, |
961 |
{ |
FT_Bool next ) |
962 |
FT_Byte* table = cmap->data; |
{ |
963 |
FT_UInt result = 0; |
FT_UInt num_segs2, start, end, offset; |
964 |
|
FT_Int delta; |
965 |
|
FT_UInt i, num_segs; |
966 |
|
FT_UInt32 charcode = *pcharcode; |
967 |
|
FT_UInt gindex = 0; |
968 |
|
FT_Byte* p; |
969 |
|
|
970 |
|
|
971 |
if ( char_code < 0x10000UL ) |
p = cmap->data + 6; |
972 |
{ |
num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); |
|
FT_UInt idx, num_segs2; |
|
|
FT_Int delta; |
|
|
FT_UInt code = (FT_UInt)char_code; |
|
|
FT_Byte* p; |
|
973 |
|
|
974 |
p = table + 6; |
num_segs = num_segs2 >> 1; |
|
num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* be paranoid! */ |
|
|
|
|
|
if ( !cmap->unsorted ) |
|
|
{ |
|
|
/* Some fonts have more than 170 segments in their charmaps! */ |
|
|
/* We changed this function to use a more efficient binary */ |
|
|
/* search for improving performance */ |
|
|
FT_UInt min = 0; |
|
|
FT_UInt max = num_segs2 >> 1; |
|
|
FT_UInt mid, start, end, offset; |
|
975 |
|
|
976 |
|
if ( !num_segs ) |
977 |
|
return 0; |
978 |
|
|
979 |
while ( min < max ) |
if ( next ) |
980 |
{ |
charcode++; |
|
mid = ( min + max ) >> 1; |
|
|
p = table + 14 + mid * 2; |
|
|
end = TT_NEXT_USHORT( p ); |
|
|
p += num_segs2; |
|
|
start = TT_PEEK_USHORT( p); |
|
|
|
|
|
if ( code < start ) |
|
|
max = mid; |
|
|
else if ( code > end ) |
|
|
min = mid + 1; |
|
|
else |
|
|
{ |
|
|
/* we found the segment */ |
|
|
idx = code; |
|
981 |
|
|
982 |
p += num_segs2; |
/* linear search */ |
983 |
delta = TT_PEEK_SHORT( p ); |
for ( ; charcode <= 0xFFFFU; charcode++ ) |
984 |
|
{ |
985 |
|
FT_Byte* q; |
986 |
|
|
987 |
|
|
988 |
p += num_segs2; |
p = cmap->data + 14; /* ends table */ |
989 |
offset = TT_PEEK_USHORT( p ); |
q = cmap->data + 16 + num_segs2; /* starts table */ |
990 |
|
|
991 |
if ( offset == 0xFFFFU ) |
for ( i = 0; i < num_segs; i++ ) |
992 |
goto Exit; |
{ |
993 |
|
end = TT_NEXT_USHORT( p ); |
994 |
|
start = TT_NEXT_USHORT( q ); |
995 |
|
|
996 |
if ( offset != 0 ) |
if ( charcode >= start && charcode <= end ) |
997 |
{ |
{ |
998 |
p += offset + 2 * ( idx - start ); |
p = q - 2 + num_segs2; |
999 |
idx = TT_PEEK_USHORT( p ); |
delta = TT_PEEK_SHORT( p ); |
1000 |
} |
p += num_segs2; |
1001 |
|
offset = TT_PEEK_USHORT( p ); |
1002 |
|
|
1003 |
if ( idx != 0 ) |
if ( offset == 0xFFFFU ) |
1004 |
result = (FT_UInt)( idx + delta ) & 0xFFFFU; |
continue; |
1005 |
|
|
1006 |
goto Exit; |
if ( offset ) |
1007 |
|
{ |
1008 |
|
p += offset + ( charcode - start ) * 2; |
1009 |
|
gindex = TT_PEEK_USHORT( p ); |
1010 |
|
if ( gindex != 0 ) |
1011 |
|
gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; |
1012 |
} |
} |
1013 |
|
else |
1014 |
|
gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU; |
1015 |
|
|
1016 |
|
break; |
1017 |
} |
} |
1018 |
} |
} |
|
else |
|
|
{ |
|
|
FT_UInt n; |
|
|
FT_Byte* q; |
|
1019 |
|
|
1020 |
|
if ( !next || gindex ) |
1021 |
|
break; |
1022 |
|
} |
1023 |
|
|
1024 |
p = table + 14; /* ends table */ |
if ( next && gindex ) |
1025 |
q = table + 16 + num_segs2; /* starts table */ |
*pcharcode = charcode; |
1026 |
|
|
1027 |
|
return gindex; |
1028 |
|
} |
1029 |
|
|
|
for ( n = 0; n < num_segs2; n += 2 ) |
|
|
{ |
|
|
FT_UInt end = TT_NEXT_USHORT( p ); |
|
|
FT_UInt start = TT_NEXT_USHORT( q ); |
|
|
FT_UInt offset; |
|
1030 |
|
|
1031 |
|
static FT_UInt |
1032 |
|
tt_cmap4_char_map_binary( TT_CMap cmap, |
1033 |
|
FT_UInt* pcharcode, |
1034 |
|
FT_Bool next ) |
1035 |
|
{ |
1036 |
|
FT_UInt num_segs2, start, end, offset; |
1037 |
|
FT_Int delta; |
1038 |
|
FT_UInt max, min, mid, num_segs; |
1039 |
|
FT_UInt charcode = *pcharcode; |
1040 |
|
FT_UInt gindex = 0; |
1041 |
|
FT_Byte* p; |
1042 |
|
|
1043 |
|
|
1044 |
if ( code < start ) |
p = cmap->data + 6; |
1045 |
break; |
num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); |
1046 |
|
|
1047 |
if ( code <= end ) |
num_segs = num_segs2 >> 1; |
|
{ |
|
|
idx = code; |
|
1048 |
|
|
1049 |
p = q + num_segs2 - 2; |
if ( !num_segs ) |
1050 |
delta = TT_PEEK_SHORT( p ); |
return 0; |
|
p += num_segs2; |
|
|
offset = TT_PEEK_USHORT( p ); |
|
1051 |
|
|
1052 |
if ( offset == 0xFFFFU ) |
if ( next ) |
1053 |
goto Exit; |
charcode++; |
1054 |
|
|
1055 |
if ( offset != 0 ) |
min = 0; |
1056 |
{ |
max = num_segs; |
|
p += offset + 2 * ( idx - start ); |
|
|
idx = TT_PEEK_USHORT( p ); |
|
|
} |
|
1057 |
|
|
1058 |
if ( idx != 0 ) |
/* binary search */ |
1059 |
result = (FT_UInt)( idx + delta ) & 0xFFFFU; |
while ( min < max ) |
1060 |
} |
{ |
1061 |
} |
mid = ( min + max ) >> 1; |
1062 |
} |
p = cmap->data + 14 + mid * 2; |
1063 |
} |
end = TT_PEEK_USHORT( p ); |
1064 |
|
p += 2 + num_segs2; |
1065 |
|
start = TT_PEEK_USHORT( p ); |
1066 |
|
|
1067 |
Exit: |
if ( charcode < start ) |
1068 |
return result; |
max = mid; |
1069 |
} |
else if ( charcode > end ) |
1070 |
|
min = mid + 1; |
1071 |
|
else |
1072 |
|
{ |
1073 |
|
p += num_segs2; |
1074 |
|
delta = TT_PEEK_SHORT( p ); |
1075 |
|
p += num_segs2; |
1076 |
|
offset = TT_PEEK_USHORT( p ); |
1077 |
|
|
1078 |
|
/* find the first segment containing `charcode' */ |
1079 |
|
if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPED ) |
1080 |
|
{ |
1081 |
|
FT_UInt i; |
1082 |
|
|
|
FT_CALLBACK_DEF( FT_UInt ) |
|
|
tt_cmap4_char_next( TT_CMap cmap, |
|
|
FT_UInt32 *pchar_code ) |
|
|
{ |
|
|
FT_Byte* table = cmap->data; |
|
|
FT_UInt32 result = 0; |
|
|
FT_UInt gindex = 0; |
|
|
FT_UInt32 char_code = *pchar_code; |
|
|
FT_Byte* p; |
|
|
FT_UInt code, num_segs2; |
|
1083 |
|
|
1084 |
|
/* call the current segment `max' */ |
1085 |
|
max = mid; |
1086 |
|
|
1087 |
if ( char_code >= 0xFFFFUL ) |
if ( offset == 0xFFFFU ) |
1088 |
goto Exit; |
mid = max + 1; |
1089 |
|
|
1090 |
#ifdef OPT_CMAP4 |
/* find in segments before the current segment */ |
1091 |
{ |
for ( i = max ; i > 0; i-- ) |
1092 |
TT_CMap4 cmap4 = (TT_CMap4)cmap; |
{ |
1093 |
|
FT_UInt prev_end; |
1094 |
|
|
1095 |
|
|
1096 |
if ( char_code == cmap4->old_charcode ) |
p = cmap->data + 14 + ( i - 1 ) * 2; |
1097 |
{ |
prev_end = TT_PEEK_USHORT( p ); |
|
result = cmap4->cur_charcode; |
|
|
gindex = cmap4->cur_gindex; |
|
|
if ( result != 0 ) |
|
|
{ |
|
|
tt_cmap4_next( cmap4 ); |
|
|
goto Exit; |
|
|
} |
|
|
} |
|
|
} |
|
|
#endif /* OPT_CMAP4 */ |
|
1098 |
|
|
1099 |
code = (FT_UInt)char_code + 1; |
if ( charcode > prev_end ) |
1100 |
p = table + 6; |
break; |
|
num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* ensure even-ness */ |
|
|
|
|
|
if ( !cmap->unsorted ) |
|
|
{ |
|
|
for (;;) |
|
|
{ |
|
|
/* Some fonts have more than 170 segments in their charmaps! */ |
|
|
/* We changed this function to use a more efficient binary */ |
|
|
/* search */ |
|
|
FT_UInt offset; |
|
|
FT_Int delta; |
|
|
FT_UInt min = 0; |
|
|
FT_UInt max = num_segs2 >> 1; |
|
|
FT_UInt mid, start, end; |
|
|
FT_UInt hi; |
|
|
|
|
|
|
|
|
/* we begin by finding the segment which end is |
|
|
closer to our code point */ |
|
|
hi = max + 1; |
|
|
while ( min < max ) |
|
|
{ |
|
|
mid = ( min + max ) >> 1; |
|
|
p = table + 14 + mid * 2; |
|
|
end = TT_PEEK_USHORT( p ); |
|
1101 |
|
|
1102 |
if ( end < code ) |
end = prev_end; |
1103 |
min = mid + 1; |
p += 2 + num_segs2; |
1104 |
else |
start = TT_PEEK_USHORT( p ); |
1105 |
{ |
p += num_segs2; |
1106 |
hi = mid; |
delta = TT_PEEK_SHORT( p ); |
1107 |
max = mid; |
p += num_segs2; |
1108 |
|
offset = TT_PEEK_USHORT( p ); |
1109 |
|
|
1110 |
|
if ( offset != 0xFFFFU ) |
1111 |
|
mid = i - 1; |
1112 |
} |
} |
|
} |
|
1113 |
|
|
1114 |
if ( hi > max ) |
/* no luck */ |
1115 |
{ |
if ( mid == max + 1 ) |
1116 |
/* the point is behind the last segment; |
{ |
1117 |
we will exit right now */ |
if ( i != max ) |
1118 |
goto Exit; |
{ |
1119 |
} |
p = cmap->data + 14 + max * 2; |
1120 |
|
end = TT_PEEK_USHORT( p ); |
1121 |
|
p += 2 + num_segs2; |
1122 |
|
start = TT_PEEK_USHORT( p ); |
1123 |
|
p += num_segs2; |
1124 |
|
delta = TT_PEEK_SHORT( p ); |
1125 |
|
p += num_segs2; |
1126 |
|
offset = TT_PEEK_USHORT( p ); |
1127 |
|
} |
1128 |
|
|
1129 |
p = table + 14 + hi * 2; |
mid = max; |
|
end = TT_PEEK_USHORT( p ); |
|
1130 |
|
|
1131 |
p += 2 + num_segs2; |
/* find in segments after the current segment */ |
1132 |
start = TT_PEEK_USHORT( p ); |
for ( i = max + 1; i < num_segs; i++ ) |
1133 |
|
{ |
1134 |
|
FT_UInt next_end, next_start; |
1135 |
|
|
|
if ( code < start ) |
|
|
code = start; |
|
1136 |
|
|
1137 |
p += num_segs2; |
p = cmap->data + 14 + i * 2; |
1138 |
delta = TT_PEEK_USHORT( p ); |
next_end = TT_PEEK_USHORT( p ); |
1139 |
|
p += 2 + num_segs2; |
1140 |
|
next_start = TT_PEEK_USHORT( p ); |
1141 |
|
|
1142 |
|
if ( charcode < next_start ) |
1143 |
|
break; |
1144 |
|
|
1145 |
|
end = next_end; |
1146 |
|
start = next_start; |
1147 |
|
p += num_segs2; |
1148 |
|
delta = TT_PEEK_SHORT( p ); |
1149 |
|
p += num_segs2; |
1150 |
|
offset = TT_PEEK_USHORT( p ); |
1151 |
|
|
1152 |
p += num_segs2; |
if ( offset != 0xFFFFU ) |
1153 |
offset = TT_PEEK_USHORT( p ); |
mid = i; |
1154 |
|
} |
1155 |
|
i--; |
1156 |
|
|
1157 |
if ( offset != 0 && offset != 0xFFFFU ) |
/* still no luck */ |
1158 |
{ |
if ( mid == max ) |
|
/* parse the glyph ids array for non-zero index */ |
|
|
p += offset + ( code - start ) * 2; |
|
|
while ( code <= end ) |
|
|
{ |
|
|
gindex = TT_NEXT_USHORT( p ); |
|
|
if ( gindex != 0 ) |
|
1159 |
{ |
{ |
1160 |
gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; |
mid = i; |
1161 |
if ( gindex != 0 ) |
|
1162 |
{ |
break; |
|
result = code; |
|
|
#ifdef OPT_CMAP4 |
|
|
tt_cmap4_reset( (TT_CMap4)cmap, code, hi ); |
|
|
#endif |
|
|
goto Exit; |
|
|
} |
|
1163 |
} |
} |
1164 |
code++; |
} |
1165 |
|
|
1166 |
|
/* end, start, delta and offset are for the i'th segment */ |
1167 |
|
if ( mid != i ) |
1168 |
|
{ |
1169 |
|
p = cmap->data + 14 + mid * 2; |
1170 |
|
end = TT_PEEK_USHORT( p ); |
1171 |
|
p += 2 + num_segs2; |
1172 |
|
start = TT_PEEK_USHORT( p ); |
1173 |
|
p += num_segs2; |
1174 |
|
delta = TT_PEEK_SHORT( p ); |
1175 |
|
p += num_segs2; |
1176 |
|
offset = TT_PEEK_USHORT( p ); |
1177 |
} |
} |
1178 |
} |
} |
1179 |
else if ( offset == 0xFFFFU ) |
else |
1180 |
{ |
{ |
1181 |
/* an offset of 0xFFFF means an empty segment in certain fonts! */ |
if ( offset == 0xFFFFU ) |
1182 |
code = end + 1; |
break; |
1183 |
} |
} |
1184 |
else /* offset == 0 */ |
|
1185 |
|
if ( offset ) |
1186 |
{ |
{ |
1187 |
gindex = (FT_UInt)( code + delta ) & 0xFFFFU; |
p += offset + ( charcode - start ) * 2; |
1188 |
|
gindex = TT_PEEK_USHORT( p ); |
1189 |
if ( gindex != 0 ) |
if ( gindex != 0 ) |
1190 |
{ |
gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; |
|
result = code; |
|
|
#ifdef OPT_CMAP4 |
|
|
tt_cmap4_reset( (TT_CMap4)cmap, code, hi ); |
|
|
#endif |
|
|
goto Exit; |
|
|
} |
|
|
code++; |
|
1191 |
} |
} |
1192 |
|
else |
1193 |
|
gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU; |
1194 |
|
|
1195 |
|
break; |
1196 |
} |
} |
1197 |
} |
} |
1198 |
else |
|
1199 |
|
if ( next ) |
1200 |
{ |
{ |
1201 |
for ( ;; ) |
TT_CMap4 cmap4 = (TT_CMap4)cmap; |
|
{ |
|
|
FT_UInt offset, n; |
|
|
FT_Int delta; |
|
|
FT_Byte* q; |
|
1202 |
|
|
1203 |
|
|
1204 |
p = table + 14; /* ends table */ |
/* if `charcode' is not in any segment, then `mid' is */ |
1205 |
q = table + 16 + num_segs2; /* starts table */ |
/* the segment nearest to `charcode' */ |
1206 |
|
/* */ |
1207 |
|
|
1208 |
for ( n = 0; n < num_segs2; n += 2 ) |
if ( charcode > end ) |
1209 |
|
{ |
1210 |
|
mid++; |
1211 |
|
if ( mid == num_segs ) |
1212 |
|
return 0; |
1213 |
|
} |
1214 |
|
|
1215 |
|
if ( tt_cmap4_set_range( cmap4, mid ) ) |
1216 |
|
{ |
1217 |
|
if ( gindex ) |
1218 |
|
*pcharcode = charcode; |
1219 |
|
} |
1220 |
|
else |
1221 |
|
{ |
1222 |
|
cmap4->cur_charcode = charcode; |
1223 |
|
|
1224 |
|
if ( gindex ) |
1225 |
|
cmap4->cur_gindex = gindex; |
1226 |
|
else |
1227 |
{ |
{ |
1228 |
FT_UInt end = TT_NEXT_USHORT( p ); |
cmap4->cur_charcode = charcode; |
1229 |
FT_UInt start = TT_NEXT_USHORT( q ); |
tt_cmap4_next( cmap4 ); |
1230 |
|
gindex = cmap4->cur_gindex; |
1231 |
|
} |
1232 |
|
|
1233 |
|
if ( gindex ) |
1234 |
|
*pcharcode = cmap4->cur_charcode; |
1235 |
|
} |
1236 |
|
} |
1237 |
|
|
1238 |
if ( code < start ) |
return gindex; |
1239 |
code = start; |
} |
1240 |
|
|
|
if ( code <= end ) |
|
|
{ |
|
|
p = q + num_segs2 - 2; |
|
|
delta = TT_PEEK_SHORT( p ); |
|
|
p += num_segs2; |
|
|
offset = TT_PEEK_USHORT( p ); |
|
1241 |
|
|
1242 |
if ( offset != 0 && offset != 0xFFFFU ) |
FT_CALLBACK_DEF( FT_UInt ) |
1243 |
{ |
tt_cmap4_char_index( TT_CMap cmap, |
1244 |
/* parse the glyph ids array for non-0 index */ |
FT_UInt32 char_code ) |
1245 |
p += offset + ( code - start ) * 2; |
{ |
1246 |
while ( code <= end ) |
if ( char_code >= 0x10000U ) |
1247 |
{ |
return 0; |
|
gindex = TT_NEXT_USHORT( p ); |
|
|
if ( gindex != 0 ) |
|
|
{ |
|
|
gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; |
|
|
if ( gindex != 0 ) |
|
|
break; |
|
|
} |
|
|
code++; |
|
|
} |
|
|
} |
|
|
else if ( offset == 0xFFFFU ) |
|
|
{ |
|
|
/* an offset of 0xFFFF means an empty glyph in certain fonts! */ |
|
|
code = end; |
|
|
break; |
|
|
} |
|
|
else |
|
|
gindex = (FT_UInt)( code + delta ) & 0xFFFFU; |
|
1248 |
|
|
1249 |
if ( gindex == 0 ) |
if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) |
1250 |
break; |
return tt_cmap4_char_map_linear( cmap, &char_code, 0 ); |
1251 |
|
else |
1252 |
|
return tt_cmap4_char_map_binary( cmap, &char_code, 0 ); |
1253 |
|
} |
1254 |
|
|
1255 |
|
|
1256 |
|
FT_CALLBACK_DEF( FT_UInt ) |
1257 |
|
tt_cmap4_char_next( TT_CMap cmap, |
1258 |
|
FT_UInt32 *pchar_code ) |
1259 |
|
{ |
1260 |
|
FT_UInt gindex; |
1261 |
|
|
1262 |
|
|
1263 |
|
if ( *pchar_code >= 0xFFFFU ) |
1264 |
|
return 0; |
1265 |
|
|
1266 |
|
if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) |
1267 |
|
gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 ); |
1268 |
|
else |
1269 |
|
{ |
1270 |
|
TT_CMap4 cmap4 = (TT_CMap4)cmap; |
1271 |
|
|
|
result = code; |
|
|
goto Exit; |
|
|
} |
|
|
} |
|
|
/* loop to next trial charcode */ |
|
|
if ( code >= 0xFFFFU ) |
|
|
break; |
|
1272 |
|
|
1273 |
code++; |
/* no need to search */ |
1274 |
|
if ( *pchar_code == cmap4->cur_charcode ) |
1275 |
|
{ |
1276 |
|
tt_cmap4_next( cmap4 ); |
1277 |
|
gindex = cmap4->cur_gindex; |
1278 |
|
if ( gindex ) |
1279 |
|
*pchar_code = cmap4->cur_charcode; |
1280 |
} |
} |
1281 |
|
else |
1282 |
|
gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 ); |
1283 |
} |
} |
1284 |
|
|
|
Exit: |
|
|
*pchar_code = result; |
|
1285 |
return gindex; |
return gindex; |
1286 |
} |
} |
1287 |
|
|
1303 |
const TT_CMap_ClassRec tt_cmap4_class_rec = |
const TT_CMap_ClassRec tt_cmap4_class_rec = |
1304 |
{ |
{ |
1305 |
{ |
{ |
|
#ifdef OPT_CMAP4 |
|
1306 |
sizeof ( TT_CMap4Rec ), |
sizeof ( TT_CMap4Rec ), |
1307 |
(FT_CMap_InitFunc) tt_cmap4_init, |
(FT_CMap_InitFunc) tt_cmap4_init, |
|
#else |
|
|
sizeof ( TT_CMapRec ), |
|
|
(FT_CMap_InitFunc) tt_cmap_init, |
|
|
#endif |
|
1308 |
(FT_CMap_DoneFunc) NULL, |
(FT_CMap_DoneFunc) NULL, |
1309 |
(FT_CMap_CharIndexFunc)tt_cmap4_char_index, |
(FT_CMap_CharIndexFunc)tt_cmap4_char_index, |
1310 |
(FT_CMap_CharNextFunc) tt_cmap4_char_next |
(FT_CMap_CharNextFunc) tt_cmap4_char_next |
2293 |
|
|
2294 |
if ( valid.validator.error == 0 ) |
if ( valid.validator.error == 0 ) |
2295 |
{ |
{ |
2296 |
(void)FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, NULL ); |
FT_CMap ttcmap; |
2297 |
|
|
2298 |
/* it is simpler to directly set the `unsorted' flag instead */ |
|
2299 |
/* of adding a parameter to FT_CMap_New */ |
if ( !FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, &ttcmap ) ) |
2300 |
((TT_CMap)(face->root.charmaps |
{ |
2301 |
[face->root.num_charmaps - 1]))->unsorted = |
/* it is simpler to directly set `flags' than adding */ |
2302 |
FT_BOOL( error ); |
/* a parameter to FT_CMap_New */ |
2303 |
|
((TT_CMap)ttcmap)->flags = (FT_Int)error; |
2304 |
|
} |
2305 |
} |
} |
2306 |
else |
else |
2307 |
{ |
{ |