webamp/js/skinParser.js
2017-03-20 23:14:15 +00:00

105 lines
2.8 KiB
JavaScript

import SKIN_SPRITES from "./skinSprites";
import JSZip from "../node_modules/jszip/dist/jszip"; // Hack
import { parseViscolors, parseIni } from "./utils";
const bmpUriFromFile = file => `data:image/bmp;base64,${btoa(file.asBinary())}`;
// "Promisify" processBuffer
const getBufferFromFile = file =>
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 =>
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 => ({
...spriteObj,
colors: parseViscolors(spriteObj.file.asText())
});
// Extract the color data from a VISCOLOR.TXT file and add it to the object
const extractPlaylistStyle = spriteObj => ({
...spriteObj,
playlistStyle: parseIni(spriteObj.file.asText())
});
const getSkinDataFromFiles = spriteObjs =>
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 =>
getBufferFromFile(file)
.then(getZipFromBuffer)
.then(getSpriteSheetFilesFromZip)
.then(getSkinDataFromFiles)
.then(collectCssAndColors);
export default parseSkin;