@hirokisakabe/pom 9.1.1 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/buildContext.js +2 -6
- package/dist/buildContext.js.map +1 -1
- package/dist/buildPptx.d.ts +2 -1
- package/dist/buildPptx.d.ts.map +1 -1
- package/dist/buildPptx.js +4 -9
- package/dist/buildPptx.js.map +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/registry/definitions/icon.js +1 -1
- package/dist/registry/definitions/list.js.map +1 -1
- package/dist/renderPptx/nodes/chart.js +172 -47
- package/dist/renderPptx/nodes/chart.js.map +1 -1
- package/dist/renderPptx/nodes/flow.js +98 -90
- package/dist/renderPptx/nodes/flow.js.map +1 -1
- package/dist/renderPptx/nodes/icon.js +36 -24
- package/dist/renderPptx/nodes/icon.js.map +1 -1
- package/dist/renderPptx/nodes/image.js +5 -22
- package/dist/renderPptx/nodes/image.js.map +1 -1
- package/dist/renderPptx/nodes/list.js +94 -111
- package/dist/renderPptx/nodes/list.js.map +1 -1
- package/dist/renderPptx/nodes/matrix.js +95 -70
- package/dist/renderPptx/nodes/matrix.js.map +1 -1
- package/dist/renderPptx/nodes/processArrow.js +74 -35
- package/dist/renderPptx/nodes/processArrow.js.map +1 -1
- package/dist/renderPptx/nodes/pyramid.js +37 -16
- package/dist/renderPptx/nodes/pyramid.js.map +1 -1
- package/dist/renderPptx/nodes/shape.js +66 -37
- package/dist/renderPptx/nodes/shape.js.map +1 -1
- package/dist/renderPptx/nodes/svg.js +2 -5
- package/dist/renderPptx/nodes/svg.js.map +1 -1
- package/dist/renderPptx/nodes/table.js +89 -59
- package/dist/renderPptx/nodes/table.js.map +1 -1
- package/dist/renderPptx/nodes/text.js +1 -18
- package/dist/renderPptx/nodes/text.js.map +1 -1
- package/dist/renderPptx/nodes/timeline.js +114 -74
- package/dist/renderPptx/nodes/timeline.js.map +1 -1
- package/dist/renderPptx/nodes/tree.js +81 -79
- package/dist/renderPptx/nodes/tree.js.map +1 -1
- package/dist/renderPptx/pptxAuthoring.js +381 -0
- package/dist/renderPptx/pptxAuthoring.js.map +1 -0
- package/dist/renderPptx/renderPptx.js +158 -128
- package/dist/renderPptx/renderPptx.js.map +1 -1
- package/dist/renderPptx/textOptions.js +7 -8
- package/dist/renderPptx/textOptions.js.map +1 -1
- package/dist/renderPptx/units.js +3 -3
- package/dist/renderPptx/units.js.map +1 -1
- package/dist/renderPptx/utils/backgroundBorder.js +70 -48
- package/dist/renderPptx/utils/backgroundBorder.js.map +1 -1
- package/dist/renderPptx/utils/contentArea.js +1 -1
- package/dist/renderPptx/utils/contentArea.js.map +1 -1
- package/dist/renderPptx/utils/glimpsePicture.js +111 -0
- package/dist/renderPptx/utils/glimpsePicture.js.map +1 -0
- package/dist/renderPptx/utils/glimpseShape.js +71 -0
- package/dist/renderPptx/utils/glimpseShape.js.map +1 -0
- package/dist/renderPptx/utils/glimpseTextBox.js +107 -0
- package/dist/renderPptx/utils/glimpseTextBox.js.map +1 -0
- package/dist/renderPptx/utils/straightLine.js +33 -15
- package/dist/renderPptx/utils/straightLine.js.map +1 -1
- package/dist/renderPptx/utils/visualStyle.js +3 -56
- package/dist/renderPptx/utils/visualStyle.js.map +1 -1
- package/dist/renderPptx/writablePptx.d.ts +23 -0
- package/dist/renderPptx/writablePptx.d.ts.map +1 -0
- package/dist/renderPptx/writablePptx.js +74 -0
- package/dist/renderPptx/writablePptx.js.map +1 -0
- package/dist/shared/measureImage.js.map +1 -1
- package/package.json +4 -5
- package/dist/renderPptx/glimpseTextBoxes.js +0 -347
- package/dist/renderPptx/glimpseTextBoxes.js.map +0 -1
- package/dist/renderPptx/glowEffects.js +0 -157
- package/dist/renderPptx/glowEffects.js.map +0 -1
- package/dist/renderPptx/gradientFills.js +0 -154
- package/dist/renderPptx/gradientFills.js.map +0 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { pxToIn, pxToPt } from "../units.js";
|
|
2
1
|
import { withContentBounds } from "../utils/contentArea.js";
|
|
3
|
-
import {
|
|
2
|
+
import { addGlimpseTextBox, createGlimpseParagraphs } from "../utils/glimpseTextBox.js";
|
|
3
|
+
import { addGlimpseShape, createShapeBoundsInput, shapeOutline, solidShapeFill } from "../utils/glimpseShape.js";
|
|
4
|
+
import { addStraightLine } from "../utils/straightLine.js";
|
|
4
5
|
import { measureFlow } from "../../calcYogaLayout/measureCompositeNodes.js";
|
|
6
|
+
import { stripHash } from "../utils/visualStyle.js";
|
|
5
7
|
import { resolveScaledContentArea } from "../utils/scaleToFit.js";
|
|
6
8
|
//#region src/renderPptx/nodes/flow.ts
|
|
7
9
|
function renderFlowNode(node, ctx) {
|
|
@@ -30,12 +32,14 @@ function renderFlowNode(node, ctx) {
|
|
|
30
32
|
const labelY = (fromLayout.y + fromLayout.height / 2 + toLayout.y + toLayout.height / 2) / 2;
|
|
31
33
|
const labelW = 60 * scaleFactor;
|
|
32
34
|
const labelH = 20 * scaleFactor;
|
|
33
|
-
ctx
|
|
34
|
-
x:
|
|
35
|
-
y:
|
|
36
|
-
w:
|
|
37
|
-
h:
|
|
38
|
-
|
|
35
|
+
addGlimpseTextBox(ctx, {
|
|
36
|
+
x: labelX - labelW / 2,
|
|
37
|
+
y: labelY - labelH / 2,
|
|
38
|
+
w: labelW,
|
|
39
|
+
h: labelH
|
|
40
|
+
}, {
|
|
41
|
+
text: conn.label,
|
|
42
|
+
fontSize: 10 * scaleFactor,
|
|
39
43
|
fontFace: "Noto Sans JP",
|
|
40
44
|
color: stripHash(conn.labelColor) ?? stripHash(connectorStyle.labelColor) ?? "64748B",
|
|
41
45
|
align: "center",
|
|
@@ -48,23 +52,34 @@ function renderFlowNode(node, ctx) {
|
|
|
48
52
|
if (!layout) continue;
|
|
49
53
|
const fillColor = item.color ?? defaultColor;
|
|
50
54
|
const textColor = item.textColor ?? "FFFFFF";
|
|
51
|
-
ctx
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
h: pxToIn(layout.height),
|
|
56
|
-
shape: item.shape,
|
|
57
|
-
fill: { color: fillColor },
|
|
58
|
-
line: {
|
|
59
|
-
color: "333333",
|
|
60
|
-
width: pxToPt(1 * scaleFactor)
|
|
55
|
+
addGlimpseShape(ctx, {
|
|
56
|
+
geometry: {
|
|
57
|
+
kind: "preset",
|
|
58
|
+
preset: item.shape
|
|
61
59
|
},
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
...createShapeBoundsInput({
|
|
61
|
+
x: layout.x,
|
|
62
|
+
y: layout.y,
|
|
63
|
+
w: layout.width,
|
|
64
|
+
h: layout.height
|
|
65
|
+
}),
|
|
66
|
+
fill: solidShapeFill(fillColor),
|
|
67
|
+
outline: shapeOutline({
|
|
68
|
+
color: "333333",
|
|
69
|
+
width: 1 * scaleFactor
|
|
70
|
+
}),
|
|
71
|
+
body: { anchor: "middle" },
|
|
72
|
+
paragraphs: createGlimpseParagraphs(item.text, {
|
|
73
|
+
fontSize: 14 * scaleFactor,
|
|
74
|
+
fontFace: "Noto Sans JP",
|
|
75
|
+
color: textColor
|
|
76
|
+
}, { align: "center" })
|
|
77
|
+
}, {
|
|
78
|
+
x: layout.x,
|
|
79
|
+
y: layout.y,
|
|
80
|
+
w: layout.width,
|
|
81
|
+
h: layout.height
|
|
82
|
+
}, { fillColor });
|
|
68
83
|
}
|
|
69
84
|
}
|
|
70
85
|
function calculateHorizontalLayout(node, layouts, nodeCount, nodeWidth, nodeHeight, nodeGap, scaleFactor) {
|
|
@@ -116,16 +131,15 @@ function drawConnection(ctx, direction, fromLayout, toLayout, lineColor, lineWid
|
|
|
116
131
|
}
|
|
117
132
|
const isHorizontalLine = Math.abs(startY - endY) < 1;
|
|
118
133
|
const isVerticalLine = Math.abs(startX - endX) < 1;
|
|
119
|
-
if (isHorizontalLine || isVerticalLine)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
134
|
+
if (isHorizontalLine || isVerticalLine) addStraightLine(ctx, {
|
|
135
|
+
x1: startX,
|
|
136
|
+
y1: startY,
|
|
137
|
+
x2: endX,
|
|
138
|
+
y2: endY
|
|
139
|
+
}, {
|
|
140
|
+
color: lineColor,
|
|
141
|
+
lineWidth,
|
|
142
|
+
endArrow: { type: arrowType }
|
|
129
143
|
});
|
|
130
144
|
else drawLShapedConnection(ctx, direction, startX, startY, endX, endY, lineColor, lineWidth, arrowType);
|
|
131
145
|
}
|
|
@@ -133,68 +147,62 @@ function drawLShapedConnection(ctx, direction, startX, startY, endX, endY, lineC
|
|
|
133
147
|
const midX = (startX + endX) / 2;
|
|
134
148
|
const midY = (startY + endY) / 2;
|
|
135
149
|
if (direction === "horizontal") {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
150
|
+
addStraightLine(ctx, {
|
|
151
|
+
x1: startX,
|
|
152
|
+
y1: startY,
|
|
153
|
+
x2: midX,
|
|
154
|
+
y2: startY
|
|
155
|
+
}, {
|
|
156
|
+
color: lineColor,
|
|
157
|
+
lineWidth
|
|
145
158
|
});
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
159
|
+
addStraightLine(ctx, {
|
|
160
|
+
x1: midX,
|
|
161
|
+
y1: startY,
|
|
162
|
+
x2: midX,
|
|
163
|
+
y2: endY
|
|
164
|
+
}, {
|
|
165
|
+
color: lineColor,
|
|
166
|
+
lineWidth
|
|
155
167
|
});
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
168
|
+
addStraightLine(ctx, {
|
|
169
|
+
x1: midX,
|
|
170
|
+
y1: endY,
|
|
171
|
+
x2: endX,
|
|
172
|
+
y2: endY
|
|
173
|
+
}, {
|
|
174
|
+
color: lineColor,
|
|
175
|
+
lineWidth,
|
|
176
|
+
endArrow: { type: arrowType }
|
|
166
177
|
});
|
|
167
178
|
} else {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}
|
|
179
|
+
addStraightLine(ctx, {
|
|
180
|
+
x1: startX,
|
|
181
|
+
y1: startY,
|
|
182
|
+
x2: startX,
|
|
183
|
+
y2: midY
|
|
184
|
+
}, {
|
|
185
|
+
color: lineColor,
|
|
186
|
+
lineWidth
|
|
177
187
|
});
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
188
|
+
addStraightLine(ctx, {
|
|
189
|
+
x1: startX,
|
|
190
|
+
y1: midY,
|
|
191
|
+
x2: endX,
|
|
192
|
+
y2: midY
|
|
193
|
+
}, {
|
|
194
|
+
color: lineColor,
|
|
195
|
+
lineWidth
|
|
187
196
|
});
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
197
|
+
addStraightLine(ctx, {
|
|
198
|
+
x1: endX,
|
|
199
|
+
y1: midY,
|
|
200
|
+
x2: endX,
|
|
201
|
+
y2: endY
|
|
202
|
+
}, {
|
|
203
|
+
color: lineColor,
|
|
204
|
+
lineWidth,
|
|
205
|
+
endArrow: { type: arrowType }
|
|
198
206
|
});
|
|
199
207
|
}
|
|
200
208
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.js","names":[],"sources":["../../../src/renderPptx/nodes/flow.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { stripHash } from \"../utils/visualStyle.ts\";\nimport { pxToIn, pxToPt } from \"../units.ts\";\nimport { measureFlow } from \"../../calcYogaLayout/measureCompositeNodes.ts\";\nimport { resolveScaledContentArea } from \"../utils/scaleToFit.ts\";\nimport { withContentBounds } from \"../utils/contentArea.ts\";\n\ntype FlowPositionedNode = Extract<PositionedNode, { type: \"flow\" }>;\n\ninterface FlowNodeLayout {\n id: string;\n x: number;\n y: number;\n width: number;\n height: number;\n item: FlowPositionedNode[\"nodes\"][0];\n}\n\nexport function renderFlowNode(\n node: FlowPositionedNode,\n ctx: RenderContext,\n): void {\n const direction = node.direction ?? \"horizontal\";\n const nodeWidth = node.nodeWidth ?? 120;\n const nodeHeight = node.nodeHeight ?? 60;\n const nodeGap = node.nodeGap ?? 80;\n const connectorStyle = node.connectorStyle ?? {};\n const defaultColor = \"1D4ED8\";\n\n // スケール係数を計算(コンテンツ領域基準)\n const { content, scaleFactor } = resolveScaledContentArea(\n node,\n measureFlow(node),\n ctx,\n );\n\n const scaledNodeWidth = nodeWidth * scaleFactor;\n const scaledNodeHeight = nodeHeight * scaleFactor;\n const scaledNodeGap = nodeGap * scaleFactor;\n\n const layouts = new Map<string, FlowNodeLayout>();\n const nodeCount = node.nodes.length;\n\n // コンテンツ領域を使用するための仮想ノードを作成\n const contentNode = withContentBounds(node, content);\n\n // ノードのレイアウトを計算\n if (direction === \"horizontal\") {\n calculateHorizontalLayout(\n contentNode,\n layouts,\n nodeCount,\n scaledNodeWidth,\n scaledNodeHeight,\n scaledNodeGap,\n scaleFactor,\n );\n } else {\n calculateVerticalLayout(\n contentNode,\n layouts,\n nodeCount,\n scaledNodeWidth,\n scaledNodeHeight,\n scaledNodeGap,\n scaleFactor,\n );\n }\n\n // 接続線を描画(ノードより先に描画して背面に配置)\n for (const conn of node.connections) {\n const fromLayout = layouts.get(conn.from);\n const toLayout = layouts.get(conn.to);\n\n if (!fromLayout || !toLayout) continue;\n\n const lineColor = conn.color ?? connectorStyle.color ?? \"333333\";\n const lineWidth = (connectorStyle.width ?? 2) * scaleFactor;\n const arrowType = connectorStyle.arrowType ?? \"triangle\";\n\n drawConnection(\n ctx,\n direction,\n fromLayout,\n toLayout,\n lineColor,\n lineWidth,\n arrowType,\n );\n\n // ラベルを描画\n if (conn.label) {\n const labelX =\n (fromLayout.x +\n fromLayout.width / 2 +\n toLayout.x +\n toLayout.width / 2) /\n 2;\n const labelY =\n (fromLayout.y +\n fromLayout.height / 2 +\n toLayout.y +\n toLayout.height / 2) /\n 2;\n\n const labelW = 60 * scaleFactor;\n const labelH = 20 * scaleFactor;\n\n ctx.slide.addText(conn.label, {\n x: pxToIn(labelX - labelW / 2),\n y: pxToIn(labelY - labelH / 2),\n w: pxToIn(labelW),\n h: pxToIn(labelH),\n fontSize: pxToPt(10 * scaleFactor),\n fontFace: \"Noto Sans JP\",\n color:\n stripHash(conn.labelColor) ??\n stripHash(connectorStyle.labelColor) ??\n \"64748B\",\n align: \"center\",\n valign: \"middle\",\n });\n }\n }\n\n // ノードを描画\n for (const item of node.nodes) {\n const layout = layouts.get(item.id);\n if (!layout) continue;\n\n const fillColor = item.color ?? defaultColor;\n const textColor = item.textColor ?? \"FFFFFF\";\n\n // 図形を描画\n ctx.slide.addText(item.text, {\n x: pxToIn(layout.x),\n y: pxToIn(layout.y),\n w: pxToIn(layout.width),\n h: pxToIn(layout.height),\n shape: item.shape,\n fill: { color: fillColor },\n line: { color: \"333333\", width: pxToPt(1 * scaleFactor) },\n fontSize: pxToPt(14 * scaleFactor),\n fontFace: \"Noto Sans JP\",\n color: textColor,\n align: \"center\",\n valign: \"middle\",\n });\n }\n}\n\nfunction calculateHorizontalLayout(\n node: FlowPositionedNode,\n layouts: Map<string, FlowNodeLayout>,\n nodeCount: number,\n nodeWidth: number,\n nodeHeight: number,\n nodeGap: number,\n scaleFactor: number,\n): void {\n const totalWidth = nodeCount * nodeWidth + (nodeCount - 1) * nodeGap;\n const startX = node.x + (node.w - totalWidth) / 2;\n const centerY = node.y + node.h / 2;\n\n node.nodes.forEach((item, index) => {\n const w = (item.width ?? nodeWidth / scaleFactor) * scaleFactor;\n const h = (item.height ?? nodeHeight / scaleFactor) * scaleFactor;\n layouts.set(item.id, {\n id: item.id,\n x: startX + index * (nodeWidth + nodeGap) + (nodeWidth - w) / 2,\n y: centerY - h / 2,\n width: w,\n height: h,\n item,\n });\n });\n}\n\nfunction calculateVerticalLayout(\n node: FlowPositionedNode,\n layouts: Map<string, FlowNodeLayout>,\n nodeCount: number,\n nodeWidth: number,\n nodeHeight: number,\n nodeGap: number,\n scaleFactor: number,\n): void {\n const totalHeight = nodeCount * nodeHeight + (nodeCount - 1) * nodeGap;\n const startY = node.y + (node.h - totalHeight) / 2;\n const centerX = node.x + node.w / 2;\n\n node.nodes.forEach((item, index) => {\n const w = (item.width ?? nodeWidth / scaleFactor) * scaleFactor;\n const h = (item.height ?? nodeHeight / scaleFactor) * scaleFactor;\n layouts.set(item.id, {\n id: item.id,\n x: centerX - w / 2,\n y: startY + index * (nodeHeight + nodeGap) + (nodeHeight - h) / 2,\n width: w,\n height: h,\n item,\n });\n });\n}\n\nfunction drawConnection(\n ctx: RenderContext,\n direction: \"horizontal\" | \"vertical\",\n fromLayout: FlowNodeLayout,\n toLayout: FlowNodeLayout,\n lineColor: string,\n lineWidth: number,\n arrowType: \"none\" | \"arrow\" | \"diamond\" | \"oval\" | \"stealth\" | \"triangle\",\n): void {\n let startX: number, startY: number, endX: number, endY: number;\n\n if (direction === \"horizontal\") {\n // 水平: 右端から左端へ\n startX = fromLayout.x + fromLayout.width;\n startY = fromLayout.y + fromLayout.height / 2;\n endX = toLayout.x;\n endY = toLayout.y + toLayout.height / 2;\n } else {\n // 垂直: 下端から上端へ\n startX = fromLayout.x + fromLayout.width / 2;\n startY = fromLayout.y + fromLayout.height;\n endX = toLayout.x + toLayout.width / 2;\n endY = toLayout.y;\n }\n\n // 直線接続(シンプルなケース)\n const isHorizontalLine = Math.abs(startY - endY) < 1;\n const isVerticalLine = Math.abs(startX - endX) < 1;\n\n if (isHorizontalLine || isVerticalLine) {\n // 直線で描画\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(Math.min(startX, endX)),\n y: pxToIn(Math.min(startY, endY)),\n w: pxToIn(Math.abs(endX - startX)),\n h: pxToIn(Math.abs(endY - startY)),\n line: {\n color: lineColor,\n width: pxToPt(lineWidth),\n endArrowType: arrowType,\n },\n });\n } else {\n // L字型接続\n drawLShapedConnection(\n ctx,\n direction,\n startX,\n startY,\n endX,\n endY,\n lineColor,\n lineWidth,\n arrowType,\n );\n }\n}\n\nfunction drawLShapedConnection(\n ctx: RenderContext,\n direction: \"horizontal\" | \"vertical\",\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n lineColor: string,\n lineWidth: number,\n arrowType: \"none\" | \"arrow\" | \"diamond\" | \"oval\" | \"stealth\" | \"triangle\",\n): void {\n const midX = (startX + endX) / 2;\n const midY = (startY + endY) / 2;\n\n if (direction === \"horizontal\") {\n // 水平→垂直→水平\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(startX),\n y: pxToIn(startY),\n w: pxToIn(midX - startX),\n h: 0,\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(midX),\n y: pxToIn(Math.min(startY, endY)),\n w: 0,\n h: pxToIn(Math.abs(endY - startY)),\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(midX),\n y: pxToIn(endY),\n w: pxToIn(endX - midX),\n h: 0,\n line: {\n color: lineColor,\n width: pxToPt(lineWidth),\n endArrowType: arrowType,\n },\n });\n } else {\n // 垂直→水平→垂直\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(startX),\n y: pxToIn(startY),\n w: 0,\n h: pxToIn(midY - startY),\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(Math.min(startX, endX)),\n y: pxToIn(midY),\n w: pxToIn(Math.abs(endX - startX)),\n h: 0,\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(endX),\n y: pxToIn(midY),\n w: 0,\n h: pxToIn(endY - midY),\n line: {\n color: lineColor,\n width: pxToPt(lineWidth),\n endArrowType: arrowType,\n },\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"flow.js","names":[],"sources":["../../../src/renderPptx/nodes/flow.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { stripHash } from \"../utils/visualStyle.ts\";\nimport { measureFlow } from \"../../calcYogaLayout/measureCompositeNodes.ts\";\nimport { resolveScaledContentArea } from \"../utils/scaleToFit.ts\";\nimport { withContentBounds } from \"../utils/contentArea.ts\";\nimport { addStraightLine } from \"../utils/straightLine.ts\";\nimport {\n addGlimpseShape,\n createShapeBoundsInput,\n shapeOutline,\n solidShapeFill,\n} from \"../utils/glimpseShape.ts\";\nimport {\n createGlimpseParagraphs,\n addGlimpseTextBox,\n} from \"../utils/glimpseTextBox.ts\";\n\ntype FlowPositionedNode = Extract<PositionedNode, { type: \"flow\" }>;\n\ninterface FlowNodeLayout {\n id: string;\n x: number;\n y: number;\n width: number;\n height: number;\n item: FlowPositionedNode[\"nodes\"][0];\n}\n\nexport function renderFlowNode(\n node: FlowPositionedNode,\n ctx: RenderContext,\n): void {\n const direction = node.direction ?? \"horizontal\";\n const nodeWidth = node.nodeWidth ?? 120;\n const nodeHeight = node.nodeHeight ?? 60;\n const nodeGap = node.nodeGap ?? 80;\n const connectorStyle = node.connectorStyle ?? {};\n const defaultColor = \"1D4ED8\";\n\n // スケール係数を計算(コンテンツ領域基準)\n const { content, scaleFactor } = resolveScaledContentArea(\n node,\n measureFlow(node),\n ctx,\n );\n\n const scaledNodeWidth = nodeWidth * scaleFactor;\n const scaledNodeHeight = nodeHeight * scaleFactor;\n const scaledNodeGap = nodeGap * scaleFactor;\n\n const layouts = new Map<string, FlowNodeLayout>();\n const nodeCount = node.nodes.length;\n\n // コンテンツ領域を使用するための仮想ノードを作成\n const contentNode = withContentBounds(node, content);\n\n // ノードのレイアウトを計算\n if (direction === \"horizontal\") {\n calculateHorizontalLayout(\n contentNode,\n layouts,\n nodeCount,\n scaledNodeWidth,\n scaledNodeHeight,\n scaledNodeGap,\n scaleFactor,\n );\n } else {\n calculateVerticalLayout(\n contentNode,\n layouts,\n nodeCount,\n scaledNodeWidth,\n scaledNodeHeight,\n scaledNodeGap,\n scaleFactor,\n );\n }\n\n // 接続線を描画(ノードより先に描画して背面に配置)\n for (const conn of node.connections) {\n const fromLayout = layouts.get(conn.from);\n const toLayout = layouts.get(conn.to);\n\n if (!fromLayout || !toLayout) continue;\n\n const lineColor = conn.color ?? connectorStyle.color ?? \"333333\";\n const lineWidth = (connectorStyle.width ?? 2) * scaleFactor;\n const arrowType = connectorStyle.arrowType ?? \"triangle\";\n\n drawConnection(\n ctx,\n direction,\n fromLayout,\n toLayout,\n lineColor,\n lineWidth,\n arrowType,\n );\n\n // ラベルを描画\n if (conn.label) {\n const labelX =\n (fromLayout.x +\n fromLayout.width / 2 +\n toLayout.x +\n toLayout.width / 2) /\n 2;\n const labelY =\n (fromLayout.y +\n fromLayout.height / 2 +\n toLayout.y +\n toLayout.height / 2) /\n 2;\n\n const labelW = 60 * scaleFactor;\n const labelH = 20 * scaleFactor;\n\n addGlimpseTextBox(\n ctx,\n {\n x: labelX - labelW / 2,\n y: labelY - labelH / 2,\n w: labelW,\n h: labelH,\n },\n {\n text: conn.label,\n fontSize: 10 * scaleFactor,\n fontFace: \"Noto Sans JP\",\n color:\n stripHash(conn.labelColor) ??\n stripHash(connectorStyle.labelColor) ??\n \"64748B\",\n align: \"center\",\n valign: \"middle\",\n },\n );\n }\n }\n\n // ノードを描画\n for (const item of node.nodes) {\n const layout = layouts.get(item.id);\n if (!layout) continue;\n\n const fillColor = item.color ?? defaultColor;\n const textColor = item.textColor ?? \"FFFFFF\";\n\n // 図形を描画\n addGlimpseShape(\n ctx,\n {\n geometry: { kind: \"preset\", preset: item.shape },\n ...createShapeBoundsInput({\n x: layout.x,\n y: layout.y,\n w: layout.width,\n h: layout.height,\n }),\n fill: solidShapeFill(fillColor),\n outline: shapeOutline({ color: \"333333\", width: 1 * scaleFactor }),\n body: { anchor: \"middle\" },\n paragraphs: createGlimpseParagraphs(\n item.text,\n {\n fontSize: 14 * scaleFactor,\n fontFace: \"Noto Sans JP\",\n color: textColor,\n },\n { align: \"center\" },\n ),\n },\n { x: layout.x, y: layout.y, w: layout.width, h: layout.height },\n { fillColor },\n );\n }\n}\n\nfunction calculateHorizontalLayout(\n node: FlowPositionedNode,\n layouts: Map<string, FlowNodeLayout>,\n nodeCount: number,\n nodeWidth: number,\n nodeHeight: number,\n nodeGap: number,\n scaleFactor: number,\n): void {\n const totalWidth = nodeCount * nodeWidth + (nodeCount - 1) * nodeGap;\n const startX = node.x + (node.w - totalWidth) / 2;\n const centerY = node.y + node.h / 2;\n\n node.nodes.forEach((item, index) => {\n const w = (item.width ?? nodeWidth / scaleFactor) * scaleFactor;\n const h = (item.height ?? nodeHeight / scaleFactor) * scaleFactor;\n layouts.set(item.id, {\n id: item.id,\n x: startX + index * (nodeWidth + nodeGap) + (nodeWidth - w) / 2,\n y: centerY - h / 2,\n width: w,\n height: h,\n item,\n });\n });\n}\n\nfunction calculateVerticalLayout(\n node: FlowPositionedNode,\n layouts: Map<string, FlowNodeLayout>,\n nodeCount: number,\n nodeWidth: number,\n nodeHeight: number,\n nodeGap: number,\n scaleFactor: number,\n): void {\n const totalHeight = nodeCount * nodeHeight + (nodeCount - 1) * nodeGap;\n const startY = node.y + (node.h - totalHeight) / 2;\n const centerX = node.x + node.w / 2;\n\n node.nodes.forEach((item, index) => {\n const w = (item.width ?? nodeWidth / scaleFactor) * scaleFactor;\n const h = (item.height ?? nodeHeight / scaleFactor) * scaleFactor;\n layouts.set(item.id, {\n id: item.id,\n x: centerX - w / 2,\n y: startY + index * (nodeHeight + nodeGap) + (nodeHeight - h) / 2,\n width: w,\n height: h,\n item,\n });\n });\n}\n\nfunction drawConnection(\n ctx: RenderContext,\n direction: \"horizontal\" | \"vertical\",\n fromLayout: FlowNodeLayout,\n toLayout: FlowNodeLayout,\n lineColor: string,\n lineWidth: number,\n arrowType: \"none\" | \"arrow\" | \"diamond\" | \"oval\" | \"stealth\" | \"triangle\",\n): void {\n let startX: number, startY: number, endX: number, endY: number;\n\n if (direction === \"horizontal\") {\n // 水平: 右端から左端へ\n startX = fromLayout.x + fromLayout.width;\n startY = fromLayout.y + fromLayout.height / 2;\n endX = toLayout.x;\n endY = toLayout.y + toLayout.height / 2;\n } else {\n // 垂直: 下端から上端へ\n startX = fromLayout.x + fromLayout.width / 2;\n startY = fromLayout.y + fromLayout.height;\n endX = toLayout.x + toLayout.width / 2;\n endY = toLayout.y;\n }\n\n // 直線接続(シンプルなケース)\n const isHorizontalLine = Math.abs(startY - endY) < 1;\n const isVerticalLine = Math.abs(startX - endX) < 1;\n\n if (isHorizontalLine || isVerticalLine) {\n // 直線で描画\n addStraightLine(\n ctx,\n { x1: startX, y1: startY, x2: endX, y2: endY },\n { color: lineColor, lineWidth, endArrow: { type: arrowType } },\n );\n } else {\n // L字型接続\n drawLShapedConnection(\n ctx,\n direction,\n startX,\n startY,\n endX,\n endY,\n lineColor,\n lineWidth,\n arrowType,\n );\n }\n}\n\nfunction drawLShapedConnection(\n ctx: RenderContext,\n direction: \"horizontal\" | \"vertical\",\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n lineColor: string,\n lineWidth: number,\n arrowType: \"none\" | \"arrow\" | \"diamond\" | \"oval\" | \"stealth\" | \"triangle\",\n): void {\n const midX = (startX + endX) / 2;\n const midY = (startY + endY) / 2;\n\n if (direction === \"horizontal\") {\n // 水平→垂直→水平\n addStraightLine(\n ctx,\n { x1: startX, y1: startY, x2: midX, y2: startY },\n { color: lineColor, lineWidth },\n );\n addStraightLine(\n ctx,\n { x1: midX, y1: startY, x2: midX, y2: endY },\n { color: lineColor, lineWidth },\n );\n addStraightLine(\n ctx,\n { x1: midX, y1: endY, x2: endX, y2: endY },\n { color: lineColor, lineWidth, endArrow: { type: arrowType } },\n );\n } else {\n // 垂直→水平→垂直\n addStraightLine(\n ctx,\n { x1: startX, y1: startY, x2: startX, y2: midY },\n { color: lineColor, lineWidth },\n );\n addStraightLine(\n ctx,\n { x1: startX, y1: midY, x2: endX, y2: midY },\n { color: lineColor, lineWidth },\n );\n addStraightLine(\n ctx,\n { x1: endX, y1: midY, x2: endX, y2: endY },\n { color: lineColor, lineWidth, endArrow: { type: arrowType } },\n );\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pxToEmu } from "../units.js";
|
|
2
|
+
import { toColorInput } from "../pptxAuthoring.js";
|
|
3
|
+
import { addGlimpsePicture, imageBytesFromSource } from "../utils/glimpsePicture.js";
|
|
4
|
+
import { addGlimpseShape, createShapeBoundsInput, createShapeRotationInput, noShapeOutline, noneShapeFill, shapeOutline, solidShapeFill } from "../utils/glimpseShape.js";
|
|
5
|
+
import { asEmu } from "@pptx-glimpse/document";
|
|
2
6
|
//#region src/renderPptx/nodes/icon.ts
|
|
3
7
|
function renderIconNode(node, ctx) {
|
|
4
8
|
if (node.variant) {
|
|
@@ -7,35 +11,43 @@ function renderIconNode(node, ctx) {
|
|
|
7
11
|
const colorValue = (node.bgColor ?? "#E0E0E0").replace(/^#/, "");
|
|
8
12
|
const variantDefaultLine = isFilled ? void 0 : {
|
|
9
13
|
color: colorValue,
|
|
10
|
-
width:
|
|
14
|
+
width: 2
|
|
11
15
|
};
|
|
12
16
|
const outlineLine = node.outline ? {
|
|
13
17
|
color: node.outline.color ?? variantDefaultLine?.color ?? "FFFFFF",
|
|
14
|
-
width: node.outline.size !== void 0 ?
|
|
18
|
+
width: node.outline.size !== void 0 ? node.outline.size : variantDefaultLine?.width ?? 1
|
|
15
19
|
} : variantDefaultLine;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
w: pxToIn(node.bgW ?? node.w),
|
|
22
|
-
h: pxToIn(node.bgH ?? node.h),
|
|
23
|
-
fill: isFilled ? { color: colorValue } : { type: "none" },
|
|
24
|
-
line: outlineLine,
|
|
25
|
-
rectRadius: isCircle ? void 0 : .1,
|
|
26
|
-
rotate: node.rotate,
|
|
27
|
-
objectName: glowMarker
|
|
20
|
+
const bounds = {
|
|
21
|
+
x: node.bgX ?? node.x,
|
|
22
|
+
y: node.bgY ?? node.y,
|
|
23
|
+
w: node.bgW ?? node.w,
|
|
24
|
+
h: node.bgH ?? node.h
|
|
28
25
|
};
|
|
29
|
-
ctx
|
|
26
|
+
addGlimpseShape(ctx, {
|
|
27
|
+
geometry: {
|
|
28
|
+
kind: "preset",
|
|
29
|
+
preset: isCircle ? "ellipse" : "roundRect"
|
|
30
|
+
},
|
|
31
|
+
...createShapeBoundsInput(bounds),
|
|
32
|
+
rotation: createShapeRotationInput(node.rotate),
|
|
33
|
+
fill: isFilled ? solidShapeFill(colorValue) : noneShapeFill(),
|
|
34
|
+
outline: outlineLine ? shapeOutline(outlineLine) : noShapeOutline(),
|
|
35
|
+
effects: node.glow ? { glow: {
|
|
36
|
+
radius: asEmu(Math.round(pxToEmu(node.glow.size ?? 8))),
|
|
37
|
+
color: toColorInput(node.glow.color ?? "FFFFFF")
|
|
38
|
+
} } : void 0
|
|
39
|
+
}, bounds, {
|
|
40
|
+
fillColor: isFilled ? colorValue : void 0,
|
|
41
|
+
glow: node.glow,
|
|
42
|
+
rectRadius: isCircle ? void 0 : .1
|
|
43
|
+
});
|
|
30
44
|
}
|
|
31
|
-
ctx
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
rotate: node.rotate
|
|
38
|
-
});
|
|
45
|
+
addGlimpsePicture(ctx, {
|
|
46
|
+
x: node.iconX ?? node.x,
|
|
47
|
+
y: node.iconY ?? node.y,
|
|
48
|
+
w: node.iconW ?? node.w,
|
|
49
|
+
h: node.iconH ?? node.h
|
|
50
|
+
}, imageBytesFromSource("", node.iconImageData), { rotate: node.rotate });
|
|
39
51
|
}
|
|
40
52
|
//#endregion
|
|
41
53
|
export { renderIconNode };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon.js","names":[],"sources":["../../../src/renderPptx/nodes/icon.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {
|
|
1
|
+
{"version":3,"file":"icon.js","names":[],"sources":["../../../src/renderPptx/nodes/icon.ts"],"sourcesContent":["import { asEmu } from \"@pptx-glimpse/document\";\nimport type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { toColorInput } from \"../pptxAuthoring.ts\";\nimport { pxToEmu } from \"../units.ts\";\nimport {\n addGlimpsePicture,\n imageBytesFromSource,\n} from \"../utils/glimpsePicture.ts\";\nimport {\n addGlimpseShape,\n createShapeBoundsInput,\n createShapeRotationInput,\n noShapeOutline,\n noneShapeFill,\n shapeOutline,\n solidShapeFill,\n} from \"../utils/glimpseShape.ts\";\n\ntype IconPositionedNode = Extract<PositionedNode, { type: \"icon\" }>;\n\nexport function renderIconNode(\n node: IconPositionedNode,\n ctx: RenderContext,\n): void {\n // variant 指定時は背景図形を描画\n if (node.variant) {\n const isCircle = node.variant.startsWith(\"circle\");\n const isFilled = node.variant.endsWith(\"-filled\");\n const bgColor = node.bgColor ?? \"#E0E0E0\";\n const colorValue = bgColor.replace(/^#/, \"\");\n\n // 背景図形の line のデフォルト: outlined variant は colorValue / 1.5pt 相当 (2px)、\n // filled variant は undefined (枠線なし)。\n const variantDefaultLine = isFilled\n ? undefined\n : { color: colorValue, width: 2 };\n // outline 指定時は variant のデフォルト line とフィールド単位でマージする。\n // outline 側で省略された属性は variant default の値を引き継ぐので、例えば\n // outlined variant に `outline.color` だけ指定すると、太さは 1.5pt のまま\n // 色だけ outline で上書きされる。\n const outlineLine = node.outline\n ? {\n color: node.outline.color ?? variantDefaultLine?.color ?? \"FFFFFF\",\n width:\n node.outline.size !== undefined\n ? node.outline.size\n : (variantDefaultLine?.width ?? 1),\n }\n : variantDefaultLine;\n\n const bounds = {\n x: node.bgX ?? node.x,\n y: node.bgY ?? node.y,\n w: node.bgW ?? node.w,\n h: node.bgH ?? node.h,\n };\n const shapeType = isCircle ? \"ellipse\" : \"roundRect\";\n\n addGlimpseShape(\n ctx,\n {\n geometry: { kind: \"preset\", preset: shapeType },\n ...createShapeBoundsInput(bounds),\n rotation: createShapeRotationInput(node.rotate),\n fill: isFilled ? solidShapeFill(colorValue) : noneShapeFill(),\n outline: outlineLine ? shapeOutline(outlineLine) : noShapeOutline(),\n effects: node.glow\n ? {\n glow: {\n radius: asEmu(Math.round(pxToEmu(node.glow.size ?? 8))),\n color: toColorInput(node.glow.color ?? \"FFFFFF\")!,\n },\n }\n : undefined,\n },\n bounds,\n {\n fillColor: isFilled ? colorValue : undefined,\n glow: node.glow,\n rectRadius: isCircle ? undefined : 0.1,\n },\n );\n }\n\n addGlimpsePicture(\n ctx,\n {\n x: node.iconX ?? node.x,\n y: node.iconY ?? node.y,\n w: node.iconW ?? node.w,\n h: node.iconH ?? node.h,\n },\n imageBytesFromSource(\"\", node.iconImageData),\n { rotate: node.rotate },\n );\n}\n"],"mappings":";;;;;;AAqBA,SAAgB,eACd,MACA,KACM;CAEN,IAAI,KAAK,SAAS;EAChB,MAAM,WAAW,KAAK,QAAQ,WAAW,QAAQ;EACjD,MAAM,WAAW,KAAK,QAAQ,SAAS,SAAS;EAEhD,MAAM,cADU,KAAK,WAAW,UAAA,CACL,QAAQ,MAAM,EAAE;EAI3C,MAAM,qBAAqB,WACvB,KAAA,IACA;GAAE,OAAO;GAAY,OAAO;EAAE;EAKlC,MAAM,cAAc,KAAK,UACrB;GACE,OAAO,KAAK,QAAQ,SAAS,oBAAoB,SAAS;GAC1D,OACE,KAAK,QAAQ,SAAS,KAAA,IAClB,KAAK,QAAQ,OACZ,oBAAoB,SAAS;EACtC,IACA;EAEJ,MAAM,SAAS;GACb,GAAG,KAAK,OAAO,KAAK;GACpB,GAAG,KAAK,OAAO,KAAK;GACpB,GAAG,KAAK,OAAO,KAAK;GACpB,GAAG,KAAK,OAAO,KAAK;EACtB;EAGA,gBACE,KACA;GACE,UAAU;IAAE,MAAM;IAAU,QALd,WAAW,YAAY;GAKS;GAC9C,GAAG,uBAAuB,MAAM;GAChC,UAAU,yBAAyB,KAAK,MAAM;GAC9C,MAAM,WAAW,eAAe,UAAU,IAAI,cAAc;GAC5D,SAAS,cAAc,aAAa,WAAW,IAAI,eAAe;GAClE,SAAS,KAAK,OACV,EACE,MAAM;IACJ,QAAQ,MAAM,KAAK,MAAM,QAAQ,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC;IACtD,OAAO,aAAa,KAAK,KAAK,SAAS,QAAQ;GACjD,EACF,IACA,KAAA;EACN,GACA,QACA;GACE,WAAW,WAAW,aAAa,KAAA;GACnC,MAAM,KAAK;GACX,YAAY,WAAW,KAAA,IAAY;EACrC,CACF;CACF;CAEA,kBACE,KACA;EACE,GAAG,KAAK,SAAS,KAAK;EACtB,GAAG,KAAK,SAAS,KAAK;EACtB,GAAG,KAAK,SAAS,KAAK;EACtB,GAAG,KAAK,SAAS,KAAK;CACxB,GACA,qBAAqB,IAAI,KAAK,aAAa,GAC3C,EAAE,QAAQ,KAAK,OAAO,CACxB;AACF"}
|
|
@@ -1,28 +1,11 @@
|
|
|
1
|
-
import { pxToIn, rectPxToIn } from "../units.js";
|
|
2
1
|
import { getContentArea } from "../utils/contentArea.js";
|
|
3
|
-
import {
|
|
2
|
+
import { addGlimpsePicture, imageBytesFromSource } from "../utils/glimpsePicture.js";
|
|
4
3
|
//#region src/renderPptx/nodes/image.ts
|
|
5
4
|
function renderImageNode(node, ctx) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
shadow:
|
|
10
|
-
rotate: node.rotate
|
|
11
|
-
};
|
|
12
|
-
if (node.sizing) imageOptions.sizing = {
|
|
13
|
-
type: node.sizing.type,
|
|
14
|
-
w: pxToIn(node.sizing.w ?? content.w),
|
|
15
|
-
h: pxToIn(node.sizing.h ?? content.h),
|
|
16
|
-
...node.sizing.x !== void 0 && { x: pxToIn(node.sizing.x) },
|
|
17
|
-
...node.sizing.y !== void 0 && { y: pxToIn(node.sizing.y) }
|
|
18
|
-
};
|
|
19
|
-
if (node.imageData) ctx.slide.addImage({
|
|
20
|
-
...imageOptions,
|
|
21
|
-
data: node.imageData
|
|
22
|
-
});
|
|
23
|
-
else ctx.slide.addImage({
|
|
24
|
-
...imageOptions,
|
|
25
|
-
path: node.src
|
|
5
|
+
addGlimpsePicture(ctx, getContentArea(node), imageBytesFromSource(node.src, node.imageData), {
|
|
6
|
+
rotate: node.rotate,
|
|
7
|
+
sizing: node.sizing,
|
|
8
|
+
shadow: node.shadow
|
|
26
9
|
});
|
|
27
10
|
}
|
|
28
11
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","names":[],"sources":["../../../src/renderPptx/nodes/image.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {
|
|
1
|
+
{"version":3,"file":"image.js","names":[],"sources":["../../../src/renderPptx/nodes/image.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\nimport {\n addGlimpsePicture,\n imageBytesFromSource,\n} from \"../utils/glimpsePicture.ts\";\n\ntype ImagePositionedNode = Extract<PositionedNode, { type: \"image\" }>;\n\nexport function renderImageNode(\n node: ImagePositionedNode,\n ctx: RenderContext,\n): void {\n const content = getContentArea(node);\n addGlimpsePicture(\n ctx,\n content,\n imageBytesFromSource(node.src, node.imageData),\n {\n rotate: node.rotate,\n sizing: node.sizing,\n shadow: node.shadow,\n },\n );\n}\n"],"mappings":";;;AAUA,SAAgB,gBACd,MACA,KACM;CAEN,kBACE,KAFc,eAAe,IAGvB,GACN,qBAAqB,KAAK,KAAK,KAAK,SAAS,GAC7C;EACE,QAAQ,KAAK;EACb,QAAQ,KAAK;EACb,QAAQ,KAAK;CACf,CACF;AACF"}
|