mirror of
https://github.com/astefanutti/decktape.git
synced 2024-10-26 23:07:33 +03:00
Migrate to opentype.js
This commit is contained in:
parent
fc465c4a50
commit
ebbaa74e9f
54
decktape.js
54
decktape.js
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { Font } from 'fonteditor-core';
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import parser from './libs/nomnom.js';
|
import parser from './libs/nomnom.js';
|
||||||
|
import opentype from 'opentype.js'
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import puppeteer from 'puppeteer';
|
import puppeteer from 'puppeteer';
|
||||||
import URI from 'urijs';
|
import URI from 'urijs';
|
||||||
@ -371,7 +371,9 @@ async function exportSlides(page, plugin, pdf, options) {
|
|||||||
}
|
}
|
||||||
// Flush consolidated fonts
|
// Flush consolidated fonts
|
||||||
Object.values(context.pdfFonts).forEach(({ ref, font }) => {
|
Object.values(context.pdfFonts).forEach(({ ref, font }) => {
|
||||||
pdf.context.assign(ref, pdf.context.flateStream(font.write({ type: 'ttf', hinting: true })));
|
// Set missing glyph names to avoid opentype.js warnings
|
||||||
|
Object.values(font.glyphs.glyphs).forEach(g => g.name |= "name");
|
||||||
|
pdf.context.assign(ref, pdf.context.flateStream(new Uint8Array(font.toArrayBuffer())));
|
||||||
});
|
});
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
@ -465,31 +467,36 @@ async function printSlide(pdf, slide, context) {
|
|||||||
// Some fonts written in the PDF may be ill-formed. Let's skip font compression in that case,
|
// Some fonts written in the PDF may be ill-formed. Let's skip font compression in that case,
|
||||||
// until it's fixed in Puppeteer > Chromium > Skia.
|
// until it's fixed in Puppeteer > Chromium > Skia.
|
||||||
// This happens for system fonts like Helvetica Neue for which cmap table is missing.
|
// This happens for system fonts like Helvetica Neue for which cmap table is missing.
|
||||||
font = Font.create(Buffer.from(bytes), { type: 'ttf', hinting: true });
|
font = opentype.parse(bytes.buffer);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(chalk.yellow('\nSkipping font compression: %s'), e.message);
|
console.log(chalk.yellow('\nSkipping font compression: %s'), e.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Some fonts happen to have no metadata, which is required by fonteditor
|
// Some fonts happen to have missing metadata
|
||||||
if (!font.data.name) {
|
if (!font.names["fontFamily"]) {
|
||||||
font.data.name = {};
|
font.names["fontFamily"] = { en: descriptor.get(PDFName.of('FontName')).value() || "fontFamily" };
|
||||||
|
}
|
||||||
|
if (!font.names["version"]) {
|
||||||
|
font.names["version"] = { en: "version" };
|
||||||
}
|
}
|
||||||
// PDF font name does not contain sub family on Windows 10,
|
// PDF font name does not contain sub family on Windows 10,
|
||||||
// so a more robust key is computed from the font metadata
|
// so a more robust key is computed from the font metadata
|
||||||
const id = descriptor.get(PDFName.of('FontName')).value() + ' - ' + fontMetadataKey(font.data.name);
|
const id = descriptor.get(PDFName.of('FontName')).value() + ' - ' + fontMetadataKey(font.names);
|
||||||
if (context.pdfFonts[id]) {
|
if (context.pdfFonts[id]) {
|
||||||
const f = context.pdfFonts[id].font;
|
const f = context.pdfFonts[id].font;
|
||||||
font.data.glyf.forEach((g, i) => {
|
for (let i = 0; i < font.glyphs.length; i++) {
|
||||||
if (g.contours && g.contours.length > 0) {
|
const glyph = font.glyphs.glyphs[i];
|
||||||
if (!f.data.glyf[i] || !f.data.glyf[i].contours || f.data.glyf[i].contours.length === 0) {
|
if (i < f.glyphs.length) {
|
||||||
mergeGlyph(f, i, g);
|
if (glyph.unicode > 0) {
|
||||||
}
|
const g = f.glyphs.glyphs[i];
|
||||||
} else if (g.compound) {
|
if (typeof g.unicode === 'undefined') {
|
||||||
if (!f.data.glyf[i] || typeof f.data.glyf[i].compound === 'undefined') {
|
f.glyphs.glyphs[i] = glyph;
|
||||||
mergeGlyph(f, i, g);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
|
f.glyphs.push(i, glyph);
|
||||||
|
}
|
||||||
|
};
|
||||||
descriptor.set(PDFName.of('FontFile2'), context.pdfFonts[id].ref);
|
descriptor.set(PDFName.of('FontFile2'), context.pdfFonts[id].ref);
|
||||||
duplicatedEntries.push(ref);
|
duplicatedEntries.push(ref);
|
||||||
} else {
|
} else {
|
||||||
@ -499,22 +506,11 @@ async function printSlide(pdf, slide, context) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function mergeGlyph(font, index, glyf) {
|
|
||||||
if (font.data.glyf.length <= index) {
|
|
||||||
for (let i = font.data.glyf.length; i < index; i++) {
|
|
||||||
font.data.glyf.push({ contours: Array(0), advanceWidth: 0, leftSideBearing: 0 });
|
|
||||||
}
|
|
||||||
font.data.glyf.push(glyf);
|
|
||||||
} else {
|
|
||||||
font.data.glyf[index] = glyf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fontMetadataKey(font) {
|
function fontMetadataKey(font) {
|
||||||
const keys = ['fontFamily', 'fontSubFamily', 'fullName', 'preferredFamily', 'preferredSubFamily', 'uniqueSubFamily'];
|
const keys = ['fontFamily', 'fontSubFamily', 'fullName', 'postscriptName', 'preferredFamily', 'preferredSubFamily', 'version'];
|
||||||
return Object.entries(font)
|
return Object.entries(font)
|
||||||
.filter(([key, _]) => keys.includes(key))
|
.filter(([key, _]) => keys.includes(key))
|
||||||
.reduce((r, [k, v], i) => r + (i > 0 ? ',' : '') + k + '=' + v, '');
|
.reduce((r, [k, v], i) => r + (i > 0 ? ',' : '') + k + '=' + v.en || v, '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
77
npm-shrinkwrap.json
generated
77
npm-shrinkwrap.json
generated
@ -10,7 +10,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "5.1.2",
|
"chalk": "5.1.2",
|
||||||
"fonteditor-core": "2.1.10",
|
"opentype.js": "1.3.4",
|
||||||
"pdf-lib": "1.17.1",
|
"pdf-lib": "1.17.1",
|
||||||
"puppeteer": "20.1.0",
|
"puppeteer": "20.1.0",
|
||||||
"puppeteer-core": "20.1.0",
|
"puppeteer-core": "20.1.0",
|
||||||
@ -25,7 +25,7 @@
|
|||||||
"koa-static": "5.0.0"
|
"koa-static": "5.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.20"
|
"node": ">=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
@ -173,14 +173,6 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@xmldom/xmldom": {
|
|
||||||
"version": "0.8.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz",
|
|
||||||
"integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/accepts": {
|
"node_modules/accepts": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
@ -575,14 +567,6 @@
|
|||||||
"pend": "~1.2.0"
|
"pend": "~1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fonteditor-core": {
|
|
||||||
"version": "2.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/fonteditor-core/-/fonteditor-core-2.1.10.tgz",
|
|
||||||
"integrity": "sha512-NQvTBstkzkJeNTb6UUaliQs493mHj4Su0yH2d8eHQbQZQK9fIOh7X/pzKdW7BtQpDQZPSjh65ruLBqOqwGTHKQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@xmldom/xmldom": "^0.8.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fresh": {
|
"node_modules/fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
@ -997,6 +981,21 @@
|
|||||||
"integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==",
|
"integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/opentype.js": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==",
|
||||||
|
"dependencies": {
|
||||||
|
"string.prototype.codepointat": "^0.2.1",
|
||||||
|
"tiny-inflate": "^1.0.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"ot": "bin/ot"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pako": {
|
"node_modules/pako": {
|
||||||
"version": "1.0.11",
|
"version": "1.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||||
@ -1282,6 +1281,11 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/string.prototype.codepointat": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="
|
||||||
|
},
|
||||||
"node_modules/strip-ansi": {
|
"node_modules/strip-ansi": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
@ -1335,6 +1339,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
|
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/tiny-inflate": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="
|
||||||
|
},
|
||||||
"node_modules/toidentifier": {
|
"node_modules/toidentifier": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
@ -1624,11 +1633,6 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@xmldom/xmldom": {
|
|
||||||
"version": "0.8.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz",
|
|
||||||
"integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg=="
|
|
||||||
},
|
|
||||||
"accepts": {
|
"accepts": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
@ -1905,14 +1909,6 @@
|
|||||||
"pend": "~1.2.0"
|
"pend": "~1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fonteditor-core": {
|
|
||||||
"version": "2.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/fonteditor-core/-/fonteditor-core-2.1.10.tgz",
|
|
||||||
"integrity": "sha512-NQvTBstkzkJeNTb6UUaliQs493mHj4Su0yH2d8eHQbQZQK9fIOh7X/pzKdW7BtQpDQZPSjh65ruLBqOqwGTHKQ==",
|
|
||||||
"requires": {
|
|
||||||
"@xmldom/xmldom": "^0.8.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fresh": {
|
"fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
@ -2219,6 +2215,15 @@
|
|||||||
"integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==",
|
"integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"opentype.js": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==",
|
||||||
|
"requires": {
|
||||||
|
"string.prototype.codepointat": "^0.2.1",
|
||||||
|
"tiny-inflate": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"pako": {
|
"pako": {
|
||||||
"version": "1.0.11",
|
"version": "1.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||||
@ -2429,6 +2434,11 @@
|
|||||||
"strip-ansi": "^6.0.1"
|
"strip-ansi": "^6.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"string.prototype.codepointat": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="
|
||||||
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
@ -2473,6 +2483,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
|
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
|
||||||
},
|
},
|
||||||
|
"tiny-inflate": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="
|
||||||
|
},
|
||||||
"toidentifier": {
|
"toidentifier": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "5.1.2",
|
"chalk": "5.1.2",
|
||||||
"fonteditor-core": "2.1.10",
|
"opentype.js": "1.3.4",
|
||||||
"pdf-lib": "1.17.1",
|
"pdf-lib": "1.17.1",
|
||||||
"puppeteer": "20.1.0",
|
"puppeteer": "20.1.0",
|
||||||
"puppeteer-core": "20.1.0",
|
"puppeteer-core": "20.1.0",
|
||||||
|
Loading…
Reference in New Issue
Block a user