Add texture drop cap pagination

This commit is contained in:
2026-06-06 15:39:53 +02:00
parent 431e305df9
commit 1b8c8f8bce
4 changed files with 40 additions and 7 deletions
+26 -5
View File
@@ -21,6 +21,8 @@ class BookPaginationModule extends BaseModule {
'refreshFromHistory',
'buildSpreads',
'layoutTextBlock',
'getDropCapText',
'extractDropCapText',
'extractLines',
'getLineGeometry',
'getSpread',
@@ -80,7 +82,7 @@ class BookPaginationModule extends BaseModule {
let blockWordCursor = 0;
cursorLine += layout.topSpaceLines;
layout.lines.forEach((line) => {
layout.lines.forEach((line, layoutLineIndex) => {
const geometry = this.getLineGeometry(cursorLine);
const lineWordCount = line.nodes.filter(node => node?.type === 'box' && node.value).length;
if (!spreads[geometry.spreadIndex]) {
@@ -97,7 +99,8 @@ class BookPaginationModule extends BaseModule {
fontPx: layout.fontPx,
lineHeightPx: layout.lineHeightPx,
fontStyle: layout.fontStyle,
blockWordStart: blockWordCursor
blockWordStart: blockWordCursor,
dropCapText: layoutLineIndex === 0 ? layout.dropCapText : ''
});
blockWordCursor += lineWordCount;
cursorLine += 1;
@@ -109,7 +112,10 @@ class BookPaginationModule extends BaseModule {
}
layoutTextBlock(block = {}, type = 'paragraph') {
const text = String(block.layoutText || block.text || '').trim();
const sourceText = String(block.layoutText || block.text || '').trim();
const dropCap = Boolean(block.dropCap || block.metadata?.dropCap);
const dropCapText = dropCap ? this.getDropCapText(sourceText) : '';
const text = dropCap ? this.extractDropCapText(sourceText) : sourceText;
if (!text || !this.paragraphLayout) return null;
const typography = this.metrics.typography;
@@ -119,13 +125,16 @@ class BookPaginationModule extends BaseModule {
const bottomSpaceLines = role === 'chapter-heading' || role === 'section-heading' ? 1 : 0;
const lineHeightPx = Math.max(1, Number(this.metrics.typographyLineHeightPx || 1));
const fontPx = Math.max(1, Number(this.metrics.bodyFontSizePx || lineHeightPx / 1.5));
const dropCapWidth = dropCap ? lineHeightPx * 1.58 : 0;
const indent = (isHeading || block.isFirstParagraphInChapter || block.metadata?.isFirstParagraphInChapter || block.addTopSpace)
? 0
: lineHeightPx * 1.5;
const measures = isHeading
? [this.metrics.content.width]
: [Math.max(120, this.metrics.content.width - indent), this.metrics.content.width, this.metrics.content.width];
const lineOffsets = isHeading ? [0] : [indent, 0, 0];
: dropCap
? [Math.max(120, this.metrics.content.width - dropCapWidth), Math.max(120, this.metrics.content.width - dropCapWidth), this.metrics.content.width]
: [Math.max(120, this.metrics.content.width - indent), this.metrics.content.width, this.metrics.content.width];
const lineOffsets = isHeading ? [0] : dropCap ? [dropCapWidth, dropCapWidth, 0] : [indent, 0, 0];
const layout = this.paragraphLayout.calculateLayout(text, {
measures,
@@ -144,6 +153,8 @@ class BookPaginationModule extends BaseModule {
fontStyle: isHeading ? 'italic' : 'normal',
topSpaceLines,
bottomSpaceLines,
dropCapText,
dropCap,
lines: this.extractLines(layout, {
measures,
lineOffsets,
@@ -152,6 +163,16 @@ class BookPaginationModule extends BaseModule {
};
}
getDropCapText(text) {
return String(text || '').trimStart().match(/\S/u)?.[0] || '';
}
extractDropCapText(text) {
const dropCap = this.getDropCapText(text);
if (!dropCap) return String(text || '');
return String(text || '').replace(dropCap, '').trimStart();
}
extractLines(layout, options = {}) {
const lines = [];
const breaks = Array.isArray(layout.breaks) ? layout.breaks : [];