@office-kit/pptx-preview 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,6 +42,28 @@ const svg = renderSlideToSvg(pres, getSlides(pres)[0]);
42
42
  // → '<svg …>…</svg>' (text laid out via <foreignObject> — the browser wraps it)
43
43
  ```
44
44
 
45
+ Pass `{ textLayout: 'svg', measureText }` to lay text out as pure SVG
46
+ `<text>` instead of `<foreignObject>` (for example when the SVG is shown as an
47
+ `<img>` or sanitized). In that mode each run's font is replaced with one of the
48
+ bundled metric-compatible substitutes (`substituteFamily`: Carlito, Caladea,
49
+ Liberation Sans / Serif / Mono). To keep a family the viewer can load — say
50
+ through `@font-face` rules you embed in the SVG — pass `resolveFamily`, and a
51
+ `measureText` that knows that font's metrics so line breaks match its glyphs
52
+ (in a browser, for example, one that wraps `CanvasRenderingContext2D.measureText`
53
+ once the font has loaded). Return a single family name; the renderer quotes it
54
+ in the SVG when CSS requires that:
55
+
56
+ ```ts
57
+ import { renderSlideToSvg, substituteFamily } from '@office-kit/pptx-preview';
58
+
59
+ const svg = renderSlideToSvg(pres, slide, {
60
+ textLayout: 'svg',
61
+ measureText,
62
+ resolveFamily: (family) =>
63
+ family === 'Lora' || family === 'Inter' ? family : substituteFamily(family),
64
+ });
65
+ ```
66
+
45
67
  `renderSlideLayoutToSvg(pres, layout, { master })` draws what a slide master
46
68
  editor shows behind the placeholders: the layout's background and decorative
47
69
  shapes over its master's (the master's are left out when the layout hides
@@ -2,8 +2,10 @@ import { BulletStyle, PresentationData, SlideData, SlideLayoutData, SlideShapeDa
2
2
 
3
3
  //#region src/text-layout.d.ts
4
4
  /** What a measurer needs to size one run. Pixels at 96 DPI; the caller has
5
- * already applied EMU→px, pt→px and the autofit fontScale. `family` is the
6
- * resolved internal family name (see `substituteFamily`), not a CSS list. */
5
+ * already applied EMU→px, pt→px and the autofit fontScale. `family` is a
6
+ * single family name, not a CSS list: what `RenderSlideOptions.resolveFamily`
7
+ * returned, by default a bundled substitute (see `substituteFamily`). The
8
+ * text audit passes the authored name instead. */
7
9
  interface FontSpec {
8
10
  readonly family: string;
9
11
  readonly sizePx: number;
@@ -45,6 +47,17 @@ interface RenderSlideOptions {
45
47
  /** `false` paints only the slide's own shapes on a transparent surface:
46
48
  * no background fill and no master or layout graphics. Defaults to `true`. */
47
49
  readonly background?: boolean;
50
+ /** Maps an authored font name (a run's font, a bullet font, or the theme
51
+ * face; `null` when none applies) to the family written to the SVG's
52
+ * `<text font-family>` and handed to `measureText`. Return one family name,
53
+ * unquoted; the renderer quotes it in the SVG when CSS requires that. Only consulted when
54
+ * `textLayout` is `'svg'`; the foreignObject path writes the authored name
55
+ * into a CSS font stack itself. Defaults to `substituteFamily`, which maps
56
+ * every family to one of the bundled metric-compatible substitutes. Keep a
57
+ * family only when the SVG's viewer can load it (for example through an
58
+ * `@font-face` rule the host embeds), and pair it with a `measureText` that
59
+ * knows its metrics so line breaks match the glyphs. */
60
+ readonly resolveFamily?: (family: string | null) => string;
48
61
  }
49
62
  declare const SANS = "Carlito";
50
63
  declare const SERIF = "Caladea";
@@ -226,7 +239,9 @@ interface ShapeAutoFitScaleOptions {
226
239
  };
227
240
  /** Measurer for run widths, defaulting to the heuristic one the renderer
228
241
  * uses in a browser. Pass the same measurer the render call uses, or the
229
- * two disagree about how much text fits. */
242
+ * two disagree about how much text fits. Families are resolved with
243
+ * `substituteFamily`, as the foreignObject render does; an svg render
244
+ * with its own `resolveFamily` can measure a different face. */
230
245
  readonly measureText?: TextMeasurer;
231
246
  }
232
247
  /**
@@ -257,4 +272,4 @@ declare function shapeTextAnchorOffset(pres: PresentationData, shape: SlideShape
257
272
  declare function textUnderlineStyle(underline: TextFormat['underline'], color: string, includeDecorationColor?: boolean): string;
258
273
  //#endregion
259
274
  export { substituteFamily as A, RenderSlideOptions as C, TextLayoutMode as D, TIMES as E, TextMeasurer as O, MeasureResult as S, SERIF as T, renderSlideSvg as _, VerticalTextStyle as a, FontSpec as b, TextRectFractions as c, decimalSeparatorOf as d, paragraphNumberLabels as f, renderSlideLayoutSvg as g, auditTextLayout as h, shapeTextAnchorOffset as i, defaultMeasurer as k, resolveTextBodyRect as l, TextAuditIssue as m, ShapeAutoFitScaleOptions as n, textColumnsStyle as o, AuditTextLayoutOptions as p, shapeAutoFitScale as r, verticalTextStyle as s, textUnderlineStyle as t, shapeTextRect as u, renderTextEffectsSvg as v, SANS as w, MONO as x, ARIAL as y };
260
- //# sourceMappingURL=index-74n14k3Y.d.ts.map
275
+ //# sourceMappingURL=index-D1r4NkUr.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as substituteFamily, C as RenderSlideOptions, D as TextLayoutMode, E as TIMES, O as TextMeasurer, S as MeasureResult, T as SERIF, _ as renderSlideSvg, a as VerticalTextStyle, b as FontSpec, c as TextRectFractions, d as decimalSeparatorOf, f as paragraphNumberLabels, g as renderSlideLayoutSvg, h as auditTextLayout, i as shapeTextAnchorOffset, k as defaultMeasurer, l as resolveTextBodyRect, m as TextAuditIssue, n as ShapeAutoFitScaleOptions, o as textColumnsStyle, p as AuditTextLayoutOptions, r as shapeAutoFitScale, s as verticalTextStyle, t as textUnderlineStyle, u as shapeTextRect, v as renderTextEffectsSvg, w as SANS, x as MONO, y as ARIAL } from "./index-74n14k3Y.js";
1
+ import { A as substituteFamily, C as RenderSlideOptions, D as TextLayoutMode, E as TIMES, O as TextMeasurer, S as MeasureResult, T as SERIF, _ as renderSlideSvg, a as VerticalTextStyle, b as FontSpec, c as TextRectFractions, d as decimalSeparatorOf, f as paragraphNumberLabels, g as renderSlideLayoutSvg, h as auditTextLayout, i as shapeTextAnchorOffset, k as defaultMeasurer, l as resolveTextBodyRect, m as TextAuditIssue, n as ShapeAutoFitScaleOptions, o as textColumnsStyle, p as AuditTextLayoutOptions, r as shapeAutoFitScale, s as verticalTextStyle, t as textUnderlineStyle, u as shapeTextRect, v as renderTextEffectsSvg, w as SANS, x as MONO, y as ARIAL } from "./index-D1r4NkUr.js";
2
2
  export { ARIAL, type AuditTextLayoutOptions, type FontSpec, MONO, type MeasureResult, type RenderSlideOptions, SANS, SERIF, type ShapeAutoFitScaleOptions, TIMES, type TextAuditIssue, type TextLayoutMode, type TextMeasurer, type TextRectFractions, type VerticalTextStyle, auditTextLayout, decimalSeparatorOf, defaultMeasurer, paragraphNumberLabels, renderSlideLayoutSvg as renderSlideLayoutToSvg, renderSlideSvg as renderSlideToSvg, renderTextEffectsSvg, resolveTextBodyRect, shapeAutoFitScale, shapeTextAnchorOffset, shapeTextRect, substituteFamily, textColumnsStyle, textUnderlineStyle, verticalTextStyle };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { S as shapeTextRect, _ as paragraphNumberLabels, a as renderSlideSvg, b as verticalTextStyle, d as SERIF, f as TIMES, g as decimalSeparatorOf, h as substituteFamily, i as renderSlideLayoutSvg, l as MONO, n as shapeTextAnchorOffset, o as renderTextEffectsSvg, p as defaultMeasurer, r as auditTextLayout, s as ARIAL, t as shapeAutoFitScale, u as SANS, v as textUnderlineStyle, x as resolveTextBodyRect, y as textColumnsStyle } from "./src-pb3C61GD.js";
1
+ import { S as shapeTextRect, _ as paragraphNumberLabels, a as renderSlideSvg, b as verticalTextStyle, d as SERIF, f as TIMES, g as decimalSeparatorOf, h as substituteFamily, i as renderSlideLayoutSvg, l as MONO, n as shapeTextAnchorOffset, o as renderTextEffectsSvg, p as defaultMeasurer, r as auditTextLayout, s as ARIAL, t as shapeAutoFitScale, u as SANS, v as textUnderlineStyle, x as resolveTextBodyRect, y as textColumnsStyle } from "./src-u1-ERSHC.js";
2
2
  export { ARIAL, MONO, SANS, SERIF, TIMES, auditTextLayout, decimalSeparatorOf, defaultMeasurer, paragraphNumberLabels, renderSlideLayoutSvg as renderSlideLayoutToSvg, renderSlideSvg as renderSlideToSvg, renderTextEffectsSvg, resolveTextBodyRect, shapeAutoFitScale, shapeTextAnchorOffset, shapeTextRect, substituteFamily, textColumnsStyle, textUnderlineStyle, verticalTextStyle };
package/dist/node.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as substituteFamily, C as RenderSlideOptions, D as TextLayoutMode, E as TIMES, O as TextMeasurer, S as MeasureResult, T as SERIF, _ as renderSlideSvg, a as VerticalTextStyle, b as FontSpec, c as TextRectFractions, d as decimalSeparatorOf, f as paragraphNumberLabels, g as renderSlideLayoutSvg, h as auditTextLayout, i as shapeTextAnchorOffset, k as defaultMeasurer, l as resolveTextBodyRect, m as TextAuditIssue, n as ShapeAutoFitScaleOptions, o as textColumnsStyle, p as AuditTextLayoutOptions, r as shapeAutoFitScale, s as verticalTextStyle, t as textUnderlineStyle, u as shapeTextRect, v as renderTextEffectsSvg, w as SANS, x as MONO, y as ARIAL } from "./index-74n14k3Y.js";
1
+ import { A as substituteFamily, C as RenderSlideOptions, D as TextLayoutMode, E as TIMES, O as TextMeasurer, S as MeasureResult, T as SERIF, _ as renderSlideSvg, a as VerticalTextStyle, b as FontSpec, c as TextRectFractions, d as decimalSeparatorOf, f as paragraphNumberLabels, g as renderSlideLayoutSvg, h as auditTextLayout, i as shapeTextAnchorOffset, k as defaultMeasurer, l as resolveTextBodyRect, m as TextAuditIssue, n as ShapeAutoFitScaleOptions, o as textColumnsStyle, p as AuditTextLayoutOptions, r as shapeAutoFitScale, s as verticalTextStyle, t as textUnderlineStyle, u as shapeTextRect, v as renderTextEffectsSvg, w as SANS, x as MONO, y as ARIAL } from "./index-D1r4NkUr.js";
2
2
  import { PresentationData, SlideData } from "@office-kit/pptx";
3
3
 
4
4
  //#region src/measure.d.ts
package/dist/node.js CHANGED
@@ -1,4 +1,4 @@
1
- import { S as shapeTextRect, _ as paragraphNumberLabels, a as renderSlideSvg, b as verticalTextStyle, c as AVG_GLYPH_W_RATIO, d as SERIF, f as TIMES, g as decimalSeparatorOf, h as substituteFamily, i as renderSlideLayoutSvg, l as MONO, m as isCjk, n as shapeTextAnchorOffset, o as renderTextEffectsSvg, p as defaultMeasurer, r as auditTextLayout, s as ARIAL, t as shapeAutoFitScale, u as SANS, v as textUnderlineStyle, x as resolveTextBodyRect, y as textColumnsStyle } from "./src-pb3C61GD.js";
1
+ import { S as shapeTextRect, _ as paragraphNumberLabels, a as renderSlideSvg, b as verticalTextStyle, c as AVG_GLYPH_W_RATIO, d as SERIF, f as TIMES, g as decimalSeparatorOf, h as substituteFamily, i as renderSlideLayoutSvg, l as MONO, m as isCjk, n as shapeTextAnchorOffset, o as renderTextEffectsSvg, p as defaultMeasurer, r as auditTextLayout, s as ARIAL, t as shapeAutoFitScale, u as SANS, v as textUnderlineStyle, x as resolveTextBodyRect, y as textColumnsStyle } from "./src-u1-ERSHC.js";
2
2
  import { getSlideSize } from "@office-kit/pptx";
3
3
  import { Resvg } from "@resvg/resvg-js";
4
4
  import * as fontkit from "fontkit";
@@ -564,6 +564,8 @@ const escapeXml$1 = (s) => s.replace(/[&<>"]/g, (c) => ({
564
564
  ">": "&gt;",
565
565
  "\"": "&quot;"
566
566
  })[c] ?? c);
567
+ const CSS_IDENT = /^-?[A-Za-z_\u0080-\u{10FFFF}][\w\u0080-\u{10FFFF}-]*$/u;
568
+ const cssFamilyName = (family) => family.split(" ").every((word) => CSS_IDENT.test(word)) ? family : `"${family.replace(/["\\]/g, "\\$&")}"`;
567
569
  const fmt = (n) => {
568
570
  const r = Math.round(n * 100) / 100;
569
571
  return Object.is(r, -0) ? "0" : String(r);
@@ -1015,7 +1017,7 @@ const emitPlacements = (placements, effectsOnly = false, effectKind = "all") =>
1015
1017
  if (line.bullet && !effectsOnly) {
1016
1018
  const b = line.bullet.b;
1017
1019
  if (b.imageHref) parts.push(`<image x="${fmt(line.bullet.x + dx + GRID_NUDGE_X)}" y="${fmt(baselineY - b.sizePx)}" width="${fmt(b.sizePx)}" height="${fmt(b.sizePx)}" href="${b.imageHref}" xlink:href="${b.imageHref}" preserveAspectRatio="xMidYMid meet"/>`);
1018
- else parts.push(`<text x="${fmt(line.bullet.x + dx + GRID_NUDGE_X)}" y="${fmt(baselineY)}" font-family="${escapeXml$1(b.family)}" font-size="${fmt(b.sizePx)}" fill="${b.fillHex}" xml:space="preserve">${escapeXml$1(b.text)}</text>`);
1020
+ else parts.push(`<text x="${fmt(line.bullet.x + dx + GRID_NUDGE_X)}" y="${fmt(baselineY)}" font-family="${escapeXml$1(b.cssFamily ?? b.family)}" font-size="${fmt(b.sizePx)}" fill="${b.fillHex}" xml:space="preserve">${escapeXml$1(b.text)}</text>`);
1019
1021
  }
1020
1022
  parts.push(emitLine(line, baselineY, dx, line.descent, (kind) => nextEffectId(kind), effectsOnly, effectKind));
1021
1023
  }
