@office-kit/pptx-preview 0.13.0 → 0.14.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.
@@ -1,50 +1,22 @@
1
- import { getEffectiveColorMap, getGroupChildren, getGroupTransform, getParagraphAlignment, getParagraphBullet, getParagraphBulletImageBytes, getParagraphBulletStyle, getParagraphIndent, getParagraphLevel, getParagraphPropertiesEffective, getParagraphSpacing, getPresentationFirstSlideNumber, getPresentationFonts, getPresentationTheme, getShapeAdjustValues, getShapeAltTitle, getShapeBodyPrEffective, getShapeBounds, getShapeBoundsResolved, getShapeChartSpec, getShapeClickAction, getShapeCustomGeometry, getShapeDescription, getShapeEffectsEffective, getShapeFillColorResolved, getShapeFillEffective, getShapeFillOpacity, getShapeFlip, getShapeGradientFill, getShapeGradientFillEffective, getShapeHyperlinkTooltip, getShapeId, getShapeImageBiLevelThreshold, getShapeImageBrightness, getShapeImageBytes, getShapeImageContrast, getShapeImageCrop, getShapeImageDuotone, getShapeImageFillBytes, getShapeImageFillLayout, getShapeImageFormat, getShapeImageIntrinsicSize, getShapeImageLinkUrl, getShapeImageOpacity, getShapeImagePartName, getShapeKind, getShapeName, getShapeParagraphCount, getShapeParagraphElements, getShapePatternFill, getShapePlaceholderType, getShapePreset, getShapeRotation, getShapeRunClickAction, getShapeRunFormat, getShapeRunFormatEffective, getShapeRunHyperlink, getShapeRunHyperlinkTooltip, getShapeStrokeArrow, getShapeStrokeCap, getShapeStrokeColorResolved, getShapeStrokeCompound, getShapeStrokeDash, getShapeStrokeEffective, getShapeStrokeJoin, getShapeStrokeOpacity, getShapeTextAnchor, getShapeTextAutoFit, getShapeTextAutoFitParams, getShapeTextBodyRotationDeg, getShapeTextColumns, getShapeTextDirection, getShapeTextMargins, getShapeXmlString, getSlideBackground, getSlideBackgroundGradientFill, getSlideBackgroundImageBytes, getSlideBackgroundImageCrop, getSlideBackgroundImageFillLayout, getSlideBackgroundImageIntrinsicSize, getSlideBackgroundImageOpacity, getSlideBackgroundPatternFill, getSlideIndex, getSlideLayout, getSlideLayoutBackground, getSlideLayoutBackgroundGradientFill, getSlideLayoutBackgroundImageBytes, getSlideLayoutBackgroundPatternFill, getSlideLayoutShapes, getSlideMasterBackground, getSlideMasterBackgroundGradientFill, getSlideMasterBackgroundImageBytes, getSlideMasterBackgroundPatternFill, getSlideMasterShapes, getSlideShapes, getSlideSize, getSlides, getTableCellAnchor, getTableCellAppearanceEffective, getTableCellMargins, getTableCellParagraphs, getTableCellRunFormatEffective, getTableCellSpan, getTableCellTextDirection, getTableCells, getTableColumnWidths, getTableDimensions, getTableRowHeights, isChartShape, isParagraphBulletPicture, isShapeHidden, isShapeImageGrayscale, isShapePlaceholder, isShapeTextBox, isSlideBackgroundGraphicsHidden, isSlideLayoutBackgroundGraphicsHidden, isTableShape, resolveDeckBodyTextColor } from "@office-kit/pptx";
1
+ import { emu, getEffectiveColorMap, getGroupChildren, getGroupTransform, getParagraphAlignment, getParagraphBullet, getParagraphBulletImageBytes, getParagraphBulletStyle, getParagraphIndent, getParagraphLevel, getParagraphPropertiesEffective, getParagraphSpacing, getPresentationFirstSlideNumber, getPresentationFonts, getPresentationTheme, getPresetGeometry, getShapeAdjustValues, getShapeAltTitle, getShapeBodyPrEffective, getShapeBounds, getShapeBoundsResolved, getShapeChartSpec, getShapeClickAction, getShapeCustomGeometry, getShapeDescription, getShapeEffectsEffective, getShapeFillColorResolved, getShapeFillEffective, getShapeFillOpacity, getShapeFlip, getShapeGradientFill, getShapeGradientFillEffective, getShapeHyperlinkTooltip, getShapeId, getShapeImageBiLevelThreshold, getShapeImageBrightness, getShapeImageBytes, getShapeImageContrast, getShapeImageCrop, getShapeImageDuotone, getShapeImageFillBytes, getShapeImageFillLayout, getShapeImageFormat, getShapeImageIntrinsicSize, getShapeImageLinkUrl, getShapeImageOpacity, getShapeImagePartName, getShapeKind, getShapeName, getShapeParagraphCount, getShapeParagraphElements, getShapePatternFill, getShapePlaceholderType, getShapePreset, getShapeRotation, getShapeRunClickAction, getShapeRunFormat, getShapeRunFormatEffective, getShapeRunHyperlink, getShapeRunHyperlinkTooltip, getShapeStrokeArrow, getShapeStrokeCap, getShapeStrokeColorResolved, getShapeStrokeCompound, getShapeStrokeDash, getShapeStrokeEffective, getShapeStrokeJoin, getShapeStrokeOpacity, getShapeText3D, getShapeTextAnchor, getShapeTextAutoFit, getShapeTextAutoFitParams, getShapeTextBodyRotationDeg, getShapeTextColumns, getShapeTextDirection, getShapeTextMargins, getShapeXmlString, getSlideBackground, getSlideBackgroundGradientFill, getSlideBackgroundImageBytes, getSlideBackgroundImageCrop, getSlideBackgroundImageFillLayout, getSlideBackgroundImageIntrinsicSize, getSlideBackgroundImageOpacity, getSlideBackgroundPatternFill, getSlideIndex, getSlideLayout, getSlideLayoutBackground, getSlideLayoutBackgroundGradientFill, getSlideLayoutBackgroundImageBytes, getSlideLayoutBackgroundPatternFill, getSlideLayoutShapes, getSlideMasterBackground, getSlideMasterBackgroundGradientFill, getSlideMasterBackgroundImageBytes, getSlideMasterBackgroundPatternFill, getSlideMasterShapes, getSlideShapes, getSlideSize, getSlides, getTableCellAnchor, getTableCellAppearanceEffective, getTableCellMargins, getTableCellParagraphs, getTableCellRunFormatEffective, getTableCellSpan, getTableCellText3D, getTableCellTextDirection, getTableCells, getTableColumnWidths, getTableDimensions, getTableRowHeights, isChartShape, isParagraphBulletPicture, isShapeHidden, isShapeImageGrayscale, isShapePlaceholder, isShapeTextBox, isSlideBackgroundGraphicsHidden, isSlideLayoutBackgroundGraphicsHidden, isTableShape, resolveDeckBodyTextColor } from "@office-kit/pptx";
2
2
  //#region src/text-body-rect.ts
3
- const presetTextRect = (preset) => {
4
- switch (preset) {
5
- case "triangle": return {
6
- l: .25,
7
- t: .5,
8
- r: .75,
9
- b: 1
10
- };
11
- case "diamond": return {
12
- l: .25,
13
- t: .25,
14
- r: .75,
15
- b: .75
16
- };
17
- case "pentagon": return {
18
- l: .191,
19
- t: .236,
20
- r: .809,
21
- b: 1
22
- };
23
- case "star5": return {
24
- l: .309,
25
- t: .382,
26
- r: .691,
27
- b: .764
28
- };
29
- case "leftRightArrow": return {
30
- l: .18,
31
- t: .35,
32
- r: .82,
33
- b: .65
34
- };
35
- default: return null;
36
- }
37
- };
38
3
  /**
39
- * The text rectangle a custom-geometry shape states for itself, as fractions
40
- * of its own extent, or `null` for a preset shape and for a custom one that
41
- * states none. `<a:rect>` is written in EMU against the shape's extents, so
42
- * dividing by them here is what lets the result travel with a shape that a
43
- * group has scaled.
4
+ * Where a shape lays out its text, as fractions of its own extent: the
5
+ * `<a:rect>` its geometry states, written in its `<a:custGeom>` or in
6
+ * ECMA-376's definition of its preset (an ellipse's inscribed rectangle, a
7
+ * triangle's lower middle, an arrow's shaft). `null` lays text into the whole
8
+ * box: a shape that inherits its geometry, or whose rectangle has no room.
9
+ *
10
+ * The rectangle is in the shape's own `<a:ext>` space, so dividing by that —
11
+ * not by on-screen bounds, which carry a group's or autofit's scale — is what
12
+ * lets the result travel with the shape.
44
13
  */
