thedesk/app/node_modules/parse-bmfont-binary/index.js
2019-09-12 23:38:13 +09:00

160 lines
3.8 KiB
JavaScript

var HEADER = [66, 77, 70]
module.exports = function readBMFontBinary(buf) {
if (buf.length < 6)
throw new Error('invalid buffer length for BMFont')
var header = HEADER.every(function(byte, i) {
return buf.readUInt8(i) === byte
})
if (!header)
throw new Error('BMFont missing BMF byte header')
var i = 3
var vers = buf.readUInt8(i++)
if (vers > 3)
throw new Error('Only supports BMFont Binary v3 (BMFont App v1.10)')
var target = { kernings: [], chars: [] }
for (var b=0; b<5; b++)
i += readBlock(target, buf, i)
return target
}
function readBlock(target, buf, i) {
if (i > buf.length-1)
return 0
var blockID = buf.readUInt8(i++)
var blockSize = buf.readInt32LE(i)
i += 4
switch(blockID) {
case 1:
target.info = readInfo(buf, i)
break
case 2:
target.common = readCommon(buf, i)
break
case 3:
target.pages = readPages(buf, i, blockSize)
break
case 4:
target.chars = readChars(buf, i, blockSize)
break
case 5:
target.kernings = readKernings(buf, i, blockSize)
break
}
return 5 + blockSize
}
function readInfo(buf, i) {
var info = {}
info.size = buf.readInt16LE(i)
var bitField = buf.readUInt8(i+2)
info.smooth = (bitField >> 7) & 1
info.unicode = (bitField >> 6) & 1
info.italic = (bitField >> 5) & 1
info.bold = (bitField >> 4) & 1
//fixedHeight is only mentioned in binary spec
if ((bitField >> 3) & 1)
info.fixedHeight = 1
info.charset = buf.readUInt8(i+3) || ''
info.stretchH = buf.readUInt16LE(i+4)
info.aa = buf.readUInt8(i+6)
info.padding = [
buf.readInt8(i+7),
buf.readInt8(i+8),
buf.readInt8(i+9),
buf.readInt8(i+10)
]
info.spacing = [
buf.readInt8(i+11),
buf.readInt8(i+12)
]
info.outline = buf.readUInt8(i+13)
info.face = readStringNT(buf, i+14)
return info
}
function readCommon(buf, i) {
var common = {}
common.lineHeight = buf.readUInt16LE(i)
common.base = buf.readUInt16LE(i+2)
common.scaleW = buf.readUInt16LE(i+4)
common.scaleH = buf.readUInt16LE(i+6)
common.pages = buf.readUInt16LE(i+8)
var bitField = buf.readUInt8(i+10)
common.packed = 0
common.alphaChnl = buf.readUInt8(i+11)
common.redChnl = buf.readUInt8(i+12)
common.greenChnl = buf.readUInt8(i+13)
common.blueChnl = buf.readUInt8(i+14)
return common
}
function readPages(buf, i, size) {
var pages = []
var text = readNameNT(buf, i)
var len = text.length+1
var count = size / len
for (var c=0; c<count; c++) {
pages[c] = buf.slice(i, i+text.length).toString('utf8')
i += len
}
return pages
}
function readChars(buf, i, blockSize) {
var chars = []
var count = blockSize / 20
for (var c=0; c<count; c++) {
var char = {}
var off = c*20
char.id = buf.readUInt32LE(i + 0 + off)
char.x = buf.readUInt16LE(i + 4 + off)
char.y = buf.readUInt16LE(i + 6 + off)
char.width = buf.readUInt16LE(i + 8 + off)
char.height = buf.readUInt16LE(i + 10 + off)
char.xoffset = buf.readInt16LE(i + 12 + off)
char.yoffset = buf.readInt16LE(i + 14 + off)
char.xadvance = buf.readInt16LE(i + 16 + off)
char.page = buf.readUInt8(i + 18 + off)
char.chnl = buf.readUInt8(i + 19 + off)
chars[c] = char
}
return chars
}
function readKernings(buf, i, blockSize) {
var kernings = []
var count = blockSize / 10
for (var c=0; c<count; c++) {
var kern = {}
var off = c*10
kern.first = buf.readUInt32LE(i + 0 + off)
kern.second = buf.readUInt32LE(i + 4 + off)
kern.amount = buf.readInt16LE(i + 8 + off)
kernings[c] = kern
}
return kernings
}
function readNameNT(buf, offset) {
var pos=offset
for (; pos<buf.length; pos++) {
if (buf[pos] === 0x00)
break
}
return buf.slice(offset, pos)
}
function readStringNT(buf, offset) {
return readNameNT(buf, offset).toString('utf8')
}