@stll/folio-core 0.28.1 → 0.30.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/controller/folioEditor.d.ts +28 -1
- package/dist/controller/folioEditor.js +37 -26
- package/dist/controller/fontReadiness.js +28 -24
- package/dist/controller/hiddenEditorManager.d.ts +2 -7
- package/dist/controller/layoutPipeline.js +33 -3
- package/dist/controller/noteEditorManager.d.ts +3 -6
- package/dist/docx/metafileSvg.d.ts +12 -0
- package/dist/docx/metafileSvg.js +462 -0
- package/dist/docx/paragraphTextBoxEnrichment.js +55 -4
- package/dist/docx/parser.d.ts +2 -2
- package/dist/docx/parser.js +26 -0
- package/dist/docx/runParser.js +2 -1
- package/dist/docx/serializer/runSerializer.js +14 -2
- package/dist/docx/styleParser.js +2 -1
- package/dist/docx/textBoxParser.js +14 -0
- package/dist/docx/vmlImageParser.js +72 -152
- package/dist/docx/vmlPreview.d.ts +31 -0
- package/dist/docx/vmlPreview.js +535 -0
- package/dist/docx/wrapTypes.d.ts +2 -36
- package/dist/docx/wrapTypes.js +1 -39
- package/dist/fonts/fontAlternates.d.ts +8 -0
- package/dist/fonts/fontAlternates.js +16 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +34 -3
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +5 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +136 -120
- package/dist/layout-bridge/dom/noteStoryDom.d.ts +1 -1
- package/dist/layout-bridge/engine/selectionRects.js +3 -1
- package/dist/layout-engine/index.js +65 -32
- package/dist/layout-engine/justifiedLineFit.d.ts +7 -0
- package/dist/layout-engine/justifiedLineFit.js +6 -0
- package/dist/layout-engine/keep-together.js +15 -10
- package/dist/layout-engine/measure/complexScriptFormatting.d.ts +6 -1
- package/dist/layout-engine/measure/complexScriptFormatting.js +11 -2
- package/dist/layout-engine/measure/floatingTablePosition.d.ts +16 -1
- package/dist/layout-engine/measure/floatingTablePosition.js +29 -6
- package/dist/layout-engine/measure/lineBreakProvider.js +67 -8
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.js +23 -10
- package/dist/layout-engine/measure/measureBlocks.d.ts +15 -0
- package/dist/layout-engine/measure/measureBlocks.js +197 -30
- package/dist/layout-engine/measure/measureContainer.js +20 -24
- package/dist/layout-engine/measure/measureHelpers.d.ts +1 -1
- package/dist/layout-engine/measure/measureHelpers.js +14 -8
- package/dist/layout-engine/measure/measureParagraph.js +111 -37
- package/dist/layout-engine/measure/measureTypes.d.ts +3 -0
- package/dist/layout-engine/measure/tabCalculator.d.ts +123 -0
- package/dist/layout-engine/measure/tabCalculator.js +144 -0
- package/dist/layout-engine/measure/tableCellFlow.d.ts +21 -1
- package/dist/layout-engine/measure/tableCellFlow.js +45 -8
- package/dist/layout-engine/measure/tableInlinePlacement.d.ts +10 -2
- package/dist/layout-engine/measure/tableInlinePlacement.js +17 -15
- package/dist/layout-engine/paginator.d.ts +26 -2
- package/dist/layout-engine/paginator.js +76 -14
- package/dist/layout-engine/paragraphSpacing.d.ts +3 -1
- package/dist/layout-engine/paragraphSpacing.js +4 -3
- package/dist/layout-engine/renderedBreakReconciliation.d.ts +14 -3
- package/dist/layout-engine/renderedBreakReconciliation.js +45 -14
- package/dist/layout-engine/section-breaks.d.ts +3 -1
- package/dist/layout-engine/section-breaks.js +6 -2
- package/dist/layout-engine/types.d.ts +18 -1
- package/dist/layout-engine/types.js +1 -1
- package/dist/layout-painter/imageLayout.d.ts +1 -1
- package/dist/layout-painter/renderPage.js +6 -1
- package/dist/layout-painter/renderParagraph.js +169 -82
- package/dist/layout-painter/renderTable.d.ts +1 -1
- package/dist/layout-painter/renderTable.js +18 -7
- package/dist/layout-painter/renderTextBox.d.ts +1 -1
- package/dist/layout-painter/renderTextBox.js +6 -1
- package/dist/markdown/renderParagraph.js +7 -2
- package/dist/model.d.ts +3 -3
- package/dist/model.js +2 -2
- package/dist/paged-layout/sectionBlockWidths.d.ts +14 -0
- package/dist/paged-layout/sectionBlockWidths.js +103 -14
- package/dist/prosemirror/attrs/index.js +14 -2
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +8 -0
- package/dist/prosemirror/bookmarkBoundaryAttrs.js +66 -0
- package/dist/prosemirror/conversion/fromProseDoc.js +176 -54
- package/dist/prosemirror/conversion/toProseDoc.js +179 -64
- package/dist/prosemirror/extensions/StarterKit.js +11 -3
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +8 -4
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +9 -5
- package/dist/prosemirror/extensions/features/pasteCleanup.d.ts +10 -23
- package/dist/prosemirror/extensions/features/pasteCleanup.js +77 -22
- package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +9 -5
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +67 -0
- package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +10 -4
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +77 -59
- package/dist/prosemirror/extensions/nodes/TableExtension.js +2 -0
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +4 -1
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +4 -3
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +6 -2
- package/dist/prosemirror/listMarker.d.ts +58 -0
- package/dist/prosemirror/listMarker.js +185 -0
- package/dist/prosemirror/numberedRefFields.d.ts +24 -0
- package/dist/prosemirror/numberedRefFields.js +276 -0
- package/dist/prosemirror/paraText.js +56 -17
- package/dist/prosemirror/plugins/anonymizationDecorations.js +1 -1
- package/dist/prosemirror/plugins/pmTextScan.d.ts +3 -1
- package/dist/prosemirror/plugins/pmTextScan.js +28 -7
- package/dist/prosemirror/plugins/templateDirectives.js +2 -2
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/nodes.d.ts +17 -1
- package/dist/prosemirror/utils/tabCalculator.d.ts +2 -123
- package/dist/prosemirror/utils/tabCalculator.js +1 -140
- package/dist/prosemirror/validation.js +93 -0
- package/dist/render-dom/RemoteSelectionOverlay.d.ts +4 -4
- package/dist/types/documentEnumValues.d.ts +4 -1
- package/dist/types/documentEnumValues.js +12 -1
- package/dist/types/editor-story.d.ts +8 -0
- package/dist/types/editor-story.js +0 -0
- package/dist/types/remote-selection.d.ts +11 -0
- package/dist/types/remote-selection.js +0 -0
- package/dist/types/wrap.d.ts +36 -0
- package/dist/types/wrap.js +40 -0
- package/dist/utils/fontResolver.d.ts +1 -1
- package/dist/utils/fontResolver.js +42 -2
- package/dist/utils/formatToStyle.js +4 -2
- package/dist/utils/horizontalScale.d.ts +28 -0
- package/dist/utils/horizontalScale.js +42 -0
- package/package.json +2 -2
|
@@ -3,12 +3,27 @@ import { FloatingImageZone } from "./floatingZones.js";
|
|
|
3
3
|
import "./measureParagraph.js";
|
|
4
4
|
//#region src/layout-engine/measure/measureBlocks.d.ts
|
|
5
5
|
declare function measureTableBlock(tableBlock: TableBlock, contentWidth: number, fieldValues?: ReadonlyMap<number, string>): TableMeasure;
|
|
6
|
+
type PhysicalBandPageGeometry = {
|
|
7
|
+
pageWidth: number | number[];
|
|
8
|
+
pageHeight: number | number[];
|
|
9
|
+
marginTop: number | number[];
|
|
10
|
+
marginLeft: number | number[];
|
|
11
|
+
marginRight: number | number[];
|
|
12
|
+
marginBottom: number | number[];
|
|
13
|
+
};
|
|
6
14
|
type BandPageGeometry = {
|
|
7
15
|
pageWidth?: number | number[];
|
|
8
16
|
pageHeight: number | number[];
|
|
9
17
|
marginLeft?: number | number[];
|
|
10
18
|
marginRight?: number | number[];
|
|
11
19
|
marginBottom: number | number[];
|
|
20
|
+
/** Absolute page X of each block's active column origin. */
|
|
21
|
+
contentLeft?: number | number[];
|
|
22
|
+
physicalPage?: PhysicalBandPageGeometry;
|
|
23
|
+
/** Authored flow-column index occupied by each block. */
|
|
24
|
+
columnIndex?: number | number[];
|
|
25
|
+
/** Authored flow-column count for each block's section. */
|
|
26
|
+
columnCount?: number | number[];
|
|
12
27
|
};
|
|
13
28
|
/**
|
|
14
29
|
* Measure a block based on its type.
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { hasPageBreakBefore } from "../keep-together.js";
|
|
1
2
|
import { recordMeasureBlock, recordMeasureBlockError } from "../layoutInstrumentation.js";
|
|
2
3
|
import { isParagraphFrameTextBox } from "../paragraphFrame.js";
|
|
4
|
+
import { normalizeSectionBreakType } from "../section-breaks.js";
|
|
3
5
|
import { bandFragmentX, bandTopContentY, isPageFrameRelativeAnchor } from "../textBoxFlow.js";
|
|
4
6
|
import { getTextBoxGroupId } from "../textBoxGroup.js";
|
|
5
7
|
import { DEFAULT_TEXTBOX_MARGINS, floatingTextBoxReservesBand, floatingTextBoxWrapsText, resolveTableCellPadding, tableColumnsArePinned } from "../types.js";
|
|
6
8
|
import { getCachedParagraphMeasure, setCachedParagraphMeasure } from "./cache.js";
|
|
7
|
-
import {
|
|
9
|
+
import { resolveFloatingTablePageX } from "./floatingTablePosition.js";
|
|
8
10
|
import { findClearLineY, measureParagraph } from "./measureParagraph.js";
|
|
9
11
|
import { createTableCellFlowState, finishTableCellFlow, placeTableCellBlock } from "./tableCellFlow.js";
|
|
10
12
|
import { buildTableCellGrid, getFirstAvailableColumn, getTableCellVerticalBorderHeight } from "./tableCellGrid.js";
|
|
@@ -177,6 +179,42 @@ function perBlockNumberValue(value, blockIndex, fallback) {
|
|
|
177
179
|
if (Array.isArray(value)) return value[blockIndex] ?? fallback;
|
|
178
180
|
return value;
|
|
179
181
|
}
|
|
182
|
+
function resolveFloatingTableVerticalPosition({ floating, tableHeight, pageHeight, marginTop, marginBottom, distTop, distBottom }) {
|
|
183
|
+
let offset = floating.tblpY;
|
|
184
|
+
if (offset === void 0) {
|
|
185
|
+
const contentHeight = Math.max(0, pageHeight - marginTop - marginBottom);
|
|
186
|
+
switch (floating.tblpYSpec) {
|
|
187
|
+
case "top":
|
|
188
|
+
offset = 0;
|
|
189
|
+
break;
|
|
190
|
+
case "center":
|
|
191
|
+
offset = (contentHeight - tableHeight) / 2;
|
|
192
|
+
break;
|
|
193
|
+
case "bottom":
|
|
194
|
+
offset = contentHeight - tableHeight;
|
|
195
|
+
break;
|
|
196
|
+
case "inside":
|
|
197
|
+
case "outside":
|
|
198
|
+
case "inline":
|
|
199
|
+
case void 0: break;
|
|
200
|
+
default: floating.tblpYSpec;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (offset === void 0 || floating.vertAnchor === "text") {
|
|
204
|
+
const anchorOffset = offset ?? 0;
|
|
205
|
+
return {
|
|
206
|
+
type: "anchorRelative",
|
|
207
|
+
topOffset: anchorOffset - distTop,
|
|
208
|
+
bottomOffset: anchorOffset + tableHeight + distBottom
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const frameTop = floating.vertAnchor === "page" ? 0 : marginTop;
|
|
212
|
+
return {
|
|
213
|
+
type: "pageRelative",
|
|
214
|
+
pageTop: frameTop + offset - distTop,
|
|
215
|
+
pageBottom: frameTop + offset + tableHeight + distBottom
|
|
216
|
+
};
|
|
217
|
+
}
|
|
180
218
|
function textBoxWrapSide({ box, contentX, boxWidth, contentWidth }) {
|
|
181
219
|
if (box.wrapText === "left") return "left";
|
|
182
220
|
if (box.wrapText === "right") return "right";
|
|
@@ -187,6 +225,7 @@ function textBoxWrapSide({ box, contentX, boxWidth, contentWidth }) {
|
|
|
187
225
|
}
|
|
188
226
|
function extractFloatingZones(blocks, contentWidth, marginTop = 0, pageGeometry) {
|
|
189
227
|
const zones = [];
|
|
228
|
+
const tablePageRects = [];
|
|
190
229
|
const defaultContentWidth = Array.isArray(contentWidth) ? contentWidth[0] ?? 0 : contentWidth;
|
|
191
230
|
const textBoxGroupAnchors = /* @__PURE__ */ new Map();
|
|
192
231
|
const paragraphFrameGroupSizes = /* @__PURE__ */ new Map();
|
|
@@ -201,11 +240,25 @@ function extractFloatingZones(blocks, contentWidth, marginTop = 0, pageGeometry)
|
|
|
201
240
|
const marginLeftInput = pageGeometry?.marginLeft ?? 0;
|
|
202
241
|
const marginRightInput = pageGeometry?.marginRight ?? 0;
|
|
203
242
|
const marginBottomInput = pageGeometry?.marginBottom ?? 0;
|
|
243
|
+
const contentLeftInput = pageGeometry?.contentLeft ?? marginLeftInput;
|
|
244
|
+
const physicalPageWidthInput = pageGeometry?.physicalPage?.pageWidth ?? pageWidthInput;
|
|
245
|
+
const physicalPageHeightInput = pageGeometry?.physicalPage?.pageHeight ?? pageHeightInput;
|
|
246
|
+
const physicalMarginTopInput = pageGeometry?.physicalPage?.marginTop ?? marginTop;
|
|
247
|
+
const physicalMarginLeftInput = pageGeometry?.physicalPage?.marginLeft ?? marginLeftInput;
|
|
248
|
+
const physicalMarginRightInput = pageGeometry?.physicalPage?.marginRight ?? marginRightInput;
|
|
249
|
+
const physicalMarginBottomInput = pageGeometry?.physicalPage?.marginBottom ?? marginBottomInput;
|
|
204
250
|
const defaultPageWidth = Array.isArray(pageWidthInput) ? pageWidthInput[0] ?? defaultContentWidth : pageWidthInput;
|
|
205
251
|
const defaultPageHeight = Array.isArray(pageHeightInput) ? pageHeightInput[0] ?? 0 : pageHeightInput;
|
|
206
252
|
const defaultMarginLeft = Array.isArray(marginLeftInput) ? marginLeftInput[0] ?? 0 : marginLeftInput;
|
|
207
253
|
const defaultMarginRight = Array.isArray(marginRightInput) ? marginRightInput[0] ?? 0 : marginRightInput;
|
|
208
254
|
const defaultMarginBottom = Array.isArray(marginBottomInput) ? marginBottomInput[0] ?? 0 : marginBottomInput;
|
|
255
|
+
const defaultContentLeft = Array.isArray(contentLeftInput) ? contentLeftInput[0] ?? defaultMarginLeft : contentLeftInput;
|
|
256
|
+
const defaultPhysicalPageWidth = Array.isArray(physicalPageWidthInput) ? physicalPageWidthInput[0] ?? defaultPageWidth : physicalPageWidthInput;
|
|
257
|
+
const defaultPhysicalPageHeight = Array.isArray(physicalPageHeightInput) ? physicalPageHeightInput[0] ?? defaultPageHeight : physicalPageHeightInput;
|
|
258
|
+
const defaultPhysicalMarginTop = Array.isArray(physicalMarginTopInput) ? physicalMarginTopInput[0] ?? defaultMarginTop : physicalMarginTopInput;
|
|
259
|
+
const defaultPhysicalMarginLeft = Array.isArray(physicalMarginLeftInput) ? physicalMarginLeftInput[0] ?? defaultMarginLeft : physicalMarginLeftInput;
|
|
260
|
+
const defaultPhysicalMarginRight = Array.isArray(physicalMarginRightInput) ? physicalMarginRightInput[0] ?? defaultMarginRight : physicalMarginRightInput;
|
|
261
|
+
const defaultPhysicalMarginBottom = Array.isArray(physicalMarginBottomInput) ? physicalMarginBottomInput[0] ?? defaultMarginBottom : physicalMarginBottomInput;
|
|
209
262
|
for (let blockIndex = 0; blockIndex < blocks.length; blockIndex++) {
|
|
210
263
|
const block = blocks[blockIndex];
|
|
211
264
|
if (block.kind !== "paragraph") continue;
|
|
@@ -281,25 +334,43 @@ function extractFloatingZones(blocks, contentWidth, marginTop = 0, pageGeometry)
|
|
|
281
334
|
const tableBlock = block;
|
|
282
335
|
const floating = tableBlock.floating;
|
|
283
336
|
if (!floating) continue;
|
|
284
|
-
const
|
|
337
|
+
const blockPageWidth = perBlockNumberValue(physicalPageWidthInput, blockIndex, defaultPhysicalPageWidth);
|
|
338
|
+
const blockPageHeight = perBlockNumberValue(physicalPageHeightInput, blockIndex, defaultPhysicalPageHeight);
|
|
339
|
+
const blockContentTop = perBlockNumberValue(physicalMarginTopInput, blockIndex, defaultPhysicalMarginTop);
|
|
340
|
+
const blockMarginLeft = perBlockNumberValue(physicalMarginLeftInput, blockIndex, defaultPhysicalMarginLeft);
|
|
341
|
+
const blockMarginRight = perBlockNumberValue(physicalMarginRightInput, blockIndex, defaultPhysicalMarginRight);
|
|
342
|
+
const blockMarginBottom = perBlockNumberValue(physicalMarginBottomInput, blockIndex, defaultPhysicalMarginBottom);
|
|
343
|
+
const blockContentWidth = perBlockNumberValue(contentWidth, blockIndex, defaultContentWidth);
|
|
344
|
+
const blockContentLeft = perBlockNumberValue(contentLeftInput, blockIndex, defaultContentLeft);
|
|
345
|
+
const tableMeasure = measureTableBlock(tableBlock, blockContentWidth);
|
|
285
346
|
const tableWidth = tableMeasure.totalWidth;
|
|
286
347
|
const tableHeight = tableMeasure.totalHeight;
|
|
287
348
|
const distLeft = floating.leftFromText ?? 12;
|
|
288
349
|
const distRight = floating.rightFromText ?? 12;
|
|
289
350
|
const distTop = floating.topFromText ?? 0;
|
|
290
351
|
const distBottom = floating.bottomFromText ?? 0;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
352
|
+
const pageX = resolveFloatingTablePageX({
|
|
353
|
+
anchor: floating,
|
|
354
|
+
justification: tableBlock.justification,
|
|
355
|
+
tableWidth,
|
|
356
|
+
marginWidth: blockPageWidth - blockMarginLeft - blockMarginRight,
|
|
357
|
+
pageWidth: blockPageWidth,
|
|
358
|
+
marginLeft: blockMarginLeft,
|
|
359
|
+
textFrameWidth: blockContentWidth,
|
|
360
|
+
textFrameLeft: blockContentLeft
|
|
361
|
+
});
|
|
362
|
+
tablePageRects.push({
|
|
363
|
+
pageLeft: pageX - distLeft,
|
|
364
|
+
pageRight: pageX + tableWidth + distRight,
|
|
365
|
+
vertical: resolveFloatingTableVerticalPosition({
|
|
366
|
+
floating,
|
|
367
|
+
tableHeight,
|
|
368
|
+
pageHeight: blockPageHeight,
|
|
369
|
+
marginTop: blockContentTop,
|
|
370
|
+
marginBottom: blockMarginBottom,
|
|
371
|
+
distTop,
|
|
372
|
+
distBottom
|
|
373
|
+
}),
|
|
303
374
|
anchorBlockIndex: blockIndex
|
|
304
375
|
});
|
|
305
376
|
}
|
|
@@ -393,7 +464,56 @@ function extractFloatingZones(blocks, contentWidth, marginTop = 0, pageGeometry)
|
|
|
393
464
|
fullWidthBlock: true
|
|
394
465
|
});
|
|
395
466
|
}
|
|
396
|
-
return zones
|
|
467
|
+
return [...zones.map((zone) => ({
|
|
468
|
+
type: "contentZone",
|
|
469
|
+
zone
|
|
470
|
+
})), ...tablePageRects.map((rect) => ({
|
|
471
|
+
type: "tablePageRect",
|
|
472
|
+
rect
|
|
473
|
+
}))];
|
|
474
|
+
}
|
|
475
|
+
function projectFloatingTablePageRect({ rect, contentLeft, contentTop, contentWidth }) {
|
|
476
|
+
const rectLeft = rect.pageLeft - contentLeft;
|
|
477
|
+
const rectRight = rect.pageRight - contentLeft;
|
|
478
|
+
const topY = rect.pageTop - contentTop;
|
|
479
|
+
const bottomY = rect.pageBottom - contentTop;
|
|
480
|
+
if (rectRight <= 0 || rectLeft >= contentWidth) return {
|
|
481
|
+
leftMargin: 0,
|
|
482
|
+
rightMargin: 0,
|
|
483
|
+
topY,
|
|
484
|
+
bottomY
|
|
485
|
+
};
|
|
486
|
+
if (rectLeft < contentWidth / 2) return {
|
|
487
|
+
leftMargin: Math.max(0, Math.min(rectRight, contentWidth)),
|
|
488
|
+
rightMargin: 0,
|
|
489
|
+
topY,
|
|
490
|
+
bottomY
|
|
491
|
+
};
|
|
492
|
+
return {
|
|
493
|
+
leftMargin: 0,
|
|
494
|
+
rightMargin: Math.max(0, Math.min(contentWidth - rectLeft, contentWidth)),
|
|
495
|
+
topY,
|
|
496
|
+
bottomY
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
function activateFloatingTablePageRect(template, anchorPageY) {
|
|
500
|
+
switch (template.vertical.type) {
|
|
501
|
+
case "anchorRelative": return {
|
|
502
|
+
pageLeft: template.pageLeft,
|
|
503
|
+
pageRight: template.pageRight,
|
|
504
|
+
pageTop: anchorPageY + template.vertical.topOffset,
|
|
505
|
+
pageBottom: anchorPageY + template.vertical.bottomOffset
|
|
506
|
+
};
|
|
507
|
+
case "pageRelative": return {
|
|
508
|
+
pageLeft: template.pageLeft,
|
|
509
|
+
pageRight: template.pageRight,
|
|
510
|
+
pageTop: template.vertical.pageTop,
|
|
511
|
+
pageBottom: template.vertical.pageBottom
|
|
512
|
+
};
|
|
513
|
+
default:
|
|
514
|
+
template.vertical;
|
|
515
|
+
return template.vertical;
|
|
516
|
+
}
|
|
397
517
|
}
|
|
398
518
|
/**
|
|
399
519
|
* Measure a block based on its type.
|
|
@@ -471,16 +591,11 @@ function measureTextBoxBlock(tb, fieldValues) {
|
|
|
471
591
|
innerMeasures
|
|
472
592
|
};
|
|
473
593
|
}
|
|
474
|
-
/**
|
|
475
|
-
* `true` for a section break that explicitly starts a new page
|
|
476
|
-
* (`nextPage`/`evenPage`/`oddPage`). An absent type follows
|
|
477
|
-
* `scheduleSectionBreak` and stays continuous, so measurement must retain any
|
|
478
|
-
* active exclusion zones across it. Used by `measureBlocks` to reset the
|
|
479
|
-
* running Y for a page-pinned band that lands right after the break.
|
|
480
|
-
* eigenpal #694.
|
|
481
|
-
*/
|
|
482
594
|
function isNextPageSectionBreak(block) {
|
|
483
|
-
return block.kind === "sectionBreak" && block.type !==
|
|
595
|
+
return block.kind === "sectionBreak" && normalizeSectionBreakType(block.type) !== "continuous";
|
|
596
|
+
}
|
|
597
|
+
function isContinuousSectionBreak(block) {
|
|
598
|
+
return block.kind === "sectionBreak" && normalizeSectionBreakType(block.type) === "continuous";
|
|
484
599
|
}
|
|
485
600
|
/**
|
|
486
601
|
* Measure all blocks with floating image support.
|
|
@@ -491,7 +606,18 @@ function isNextPageSectionBreak(block) {
|
|
|
491
606
|
*/
|
|
492
607
|
function measureBlocks(blocks, contentWidth, marginTop = 0, pageGeometry, fieldValues) {
|
|
493
608
|
const defaultWidth = Array.isArray(contentWidth) ? contentWidth[0] ?? 0 : contentWidth;
|
|
494
|
-
const
|
|
609
|
+
const extractedZones = extractFloatingZones(blocks, contentWidth, marginTop, pageGeometry);
|
|
610
|
+
const floatingZonesWithAnchors = [];
|
|
611
|
+
const tablePageRects = [];
|
|
612
|
+
for (const extracted of extractedZones) switch (extracted.type) {
|
|
613
|
+
case "contentZone":
|
|
614
|
+
floatingZonesWithAnchors.push(extracted.zone);
|
|
615
|
+
break;
|
|
616
|
+
case "tablePageRect":
|
|
617
|
+
tablePageRects.push(extracted.rect);
|
|
618
|
+
break;
|
|
619
|
+
default:
|
|
620
|
+
}
|
|
495
621
|
const marginRelative = floatingZonesWithAnchors.filter((z) => z.isMarginRelative && !z.fullWidthBlock);
|
|
496
622
|
const ownAnchorZones = floatingZonesWithAnchors.filter((z) => !z.isMarginRelative || z.fullWidthBlock);
|
|
497
623
|
const marginByTopY = /* @__PURE__ */ new Map();
|
|
@@ -515,24 +641,59 @@ function measureBlocks(blocks, contentWidth, marginTop = 0, pageGeometry, fieldV
|
|
|
515
641
|
existing.push(zone);
|
|
516
642
|
zonesByAnchor.set(z.anchorBlockIndex, existing);
|
|
517
643
|
}
|
|
518
|
-
const
|
|
644
|
+
const tableRectsByAnchor = /* @__PURE__ */ new Map();
|
|
645
|
+
for (const rect of tablePageRects) {
|
|
646
|
+
const existing = tableRectsByAnchor.get(rect.anchorBlockIndex) ?? [];
|
|
647
|
+
existing.push(rect);
|
|
648
|
+
tableRectsByAnchor.set(rect.anchorBlockIndex, existing);
|
|
649
|
+
}
|
|
650
|
+
const anchorIndices = /* @__PURE__ */ new Set([...zonesByAnchor.keys(), ...tableRectsByAnchor.keys()]);
|
|
519
651
|
let cumulativeY = 0;
|
|
520
652
|
let pageRelativeY = 0;
|
|
653
|
+
let columnRegionMaxBottom = 0;
|
|
521
654
|
let activeZones = [];
|
|
655
|
+
let activeTablePageRects = [];
|
|
656
|
+
const contentLeftInput = pageGeometry?.contentLeft ?? pageGeometry?.marginLeft ?? 0;
|
|
657
|
+
const defaultContentLeft = Array.isArray(contentLeftInput) ? contentLeftInput[0] ?? 0 : contentLeftInput;
|
|
658
|
+
const physicalMarginTopInput = pageGeometry?.physicalPage?.marginTop ?? marginTop;
|
|
659
|
+
const defaultPhysicalMarginTop = Array.isArray(physicalMarginTopInput) ? physicalMarginTopInput[0] ?? 0 : physicalMarginTopInput;
|
|
660
|
+
const columnIndexInput = pageGeometry?.columnIndex ?? 0;
|
|
661
|
+
const columnCountInput = pageGeometry?.columnCount ?? 1;
|
|
522
662
|
return blocks.map((block, blockIndex) => {
|
|
523
663
|
recordMeasureBlock(blockIndex, block);
|
|
524
|
-
|
|
664
|
+
const blockWidth = Array.isArray(contentWidth) ? contentWidth[blockIndex] ?? defaultWidth : contentWidth;
|
|
665
|
+
const blockContentLeft = perBlockNumberValue(contentLeftInput, blockIndex, defaultContentLeft);
|
|
666
|
+
const blockContentTop = perBlockNumberValue(physicalMarginTopInput, blockIndex, defaultPhysicalMarginTop);
|
|
667
|
+
const blockColumnIndex = perBlockNumberValue(columnIndexInput, blockIndex, 0);
|
|
668
|
+
const blockColumnCount = perBlockNumberValue(columnCountInput, blockIndex, 1);
|
|
669
|
+
if (block.kind === "pageBreak" || isNextPageSectionBreak(block) || hasPageBreakBefore(block)) {
|
|
525
670
|
activeZones = [];
|
|
671
|
+
activeTablePageRects = [];
|
|
672
|
+
cumulativeY = 0;
|
|
673
|
+
pageRelativeY = 0;
|
|
674
|
+
columnRegionMaxBottom = 0;
|
|
675
|
+
} else if (block.kind === "columnBreak") {
|
|
676
|
+
if (blockColumnIndex + 1 >= blockColumnCount) {
|
|
677
|
+
activeZones = [];
|
|
678
|
+
activeTablePageRects = [];
|
|
679
|
+
columnRegionMaxBottom = 0;
|
|
680
|
+
} else columnRegionMaxBottom = Math.max(columnRegionMaxBottom, pageRelativeY);
|
|
526
681
|
cumulativeY = 0;
|
|
527
682
|
pageRelativeY = 0;
|
|
528
683
|
}
|
|
529
684
|
if (anchorIndices.has(blockIndex)) {
|
|
530
685
|
activeZones = zonesByAnchor.get(blockIndex) ?? [];
|
|
531
|
-
|
|
686
|
+
activeTablePageRects = (tableRectsByAnchor.get(blockIndex) ?? []).map((template) => activateFloatingTablePageRect(template, blockContentTop + pageRelativeY));
|
|
687
|
+
cumulativeY = activeTablePageRects.length === 0 && activeZones.length > 0 && activeZones.every((z) => z.fullWidthBlock) || activeTablePageRects.length > 0 ? pageRelativeY : 0;
|
|
532
688
|
}
|
|
533
|
-
const
|
|
689
|
+
const projectedTableZones = activeTablePageRects.map((rect) => projectFloatingTablePageRect({
|
|
690
|
+
rect,
|
|
691
|
+
contentLeft: blockContentLeft,
|
|
692
|
+
contentTop: blockContentTop,
|
|
693
|
+
contentWidth: blockWidth
|
|
694
|
+
}));
|
|
695
|
+
const zones = activeZones.length > 0 || projectedTableZones.length > 0 ? [...activeZones, ...projectedTableZones] : void 0;
|
|
534
696
|
try {
|
|
535
|
-
const blockWidth = Array.isArray(contentWidth) ? contentWidth[blockIndex] ?? defaultWidth : contentWidth;
|
|
536
697
|
const measure = measureBlock(block, blockWidth, zones, cumulativeY, fieldValues);
|
|
537
698
|
const clearingZones = measure.kind === "table" ? zones : zones?.filter((zone) => zone.fullWidthBlock);
|
|
538
699
|
if (clearingZones?.length && (measure.kind === "image" || measure.kind === "table" && !block.floating)) {
|
|
@@ -549,6 +710,12 @@ function measureBlocks(blocks, contentWidth, marginTop = 0, pageGeometry, fieldV
|
|
|
549
710
|
cumulativeY += measure.totalHeight;
|
|
550
711
|
pageRelativeY += measure.totalHeight;
|
|
551
712
|
}
|
|
713
|
+
if (isContinuousSectionBreak(block)) {
|
|
714
|
+
const nextSectionY = Math.max(pageRelativeY, columnRegionMaxBottom);
|
|
715
|
+
cumulativeY = nextSectionY;
|
|
716
|
+
pageRelativeY = nextSectionY;
|
|
717
|
+
columnRegionMaxBottom = 0;
|
|
718
|
+
}
|
|
552
719
|
return measure;
|
|
553
720
|
} catch (error) {
|
|
554
721
|
recordMeasureBlockError(blockIndex, block, error);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { getHorizontalScaleFactor } from "../../utils/horizontalScale.js";
|
|
1
2
|
import { SCRIPT_CLASS, hasCjk, hasComplexScript, scriptClassOf, segmentByScript } from "../../utils/scriptSegments.js";
|
|
2
3
|
import { getCachedFontMetrics, getCachedTextWidth, getTextWidthCacheGeneration, setCachedFontMetrics, setCachedTextWidth } from "./cache.js";
|
|
3
|
-
import {
|
|
4
|
+
import { applyComplexScriptFormatting, hasComplexScriptFormatting } from "./complexScriptFormatting.js";
|
|
4
5
|
import { buildFontString, getResolvedData, ptToPx } from "./measureHelpers.js";
|
|
5
6
|
import { setMeasureProvider } from "./measureProvider.js";
|
|
6
7
|
import { canPrefetchMeasurement, prefetchMeasurement } from "./measureWorker.js";
|
|
@@ -73,7 +74,9 @@ function canvasGetFontMetrics(style) {
|
|
|
73
74
|
const bold = style.bold ?? false;
|
|
74
75
|
const italic = style.italic ?? false;
|
|
75
76
|
const fontVariant = style.fontVariant;
|
|
76
|
-
const
|
|
77
|
+
const alternateFontFamily = style.alternateFontFamily;
|
|
78
|
+
const fontCacheFamily = alternateFontFamily ? `${fontFamily}\u0000${alternateFontFamily}` : fontFamily;
|
|
79
|
+
const cached = getCachedFontMetrics(fontCacheFamily, fontSize, bold, italic, fontVariant);
|
|
77
80
|
if (cached !== void 0) return {
|
|
78
81
|
fontSize,
|
|
79
82
|
ascent: cached.ascent,
|
|
@@ -97,7 +100,7 @@ function canvasGetFontMetrics(style) {
|
|
|
97
100
|
}
|
|
98
101
|
} catch {}
|
|
99
102
|
lineHeight = Math.max(lineHeight, ascent + descent);
|
|
100
|
-
const singleLineRatio = getResolvedData(fontFamily).singleLineRatio;
|
|
103
|
+
const singleLineRatio = getResolvedData(fontFamily, alternateFontFamily).singleLineRatio;
|
|
101
104
|
const result = {
|
|
102
105
|
fontSize,
|
|
103
106
|
ascent,
|
|
@@ -106,7 +109,7 @@ function canvasGetFontMetrics(style) {
|
|
|
106
109
|
fontFamily,
|
|
107
110
|
singleLineRatio
|
|
108
111
|
};
|
|
109
|
-
setCachedFontMetrics(
|
|
112
|
+
setCachedFontMetrics(fontCacheFamily, fontSize, bold, italic, result, fontVariant);
|
|
110
113
|
return result;
|
|
111
114
|
}
|
|
112
115
|
/**
|
|
@@ -118,16 +121,13 @@ function canvasGetFontMetrics(style) {
|
|
|
118
121
|
*/
|
|
119
122
|
function canvasMeasureTextWidth(text, sourceStyle) {
|
|
120
123
|
if (!text) return 0;
|
|
121
|
-
const style = sourceStyle.forceComplexScript ?
|
|
122
|
-
...sourceStyle,
|
|
123
|
-
...resolveComplexScriptFormatting(sourceStyle)
|
|
124
|
-
} : sourceStyle;
|
|
124
|
+
const style = sourceStyle.forceComplexScript ? applyComplexScriptFormatting(sourceStyle, sourceStyle) : sourceStyle;
|
|
125
125
|
const measuredText = applyTextTransform(text, style);
|
|
126
126
|
if (!sourceStyle.forceComplexScript && !style.letterSpacing && needsPerScriptFonts(style, measuredText)) return measureMixedScriptWidth(measuredText, style);
|
|
127
127
|
const ctx = getCanvasContext();
|
|
128
128
|
const font = buildFontString(style);
|
|
129
129
|
const letterSpacing = style.letterSpacing ?? 0;
|
|
130
|
-
const horizontalScale = getHorizontalScaleFactor(style);
|
|
130
|
+
const horizontalScale = getHorizontalScaleFactor(style.horizontalScale);
|
|
131
131
|
const fontKerning = getFontKerningMode(style);
|
|
132
132
|
const fontCacheKey = style.kerning ? `${font}|kerning:normal|scale:${horizontalScale}` : `${font}|scale:${horizontalScale}`;
|
|
133
133
|
const cached = getCachedTextWidth(measuredText, fontCacheKey, letterSpacing);
|
|
@@ -164,6 +164,7 @@ function canvasMeasureTextWidth(text, sourceStyle) {
|
|
|
164
164
|
function glyphAdvanceStyle(style) {
|
|
165
165
|
const result = {};
|
|
166
166
|
if (style.fontFamily !== void 0) result.fontFamily = style.fontFamily;
|
|
167
|
+
if (style.alternateFontFamily !== void 0) result.alternateFontFamily = style.alternateFontFamily;
|
|
167
168
|
if (style.fontSize !== void 0) result.fontSize = style.fontSize;
|
|
168
169
|
if (style.bold !== void 0) result.bold = style.bold;
|
|
169
170
|
if (style.italic !== void 0) result.italic = style.italic;
|
|
@@ -190,20 +191,20 @@ function needsPerScriptFonts(style, measuredText) {
|
|
|
190
191
|
function scriptStyle(style, script) {
|
|
191
192
|
if (script === SCRIPT_CLASS.eastAsia) {
|
|
192
193
|
if (style.eastAsiaFontFamily === void 0) return style;
|
|
193
|
-
|
|
194
|
+
const result = {
|
|
194
195
|
...style,
|
|
195
196
|
fontFamily: style.eastAsiaFontFamily
|
|
196
197
|
};
|
|
198
|
+
delete result.alternateFontFamily;
|
|
199
|
+
if (style.eastAsiaAlternateFontFamily !== void 0) result.alternateFontFamily = style.eastAsiaAlternateFontFamily;
|
|
200
|
+
return result;
|
|
197
201
|
}
|
|
198
|
-
if (script === SCRIPT_CLASS.complex) return
|
|
199
|
-
...style,
|
|
200
|
-
...resolveComplexScriptFormatting(style)
|
|
201
|
-
};
|
|
202
|
+
if (script === SCRIPT_CLASS.complex) return applyComplexScriptFormatting(style, style);
|
|
202
203
|
return style;
|
|
203
204
|
}
|
|
204
205
|
function measureMixedScriptWidth(measuredText, style) {
|
|
205
206
|
const letterSpacing = style.letterSpacing ?? 0;
|
|
206
|
-
const horizontalScale = getHorizontalScaleFactor(style);
|
|
207
|
+
const horizontalScale = getHorizontalScaleFactor(style.horizontalScale);
|
|
207
208
|
let glyphWidth = 0;
|
|
208
209
|
for (const segment of segmentByScript(measuredText)) glyphWidth += canvasMeasureTextWidth(segment.text, glyphAdvanceStyle(scriptStyle(style, segment.script)));
|
|
209
210
|
let width = glyphWidth;
|
|
@@ -262,10 +263,7 @@ function canvasMeasureText(text, style) {
|
|
|
262
263
|
* @returns Run measurement with width and per-character widths
|
|
263
264
|
*/
|
|
264
265
|
function canvasMeasureRun(text, sourceStyle) {
|
|
265
|
-
const style = sourceStyle.forceComplexScript ?
|
|
266
|
-
...sourceStyle,
|
|
267
|
-
...resolveComplexScriptFormatting(sourceStyle)
|
|
268
|
-
} : sourceStyle;
|
|
266
|
+
const style = sourceStyle.forceComplexScript ? applyComplexScriptFormatting(sourceStyle, sourceStyle) : sourceStyle;
|
|
269
267
|
const metrics = canvasGetFontMetrics(style);
|
|
270
268
|
if (!text) return {
|
|
271
269
|
width: 0,
|
|
@@ -278,11 +276,12 @@ function canvasMeasureRun(text, sourceStyle) {
|
|
|
278
276
|
ctx.fontKerning = style.kerning ? "normal" : "none";
|
|
279
277
|
const eastAsiaFont = style.eastAsiaFontFamily !== void 0 && !style.letterSpacing ? buildFontString({
|
|
280
278
|
...style,
|
|
281
|
-
fontFamily: style.eastAsiaFontFamily
|
|
279
|
+
fontFamily: style.eastAsiaFontFamily,
|
|
280
|
+
...style.eastAsiaAlternateFontFamily !== void 0 ? { alternateFontFamily: style.eastAsiaAlternateFontFamily } : {}
|
|
282
281
|
}) : void 0;
|
|
283
282
|
const complexScriptFont = hasComplexScriptFormatting(style) && !style.letterSpacing ? buildFontString(scriptStyle(style, SCRIPT_CLASS.complex)) : void 0;
|
|
284
283
|
const letterSpacing = style.letterSpacing ?? 0;
|
|
285
|
-
const scale = getHorizontalScaleFactor(style);
|
|
284
|
+
const scale = getHorizontalScaleFactor(style.horizontalScale);
|
|
286
285
|
const charWidths = [];
|
|
287
286
|
let totalWidth = 0;
|
|
288
287
|
let offset = 0;
|
|
@@ -329,8 +328,5 @@ function applyTextTransform(text, style) {
|
|
|
329
328
|
if (style.textTransform === "uppercase") return text.toLocaleUpperCase();
|
|
330
329
|
return text;
|
|
331
330
|
}
|
|
332
|
-
function getHorizontalScaleFactor(style) {
|
|
333
|
-
return (style.horizontalScale ?? 100) / 100;
|
|
334
|
-
}
|
|
335
331
|
//#endregion
|
|
336
332
|
export { canvasMeasureProvider, getCanvasContext, installCanvasMeasureProvider, resetCanvasContext };
|
|
@@ -21,7 +21,7 @@ type ResolvedFontCache = {
|
|
|
21
21
|
/**
|
|
22
22
|
* Get the resolved font data for a font family, with caching.
|
|
23
23
|
*/
|
|
24
|
-
declare function getResolvedData(fontFamily: string): ResolvedFontCache;
|
|
24
|
+
declare function getResolvedData(fontFamily: string, alternateFontFamily?: string): ResolvedFontCache;
|
|
25
25
|
/**
|
|
26
26
|
* Clear the resolved-font-family cache. `resolveFontFamily`'s output for a
|
|
27
27
|
* given key can change even when the raw font names don't — e.g. when the
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { resolveFontFamily } from "../../utils/fontResolver.js";
|
|
2
2
|
import "../../utils/fontWeights.js";
|
|
3
|
+
import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
|
|
3
4
|
import { FONT_KERNING_MODE, getRunFontKerningMode } from "./textMeasurementPolicy.js";
|
|
4
5
|
//#region src/layout-engine/measure/measureHelpers.ts
|
|
5
6
|
/**
|
|
@@ -28,10 +29,14 @@ const DOCX_SCRIPT_FONT_SCALE = .75;
|
|
|
28
29
|
function buildRunFontStyle(run, fallbackFontFamily, fallbackFontSize) {
|
|
29
30
|
const baseFontSize = run.fontSize ?? fallbackFontSize;
|
|
30
31
|
const fontSize = run.superscript || run.subscript ? baseFontSize * DOCX_SCRIPT_FONT_SCALE : baseFontSize;
|
|
32
|
+
const horizontalScale = normalizeHorizontalScalePercent(run.horizontalScale);
|
|
31
33
|
return {
|
|
32
34
|
fontFamily: run.fontFamily ?? fallbackFontFamily,
|
|
35
|
+
...run.alternateFontFamily !== void 0 ? { alternateFontFamily: run.alternateFontFamily } : {},
|
|
33
36
|
...run.eastAsiaFontFamily !== void 0 ? { eastAsiaFontFamily: run.eastAsiaFontFamily } : {},
|
|
37
|
+
...run.eastAsiaAlternateFontFamily !== void 0 ? { eastAsiaAlternateFontFamily: run.eastAsiaAlternateFontFamily } : {},
|
|
34
38
|
...run.complexScriptFontFamily !== void 0 ? { complexScriptFontFamily: run.complexScriptFontFamily } : {},
|
|
39
|
+
...run.complexScriptAlternateFontFamily !== void 0 ? { complexScriptAlternateFontFamily: run.complexScriptAlternateFontFamily } : {},
|
|
35
40
|
...run.complexScriptFontSize !== void 0 ? { complexScriptFontSize: run.complexScriptFontSize } : {},
|
|
36
41
|
...run.complexScriptBold !== void 0 ? { complexScriptBold: run.complexScriptBold } : {},
|
|
37
42
|
...run.complexScriptItalic !== void 0 ? { complexScriptItalic: run.complexScriptItalic } : {},
|
|
@@ -42,7 +47,7 @@ function buildRunFontStyle(run, fallbackFontFamily, fallbackFontSize) {
|
|
|
42
47
|
...run.letterSpacing !== void 0 ? { letterSpacing: run.letterSpacing } : {},
|
|
43
48
|
...run.allCaps ? { textTransform: "uppercase" } : {},
|
|
44
49
|
...run.smallCaps ? { fontVariant: "small-caps" } : {},
|
|
45
|
-
...
|
|
50
|
+
...horizontalScale !== void 0 ? { horizontalScale } : {},
|
|
46
51
|
kerning: getRunFontKerningMode(run, fallbackFontSize) === FONT_KERNING_MODE.enabled
|
|
47
52
|
};
|
|
48
53
|
}
|
|
@@ -51,23 +56,24 @@ const fontResolvedCache = /* @__PURE__ */ new Map();
|
|
|
51
56
|
/**
|
|
52
57
|
* Get the resolved font data for a font family, with caching.
|
|
53
58
|
*/
|
|
54
|
-
function getResolvedData(fontFamily) {
|
|
55
|
-
|
|
59
|
+
function getResolvedData(fontFamily, alternateFontFamily) {
|
|
60
|
+
const cacheKey = `${fontFamily}\u0000${alternateFontFamily ?? ""}`;
|
|
61
|
+
let cached = fontResolvedCache.get(cacheKey);
|
|
56
62
|
if (cached === void 0) {
|
|
57
|
-
const resolved = resolveFontFamily(fontFamily);
|
|
63
|
+
const resolved = resolveFontFamily(fontFamily, alternateFontFamily);
|
|
58
64
|
cached = {
|
|
59
65
|
cssFallback: resolved.cssFallback,
|
|
60
66
|
singleLineRatio: resolved.singleLineRatio
|
|
61
67
|
};
|
|
62
|
-
fontResolvedCache.set(
|
|
68
|
+
fontResolvedCache.set(cacheKey, cached);
|
|
63
69
|
}
|
|
64
70
|
return cached;
|
|
65
71
|
}
|
|
66
72
|
/**
|
|
67
73
|
* Get the CSS fallback string for a font family, with caching.
|
|
68
74
|
*/
|
|
69
|
-
function getResolvedFallback(fontFamily) {
|
|
70
|
-
return getResolvedData(fontFamily).cssFallback;
|
|
75
|
+
function getResolvedFallback(fontFamily, alternateFontFamily) {
|
|
76
|
+
return getResolvedData(fontFamily, alternateFontFamily).cssFallback;
|
|
71
77
|
}
|
|
72
78
|
/**
|
|
73
79
|
* Clear the resolved-font-family cache. `resolveFontFamily`'s output for a
|
|
@@ -102,7 +108,7 @@ function buildFontString(style) {
|
|
|
102
108
|
const fontSizePx = ptToPx(style.fontSize ?? 11);
|
|
103
109
|
parts.push(`${fontSizePx}px`);
|
|
104
110
|
const fontFamily = style.fontFamily ?? "Calibri";
|
|
105
|
-
parts.push(getResolvedFallback(fontFamily));
|
|
111
|
+
parts.push(getResolvedFallback(fontFamily, style.alternateFontFamily));
|
|
106
112
|
return parts.join(" ");
|
|
107
113
|
}
|
|
108
114
|
/**
|