oasis-editor 0.0.99 → 0.0.100

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-CNuDp_SC.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-BuxYvaSC.js";
5
5
  function cloneStyle(style2) {
6
6
  return style2 ? { ...style2 } : void 0;
7
7
  }
@@ -36714,7 +36714,10 @@ async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, do
36714
36714
  styles.color ?? "#000000"
36715
36715
  );
36716
36716
  const paragraphAlign = resolveEffectiveParagraphStyle(paragraph.style, document2.styles).align ?? "left";
36717
- const fontFeatures = resolveOpenTypeFeatureTags(styles);
36717
+ const fontFeatures = resolveOpenTypeFeatureTags(
36718
+ styles,
36719
+ textStyleToFontSizePt(styles)
36720
+ );
36718
36721
  const baseTextOptions = {
36719
36722
  fontSize: fontSizePt,
36720
36723
  bold: styles.bold,
@@ -37875,9 +37878,6 @@ class PdfContentStream {
37875
37878
  );
37876
37879
  }
37877
37880
  }
37878
- function readTag(reader) {
37879
- return reader.tag();
37880
- }
37881
37881
  function parseCoverage(reader, offset) {
37882
37882
  reader.seek(offset);
37883
37883
  const format = reader.u16();
@@ -37944,6 +37944,83 @@ function parseClassDef(reader, offset) {
37944
37944
  }
37945
37945
  return () => 0;
37946
37946
  }
37947
+ function parseFeatureList(reader, featureListOffset) {
37948
+ reader.seek(featureListOffset);
37949
+ const featureCount = reader.u16();
37950
+ const records = [];
37951
+ for (let i = 0; i < featureCount; i += 1) {
37952
+ const tag = reader.tag();
37953
+ const offset = featureListOffset + reader.u16();
37954
+ records.push({ tag, offset });
37955
+ }
37956
+ return records.map(({ tag, offset }) => {
37957
+ reader.seek(offset);
37958
+ reader.skip(2);
37959
+ const lookupIndexCount = reader.u16();
37960
+ const lookupIndices = new Array(lookupIndexCount);
37961
+ for (let i = 0; i < lookupIndexCount; i += 1) {
37962
+ lookupIndices[i] = reader.u16();
37963
+ }
37964
+ return { tag, lookupIndices };
37965
+ });
37966
+ }
37967
+ function parseScriptList(reader, scriptListOffset) {
37968
+ reader.seek(scriptListOffset);
37969
+ const scriptCount = reader.u16();
37970
+ const scripts = [];
37971
+ for (let i = 0; i < scriptCount; i += 1) {
37972
+ const tag = reader.tag();
37973
+ const offset = scriptListOffset + reader.u16();
37974
+ scripts.push({ tag, offset });
37975
+ }
37976
+ if (scripts.length === 0) return [];
37977
+ const chosen = scripts.find((s) => s.tag === "latn") ?? scripts.find((s) => s.tag === "DFLT") ?? scripts[0];
37978
+ reader.seek(chosen.offset);
37979
+ const defaultLangSysOffset = reader.u16();
37980
+ if (defaultLangSysOffset === 0) return [];
37981
+ reader.seek(chosen.offset + defaultLangSysOffset);
37982
+ reader.skip(2);
37983
+ const requiredFeatureIndex = reader.u16();
37984
+ const featureIndexCount = reader.u16();
37985
+ const featureIndices = [];
37986
+ if (requiredFeatureIndex !== 65535) {
37987
+ featureIndices.push(requiredFeatureIndex);
37988
+ }
37989
+ for (let i = 0; i < featureIndexCount; i += 1) {
37990
+ featureIndices.push(reader.u16());
37991
+ }
37992
+ return featureIndices;
37993
+ }
37994
+ function parseLayoutTableHeader(reader) {
37995
+ reader.seek(0);
37996
+ reader.skip(2);
37997
+ reader.skip(2);
37998
+ const scriptListOffset = reader.u16();
37999
+ const featureListOffset = reader.u16();
38000
+ const lookupListOffset = reader.u16();
38001
+ const featureRecords = parseFeatureList(reader, featureListOffset);
38002
+ const activeFeatureIndices = parseScriptList(reader, scriptListOffset);
38003
+ const featureToLookups = /* @__PURE__ */ new Map();
38004
+ for (const featureIndex of activeFeatureIndices) {
38005
+ const record = featureRecords[featureIndex];
38006
+ if (!record) continue;
38007
+ const existing = featureToLookups.get(record.tag) ?? [];
38008
+ for (const lookupIndex of record.lookupIndices) {
38009
+ if (!existing.includes(lookupIndex)) existing.push(lookupIndex);
38010
+ }
38011
+ featureToLookups.set(record.tag, existing);
38012
+ }
38013
+ return { featureToLookups, lookupListOffset };
38014
+ }
38015
+ function collectLookupIndices(featureToLookups, tags) {
38016
+ const indices = /* @__PURE__ */ new Set();
38017
+ for (const tag of tags) {
38018
+ for (const lookupIndex of featureToLookups.get(tag) ?? []) {
38019
+ indices.add(lookupIndex);
38020
+ }
38021
+ }
38022
+ return Array.from(indices).sort((a, b) => a - b);
38023
+ }
37947
38024
  function parseSingleSubst(reader, offset) {
37948
38025
  reader.seek(offset);
37949
38026
  const format = reader.u16();
@@ -38293,7 +38370,7 @@ function applyChainRules(rules, glyphs, pos, engine, resolver) {
38293
38370
  }
38294
38371
  return null;
38295
38372
  }
