Skip to content

Commit

Permalink
redo font loading, caching, persist configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
xsrf committed Apr 16, 2021
1 parent a0f3d27 commit 23512c5
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 61 deletions.
127 changes: 127 additions & 0 deletions extension/easyeda-helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
Common Helper Functions for EasyEDA API
*/
const extensionId = Object.entries(easyeda.extension.instances).filter(e => e[1].blobURLs && e[1].blobURLs['manifest.json'] == api('getRes',{file:'manifest.json'}))[0][1].id;
const instance = easyeda.extension.instances[extensionId];

instance.Helper = class Helper {

static createCommand(callback) {
const id = 'extension-' + extensionId + '-' + Math.round(Math.random()*1e9);
let cmd={};
cmd[id] = callback;
api('createCommand', cmd);
return id;
}

static async loadExtensionModule(filename) {
try {
const url = api('getRes',{file: filename});
if(!url) throw 'blob-url undefined';
return await import(url);
} catch (error) {
const msg = `Failed to load module '${filename}' of extension '${extensionId}'. Maybe you didn't select all files for install?! Please reinstall! ${error}`;
$.messager.error(msg);
throw msg;
}
}

static async loadExtensionScript(filename) {
try {
const response = await fetch(api('getRes',{file: filename}));
const body = await response.text();
return eval(body);
} catch (error) {
const msg = `Failed to load script '${filename}' of extension '${extensionId}'. Maybe you didn't select all files for install?! Please reinstall! ${error}`;
$.messager.error(msg);
throw msg;
}
}

static async getExtensionScript(filename) {
try {
const url = api('getRes',{file: filename});
if(!url) throw 'blob-url undefined';
const response = await fetch(url);
const body = await response.text();
return body;
} catch (error) {
const msg = `Failed to load script '${filename}' of extension '${extensionId}'. Maybe you didn't select all files for install?! Please reinstall! ${error}`;
$.messager.error(msg);
throw msg;
}
}

static setConfig(key,value) {
var conf = {};
try {
conf = localStorage.getItem(`extension.${extensionId}.config`) || '{}';
conf = JSON.parse(conf);
} catch (error) {
conf = {};
}
conf[key] = value;
if(value === null) delete conf[value];
localStorage.setItem(`extension.${extensionId}.config`,JSON.stringify(conf));
}

static getConfig(key,defaultValue) {
try {
var conf = localStorage.getItem(`extension.${extensionId}.config`) || '{}';
conf = JSON.parse(conf);
if(!(key in conf)) return defaultValue;
return conf[key];
} catch (error) {
return defaultValue;
}
}

static checkUpdate() {
(async ()=>{
try {
if(!('version' in instance.manifest)) return;
if(!('homepage' in instance.manifest)) return;
if(!('updatebaseurl' in instance.manifest)) return;
var skipVersion = this.getConfig('update-skip',instance.manifest.version);
var cmdUpdatePage = this.createCommand(()=>{ window.open(instance.manifest.homepage,'_blank') });
var cmdUpdateSkip = this.createCommand(()=>{ this.setConfig('update-skip',skipVersion) });
var response = await fetch(instance.manifest.updatebaseurl + 'manifest.json');
if(response.status != 200) {
console.log('Update check failed, Status: ' + response.status);
return;
}
var onlineManifest = await response.json();
if(onlineManifest.version == instance.manifest.version) {
console.log(`Update check ok, "${extensionId}" is up to date`);
return;
}
if(onlineManifest.version == skipVersion) {
console.log(`Update check ok, "${extensionId}" is not up to date but version is skipped`);
return;
}
console.log(`Update check ok, "${extensionId}" is not up to date`);
skipVersion = onlineManifest.version;
$.messager.show({
title: `Update Available for <b>${instance.manifest.name}</b>`,
msg: `<table>
<tr><td>Installed:</td><td>${instance.manifest.name} ${instance.manifest.version}</td></tr>
<tr><td>Available:</td><td>${onlineManifest.name} ${onlineManifest.version}</td></tr>
</table>
<div class="dialog-button">
<a tabindex="0" cmd="${cmdUpdatePage};dialog-close" class="l-btn"><span class="l-btn-left"><span class="l-btn-text i18n">Download</span></span></a>
<a tabindex="0" cmd="${cmdUpdateSkip};dialog-close" class="l-btn"><span class="l-btn-left"><span class="l-btn-text i18n">Skip Version</span></span></a>
</div>
`,
height: 'auto',
timeout: 30e3,
showType: "slide"
});
} catch (error) {
console.log('Update check failed: '+error);
}
})();
}

}

