webamp/js/skinParser.js
2016-08-29 20:15:21 -07:00

113 lines
2.9 KiB
JavaScript

import SKIN_SPRITES from './skinSprites';
import JSZip from '../node_modules/jszip/dist/jszip'; // Hack
import {parseViscolors, parseIni} from './utils';
const bmpUriFromFile = (file) => {
return `data:image/bmp;base64,${btoa(file.asBinary())}`;
};
// "Promisify" processBuffer
const getBufferFromFile = (file) => {
return new Promise((resolve) => {
file.processBuffer(resolve);
});
};
const getZipFromBuffer = (buffer) => new JSZip(buffer);
const getSpriteSheetFilesFromZip = (zip) => {
const spriteObjs = SKIN_SPRITES.map((spriteObj) => ({
...spriteObj,
file: zip.file(new RegExp(`(/|^)${spriteObj.name}`, 'i'))[0]
}));
return spriteObjs.filter((spriteObj) => spriteObj.file);
};
// Extract the CSS rules for a given file, and add them to the object
const extractCss = (spriteObj) => {
return new Promise((resolve) => {
const uri = bmpUriFromFile(spriteObj.file);
const img = new Image();
img.onload = () => {
const canvas = document.createElement('canvas');
const images = {};
spriteObj.sprites.forEach((sprite) => {
canvas.height = sprite.height;
canvas.width = sprite.width;
const context = canvas.getContext('2d');
context.drawImage(img, -sprite.x, -sprite.y);
const image = canvas.toDataURL();
if (sprite.name) {
images[sprite.name] = image;
}
});
resolve({...spriteObj, images});
};
img.src = uri;
});
};
// Extract the color data from a VISCOLOR.TXT file and add it to the object
const extractColors = (spriteObj) => {
return {
...spriteObj,
colors: parseViscolors(spriteObj.file.asText())
};
};
// Extract the color data from a VISCOLOR.TXT file and add it to the object
const extractPlaylistStyle = (spriteObj) => {
return {
...spriteObj,
playlistStyle: parseIni(spriteObj.file.asText())
};
};
const getSkinDataFromFiles = (spriteObjs) => {
return Promise.all(spriteObjs.map((spriteObj) => {
switch (spriteObj.name) {
case 'VISCOLOR':
return extractColors(spriteObj);
case 'PLEDIT.TXT':
return extractPlaylistStyle(spriteObj);
default:
return extractCss(spriteObj);
}
}));
};
const collectCssAndColors = (spriteObjs) => {
let images = {};
let colors = null;
let playlistStyle = null;
spriteObjs.forEach((spriteObj) => {
if (spriteObj.images) {
images = {...images, ...spriteObj.images};
}
if (spriteObj.colors) {
colors = spriteObj.colors;
}
if (spriteObj.playlistStyle) {
playlistStyle = spriteObj.playlistStyle;
}
});
return {
images,
colors,
playlistStyle
};
};
// A promise that, given a File object, returns a skin style object
const parseSkin = (file) => {
return getBufferFromFile(file)
.then(getZipFromBuffer)
.then(getSpriteSheetFilesFromZip)
.then(getSkinDataFromFiles)
.then(collectCssAndColors);
};
module.exports = parseSkin;