问题
I have this cmap table roughly:
{ name: 'cmap',
fields:
{ version: { type: 'USHORT', value: 0 },
numTables: { type: 'USHORT', value: 1 },
platformID: { type: 'USHORT', value: 0 },
encodingID: { type: 'USHORT', value: 6 },
offset: { type: 'ULONG', value: 12 },
format: { type: 'USHORT', value: 4 },
cmap4Length: { type: 'USHORT', value: 16 },
language: { type: 'USHORT', value: 0 },
segCountX2: { type: 'USHORT', value: 126 },
searchRange: { type: 'USHORT', value: 64 },
entrySelector: { type: 'USHORT', value: 5 },
rangeShift: { type: 'USHORT', value: 62 },
end_0: { type: 'USHORT', value: 48 },
end_1: { type: 'USHORT', value: 49 },
end_2: { type: 'USHORT', value: 50 },
end_3: { type: 'USHORT', value: 51 },
end_4: { type: 'USHORT', value: 52 },
end_5: { type: 'USHORT', value: 53 },
end_6: { type: 'USHORT', value: 54 },
end_7: { type: 'USHORT', value: 55 },
end_8: { type: 'USHORT', value: 56 },
end_9: { type: 'USHORT', value: 57 },
end_10: { type: 'USHORT', value: 65 },
end_11: { type: 'USHORT', value: 66 },
end_12: { type: 'USHORT', value: 67 },
end_13: { type: 'USHORT', value: 68 },
end_14: { type: 'USHORT', value: 69 },
end_15: { type: 'USHORT', value: 70 },
end_16: { type: 'USHORT', value: 71 },
end_17: { type: 'USHORT', value: 72 },
end_18: { type: 'USHORT', value: 73 },
end_19: { type: 'USHORT', value: 74 },
end_20: { type: 'USHORT', value: 75 },
end_21: { type: 'USHORT', value: 76 },
end_22: { type: 'USHORT', value: 77 },
end_23: { type: 'USHORT', value: 78 },
end_24: { type: 'USHORT', value: 79 },
end_25: { type: 'USHORT', value: 80 },
end_26: { type: 'USHORT', value: 81 },
end_27: { type: 'USHORT', value: 82 },
end_28: { type: 'USHORT', value: 83 },
end_29: { type: 'USHORT', value: 84 },
end_30: { type: 'USHORT', value: 85 },
end_31: { type: 'USHORT', value: 86 },
end_32: { type: 'USHORT', value: 87 },
end_33: { type: 'USHORT', value: 88 },
end_34: { type: 'USHORT', value: 89 },
end_35: { type: 'USHORT', value: 90 },
end_36: { type: 'USHORT', value: 97 },
end_37: { type: 'USHORT', value: 98 },
end_38: { type: 'USHORT', value: 99 },
end_39: { type: 'USHORT', value: 100 },
end_40: { type: 'USHORT', value: 101 },
end_41: { type: 'USHORT', value: 102 },
end_42: { type: 'USHORT', value: 103 },
end_43: { type: 'USHORT', value: 104 },
end_44: { type: 'USHORT', value: 105 },
end_45: { type: 'USHORT', value: 106 },
end_46: { type: 'USHORT', value: 107 },
end_47: { type: 'USHORT', value: 108 },
end_48: { type: 'USHORT', value: 109 },
end_49: { type: 'USHORT', value: 110 },
end_50: { type: 'USHORT', value: 111 },
end_51: { type: 'USHORT', value: 112 },
end_52: { type: 'USHORT', value: 113 },
end_53: { type: 'USHORT', value: 114 },
end_54: { type: 'USHORT', value: 115 },
end_55: { type: 'USHORT', value: 116 },
end_56: { type: 'USHORT', value: 117 },
end_57: { type: 'USHORT', value: 118 },
end_58: { type: 'USHORT', value: 119 },
end_59: { type: 'USHORT', value: 120 },
end_60: { type: 'USHORT', value: 121 },
end_61: { type: 'USHORT', value: 122 },
end_62: { type: 'USHORT', value: 65535 },
reservedPad: { type: 'USHORT', value: 0 },
start_0: { type: 'USHORT', value: 48 },
start_1: { type: 'USHORT', value: 49 },
start_2: { type: 'USHORT', value: 50 },
start_3: { type: 'USHORT', value: 51 },
start_4: { type: 'USHORT', value: 52 },
start_5: { type: 'USHORT', value: 53 },
start_6: { type: 'USHORT', value: 54 },
start_7: { type: 'USHORT', value: 55 },
start_8: { type: 'USHORT', value: 56 },
start_9: { type: 'USHORT', value: 57 },
start_10: { type: 'USHORT', value: 65 },
start_11: { type: 'USHORT', value: 66 },
start_12: { type: 'USHORT', value: 67 },
start_13: { type: 'USHORT', value: 68 },
start_14: { type: 'USHORT', value: 69 },
start_15: { type: 'USHORT', value: 70 },
start_16: { type: 'USHORT', value: 71 },
start_17: { type: 'USHORT', value: 72 },
start_18: { type: 'USHORT', value: 73 },
start_19: { type: 'USHORT', value: 74 },
start_20: { type: 'USHORT', value: 75 },
start_21: { type: 'USHORT', value: 76 },
start_22: { type: 'USHORT', value: 77 },
start_23: { type: 'USHORT', value: 78 },
start_24: { type: 'USHORT', value: 79 },
start_25: { type: 'USHORT', value: 80 },
start_26: { type: 'USHORT', value: 81 },
start_27: { type: 'USHORT', value: 82 },
start_28: { type: 'USHORT', value: 83 },
start_29: { type: 'USHORT', value: 84 },
start_30: { type: 'USHORT', value: 85 },
start_31: { type: 'USHORT', value: 86 },
start_32: { type: 'USHORT', value: 87 },
start_33: { type: 'USHORT', value: 88 },
start_34: { type: 'USHORT', value: 89 },
start_35: { type: 'USHORT', value: 90 },
start_36: { type: 'USHORT', value: 97 },
start_37: { type: 'USHORT', value: 98 },
start_38: { type: 'USHORT', value: 99 },
start_39: { type: 'USHORT', value: 100 },
start_40: { type: 'USHORT', value: 101 },
start_41: { type: 'USHORT', value: 102 },
start_42: { type: 'USHORT', value: 103 },
start_43: { type: 'USHORT', value: 104 },
start_44: { type: 'USHORT', value: 105 },
start_45: { type: 'USHORT', value: 106 },
start_46: { type: 'USHORT', value: 107 },
start_47: { type: 'USHORT', value: 108 },
start_48: { type: 'USHORT', value: 109 },
start_49: { type: 'USHORT', value: 110 },
start_50: { type: 'USHORT', value: 111 },
start_51: { type: 'USHORT', value: 112 },
start_52: { type: 'USHORT', value: 113 },
start_53: { type: 'USHORT', value: 114 },
start_54: { type: 'USHORT', value: 115 },
start_55: { type: 'USHORT', value: 116 },
start_56: { type: 'USHORT', value: 117 },
start_57: { type: 'USHORT', value: 118 },
start_58: { type: 'USHORT', value: 119 },
start_59: { type: 'USHORT', value: 120 },
start_60: { type: 'USHORT', value: 121 },
start_61: { type: 'USHORT', value: 122 },
start_62: { type: 'USHORT', value: 65535 },
idDelta_0: { type: 'SHORT', value: 4 },
idDelta_1: { type: 'SHORT', value: 4 },
idDelta_2: { type: 'SHORT', value: 4 },
idDelta_3: { type: 'SHORT', value: 4 },
idDelta_4: { type: 'SHORT', value: 4 },
idDelta_5: { type: 'SHORT', value: 4 },
idDelta_6: { type: 'SHORT', value: 4 },
idDelta_7: { type: 'SHORT', value: 4 },
idDelta_8: { type: 'SHORT', value: 4 },
idDelta_9: { type: 'SHORT', value: 4 },
idDelta_10: { type: 'SHORT', value: -39 },
idDelta_11: { type: 'SHORT', value: -39 },
idDelta_12: { type: 'SHORT', value: -39 },
idDelta_13: { type: 'SHORT', value: -39 },
idDelta_14: { type: 'SHORT', value: -39 },
idDelta_15: { type: 'SHORT', value: -39 },
idDelta_16: { type: 'SHORT', value: -39 },
idDelta_17: { type: 'SHORT', value: -39 },
idDelta_18: { type: 'SHORT', value: -39 },
idDelta_19: { type: 'SHORT', value: -39 },
idDelta_20: { type: 'SHORT', value: -39 },
idDelta_21: { type: 'SHORT', value: -39 },
idDelta_22: { type: 'SHORT', value: -39 },
idDelta_23: { type: 'SHORT', value: -39 },
idDelta_24: { type: 'SHORT', value: -39 },
idDelta_25: { type: 'SHORT', value: -39 },
idDelta_26: { type: 'SHORT', value: -39 },
idDelta_27: { type: 'SHORT', value: -39 },
idDelta_28: { type: 'SHORT', value: -39 },
idDelta_29: { type: 'SHORT', value: -39 },
idDelta_30: { type: 'SHORT', value: -39 },
idDelta_31: { type: 'SHORT', value: -39 },
idDelta_32: { type: 'SHORT', value: -39 },
idDelta_33: { type: 'SHORT', value: -39 },
idDelta_34: { type: 'SHORT', value: -39 },
idDelta_35: { type: 'SHORT', value: -39 },
idDelta_36: { type: 'SHORT', value: -97 },
idDelta_37: { type: 'SHORT', value: -97 },
idDelta_38: { type: 'SHORT', value: -97 },
idDelta_39: { type: 'SHORT', value: -97 },
idDelta_40: { type: 'SHORT', value: -97 },
idDelta_41: { type: 'SHORT', value: -97 },
idDelta_42: { type: 'SHORT', value: -97 },
idDelta_43: { type: 'SHORT', value: -97 },
idDelta_44: { type: 'SHORT', value: -97 },
idDelta_45: { type: 'SHORT', value: -97 },
idDelta_46: { type: 'SHORT', value: -97 },
idDelta_47: { type: 'SHORT', value: -97 },
idDelta_48: { type: 'SHORT', value: -97 },
idDelta_49: { type: 'SHORT', value: -97 },
idDelta_50: { type: 'SHORT', value: -97 },
idDelta_51: { type: 'SHORT', value: -97 },
idDelta_52: { type: 'SHORT', value: -97 },
idDelta_53: { type: 'SHORT', value: -97 },
idDelta_54: { type: 'SHORT', value: -97 },
idDelta_55: { type: 'SHORT', value: -97 },
idDelta_56: { type: 'SHORT', value: -97 },
idDelta_57: { type: 'SHORT', value: -97 },
idDelta_58: { type: 'SHORT', value: -97 },
idDelta_59: { type: 'SHORT', value: -97 },
idDelta_60: { type: 'SHORT', value: -97 },
idDelta_61: { type: 'SHORT', value: -97 },
idDelta_62: { type: 'SHORT', value: 1 },
idRangeOffset_0: { type: 'USHORT', value: 0 },
idRangeOffset_1: { type: 'USHORT', value: 0 },
idRangeOffset_2: { type: 'USHORT', value: 0 },
idRangeOffset_3: { type: 'USHORT', value: 0 },
idRangeOffset_4: { type: 'USHORT', value: 0 },
idRangeOffset_5: { type: 'USHORT', value: 0 },
idRangeOffset_6: { type: 'USHORT', value: 0 },
idRangeOffset_7: { type: 'USHORT', value: 0 },
idRangeOffset_8: { type: 'USHORT', value: 0 },
idRangeOffset_9: { type: 'USHORT', value: 0 },
idRangeOffset_10: { type: 'USHORT', value: 0 },
idRangeOffset_11: { type: 'USHORT', value: 0 },
idRangeOffset_12: { type: 'USHORT', value: 0 },
idRangeOffset_13: { type: 'USHORT', value: 0 },
idRangeOffset_14: { type: 'USHORT', value: 0 },
idRangeOffset_15: { type: 'USHORT', value: 0 },
idRangeOffset_16: { type: 'USHORT', value: 0 },
idRangeOffset_17: { type: 'USHORT', value: 0 },
idRangeOffset_18: { type: 'USHORT', value: 0 },
idRangeOffset_19: { type: 'USHORT', value: 0 },
idRangeOffset_20: { type: 'USHORT', value: 0 },
idRangeOffset_21: { type: 'USHORT', value: 0 },
idRangeOffset_22: { type: 'USHORT', value: 0 },
idRangeOffset_23: { type: 'USHORT', value: 0 },
idRangeOffset_24: { type: 'USHORT', value: 0 },
idRangeOffset_25: { type: 'USHORT', value: 0 },
idRangeOffset_26: { type: 'USHORT', value: 0 },
idRangeOffset_27: { type: 'USHORT', value: 0 },
idRangeOffset_28: { type: 'USHORT', value: 0 },
idRangeOffset_29: { type: 'USHORT', value: 0 },
idRangeOffset_30: { type: 'USHORT', value: 0 },
idRangeOffset_31: { type: 'USHORT', value: 0 },
idRangeOffset_32: { type: 'USHORT', value: 0 },
idRangeOffset_33: { type: 'USHORT', value: 0 },
idRangeOffset_34: { type: 'USHORT', value: 0 },
idRangeOffset_35: { type: 'USHORT', value: 0 },
idRangeOffset_36: { type: 'USHORT', value: 0 },
idRangeOffset_37: { type: 'USHORT', value: 0 },
idRangeOffset_38: { type: 'USHORT', value: 0 },
idRangeOffset_39: { type: 'USHORT', value: 0 },
idRangeOffset_40: { type: 'USHORT', value: 0 },
idRangeOffset_41: { type: 'USHORT', value: 0 },
idRangeOffset_42: { type: 'USHORT', value: 0 },
idRangeOffset_43: { type: 'USHORT', value: 0 },
idRangeOffset_44: { type: 'USHORT', value: 0 },
idRangeOffset_45: { type: 'USHORT', value: 0 },
idRangeOffset_46: { type: 'USHORT', value: 0 },
idRangeOffset_47: { type: 'USHORT', value: 0 },
idRangeOffset_48: { type: 'USHORT', value: 0 },
idRangeOffset_49: { type: 'USHORT', value: 0 },
idRangeOffset_50: { type: 'USHORT', value: 0 },
idRangeOffset_51: { type: 'USHORT', value: 0 },
idRangeOffset_52: { type: 'USHORT', value: 0 },
idRangeOffset_53: { type: 'USHORT', value: 0 },
idRangeOffset_54: { type: 'USHORT', value: 0 },
idRangeOffset_55: { type: 'USHORT', value: 0 },
idRangeOffset_56: { type: 'USHORT', value: 0 },
idRangeOffset_57: { type: 'USHORT', value: 0 },
idRangeOffset_58: { type: 'USHORT', value: 0 },
idRangeOffset_59: { type: 'USHORT', value: 0 },
idRangeOffset_60: { type: 'USHORT', value: 0 },
idRangeOffset_61: { type: 'USHORT', value: 0 },
idRangeOffset_62: { type: 'USHORT', value: 0 } } }
With the encoded output as an array of 8-bit integers like this:
0 0 0 1 0 0 0 6 0 0 0 12 0 4 0 16 0 0 0 126 0 64 0 5 0 62 0 48 0 49 0 50 0 51 0 52 0 53 0 54 0 55 0 56 0 57 0 65 0 66 0 67 0 68 0 69 0 70 0 71 0 72 0 73 0 74 0 75 0 76 0 77 0 78 0 79 0 80 0 81 0 82 0 83 0 84 0 85 0 86 0 87 0 88 0 89 0 90 0 97 0 98 0 99 0 100 0 101 0 102 0 103 0 104 0 105 0 106 0 107 0 108 0 109 0 110 0 111 0 112 0 113 0 114 0 115 0 116 0 117 0 118 0 119 0 120 0 121 0 122 255 255 0 0 0 48 0 49 0 50 0 51 0 52 0 53 0 54 0 55 0 56 0 57 0 65 0 66 0 67 0 68 0 69 0 70 0 71 0 72 0 73 0 74 0 75 0 76 0 77 0 78 0 79 0 80 0 81 0 82 0 83 0 84 0 85 0 86 0 87 0 88 0 89 0 90 0 97 0 98 0 99 0 100 0 101 0 102 0 103 0 104 0 105 0 106 0 107 0 108 0 109 0 110 0 111 0 112 0 113 0 114 0 115 0 116 0 117 0 118 0 119 0 120 0 121 0 122 255 255 0 4 0 4 0 4 0 4 0 4 0 4 0 4 0 4 0 4 0 4 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 217 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 255 159 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
I am not sure how to best debug this, but I wanted to ask if this looks right, or what I should do to debug. Not asking if the exact values are right, but the values I am pretty sure I entered in correctly are everything up to rangeShift
. After that it is generated. But those values from segCountX2
to rangeShift
, even though I think I'm getting them right, I keep getting this error: OTS parsing error: incorrect entrySelector for table directory
, even if I just make the font-file only have all the fields up to that point! So the font file is tiny, but still the same error. I am doing the calculations according to the spec, like this:
var numTables = tables.length
var highestPowerOf2 = Math.pow(2, Math.log2(numTables))
var searchRange = 16 * highestPowerOf2
var entrySelector = Math.log2(highestPowerOf2) * 16
var rangeShift = (numTables * 16) - searchRange
var fields = {
sfntVersion: { type: 'TAG', value: 'OTTO'},
numTables: { type: 'USHORT', value: numTables},
searchRange: { type: 'USHORT', value: searchRange},
entrySelector: { type: 'USHORT', value: entrySelector},
rangeShift: { type: 'USHORT', value: rangeShift},
}
But still not working. I have also tried this.
回答1:
It seems to have been fixed by switching to use the Apple reference instead of Microsofts for the calculations:
https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6.html
The offset subtable, documented in Table 4, begins with the scaler type of the font. The number of tagged tables in the 'sfnt' follows.The table directory itself and any subtables are not included in this count. The entries for searchRange, entrySelector and rangeShift are used to facilitate quick binary searches of the table directory that follows. Unless a font has a large number of tables, a sequential search will be fast enough.
If a faster search is necessary, a binary search is most easily done on a number of entries that is a power of two. This makes it possible to cut the number of items to search in half by shifting. The remaining offset subtable entries should be set as follows:
searchRange is the largest power of two less than or equal to the number of items in the table, i.e. the largest number of items that can be easily searched. rangeShift is the number of items minus searchRange; i.e. the number of items that will not get looked at if you only look at searchRange items. Before the search loop starts, compare the target item to the item with number rangeShift. If the target item is less than rangeShift, search from the beginning of the table. If it is greater, search starting at the item with number rangeShift.
entrySelector is log2(searchRange). It tells how many iterations of the search loop are needed. (i.e. how many times to cut the range in half) Note that the searchRange, the entrySelector and the rangeShift are all multiplied by 16 which represents the size of a directory entry.
来源:https://stackoverflow.com/questions/54216664/ots-parsing-error-incorrect-entryselector-for-table-directory-opentype-font-er