38296
- function parseSubtable(reader, offset, lookupType) {
38373
+ function parseSubtable$1(reader, offset, lookupType) {
38297
38374
  switch (lookupType) {
38298
38375
  case 1:
38299
38376
  return parseSingleSubst(reader, offset);
@@ -38311,7 +38388,7 @@ function parseSubtable(reader, offset, lookupType) {
38311
38388
  if (format !== 1) return null;
38312
38389
  const extensionType = reader.u16();
38313
38390
  const extensionOffset = offset + reader.u32();
38314
- return parseSubtable(reader, extensionOffset, extensionType);
38391
+ return parseSubtable$1(reader, extensionOffset, extensionType);
38315
38392
  }
38316
38393
  default:
38317
38394
  return null;
@@ -38326,25 +38403,8 @@ class GsubTable {
38326
38403
  static parse(bytes) {
38327
38404
  try {
38328
38405
  const reader = new BinaryReader(bytes);
38329
- reader.seek(0);
38330
- reader.skip(2);
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
- }
38406
+ const { featureToLookups, lookupListOffset } = parseLayoutTableHeader(reader);
38407
+ const lookups = parseLookupList$1(reader, lookupListOffset);
38348
38408
  return new GsubTable(lookups, featureToLookups);
38349
38409
  } catch {
38350
38410
  return null;
@@ -38356,13 +38416,7 @@ class GsubTable {
38356
38416
  }
38357
38417
  /** Ordered (ascending) unique lookup indices referenced by the given tags. */
38358
38418
  collectLookupIndices(tags) {
38359
- const indices = /* @__PURE__ */ new Set();
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);
38419
+ return collectLookupIndices(this.featureToLookups, tags);
38366
38420
  }
38367
38421
  /**
38368
38422
  * Applies one lookup (by index) at a single position. Tries each subtable in
@@ -38391,52 +38445,214 @@ class GsubTable {
38391
38445
  }
38392
38446
  }
38393
38447
  }
38394
- function parseFeatureList(reader, featureListOffset) {
38395
- reader.seek(featureListOffset);
38396
- const featureCount = reader.u16();
38397
- const records = [];
38398
- for (let i = 0; i < featureCount; i += 1) {
38399
- const tag = readTag(reader);
38400
- const offset = featureListOffset + reader.u16();
38401
- records.push({ tag, offset });
38448
+ function parseLookupList$1(reader, lookupListOffset) {
38449
+ reader.seek(lookupListOffset);
38450
+ const lookupCount = reader.u16();
38451
+ const lookupOffsets = new Array(lookupCount);
38452
+ for (let i = 0; i < lookupCount; i += 1) {
38453
+ lookupOffsets[i] = lookupListOffset + reader.u16();
38402
38454
  }
38403
- return records.map(({ tag, offset }) => {
38404
- reader.seek(offset);
38455
+ return lookupOffsets.map((lookupOffset) => {
38456
+ reader.seek(lookupOffset);
38457
+ const lookupType = reader.u16();
38405
38458
  reader.skip(2);
38406
- const lookupIndexCount = reader.u16();
38407
- const lookupIndices = new Array(lookupIndexCount);
38408
- for (let i = 0; i < lookupIndexCount; i += 1) {
38409
- lookupIndices[i] = reader.u16();
38459
+ const subTableCount = reader.u16();
38460
+ const subtableOffsets = new Array(subTableCount);
38461
+ for (let i = 0; i < subTableCount; i += 1) {
38462
+ subtableOffsets[i] = lookupOffset + reader.u16();
38410
38463
  }
38411
- return { tag, lookupIndices };
38464
+ const subtables = [];
38465
+ for (const subtableOffset of subtableOffsets) {
38466
+ try {
38467
+ const subtable = parseSubtable$1(reader, subtableOffset, lookupType);
38468
+ if (subtable) subtables.push(subtable);
38469
+ } catch {
38470
+ }
38471
+ }
38472
+ return { lookupType, subtables };
38412
38473
  });
38413
38474
  }
38414
- function parseScriptList(reader, scriptListOffset) {
38415
- reader.seek(scriptListOffset);
38416
- const scriptCount = reader.u16();
38417
- const scripts = [];
38418
- for (let i = 0; i < scriptCount; i += 1) {
38419
- const tag = readTag(reader);
38420
- const offset = scriptListOffset + reader.u16();
38421
- scripts.push({ tag, offset });
38475
+ const X_PLACEMENT = 1;
38476
+ const Y_PLACEMENT = 2;
38477
+ const X_ADVANCE = 4;
38478
+ const Y_ADVANCE = 8;
38479
+ const X_PLACEMENT_DEVICE = 16;
38480
+ const Y_PLACEMENT_DEVICE = 32;
38481
+ const X_ADVANCE_DEVICE = 64;
38482
+ const Y_ADVANCE_DEVICE = 128;
38483
+ function readValueRecordXAdvance(reader, valueFormat) {
38484
+ let xAdvance = 0;
38485
+ if (valueFormat & X_PLACEMENT) reader.i16();
38486
+ if (valueFormat & Y_PLACEMENT) reader.i16();
38487
+ if (valueFormat & X_ADVANCE) xAdvance = reader.i16();
38488
+ if (valueFormat & Y_ADVANCE) reader.i16();
38489
+ if (valueFormat & X_PLACEMENT_DEVICE) reader.u16();
38490
+ if (valueFormat & Y_PLACEMENT_DEVICE) reader.u16();
38491
+ if (valueFormat & X_ADVANCE_DEVICE) reader.u16();
38492
+ if (valueFormat & Y_ADVANCE_DEVICE) reader.u16();
38493
+ return xAdvance;
38494
+ }
38495
+ function valueRecordSize(valueFormat) {
38496
+ let count = 0;
38497
+ for (let bit = 0; bit < 8; bit += 1) {
38498
+ if (valueFormat & 1 << bit) count += 1;
38499
+ }
38500
+ return count * 2;
38501
+ }
38502
+ function parseSinglePos(reader, offset) {
38503
+ reader.seek(offset);
38504
+ const format = reader.u16();
38505
+ const coverageOffset = offset + reader.u16();
38506
+ if (format === 1) {
38507
+ const valueFormat = reader.u16();
38508
+ const xAdvance = readValueRecordXAdvance(reader, valueFormat);
38509
+ const coverage = parseCoverage(reader, coverageOffset);
38510
+ if (xAdvance === 0) return null;
38511
+ return {
38512
+ apply(glyphIds, advances, pos) {
38513
+ if (coverage(glyphIds[pos]) < 0) return null;
38514
+ advances[pos] += xAdvance;
38515
+ return 1;
38516
+ }
38517
+ };
38422
38518
  }
38423
- if (scripts.length === 0) return [];
38424
- const chosen = scripts.find((s) => s.tag === "latn") ?? scripts.find((s) => s.tag === "DFLT") ?? scripts[0];
38425
- reader.seek(chosen.offset);
38426
- const defaultLangSysOffset = reader.u16();
38427
- if (defaultLangSysOffset === 0) return [];
38428
- reader.seek(chosen.offset + defaultLangSysOffset);
38429
- reader.skip(2);
38430
- const requiredFeatureIndex = reader.u16();
38431
- const featureIndexCount = reader.u16();
38432
- const featureIndices = [];
38433
- if (requiredFeatureIndex !== 65535) {
38434
- featureIndices.push(requiredFeatureIndex);
38519
+ if (format === 2) {
38520
+ const valueFormat = reader.u16();
38521
+ const valueCount = reader.u16();
38522
+ const recordSize = valueRecordSize(valueFormat);
38523
+ const recordsStart = reader.tell();
38524
+ const xAdvances = new Array(valueCount);
38525
+ for (let i = 0; i < valueCount; i += 1) {
38526
+ reader.seek(recordsStart + i * recordSize);
38527
+ xAdvances[i] = readValueRecordXAdvance(reader, valueFormat);
38528
+ }
38529
+ const coverage = parseCoverage(reader, coverageOffset);
38530
+ return {
38531
+ apply(glyphIds, advances, pos) {
38532
+ const index = coverage(glyphIds[pos]);
38533
+ if (index < 0 || index >= valueCount) return null;
38534
+ const delta = xAdvances[index];
38535
+ if (delta === 0) return null;
38536
+ advances[pos] += delta;
38537
+ return 1;
38538
+ }
38539
+ };
38435
38540
  }
38436
- for (let i = 0; i < featureIndexCount; i += 1) {
38437
- featureIndices.push(reader.u16());
38541
+ return null;
38542
+ }
38543
+ function parsePairPos(reader, offset) {
38544
+ reader.seek(offset);
38545
+ const format = reader.u16();
38546
+ const coverageOffset = offset + reader.u16();
38547
+ const valueFormat1 = reader.u16();
38548
+ const valueFormat2 = reader.u16();
38549
+ const hasSecondAdjustment = (valueFormat2 & X_ADVANCE) !== 0;
38550
+ if (format === 1) {
38551
+ const pairSetCount = reader.u16();
38552
+ const pairSetOffsets = new Array(pairSetCount);
38553
+ for (let i = 0; i < pairSetCount; i += 1) {
38554
+ pairSetOffsets[i] = offset + reader.u16();
38555
+ }
38556
+ const pairSets = pairSetOffsets.map(
38557
+ (setOffset) => {
38558
+ reader.seek(setOffset);
38559
+ const pairValueCount = reader.u16();
38560
+ const pairs = /* @__PURE__ */ new Map();
38561
+ for (let i = 0; i < pairValueCount; i += 1) {
38562
+ const secondGlyph = reader.u16();
38563
+ const value1XAdvance = readValueRecordXAdvance(reader, valueFormat1);
38564
+ const value2XAdvance = readValueRecordXAdvance(reader, valueFormat2);
38565
+ pairs.set(secondGlyph, {
38566
+ secondGlyph,
38567
+ value1XAdvance,
38568
+ value2XAdvance
38569
+ });
38570
+ }
38571
+ return pairs;
38572
+ }
38573
+ );
38574
+ const coverage = parseCoverage(reader, coverageOffset);
38575
+ return {
38576
+ apply(glyphIds, advances, pos) {
38577
+ const second = glyphIds[pos + 1];
38578
+ if (second === void 0) return null;
38579
+ const setIndex = coverage(glyphIds[pos]);
38580
+ if (setIndex < 0 || setIndex >= pairSets.length) return null;
38581
+ const pair = pairSets[setIndex].get(second);
38582
+ if (!pair) return null;
38583
+ advances[pos] += pair.value1XAdvance;
38584
+ advances[pos + 1] += pair.value2XAdvance;
38585
+ return hasSecondAdjustment ? 2 : 1;
38586
+ }
38587
+ };
38588
+ }
38589
+ if (format === 2) {
38590
+ const classDef1Offset = offset + reader.u16();
38591
+ const classDef2Offset = offset + reader.u16();
38592
+ const class1Count = reader.u16();
38593
+ const class2Count = reader.u16();
38594
+ const value1Size = valueRecordSize(valueFormat1);
38595
+ const value2Size = valueRecordSize(valueFormat2);
38596
+ const cellSize = value1Size + value2Size;
38597
+ const matrixStart = reader.tell();
38598
+ const value1 = new Array(class1Count * class2Count);
38599
+ const value2 = new Array(class1Count * class2Count);
38600
+ for (let c1 = 0; c1 < class1Count; c1 += 1) {
38601
+ for (let c2 = 0; c2 < class2Count; c2 += 1) {
38602
+ const cell = (c1 * class2Count + c2) * cellSize;
38603
+ reader.seek(matrixStart + cell);
38604
+ value1[c1 * class2Count + c2] = readValueRecordXAdvance(
38605
+ reader,
38606
+ valueFormat1
38607
+ );
38608
+ reader.seek(matrixStart + cell + value1Size);
38609
+ value2[c1 * class2Count + c2] = readValueRecordXAdvance(
38610
+ reader,
38611
+ valueFormat2
38612
+ );
38613
+ }
38614
+ }
38615
+ const coverage = parseCoverage(reader, coverageOffset);
38616
+ const classDef1 = parseClassDef(reader, classDef1Offset);
38617
+ const classDef2 = parseClassDef(reader, classDef2Offset);
38618
+ return {
38619
+ apply(glyphIds, advances, pos) {
38620
+ const first = glyphIds[pos];
38621
+ const second = glyphIds[pos + 1];
38622
+ if (second === void 0) return null;
38623
+ if (coverage(first) < 0) return null;
38624
+ const c1 = classDef1(first);
38625
+ const c2 = classDef2(second);
38626
+ if (c1 >= class1Count || c2 >= class2Count) return null;
38627
+ const cellIndex = c1 * class2Count + c2;
38628
+ const v1 = value1[cellIndex];
38629
+ const v2 = value2[cellIndex];
38630
+ if (v1 === 0 && v2 === 0) return null;
38631
+ advances[pos] += v1;
38632
+ advances[pos + 1] += v2;
38633
+ return hasSecondAdjustment ? 2 : 1;
38634
+ }
38635
+ };
38636
+ }
38637
+ return null;
38638
+ }
38639
+ function parseSubtable(reader, offset, lookupType) {
38640
+ switch (lookupType) {
38641
+ case 1:
38642
+ return parseSinglePos(reader, offset);
38643
+ case 2:
38644
+ return parsePairPos(reader, offset);
38645
+ case 9: {
38646
+ reader.seek(offset);
38647
+ const format = reader.u16();
38648
+ if (format !== 1) return null;
38649
+ const extensionType = reader.u16();
38650
+ const extensionOffset = offset + reader.u32();
38651
+ return parseSubtable(reader, extensionOffset, extensionType);
38652
+ }
38653
+ default:
38654
+ return null;
38438
38655
  }
38439
- return featureIndices;
38440
38656
  }
