oasis-editor 0.0.99 → 0.0.101
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/{OasisEditorApp-kxR9P2nm.js → OasisEditorApp-B421ezvO.js} +635 -112
- package/dist/assets/{importDocxWorker-BulqJDJj.js → importDocxWorker-DkjxuxwM.js} +1 -1
- package/dist/core/editorState.d.ts +1 -1
- package/dist/core/model/index.d.ts +1 -1
- package/dist/core/model/types/nodes.d.ts +19 -0
- package/dist/core/textStyleMappings.d.ts +10 -5
- package/dist/export/docx/text/blocksXml.d.ts +6 -0
- package/dist/export/pdf/OasisPdfWriter.d.ts +8 -1
- package/dist/export/pdf/writer/PdfContentStream.d.ts +19 -2
- package/dist/export/pdf/writer/PdfDocumentSerializer.d.ts +2 -1
- package/dist/export/pdf/writer/PdfShadingTable.d.ts +22 -0
- package/dist/export/pdf/writer/pdfPrimitives.d.ts +1 -0
- package/dist/export/pdf/writer/pdfTypes.d.ts +24 -0
- package/dist/import/docx/nestedBlocks.d.ts +14 -0
- package/dist/{index-CNuDp_SC.js → index-BPpHyg6q.js} +104 -27
- package/dist/oasis-editor.js +1 -1
- package/dist/oasis-editor.umd.cjs +4 -4
- package/dist/text/fonts/layout/OpenTypeLayouter.d.ts +18 -9
- package/dist/text/fonts/opentype/GposTable.d.ts +15 -0
- package/dist/text/fonts/opentype/GsubTable.d.ts +4 -3
- package/dist/text/fonts/opentype/otLayoutCommon.d.ts +38 -0
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { v as visitRun, a as assertNever, c as createSignal, b as createEditorStateFromDocument, d as createInitialEditorState, S as STANDARD_FONT_SIZES_PT, f as fontSizePxToPt, p as probeLocalFontFamilies, e as createEditorParagraphFromRuns, i as isInlineObjectRun, g as createEditorStyledRun, h as getParagraphLength, j as getParagraphText, k as getActiveZone, l as getDocumentSections, m as getActiveSectionIndex, n as getParagraphs, o as normalizeSelection, q as positionToParagraphOffset, r as paragraphOffsetToPosition, s as clampPosition, t as findParagraphIndex, u as createCollapsedSelection, w as isSelectionCollapsed, x as parseFontSizePtToPx, y as formatFontSizePt, z as createEditorParagraph, A as getBlockParagraphs, B as findParagraphTableLocation, C as buildTableCellLayout, P as PT_PER_PX, D as createEditorTableCell, E as createEditorTableRow, F as createEditorTable, G as underlineStyleToCssDecorationStyle, H as resolveImageSrc, I as listKindForTag, J as isParagraphTag, K as collectInlineRuns, L as parseParagraphStyle, M as getRunImage, N as InlineShell, O as BalloonShell, Q as DocumentShell, R as createMemo, T as buildCanvasLayoutSnapshot, U as getCaretRectFromSnapshot, V as getParagraphRectFromSnapshot, W as createComponent, X as CaretOverlay, Y as Show, Z as createRenderEffect, _ as style, $ as setAttribute, a0 as setStyleProperty, a1 as memo, a2 as template, a3 as useI18n, a4 as createEffect, a5 as insert, a6 as use, a7 as addEventListener, a8 as Dialog, a9 as delegateEvents, aa as className, ab as For, ac as UNDERLINE_STYLE_OPTIONS, ad as Tabs, ae as onMount, af as onCleanup, ag as PluginUiHost, ah as OasisEditorEditor, ai as OasisBrandMark, aj as setPreciseFontPreference, ak as setWelcomeSeen, al as enablePreciseFontMode, am as TWIPS_PER_POINT, an as PX_PER_INCH, ao as TWIPS_PER_INCH, ap as resolveEffectiveParagraphStyle, aq as resolveEffectiveTextStyleForParagraph, ar as EMU_PER_PX, as as EMU_PER_PT, at as getRunFootnoteReference, au as getRunEndnoteReference, av as iterateFootnoteReferenceRuns, aw as iterateEndnoteReferenceRuns, ax as imageContentTypeDefaults, ay as getRunFieldChar, az as getRunFieldInstruction, aA as createEditorRun, aB as JSZip, aC as imageExtensionFromMime, aD as pxToPt$1, aE as resolveFloatingObjectRect, aF as getTextBoxFloatingGeometry, aG as getPresetPathSegments, aH as projectBlocksLayout, aI as buildListLabels, aJ as getImageFloatingGeometry, aK as textStyleToFontSizePt, aL as PX_PER_POINT, aM as resolveOpenTypeFeatureTags, aN as DEFAULT_FONT_SIZE_PX, aO as isDoubleUnderlineStyle, aP as isWavyUnderlineStyle, aQ as underlineStyleLineWidthPx, aR as underlineStyleDashArray, aS as resolveListLabel, aT as getListLabelInset, aU as getAlignedListLabelInset, aV as getParagraphBorderInsets, aW as buildSegmentTable, aX as buildCanvasTableLayout, aY as resolveCanvasTableWidth, aZ as resolveFloatingTableRect, a_ as normalizeFamily, a$ as ROBOTO_FONT_FILES, b0 as loadFontAsset, b1 as OFFICE_COMPAT_FONT_FAMILIES, b2 as BinaryReader, b3 as buildSfnt, b4 as defaultFontDecoderRegistry, b5 as SfntFontProgram, b6 as collectPdfFontFamilies, b7 as projectDocumentLayout, b8 as getPageContentWidth, b9 as getPageHeaderZoneTop, ba as getPageBodyTop, bb as getPageColumnRects, bc as findFootnoteReference, bd as FOOTNOTE_MARKER_GUTTER_PX, be as resolveImporterForFile, bf as getDocumentSectionsCanonical, bg as getDocumentParagraphsCanonical, bh as getDocumentParagraphs, bi as getDocumentPageSettings, bj as getTableCellContentWidthForParagraph, bk as on, bl as debounce, bm as unwrap, bn as perfTimer, bo as getRunTextBox, bp as createEditorDocument, bq as resolveResizedDimensions, br as resolveTextBoxRenderHeight, bs as getToolbarStyleState, bt as getCachedCanvasImage, bu as measureParagraphMinContentWidthPx, bv as getEditableBlocksForZone, bw as findParagraphLocation, bx as createSectionBoundaryParagraph, by as normalizePageSettings, bz as DEFAULT_EDITOR_PAGE_SETTINGS, bA as markStart, bB as markEnd, bC as getParagraphEntries, bD as getParagraphById, bE as createEditorFootnote, bF as createFootnoteReferenceRun, bG as renumberFootnotes, bH as getFootnoteDisplayMarker, bI as getHeadingLevel, bJ as preciseFontModeVersion, bK as isPreciseFontModeEnabled, bL as resolveNamedTextStyle, bM as togglePreciseFontMode, bN as nextFontSizePt, bO as previousFontSizePt, bP as fontSizePtToPx, bQ as createDefaultToolbarPreset, bR as MenuRegistry, bS as createToolbarRegistry, bT as Editor, bU as resolveCommandRef, bV as commandRefName, bW as createOasisEditorClient, bX as createEditorZoom, bY as startLongTaskObserver, bZ as installGlobalReport, b_ as applyStoredPreciseFontPreference, b$ as getWelcomeSeen, c0 as isLocalFontAccessSupported, c1 as EDITOR_SCROLL_PADDING_PX, c2 as Toolbar, c3 as OasisEditorLoading, c4 as I18nProvider, c5 as createTranslator, c6 as createEditorLogger, c7 as registerDomStatsSurface } from "./index-
|
|
4
|
+
import { v as visitRun, a as assertNever, c as createSignal, b as createEditorStateFromDocument, d as createInitialEditorState, S as STANDARD_FONT_SIZES_PT, f as fontSizePxToPt, p as probeLocalFontFamilies, e as createEditorParagraphFromRuns, i as isInlineObjectRun, g as createEditorStyledRun, h as getParagraphLength, j as getParagraphText, k as getActiveZone, l as getDocumentSections, m as getActiveSectionIndex, n as getParagraphs, o as normalizeSelection, q as positionToParagraphOffset, r as paragraphOffsetToPosition, s as clampPosition, t as findParagraphIndex, u as createCollapsedSelection, w as isSelectionCollapsed, x as parseFontSizePtToPx, y as formatFontSizePt, z as createEditorParagraph, A as getBlockParagraphs, B as findParagraphTableLocation, C as buildTableCellLayout, P as PT_PER_PX, D as createEditorTableCell, E as createEditorTableRow, F as createEditorTable, G as underlineStyleToCssDecorationStyle, H as resolveImageSrc, I as listKindForTag, J as isParagraphTag, K as collectInlineRuns, L as parseParagraphStyle, M as getRunImage, N as InlineShell, O as BalloonShell, Q as DocumentShell, R as createMemo, T as buildCanvasLayoutSnapshot, U as getCaretRectFromSnapshot, V as getParagraphRectFromSnapshot, W as createComponent, X as CaretOverlay, Y as Show, Z as createRenderEffect, _ as style, $ as setAttribute, a0 as setStyleProperty, a1 as memo, a2 as template, a3 as useI18n, a4 as createEffect, a5 as insert, a6 as use, a7 as addEventListener, a8 as Dialog, a9 as delegateEvents, aa as className, ab as For, ac as UNDERLINE_STYLE_OPTIONS, ad as Tabs, ae as onMount, af as onCleanup, ag as PluginUiHost, ah as OasisEditorEditor, ai as OasisBrandMark, aj as setPreciseFontPreference, ak as setWelcomeSeen, al as enablePreciseFontMode, am as TWIPS_PER_POINT, an as PX_PER_INCH, ao as TWIPS_PER_INCH, ap as resolveEffectiveParagraphStyle, aq as resolveEffectiveTextStyleForParagraph, ar as EMU_PER_PX, as as EMU_PER_PT, at as getRunFootnoteReference, au as getRunEndnoteReference, av as iterateFootnoteReferenceRuns, aw as iterateEndnoteReferenceRuns, ax as imageContentTypeDefaults, ay as getRunFieldChar, az as getRunFieldInstruction, aA as createEditorRun, aB as JSZip, aC as imageExtensionFromMime, aD as pxToPt$1, aE as resolveFloatingObjectRect, aF as getTextBoxFloatingGeometry, aG as getPresetPathSegments, aH as projectBlocksLayout, aI as buildListLabels, aJ as getImageFloatingGeometry, aK as textStyleToFontSizePt, aL as PX_PER_POINT, aM as resolveOpenTypeFeatureTags, aN as DEFAULT_FONT_SIZE_PX, aO as isDoubleUnderlineStyle, aP as isWavyUnderlineStyle, aQ as underlineStyleLineWidthPx, aR as underlineStyleDashArray, aS as resolveListLabel, aT as getListLabelInset, aU as getAlignedListLabelInset, aV as getParagraphBorderInsets, aW as buildSegmentTable, aX as buildCanvasTableLayout, aY as resolveCanvasTableWidth, aZ as resolveFloatingTableRect, a_ as normalizeFamily, a$ as ROBOTO_FONT_FILES, b0 as loadFontAsset, b1 as OFFICE_COMPAT_FONT_FAMILIES, b2 as BinaryReader, b3 as buildSfnt, b4 as defaultFontDecoderRegistry, b5 as SfntFontProgram, b6 as collectPdfFontFamilies, b7 as projectDocumentLayout, b8 as getPageContentWidth, b9 as getPageHeaderZoneTop, ba as getPageBodyTop, bb as getPageColumnRects, bc as findFootnoteReference, bd as FOOTNOTE_MARKER_GUTTER_PX, be as resolveImporterForFile, bf as getDocumentSectionsCanonical, bg as getDocumentParagraphsCanonical, bh as getDocumentParagraphs, bi as getDocumentPageSettings, bj as getTableCellContentWidthForParagraph, bk as on, bl as debounce, bm as unwrap, bn as perfTimer, bo as getRunTextBox, bp as createEditorDocument, bq as resolveResizedDimensions, br as resolveTextBoxRenderHeight, bs as getToolbarStyleState, bt as getCachedCanvasImage, bu as measureParagraphMinContentWidthPx, bv as getEditableBlocksForZone, bw as findParagraphLocation, bx as createSectionBoundaryParagraph, by as normalizePageSettings, bz as DEFAULT_EDITOR_PAGE_SETTINGS, bA as markStart, bB as markEnd, bC as getParagraphEntries, bD as getParagraphById, bE as createEditorFootnote, bF as createFootnoteReferenceRun, bG as renumberFootnotes, bH as getFootnoteDisplayMarker, bI as getHeadingLevel, bJ as preciseFontModeVersion, bK as isPreciseFontModeEnabled, bL as resolveNamedTextStyle, bM as togglePreciseFontMode, bN as nextFontSizePt, bO as previousFontSizePt, bP as fontSizePtToPx, bQ as createDefaultToolbarPreset, bR as MenuRegistry, bS as createToolbarRegistry, bT as Editor, bU as resolveCommandRef, bV as commandRefName, bW as createOasisEditorClient, bX as createEditorZoom, bY as startLongTaskObserver, bZ as installGlobalReport, b_ as applyStoredPreciseFontPreference, b$ as getWelcomeSeen, c0 as isLocalFontAccessSupported, c1 as EDITOR_SCROLL_PADDING_PX, c2 as Toolbar, c3 as OasisEditorLoading, c4 as I18nProvider, c5 as createTranslator, c6 as createEditorLogger, c7 as registerDomStatsSurface } from "./index-BPpHyg6q.js";
|
|
5
5
|
function cloneStyle(style2) {
|
|
6
6
|
return style2 ? { ...style2 } : void 0;
|
|
7
7
|
}
|
|
@@ -34711,28 +34711,54 @@ function serializeRunsWithBoundaries(runs, tokens, context, paragraphStyleId, st
|
|
|
34711
34711
|
flushUpTo(Number.POSITIVE_INFINITY);
|
|
34712
34712
|
return out;
|
|
34713
34713
|
}
|
|
34714
|
+
function serializeSingleBlockXml(block, context, styles) {
|
|
34715
|
+
var _a;
|
|
34716
|
+
switch (block.type) {
|
|
34717
|
+
case "paragraph":
|
|
34718
|
+
return serializeParagraphXml(block, context, styles);
|
|
34719
|
+
case "table": {
|
|
34720
|
+
const pageBreakXml = ((_a = block.style) == null ? void 0 : _a.pageBreakBefore) ? '<w:p><w:r><w:br w:type="page"/></w:r></w:p>' : "";
|
|
34721
|
+
return pageBreakXml + serializeTableXml(
|
|
34722
|
+
block,
|
|
34723
|
+
(paragraph, cell) => {
|
|
34724
|
+
var _a2;
|
|
34725
|
+
return serializeParagraphXml(paragraph, context, styles, {
|
|
34726
|
+
align: (_a2 = cell.style) == null ? void 0 : _a2.horizontalAlign
|
|
34727
|
+
});
|
|
34728
|
+
}
|
|
34729
|
+
);
|
|
34730
|
+
}
|
|
34731
|
+
default:
|
|
34732
|
+
return assertNever(block, "block");
|
|
34733
|
+
}
|
|
34734
|
+
}
|
|
34714
34735
|
function serializeBlocksXml(blocks, context, styles) {
|
|
34715
|
-
|
|
34716
|
-
|
|
34717
|
-
|
|
34718
|
-
|
|
34719
|
-
|
|
34720
|
-
|
|
34721
|
-
|
|
34722
|
-
|
|
34723
|
-
|
|
34724
|
-
|
|
34725
|
-
var _a2;
|
|
34726
|
-
return serializeParagraphXml(paragraph, context, styles, {
|
|
34727
|
-
align: (_a2 = cell.style) == null ? void 0 : _a2.horizontalAlign
|
|
34728
|
-
});
|
|
34729
|
-
}
|
|
34730
|
-
);
|
|
34731
|
-
}
|
|
34732
|
-
default:
|
|
34733
|
-
return assertNever(block, "block");
|
|
34736
|
+
var _a, _b, _c;
|
|
34737
|
+
let out = "";
|
|
34738
|
+
let i = 0;
|
|
34739
|
+
while (i < blocks.length) {
|
|
34740
|
+
const block = blocks[i];
|
|
34741
|
+
const wrapper = (_a = block.sdtWrappers) == null ? void 0 : _a[0];
|
|
34742
|
+
if (!wrapper) {
|
|
34743
|
+
out += serializeSingleBlockXml(block, context, styles);
|
|
34744
|
+
i += 1;
|
|
34745
|
+
continue;
|
|
34734
34746
|
}
|
|
34735
|
-
|
|
34747
|
+
const group = [];
|
|
34748
|
+
let j = i;
|
|
34749
|
+
while (j < blocks.length && ((_c = (_b = blocks[j].sdtWrappers) == null ? void 0 : _b[0]) == null ? void 0 : _c.groupId) === wrapper.groupId) {
|
|
34750
|
+
const rest = blocks[j].sdtWrappers.slice(1);
|
|
34751
|
+
group.push({
|
|
34752
|
+
...blocks[j],
|
|
34753
|
+
sdtWrappers: rest.length > 0 ? rest : void 0
|
|
34754
|
+
});
|
|
34755
|
+
j += 1;
|
|
34756
|
+
}
|
|
34757
|
+
const inner = serializeBlocksXml(group, context, styles);
|
|
34758
|
+
out += `<w:sdt>${wrapper.sdtPrXml}${wrapper.sdtEndPrXml ?? ""}<w:sdtContent>${inner}</w:sdtContent></w:sdt>`;
|
|
34759
|
+
i = j;
|
|
34760
|
+
}
|
|
34761
|
+
return out;
|
|
34736
34762
|
}
|
|
34737
34763
|
function serializeParagraphXml(paragraph, context, styles, overrides) {
|
|
34738
34764
|
var _a, _b, _c;
|
|
@@ -36356,6 +36382,39 @@ function drawFragmentShading(writer, pageIndex, line, fragment, originX, originY
|
|
|
36356
36382
|
fill: styles.shading
|
|
36357
36383
|
});
|
|
36358
36384
|
}
|
|
36385
|
+
function resolveGradientShadingName(writer, pageIndex, line, fragment, originX, originY, styles) {
|
|
36386
|
+
const fill = styles.textFill;
|
|
36387
|
+
if (!fill || fill.type !== "gradient" || fill.stops.length < 2) {
|
|
36388
|
+
return void 0;
|
|
36389
|
+
}
|
|
36390
|
+
const bounds = resolveFragmentBounds(
|
|
36391
|
+
line,
|
|
36392
|
+
fragment,
|
|
36393
|
+
styles.fontSize ?? DEFAULT_FONT_SIZE_PX
|
|
36394
|
+
);
|
|
36395
|
+
if (!bounds) {
|
|
36396
|
+
return void 0;
|
|
36397
|
+
}
|
|
36398
|
+
const x0px = originX + bounds.left;
|
|
36399
|
+
const x1px = originX + bounds.right;
|
|
36400
|
+
const y0px = originY + line.top;
|
|
36401
|
+
const y1px = originY + line.top + line.height;
|
|
36402
|
+
const cx = (x0px + x1px) / 2;
|
|
36403
|
+
const cy = (y0px + y1px) / 2;
|
|
36404
|
+
const rad = (fill.angle ?? 0) * Math.PI / 180;
|
|
36405
|
+
const dx = Math.cos(rad) * (x1px - x0px) / 2;
|
|
36406
|
+
const dy = Math.sin(rad) * (y1px - y0px) / 2;
|
|
36407
|
+
return writer.registerAxialGradient(pageIndex, {
|
|
36408
|
+
x0: pxToPt$1(cx - dx),
|
|
36409
|
+
y0: pxToPt$1(cy - dy),
|
|
36410
|
+
x1: pxToPt$1(cx + dx),
|
|
36411
|
+
y1: pxToPt$1(cy + dy),
|
|
36412
|
+
stops: fill.stops.map((stop) => ({
|
|
36413
|
+
offset: stop.position,
|
|
36414
|
+
color: stop.color
|
|
36415
|
+
}))
|
|
36416
|
+
}) ?? void 0;
|
|
36417
|
+
}
|
|
36359
36418
|
function drawFragmentBorder(writer, pageIndex, line, fragment, originX, originY, styles) {
|
|
36360
36419
|
const border = styles.textBorder;
|
|
36361
36420
|
if (!border || border.type === "none" || border.width <= 0) {
|
|
@@ -36714,7 +36773,10 @@ async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, do
|
|
|
36714
36773
|
styles.color ?? "#000000"
|
|
36715
36774
|
);
|
|
36716
36775
|
const paragraphAlign = resolveEffectiveParagraphStyle(paragraph.style, document2.styles).align ?? "left";
|
|
36717
|
-
const fontFeatures = resolveOpenTypeFeatureTags(
|
|
36776
|
+
const fontFeatures = resolveOpenTypeFeatureTags(
|
|
36777
|
+
styles,
|
|
36778
|
+
textStyleToFontSizePt(styles)
|
|
36779
|
+
);
|
|
36718
36780
|
const baseTextOptions = {
|
|
36719
36781
|
fontSize: fontSizePt,
|
|
36720
36782
|
bold: styles.bold,
|
|
@@ -36725,6 +36787,15 @@ async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, do
|
|
|
36725
36787
|
fontFeatures
|
|
36726
36788
|
};
|
|
36727
36789
|
const mainColor = ((_b = styles.textFill) == null ? void 0 : _b.type) === "solid" ? styles.textFill.color : ((_c = styles.textFill) == null ? void 0 : _c.type) === "gradient" && styles.textFill.stops[0] ? styles.textFill.stops[0].color : styles.color ?? "#000000";
|
|
36790
|
+
const gradientShadingName = resolveGradientShadingName(
|
|
36791
|
+
writer,
|
|
36792
|
+
pageIndex,
|
|
36793
|
+
line,
|
|
36794
|
+
fragment,
|
|
36795
|
+
originX,
|
|
36796
|
+
originY,
|
|
36797
|
+
styles
|
|
36798
|
+
);
|
|
36728
36799
|
const offsetPt = pxToPt$1(1);
|
|
36729
36800
|
const emitChunk = (leftPx, text2) => {
|
|
36730
36801
|
if (styles.emboss || styles.imprint) {
|
|
@@ -36800,7 +36871,9 @@ async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, do
|
|
|
36800
36871
|
y: pxToPt$1(baselineY),
|
|
36801
36872
|
text: text2,
|
|
36802
36873
|
color: mainColor,
|
|
36803
|
-
|
|
36874
|
+
// A gradient fill paints the glyphs via the shading clip; it supersedes
|
|
36875
|
+
// both the solid color and any outline/stroke render mode.
|
|
36876
|
+
...gradientShadingName ? { gradientShadingName } : textOutline ? {
|
|
36804
36877
|
renderMode: 2,
|
|
36805
36878
|
strokeColor: textOutline.color ?? mainColor,
|
|
36806
36879
|
strokeWidth: textOutline.widthPt
|
|
@@ -37631,10 +37704,27 @@ function textMarkerComment(value) {
|
|
|
37631
37704
|
return `% OasisText ${encodePdfUtf16Hex(codePoints)}`;
|
|
37632
37705
|
}
|
|
37633
37706
|
class PdfContentStream {
|
|
37634
|
-
constructor(page, fonts, images) {
|
|
37707
|
+
constructor(page, fonts, images, shadings) {
|
|
37635
37708
|
this.page = page;
|
|
37636
37709
|
this.fonts = fonts;
|
|
37637
37710
|
this.images = images;
|
|
37711
|
+
this.shadings = shadings;
|
|
37712
|
+
}
|
|
37713
|
+
/**
|
|
37714
|
+
* Registers an axial gradient for use as a glyph fill on this page. Coordinates
|
|
37715
|
+
* come in the writer's top-left point space and are flipped to PDF bottom-left
|
|
37716
|
+
* space here; the returned name is referenced via `OasisPdfTextOptions`.
|
|
37717
|
+
*/
|
|
37718
|
+
registerAxialGradient(gradient) {
|
|
37719
|
+
const name = this.shadings.register({
|
|
37720
|
+
x0: gradient.x0,
|
|
37721
|
+
y0: this.page.height - gradient.y0,
|
|
37722
|
+
x1: gradient.x1,
|
|
37723
|
+
y1: this.page.height - gradient.y1,
|
|
37724
|
+
stops: gradient.stops
|
|
37725
|
+
});
|
|
37726
|
+
this.page.shadingResourceNames.add(name);
|
|
37727
|
+
return name;
|
|
37638
37728
|
}
|
|
37639
37729
|
drawRect(options) {
|
|
37640
37730
|
const page = this.page;
|
|
@@ -37792,8 +37882,24 @@ class PdfContentStream {
|
|
|
37792
37882
|
if (showCommand === null) {
|
|
37793
37883
|
return;
|
|
37794
37884
|
}
|
|
37885
|
+
if (options.gradientShadingName) {
|
|
37886
|
+
this.emitGradientTextBlock(
|
|
37887
|
+
fontResourceName,
|
|
37888
|
+
showCommand,
|
|
37889
|
+
options,
|
|
37890
|
+
options.gradientShadingName
|
|
37891
|
+
);
|
|
37892
|
+
return;
|
|
37893
|
+
}
|
|
37795
37894
|
this.emitTextBlock(fontResourceName, showCommand, options);
|
|
37796
37895
|
}
|
|
37896
|
+
textSetupCommands(fontResourceName, options) {
|
|
37897
|
+
return [
|
|
37898
|
+
`/${fontResourceName} ${formatNumber(options.fontSize ?? 12)} Tf`,
|
|
37899
|
+
...options.horizontalScale && options.horizontalScale > 0 && options.horizontalScale !== 100 ? [`${formatNumber(options.horizontalScale)} Tz`] : [],
|
|
37900
|
+
...options.characterSpacing && options.characterSpacing !== 0 ? [`${formatNumber(options.characterSpacing)} Tc`] : []
|
|
37901
|
+
];
|
|
37902
|
+
}
|
|
37797
37903
|
emitTextBlock(fontResourceName, showCommand, options) {
|
|
37798
37904
|
const page = this.page;
|
|
37799
37905
|
page.commands.push(
|
|
@@ -37801,7 +37907,6 @@ class PdfContentStream {
|
|
|
37801
37907
|
textMarkerComment(options.text),
|
|
37802
37908
|
"BT",
|
|
37803
37909
|
colorCommand(options.color, "rg", [0, 0, 0]),
|
|
37804
|
-
`/${fontResourceName} ${formatNumber(options.fontSize ?? 12)} Tf`,
|
|
37805
37910
|
...options.renderMode && options.renderMode !== 0 ? [
|
|
37806
37911
|
colorCommand(
|
|
37807
37912
|
options.strokeColor ?? options.color,
|
|
@@ -37813,14 +37918,37 @@ class PdfContentStream {
|
|
|
37813
37918
|
)} w`,
|
|
37814
37919
|
`${options.renderMode} Tr`
|
|
37815
37920
|
] : [],
|
|
37816
|
-
...
|
|
37817
|
-
...options.characterSpacing && options.characterSpacing !== 0 ? [`${formatNumber(options.characterSpacing)} Tc`] : [],
|
|
37921
|
+
...this.textSetupCommands(fontResourceName, options),
|
|
37818
37922
|
`${formatNumber(options.x)} ${formatNumber(page.height - options.y)} Td`,
|
|
37819
37923
|
showCommand,
|
|
37820
37924
|
"ET"
|
|
37821
37925
|
].join("\n")
|
|
37822
37926
|
);
|
|
37823
37927
|
}
|
|
37928
|
+
/**
|
|
37929
|
+
* Fills glyphs with an axial gradient: the text is drawn in clip render mode
|
|
37930
|
+
* (`7 Tr`) so the glyph outlines become the clip path, then the shading is
|
|
37931
|
+
* painted through them with `sh`. The whole sequence is isolated in a
|
|
37932
|
+
* `q … Q` pair so the clip does not leak. Outline/stroke is not combined with
|
|
37933
|
+
* gradient fill (the gradient supersedes it).
|
|
37934
|
+
*/
|
|
37935
|
+
emitGradientTextBlock(fontResourceName, showCommand, options, shadingName) {
|
|
37936
|
+
const page = this.page;
|
|
37937
|
+
page.commands.push(
|
|
37938
|
+
[
|
|
37939
|
+
textMarkerComment(options.text),
|
|
37940
|
+
"q",
|
|
37941
|
+
"BT",
|
|
37942
|
+
...this.textSetupCommands(fontResourceName, options),
|
|
37943
|
+
"7 Tr",
|
|
37944
|
+
`${formatNumber(options.x)} ${formatNumber(page.height - options.y)} Td`,
|
|
37945
|
+
showCommand,
|
|
37946
|
+
"ET",
|
|
37947
|
+
`/${shadingName} sh`,
|
|
37948
|
+
"Q"
|
|
37949
|
+
].join("\n")
|
|
37950
|
+
);
|
|
37951
|
+
}
|
|
37824
37952
|
drawImage(options) {
|
|
37825
37953
|
const page = this.page;
|
|
37826
37954
|
if (options.width <= 0 || options.height <= 0 || !this.images.has(options.resourceName)) {
|
|
@@ -37875,9 +38003,6 @@ class PdfContentStream {
|
|
|
37875
38003
|
);
|
|
37876
38004
|
}
|
|
37877
38005
|
}
|
|
37878
|
-
function readTag(reader) {
|
|
37879
|
-
return reader.tag();
|
|
37880
|
-
}
|
|
37881
38006
|
function parseCoverage(reader, offset) {
|
|
37882
38007
|
reader.seek(offset);
|
|
37883
38008
|
const format = reader.u16();
|
|
@@ -37944,6 +38069,83 @@ function parseClassDef(reader, offset) {
|
|
|
37944
38069
|
}
|
|
37945
38070
|
return () => 0;
|
|
37946
38071
|
}
|
|
38072
|
+
function parseFeatureList(reader, featureListOffset) {
|
|
38073
|
+
reader.seek(featureListOffset);
|
|
38074
|
+
const featureCount = reader.u16();
|
|
38075
|
+
const records = [];
|
|
38076
|
+
for (let i = 0; i < featureCount; i += 1) {
|
|
38077
|
+
const tag = reader.tag();
|
|
38078
|
+
const offset = featureListOffset + reader.u16();
|
|
38079
|
+
records.push({ tag, offset });
|
|
38080
|
+
}
|
|
38081
|
+
return records.map(({ tag, offset }) => {
|
|
38082
|
+
reader.seek(offset);
|
|
38083
|
+
reader.skip(2);
|
|
38084
|
+
const lookupIndexCount = reader.u16();
|
|
38085
|
+
const lookupIndices = new Array(lookupIndexCount);
|
|
38086
|
+
for (let i = 0; i < lookupIndexCount; i += 1) {
|
|
38087
|
+
lookupIndices[i] = reader.u16();
|
|
38088
|
+
}
|
|
38089
|
+
return { tag, lookupIndices };
|
|
38090
|
+
});
|
|
38091
|
+
}
|
|
38092
|
+
function parseScriptList(reader, scriptListOffset) {
|
|
38093
|
+
reader.seek(scriptListOffset);
|
|
38094
|
+
const scriptCount = reader.u16();
|
|
38095
|
+
const scripts = [];
|
|
38096
|
+
for (let i = 0; i < scriptCount; i += 1) {
|
|
38097
|
+
const tag = reader.tag();
|
|
38098
|
+
const offset = scriptListOffset + reader.u16();
|
|
38099
|
+
scripts.push({ tag, offset });
|
|
38100
|
+
}
|
|
38101
|
+
if (scripts.length === 0) return [];
|
|
38102
|
+
const chosen = scripts.find((s) => s.tag === "latn") ?? scripts.find((s) => s.tag === "DFLT") ?? scripts[0];
|
|
38103
|
+
reader.seek(chosen.offset);
|
|
38104
|
+
const defaultLangSysOffset = reader.u16();
|
|
38105
|
+
if (defaultLangSysOffset === 0) return [];
|
|
38106
|
+
reader.seek(chosen.offset + defaultLangSysOffset);
|
|
38107
|
+
reader.skip(2);
|
|
38108
|
+
const requiredFeatureIndex = reader.u16();
|
|
38109
|
+
const featureIndexCount = reader.u16();
|
|
38110
|
+
const featureIndices = [];
|
|
38111
|
+
if (requiredFeatureIndex !== 65535) {
|
|
38112
|
+
featureIndices.push(requiredFeatureIndex);
|
|
38113
|
+
}
|
|
38114
|
+
for (let i = 0; i < featureIndexCount; i += 1) {
|
|
38115
|
+
featureIndices.push(reader.u16());
|
|
38116
|
+
}
|
|
38117
|
+
return featureIndices;
|
|
38118
|
+
}
|
|
38119
|
+
function parseLayoutTableHeader(reader) {
|
|
38120
|
+
reader.seek(0);
|
|
38121
|
+
reader.skip(2);
|
|
38122
|
+
reader.skip(2);
|
|
38123
|
+
const scriptListOffset = reader.u16();
|
|
38124
|
+
const featureListOffset = reader.u16();
|
|
38125
|
+
const lookupListOffset = reader.u16();
|
|
38126
|
+
const featureRecords = parseFeatureList(reader, featureListOffset);
|
|
38127
|
+
const activeFeatureIndices = parseScriptList(reader, scriptListOffset);
|
|
38128
|
+
const featureToLookups = /* @__PURE__ */ new Map();
|
|
38129
|
+
for (const featureIndex of activeFeatureIndices) {
|
|
38130
|
+
const record = featureRecords[featureIndex];
|
|
38131
|
+
if (!record) continue;
|
|
38132
|
+
const existing = featureToLookups.get(record.tag) ?? [];
|
|
38133
|
+
for (const lookupIndex of record.lookupIndices) {
|
|
38134
|
+
if (!existing.includes(lookupIndex)) existing.push(lookupIndex);
|
|
38135
|
+
}
|
|
38136
|
+
featureToLookups.set(record.tag, existing);
|
|
38137
|
+
}
|
|
38138
|
+
return { featureToLookups, lookupListOffset };
|
|
38139
|
+
}
|
|
38140
|
+
function collectLookupIndices(featureToLookups, tags) {
|
|
38141
|
+
const indices = /* @__PURE__ */ new Set();
|
|
38142
|
+
for (const tag of tags) {
|
|
38143
|
+
for (const lookupIndex of featureToLookups.get(tag) ?? []) {
|
|
38144
|
+
indices.add(lookupIndex);
|
|
38145
|
+
}
|
|
38146
|
+
}
|
|
38147
|
+
return Array.from(indices).sort((a, b) => a - b);
|
|
38148
|
+
}
|
|
37947
38149
|
function parseSingleSubst(reader, offset) {
|
|
37948
38150
|
reader.seek(offset);
|
|
37949
38151
|
const format = reader.u16();
|
|
@@ -38293,7 +38495,7 @@ function applyChainRules(rules, glyphs, pos, engine, resolver) {
|
|
|
38293
38495
|
}
|
|
38294
38496
|
return null;
|
|
38295
38497
|
}
|
|
38296
|
-
function parseSubtable(reader, offset, lookupType) {
|
|
38498
|
+
function parseSubtable$1(reader, offset, lookupType) {
|
|
38297
38499
|
switch (lookupType) {
|
|
38298
38500
|
case 1:
|
|
38299
38501
|
return parseSingleSubst(reader, offset);
|
|
@@ -38311,7 +38513,7 @@ function parseSubtable(reader, offset, lookupType) {
|
|
|
38311
38513
|
if (format !== 1) return null;
|
|
38312
38514
|
const extensionType = reader.u16();
|
|
38313
38515
|
const extensionOffset = offset + reader.u32();
|
|
38314
|
-
return parseSubtable(reader, extensionOffset, extensionType);
|
|
38516
|
+
return parseSubtable$1(reader, extensionOffset, extensionType);
|
|
38315
38517
|
}
|
|
38316
38518
|
default:
|
|
38317
38519
|
return null;
|
|
@@ -38326,25 +38528,8 @@ class GsubTable {
|
|
|
38326
38528
|
static parse(bytes) {
|
|
38327
38529
|
try {
|
|
38328
38530
|
const reader = new BinaryReader(bytes);
|
|
38329
|
-
reader
|
|
38330
|
-
reader
|
|
38331
|
-
reader.skip(2);
|
|
38332
|
-
const scriptListOffset = reader.u16();
|
|
38333
|
-
const featureListOffset = reader.u16();
|
|
38334
|
-
const lookupListOffset = reader.u16();
|
|
38335
|
-
const featureRecords = parseFeatureList(reader, featureListOffset);
|
|
38336
|
-
const activeFeatureIndices = parseScriptList(reader, scriptListOffset);
|
|
38337
|
-
const lookups = parseLookupList(reader, lookupListOffset);
|
|
38338
|
-
const featureToLookups = /* @__PURE__ */ new Map();
|
|
38339
|
-
for (const featureIndex of activeFeatureIndices) {
|
|
38340
|
-
const record = featureRecords[featureIndex];
|
|
38341
|
-
if (!record) continue;
|
|
38342
|
-
const existing = featureToLookups.get(record.tag) ?? [];
|
|
38343
|
-
for (const lookupIndex of record.lookupIndices) {
|
|
38344
|
-
if (!existing.includes(lookupIndex)) existing.push(lookupIndex);
|
|
38345
|
-
}
|
|
38346
|
-
featureToLookups.set(record.tag, existing);
|
|
38347
|
-
}
|
|
38531
|
+
const { featureToLookups, lookupListOffset } = parseLayoutTableHeader(reader);
|
|
38532
|
+
const lookups = parseLookupList$1(reader, lookupListOffset);
|
|
38348
38533
|
return new GsubTable(lookups, featureToLookups);
|
|
38349
38534
|
} catch {
|
|
38350
38535
|
return null;
|
|
@@ -38356,13 +38541,7 @@ class GsubTable {
|
|
|
38356
38541
|
}
|
|
38357
38542
|
/** Ordered (ascending) unique lookup indices referenced by the given tags. */
|
|
38358
38543
|
collectLookupIndices(tags) {
|
|
38359
|
-
|
|
38360
|
-
for (const tag of tags) {
|
|
38361
|
-
for (const lookupIndex of this.featureToLookups.get(tag) ?? []) {
|
|
38362
|
-
indices.add(lookupIndex);
|
|
38363
|
-
}
|
|
38364
|
-
}
|
|
38365
|
-
return Array.from(indices).sort((a, b) => a - b);
|
|
38544
|
+
return collectLookupIndices(this.featureToLookups, tags);
|
|
38366
38545
|
}
|
|
38367
38546
|
/**
|
|
38368
38547
|
* Applies one lookup (by index) at a single position. Tries each subtable in
|
|
@@ -38391,52 +38570,214 @@ class GsubTable {
|
|
|
38391
38570
|
}
|
|
38392
38571
|
}
|
|
38393
38572
|
}
|
|
38394
|
-
function
|
|
38395
|
-
reader.seek(
|
|
38396
|
-
const
|
|
38397
|
-
const
|
|
38398
|
-
for (let i = 0; i <
|
|
38399
|
-
|
|
38400
|
-
const offset = featureListOffset + reader.u16();
|
|
38401
|
-
records.push({ tag, offset });
|
|
38573
|
+
function parseLookupList$1(reader, lookupListOffset) {
|
|
38574
|
+
reader.seek(lookupListOffset);
|
|
38575
|
+
const lookupCount = reader.u16();
|
|
38576
|
+
const lookupOffsets = new Array(lookupCount);
|
|
38577
|
+
for (let i = 0; i < lookupCount; i += 1) {
|
|
38578
|
+
lookupOffsets[i] = lookupListOffset + reader.u16();
|
|
38402
38579
|
}
|
|
38403
|
-
return
|
|
38404
|
-
reader.seek(
|
|
38580
|
+
return lookupOffsets.map((lookupOffset) => {
|
|
38581
|
+
reader.seek(lookupOffset);
|
|
38582
|
+
const lookupType = reader.u16();
|
|
38405
38583
|
reader.skip(2);
|
|
38406
|
-
const
|
|
38407
|
-
const
|
|
38408
|
-
for (let i = 0; i <
|
|
38409
|
-
|
|
38584
|
+
const subTableCount = reader.u16();
|
|
38585
|
+
const subtableOffsets = new Array(subTableCount);
|
|
38586
|
+
for (let i = 0; i < subTableCount; i += 1) {
|
|
38587
|
+
subtableOffsets[i] = lookupOffset + reader.u16();
|
|
38410
38588
|
}
|
|
38411
|
-
|
|
38589
|
+
const subtables = [];
|
|
38590
|
+
for (const subtableOffset of subtableOffsets) {
|
|
38591
|
+
try {
|
|
38592
|
+
const subtable = parseSubtable$1(reader, subtableOffset, lookupType);
|
|
38593
|
+
if (subtable) subtables.push(subtable);
|
|
38594
|
+
} catch {
|
|
38595
|
+
}
|
|
38596
|
+
}
|
|
38597
|
+
return { lookupType, subtables };
|
|
38412
38598
|
});
|
|
38413
38599
|
}
|
|
38414
|
-
|
|
38415
|
-
|
|
38416
|
-
|
|
38417
|
-
|
|
38418
|
-
|
|
38419
|
-
|
|
38420
|
-
|
|
38421
|
-
|
|
38600
|
+
const X_PLACEMENT = 1;
|
|
38601
|
+
const Y_PLACEMENT = 2;
|
|
38602
|
+
const X_ADVANCE = 4;
|
|
38603
|
+
const Y_ADVANCE = 8;
|
|
38604
|
+
const X_PLACEMENT_DEVICE = 16;
|
|
38605
|
+
const Y_PLACEMENT_DEVICE = 32;
|
|
38606
|
+
const X_ADVANCE_DEVICE = 64;
|
|
38607
|
+
const Y_ADVANCE_DEVICE = 128;
|
|
38608
|
+
function readValueRecordXAdvance(reader, valueFormat) {
|
|
38609
|
+
let xAdvance = 0;
|
|
38610
|
+
if (valueFormat & X_PLACEMENT) reader.i16();
|
|
38611
|
+
if (valueFormat & Y_PLACEMENT) reader.i16();
|
|
38612
|
+
if (valueFormat & X_ADVANCE) xAdvance = reader.i16();
|
|
38613
|
+
if (valueFormat & Y_ADVANCE) reader.i16();
|
|
38614
|
+
if (valueFormat & X_PLACEMENT_DEVICE) reader.u16();
|
|
38615
|
+
if (valueFormat & Y_PLACEMENT_DEVICE) reader.u16();
|
|
38616
|
+
if (valueFormat & X_ADVANCE_DEVICE) reader.u16();
|
|
38617
|
+
if (valueFormat & Y_ADVANCE_DEVICE) reader.u16();
|
|
38618
|
+
return xAdvance;
|
|
38619
|
+
}
|
|
38620
|
+
function valueRecordSize(valueFormat) {
|
|
38621
|
+
let count = 0;
|
|
38622
|
+
for (let bit = 0; bit < 8; bit += 1) {
|
|
38623
|
+
if (valueFormat & 1 << bit) count += 1;
|
|
38624
|
+
}
|
|
38625
|
+
return count * 2;
|
|
38626
|
+
}
|
|
38627
|
+
function parseSinglePos(reader, offset) {
|
|
38628
|
+
reader.seek(offset);
|
|
38629
|
+
const format = reader.u16();
|
|
38630
|
+
const coverageOffset = offset + reader.u16();
|
|
38631
|
+
if (format === 1) {
|
|
38632
|
+
const valueFormat = reader.u16();
|
|
38633
|
+
const xAdvance = readValueRecordXAdvance(reader, valueFormat);
|
|
38634
|
+
const coverage = parseCoverage(reader, coverageOffset);
|
|
38635
|
+
if (xAdvance === 0) return null;
|
|
38636
|
+
return {
|
|
38637
|
+
apply(glyphIds, advances, pos) {
|
|
38638
|
+
if (coverage(glyphIds[pos]) < 0) return null;
|
|
38639
|
+
advances[pos] += xAdvance;
|
|
38640
|
+
return 1;
|
|
38641
|
+
}
|
|
38642
|
+
};
|
|
38422
38643
|
}
|
|
38423
|
-
if (
|
|
38424
|
-
|
|
38425
|
-
|
|
38426
|
-
|
|
38427
|
-
|
|
38428
|
-
|
|
38429
|
-
|
|
38430
|
-
|
|
38431
|
-
|
|
38432
|
-
|
|
38433
|
-
|
|
38434
|
-
|
|
38644
|
+
if (format === 2) {
|
|
38645
|
+
const valueFormat = reader.u16();
|
|
38646
|
+
const valueCount = reader.u16();
|
|
38647
|
+
const recordSize = valueRecordSize(valueFormat);
|
|
38648
|
+
const recordsStart = reader.tell();
|
|
38649
|
+
const xAdvances = new Array(valueCount);
|
|
38650
|
+
for (let i = 0; i < valueCount; i += 1) {
|
|
38651
|
+
reader.seek(recordsStart + i * recordSize);
|
|
38652
|
+
xAdvances[i] = readValueRecordXAdvance(reader, valueFormat);
|
|
38653
|
+
}
|
|
38654
|
+
const coverage = parseCoverage(reader, coverageOffset);
|
|
38655
|
+
return {
|
|
38656
|
+
apply(glyphIds, advances, pos) {
|
|
38657
|
+
const index = coverage(glyphIds[pos]);
|
|
38658
|
+
if (index < 0 || index >= valueCount) return null;
|
|
38659
|
+
const delta = xAdvances[index];
|
|
38660
|
+
if (delta === 0) return null;
|
|
38661
|
+
advances[pos] += delta;
|
|
38662
|
+
return 1;
|
|
38663
|
+
}
|
|
38664
|
+
};
|
|
38435
38665
|
}
|
|
38436
|
-
|
|
38437
|
-
|
|
38666
|
+
return null;
|
|
38667
|
+
}
|
|
38668
|
+
function parsePairPos(reader, offset) {
|
|
38669
|
+
reader.seek(offset);
|
|
38670
|
+
const format = reader.u16();
|
|
38671
|
+
const coverageOffset = offset + reader.u16();
|
|
38672
|
+
const valueFormat1 = reader.u16();
|
|
38673
|
+
const valueFormat2 = reader.u16();
|
|
38674
|
+
const hasSecondAdjustment = (valueFormat2 & X_ADVANCE) !== 0;
|
|
38675
|
+
if (format === 1) {
|
|
38676
|
+
const pairSetCount = reader.u16();
|
|
38677
|
+
const pairSetOffsets = new Array(pairSetCount);
|
|
38678
|
+
for (let i = 0; i < pairSetCount; i += 1) {
|
|
38679
|
+
pairSetOffsets[i] = offset + reader.u16();
|
|
38680
|
+
}
|
|
38681
|
+
const pairSets = pairSetOffsets.map(
|
|
38682
|
+
(setOffset) => {
|
|
38683
|
+
reader.seek(setOffset);
|
|
38684
|
+
const pairValueCount = reader.u16();
|
|
38685
|
+
const pairs = /* @__PURE__ */ new Map();
|
|
38686
|
+
for (let i = 0; i < pairValueCount; i += 1) {
|
|
38687
|
+
const secondGlyph = reader.u16();
|
|
38688
|
+
const value1XAdvance = readValueRecordXAdvance(reader, valueFormat1);
|
|
38689
|
+
const value2XAdvance = readValueRecordXAdvance(reader, valueFormat2);
|
|
38690
|
+
pairs.set(secondGlyph, {
|
|
38691
|
+
secondGlyph,
|
|
38692
|
+
value1XAdvance,
|
|
38693
|
+
value2XAdvance
|
|
38694
|
+
});
|
|
38695
|
+
}
|
|
38696
|
+
return pairs;
|
|
38697
|
+
}
|
|
38698
|
+
);
|
|
38699
|
+
const coverage = parseCoverage(reader, coverageOffset);
|
|
38700
|
+
return {
|
|
38701
|
+
apply(glyphIds, advances, pos) {
|
|
38702
|
+
const second = glyphIds[pos + 1];
|
|
38703
|
+
if (second === void 0) return null;
|
|
38704
|
+
const setIndex = coverage(glyphIds[pos]);
|
|
38705
|
+
if (setIndex < 0 || setIndex >= pairSets.length) return null;
|
|
38706
|
+
const pair = pairSets[setIndex].get(second);
|
|
38707
|
+
if (!pair) return null;
|
|
38708
|
+
advances[pos] += pair.value1XAdvance;
|
|
38709
|
+
advances[pos + 1] += pair.value2XAdvance;
|
|
38710
|
+
return hasSecondAdjustment ? 2 : 1;
|
|
38711
|
+
}
|
|
38712
|
+
};
|
|
38713
|
+
}
|
|
38714
|
+
if (format === 2) {
|
|
38715
|
+
const classDef1Offset = offset + reader.u16();
|
|
38716
|
+
const classDef2Offset = offset + reader.u16();
|
|
38717
|
+
const class1Count = reader.u16();
|
|
38718
|
+
const class2Count = reader.u16();
|
|
38719
|
+
const value1Size = valueRecordSize(valueFormat1);
|
|
38720
|
+
const value2Size = valueRecordSize(valueFormat2);
|
|
38721
|
+
const cellSize = value1Size + value2Size;
|
|
38722
|
+
const matrixStart = reader.tell();
|
|
38723
|
+
const value1 = new Array(class1Count * class2Count);
|
|
38724
|
+
const value2 = new Array(class1Count * class2Count);
|
|
38725
|
+
for (let c1 = 0; c1 < class1Count; c1 += 1) {
|
|
38726
|
+
for (let c2 = 0; c2 < class2Count; c2 += 1) {
|
|
38727
|
+
const cell = (c1 * class2Count + c2) * cellSize;
|
|
38728
|
+
reader.seek(matrixStart + cell);
|
|
38729
|
+
value1[c1 * class2Count + c2] = readValueRecordXAdvance(
|
|
38730
|
+
reader,
|
|
38731
|
+
valueFormat1
|
|
38732
|
+
);
|
|
38733
|
+
reader.seek(matrixStart + cell + value1Size);
|
|
38734
|
+
value2[c1 * class2Count + c2] = readValueRecordXAdvance(
|
|
38735
|
+
reader,
|
|
38736
|
+
valueFormat2
|
|
38737
|
+
);
|
|
38738
|
+
}
|
|
38739
|
+
}
|
|
38740
|
+
const coverage = parseCoverage(reader, coverageOffset);
|
|
38741
|
+
const classDef1 = parseClassDef(reader, classDef1Offset);
|
|
38742
|
+
const classDef2 = parseClassDef(reader, classDef2Offset);
|
|
38743
|
+
return {
|
|
38744
|
+
apply(glyphIds, advances, pos) {
|
|
38745
|
+
const first = glyphIds[pos];
|
|
38746
|
+
const second = glyphIds[pos + 1];
|
|
38747
|
+
if (second === void 0) return null;
|
|
38748
|
+
if (coverage(first) < 0) return null;
|
|
38749
|
+
const c1 = classDef1(first);
|
|
38750
|
+
const c2 = classDef2(second);
|
|
38751
|
+
if (c1 >= class1Count || c2 >= class2Count) return null;
|
|
38752
|
+
const cellIndex = c1 * class2Count + c2;
|
|
38753
|
+
const v1 = value1[cellIndex];
|
|
38754
|
+
const v2 = value2[cellIndex];
|
|
38755
|
+
if (v1 === 0 && v2 === 0) return null;
|
|
38756
|
+
advances[pos] += v1;
|
|
38757
|
+
advances[pos + 1] += v2;
|
|
38758
|
+
return hasSecondAdjustment ? 2 : 1;
|
|
38759
|
+
}
|
|
38760
|
+
};
|
|
38761
|
+
}
|
|
38762
|
+
return null;
|
|
38763
|
+
}
|
|
38764
|
+
function parseSubtable(reader, offset, lookupType) {
|
|
38765
|
+
switch (lookupType) {
|
|
38766
|
+
case 1:
|
|
38767
|
+
return parseSinglePos(reader, offset);
|
|
38768
|
+
case 2:
|
|
38769
|
+
return parsePairPos(reader, offset);
|
|
38770
|
+
case 9: {
|
|
38771
|
+
reader.seek(offset);
|
|
38772
|
+
const format = reader.u16();
|
|
38773
|
+
if (format !== 1) return null;
|
|
38774
|
+
const extensionType = reader.u16();
|
|
38775
|
+
const extensionOffset = offset + reader.u32();
|
|
38776
|
+
return parseSubtable(reader, extensionOffset, extensionType);
|
|
38777
|
+
}
|
|
38778
|
+
default:
|
|
38779
|
+
return null;
|
|
38438
38780
|
}
|
|
38439
|
-
return featureIndices;
|
|
38440
38781
|
}
|
|
38441
38782
|
function parseLookupList(reader, lookupListOffset) {
|
|
38442
38783
|
reader.seek(lookupListOffset);
|
|
@@ -38465,17 +38806,71 @@ function parseLookupList(reader, lookupListOffset) {
|
|
|
38465
38806
|
return { lookupType, subtables };
|
|
38466
38807
|
});
|
|
38467
38808
|
}
|
|
38809
|
+
class GposTable {
|
|
38810
|
+
constructor(lookups, featureToLookups) {
|
|
38811
|
+
this.lookups = lookups;
|
|
38812
|
+
this.featureToLookups = featureToLookups;
|
|
38813
|
+
}
|
|
38814
|
+
/** Parses GPOS bytes (table-relative). Returns null on any structural failure. */
|
|
38815
|
+
static parse(bytes) {
|
|
38816
|
+
try {
|
|
38817
|
+
const reader = new BinaryReader(bytes);
|
|
38818
|
+
const { featureToLookups, lookupListOffset } = parseLayoutTableHeader(reader);
|
|
38819
|
+
const lookups = parseLookupList(reader, lookupListOffset);
|
|
38820
|
+
return new GposTable(lookups, featureToLookups);
|
|
38821
|
+
} catch {
|
|
38822
|
+
return null;
|
|
38823
|
+
}
|
|
38824
|
+
}
|
|
38825
|
+
/** True when at least one of the requested feature tags exists in this font. */
|
|
38826
|
+
hasAnyFeature(tags) {
|
|
38827
|
+
return tags.some((tag) => this.featureToLookups.has(tag));
|
|
38828
|
+
}
|
|
38829
|
+
/**
|
|
38830
|
+
* Applies the positioning lookups for the given features across `advances`
|
|
38831
|
+
* (font design units), mutating it in place. `glyphIds[i]` is the glyph at
|
|
38832
|
+
* advance slot `i`; the arrays are parallel and equal length.
|
|
38833
|
+
*/
|
|
38834
|
+
position(glyphIds, advances, tags) {
|
|
38835
|
+
const lookupIndices = collectLookupIndices(this.featureToLookups, tags);
|
|
38836
|
+
for (const lookupIndex of lookupIndices) {
|
|
38837
|
+
const lookup = this.lookups[lookupIndex];
|
|
38838
|
+
if (!lookup) continue;
|
|
38839
|
+
let pos = 0;
|
|
38840
|
+
while (pos < glyphIds.length) {
|
|
38841
|
+
let advance = null;
|
|
38842
|
+
for (const subtable of lookup.subtables) {
|
|
38843
|
+
advance = subtable.apply(glyphIds, advances, pos);
|
|
38844
|
+
if (advance !== null) break;
|
|
38845
|
+
}
|
|
38846
|
+
pos += advance && advance > 0 ? advance : 1;
|
|
38847
|
+
}
|
|
38848
|
+
}
|
|
38849
|
+
}
|
|
38850
|
+
}
|
|
38851
|
+
const GPOS_FEATURE_TAGS = /* @__PURE__ */ new Set(["kern"]);
|
|
38468
38852
|
class OpenTypeLayouter {
|
|
38469
38853
|
constructor(font) {
|
|
38470
38854
|
__publicField(this, "gsub");
|
|
38855
|
+
__publicField(this, "gpos");
|
|
38471
38856
|
this.font = font;
|
|
38472
|
-
const
|
|
38473
|
-
this.gsub =
|
|
38857
|
+
const gsubRaw = font.getRawTableData("GSUB");
|
|
38858
|
+
this.gsub = gsubRaw ? GsubTable.parse(gsubRaw) : null;
|
|
38859
|
+
const gposRaw = font.getRawTableData("GPOS");
|
|
38860
|
+
this.gpos = gposRaw ? GposTable.parse(gposRaw) : null;
|
|
38474
38861
|
}
|
|
38475
|
-
/** True when the font exposes a GSUB table the shaper could use. */
|
|
38862
|
+
/** True when the font exposes a GSUB table the substitution shaper could use. */
|
|
38476
38863
|
get hasGsub() {
|
|
38477
38864
|
return this.gsub !== null;
|
|
38478
38865
|
}
|
|
38866
|
+
/** True when the font exposes a GPOS table the kerning shaper could use. */
|
|
38867
|
+
get hasGpos() {
|
|
38868
|
+
return this.gpos !== null;
|
|
38869
|
+
}
|
|
38870
|
+
/** True when either shaping table is present (so this layouter adds value). */
|
|
38871
|
+
get hasShaping() {
|
|
38872
|
+
return this.gsub !== null || this.gpos !== null;
|
|
38873
|
+
}
|
|
38479
38874
|
layout(text, features) {
|
|
38480
38875
|
const buffer = [];
|
|
38481
38876
|
for (const char of text) {
|
|
@@ -38486,21 +38881,35 @@ class OpenTypeLayouter {
|
|
|
38486
38881
|
codePoints: glyphId === 0 ? [65533] : [codePoint]
|
|
38487
38882
|
});
|
|
38488
38883
|
}
|
|
38489
|
-
|
|
38490
|
-
|
|
38884
|
+
const gsubTags = (features == null ? void 0 : features.filter((tag) => !GPOS_FEATURE_TAGS.has(tag))) ?? [];
|
|
38885
|
+
const gposTags = (features == null ? void 0 : features.filter((tag) => GPOS_FEATURE_TAGS.has(tag))) ?? [];
|
|
38886
|
+
if (this.gsub && gsubTags.length > 0) {
|
|
38887
|
+
this.gsub.shape(buffer, gsubTags);
|
|
38888
|
+
}
|
|
38889
|
+
const advances = buffer.map(
|
|
38890
|
+
(glyph) => this.font.advanceWidthForGlyph(glyph.id)
|
|
38891
|
+
);
|
|
38892
|
+
if (this.gpos && gposTags.length > 0) {
|
|
38893
|
+
this.gpos.position(
|
|
38894
|
+
buffer.map((glyph) => glyph.id),
|
|
38895
|
+
advances,
|
|
38896
|
+
gposTags
|
|
38897
|
+
);
|
|
38491
38898
|
}
|
|
38492
38899
|
const glyphs = [];
|
|
38493
38900
|
const positions = [];
|
|
38494
38901
|
let advanceWidth = 0;
|
|
38495
|
-
for (
|
|
38496
|
-
const
|
|
38902
|
+
for (let i = 0; i < buffer.length; i += 1) {
|
|
38903
|
+
const glyph = buffer[i];
|
|
38904
|
+
const nominalAdvance = this.font.advanceWidthForGlyph(glyph.id);
|
|
38905
|
+
const positionedAdvance = advances[i];
|
|
38497
38906
|
glyphs.push({
|
|
38498
38907
|
id: glyph.id,
|
|
38499
38908
|
codePoints: glyph.codePoints,
|
|
38500
|
-
advanceWidth:
|
|
38909
|
+
advanceWidth: nominalAdvance
|
|
38501
38910
|
});
|
|
38502
|
-
positions.push({ xAdvance:
|
|
38503
|
-
advanceWidth +=
|
|
38911
|
+
positions.push({ xAdvance: positionedAdvance });
|
|
38912
|
+
advanceWidth += positionedAdvance;
|
|
38504
38913
|
}
|
|
38505
38914
|
return { glyphs, positions, advanceWidth };
|
|
38506
38915
|
}
|
|
@@ -38721,7 +39130,7 @@ function parseEmbeddedFontSync(sourceBytes) {
|
|
|
38721
39130
|
}
|
|
38722
39131
|
function createPdfEmbeddableFont(program) {
|
|
38723
39132
|
const shaper = new OpenTypeLayouter(program);
|
|
38724
|
-
const layouter = shaper.
|
|
39133
|
+
const layouter = shaper.hasShaping ? shaper : new SimpleTextLayouter(program);
|
|
38725
39134
|
return {
|
|
38726
39135
|
program,
|
|
38727
39136
|
layouter,
|
|
@@ -38948,7 +39357,97 @@ class PdfImageTable {
|
|
|
38948
39357
|
);
|
|
38949
39358
|
}
|
|
38950
39359
|
}
|
|
38951
|
-
|
|
39360
|
+
class PdfShadingTable {
|
|
39361
|
+
constructor() {
|
|
39362
|
+
__publicField(this, "shadings", []);
|
|
39363
|
+
}
|
|
39364
|
+
/** Registers a gradient (PDF space) and returns its `/Shading` resource name. */
|
|
39365
|
+
register(spec) {
|
|
39366
|
+
const name = `Sh${this.shadings.length + 1}`;
|
|
39367
|
+
this.shadings.push({ name, spec });
|
|
39368
|
+
return name;
|
|
39369
|
+
}
|
|
39370
|
+
/** Emits each gradient's Function + Shading objects, keyed by resource name. */
|
|
39371
|
+
buildShadingObjects(addObject) {
|
|
39372
|
+
const ids = /* @__PURE__ */ new Map();
|
|
39373
|
+
for (const { name, spec } of this.shadings) {
|
|
39374
|
+
ids.set(name, this.addShadingObject(spec, addObject));
|
|
39375
|
+
}
|
|
39376
|
+
return ids;
|
|
39377
|
+
}
|
|
39378
|
+
addShadingObject(spec, addObject) {
|
|
39379
|
+
const stops = normalizeStops(spec.stops);
|
|
39380
|
+
const functionObjectId = addObject(buildFunctionObject(stops));
|
|
39381
|
+
return addObject(
|
|
39382
|
+
[
|
|
39383
|
+
"<< /ShadingType 2",
|
|
39384
|
+
"/ColorSpace /DeviceRGB",
|
|
39385
|
+
`/Coords [${[spec.x0, spec.y0, spec.x1, spec.y1].map(formatNumber).join(" ")}]`,
|
|
39386
|
+
"/Domain [0 1]",
|
|
39387
|
+
`/Function ${functionObjectId} 0 R`,
|
|
39388
|
+
"/Extend [true true]",
|
|
39389
|
+
">>"
|
|
39390
|
+
].join("\n")
|
|
39391
|
+
);
|
|
39392
|
+
}
|
|
39393
|
+
}
|
|
39394
|
+
function normalizeStops(stops) {
|
|
39395
|
+
const resolved = stops.map((stop) => ({
|
|
39396
|
+
offset: Math.min(1, Math.max(0, stop.offset)),
|
|
39397
|
+
rgb: colorToRgb(stop.color, [0, 0, 0])
|
|
39398
|
+
})).sort((a, b) => a.offset - b.offset);
|
|
39399
|
+
if (resolved.length === 0) {
|
|
39400
|
+
return [
|
|
39401
|
+
{ offset: 0, rgb: [0, 0, 0] },
|
|
39402
|
+
{ offset: 1, rgb: [0, 0, 0] }
|
|
39403
|
+
];
|
|
39404
|
+
}
|
|
39405
|
+
if (resolved.length === 1) {
|
|
39406
|
+
return [
|
|
39407
|
+
{ offset: 0, rgb: resolved[0].rgb },
|
|
39408
|
+
{ offset: 1, rgb: resolved[0].rgb }
|
|
39409
|
+
];
|
|
39410
|
+
}
|
|
39411
|
+
resolved[0].offset = 0;
|
|
39412
|
+
resolved[resolved.length - 1].offset = 1;
|
|
39413
|
+
for (let i = 1; i < resolved.length - 1; i += 1) {
|
|
39414
|
+
const min = resolved[i - 1].offset + 1e-4;
|
|
39415
|
+
if (resolved[i].offset <= min) {
|
|
39416
|
+
resolved[i].offset = Math.min(1 - 1e-4, min);
|
|
39417
|
+
}
|
|
39418
|
+
}
|
|
39419
|
+
return resolved;
|
|
39420
|
+
}
|
|
39421
|
+
function exponentialFunction(c0, c1) {
|
|
39422
|
+
return [
|
|
39423
|
+
"<< /FunctionType 2",
|
|
39424
|
+
"/Domain [0 1]",
|
|
39425
|
+
`/C0 [${c0.map(formatNumber).join(" ")}]`,
|
|
39426
|
+
`/C1 [${c1.map(formatNumber).join(" ")}]`,
|
|
39427
|
+
"/N 1",
|
|
39428
|
+
">>"
|
|
39429
|
+
].join("\n");
|
|
39430
|
+
}
|
|
39431
|
+
function buildFunctionObject(stops) {
|
|
39432
|
+
if (stops.length === 2) {
|
|
39433
|
+
return exponentialFunction(stops[0].rgb, stops[1].rgb);
|
|
39434
|
+
}
|
|
39435
|
+
const subFunctions = [];
|
|
39436
|
+
for (let i = 0; i < stops.length - 1; i += 1) {
|
|
39437
|
+
subFunctions.push(exponentialFunction(stops[i].rgb, stops[i + 1].rgb));
|
|
39438
|
+
}
|
|
39439
|
+
const bounds = stops.slice(1, -1).map((stop) => formatNumber(stop.offset));
|
|
39440
|
+
const encode = stops.slice(0, -1).map(() => "0 1").join(" ");
|
|
39441
|
+
return [
|
|
39442
|
+
"<< /FunctionType 3",
|
|
39443
|
+
"/Domain [0 1]",
|
|
39444
|
+
`/Functions [${subFunctions.join(" ")}]`,
|
|
39445
|
+
`/Bounds [${bounds.join(" ")}]`,
|
|
39446
|
+
`/Encode [${encode}]`,
|
|
39447
|
+
">>"
|
|
39448
|
+
].join("\n");
|
|
39449
|
+
}
|
|
39450
|
+
function serializePdfDocument(pages, fonts, images, shadings) {
|
|
38952
39451
|
const objects = [];
|
|
38953
39452
|
const addObject = (body2) => {
|
|
38954
39453
|
const id = objects.length + 1;
|
|
@@ -38959,6 +39458,7 @@ function serializePdfDocument(pages, fonts, images) {
|
|
|
38959
39458
|
const pagesObjectId = addObject("");
|
|
38960
39459
|
const { resourceXml: fontResourceXml } = fonts.buildFontObjects(addObject);
|
|
38961
39460
|
const imageObjectIds = images.buildImageObjects(addObject);
|
|
39461
|
+
const shadingObjectIds = shadings.buildShadingObjects(addObject);
|
|
38962
39462
|
const pageObjectIds = [];
|
|
38963
39463
|
for (const page of pages) {
|
|
38964
39464
|
const stream = `${page.commands.join("\n")}
|
|
@@ -38973,12 +39473,17 @@ ${stream}endstream`
|
|
|
38973
39473
|
return objectId ? `/${resourceName} ${objectId} 0 R` : "";
|
|
38974
39474
|
}).filter(Boolean).join(" ");
|
|
38975
39475
|
const xObjectResourceXml = imageResourceXml ? ` /XObject << ${imageResourceXml} >>` : "";
|
|
39476
|
+
const shadingResourceXml = Array.from(page.shadingResourceNames).map((resourceName) => {
|
|
39477
|
+
const objectId = shadingObjectIds.get(resourceName);
|
|
39478
|
+
return objectId ? `/${resourceName} ${objectId} 0 R` : "";
|
|
39479
|
+
}).filter(Boolean).join(" ");
|
|
39480
|
+
const shadingResourceDictXml = shadingResourceXml ? ` /Shading << ${shadingResourceXml} >>` : "";
|
|
38976
39481
|
const pageObjectId = addObject(
|
|
38977
39482
|
[
|
|
38978
39483
|
"<< /Type /Page",
|
|
38979
39484
|
`/Parent ${pagesObjectId} 0 R`,
|
|
38980
39485
|
`/MediaBox [0 0 ${formatNumber(page.width)} ${formatNumber(page.height)}]`,
|
|
38981
|
-
`/Resources << /Font << ${fontResourceXml} >>${xObjectResourceXml} >>`,
|
|
39486
|
+
`/Resources << /Font << ${fontResourceXml} >>${xObjectResourceXml}${shadingResourceDictXml} >>`,
|
|
38982
39487
|
`/Contents ${contentObjectId} 0 R`,
|
|
38983
39488
|
">>"
|
|
38984
39489
|
].join("\n")
|
|
@@ -39026,6 +39531,7 @@ class OasisPdfWriter {
|
|
|
39026
39531
|
__publicField(this, "streams", []);
|
|
39027
39532
|
__publicField(this, "fonts");
|
|
39028
39533
|
__publicField(this, "images", new PdfImageTable());
|
|
39534
|
+
__publicField(this, "shadings", new PdfShadingTable());
|
|
39029
39535
|
this.fonts = new PdfFontTable(fontResources);
|
|
39030
39536
|
}
|
|
39031
39537
|
registerFontResource(resource) {
|
|
@@ -39036,10 +39542,13 @@ class OasisPdfWriter {
|
|
|
39036
39542
|
width: Math.max(1, size.width),
|
|
39037
39543
|
height: Math.max(1, size.height),
|
|
39038
39544
|
commands: [],
|
|
39039
|
-
imageResourceNames: /* @__PURE__ */ new Set()
|
|
39545
|
+
imageResourceNames: /* @__PURE__ */ new Set(),
|
|
39546
|
+
shadingResourceNames: /* @__PURE__ */ new Set()
|
|
39040
39547
|
};
|
|
39041
39548
|
this.pages.push(page);
|
|
39042
|
-
this.streams.push(
|
|
39549
|
+
this.streams.push(
|
|
39550
|
+
new PdfContentStream(page, this.fonts, this.images, this.shadings)
|
|
39551
|
+
);
|
|
39043
39552
|
return this.pages.length - 1;
|
|
39044
39553
|
}
|
|
39045
39554
|
getPageCount() {
|
|
@@ -39077,6 +39586,15 @@ class OasisPdfWriter {
|
|
|
39077
39586
|
var _a;
|
|
39078
39587
|
(_a = this.streams[pageIndex]) == null ? void 0 : _a.drawText(options);
|
|
39079
39588
|
}
|
|
39589
|
+
/**
|
|
39590
|
+
* Registers an axial (linear) gradient on a page for use as a glyph fill, and
|
|
39591
|
+
* returns its shading resource name to pass as `gradientShadingName` on a
|
|
39592
|
+
* subsequent `drawText`. Coordinates are in the writer's top-left point space.
|
|
39593
|
+
*/
|
|
39594
|
+
registerAxialGradient(pageIndex, gradient) {
|
|
39595
|
+
var _a;
|
|
39596
|
+
return ((_a = this.streams[pageIndex]) == null ? void 0 : _a.registerAxialGradient(gradient)) ?? null;
|
|
39597
|
+
}
|
|
39080
39598
|
registerImageResource(resource) {
|
|
39081
39599
|
return this.images.registerImageResource(resource);
|
|
39082
39600
|
}
|
|
@@ -39095,7 +39613,12 @@ class OasisPdfWriter {
|
|
|
39095
39613
|
if (this.pages.length === 0) {
|
|
39096
39614
|
this.addPage({ width: 612, height: 792 });
|
|
39097
39615
|
}
|
|
39098
|
-
return serializePdfDocument(
|
|
39616
|
+
return serializePdfDocument(
|
|
39617
|
+
this.pages,
|
|
39618
|
+
this.fonts,
|
|
39619
|
+
this.images,
|
|
39620
|
+
this.shadings
|
|
39621
|
+
);
|
|
39099
39622
|
}
|
|
39100
39623
|
}
|
|
39101
39624
|
const FOOTNOTE_BLOCK_GAP_PX = 2;
|