
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
import r from '@foliojs-fork/restructure';
class UnboundedArrayAccessor {
constructor(type, stream, parent) {
this.type = type;
this.stream = stream;
this.parent = parent;
this.base = this.stream.pos;
this._items = [];
}
getItem(index) {
if (this._items[index] == null) {
let pos = this.stream.pos;
this.stream.pos = this.base + this.type.size(null, this.parent) * index;
this._items[index] = this.type.decode(this.stream, this.parent);
this.stream.pos = pos;
}
return this._items[index];
}
inspect() {
return `[UnboundedArray ${this.type.constructor.name}]`;
}
}
export class UnboundedArray extends r.Array {
constructor(type) {
super(type, 0);
}
decode(stream, parent) {
return new UnboundedArrayAccessor(this.type, stream, parent);
}
}
export let LookupTable = function(ValueType = r.uint16) {
// Helper class that makes internal structures invisible to pointers
class Shadow {
constructor(type) {
this.type = type;
}
decode(stream, ctx) {
ctx = ctx.parent.parent;
return this.type.decode(stream, ctx);
}
size(val, ctx) {
ctx = ctx.parent.parent;
return this.type.size(val, ctx);
}
encode(stream, val, ctx) {
ctx = ctx.parent.parent;
return this.type.encode(stream, val, ctx);
}
}
ValueType = new Shadow(ValueType);
let BinarySearchHeader = new r.Struct({
unitSize: r.uint16,
nUnits: r.uint16,
searchRange: r.uint16,
entrySelector: r.uint16,
rangeShift: r.uint16
});
let LookupSegmentSingle = new r.Struct({
lastGlyph: r.uint16,
firstGlyph: r.uint16,
value: ValueType
});
let LookupSegmentArray = new r.Struct({
lastGlyph: r.uint16,
firstGlyph: r.uint16,
values: new r.Pointer(r.uint16, new r.Array(ValueType, t => t.lastGlyph - t.firstGlyph + 1), {type: 'parent'})
});
let LookupSingle = new r.Struct({
glyph: r.uint16,
value: ValueType
});
return new r.VersionedStruct(r.uint16, {
0: {
values: new UnboundedArray(ValueType) // length == number of glyphs maybe?
},
2: {
binarySearchHeader: BinarySearchHeader,
segments: new r.Array(LookupSegmentSingle, t => t.binarySearchHeader.nUnits)
},
4: {
binarySearchHeader: BinarySearchHeader,
segments: new r.Array(LookupSegmentArray, t => t.binarySearchHeader.nUnits)
},
6: {
binarySearchHeader: BinarySearchHeader,
segments: new r.Array(LookupSingle, t => t.binarySearchHeader.nUnits)
},
8: {
firstGlyph: r.uint16,
count: r.uint16,
values: new r.Array(ValueType, 'count')
}
});
};
export function StateTable(entryData = {}, lookupType = r.uint16) {
let entry = Object.assign({
newState: r.uint16,
flags: r.uint16
}, entryData);
let Entry = new r.Struct(entry);
let StateArray = new UnboundedArray(new r.Array(r.uint16, t => t.nClasses));
let StateHeader = new r.Struct({
nClasses: r.uint32,
classTable: new r.Pointer(r.uint32, new LookupTable(lookupType)),
stateArray: new r.Pointer(r.uint32, StateArray),
entryTable: new r.Pointer(r.uint32, new UnboundedArray(Entry))
});
return StateHeader;
}
// This is the old version of the StateTable structure
export function StateTable1(entryData = {}, lookupType = r.uint16) {
let ClassLookupTable = new r.Struct({
version() { return 8; }, // simulate LookupTable
firstGlyph: r.uint16,
values: new r.Array(r.uint8, r.uint16)
});
let entry = Object.assign({
newStateOffset: r.uint16,
// convert offset to stateArray index
newState: t => (t.newStateOffset - (t.parent.stateArray.base - t.parent._startOffset)) / t.parent.nClasses,
flags: r.uint16
}, entryData);
let Entry = new r.Struct(entry);
let StateArray = new UnboundedArray(new r.Array(r.uint8, t => t.nClasses));
let StateHeader1 = new r.Struct({
nClasses: r.uint16,
classTable: new r.Pointer(r.uint16, ClassLookupTable),
stateArray: new r.Pointer(r.uint16, StateArray),
entryTable: new r.Pointer(r.uint16, new UnboundedArray(Entry))
});
return StateHeader1;
}