diff --git a/src/js/LogoManager.js b/src/js/LogoManager.js index a7d9aa01..5b73e468 100644 --- a/src/js/LogoManager.js +++ b/src/js/LogoManager.js @@ -1,6 +1,84 @@ 'use strict'; -var LogoManager = LogoManager || { +(function () { + +/** + * Takes an ImageData object and returns an MCM symbol as an array of strings. + * + * @param {ImageData} data + */ +function imageToCharacter(data) { + const char = []; + let line = ""; + for (let i = 0, I = data.length; i < I; i += 4) { + const rgbPixel = data.slice(i, i + 3), + colorKey = rgbPixel.join("-"); + line += this.constants.MCM_COLORMAP[colorKey] + || this.constants.MCM_COLORMAP['default']; + if (line.length === 8) { + char.push(line); + line = ""; + } + } + const fieldSize = this.font.constants.SIZES.MAX_NVM_FONT_CHAR_FIELD_SIZE; + if (char.length < fieldSize) { + const pad = this.constants.MCM_COLORMAP['default'].repeat(4); + for (let i = 0, I = fieldSize - char.length; i < I; i++) { + char.push(pad); + } + } + return char; +} + +/** + * Takes an OSD symbol as an array of strings and replaces the in-memory character at charAddress with it. + * + * @param {Array} lines + * @param {Number} charAddress + */ +function replaceChar(lines, charAddress) { + const characterBits = [], + characterBytes = []; + for (let n = 0, N = lines.length; n < N; n++) { + const line = lines[n]; + for (let y = 0; y < 8; y = y + 2) { + characterBits.push(parseInt(line.slice(y, y + 2), 2)); + } + characterBytes.push(parseInt(line, 2)); + } + this.font.data.characters[charAddress] = characterBits; + this.font.data.characters_bytes[charAddress] = characterBytes; + this.font.data.character_image_urls[charAddress] = null; + this.font.draw(charAddress); +} + +/** + * Validate image using defined constraints and display results on the UI. + * + * @param {HTMLImageElement} img + */ +function validateImage(img) { + return new Promise((resolveValidateImage, rejectValidateImage) => { + this.resetImageInfo(); + for (const key in this.constraints) { + if (!this.constraints.hasOwnProperty(key)) { + continue; + } + const constraint = this.constraints[key], + satisfied = constraint.test(img); + if (satisfied) { + this.showConstraintSatisfied(constraint); + } else { + this.showConstraintNotSatisfied(constraint); + rejectValidateImage("Boot logo image constraint violation"); + return; + } + } + resolveValidateImage(); + }); +} + +const LogoManager = { // dependencies set by init() font: null, logoStartIndex: null, @@ -32,7 +110,7 @@ var LogoManager = LogoManager || { /** * Initialize Logo Manager UI with dependencies. - * + * * @param {FONT} font * @param {number} logoStartIndex */ @@ -51,9 +129,9 @@ LogoManager.init = function (font, logoStartIndex) { * @param {HTMLImageElement} img */ test: img => { - var constraint = this.constraints.imageSize; - if (img.width != constraint.expectedWidth - || img.height != constraint.expectedHeight) { + const constraint = this.constraints.imageSize; + if (img.width !== constraint.expectedWidth + || img.height !== constraint.expectedHeight) { GUI.log(i18n.getMessage("osdSetupCustomLogoImageSizeError", { width: img.width, height: img.height, @@ -70,14 +148,14 @@ LogoManager.init = function (font, logoStartIndex) { * @param {HTMLImageElement} img */ test: img => { - var canvas = document.createElement('canvas'), + const canvas = document.createElement('canvas'), ctx = canvas.getContext('2d'); canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); - for (var y = 0, Y = canvas.height; y < Y; y++) { - for (var x = 0, X = canvas.width; x < X; x++) { - var rgbPixel = ctx.getImageData(x, y, 1, 1).data.slice(0, 3), + for (let y = 0, Y = canvas.height; y < Y; y++) { + for (let x = 0, X = canvas.width; x < X; x++) { + const rgbPixel = ctx.getImageData(x, y, 1, 1).data.slice(0, 3), colorKey = rgbPixel.join("-"); if (!this.constants.MCM_COLORMAP[colorKey]) { GUI.log(i18n.getMessage("osdSetupCustomLogoColorMapError", { @@ -101,12 +179,12 @@ LogoManager.init = function (font, logoStartIndex) { this.logoStartIndex = logoStartIndex; // inject logo size variables for dynamic translation strings i18n.addResources({ - logoWidthPx: "" + this.constraints.imageSize.expectedWidth, - logoHeightPx: "" + this.constraints.imageSize.expectedHeight, + logoWidthPx: "" + this.constraints.imageSize.expectedWidth, // NOSONAR + logoHeightPx: "" + this.constraints.imageSize.expectedHeight, // NOSONAR }); // find/cache DOM elements Object.keys(this.elements).forEach(key => { - this.elements["$" + key] = $(this.elements[key]); + this.elements[`$${key}`] = $(this.elements[key]); }); Object.keys(this.constraints).forEach(key => { this.constraints[key].$el = $(this.constraints[key].el); @@ -121,7 +199,7 @@ LogoManager.init = function (font, logoStartIndex) { LogoManager.resetImageInfo = function () { this.hideUploadHint(); Object.values(this.constraints).forEach(constraint => { - var $el = constraint.$el; + const $el = constraint.$el; $el.toggleClass("invalid", false); $el.toggleClass("valid", false); }); @@ -145,39 +223,14 @@ LogoManager.hideUploadHint = function () { /** * Show a file open dialog and resolve to an Image object. - * + * * @returns {Promise} */ LogoManager.openImage = function () { - return new Promise((resolve, reject) => { - /** - * Validate image using defined constraints and display results on the UI. - * - * @param {HTMLImageElement} img - */ - var validateImage = img => { - return new Promise((resolve, reject) => { - this.resetImageInfo(); - for (var key in this.constraints) { - if (!this.constraints.hasOwnProperty(key)) { - continue; - } - var constraint = this.constraints[key], - satisfied = constraint.test(img); - if (satisfied) { - this.showConstraintSatisfied(constraint); - } else { - this.showConstraintNotSatisfied(constraint); - reject("Boot logo image constraint violation"); - return; - } - } - resolve(); - }); - }; - var dialogOptions = { + return new Promise((resolveOpenImage, rejectOpenImage) => { + const dialogOptions = { type: 'openFile', - accepts: this.acceptFileTypes + accepts: this.acceptFileTypes, }; chrome.fileSystem.chooseEntry(dialogOptions, fileEntry => { if (chrome.runtime.lastError) { @@ -185,84 +238,41 @@ LogoManager.openImage = function () { return; } // load and validate selected image - var img = new Image(); + const img = new Image(); img.onload = () => { - validateImage(img) - .then(() => resolve(img)) - .catch(error => reject(error)); + validateImage.apply(this, [img]) + .then(() => resolveOpenImage(img)) + .catch(error => rejectOpenImage(error)); }; - img.onerror = error => reject(error); - fileEntry.file(file => img.src = "file://" + file.path); + img.onerror = error => rejectOpenImage(error); + fileEntry.file(file => img.src = `file://${file.path}`); }); }); }; /** * Replaces the logo in the loaded font based on an image. - * + * * @param {HTMLImageElement} img */ LogoManager.replaceLogoInFont = function (img) { - /** - * Takes an ImageData object and returns an MCM symbol as an array of strings. - * - * @param {ImageData} data - */ - var imageToCharacter = data => { - var char = [], - line = ""; - for (var i = 0, I = data.length; i < I; i += 4) { - var rgbPixel = data.slice(i, i + 3), - colorKey = rgbPixel.join("-"); - line += this.constants.MCM_COLORMAP[colorKey] - || this.constants.MCM_COLORMAP['default']; - if (line.length == 8) { - char.push(line); - line = ""; - } - } - var fieldSize = this.font.constants.SIZES.MAX_NVM_FONT_CHAR_FIELD_SIZE; - if (char.length < fieldSize) { - var pad = this.constants.MCM_COLORMAP['default'].repeat(4); - for (var i = 0, I = fieldSize - char.length; i < I; i++) - char.push(pad); - } - return char; - }; - // takes an OSD symbol as an array of strings and replaces the in-memory character at charAddress with it - var replaceChar = (lines, charAddress) => { - var characterBits = []; - var characterBytes = []; - for (var n = 0, N = lines.length; n < N; n++) { - var line = lines[n]; - for (var y = 0; y < 8; y = y + 2) { - var v = parseInt(line.slice(y, y + 2), 2); - characterBits.push(v); - } - characterBytes.push(parseInt(line, 2)); - } - this.font.data.characters[charAddress] = characterBits; - this.font.data.characters_bytes[charAddress] = characterBytes; - this.font.data.character_image_urls[charAddress] = null; - this.font.draw(charAddress); - }; // loop through an image and replace font symbols - var canvas = document.createElement('canvas'), - ctx = canvas.getContext('2d'), - charAddr = this.logoStartIndex; + const canvas = document.createElement('canvas'), + ctx = canvas.getContext('2d'); + let charAddr = this.logoStartIndex; canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); - for (var y = 0; y < this.constants.TILES_NUM_VERT; y++) { - for (var x = 0; x < this.constants.TILES_NUM_HORIZ; x++) { - var imageData = ctx.getImageData( + for (let y = 0; y < this.constants.TILES_NUM_VERT; y++) { + for (let x = 0; x < this.constants.TILES_NUM_HORIZ; x++) { + const imageData = ctx.getImageData( x * this.font.constants.SIZES.CHAR_WIDTH, y * this.font.constants.SIZES.CHAR_HEIGHT, this.font.constants.SIZES.CHAR_WIDTH, this.font.constants.SIZES.CHAR_HEIGHT ), - newChar = imageToCharacter(imageData.data); - replaceChar(newChar, charAddr); + newChar = imageToCharacter.apply(this, [imageData.data]); + replaceChar.apply(this, [newChar, charAddr]); charAddr++; } } @@ -272,9 +282,13 @@ LogoManager.replaceLogoInFont = function (img) { * Draw the logo using the loaded font data. */ LogoManager.drawPreview = function () { - var $el = this.elements.$preview.empty(); - for (var i = this.logoStartIndex, I = this.font.constants.MAX_CHAR_COUNT; i < I; i++) { - var url = this.font.data.character_image_urls[i]; - $el.append(''); + const $el = this.elements.$preview.empty(); + for (let i = this.logoStartIndex, I = this.font.constants.MAX_CHAR_COUNT; i < I; i++) { + const url = this.font.data.character_image_urls[i]; + $el.append(``); } }; + +window.LogoManager = LogoManager; + +})();