console.log(`EasyEDA Helper loaded for extension "${extensionId}"`);
36 changes: 0 additions & 36 deletions extension/loadfonts.js

This file was deleted.

96 changes: 79 additions & 17 deletions extension/main.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const extensionId = 'extension-labelmaker-id'.split('-')[1]; // this format is needed to set the Extension ID during install
const manifest = easyeda.extension.instances[extensionId].manifest;
var extension = easyeda.extension.instances[extensionId];
const instance = easyeda.extension.instances[extensionId];
const manifest = instance.manifest;
const Helper = instance.Helper; // Helper class declared in easyeda-helper.js
const createCommand = Helper.createCommand;
const setConfig = Helper.setConfig;
const getConfig = Helper.getConfig;
const paper = instance.paper;
var opentypeFontCache = new Array();

function createCommand(callback) {
id = 'extension-'+extensionId+'-' + Math.round(Math.random()*1e9);
cmd=[];
cmd[id] = callback;
api('createCommand', cmd);
return id;
}
var cmdVisitGithub = createCommand(()=>{ window.open(manifest.homepage,'_blank'); });

api('createToolbarButton', {
fordoctype: 'pcb,pcblib',
Expand All @@ -18,16 +18,23 @@ api('createToolbarButton', {
cmd: createCommand(()=>{ labeldlg.dialog('open'); labeldlg.dialog('expand'); reloadFontList(); previewLabel(); }),
title: 'Open Dialog for Label Maker',
},
{},
{
text: "Manage Fonts",
cmd: createCommand(()=>{ labeldlg.dialog('close'); api('doCommand','fontsManagement'); }),
title: 'Manage Fonts',
},
{
text: "Rebuild Fonts Cache",
cmd: createCommand(()=>{ extension.updateFontsCache(); }),
cmd: createCommand(()=>{ labeldlg.dialog('close'); updateFontsCache(); }),
title: 'Rebuild the Fonts Cache - required after adding Fonts to EasyEDA',
},
{},
{
text: "Visit GitHub Page",
cmd: cmdVisitGithub,
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFxSURBVHjajNPNK0RhFMfxe2dI04y8NExNNmzJ2igRWwtlRRllryz8DVhYiKLZaHbyWv4ALyHCgvwBQyEW5GVhphDfU7+rJ0n31Gfufe4959w7z3MfP1VX7/2KLgygHQ26doNDLGHXTfadBjWYxoj3fyxiHE82iDjFGyGKPeVsqMaLJuJxOy6gD0eYQhJVuMIjKnCOSdSiAylslvHTiWF1v8C8XrMaz7oenJfQioxq8tYga3OhxJJzvHde2z0PcqwmG1E3izfkQsxBTrkWGWuQ1uABhRANCsq1SFuDLw0SiIVoEFOuxZc1uNbAZrcnRIPuYAmt1hocaPCKGS2R/0ehr3vTzv19a5DXYBlb2MMx2pxim+ht7KBR1z6CZTzBHEbRi0s049Zp8KI94obVnAZ7wSZmBS0YU/EZPpWc1OxXaryOIRSDvVBEP9awqr+QdJ4WVbHlTWBQ5z97wdPTbKveaWnXna+uHE167Vm8B0XfAgwAj8RQQEL6HPwAAAAASUVORK5CYII="
},
{
text: "About",
cmd: createCommand(()=>{ aboutdlg.dialog('open') })
Expand Down Expand Up @@ -161,18 +168,71 @@ var labeldlg = api('createDialog', {
]
});

// Add Event-Listeners to GUI
document.querySelector(`#extension-${extensionId}-dlg`).querySelectorAll('input,select').forEach((el)=>{
el.addEventListener('change',previewLabel);
el.addEventListener('change',(e)=>{
previewLabel();
setConfig(el.id,$('#'+el.id).val());
});
el.addEventListener('keypress',(e)=>{
if(e.key=='Enter') {
$(`#extension-${extensionId}-text`).select();
$(`#extension-${extensionId}-text`).focus();
placeLabel();
}
});
})
});

loadBundledFonts();
updateFontsCache();
initDialog();
Helper.checkUpdate();
setTimeout(updateFontsCache,1e3); // Files aren't always available right away, so reload later to be safe


/*
Functions
*/

function loadBundledFonts() {
// Loads *.ttf fonts that were bundled with the extension into EasyEDAs Fonts database
const db = simpleDB("DBEasyEDA", 9, [{exportAPI: 'files', storeName: 'files'},{exportAPI: 'fonts', storeName: 'fonts'}]);
db.files.get(`extension-${extensionId}`,(files)=>{
files.filter(file=>file.name.toLowerCase().endsWith('.ttf')).forEach(file=>{
font = opentype.parse(file.contentArrayBuffer);
if(font && font.names.fullName) {
let nameLanguages = Object.keys(font.names.fullName);
let nameLanguage = nameLanguages.includes('en') ? 'en' : nameLanguages[0];
let name = font.names.fullName[nameLanguage];
db.fonts.put(name,file.contentArrayBuffer);
console.log(`Bundled Font "${file.name}" loaded as "${name}"`);
} else {
console.error(`Bundled Font "${file.name}" was not parsed correctly!`);
}
})
})
}

function updateFontsCache() {
const db = simpleDB("DBEasyEDA", 9, [{exportAPI: 'fonts', storeName: 'fonts'}]);
db.fonts.each((cursor,next)=>{
if(!opentypeFontCache.map(e=>e.key).includes(cursor.key)) {
font = opentype.parse(cursor.value);
font.key = cursor.key;
font.buffer = cursor.value;
opentypeFontCache.push(font);
}
next();
});
}

function initDialog() {
// Restore Dialog values from localStorage
document.querySelector(`#extension-${extensionId}-dlg`).querySelectorAll('input,select').forEach((el)=>{
if(v = getConfig(el.id,false)) $('#'+el.id).val(v);
})
}

function getLabelOptions() {
return {
text: $(`#extension-${extensionId}-text`).val().length ? $(`#extension-${extensionId}-text`).val() : '?',
Expand Down Expand Up @@ -216,9 +276,9 @@ function previewLabel() {

function reloadFontList() {
var el = document.querySelector(`#extension-${extensionId}-font`);
var selectedFont = el.value;
var selectedFont = el.value || getConfig(el.id);
while(e=el.firstChild) el.removeChild(e); // remove all options
const fonts = easyeda.extension.instances[extensionId].opentypeFontCache.map((f)=>f.key);
const fonts = opentypeFontCache.map((f)=>f.key);
fonts.forEach( font => {
selected = font==selectedFont ? 'selected' : '';
el.insertAdjacentHTML("beforeend",`<option value="${font}" ${selected}>${font}</option>`);
Expand All @@ -232,8 +292,6 @@ function autoScaleViewBox(el) {
}

function createLabelPath(options) {
// Get paper.js instance
paper = easyeda.extension.instances[extensionId].paper;
// store options in local vars
const size = options.size;
const paddingV = options.padding.y;
Expand All @@ -244,7 +302,11 @@ function createLabelPath(options) {
const width = options.width;
const textalign = options.textalign;
// get opentype.js font instance from cache (generated in loadfonts.js)
font = extension.opentypeFontCache.filter(f=>f.key==fontfamily)[0];
font = opentypeFontCache.filter(f=>f.key==fontfamily)[0];
if(!font) {
$.messager.error('Font not found!');
return '';
}
// get Bounds for Char "X" to calculate height (ignore chars below baseline like "y")
bbx = font.getPath('X', 0, 0, size).getBoundingBox();
const textHeight = bbx.y2 - bbx.y1;
Expand Down
8 changes: 5 additions & 3 deletions extension/manifest.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
{
"name": "Label Maker",
"description": "Creates awesome shaped labels",
"version": "1.0",
"version": "1.1",
"homepage": "https://github.com/xsrf/easyeda-labelmaker",
"author" : "Andreas Bernhofer",
"icons": {
"default": "icon.svg"
},
"scripts": [
"easyeda-helper.js",
"paper-full.min.js",
"loadfonts.js",
"main.js"
]
],
"updatebaseurl" : "https://raw.githubusercontent.com/xsrf/easyeda-labelmaker/autoupdate/extension/"
}
8 changes: 3 additions & 5 deletions extension/paper-full.min.js

Large diffs are not rendered by default.

0 comments on commit 23512c5

Please sign in to comment.