Skip to content

Commit

Permalink
merged in main, resolved conflict with book & drawing
Browse files Browse the repository at this point in the history
  • Loading branch information
sithel committed Apr 28, 2024
2 parents 087172b + 6ccd741 commit 92bceae
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 6 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bookbinder",
"version": "1.3.7",
"version": "1.5.0",
"description": "An app to rearrange PDF pages for printing for bookbinding",
"type": "module",
"scripts": {
Expand Down
Binary file added public/img/sewing_settings_explanation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 34 additions & 1 deletion 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, drawSpineMark, drawSigOrderMark } from './utils/drawing.js';
import { drawFoldlines, drawCropmarks, drawSpineMarks, drawSigOrderMark, drawSewingMarks } from './utils/drawing.js';
import { calculateDimensions, calculateLayout } from './utils/layout.js';
import { interleavePages, embedPagesInNewPdf } from './utils/pdf.js';

Expand All @@ -37,6 +37,15 @@ import { interleavePages, embedPagesInNewPdf } from './utils/pdf.js';
* @property {boolean} [isLeftPage]: isLeftPage,
*/

/**
* @typedef SewingMarks
* @type {object}
* @property {boolean} isEnabled - specifies if marks should be drawed,
* @property {number} amount - amount of places to saw.
* @property {number} marginPt - distance from the end of page to a kettle point,
* @property {number} tapeWidthPt - distance between two seing points
*/