38441
38657
  function parseLookupList(reader, lookupListOffset) {
38442
38658
  reader.seek(lookupListOffset);
@@ -38465,17 +38681,71 @@ function parseLookupList(reader, lookupListOffset) {
38465
38681
  return { lookupType, subtables };
38466
38682
  });
38467
38683
  }
38684
+ class GposTable {
38685
+ constructor(lookups, featureToLookups) {
38686
+ this.lookups = lookups;
38687
+ this.featureToLookups = featureToLookups;
38688
+ }
38689
+ /** Parses GPOS bytes (table-relative). Returns null on any structural failure. */
38690
+ static parse(bytes) {
38691
+ try {
38692
+ const reader = new BinaryReader(bytes);
38693
+ const { featureToLookups, lookupListOffset } = parseLayoutTableHeader(reader);
38694
+ const lookups = parseLookupList(reader, lookupListOffset);
38695
+ return new GposTable(lookups, featureToLookups);
38696
+ } catch {
38697
+ return null;
38698
+ }
38699
+ }
38700
+ /** True when at least one of the requested feature tags exists in this font. */
38701
+ hasAnyFeature(tags) {
38702
+ return tags.some((tag) => this.featureToLookups.has(tag));
38703
+ }
38704
+ /**
38705
+ * Applies the positioning lookups for the given features across `advances`
38706
+ * (font design units), mutating it in place. `glyphIds[i]` is the glyph at
38707
+ * advance slot `i`; the arrays are parallel and equal length.
38708
+ */
38709
+ position(glyphIds, advances, tags) {
38710
+ const lookupIndices = collectLookupIndices(this.featureToLookups, tags);
38711
+ for (const lookupIndex of lookupIndices) {
38712
+ const lookup = this.lookups[lookupIndex];
38713
+ if (!lookup) continue;
38714
+ let pos = 0;
38715
+ while (pos < glyphIds.length) {
38716
+ let advance = null;
38717
+ for (const subtable of lookup.subtables) {
38718
+ advance = subtable.apply(glyphIds, advances, pos);
38719
+ if (advance !== null) break;
38720
+ }
38721
+ pos += advance && advance > 0 ? advance : 1;
38722
+ }
38723
+ }
38724
+ }
38725
+ }
38726
+ const GPOS_FEATURE_TAGS = /* @__PURE__ */ new Set(["kern"]);
38468
38727
  class OpenTypeLayouter {
38469
38728
  constructor(font) {
38470
38729
  __publicField(this, "gsub");
38730
+ __publicField(this, "gpos");
38471
38731
  this.font = font;
38472
- const raw = font.getRawTableData("GSUB");
38473
- this.gsub = raw ? GsubTable.parse(raw) : null;
38732
+ const gsubRaw = font.getRawTableData("GSUB");
38733
+ this.gsub = gsubRaw ? GsubTable.parse(gsubRaw) : null;
38734
+ const gposRaw = font.getRawTableData("GPOS");
38735
+ this.gpos = gposRaw ? GposTable.parse(gposRaw) : null;
38474
38736
  }
38475
- /** True when the font exposes a GSUB table the shaper could use. */
38737
+ /** True when the font exposes a GSUB table the substitution shaper could use. */
38476
38738
  get hasGsub() {
38477
38739
  return this.gsub !== null;
38478
38740
  }
38741
+ /** True when the font exposes a GPOS table the kerning shaper could use. */
38742
+ get hasGpos() {
38743
+ return this.gpos !== null;
38744
+ }
38745
+ /** True when either shaping table is present (so this layouter adds value). */
38746
+ get hasShaping() {
38747
+ return this.gsub !== null || this.gpos !== null;
38748
+ }
38479
38749
  layout(text, features) {
38480
38750
  const buffer = [];
38481
38751
  for (const char of text) {
@@ -38486,21 +38756,35 @@ class OpenTypeLayouter {
38486
38756
  codePoints: glyphId === 0 ? [65533] : [codePoint]
38487
38757
  });
38488
38758
  }
38489
- if (this.gsub && features && features.length > 0) {
38490
- this.gsub.shape(buffer, features);
38759
+ const gsubTags = (features == null ? void 0 : features.filter((tag) => !GPOS_FEATURE_TAGS.has(tag))) ?? [];
38760
+ const gposTags = (features == null ? void 0 : features.filter((tag) => GPOS_FEATURE_TAGS.has(tag))) ?? [];
38761
+ if (this.gsub && gsubTags.length > 0) {
38762
+ this.gsub.shape(buffer, gsubTags);
38763
+ }
38764
+ const advances = buffer.map(
38765
+ (glyph) => this.font.advanceWidthForGlyph(glyph.id)
38766
+ );
38767
+ if (this.gpos && gposTags.length > 0) {
38768
+ this.gpos.position(
38769
+ buffer.map((glyph) => glyph.id),
38770
+ advances,
38771
+ gposTags
38772
+ );
38491
38773
  }
38492
38774
  const glyphs = [];
38493
38775
  const positions = [];
38494
38776
  let advanceWidth = 0;
38495
- for (const glyph of buffer) {
38496
- const glyphAdvance = this.font.advanceWidthForGlyph(glyph.id);
38777
+ for (let i = 0; i < buffer.length; i += 1) {
38778
+ const glyph = buffer[i];
38779
+ const nominalAdvance = this.font.advanceWidthForGlyph(glyph.id);
38780
+ const positionedAdvance = advances[i];
38497
38781
  glyphs.push({
38498
38782
  id: glyph.id,
38499
38783
  codePoints: glyph.codePoints,
38500
- advanceWidth: glyphAdvance
38784
+ advanceWidth: nominalAdvance
38501
38785
  });
38502
- positions.push({ xAdvance: glyphAdvance });
38503
- advanceWidth += glyphAdvance;
38786
+ positions.push({ xAdvance: positionedAdvance });
38787
+ advanceWidth += positionedAdvance;
38504
38788
  }
38505
38789
  return { glyphs, positions, advanceWidth };
38506
38790
  }
@@ -38721,7 +39005,7 @@ function parseEmbeddedFontSync(sourceBytes) {
38721
39005
  }
38722
39006
  function createPdfEmbeddableFont(program) {
38723
39007
  const shaper = new OpenTypeLayouter(program);
38724
- const layouter = shaper.hasGsub ? shaper : new SimpleTextLayouter(program);
39008
+ const layouter = shaper.hasShaping ? shaper : new SimpleTextLayouter(program);
38725
39009
  return {
38726
39010
  program,
38727
39011
  layouter,
@@ -6,10 +6,15 @@ export declare function isDoubleUnderlineStyle(underlineStyle: UnderlineStyle):
6
6
  export declare function isWavyUnderlineStyle(underlineStyle: UnderlineStyle): boolean;
7
7
  export declare function underlineStyleLineWidthPx(underlineStyle: UnderlineStyle): number;
8
8
  /**
9
- * Resolves the OpenType GSUB feature tags a run explicitly enables, mirroring the
10
- * CSS semantics in `styleCss.ts` (only enabled features, no implicit liga/kern).
11
- * Used by the PDF shaper to drive glyph substitution. Returns a sorted, de-duped
12
- * array so it doubles as a stable cache key.
9
+ * Resolves the OpenType feature tags a run explicitly enables, mirroring the CSS
10
+ * semantics in `styleCss.ts` (only enabled features, no implicit defaults). Used
11
+ * by the PDF shaper to drive GSUB substitution and GPOS kerning. Returns a sorted,
12
+ * de-duped array so it doubles as a stable cache key.
13
+ *
14
+ * `fontSizePt` (the run's resolved point size) gates the GPOS `kern` tag the same
15
+ * way Word's `w:kern` threshold and the canvas painter do: kerning applies only
16
+ * when the run's size meets `kerningThreshold`. Omit it to resolve substitution
17
+ * tags alone.
13
18
  */
14
- export declare function resolveOpenTypeFeatureTags(style: EditorTextStyle): string[];
19
+ export declare function resolveOpenTypeFeatureTags(style: EditorTextStyle, fontSizePt?: number): string[];
15
20
  export declare function underlineStyleDashArray(underlineStyle: UnderlineStyle): number[] | undefined;
@@ -2519,7 +2519,7 @@ function OasisEditorAppLazy(props = {}) {
2519
2519
  onCleanup(() => {
2520
2520
  cancelled = true;
2521
2521
  });
2522
- import("./OasisEditorApp-kxR9P2nm.js").then((m) => {
2522
+ import("./OasisEditorApp-CRjXmvyC.js").then((m) => {
2523
2523
  cancelled = true;
2524
2524
  setProgress(1);
2525
2525
  setTimeout(() => setApp(() => m.OasisEditorApp), 180);
@@ -20934,7 +20934,7 @@ function underlineStyleLineWidthPx(underlineStyle) {
20934
20934
  return 1;
20935
20935
  }
20936
20936
  }
20937
- function resolveOpenTypeFeatureTags(style2) {
20937
+ function resolveOpenTypeFeatureTags(style2, fontSizePt) {
20938
20938
  const tags = /* @__PURE__ */ new Set();
20939
20939
  switch (style2.ligatures) {
20940
20940
  case "standard":
@@ -20959,6 +20959,9 @@ function resolveOpenTypeFeatureTags(style2) {
20959
20959
  tags.add(`ss${String(style2.stylisticSet).padStart(2, "0")}`);
20960
20960
  }
20961
20961
  if (style2.contextualAlternates) tags.add("calt");
20962
+ if (typeof fontSizePt === "number" && typeof style2.kerningThreshold === "number" && Number.isFinite(style2.kerningThreshold) && fontSizePt >= style2.kerningThreshold) {
20963
+ tags.add("kern");
20964
+ }
20962
20965
  return Array.from(tags).sort();
20963
20966
  }
20964
20967
  function underlineStyleDashArray(underlineStyle) {
@@ -1,4 +1,4 @@
1
- import { O, c8, c9, ca, cb, cc, a8, cd, Q, bT, ce, cf, cg, N, ch, bR, ci, cj, ck, cl, cm, c3, cn, co, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, ad, cz, c2, cA, ca as ca2, cf as cf2, ch as ch2, cq as cq2, cs as cs2, cx as cx2, cB, bV, bQ, cC, cD, cE, bS, cF, cG, bU } from "./index-CNuDp_SC.js";
1
+ import { O, c8, c9, ca, cb, cc, a8, cd, Q, bT, ce, cf, cg, N, ch, bR, ci, cj, ck, cl, cm, c3, cn, co, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, ad, cz, c2, cA, ca as ca2, cf as cf2, ch as ch2, cq as cq2, cs as cs2, cx as cx2, cB, bV, bQ, cC, cD, cE, bS, cF, cG, bU } from "./index-BuxYvaSC.js";
2
2
  export {
3
3
  O as BalloonShell,
4
4
  c8 as Button,