@plait/common 0.75.0 → 0.76.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,5 +1,6 @@
1
1
  import { Node } from 'slate';
2
2
  import { getLineHeightByFontSize } from '../utils/text';
3
+ import { IS_WINDOWS } from '@plait/core';
3
4
  export function measureElement(element, options, containerMaxWidth = 10000) {
4
5
  const canvas = document.createElement('canvas');
5
6
  const ctx = canvas.getContext('2d');
@@ -30,8 +31,35 @@ export function measureElement(element, options, containerMaxWidth = 10000) {
30
31
  lineTexts.forEach((text, index) => {
31
32
  const font = getFont(text, { fontFamily: options.fontFamily, fontSize: options.fontSize });
32
33
  ctx.font = font;
33
- const textMetrics = ctx.measureText(text.text);
34
- lineWidth += textMetrics.width;
34
+ // Windows 平台下的特殊处理
35
+ if (IS_WINDOWS) {
36
+ let adjustedWidth = 0;
37
+ // 逐字符处理
38
+ for (let i = 0; i < text.text.length; i++) {
39
+ const char = text.text[i];
40
+ const charMetrics = ctx.measureText(char);
41
+ // 判断是否为汉字(通过 Unicode 范围)
42
+ if (/[\u4e00-\u9fa5]/.test(char)) {
43
+ adjustedWidth += charMetrics.width;
44
+ }
45
+ else {
46
+ // 非汉字字符的宽度调整
47
+ if (/[a-zA-Z]/.test(char)) {
48
+ adjustedWidth += charMetrics.width + 1.5; // 字母
49
+ }
50
+ else if (/[0-9]/.test(char)) {
51
+ adjustedWidth += charMetrics.width + 1.5; // 数字
52
+ }
53
+ else {
54
+ adjustedWidth += charMetrics.width + 0.8; // 其他符号
55
+ }
56
+ }
57
+ }
58
+ lineWidth += adjustedWidth;
59
+ }
60
+ else {
61
+ lineWidth += ctx.measureText(text.text).width;
62
+ }
35
63
  const isLast = index === lineTexts.length - 1;
36
64
  // skip when text is empty and is not last text of line
37
65
  if (text['font-size'] && (isLast || text.text !== '')) {
@@ -58,4 +86,4 @@ export function measureElement(element, options, containerMaxWidth = 10000) {
58
86
  const getFont = (text, options) => {
59
87
  return `${text.italic ? 'italic ' : ''} ${text.bold ? 'bold ' : ''} ${text['font-size'] || options.fontSize}px ${options.fontFamily} `;
60
88
  };
61
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC1tZWFzdXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tbW9uL3NyYy90ZXh0L3RleHQtbWVhc3VyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBRTdCLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUV4RCxNQUFNLFVBQVUsY0FBYyxDQUMxQixPQUF5QixFQUN6QixPQUdDLEVBQ0Qsb0JBQTRCLEtBQUs7SUFFakMsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNoRCxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBNkIsQ0FBQztJQUNoRSxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3hDLE1BQU0sS0FBSyxHQUFtQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25DLEtBQUssTUFBTSxTQUFTLElBQUksV0FBVyxFQUFFLENBQUM7UUFDbEMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLFNBQVMsQ0FBQztRQUN6QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLGlCQUF5QixFQUFFLEtBQWEsRUFBRSxFQUFFO1lBQzNELE1BQU0sV0FBVyxHQUFHLEVBQUUsR0FBRyxJQUFJLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFLENBQUM7WUFDekQsSUFBSSxLQUFLLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ2QsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFN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XG5pbXBvcnQgeyBDdXN0b21UZXh0LCBQYXJhZ3JhcGhFbGVtZW50IH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBnZXRMaW5lSGVpZ2h0QnlGb250U2l6ZSB9IGZyb20gJy4uL3V0aWxzL3RleHQnO1xuXG5leHBvcnQgZnVuY3Rpb24gbWVhc3VyZUVsZW1lbnQoXG4gICAgZWxlbWVudDogUGFyYWdyYXBoRWxlbWVudCxcbiAgICBvcHRpb25zOiB7XG4gICAgICAgIGZvbnRTaXplOiBudW1iZXI7XG4gICAgICAgIGZvbnRGYW1pbHk6IHN0cmluZztcbiAgICB9LFxuICAgIGNvbnRhaW5lck1heFdpZHRoOiBudW1iZXIgPSAxMDAwMFxuKSB7XG4gICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJykgYXMgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xuICAgIGNvbnN0IHRleHRFbnRyaWVzID0gTm9kZS50ZXh0cyhlbGVtZW50KTtcbiAgICBjb25zdCBsaW5lczogQ3VzdG9tVGV4dFtdW10gPSBbW11dO1xuICAgIGZvciAoY29uc3QgdGV4dEVudHJ5IG9mIHRleHRFbnRyaWVzKSB7XG4gICAgICAgIGNvbnN0IFt0ZXh0XSA9IHRleHRFbnRyeTtcbiAgICAgICAgY29uc3QgdGV4dFN0cmluZyA9IE5vZGUuc3RyaW5nKHRleHQpO1xuICAgICAgICBjb25zdCB0ZXh0QXJyYXkgPSB0ZXh0U3RyaW5nLnNwbGl0KCdcXG4nKTtcbiAgICAgICAgdGV4dEFycmF5LmZvckVhY2goKHNlZ21lbnRUZXh0U3RyaW5nOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHNlZ21lbnRUZXh0ID0geyAuLi50ZXh0LCB0ZXh0OiBzZWdtZW50VGV4dFN0cmluZyB9O1xuICAgICAgICAgICAgaWYgKGluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY3VycmVudExpbmUgPSBsaW5lc1tsaW5lcy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICBjdXJyZW50TGluZS5wdXNoKHNlZ21lbnRUZXh0KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV3TGluZTogQ3VzdG9tVGV4dFtdID0gW107XG4gICAgICAgICAgICAgICAgbmV3TGluZS5wdXNoKHNlZ21lbnRUZXh0KTtcbiAgICAgICAgICAgICAgICBsaW5lcy5wdXNoKG5ld0xpbmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgbGV0IHdpZHRoID0gMDtcbiAgICBsZXQgaGVpZ2h0ID0gMDtcbiAgICBsaW5lcy5mb3JFYWNoKChsaW5lVGV4dHM6IEN1c3RvbVRleHRbXSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICBsZXQgbGluZVdpZHRoID0gMDtcbiAgICAgICAgbGV0IG1heExpbmVIZWlnaHQgPSBnZXRMaW5lSGVpZ2h0QnlGb250U2l6ZShvcHRpb25zLmZvbnRTaXplKTtcbiAgICAgICAgbGluZVRleHRzLmZvckVhY2goKHRleHQ6IEN1c3RvbVRleHQsIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGZvbnQgPSBnZXRGb250KHRleHQsIHsgZm9udEZhbWlseTogb3B0aW9ucy5mb250RmFtaWx5LCBmb250U2l6ZTogb3B0aW9ucy5mb250U2l6ZSB9KTtcbiAgICAgICAgICAgIGN0eC5mb250ID0gZm9udDtcbiAgICAgICAgICAgIGNvbnN0IHRleHRNZXRyaWNzID0gY3R4Lm1lYXN1cmVUZXh0KHRleHQudGV4dCk7XG4gICAgICAgICAgICBsaW5lV2lkdGggKz0gdGV4dE1ldHJpY3Mud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBpc0xhc3QgPSBpbmRleCA9PT0gbGluZVRleHRzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAvLyBza2lwIHdoZW4gdGV4dCBpcyBlbXB0eSBhbmQgaXMgbm90IGxhc3QgdGV4dCBvZiBsaW5lXG4gICAgICAgICAgICBpZiAodGV4dFsnZm9udC1zaXplJ10gJiYgKGlzTGFzdCB8fCB0ZXh0LnRleHQgIT09ICcnKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxpbmVIZWlnaHQgPSBnZXRMaW5lSGVpZ2h0QnlGb250U2l6ZShwYXJzZUZsb2F0KHRleHRbJ2ZvbnQtc2l6ZSddKSk7XG4gICAgICAgICAgICAgICAgaWYgKGxpbmVIZWlnaHQgPiBtYXhMaW5lSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIG1heExpbmVIZWlnaHQgPSBsaW5lSGVpZ2h0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChsaW5lV2lkdGggPD0gY29udGFpbmVyTWF4V2lkdGgpIHtcbiAgICAgICAgICAgIGlmIChsaW5lV2lkdGggPiB3aWR0aCkge1xuICAgICAgICAgICAgICAgIHdpZHRoID0gbGluZVdpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGVpZ2h0ICs9IG1heExpbmVIZWlnaHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3aWR0aCA9IGNvbnRhaW5lck1heFdpZHRoO1xuICAgICAgICAgICAgY29uc3QgbGluZVdyYXBOdW1iZXIgPSBNYXRoLmNlaWwobGluZVdpZHRoIC8gY29udGFpbmVyTWF4V2lkdGgpO1xuICAgICAgICAgICAgaGVpZ2h0ICs9IG1heExpbmVIZWlnaHQgKiBsaW5lV3JhcE51bWJlcjtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB7IHdpZHRoLCBoZWlnaHQgfTtcbn1cblxuY29uc3QgZ2V0Rm9udCA9IChcbiAgICB0ZXh0OiBDdXN0b21UZXh0LFxuICAgIG9wdGlvbnM6IHtcbiAgICAgICAgZm9udFNpemU6IG51bWJlcjtcbiAgICAgICAgZm9udEZhbWlseTogc3RyaW5nO1xuICAgIH1cbikgPT4ge1xuICAgIHJldHVybiBgJHt0ZXh0Lml0YWxpYyA/ICdpdGFsaWMgJyA6ICcnfSAke3RleHQuYm9sZCA/ICdib2xkICcgOiAnJ30gJHt0ZXh0Wydmb250LXNpemUnXSB8fCBvcHRpb25zLmZvbnRTaXplfXB4ICR7b3B0aW9ucy5mb250RmFtaWx5fSBgO1xufTtcbiJdfQ==
89
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC1tZWFzdXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tbW9uL3NyYy90ZXh0L3RleHQtbWVhc3VyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBRTdCLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXpDLE1BQU0sVUFBVSxjQUFjLENBQzFCLE9BQXlCLEVBQ3pCLE9BR0MsRUFDRCxvQkFBNEIsS0FBSztJQUVqQyxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2hELE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUE2QixDQUFDO0lBQ2hFLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDeEMsTUFBTSxLQUFLLEdBQW1CLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbkMsS0FBSyxNQUFNLFNBQVMsSUFBSSxXQUFXLEVBQUUsQ0FBQztRQUNsQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsU0FBUyxDQUFDO1FBQ3pCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDckMsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsaUJBQXlCLEVBQUUsS0FBYSxFQUFFLEVBQUU7WUFDM0QsTUFBTSxXQUFXLEdBQUcsRUFBRSxHQUFHLElBQUksRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQztZQUN6RCxJQUFJLEtBQUssS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFD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VSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzFFLElBQUksVUFBVSxHQUFHLGFBQWEsRUFBRSxDQUFDO29CQUM3QixhQUFhLEdBQUcsVUFBVSxDQUFDO2dCQUMvQixDQUFDO1lBQ0wsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxTQUFTLElBQUksaUJBQWlCLEVBQUUsQ0FBQztZQUNqQyxJQUFJLFNBQVMsR0FBRyxLQUFLLEVBQUUsQ0FBQztnQkFDcEIsS0FBSyxHQUFHLFNBQVMsQ0FBQztZQUN0QixDQUFDO1lBQ0QsTUFBTSxJQUFJLGFBQWEsQ0FBQztRQUM1QixDQUFDO2FBQU0sQ0FBQztZQUNKLEtBQUssR0FBRyxpQkFBaUIsQ0FBQztZQUMxQixNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxpQkFBaUIsQ0FBQyxDQUFDO1lBQ2hFLE1BQU0sSUFBSSxhQUFhLEdBQUcsY0FBYyxDQUFDO1FBQzdDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUM7QUFDN0IsQ0FBQztBQUVELE1BQU0sT0FBTyxHQUFHLENBQ1osSUFBZ0IsRUFDaEIsT0FHQyxFQUNILEVBQUU7SUFDQSxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxRQUFRLE1BQU0sT0FBTyxDQUFDLFVBQVUsR0FBRyxDQUFDO0FBQzNJLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5vZGUgfSBmcm9tICdzbGF0ZSc7XG5pbXBvcnQgeyBDdXN0b21UZXh0LCBQYXJhZ3JhcGhFbGVtZW50IH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBnZXRMaW5lSGVpZ2h0QnlGb250U2l6ZSB9IGZyb20gJy4uL3V0aWxzL3RleHQnO1xuaW1wb3J0IHsgSVNfV0lORE9XUyB9IGZyb20gJ0BwbGFpdC9jb3JlJztcblxuZXhwb3J0IGZ1bmN0aW9uIG1lYXN1cmVFbGVtZW50KFxuICAgIGVsZW1lbnQ6IFBhcmFncmFwaEVsZW1lbnQsXG4gICAgb3B0aW9uczoge1xuICAgICAgICBmb250U2l6ZTogbnVtYmVyO1xuICAgICAgICBmb250RmFtaWx5OiBzdHJpbmc7XG4gICAgfSxcbiAgICBjb250YWluZXJNYXhXaWR0aDogbnVtYmVyID0gMTAwMDBcbikge1xuICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgIGNvbnN0IGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpIGFzIENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcbiAgICBjb25zdCB0ZXh0RW50cmllcyA9IE5vZGUudGV4dHMoZWxlbWVudCk7XG4gICAgY29uc3QgbGluZXM6IEN1c3RvbVRleHRbXVtdID0gW1tdXTtcbiAgICBmb3IgKGNvbnN0IHRleHRFbnRyeSBvZiB0ZXh0RW50cmllcykge1xuICAgICAgICBjb25zdCBbdGV4dF0gPSB0ZXh0RW50cnk7XG4gICAgICAgIGNvbnN0IHRleHRTdHJpbmcgPSBOb2RlLnN0cmluZyh0ZXh0KTtcbiAgICAgICAgY29uc3QgdGV4dEFycmF5ID0gdGV4dFN0cmluZy5zcGxpdCgnXFxuJyk7XG4gICAgICAgIHRleHRBcnJheS5mb3JFYWNoKChzZWdtZW50VGV4dFN0cmluZzogc3RyaW5nLCBpbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzZWdtZW50VGV4dCA9IHsgLi4udGV4dCwgdGV4dDogc2VnbWVudFRleHRTdHJpbmcgfTtcbiAgICAgICAgICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRMaW5lID0gbGluZXNbbGluZXMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgY3VycmVudExpbmUucHVzaChzZWdtZW50VGV4dCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld0xpbmU6IEN1c3RvbVRleHRbXSA9IFtdO1xuICAgICAgICAgICAgICAgIG5ld0xpbmUucHVzaChzZWdtZW50VGV4dCk7XG4gICAgICAgICAgICAgICAgbGluZXMucHVzaChuZXdMaW5lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGxldCB3aWR0aCA9IDA7XG4gICAgbGV0IGhlaWdodCA9IDA7XG4gICAgbGluZXMuZm9yRWFjaCgobGluZVRleHRzOiBDdXN0b21UZXh0W10sIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgbGV0IGxpbmVXaWR0aCA9IDA7XG4gICAgICAgIGxldCBtYXhMaW5lSGVpZ2h0ID0gZ2V0TGluZUhlaWdodEJ5Rm9udFNpemUob3B0aW9ucy5mb250U2l6ZSk7XG4gICAgICAgIGxpbmVUZXh0cy5mb3JFYWNoKCh0ZXh0OiBDdXN0b21UZXh0LCBpbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmb250ID0gZ2V0Rm9udCh0ZXh0LCB7IGZvbnRGYW1pbHk6IG9wdGlvbnMuZm9udEZhbWlseSwgZm9udFNpemU6IG9wdGlvbnMuZm9udFNpemUgfSk7XG4gICAgICAgICAgICBjdHguZm9udCA9IGZvbnQ7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIFdpbmRvd3Mg5bmz5Y+w5LiL55qE54m55q6K5aSE55CGXG4gICAgICAgICAgICBpZiAoSVNfV0lORE9XUykge1xuICAgICAgICAgICAgICAgIGxldCBhZGp1c3RlZFdpZHRoID0gMDtcbiAgICAgICAgICAgICAgICAvLyDpgJDlrZfnrKblpITnkIZcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRleHQudGV4dC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFyID0gdGV4dC50ZXh0W2ldO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFyTWV0cmljcyA9IGN0eC5tZWFzdXJlVGV4dChjaGFyKTtcbiAgICAgICAgICAgICAgICAgICAgLy8g5Yik5pat5piv5ZCm5Li65rGJ5a2X77yI6YCa6L+HIFVuaWNvZGUg6IyD5Zu077yJXG4gICAgICAgICAgICAgICAgICAgIGlmICgvW1xcdTRlMDAtXFx1OWZhNV0vLnRlc3QoY2hhcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkanVzdGVkV2lkdGggKz0gY2hhck1ldHJpY3Mud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyDpnZ7msYnlrZflrZfnrKbnmoTlrr3luqbosIPmlbRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgvW2EtekEtWl0vLnRlc3QoY2hhcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGp1c3RlZFdpZHRoICs9IGNoYXJNZXRyaWNzLndpZHRoICsgMS41OyAvLyDlrZfmr41cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoL1swLTldLy50ZXN0KGNoYXIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRqdXN0ZWRXaWR0aCArPSBjaGFyTWV0cmljcy53aWR0aCArIDEuNTsgLy8g5pWw5a2XXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkanVzdGVkV2lkdGggKz0gY2hhck1ldHJpY3Mud2lkdGggKyAwLjg7IC8vIOWFtuS7luespuWPt1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxpbmVXaWR0aCArPSBhZGp1c3RlZFdpZHRoO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsaW5lV2lkdGggKz0gY3R4Lm1lYXN1cmVUZXh0KHRleHQudGV4dCkud2lkdGg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGlzTGFzdCA9IGluZGV4ID09PSBsaW5lVGV4dHMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgIC8vIHNraXAgd2hlbiB0ZXh0IGlzIGVtcHR5IGFuZCBpcyBub3QgbGFzdCB0ZXh0IG9mIGxpbmVcbiAgICAgICAgICAgIGlmICh0ZXh0Wydmb250LXNpemUnXSAmJiAoaXNMYXN0IHx8IHRleHQudGV4dCAhPT0gJycpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbGluZUhlaWdodCA9IGdldExpbmVIZWlnaHRCeUZvbnRTaXplKHBhcnNlRmxvYXQodGV4dFsnZm9udC1zaXplJ10pKTtcbiAgICAgICAgICAgICAgICBpZiAobGluZUhlaWdodCA+IG1heExpbmVIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF4TGluZUhlaWdodCA9IGxpbmVIZWlnaHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGxpbmVXaWR0aCA8PSBjb250YWluZXJNYXhXaWR0aCkge1xuICAgICAgICAgICAgaWYgKGxpbmVXaWR0aCA+IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgd2lkdGggPSBsaW5lV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoZWlnaHQgKz0gbWF4TGluZUhlaWdodDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdpZHRoID0gY29udGFpbmVyTWF4V2lkdGg7XG4gICAgICAgICAgICBjb25zdCBsaW5lV3JhcE51bWJlciA9IE1hdGguY2VpbChsaW5lV2lkdGggLyBjb250YWluZXJNYXhXaWR0aCk7XG4gICAgICAgICAgICBoZWlnaHQgKz0gbWF4TGluZUhlaWdodCAqIGxpbmVXcmFwTnVtYmVyO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHsgd2lkdGgsIGhlaWdodCB9O1xufVxuXG5jb25zdCBnZXRGb250ID0gKFxuICAgIHRleHQ6IEN1c3RvbVRleHQsXG4gICAgb3B0aW9uczoge1xuICAgICAgICBmb250U2l6ZTogbnVtYmVyO1xuICAgICAgICBmb250RmFtaWx5OiBzdHJpbmc7XG4gICAgfVxuKSA9PiB7XG4gICAgcmV0dXJuIGAke3RleHQuaXRhbGljID8gJ2l0YWxpYyAnIDogJyd9ICR7dGV4dC5ib2xkID8gJ2JvbGQgJyA6ICcnfSAke3RleHRbJ2ZvbnQtc2l6ZSddIHx8IG9wdGlvbnMuZm9udFNpemV9cHggJHtvcHRpb25zLmZvbnRGYW1pbHl9IGA7XG59O1xuIl19
@@ -1,4 +1,4 @@
1
- import { PlaitGroupElement, getSelectionAngle, getElementsInGroup, setAngleForG, RectangleClient, drawCircle, PlaitBoard, RESIZE_HANDLE_CLASS_NAME, DEFAULT_COLOR, createG, setStrokeLinecap, drawRectangle, SELECTION_RECTANGLE_CLASS_NAME, ResizeCursorClass, RESIZE_CURSORS, setDragging, rotatePoints, isSelectionMoving, getSelectedElements, distanceBetweenPointAndPoint, Point, Direction, hotkeys, PlaitElement, createDebugGenerator, idCreator, Transforms, createForeignObject, ACTIVE_STROKE_WIDTH, updateForeignObject, getHighestSelectedElements, getRectangleByElements, MERGING, PlaitPointerType, isMainPointer, toViewBoxPoint, toHostPoint, PRESS_AND_MOVE_BUFFER, isDragging, throttleRAF, getRectangleByGroup, ElementFlavour, isSelectedElementOrGroup, Selection, isMovingElements, getHitElementsBySelection, createGroupRectangleG, getSelectedGroups, getHighestSelectedGroups, getSelectedIsolatedElements, getSelectedIsolatedElementsCanAddToGroup, getGroupByElement, updateForeignObjectWidth, IS_TEXT_EDITABLE } from '@plait/core';
1
+ import { RectangleClient, toActiveRectangleFromViewBoxRectangle, PlaitGroupElement, getSelectionAngle, getElementsInGroup, setAngleForG, drawCircle, PlaitBoard, RESIZE_HANDLE_CLASS_NAME, DEFAULT_COLOR, createG, setStrokeLinecap, drawRectangle, ACTIVE_STROKE_WIDTH, SELECTION_RECTANGLE_CLASS_NAME, ResizeCursorClass, RESIZE_CURSORS, setDragging, rotatePoints, isSelectionMoving, getSelectedElements, distanceBetweenPointAndPoint, Point, Direction, hotkeys, PlaitElement, createDebugGenerator, idCreator, Transforms, createForeignObject, updateForeignObject, getHighestSelectedElements, getRectangleByElements, MERGING, PlaitPointerType, isMainPointer, toViewBoxPoint, toHostPoint, PRESS_AND_MOVE_BUFFER, isDragging, throttleRAF, getRectangleByGroup, ElementFlavour, isSelectedElementOrGroup, Selection, isMovingElements, getHitElementsBySelection, createGroupRectangleG, getSelectedGroups, getHighestSelectedGroups, getSelectedIsolatedElements, getSelectedIsolatedElementsCanAddToGroup, getGroupByElement, IS_WINDOWS, updateForeignObjectWidth, IS_TEXT_EDITABLE } from '@plait/core';
2
2
  import { isKeyHotkey } from 'is-hotkey';
3
3
  import { Node, Operation, Transforms as Transforms$1, Range, Editor } from 'slate';
4
4
  import { fromEvent, timer } from 'rxjs';
@@ -65,18 +65,24 @@ class Generator {
65
65
  }
66
66
  }
67
67
  this.g = g;
68
- const rect = this.board.getRectangle(element);
69
- if (rect) {
70
- let angle;
71
- if (PlaitGroupElement.isGroup(element)) {
72
- angle = getSelectionAngle(getElementsInGroup(this.board, element, true));
73
- }
74
- else {
75
- angle = element.angle;
76
- }
77
- if (angle) {
78
- setAngleForG(g, RectangleClient.getCenterPoint(rect), angle);
79
- }
68
+ const rectangle = this.board.getRectangle(element);
69
+ if (!rectangle) {
70
+ return;
71
+ }
72
+ let centerPoint = RectangleClient.getCenterPoint(rectangle);
73
+ if (this.options?.active) {
74
+ const activeRectangle = toActiveRectangleFromViewBoxRectangle(this.board, rectangle);
75
+ centerPoint = RectangleClient.getCenterPoint(activeRectangle);
76
+ }
77
+ let angle;
78
+ if (PlaitGroupElement.isGroup(element)) {
79
+ angle = getSelectionAngle(getElementsInGroup(this.board, element, true));
80
+ }
81
+ else {
82
+ angle = element.angle;
83
+ }
84
+ if (angle) {
85
+ setAngleForG(g, centerPoint, angle);
80
86
  }
81
87
  }
82
88
  else {
@@ -147,10 +153,13 @@ const drawRotateHandle = (board, rectangle) => {
147
153
  return handleG;
148
154
  };
149
155
 
156
+ const createActiveGenerator = (board, options) => {
157
+ return new ActiveGenerator(board, { ...options, active: true });
158
+ };
150
159
  class ActiveGenerator extends Generator {
151
160
  static { this.key = 'active-generator'; }
152
161
  constructor(board, options) {
153
- super(board, options);
162
+ super(board, { ...options, active: true });
154
163
  this.board = board;
155
164
  this.options = options;
156
165
  this.hasResizeHandle = false;
@@ -165,12 +174,12 @@ class ActiveGenerator extends Generator {
165
174
  }
166
175
  draw(element, data) {
167
176
  const activeG = createG();
168
- const rectangle = this.options.getRectangle(element);
169
- const delta = this.options.getStrokeWidth();
170
- const activeRectangle = RectangleClient.inflate(rectangle, delta);
171
- const strokeG = drawRectangle(this.board, activeRectangle, {
177
+ const activeRectangle = toActiveRectangleFromViewBoxRectangle(this.board, this.options.getRectangle(element));
178
+ const delta = this.options.getStrokeWidth() * this.board.viewport.zoom;
179
+ const activeRectangleWithDelta = RectangleClient.inflate(activeRectangle, delta);
180
+ const strokeG = drawRectangle(this.board, activeRectangleWithDelta, {
172
181
  stroke: PRIMARY_COLOR,
173
- strokeWidth: delta
182
+ strokeWidth: ACTIVE_STROKE_WIDTH
174
183
  });
175
184
  activeG.append(strokeG);
176
185
  strokeG.classList.add(SELECTION_RECTANGLE_CLASS_NAME);
@@ -178,7 +187,7 @@ class ActiveGenerator extends Generator {
178
187
  if (this.options.hasResizeHandle()) {
179
188
  this.hasResizeHandle = true;
180
189
  // draw resize handle
181
- RectangleClient.getCornerPoints(activeRectangle).forEach(corner => {
190
+ RectangleClient.getCornerPoints(activeRectangleWithDelta).forEach((corner) => {
182
191
  const cornerHandleG = drawHandle(this.board, corner);
183
192
  activeG.append(cornerHandleG);
184
193
  });
@@ -1362,7 +1371,7 @@ class ImageGenerator extends Generator {
1362
1371
  }
1363
1372
  };
1364
1373
  this.imageComponentRef = this.board.renderImage(this.foreignObject, props);
1365
- this.activeGenerator = new ActiveGenerator(this.board, {
1374
+ this.activeGenerator = createActiveGenerator(this.board, {
1366
1375
  getStrokeWidth: () => {
1367
1376
  const selectedElements = getSelectedElements(this.board);
1368
1377
  if (!(selectedElements.length === 1 && !isSelectionMoving(this.board))) {
@@ -1409,12 +1418,12 @@ class ImageGenerator extends Generator {
1409
1418
  if (currentForeignObject && current.angle) {
1410
1419
  setAngleForG(this.g, RectangleClient.getCenterPoint(currentForeignObject), current.angle);
1411
1420
  }
1412
- const activeG = PlaitBoard.getElementActiveHost(this.board);
1421
+ const activeG = PlaitBoard.getActiveHost(this.board);
1413
1422
  this.activeGenerator.processDrawing(current, activeG, { selected: this.isFocus });
1414
1423
  }
1415
1424
  setFocus(element, isFocus) {
1416
1425
  this.isFocus = isFocus;
1417
- const activeG = PlaitBoard.getElementActiveHost(this.board);
1426
+ const activeG = PlaitBoard.getActiveHost(this.board);
1418
1427
  this.activeGenerator.processDrawing(element, activeG, { selected: isFocus });
1419
1428
  const props = {
1420
1429
  isFocus
@@ -1727,6 +1736,7 @@ class PlaitCommonElementRef {
1727
1736
  constructor() {
1728
1737
  this.textManages = [];
1729
1738
  this.generatorMap = new Map();
1739
+ this.updateActiveSection = () => { };
1730
1740
  }
1731
1741
  addGenerator(key, generator) {
1732
1742
  this.generatorMap.set(key, generator);
@@ -1747,7 +1757,7 @@ class PlaitCommonElementRef {
1747
1757
  return this.textManages;
1748
1758
  }
1749
1759
  destroyTextManage() {
1750
- this.textManages.forEach(textManage => {
1760
+ this.textManages.forEach((textManage) => {
1751
1761
  textManage.destroy();
1752
1762
  });
1753
1763
  this.textManages = [];
@@ -1765,7 +1775,7 @@ class GroupComponent extends CommonElementFlavour {
1765
1775
  super();
1766
1776
  }
1767
1777
  initializeGenerator() {
1768
- this.activeGenerator = new ActiveGenerator(this.board, {
1778
+ this.activeGenerator = createActiveGenerator(this.board, {
1769
1779
  getRectangle: (element) => {
1770
1780
  return getRectangleByGroup(this.board, element);
1771
1781
  },
@@ -1818,7 +1828,7 @@ function withGroup(board) {
1818
1828
  const hitElements = getHitElementsBySelection(board, selection);
1819
1829
  if (hitElements.length) {
1820
1830
  groupRectangleG = createGroupRectangleG(board, hitElements);
1821
- groupRectangleG && PlaitBoard.getElementActiveHost(board).append(groupRectangleG);
1831
+ groupRectangleG && PlaitBoard.getElementTopHost(board).append(groupRectangleG);
1822
1832
  }
1823
1833
  }
1824
1834
  });
@@ -1839,13 +1849,13 @@ function withGroup(board) {
1839
1849
  elements = new Array(clipboardData?.elements?.length);
1840
1850
  const groups = getHighestSelectedGroups(board, clipboardData?.elements);
1841
1851
  const selectedIsolatedElements = getSelectedIsolatedElements(board, clipboardData?.elements);
1842
- selectedIsolatedElements.forEach(item => {
1843
- const index = clipboardData.elements.map(element => element.id).indexOf(item.id);
1852
+ selectedIsolatedElements.forEach((item) => {
1853
+ const index = clipboardData.elements.map((element) => element.id).indexOf(item.id);
1844
1854
  elements.splice(index, 1, !item.groupId ? item : updateGroupId(item, undefined));
1845
1855
  });
1846
1856
  if (groups.length) {
1847
- groups.forEach(item => {
1848
- const index = clipboardData.elements.map(element => element.id).indexOf(item.id);
1857
+ groups.forEach((item) => {
1858
+ const index = clipboardData.elements.map((element) => element.id).indexOf(item.id);
1849
1859
  const newGroup = { ...updateGroupId(item, undefined), id: idCreator() };
1850
1860
  elements.splice(index, 1, newGroup);
1851
1861
  updateElementsGroupId(item, clipboardData.elements, newGroup.id, elements);
@@ -1854,8 +1864,8 @@ function withGroup(board) {
1854
1864
  clipboardData.elements = elements;
1855
1865
  }
1856
1866
  insertFragment(clipboardData, targetPoint, operationType);
1857
- const groupElements = elements?.filter(value => PlaitGroupElement.isGroup(value));
1858
- groupElements.forEach(element => {
1867
+ const groupElements = elements?.filter((value) => PlaitGroupElement.isGroup(value));
1868
+ groupElements.forEach((element) => {
1859
1869
  Transforms.insertNode(board, element, [board.children.length]);
1860
1870
  });
1861
1871
  };
@@ -1903,10 +1913,10 @@ const updateGroupId = (element, groupId) => {
1903
1913
  };
1904
1914
  };
1905
1915
  const updateElementsGroupId = (group, clipboardDataElements, newGroupId, elements) => {
1906
- const elementsInGroup = clipboardDataElements.filter(item => item.groupId === group.id);
1916
+ const elementsInGroup = clipboardDataElements.filter((item) => item.groupId === group.id);
1907
1917
  if (elementsInGroup.length) {
1908
- elementsInGroup.forEach(item => {
1909
- const index = clipboardDataElements.map(item => item.id).indexOf(item.id);
1918
+ elementsInGroup.forEach((item) => {
1919
+ const index = clipboardDataElements.map((item) => item.id).indexOf(item.id);
1910
1920
  if (PlaitGroupElement.isGroup(item)) {
1911
1921
  const newGroup = { ...updateGroupId(item, newGroupId), id: idCreator() };
1912
1922
  elements.splice(index, 1, newGroup);
@@ -1925,11 +1935,11 @@ const getRemoveGroups = (board) => {
1925
1935
  const highestSelectedGroups = getHighestSelectedGroups(board);
1926
1936
  const selectedIsolatedElements = getSelectedIsolatedElementsCanAddToGroup(board);
1927
1937
  const removeNodes = [...highestSelectedGroups, ...selectedIsolatedElements];
1928
- removeNodes.forEach(item => {
1938
+ removeNodes.forEach((item) => {
1929
1939
  const hitElementGroups = getGroupByElement(board, item, true);
1930
1940
  if (hitElementGroups.length) {
1931
1941
  const elementsInGroup = getElementsInGroup(board, hitElementGroups[0], false, true);
1932
- const siblingElements = elementsInGroup.filter(element => ![...removeNodes, ...removeGroups].map(item => item.id).includes(element.id));
1942
+ const siblingElements = elementsInGroup.filter((element) => ![...removeNodes, ...removeGroups].map((item) => item.id).includes(element.id));
1933
1943
  if (siblingElements.length === 1 || siblingElements.length === 0) {
1934
1944
  if (!removeGroups.includes(hitElementGroups[0])) {
1935
1945
  removeGroups.push(hitElementGroups[0]);
@@ -1942,9 +1952,9 @@ const getRemoveGroups = (board) => {
1942
1952
  ]);
1943
1953
  let index = hitElementGroups.length;
1944
1954
  if (aboveGroup) {
1945
- index = hitElementGroups.findIndex(item => item.id === aboveGroup.id);
1955
+ index = hitElementGroups.findIndex((item) => item.id === aboveGroup.id);
1946
1956
  }
1947
- [...hitElementGroups.slice(1, index)].forEach(item => {
1957
+ [...hitElementGroups.slice(1, index)].forEach((item) => {
1948
1958
  if (!removeGroups.includes(item)) {
1949
1959
  removeGroups.push(item);
1950
1960
  }
@@ -1960,7 +1970,7 @@ const findAboveGroupWithAnotherElement = (board, groups, excludeNodes) => {
1960
1970
  let group = null;
1961
1971
  for (let i = 0; i < groups.length; i++) {
1962
1972
  const elementsInGroup = getElementsInGroup(board, groups[i], false, true);
1963
- const siblingElements = elementsInGroup.filter(element => !excludeNodes.map(item => item.id).includes(element.id));
1973
+ const siblingElements = elementsInGroup.filter((element) => !excludeNodes.map((item) => item.id).includes(element.id));
1964
1974
  if (siblingElements.length > 0) {
1965
1975
  group = groups[i];
1966
1976
  break;
@@ -1971,16 +1981,16 @@ const findAboveGroupWithAnotherElement = (board, groups, excludeNodes) => {
1971
1981
  const updateSiblingElementGroupId = (board, removeGroups) => {
1972
1982
  const selectedIsolatedElements = getSelectedIsolatedElementsCanAddToGroup(board);
1973
1983
  const highestSelectedGroups = getHighestSelectedGroups(board);
1974
- const isolatedElementsInGroup = selectedIsolatedElements.filter(item => item.groupId);
1975
- [...highestSelectedGroups, ...isolatedElementsInGroup].forEach(item => {
1984
+ const isolatedElementsInGroup = selectedIsolatedElements.filter((item) => item.groupId);
1985
+ [...highestSelectedGroups, ...isolatedElementsInGroup].forEach((item) => {
1976
1986
  const hitElementGroups = getGroupByElement(board, item, true);
1977
1987
  if (hitElementGroups.length) {
1978
1988
  const elementsInGroup = getElementsInGroup(board, hitElementGroups[0], false, true);
1979
- const siblingElements = elementsInGroup.filter(element => element.id !== item.id);
1989
+ const siblingElements = elementsInGroup.filter((element) => element.id !== item.id);
1980
1990
  if (siblingElements.length === 1) {
1981
- const removeGroupIds = removeGroups.map(item => item.id);
1982
- if (hitElementGroups.some(group => removeGroupIds.includes(group.id))) {
1983
- const group = hitElementGroups.find(group => !removeGroupIds.includes(group.id));
1991
+ const removeGroupIds = removeGroups.map((item) => item.id);
1992
+ if (hitElementGroups.some((group) => removeGroupIds.includes(group.id))) {
1993
+ const group = hitElementGroups.find((group) => !removeGroupIds.includes(group.id));
1984
1994
  const path = PlaitBoard.findPath(board, siblingElements[0]);
1985
1995
  Transforms.setNode(board, { groupId: group?.id || undefined }, path);
1986
1996
  }
@@ -2028,8 +2038,35 @@ function measureElement(element, options, containerMaxWidth = 10000) {
2028
2038
  lineTexts.forEach((text, index) => {
2029
2039
  const font = getFont(text, { fontFamily: options.fontFamily, fontSize: options.fontSize });
2030
2040
  ctx.font = font;
2031
- const textMetrics = ctx.measureText(text.text);
2032
- lineWidth += textMetrics.width;
2041
+ // Windows 平台下的特殊处理
2042
+ if (IS_WINDOWS) {
2043
+ let adjustedWidth = 0;
2044
+ // 逐字符处理
2045
+ for (let i = 0; i < text.text.length; i++) {
2046
+ const char = text.text[i];
2047
+ const charMetrics = ctx.measureText(char);
2048
+ // 判断是否为汉字(通过 Unicode 范围)
2049
+ if (/[\u4e00-\u9fa5]/.test(char)) {
2050
+ adjustedWidth += charMetrics.width;
2051
+ }
2052
+ else {
2053
+ // 非汉字字符的宽度调整
2054
+ if (/[a-zA-Z]/.test(char)) {
2055
+ adjustedWidth += charMetrics.width + 1.5; // 字母
2056
+ }
2057
+ else if (/[0-9]/.test(char)) {
2058
+ adjustedWidth += charMetrics.width + 1.5; // 数字
2059
+ }
2060
+ else {
2061
+ adjustedWidth += charMetrics.width + 0.8; // 其他符号
2062
+ }
2063
+ }
2064
+ }
2065
+ lineWidth += adjustedWidth;
2066
+ }
2067
+ else {
2068
+ lineWidth += ctx.measureText(text.text).width;
2069
+ }
2033
2070
  const isLast = index === lineTexts.length - 1;
2034
2071
  // skip when text is empty and is not last text of line
2035
2072
  if (text['font-size'] && (isLast || text.text !== '')) {
@@ -2231,5 +2268,5 @@ const withImage = (board) => {
2231
2268
  * Generated bundle index. Do not edit.
2232
2269
  */
2233
2270
 
2234
- export { AStar, ActiveGenerator, AlignTransform, Alignment, BASE, BoardCreationMode, CommonElementFlavour, DEFAULT_FILL, DEFAULT_FONT_FAMILY, DEFAULT_ROUTE_MARGIN, FOREIGN_OBJECT_IMAGE_CLASS_NAME, Generator, GroupComponent, IS_RESIZING, IS_ROTATING, ImageBaseComponent, ImageGenerator, MediaKeys, PICTURE_ACCEPTED_UPLOAD_SIZE, PRIMARY_COLOR, PlaitCommonElementRef, PointGraph, PointNode, PriorityQueue, PropertyTransforms, RESIZE_HANDLE_DIAMETER, ROTATE_HANDLE_DISTANCE_TO_ELEMENT, ROTATE_HANDLE_SIZE, ResizeHandle, StrokeStyle, TRANSPARENT, TextManage, WithCommonPluginKey, WithTextPluginKey, acceptImageTypes, addElementOfFocusedImage, addResizing, addRotating, alignBottom, alignHorizontalCenter, alignLeft, alignRight, alignTop, alignVerticalCenter, animate, buildClipboardData, buildCompositionData, buildImage, buildText, calculatePolylineLength, createGraph, distributeHorizontal, distributeVertical, drawFillPrimaryHandle, drawHandle, drawPrimaryHandle, drawRotateHandle, findFirstTextEditor, generateElbowLineRoute, getCreationMode, getCrossingPointsBetweenPointAndSegment, getDirectionBetweenPointAndPoint, getDirectionByPointOfRectangle, getDirectionByVector, getDirectionFactor, getDirectionFactorByDirectionComponent, getEditingTextEditor, getElementArea, getElementOfFocusedImage, getElementsText, getExtendPoint, getFirstTextEditor, getFirstTextManage, getGraphPoints, getIndexByResizeHandle, getLineHeightByFontSize, getMemorizedLatest, getNextPoint, getOppositeDirection, getPointByVectorComponent, getPointByVectorDirectionComponent, getPointOnPolyline, getPoints, getRatioByPoint, getRectangleResizeHandleRefs, getResizeHandleByIndex, getResizeHandlePointByIndex, getRotatedResizeCursorClassByAngle, getSourceAndTargetOuterRectangle, getStrokeLineDash, getSymmetricHandleIndex, getTextEditors, getTextEditorsByElement, getTextManages, getTimestamp, getUnitVectorByPointAndPoint, hasAfterDraw, hasMoreThanOnePoint, hasResizeHandle, insertClipboardData, isCornerHandle, isDelete, isDndMode, isDrawingMode, isEdgeHandle, isEnterHotkey, isExpandHotkey, isFilled, isPointOnSegment, isResizing, isResizingByCondition, isRotating, isSourceAndTargetIntersect, isSpaceHotkey, isTabHotkey, isVirtualKey, linear, measureElement, memorizeLatest, normalizeShapePoints, reduceRouteMargin, removeDuplicatePoints, removeElementOfFocusedImage, removeResizing, removeRotating, resetPointsAfterResize, rotateVector, rotateVectorAnti90, routeAdjust, selectImage, setCreationMode, setProperty, simplifyOrthogonalPoints, sortElementsByArea, withGroup, withImage, withResize, withText };
2271
+ export { AStar, ActiveGenerator, AlignTransform, Alignment, BASE, BoardCreationMode, CommonElementFlavour, DEFAULT_FILL, DEFAULT_FONT_FAMILY, DEFAULT_ROUTE_MARGIN, FOREIGN_OBJECT_IMAGE_CLASS_NAME, Generator, GroupComponent, IS_RESIZING, IS_ROTATING, ImageBaseComponent, ImageGenerator, MediaKeys, PICTURE_ACCEPTED_UPLOAD_SIZE, PRIMARY_COLOR, PlaitCommonElementRef, PointGraph, PointNode, PriorityQueue, PropertyTransforms, RESIZE_HANDLE_DIAMETER, ROTATE_HANDLE_DISTANCE_TO_ELEMENT, ROTATE_HANDLE_SIZE, ResizeHandle, StrokeStyle, TRANSPARENT, TextManage, WithCommonPluginKey, WithTextPluginKey, acceptImageTypes, addElementOfFocusedImage, addResizing, addRotating, alignBottom, alignHorizontalCenter, alignLeft, alignRight, alignTop, alignVerticalCenter, animate, buildClipboardData, buildCompositionData, buildImage, buildText, calculatePolylineLength, createActiveGenerator, createGraph, distributeHorizontal, distributeVertical, drawFillPrimaryHandle, drawHandle, drawPrimaryHandle, drawRotateHandle, findFirstTextEditor, generateElbowLineRoute, getCreationMode, getCrossingPointsBetweenPointAndSegment, getDirectionBetweenPointAndPoint, getDirectionByPointOfRectangle, getDirectionByVector, getDirectionFactor, getDirectionFactorByDirectionComponent, getEditingTextEditor, getElementArea, getElementOfFocusedImage, getElementsText, getExtendPoint, getFirstTextEditor, getFirstTextManage, getGraphPoints, getIndexByResizeHandle, getLineHeightByFontSize, getMemorizedLatest, getNextPoint, getOppositeDirection, getPointByVectorComponent, getPointByVectorDirectionComponent, getPointOnPolyline, getPoints, getRatioByPoint, getRectangleResizeHandleRefs, getResizeHandleByIndex, getResizeHandlePointByIndex, getRotatedResizeCursorClassByAngle, getSourceAndTargetOuterRectangle, getStrokeLineDash, getSymmetricHandleIndex, getTextEditors, getTextEditorsByElement, getTextManages, getTimestamp, getUnitVectorByPointAndPoint, hasAfterDraw, hasMoreThanOnePoint, hasResizeHandle, insertClipboardData, isCornerHandle, isDelete, isDndMode, isDrawingMode, isEdgeHandle, isEnterHotkey, isExpandHotkey, isFilled, isPointOnSegment, isResizing, isResizingByCondition, isRotating, isSourceAndTargetIntersect, isSpaceHotkey, isTabHotkey, isVirtualKey, linear, measureElement, memorizeLatest, normalizeShapePoints, reduceRouteMargin, removeDuplicatePoints, removeElementOfFocusedImage, removeResizing, removeRotating, resetPointsAfterResize, rotateVector, rotateVectorAnti90, routeAdjust, selectImage, setCreationMode, setProperty, simplifyOrthogonalPoints, sortElementsByArea, withGroup, withImage, withResize, withText };
2235
2272
  //# sourceMappingURL=plait-common.mjs.map