oasis-editor 0.0.100 → 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.
@@ -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-BuxYvaSC.js";
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
- return blocks.map((block) => {
34716
- var _a;
34717
- switch (block.type) {
34718
- case "paragraph":
34719
- return serializeParagraphXml(block, context, styles);
34720
- case "table": {
34721
- const pageBreakXml = ((_a = block.style) == null ? void 0 : _a.pageBreakBefore) ? '<w:p><w:r><w:br w:type="page"/></w:r></w:p>' : "";
34722
- return pageBreakXml + serializeTableXml(
34723
- block,
34724
- (paragraph, cell) => {
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
- }).join("");
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) {
@@ -36728,6 +36787,15 @@ async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, do
36728
36787
  fontFeatures
36729
36788
  };
36730
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
+ );
36731
36799
  const offsetPt = pxToPt$1(1);
36732
36800
  const emitChunk = (leftPx, text2) => {
36733
36801
  if (styles.emboss || styles.imprint) {
@@ -36803,7 +36871,9 @@ async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, do
36803
36871
  y: pxToPt$1(baselineY),
36804
36872
  text: text2,
36805
36873
  color: mainColor,
36806
- ...textOutline ? {
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 ? {
36807
36877
  renderMode: 2,
36808
36878
  strokeColor: textOutline.color ?? mainColor,
36809
36879
  strokeWidth: textOutline.widthPt
@@ -37634,10 +37704,27 @@ function textMarkerComment(value) {
37634
37704
  return `% OasisText ${encodePdfUtf16Hex(codePoints)}`;
37635
37705
  }
37636
37706
  class PdfContentStream {
37637
- constructor(page, fonts, images) {
37707
+ constructor(page, fonts, images, shadings) {
37638
37708
  this.page = page;
37639
37709
  this.fonts = fonts;
37640
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;
37641
37728
  }
37642
37729
  drawRect(options) {
37643
37730
  const page = this.page;
@@ -37795,8 +37882,24 @@ class PdfContentStream {
37795
37882
  if (showCommand === null) {
37796
37883
  return;
37797
37884
  }
37885
+ if (options.gradientShadingName) {
37886
+ this.emitGradientTextBlock(
37887
+ fontResourceName,
37888
+ showCommand,
37889
+ options,
37890
+ options.gradientShadingName
37891
+ );
37892
+ return;
37893
+ }
37798
37894
  this.emitTextBlock(fontResourceName, showCommand, options);
37799
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
+ }
37800
37903
  emitTextBlock(fontResourceName, showCommand, options) {
37801
37904
  const page = this.page;
37802
37905
  page.commands.push(
@@ -37804,7 +37907,6 @@ class PdfContentStream {
37804
37907
  textMarkerComment(options.text),
37805
37908
  "BT",
37806
37909
  colorCommand(options.color, "rg", [0, 0, 0]),
37807
- `/${fontResourceName} ${formatNumber(options.fontSize ?? 12)} Tf`,
37808
37910
  ...options.renderMode && options.renderMode !== 0 ? [
37809
37911
  colorCommand(
37810
37912
  options.strokeColor ?? options.color,
@@ -37816,14 +37918,37 @@ class PdfContentStream {
37816
37918
  )} w`,
37817
37919
  `${options.renderMode} Tr`
37818
37920
  ] : [],
37819
- ...options.horizontalScale && options.horizontalScale > 0 && options.horizontalScale !== 100 ? [`${formatNumber(options.horizontalScale)} Tz`] : [],
37820
- ...options.characterSpacing && options.characterSpacing !== 0 ? [`${formatNumber(options.characterSpacing)} Tc`] : [],
37921
+ ...this.textSetupCommands(fontResourceName, options),
37821
37922
  `${formatNumber(options.x)} ${formatNumber(page.height - options.y)} Td`,
37822
37923
  showCommand,
37823
37924
  "ET"
37824
37925
  ].join("\n")
37825
37926
  );
37826
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
+ }
37827
37952
  drawImage(options) {
37828
37953
  const page = this.page;
37829
37954
  if (options.width <= 0 || options.height <= 0 || !this.images.has(options.resourceName)) {
@@ -39232,7 +39357,97 @@ class PdfImageTable {
39232
39357
  );
39233
39358
  }
39234
39359
  }
39235
- function serializePdfDocument(pages, fonts, images) {
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) {
39236
39451
  const objects = [];
39237
39452
  const addObject = (body2) => {
39238
39453
  const id = objects.length + 1;
@@ -39243,6 +39458,7 @@ function serializePdfDocument(pages, fonts, images) {
39243
39458
  const pagesObjectId = addObject("");
39244
39459
  const { resourceXml: fontResourceXml } = fonts.buildFontObjects(addObject);
39245
39460
  const imageObjectIds = images.buildImageObjects(addObject);
39461
+ const shadingObjectIds = shadings.buildShadingObjects(addObject);
39246
39462
  const pageObjectIds = [];
39247
39463
  for (const page of pages) {
39248
39464
  const stream = `${page.commands.join("\n")}
@@ -39257,12 +39473,17 @@ ${stream}endstream`
39257
39473
  return objectId ? `/${resourceName} ${objectId} 0 R` : "";
39258
39474
  }).filter(Boolean).join(" ");
39259
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} >>` : "";
39260
39481
  const pageObjectId = addObject(
39261
39482
  [
39262
39483
  "<< /Type /Page",
39263
39484
  `/Parent ${pagesObjectId} 0 R`,
39264
39485
  `/MediaBox [0 0 ${formatNumber(page.width)} ${formatNumber(page.height)}]`,
39265
- `/Resources << /Font << ${fontResourceXml} >>${xObjectResourceXml} >>`,
39486
+ `/Resources << /Font << ${fontResourceXml} >>${xObjectResourceXml}${shadingResourceDictXml} >>`,
39266
39487
  `/Contents ${contentObjectId} 0 R`,
39267
39488
  ">>"
39268
39489
  ].join("\n")
@@ -39310,6 +39531,7 @@ class OasisPdfWriter {
39310
39531
  __publicField(this, "streams", []);
39311
39532
  __publicField(this, "fonts");
39312
39533
  __publicField(this, "images", new PdfImageTable());
39534
+ __publicField(this, "shadings", new PdfShadingTable());
39313
39535
  this.fonts = new PdfFontTable(fontResources);
39314
39536
  }
39315
39537
  registerFontResource(resource) {
@@ -39320,10 +39542,13 @@ class OasisPdfWriter {
39320
39542
  width: Math.max(1, size.width),
39321
39543
  height: Math.max(1, size.height),
39322
39544
  commands: [],
39323
- imageResourceNames: /* @__PURE__ */ new Set()
39545
+ imageResourceNames: /* @__PURE__ */ new Set(),
39546
+ shadingResourceNames: /* @__PURE__ */ new Set()
39324
39547
  };
39325
39548
  this.pages.push(page);
39326
- this.streams.push(new PdfContentStream(page, this.fonts, this.images));
39549
+ this.streams.push(
39550
+ new PdfContentStream(page, this.fonts, this.images, this.shadings)
39551
+ );
39327
39552
  return this.pages.length - 1;
39328
39553
  }
39329
39554
  getPageCount() {
@@ -39361,6 +39586,15 @@ class OasisPdfWriter {
39361
39586
  var _a;
39362
39587
  (_a = this.streams[pageIndex]) == null ? void 0 : _a.drawText(options);
39363
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
+ }
39364
39598
  registerImageResource(resource) {
39365
39599
  return this.images.registerImageResource(resource);
39366
39600
  }
@@ -39379,7 +39613,12 @@ class OasisPdfWriter {
39379
39613
  if (this.pages.length === 0) {
39380
39614
  this.addPage({ width: 612, height: 792 });
39381
39615
  }
39382
- return serializePdfDocument(this.pages, this.fonts, this.images);
39616
+ return serializePdfDocument(
39617
+ this.pages,
39618
+ this.fonts,
39619
+ this.images,
39620
+ this.shadings
39621
+ );
39383
39622
  }
39384
39623
  }
39385
39624
  const FOOTNOTE_BLOCK_GAP_PX = 2;