Skip to content

Commit

Permalink
initial stab & functionality of spine marks
Browse files Browse the repository at this point in the history
  • Loading branch information
sithel committed Mar 10, 2024
1 parent 261a32f commit 084914a
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 18 deletions.
55 changes: 45 additions & 10 deletions src/book.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PAGE_LAYOUTS, PAGE_SIZES } from './constants.js';
import { updatePageLayoutInfo } from './utils/renderUtils.js';
import JSZip from 'jszip';
import { loadConfiguration } from './utils/formUtils.js';
import { drawFoldlines, drawCropmarks, drawSpineMarks } from './utils/drawing.js';
import { drawFoldlines, drawCropmarks, drawSpineMark, drawSigOrderMark } from './utils/drawing.js';
import { calculateDimensions, calculateLayout } from './utils/layout.js';
import { interleavePages, embedPagesInNewPdf } from './utils/pdf.js';

Expand All @@ -21,6 +21,7 @@ import { interleavePages, embedPagesInNewPdf } from './utils/pdf.js';
* @property {string|number} info - page # or 'b'
* @property {boolean} isSigStart
* @property {boolean} isSigEnd
* @property {number} signatureNum - which signature is this page in. 0 based
*/

/**
Expand Down Expand Up @@ -81,6 +82,7 @@ export class Book {
this.flyleafs = configuration.flyleafs;
this.cropmarks = configuration.cropMarks;
this.pdfEdgeMarks = configuration.pdfEdgeMarks;
this.sigOrderMarks = configuration.sigOrderMarks;
this.cutmarks = configuration.cutMarks;
this.format = configuration.sigFormat;
if (configuration.sigFormat === 'standardsig') {
Expand Down Expand Up @@ -308,14 +310,15 @@ export class Book {
this.format == 'customsig'
) {
// Only generate the first signature for preview
const pagesArr = isPreview ? this.rearrangedpages.slice(0, 1) : this.rearrangedpages;
const pagesArr = this.rearrangedpages;
const signatures = [{}];
const makeSignatures = async () => {
const tasks = pagesArr.map(async (pages, i) => {
console.log(pages);
signatures[i] = { name: `${this.filename}_signature${i}` };
[signatures[i].front, signatures[i].back] = await this.createSignatures({
pageIndexDetails: pages,
maxSigCount: pagesArr.length
});
});
await Promise.all(tasks);
Expand All @@ -332,7 +335,8 @@ export class Book {
await Promise.all(tasks);
};
await duplexSignatures();
previewPdf = signatures[0].duplex;
console.log("Shark")
// previewPdf = signatures[0].duplex;
}

if (this.print_file != 'aggregated' && !isPreview) {
Expand All @@ -353,7 +357,7 @@ export class Book {
await saveSignatures();
}

if (this.print_file != 'signatures' && !isPreview) {
if (this.print_file != 'signatures') {
const saveAggregate = async () => {
const aggregate = {
front: !this.duplex ? await PDFDocument.create() : null,
Expand Down Expand Up @@ -399,8 +403,11 @@ export class Book {
this.zip.file(`${this.filename}_typeset.pdf`, pdfBytes);
});
}
console.log("Do I have this? ",aggregate.duplex.getPageCount())
previewPdf = aggregate.duplex
return aggregate
};
await saveAggregate();
var results = await saveAggregate();
}

var rotationMetaInfo =
Expand Down Expand Up @@ -450,14 +457,17 @@ export class Book {
* (conditionally) populates the destPdf and (conditionally) generates the outname PDF
*
* @param {Object} config - object /w the following parameters:
* @param {PageInfo[]} config.pageList : objects that contain 3 values: { isSigStart: boolean, isSigEnd: boolean, info: either the page number or 'b'}
* @param {PageInfo[]} config.pageList : see documentation at top of file
* @param {boolean} config.back : is 'back' of page (boolean)
* @param {boolean} config.alt : alternate pages (boolean)
* @param {number} config.maxSigCount
* @return reference to the new PDF created
*/
async writepages(config) {
console.log("Write pages ", config)
const pagelist = config.pageList;
const back = config.back;
const maxSigCount = config.maxSigCount;
const filteredList = [];
const blankIndices = [];
pagelist.forEach((pageInfo, i) => {
Expand All @@ -467,6 +477,7 @@ export class Book {
blankIndices.push(i);
}
});

const [outPDF, embeddedPages] = await embedPagesInNewPdf(this.managedDoc, filteredList);

blankIndices.forEach((i) => embeddedPages.splice(i, 0, 'b'));
Expand All @@ -482,7 +493,7 @@ export class Book {
let side2flag = back;

while (block_end <= pagelist.length) {
const sigDetails = config.pageList.slice(block_start, block_end);
const sigDetails = pagelist.slice(block_start, block_end);
side2flag = this.draw_block_onto_page({
outPDF: outPDF,
embeddedPages: embeddedPages,
Expand All @@ -492,10 +503,12 @@ export class Book {
papersize: this.papersize,
positions: positions,
cropmarks: this.cropmarks,
sigOrderMarks: this.sigOrderMarks,
pdfEdgeMarks: this.pdfEdgeMarks,
cutmarks: this.cutmarks,
alt: config.alt,
side2flag: side2flag,
maxSigCount: maxSigCount,
});
block_start += offset;
block_end += offset;
Expand All @@ -507,7 +520,8 @@ export class Book {
*
* @param {Object} config - object /w the following parameters:
* @param {string|null} config.outname : name of pdf added to ongoing zip file. Ex: 'signature1duplex.pdf' (or null if no signature file needed)
* @param {PageInfo[]} config.sigDetails : objects that contain 3 values: { isSigStart: boolean, isSigEnd: boolean, info: either the page number or 'b'}
* @param {PageInfo[]} config.sigDetails : see documentation at top of file
* @param {number} config.maxSigCount: Total number of signatures
* @param {boolean} config.side2flag : is 'back' of page (boolean)
* @param {[number, number]} config.papersize : paper size (as [number, number])
* @param {number} config.block_start: Starting page index
Expand All @@ -529,10 +543,13 @@ export class Book {
const outPDF = config.outPDF;
const positions = config.positions;
const foldmarks = config.cropmarks;
const sigOrderMarks = config.sigOrderMarks;
const pdfEdgeMarks = config.pdfEdgeMarks;
const cutmarks = config.cutmarks;
const alt = config.alt;
const maxSigCount = config.maxSigCount
let side2flag = config.side2flag;
console.log("burp I see ",maxSigCount)

const block = config.embeddedPages.slice(block_start, block_end);
const currPage = outPDF.addPage(papersize);
Expand All @@ -541,6 +558,7 @@ export class Book {
? drawFoldlines(side2flag, this.duplexrotate, papersize, this.per_sheet)
: [];
const drawLines = [...cropLines, ...foldLines];
const drawRects = [];

block.forEach((page, i) => {
if (page == 'b' || page === undefined) {
Expand All @@ -558,14 +576,27 @@ export class Book {
console.error('Unexpected type for page: ', page);
}

if (pdfEdgeMarks && (sigDetails[i].isSigStart || sigDetails[i].isSigEnd)) {
drawLines.push(drawSpineMarks(sigDetails[i], positions[i]));
if (sigDetails[i].isSigStart) {
if (pdfEdgeMarks) {
drawLines.push(drawSpineMark(true, positions[i], 5));
}
if (sigOrderMarks) {
drawRects.push(drawSigOrderMark(sigDetails[i], positions[i], maxSigCount, 5, 20));
}
}
else if (sigDetails[i].isSigEnd) {
if (pdfEdgeMarks) {
drawLines.push(drawSpineMark(false, positions[i], 5));
}
}
});

drawLines.forEach((line) => {
currPage.drawLine(line);
});
drawRects.forEach((rect) => {
currPage.drawRectangle(rect);
})

if (alt) {
side2flag = !side2flag;
Expand All @@ -577,20 +608,24 @@ export class Book {
* PDF builder base function for Classic (non-Wacky) layouts. Called by [createoutputfiles]
*
* @param {Object} config
* @param {number} config.maxSigCount
* @param {PageInfo[][]} config.pageIndexDetails : a nested list of objects.
*/
async createSignatures(config) {
console.log("createSignatures ",config)
const pages = config.pageIndexDetails;
const tasks = [
this.writepages({
pageList: pages[0],
back: false,
alt: false,
maxSigCount: config.maxSigCount,
}),
this.writepages({
pageList: pages[1],
back: true,
alt: false,
maxSigCount: config.maxSigCount,
}),
];
const [pdfFront, pdfBack] = await Promise.all(tasks);
Expand Down
9 changes: 9 additions & 0 deletions src/html/page_layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ <h2>Page Layout</h2>
data-balloon-pos="up"
>
<input type="checkbox" name="pdf_edge_marks" /></span
></label><br>
<label
>Add signature order marks (spine)
<span
data-balloon-length="medium"
aria-label="Puts staggered lines down the different signature spines to indicate order"
data-balloon-pos="up"
>
<input type="checkbox" name="sig_order_marks" /></span
></label>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/models/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export const schema = z.object({
cropMarks: urlSafe(coercedBoolean).default(false),
cutMarks: urlSafe(coercedBoolean).default(false),
pdfEdgeMarks: urlSafe(coercedBoolean).default(false),
sigOrderMarks: urlSafe(coercedBoolean).default(false),
pageScaling,
pagePositioning,
mainForeEdgePaddingPt: urlSafe(z.coerce.number()).default(0),
Expand Down
15 changes: 11 additions & 4 deletions src/signatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ export class Signatures {
const newsigs = [];

// Use the booklet class for each signature
this.signaturepagelists.forEach((pagerange) => {
this.signaturepagelists.forEach((pagerange, i) => {
const pagelistdetails = this.booklet(
pagerange,
this.duplex,
this.per_sheet,
this.duplexrotate
this.duplexrotate,
i
);
newsigs.push(pagelistdetails);
});
Expand Down Expand Up @@ -122,8 +123,9 @@ export class Signatures {
* @param {boolean} duplex - Whether both front and back sides go in the same file or not.
* @param {number} per_sheet - number of pages per sheet (front and back combined)
* @param {boolean} duplexrotate - whether to rotate alternating sheets or not.
* @param {number} sig_num - signature number (0 indexed)
*/
booklet(pages, duplex, per_sheet, duplexrotate) {
booklet(pages, duplex, per_sheet, duplexrotate, sig_num) {
const pagelistdetails = duplex ? [[]] : [[], []];
const { front, rotate, back } = BOOKLET_LAYOUTS[per_sheet];

Expand All @@ -139,19 +141,21 @@ export class Signatures {
let front_end = center;
let back_start = center;
let back_end = center + pageblock;

console.log("outside")
while (front_start >= 0 && back_end <= pages.length) {
const front_block = pages.slice(front_start, front_end);
const back_block = pages.slice(back_start, back_end);

const block = [...front_block, ...back_block];

console.log(" ~~~~ SIG NUM "+sig_num+" on "+front_start+" --> "+back_end)
front_config.forEach((pnum) => {
const page = block[pnum - 1]; //page layouts are 1-indexed, not 0-index
pagelistdetails[0].push({
info: page,
isSigStart: front_start == 0 && pnum == 1,
isSigEnd: front_start == 0 && pnum == block.length,
signatureNum: sig_num,
});
});

Expand All @@ -163,11 +167,14 @@ export class Signatures {
info: page,
isSigStart: front_start == 0 && pnum == 1,
isSigEnd: front_start == 0 && pnum == block.length,
signatureNum: sig_num,
});
});

// Update all our counters
console.log("stepa "+front_start)
front_start -= pageblock;
console.log("stepb "+front_start)
front_end -= pageblock;
back_start += pageblock;
back_end += pageblock;
Expand Down
49 changes: 45 additions & 4 deletions src/utils/drawing.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ export function drawCropmarks(papersize, per_sheet) {
}

/**
* @param {import("../book.js").PageInfo} sigDetails - page info object
* @param {boolean} draw_top_mark - true to draw mark at top of PDF, false for bottom of PDF
* @param {import("../book.js").Position} position - position info object
* @param {number} w - width of the line in pts
* @returns {Line}
*/
export function drawSpineMarks(sigDetails, position) {
const w = 5;
export function drawSpineMark(draw_top_mark, position, w) {
let startX, startY, endX, endY;
if (sigDetails.isSigStart) {
if (draw_top_mark) {
[startX, startY] = position.spineMarkTop;
[endX, endY] = position.spineMarkTop;
} else {
Expand Down Expand Up @@ -148,6 +148,47 @@ export function drawSpineMarks(sigDetails, position) {
return drawLineArgs;
}


/**
* @param {import("../book.js").PageInfo} sigDetails - page info object
* @param {import("../book.js").Position} position - position info object
* @param {number} maxSigCount - number of total signatures
* @param {number} w - width of the mark in pts
* @param {number} suggested_h - suggested height of the mark in pts (can be scaled down to fit all marks between PDF top/bottom)
* @returns {Line}
*/
export function drawSigOrderMark(sigDetails, position, maxSigCount, w, suggested_h) {
const top = drawSpineMark(true, position, w);
const bottom = drawSpineMark(false, position, w);

let x = top.start.x
let y = top.start.y

const dist = (position.rotation == 0) ? top.start.y - bottom.start.y : top.start.x - bottom.start.x
let h = Math.min(suggested_h, dist/maxSigCount)
const offset = h * sigDetails.signatureNum;
console.log("Looking at signature ",sigDetails.signatureNum," of ",maxSigCount," PDF top/bottom distance ",dist," results in ",h," (",suggested_h," vs ",(dist/maxSigCount),") order mark height w/ offset ",offset," (width ",w,")")

if (position.rotation == 0) {
h = h * -1;
y -= offset;
} else {
const temp = h;
h = w;
w = temp * -1;
x -= offset
}

return {
x: x,
y: y,
width: w,
height: h,
borderWidth: 0,
color: rgb(0, 0, 0),
opacity: 0.5,
};
}
/**
* @param {number} x
* @param {number} ystart
Expand Down
1 change: 1 addition & 0 deletions src/utils/formUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const fromFormToConfiguration = (form) =>
paperRotation90: form.has('paper_rotation_90'),
pageLayout: form.get('pagelayout'),
cropMarks: form.has('cropmarks'),
sigOrderMarks: form.has('sig_order_marks'),
pdfEdgeMarks: form.has('pdf_edge_marks'),
cutMarks: form.has('cutmarks'),
pageScaling: form.get('page_scaling'),
Expand Down
4 changes: 4 additions & 0 deletions src/utils/renderUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ export function renderFormFromSettings(configuration) {
document.querySelector("input[name='cropmarks']").checked = true;
}

if (configuration.sigOrderMarks) {
document.querySelector("input[name='sig_order_marks']").checked = true;
}

if (configuration.pdfEdgeMarks) {
document.querySelector("input[name='pdf_edge_marks']").checked = true;
}
Expand Down

0 comments on commit 084914a

Please sign in to comment.