@mce/bigesj 0.18.5 → 0.19.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/dist/convert/image.d.ts +1 -0
- package/dist/index.js +267 -233
- package/package.json +3 -3
package/dist/convert/image.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { definePlugin, useEditor } from "mce";
|
|
2
2
|
import { onBeforeMount, onScopeDispose, ref } from "vue";
|
|
3
|
-
import { clearUndef, idGenerator, isGradient, isGradientFill, normalizeCRLF, normalizeGradientFill } from "modern-idoc";
|
|
3
|
+
import { clearUndef, idGenerator, isGradient, isGradientFill, normalizeCRLF, normalizeGradientFill, normalizeNumber } from "modern-idoc";
|
|
4
4
|
import { OoxmlNode, parsePresetShapeDefinition } from "modern-openxml";
|
|
5
5
|
import { assets } from "modern-canvas";
|
|
6
6
|
import { gunzipSync } from "fflate";
|
|
@@ -16,6 +16,17 @@ function levenshteinDistance(a, b) {
|
|
|
16
16
|
}
|
|
17
17
|
return matrix[b.length][a.length];
|
|
18
18
|
}
|
|
19
|
+
var indexedFonts;
|
|
20
|
+
var idIndexMap = /* @__PURE__ */ new Map();
|
|
21
|
+
var nameIndexMap = /* @__PURE__ */ new Map();
|
|
22
|
+
var searchCache = /* @__PURE__ */ new Map();
|
|
23
|
+
function ensureFontIndex(fonts) {
|
|
24
|
+
if (indexedFonts === fonts) return;
|
|
25
|
+
indexedFonts = fonts;
|
|
26
|
+
idIndexMap = new Map(fonts.map((item, index) => [item.id, index]));
|
|
27
|
+
nameIndexMap = new Map(fonts.flatMap((item, index) => [...item.en_name.split(","), ...item.name.split(",")].map((name) => [name, index])));
|
|
28
|
+
searchCache.clear();
|
|
29
|
+
}
|
|
19
30
|
function useFonts(editor) {
|
|
20
31
|
const { http, loadFont: baseLoadFont } = editor ?? useEditor();
|
|
21
32
|
async function loadBigeFonts(url, init = false) {
|
|
@@ -30,12 +41,8 @@ function useFonts(editor) {
|
|
|
30
41
|
return result;
|
|
31
42
|
}
|
|
32
43
|
function searchBigeFont(keyword, fonts = bigeFonts.value) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return [...item.en_name.split(","), ...item.name.split(",")].map((name) => {
|
|
36
|
-
return [name, index];
|
|
37
|
-
});
|
|
38
|
-
}));
|
|
44
|
+
ensureFontIndex(fonts);
|
|
45
|
+
if (searchCache.has(keyword)) return searchCache.get(keyword);
|
|
39
46
|
const fontFamilies = keyword.replace(/"/g, "").split(",");
|
|
40
47
|
let index;
|
|
41
48
|
fontFamilies.forEach((fontFamily) => {
|
|
@@ -50,6 +57,7 @@ function useFonts(editor) {
|
|
|
50
57
|
else if (a.endsWith(" B")) a = `${a.substring(0, a.length - 2)}粗体`;
|
|
51
58
|
const aLen = a.length;
|
|
52
59
|
nameIndexMap.forEach((i, b) => {
|
|
60
|
+
if (Math.abs(aLen - b.length) >= aLen) return;
|
|
53
61
|
const dist = levenshteinDistance(a, b);
|
|
54
62
|
if (aLen <= dist) return;
|
|
55
63
|
const weight = -(dist * .9 + (b.endsWith("常规") ? 0 : 1) * .1);
|
|
@@ -60,7 +68,9 @@ function useFonts(editor) {
|
|
|
60
68
|
});
|
|
61
69
|
});
|
|
62
70
|
}
|
|
63
|
-
|
|
71
|
+
const result = index !== void 0 ? fonts[index] : void 0;
|
|
72
|
+
searchCache.set(keyword, result);
|
|
73
|
+
return result;
|
|
64
74
|
}
|
|
65
75
|
async function loadFont(name) {
|
|
66
76
|
const names = typeof name === "string" ? [name] : name;
|
|
@@ -1138,6 +1148,23 @@ function parseAnimations(el) {
|
|
|
1138
1148
|
}
|
|
1139
1149
|
//#endregion
|
|
1140
1150
|
//#region src/convert/style.ts
|
|
1151
|
+
var NUMERIC_STYLE_KEYS = [
|
|
1152
|
+
"textIndent",
|
|
1153
|
+
"lineHeight",
|
|
1154
|
+
"letterSpacing",
|
|
1155
|
+
"wordSpacing",
|
|
1156
|
+
"fontSize",
|
|
1157
|
+
"textStrokeWidth",
|
|
1158
|
+
"borderRadius",
|
|
1159
|
+
"opacity",
|
|
1160
|
+
"rotate",
|
|
1161
|
+
"scaleX",
|
|
1162
|
+
"scaleY",
|
|
1163
|
+
"skewX",
|
|
1164
|
+
"skewY",
|
|
1165
|
+
"translateX",
|
|
1166
|
+
"translateY"
|
|
1167
|
+
];
|
|
1141
1168
|
function getStyle(el, clone = false) {
|
|
1142
1169
|
let style = el.style ?? el;
|
|
1143
1170
|
if (clone) {
|
|
@@ -1154,6 +1181,11 @@ function getStyle(el, clone = false) {
|
|
|
1154
1181
|
delete style.backgroundUrl;
|
|
1155
1182
|
delete style.elements;
|
|
1156
1183
|
delete style.imageTransform;
|
|
1184
|
+
for (const key of NUMERIC_STYLE_KEYS) if (key in style) {
|
|
1185
|
+
const value = normalizeNumber(style[key]);
|
|
1186
|
+
if (value === void 0) delete style[key];
|
|
1187
|
+
else style[key] = value;
|
|
1188
|
+
}
|
|
1157
1189
|
}
|
|
1158
1190
|
return style;
|
|
1159
1191
|
}
|
|
@@ -6074,6 +6106,221 @@ function convertSvgLinearGradient(value) {
|
|
|
6074
6106
|
}
|
|
6075
6107
|
}
|
|
6076
6108
|
//#endregion
|
|
6109
|
+
//#region src/convert/image.ts
|
|
6110
|
+
function cachedFetchImageBitmap(url) {
|
|
6111
|
+
if (typeof url === "string" && url.startsWith("http")) return assets.loadBy(url).then((blob) => assets.fetchImageBitmap(blob));
|
|
6112
|
+
return assets.fetchImageBitmap(url);
|
|
6113
|
+
}
|
|
6114
|
+
async function convertImageElementToUrl(el) {
|
|
6115
|
+
const { cropping = {}, transform = {}, style = {}, maskUrl, imageEffects = [], imageEffectsRatio = 1 } = el;
|
|
6116
|
+
const url = el.clipUrl || el.url;
|
|
6117
|
+
const { translateX = 0, translateY = 0, zoom = 1 } = transform ?? {};
|
|
6118
|
+
const { scaleX = 1, scaleY = 1, filter } = style;
|
|
6119
|
+
if (translateX === 0 && translateY === 0 && zoom === 1 && scaleX === 1 && scaleY === 1 && !maskUrl && !filter && !imageEffects.length) return url;
|
|
6120
|
+
const img = await cachedFetchImageBitmap(url);
|
|
6121
|
+
const { originWidth = img.width, originHeight = img.height, imageWidth = originWidth, imageHeight = originHeight } = transform;
|
|
6122
|
+
const { width = originWidth, height = originHeight } = style;
|
|
6123
|
+
const dpr = window.devicePixelRatio || 1;
|
|
6124
|
+
const [canvas, ctx] = createCanvas(width, height, dpr);
|
|
6125
|
+
if (filter) ctx.filter = filter;
|
|
6126
|
+
ctx.scale(scaleX, scaleY);
|
|
6127
|
+
ctx.translate(scaleX < 0 ? -width : 0, scaleY < 0 ? -height : 0);
|
|
6128
|
+
if (maskUrl) {
|
|
6129
|
+
const mask = await cachedFetchImageBitmap(maskUrl);
|
|
6130
|
+
ctx.drawImage(mask, 0, 0, cropping?.maskWidth ?? width, cropping?.maskHeight ?? height);
|
|
6131
|
+
ctx.globalCompositeOperation = "source-in";
|
|
6132
|
+
mask.close();
|
|
6133
|
+
}
|
|
6134
|
+
const dw = imageWidth * zoom;
|
|
6135
|
+
const dh = imageHeight * zoom;
|
|
6136
|
+
const dx = -(dw / 2 - imageWidth / 2) + translateX;
|
|
6137
|
+
const dy = -(dh / 2 - imageHeight / 2) + translateY;
|
|
6138
|
+
ctx.drawImage(img, 0, 0, img.width, img.height, dx, dy, dw, dh);
|
|
6139
|
+
img.close();
|
|
6140
|
+
ctx.globalCompositeOperation = "source-over";
|
|
6141
|
+
if (imageEffects.length > 0) {
|
|
6142
|
+
const scale = .9;
|
|
6143
|
+
const center = {
|
|
6144
|
+
x: (width - width * scale) / 2,
|
|
6145
|
+
y: (height - height * scale) / 2
|
|
6146
|
+
};
|
|
6147
|
+
const canvasBitmap = await createImageBitmap(canvas);
|
|
6148
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
6149
|
+
ctx.scale(scale, scale);
|
|
6150
|
+
for (let i = imageEffects.length - 1; i >= 0; i--) {
|
|
6151
|
+
const { filling, offset, stroke } = imageEffects[i];
|
|
6152
|
+
let effectCanvas = canvasBitmap;
|
|
6153
|
+
if (filling) {
|
|
6154
|
+
const [canvas1, ctx1] = createCanvas(width, height, dpr);
|
|
6155
|
+
ctx1.drawImage(effectCanvas, 0, 0, width, height);
|
|
6156
|
+
ctx1.globalCompositeOperation = "source-in";
|
|
6157
|
+
if (filling.color) {
|
|
6158
|
+
const [canvas2, ctx2] = createCanvas(width, height, dpr);
|
|
6159
|
+
ctx2.fillStyle = filling.color;
|
|
6160
|
+
ctx2.fillRect(0, 0, width, height);
|
|
6161
|
+
ctx1.drawImage(canvas2, 0, 0, width, height);
|
|
6162
|
+
} else if (filling.imageContent?.image) {
|
|
6163
|
+
const img2 = await cachedFetchImageBitmap(filling.imageContent.image);
|
|
6164
|
+
ctx1.drawImage(img2, 0, 0, width, height);
|
|
6165
|
+
img2.close();
|
|
6166
|
+
}
|
|
6167
|
+
effectCanvas = canvas1;
|
|
6168
|
+
}
|
|
6169
|
+
stroke?.forEach(({ width, color }) => {
|
|
6170
|
+
effectCanvas = new ImageStroke().use((ctx, image, options) => {
|
|
6171
|
+
const [, ctx1] = createCanvas(image.width, image.height);
|
|
6172
|
+
ctx1.drawImage(image, 0, 0);
|
|
6173
|
+
const paths = getContours(ctx1);
|
|
6174
|
+
const x = options.thickness;
|
|
6175
|
+
const y = options.thickness;
|
|
6176
|
+
ctx.strokeStyle = options.color;
|
|
6177
|
+
ctx.lineWidth = options.thickness * 2;
|
|
6178
|
+
ctx.lineJoin = "round";
|
|
6179
|
+
paths.forEach((path) => {
|
|
6180
|
+
ctx.beginPath();
|
|
6181
|
+
ctx.moveTo(x + path[0].x, y + path[1].y);
|
|
6182
|
+
for (let i = 1; i < path.length; i++) ctx.lineTo(x + path[i].x, y + path[i].y);
|
|
6183
|
+
ctx.closePath();
|
|
6184
|
+
});
|
|
6185
|
+
ctx.stroke();
|
|
6186
|
+
}).make(effectCanvas, {
|
|
6187
|
+
color,
|
|
6188
|
+
thickness: width / 50 * imageEffectsRatio
|
|
6189
|
+
});
|
|
6190
|
+
});
|
|
6191
|
+
if (offset) {
|
|
6192
|
+
let { x, y } = offset;
|
|
6193
|
+
x = x / 50 * imageEffectsRatio * 200;
|
|
6194
|
+
y = y / 50 * imageEffectsRatio * 200;
|
|
6195
|
+
ctx.drawImage(effectCanvas, x + center.x, y + center.y, width, height);
|
|
6196
|
+
} else ctx.drawImage(effectCanvas, center.x, center.y, width, height);
|
|
6197
|
+
}
|
|
6198
|
+
canvasBitmap.close();
|
|
6199
|
+
}
|
|
6200
|
+
return await new Promise((resolve) => {
|
|
6201
|
+
canvas.toBlob((blob) => {
|
|
6202
|
+
try {
|
|
6203
|
+
resolve(URL.createObjectURL(blob));
|
|
6204
|
+
} catch (e) {
|
|
6205
|
+
console.error(`Failed to URL.createObjectURL, url: ${url}`, e);
|
|
6206
|
+
resolve(url);
|
|
6207
|
+
}
|
|
6208
|
+
});
|
|
6209
|
+
});
|
|
6210
|
+
}
|
|
6211
|
+
function createCanvas(width, height, ratio = 1) {
|
|
6212
|
+
const canvas = document.createElement("canvas");
|
|
6213
|
+
canvas.width = width * ratio;
|
|
6214
|
+
canvas.height = height * ratio;
|
|
6215
|
+
canvas.style.width = `${width}px`;
|
|
6216
|
+
canvas.style.height = `${height}px`;
|
|
6217
|
+
const ctx = canvas.getContext("2d");
|
|
6218
|
+
ctx.scale(ratio, ratio);
|
|
6219
|
+
return [canvas, ctx];
|
|
6220
|
+
}
|
|
6221
|
+
var ImageStroke = class {
|
|
6222
|
+
canvas = document.createElement("canvas");
|
|
6223
|
+
method;
|
|
6224
|
+
use(method) {
|
|
6225
|
+
this.method = method;
|
|
6226
|
+
return this;
|
|
6227
|
+
}
|
|
6228
|
+
make(image, options) {
|
|
6229
|
+
const { canvas } = this;
|
|
6230
|
+
const ctx = this.canvas.getContext("2d");
|
|
6231
|
+
const strokeSize = options.thickness * 2;
|
|
6232
|
+
const [resultWidth, resultHeight] = [image.width, image.height].map((val) => val + strokeSize);
|
|
6233
|
+
if (resultWidth !== canvas.width || resultHeight !== canvas.height) {
|
|
6234
|
+
canvas.width = resultWidth;
|
|
6235
|
+
canvas.height = resultHeight;
|
|
6236
|
+
}
|
|
6237
|
+
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
6238
|
+
this.method(ctx, image, options);
|
|
6239
|
+
ctx.drawImage(image, options.thickness, options.thickness);
|
|
6240
|
+
return canvas;
|
|
6241
|
+
}
|
|
6242
|
+
};
|
|
6243
|
+
function getContours(ctx) {
|
|
6244
|
+
const cx = 0;
|
|
6245
|
+
const cy = 0;
|
|
6246
|
+
const canvasWidth = ctx.canvas.width;
|
|
6247
|
+
const canvasHeight = ctx.canvas.height;
|
|
6248
|
+
const paths = [];
|
|
6249
|
+
let lastPos = 3;
|
|
6250
|
+
const alpha = 100;
|
|
6251
|
+
const trace = () => {
|
|
6252
|
+
const path = [];
|
|
6253
|
+
const data = new Uint32Array(ctx.getImageData(cx, cy, canvasWidth, canvasHeight).data.buffer);
|
|
6254
|
+
let x;
|
|
6255
|
+
let y;
|
|
6256
|
+
let startX;
|
|
6257
|
+
let startY;
|
|
6258
|
+
let startPos = -1;
|
|
6259
|
+
let step;
|
|
6260
|
+
let prevStep = 9;
|
|
6261
|
+
const steps = [
|
|
6262
|
+
9,
|
|
6263
|
+
0,
|
|
6264
|
+
3,
|
|
6265
|
+
3,
|
|
6266
|
+
2,
|
|
6267
|
+
0,
|
|
6268
|
+
9,
|
|
6269
|
+
3,
|
|
6270
|
+
1,
|
|
6271
|
+
9,
|
|
6272
|
+
1,
|
|
6273
|
+
1,
|
|
6274
|
+
2,
|
|
6275
|
+
0,
|
|
6276
|
+
2,
|
|
6277
|
+
9
|
|
6278
|
+
];
|
|
6279
|
+
let time = 50;
|
|
6280
|
+
function getState(x, y) {
|
|
6281
|
+
return x >= 0 && y >= 0 && x < canvasWidth && y < canvasHeight ? data[y * canvasWidth + x] >>> 24 > alpha : false;
|
|
6282
|
+
}
|
|
6283
|
+
function getNextStep(x, y) {
|
|
6284
|
+
let v = 0;
|
|
6285
|
+
if (getState(x - 1, y - 1)) v += 1;
|
|
6286
|
+
if (getState(x, y - 1)) v += 2;
|
|
6287
|
+
if (getState(x - 1, y)) v += 4;
|
|
6288
|
+
if (getState(x, y)) v += 8;
|
|
6289
|
+
if (time > 50) time += 10;
|
|
6290
|
+
else time += 10;
|
|
6291
|
+
if (v === 6) return prevStep === 0 ? 2 : 3;
|
|
6292
|
+
else if (v === 9) return prevStep === 3 ? 0 : 1;
|
|
6293
|
+
else return steps[v];
|
|
6294
|
+
}
|
|
6295
|
+
for (let i = lastPos; i < data.length; i++) if (data[i] >>> 24 > alpha) {
|
|
6296
|
+
startPos = lastPos = i;
|
|
6297
|
+
break;
|
|
6298
|
+
}
|
|
6299
|
+
if (startPos >= 0) {
|
|
6300
|
+
x = startX = startPos % canvasWidth;
|
|
6301
|
+
y = startY = Math.floor(startPos / canvasWidth);
|
|
6302
|
+
do {
|
|
6303
|
+
step = getNextStep(x, y);
|
|
6304
|
+
if (step === 0) y--;
|
|
6305
|
+
else if (step === 1) y++;
|
|
6306
|
+
else if (step === 2) x--;
|
|
6307
|
+
else if (step === 3) x++;
|
|
6308
|
+
if (step !== prevStep) {
|
|
6309
|
+
path.push({
|
|
6310
|
+
x: x + cx,
|
|
6311
|
+
y: y + cy
|
|
6312
|
+
});
|
|
6313
|
+
prevStep = step;
|
|
6314
|
+
}
|
|
6315
|
+
} while (x !== startX || y !== startY);
|
|
6316
|
+
}
|
|
6317
|
+
paths.push(path);
|
|
6318
|
+
return path;
|
|
6319
|
+
};
|
|
6320
|
+
trace();
|
|
6321
|
+
return paths;
|
|
6322
|
+
}
|
|
6323
|
+
//#endregion
|
|
6077
6324
|
//#region src/convert/svg.ts
|
|
6078
6325
|
async function convertSvgElementToUrl(el) {
|
|
6079
6326
|
const { id, doc, url, style = {}, background = {} } = el;
|
|
@@ -6082,25 +6329,23 @@ async function convertSvgElementToUrl(el) {
|
|
|
6082
6329
|
const svg = new DOMParser().parseFromString(xml.replace(new RegExp(`#el-${id} `, "gi"), "").replace(/data-colors\s/, " ").replace(/[a-z-]+="([^\s<]*<\S*)"/gi, ""), "image/svg+xml").documentElement;
|
|
6083
6330
|
if (!(svg instanceof SVGElement)) throw new TypeError(`Failed to DOMParser, parse svg to DOM error: ${xml}`);
|
|
6084
6331
|
const images = svg.querySelectorAll("image");
|
|
6085
|
-
|
|
6086
|
-
const image = images[i];
|
|
6332
|
+
await Promise.all(Array.from(images).map(async (image) => {
|
|
6087
6333
|
const url = image.href.baseVal;
|
|
6088
|
-
if (!url.startsWith("http"))
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
}
|
|
6334
|
+
if (!url.startsWith("http")) return;
|
|
6335
|
+
const bitmap = await cachedFetchImageBitmap(url);
|
|
6336
|
+
const canvas = document.createElement("canvas");
|
|
6337
|
+
canvas.width = bitmap.width;
|
|
6338
|
+
canvas.height = bitmap.height;
|
|
6339
|
+
canvas.getContext("2d")?.drawImage(bitmap, 0, 0);
|
|
6340
|
+
bitmap.close();
|
|
6341
|
+
image.setAttribute("href", canvas.toDataURL("image/png"));
|
|
6342
|
+
}));
|
|
6098
6343
|
if (background.src) {
|
|
6099
6344
|
const fillId = `#${id}-fill-blip`;
|
|
6100
6345
|
const fillPattern = svg.querySelector(fillId);
|
|
6101
6346
|
const fillImage = fillPattern?.querySelector("image");
|
|
6102
6347
|
if (fillPattern && fillImage) try {
|
|
6103
|
-
const base64Url = await
|
|
6348
|
+
const base64Url = await cachedFetchImageBitmap(background.src).then((bitmap) => {
|
|
6104
6349
|
const canvas = document.createElement("canvas");
|
|
6105
6350
|
canvas.width = bitmap.width;
|
|
6106
6351
|
canvas.height = bitmap.height;
|
|
@@ -6500,217 +6745,6 @@ async function convertDoc(doc, options = {}) {
|
|
|
6500
6745
|
};
|
|
6501
6746
|
}
|
|
6502
6747
|
//#endregion
|
|
6503
|
-
//#region src/convert/image.ts
|
|
6504
|
-
async function convertImageElementToUrl(el) {
|
|
6505
|
-
const { cropping = {}, transform = {}, style = {}, maskUrl, imageEffects = [], imageEffectsRatio = 1 } = el;
|
|
6506
|
-
const url = el.clipUrl || el.url;
|
|
6507
|
-
const { translateX = 0, translateY = 0, zoom = 1 } = transform ?? {};
|
|
6508
|
-
const { scaleX = 1, scaleY = 1, filter } = style;
|
|
6509
|
-
if (translateX === 0 && translateY === 0 && zoom === 1 && scaleX === 1 && scaleY === 1 && !maskUrl && !filter && !imageEffects.length) return url;
|
|
6510
|
-
const img = await assets.fetchImageBitmap(url);
|
|
6511
|
-
const { originWidth = img.width, originHeight = img.height, imageWidth = originWidth, imageHeight = originHeight } = transform;
|
|
6512
|
-
const { width = originWidth, height = originHeight } = style;
|
|
6513
|
-
const dpr = window.devicePixelRatio || 1;
|
|
6514
|
-
const [canvas, ctx] = createCanvas(width, height, dpr);
|
|
6515
|
-
if (filter) ctx.filter = filter;
|
|
6516
|
-
ctx.scale(scaleX, scaleY);
|
|
6517
|
-
ctx.translate(scaleX < 0 ? -width : 0, scaleY < 0 ? -height : 0);
|
|
6518
|
-
if (maskUrl) {
|
|
6519
|
-
const mask = await assets.fetchImageBitmap(maskUrl);
|
|
6520
|
-
ctx.drawImage(mask, 0, 0, cropping?.maskWidth ?? width, cropping?.maskHeight ?? height);
|
|
6521
|
-
ctx.globalCompositeOperation = "source-in";
|
|
6522
|
-
mask.close();
|
|
6523
|
-
}
|
|
6524
|
-
const dw = imageWidth * zoom;
|
|
6525
|
-
const dh = imageHeight * zoom;
|
|
6526
|
-
const dx = -(dw / 2 - imageWidth / 2) + translateX;
|
|
6527
|
-
const dy = -(dh / 2 - imageHeight / 2) + translateY;
|
|
6528
|
-
ctx.drawImage(img, 0, 0, img.width, img.height, dx, dy, dw, dh);
|
|
6529
|
-
img.close();
|
|
6530
|
-
ctx.globalCompositeOperation = "source-over";
|
|
6531
|
-
if (imageEffects.length > 0) {
|
|
6532
|
-
const scale = .9;
|
|
6533
|
-
const center = {
|
|
6534
|
-
x: (width - width * scale) / 2,
|
|
6535
|
-
y: (height - height * scale) / 2
|
|
6536
|
-
};
|
|
6537
|
-
const canvasBitmap = await createImageBitmap(canvas);
|
|
6538
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
6539
|
-
ctx.scale(scale, scale);
|
|
6540
|
-
for (let i = imageEffects.length - 1; i >= 0; i--) {
|
|
6541
|
-
const { filling, offset, stroke } = imageEffects[i];
|
|
6542
|
-
let effectCanvas = canvasBitmap;
|
|
6543
|
-
if (filling) {
|
|
6544
|
-
const [canvas1, ctx1] = createCanvas(width, height, dpr);
|
|
6545
|
-
ctx1.drawImage(effectCanvas, 0, 0, width, height);
|
|
6546
|
-
ctx1.globalCompositeOperation = "source-in";
|
|
6547
|
-
if (filling.color) {
|
|
6548
|
-
const [canvas2, ctx2] = createCanvas(width, height, dpr);
|
|
6549
|
-
ctx2.fillStyle = filling.color;
|
|
6550
|
-
ctx2.fillRect(0, 0, width, height);
|
|
6551
|
-
ctx1.drawImage(canvas2, 0, 0, width, height);
|
|
6552
|
-
} else if (filling.imageContent?.image) {
|
|
6553
|
-
const img2 = await assets.fetchImageBitmap(filling.imageContent.image);
|
|
6554
|
-
ctx1.drawImage(img2, 0, 0, width, height);
|
|
6555
|
-
img2.close();
|
|
6556
|
-
}
|
|
6557
|
-
effectCanvas = canvas1;
|
|
6558
|
-
}
|
|
6559
|
-
stroke?.forEach(({ width, color }) => {
|
|
6560
|
-
effectCanvas = new ImageStroke().use((ctx, image, options) => {
|
|
6561
|
-
const [, ctx1] = createCanvas(image.width, image.height);
|
|
6562
|
-
ctx1.drawImage(image, 0, 0);
|
|
6563
|
-
const paths = getContours(ctx1);
|
|
6564
|
-
const x = options.thickness;
|
|
6565
|
-
const y = options.thickness;
|
|
6566
|
-
ctx.strokeStyle = options.color;
|
|
6567
|
-
ctx.lineWidth = options.thickness * 2;
|
|
6568
|
-
ctx.lineJoin = "round";
|
|
6569
|
-
paths.forEach((path) => {
|
|
6570
|
-
ctx.beginPath();
|
|
6571
|
-
ctx.moveTo(x + path[0].x, y + path[1].y);
|
|
6572
|
-
for (let i = 1; i < path.length; i++) ctx.lineTo(x + path[i].x, y + path[i].y);
|
|
6573
|
-
ctx.closePath();
|
|
6574
|
-
});
|
|
6575
|
-
ctx.stroke();
|
|
6576
|
-
}).make(effectCanvas, {
|
|
6577
|
-
color,
|
|
6578
|
-
thickness: width / 50 * imageEffectsRatio
|
|
6579
|
-
});
|
|
6580
|
-
});
|
|
6581
|
-
if (offset) {
|
|
6582
|
-
let { x, y } = offset;
|
|
6583
|
-
x = x / 50 * imageEffectsRatio * 200;
|
|
6584
|
-
y = y / 50 * imageEffectsRatio * 200;
|
|
6585
|
-
ctx.drawImage(effectCanvas, x + center.x, y + center.y, width, height);
|
|
6586
|
-
} else ctx.drawImage(effectCanvas, center.x, center.y, width, height);
|
|
6587
|
-
}
|
|
6588
|
-
canvasBitmap.close();
|
|
6589
|
-
}
|
|
6590
|
-
return await new Promise((resolve) => {
|
|
6591
|
-
canvas.toBlob((blob) => {
|
|
6592
|
-
try {
|
|
6593
|
-
resolve(URL.createObjectURL(blob));
|
|
6594
|
-
} catch (e) {
|
|
6595
|
-
console.error(`Failed to URL.createObjectURL, url: ${url}`, e);
|
|
6596
|
-
resolve(url);
|
|
6597
|
-
}
|
|
6598
|
-
});
|
|
6599
|
-
});
|
|
6600
|
-
}
|
|
6601
|
-
function createCanvas(width, height, ratio = 1) {
|
|
6602
|
-
const canvas = document.createElement("canvas");
|
|
6603
|
-
canvas.width = width * ratio;
|
|
6604
|
-
canvas.height = height * ratio;
|
|
6605
|
-
canvas.style.width = `${width}px`;
|
|
6606
|
-
canvas.style.height = `${height}px`;
|
|
6607
|
-
const ctx = canvas.getContext("2d");
|
|
6608
|
-
ctx.scale(ratio, ratio);
|
|
6609
|
-
return [canvas, ctx];
|
|
6610
|
-
}
|
|
6611
|
-
var ImageStroke = class {
|
|
6612
|
-
canvas = document.createElement("canvas");
|
|
6613
|
-
method;
|
|
6614
|
-
use(method) {
|
|
6615
|
-
this.method = method;
|
|
6616
|
-
return this;
|
|
6617
|
-
}
|
|
6618
|
-
make(image, options) {
|
|
6619
|
-
const { canvas } = this;
|
|
6620
|
-
const ctx = this.canvas.getContext("2d");
|
|
6621
|
-
const strokeSize = options.thickness * 2;
|
|
6622
|
-
const [resultWidth, resultHeight] = [image.width, image.height].map((val) => val + strokeSize);
|
|
6623
|
-
if (resultWidth !== canvas.width || resultHeight !== canvas.height) {
|
|
6624
|
-
canvas.width = resultWidth;
|
|
6625
|
-
canvas.height = resultHeight;
|
|
6626
|
-
}
|
|
6627
|
-
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
6628
|
-
this.method(ctx, image, options);
|
|
6629
|
-
ctx.drawImage(image, options.thickness, options.thickness);
|
|
6630
|
-
return canvas;
|
|
6631
|
-
}
|
|
6632
|
-
};
|
|
6633
|
-
function getContours(ctx) {
|
|
6634
|
-
const cx = 0;
|
|
6635
|
-
const cy = 0;
|
|
6636
|
-
const canvasWidth = ctx.canvas.width;
|
|
6637
|
-
const canvasHeight = ctx.canvas.height;
|
|
6638
|
-
const paths = [];
|
|
6639
|
-
let lastPos = 3;
|
|
6640
|
-
const alpha = 100;
|
|
6641
|
-
const trace = () => {
|
|
6642
|
-
const path = [];
|
|
6643
|
-
const data = new Uint32Array(ctx.getImageData(cx, cy, canvasWidth, canvasHeight).data.buffer);
|
|
6644
|
-
let x;
|
|
6645
|
-
let y;
|
|
6646
|
-
let startX;
|
|
6647
|
-
let startY;
|
|
6648
|
-
let startPos = -1;
|
|
6649
|
-
let step;
|
|
6650
|
-
let prevStep = 9;
|
|
6651
|
-
const steps = [
|
|
6652
|
-
9,
|
|
6653
|
-
0,
|
|
6654
|
-
3,
|
|
6655
|
-
3,
|
|
6656
|
-
2,
|
|
6657
|
-
0,
|
|
6658
|
-
9,
|
|
6659
|
-
3,
|
|
6660
|
-
1,
|
|
6661
|
-
9,
|
|
6662
|
-
1,
|
|
6663
|
-
1,
|
|
6664
|
-
2,
|
|
6665
|
-
0,
|
|
6666
|
-
2,
|
|
6667
|
-
9
|
|
6668
|
-
];
|
|
6669
|
-
let time = 50;
|
|
6670
|
-
function getState(x, y) {
|
|
6671
|
-
return x >= 0 && y >= 0 && x < canvasWidth && y < canvasHeight ? data[y * canvasWidth + x] >>> 24 > alpha : false;
|
|
6672
|
-
}
|
|
6673
|
-
function getNextStep(x, y) {
|
|
6674
|
-
let v = 0;
|
|
6675
|
-
if (getState(x - 1, y - 1)) v += 1;
|
|
6676
|
-
if (getState(x, y - 1)) v += 2;
|
|
6677
|
-
if (getState(x - 1, y)) v += 4;
|
|
6678
|
-
if (getState(x, y)) v += 8;
|
|
6679
|
-
if (time > 50) time += 10;
|
|
6680
|
-
else time += 10;
|
|
6681
|
-
if (v === 6) return prevStep === 0 ? 2 : 3;
|
|
6682
|
-
else if (v === 9) return prevStep === 3 ? 0 : 1;
|
|
6683
|
-
else return steps[v];
|
|
6684
|
-
}
|
|
6685
|
-
for (let i = lastPos; i < data.length; i++) if (data[i] >>> 24 > alpha) {
|
|
6686
|
-
startPos = lastPos = i;
|
|
6687
|
-
break;
|
|
6688
|
-
}
|
|
6689
|
-
if (startPos >= 0) {
|
|
6690
|
-
x = startX = startPos % canvasWidth;
|
|
6691
|
-
y = startY = Math.floor(startPos / canvasWidth);
|
|
6692
|
-
do {
|
|
6693
|
-
step = getNextStep(x, y);
|
|
6694
|
-
if (step === 0) y--;
|
|
6695
|
-
else if (step === 1) y++;
|
|
6696
|
-
else if (step === 2) x--;
|
|
6697
|
-
else if (step === 3) x++;
|
|
6698
|
-
if (step !== prevStep) {
|
|
6699
|
-
path.push({
|
|
6700
|
-
x: x + cx,
|
|
6701
|
-
y: y + cy
|
|
6702
|
-
});
|
|
6703
|
-
prevStep = step;
|
|
6704
|
-
}
|
|
6705
|
-
} while (x !== startX || y !== startY);
|
|
6706
|
-
}
|
|
6707
|
-
paths.push(path);
|
|
6708
|
-
return path;
|
|
6709
|
-
};
|
|
6710
|
-
trace();
|
|
6711
|
-
return paths;
|
|
6712
|
-
}
|
|
6713
|
-
//#endregion
|
|
6714
6748
|
//#region src/loaders/bidTid.ts
|
|
6715
6749
|
function bidTidLoader(editor, api) {
|
|
6716
6750
|
const { config, http } = editor;
|
|
@@ -6930,4 +6964,4 @@ var options = {
|
|
|
6930
6964
|
//#region src/index.ts
|
|
6931
6965
|
var src_default = plugin;
|
|
6932
6966
|
//#endregion
|
|
6933
|
-
export { bidTidLoader, bigeLoader, clipboardLoader, convertAnimation, convertBackground, convertDoc, convertElement, convertImageElementToUrl, convertLayout, convertSvgElementToUrl, convertTextContent, convertTextEffects, convertTextStyle, croppingToCropRect, src_default as default, getStyle, getTextContents, options, parseAnimations, plugin, transformToCropRect, useFonts };
|
|
6967
|
+
export { bidTidLoader, bigeLoader, cachedFetchImageBitmap, clipboardLoader, convertAnimation, convertBackground, convertDoc, convertElement, convertImageElementToUrl, convertLayout, convertSvgElementToUrl, convertTextContent, convertTextEffects, convertTextStyle, croppingToCropRect, src_default as default, getStyle, getTextContents, options, parseAnimations, plugin, transformToCropRect, useFonts };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mce/bigesj",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.19.1",
|
|
5
5
|
"description": "Plugin for mce",
|
|
6
6
|
"author": "wxm",
|
|
7
7
|
"license": "MIT",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
],
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"fflate": "^0.8.3",
|
|
49
|
-
"modern-openxml": "^1.
|
|
49
|
+
"modern-openxml": "^1.12.3"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"mce": "0.
|
|
52
|
+
"mce": "0.19.1"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"mce": "^0"
|