dom-to-pptx 1.1.0 → 1.1.1
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/CHANGELOG.md +12 -2
- package/README.md +295 -323
- package/dist/dom-to-pptx.bundle.js +247 -95
- package/dist/dom-to-pptx.cjs +247 -95
- package/dist/dom-to-pptx.cjs.map +1 -1
- package/dist/dom-to-pptx.mjs +247 -95
- package/dist/dom-to-pptx.mjs.map +1 -1
- package/package.json +83 -83
- package/rollup.config.js +9 -14
- package/src/font-embedder.js +163 -159
- package/src/font-utils.js +32 -35
- package/src/image-processor.js +58 -19
- package/src/index.js +971 -905
- package/src/utils.js +711 -674
- package/dist/dom-to-pptx.min.js +0 -64284
package/src/image-processor.js
CHANGED
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
// src/image-processor.js
|
|
2
2
|
|
|
3
|
-
export async function getProcessedImage(
|
|
3
|
+
export async function getProcessedImage(
|
|
4
|
+
src,
|
|
5
|
+
targetW,
|
|
6
|
+
targetH,
|
|
7
|
+
radius,
|
|
8
|
+
objectFit = 'fill',
|
|
9
|
+
objectPosition = '50% 50%'
|
|
10
|
+
) {
|
|
4
11
|
return new Promise((resolve) => {
|
|
5
12
|
const img = new Image();
|
|
6
|
-
img.crossOrigin = 'Anonymous';
|
|
13
|
+
img.crossOrigin = 'Anonymous';
|
|
7
14
|
|
|
8
15
|
img.onload = () => {
|
|
9
16
|
const canvas = document.createElement('canvas');
|
|
10
|
-
// Double resolution
|
|
11
|
-
const scale = 2;
|
|
17
|
+
const scale = 2; // Double resolution
|
|
12
18
|
canvas.width = targetW * scale;
|
|
13
19
|
canvas.height = targetH * scale;
|
|
14
20
|
const ctx = canvas.getContext('2d');
|
|
15
21
|
ctx.scale(scale, scale);
|
|
16
22
|
|
|
17
|
-
// Normalize radius
|
|
23
|
+
// Normalize radius
|
|
18
24
|
let r = { tl: 0, tr: 0, br: 0, bl: 0 };
|
|
19
25
|
if (typeof radius === 'number') {
|
|
20
26
|
r = { tl: radius, tr: radius, br: radius, bl: radius };
|
|
21
27
|
} else if (typeof radius === 'object' && radius !== null) {
|
|
22
|
-
r = { ...r, ...radius };
|
|
28
|
+
r = { ...r, ...radius };
|
|
23
29
|
}
|
|
24
30
|
|
|
25
|
-
// 1. Draw
|
|
31
|
+
// 1. Draw Mask
|
|
26
32
|
ctx.beginPath();
|
|
27
|
-
|
|
28
|
-
// Border Radius Clamping Logic (CSS Spec)
|
|
29
|
-
// Prevents corners from overlapping if radii are too large for the container
|
|
33
|
+
// ... (radius clamping logic remains the same) ...
|
|
30
34
|
const factor = Math.min(
|
|
31
35
|
targetW / (r.tl + r.tr) || Infinity,
|
|
32
36
|
targetH / (r.tr + r.br) || Infinity,
|
|
@@ -41,7 +45,6 @@ export async function getProcessedImage(src, targetW, targetH, radius) {
|
|
|
41
45
|
r.bl *= factor;
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
// Draw path: Top-Left -> Top-Right -> Bottom-Right -> Bottom-Left
|
|
45
48
|
ctx.moveTo(r.tl, 0);
|
|
46
49
|
ctx.lineTo(targetW - r.tr, 0);
|
|
47
50
|
ctx.arcTo(targetW, 0, targetW, r.tr, r.tr);
|
|
@@ -51,22 +54,58 @@ export async function getProcessedImage(src, targetW, targetH, radius) {
|
|
|
51
54
|
ctx.arcTo(0, targetH, 0, targetH - r.bl, r.bl);
|
|
52
55
|
ctx.lineTo(0, r.tl);
|
|
53
56
|
ctx.arcTo(0, 0, r.tl, 0, r.tl);
|
|
54
|
-
|
|
55
57
|
ctx.closePath();
|
|
56
58
|
ctx.fillStyle = '#000';
|
|
57
59
|
ctx.fill();
|
|
58
60
|
|
|
59
|
-
// 2. Composite Source-In
|
|
61
|
+
// 2. Composite Source-In
|
|
60
62
|
ctx.globalCompositeOperation = 'source-in';
|
|
61
63
|
|
|
62
|
-
// 3. Draw Image
|
|
64
|
+
// 3. Draw Image with Object Fit logic
|
|
63
65
|
const wRatio = targetW / img.width;
|
|
64
66
|
const hRatio = targetH / img.height;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
let renderW, renderH;
|
|
68
|
+
|
|
69
|
+
if (objectFit === 'contain') {
|
|
70
|
+
const fitScale = Math.min(wRatio, hRatio);
|
|
71
|
+
renderW = img.width * fitScale;
|
|
72
|
+
renderH = img.height * fitScale;
|
|
73
|
+
} else if (objectFit === 'cover') {
|
|
74
|
+
const coverScale = Math.max(wRatio, hRatio);
|
|
75
|
+
renderW = img.width * coverScale;
|
|
76
|
+
renderH = img.height * coverScale;
|
|
77
|
+
} else if (objectFit === 'none') {
|
|
78
|
+
renderW = img.width;
|
|
79
|
+
renderH = img.height;
|
|
80
|
+
} else if (objectFit === 'scale-down') {
|
|
81
|
+
const scaleDown = Math.min(1, Math.min(wRatio, hRatio));
|
|
82
|
+
renderW = img.width * scaleDown;
|
|
83
|
+
renderH = img.height * scaleDown;
|
|
84
|
+
} else {
|
|
85
|
+
// 'fill' (default)
|
|
86
|
+
renderW = targetW;
|
|
87
|
+
renderH = targetH;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Handle Object Position (simplified parsing for "x% y%" or keywords)
|
|
91
|
+
let posX = 0.5; // Default center
|
|
92
|
+
let posY = 0.5;
|
|
93
|
+
|
|
94
|
+
const posParts = objectPosition.split(' ');
|
|
95
|
+
if (posParts.length > 0) {
|
|
96
|
+
const parsePos = (val) => {
|
|
97
|
+
if (val === 'left' || val === 'top') return 0;
|
|
98
|
+
if (val === 'center') return 0.5;
|
|
99
|
+
if (val === 'right' || val === 'bottom') return 1;
|
|
100
|
+
if (val.includes('%')) return parseFloat(val) / 100;
|
|
101
|
+
return 0.5; // fallback
|
|
102
|
+
};
|
|
103
|
+
posX = parsePos(posParts[0]);
|
|
104
|
+
posY = posParts.length > 1 ? parsePos(posParts[1]) : 0.5;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const renderX = (targetW - renderW) * posX;
|
|
108
|
+
const renderY = (targetH - renderH) * posY;
|
|
70
109
|
|
|
71
110
|
ctx.drawImage(img, renderX, renderY, renderW, renderH);
|
|
72
111
|
|