postext 1.20.2 → 1.21.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__/color.test.d.ts +2 -0
- package/dist/__tests__/color.test.d.ts.map +1 -0
- package/dist/__tests__/color.test.js +110 -0
- package/dist/__tests__/color.test.js.map +1 -0
- package/dist/__tests__/comics/build.test.js +4 -3
- package/dist/__tests__/comics/build.test.js.map +1 -1
- package/dist/__tests__/comics/canvas.test.js +21 -2
- package/dist/__tests__/comics/canvas.test.js.map +1 -1
- package/dist/__tests__/comics/config.test.js +62 -0
- package/dist/__tests__/comics/config.test.js.map +1 -1
- package/dist/__tests__/comics/geometry.test.js +9 -2
- package/dist/__tests__/comics/geometry.test.js.map +1 -1
- package/dist/__tests__/comics/html.test.js +31 -0
- package/dist/__tests__/comics/html.test.js.map +1 -1
- package/dist/__tests__/comics/readingDirection.test.d.ts +2 -0
- package/dist/__tests__/comics/readingDirection.test.d.ts.map +1 -0
- package/dist/__tests__/comics/readingDirection.test.js +95 -0
- package/dist/__tests__/comics/readingDirection.test.js.map +1 -0
- package/dist/__tests__/comics/skew.test.d.ts +2 -0
- package/dist/__tests__/comics/skew.test.d.ts.map +1 -0
- package/dist/__tests__/comics/skew.test.js +57 -0
- package/dist/__tests__/comics/skew.test.js.map +1 -0
- package/dist/__tests__/comics/strip.test.js +186 -6
- package/dist/__tests__/comics/strip.test.js.map +1 -1
- package/dist/__tests__/exports.test.js +43 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/__tests__/pipeline/resourceNumbering.test.js +33 -1
- package/dist/__tests__/pipeline/resourceNumbering.test.js.map +1 -1
- package/dist/__tests__/preflight.test.d.ts +2 -0
- package/dist/__tests__/preflight.test.d.ts.map +1 -0
- package/dist/__tests__/preflight.test.js +115 -0
- package/dist/__tests__/preflight.test.js.map +1 -0
- package/dist/__tests__/printConfig.test.d.ts +2 -0
- package/dist/__tests__/printConfig.test.d.ts.map +1 -0
- package/dist/__tests__/printConfig.test.js +44 -0
- package/dist/__tests__/printConfig.test.js.map +1 -0
- package/dist/canvas-backend/blockRender.d.ts.map +1 -1
- package/dist/canvas-backend/blockRender.js +36 -1
- package/dist/canvas-backend/blockRender.js.map +1 -1
- package/dist/canvas-backend/comic.d.ts +2 -1
- package/dist/canvas-backend/comic.d.ts.map +1 -1
- package/dist/canvas-backend/comic.js +6 -9
- package/dist/canvas-backend/comic.js.map +1 -1
- package/dist/color/authored.d.ts +9 -0
- package/dist/color/authored.d.ts.map +1 -0
- package/dist/color/authored.js +31 -0
- package/dist/color/authored.js.map +1 -0
- package/dist/color/catalogue.d.ts +29 -0
- package/dist/color/catalogue.d.ts.map +1 -0
- package/dist/color/catalogue.js +52 -0
- package/dist/color/catalogue.js.map +1 -0
- package/dist/color/icc.d.ts +68 -0
- package/dist/color/icc.d.ts.map +1 -0
- package/dist/color/icc.js +533 -0
- package/dist/color/icc.js.map +1 -0
- package/dist/color/index.d.ts +6 -0
- package/dist/color/index.d.ts.map +1 -0
- package/dist/color/index.js +6 -0
- package/dist/color/index.js.map +1 -0
- package/dist/color/srgbProfile.d.ts +8 -0
- package/dist/color/srgbProfile.d.ts.map +1 -0
- package/dist/color/srgbProfile.js +86 -0
- package/dist/color/srgbProfile.js.map +1 -0
- package/dist/color/transform.d.ts +73 -0
- package/dist/color/transform.d.ts.map +1 -0
- package/dist/color/transform.js +329 -0
- package/dist/color/transform.js.map +1 -0
- package/dist/comics/index.d.ts +3 -3
- package/dist/comics/index.d.ts.map +1 -1
- package/dist/comics/index.js +2 -2
- package/dist/comics/index.js.map +1 -1
- package/dist/comics/layoutPage.d.ts +8 -4
- package/dist/comics/layoutPage.d.ts.map +1 -1
- package/dist/comics/layoutPage.js +17 -9
- package/dist/comics/layoutPage.js.map +1 -1
- package/dist/comics/lettering/__tests__/letterPanel.test.js +19 -9
- package/dist/comics/lettering/__tests__/letterPanel.test.js.map +1 -1
- package/dist/comics/lettering/letter.js +13 -7
- package/dist/comics/lettering/letter.js.map +1 -1
- package/dist/comics/lettering/placement.d.ts +2 -0
- package/dist/comics/lettering/placement.d.ts.map +1 -1
- package/dist/comics/lettering/placement.js.map +1 -1
- package/dist/comics/lettering/types.d.ts +5 -0
- package/dist/comics/lettering/types.d.ts.map +1 -1
- package/dist/comics/paint.d.ts +6 -0
- package/dist/comics/paint.d.ts.map +1 -1
- package/dist/comics/paint.js +23 -0
- package/dist/comics/paint.js.map +1 -1
- package/dist/comics/script.d.ts.map +1 -1
- package/dist/comics/script.js +4 -1
- package/dist/comics/script.js.map +1 -1
- package/dist/comics/strip.d.ts +50 -3
- package/dist/comics/strip.d.ts.map +1 -1
- package/dist/comics/strip.js +55 -5
- package/dist/comics/strip.js.map +1 -1
- package/dist/comics/types.d.ts +3 -0
- package/dist/comics/types.d.ts.map +1 -1
- package/dist/configWarnings.d.ts +1 -1
- package/dist/configWarnings.d.ts.map +1 -1
- package/dist/configWarnings.js +93 -4
- package/dist/configWarnings.js.map +1 -1
- package/dist/defaults/comics.d.ts +48 -1
- package/dist/defaults/comics.d.ts.map +1 -1
- package/dist/defaults/comics.js +77 -8
- package/dist/defaults/comics.js.map +1 -1
- package/dist/defaults/index.d.ts +2 -1
- package/dist/defaults/index.d.ts.map +1 -1
- package/dist/defaults/index.js +10 -1
- package/dist/defaults/index.js.map +1 -1
- package/dist/defaults/page.d.ts +12 -6
- package/dist/defaults/page.d.ts.map +1 -1
- package/dist/defaults/page.js +15 -9
- package/dist/defaults/page.js.map +1 -1
- package/dist/defaults/print.d.ts +13 -0
- package/dist/defaults/print.d.ts.map +1 -0
- package/dist/defaults/print.js +147 -0
- package/dist/defaults/print.js.map +1 -0
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +46 -2
- package/dist/html-backend.js.map +1 -1
- package/dist/htmlComic.d.ts.map +1 -1
- package/dist/htmlComic.js +8 -3
- package/dist/htmlComic.js.map +1 -1
- package/dist/index.d.ts +11 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/locale.d.ts +9 -0
- package/dist/locale.d.ts.map +1 -1
- package/dist/locale.js +11 -0
- package/dist/locale.js.map +1 -1
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +211 -36
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/calloutLayout.d.ts +5 -0
- package/dist/pipeline/calloutLayout.d.ts.map +1 -1
- package/dist/pipeline/calloutLayout.js +36 -3
- package/dist/pipeline/calloutLayout.js.map +1 -1
- package/dist/pipeline/config.d.ts.map +1 -1
- package/dist/pipeline/config.js +13 -2
- package/dist/pipeline/config.js.map +1 -1
- package/dist/pipeline/contentWarnings.d.ts.map +1 -1
- package/dist/pipeline/contentWarnings.js +8 -0
- package/dist/pipeline/contentWarnings.js.map +1 -1
- package/dist/pipeline/crossRefs.d.ts.map +1 -1
- package/dist/pipeline/crossRefs.js +2 -1
- package/dist/pipeline/crossRefs.js.map +1 -1
- package/dist/pipeline/resourceLayout.d.ts +51 -2
- package/dist/pipeline/resourceLayout.d.ts.map +1 -1
- package/dist/pipeline/resourceLayout.js +96 -51
- package/dist/pipeline/resourceLayout.js.map +1 -1
- package/dist/pipeline/resourceNumbering.d.ts +5 -0
- package/dist/pipeline/resourceNumbering.d.ts.map +1 -1
- package/dist/pipeline/resourceNumbering.js +34 -5
- package/dist/pipeline/resourceNumbering.js.map +1 -1
- package/dist/pipeline/spanEmbeds.d.ts +6 -1
- package/dist/pipeline/spanEmbeds.d.ts.map +1 -1
- package/dist/pipeline/spanEmbeds.js +18 -3
- package/dist/pipeline/spanEmbeds.js.map +1 -1
- package/dist/preflight.d.ts +89 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +314 -0
- package/dist/preflight.js.map +1 -0
- package/dist/types.d.ts +167 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +47 -5
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js.map +1 -1
- package/icc/README.md +43 -0
- package/icc/fogra27.icc +0 -0
- package/icc/fogra28.icc +0 -0
- package/icc/fogra29.icc +0 -0
- package/icc/fogra30.icc +0 -0
- package/icc/fogra39.icc +0 -0
- package/icc/fogra40.icc +0 -0
- package/icc/fogra45.icc +0 -0
- package/icc/fogra47.icc +0 -0
- package/icc/fogra51.icc +0 -0
- package/icc/fogra52.icc +0 -0
- package/icc/gracol2006.icc +0 -0
- package/icc/ifra26.icc +0 -0
- package/icc/snap2007.icc +0 -0
- package/icc/swop3.icc +0 -0
- package/icc/swop5.icc +0 -0
- package/package.json +4 -2
package/dist/pipeline/build.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { plainTitleBreaks } from '../parse/inlineFormatting';
|
|
2
2
|
import { dimensionToPx } from '../units';
|
|
3
|
-
import { createVDTDocument, createVDTBlock, createBoundingBox, createVDTColumn, pageIsMirrored, pageIsVertical, } from '../vdt';
|
|
3
|
+
import { createVDTDocument, createVDTBlock, createBoundingBox, createVDTColumn, pageIsMirrored, pageIsVertical, flowRectToPage, } from '../vdt';
|
|
4
4
|
import { anchorBox } from '../design/layout';
|
|
5
5
|
import { parseMarkdownMemo, spaceDirectiveLines } from '../parse';
|
|
6
6
|
import { buildPageLabels, computeHeadingNumbering, parseNumberFormat, } from '../numbering';
|
|
@@ -15,14 +15,14 @@ import { orientLinesToFrames } from './mirrorFrame';
|
|
|
15
15
|
import { verseMarginTopPx } from './buildBlockKind';
|
|
16
16
|
import { resolveAllConfig, computeBaselineGrid, resolvedDirection, resolvedLocale } from './config';
|
|
17
17
|
import { asciiDigits } from '../arabicNumerals';
|
|
18
|
-
import { getMeasureDirection, setMeasureDirection } from '../measure/bidiLines';
|
|
18
|
+
import { getMeasureDirection, setMeasureDirection, shiftLineX } from '../measure/bidiLines';
|
|
19
19
|
import { createHeadingLevelResolver, deriveSectionGeometryConfig, sectionWritingMode, deriveSectionMeasureContext, headingIsHidden, headingIsNumbered, headingMarksFor, headingStyleOf, numberTitlesFor, planHeadingSections, } from './headingStyles';
|
|
20
20
|
import { locateAnchors } from './anchors';
|
|
21
21
|
import { applyCitations, citationLocale, processCitations, withBibliographyStyle } from './citations';
|
|
22
22
|
import { bookCitationContexts, needsCitationContext } from '../citations/context';
|
|
23
23
|
import { anchorTargetsOf, hasAnchorRefs, printsAnchorPages } from './crossRefs';
|
|
24
24
|
import { applyStatementNumbering, numberStatements, outlineLookup } from './statementNumbering';
|
|
25
|
-
import { spanEmbedStyle, wrapPageSpanEmbeds } from './spanEmbeds';
|
|
25
|
+
import { SPAN_EMBED_STYLE_ID, isPageSpanStrip, spanEmbedStyle, wrapPageSpanEmbeds } from './spanEmbeds';
|
|
26
26
|
import { anchorOutline, computeOutline, hasIndexDirective, hasTocDirective, headingNumberingOptions, headingTemplatesOf, outlineFromDoc, sameOutline } from './outline';
|
|
27
27
|
import { expandTocDirectives } from './toc';
|
|
28
28
|
import { expandIndexDirectives, locateIndexMarks } from './indexDirective';
|
|
@@ -31,7 +31,7 @@ import { computeLevelIndentsPx, computeOrderedLevelIndentsPx, computeOrderedList
|
|
|
31
31
|
import { resetLinePositions, createPageWithColumns, currentColumn, advanceToNextColumn, advanceToNextPageBoundary, enforcePageParity, placeBlockInColumn, placeAtomicBlock, createPartPage, pageHasContent, sideColumnOf, sideColumns, sideUsedBottom, pageIsOccupied, bandColumns, currentBand, isBandLevel, bandUsedBottom, closeBandAndInsertSpan, closeBandAt, pageLayoutOf, } from './placement';
|
|
32
32
|
import { chooseParagraphSplit } from './orphanWidow';
|
|
33
33
|
import { layoutComicPage, comicPageLayoutWarnings } from '../comics/layoutPage';
|
|
34
|
-
import { comicStripExtent, comicStripPlacement, layoutComicStrip } from '../comics/strip';
|
|
34
|
+
import { comicStripExtent, comicStripOffset, comicStripPlacement, comicStripWidth, layoutComicStrip } from '../comics/strip';
|
|
35
35
|
import { isComicSpread, layoutComicSpread } from '../comics/spread';
|
|
36
36
|
import { applyStyleAttrs, computePageMetrics, flowPageMirrored, pageMirrored, sheetRectToFlow, isMarkerBlock, nextNonMarkerBlock, spaceLinesAfter, prevNonMarkerBlock, rollbackTrailingBlocks, } from './buildHelpers';
|
|
37
37
|
import { measureContentBlock } from './measureContentBlock';
|
|
@@ -39,10 +39,10 @@ import { containerStyle, paragraphStyleIdOf, planParagraphContainers } from './p
|
|
|
39
39
|
import { appendChapterEndNotes, footnoteIdsOfLines, footnoteParagraphStyle, noteContentBlock, noteNumberPositionOf, numberFootnotes, footnoteFormatOf, numberFootnotesByPlacement, sameFootnoteNumbers, splitFootnoteDefinitions, withFootnoteStyle, } from './footnotes';
|
|
40
40
|
import { planParts, derivePartMeasureContext } from './parts';
|
|
41
41
|
import { layoutCallout, offsetBlock, offsetCalloutToAbsolute, pickCalloutStyle, planCallouts, resolveCalloutAttrs, } from './calloutLayout';
|
|
42
|
-
import { layoutResourceBlock, planTableSlice } from './resourceLayout';
|
|
42
|
+
import { layoutCaptionText, layoutResourceBlock, planTableSlice } from './resourceLayout';
|
|
43
43
|
import { computeFloatPlan, floatedResourceIds, floatColumnCount, } from './floatPlacement';
|
|
44
44
|
import { enumerateCurrentPageSlots, measureFloatBand, floatGapAbove, measureSideStack, clearSideObstacles, columnHasFloatBand, fitsStrict, trueBottom, } from './floatSlots';
|
|
45
|
-
import { computeHeadingContext,
|
|
45
|
+
import { computeHeadingContext, computeResourceNumberingState, } from './resourceNumbering';
|
|
46
46
|
import { documentLocale, effectiveResourceTypes } from '../defaults/resourceTypes';
|
|
47
47
|
import { resolveCalloutStylesConfig } from '../defaults/calloutStyles';
|
|
48
48
|
import { pickTableStyle } from '../defaults/tableStyle';
|
|
@@ -392,7 +392,10 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
392
392
|
const resources = content.resources ?? [];
|
|
393
393
|
const resourceTypes = effectiveResourceTypes(config, resources);
|
|
394
394
|
const headingContext = computeHeadingContext(contentBlocks, headingStart, isNumbered);
|
|
395
|
-
const
|
|
395
|
+
const numberingState = computeResourceNumberingState(contentBlocks, resourceTypes, resources, headingContext, continuation ? { counters: continuation.resourceCounters, numbered: continuation.resourceNumbers } : undefined, resolved.numerals, documentLocale(config));
|
|
396
|
+
const resourceNumbering = numberingState.map;
|
|
397
|
+
/** The numbers of the strips counted in a resource type (#590). */
|
|
398
|
+
const stripNumbers = numberingState.strips;
|
|
396
399
|
// Lookups threaded into block-kind resolution + measurement.
|
|
397
400
|
const resourceById = new Map();
|
|
398
401
|
for (const r of resources)
|
|
@@ -643,14 +646,69 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
643
646
|
const source = contentBlocks[idx]?.comic;
|
|
644
647
|
return source ? { idx, source } : undefined;
|
|
645
648
|
};
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
649
|
+
const stripGeometryMemo = new Map();
|
|
650
|
+
const stripGeometry = (blockIdx, source, measure, max, vertical) => {
|
|
651
|
+
const key = `${blockIdx}:${measure.toFixed(2)}:${max.toFixed(2)}:${vertical ? 1 : 0}`;
|
|
652
|
+
const memo = stripGeometryMemo.get(key);
|
|
653
|
+
if (memo)
|
|
654
|
+
return memo;
|
|
655
|
+
const dpi = resolved.page.dpi;
|
|
656
|
+
const place = comicStripPlacement(source.attrs);
|
|
657
|
+
const stripWidth = comicStripWidth(place, measure, dpi);
|
|
658
|
+
const dx = comicStripOffset(place.align, measure, stripWidth);
|
|
659
|
+
const typeId = place.type !== undefined && resourceTypeById.has(place.type) ? place.type : undefined;
|
|
660
|
+
const numbered = typeId !== undefined ? stripNumbers[blockIdx] : undefined;
|
|
661
|
+
const caption = place.caption
|
|
662
|
+
? layoutCaptionText({
|
|
663
|
+
text: place.caption,
|
|
664
|
+
// A type the strip is not counted in (no caption, an unknown id)
|
|
665
|
+
// lends nothing: the caption is plain.
|
|
666
|
+
resourceType: numbered ? resourceTypeById.get(typeId) : undefined,
|
|
667
|
+
number: numbered?.number ?? '',
|
|
668
|
+
resolved,
|
|
669
|
+
width: stripWidth,
|
|
670
|
+
resourceNumbering,
|
|
671
|
+
resourceTypes,
|
|
672
|
+
resources,
|
|
673
|
+
})
|
|
674
|
+
: undefined;
|
|
675
|
+
const captionRoom = caption && caption.bandHeight > 0 ? caption.bandHeight + caption.gapPx : 0;
|
|
676
|
+
const extent = comicStripExtent(source, stripWidth, dpi, vertical, Math.max(1, max - captionRoom));
|
|
677
|
+
const geometry = {
|
|
678
|
+
stripWidth,
|
|
679
|
+
dx,
|
|
680
|
+
extent,
|
|
681
|
+
...(caption && captionRoom > 0 ? { caption } : {}),
|
|
682
|
+
captionAbove: captionRoom > 0 && caption.style.position === 'above',
|
|
683
|
+
captionRoom,
|
|
684
|
+
height: extent + captionRoom,
|
|
685
|
+
};
|
|
686
|
+
stripGeometryMemo.set(key, geometry);
|
|
687
|
+
return geometry;
|
|
688
|
+
};
|
|
689
|
+
/** Geometry `g` at another measure: the strip's width and offset
|
|
690
|
+
* follow it, its extent and caption stay. */
|
|
691
|
+
const stripGeometryKept = (g, source, measure) => {
|
|
692
|
+
const place = comicStripPlacement(source.attrs);
|
|
693
|
+
const stripWidth = comicStripWidth(place, measure, resolved.page.dpi);
|
|
694
|
+
return { ...g, stripWidth, dx: comicStripOffset(place.align, measure, stripWidth) };
|
|
695
|
+
};
|
|
696
|
+
/**
|
|
697
|
+
* The block of a strip a measure `width` px wide and at most `max` px
|
|
698
|
+
* tall (flow): its comic laid out in the strip's box on the sheet (the
|
|
699
|
+
* flow box turned on a vertical page, mirrored on a right-to-left one),
|
|
700
|
+
* placed in the block's box; its caption as the block's lines, in the
|
|
701
|
+
* caption style, block-relative (placing the block moves them). `x` is
|
|
702
|
+
* where the block stands; `y` is 0 until it is placed.
|
|
703
|
+
*/
|
|
704
|
+
const buildComicStripBlock = (blockIdx, source, x, width, max, pageIndex,
|
|
705
|
+
/** The geometry the block was placed with, kept at another measure
|
|
706
|
+
* (its extent and caption; only its width and offset follow). */
|
|
707
|
+
keep) => {
|
|
653
708
|
const raw = contentBlocks[blockIdx];
|
|
709
|
+
const page = doc.pages[pageIndex] ?? doc.pages[cursor.pageIndex];
|
|
710
|
+
const vertical = pageIsVertical(page);
|
|
711
|
+
const g = keep ? stripGeometryKept(keep, source, width) : stripGeometry(blockIdx, source, width, max, vertical);
|
|
654
712
|
const blk = createVDTBlock(`comic-strip-${blockIdx}`, 'resource', bodyStyle.fontString, bodyStyle.color, bodyStyle.textAlign);
|
|
655
713
|
blk.contentIndex = blockIdx;
|
|
656
714
|
blk.sourceStart = raw.sourceStart + bodyOffset;
|
|
@@ -658,18 +716,92 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
658
716
|
blk.dirty = false;
|
|
659
717
|
blk.snappedToGrid = false;
|
|
660
718
|
blk.lines = [];
|
|
661
|
-
blk.bbox = createBoundingBox(x, 0, width,
|
|
662
|
-
|
|
719
|
+
blk.bbox = createBoundingBox(x, 0, width, g.height);
|
|
720
|
+
// The strip's box inside the block's, then both on the sheet: the
|
|
721
|
+
// offset between them is where the comic stands in the block's box
|
|
722
|
+
// there (a mirrored or turned frame moves it, wherever the block is).
|
|
723
|
+
const stripY = g.captionAbove ? g.captionRoom : 0;
|
|
724
|
+
const blockOnSheet = flowRectToPage(page, createBoundingBox(0, 0, width, g.height));
|
|
725
|
+
const stripOnSheet = flowRectToPage(page, createBoundingBox(g.dx, stripY, g.stripWidth, g.extent));
|
|
663
726
|
blk.comic = layoutComicStrip(source, {
|
|
664
727
|
resolved,
|
|
665
|
-
width: vertical ? extent :
|
|
666
|
-
height: vertical ?
|
|
728
|
+
width: vertical ? g.extent : g.stripWidth,
|
|
729
|
+
height: vertical ? g.stripWidth : g.extent,
|
|
730
|
+
x: stripOnSheet.x - blockOnSheet.x,
|
|
731
|
+
y: stripOnSheet.y - blockOnSheet.y,
|
|
667
732
|
resources: resourceById,
|
|
668
733
|
sourceOffset: bodyOffset,
|
|
669
734
|
pageIndex,
|
|
670
735
|
});
|
|
736
|
+
if (g.caption) {
|
|
737
|
+
const c = g.caption;
|
|
738
|
+
const fonts = c.fonts;
|
|
739
|
+
const color = c.style.color.hex;
|
|
740
|
+
const labelColor = c.style.labelColor.hex;
|
|
741
|
+
// Under the strip after the gap, or over it with the gap below.
|
|
742
|
+
const bandY = g.captionAbove ? 0 : g.extent + c.gapPx;
|
|
743
|
+
blk.fontString = fonts.fontString;
|
|
744
|
+
blk.boldFontString = fonts.boldFontString;
|
|
745
|
+
blk.italicFontString = fonts.italicFontString;
|
|
746
|
+
blk.boldItalicFontString = fonts.boldItalicFontString;
|
|
747
|
+
blk.color = color;
|
|
748
|
+
blk.refColor = c.linkColor;
|
|
749
|
+
blk.textAlign = c.style.align;
|
|
750
|
+
// Every segment carries its font and colour: a renderer paints them
|
|
751
|
+
// as the lines of a paragraph, in the caption's face and colours.
|
|
752
|
+
const fontOf = (bold, italic) => bold && italic ? fonts.boldItalicFontString : bold ? fonts.boldFontString : italic ? fonts.italicFontString : fonts.fontString;
|
|
753
|
+
blk.lines = c.lines.map((line) => ({
|
|
754
|
+
...line,
|
|
755
|
+
bbox: createBoundingBox(line.bbox.x + g.dx + c.paddingPx, line.bbox.y + bandY + c.paddingPx, line.bbox.width, line.bbox.height),
|
|
756
|
+
baseline: line.baseline + bandY + c.paddingPx,
|
|
757
|
+
...(line.segments
|
|
758
|
+
? {
|
|
759
|
+
segments: line.segments.map((seg) => ({
|
|
760
|
+
...seg,
|
|
761
|
+
...(seg.fontString === undefined && (seg.kind === 'text' || seg.kind === 'space') ? { fontString: fontOf(seg.bold, seg.italic) } : {}),
|
|
762
|
+
...(seg.color === undefined && seg.refResourceId === undefined ? { color: seg.captionLabel ? labelColor : color } : {}),
|
|
763
|
+
})),
|
|
764
|
+
}
|
|
765
|
+
: {}),
|
|
766
|
+
}));
|
|
767
|
+
const place = comicStripPlacement(source.attrs);
|
|
768
|
+
const numbered = place.type !== undefined ? stripNumbers[blockIdx] : undefined;
|
|
769
|
+
blk.stripCaption = {
|
|
770
|
+
firstLine: 0,
|
|
771
|
+
lineCount: blk.lines.length,
|
|
772
|
+
position: g.captionAbove ? 'above' : 'below',
|
|
773
|
+
...(numbered ? { typeId: numbered.typeId, number: numbered.number, ...(place.id ? { id: place.id } : {}) } : {}),
|
|
774
|
+
...(c.style.backgroundEnabled
|
|
775
|
+
? { bar: { rect: createBoundingBox(g.dx, bandY, g.stripWidth, c.bandHeight), background: c.style.background.hex } }
|
|
776
|
+
: {}),
|
|
777
|
+
};
|
|
778
|
+
}
|
|
671
779
|
return blk;
|
|
672
780
|
};
|
|
781
|
+
/** Give a strip set in the flow (`here`, or in a box) the placeholder
|
|
782
|
+
* line that carries its height, as an inline figure's does: before its
|
|
783
|
+
* caption, or after a caption set over it (block-relative). */
|
|
784
|
+
const withStripPlaceholder = (blk, g) => {
|
|
785
|
+
const y = g.captionAbove ? g.captionRoom : 0;
|
|
786
|
+
const placeholder = { text: '', bbox: { x: g.dx, y, width: g.stripWidth, height: g.extent }, baseline: y, hyphenated: false, segments: [], isLastLine: true };
|
|
787
|
+
if (g.captionAbove) {
|
|
788
|
+
blk.lines = [...blk.lines, placeholder];
|
|
789
|
+
}
|
|
790
|
+
else {
|
|
791
|
+
blk.lines = [placeholder, ...blk.lines];
|
|
792
|
+
if (blk.stripCaption)
|
|
793
|
+
blk.stripCaption.firstLine = 1;
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
/** Shift a strip block's lines (its caption, its placeholder) by
|
|
797
|
+
* `(dx, dy)`: a float set at its band. */
|
|
798
|
+
const shiftStripLines = (blk, dx, dy) => {
|
|
799
|
+
for (const line of blk.lines) {
|
|
800
|
+
shiftLineX(line, dx);
|
|
801
|
+
line.bbox.y += dy;
|
|
802
|
+
line.baseline += dy;
|
|
803
|
+
}
|
|
804
|
+
};
|
|
673
805
|
/** Boxes laid out for a band, waiting for the band's `y` (built in
|
|
674
806
|
* `buildFloatBlock`, committed in `commitFloatBlock`). */
|
|
675
807
|
const calloutFloatResults = new Map();
|
|
@@ -837,9 +969,16 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
837
969
|
return memo;
|
|
838
970
|
const strip = comicStripOf(resourceId);
|
|
839
971
|
if (strip) {
|
|
840
|
-
// A strip: its height at the band's width
|
|
841
|
-
// keeps for a float band.
|
|
842
|
-
|
|
972
|
+
// A strip: its height at the band's width (its caption's included),
|
|
973
|
+
// never taller than a page keeps for a float band. A caption under
|
|
974
|
+
// it is the last text line a bottom band aligns to the grid.
|
|
975
|
+
const max = contentArea.height - 2 * floatGapPx;
|
|
976
|
+
const g = stripGeometry(strip.idx, strip.source, width, max, pageIsVertical(doc.pages[cursor.pageIndex]));
|
|
977
|
+
const last = g.caption && !g.captionAbove ? g.caption.lines[g.caption.lines.length - 1] : undefined;
|
|
978
|
+
const ms = {
|
|
979
|
+
height: g.height,
|
|
980
|
+
...(last ? { lastCaptionBaseline: g.extent + g.caption.gapPx + g.caption.paddingPx + last.baseline } : {}),
|
|
981
|
+
};
|
|
843
982
|
floatMeasureMemo.set(key, ms);
|
|
844
983
|
return ms;
|
|
845
984
|
}
|
|
@@ -901,8 +1040,8 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
901
1040
|
mirrored = false) => {
|
|
902
1041
|
const strip = comicStripOf(resourceId);
|
|
903
1042
|
if (strip) {
|
|
904
|
-
const
|
|
905
|
-
return { block
|
|
1043
|
+
const block = buildComicStripBlock(strip.idx, strip.source, x, width, contentArea.height - 2 * floatGapPx, cursor.pageIndex);
|
|
1044
|
+
return { block, height: block.bbox.height };
|
|
906
1045
|
}
|
|
907
1046
|
const cf = calloutFloatOf(resourceId);
|
|
908
1047
|
if (cf) {
|
|
@@ -1191,9 +1330,12 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
1191
1330
|
calloutBandPages.add(page);
|
|
1192
1331
|
return;
|
|
1193
1332
|
}
|
|
1194
|
-
// (A strip's comic is relative to its block
|
|
1333
|
+
// (A strip's comic is relative to its block; its caption lines are
|
|
1334
|
+
// relative to it until now.)
|
|
1195
1335
|
if (built.block.resourceBlock)
|
|
1196
1336
|
offsetResourceBlockToAbsolute(built.block.resourceBlock, 0, y);
|
|
1337
|
+
else if (built.block.comic)
|
|
1338
|
+
shiftStripLines(built.block, x, y);
|
|
1197
1339
|
built.block.bbox = createBoundingBox(x, y, width, built.height);
|
|
1198
1340
|
built.block.pageIndex = page.index;
|
|
1199
1341
|
built.block.columnIndex = col.index;
|
|
@@ -2877,11 +3019,21 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
2877
3019
|
return Math.abs(last.width - width) <= 0.5 ? before : [...before, { fromLine: from.line, width }];
|
|
2878
3020
|
};
|
|
2879
3021
|
const CUT_START = { child: 0, line: 0 };
|
|
3022
|
+
/** A strip in a box (the box of a page-wide strip set `here`, #590):
|
|
3023
|
+
* laid out at the box's inner width, as tall as a page allows, with its
|
|
3024
|
+
* placeholder line; the page it lays out for is the cursor's. */
|
|
3025
|
+
const calloutStripBlock = (raw, idx, width) => {
|
|
3026
|
+
if (!raw.comic)
|
|
3027
|
+
return undefined;
|
|
3028
|
+
const blk = buildComicStripBlock(idx, raw.comic, 0, width, contentArea.height - 2 * floatGapPx, cursor.pageIndex);
|
|
3029
|
+
withStripPlaceholder(blk, stripGeometry(idx, raw.comic, width, contentArea.height - 2 * floatGapPx, pageIsVertical(doc.pages[cursor.pageIndex])));
|
|
3030
|
+
return blk;
|
|
3031
|
+
};
|
|
2880
3032
|
const makeCalloutLayouter = (startIdx, plan, style) => {
|
|
2881
3033
|
const children = contentBlocks.slice(startIdx + 1, plan.endIdx);
|
|
2882
3034
|
const realAt = [];
|
|
2883
3035
|
children.forEach((c, k) => {
|
|
2884
|
-
if (c.type !== 'directive' && !isMarkerBlock(c))
|
|
3036
|
+
if ((c.type !== 'directive' || (c.directiveName === 'strip' && c.comic)) && !isMarkerBlock(c))
|
|
2885
3037
|
realAt.push(k);
|
|
2886
3038
|
});
|
|
2887
3039
|
// `:::columns` groups among the children, as [start marker, end marker]
|
|
@@ -2939,6 +3091,7 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
2939
3091
|
...(to.line > 0 ? { lineTo: to.line } : {}),
|
|
2940
3092
|
...(open.length > 0 ? { openNested: open } : {}),
|
|
2941
3093
|
mirrored,
|
|
3094
|
+
stripBlock: calloutStripBlock,
|
|
2942
3095
|
});
|
|
2943
3096
|
};
|
|
2944
3097
|
return { children, childBase: startIdx + 1, realAt, end: { child: children.length, line: 0 }, layoutRange, groups };
|
|
@@ -4201,10 +4354,15 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
4201
4354
|
* several columns, it waits in the float queue for the first free band
|
|
4202
4355
|
* from here on, as a figure does.
|
|
4203
4356
|
*/
|
|
4357
|
+
/** Boxes of page-wide strips set in the flow (no band of several
|
|
4358
|
+
* columns where they stood): their markers are passed over. */
|
|
4359
|
+
const looseStripBoxes = new Set();
|
|
4204
4360
|
const placeComicStrip = (blockIdx, source) => {
|
|
4205
4361
|
const place = comicStripPlacement(source.attrs);
|
|
4206
4362
|
const page = doc.pages[cursor.pageIndex];
|
|
4207
|
-
|
|
4363
|
+
// (A page-wide strip set `here` on a page of several columns is boxed
|
|
4364
|
+
// by `wrapPageSpanEmbeds` and cuts the band as a page-span box does.)
|
|
4365
|
+
if (place.position !== 'here') {
|
|
4208
4366
|
const key = `${COMIC_STRIP_PREFIX}${blockIdx}`;
|
|
4209
4367
|
// A keep-with-next replay passes the fence again: enqueue once.
|
|
4210
4368
|
if (!enqueuedFloatIds.has(key)) {
|
|
@@ -4213,7 +4371,7 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
4213
4371
|
pendingFloats.push({
|
|
4214
4372
|
resourceId: key,
|
|
4215
4373
|
firstBlockIdx: blockIdx,
|
|
4216
|
-
position: place.position
|
|
4374
|
+
position: place.position,
|
|
4217
4375
|
span: place.span,
|
|
4218
4376
|
...(col ? { refPageIndex: page.index, refY: col.bbox.y + (col.bbox.height - col.availableHeight) } : {}),
|
|
4219
4377
|
});
|
|
@@ -4221,27 +4379,26 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
4221
4379
|
return undefined;
|
|
4222
4380
|
}
|
|
4223
4381
|
const col = currentColumn(doc, cursor);
|
|
4224
|
-
const
|
|
4382
|
+
const g = stripGeometry(blockIdx, source, col.bbox.width, contentArea.height, pageIsVertical(page));
|
|
4383
|
+
const height = g.height;
|
|
4225
4384
|
const spacingBefore = Math.max(pendingSpacing, floatGapPx);
|
|
4226
|
-
if (col.blocks.length > 0 &&
|
|
4385
|
+
if (col.blocks.length > 0 && height > col.availableHeight - spacingBefore + FIT_EPS) {
|
|
4227
4386
|
const run = trailingHeadingRun(col);
|
|
4228
4387
|
if (run > 0 && run < col.blocks.length) {
|
|
4229
4388
|
const rolled = rollbackHeadings(col);
|
|
4230
4389
|
pendingSpacing = 0;
|
|
4231
|
-
advanceToNextColumn(doc, cursor, geomResolved, contentArea, pageWidthPx, pageHeightPx, onAtomicNewPage(
|
|
4390
|
+
advanceToNextColumn(doc, cursor, geomResolved, contentArea, pageWidthPx, pageHeightPx, onAtomicNewPage(height));
|
|
4232
4391
|
return (rolled[0].contentIndex ?? blockIdx - rolled.length) - 1;
|
|
4233
4392
|
}
|
|
4234
4393
|
}
|
|
4235
|
-
const blk = buildComicStripBlock(blockIdx, source, 0, col.bbox.width,
|
|
4236
|
-
|
|
4237
|
-
// figure's does).
|
|
4238
|
-
blk.lines = [{ text: '', bbox: { x: 0, y: 0, width: col.bbox.width, height: extent }, baseline: 0, hyphenated: false, segments: [], isLastLine: true }];
|
|
4394
|
+
const blk = buildComicStripBlock(blockIdx, source, 0, col.bbox.width, contentArea.height, cursor.pageIndex);
|
|
4395
|
+
withStripPlaceholder(blk, g);
|
|
4239
4396
|
enterBand(blockIdx, 0);
|
|
4240
|
-
placeAtomicBlock(blk,
|
|
4397
|
+
placeAtomicBlock(blk, height, spacingBefore, cursor, doc, geomResolved, contentArea, pageWidthPx, pageHeightPx, onAtomicNewPage(height));
|
|
4241
4398
|
enterBand(blockIdx, 0);
|
|
4242
4399
|
// Laid out again where it landed: the page it reports on, and the
|
|
4243
4400
|
// measure of that column (a side column, another section's).
|
|
4244
|
-
const landed = buildComicStripBlock(blockIdx, source, 0, blk.bbox.width,
|
|
4401
|
+
const landed = buildComicStripBlock(blockIdx, source, 0, blk.bbox.width, contentArea.height, cursor.pageIndex, g);
|
|
4245
4402
|
blk.comic = landed.comic;
|
|
4246
4403
|
doc.blocks.push(blk);
|
|
4247
4404
|
// The flow after the strip goes back to the baseline grid, and the
|
|
@@ -4497,6 +4654,24 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
4497
4654
|
flushPendingNumberingAtBoundary();
|
|
4498
4655
|
continue;
|
|
4499
4656
|
}
|
|
4657
|
+
// The box of a page-wide strip set `here` (`wrapPageSpanEmbeds`) cuts a
|
|
4658
|
+
// band of several columns; elsewhere the strip is set in the flow as any
|
|
4659
|
+
// strip, its box markers passed over.
|
|
4660
|
+
if (rawBlock.type === 'containerStart' && rawBlock.containerName === 'callout'
|
|
4661
|
+
&& rawBlock.containerAttrs?.type === SPAN_EMBED_STYLE_ID && isPageSpanStrip(contentBlocks[blockIdx + 1])
|
|
4662
|
+
&& !multiColumnBand(doc.pages[cursor.pageIndex])) {
|
|
4663
|
+
looseStripBoxes.add(rawBlock.containerId);
|
|
4664
|
+
continue;
|
|
4665
|
+
}
|
|
4666
|
+
if (rawBlock.type === 'containerEnd' && rawBlock.containerId !== undefined && looseStripBoxes.has(rawBlock.containerId)) {
|
|
4667
|
+
// What the strip owes below it passes through its box's closing marker.
|
|
4668
|
+
// (Set by the strip's placement, in a callback the flow analysis
|
|
4669
|
+
// does not follow.)
|
|
4670
|
+
const owed = inlineGapOwed;
|
|
4671
|
+
if (owed && owed.afterIdx === blockIdx - 1)
|
|
4672
|
+
inlineGapOwed = { ...owed, afterIdx: blockIdx };
|
|
4673
|
+
continue;
|
|
4674
|
+
}
|
|
4500
4675
|
if (rawBlock.type === 'containerStart' && rawBlock.containerName === 'callout') {
|
|
4501
4676
|
const plan = calloutPlan.get(blockIdx);
|
|
4502
4677
|
if (plan && pickCalloutStyle(calloutStyles, plan.attrs.type)) {
|