postext 1.39.1 → 1.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/comics/frames.test.js +0 -8
- package/dist/__tests__/comics/frames.test.js.map +1 -1
- package/dist/__tests__/comics/textPanelsStripsSpreads.test.d.ts +2 -0
- package/dist/__tests__/comics/textPanelsStripsSpreads.test.d.ts.map +1 -0
- package/dist/__tests__/comics/textPanelsStripsSpreads.test.js +277 -0
- package/dist/__tests__/comics/textPanelsStripsSpreads.test.js.map +1 -0
- package/dist/__tests__/composed/crossChapterJumps.test.d.ts +2 -0
- package/dist/__tests__/composed/crossChapterJumps.test.d.ts.map +1 -0
- package/dist/__tests__/composed/crossChapterJumps.test.js +299 -0
- package/dist/__tests__/composed/crossChapterJumps.test.js.map +1 -0
- package/dist/__tests__/composed/fit.test.js +77 -0
- package/dist/__tests__/composed/fit.test.js.map +1 -1
- package/dist/__tests__/composed/frameModesChain.test.d.ts +2 -0
- package/dist/__tests__/composed/frameModesChain.test.d.ts.map +1 -0
- package/dist/__tests__/composed/frameModesChain.test.js +69 -0
- package/dist/__tests__/composed/frameModesChain.test.js.map +1 -0
- package/dist/__tests__/composed/framePictures.test.d.ts +2 -0
- package/dist/__tests__/composed/framePictures.test.d.ts.map +1 -0
- package/dist/__tests__/composed/framePictures.test.js +121 -0
- package/dist/__tests__/composed/framePictures.test.js.map +1 -0
- package/dist/__tests__/composed/frameWritingMode.test.js +79 -3
- package/dist/__tests__/composed/frameWritingMode.test.js.map +1 -1
- package/dist/__tests__/composed/labels.test.js +19 -0
- package/dist/__tests__/composed/labels.test.js.map +1 -1
- package/dist/__tests__/composed/labelsMirrored.test.d.ts +2 -0
- package/dist/__tests__/composed/labelsMirrored.test.d.ts.map +1 -0
- package/dist/__tests__/composed/labelsMirrored.test.js +128 -0
- package/dist/__tests__/composed/labelsMirrored.test.js.map +1 -0
- package/dist/__tests__/composed/measureMemo.test.d.ts +2 -0
- package/dist/__tests__/composed/measureMemo.test.d.ts.map +1 -0
- package/dist/__tests__/composed/measureMemo.test.js +45 -0
- package/dist/__tests__/composed/measureMemo.test.js.map +1 -0
- package/dist/__tests__/composedTemplates.test.js +5 -2
- package/dist/__tests__/composedTemplates.test.js.map +1 -1
- package/dist/__tests__/exports.test.js +6 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/__tests__/migrate/labelsOnPictures.test.js +49 -1
- package/dist/__tests__/migrate/labelsOnPictures.test.js.map +1 -1
- package/dist/bundle/book.d.ts +5 -0
- package/dist/bundle/book.d.ts.map +1 -1
- package/dist/bundle/book.js +53 -7
- package/dist/bundle/book.js.map +1 -1
- package/dist/bundle/layoutCache.d.ts +5 -0
- package/dist/bundle/layoutCache.d.ts.map +1 -1
- package/dist/bundle/layoutCache.js.map +1 -1
- package/dist/canvas-backend/composed.d.ts +2 -2
- package/dist/canvas-backend/composed.d.ts.map +1 -1
- package/dist/canvas-backend/composed.js +11 -2
- package/dist/canvas-backend/composed.js.map +1 -1
- package/dist/canvas-backend/index.d.ts.map +1 -1
- package/dist/canvas-backend/index.js +10 -1
- package/dist/canvas-backend/index.js.map +1 -1
- package/dist/canvas-backend/mirrorFrame.d.ts +19 -0
- package/dist/canvas-backend/mirrorFrame.d.ts.map +1 -1
- package/dist/canvas-backend/mirrorFrame.js +47 -0
- package/dist/canvas-backend/mirrorFrame.js.map +1 -1
- package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -1
- package/dist/canvas-backend/renderResourceBlock.js +35 -26
- package/dist/canvas-backend/renderResourceBlock.js.map +1 -1
- package/dist/comics/frames.d.ts +5 -0
- package/dist/comics/frames.d.ts.map +1 -1
- package/dist/comics/frames.js +7 -0
- package/dist/comics/frames.js.map +1 -1
- package/dist/comics/layoutPage.d.ts +5 -0
- package/dist/comics/layoutPage.d.ts.map +1 -1
- package/dist/comics/layoutPage.js +9 -0
- package/dist/comics/layoutPage.js.map +1 -1
- package/dist/comics/sourceMap.d.ts.map +1 -1
- package/dist/comics/sourceMap.js +6 -4
- package/dist/comics/sourceMap.js.map +1 -1
- package/dist/comics/spread.d.ts +6 -1
- package/dist/comics/spread.d.ts.map +1 -1
- package/dist/comics/spread.js +15 -1
- package/dist/comics/spread.js.map +1 -1
- package/dist/comics/textPanels.d.ts +30 -6
- package/dist/comics/textPanels.d.ts.map +1 -1
- package/dist/comics/textPanels.js +226 -69
- package/dist/comics/textPanels.js.map +1 -1
- package/dist/comics/transform.d.ts.map +1 -1
- package/dist/comics/transform.js +4 -2
- package/dist/comics/transform.js.map +1 -1
- package/dist/composed/carry.d.ts +53 -0
- package/dist/composed/carry.d.ts.map +1 -0
- package/dist/composed/carry.js +114 -0
- package/dist/composed/carry.js.map +1 -0
- package/dist/composed/carryTypes.d.ts +76 -0
- package/dist/composed/carryTypes.d.ts.map +1 -0
- package/dist/composed/carryTypes.js +2 -0
- package/dist/composed/carryTypes.js.map +1 -0
- package/dist/composed/continuation.d.ts +8 -0
- package/dist/composed/continuation.d.ts.map +1 -1
- package/dist/composed/continuation.js.map +1 -1
- package/dist/composed/labels.d.ts +9 -0
- package/dist/composed/labels.d.ts.map +1 -1
- package/dist/composed/labels.js +36 -4
- package/dist/composed/labels.js.map +1 -1
- package/dist/composed/paint.d.ts +10 -6
- package/dist/composed/paint.d.ts.map +1 -1
- package/dist/composed/paint.js +38 -7
- package/dist/composed/paint.js.map +1 -1
- package/dist/composed/sourceMap.d.ts +16 -0
- package/dist/composed/sourceMap.d.ts.map +1 -1
- package/dist/composed/sourceMap.js +43 -9
- package/dist/composed/sourceMap.js.map +1 -1
- package/dist/composed/templates.d.ts.map +1 -1
- package/dist/composed/templates.js +9 -4
- package/dist/composed/templates.js.map +1 -1
- package/dist/composed/types.d.ts +9 -4
- package/dist/composed/types.d.ts.map +1 -1
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +36 -14
- package/dist/html-backend.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/migrate/pageDesign.d.ts +6 -1
- package/dist/migrate/pageDesign.d.ts.map +1 -1
- package/dist/migrate/pageDesign.js +26 -10
- package/dist/migrate/pageDesign.js.map +1 -1
- package/dist/migrate/textToMarkdown.js +4 -3
- package/dist/migrate/textToMarkdown.js.map +1 -1
- package/dist/pipeline/build.d.ts +12 -0
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +304 -25
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/calloutLayout.d.ts +13 -17
- package/dist/pipeline/calloutLayout.d.ts.map +1 -1
- package/dist/pipeline/calloutLayout.js +20 -1
- package/dist/pipeline/calloutLayout.js.map +1 -1
- package/dist/pipeline/composedLayout.d.ts +12 -0
- package/dist/pipeline/composedLayout.d.ts.map +1 -1
- package/dist/pipeline/composedLayout.js +179 -25
- package/dist/pipeline/composedLayout.js.map +1 -1
- package/dist/pipeline/contentWarnings.d.ts.map +1 -1
- package/dist/pipeline/contentWarnings.js +5 -3
- package/dist/pipeline/contentWarnings.js.map +1 -1
- package/dist/pipeline/continuation.d.ts +11 -0
- package/dist/pipeline/continuation.d.ts.map +1 -1
- package/dist/pipeline/continuation.js +36 -0
- package/dist/pipeline/continuation.js.map +1 -1
- package/dist/pipeline/cutTypes.d.ts +42 -0
- package/dist/pipeline/cutTypes.d.ts.map +1 -0
- package/dist/pipeline/cutTypes.js +6 -0
- package/dist/pipeline/cutTypes.js.map +1 -0
- package/dist/pipeline/frameLayout.d.ts +8 -22
- package/dist/pipeline/frameLayout.d.ts.map +1 -1
- package/dist/pipeline/frameLayout.js +1 -0
- package/dist/pipeline/frameLayout.js.map +1 -1
- package/dist/pipeline/index.d.ts +2 -1
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +2 -1
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/measureMemo.d.ts +39 -0
- package/dist/pipeline/measureMemo.d.ts.map +1 -0
- package/dist/pipeline/measureMemo.js +61 -0
- package/dist/pipeline/measureMemo.js.map +1 -0
- package/dist/pipeline/mirrorFrame.d.ts +2 -1
- package/dist/pipeline/mirrorFrame.d.ts.map +1 -1
- package/dist/pipeline/mirrorFrame.js +31 -5
- package/dist/pipeline/mirrorFrame.js.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +53 -0
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js.map +1 -1
- package/package.json +1 -1
|
@@ -15,6 +15,9 @@ import { frameElementId } from '../composed/ids';
|
|
|
15
15
|
import { frameLinePx, frameRuleBlocks } from '../composed/rules';
|
|
16
16
|
import { offsetCalloutToAbsolute } from './calloutLayout';
|
|
17
17
|
import { isMarkerBlock } from './buildHelpers';
|
|
18
|
+
import { createMeasureMemo } from './measureMemo';
|
|
19
|
+
import { computeOrderedListRunMetrics } from './lists';
|
|
20
|
+
import { planParagraphContainers } from './paragraphContainers';
|
|
18
21
|
import { CUT_START, fragmentRange, frameCutRules, makeCalloutLayouter, splitCalloutFragment } from './frameLayout';
|
|
19
22
|
const MM_PER_IN = 25.4;
|
|
20
23
|
const NO_FIT = { patches: new Map(), text: new Map(), pictures: new Map(), yieldAll: new Set(), goOn: new Set() };
|
|
@@ -66,7 +69,10 @@ export function layoutComposedPage(given) {
|
|
|
66
69
|
// A page added by continuation (#859) lays its template with the
|
|
67
70
|
// continuation's rules (and, for the template laid again, its other
|
|
68
71
|
// frames collapsed).
|
|
69
|
-
|
|
72
|
+
// The ladder lays the page again at each step: the measurements of one
|
|
73
|
+
// step answer the next (#953).
|
|
74
|
+
const memoed = { ...given, pass: { ...given.pass, measureMemo: createMeasureMemo() } };
|
|
75
|
+
const input = given.continuing ? { ...memoed, template: continuationTemplate(given.template, given.continuing) } : memoed;
|
|
70
76
|
const { template, fence, dpi } = input;
|
|
71
77
|
const fi = fence.fenceIndex;
|
|
72
78
|
const mmPx = dpi / MM_PER_IN;
|
|
@@ -427,14 +433,133 @@ export function layoutComposedPage(given) {
|
|
|
427
433
|
}
|
|
428
434
|
return { composed, blocks, warnings, laid, ...(fitted.size > 0 ? { fitted } : {}), ...(continuations.length > 0 ? { continuations } : {}) };
|
|
429
435
|
}
|
|
436
|
+
/** The pass of a trial layout (#953): `base` with `extra` blocks appended to
|
|
437
|
+
* its content, each a copy of the block at `originOf[k]`, and every lookup
|
|
438
|
+
* the box typesetter keys by content index answered for the appended
|
|
439
|
+
* blocks as for the blocks they copy. The paragraph groups
|
|
440
|
+
* (`paragraphContainers.byBlock`), the heading and list numbers, the drop
|
|
441
|
+
* cap and indent rules (which read the neighbours of a block in
|
|
442
|
+
* `contentBlocks`), the comic strips and heading designs follow the
|
|
443
|
+
* copies, so a trial sets a merged story as the build sets the story
|
|
444
|
+
* itself. The trial also keeps its own notes (`dropCapNotes`,
|
|
445
|
+
* `joiningLetterSpacing`), which the build reports for the page it lays. */
|
|
446
|
+
function trialPass(base, extra, originOf, measureOrigin) {
|
|
447
|
+
const n = base.contentBlocks.length;
|
|
448
|
+
const at = (idx) => (idx < n ? idx : originOf[idx - n] ?? idx);
|
|
449
|
+
const extend = (arr) => (arr && extra.length > 0 ? [...arr, ...originOf.map((o) => arr[o])] : arr);
|
|
450
|
+
const contentBlocks = extra.length > 0 ? [...base.contentBlocks, ...extra] : base.contentBlocks;
|
|
451
|
+
const contexts = new Map();
|
|
452
|
+
const trialCtx = (ctx) => {
|
|
453
|
+
const known = contexts.get(ctx);
|
|
454
|
+
if (known)
|
|
455
|
+
return known;
|
|
456
|
+
const perBlock = new Map(ctx.orderedMetrics.perBlock);
|
|
457
|
+
originOf.forEach((o, k) => {
|
|
458
|
+
const m = ctx.orderedMetrics.perBlock.get(o);
|
|
459
|
+
if (m)
|
|
460
|
+
perBlock.set(n + k, m);
|
|
461
|
+
});
|
|
462
|
+
const out = {
|
|
463
|
+
...ctx,
|
|
464
|
+
contentBlocks,
|
|
465
|
+
headingPrefixes: extend(ctx.headingPrefixes),
|
|
466
|
+
...(ctx.headingNumbers ? { headingNumbers: extend(ctx.headingNumbers) } : {}),
|
|
467
|
+
orderedMetrics: { ...ctx.orderedMetrics, perBlock },
|
|
468
|
+
dropCapNotes: new Map(),
|
|
469
|
+
joiningLetterSpacing: new Set(),
|
|
470
|
+
};
|
|
471
|
+
contexts.set(ctx, out);
|
|
472
|
+
return out;
|
|
473
|
+
};
|
|
474
|
+
const byBlock = base.paragraphContainers.byBlock;
|
|
475
|
+
return {
|
|
476
|
+
...base,
|
|
477
|
+
contentBlocks,
|
|
478
|
+
paragraphContainers: extra.length > 0 ? { byId: base.paragraphContainers.byId, byBlock: [...byBlock, ...originOf.map((o) => byBlock[o])] } : base.paragraphContainers,
|
|
479
|
+
// A merged story's box is set in the context of the story whose box
|
|
480
|
+
// it replaces.
|
|
481
|
+
measureCtxFor: (startIdx, style) => trialCtx(base.measureCtxFor(measureOrigin.get(startIdx) ?? startIdx, style)),
|
|
482
|
+
stripBlock: (raw, idx, width) => base.stripBlock(raw, at(idx), width),
|
|
483
|
+
...(base.headingDesign ? { headingDesign: (raw, blockIdx, heading, width) => base.headingDesign(raw, at(blockIdx), heading, width) } : {}),
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* The pass the stories carried in from other chapters (#943) are laid with:
|
|
488
|
+
* `base` with their blocks appended to its content, and every lookup the
|
|
489
|
+
* box typesetter keys by content index answered for them from what the
|
|
490
|
+
* sender gave (heading numbers) or worked out again from the carried
|
|
491
|
+
* blocks alone (paragraph groups, ordered-list markers). A carried story's
|
|
492
|
+
* box is set in the context of the text, with the list indents its sender
|
|
493
|
+
* set its lists with; the typography of a styled section or a part of this
|
|
494
|
+
* chapter does not reach it.
|
|
495
|
+
*/
|
|
496
|
+
export function carriedPass(base, carried) {
|
|
497
|
+
if (carried.blocks.length === 0)
|
|
498
|
+
return base;
|
|
499
|
+
const n = base.contentBlocks.length;
|
|
500
|
+
const contentBlocks = [...base.contentBlocks, ...carried.blocks];
|
|
501
|
+
const local = planParagraphContainers(carried.blocks, base.resolved);
|
|
502
|
+
const byBlock = [...base.paragraphContainers.byBlock];
|
|
503
|
+
byBlock.length = n;
|
|
504
|
+
byBlock.push(...local.byBlock);
|
|
505
|
+
const paragraphContainers = { byId: new Map([...base.paragraphContainers.byId, ...local.byId]), byBlock };
|
|
506
|
+
const numberAt = new Map();
|
|
507
|
+
for (const story of carried.stories.values())
|
|
508
|
+
for (const [at, num] of story.numbers)
|
|
509
|
+
numberAt.set(at, num);
|
|
510
|
+
const extend = (arr, pick) => {
|
|
511
|
+
if (!arr)
|
|
512
|
+
return arr;
|
|
513
|
+
const out = [...arr];
|
|
514
|
+
out.length = n;
|
|
515
|
+
out.length = contentBlocks.length;
|
|
516
|
+
for (const [at, num] of numberAt)
|
|
517
|
+
out[at] = pick(num);
|
|
518
|
+
return out;
|
|
519
|
+
};
|
|
520
|
+
const contexts = new Map();
|
|
521
|
+
const carriedCtx = (ctx, startIdx) => {
|
|
522
|
+
const story = carried.stories.get(startIdx);
|
|
523
|
+
const of = contexts.get(ctx) ?? new Map();
|
|
524
|
+
contexts.set(ctx, of);
|
|
525
|
+
const known = of.get(startIdx);
|
|
526
|
+
if (known)
|
|
527
|
+
return known;
|
|
528
|
+
const metrics = computeOrderedListRunMetrics(carried.blocks, base.resolved, ctx.bodyStyle.fontSizePx);
|
|
529
|
+
const perBlock = new Map(ctx.orderedMetrics.perBlock);
|
|
530
|
+
for (const [i, m] of metrics.perBlock)
|
|
531
|
+
perBlock.set(n + i, m);
|
|
532
|
+
const out = {
|
|
533
|
+
...ctx,
|
|
534
|
+
contentBlocks,
|
|
535
|
+
headingPrefixes: extend(ctx.headingPrefixes, (num) => num.prefix),
|
|
536
|
+
...(ctx.headingNumbers ? { headingNumbers: extend(ctx.headingNumbers, (num) => num.value) } : {}),
|
|
537
|
+
orderedMetrics: { perBlock, maxWidthByDepth: ctx.orderedMetrics.maxWidthByDepth },
|
|
538
|
+
...(story.jump.orderedLevelIndentsPx ? { orderedLevelIndentsPx: story.jump.orderedLevelIndentsPx } : {}),
|
|
539
|
+
dropCapNotes: new Map(),
|
|
540
|
+
joiningLetterSpacing: new Set(),
|
|
541
|
+
};
|
|
542
|
+
of.set(startIdx, out);
|
|
543
|
+
return out;
|
|
544
|
+
};
|
|
545
|
+
return {
|
|
546
|
+
...base,
|
|
547
|
+
contentBlocks,
|
|
548
|
+
paragraphContainers,
|
|
549
|
+
measureCtxFor: (startIdx, style) => {
|
|
550
|
+
const ctx = base.measureCtxFor(startIdx, style);
|
|
551
|
+
return carried.stories.has(startIdx) ? carriedCtx(ctx, startIdx) : ctx;
|
|
552
|
+
},
|
|
553
|
+
};
|
|
554
|
+
}
|
|
430
555
|
/** The page's stories as `wrapComposedPages` would group them for template
|
|
431
556
|
* `alt` (#937): a story whose head names a frame of `alt` stays the story
|
|
432
557
|
* of that frame's chain, one a `takes` frame took goes to `alt`'s frame
|
|
433
558
|
* that takes the same level, and the rest go to `alt`'s flow frame, after
|
|
434
559
|
* its own content, in Markdown order. Merged stories are boxes appended
|
|
435
|
-
* past the pass's content blocks (
|
|
436
|
-
*
|
|
437
|
-
*
|
|
560
|
+
* past the pass's content blocks (`trialPass`), so the page can be laid
|
|
561
|
+
* with them. `undefined` when some content would leave the page (no frame
|
|
562
|
+
* of `alt` takes it). */
|
|
438
563
|
function regroupStories(input, alt) {
|
|
439
564
|
const names = new Set(alt.frames.map((f) => f.name));
|
|
440
565
|
const flow = alt.frames.find((f) => f.flow);
|
|
@@ -454,10 +579,13 @@ function regroupStories(input, alt) {
|
|
|
454
579
|
return undefined;
|
|
455
580
|
groups.set(to, [...(groups.get(to) ?? []), [head, story]]);
|
|
456
581
|
}
|
|
582
|
+
// Every story stays its frame's own: the page as it is.
|
|
457
583
|
if ([...groups].every(([to, list]) => list.length === 1 && list[0][0] === to))
|
|
458
|
-
return { pass: input.pass, stories: new Map(input.stories) };
|
|
584
|
+
return { pass: trialPass(input.pass, [], [], new Map()), stories: new Map(input.stories) };
|
|
459
585
|
const base = input.pass.contentBlocks;
|
|
460
586
|
const extra = [];
|
|
587
|
+
/** The block of the page each appended block copies. */
|
|
588
|
+
const originOf = [];
|
|
461
589
|
/** Where each appended box's blocks come from: the first story's box. */
|
|
462
590
|
const origin = new Map();
|
|
463
591
|
let nextId = base.reduce((m, b) => Math.max(m, b.containerId ?? 0), 0) + 1;
|
|
@@ -473,19 +601,19 @@ function regroupStories(input, alt) {
|
|
|
473
601
|
const startIdx = base.length + extra.length;
|
|
474
602
|
const attrs = { ...own.plan.attrs, [FRAME_ATTR]: to };
|
|
475
603
|
extra.push({ ...open, containerAttrs: attrs, containerId: id });
|
|
476
|
-
|
|
604
|
+
originOf.push(own.startIdx);
|
|
605
|
+
for (const [, s] of list) {
|
|
477
606
|
extra.push(...base.slice(s.startIdx + 1, s.plan.endIdx));
|
|
478
|
-
|
|
479
|
-
|
|
607
|
+
for (let i = s.startIdx + 1; i < s.plan.endIdx; i++)
|
|
608
|
+
originOf.push(i);
|
|
609
|
+
}
|
|
610
|
+
const last = list[list.length - 1][1];
|
|
611
|
+
extra.push({ ...base[last.plan.endIdx], containerId: id });
|
|
612
|
+
originOf.push(last.plan.endIdx);
|
|
480
613
|
origin.set(startIdx, own.startIdx);
|
|
481
614
|
stories.set(to, { startIdx, plan: { endIdx: base.length + extra.length - 1, attrs, containerId: id } });
|
|
482
615
|
}
|
|
483
|
-
|
|
484
|
-
...input.pass,
|
|
485
|
-
contentBlocks: [...base, ...extra],
|
|
486
|
-
measureCtxFor: (startIdx, style) => input.pass.measureCtxFor(origin.get(startIdx) ?? startIdx, style),
|
|
487
|
-
};
|
|
488
|
-
return { pass, stories };
|
|
616
|
+
return { pass: trialPass(input.pass, extra, originOf, origin), stories };
|
|
489
617
|
}
|
|
490
618
|
/** The page fits when set with template `alt` (#937): its stories regrouped
|
|
491
619
|
* for it (`regroupStories`), its own reflow ladder run; no frame
|
|
@@ -682,9 +810,30 @@ function composePage(input, template, fit, collapsed) {
|
|
|
682
810
|
* mode, else undefined. Its content is laid out in that mode, its lines
|
|
683
811
|
* along the box's height and following each other across its width. */
|
|
684
812
|
const pageMode = pageIsVertical(input.page) ? 'vertical-rl' : 'horizontal-tb';
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
813
|
+
const ownMode = (frame) => frame.writingMode !== undefined && frame.writingMode !== pageMode ? frame.writingMode : undefined;
|
|
814
|
+
/** A vertical frame of a right-to-left page (#960): the page's flow is
|
|
815
|
+
* painted mirrored, which would set its lines from left to right, so the
|
|
816
|
+
* frame is laid out as on a left-to-right page and painted unmirrored
|
|
817
|
+
* (`VDTFrame.unmirrorX`). The mirror's origin, else undefined. */
|
|
818
|
+
const unmirroredAt = (frame) => {
|
|
819
|
+
const flow = input.page.flow;
|
|
820
|
+
return ownMode(frame) && flow?.writingMode === 'horizontal-tb' ? flow.mirror.originX : undefined;
|
|
821
|
+
};
|
|
822
|
+
/** Whether a frame's lines are set as on a mirrored page: those of the
|
|
823
|
+
* page's own mode, not an unmirrored frame's. */
|
|
824
|
+
const mirroredIn = (frame) => input.mirrored && unmirroredAt(frame) === undefined;
|
|
825
|
+
/** The widest a picture's upright frame may be in a vertical frame of a
|
|
826
|
+
* horizontal page (#960): the frame's extent across its lines, less the
|
|
827
|
+
* box's padding. The page turns such a frame a quarter turn, so its
|
|
828
|
+
* pictures are laid out counter-rotated to stand upright; none of that
|
|
829
|
+
* in a frame of the page's own mode. */
|
|
830
|
+
const uprightIn = (frame, across) => {
|
|
831
|
+
if (ownMode(frame) !== 'vertical-rl')
|
|
832
|
+
return {};
|
|
833
|
+
const pad = styleOf(frame).padding;
|
|
834
|
+
const room = across - lengthPx(pad.top, dpi, input.emPx) - lengthPx(pad.bottom, dpi, input.emPx);
|
|
835
|
+
return { uprightMaxLength: Math.max(1, room) };
|
|
836
|
+
};
|
|
688
837
|
/** `fn` measured in the frame's own writing mode. */
|
|
689
838
|
const inMode = (frame, fn) => {
|
|
690
839
|
const mode = ownMode(frame);
|
|
@@ -847,8 +996,8 @@ function composePage(input, template, fit, collapsed) {
|
|
|
847
996
|
const known = memo.get(key);
|
|
848
997
|
if (known !== undefined)
|
|
849
998
|
return known;
|
|
850
|
-
const opts = { ...(pic !== undefined ? { pictureScale: pic } : {}), ...(p.fromMark !== undefined ? { continuedMark: p.fromMark } : {}) };
|
|
851
|
-
const across = (measure) => inMode(p.frame, () => p.st.L.layoutRange(p.st.cut, p.st.L.end, measure / s, p.blockId, p.continuation,
|
|
999
|
+
const opts = { ...(pic !== undefined ? { pictureScale: pic } : {}), ...(p.fromMark !== undefined ? { continuedMark: p.fromMark } : {}), ...uprightIn(p.frame, width / s) };
|
|
1000
|
+
const across = (measure) => inMode(p.frame, () => p.st.L.layoutRange(p.st.cut, p.st.L.end, measure / s, p.blockId, p.continuation, mirroredIn(p.frame), Object.keys(opts).length > 0 ? opts : undefined).totalHeight * s);
|
|
852
1001
|
const most = Math.max(input.areas.area.height, input.emPx);
|
|
853
1002
|
let h = most;
|
|
854
1003
|
if (across(most) <= width + 0.5) {
|
|
@@ -1066,9 +1215,9 @@ function composePage(input, template, fit, collapsed) {
|
|
|
1066
1215
|
// Text running round the frames that push it runs along the page's
|
|
1067
1216
|
// lines: a frame set across them keeps its whole box.
|
|
1068
1217
|
const exclusions = turned ? undefined : unscale(exclusionsFor(frame, rect, false), s);
|
|
1069
|
-
const extra = { ...(exclusions ? { exclusions } : {}), ...(pic !== undefined ? { pictureScale: pic } : {}), ...(p.fromMark !== undefined ? { continuedMark: p.fromMark } : {}) };
|
|
1218
|
+
const extra = { ...(exclusions ? { exclusions } : {}), ...(pic !== undefined ? { pictureScale: pic } : {}), ...(p.fromMark !== undefined ? { continuedMark: p.fromMark } : {}), ...uprightIn(frame, laidH) };
|
|
1070
1219
|
const opts = { boxHeight: laidH, verticalAlign: frame.verticalAlign, ...extra };
|
|
1071
|
-
const whole = inMode(frame, () => st.L.layoutRange(from, st.L.end, laidW, blockId, continuation,
|
|
1220
|
+
const whole = inMode(frame, () => st.L.layoutRange(from, st.L.end, laidW, blockId, continuation, mirroredIn(frame), opts));
|
|
1072
1221
|
const nextName = nextFrameOf(frame);
|
|
1073
1222
|
const nextFrame = nextName !== undefined ? byName.get(nextName) : undefined;
|
|
1074
1223
|
const chained = nextFrame !== undefined && !vdtByName.has(nextFrame.name);
|
|
@@ -1080,11 +1229,11 @@ function composePage(input, template, fit, collapsed) {
|
|
|
1080
1229
|
const minLines = Math.max(1, style.splitMinLines);
|
|
1081
1230
|
// A heading stays with what follows it, a list keeps two items
|
|
1082
1231
|
// on each side of the cut (#913).
|
|
1083
|
-
const frag = inMode(frame, () => splitCalloutFragment(pass, st.L, from, laidW, laidH, blockId, continuation, minLines,
|
|
1232
|
+
const frag = inMode(frame, () => splitCalloutFragment(pass, st.L, from, laidW, laidH, blockId, continuation, minLines, mirroredIn(frame), extra.exclusions || extra.pictureScale !== undefined || extra.continuedMark !== undefined || extra.uprightMaxLength !== undefined ? extra : undefined, cutRules));
|
|
1084
1233
|
const to = frag?.to ?? from;
|
|
1085
1234
|
// A frame none of whose content fits draws nothing: the whole box
|
|
1086
1235
|
// goes on (#912), not a tab and a mark over an empty piece.
|
|
1087
|
-
result = frag ? inMode(frame, () => st.L.layoutRange(from, to, laidW, blockId, continuation,
|
|
1236
|
+
result = frag ? inMode(frame, () => st.L.layoutRange(from, to, laidW, blockId, continuation, mirroredIn(frame), opts)) : undefined;
|
|
1088
1237
|
st.cut = to;
|
|
1089
1238
|
}
|
|
1090
1239
|
else {
|
|
@@ -1096,7 +1245,7 @@ function composePage(input, template, fit, collapsed) {
|
|
|
1096
1245
|
}
|
|
1097
1246
|
else if (st && frame.style) {
|
|
1098
1247
|
// A styled frame with nothing (left) to hold still draws its box.
|
|
1099
|
-
result = inMode(frame, () => st.L.layoutRange(st.L.end, st.L.end, laidW, blockId, true,
|
|
1248
|
+
result = inMode(frame, () => st.L.layoutRange(st.L.end, st.L.end, laidW, blockId, true, mirroredIn(frame), { boxHeight: laidH }));
|
|
1100
1249
|
}
|
|
1101
1250
|
// A frame cut below its least height overflows by the cut, holding
|
|
1102
1251
|
// content or not (#911).
|
|
@@ -1126,6 +1275,7 @@ function composePage(input, template, fit, collapsed) {
|
|
|
1126
1275
|
rect: { ...rect },
|
|
1127
1276
|
rotate: frame.rotate + (turned ? frameModeTurn({ writingMode: turned }) : 0),
|
|
1128
1277
|
...(turned ? { writingMode: turned } : {}),
|
|
1278
|
+
...(unmirroredAt(frame) !== undefined ? { unmirrorX: unmirroredAt(frame) } : {}),
|
|
1129
1279
|
layer: frame.layer,
|
|
1130
1280
|
...(frame.style ? { styleId: frame.style } : {}),
|
|
1131
1281
|
scale: s,
|
|
@@ -1149,7 +1299,11 @@ function composePage(input, template, fit, collapsed) {
|
|
|
1149
1299
|
}
|
|
1150
1300
|
else if (holds && cont?.receivers.has(frame.name)) {
|
|
1151
1301
|
// Content from the page before (#859).
|
|
1152
|
-
|
|
1302
|
+
const came = cont.receivers.get(frame.name);
|
|
1303
|
+
vdt.continuedFrom = came.fromFrameId;
|
|
1304
|
+
// From a page of an earlier chapter (#943).
|
|
1305
|
+
if (came.foreign)
|
|
1306
|
+
vdt.continuedFromChapter = came.foreign.from;
|
|
1153
1307
|
}
|
|
1154
1308
|
if (result) {
|
|
1155
1309
|
// The marks whose `{page}` the build fills in (#917).
|