diff --git a/index.html b/index.html
index b059e65..47153f6 100644
--- a/index.html
+++ b/index.html
@@ -279,8 +279,8 @@
Wacky Small Layouts
-
-
+
+
diff --git a/src/book.js b/src/book.js
index 3c9fc41..18bd3f8 100644
--- a/src/book.js
+++ b/src/book.js
@@ -114,35 +114,32 @@ export class Book {
}
/**
- * Populates [this.orderedpages] (array [0, 1, ... this.page_sheets * # of sheets])
+ * Populates `this.orderedpages` array with page numbers and 'b' placeholders to represent flyleafs.
+ * Flyleafs are added to the beginning and end of the ordered pages array.
+ *
+ * @returns {void}
*/
createpagelist() {
this.pagecount = this.currentdoc.getPageCount();
- this.orderedpages = Array.from({ length: this.pagecount }, (x, i) => i);
-
- for (let i = 0; i < this.flyleafs; i++) {
- this.orderedpages.unshift('b');
- this.orderedpages.unshift('b');
-
- this.orderedpages.push('b');
- this.orderedpages.push('b');
- }
-
- // padding calculations if needed
- let pagetotal = this.orderedpages.length;
-
- // calculate how many sheets of paper the output document needs
+ this.orderedpages = Array.from({ length: this.pagecount }, (_, i) => i);
+
+ // Add flyleafs to the beginning and end of the ordered pages array
+ const flyleafPages = Array.from({ length: this.flyleafs * 2 }, () => 'b');
+ this.orderedpages = [...flyleafPages, ...this.orderedpages, ...flyleafPages];
+
+ // Calculate total number of pages after adding flyleafs
+ const pagetotal = this.orderedpages.length;
+
+ // Calculate the number of sheets needed for the output document
let sheets = Math.floor(pagetotal / this.per_sheet);
-
- // pad out end of document if necessary
- if (pagetotal % this.per_sheet > 0) {
- sheets += 1;
- let padding = (sheets * this.per_sheet) - pagetotal;
- for (let i = 0; i < padding; i++) {
- this.orderedpages.push('b');
- }
+
+ // Pad out the end of the document if necessary
+ const padding = sheets * this.per_sheet - pagetotal;
+ if (padding > 0) {
+ this.orderedpages.push(...Array(padding).fill('b'));
}
- console.log("Calculated pagecount [",this.pagecount,"] and ordered pages: ", this.orderedpages);
+
+ console.log("Calculated pagecount [", this.pagecount, "] and ordered pages: ", this.orderedpages);
}
/**
@@ -154,40 +151,50 @@ export class Book {
let pages;
[this.managedDoc, pages] = await this.embedPagesInNewPdf(this.currentdoc);
- for (var i = 0; i < pages.length; ++i) {
- var page = pages[i];
- var newPage = this.managedDoc.addPage();
- var rotate90cw = this.source_rotation == '90cw'
- || (this.source_rotation == 'out_binding' && i % 2 == 0)
- || (this.source_rotation == 'in_binding' && i % 2 == 1);
- var rotate90ccw = this.source_rotation == '90ccw'
- || (this.source_rotation == 'out_binding' && i % 2 == 1)
- || (this.source_rotation == 'in_binding' && i % 2 == 0);
- if (this.source_rotation == 'none') {
- newPage.setSize(page.width, page.height);
- newPage.drawPage(page);
- } else if (rotate90ccw) {
+ pages.forEach((page, i) => {
+ const newPage = this.managedDoc.addPage();
+ let rotateAngle = -1;
+ let evenPage = i % 2 === 0;
+
+ // Determine rotation angle
+ switch (this.source_rotation) {
+ case 'none':
+ rotateAngle = 0;
+ break;
+ case '90cw':
+ rotateAngle = -90;
+ break;
+ case '90ccw':
+ rotateAngle = 90;
+ break;
+ case 'out_binding':
+ rotateAngle = evenPage ? -90 : 90;
+ break;
+ case 'in_binding':
+ rotateAngle = evenPage ? 90 : -90;
+ break;
+ default:
+ const e = new Error("Invalid source rotation");
+ console.error(e);
+ throw e;
+ }
+
+ // Apply rotation to the new page
+ if (rotateAngle !== 0) {
newPage.setSize(page.height, page.width);
newPage.drawPage(page, {
- x: page.height,
- y: 0,
- rotate: degrees(90),
- });
- } else if (rotate90cw) {
- newPage.setSize(page.height, page.width);
- newPage.drawPage(page, {
- x: 0,
- y: page.width,
- rotate: degrees(-90),
+ x: (rotateAngle === 90 ? page.height : 0),
+ y: (rotateAngle === -90 ? page.width : 0),
+ rotate: degrees(rotateAngle),
});
} else {
- var e = new Error("??? what sorta' layout you think you're going to get?");
- console.error(e);
- throw e;
+ newPage.setSize(page.width, page.height);
+ newPage.drawPage(page);
}
+
page.embed();
this.cropbox = newPage.getCropBox();
- }
+ });
console.log("The updatedDoc doc has : ", this.managedDoc.getPages(), " vs --- ", this.managedDoc.getPageCount());
@@ -213,7 +220,7 @@ export class Book {
break;
case 'a9_3_3_4':
case 'a10_6_10s':
- case 'A7_2_16s':
+ case 'a7_2_16s':
case '1_3rd':
case '8_zine':
case 'a_3_6s':
@@ -237,81 +244,56 @@ export class Book {
}
/**
- * Calls the appropriate builder based on [this.format]
- * to generate PDF & populate Previewer
- * @param isPreview - if it's true we only generate preview content, if it's not true... we still
- * generate preview content AND a downloadable zip
+ * Calls the appropriate builder based on `this.format` to generate PDF & populate Previewer.
+ * @param {boolean} isPreview - If true, generates only preview content; otherwise, generates both preview content and a downloadable zip.
+ * @returns {Promise} - A promise resolving to 1 if it's a preview or a file blob if it's not.
*/
async createoutputfiles(isPreview) {
- let previewFrame = document.getElementById('pdf');
+ const previewFrame = document.getElementById('pdf');
previewFrame.style.display = 'none';
let resultPDF = null;
- // create a directory named after the input pdf and fill it with
- // the signatures
this.zip = new JSZip();
- var origFileName = this.inputpdf.replace(/\s|,|\.pdf/, '');
+ const origFileName = this.inputpdf.replace(/\s|,|\.pdf/, '');
this.filename = origFileName;
- if (this.format == 'perfect' || this.format == 'booklet' || this.format == 'standardsig' || this.format == 'customsig') {
- const generateAggregate = this.print_file != "signatures";
- const generateSignatures = this.print_file != "aggregated";
- const filename = (this.format == 'standardsig' || this.format == 'customsig') ? 'signatures' : this.format;
- const side1PageNumbers = new Set(this.rearrangedpages.reduce((accumulator, currentValue) => { return accumulator.concat(currentValue[0]); },[]));
+ if (['perfect', 'booklet', 'standardsig', 'customsig'].includes(this.format)) {
+ const generateAggregate = this.print_file !== "signatures";
+ const generateSignatures = this.print_file !== "aggregated";
+ const side1PageNumbers = new Set(this.rearrangedpages.reduce((accumulator, currentValue) => accumulator.concat(currentValue[0]), []));
const [pdf0PageNumbers, pdf1PageNumbers] = (!generateAggregate || this.duplex) ? [null, null]
- : [
- Array.from(Array(this.managedDoc.getPageCount()).keys()).map( p => { return (side1PageNumbers.has(p) ? p : 'b');}),
- Array.from(Array(this.managedDoc.getPageCount()).keys()).map( p => { return (!side1PageNumbers.has(p) ? p : 'b');})
- ];
- const [aggregatePdf0, embeddedPages0] = (generateAggregate) ? await this.embedPagesInNewPdf(this.managedDoc, pdf0PageNumbers) : [null, null];
+ : [
+ Array.from(Array(this.managedDoc.getPageCount()).keys()).map(p => side1PageNumbers.has(p) ? p : 'b'),
+ Array.from(Array(this.managedDoc.getPageCount()).keys()).map(p => !side1PageNumbers.has(p) ? p : 'b')
+ ];
+ const [aggregatePdf0, embeddedPages0] = generateAggregate ? await this.embedPagesInNewPdf(this.managedDoc, pdf0PageNumbers) : [null, null];
const [aggregatePdf1, embeddedPages1] = (generateAggregate && !this.duplex) ? await this.embedPagesInNewPdf(this.managedDoc, pdf1PageNumbers) : [null, null];
- const forLoop = async _ => {
- for (let i = 0; i < this.rearrangedpages.length; i++) {
- let signature = this.rearrangedpages[i];
- await this.createsignatures({
- embeddedPages: (generateAggregate) ? [embeddedPages0, embeddedPages1] : null,
- aggregatePdfs: (generateAggregate) ? [aggregatePdf0, aggregatePdf1] : null,
- pageIndexDetails: signature,
- id: (generateSignatures) ? `signature${i}` : null,
- isDuplex: this.duplex,
- fileList: this.filelist
- });
- }
- };
- await forLoop();
-
- if (aggregatePdf1 != null) {
- await aggregatePdf1.save().then(pdfBytes => {
- if (!isPreview)
- this.zip.file('aggregate_side2.pdf', pdfBytes);
- });
- }
- if (aggregatePdf0 != null) {
- await aggregatePdf0.save().then(pdfBytes => {
- if (!isPreview)
- this.zip.file((this.duplex) ? 'aggregate_book.pdf' : 'aggregate_side1.pdf', pdfBytes);
+
+ for (let i = 0; i < this.rearrangedpages.length; i++) {
+ const signature = this.rearrangedpages[i];
+ await this.createsignatures({
+ embeddedPages: generateAggregate ? [embeddedPages0, embeddedPages1] : null,
+ aggregatePdfs: generateAggregate ? [aggregatePdf0, aggregatePdf1] : null,
+ pageIndexDetails: signature,
+ id: generateSignatures ? `signature${i}` : null,
+ isDuplex: this.duplex,
+ fileList: this.filelist
});
}
- var rotationMetaInfo = ((this.paper_rotation_90) ? "_paperRotated" : "")
- + ((this.source_rotation == 'none') ? "" : `_${this.source_rotation}`);
+
+ if (aggregatePdf1 != null && !isPreview)
+ this.zip.file('aggregate_side2.pdf', await aggregatePdf1.save());
+ if (aggregatePdf0 != null && !isPreview)
+ this.zip.file(this.duplex ? 'aggregate_book.pdf' : 'aggregate_side1.pdf', await aggregatePdf0.save());
+
+ const rotationMetaInfo = (this.paper_rotation_90 ? "_paperRotated" : "") + (this.source_rotation === 'none' ? "" : `_${this.source_rotation}`);
this.filename = `${origFileName}${rotationMetaInfo}`;
resultPDF = aggregatePdf0;
- } else if (this.format == 'a9_3_3_4') {
- resultPDF = await this.buildSheets(this.filename, this.book.a9_3_3_4_builder());
- } else if (this.format == 'a10_6_10s') {
- resultPDF = await this.buildSheets(this.filename, this.book.a10_6_10s_builder());
- } else if (this.format == 'a_4_8s') {
- resultPDF = await this.buildSheets(this.filename, this.book.a_4_8s_builder());
- } else if (this.format == 'a_3_6s') {
- resultPDF = await this.buildSheets(this.filename, this.book.a_3_6s_builder());
- } else if (this.format == 'A7_2_16s') {
- resultPDF = await this.buildSheets(this.filename, this.book.a7_2_16s_builder());
- } else if (this.format == '1_3rd') {
- resultPDF = await this.buildSheets(this.filename, this.book.page_1_3rd_builder());
- } else if (this.format == '8_zine') {
- resultPDF = await this.buildSheets(this.filename, this.book.page_8_zine_builder());
+ } else if (['a9_3_3_4', 'a10_6_10s', 'a_4_8s', 'a_3_6s', 'a7_2_16s', '1_3rd', '8_zine'].includes(this.format)) {
+ resultPDF = await this.buildSheets(this.filename, this.book[`${this.format}_builder`]());
}
- console.log("Attempting to generate preview for ",resultPDF);
+
+ console.log("Attempting to generate preview for ", resultPDF);
if (resultPDF != null) {
const pdfDataUri = await resultPDF.saveAsBase64({ dataUri: true });
@@ -324,23 +306,13 @@ export class Book {
viewerPrefs.setDisplayDocTitle(true);
previewFrame.style.width = `450px`;
- let height = this.papersize[1] / this.papersize[0] * 500;
+ const height = this.papersize[1] / this.papersize[0] * 500;
previewFrame.style.height = `${height}px`;
previewFrame.style.display = '';
previewFrame.src = pdfDataUri;
}
- if (!isPreview)
- return this.saveZip();
- else
- return Promise.resolve(1);
- }
-
- /**
- * @return the aggregate file w/ all the original pages embedded, but nothing placed
- */
- async create_base_aggregate_files() {
- return aggregatePdf;
+ return isPreview ? Promise.resolve(1) : this.saveZip();
}
/**
@@ -515,117 +487,99 @@ export class Book {
*/
draw_spine_marks(curPage, sigDetails, position) {
let w = 5;
+ let startX, startY, endX, endY;
+
+ if (sigDetails.isSigStart) {
+ startX = position.spineMarkTop[0];
+ startY = position.spineMarkTop[1];
+ endX = position.spineMarkTop[0];
+ endY = position.spineMarkTop[1];
+ } else {
+ startX = position.spineMarkBottom[0];
+ startY = position.spineMarkBottom[1];
+ endX = position.spineMarkBottom[0];
+ endY = position.spineMarkBottom[1];
+ }
+
if (position.rotation == 0) {
- console.log(" --> draw this: ",{
- start: {
- x: (sigDetails.isSigStart) ? position.spineMarkTop[0] - w/2: position.spineMarkBottom[0] - w/2,
- y: ((sigDetails.isSigStart) ? position.spineMarkTop[1] : position.spineMarkBottom[1] )
- },
- end: {
- x: (sigDetails.isSigStart) ? position.spineMarkTop[0] + w/2: position.spineMarkBottom[0]+ w/2,
- y: ((sigDetails.isSigStart) ? position.spineMarkTop[1] : position.spineMarkBottom[1] )
- },
- thickness: 0.5,
- color: rgb(0,0,0),
- opacity: 1,
- })
- curPage.drawLine({
- start: {
- x: (sigDetails.isSigStart) ? position.spineMarkTop[0] - w/2: position.spineMarkBottom[0] - w/2,
- y: ((sigDetails.isSigStart) ? position.spineMarkTop[1] : position.spineMarkBottom[1] )
- },
- end: {
- x: (sigDetails.isSigStart) ? position.spineMarkTop[0] + w/2: position.spineMarkBottom[0]+ w/2,
- y: ((sigDetails.isSigStart) ? position.spineMarkTop[1] : position.spineMarkBottom[1] )
- },
- thickness: 0.5,
- color: rgb(0,0,0),
- opacity: 1,
- })
+ startX -= w / 2;
+ endX += w / 2;
} else {
- curPage.drawLine({
- start: {
- x: (sigDetails.isSigStart) ? position.spineMarkTop[0] : position.spineMarkBottom[0],
- y: ((sigDetails.isSigStart) ? position.spineMarkTop[1] - w/2: position.spineMarkBottom[1] ) - w/2
- },
- end: {
- x: (sigDetails.isSigStart) ? position.spineMarkTop[0] : position.spineMarkBottom[0],
- y: ((sigDetails.isSigStart) ? position.spineMarkTop[1] + w/2: position.spineMarkBottom[1] ) + w/2
- },
- thickness: 0.25,
- color: rgb(0,0,0),
- opacity: 1,
- })
+ startY -= w / 2;
+ endY += w / 2;
+ }
+
+ let drawLineArgs = {
+ start: { x: startX, y: startY },
+ end: { x: endX, y: endY },
+ thickness: position.rotation == 0 ? 0.5 : 0.25,
+ color: rgb(0, 0, 0),
+ opacity: 1,
}
+
+ console.log(" --> draw this: ", drawLineArgs);
+ curPage.drawLine(drawLineArgs);
}
+
draw_cropmarks(currPage, side2flag) {
- switch(this.per_sheet){
+ const lineSettings = {
+ opacity: 0.4,
+ dashArray: [1, 5]
+ };
+ let start, end;
+
+ switch (this.per_sheet) {
case 32:
if (side2flag) {
- if (this.duplexrotate){
- currPage.drawLine({
- start: {x: this.papersize[0] * 0.75, y: this.papersize[1] * 0.75 },
- end: {x: this.papersize[0] * 0.75, y: this.papersize[1] * 0.5 },
- opacity: 0.4,
- dashArray: [1, 5]
- });} else {
- currPage.drawLine({
- start: {x: this.papersize[0] * 0.25, y: this.papersize[1] * 0.5 },
- end: {x: this.papersize[0] * 0.25, y: this.papersize[1] * 0.25 },
- opacity: 0.4,
- dashArray: [1, 5]
- });
+ lineSettings.dashArray = [1, 5];
+ if (this.duplexrotate) {
+ start = { x: this.papersize[0] * 0.75, y: this.papersize[1] * 0.75 };
+ end = { x: this.papersize[0] * 0.75, y: this.papersize[1] * 0.5 };
+ } else {
+ start = { x: this.papersize[0] * 0.25, y: this.papersize[1] * 0.5 };
+ end = { x: this.papersize[0] * 0.25, y: this.papersize[1] * 0.25 };
+ }
+ currPage.drawLine({ start, end, ...lineSettings });
}
- }
- /* falls through */
+ /* falls through */
case 16:
if (side2flag) {
- if (this.duplexrotate){
- currPage.drawLine({
- start: {x: 0, y: this.papersize[1] * 0.75 },
- end: {x: this.papersize[0] * 0.5, y: this.papersize[1] * 0.75 },
- opacity: 0.4,
- dashArray: [3, 5]
- });} else {
- currPage.drawLine({
- start: {x: this.papersize[0] * 0.5, y: this.papersize[1] * 0.25 },
- end: {x: this.papersize[0], y: this.papersize[1] * 0.25 },
- opacity: 0.4,
- dashArray: [3, 5]
- });
+ lineSettings.dashArray = [3, 5];
+ if (this.duplexrotate) {
+ start = { x: 0, y: this.papersize[1] * 0.75 };
+ end = { x: this.papersize[0] * 0.5, y: this.papersize[1] * 0.75 };
+ } else {
+ start = { x: this.papersize[0] * 0.5, y: this.papersize[1] * 0.25 };
+ end = { x: this.papersize[0], y: this.papersize[1] * 0.25 };
+ }
+ currPage.drawLine({ start, end, ...lineSettings });
}
- }
- /* falls through */
+ /* falls through */
case 8:
if (side2flag) {
- if (this.duplexrotate){
- currPage.drawLine({
- start: {x: this.papersize[0] * 0.5, y: 0 },
- end: { y: this.papersize[1] * 0.5, x: this.papersize[0] * 0.5 },
- opacity: 0.4,
- dashArray: [5, 5]
- });} else {
- currPage.drawLine({
- start: {x: this.papersize[0] * 0.5, y: this.papersize[1] },
- end: { y: this.papersize[1] * 0.5, x: this.papersize[0] * 0.5 },
- opacity: 0.4,
- dashArray: [5, 5]
- });
+ lineSettings.dashArray = [5, 5];
+ if (this.duplexrotate) {
+ start = { x: this.papersize[0] * 0.5, y: 0 };
+ end = { y: this.papersize[1] * 0.5, x: this.papersize[0] * 0.5 };
+ } else {
+ start = { x: this.papersize[0] * 0.5, y: this.papersize[1] };
+ end = { y: this.papersize[1] * 0.5, x: this.papersize[0] * 0.5 };
+ }
+ currPage.drawLine({ start, end, ...lineSettings });
}
- }
- /* falls through */
+ /* falls through */
case 4:
if (!side2flag) {
- currPage.drawLine({
- start: { x: 0, y: this.papersize[1] * 0.5 },
- end: { x: this.papersize[0], y: this.papersize[1] * 0.5 },
- opacity: 0.4,
- dashArray: [10, 5]
- });
- }
- }
+ lineSettings.dashArray = [10, 5];
+ start = { x: 0, y: this.papersize[1] * 0.5 };
+ end = { x: this.papersize[0], y: this.papersize[1] * 0.5 };
+ currPage.drawLine({ start, end, ...lineSettings });
+ }
+ break;
+ }
}
+
draw_cutmarks(currPage) {
let lines = [];
diff --git a/src/models/configuration.js b/src/models/configuration.js
index d96465f..ed604e1 100644
--- a/src/models/configuration.js
+++ b/src/models/configuration.js
@@ -48,7 +48,7 @@ const pageScaling = urlSafe(z.enum(["centered", "lockratio", "stretch"])).defaul
const pagePositioning = urlSafe(z.enum(["centered", "binding_aligned"])).default("centered");
-const sigFormat = urlSafe(z.enum(["booklet", "perfect", "standardsig", "customsig", "1_3rd", "A7_2_16s", "8_zine", "a_3_6s", "a9_3_3_4", "a_4_8s", "a10_6_10s"])).default("standardsig");
+const sigFormat = urlSafe(z.enum(["booklet", "perfect", "standardsig", "customsig", "1_3rd", "a7_2_16s", "8_zine", "a_3_6s", "a9_3_3_4", "a_4_8s", "a10_6_10s"])).default("standardsig");
const wackySpacing = urlSafe(z.enum(["wacky_pack", "wacky_gap"])).default("wacky_pack");
diff --git a/src/utils/renderUtils.js b/src/utils/renderUtils.js
index efebef4..6816dea 100644
--- a/src/utils/renderUtils.js
+++ b/src/utils/renderUtils.js
@@ -136,7 +136,7 @@ export function renderWacky() {
document.getElementById('a10_6_10s').checked ||
document.getElementById('a_3_6s').checked ||
document.getElementById('a_4_8s').checked ||
- document.getElementById('A7_2_16s').checked ||
+ document.getElementById('a7_2_16s').checked ||
document.getElementById('1_3rd').checked;
console.log('Is a wacky layout? ', isWacky);
document
diff --git a/src/wacky_imposition.js b/src/wacky_imposition.js
index cc21632..e448575 100644
--- a/src/wacky_imposition.js
+++ b/src/wacky_imposition.js
@@ -29,7 +29,7 @@ export class WackyImposition{
} else if (format == "a_3_6s") {
this.sheets = Math.ceil(pages.length/36.0);
this.sigconfig = Array(Math.ceil(pages.length/12))
- } else if (format == "A7_2_16s") {
+ } else if (format == "a7_2_16s") {
this.sheets = Math.ceil(pages.length/32.0);
this.sigconfig = Array(this.sheets * 2)
} else if (format == "8_zine") {