From 2492cad3e0fac298c58c447eb9929494fb3f9350 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Tue, 7 Sep 2021 00:19:31 +0300 Subject: [PATCH] fonts rework - add fonts to downloaded image --- modules/fonts.js | 59 +++++++++++++++---------------------------- modules/save.js | 18 +++++++++---- modules/ui/general.js | 9 +++++-- 3 files changed, 40 insertions(+), 46 deletions(-) diff --git a/modules/fonts.js b/modules/fonts.js index beb629a3..82713ce6 100644 --- a/modules/fonts.js +++ b/modules/fonts.js @@ -197,43 +197,24 @@ async function fetchGoogleFont(family) { } } -function convertFontToDataURI(url) { - if (!url) return Promise.resolve(); - return fetch(url) - .then(resp => resp.text()) - .then(text => { - const style = document.createElement("style"); - style.innerHTML = text; - document.head.appendChild(style); - - const styleSheet = document.styleSheets.find(sheet => sheet.ownerNode === style); - - const FontRule = rule => { - const src = rule.style.getPropertyValue("src"); - const url = src ? src.split("url(")[1].split(")")[0] : ""; - return {rule, src, url: url.substring(url.length - 1, 1)}; - }; - const fontProms = []; - - for (const rule of styleSheet.cssRules) { - let fR = FontRule(rule); - if (!fR.url) continue; - - fontProms.push( - fetch(fR.url) - .then(resp => resp.blob()) - .then(blob => { - return new Promise(resolve => { - let f = new FileReader(); - f.onload = e => resolve(f.result); - f.readAsDataURL(blob); - }); - }) - .then(dataURL => fR.rule.cssText.replace(fR.url, dataURL)) - ); - } - - document.head.removeChild(style); // clean up - return Promise.all(fontProms); // wait for all this has been done - }); +function readBlobAsDataURL(blob) { + return new Promise(function (resolve, reject) { + const reader = new FileReader(); + reader.onloadend = () => resolve(reader.result); + reader.onerror = reject; + reader.readAsDataURL(blob); + }); +} + +async function loadFontsAsDataURI(fonts) { + const promises = fonts.map(async font => { + const url = font.src.match(/url\(['"]?(.+?)['"]?\)/)[1]; + const resp = await fetch(url); + const blob = await resp.blob(); + const dataURL = await readBlobAsDataURL(blob); + + return {...font, src: `url('${dataURL}')`}; + }); + + return await Promise.all(promises); } diff --git a/modules/save.js b/modules/save.js index de01ae98..1a995497 100644 --- a/modules/save.js +++ b/modules/save.js @@ -277,12 +277,20 @@ async function getMapURL(type, options = {}) { // TODO: add dataURL for all used fonts const usedFonts = getUsedFonts(cloneEl); - const websafe = ["Georgia", "Times+New+Roman", "Comic+Sans+MS", "Lucida+Sans+Unicode", "Courier+New", "Verdana", "Arial", "Impact"]; - const fontsToLoad = usedFonts.filter(font => !websafe.includes(font)); + const fontsToLoad = usedFonts.filter(font => font.src); if (fontsToLoad.length) { - const url = "https://fonts.googleapis.com/css?family=" + fontsToLoad.join("|"); - const fontStyle = await convertFontToDataURI(url); - if (fontStyle) clone.select("defs").append("style").text(fontStyle.join("\n")); + const dataURLfonts = await loadFontsAsDataURI(fontsToLoad); + + const fontFaces = dataURLfonts + .map(({family, src, unicodeRange = "", variant = "normal"}) => { + return `@font-face {font-family: "${family}"; src: ${src}; unicode-range: ${unicodeRange}; font-variant: ${variant};}`; + }) + .join("\n"); + + const style = document.createElement("style"); + style.setAttribute("type", "text/css"); + style.innerHTML = fontFaces; + cloneEl.querySelector("defs").appendChild(style); } clone.remove(); diff --git a/modules/ui/general.js b/modules/ui/general.js index b99ae898..b001b9fd 100644 --- a/modules/ui/general.js +++ b/modules/ui/general.js @@ -32,15 +32,20 @@ function tip(tip = "Tip is undefined", main, type, time) { else if (type === "warn") tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #be5d08cc, #ffffff00)"; else if (type === "success") tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #127912cc, #ffffff00)"; - if (main) tooltip.dataset.main = tip; // set main tip - if (time) setTimeout(() => (tooltip.dataset.main = ""), time); // clear main in some time + if (main) { + tooltip.dataset.main = tip; + tooltip.dataset.color = tooltip.style.background; + } + if (time) setTimeout(() => clearMainTip(), time); } function showMainTip() { + tooltip.style.background = tooltip.dataset.color; tooltip.innerHTML = tooltip.dataset.main; } function clearMainTip() { + tooltip.dataset.color = ""; tooltip.dataset.main = ""; tooltip.innerHTML = ""; }