/*
PDF Tool — conversion dialogs
"Export Images" : renders the open document's pages to JPEG/PNG, including
any overlays currently placed (what you see is what you get).
"From Images" : builds a brand new PDF out of a list of images via pdf-lib,
either onto page-sized "base plates" or pages matching each
image. The result can be opened straight in the editor
without ever touching the server.
*/
(function (T) {
'use strict';
var FONT = "'Helvetica Neue', Arial, sans-serif";
/* Page sizes in PDF points (72 per inch) */
var PAGE_PRESETS = {
auto: null,
a4p: [595.28, 841.89],
a4l: [841.89, 595.28],
a3p: [841.89, 1190.55],
a3l: [1190.55, 841.89],
letterp: [612, 792],
letterl: [792, 612],
legalp: [612, 1008]
};
/* Draw the editor's overlays onto an export canvas at its own resolution. */
function drawOverlays(cx, overlays, W, H, imgMap) {
(overlays || []).forEach(function (o) {
if (o.type === 'text') {
var fontPx = o.fontFrac * H;
cx.fillStyle = o.color || '#000';
cx.textBaseline = 'top';
cx.font = fontPx + 'px ' + FONT;
String(o.t).split('\n').forEach(function (ln, i) {
cx.fillText(ln, o.fx * W, o.fy * H + i * fontPx * 1.25);
});
} else if (o.type === 'image' && imgMap[o.src]) {
cx.drawImage(imgMap[o.src], o.fx * W, o.fy * H, o.fwFrac * W, o.fhFrac * H);
}
});
}
function preloadOverlayImages(overlaysByPage) {
var srcs = {};
Object.keys(overlaysByPage || {}).forEach(function (k) {
(overlaysByPage[k] || []).forEach(function (o) {
if (o.type === 'image') { srcs[o.src] = 1; }
});
});
var map = {};
return Promise.all(Object.keys(srcs).map(function (src) {
return T.loadImage(src).then(function (img) { map[src] = img; },
function () { /* skip an image that will not load */ });
})).then(function () { return map; });
}
/* ── Export pages as images ─────────────────────────────────────── */
T.openExportImages = function (doc) {
if (!doc || !doc.pdf) { return; }
if (!doc.savePath) {
T.toast('Save this document first so the images have somewhere to go.', true);
return;
}
var dlg = T.modal({
title: 'Export Pages as Images',
bodyHtml:
'
' +
'Format' +
'
' +
'' +
'' +
'
' +
'
' +
'
' +
'JPEG quality: 90%' +
'' +
'
' +
'
' +
'Resolution' +
'' +
'
' +
'
Saved next to the document. Text, images and chops you have placed are included.
' +
'',
actions: [
{ label: 'Cancel', onClick: function (c) { c.close(); } },
{ label: 'Export', primary: true, onClick: run }
]
});
var qField = dlg.body.querySelector('#exQField');
var qRange = dlg.body.querySelector('#exQ');
qRange.addEventListener('input', function () {
dlg.body.querySelector('#exQVal').textContent = this.value;
});
Array.prototype.forEach.call(dlg.body.querySelectorAll('input[name=exFmt]'), function (r) {
r.addEventListener('change', function () {
qField.style.display = this.value === 'jpg' ? '' : 'none';
});
});
function run(ctx) {
var fmt = dlg.body.querySelector('input[name=exFmt]:checked').value;
var quality = parseInt(qRange.value, 10) / 100;
var scale = parseFloat(dlg.body.querySelector('#exScale').value);
var mime = fmt === 'png' ? 'image/png' : 'image/jpeg';
var ext = fmt === 'png' ? '.png' : '.jpg';
var outDir = T.dirOf(doc.savePath);
var base = T.basenameNoExt(doc.savePath);
var prog = dlg.body.querySelector('#exProg');
ctx.button.disabled = true;
prog.innerHTML = '
Preparing…
';
preloadOverlayImages(doc.overlays).then(function (imgMap) {
var n = doc.pdf.numPages;
function fail(err) {
prog.innerHTML = '