@@ -1376,7 +1378,7 @@ const tspan = (g) => {
1376
1378
  const p = g.piece;
1377
1379
  const sizePx = renderedSizePxOf(p);
1378
1380
  const attrs = [
1379
- `font-family="${escapeXml$1(p.family)}"`,
1381
+ `font-family="${escapeXml$1(p.cssFamily ?? p.family)}"`,
1380
1382
  `font-size="${fmt(sizePx)}"`,
1381
1383
  `fill="${p.fillHex}"`
1382
1384
  ];
@@ -1714,6 +1716,10 @@ const DEFAULT_BODY_PT = 18;
1714
1716
  const DEFAULT_TITLE_PT = 44;
1715
1717
  const DEFAULT_FONT = "Calibri, 'Helvetica Neue', Arial, sans-serif";
1716
1718
  const browserFontFamily = (family) => family ? `${JSON.stringify(family)}, ${DEFAULT_FONT}` : DEFAULT_FONT;
1719
+ const BROWSER_FAMILIES = {
1720
+ resolveFamily: browserFontFamily,
1721
+ familyIsCssList: true
1722
+ };
1717
1723
  const DEFAULT_BULLET_FONT = "Arial";
1718
1724
  const DEFAULT_INSET_X = 91440;
1719
1725
  const DEFAULT_INSET_Y = 45720;
@@ -2557,6 +2563,13 @@ const smallCapsParts = (text, base) => {
2557
2563
  flush();
2558
2564
  return parts;
2559
2565
  };
2566
+ const faceOf = (a, font) => {
2567
+ const family = (a.resolveFamily ?? substituteFamily)(font);
2568
+ return a.familyIsCssList ? { family } : {
2569
+ family,
2570
+ cssFamily: cssFamilyName(family)
2571
+ };
2572
+ };
2560
2573
  const buildSvgTextInput = (a) => {
2561
2574
  const scale = a.autoFitScale;
2562
2575
  const paragraphs = a.paraData.map((para, pi) => {
@@ -2565,7 +2578,7 @@ const buildSvgTextInput = (a) => {
2565
2578
  if (run.text === "\n") {
2566
2579
  pieces.push({
2567
2580
  ...breakPiece(),
2568
- family: (a.resolveFamily ?? substituteFamily)(run.fmt?.font ?? a.themeFace),
2581
+ ...faceOf(a, run.fmt?.font ?? a.themeFace),
2569
2582
  sizePx: run.sizePt * scale * PX_PER_PT,
2570
2583
  bold: run.fmt?.bold ?? false,
2571
2584
  italic: run.fmt?.italic ?? false
@@ -2581,7 +2594,7 @@ const buildSvgTextInput = (a) => {
2581
2594
  underline: fmt?.underline ?? true
2582
2595
  };
2583
2596
  }
2584
- const family = (a.resolveFamily ?? substituteFamily)(fmt?.font ?? a.themeFace);
2597
+ const face = faceOf(a, fmt?.font ?? a.themeFace);
2585
2598
  const sizePx = run.sizePt * scale * PX_PER_PT;
2586
2599
  const fillHex = fmt?.color !== void 0 && fmt.color !== null ? resolveColor(fmt.color, a.theme, "#000000") : a.defaultColor;
2587
2600
  const baseline = fmt?.baseline ?? 0;
@@ -2590,7 +2603,7 @@ const buildSvgTextInput = (a) => {
2590
2603
  const cap = fmt?.cap;
2591
2604
  const caps = cap === "all" || cap === "small";
2592
2605
  const base = {
2593
- family,
2606
+ ...face,
2594
2607
  sizePx,
2595
2608
  bold: fmt?.bold ?? false,
2596
2609
  italic: fmt?.italic ?? false,
@@ -2736,10 +2749,9 @@ const buildBullet = (a, para, pi) => {
2736
2749
  const baseSizePx = (para.runs.find((r) => r.text !== "\n" && r.text !== "")?.sizePt ?? a.defaultPt) * PX_PER_PT * a.autoFitScale;
2737
2750
  const sizePx = para.bulletDetail.sizePct !== null ? baseSizePx * para.bulletDetail.sizePct : para.bulletDetail.sizePts !== null ? para.bulletDetail.sizePts * PX_PER_PT * a.autoFitScale : baseSizePx;
2738
2751
  const fillHex = bulletFillOf(para, a.theme, a.defaultColor);
2739
- const bulletFont = para.bulletDetail.fontFollowText ? para.runs.find((r) => r.text !== "\n" && r.text !== "")?.fmt?.font ?? DEFAULT_BULLET_FONT : para.bulletDetail.font ?? DEFAULT_BULLET_FONT;
2740
2752
  return {
2741
2753
  text: char,
2742
- family: (a.resolveFamily ?? substituteFamily)(bulletFont),
2754
+ ...faceOf(a, para.bulletDetail.fontFollowText ? para.runs.find((r) => r.text !== "\n" && r.text !== "")?.fmt?.font ?? DEFAULT_BULLET_FONT : para.bulletDetail.font ?? DEFAULT_BULLET_FONT),
2743
2755
  sizePx,
2744
2756
  fillHex,
2745
2757
  ...para.bulletImageHref ? { imageHref: para.bulletImageHref } : {}
@@ -2750,7 +2762,7 @@ const bulletFillOf = (para, theme, defaultColor) => {
2750
2762
  const runColor = para.runs.find((r) => r.text !== "\n" && r.text !== "")?.fmt?.color;
2751
2763
  return runColor === void 0 || runColor === null ? defaultColor : resolveColor(runColor, theme, defaultColor);
2752
2764
  };
2753
- const resolveTextBodyModel = (pres, shape, bounds, theme, phType, measure, defaultColor, useSvgTextRect = false) => {
2765
+ const resolveTextBodyModel = (pres, shape, bounds, theme, phType, measure, defaultColor, useSvgTextRect = false, resolveFamily = substituteFamily) => {
2754
2766
  let paragraphCount;
2755
2767
  try {
2756
2768
  paragraphCount = getShapeParagraphCount(shape);
@@ -2969,7 +2981,8 @@ const resolveTextBodyModel = (pres, shape, bounds, theme, phType, measure, defau
2969
2981
  innerH: fitRect.h,
2970
2982
  measure,
2971
2983
  vert: fitVert,
2972
- columns: fitColumns
2984
+ columns: fitColumns,
2985
+ resolveFamily
2973
2986
  };
2974
2987
  let s = 1;
2975
2988
  while (s > AUTOFIT_FLOOR) {
@@ -3009,6 +3022,7 @@ const resolveTextBodyModel = (pres, shape, bounds, theme, phType, measure, defau
3009
3022
  measure,
3010
3023
  vert,
3011
3024
  autoFitScale,
3025
+ resolveFamily,
3012
3026
  columns: vert === "none" && cols && cols.count >= 2 ? {
3013
3027
  count: cols.count,
3014
3028
  gapPx: cols.gapEmu !== void 0 ? cols.gapEmu / EMU_PER_PX : 0
@@ -3126,7 +3140,7 @@ const renderHtmlParagraphs = (paraData, numberLabels, theme, autoFitScale, defau
3126
3140
  return paragraphs;
3127
3141
  };
3128
3142
  const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body") => {
3129
- const model = resolveTextBodyModel(pres, shape, bounds, theme, phType, ctx.measure, activeDeckTextColor, ctx.mode === "svg" && output === "body");
3143
+ const model = resolveTextBodyModel(pres, shape, bounds, theme, phType, ctx.measure, activeDeckTextColor, ctx.mode === "svg" && output === "body", ctx.resolveFamily);
3130
3144
  if (model === null) return "";
3131
3145
  const bevel = textBevelOf(getShapeText3D(shape));
3132
3146
  const { paraData, numberLabels, authoredAutofit, autoFitScale, defaultPt, themeFace, effectiveDefaultFont, effectiveBody, anchor, innerX, innerY, innerW, innerH, svgTextRect } = model;
@@ -3162,7 +3176,7 @@ const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body"
3162
3176
  innerW: vInnerW,
3163
3177
  innerH: vInnerH,
3164
3178
  measure: ctx.mode === "svg" ? ctx.measure : browserTextMeasurer() ?? ctx.measure,
3165
- ...ctx.mode === "foreignObject" ? { resolveFamily: browserFontFamily } : {},
3179
+ ...ctx.mode === "foreignObject" ? BROWSER_FAMILIES : { resolveFamily: ctx.resolveFamily },
3166
3180
  vert: svgVert,
3167
3181
  columns: svgColumns,
3168
3182
  bevel
@@ -3172,7 +3186,7 @@ const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body"
3172
3186
  ...svgArgsBase,
3173
3187
  autoFitScale: authoredAutofit ? autoFitScale : 1,
3174
3188
  effectsOnly: true,
3175
- resolveFamily: browserFontFamily
3189
+ ...BROWSER_FAMILIES
3176
3190
  };
3177
3191
  const effects = [
3178
3192
  paraData.some((para) => para.runs.some((run) => run.fmt?.reflection != null)) ? buildAndLayoutSvgText({
@@ -3253,7 +3267,7 @@ const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body"
3253
3267
  vert: svgVert,
3254
3268
  columns: null,
3255
3269
  effectsOnly: true,
3256
- resolveFamily: browserFontFamily,
3270
+ ...BROWSER_FAMILIES,
3257
3271
  bevel
3258
3272
  };
3259
3273
  const hasCharacterReflection = paraData.some((para) => para.runs.some((run) => run.fmt?.reflection !== void 0 && run.fmt.reflection !== null));
@@ -3310,6 +3324,7 @@ const renderTextEffectsSvg = (pres, slide, shape, bounds, opts = {}) => {
3310
3324
  groupReflected: false,
3311
3325
  mode: "foreignObject",
3312
3326
  measure: opts.measureText ?? browserTextMeasurer() ?? defaultMeasurer,
3327
+ resolveFamily: substituteFamily,
3313
3328
  ownShapes: true,
3314
3329
  background: {
3315
3330
  id: "",
@@ -3346,6 +3361,7 @@ const renderTableCellEffectsSvgInternal = (pres, slide, shape, cellPosition, bou
3346
3361
  groupReflected: false,
3347
3362
  mode: "foreignObject",
3348
3363
  measure: opts.measureText ?? browserTextMeasurer() ?? defaultMeasurer,
3364
+ resolveFamily: substituteFamily,
3349
3365
  ownShapes: true,
3350
3366
  background: {
3351
3367
  id: "",
@@ -4841,7 +4857,7 @@ const renderTableCellText = (cell, paragraphs, cx, cy, cw, ch, color, pres, shap
4841
4857
  innerW: innerW * EMU_PER_PX,
4842
4858
  innerH: innerH * EMU_PER_PX,
4843
4859
  measure: ctx.mode === "svg" ? ctx.measure : browserTextMeasurer() ?? ctx.measure,
4844
- ...ctx.mode === "foreignObject" ? { resolveFamily: browserFontFamily } : {},
4860
+ ...ctx.mode === "foreignObject" ? BROWSER_FAMILIES : { resolveFamily: ctx.resolveFamily },
4845
4861
  vert: verticalLayoutOf(getTableCellTextDirection(cell)),
4846
4862
  columns: null,
4847
4863
  ...effectsOnly ? { effectsOnly: true } : {},
@@ -5720,6 +5736,7 @@ const renderSurface = (pres, surface, opts) => {
5720
5736
  groupReflected: false,
5721
5737
  mode: opts.textLayout ?? "foreignObject",
5722
5738
  measure: opts.measureText ?? defaultMeasurer,
5739
+ resolveFamily: opts.textLayout === "svg" ? opts.resolveFamily ?? substituteFamily : substituteFamily,
5723
5740
  ownShapes: true,
5724
5741
  background: {
5725
5742
  id: "",
@@ -5865,7 +5882,7 @@ const auditShape = (pres, theme, shape, slideIndex, measure, tolerancePx, report
5865
5882
  y: bounds.y,
5866
5883
  w: bounds.w,
5867
5884
  h: bounds.h
5868
- }, theme, getShapePlaceholderType(shape), measure, "#000000");
5885
+ }, theme, getShapePlaceholderType(shape), measure, "#000000", false, passthroughFamily);
5869
5886
  if (model === null) return;
5870
5887
  const vert = verticalLayoutOf(model.effectiveBody.vert ?? getShapeTextDirection(shape));
5871
5888
  const cols = model.effectiveBody.columns;
@@ -6043,4 +6060,4 @@ function shapeTextAnchorOffset(pres, shape, options = {}) {
6043
6060
  //#endregion
6044
6061
  export { shapeTextRect as S, paragraphNumberLabels as _, renderSlideSvg as a, verticalTextStyle as b, AVG_GLYPH_W_RATIO as c, SERIF as d, TIMES as f, decimalSeparatorOf as g, substituteFamily as h, renderSlideLayoutSvg as i, MONO as l, isCjk as m, shapeTextAnchorOffset as n, renderTextEffectsSvg as o, defaultMeasurer as p, auditTextLayout as r, ARIAL as s, shapeAutoFitScale as t, SANS as u, textUnderlineStyle as v, resolveTextBodyRect as x, textColumnsStyle as y };
6045
6062
 
6046
- //# sourceMappingURL=src-pb3C61GD.js.map
6063
+ //# sourceMappingURL=src-u1-ERSHC.js.map