Start abstracting skin data

This commit is contained in:
Jordan Eldredge 2015-02-07 18:10:16 -08:00
parent e75a06a96e
commit e74eded3f1
5 changed files with 150 additions and 119 deletions

View file

@ -64,23 +64,9 @@
left: 0;
height: 14px;
width: 275px;
/* background-image: TITLEBAR.BMP via Javascript */
background-position: -27px -14px;
cursor:url('../cursors/TITLEBAR.PNG?inline'), auto;
}
#title-bar.selected {
background-position: -27px 0px;
}
.llama #title-bar {
background-position: -27px -61px;
}
.llama #title-bar.selected {
background-position: -27px -57px;
}
#option,
#minimize,
#shade,
@ -101,11 +87,6 @@
top: 12px;
left: 0px;
}
#title-bar #option:active,
#title-bar #option.selected
{
background-position: 0 -9px;
}
#title-bar #option:active #context-menu,
#title-bar #option.selected #context-menu
{
@ -114,44 +95,20 @@
#title-bar #minimize {
left: 244px;
/* background-image: TITLEBAR.BMP via Javascript */
background-position: -9px 0;
}
#title-bar #minimize:active {
background-position: -9px -9px;
}
#title-bar #shade {
left: 254px;
/* background-image: TITLEBAR.BMP via Javascript */
background-position: 0px -18px;
}
#title-bar #shade:active {
background-position: -9px -18px;
}
#title-bar #close {
left: 264px;
/* background-image: TITLEBAR.BMP via Javascript */
background-position: -18px 0px;
cursor:url('../cursors/CLOSE.PNG?inline'), auto;
}
#title-bar #close:active {
background-position: -18px -9px;
}
.status #clutter-bar {
#clutter-bar {
position: absolute;
top: 22px;
left: 10px;
height: 43px;
width: 8px;
/* background-image: TITLEBAR.BMP via Javascript */
background-position: -304px 0;
}
.status #clutter-bar.disabled {
background-position: -312px 0;
}
#clutter-bar div {
@ -165,38 +122,21 @@
top: 3px;
height: 8px;
}
#clutter-bar #button-o:active {
background-position: -304px -47px;
}
#clutter-bar #button-a {
top: 11px;
}
#clutter-bar #button-a:active,
#clutter-bar #button-a.selected {
background-position: -312px -55px;
}
#clutter-bar #button-i {
top: 18px;
}
#clutter-bar #button-i:active {
background-position: -320px -62px;
}
#clutter-bar #button-d {
top: 25px;
height: 8px;
}
#clutter-bar #button-d:active,
#clutter-bar #button-d.selected {
background-position: -328px -69px;
}
#clutter-bar #button-v {
top: 33px;
}
#clutter-bar #button-v:active {
background-position: -336px -77px;
}
.status #play-pause {
#play-pause {
position: absolute;
top: 28px;
left: 26px;
@ -206,7 +146,7 @@
background-repeat: no-repeat;
}
.play .status #work-indicator {
.play #work-indicator {
position: absolute;
top: 28px;
left: 24px;
@ -215,13 +155,6 @@
/* background-image: PLAYPAUS.BMP via Javascript */
background-position: -36px 0;
}
.play .status #work-indicator.selected {
background-position: -39px 0;
}
.play .status #play-pause { }
.pause .status #play-pause { background-position: -9px 0; }
.stop .status #play-pause { background-position: -18px 0; }
.status #time {
position: absolute;
left: 39px;
@ -243,23 +176,14 @@
left: -1px;
width: 5px;
height: 1px;
/* background-image: NUMBERS.BMP via Javascript */
background-position: -9px -6px;
}
.status #time.countdown #minus-sign {
background-position: -20px -6px;
}
/* Alternate format for minus sign, when skin supports it */
.status #time.ex #minus-sign {
top: 0px;
left: -1px;
width: 9px;
height: 13px;
/* background-image: NUMS_EX.BMP via Javascript */
background-position: -90px 0px;
}
.status #time.ex.countdown #minus-sign {
background-position: -99px 0px;
}
.status #time #minute-first-digit {
@ -658,20 +582,9 @@
display: none;
}
.shade #title-bar {
background-position: -27px -42px;
cursor:url('../cursors/MAINMENU.PNG?inline'), auto;
}
.shade #title-bar.selected {
background-position: -27px -29px;
}
.shade #title-bar #shade {
background-position: 0px -27px;
}
.shade #title-bar #shade:active {
background-position: -9px -27px;
}
.shade .actions div {
background: none;
position: absolute;

View file

@ -117,6 +117,7 @@
<script src="js/visualizer.js?inline"></script>
<script src="js/media.js?inline"></script>
<script src="js/font.js?inline"></script>
<script src="js/skin-sprites.js?inline"></script>
<script src="js/skin.js?inline"></script>
<script src="js/multi-display.js?inline"></script>
<script src="js/hotkeys.js?inline"></script>

View file

@ -32,13 +32,9 @@ Font = {
// Get a <div> containing a digit
digitNode: function(digit) {
var horizontalOffset = digit * 9;
var div = document.createElement('div');
div.classList.add('digit');
// Ex rules superseed if nums_ex.bmp is present
div.classList.add('digit-ex');
div.style.backgroundPosition = '-' + horizontalOffset + 'px 0';
div.innerHTML = digit;
div.classList.add('digit-' + digit);
return div;
},

92
js/skin-sprites.js Normal file
View file

@ -0,0 +1,92 @@
var SKIN_SPRITES = [
{
img: "MAIN",
sprites: [
{ selectors: ["#main-window"], x: 0, y: 0, width: 275, height: 116}
]
},
{
img: "NUMBERS",
sprites: [
{ selectors: ["#time #minus-sign"], x: 9, y: 6, width: 5, height: 1},
{ selectors: ["#time.countdown #minus-sign"], x: 20, y: 6, width: 5, height: 1},
{ selectors: [".digit-0"], x: 0, y: 0, width: 9, height: 13},
{ selectors: [".digit-1"], x: 9, y: 0, width: 9, height: 13},
{ selectors: [".digit-2"], x: 18, y: 0, width: 9, height: 13},
{ selectors: [".digit-3"], x: 27, y: 0, width: 9, height: 13},
{ selectors: [".digit-4"], x: 36, y: 0, width: 9, height: 13},
{ selectors: [".digit-5"], x: 45, y: 0, width: 9, height: 13},
{ selectors: [".digit-6"], x: 54, y: 0, width: 9, height: 13},
{ selectors: [".digit-7"], x: 63, y: 0, width: 9, height: 13},
{ selectors: [".digit-8"], x: 72, y: 0, width: 9, height: 13},
{ selectors: [".digit-9"], x: 81, y: 0, width: 9, height: 13},
]
},
{
img: "NUMS_EX",
sprites: [
{ selectors: ["#time.ex #minus-sign"], x: 90, y: 0, width: 9, height: 13},
{ selectors: ["#time.ex.countdown #minus-sign"], x: 99, y: 0, width: 9, height: 13},
{ selectors: [".digit-0"], x: 0, y: 0, width: 9, height: 13},
{ selectors: [".digit-1"], x: 9, y: 0, width: 9, height: 13},
{ selectors: [".digit-2"], x: 18, y: 0, width: 9, height: 13},
{ selectors: [".digit-3"], x: 27, y: 0, width: 9, height: 13},
{ selectors: [".digit-4"], x: 36, y: 0, width: 9, height: 13},
{ selectors: [".digit-5"], x: 45, y: 0, width: 9, height: 13},
{ selectors: [".digit-6"], x: 54, y: 0, width: 9, height: 13},
{ selectors: [".digit-7"], x: 63, y: 0, width: 9, height: 13},
{ selectors: [".digit-8"], x: 72, y: 0, width: 9, height: 13},
{ selectors: [".digit-9"], x: 81, y: 0, width: 9, height: 13},
]
},
{
img: "PLAYPAUS",
sprites: [
{ selectors: [".play #play-pause"], x: 0, y: 0, width: 9, height: 9},
{ selectors: [".pause #play-pause"], x: 9, y: 0, width: 9, height: 9},
{ selectors: [".stop #play-pause"], x: 18, y: 0, width: 9, height: 9},
{ selectors: [".play #work-indicator"], x: 36, y: 0, width: 9, height: 9},
{ selectors: [".play #work-indicator.selected"], x: 39, y: 0, width: 9, height: 9}
]
},
{
img: "PLEDIT",
sprites: [
{ selectors: [".playlist-top-tile"], x: 127, y: 21, width: 25, height: 20},
{ selectors: [".selected .playlist-top-tile"], x: 127, y: 0, width: 25, height: 20},
{ selectors: [".playlist-left-tile"], x: 0, y: 42, width: 25, height: 29},
{ selectors: [".playlist-right-tile"], x: 27, y: 42, width: 25, height: 29},
{ selectors: [".playlist-bottom-tile"], x: 179, y: 0, width: 25, height: 38},
{ selectors: ["#playlist.shade"], x: 72, y: 57, width: 25, height: 14}
]
},
{
img: "TITLEBAR",
sprites: [
{ selectors: ["#title-bar"], x: 27, y: 15, width: 275, height: 14},
{ selectors: ["#title-bar.selected"], x: 27, y: 0, width: 275, height: 14},
{ selectors: [".lllama #title-bar"], x: 27, y: 61, width: 275, height: 14},
{ selectors: [".lllama #title-bar.selected"], x: 27, y: 57, width: 275, height: 14},
{ selectors: ["#title-bar #option"], x: 0, y: 0, width: 9, height: 9},
{ selectors: ["#title-bar #option"], x: 0, y: 0, width: 9, height: 9},
{ selectors: ["#title-bar #option:active", "#title-bar #option:selected"], x: 0, y: 9, width: 9, height: 9},
{ selectors: ["#title-bar #minimize"], x: 9, y: 0, width: 9, height: 9},
{ selectors: ["#title-bar #minimize:active"], x: 9, y: 9, width: 9, height: 9},
{ selectors: ["#title-bar #shade"], x: 0, y: 18, width: 9, height: 9},
{ selectors: ["#title-bar #shade:active"], x: 9, y: 18, width: 9, height: 9},
{ selectors: ["#title-bar #close"], x: 18, y: 0, width: 9, height: 9},
{ selectors: ["#title-bar #close:active"], x: 18, y: 9, width: 9, height: 9},
{ selectors: ["#clutter-bar"], x: 304, y: 0, width: 8, height: 43},
{ selectors: ["#clutter-bar.disabled"], x: 312, y: 0, width: 8, height: 43},
{ selectors: ["#button-o:active", "#button-0:selected"], x: 304, y: 47, width: 8, height: 8},
{ selectors: ["#button-a:active", "#button-a.selected"], x: 312, y: 55, width: 8, height: 7},
{ selectors: ["#button-i:active", "#button-i.selected"], x: 320, y: 62, width: 8, height: 7},
{ selectors: ["#button-d:active", "#button-d.selected"], x: 328, y: 69, width: 8, height: 8},
{ selectors: ["#button-v:active", "#button-v.selected"], x: 336, y: 77, width: 8, height: 7},
{ selectors: [".shade #title-bar"], x: 27, y: 42, width: 275, height: 14},
{ selectors: [".shade #title-bar.selected"], x: 27, y: 29, width: 275, height: 14},
{ selectors: [".shade #title-bar #shade"], x: 0, y: 27, width: 9, height: 9},
{ selectors: [".shade #title-bar #shade:active"], x: 9, y: 27, width: 9, height: 9}
]
},
];

View file

@ -8,19 +8,6 @@ SkinManager = {
},
_skinImages: {
"#main-window": "MAIN.BMP",
"#title-bar": "TITLEBAR.BMP",
"#title-bar #option": "TITLEBAR.BMP",
"#title-bar #minimize": "TITLEBAR.BMP",
"#title-bar #shade": "TITLEBAR.BMP",
"#title-bar #close": "TITLEBAR.BMP",
".status #clutter-bar": "TITLEBAR.BMP",
".status #clutter-bar div:active": "TITLEBAR.BMP",
".status #clutter-bar div.selected": "TITLEBAR.BMP",
".status #play-pause": "PLAYPAUS.BMP",
".play .status #work-indicator": "PLAYPAUS.BMP",
".status #time #minus-sign": "NUMBERS.BMP",
".status #time.ex #minus-sign": "NUMS_EX.BMP",
".media-info .mono-stereo div": "MONOSTER.BMP",
"#volume": "VOLUME.BMP",
"#volume::-webkit-slider-thumb": "VOLUME.BMP",
@ -36,7 +23,6 @@ SkinManager = {
"#eject": "CBUTTONS.BMP",
".shuffle-repeat div": "SHUFREP.BMP",
".character": "TEXT.BMP",
".digit": "NUMBERS.BMP",
// Put this second, since it will trump .digit
".digit-ex": "NUMS_EX.BMP",
".shade #position": "TITLEBAR.BMP",
@ -44,6 +30,9 @@ SkinManager = {
".shade #position::-moz-range-thumb": "TITLEBAR.BMP",
},
// For sprites that tile, we need to use just the sprite, not the whole image
_skinSprites: SKIN_SPRITES,
// Given a file of an original Winamp WSZ file, set the current skin
setSkinByFile: function(file, completedCallback) {
this.completedCallback = completedCallback;
@ -56,16 +45,14 @@ SkinManager = {
var zip = new JSZip(buffer);
document.getElementById('time').classList.remove('ex');
this._createNewStyleNode();
var cssRules = '';
for(var selector in SkinManager._skinImages) {
var fileName = SkinManager._skinImages[selector];
var promisedCssRules = [];
for(var selector in this._skinImages) {
var fileName = this._skinImages[selector];
var file = this._findFileInZip(fileName, zip);
if (file) {
var value = "background-image: url(data:image/bmp;base64," + btoa(file.asBinary()) + ")";
cssRules += selector + "{" + value + "}\n";
promisedCssRules.push(selector + "{" + value + "}");
// CSS has to change if this file is present
if(fileName == 'NUMS_EX.BMP') {
@ -74,9 +61,24 @@ SkinManager = {
}
}
this.styleNode.appendChild(document.createTextNode(cssRules));
this._parseVisColors(zip);
this.completedCallback();
Array.prototype.push.apply(promisedCssRules, this._skinSprites.map(function(spriteObj) {
var file = this._findFileInZip(spriteObj.img, zip);
if (file) {
var src = "data:image/bmp;base64," + btoa(file.asBinary());
return this._spriteCssRule(src, spriteObj);
}
}, this));
// Extract sprite images
Promise.all(promisedCssRules).then(function(newCssRules) {
this._createNewStyleNode();
cssRules = newCssRules.join('\n');
console.log(cssRules.length);
this.styleNode.appendChild(document.createTextNode(cssRules));
this._parseVisColors(zip);
this.completedCallback();
}.bind(this));
},
_parseVisColors: function(zip) {
@ -109,5 +111,32 @@ SkinManager = {
}
this.styleNode = document.createElement('style');
document.head.appendChild(this.styleNode);
},
// Given an image URL and coordinates, returns a data url for a sub-section
// of that image
_spriteCssRule: function(src, spriteObj) {
return new Promise(function(resolve, reject) {
var imageObj = new Image();
imageObj.src = src;
imageObj.onload = function() {
var skinImage = this;
var cssRules = '';
var canvas = document.createElement('canvas');
spriteObj.sprites.forEach(function(sprite) {
canvas.height = sprite.height;
canvas.width = sprite.width;
var context = canvas.getContext('2d');
context.drawImage(skinImage, -sprite.x, -sprite.y);
var value = "background-image: url(" + canvas.toDataURL() + ")";
sprite.selectors.forEach(function(selector) {
cssRules += selector + "{" + value + "}\n";
});
});
resolve(cssRules);
};
});
}
};