export class Book {
/** @param { import("./models/configuration.js").Configuration } configuration */
constructor(configuration) {
Expand Down Expand Up @@ -81,6 +90,12 @@ export class Book {
this.page_positioning = configuration.pagePositioning;
this.flyleafs = configuration.flyleafs;
this.cropmarks = configuration.cropMarks;
this.sewingMarks = {
isEnabled: configuration.sewingMarksEnabled,
amount: configuration.sewingMarksAmount,
marginPt: configuration.sewingMarksMarginPt,
tapeWidthPt: configuration.sewingMarksTapeWidthPt,
};
this.pdfEdgeMarks = configuration.pdfEdgeMarks;
this.sigOrderMarks = configuration.sigOrderMarks;
this.cutmarks = configuration.cutMarks;
Expand Down Expand Up @@ -509,6 +524,7 @@ export class Book {
alt: config.alt,
side2flag: side2flag,
maxSigCount: maxSigCount,
sewingMarks: this.sewingMarks,
});
block_start += offset;
block_end += offset;
Expand All @@ -533,6 +549,7 @@ export class Book {
* @param {Position[]} config.positions: list of page positions
* @param {PDFDocument} [config.outPDF]: PDF to write to, in addition to PDF created w/ `outname` (or null)
* @param {(PDFEmbeddedPage|string)[]} [config.embeddedPages] : pages already embedded in the `destPdf` to assemble in addition (or null)
* @param {SewingMarks} config.sewingMarks: config for drawing FrenchMarks
*/

draw_block_onto_page(config) {
Expand All @@ -549,6 +566,7 @@ export class Book {
const alt = config.alt;
const maxSigCount = config.maxSigCount;
let side2flag = config.side2flag;
const sewingMarks = config.sewingMarks;

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

block.forEach((page, i) => {
if (page == 'b' || page === undefined) {
Expand Down Expand Up @@ -587,6 +606,16 @@ export class Book {
drawLines.push(drawSpineMark(false, positions[i], 5));
}
}
const sewingMarkPoints = sewingMarks.isEnabled
? drawSewingMarks(
sigDetails[i],
positions[i],
sewingMarks.amount,
sewingMarks.marginPt,
sewingMarks.tapeWidthPt
)
: [];
drawPoints.push(...sewingMarkPoints);
});

drawLines.forEach((line) => {
Expand All @@ -596,6 +625,10 @@ export class Book {
currPage.drawRectangle(rect);
});

drawPoints.forEach((point) => {
currPage.drawCircle(point);
});

if (alt) {
side2flag = !side2flag;
}
Expand Down
6 changes: 6 additions & 0 deletions src/book.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ describe('Book model', () => {
fore_edge: 0,
top: 0,
},
sewingMarks: {
amount: 3,
isEnabled: false,
marginPt: 72,
tapeWidthPt: 36,
},
managedDoc: null,
page_positioning: 'centered',
page_scaling: 'lockratio',
Expand Down
39 changes: 39 additions & 0 deletions src/html/page_layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,45 @@ <h2>Page Layout</h2>
</select>
</span>

<span class="row">
<label>Add marks for sewing</label>
<input type="checkbox" id="add_sewing_marks_checkbox" name="add_sewing_marks_checkbox" />
<details>
<summary>Detailed settings for sewing</summary>
Look at the image below.
<span class="row">
<label>(A) Margin (distance where first point should be draw):</label>
<input
type="number"
id="sewing_marks_margin_pt"
name="sewing_marks_margin_pt"
class="layout_margin_user_input_field"
/><sub>pt</sub><br />

<label>(B) Amount of sewing points:</label>
<input
type="number"
id="sewing_marks_amount"
name="sewing_marks_amount"
class="layout_margin_user_input_field"
/><br />

<label>(C) Tape width:</label>
<input
type="number"
id="sewing_marks_tape_width_pt"
name="sewing_marks_tape_width_pt"
class="layout_margin_user_input_field"
/><sub>pt</sub><br />
<img
alt="sewing image"
src="/img/sewing_settings_explanation.png"
style="height: 100%; width: 100%; object-fit: contain"
/>
</span>
</details>
</span>

<span class="row">
<div class="layout_margin_description">
White Space Manipulation. All values are in points, relative to original document.<br /><br />1
Expand Down
14 changes: 11 additions & 3 deletions src/models/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,20 @@ export const schema = z.object({
bottomEdgePaddingPt: urlSafe(z.coerce.number()).default(0),
sigFormat,
sigLength: urlSafe(z.coerce.number()).default(4), // Specific to standard
customSigLength: urlSafe(commaSeparatedNumberList).default([]), // Specific to custom.
customSigLength: urlSafe(commaSeparatedNumberList).default(null), // Specific to custom.
foreEdgePaddingPt: urlSafe(z.coerce.number()).default(0), // specific to wacky small
wackySpacing, // specific to wacky small
flyleafs: urlSafe(z.coerce.number()).default(1),
paperSizeCustomWidth: urlSafe(z.coerce.number()),
paperSizeCustomHeight: urlSafe(z.coerce.number()),

sewingMarksEnabled: urlSafe(coercedBoolean).default(false),
sewingMarksMarginPt: urlSafe(z.coerce.number()).default(72),
sewingMarksAmount: urlSafe(z.coerce.number()).default(3),
sewingMarksTapeWidthPt: urlSafe(z.coerce.number()).default(36),

paperSizeCustomWidth: urlSafe(z.coerce.number()).default(0),
paperSizeCustomHeight: urlSafe(z.coerce.number()).default(0),
});

/** @typedef {z.infer<typeof schema>} Configuration */

export const defaultConfig = schema.parse({});
77 changes: 76 additions & 1 deletion src/utils/drawing.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LINE_LEN } from '../constants';
import { rgb } from '@cantoo/pdf-lib';
import { rgb, grayscale } from '@cantoo/pdf-lib';

/**
* @typedef Point
Expand All @@ -17,6 +17,15 @@ import { rgb } from '@cantoo/pdf-lib';
* @property {number[]} [dashArray] - sequence of dash and gap lengths to be repeated for a dashed line
*/

/**
* @typedef Point
* @property {number} x,
* @property {number} y,
* @property {number} size,
* @property {Grayscale|RGB|CMYK} color,
*
*/

/**
* @param {boolean} side2flag - whether we're on the back or not.
* @param {boolean} duplexrotate - if alternate sides are rotated or not
Expand Down Expand Up @@ -112,6 +121,72 @@ export function drawCropmarks(papersize, per_sheet) {
return lines;
}

/*
* @param {@param {import("../book.js").PageInfo}} sigDetails - information about signature where marks will be printed
* @param {import("../book.js").Position} position - position info object
* @param {number} amount - amount of sewing crosses.
* @param {number} marginPt - distance from the end of sheet of paper to kettle mark
* @param {number} tapeWidthPt - distance between two points in a single sewwing cross.
* @returns {Point[]}
*/
export function drawSewingMarks(sigDetails, position, amount, marginPt, tapeWidthPt) {
// Here normalize coordinates to always think in x an y like this
// | P |H| P |
// | A |E| A |
// | G |I| G |
// | E |G| E |
// | |T| |
// |-POSITION-| | |

// Left pages have spine position on the edge :/
if (position.isLeftPage) return [];

var arePageRotated = Math.abs(position.rotation) === 90;
let totalSpineHeight = 0;
let spinePosition = 0;

if (arePageRotated) {
totalSpineHeight = Math.abs(position.spineMarkTop[0] - position.spineMarkBottom[0]);
spinePosition = position.spineMarkTop[1];
} else {
totalSpineHeight = Math.abs(position.spineMarkTop[1] - position.spineMarkBottom[1]);
spinePosition = position.spineMarkTop[0];
}

const workingWidth = totalSpineHeight - 2 * marginPt;
const spaceBetweenPoints = workingWidth / (amount + 1);

const sewingPoints = [];
for (let index = 1; index <= amount; index++) {
const halfOfTape = tapeWidthPt / 2;
sewingPoints.push(
{ pointHeight: marginPt + spaceBetweenPoints * index + halfOfTape },
{ pointHeight: marginPt + spaceBetweenPoints * index - halfOfTape }
);
}

const allPoints = [
{ pointHeight: marginPt },
{ pointHeight: totalSpineHeight - marginPt },
...sewingPoints,
];

const commonCircleValues = { size: 1, color: grayscale(0.0) };
const drawablePoints = allPoints.map((point) => {
point = { ...point, ...commonCircleValues };
if (arePageRotated) {
point.y = spinePosition;
point.x = point.pointHeight + position.spineMarkBottom[0];
} else {
point.y = point.pointHeight + position.spineMarkBottom[1];
point.x = spinePosition;
}
return point;
});

return drawablePoints;
}

/**
* @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
Expand Down
5 changes: 5 additions & 0 deletions src/utils/formUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ const fromFormToConfiguration = (form) =>
flyleafs: form.get('flyleafs'),
paperSizeCustomWidth: form.get('paper_size_custom_width'),
paperSizeCustomHeight: form.get('paper_size_custom_height'),

sewingMarksEnabled: form.get('add_sewing_marks_checkbox'),
sewingMarksMarginPt: form.get('sewing_marks_margin_pt'),
sewingMarksAmount: form.get('sewing_marks_amount'),
sewingMarksTapeWidthPt: form.get('sewing_marks_tape_width_pt'),
});

/**
Expand Down
10 changes: 10 additions & 0 deletions src/utils/renderUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,16 @@ export function renderFormFromSettings(configuration) {
`input[name="wacky_spacing"][value="${configuration.wackySpacing}"]`
).checked = true;

// Set french link stitches settings
document.querySelector('input[name="add_sewing_marks_checkbox"]').checked =
configuration.sewingMarksEnabled;
document.querySelector('input[name="sewing_marks_margin_pt"]').value =
configuration.sewingMarksMarginPt;
document.querySelector('input[name="sewing_marks_amount"]').value =
configuration.sewingMarksAmount;
document.querySelector('input[name="sewing_marks_tape_width_pt"]').value =
configuration.sewingMarksTapeWidthPt;

// Set freeform inputs
document.querySelector('input[name="main_fore_edge_padding_pt"]').value =
configuration.mainForeEdgePaddingPt;
Expand Down
7 changes: 7 additions & 0 deletions src/utils/uri.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

import { defaultConfig } from '../models/configuration';

/**
* Gets parameters from a URL.
* @param { string } url The URL to get the params from
Expand All @@ -26,6 +28,11 @@ export const setUrlParams = (url, params) => {
continue;
}

if (value === defaultConfig[key]) {
urlRepresentation.searchParams.delete(key);
continue;
}

urlRepresentation.searchParams.set(key, String(value));
}

Expand Down

0 comments on commit 92bceae

Please sign in to comment.