feat(typesetting): 分页算法增加orphan control - 标题不再孤悬页面底部

- paginateContent正常块判断增加标题orphan control
- 标题(h2/h3/h4)后检查下一个块能否放入当前页
- 若放不下则回退标题到下一页开头
- 超大块处理增加标题回退逻辑
- 超大表格拆分时前面的h2标题和表格第一部分同页
This commit is contained in:
augushong
2026-05-17 13:30:31 +08:00
parent 665a9cc9e5
commit 0f38e4a52c

View File

@@ -615,6 +615,15 @@ var PhoneImageEngine = (function () {
// 超大块处理:单个块超过整页高度时需要拆分
if (block.estimatedHeight > contentAreaHeight) {
// 检查当前页最后一个块是否为标题,若是则回退使其与超大块第一部分同页
var lastBlockInPage = currentPageBlocks.length > 0 ? currentPageBlocks[currentPageBlocks.length - 1] : null;
var lastBlockIsHeading = lastBlockInPage && (lastBlockInPage.type === 'h2' || lastBlockInPage.type === 'h3' || lastBlockInPage.type === 'h4');
if (lastBlockIsHeading) {
currentPageBlocks.pop();
currentHeight -= lastBlockInPage.estimatedHeight;
}
// 先把当前页已有的内容推出去
if (currentPageBlocks.length > 0) {
contentPages.push(generateContentPage(
@@ -625,6 +634,12 @@ var PhoneImageEngine = (function () {
pageNumber++;
}
// 超大块拆分后,若有回退的标题,加到新页开头
if (lastBlockIsHeading) {
currentPageBlocks = [lastBlockInPage];
currentHeight = lastBlockInPage.estimatedHeight;
}
// 尝试拆分超大块
var splitBlocks = splitOversizedBlock(block, contentAreaHeight);
for (var s = 0; s < splitBlocks.length; s++) {
@@ -644,6 +659,9 @@ var PhoneImageEngine = (function () {
}
// 正常块:判断是否需要换页
var isHeading = block.type === 'h2' || block.type === 'h3' || block.type === 'h4';
var nextBlock = (i + 1 < blocks.length) ? blocks[i + 1] : null;
if (currentHeight + block.estimatedHeight > contentAreaHeight && currentPageBlocks.length > 0) {
contentPages.push(generateContentPage(
currentPageBlocks, pageNumber, sizeConfig, false
@@ -655,6 +673,22 @@ var PhoneImageEngine = (function () {
currentPageBlocks.push(block);
currentHeight += block.estimatedHeight;
// Orphan control: 标题后至少跟一个内容块,若下一个块放不下则标题移到下一页
if (isHeading && nextBlock) {
if (currentHeight + nextBlock.estimatedHeight > contentAreaHeight) {
currentPageBlocks.pop();
currentHeight -= block.estimatedHeight;
if (currentPageBlocks.length > 0) {
contentPages.push(generateContentPage(
currentPageBlocks, pageNumber, sizeConfig, false
));
pageNumber++;
}
currentPageBlocks = [block];
currentHeight = block.estimatedHeight;
}
}
}
// 最后一页