src/asset-loaders/FontAsset.js
import Asset from '../systems/AssetSystem/Asset';
const regexNewLine = /[\r\n]+/;
const regexWhiteSpaces = /\s+/;
const regexKeyValuePair = /(\w+)=("(.*)"|(-?\d+)(,(-?\d+))?(,(-?\d+))?(,(-?\d+))?)/;
function getLineData(line) {
const words = line.split(regexWhiteSpaces);
if (words.length < 1) {
throw new Error(`There is no words in line: ${line}`);
}
const result = {
id: words[0],
data: {}
};
for (let i = 1, c = words.length; i < c; ++i) {
const word = words[i];
const matches = regexKeyValuePair.exec(word);
if (!matches) {
throw new Error(`There is no key-value in word: ${word}`);
}
const [ , key,, txt, num0,, num1,, num2,, num3 ] = matches;
if (typeof txt !== 'undefined') {
result.data[key] = txt;
} else if (typeof num3 !== 'undefined') {
result.data[key] = [
parseInt(num0),
parseInt(num1),
parseInt(num2),
parseInt(num3)
];
} else if (typeof num2 !== 'undefined') {
result.data[key] = [
parseInt(num0),
parseInt(num1),
parseInt(num2)
];
} else if (typeof num1 !== 'undefined') {
result.data[key] = [
parseInt(num0),
parseInt(num1)
];
} else if (typeof num0 !== 'undefined') {
result.data[key] = parseInt(num0);
}
}
return result;
}
/**
* Font asset loader.
*/
export default class FontAsset extends Asset {
/**
* Asset factory.
*
* @param {*} args - Factory parameters.
*
* @return {FontAsset} Asset instance.
*
* @example
* system.registerProtocol('font', FontAsset.factory);
*/
static factory(...args) {
return new FontAsset(...args);
}
/**
* @override
*/
constructor(...args) {
super(...args);
this._descriptor = null;
this._textAsset = null;
this._imageAssets = null;
}
/**
* @override
*/
dispose() {
super.dispose();
const { _descriptor, _textAsset, _imageAssets } = this;
if (!!_descriptor) {
_descriptor.pages.clear();
_descriptor.chars.clear();
}
if (!!_textAsset) {
_textAsset.dispose();
}
if (!!_imageAssets) {
for (let i = 0, c = _imageAssets.length; i < c; ++i) {
_imageAssets[i].dispose();
}
}
this._descriptor = null;
this._textAsset = null;
this._imageAssets = null;
}
/**
* @override
*/
load() {
const { filename, owner } = this;
return owner.load(`text://${filename}`)
.then(textAsset => {
const data = textAsset.data;
this._textAsset = textAsset;
const descriptor = this._descriptor = {
info: null,
common: null,
pages: new Map(),
chars: new Map()
};
const lines = data.split(regexNewLine);
const images = [];
for (let i = 0, c = lines.length; i < c; ++i) {
const meta = getLineData(lines[i]);
const { id } = meta;
if (id === 'info') {
descriptor.info = meta.data;
} else if (id === 'common') {
descriptor.common = meta.data;
} else if (id === 'page') {
descriptor.pages.set(meta.data.id, meta.data);
images.push(meta.data.file);
} else if (id === 'char') {
descriptor.chars.set(meta.data.id, meta.data);
}
}
return images;
})
.then(paths => owner.loadSequence(paths.map(path => `image://${path}`)))
.then(imageAssets => {
this._imageAssets = imageAssets;
this.data = {
descriptor: this._descriptor,
images: imageAssets.map(asset => asset.data)
};
return this;
});
}
}