|
|
import r from 'restructure';
|
|
|
|
|
|
let SubHeader = new r.Struct({
|
|
|
firstCode: r.uint16,
|
|
|
entryCount: r.uint16,
|
|
|
idDelta: r.int16,
|
|
|
idRangeOffset: r.uint16
|
|
|
});
|
|
|
|
|
|
let CmapGroup = new r.Struct({
|
|
|
startCharCode: r.uint32,
|
|
|
endCharCode: r.uint32,
|
|
|
glyphID: r.uint32
|
|
|
});
|
|
|
|
|
|
let UnicodeValueRange = new r.Struct({
|
|
|
startUnicodeValue: r.uint24,
|
|
|
additionalCount: r.uint8
|
|
|
});
|
|
|
|
|
|
let UVSMapping = new r.Struct({
|
|
|
unicodeValue: r.uint24,
|
|
|
glyphID: r.uint16
|
|
|
});
|
|
|
|
|
|
let DefaultUVS = new r.Array(UnicodeValueRange, r.uint32);
|
|
|
let NonDefaultUVS = new r.Array(UVSMapping, r.uint32);
|
|
|
|
|
|
let VarSelectorRecord = new r.Struct({
|
|
|
varSelector: r.uint24,
|
|
|
defaultUVS: new r.Pointer(r.uint32, DefaultUVS, {type: 'parent'}),
|
|
|
nonDefaultUVS: new r.Pointer(r.uint32, NonDefaultUVS, {type: 'parent'})
|
|
|
});
|
|
|
|
|
|
let CmapSubtable = new r.VersionedStruct(r.uint16, {
|
|
|
0: { // Byte encoding
|
|
|
length: r.uint16, // Total table length in bytes (set to 262 for format 0)
|
|
|
language: r.uint16, // Language code for this encoding subtable, or zero if language-independent
|
|
|
codeMap: new r.LazyArray(r.uint8, 256)
|
|
|
},
|
|
|
|
|
|
2: { // High-byte mapping (CJK)
|
|
|
length: r.uint16,
|
|
|
language: r.uint16,
|
|
|
subHeaderKeys: new r.Array(r.uint16, 256),
|
|
|
subHeaderCount: t => Math.max.apply(Math, t.subHeaderKeys),
|
|
|
subHeaders: new r.LazyArray(SubHeader, 'subHeaderCount'),
|
|
|
glyphIndexArray: new r.LazyArray(r.uint16, 'subHeaderCount')
|
|
|
},
|
|
|
|
|
|
4: { // Segment mapping to delta values
|
|
|
length: r.uint16, // Total table length in bytes
|
|
|
language: r.uint16, // Language code
|
|
|
segCountX2: r.uint16,
|
|
|
segCount: t => t.segCountX2 >> 1,
|
|
|
searchRange: r.uint16,
|
|
|
entrySelector: r.uint16,
|
|
|
rangeShift: r.uint16,
|
|
|
endCode: new r.LazyArray(r.uint16, 'segCount'),
|
|
|
reservedPad: new r.Reserved(r.uint16), // This value should be zero
|
|
|
startCode: new r.LazyArray(r.uint16, 'segCount'),
|
|
|
idDelta: new r.LazyArray(r.int16, 'segCount'),
|
|
|
idRangeOffset: new r.LazyArray(r.uint16, 'segCount'),
|
|
|
glyphIndexArray: new r.LazyArray(r.uint16, t => (t.length - t._currentOffset) / 2)
|
|
|
},
|
|
|
|
|
|
6: { // Trimmed table
|
|
|
length: r.uint16,
|
|
|
language: r.uint16,
|
|
|
firstCode: r.uint16,
|
|
|
entryCount: r.uint16,
|
|
|
glyphIndices: new r.LazyArray(r.uint16, 'entryCount')
|
|
|
},
|
|
|
|
|
|
8: { // mixed 16-bit and 32-bit coverage
|
|
|
reserved: new r.Reserved(r.uint16),
|
|
|
length: r.uint32,
|
|
|
language: r.uint16,
|
|
|
is32: new r.LazyArray(r.uint8, 8192),
|
|
|
nGroups: r.uint32,
|
|
|
groups: new r.LazyArray(CmapGroup, 'nGroups')
|
|
|
},
|
|
|
|
|
|
10: { // Trimmed Array
|
|
|
reserved: new r.Reserved(r.uint16),
|
|
|
length: r.uint32,
|
|
|
language: r.uint32,
|
|
|
firstCode: r.uint32,
|
|
|
entryCount: r.uint32,
|
|
|
glyphIndices: new r.LazyArray(r.uint16, 'numChars')
|
|
|
},
|
|
|
|
|
|
12: { // Segmented coverage
|
|
|
reserved: new r.Reserved(r.uint16),
|
|
|
length: r.uint32,
|
|
|
language: r.uint32,
|
|
|
nGroups: r.uint32,
|
|
|
groups: new r.LazyArray(CmapGroup, 'nGroups')
|
|
|
},
|
|
|
|
|
|
13: { // Many-to-one range mappings (same as 12 except for group.startGlyphID)
|
|
|
reserved: new r.Reserved(r.uint16),
|
|
|
length: r.uint32,
|
|
|
language: r.uint32,
|
|
|
nGroups: r.uint32,
|
|
|
groups: new r.LazyArray(CmapGroup, 'nGroups')
|
|
|
},
|
|
|
|
|
|
14: { // Unicode Variation Sequences
|
|
|
length: r.uint32,
|
|
|
numRecords: r.uint32,
|
|
|
varSelectors: new r.LazyArray(VarSelectorRecord, 'numRecords')
|
|
|
}
|
|
|
});
|
|
|
|
|
|
let CmapEntry = new r.Struct({
|
|
|
platformID: r.uint16, // Platform identifier
|
|
|
encodingID: r.uint16, // Platform-specific encoding identifier
|
|
|
table: new r.Pointer(r.uint32, CmapSubtable, {type: 'parent', lazy: true})
|
|
|
});
|
|
|
|
|
|
// character to glyph mapping
|
|
|
export default new r.Struct({
|
|
|
version: r.uint16,
|
|
|
numSubtables: r.uint16,
|
|
|
tables: new r.Array(CmapEntry, 'numSubtables')
|
|
|
});
|
|
|
|