45
- function shapeCustomTextRect(custom, extent) {
46
- const rect = custom?.textRect;
47
- if (!rect || extent === null || extent.w <= 0 || extent.h <= 0) return null;
14
+ function shapeTextRect(shape) {
15
+ const extent = getShapeBounds(shape);
16
+ if (extent === null || extent.w <= 0 || extent.h <= 0) return null;
17
+ const preset = getShapePreset(shape);
18
+ const rect = (preset === null ? getShapeCustomGeometry(shape) : getPresetGeometry(preset, extent, getShapeAdjustValues(shape)))?.textRect;
19
+ if (!rect || rect.r <= rect.l || rect.b <= rect.t) return null;
48
20
  return {
49
21
  l: rect.l / extent.w,
50
22
  t: rect.t / extent.h,
@@ -53,18 +25,13 @@ function shapeCustomTextRect(custom, extent) {
53
25
  };
54
26
  }
55
27
  /**
56
- * Text layout rectangle used by the preview, including preset geometry and body
57
- * insets. All coordinates and margins must use the same unit (normally EMU).
58
- * Preset regions follow the preview's current geometry approximations. When
59
- * margins collapse a preset region, retain that region without margins.
60
- *
61
- * A custom-geometry shape states its own rectangle in `<a:custGeom><a:rect>`.
62
- * Pass it as `custom`, as fractions of the shape's extent so that it scales
63
- * with `bounds` the way a preset region does, and it wins: unlike the table
64
- * above it is not an approximation of anything — it is what the file says.
28
+ * Text layout rectangle used by the preview: `region` (from
29
+ * {@link shapeTextRect}, or `null` for the whole box) placed in `bounds`, less
30
+ * the body insets. All coordinates and margins must use the same unit
31
+ * (normally EMU). When margins collapse a region, the region is kept without
32
+ * them, as PowerPoint does.
65
33
  */
66
- function resolveTextBodyRect(preset, bounds, margins, custom) {
67
- const region = custom ?? presetTextRect(preset);
34
+ function resolveTextBodyRect(bounds, margins, region) {
68
35
  const x = bounds.x + (region?.l ?? 0) * bounds.w;
69
36
  const y = bounds.y + (region?.t ?? 0) * bounds.h;
70
37
  const w = ((region?.r ?? 1) - (region?.l ?? 0)) * bounds.w;
@@ -1069,8 +1036,9 @@ const emitLine = (line, baselineY, dx, descent, nextEffectId, effectsOnly, effec
1069
1036
  const reflections = effectKind === "reflection" || effectKind === "all" ? emitTextReflections(groups, line.textAnchor, x0, baselineY, descent, nextEffectId) : "";
1070
1037
  const outerEffects = effectKind === "outer" || effectKind === "all" ? emitTextOuterEffects(groups, line.textAnchor, x0, baselineY, nextEffectId) : "";
1071
1038
  const innerShadows = effectKind === "innerShadow" || effectKind === "all" ? emitTextInnerShadows(groups, line.textAnchor, x0, baselineY, nextEffectId) : "";
1072
- if (effectsOnly) return outerEffects + reflections + innerShadows;
1073
- return emitHighlights(groups, line.textAnchor, x0, baselineY) + outerEffects + reflections + text + innerShadows + emitTextDecorations(groups, line.textAnchor, x0, baselineY);
1039
+ const bevels = effectKind === "bevel" || effectKind === "all" ? emitTextBevel(groups, line.textAnchor, x0, baselineY, nextEffectId) : "";
1040
+ if (effectsOnly) return outerEffects + reflections + bevels + innerShadows;
1041
+ return emitHighlights(groups, line.textAnchor, x0, baselineY) + outerEffects + reflections + text + bevels + innerShadows + emitTextDecorations(groups, line.textAnchor, x0, baselineY);
1074
1042
  };
1075
1043
  const unpaintedPiece = (piece) => {
1076
1044
  const { outlineHex: _outline, shadow: _shadow, glow: _glow, ...rest } = piece;
@@ -1214,6 +1182,25 @@ const emitTextInnerShadows = (groups, textAnchor, x0, baselineY, nextId) => {
1214
1182
  }
1215
1183
  return parts.join("");
1216
1184
  };
1185
+ const emitTextBevel = (groups, textAnchor, x0, baselineY, nextId) => {
1186
+ const bevel = groups.find((g) => g.piece.bevel && !g.isTab && g.width > 0)?.piece.bevel;
1187
+ if (!bevel) return "";
1188
+ const id = nextId("bevel");
1189
+ const widthPx = bevel.widthEmu / EMU_PER_PX$1;
1190
+ const surfaceScale = bevel.heightEmu / EMU_PER_PX$1 * bevel.relief;
1191
+ const table = [...bevel.profile.slice(1).map(() => 0), ...bevel.profile];
1192
+ const flat = Math.sin(bevel.elevationDeg * Math.PI / 180);
1193
+ const lightGain = bevel.contrast / (1 - flat);
1194
+ const shadeGain = bevel.contrast / flat;
1195
+ const light = `<feDistantLight azimuth="${fmt(bevel.azimuthDeg)}" elevation="${fmt(bevel.elevationDeg)}"/>`;
1196
+ 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>` : "";
1197
+ 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>`;
1198
+ const beveled = groups.map((g) => g.piece.bevel && !g.isTab ? g : {
1199
+ ...g,
1200
+ piece: unpaintedPiece(g.piece)
1201
+ });
1202
+ 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>`;
1203
+ };
1217
1204
  const baselineShiftPxOf = (p) => p.sizePx * p.baseline;
1218
1205
  const SUPER_SUB_SIZE_RATIO = .65;
1219
1206
  const SMALL_CAPS_LOWERCASE_RATIO = .8;
@@ -1473,6 +1460,149 @@ function browserTextMeasurer() {
1473
1460
  };
1474
1461
  }
1475
1462
  //#endregion
1463
+ //#region src/text-bevel.ts
1464
+ const DEFAULT_BEVEL_EMU = 76200;
1465
+ const DEFAULT_PRESET = "circle";
1466
+ const DEFAULT_RIG = {
1467
+ type: "threePt",
1468
+ direction: "t"
1469
+ };
1470
+ const PROFILE_SAMPLES = 9;
1471
+ const PROFILES = {
1472
+ circle: (t) => Math.sqrt(1 - (1 - t) ** 2),
1473
+ relaxedInset: (t) => Math.sin(t * Math.PI / 2) ** 2,
1474
+ slope: (t) => t,
1475
+ angle: (t) => t,
1476
+ softRound: (t) => t * t * (3 - 2 * t),
1477
+ convex: (t) => Math.sqrt(Math.sqrt(1 - (1 - t) ** 2)),
1478
+ coolSlant: (t) => Math.min(1, t * 1.6),
1479
+ hardEdge: (t) => Math.min(1, t * 3),
1480
+ cross: (t) => t < .5 ? t * 1.6 : .8 + (t - .5) * .4,
1481
+ divot: (t) => t < .35 ? t / .35 : 1 - .55 * Math.sin((t - .35) / .65 * Math.PI),
1482
+ riblet: (t) => t * .7 + .3 * Math.abs(Math.sin(t * 2.5 * Math.PI)),
1483
+ artDeco: (t) => Math.min(1, Math.floor(t * 3 + .5) / 3 + (t * 3 - Math.floor(t * 3)) * .12)
1484
+ };
1485
+ const DIRECTION_AZIMUTH = {
1486
+ r: 0,
1487
+ br: 45,
1488
+ b: 90,
1489
+ bl: 135,
1490
+ l: 180,
1491
+ tl: 225,
1492
+ t: 270,
1493
+ tr: 315
1494
+ };
1495
+ const RIG_LOOK = (type) => {
1496
+ if (type === "flat" || type.startsWith("legacyFlat")) return null;
1497
+ if (type === "harsh" || type.startsWith("legacyHarsh") || type === "contrasting") return {
1498
+ elevationDeg: 30,
1499
+ contrast: .65
1500
+ };
1501
+ if (type === "soft" || type === "flood" || type === "brightRoom" || type === "glow") return {
1502
+ elevationDeg: 45,
1503
+ contrast: .55
1504
+ };
1505
+ return {
1506
+ elevationDeg: 38,
1507
+ contrast: .65
1508
+ };
1509
+ };
1510
+ const MATTE = {
1511
+ contrastScale: 1,
1512
+ specular: null
1513
+ };
1514
+ const MATERIAL_LOOK = {
1515
+ plastic: {
1516
+ contrastScale: 1,
1517
+ specular: {
1518
+ constant: .6,
1519
+ exponent: 20
1520
+ }
1521
+ },
1522
+ legacyPlastic: {
1523
+ contrastScale: 1,
1524
+ specular: {
1525
+ constant: .6,
1526
+ exponent: 20
1527
+ }
1528
+ },
1529
+ metal: {
1530
+ contrastScale: 1.2,
1531
+ specular: {
1532
+ constant: .9,
1533
+ exponent: 12
1534
+ }
1535
+ },
1536
+ legacyMetal: {
1537
+ contrastScale: 1.2,
1538
+ specular: {
1539
+ constant: .9,
1540
+ exponent: 12
1541
+ }
1542
+ },
1543
+ softmetal: {
1544
+ contrastScale: 1.1,
1545
+ specular: {
1546
+ constant: .6,
1547
+ exponent: 8
1548
+ }
1549
+ },
1550
+ clear: {
1551
+ contrastScale: .9,
1552
+ specular: {
1553
+ constant: .8,
1554
+ exponent: 30
1555
+ }
1556
+ },
1557
+ softEdge: {
1558
+ contrastScale: .9,
1559
+ specular: {
1560
+ constant: .25,
1561
+ exponent: 10
1562
+ }
1563
+ },
1564
+ powder: {
1565
+ contrastScale: .8,
1566
+ specular: null
1567
+ },
1568
+ translucentPowder: {
1569
+ contrastScale: .7,
1570
+ specular: null
1571
+ },
1572
+ flat: {
1573
+ contrastScale: 0,
1574
+ specular: null
1575
+ }
1576
+ };
1577
+ const RELIEF = 2.5;
1578
+ /**
1579
+ * The bevel to shade a text body with, or `null` when it has no top bevel or
1580
+ * its rig/material renders it unshaded.
1581
+ */
1582
+ const textBevelOf = (text3d) => {
1583
+ const bevel = text3d?.bevelTop;
1584
+ if (!bevel) return null;
1585
+ const widthEmu = bevel.widthEmu ?? DEFAULT_BEVEL_EMU;
1586
+ const heightEmu = bevel.heightEmu ?? DEFAULT_BEVEL_EMU;
1587
+ if (widthEmu <= 0 || heightEmu <= 0) return null;
1588
+ const rig = text3d.scene?.lightRig ?? DEFAULT_RIG;
1589
+ const look = RIG_LOOK(rig.type);
1590
+ const material = (text3d.material && MATERIAL_LOOK[text3d.material]) ?? MATTE;
1591
+ if (!look || material.contrastScale === 0) return null;
1592
+ const profile = PROFILES[bevel.preset ?? DEFAULT_PRESET];
1593
+ const azimuthDeg = (DIRECTION_AZIMUTH[rig.direction] + (rig.rotation?.revolutionDeg ?? 0)) % 360;
1594
+ return {
1595
+ widthEmu,
1596
+ heightEmu,
1597
+ profile: Array.from({ length: PROFILE_SAMPLES }, (_, i) => Math.max(0, Math.min(1, profile(i / (PROFILE_SAMPLES - 1))))),
1598
+ azimuthDeg,
1599
+ elevationDeg: look.elevationDeg,
1600
+ contrast: Math.min(1, look.contrast * material.contrastScale),
1601
+ relief: RELIEF,
1602
+ specular: material.specular
1603
+ };
1604
+ };
1605
+ //#endregion
1476
1606
  //#region src/render-slide.ts
1477
1607
  const clickActionHref = (pres, action) => {
1478
1608
  if (!action) return void 0;
@@ -1677,15 +1807,11 @@ const imageTilePattern = (dataUrl, layout, intrinsic, x, y, w, h, cropL = 0, cro
1677
1807
  };
1678
1808
  };
1679
1809
  const pictureClipGeometry = (shape, preset, x, y, w, h) => {
1680
- if (preset === "ellipse") return `<ellipse cx="${E(x + w / 2)}" cy="${E(y + h / 2)}" rx="${E(w / 2)}" ry="${E(h / 2)}"/>`;
1681
- if (preset === "roundRect") {
1682
- const radius = E(Math.min(w, h) * Math.max(0, Math.min(.5, (getShapeAdjustValues(shape).adj ?? 16667) / 1e5)));
1683
- return `<rect x="${E(x)}" y="${E(y)}" width="${E(w)}" height="${E(h)}" rx="${radius}" ry="${radius}"/>`;
1684
- }
1685
- const path = PRESET_PATHS[preset];
1686
- if (path) return `<path d="${path(x / EMU_PER_PX, y / EMU_PER_PX, w / EMU_PER_PX, h / EMU_PER_PX)}" clip-rule="evenodd"/>`;
1687
- const points = PRESET_POINTS[preset];
1688
- if (points) return `<polygon points="${points(w / EMU_PER_PX, h / EMU_PER_PX).map(([nx, ny]) => `${E(x + nx * w)},${E(y + ny * h)}`).join(" ")}"/>`;
1810
+ const d = ((preset === "rect" ? null : getPresetGeometry(preset, {
1811
+ w: emu(w),
1812
+ h: emu(h)
1813
+ }, getShapeAdjustValues(shape)))?.paths ?? []).filter((path) => path.fill !== "none").map((path) => geometryPathData(path, x, y, w, h)).filter((data) => data !== "").join(" ");
1814
+ if (d !== "") return `<path d="${d}" clip-rule="evenodd"/>`;
1689
1815
  return `<rect x="${E(x)}" y="${E(y)}" width="${E(w)}" height="${E(h)}"/>`;
1690
1816
  };
1691
1817
  const renderPicturePlaceholderLabel = (x, y, w, h, text) => {
@@ -2103,904 +2229,6 @@ const paint = (shape, fill, stroke, theme, isPlaceholder, pres) => {
2103
2229
  markerAttrs
2104
2230
  };
2105
2231
  };
2106
- const polygon = (n, rotation = -Math.PI / 2) => {
2107
- const out = [];
2108
- for (let i = 0; i < n; i++) {
2109
- const a = rotation + i * 2 * Math.PI / n;
2110
- out.push([.5 + .5 * Math.cos(a), .5 + .5 * Math.sin(a)]);
2111
- }
2112
- return out;
2113
- };
2114
- const star = (points, innerRatio = .42) => {
2115
- const out = [];
2116
- const rotation = -Math.PI / 2;
2117
- for (let i = 0; i < points * 2; i++) {
2118
- const a = rotation + i * Math.PI / points;
2119
- const r = i % 2 === 0 ? .5 : .5 * innerRatio;
2120
- out.push([.5 + r * Math.cos(a), .5 + r * Math.sin(a)]);
2121
- }
2122
- return out;
2123
- };
2124
- const PRESET_POINTS = {
2125
- triangle: () => [
2126
- [.5, 0],
2127
- [1, 1],
2128
- [0, 1]
2129
- ],
2130
- rtTriangle: () => [
2131
- [0, 0],
2132
- [1, 1],
2133
- [0, 1]
2134
- ],
2135
- diamond: () => [
2136
- [.5, 0],
2137
- [1, .5],
2138
- [.5, 1],
2139
- [0, .5]
2140
- ],
2141
- parallelogram: () => [
2142
- [.25, 0],
2143
- [1, 0],
2144
- [.75, 1],
2145
- [0, 1]
2146
- ],
2147
- trapezoid: () => [
2148
- [.25, 0],
2149
- [.75, 0],
2150
- [1, 1],
2151
- [0, 1]
2152
- ],
2153
- pentagon: () => polygon(5),
2154
- hexagon: () => polygon(6),
2155
- heptagon: () => polygon(7),
2156
- octagon: () => polygon(8),
2157
- decagon: () => polygon(10),
2158
- dodecagon: () => polygon(12),
2159
- star4: () => star(4),
2160
- star5: () => star(5),
2161
- star6: () => star(6),
2162
- star7: () => star(7),
2163
- star8: () => star(8),
2164
- star10: () => star(10),
2165
- star12: () => star(12),
2166
- star16: () => star(16),
2167
- star24: () => star(24),
2168
- star32: () => star(32),
2169
- rightArrow: (w, h) => {
2170
- const bx = 1 - Math.min(1, .5 * Math.min(w, h) / w);
2171
- return [
2172
- [0, .25],
2173
- [bx, .25],
2174
- [bx, 0],
2175
- [1, .5],
2176
- [bx, 1],
2177
- [bx, .75],
2178
- [0, .75]
2179
- ];
2180
- },
2181
- leftArrow: (w, h) => {
2182
- const bx = Math.min(1, .5 * Math.min(w, h) / w);
2183
- return [
2184
- [1, .25],
2185
- [bx, .25],
2186
- [bx, 0],
2187
- [0, .5],
2188
- [bx, 1],
2189
- [bx, .75],
2190
- [1, .75]
2191
- ];
2192
- },
2193
- upArrow: (w, h) => {
2194
- const by = Math.min(1, .5 * Math.min(w, h) / h);
2195
- return [
2196
- [.25, 1],
2197
- [.25, by],
2198
- [0, by],
2199
- [.5, 0],
2200
- [1, by],
2201
- [.75, by],
2202
- [.75, 1]
2203
- ];
2204
- },
2205
- downArrow: (w, h) => {
2206
- const by = 1 - Math.min(1, .5 * Math.min(w, h) / h);
2207
- return [
2208
- [.25, 0],
2209
- [.25, by],
2210
- [0, by],
2211
- [.5, 1],
2212
- [1, by],
2213
- [.75, by],
2214
- [.75, 0]
2215
- ];
2216
- },
2217
- leftRightArrow: () => [
2218
- [0, .5],
2219
- [.18, .2],
2220
- [.18, .35],
2221
- [.82, .35],
2222
- [.82, .2],
2223
- [1, .5],
2224
- [.82, .8],
2225
- [.82, .65],
2226
- [.18, .65],
2227
- [.18, .8]
2228
- ],
2229
- upDownArrow: () => [
2230
- [.5, 0],
2231
- [.2, .18],
2232
- [.35, .18],
2233
- [.35, .82],
2234
- [.2, .82],
2235
- [.5, 1],
2236
- [.8, .82],
2237
- [.65, .82],
2238
- [.65, .18],
2239
- [.8, .18]
2240
- ],
2241
- chevron: () => [
2242
- [0, 0],
2243
- [.7, 0],
2244
- [1, .5],
2245
- [.7, 1],
2246
- [0, 1],
2247
- [.3, .5]
2248
- ],
2249
- bentArrow: () => [
2250
- [0, .45],
2251
- [.55, .45],
2252
- [.55, .25],
2253
- [.55, .05],
2254
- [.95, .05],
2255
- [.95, .55],
2256
- [.8, .55],
2257
- [.8, .85],
2258
- [0, .85]
2259
- ],
2260
- homePlate: () => [
2261
- [0, 0],
2262
- [.75, 0],
2263
- [1, .5],
2264
- [.75, 1],
2265
- [0, 1]
2266
- ]
2267
- };
2268
- const PRESET_PATHS = {
2269
- wedgeRectCallout: (x, y, w, h) => {
2270
- const bodyH = h * .78;
2271
- const tailTipX = x + w * .12;
2272
- const tailTipY = y + h;
2273
- const tailBaseLeft = x + w * .18;
2274
- const tailBaseRight = x + w * .32;
2275
- const bodyB = y + bodyH;
2276
- return `M${x},${y} L${x + w},${y} L${x + w},${bodyB} L${tailBaseRight},${bodyB} L${tailTipX},${tailTipY} L${tailBaseLeft},${bodyB} L${x},${bodyB} Z`;
2277
- },
2278
- wedgeRoundRectCallout: (x, y, w, h) => {
2279
- const r = Math.min(w, h) * .08;
2280
- const bodyH = h * .78;
2281
- const tailTipX = x + w * .12;
2282
- const tailTipY = y + h;
2283
- const tailBaseLeft = x + w * .18;
2284
- const tailBaseRight = x + w * .32;
2285
- const bodyB = y + bodyH;
2286
- return `M${x + r},${y} L${x + w - r},${y} A${r},${r} 0 0 1 ${x + w},${y + r} L${x + w},${bodyB - r} A${r},${r} 0 0 1 ${x + w - r},${bodyB} L${tailBaseRight},${bodyB} L${tailTipX},${tailTipY} L${tailBaseLeft},${bodyB} L${x + r},${bodyB} A${r},${r} 0 0 1 ${x},${bodyB - r} L${x},${y + r} A${r},${r} 0 0 1 ${x + r},${y} Z`;
2287
- },
2288
- wedgeEllipseCallout: (x, y, w, h) => {
2289
- const bodyCy = y + h * .39;
2290
- const bodyRy = h * .39;
2291
- const cx = x + w / 2;
2292
- const bodyRx = w / 2;
2293
- const tailTipX = x + w * .12;
2294
- const tailTipY = y + h;
2295
- const tailBaseAngle = 1.5;
2296
- return `M${cx + bodyRx * Math.cos(tailBaseAngle - .18)},${bodyCy + bodyRy * Math.sin(tailBaseAngle - .18)} A${bodyRx},${bodyRy} 0 1 0 ${cx + bodyRx * Math.cos(1.68)},${bodyCy + bodyRy * Math.sin(1.68)} L${tailTipX},${tailTipY} Z`;
2297
- },
2298
- cloudCallout: (x, y, w, h) => {
2299
- const bodyH = h * .78;
2300
- const cx = x + w / 2;
2301
- const cy = y + bodyH / 2;
2302
- const rx = w / 2 * .92;
2303
- const ry = bodyH / 2 * .85;
2304
- const lobes = 10;
2305
- const path = [];
2306
- for (let i = 0; i < lobes; i++) {
2307
- const a = i / lobes * 2 * Math.PI - Math.PI / 2;
2308
- const lobeRx = rx * .32;
2309
- const lobeRy = ry * .32;
2310
- const px0 = cx + rx * Math.cos(a);
2311
- const py0 = cy + ry * Math.sin(a);
2312
- if (i === 0) path.push(`M${px0 - lobeRx},${py0}`);
2313
- path.push(`A${lobeRx},${lobeRy} 0 1 1 ${px0 + lobeRx},${py0}`);
2314
- const nextA = (i + 1) / lobes * 2 * Math.PI - Math.PI / 2;
2315
- const nextX = cx + rx * Math.cos(nextA) - lobeRx;
2316
- const nextY = cy + ry * Math.sin(nextA);
2317
- path.push(`L${nextX},${nextY}`);
2318
- }
2319
- path.push("Z");
2320
- const tailX = x + w * .18;
2321
- const tailY = y + h * .95;
2322
- return `${path.join(" ")} M${tailX - 6},${tailY - 14} a4,3 0 1 0 1,0 Z M${tailX},${tailY} a6,4 0 1 0 1,0 Z`;
2323
- },
2324
- heart: (x, y, w, h) => {
2325
- const cx = x + w / 2;
2326
- const top = y + h * .27;
2327
- return `M${cx},${y + h} C${x},${y + h * .55} ${x},${top} ${cx},${y + h * .4} C${x + w},${top} ${x + w},${y + h * .55} ${cx},${y + h} Z`;
2328
- },
2329
- sun: (x, y, w, h) => {
2330
- const cx = x + w / 2;
2331
- const cy = y + h / 2;
2332
- const innerR = Math.min(w, h) * .25;
2333
- const outerR = Math.min(w, h) * .5;
2334
- const rays = 12;
2335
- const path = [];
2336
- for (let i = 0; i < rays * 2; i++) {
2337
- const r = i % 2 === 0 ? outerR : innerR;
2338
- const a = i / (rays * 2) * 2 * Math.PI - Math.PI / 2;
2339
- const px0 = cx + r * Math.cos(a);
2340
- const py0 = cy + r * Math.sin(a);
2341
- path.push(`${i === 0 ? "M" : "L"}${px0},${py0}`);
2342
- }
2343
- path.push("Z");
2344
- return path.join(" ");
2345
- },
2346
- smileyFace: (x, y, w, h) => {
2347
- const cx = x + w / 2;
2348
- const cy = y + h / 2;
2349
- const r = Math.min(w, h) / 2 - 1;
2350
- const eyeR = r * .07;
2351
- const eyeOff = r * .32;
2352
- const mouthW = r * .5;
2353
- const mouthY = cy + r * .18;
2354
- return `M${cx + r},${cy} A${r},${r} 0 1 0 ${cx - r},${cy} A${r},${r} 0 1 0 ${cx + r},${cy} Z M${cx - eyeOff + eyeR},${cy - eyeOff} A${eyeR},${eyeR} 0 1 1 ${cx - eyeOff - eyeR},${cy - eyeOff} A${eyeR},${eyeR} 0 1 1 ${cx - eyeOff + eyeR},${cy - eyeOff} Z M${cx + eyeOff + eyeR},${cy - eyeOff} A${eyeR},${eyeR} 0 1 1 ${cx + eyeOff - eyeR},${cy - eyeOff} A${eyeR},${eyeR} 0 1 1 ${cx + eyeOff + eyeR},${cy - eyeOff} Z M${cx - mouthW},${mouthY} Q${cx},${mouthY + r * .32} ${cx + mouthW},${mouthY}`;
2355
- },
2356
- lightningBolt: (x, y, w, h) => {
2357
- return `M${x + w * .5},${y} L${x + w * .15},${y + h * .55} L${x + w * .45},${y + h * .55} L${x + w * .3},${y + h} L${x + w * .85},${y + h * .4} L${x + w * .55},${y + h * .4} L${x + w * .7},${y} Z`;
2358
- },
2359
- flowChartProcess: (x, y, w, h) => `M${x},${y} L${x + w},${y} L${x + w},${y + h} L${x},${y + h} Z`,
2360
- flowChartAlternateProcess: (x, y, w, h) => {
2361
- const r = Math.min(w, h) * .18;
2362
- return `M${x + r},${y} L${x + w - r},${y} A${r},${r} 0 0 1 ${x + w},${y + r} L${x + w},${y + h - r} A${r},${r} 0 0 1 ${x + w - r},${y + h} L${x + r},${y + h} A${r},${r} 0 0 1 ${x},${y + h - r} L${x},${y + r} A${r},${r} 0 0 1 ${x + r},${y} Z`;
2363
- },
2364
- flowChartDecision: (x, y, w, h) => {
2365
- const cx = x + w / 2;
2366
- const cy = y + h / 2;
2367
- return `M${cx},${y} L${x + w},${cy} L${cx},${y + h} L${x},${cy} Z`;
2368
- },
2369
- flowChartTerminator: (x, y, w, h) => {
2370
- const r = h / 2;
2371
- return `M${x + r},${y} L${x + w - r},${y} A${r},${r} 0 0 1 ${x + w - r},${y + h} L${x + r},${y + h} A${r},${r} 0 0 1 ${x + r},${y} Z`;
2372
- },
2373
- flowChartConnector: (x, y, w, h) => {
2374
- const cx = x + w / 2;
2375
- const cy = y + h / 2;
2376
- const r = Math.min(w, h) / 2;
2377
- return `M${cx + r},${cy} A${r},${r} 0 1 1 ${cx - r},${cy} A${r},${r} 0 1 1 ${cx + r},${cy} Z`;
2378
- },
2379
- flowChartDocument: (x, y, w, h) => {
2380
- const wave = h * .18;
2381
- return `M${x},${y} L${x + w},${y} L${x + w},${y + h - wave} C${x + w * .75},${y + h + wave * .5} ${x + w * .25},${y + h - wave * 2} ${x},${y + h - wave * .5} Z`;
2382
- },
2383
- flowChartMultidocument: (x, y, w, h) => {
2384
- const inset = w * .06;
2385
- return `${`M${x + inset},${y + inset * .6} L${x + w},${y + inset * .6} L${x + w},${y + h - inset * .6} L${x + w - inset},${y + h - inset * .6} L${x + w - inset},${y + inset * .6}`} Z ${`M${x},${y + inset * 1.2} L${x + w - inset},${y + inset * 1.2} L${x + w - inset},${y + h * .85} C${x + (w - inset) * .75},${y + h + 6} ${x + (w - inset) * .25},${y + h * .75} ${x},${y + h * .95} Z`}`;
2386
- },
2387
- flowChartPredefinedProcess: (x, y, w, h) => {
2388
- const inset = w * .1;
2389
- return `M${x},${y} L${x + w},${y} L${x + w},${y + h} L${x},${y + h} Z M${x + inset},${y} L${x + inset},${y + h} M${x + w - inset},${y} L${x + w - inset},${y + h}`;
2390
- },
2391
- flowChartInternalStorage: (x, y, w, h) => {
2392
- const inset = Math.min(w, h) * .1;
2393
- return `M${x},${y} L${x + w},${y} L${x + w},${y + h} L${x},${y + h} Z M${x + inset},${y} L${x + inset},${y + h} M${x},${y + inset} L${x + w},${y + inset}`;
2394
- },
2395
- flowChartManualInput: (x, y, w, h) => {
2396
- return `M${x},${y + h * .35} L${x + w},${y} L${x + w},${y + h} L${x},${y + h} Z`;
2397
- },
2398
- flowChartManualOperation: (x, y, w, h) => {
2399
- return `M${x},${y} L${x + w},${y} L${x + w * .8},${y + h} L${x + w * .2},${y + h} Z`;
2400
- },
2401
- flowChartInputOutput: (x, y, w, h) => {
2402
- const skew = w * .18;
2403
- return `M${x + skew},${y} L${x + w},${y} L${x + w - skew},${y + h} L${x},${y + h} Z`;
2404
- },
2405
- flowChartPunchedTape: (x, y, w, h) => {
2406
- const wave = h * .12;
2407
- return `M${x},${y + wave} C${x + w * .25},${y - wave} ${x + w * .75},${y + wave * 2} ${x + w},${y + wave} L${x + w},${y + h - wave} C${x + w * .75},${y + h + wave} ${x + w * .25},${y + h - wave * 2} ${x},${y + h - wave} Z`;
2408
- },
2409
- flowChartCard: (x, y, w, h) => {
2410
- const cut = h * .3;
2411
- return `M${x + cut},${y} L${x + w},${y} L${x + w},${y + h} L${x},${y + h} L${x},${y + cut} Z`;
2412
- },
2413
- flowChartPunchedCard: (x, y, w, h) => {
2414
- const cut = h * .2;
2415
- return `M${x + cut},${y} L${x + w},${y} L${x + w},${y + h} L${x},${y + h} L${x},${y + cut} Z`;
2416
- },
2417
- flowChartOnlineStorage: (x, y, w, h) => {
2418
- const cap = w * .12;
2419
- return `M${x + cap},${y} L${x + w},${y} L${x + w},${y + h} L${x + cap},${y + h} A${cap},${h / 2} 0 0 1 ${x + cap},${y} Z`;
2420
- },
2421
- flowChartMagneticDisk: (x, y, w, h) => {
2422
- const er = h * .12;
2423
- return `M${x},${y + er} A${w / 2},${er} 0 0 1 ${x + w},${y + er} L${x + w},${y + h - er} A${w / 2},${er} 0 0 1 ${x},${y + h - er} Z M${x},${y + er} A${w / 2},${er} 0 0 0 ${x + w},${y + er}`;
2424
- },
2425
- flowChartMagneticDrum: (x, y, w, h) => {
2426
- const er = w * .12;
2427
- return `M${x + er},${y} L${x + w - er},${y} A${er},${h / 2} 0 0 1 ${x + w - er},${y + h} L${x + er},${y + h} A${er},${h / 2} 0 0 1 ${x + er},${y} Z M${x + w - er},${y} A${er},${h / 2} 0 0 0 ${x + w - er},${y + h}`;
2428
- },
2429
- flowChartMagneticTape: (x, y, w, h) => {
2430
- const cx = x + w / 2;
2431
- const cy = y + h / 2;
2432
- const r = Math.min(w, h) / 2;
2433
- return `M${cx + r},${cy} A${r},${r} 0 1 0 ${cx - r * .7},${cy + r * .7} L${x + w},${y + h} L${cx + r},${cy} Z`;
2434
- },
2435
- flowChartSummingJunction: (x, y, w, h) => {
2436
- const cx = x + w / 2;
2437
- const cy = y + h / 2;
2438
- const r = Math.min(w, h) / 2;
2439
- const off = r * Math.SQRT1_2;
2440
- return `M${cx + r},${cy} A${r},${r} 0 1 0 ${cx - r},${cy} A${r},${r} 0 1 0 ${cx + r},${cy} Z M${cx - off},${cy - off} L${cx + off},${cy + off} M${cx - off},${cy + off} L${cx + off},${cy - off}`;
2441
- },
2442
- flowChartOr: (x, y, w, h) => {
2443
- const cx = x + w / 2;
2444
- const cy = y + h / 2;
2445
- const r = Math.min(w, h) / 2;
2446
- return `M${cx + r},${cy} A${r},${r} 0 1 0 ${cx - r},${cy} A${r},${r} 0 1 0 ${cx + r},${cy} Z M${cx - r},${cy} L${cx + r},${cy} M${cx},${cy - r} L${cx},${cy + r}`;
2447
- },
2448
- flowChartCollate: (x, y, w, h) => {
2449
- return `M${x},${y} L${x + w},${y} L${x},${y + h} L${x + w},${y + h} Z`;
2450
- },
2451
- flowChartSort: (x, y, w, h) => {
2452
- const cx = x + w / 2;
2453
- const cy = y + h / 2;
2454
- return `M${cx},${y} L${x + w},${cy} L${cx},${y + h} L${x},${cy} Z M${x},${cy} L${x + w},${cy}`;
2455
- },
2456
- flowChartExtract: (x, y, w, h) => {
2457
- return `M${x + w / 2},${y} L${x + w},${y + h} L${x},${y + h} Z`;
2458
- },
2459
- flowChartMerge: (x, y, w, h) => {
2460
- return `M${x},${y} L${x + w},${y} L${x + w / 2},${y + h} Z`;
2461
- },
2462
- flowChartOfflineStorage: (x, y, w, h) => {
2463
- return `M${x + w / 2},${y} L${x + w},${y + h} L${x},${y + h} Z M${x + w * .25},${y + h * .75} L${x + w * .75},${y + h * .75}`;
2464
- },
2465
- flowChartDelay: (x, y, w, h) => {
2466
- const r = h / 2;
2467
- return `M${x},${y} L${x + w - r},${y} A${r},${r} 0 0 1 ${x + w - r},${y + h} L${x},${y + h} Z`;
2468
- },
2469
- flowChartDisplay: (x, y, w, h) => {
2470
- const r = h / 2;
2471
- return `M${x + r * .5},${y} L${x + w - r},${y} A${r},${r} 0 0 1 ${x + w - r},${y + h} L${x + r * .5},${y + h} L${x},${y + h / 2} Z`;
2472
- },
2473
- flowChartPreparation: (x, y, w, h) => {
2474
- const cut = w * .18;
2475
- return `M${x + cut},${y} L${x + w - cut},${y} L${x + w},${y + h / 2} L${x + w - cut},${y + h} L${x + cut},${y + h} L${x},${y + h / 2} Z`;
2476
- },
2477
- notchedRightArrow: (x, y, w, h) => {
2478
- return `M${x},${y + h * .3} L${x + w * .65},${y + h * .3} L${x + w * .65},${y} L${x + w},${y + h / 2} L${x + w * .65},${y + h} L${x + w * .65},${y + h * .7} L${x},${y + h * .7} L${x + w * .15},${y + h / 2} Z`;
2479
- },
2480
- stripedRightArrow: (x, y, w, h) => {
2481
- const stripe = w * .04;
2482
- return `M${x},${y + h * .3} L${x + stripe},${y + h * .3} L${x + stripe},${y + h * .7} L${x},${y + h * .7} Z M${x + stripe * 2.5},${y + h * .3} L${x + stripe * 3.5},${y + h * .3} L${x + stripe * 3.5},${y + h * .7} L${x + stripe * 2.5},${y + h * .7} Z M${x + stripe * 5},${y + h * .3} L${x + w * .65},${y + h * .3} L${x + w * .65},${y} L${x + w},${y + h / 2} L${x + w * .65},${y + h} L${x + w * .65},${y + h * .7} L${x + stripe * 5},${y + h * .7} Z`;
2483
- },
2484
- curvedRightArrow: (x, y, w, h) => {
2485
- return `M${x},${y + h * .6} Q${x + w * .5},${y} ${x + w * .85},${y + h * .25} L${x + w},${y + h * .45} L${x + w * .85},${y + h * .55} L${x + w * .7},${y + h * .35} Q${x + w * .45},${y + h * .18} ${x + w * .15},${y + h * .75} Z`;
2486
- },
2487
- uturnArrow: (x, y, w, h) => {
2488
- return `M${x},${y + h} L${x},${y + h / 2} A${w * .4},${h * .4} 0 0 1 ${x + w * .8},${y + h / 2} L${x + w * .8},${y + h * .25} L${x + w},${y + h * .45} L${x + w * .8},${y + h * .65} L${x + w * .8},${y + h / 2} A${w * .2},${h * .25} 0 0 0 ${x + w * .2},${y + h / 2} L${x + w * .2},${y + h} Z`;
2489
- },
2490
- leftBracket: (x, y, w, h) => {
2491
- return `M${x + w},${y} L${x},${y} L${x},${y + h} L${x + w},${y + h}`;
2492
- },
2493
- rightBracket: (x, y, w, h) => {
2494
- return `M${x},${y} L${x + w},${y} L${x + w},${y + h} L${x},${y + h}`;
2495
- },
2496
- bracketPair: (x, y, w, h) => {
2497
- return `M${x + w * .1},${y} L${x},${y} L${x},${y + h} L${x + w * .1},${y + h} M${x + w * .9},${y} L${x + w},${y} L${x + w},${y + h} L${x + w * .9},${y + h}`;
2498
- },
2499
- leftBrace: (x, y, w, h) => {
2500
- const mid = y + h / 2;
2501
- return `M${x + w},${y} Q${x},${y} ${x},${mid - 8} Q${x},${mid} ${x - 4},${mid} Q${x},${mid} ${x},${mid + 8} Q${x},${y + h} ${x + w},${y + h}`;
2502
- },
2503
- rightBrace: (x, y, w, h) => {
2504
- const mid = y + h / 2;
2505
- return `M${x},${y} Q${x + w},${y} ${x + w},${mid - 8} Q${x + w},${mid} ${x + w + 4},${mid} Q${x + w},${mid} ${x + w},${mid + 8} Q${x + w},${y + h} ${x},${y + h}`;
2506
- },
2507
- bracePair: (x, y, w, h) => {
2508
- const mid = y + h / 2;
2509
- return `M${x + w * .12},${y} Q${x},${y} ${x},${mid - 8} Q${x},${mid} ${x - 4},${mid} Q${x},${mid} ${x},${mid + 8} Q${x},${y + h} ${x + w * .12},${y + h} M${x + w * .88},${y} Q${x + w},${y} ${x + w},${mid - 8} Q${x + w},${mid} ${x + w + 4},${mid} Q${x + w},${mid} ${x + w},${mid + 8} Q${x + w},${y + h} ${x + w * .88},${y + h}`;
2510
- },
2511
- snip1Rect: (x, y, w, h) => {
2512
- const c = Math.min(w, h) * .18;
2513
- return `M${x},${y} L${x + w - c},${y} L${x + w},${y + c} L${x + w},${y + h} L${x},${y + h} Z`;
2514
- },
2515
- snip2SameRect: (x, y, w, h) => {
2516
- const c = Math.min(w, h) * .18;
2517
- return `M${x + c},${y} L${x + w - c},${y} L${x + w},${y + c} L${x + w},${y + h} L${x},${y + h} L${x},${y + c} Z`;
2518
- },
2519
- snip2DiagRect: (x, y, w, h) => {
2520
- const c = Math.min(w, h) * .18;
2521
- return `M${x},${y} L${x + w - c},${y} L${x + w},${y + c} L${x + w},${y + h} L${x + c},${y + h} L${x},${y + h - c} Z`;
2522
- },
2523
- snipRoundRect: (x, y, w, h) => {
2524
- const c = Math.min(w, h) * .18;
2525
- return `M${x + c},${y} A${c},${c} 0 0 0 ${x},${y + c} L${x},${y + h} L${x + w},${y + h} L${x + w},${y + c} L${x + w - c},${y} Z`;
2526
- },
2527
- round1Rect: (x, y, w, h) => {
2528
- const r = Math.min(w, h) * .18;
2529
- return `M${x},${y} L${x + w - r},${y} A${r},${r} 0 0 1 ${x + w},${y + r} L${x + w},${y + h} L${x},${y + h} Z`;
2530
- },
2531
- round2SameRect: (x, y, w, h) => {
2532
- const r = Math.min(w, h) * .18;
2533
- return `M${x + r},${y} L${x + w - r},${y} A${r},${r} 0 0 1 ${x + w},${y + r} L${x + w},${y + h} L${x},${y + h} L${x},${y + r} A${r},${r} 0 0 1 ${x + r},${y} Z`;
2534
- },
2535
- round2DiagRect: (x, y, w, h) => {
2536
- const r = Math.min(w, h) * .18;
2537
- return `M${x},${y} L${x + w - r},${y} A${r},${r} 0 0 1 ${x + w},${y + r} L${x + w},${y + h} L${x + r},${y + h} A${r},${r} 0 0 1 ${x},${y + h - r} Z`;
2538
- },
2539
- ribbon: (x, y, w, h) => {
2540
- const notch = w * .06;
2541
- const bodyTop = y + h * .2;
2542
- const bodyBot = y + h * .8;
2543
- return `M${x},${bodyTop} L${x + notch * 2},${y} L${x + w - notch * 2},${y} L${x + w},${bodyTop} L${x + w * .85},${bodyTop + (bodyBot - bodyTop) / 2} L${x + w},${bodyBot} L${x + w - notch * 2},${y + h} L${x + w - notch * 4},${bodyBot} L${x + notch * 4},${bodyBot} L${x + notch * 2},${y + h} L${x},${bodyBot} L${x + w * .15},${bodyTop + (bodyBot - bodyTop) / 2} Z`;
2544
- },
2545
- ribbon2: (x, y, w, h) => {
2546
- const notch = w * .06;
2547
- const bodyTop = y + h * .2;
2548
- const bodyBot = y + h * .8;
2549
- return `M${x},${bodyBot} L${x + notch * 2},${y + h} L${x + w - notch * 2},${y + h} L${x + w},${bodyBot} L${x + w * .85},${bodyTop + (bodyBot - bodyTop) / 2} L${x + w},${bodyTop} L${x + w - notch * 2},${y} L${x + w - notch * 4},${bodyTop} L${x + notch * 4},${bodyTop} L${x + notch * 2},${y} L${x},${bodyTop} L${x + w * .15},${bodyTop + (bodyBot - bodyTop) / 2} Z`;
2550
- },
2551
- verticalScroll: (x, y, w, h) => {
2552
- const r = w * .08;
2553
- return `M${x + r},${y + r} A${r},${r} 0 0 1 ${x + r * 2},${y} L${x + w},${y} L${x + w},${y + h - r} A${r},${r} 0 0 1 ${x + w - r * 2},${y + h} L${x},${y + h} L${x},${y + r} A${r},${r} 0 0 1 ${x + r},${y + r} Z`;
2554
- },
2555
- horizontalScroll: (x, y, w, h) => {
2556
- const r = h * .08;
2557
- return `M${x + r},${y + r} A${r},${r} 0 0 1 ${x},${y + r * 2} L${x},${y + h} L${x + w - r},${y + h} A${r},${r} 0 0 1 ${x + w},${y + h - r * 2} L${x + w},${y} L${x + r},${y} A${r},${r} 0 0 1 ${x + r},${y + r} Z`;
2558
- },
2559
- wave: (x, y, w, h) => {
2560
- return `M${x},${y + h * .5} C${x + w * .25},${y - h * .1} ${x + w * .5},${y + h * .85} ${x + w * .75},${y + h * .3} C${x + w * .85},${y + h * .05} ${x + w * .95},${y + h * .4} ${x + w},${y + h * .5} L${x + w},${y + h} C${x + w * .75},${y + h * .4} ${x + w * .5},${y + h * 1.1} ${x + w * .25},${y + h * .55} C${x + w * .15},${y + h * .3} ${x + w * .05},${y + h * .6} ${x},${y + h * .55} Z`;
2561
- },
2562
- doubleWave: (x, y, w, h) => {
2563
- return `M${x},${y + h * .4} C${x + w * .15},${y - h * .05} ${x + w * .35},${y + h * .65} ${x + w * .5},${y + h * .3} C${x + w * .65},${y - h * .05} ${x + w * .85},${y + h * .65} ${x + w},${y + h * .4} L${x + w},${y + h} C${x + w * .85},${y + h * .4} ${x + w * .65},${y + h * 1.05} ${x + w * .5},${y + h * .7} C${x + w * .35},${y + h * 1.05} ${x + w * .15},${y + h * .4} ${x},${y + h} Z`;
2564
- },
2565
- mathPlus: (x, y, w, h) => {
2566
- const t = Math.min(w, h) * .2;
2567
- const cx = x + w / 2;
2568
- const cy = y + h / 2;
2569
- return `M${cx - t / 2},${y} L${cx + t / 2},${y} L${cx + t / 2},${cy - t / 2} L${x + w},${cy - t / 2} L${x + w},${cy + t / 2} L${cx + t / 2},${cy + t / 2} L${cx + t / 2},${y + h} L${cx - t / 2},${y + h} L${cx - t / 2},${cy + t / 2} L${x},${cy + t / 2} L${x},${cy - t / 2} L${cx - t / 2},${cy - t / 2} Z`;
2570
- },
2571
- mathMinus: (x, y, w, h) => {
2572
- const t = h * .3;
2573
- const cy = y + h / 2;
2574
- return `M${x},${cy - t / 2} L${x + w},${cy - t / 2} L${x + w},${cy + t / 2} L${x},${cy + t / 2} Z`;
2575
- },
2576
- mathMultiply: (x, y, w, h) => {
2577
- const t = Math.min(w, h) * .16;
2578
- const cx = x + w / 2;
2579
- const cy = y + h / 2;
2580
- return `M${x},${y + t} L${x + t},${y} L${cx},${cy - t} L${x + w - t},${y} L${x + w},${y + t} L${cx + t},${cy} L${x + w},${y + h - t} L${x + w - t},${y + h} L${cx},${cy + t} L${x + t},${y + h} L${x},${y + h - t} L${cx - t},${cy} Z`;
2581
- },
2582
- mathDivide: (x, y, w, h) => {
2583
- const dot = Math.min(w, h) * .1;
2584
- const cx = x + w / 2;
2585
- const cy = y + h / 2;
2586
- return `M${x},${cy - dot * .4} L${x + w},${cy - dot * .4} L${x + w},${cy + dot * .4} L${x},${cy + dot * .4} Z M${cx - dot},${y + h * .18} A${dot},${dot} 0 1 0 ${cx + dot},${y + h * .18} A${dot},${dot} 0 1 0 ${cx - dot},${y + h * .18} Z M${cx - dot},${y + h * .82} A${dot},${dot} 0 1 0 ${cx + dot},${y + h * .82} A${dot},${dot} 0 1 0 ${cx - dot},${y + h * .82} Z`;
2587
- },
2588
- mathEqual: (x, y, w, h) => {
2589
- const t = h * .2;
2590
- return `M${x},${y + h * .3 - t / 2} L${x + w},${y + h * .3 - t / 2} L${x + w},${y + h * .3 + t / 2} L${x},${y + h * .3 + t / 2} Z M${x},${y + h * .7 - t / 2} L${x + w},${y + h * .7 - t / 2} L${x + w},${y + h * .7 + t / 2} L${x},${y + h * .7 + t / 2} Z`;
2591
- },
2592
- mathNotEqual: (x, y, w, h) => {
2593
- const t = h * .15;
2594
- const cy = y + h / 2;
2595
- return `M${x},${cy - h * .18 - t / 2} L${x + w},${cy - h * .18 - t / 2} L${x + w},${cy - h * .18 + t / 2} L${x},${cy - h * .18 + t / 2} Z M${x},${cy + h * .18 - t / 2} L${x + w},${cy + h * .18 - t / 2} L${x + w},${cy + h * .18 + t / 2} L${x},${cy + h * .18 + t / 2} Z M${x + w * .7},${y} L${x + w * .85},${y} L${x + w * .3},${y + h} L${x + w * .15},${y + h} Z`;
2596
- },
2597
- actionButtonBlank: (x, y, w, h) => {
2598
- const r = Math.min(w, h) * .06;
2599
- return `M${x + r},${y} L${x + w - r},${y} A${r},${r} 0 0 1 ${x + w},${y + r} L${x + w},${y + h - r} A${r},${r} 0 0 1 ${x + w - r},${y + h} L${x + r},${y + h} A${r},${r} 0 0 1 ${x},${y + h - r} L${x},${y + r} A${r},${r} 0 0 1 ${x + r},${y} Z`;
2600
- },
2601
- irregularSeal1: (x, y, w, h) => {
2602
- const cx = x + w / 2;
2603
- const cy = y + h / 2;
2604
- const rx = w / 2;
2605
- const ry = h / 2;
2606
- const offsets = [
2607
- 1,
2608
- .45,
2609
- .95,
2610
- .5,
2611
- 1,
2612
- .4,
2613
- .9,
2614
- .55,
2615
- 1,
2616
- .45,
2617
- .95,
2618
- .5,
2619
- 1,
2620
- .4,
2621
- .9,
2622
- .55
2623
- ];
2624
- const points = [];
2625
- for (let i = 0; i < offsets.length; i++) {
2626
- const a = i / offsets.length * 2 * Math.PI - Math.PI / 2;
2627
- const r = offsets[i] ?? 1;
2628
- const px0 = cx + rx * r * Math.cos(a);
2629
- const py0 = cy + ry * r * Math.sin(a);
2630
- points.push(`${i === 0 ? "M" : "L"}${px0},${py0}`);
2631
- }
2632
- points.push("Z");
2633
- return points.join(" ");
2634
- },
2635
- irregularSeal2: (x, y, w, h) => {
2636
- const cx = x + w / 2;
2637
- const cy = y + h / 2;
2638
- const rx = w / 2;
2639
- const ry = h / 2;
2640
- const offsets = [
2641
- 1,
2642
- .4,
2643
- .95,
2644
- .5,
2645
- .9,
2646
- .35,
2647
- .85,
2648
- .45,
2649
- 1,
2650
- .4,
2651
- .95,
2652
- .5,
2653
- .9,
2654
- .35,
2655
- .85,
2656
- .45,
2657
- 1,
2658
- .4,
2659
- .95,
2660
- .5,
2661
- .9,
2662
- .35,
2663
- .85,
2664
- .45
2665
- ];
2666
- const points = [];
2667
- for (let i = 0; i < offsets.length; i++) {
2668
- const a = i / offsets.length * 2 * Math.PI - Math.PI / 2;
2669
- const r = offsets[i] ?? 1;
2670
- const px0 = cx + rx * r * Math.cos(a);
2671
- const py0 = cy + ry * r * Math.sin(a);
2672
- points.push(`${i === 0 ? "M" : "L"}${px0},${py0}`);
2673
- }
2674
- points.push("Z");
2675
- return points.join(" ");
2676
- },
2677
- cloud: (x, y, w, h) => {
2678
- const cx = x + w / 2;
2679
- const cy = y + h / 2;
2680
- const rx = w / 2 * .92;
2681
- const ry = h / 2 * .85;
2682
- const lobes = 10;
2683
- const path = [];
2684
- for (let i = 0; i < lobes; i++) {
2685
- const a = i / lobes * 2 * Math.PI - Math.PI / 2;
2686
- const lobeRx = rx * .32;
2687
- const lobeRy = ry * .32;
2688
- const px0 = cx + rx * Math.cos(a);
2689
- const py0 = cy + ry * Math.sin(a);
2690
- if (i === 0) path.push(`M${px0 - lobeRx},${py0}`);
2691
- path.push(`A${lobeRx},${lobeRy} 0 1 1 ${px0 + lobeRx},${py0}`);
2692
- const nextA = (i + 1) / lobes * 2 * Math.PI - Math.PI / 2;
2693
- const nextX = cx + rx * Math.cos(nextA) - lobeRx;
2694
- const nextY = cy + ry * Math.sin(nextA);
2695
- path.push(`L${nextX},${nextY}`);
2696
- }
2697
- path.push("Z");
2698
- return path.join(" ");
2699
- },
2700
- pie: (x, y, w, h) => {
2701
- const cx = x + w / 2;
2702
- const cy = y + h / 2;
2703
- const r = Math.min(w, h) / 2;
2704
- return `M${cx},${cy} L${cx + r},${cy} A${r},${r} 0 1 1 ${cx},${cy - r} Z`;
2705
- },
2706
- chord: (x, y, w, h) => {
2707
- const cx = x + w / 2;
2708
- const cy = y + h / 2;
2709
- const rx = w / 2;
2710
- const ry = h / 2;
2711
- return `M${cx + rx},${cy} A${rx},${ry} 0 1 1 ${cx - rx},${cy} L${cx + rx},${cy} Z`;
2712
- },
2713
- teardrop: (x, y, w, h) => {
2714
- const cx = x + w / 2;
2715
- const cy = y + h / 2;
2716
- const rx = w / 2;
2717
- const ry = h / 2;
2718
- return `M${cx},${y} L${x + w},${y} L${x + w},${cy} A${rx},${ry} 0 1 1 ${cx - rx},${cy} A${rx},${ry} 0 0 1 ${cx},${y} Z`;
2719
- },
2720
- arc: (x, y, w, h) => {
2721
- const cx = x + w / 2;
2722
- const cy = y + h / 2;
2723
- const rx = w / 2;
2724
- const ry = h / 2;
2725
- return `M${cx + rx},${cy} A${rx},${ry} 0 1 1 ${cx},${cy + ry}`;
2726
- },
2727
- blockArc: (x, y, w, h) => {
2728
- const cx = x + w / 2;
2729
- const cy = y + h / 2;
2730
- const outerR = Math.min(w, h) / 2;
2731
- const innerR = outerR * .6;
2732
- return `M${cx + outerR},${cy} A${outerR},${outerR} 0 1 1 ${cx},${cy - outerR} L${cx},${cy - innerR} A${innerR},${innerR} 0 1 0 ${cx + innerR},${cy} Z`;
2733
- },
2734
- moon: (x, y, w, h) => {
2735
- const cx = x + w / 2;
2736
- const cy = y + h / 2;
2737
- const rx = w / 2;
2738
- const ry = h / 2;
2739
- const innerRx = rx * .78;
2740
- const offsetX = rx * .32;
2741
- return `M${cx + rx},${cy} A${rx},${ry} 0 1 1 ${cx - rx},${cy} A${rx},${ry} 0 1 1 ${cx + rx},${cy} M${cx - rx + offsetX + innerRx},${cy} A${innerRx},${ry * .95} 0 1 1 ${cx - rx + offsetX - innerRx},${cy} A${innerRx},${ry * .95} 0 1 1 ${cx - rx + offsetX + innerRx},${cy}`;
2742
- },
2743
- plus: (x, y, w, h) => {
2744
- const t = Math.min(w, h) * .3;
2745
- const cx = x + w / 2;
2746
- const cy = y + h / 2;
2747
- return `M${cx - t / 2},${y} L${cx + t / 2},${y} L${cx + t / 2},${cy - t / 2} L${x + w},${cy - t / 2} L${x + w},${cy + t / 2} L${cx + t / 2},${cy + t / 2} L${cx + t / 2},${y + h} L${cx - t / 2},${y + h} L${cx - t / 2},${cy + t / 2} L${x},${cy + t / 2} L${x},${cy - t / 2} L${cx - t / 2},${cy - t / 2} Z`;
2748
- },
2749
- plaque: (x, y, w, h) => {
2750
- const r = Math.min(w, h) * .18;
2751
- return `M${x + r},${y} L${x + w - r},${y} A${r},${r} 0 0 0 ${x + w},${y + r} L${x + w},${y + h - r} A${r},${r} 0 0 0 ${x + w - r},${y + h} L${x + r},${y + h} A${r},${r} 0 0 0 ${x},${y + h - r} L${x},${y + r} A${r},${r} 0 0 0 ${x + r},${y} Z`;
2752
- },
2753
- can: (x, y, w, h) => {
2754
- const er = h * .12;
2755
- return `M${x},${y + er} A${w / 2},${er} 0 0 1 ${x + w},${y + er} L${x + w},${y + h - er} A${w / 2},${er} 0 0 1 ${x},${y + h - er} Z M${x},${y + er} A${w / 2},${er} 0 0 0 ${x + w},${y + er}`;
2756
- },
2757
- cube: (x, y, w, h) => {
2758
- const d = Math.min(w, h) * .2;
2759
- return `M${x},${y + d} L${x + d},${y} L${x + w},${y} L${x + w},${y + h - d} L${x + w - d},${y + h} L${x},${y + h} Z M${x},${y + d} L${x + w - d},${y + d} L${x + w},${y} M${x + w - d},${y + d} L${x + w - d},${y + h}`;
2760
- },
2761
- bevel: (x, y, w, h) => {
2762
- const d = Math.min(w, h) * .12;
2763
- return `M${x},${y} L${x + w},${y} L${x + w},${y + h} L${x},${y + h} Z M${x + d},${y + d} L${x + w - d},${y + d} L${x + w - d},${y + h - d} L${x + d},${y + h - d} Z M${x},${y} L${x + d},${y + d} M${x + w},${y} L${x + w - d},${y + d} M${x},${y + h} L${x + d},${y + h - d} M${x + w},${y + h} L${x + w - d},${y + h - d}`;
2764
- },
2765
- donut: (x, y, w, h) => {
2766
- const cx = x + w / 2;
2767
- const cy = y + h / 2;
2768
- const r = Math.min(w, h) / 2;
2769
- const innerR = r * .65;
2770
- return `M${cx + r},${cy} A${r},${r} 0 1 0 ${cx - r},${cy} A${r},${r} 0 1 0 ${cx + r},${cy} Z M${cx + innerR},${cy} A${innerR},${innerR} 0 1 1 ${cx - innerR},${cy} A${innerR},${innerR} 0 1 1 ${cx + innerR},${cy} Z`;
2771
- },
2772
- noSmoking: (x, y, w, h) => {
2773
- const cx = x + w / 2;
2774
- const cy = y + h / 2;
2775
- const r = Math.min(w, h) / 2;
2776
- const innerR = r * .78;
2777
- const t = r * .12;
2778
- return `M${cx + r},${cy} A${r},${r} 0 1 0 ${cx - r},${cy} A${r},${r} 0 1 0 ${cx + r},${cy} Z M${cx + innerR},${cy} A${innerR},${innerR} 0 1 1 ${cx - innerR},${cy} A${innerR},${innerR} 0 1 1 ${cx + innerR},${cy} Z M${cx - r * .71 - t},${cy - r * .71 + t} L${cx - r * .71 + t},${cy - r * .71 - t} L${cx + r * .71 + t},${cy + r * .71 - t} L${cx + r * .71 - t},${cy + r * .71 + t} Z`;
2779
- },
2780
- frame: (x, y, w, h) => {
2781
- const f = Math.min(w, h) * .1;
2782
- return `M${x},${y} L${x + w},${y} L${x + w},${y + h} L${x},${y + h} Z M${x + f},${y + f} L${x + f},${y + h - f} L${x + w - f},${y + h - f} L${x + w - f},${y + f} Z`;
2783
- },
2784
- halfFrame: (x, y, w, h) => {
2785
- const f = Math.min(w, h) * .15;
2786
- return `M${x},${y} L${x + w},${y} L${x + w - f},${y + f} L${x + f},${y + f} L${x + f},${y + h - f} L${x},${y + h} Z`;
2787
- },
2788
- corner: (x, y, w, h) => {
2789
- const tx = w * .4;
2790
- const ty = h * .4;
2791
- return `M${x},${y} L${x + tx},${y} L${x + tx},${y + h - ty} L${x + w},${y + h - ty} L${x + w},${y + h} L${x},${y + h} Z`;
2792
- },
2793
- diagStripe: (x, y, w, h) => {
2794
- return `M${x},${y} L${x + w * .6},${y} L${x},${y + h * .6} Z`;
2795
- },
2796
- ellipseRibbon: (x, y, w, h) => {
2797
- const notch = w * .08;
2798
- const bodyTop = y + h * .2;
2799
- const bodyBot = y + h * .85;
2800
- const arcDip = h * .15;
2801
- return `M${x},${bodyTop} C${x + w * .3},${bodyTop - arcDip} ${x + w * .7},${bodyTop - arcDip} ${x + w},${bodyTop} L${x + w * .85},${bodyTop + (bodyBot - bodyTop) / 2} L${x + w},${bodyBot} L${x + w - notch * 2},${y + h} L${x + w - notch * 4},${bodyBot} C${x + w * .7},${bodyBot + arcDip * .4} ${x + w * .3},${bodyBot + arcDip * .4} L${x + notch * 4},${bodyBot} L${x + notch * 2},${y + h} L${x},${bodyBot} L${x + w * .15},${bodyTop + (bodyBot - bodyTop) / 2} Z`;
2802
- },
2803
- ellipseRibbon2: (x, y, w, h) => {
2804
- const notch = w * .08;
2805
- const bodyTop = y + h * .15;
2806
- const bodyBot = y + h * .8;
2807
- const arcRise = h * .15;
2808
- return `M${x},${bodyBot} C${x + w * .3},${bodyBot + arcRise} ${x + w * .7},${bodyBot + arcRise} ${x + w},${bodyBot} L${x + w * .85},${bodyTop + (bodyBot - bodyTop) / 2} L${x + w},${bodyTop} L${x + w - notch * 2},${y} L${x + w - notch * 4},${bodyTop} C${x + w * .7},${bodyTop - arcRise * .4} ${x + w * .3},${bodyTop - arcRise * .4} L${x + notch * 4},${bodyTop} L${x + notch * 2},${y} L${x},${bodyTop} L${x + w * .15},${bodyTop + (bodyBot - bodyTop) / 2} Z`;
2809
- },
2810
- quadArrow: (x, y, w, h) => {
2811
- const cx = x + w / 2;
2812
- const cy = y + h / 2;
2813
- const tip = .2;
2814
- const stem = .15;
2815
- const headW = .35;
2816
- return `M${cx},${y} L${cx + headW * w},${y + tip * h} L${cx + stem * w},${y + tip * h} L${cx + stem * w},${cy - stem * h} L${x + w - tip * w},${cy - stem * h} L${x + w - tip * w},${cy - headW * h} L${x + w},${cy} L${x + w - tip * w},${cy + headW * h} L${x + w - tip * w},${cy + stem * h} L${cx + stem * w},${cy + stem * h} L${cx + stem * w},${y + h - tip * h} L${cx + headW * w},${y + h - tip * h} L${cx},${y + h} L${cx - headW * w},${y + h - tip * h} L${cx - stem * w},${y + h - tip * h} L${cx - stem * w},${cy + stem * h} L${x + tip * w},${cy + stem * h} L${x + tip * w},${cy + headW * h} L${x},${cy} L${x + tip * w},${cy - headW * h} L${x + tip * w},${cy - stem * h} L${cx - stem * w},${cy - stem * h} L${cx - stem * w},${y + tip * h} L${cx - headW * w},${y + tip * h} Z`;
2817
- },
2818
- leftRightUpArrow: (x, y, w, h) => {
2819
- const cx = x + w / 2;
2820
- const tip = .2;
2821
- const stem = .15;
2822
- const headW = .35;
2823
- return `M${cx},${y} L${cx + headW * w},${y + tip * h} L${cx + stem * w},${y + tip * h} L${cx + stem * w},${y + h - tip * h} L${x + w - tip * w},${y + h - tip * h} L${x + w - tip * w},${y + h - headW * h} L${x + w},${y + h} L${x + w - tip * w},${y + h + headW * h} L${x + w - tip * w},${y + h - tip * h} L${cx - stem * w},${y + h - tip * h} L${cx - stem * w},${y + tip * h} L${cx - headW * w},${y + tip * h} Z`;
2824
- },
2825
- bentUpArrow: (x, y, w, h) => {
2826
- const stem = .3;
2827
- const tip = .25;
2828
- return `M${x},${y + h * .55} L${x + w * .5},${y + h * .55} L${x + w * .5},${y + tip * h} L${x + w * (.5 - stem * .5)},${y + tip * h} L${x + w * .75},${y} L${x + w},${y + tip * h} L${x + w * .65},${y + tip * h} L${x + w * .65},${y + h * .55 + h * .4} L${x},${y + h * .55 + h * .4} Z`;
2829
- },
2830
- curvedLeftArrow: (x, y, w, h) => {
2831
- return `M${x + w},${y + h * .6} Q${x + w * .5},${y} ${x + w * .15},${y + h * .25} L${x},${y + h * .45} L${x + w * .15},${y + h * .55} L${x + w * .3},${y + h * .35} Q${x + w * .55},${y + h * .18} ${x + w * .85},${y + h * .75} Z`;
2832
- },
2833
- curvedUpArrow: (x, y, w, h) => {
2834
- return `M${x + w * .4},${y + h} Q${x},${y + h * .5} ${x + w * .25},${y + h * .15} L${x + w * .45},${y} L${x + w * .55},${y + h * .15} L${x + w * .35},${y + h * .3} Q${x + w * .18},${y + h * .55} ${x + w * .75},${y + h * .85} Z`;
2835
- },
2836
- curvedDownArrow: (x, y, w, h) => {
2837
- return `M${x + w * .4},${y} Q${x},${y + h * .5} ${x + w * .25},${y + h * .85} L${x + w * .45},${y + h} L${x + w * .55},${y + h * .85} L${x + w * .35},${y + h * .7} Q${x + w * .18},${y + h * .45} ${x + w * .75},${y + h * .15} Z`;
2838
- },
2839
- swooshArrow: (x, y, w, h) => {
2840
- return `M${x},${y + h * .75} C${x + w * .35},${y + h} ${x + w * .65},${y + h * .3} ${x + w * .75},${y + h * .2} L${x + w * .65},${y + h * .05} L${x + w},${y + h * .18} L${x + w * .78},${y + h * .45} L${x + w * .7},${y + h * .3} C${x + w * .55},${y + h * .6} ${x + w * .35},${y + h * .9} ${x},${y + h * .85} Z`;
2841
- },
2842
- circularArrow: (x, y, w, h) => {
2843
- const cx = x + w / 2;
2844
- const cy = y + h / 2;
2845
- const outerR = Math.min(w, h) / 2;
2846
- const innerR = outerR * .62;
2847
- const midR = (outerR + innerR) / 2;
2848
- return `M${cx},${cy - outerR} A${outerR},${outerR} 0 1 1 ${cx - outerR},${cy} L${cx - midR - midR * .25},${cy + outerR * .15} L${cx - midR + midR * .25},${cy + outerR * .3} L${cx - innerR},${cy} A${innerR},${innerR} 0 1 0 ${cx},${cy - innerR} Z`;
2849
- },
2850
- leftCircularArrow: (x, y, w, h) => {
2851
- const cx = x + w / 2;
2852
- const cy = y + h / 2;
2853
- const outerR = Math.min(w, h) / 2;
2854
- const innerR = outerR * .62;
2855
- return `M${cx},${cy - outerR} A${outerR},${outerR} 0 1 0 ${cx + outerR},${cy} L${cx + (outerR + innerR) / 2 + (outerR + innerR) / 2 * .25},${cy + outerR * .15} L${cx + (outerR + innerR) / 2 - (outerR + innerR) / 2 * .25},${cy + outerR * .3} L${cx + innerR},${cy} A${innerR},${innerR} 0 1 1 ${cx},${cy - innerR} Z`;
2856
- },
2857
- leftRightCircularArrow: (x, y, w, h) => {
2858
- const cx = x + w / 2;
2859
- const cy = y + h / 2;
2860
- const outerR = Math.min(w, h) / 2;
2861
- const innerR = outerR * .62;
2862
- return `M${cx - outerR * .15},${cy - outerR * 1.05} L${cx + outerR * .15},${cy - outerR * 1.05} L${cx + outerR * .1},${cy - outerR * .85} A${outerR},${outerR} 0 1 1 ${cx - outerR * .1},${cy - outerR * .85} Z M${cx},${cy - innerR} A${innerR},${innerR} 0 1 0 ${cx},${cy + innerR}`;
2863
- },
2864
- rightArrowCallout: (x, y, w, h) => {
2865
- const headW = w * .25;
2866
- return `M${x},${y + h * .3} L${x + w - headW},${y + h * .3} L${x + w - headW},${y} L${x + w},${y + h / 2} L${x + w - headW},${y + h} L${x + w - headW},${y + h * .7} L${x},${y + h * .7} Z`;
2867
- },
2868
- leftArrowCallout: (x, y, w, h) => {
2869
- const headW = w * .25;
2870
- return `M${x + headW},${y + h * .3} L${x + w},${y + h * .3} L${x + w},${y + h * .7} L${x + headW},${y + h * .7} L${x + headW},${y + h} L${x},${y + h / 2} L${x + headW},${y} Z`;
2871
- },
2872
- upArrowCallout: (x, y, w, h) => {
2873
- const headH = h * .25;
2874
- return `M${x + w * .3},${y + headH} L${x + w * .3},${y + h} L${x + w * .7},${y + h} L${x + w * .7},${y + headH} L${x + w},${y + headH} L${x + w / 2},${y} L${x},${y + headH} Z`;
2875
- },
2876
- downArrowCallout: (x, y, w, h) => {
2877
- const headH = h * .25;
2878
- return `M${x + w * .3},${y} L${x + w * .7},${y} L${x + w * .7},${y + h - headH} L${x + w},${y + h - headH} L${x + w / 2},${y + h} L${x},${y + h - headH} L${x + w * .3},${y + h - headH} Z`;
2879
- },
2880
- leftRightArrowCallout: (x, y, w, h) => {
2881
- const headW = w * .2;
2882
- return `M${x},${y + h / 2} L${x + headW},${y} L${x + headW},${y + h * .3} L${x + w - headW},${y + h * .3} L${x + w - headW},${y} L${x + w},${y + h / 2} L${x + w - headW},${y + h} L${x + w - headW},${y + h * .7} L${x + headW},${y + h * .7} L${x + headW},${y + h} Z`;
2883
- },
2884
- upDownArrowCallout: (x, y, w, h) => {
2885
- const headH = h * .2;
2886
- return `M${x + w / 2},${y} L${x},${y + headH} L${x + w * .3},${y + headH} L${x + w * .3},${y + h - headH} L${x},${y + h - headH} L${x + w / 2},${y + h} L${x + w},${y + h - headH} L${x + w * .7},${y + h - headH} L${x + w * .7},${y + headH} L${x + w},${y + headH} Z`;
2887
- },
2888
- quadArrowCallout: (x, y, w, h) => {
2889
- const cx = x + w / 2;
2890
- const cy = y + h / 2;
2891
- const tip = .16;
2892
- const stem = .18;
2893
- const headW = .32;
2894
- const txt = .28;
2895
- return `M${cx - txt * w},${cy - txt * h} L${cx - txt * w},${cy - stem * h} L${cx - stem * w},${cy - stem * h} L${cx - stem * w},${y + tip * h} L${cx - headW * w},${y + tip * h} L${cx},${y} L${cx + headW * w},${y + tip * h} L${cx + stem * w},${y + tip * h} L${cx + stem * w},${cy - stem * h} L${cx + txt * w},${cy - stem * h} L${cx + txt * w},${cy - txt * h} L${x + w - tip * w},${cy - txt * h} L${x + w - tip * w},${cy - headW * h} L${x + w},${cy} L${x + w - tip * w},${cy + headW * h} L${x + w - tip * w},${cy + txt * h} L${cx + txt * w},${cy + txt * h} L${cx + txt * w},${cy + stem * h} L${cx + stem * w},${cy + stem * h} L${cx + stem * w},${y + h - tip * h} L${cx + headW * w},${y + h - tip * h} L${cx},${y + h} L${cx - headW * w},${y + h - tip * h} L${cx - stem * w},${y + h - tip * h} L${cx - stem * w},${cy + stem * h} L${cx - txt * w},${cy + stem * h} L${cx - txt * w},${cy + txt * h} L${x + tip * w},${cy + txt * h} L${x + tip * w},${cy + headW * h} L${x},${cy} L${x + tip * w},${cy - headW * h} L${x + tip * w},${cy - txt * h} Z`;
2896
- },
2897
- actionButtonHome: (x, y, w, h) => {
2898
- const cx = x + w / 2;
2899
- const cy = y + h / 2;
2900
- const s = Math.min(w, h) * .3;
2901
- return `${PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""} M${cx - s},${cy + s * .6} L${cx - s},${cy - s * .1} L${cx},${cy - s * .7} L${cx + s},${cy - s * .1} L${cx + s},${cy + s * .6} L${cx + s * .3},${cy + s * .6} L${cx + s * .3},${cy + s * .1} L${cx - s * .3},${cy + s * .1} L${cx - s * .3},${cy + s * .6} Z`;
2902
- },
2903
- actionButtonForwardNext: (x, y, w, h) => {
2904
- const cx = x + w / 2;
2905
- const cy = y + h / 2;
2906
- const s = Math.min(w, h) * .3;
2907
- return `${PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""} M${cx - s * .7},${cy - s} L${cx + s * .7},${cy} L${cx - s * .7},${cy + s} Z`;
2908
- },
2909
- actionButtonBackPrevious: (x, y, w, h) => {
2910
- const cx = x + w / 2;
2911
- const cy = y + h / 2;
2912
- const s = Math.min(w, h) * .3;
2913
- return `${PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""} M${cx + s * .7},${cy - s} L${cx - s * .7},${cy} L${cx + s * .7},${cy + s} Z`;
2914
- },
2915
- actionButtonEnd: (x, y, w, h) => {
2916
- const cx = x + w / 2;
2917
- const cy = y + h / 2;
2918
- const s = Math.min(w, h) * .3;
2919
- return `${PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""} M${cx - s},${cy - s} L${cx + s * .4},${cy} L${cx - s},${cy + s} Z M${cx + s * .5},${cy - s} L${cx + s},${cy - s} L${cx + s},${cy + s} L${cx + s * .5},${cy + s} Z`;
2920
- },
2921
- actionButtonBeginning: (x, y, w, h) => {
2922
- const cx = x + w / 2;
2923
- const cy = y + h / 2;
2924
- const s = Math.min(w, h) * .3;
2925
- return `${PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""} M${cx + s},${cy - s} L${cx - s * .4},${cy} L${cx + s},${cy + s} Z M${cx - s * .5},${cy - s} L${cx - s},${cy - s} L${cx - s},${cy + s} L${cx - s * .5},${cy + s} Z`;
2926
- },
2927
- actionButtonReturn: (x, y, w, h) => {
2928
- const cx = x + w / 2;
2929
- const cy = y + h / 2;
2930
- const s = Math.min(w, h) * .28;
2931
- return `${PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""} M${cx + s},${cy - s} L${cx + s * .4},${cy - s} L${cx + s * .4},${cy + s * .2} L${cx - s * .2},${cy + s * .2} L${cx - s * .2},${cy - s * .2} L${cx - s},${cy + s * .2} L${cx - s * .2},${cy + s} L${cx - s * .2},${cy + s * .5} L${cx + s},${cy + s * .5} Z`;
2932
- },
2933
- actionButtonHelp: (x, y, w, h) => {
2934
- const cx = x + w / 2;
2935
- const cy = y + h / 2;
2936
- const s = Math.min(w, h) * .3;
2937
- return `${PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""} M${cx - s * .4},${cy - s * .4} Q${cx - s * .4},${cy - s} ${cx},${cy - s} Q${cx + s * .4},${cy - s} ${cx + s * .4},${cy - s * .4} Q${cx + s * .4},${cy} ${cx},${cy} L${cx},${cy + s * .4} M${cx - s * .18},${cy + s * .8} L${cx + s * .18},${cy + s * .8} L${cx + s * .18},${cy + s} L${cx - s * .18},${cy + s} Z`;
2938
- },
2939
- actionButtonInformation: (x, y, w, h) => {
2940
- const cx = x + w / 2;
2941
- const cy = y + h / 2;
2942
- const s = Math.min(w, h) * .3;
2943
- return `${PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""} M${cx - s * .2},${cy - s * .7} L${cx + s * .2},${cy - s * .7} L${cx + s * .2},${cy - s * .35} L${cx - s * .2},${cy - s * .35} Z M${cx - s * .2},${cy - s * .1} L${cx + s * .2},${cy - s * .1} L${cx + s * .2},${cy + s} L${cx - s * .2},${cy + s} Z`;
2944
- },
2945
- actionButtonDocument: (x, y, w, h) => {
2946
- const cx = x + w / 2;
2947
- const cy = y + h / 2;
2948
- const s = Math.min(w, h) * .3;
2949
- return `${PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""} M${cx - s * .6},${cy - s} L${cx + s * .3},${cy - s} L${cx + s * .6},${cy - s * .7} L${cx + s * .6},${cy + s} L${cx - s * .6},${cy + s} Z M${cx + s * .3},${cy - s} L${cx + s * .3},${cy - s * .7} L${cx + s * .6},${cy - s * .7}`;
2950
- },
2951
- actionButtonSound: (x, y, w, h) => {
2952
- const cx = x + w / 2;
2953
- const cy = y + h / 2;
2954
- const s = Math.min(w, h) * .3;
2955
- return `${PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""} M${cx - s},${cy - s * .4} L${cx - s * .3},${cy - s * .4} L${cx + s * .3},${cy - s} L${cx + s * .3},${cy + s} L${cx - s * .3},${cy + s * .4} L${cx - s},${cy + s * .4} Z M${cx + s * .55},${cy - s * .4} Q${cx + s * .95},${cy} ${cx + s * .55},${cy + s * .4}`;
2956
- },
2957
- actionButtonMovie: (x, y, w, h) => {
2958
- const cx = x + w / 2;
2959
- const cy = y + h / 2;
2960
- const s = Math.min(w, h) * .3;
2961
- const out = [PRESET_PATHS.actionButtonBlank?.(x, y, w, h) ?? ""];
2962
- out.push(`M${cx - s},${cy - s * .6} L${cx + s},${cy - s * .6} L${cx + s},${cy + s * .6} L${cx - s},${cy + s * .6} Z`);
2963
- for (let i = 0; i < 4; i++) {
2964
- const px0 = cx - s + (i + .5) * (s * 2 / 4);
2965
- out.push(`M${px0 - s * .08},${cy - s * .45} L${px0 + s * .08},${cy - s * .45} L${px0 + s * .08},${cy - s * .3} L${px0 - s * .08},${cy - s * .3} Z`);
2966
- out.push(`M${px0 - s * .08},${cy + s * .3} L${px0 + s * .08},${cy + s * .3} L${px0 + s * .08},${cy + s * .45} L${px0 - s * .08},${cy + s * .45} Z`);
2967
- }
2968
- return out.join(" ");
2969
- },
2970
- borderCallout1: (x, y, w, h) => {
2971
- return `M${x},${y} L${x + w * .6},${y} L${x + w * .6},${y + h * .5} L${x},${y + h * .5} Z M${x + w * .6},${y + h * .5} L${x + w},${y + h}`;
2972
- },
2973
- borderCallout2: (x, y, w, h) => {
2974
- return `M${x},${y} L${x + w * .6},${y} L${x + w * .6},${y + h * .5} L${x},${y + h * .5} Z M${x + w * .6},${y + h * .5} L${x + w * .85},${y + h * .75} L${x + w},${y + h}`;
2975
- },
2976
- borderCallout3: (x, y, w, h) => {
2977
- return `M${x},${y} L${x + w * .6},${y} L${x + w * .6},${y + h * .5} L${x},${y + h * .5} Z M${x + w * .6},${y + h * .5} L${x + w * .75},${y + h * .65} L${x + w * .9},${y + h * .65} L${x + w},${y + h}`;
2978
- },
2979
- accentCallout1: (x, y, w, h) => {
2980
- return `M${x},${y} L${x + w * .6},${y} L${x + w * .6},${y + h * .5} L${x},${y + h * .5} Z M${x + w * .58},${y} L${x + w * .58},${y + h * .5} M${x + w * .6},${y + h * .5} L${x + w},${y + h}`;
2981
- },
2982
- accentBorderCallout1: (x, y, w, h) => {
2983
- return PRESET_PATHS.accentCallout1?.(x, y, w, h) ?? "";
2984
- },
2985
- callout1: (x, y, w, h) => {
2986
- return `M${x},${y + h * .5} L${x + w},${y + h}`;
2987
- },
2988
- callout2: (x, y, w, h) => {
2989
- return `M${x},${y + h * .5} L${x + w * .6},${y + h * .7} L${x + w},${y + h}`;
2990
- },
2991
- callout3: (x, y, w, h) => {
2992
- return `M${x},${y + h * .5} L${x + w * .4},${y + h * .55} L${x + w * .7},${y + h * .8} L${x + w},${y + h}`;
2993
- },
2994
- straightConnector1: (x, y, w, h) => `M${x},${y} L${x + w},${y + h}`,
2995
- bentConnector2: (x, y, w, h) => `M${x},${y} L${x + w},${y} L${x + w},${y + h}`,
2996
- bentConnector3: (x, y, w, h) => `M${x},${y} L${x + w / 2},${y} L${x + w / 2},${y + h} L${x + w},${y + h}`,
2997
- bentConnector4: (x, y, w, h) => `M${x},${y} L${x + w * .33},${y} L${x + w * .33},${y + h * .5} L${x + w * .66},${y + h * .5} L${x + w * .66},${y + h} L${x + w},${y + h}`,
2998
- bentConnector5: (x, y, w, h) => `M${x},${y} L${x + w * .25},${y} L${x + w * .25},${y + h * .5} L${x + w * .75},${y + h * .5} L${x + w * .75},${y + h} L${x + w},${y + h}`,
2999
- curvedConnector2: (x, y, w, h) => `M${x},${y} Q${x + w},${y} ${x + w},${y + h}`,
3000
- curvedConnector3: (x, y, w, h) => `M${x},${y} C${x + w * .5},${y} ${x + w * .5},${y + h} ${x + w},${y + h}`,
3001
- curvedConnector4: (x, y, w, h) => `M${x},${y} C${x + w * .33},${y} ${x + w * .33},${y + h * .5} ${x + w * .5},${y + h * .5} C${x + w * .66},${y + h * .5} ${x + w * .66},${y + h} ${x + w},${y + h}`,
3002
- curvedConnector5: (x, y, w, h) => `M${x},${y} C${x + w * .25},${y} ${x + w * .25},${y + h * .25} ${x + w * .5},${y + h * .5} C${x + w * .75},${y + h * .75} ${x + w * .75},${y + h} ${x + w},${y + h}`
3003
- };
3004
2232
  const ALIGNMENT_TO_CSS = {
3005
2233
  left: "left",
3006
2234
  center: "center",
@@ -3222,6 +2450,7 @@ const buildSvgTextInput = (a) => {
3222
2450
  ...fmt.innerShadow,
3223
2451
  ...fmt.innerShadow.color ? { color: resolveColor(fmt.innerShadow.color, a.theme, "#000000") } : {}
3224
2452
  } } : {},
2453
+ ...a.bevel ? { bevel: a.bevel } : {},
3225
2454
  href: run.href ?? null,
3226
2455
  ...run.hrefTip !== void 0 ? { hrefTip: run.hrefTip } : {}
3227
2456
  };
@@ -3373,12 +2602,12 @@ const resolveTextBodyModel = (pres, shape, bounds, theme, phType, measure, defau
3373
2602
  const tIns = margins.top ?? DEFAULT_INSET_Y;
3374
2603
  const rIns = margins.right ?? DEFAULT_INSET_X;
3375
2604
  const bIns = margins.bottom ?? DEFAULT_INSET_Y;
3376
- const { x: innerX, y: innerY, w: innerW, h: innerH } = resolveTextBodyRect(getShapePreset(shape), bounds, {
2605
+ const { x: innerX, y: innerY, w: innerW, h: innerH } = resolveTextBodyRect(bounds, {
3377
2606
  left: lIns,
3378
2607
  top: tIns,
3379
2608
  right: rIns,
3380
2609
  bottom: bIns
3381
- }, shapeCustomTextRect(getShapeCustomGeometry(shape), getShapeBounds(shape)));
2610
+ }, shapeTextRect(shape));
3382
2611
  if (innerW <= 0 || innerH <= 0) return null;
3383
2612
  const svgTextRect = (v) => useSvgTextRect && v !== "none" && v !== "upright" ? {
3384
2613
  x: bounds.x + tIns,
@@ -3702,6 +2931,7 @@ const renderHtmlParagraphs = (paraData, numberLabels, theme, autoFitScale, defau
3702
2931
  const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body") => {
3703
2932
  const model = resolveTextBodyModel(pres, shape, bounds, theme, phType, ctx.measure, activeDeckTextColor, ctx.mode === "svg" && output === "body");
3704
2933
  if (model === null) return "";
2934
+ const bevel = textBevelOf(getShapeText3D(shape));
3705
2935
  const { paraData, numberLabels, authoredAutofit, autoFitScale, defaultPt, themeFace, effectiveDefaultFont, effectiveBody, anchor, innerX, innerY, innerW, innerH, svgTextRect } = model;
3706
2936
  const defaultColor = activeDeckTextColor;
3707
2937
  const paragraphs = renderHtmlParagraphs(paraData, numberLabels, theme, autoFitScale, defaultPt, defaultColor, effectiveBody.wrap !== "none");
@@ -3737,7 +2967,8 @@ const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body"
3737
2967
  measure: ctx.mode === "svg" ? ctx.measure : browserTextMeasurer() ?? ctx.measure,
3738
2968
  ...ctx.mode === "foreignObject" ? { resolveFamily: browserFontFamily } : {},
3739
2969
  vert: svgVert,
3740
- columns: svgColumns
2970
+ columns: svgColumns,
2971
+ bevel
3741
2972
  };
3742
2973
  if (output === "effects") {
3743
2974
  const effectArgs = {
@@ -3755,6 +2986,10 @@ const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body"
3755
2986
  ...effectArgs,
3756
2987
  effectKind: "fill"
3757
2988
  }) : "",
2989
+ bevel ? buildAndLayoutSvgText({
2990
+ ...effectArgs,
2991
+ effectKind: "bevel"
2992
+ }) : "",
3758
2993
  paraData.some((para) => para.runs.some((run) => run.fmt?.innerShadow != null)) ? buildAndLayoutSvgText({
3759
2994
  ...effectArgs,
3760
2995
  effectKind: "innerShadow"
@@ -3791,10 +3026,11 @@ const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body"
3791
3026
  const content = paragraphs.join("");
3792
3027
  const body = `<div xmlns="http://www.w3.org/1999/xhtml" style="display:flex;flex-direction:column;justify-content:${justify};width:100%;height:100%;box-sizing:border-box;overflow:visible;font-family:${effectiveDefaultFont};color:${defaultColor};${`translate:${model.anchorOffset.x}px ${model.anchorOffset.y}px;`}${wrapStyle}${vertStyles}">${content}</div>`;
3793
3028
  const foreign = `<foreignObject x="${E(innerX)}" y="${E(innerY)}" width="${E(innerW)}" height="${E(innerH)}" overflow="visible">${body}</foreignObject>`;
3794
- const hasCharacterEffect = paraData.some((para) => para.runs.some((run) => run.fmt?.reflection !== void 0 && run.fmt.reflection !== null || run.fmt?.innerShadow !== void 0 && run.fmt.innerShadow !== null || hasPaintedTextFill(run)));
3029
+ const hasCharacterEffect = bevel !== null || paraData.some((para) => para.runs.some((run) => run.fmt?.reflection !== void 0 && run.fmt.reflection !== null || run.fmt?.innerShadow !== void 0 && run.fmt.innerShadow !== null || hasPaintedTextFill(run)));
3795
3030
  let reflectionOverlay = "";
3796
3031
  let fillOverlay = "";
3797
3032
  let innerShadowOverlay = "";
3033
+ let bevelOverlay = "";
3798
3034
  if (hasCharacterEffect) {
3799
3035
  const svgVert = verticalLayoutOf(effectiveBody.vert ?? getShapeTextDirection(shape));
3800
3036
  const { x: rX, y: rY, w: rW, h: rH } = svgTextRect(svgVert);
@@ -3820,7 +3056,8 @@ const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body"
3820
3056
  vert: svgVert,
3821
3057
  columns: null,
3822
3058
  effectsOnly: true,
3823
- resolveFamily: browserFontFamily
3059
+ resolveFamily: browserFontFamily,
3060
+ bevel
3824
3061
  };
3825
3062
  const hasCharacterReflection = paraData.some((para) => para.runs.some((run) => run.fmt?.reflection !== void 0 && run.fmt.reflection !== null));
3826
3063
  const hasCharacterInnerShadow = paraData.some((para) => para.runs.some((run) => run.fmt?.innerShadow !== void 0 && run.fmt.innerShadow !== null));
@@ -3832,6 +3069,10 @@ const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body"
3832
3069
  ...effectArgs,
3833
3070
  effectKind: "fill"
3834
3071
  });
3072
+ if (bevel) bevelOverlay = buildAndLayoutSvgText({
3073
+ ...effectArgs,
3074
+ effectKind: "bevel"
3075
+ });
3835
3076
  if (hasCharacterInnerShadow) innerShadowOverlay = buildAndLayoutSvgText({
3836
3077
  ...effectArgs,
3837
3078
  effectKind: "innerShadow"
@@ -3841,10 +3082,10 @@ const renderTextBody = (pres, shape, bounds, theme, phType, ctx, output = "body"
3841
3082
  if (bodyRotDeg !== null && bodyRotDeg !== 0) {
3842
3083
  const pivotX = innerX + innerW / 2;
3843
3084
  const pivotY = innerY + innerH / 2;
3844
- const content = output === "effects" ? `${reflectionOverlay}${fillOverlay}${innerShadowOverlay}` : `${reflectionOverlay}${foreign}${fillOverlay}${innerShadowOverlay}`;
3085
+ const content = output === "effects" ? `${reflectionOverlay}${fillOverlay}${bevelOverlay}${innerShadowOverlay}` : `${reflectionOverlay}${foreign}${fillOverlay}${bevelOverlay}${innerShadowOverlay}`;
3845
3086
  return `<g transform="rotate(${bodyRotDeg} ${E(pivotX)} ${E(pivotY)})">${content}</g>`;
3846
3087
  }
3847
- return output === "effects" ? reflectionOverlay + fillOverlay + innerShadowOverlay : reflectionOverlay + foreign + fillOverlay + innerShadowOverlay;
3088
+ return output === "effects" ? reflectionOverlay + fillOverlay + bevelOverlay + innerShadowOverlay : reflectionOverlay + foreign + fillOverlay + bevelOverlay + innerShadowOverlay;
3848
3089
  };
3849
3090
  /**
3850
3091
  * Paint only character reflection/inner-shadow effects for an editable text
@@ -5404,13 +4645,19 @@ const renderTableCellText = (cell, paragraphs, cx, cy, cw, ch, color, pres, shap
5404
4645
  ...ctx.mode === "foreignObject" ? { resolveFamily: browserFontFamily } : {},
5405
4646
  vert: verticalLayoutOf(getTableCellTextDirection(cell)),
5406
4647
  columns: null,
5407
- ...effectsOnly ? { effectsOnly: true } : {}
4648
+ ...effectsOnly ? { effectsOnly: true } : {},
4649
+ bevel: textBevelOf(getTableCellText3D(cell))
5408
4650
  };
5409
4651
  const fillOverlay = () => paraData.some((para) => para.runs.some(hasPaintedTextFill)) ? buildAndLayoutSvgText({
5410
4652
  ...svgArgs,
5411
4653
  effectsOnly: true,
5412
4654
  effectKind: "fill"
5413
4655
  }) : "";
4656
+ const bevelOverlay = () => svgArgs.bevel ? buildAndLayoutSvgText({
4657
+ ...svgArgs,
4658
+ effectsOnly: true,
4659
+ effectKind: "bevel"
4660
+ }) : "";
5414
4661
  if (ctx.mode === "svg" || customTabs || effectsOnly) {
5415
4662
  if (effectsOnly) {
5416
4663
  const reflection = paraData.some((para) => para.runs.some((run) => run.fmt?.reflection != null)) ? buildAndLayoutSvgText({
@@ -5421,7 +4668,7 @@ const renderTableCellText = (cell, paragraphs, cx, cy, cw, ch, color, pres, shap
5421
4668
  ...svgArgs,
5422
4669
  effectKind: "innerShadow"
5423
4670
  }) : "";
5424
- return reflection + fillOverlay() + innerShadow;
4671
+ return reflection + fillOverlay() + bevelOverlay() + innerShadow;
5425
4672
  }
5426
4673
  return buildAndLayoutSvgText(svgArgs);
5427
4674
  }
@@ -5430,7 +4677,7 @@ const renderTableCellText = (cell, paragraphs, cx, cy, cw, ch, color, pres, shap
5430
4677
  const justify = vAnchor === "top" ? "flex-start" : vAnchor === "bottom" ? "flex-end" : "center";
5431
4678
  const familyFont = themeFace ? `${escapeXml(themeFace)}, ${DEFAULT_FONT}` : DEFAULT_FONT;
5432
4679
  const body = renderHtmlParagraphs(paraData, numberLabels, theme, 1, DEFAULT_BODY_PT, color).join("");
5433
- return `<foreignObject x="${px(innerX)}" y="${px(innerY)}" width="${px(innerW)}" height="${px(innerH)}"><div xmlns="http://www.w3.org/1999/xhtml" style="display:flex;flex-direction:column;justify-content:${justify};width:100%;height:100%;box-sizing:border-box;overflow:hidden;line-height:${LINE_HEIGHT};font-family:${familyFont};color:${color};word-break:break-word;${directionStyle}">${body}</div></foreignObject>${fillOverlay()}`;
4680
+ return `<foreignObject x="${px(innerX)}" y="${px(innerY)}" width="${px(innerW)}" height="${px(innerH)}"><div xmlns="http://www.w3.org/1999/xhtml" style="display:flex;flex-direction:column;justify-content:${justify};width:100%;height:100%;box-sizing:border-box;overflow:hidden;line-height:${LINE_HEIGHT};font-family:${familyFont};color:${color};word-break:break-word;${directionStyle}">${body}</div></foreignObject>${fillOverlay()}${bevelOverlay()}`;
5434
4681
  };
5435
4682
  const renderTable = (shape, pres, x, y, w, h, transform, theme, ctx) => {
5436
4683
  let dims;
@@ -5547,8 +4794,12 @@ const renderTable = (shape, pres, x, y, w, h, transform, theme, ctx) => {
5547
4794
  */
5548
4795
  const arcToCubicSegments = (startX, startY, wR, hR, stAng, swAng) => {
5549
4796
  const toRad = (a) => a / 6e4 * (Math.PI / 180);
5550
- const st = toRad(stAng);
5551
- const sw = toRad(swAng);
4797
+ const parametric = (visual) => {
4798
+ const offset = Math.atan2(wR * Math.sin(visual), hR * Math.cos(visual)) - visual;
4799
+ return visual + Math.atan2(Math.sin(offset), Math.cos(offset));
4800
+ };
4801
+ const st = parametric(toRad(stAng));
4802
+ const sw = parametric(toRad(stAng + swAng)) - st;
5552
4803
  const cx = startX - wR * Math.cos(st);
5553
4804
  const cy = startY - hR * Math.sin(st);
5554
4805
  const segCount = Math.max(1, Math.ceil(Math.abs(sw) / (Math.PI / 2)));
@@ -5577,11 +4828,76 @@ const arcToCubicSegments = (startX, startY, wR, hR, stAng, swAng) => {
5577
4828
  return segs;
5578
4829
  };
5579
4830
  /**
5580
- * Renders an evaluated {@link CustomGeometry} as one `<path>` per
5581
- * `GeomPath`, scaling each path's coordinate space (its own `w`/`h`, or
5582
- * the shape extents when those are absent) onto the shape's slide box
5583
- * `(x, y, w, h)` in EMU. Returns `''` when nothing drawable remains, so
5584
- * the caller can fall back to the labelled rect.
4831
+ * The SVG path data of one evaluated {@link GeomPath}, scaling its coordinate
4832
+ * space (its own `w`/`h`, or the shape extents when those are absent) onto
4833
+ * the shape's slide box `(x, y, w, h)` in EMU. `''` when nothing is drawable.
4834
+ */
4835
+ const geometryPathData = (path, x, y, w, h) => {
4836
+ const cw = path.w ?? w;
4837
+ const ch = path.h ?? h;
4838
+ if (cw === 0 || ch === 0) return "";
4839
+ const sx = w / cw;
4840
+ const sy = h / ch;
4841
+ const fx = (gx) => ((x + gx * sx) / EMU_PER_PX).toFixed(2);
4842
+ const fy = (gy) => ((y + gy * sy) / EMU_PER_PX).toFixed(2);
4843
+ const pt = (gx, gy) => `${fx(gx)},${fy(gy)}`;
4844
+ let curX = 0;
4845
+ let curY = 0;
4846
+ let startX = 0;
4847
+ let startY = 0;
4848
+ const d = [];
4849
+ for (const cmd of path.commands) switch (cmd.kind) {
4850
+ case "moveTo":
4851
+ curX = cmd.pt.x;
4852
+ curY = cmd.pt.y;
4853
+ startX = curX;
4854
+ startY = curY;
4855
+ d.push(`M${pt(curX, curY)}`);
4856
+ break;
4857
+ case "lnTo":
4858
+ curX = cmd.pt.x;
4859
+ curY = cmd.pt.y;
4860
+ d.push(`L${pt(curX, curY)}`);
4861
+ break;
4862
+ case "quadBezTo":
4863
+ d.push(`Q${pt(cmd.pts[0].x, cmd.pts[0].y)} ${pt(cmd.pts[1].x, cmd.pts[1].y)}`);
4864
+ curX = cmd.pts[1].x;
4865
+ curY = cmd.pts[1].y;
4866
+ break;
4867
+ case "cubicBezTo":
4868
+ d.push(`C${pt(cmd.pts[0].x, cmd.pts[0].y)} ${pt(cmd.pts[1].x, cmd.pts[1].y)} ${pt(cmd.pts[2].x, cmd.pts[2].y)}`);
4869
+ curX = cmd.pts[2].x;
4870
+ curY = cmd.pts[2].y;
4871
+ break;
4872
+ case "arcTo": {
4873
+ const segs = arcToCubicSegments(curX, curY, cmd.wR, cmd.hR, cmd.stAng, cmd.swAng);
4874
+ for (const s of segs) d.push(`C${pt(s.c1x, s.c1y)} ${pt(s.c2x, s.c2y)} ${pt(s.ex, s.ey)}`);
4875
+ const last = segs[segs.length - 1];
4876
+ if (last) {
4877
+ curX = last.ex;
4878
+ curY = last.ey;
4879
+ }
4880
+ break;
4881
+ }
4882
+ case "close":
4883
+ d.push("Z");
4884
+ curX = startX;
4885
+ curY = startY;
4886
+ break;
4887
+ }
4888
+ return d.join(" ");
4889
+ };
4890
+ const PATH_SHADE = {
4891
+ darken: "fill=\"#000\" fill-opacity=\"0.4\"",
4892
+ darkenLess: "fill=\"#000\" fill-opacity=\"0.2\"",
4893
+ lighten: "fill=\"#fff\" fill-opacity=\"0.4\"",
4894
+ lightenLess: "fill=\"#fff\" fill-opacity=\"0.2\""
4895
+ };
4896
+ /**
4897
+ * Renders an evaluated {@link CustomGeometry} (a `<a:custGeom>` or a preset
4898
+ * from `getPresetGeometry`) as `<path>`s in the shape's slide box. Returns
4899
+ * `''` when nothing drawable remains, so the caller can fall back to the
4900
+ * labelled rect.
5585
4901
  *
5586
4902
  * Per-path `fill="none"` paints stroke-only; `stroke="0"` paints
5587
4903
  * fill-only — mirroring `ST_PathFillMode` / the path `stroke` flag.
@@ -5589,63 +4905,18 @@ const arcToCubicSegments = (startX, startY, wR, hR, stAng, swAng) => {
5589
4905
  const customGeometryToSvg = (geom, x, y, w, h, fill, fillExtra, stroke, strokeWidthEmu, strokeExtra, markerExtra) => {
5590
4906
  const out = [];
5591
4907
  for (const path of geom.paths) {
5592
- const cw = path.w ?? w;
5593
- const ch = path.h ?? h;
5594
- if (cw === 0 || ch === 0) continue;
5595
- const sx = w / cw;
5596
- const sy = h / ch;
5597
- const fx = (gx) => ((x + gx * sx) / EMU_PER_PX).toFixed(2);
5598
- const fy = (gy) => ((y + gy * sy) / EMU_PER_PX).toFixed(2);
5599
- const pt = (gx, gy) => `${fx(gx)},${fy(gy)}`;
5600
- let curX = 0;
5601
- let curY = 0;
5602
- let startX = 0;
5603
- let startY = 0;
5604
- const d = [];
5605
- for (const cmd of path.commands) switch (cmd.kind) {
5606
- case "moveTo":
5607
- curX = cmd.pt.x;
5608
- curY = cmd.pt.y;
5609
- startX = curX;
5610
- startY = curY;
5611
- d.push(`M${pt(curX, curY)}`);
5612
- break;
5613
- case "lnTo":
5614
- curX = cmd.pt.x;
5615
- curY = cmd.pt.y;
5616
- d.push(`L${pt(curX, curY)}`);
5617
- break;
5618
- case "quadBezTo":
5619
- d.push(`Q${pt(cmd.pts[0].x, cmd.pts[0].y)} ${pt(cmd.pts[1].x, cmd.pts[1].y)}`);
5620
- curX = cmd.pts[1].x;
5621
- curY = cmd.pts[1].y;
5622
- break;
5623
- case "cubicBezTo":
5624
- d.push(`C${pt(cmd.pts[0].x, cmd.pts[0].y)} ${pt(cmd.pts[1].x, cmd.pts[1].y)} ${pt(cmd.pts[2].x, cmd.pts[2].y)}`);
5625
- curX = cmd.pts[2].x;
5626
- curY = cmd.pts[2].y;
5627
- break;
5628
- case "arcTo": {
5629
- const segs = arcToCubicSegments(curX, curY, cmd.wR, cmd.hR, cmd.stAng, cmd.swAng);
5630
- for (const s of segs) d.push(`C${pt(s.c1x, s.c1y)} ${pt(s.c2x, s.c2y)} ${pt(s.ex, s.ey)}`);
5631
- const last = segs[segs.length - 1];
5632
- if (last) {
5633
- curX = last.ex;
5634
- curY = last.ey;
5635
- }
5636
- break;
5637
- }
5638
- case "close":
5639
- d.push("Z");
5640
- curX = startX;
5641
- curY = startY;
5642
- break;
5643
- }
5644
- if (d.length === 0) continue;
5645
- const pathFill = path.fill === "none" ? "none" : fill;
5646
- const fillAttrs = path.fill === "none" ? "" : fillExtra;
4908
+ const d = geometryPathData(path, x, y, w, h);
4909
+ if (d === "") continue;
4910
+ const filled = path.fill !== "none" && fill !== "none";
5647
4911
  const strokeAttrs = path.stroke ? ` stroke="${stroke}" stroke-width="${E(strokeWidthEmu)}"${strokeExtra}${markerExtra}` : " stroke=\"none\"";
5648
- out.push(`<path d="${d.join(" ")}" fill="${pathFill}"${fillAttrs}${strokeAttrs} fill-rule="evenodd"/>`);
4912
+ if (filled && path.fill !== "norm") {
4913
+ out.push(`<path d="${d}" fill="${fill}"${fillExtra} stroke="none" fill-rule="evenodd"/>`);
4914
+ out.push(`<path d="${d}" ${PATH_SHADE[path.fill]} stroke="none" fill-rule="evenodd"/>`);
4915
+ if (path.stroke) out.push(`<path d="${d}" fill="none"${strokeAttrs}/>`);
4916
+ continue;
4917
+ }
4918
+ const fillAttrs = filled ? `fill="${fill}"${fillExtra}` : "fill=\"none\"";
4919
+ out.push(`<path d="${d}" ${fillAttrs}${strokeAttrs} fill-rule="evenodd"/>`);
5649
4920
  }
5650
4921
  return out.join("");
5651
4922
  };
@@ -5839,20 +5110,10 @@ const renderShapeContent = (shape, pres, theme, ctx) => {
5839
5110
  let geomSvg = customGeom !== null ? customGeometryToSvg(customGeom, x, y, w, h, p.fill, fa, p.stroke, p.strokeWidth, sa, ma) : "";
5840
5111
  const isCustGeom = geomSvg === "" && rawPreset === null && getShapeXmlString(shape).includes("custGeom");
5841
5112
  if (geomSvg !== "") {} else if (preset === "rect") geomSvg = `<rect x="${E(x)}" y="${E(y)}" width="${E(w)}" height="${E(h)}" fill="${p.fill}"${fa} stroke="${p.stroke}" stroke-width="${E(p.strokeWidth)}"${sa}${ma}/>`;
5842
- else if (preset === "roundRect") {
5843
- const adjVal = getShapeAdjustValues(shape).adj ?? 16667;
5844
- const ratio = Math.max(0, Math.min(.5, adjVal / 1e5));
5845
- const r = E(Math.min(w, h) * ratio);
5846
- geomSvg = `<rect x="${E(x)}" y="${E(y)}" width="${E(w)}" height="${E(h)}" rx="${r}" ry="${r}" fill="${p.fill}"${fa} stroke="${p.stroke}" stroke-width="${E(p.strokeWidth)}"${sa}${ma}/>`;
5847
- } else if (preset === "ellipse" || preset === "oval") geomSvg = `<ellipse cx="${E(cx)}" cy="${E(cy)}" rx="${E(w / 2)}" ry="${E(h / 2)}" fill="${p.fill}"${fa} stroke="${p.stroke}" stroke-width="${E(p.strokeWidth)}"${sa}${ma}/>`;
5848
5113
  else {
5849
- const pathFn = PRESET_PATHS[preset];
5850
- if (pathFn) geomSvg = `<path d="${pathFn(x / EMU_PER_PX, y / EMU_PER_PX, w / EMU_PER_PX, h / EMU_PER_PX)}" fill="${p.fill}"${fa} stroke="${p.stroke}" stroke-width="${E(p.strokeWidth)}" fill-rule="evenodd"${sa}${ma}/>`;
5851
- else {
5852
- const pointsFn = PRESET_POINTS[preset];
5853
- if (pointsFn) geomSvg = `<polygon points="${pointsFn(w / EMU_PER_PX, h / EMU_PER_PX).map(([nx, ny]) => `${E(x + nx * w)},${E(y + ny * h)}`).join(" ")}" fill="${p.fill}"${fa} stroke="${p.stroke}" stroke-width="${E(p.strokeWidth)}"${sa}${ma}/>`;
5854
- else geomSvg = `<rect x="${E(x)}" y="${E(y)}" width="${E(w)}" height="${E(h)}" fill="${p.fill}"${fa} stroke="${p.stroke}" stroke-width="${E(p.strokeWidth)}"${sa}${ma} data-pptx-preset="${escapeXml(preset)}"><title>${escapeXml(`preset: ${preset}`)}</title></rect>`;
5855
- }
5114
+ const geometry = getPresetGeometry(preset, bounds, getShapeAdjustValues(shape));
5115
+ if (geometry !== null) geomSvg = customGeometryToSvg(geometry, x, y, w, h, p.fill, fa, p.stroke, p.strokeWidth, sa, ma);
5116
+ if (geomSvg === "") geomSvg = `<rect x="${E(x)}" y="${E(y)}" width="${E(w)}" height="${E(h)}" fill="${p.fill}"${fa} stroke="${p.stroke}" stroke-width="${E(p.strokeWidth)}"${sa}${ma} data-pptx-preset="${escapeXml(preset)}"><title>${escapeXml(`preset: ${preset}`)}</title></rect>`;
5856
5117
  }
5857
5118
  const fx = buildEffectsFilter(pres, shape);
5858
5119
  const filterAttr = fx ? ` filter="url(#${fx.id})"` : "";
@@ -6373,6 +5634,6 @@ function shapeTextAnchorOffset(pres, shape, options = {}) {
6373
5634
  };
6374
5635
  }
6375
5636
  //#endregion
6376
- export { textColumnsStyle as _, renderTextEffectsSvg as a, shapeCustomTextRect as b, MONO as c, TIMES as d, defaultMeasurer as f, textUnderlineStyle as g, paragraphNumberLabels as h, renderSlideSvg as i, SANS as l, substituteFamily as m, shapeTextAnchorOffset as n, ARIAL as o, isCjk as p, auditTextLayout as r, AVG_GLYPH_W_RATIO as s, shapeAutoFitScale as t, SERIF as u, verticalTextStyle as v, resolveTextBodyRect as y };
5637
+ export { textColumnsStyle as _, renderTextEffectsSvg as a, shapeTextRect as b, MONO as c, TIMES as d, defaultMeasurer as f, textUnderlineStyle as g, paragraphNumberLabels as h, renderSlideSvg as i, SANS as l, substituteFamily as m, shapeTextAnchorOffset as n, ARIAL as o, isCjk as p, auditTextLayout as r, AVG_GLYPH_W_RATIO as s, shapeAutoFitScale as t, SERIF as u, verticalTextStyle as v, resolveTextBodyRect as y };
6377
5638
 
6378
- //# sourceMappingURL=src-DYfIZIh8.js.map
5639
+ //# sourceMappingURL=src-Bwmf324Z.js.map