diff --git a/chrome/content/zotero/xpcom/data/tags.js b/chrome/content/zotero/xpcom/data/tags.js index 6f13e314c6..898cc231d5 100644 --- a/chrome/content/zotero/xpcom/data/tags.js +++ b/chrome/content/zotero/xpcom/data/tags.js @@ -840,162 +840,6 @@ Zotero.Tags = new function () { }; - /** - * A tree cell can show only one image, and (as of Fx19) it can't be an SVG, - * so we need to generate a composite image containing the existing item type - * icon and one or more tag color swatches. - * - * @params {String[]} colors - Array of swatch colors - * @params {String} extraImage - chrome:// URL of image to add to final image - * @params {Boolean} [retracted = false] - If true, show an icon indicating the item was retracted - * @return {Promise} - A promise for a data: URL for a PNG - */ - this.generateItemsListImage = async function (colors, extraImage, retracted) { - var multiplier = Zotero.hiDPI ? 2 : 1; - - var canvasHeight = 16 * multiplier; - var extraImageWidth = 16 * multiplier; - var extraImageHeight = 16 * multiplier; - var retractionImage = `chrome://zotero/skin/cross${Zotero.hiDPI ? '@1.5x' : ''}.png`; - var retractionImageLeftPadding = 1 * multiplier; - var retractionImageWidth = 16 * multiplier; - var retractionImageHeight = 16 * multiplier; - var retractionImageScaledWidth = 12 * multiplier; - var retractionImageScaledHeight = 12 * multiplier; - var tagsLeftPadding = 3 * multiplier; - var swatchSeparator = 3 * multiplier; - var swatchWidth = 8 * multiplier; - var swatchHeight = 8 * multiplier; - - var hash = colors.join("") + (extraImage ? extraImage : "") + (retracted ? "retracted" : ""); - - if (_itemsListImagePromises[hash]) { - return _itemsListImagePromises[hash]; - } - - var win = Components.classes["@mozilla.org/appshell/appShellService;1"] - .getService(Components.interfaces.nsIAppShellService) - .hiddenDOMWindow; - var doc = win.document; - var canvas = doc.createElement('canvas'); - - var width = extraImageWidth - + (retracted - ? (retractionImageLeftPadding - + ((retractionImageWidth - retractionImageScaledWidth) / 2) - + retractionImageScaledWidth) - : 0) - + (colors.length ? tagsLeftPadding : 0) - + (colors.length * (swatchWidth + swatchSeparator)); - - canvas.width = width; - canvas.height = canvasHeight; - var swatchTop = Math.floor((canvasHeight - swatchHeight) / 2); - var ctx = canvas.getContext('2d'); - - // If extra image hasn't started loading, start now - if (_itemsListImagePromises[extraImage] === undefined) { - let ios = Services.io; - let uri = ios.newURI(extraImage, null, null); - let img = new win.Image(); - img.src = uri.spec; - _itemsListImagePromises[extraImage] = new Zotero.Promise((resolve) => { - img.onload = function () { - resolve(img); - }; - }); - } - - // If retraction image hasn't started loading, start now - if (_itemsListImagePromises[retractionImage] === undefined) { - let ios = Services.io; - let uri = ios.newURI(retractionImage, null, null); - let img = new win.Image(); - img.src = uri.spec; - _itemsListImagePromises[retractionImage] = new Zotero.Promise((resolve) => { - img.onload = function () { - resolve(img); - }; - }); - } - - var x = extraImageWidth - + (retracted ? retractionImageLeftPadding + retractionImageWidth: 0) - + tagsLeftPadding; - for (let i = 0, len = colors.length; i < len; i++) { - ctx.fillStyle = colors[i]; - _canvasRoundRect(ctx, x, swatchTop + 1, swatchWidth, swatchHeight, 2, true, false); - x += swatchWidth + swatchSeparator; - } - - if (retracted) { - let [img1, img2] = await Promise.all([ - _itemsListImagePromises[extraImage], - _itemsListImagePromises[retractionImage] - ]); - ctx.drawImage(img1, 0, 0, extraImageWidth, extraImageHeight); - ctx.drawImage( - img2, - extraImageWidth + retractionImageLeftPadding - + ((retractionImageWidth - retractionImageScaledWidth) / 2), - (retractionImageHeight - retractionImageScaledHeight) / 2 + 1, // Lower by 1 - retractionImageScaledWidth, - retractionImageScaledHeight - ); - } - else { - let img = await _itemsListImagePromises[extraImage]; - ctx.drawImage(img, 0, 0, extraImageWidth, extraImageHeight); - } - - var dataURI = canvas.toDataURL("image/png"); - _itemsListImagePromises[hash] = Promise.resolve(dataURI); - return dataURI; - }; - - - /** - * From http://js-bits.blogspot.com/2010/07/canvas-rounded-corner-rectangles.html - * - * Draws a rounded rectangle using the current state of the canvas. - * If you omit the last three params, it will draw a rectangle - * outline with a 5 pixel border radius - * - * @param {CanvasRenderingContext2D} ctx - * @param {Number} x The top left x coordinate - * @param {Number} y The top left y coordinate - * @param {Number} width The width of the rectangle - * @param {Number} height The height of the rectangle - * @param {Number} radius The corner radius. Defaults to 5; - * @param {Boolean} fill Whether to fill the rectangle. Defaults to false. - * @param {Boolean} stroke Whether to stroke the rectangle. Defaults to true. - */ - function _canvasRoundRect(ctx, x, y, width, height, radius, fill, stroke) { - if (typeof stroke == "undefined" ) { - stroke = true; - } - if (typeof radius === "undefined") { - radius = 5; - } - ctx.beginPath(); - ctx.moveTo(x + radius, y); - ctx.lineTo(x + width - radius, y); - ctx.quadraticCurveTo(x + width, y, x + width, y + radius); - ctx.lineTo(x + width, y + height - radius); - ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); - ctx.lineTo(x + radius, y + height); - ctx.quadraticCurveTo(x, y + height, x, y + height - radius); - ctx.lineTo(x, y + radius); - ctx.quadraticCurveTo(x, y, x + radius, y); - ctx.closePath(); - if (stroke) { - ctx.stroke(); - } - if (fill) { - ctx.fill(); - } - } - // Return the first sequence of emojis from a string this.extractEmojiForItemsList = function (str) { // Split by anything that is not an emoji, Zero Width Joiner, or Variation Selector-16