@office-kit/pptx-preview 0.19.0 → 0.21.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.
@@ -1058,6 +1058,30 @@ const emitPlacements = (placements, effectsOnly = false, effectKind = "all") =>
1058
1058
  close();
1059
1059
  return paragraphs.join("");
1060
1060
  };
1061
+ const familyOf = (g) => g.piece.cssFamily ?? g.piece.family;
1062
+ const lineText = (groups, textAnchor, x0, span) => {
1063
+ if (new Set(groups.filter((g) => !g.isTab).map(familyOf)).size < 2 || !groups.some((g) => EAST_ASIAN_CHAR.test(g.text))) return {
1064
+ x: x0,
1065
+ anchor: textAnchor,
1066
+ body: groups.map((g) => span(g)).join("")
1067
+ };
1068
+ const totalWidth = groups.reduce((sum, g) => sum + g.width, 0);
1069
+ const start = x0 - (textAnchor === "middle" ? totalWidth / 2 : textAnchor === "end" ? totalWidth : 0);
1070
+ let cursor = start;
1071
+ let family = null;
1072
+ const parts = [];
1073
+ for (const g of groups) {
1074
+ const changes = !g.isTab && familyOf(g) !== family;
1075
+ parts.push(span(g, changes && family !== null ? cursor : void 0));
1076
+ if (changes) family = familyOf(g);
1077
+ cursor += g.width;
1078
+ }
1079
+ return {
1080
+ x: start,
1081
+ anchor: "start",
1082
+ body: parts.join("")
1083
+ };
1084
+ };
1061
1085
  const topPad = (line) => {
1062
1086
  const lead = line.advance - (line.ascent + line.descent);
1063
1087
  return lead > 0 ? lead / 2 : 0;
@@ -1076,24 +1100,25 @@ const emitLine = (line, baselineY, dx, descent, nextEffectId, effectsOnly, effec
1076
1100
  const content = toks.filter((t) => !t.isBreak);
1077
1101
  if (content.length === 0) return "";
1078
1102
  const groups = groupTokens(content);
1079
- const tspans = groups.map((g) => {
1080
- const span = tspan(g);
1103
+ const x0 = line.anchorX + dx + GRID_NUDGE_X;
1104
+ const linked = lineText(groups, line.textAnchor, x0, (g, x) => {
1105
+ const span = tspan(g, x);
1081
1106
  const href = g.piece.href ? safeLinkHref(g.piece.href) : void 0;
1082
1107
  if (!href) return span;
1083
1108
  const target = href.startsWith("#") ? "" : " target=\"_blank\" rel=\"noopener noreferrer\"";
1084
1109
  const title = g.piece.hrefTip ? `<title>${escapeXml$1(g.piece.hrefTip)}</title>` : "";
1085
1110
  return `<a href="${escapeXml$1(href)}"${target}>${title}${span}</a>`;
1086
- }).join("");
1087
- if (tspans === "") return "";
1088
- const x0 = line.anchorX + dx + GRID_NUDGE_X;
1089
- const text = `<text x="${fmt(x0)}" y="${fmt(baselineY)}" text-anchor="${line.textAnchor}" xml:space="preserve">${tspans}</text>`;
1111
+ });
1112
+ if (linked.body === "") return "";
1113
+ const text = `<text x="${fmt(linked.x)}" y="${fmt(baselineY)}" text-anchor="${linked.anchor}" xml:space="preserve">${linked.body}</text>`;
1090
1114
  if (effectsOnly && effectKind === "fill") {
1091
1115
  const painted = groups.map((g) => g.piece.fillPaint ? g : {
1092
1116
  ...g,
1093
1117
  piece: unpaintedPiece(g.piece)
1094
1118
  });
1095
1119
  if (!painted.some((g) => g.piece.fillPaint)) return "";
1096
- const glyphs = `<text x="${fmt(x0)}" y="${fmt(baselineY)}" text-anchor="${line.textAnchor}" xml:space="preserve" aria-hidden="true" pointer-events="none">${painted.map(tspan).join("")}</text>`;
1120
+ const paintedText = lineText(painted, line.textAnchor, x0, tspan);
1121
+ const glyphs = `<text x="${fmt(paintedText.x)}" y="${fmt(baselineY)}" text-anchor="${paintedText.anchor}" xml:space="preserve" aria-hidden="true" pointer-events="none">${paintedText.body}</text>`;
1097
1122
  return emitTextOuterEffects(painted, line.textAnchor, x0, baselineY, nextEffectId) + glyphs + emitTextDecorations(painted, line.textAnchor, x0, baselineY);
1098
1123
  }
1099
1124
  const reflections = effectKind === "reflection" || effectKind === "all" ? emitTextReflections(groups, line.textAnchor, x0, baselineY, descent, nextEffectId) : "";
@@ -1258,11 +1283,11 @@ const emitTextBevel = (groups, textAnchor, x0, baselineY, nextId) => {
1258
1283
  const light = `<feDistantLight azimuth="${fmt(bevel.azimuthDeg)}" elevation="${fmt(bevel.elevationDeg)}"/>`;
1259
1284
  const specular = bevel.specular ? `<feSpecularLighting in="bevelHeight" surfaceScale="${fmt(surfaceScale)}" specularConstant="${fmt(bevel.specular.constant)}" specularExponent="${fmt(bevel.specular.exponent)}" lighting-color="#fff" result="bevelSpecular">${light}</feSpecularLighting>` : "";
1260
1285
  const defs = `<defs><filter id="${id}" x="-25%" y="-25%" width="150%" height="150%" color-interpolation-filters="sRGB" data-pptx-bevel="1"><feGaussianBlur in="SourceAlpha" stdDeviation="${fmt(widthPx / 2)}" result="bevelBlur"/><feComponentTransfer in="bevelBlur" result="bevelHeight"><feFuncA type="table" tableValues="${table.map(fmt).join(" ")}"/></feComponentTransfer><feDiffuseLighting in="bevelHeight" surfaceScale="${fmt(surfaceScale)}" diffuseConstant="1" lighting-color="#fff" result="bevelDiffuse">${light}</feDiffuseLighting><feColorMatrix in="bevelDiffuse" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ${fmt(lightGain)} 0 0 0 ${fmt(-lightGain * flat)}" result="bevelLight"/><feColorMatrix in="bevelDiffuse" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ${fmt(-shadeGain)} 0 0 0 ${fmt(shadeGain * flat)}" result="bevelShade"/>` + specular + `<feMerge result="bevelMerged"><feMergeNode in="bevelShade"/><feMergeNode in="bevelLight"/>${specular ? "<feMergeNode in=\"bevelSpecular\"/>" : ""}</feMerge><feComposite in="bevelMerged" in2="SourceAlpha" operator="in"/></filter></defs>`;
1261
- const beveled = groups.map((g) => g.piece.bevel && !g.isTab ? g : {
1286
+ const beveledText = lineText(groups.map((g) => g.piece.bevel && !g.isTab ? g : {
1262
1287
  ...g,
1263
1288
  piece: unpaintedPiece(g.piece)
1264
- });
1265
- return `${defs}<text x="${fmt(x0)}" y="${fmt(baselineY)}" text-anchor="${textAnchor}" xml:space="preserve" filter="url(#${id})" aria-hidden="true" pointer-events="none" data-pptx-bevel="text">${beveled.map(tspan).join("")}</text>`;
1289
+ }), textAnchor, x0, tspan);
1290
+ return `${defs}<text x="${fmt(beveledText.x)}" y="${fmt(baselineY)}" text-anchor="${beveledText.anchor}" xml:space="preserve" filter="url(#${id})" aria-hidden="true" pointer-events="none" data-pptx-bevel="text">${beveledText.body}</text>`;
1266
1291
  };
1267
1292
  const baselineShiftPxOf = (p) => p.sizePx * p.baseline;
1268
1293
  const SUPER_SUB_SIZE_RATIO = .65;
@@ -1408,11 +1433,12 @@ const sameGlow = (a, b) => {
1408
1433
  return a.color === b.color && a.radiusEmu === b.radiusEmu && a.opacity === b.opacity;
1409
1434
  };
1410
1435
  const samePiece = (a, b) => a.family === b.family && a.sizePx === b.sizePx && a.bold === b.bold && a.italic === b.italic && a.letterSpacingPx === b.letterSpacingPx && a.kerning === b.kerning && a.fillHex === b.fillHex && a.outlineHex === b.outlineHex && a.outlineWidthPx === b.outlineWidthPx && a.underlineHex === b.underlineHex && a.highlightHex === b.highlightHex && a.underline === b.underline && a.strike === b.strike && a.baseline === b.baseline && a.smallCaps === b.smallCaps && sameShadow(a.shadow, b.shadow) && sameGlow(a.glow, b.glow) && sameInnerShadow(a.innerShadow, b.innerShadow) && sameReflection(a.reflection, b.reflection) && a.href === b.href && a.hrefTip === b.hrefTip;
1411
- const tspan = (g) => {
1436
+ const tspan = (g, x) => {
1412
1437
  if (g.isTab) return `<tspan dx="${fmt(g.width)}">&#8203;</tspan>`;
1413
1438
  const p = g.piece;
1414
1439
  const sizePx = renderedSizePxOf(p);
1415
1440
  const attrs = [
1441
+ ...x === void 0 ? [] : [`x="${fmt(x)}"`],
1416
1442
  `font-family="${escapeXml$1(p.cssFamily ?? p.family)}"`,
1417
1443
  `font-size="${fmt(sizePx)}"`,
1418
1444
  `fill="${p.fillHex}"`
@@ -1756,6 +1782,10 @@ const BROWSER_FAMILIES = {
1756
1782
  resolveFamily: browserFontFamily,
1757
1783
  familyIsCssList: true
1758
1784
  };
1785
+ const svgFamilies = (ctx) => ({
1786
+ resolveFamily: ctx.resolveFamily,
1787
+ ...ctx.eastAsianFamily === void 0 ? {} : { eastAsianFamily: ctx.eastAsianFamily }
1788
+ });
1759
1789
  const DEFAULT_BULLET_FONT = "Arial";
1760
1790
  const DEFAULT_INSET_X = 91440;
1761
1791
  const DEFAULT_INSET_Y = 45720;
@@ -2607,6 +2637,36 @@ const faceOf = (a, font) => {
2607
2637
  cssFamily: cssFamilyName(family)
2608
2638
  };
2609
2639
  };
2640
+ const eastAsianParts = (piece, family) => {
2641
+ if (family === void 0 || !EAST_ASIAN_CHAR.test(piece.text)) return [piece];
2642
+ const face = {
2643
+ family,
2644
+ cssFamily: cssFamilyName(family)
2645
+ };
2646
+ const parts = [];
2647
+ let current = "";
2648
+ let currentEastAsian = false;
2649
+ const flush = () => {
2650
+ if (current === "") return;
2651
+ parts.push(currentEastAsian ? {
2652
+ ...piece,
2653
+ ...face,
2654
+ text: current
2655
+ } : {
2656
+ ...piece,
2657
+ text: current
2658
+ });
2659
+ current = "";
2660
+ };
2661
+ for (const ch of piece.text) {
2662
+ const eastAsian = EAST_ASIAN_CHAR.test(ch);
2663
+ if (eastAsian !== currentEastAsian) flush();
2664
+ currentEastAsian = eastAsian;
2665
+ current += ch;
2666
+ }
2667
+ flush();
2668
+ return parts;
2669
+ };
2610
2670
  const buildSvgTextInput = (a) => {
2611
2671
  const scale = a.autoFitScale;
2612
2672
  const paragraphs = a.paraData.map((para, pi) => {
@@ -2696,10 +2756,10 @@ const buildSvgTextInput = (a) => {
2696
2756
  const segs = run.text.split("\n");
2697
2757
  segs.forEach((seg, i) => {
2698
2758
  const segText = caps ? seg.toUpperCase() : seg;
2699
- const segPieces = cap === "small" ? smallCapsParts(seg, base) : [{
2759
+ const segPieces = (cap === "small" ? smallCapsParts(seg, base) : [{
2700
2760
  ...base,
2701
2761
  text: segText
2702
- }];
2762
+ }]).flatMap((piece) => eastAsianParts(piece, a.eastAsianFamily));
2703
2763
  if (a.vert === "upright") for (const segPiece of segPieces) for (const g of graphemesOf(segPiece.text)) {
2704
2764
  const last = pieces[pieces.length - 1];
2705
2765
  if (last !== void 0 && !last.isBreak) pieces.push(breakPiece());
@@ -2799,7 +2859,7 @@ const bulletFillOf = (para, theme, defaultColor) => {
2799
2859
  const runColor = para.runs.find((r) => r.text !== "\n" && r.text !== "")?.fmt?.color;
2800
2860
  return runColor === void 0 || runColor === null ? defaultColor : resolveColor(runColor, theme, defaultColor);
2801
2861
  };
2802
- const resolveTextBodyModel = (pres, shape, bounds, theme, phType, measure, defaultColor, useSvgTextRect = false, resolveFamily = substituteFamily) => {
2862
+ const resolveTextBodyModel = (pres, shape, bounds, theme, phType, measure, defaultColor, useSvgTextRect = false, resolveFamily = substituteFamily, eastAsianFamily) => {
2803
2863
  let paragraphCount;
2804
2864
  try {
2805
2865
  paragraphCount = getShapeParagraphCount(shape);
@@ -3019,7 +3079,8 @@ const resolveTextBodyModel = (pres, shape, bounds, theme, phType, measure, defau
3019
3079
  measure,
3020
3080
  vert: fitVert,
3021
3081
  columns: fitColumns,
3022
- resolveFamily
3082
+ resolveFamily,
3083
+ ...eastAsianFamily === void 0 ? {} : { eastAsianFamily }
3023
3084
  };
3024
3085
  let s = 1;
3025
3086
  while (s > AUTOFIT_FLOOR) {
@@ -3060,6 +3121,7 @@ const resolveTextBodyModel = (pres, shape, bounds, theme, phType, measure, defau
3060
3121
  vert,
3061
3122
  autoFitScale,
3062
3123
  resolveFamily,
3124
+ ...eastAsianFamily === void 0 ? {} : { eastAsianFamily },
3063
3125
  columns: vert === "none" && cols && cols.count >= 2 ? {
3064
3126
  count: cols.count,
3065
3127
  gapPx: cols.gapEmu !== void 0 ? cols.gapEmu / EMU_PER_PX : 0
@@ -3178,7 +3240,7 @@ const renderHtmlParagraphs = (paraData, numberLabels, theme, autoFitScale, defau
3178
3240
  return paragraphs;
3179
3241
  };
3180
3242
  const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body") => {
3181
- const model = resolveTextBodyModel(pres, shape, bounds, theme, phType, ctx.measure, activeDeckTextColor, ctx.mode === "svg" && output === "body", ctx.resolveFamily);
3243
+ const model = resolveTextBodyModel(pres, shape, bounds, theme, phType, ctx.measure, activeDeckTextColor, ctx.mode === "svg" && output === "body", ctx.resolveFamily, ctx.eastAsianFamily);
3182
3244
  if (model === null) return "";
3183
3245
  const bevel = textBevelOf(getShapeText3D(shape));
3184
3246
  const { paraData, numberLabels, authoredAutofit, autoFitScale, defaultPt, themeFace, effectiveDefaultFont, effectiveBody, anchor, innerX, innerY, innerW, innerH, svgTextRect } = model;
@@ -3214,7 +3276,7 @@ const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body"
3214
3276
  innerW: vInnerW,
3215
3277
  innerH: vInnerH,
3216
3278
  measure: ctx.mode === "svg" ? ctx.measure : browserTextMeasurer() ?? ctx.measure,
3217
- ...ctx.mode === "foreignObject" ? BROWSER_FAMILIES : { resolveFamily: ctx.resolveFamily },
3279
+ ...ctx.mode === "foreignObject" ? BROWSER_FAMILIES : svgFamilies(ctx),
3218
3280
  vert: svgVert,
3219
3281
  columns: svgColumns,
3220
3282
  bevel
@@ -3363,6 +3425,7 @@ const renderTextEffectsSvg = (pres, slide, shape, bounds, opts = {}) => {
3363
3425
  mode: "foreignObject",
3364
3426
  measure: opts.measureText ?? browserTextMeasurer() ?? defaultMeasurer,
3365
3427
  resolveFamily: substituteFamily,
3428
+ eastAsianFamily: void 0,
3366
3429
  ownShapes: true,
3367
3430
  background: {
3368
3431
  id: "",
@@ -3400,6 +3463,7 @@ const renderTableCellEffectsSvgInternal = (pres, slide, shape, cellPosition, bou
3400
3463
  mode: "foreignObject",
3401
3464
  measure: opts.measureText ?? browserTextMeasurer() ?? defaultMeasurer,
3402
3465
  resolveFamily: substituteFamily,
3466
+ eastAsianFamily: void 0,
3403
3467
  ownShapes: true,
3404
3468
  background: {
3405
3469
  id: "",
@@ -3445,17 +3509,22 @@ const chartText = (f, x, y, attrs, content) => {
3445
3509
  }
3446
3510
  return `<text x="${px(x)}" y="${px(y)}" ${attrs}>${content}</text>`;
3447
3511
  };
3448
- const layoutChart = (xEmu, yEmu, wEmu, hEmu, hasTitle, hasAxes, titleOverlay = false, legendOverlay = false, hasLegend = true, titlePx = DEFAULT_CHART_TITLE_PT * PX_PER_PT, plotAreaLayout, yAxisGutter = hasAxes ? DEFAULT_Y_AXIS_GUTTER : 0, xAxisGutter = hasAxes ? BAR_VALUE_LABEL_ROW : 0) => {
3512
+ const CHART_AREA_INSET_RATIO = .02;
3513
+ const PX_PER_MM = 96 / 25.4;
3514
+ const DEFAULT_LEGEND_PT = 11;
3515
+ const CATEGORY_LABEL_OFFSET_PX = 12;
3516
+ const layoutChart = (xEmu, yEmu, wEmu, hEmu, hasTitle, hasAxes, titleOverlay = false, legendOverlay = false, hasLegend = true, titlePx = DEFAULT_CHART_TITLE_PT * PX_PER_PT, plotAreaLayout, yAxisGutter = hasAxes ? DEFAULT_Y_AXIS_GUTTER : 0, xAxisGutter = hasAxes ? BAR_VALUE_LABEL_ROW : 0, proportionalInset = false) => {
3449
3517
  const x = xEmu / EMU_PER_PX;
3450
3518
  const y = yEmu / EMU_PER_PX;
3451
3519
  const w = wEmu / EMU_PER_PX;
3452
3520
  const h = hEmu / EMU_PER_PX;
3453
3521
  const titleStrip = hasTitle && !titleOverlay ? Math.round(titlePx * 2.4) : 0;
3454
3522
  const legendStrip = hasLegend && !legendOverlay ? 18 : 0;
3455
- const padding = 8;
3523
+ const paddingX = proportionalInset ? w * CHART_AREA_INSET_RATIO : 8;
3524
+ const paddingY = proportionalInset ? h * CHART_AREA_INSET_RATIO : 8;
3456
3525
  const inner = plotAreaLayout?.target === "inner" ? plotAreaLayout : void 0;
3457
- const plotX = inner ? x + Math.max(0, Math.min(1, inner.x)) * w : x + padding + yAxisGutter;
3458
- const plotY = inner ? y + Math.max(0, Math.min(1, inner.y)) * h : y + titleStrip + padding;
3526
+ const plotX = inner ? x + Math.max(0, Math.min(1, inner.x)) * w : x + paddingX + yAxisGutter;
3527
+ const plotY = inner ? y + Math.max(0, Math.min(1, inner.y)) * h : y + titleStrip + paddingY;
3459
3528
  return {
3460
3529
  x,
3461
3530
  y,
@@ -3463,9 +3532,9 @@ const layoutChart = (xEmu, yEmu, wEmu, hEmu, hasTitle, hasAxes, titleOverlay = f
3463
3532
  h,
3464
3533
  plotX,
3465
3534
  plotY,
3466
- plotW: inner ? Math.max(0, Math.min(x + w, x + (inner.x + inner.w) * w) - plotX) : Math.max(0, w - 2 * padding - yAxisGutter),
3467
- plotH: inner ? Math.max(0, Math.min(y + h, y + (inner.y + inner.h) * h) - plotY) : Math.max(0, h - titleStrip - legendStrip - xAxisGutter - 2 * padding),
3468
- titleY: y + (titleOverlay ? 14 : padding + titlePx * .7),
3535
+ plotW: inner ? Math.max(0, Math.min(x + w, x + (inner.x + inner.w) * w) - plotX) : Math.max(0, w - 2 * paddingX - yAxisGutter),
3536
+ plotH: inner ? Math.max(0, Math.min(y + h, y + (inner.y + inner.h) * h) - plotY) : Math.max(0, h - titleStrip - legendStrip - xAxisGutter - 2 * paddingY),
3537
+ titleY: y + (titleOverlay ? 14 : paddingY + titlePx * .7),
3469
3538
  legendY: y + h - (legendOverlay ? 18 : legendStrip / 2)
3470
3539
  };
3471
3540
  };
@@ -3631,7 +3700,7 @@ const renderValueAxis = (f, axis) => {
3631
3700
  const ty2 = tickMark === "out" ? baseY : tickMark === "cross" ? baseY - tickLen : baseY - tickLen;
3632
3701
  out.push(`<line x1="${px(xp)}" y1="${px(ty1)}" x2="${px(xp)}" y2="${px(ty2)}" stroke="${axisColor}" stroke-width="1"/>`);
3633
3702
  }
3634
- const horizLabelY = f.plotY + f.plotH + 12;
3703
+ const horizLabelY = f.plotY + f.plotH + CATEGORY_LABEL_OFFSET_PX;
3635
3704
  const rotH = axis.labelRotationDeg ?? 0;
3636
3705
  const transformH = rotH ? ` transform="rotate(${rotH} ${px(xp)} ${px(horizLabelY)})"` : "";
3637
3706
  out.push(chartText(f, xp, horizLabelY, `text-anchor="middle" dominant-baseline="middle" ${axisTickAttrs(axis.labelStyle)}${transformH}`, `${escapeXml(fmtTick(t))}`));
@@ -3723,7 +3792,7 @@ const renderCategoryAxis = (f, orientation, cats, pointCount, skip = 1, labelSty
3723
3792
  for (let i = 0; i < pointCount; i++) {
3724
3793
  if (skip > 1 && i % skip !== 0) continue;
3725
3794
  const cx = f.plotX + (i + .5) * step;
3726
- const cy = f.plotY + f.plotH + 12;
3795
+ const cy = f.plotY + f.plotH + CATEGORY_LABEL_OFFSET_PX;
3727
3796
  const truncated = labels[i] !== void 0 && labels[i].length > truncLen ? `${labels[i].slice(0, truncLen - 2)}…` : labels[i] ?? "";
3728
3797
  const transform = labelRotationDeg && labelRotationDeg !== 0 ? ` transform="rotate(${labelRotationDeg} ${px(cx)} ${px(cy)})"` : "";
3729
3798
  const anchor = labelAlign === "l" ? "start" : labelAlign === "r" ? "end" : labelAlign === "ctr" ? "middle" : labelRotationDeg && labelRotationDeg > 0 ? "end" : labelRotationDeg && labelRotationDeg < 0 ? "start" : "middle";
@@ -3839,7 +3908,7 @@ const approxLegendTextPx = (text, fontPx) => {
3839
3908
  };
3840
3909
  const renderChartLegend = (f, names, colors, position = "b", textStyle, markers) => {
3841
3910
  if (names.length === 0) return "";
3842
- const sz = textStyle?.sizePt ?? 11;
3911
+ const sz = textStyle?.sizePt ?? DEFAULT_LEGEND_PT;
3843
3912
  const fill = textStyle?.color ?? "#374151";
3844
3913
  const weight = textStyle?.bold ? " font-weight=\"600\"" : "";
3845
3914
  const italic = textStyle?.italic ? " font-style=\"italic\"" : "";
@@ -4173,8 +4242,15 @@ const formatDataLabelValue = (spec, seriesIdx, v, pointIdx) => {
4173
4242
  const nf = (pointIdx === void 0 ? void 0 : spec.series[seriesIdx]?.pointDataLabels?.[pointIdx])?.numberFormat ?? spec.series[seriesIdx]?.dataLabels?.numberFormat ?? spec.dataLabels?.numberFormat;
4174
4243
  return nf ? formatAxisLabel(v, nf) : formatChartValue(v);
4175
4244
  };
4245
+ const LINE_DATA_LABEL_PT = 9;
4246
+ const DEFAULT_MARKER_PT = 5;
4247
+ const LABEL_ASCENT_RATIO = .952;
4248
+ const LABEL_DESCENT_RATIO = .269;
4249
+ const dataLabelStyle = (spec, seriesIdx, pointIdx) => {
4250
+ return (pointIdx === void 0 ? void 0 : spec.series[seriesIdx]?.pointDataLabels?.[pointIdx])?.textStyle ?? spec.series[seriesIdx]?.dataLabels?.textStyle ?? spec.dataLabels?.textStyle;
4251
+ };
4176
4252
  const dataLabelTextAttrs = (spec, seriesIdx, fallbackFill, fallbackSizePt = 9, fallbackBold = false, pointIdx) => {
4177
- const style = (pointIdx === void 0 ? void 0 : spec.series[seriesIdx]?.pointDataLabels?.[pointIdx])?.textStyle ?? spec.series[seriesIdx]?.dataLabels?.textStyle ?? spec.dataLabels?.textStyle;
4253
+ const style = dataLabelStyle(spec, seriesIdx, pointIdx);
4178
4254
  const sz = style?.sizePt ?? fallbackSizePt;
4179
4255
  const fill = style?.color ?? fallbackFill;
4180
4256
  const weight = style?.bold ?? fallbackBold ? " font-weight=\"600\"" : "";
@@ -4333,9 +4409,11 @@ const renderLineChart = (f, spec, colors, fill) => {
4333
4409
  })() : "";
4334
4410
  out.push(`<path d="${dPath}" fill="none" stroke="${series.lineColor ?? color}" stroke-width="${lineWPx.toFixed(2)}" stroke-linejoin="round" stroke-linecap="round"${dashAttr}/>`);
4335
4411
  const explicitSymbol = series.markerSymbol !== void 0 && series.markerSymbol !== "auto" && series.markerSymbol !== "none";
4336
- if (series.markerSymbol !== "none" && !fill && (spec.lineMarkers === true || explicitSymbol)) {
4412
+ const markerShown = series.markerSymbol !== "none" && !fill && (spec.lineMarkers === true || explicitSymbol);
4413
+ const markerHalfPx = (series.markerSizePt ?? DEFAULT_MARKER_PT) * PX_PER_PT / 2;
4414
+ if (markerShown) {
4337
4415
  const symbol = autoMarkerSymbol(series.markerSymbol, s);
4338
- const size = series.markerSizePt ?? 5;
4416
+ const size = series.markerSizePt ?? DEFAULT_MARKER_PT;
4339
4417
  const r = Math.max(1, size * .5);
4340
4418
  for (const [xp, yp] of pts) out.push(seriesMarker(symbol, xp, yp, r, ...markerColors(series, color)));
4341
4419
  }
@@ -4349,9 +4427,11 @@ const renderLineChart = (f, spec, colors, fill) => {
4349
4427
  const [xp, yp] = p;
4350
4428
  const pos = chartPointLabelOptions(spec, s, c).position;
4351
4429
  const lx = pos === "l" ? xp - 6 : pos === "r" ? xp + 6 : xp;
4352
- const ly = pos === "b" ? yp + 13 : pos === "ctr" || pos === "l" || pos === "r" ? yp + 3 : yp - 5;
4430
+ const labelPx = (dataLabelStyle(spec, s, c)?.sizePt ?? LINE_DATA_LABEL_PT) * PX_PER_PT;
4431
+ const clearance = (markerShown ? markerHalfPx : 0) + PX_PER_MM;
4432
+ const ly = pos === "b" ? yp + clearance + labelPx * LABEL_ASCENT_RATIO : pos === "ctr" || pos === "l" || pos === "r" ? yp + 3 : yp - clearance - labelPx * LABEL_DESCENT_RATIO;
4353
4433
  const anchor = pos === "l" ? "end" : pos === "r" ? "start" : "middle";
4354
- out.push(chartText(f, lx, ly, `text-anchor="${anchor}" ${dataLabelTextAttrs(spec, s, "#374151", 9, false, c)}`, `${escapeXml(labelText)}`));
4434
+ out.push(chartText(f, lx, ly, `text-anchor="${anchor}" ${dataLabelTextAttrs(spec, s, "#374151", LINE_DATA_LABEL_PT, false, c)}`, `${escapeXml(labelText)}`));
4355
4435
  }
4356
4436
  if (!isStacked && series.trendline) {
4357
4437
  const finiteXs = [];
@@ -4694,10 +4774,13 @@ const renderChart = (shape, x, y, w, h, transform, theme, groupReflected, measur
4694
4774
  const barLabels = spec.kind === "bar" && !spec.categoryAxisHidden && spec.categoryAxisTickLabelPos !== "none" && !spec.categoryAxisLabelRotationDeg ? layoutBarCategoryLabels(spec, w / EMU_PER_PX, measure) : void 0;
4695
4775
  const barValueTitleRow = spec.kind === "bar" && spec.valueAxisTitle ? axisTitleRowPx(spec.valueAxisTitleStyle) : 0;
4696
4776
  const barCategoryTitleRow = spec.kind === "bar" && spec.categoryAxisTitle ? axisTitleRowPx(spec.categoryAxisTitleStyle) : 0;
4777
+ const vertical = isCartesian && spec.kind !== "bar";
4778
+ const categoryLabelsShown = !spec.categoryAxisHidden && spec.categoryAxisTickLabelPos !== "none";
4779
+ const categoryLabelRow = vertical && categoryLabelsShown ? Math.max(BAR_VALUE_LABEL_ROW, CATEGORY_LABEL_OFFSET_PX + categoryLabelFontPx(spec.categoryAxisLabelStyle) * CATEGORY_LABEL_LINE_HEIGHT / 2) : void 0;
4697
4780
  const flip = getShapeFlip(shape);
4698
4781
  const f = {
4699
4782
  reflected: groupReflected !== Boolean(flip && flip.horizontal !== flip.vertical),
4700
- ...layoutChart(x, y, w, h, !!spec.title, hasAxes, spec.titleOverlay ?? false, spec.legend?.overlay ?? false, hasLegend, (spec.titleStyle?.sizePt ?? DEFAULT_CHART_TITLE_PT) * PX_PER_PT, spec.plotAreaLayout, barLabels ? Math.max(DEFAULT_Y_AXIS_GUTTER, barLabels.widthPx + CATEGORY_LABEL_GAP) + barCategoryTitleRow : void 0, barValueTitleRow > 0 ? BAR_VALUE_LABEL_ROW + barValueTitleRow : void 0)
4783
+ ...layoutChart(x, y, w, h, !!spec.title, hasAxes, spec.titleOverlay ?? false, spec.legend?.overlay ?? false, hasLegend, (spec.titleStyle?.sizePt ?? DEFAULT_CHART_TITLE_PT) * PX_PER_PT, spec.plotAreaLayout, barLabels ? Math.max(DEFAULT_Y_AXIS_GUTTER, barLabels.widthPx + CATEGORY_LABEL_GAP) + barCategoryTitleRow : void 0, barValueTitleRow > 0 ? BAR_VALUE_LABEL_ROW + barValueTitleRow : categoryLabelRow, isCartesian)
4701
4784
  };
4702
4785
  const allNamesForLegend = spec.kind === "pie" || spec.kind === "doughnut" ? Array.from(spec.categories) : spec.series.map((s) => s.name);
4703
4786
  const allColorsForLegend = spec.kind === "pie" || spec.kind === "doughnut" ? spec.categories.map((_, i) => spec.series[0]?.pointColors?.[i] ?? spec.series[0]?.color ?? colors[i % colors.length] ?? "#888") : spec.series.map((s, i) => s.color ?? colors[i % colors.length] ?? "#888");
@@ -4994,7 +5077,7 @@ const renderTableCellText = (cell, paragraphs, cx, cy, cw, ch, color, pres, shap
4994
5077
  innerW: innerW * EMU_PER_PX,
4995
5078
  innerH: innerH * EMU_PER_PX,
4996
5079
  measure: ctx.mode === "svg" ? ctx.measure : browserTextMeasurer() ?? ctx.measure,
4997
- ...ctx.mode === "foreignObject" ? BROWSER_FAMILIES : { resolveFamily: ctx.resolveFamily },
5080
+ ...ctx.mode === "foreignObject" ? BROWSER_FAMILIES : svgFamilies(ctx),
4998
5081
  vert: verticalLayoutOf(getTableCellTextDirection(cell)),
4999
5082
  columns: null,
5000
5083
  ...effectsOnly ? { effectsOnly: true } : {},
@@ -5874,6 +5957,7 @@ const renderSurface = (pres, surface, opts) => {
5874
5957
  mode: opts.textLayout ?? "foreignObject",
5875
5958
  measure: opts.measureText ?? defaultMeasurer,
5876
5959
  resolveFamily: opts.textLayout === "svg" ? opts.resolveFamily ?? substituteFamily : substituteFamily,
5960
+ eastAsianFamily: opts.textLayout === "svg" ? opts.eastAsianFamily : void 0,
5877
5961
  ownShapes: true,
5878
5962
  background: {
5879
5963
  id: "",
@@ -6316,4 +6400,4 @@ function shapeTextAnchorOffset(pres, shape, options = {}) {
6316
6400
  //#endregion
6317
6401
  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 };
6318
6402
 
6319
- //# sourceMappingURL=src-BGzSNWjt.js.map
6403
+ //# sourceMappingURL=src-DoFuEaap.js.map