@visactor/vrender-core 0.22.0-vstory.2 → 0.22.0-vstory.5

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.
@@ -77,6 +77,8 @@ class Line {
77
77
  }
78
78
  }
79
79
  this.paragraphs.forEach(((paragraph, index) => {
80
+ paragraph instanceof icon_1.RichTextIcon || paragraph.drawBackground(ctx, y, this.ascent, x, 0 === index, this.textAlign, this.height);
81
+ })), this.paragraphs.forEach(((paragraph, index) => {
80
82
  if (paragraph instanceof icon_1.RichTextIcon) return paragraph.setAttributes({
81
83
  x: x + paragraph._x,
82
84
  y: y + paragraph._y
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/graphic/richtext/line.ts"],"names":[],"mappings":"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","file":"line.js","sourcesContent":["// import { IContext2d } from '../../IContext';\nimport type { IContext2d, IRichTextIcon } from '../../interface';\nimport { RichTextIcon } from './icon';\nimport Paragraph from './paragraph';\nimport { applyFillStyle, applyStrokeStyle, DIRECTION_KEY, measureTextCanvas, regFirstSpace } from './utils';\n\n/**\n * 部分代码参考 https://github.com/danielearwicker/carota/\n * The MIT License (MIT)\n\n \"Carota\" - Copyright (c) 2013 Daniel Earwicker\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n */\n\n// 行\n// 参考carota\n// https://github.com/danielearwicker/carota/blob/master/src/line.js\nexport default class Line {\n left: number;\n top: number;\n width: number;\n height: number;\n baseline: number;\n ascent: number;\n descent: number;\n paragraphs: (Paragraph | RichTextIcon)[];\n actualWidth: number;\n blankWidth: number;\n textAlign: string;\n direction: 'horizontal' | 'vertical';\n directionKey: { width: string; height: string; left: string; x: string; y: string };\n\n constructor(\n left: number,\n width: number,\n baseline: number,\n ascent: number,\n descent: number,\n lineBuffer: (Paragraph | RichTextIcon)[],\n direction: 'horizontal' | 'vertical',\n isWidthMax: boolean\n ) {\n this.left = left;\n this.width = width;\n this.baseline = baseline;\n this.ascent = ascent;\n this.descent = descent;\n // this.height = ascent + descent;\n this.top = baseline - ascent;\n this.paragraphs = lineBuffer.map(p => p);\n this.textAlign =\n (this.paragraphs[0] instanceof RichTextIcon\n ? this.paragraphs[0].attribute.textAlign\n : this.paragraphs[0].character.textAlign) || 'left'; // 对齐方式选择第一个paragraph属性\n this.direction = direction;\n this.directionKey = DIRECTION_KEY[this.direction];\n\n this.actualWidth = 0;\n let maxHeight = 0;\n this.paragraphs.forEach((word, index) => {\n // 每行中第一个字符不能是空格\n if (index === 0 && word instanceof Paragraph) {\n const result = regFirstSpace.exec(word.text);\n if (result?.index !== 0) {\n word.text = word.text.slice(result?.index);\n word.updateWidth();\n }\n }\n this.actualWidth += word[this.directionKey.width];\n maxHeight = Math.max(word[this.directionKey.height], maxHeight);\n });\n this.height = maxHeight;\n\n this.blankWidth = !isWidthMax ? this.width - this.actualWidth : 0;\n\n this.calcOffset(width, isWidthMax);\n }\n\n calcOffset(width: number, isWidthMax: boolean) {\n // 处理对齐方式,计算左侧偏移距离和字符之间间距\n const directionKey = this.directionKey;\n const maxHeight = this.height;\n let x = this.left;\n let spacing = 0;\n if (this.actualWidth < width && !isWidthMax) {\n if (this.textAlign === 'right' || this.textAlign === 'end') {\n x = width - this.actualWidth;\n } else if (this.textAlign === 'center') {\n x = (width - this.actualWidth) / 2;\n } else if (this.textAlign === 'justify') {\n if (this.paragraphs.length < 2) {\n // 只有一个paragraph两端对齐居中显示\n x = (width - this.actualWidth) / 2;\n } else {\n spacing = (width - this.actualWidth) / (this.paragraphs.length - 1);\n }\n }\n }\n\n this.paragraphs.map(function (paragraph) {\n if (paragraph instanceof RichTextIcon) {\n // paragraph.setAttribute(directionKey.x, x);\n paragraph['_' + directionKey.x] = x;\n x += paragraph[directionKey.width] + spacing;\n // 处理纵向对齐\n paragraph['_' + directionKey.y] =\n paragraph.attribute.textBaseline === 'top'\n ? 0\n : paragraph.attribute.textBaseline === 'bottom'\n ? maxHeight - paragraph.height\n : (maxHeight - paragraph.height) / 2;\n } else {\n paragraph[directionKey.left] = x;\n x += paragraph[directionKey.width] + spacing;\n }\n });\n }\n\n draw(\n ctx: IContext2d,\n lastLine: boolean,\n x: number,\n y: number,\n drawEllipsis: boolean | string,\n drawIcon: (icon: IRichTextIcon, context: IContext2d, x: number, y: number, baseline: number) => void\n ) {\n if (drawEllipsis && (lastLine || this.paragraphs.some(p => (p as Paragraph).overflow))) {\n // 检测是否需要省略号,因为会有多行同时省略的情况\n let emptyOverflow = true;\n let skipEllipsis = false;\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if ((paragraph as Paragraph).overflow) {\n emptyOverflow = emptyOverflow && (paragraph as Paragraph).text === '';\n } else {\n if (emptyOverflow) {\n skipEllipsis = true;\n break;\n }\n }\n }\n\n // 处理省略号\n let otherParagraphWidth = 0;\n if (!skipEllipsis) {\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if ((paragraph as Paragraph).overflow) {\n if ((paragraph as Paragraph).text === '') {\n break;\n }\n continue;\n }\n if (paragraph instanceof RichTextIcon) {\n break; // todo: 处理最后为图标,显示省略号的情况\n }\n if (this.direction === 'vertical' && paragraph.direction !== 'vertical') {\n paragraph.verticalEllipsis = true;\n break;\n }\n const ellipsis = drawEllipsis === true ? '...' : drawEllipsis || '';\n paragraph.ellipsisStr = ellipsis;\n // const { width } = measureText('...', paragraph.style);\n const { width } = measureTextCanvas(ellipsis, paragraph.character);\n const ellipsisWidth = width || 0;\n if (ellipsisWidth <= this.blankWidth + otherParagraphWidth) {\n // 省略号可以直接接在后面paragraph\n lastLine && (paragraph.ellipsis = 'add');\n\n break;\n } else if (ellipsisWidth <= this.blankWidth + otherParagraphWidth + paragraph.width) {\n // 省略号需要替换paragraph中的字符\n paragraph.ellipsis = 'replace';\n paragraph.ellipsisWidth = ellipsisWidth;\n paragraph.ellipsisOtherParagraphWidth = this.blankWidth + otherParagraphWidth;\n\n break;\n } else {\n // 省略号需要的width大于paragraph的width,隐藏paragraph,向前搜索\n paragraph.ellipsis = 'hide';\n otherParagraphWidth += paragraph.width;\n }\n }\n }\n }\n\n // 正常绘制\n this.paragraphs.forEach((paragraph, index) => {\n if (paragraph instanceof RichTextIcon) {\n // 更新icon位置\n paragraph.setAttributes({\n x: x + paragraph._x,\n y: y + paragraph._y\n });\n\n // 绘制icon\n drawIcon(paragraph, ctx, x + paragraph._x, y + paragraph._y, this.ascent);\n return;\n }\n const b = {\n x1: this.left,\n y1: this.top,\n x2: this.left + this.actualWidth,\n y2: this.top + this.height\n };\n applyStrokeStyle(ctx, paragraph.character);\n // 下面绘制underline和line-through时需要设置FillStyle\n applyFillStyle(ctx, paragraph.character, b);\n paragraph.draw(ctx, y, this.ascent, x, index === 0, this.textAlign, this.height);\n });\n }\n\n getWidthWithEllips(ellipsis: string) {\n // 处理省略号\n let otherParagraphWidth = 0;\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if (paragraph instanceof RichTextIcon) {\n break; // todo: 处理最后为图标,显示省略号的情况\n }\n\n const { width } = measureTextCanvas(ellipsis, paragraph.character);\n const ellipsisWidth = width || 0;\n if (ellipsisWidth <= this.blankWidth + otherParagraphWidth) {\n // 省略号可以直接接在后面paragraph\n paragraph.ellipsis = 'add';\n paragraph.ellipsisWidth = ellipsisWidth;\n break;\n } else if (ellipsisWidth <= this.blankWidth + otherParagraphWidth + paragraph.width) {\n // 省略号需要替换paragraph中的字符\n paragraph.ellipsis = 'replace';\n paragraph.ellipsisWidth = ellipsisWidth;\n paragraph.ellipsisOtherParagraphWidth = this.blankWidth + otherParagraphWidth;\n\n break;\n } else {\n // 省略号需要的width大于paragraph的width,隐藏paragraph,向前搜索\n paragraph.ellipsis = 'hide';\n otherParagraphWidth += paragraph.width;\n }\n }\n\n let width = 0;\n // 正常绘制\n this.paragraphs.forEach((paragraph, index) => {\n if (paragraph instanceof RichTextIcon) {\n width += paragraph.width; // todo: 处理direction\n } else {\n width += paragraph.getWidthWithEllips(this.direction);\n }\n });\n\n return width;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/graphic/richtext/line.ts"],"names":[],"mappings":"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","file":"line.js","sourcesContent":["// import { IContext2d } from '../../IContext';\nimport type { IContext2d, IRichTextIcon } from '../../interface';\nimport { RichTextIcon } from './icon';\nimport Paragraph from './paragraph';\nimport { applyFillStyle, applyStrokeStyle, DIRECTION_KEY, measureTextCanvas, regFirstSpace } from './utils';\n\n/**\n * 部分代码参考 https://github.com/danielearwicker/carota/\n * The MIT License (MIT)\n\n \"Carota\" - Copyright (c) 2013 Daniel Earwicker\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n */\n\n// 行\n// 参考carota\n// https://github.com/danielearwicker/carota/blob/master/src/line.js\nexport default class Line {\n left: number;\n top: number;\n width: number;\n height: number;\n baseline: number;\n ascent: number;\n descent: number;\n paragraphs: (Paragraph | RichTextIcon)[];\n actualWidth: number;\n blankWidth: number;\n textAlign: string;\n direction: 'horizontal' | 'vertical';\n directionKey: { width: string; height: string; left: string; x: string; y: string };\n\n constructor(\n left: number,\n width: number,\n baseline: number,\n ascent: number,\n descent: number,\n lineBuffer: (Paragraph | RichTextIcon)[],\n direction: 'horizontal' | 'vertical',\n isWidthMax: boolean\n ) {\n this.left = left;\n this.width = width;\n this.baseline = baseline;\n this.ascent = ascent;\n this.descent = descent;\n // this.height = ascent + descent;\n this.top = baseline - ascent;\n this.paragraphs = lineBuffer.map(p => p);\n this.textAlign =\n (this.paragraphs[0] instanceof RichTextIcon\n ? this.paragraphs[0].attribute.textAlign\n : this.paragraphs[0].character.textAlign) || 'left'; // 对齐方式选择第一个paragraph属性\n this.direction = direction;\n this.directionKey = DIRECTION_KEY[this.direction];\n\n this.actualWidth = 0;\n let maxHeight = 0;\n this.paragraphs.forEach((word, index) => {\n // 每行中第一个字符不能是空格\n if (index === 0 && word instanceof Paragraph) {\n const result = regFirstSpace.exec(word.text);\n if (result?.index !== 0) {\n word.text = word.text.slice(result?.index);\n word.updateWidth();\n }\n }\n this.actualWidth += word[this.directionKey.width];\n maxHeight = Math.max(word[this.directionKey.height], maxHeight);\n });\n this.height = maxHeight;\n\n this.blankWidth = !isWidthMax ? this.width - this.actualWidth : 0;\n\n this.calcOffset(width, isWidthMax);\n }\n\n calcOffset(width: number, isWidthMax: boolean) {\n // 处理对齐方式,计算左侧偏移距离和字符之间间距\n const directionKey = this.directionKey;\n const maxHeight = this.height;\n let x = this.left;\n let spacing = 0;\n if (this.actualWidth < width && !isWidthMax) {\n if (this.textAlign === 'right' || this.textAlign === 'end') {\n x = width - this.actualWidth;\n } else if (this.textAlign === 'center') {\n x = (width - this.actualWidth) / 2;\n } else if (this.textAlign === 'justify') {\n if (this.paragraphs.length < 2) {\n // 只有一个paragraph两端对齐居中显示\n x = (width - this.actualWidth) / 2;\n } else {\n spacing = (width - this.actualWidth) / (this.paragraphs.length - 1);\n }\n }\n }\n\n this.paragraphs.map(function (paragraph) {\n if (paragraph instanceof RichTextIcon) {\n // paragraph.setAttribute(directionKey.x, x);\n paragraph['_' + directionKey.x] = x;\n x += paragraph[directionKey.width] + spacing;\n // 处理纵向对齐\n paragraph['_' + directionKey.y] =\n paragraph.attribute.textBaseline === 'top'\n ? 0\n : paragraph.attribute.textBaseline === 'bottom'\n ? maxHeight - paragraph.height\n : (maxHeight - paragraph.height) / 2;\n } else {\n paragraph[directionKey.left] = x;\n x += paragraph[directionKey.width] + spacing;\n }\n });\n }\n\n draw(\n ctx: IContext2d,\n lastLine: boolean,\n x: number,\n y: number,\n drawEllipsis: boolean | string,\n drawIcon: (icon: IRichTextIcon, context: IContext2d, x: number, y: number, baseline: number) => void\n ) {\n if (drawEllipsis && (lastLine || this.paragraphs.some(p => (p as Paragraph).overflow))) {\n // 检测是否需要省略号,因为会有多行同时省略的情况\n let emptyOverflow = true;\n let skipEllipsis = false;\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if ((paragraph as Paragraph).overflow) {\n emptyOverflow = emptyOverflow && (paragraph as Paragraph).text === '';\n } else {\n if (emptyOverflow) {\n skipEllipsis = true;\n break;\n }\n }\n }\n\n // 处理省略号\n let otherParagraphWidth = 0;\n if (!skipEllipsis) {\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if ((paragraph as Paragraph).overflow) {\n if ((paragraph as Paragraph).text === '') {\n break;\n }\n continue;\n }\n if (paragraph instanceof RichTextIcon) {\n break; // todo: 处理最后为图标,显示省略号的情况\n }\n if (this.direction === 'vertical' && paragraph.direction !== 'vertical') {\n paragraph.verticalEllipsis = true;\n break;\n }\n const ellipsis = drawEllipsis === true ? '...' : drawEllipsis || '';\n paragraph.ellipsisStr = ellipsis;\n // const { width } = measureText('...', paragraph.style);\n const { width } = measureTextCanvas(ellipsis, paragraph.character);\n const ellipsisWidth = width || 0;\n if (ellipsisWidth <= this.blankWidth + otherParagraphWidth) {\n // 省略号可以直接接在后面paragraph\n lastLine && (paragraph.ellipsis = 'add');\n\n break;\n } else if (ellipsisWidth <= this.blankWidth + otherParagraphWidth + paragraph.width) {\n // 省略号需要替换paragraph中的字符\n paragraph.ellipsis = 'replace';\n paragraph.ellipsisWidth = ellipsisWidth;\n paragraph.ellipsisOtherParagraphWidth = this.blankWidth + otherParagraphWidth;\n\n break;\n } else {\n // 省略号需要的width大于paragraph的width,隐藏paragraph,向前搜索\n paragraph.ellipsis = 'hide';\n otherParagraphWidth += paragraph.width;\n }\n }\n }\n }\n\n // 绘制背景\n this.paragraphs.forEach((paragraph, index) => {\n if (paragraph instanceof RichTextIcon) {\n return;\n }\n paragraph.drawBackground(ctx, y, this.ascent, x, index === 0, this.textAlign, this.height);\n });\n // 正常绘制\n this.paragraphs.forEach((paragraph, index) => {\n if (paragraph instanceof RichTextIcon) {\n // 更新icon位置\n paragraph.setAttributes({\n x: x + paragraph._x,\n y: y + paragraph._y\n });\n\n // 绘制icon\n drawIcon(paragraph, ctx, x + paragraph._x, y + paragraph._y, this.ascent);\n return;\n }\n const b = {\n x1: this.left,\n y1: this.top,\n x2: this.left + this.actualWidth,\n y2: this.top + this.height\n };\n applyStrokeStyle(ctx, paragraph.character);\n // 下面绘制underline和line-through时需要设置FillStyle\n applyFillStyle(ctx, paragraph.character, b);\n paragraph.draw(ctx, y, this.ascent, x, index === 0, this.textAlign, this.height);\n });\n }\n\n getWidthWithEllips(ellipsis: string) {\n // 处理省略号\n let otherParagraphWidth = 0;\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if (paragraph instanceof RichTextIcon) {\n break; // todo: 处理最后为图标,显示省略号的情况\n }\n\n const { width } = measureTextCanvas(ellipsis, paragraph.character);\n const ellipsisWidth = width || 0;\n if (ellipsisWidth <= this.blankWidth + otherParagraphWidth) {\n // 省略号可以直接接在后面paragraph\n paragraph.ellipsis = 'add';\n paragraph.ellipsisWidth = ellipsisWidth;\n break;\n } else if (ellipsisWidth <= this.blankWidth + otherParagraphWidth + paragraph.width) {\n // 省略号需要替换paragraph中的字符\n paragraph.ellipsis = 'replace';\n paragraph.ellipsisWidth = ellipsisWidth;\n paragraph.ellipsisOtherParagraphWidth = this.blankWidth + otherParagraphWidth;\n\n break;\n } else {\n // 省略号需要的width大于paragraph的width,隐藏paragraph,向前搜索\n paragraph.ellipsis = 'hide';\n otherParagraphWidth += paragraph.width;\n }\n }\n\n let width = 0;\n // 正常绘制\n this.paragraphs.forEach((paragraph, index) => {\n if (paragraph instanceof RichTextIcon) {\n width += paragraph.width; // todo: 处理direction\n } else {\n width += paragraph.getWidthWithEllips(this.direction);\n }\n });\n\n return width;\n }\n}\n"]}
@@ -24,6 +24,7 @@ export default class Paragraph {
24
24
  overflow?: boolean;
25
25
  constructor(text: string, newLine: boolean, character: IRichTextParagraphCharacter);
26
26
  updateWidth(): void;
27
+ drawBackground(ctx: IContext2d, top: number, ascent: number, deltaLeft: number, isLineFirst: boolean, textAlign: string, lineHeight: number): void;
27
28
  draw(ctx: IContext2d, top: number, ascent: number, deltaLeft: number, isLineFirst: boolean, textAlign: string, lineHeight: number): void;
28
29
  getWidthWithEllips(direction: string): number;
29
30
  }
@@ -40,7 +40,8 @@ class Paragraph {
40
40
  this.width = width, "vertical" === this.direction && (this.widthOrigin = this.width,
41
41
  this.width = this.heightOrigin, this.height = this.widthOrigin);
42
42
  }
43
- draw(ctx, top, ascent, deltaLeft, isLineFirst, textAlign, lineHeight) {
43
+ drawBackground(ctx, top, ascent, deltaLeft, isLineFirst, textAlign, lineHeight) {
44
+ if (!this.character.background || this.character.backgroundOpacity && !(this.character.backgroundOpacity > 0)) return;
44
45
  let baseline = top + ascent, text = this.text, left = this.left + deltaLeft;
45
46
  baseline += this.top;
46
47
  let direction = this.direction;
@@ -62,15 +63,40 @@ class Paragraph {
62
63
  case "sub":
63
64
  baseline += this.descent / 2;
64
65
  }
65
- if ("vertical" === direction && (ctx.save(), ctx.rotateAbout(Math.PI / 2, left, baseline),
66
+ "vertical" === direction && (ctx.save(), ctx.rotateAbout(Math.PI / 2, left, baseline),
66
67
  ctx.translate(-this.heightOrigin || -this.lineHeight / 2, -this.descent / 2), ctx.translate(left, baseline),
67
- left = 0, baseline = 0), this.character.fill && this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0)) {
68
- const fillStyle = ctx.fillStyle, globalAlpha = ctx.globalAlpha;
69
- ctx.fillStyle = this.character.background, void 0 !== this.character.backgroundOpacity && (ctx.globalAlpha = this.character.backgroundOpacity);
70
- const lrtb = getFixedLRTB(left, left + (this.widthOrigin || this.width), top, top + lineHeight);
71
- ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top),
72
- ctx.fillStyle = fillStyle, ctx.globalAlpha = globalAlpha;
68
+ left = 0, baseline = 0);
69
+ const fillStyle = ctx.fillStyle, globalAlpha = ctx.globalAlpha;
70
+ ctx.fillStyle = this.character.background, void 0 !== this.character.backgroundOpacity && (ctx.globalAlpha = this.character.backgroundOpacity);
71
+ const lrtb = getFixedLRTB(left, left + (this.widthOrigin || this.width), top, top + lineHeight);
72
+ ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top),
73
+ ctx.fillStyle = fillStyle, ctx.globalAlpha = globalAlpha;
74
+ }
75
+ draw(ctx, top, ascent, deltaLeft, isLineFirst, textAlign, lineHeight) {
76
+ let baseline = top + ascent, text = this.text, left = this.left + deltaLeft;
77
+ baseline += this.top;
78
+ let direction = this.direction;
79
+ if (this.verticalEllipsis) text = this.ellipsisStr, direction = "vertical", baseline -= this.ellipsisWidth / 2; else {
80
+ if ("hide" === this.ellipsis) return;
81
+ if ("add" === this.ellipsis) text += this.ellipsisStr, "right" !== textAlign && "end" !== textAlign || (left -= this.ellipsisWidth); else if ("replace" === this.ellipsis) {
82
+ const index = (0, utils_2.getStrByWithCanvas)(text, ("vertical" === direction ? this.height : this.width) - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.character, text.length - 1);
83
+ if (text = text.slice(0, index), text += this.ellipsisStr, "right" === textAlign || "end" === textAlign) {
84
+ const {width: width} = (0, utils_2.measureTextCanvas)(this.text.slice(index), this.character);
85
+ "vertical" === direction || (left -= this.ellipsisWidth - width);
86
+ }
87
+ }
88
+ }
89
+ switch (this.character.script) {
90
+ case "super":
91
+ baseline -= this.ascent * (1 / 3);
92
+ break;
93
+
94
+ case "sub":
95
+ baseline += this.descent / 2;
73
96
  }
97
+ "vertical" === direction && (ctx.save(), ctx.rotateAbout(Math.PI / 2, left, baseline),
98
+ ctx.translate(-this.heightOrigin || -this.lineHeight / 2, -this.descent / 2), ctx.translate(left, baseline),
99
+ left = 0, baseline = 0);
74
100
  const {lineWidth: lineWidth = 1} = this.character;
75
101
  if (this.character.stroke && lineWidth && ctx.strokeText(text, left, baseline),
76
102
  this.character.fill && ctx.fillText(text, left, baseline), this.character.fill) if (this.character.lineThrough || this.character.underline) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/graphic/richtext/paragraph.ts"],"names":[],"mappings":"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","file":"paragraph.js","sourcesContent":["import { calculateLineHeight } from '../../common/utils';\nimport type { IContext2d, IRichTextParagraphCharacter } from '../../interface';\nimport { measureTextCanvas, getStrByWithCanvas } from './utils';\n\nfunction getFixedLRTB(left: number, right: number, top: number, bottom: number) {\n const leftInt = Math.round(left);\n const topInt = Math.round(top);\n const rightInt = Math.round(right);\n const bottomInt = Math.round(bottom);\n const _left = left > leftInt ? leftInt : leftInt - 0.5;\n const _top = top > topInt ? topInt : topInt - 0.5;\n const _right = rightInt > right ? rightInt : rightInt + 0.5;\n const _bottom = bottomInt > bottom ? bottomInt : bottomInt + 0.5;\n return {\n left: _left,\n top: _top,\n right: _right,\n bottom: _bottom\n };\n}\n\n/**\n * 部分代码参考 https://github.com/danielearwicker/carota/\n * The MIT License (MIT)\n\n \"Carota\" - Copyright (c) 2013 Daniel Earwicker\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n */\n\n// 文字段\n// 参考carota\n// https://github.com/danielearwicker/carota/blob/master/src/text.js\nexport default class Paragraph {\n text: string;\n ascent: number;\n descent: number;\n width: number;\n height: number;\n lineHeight: number;\n fontSize: number;\n length: number;\n newLine: boolean;\n character: IRichTextParagraphCharacter;\n left: number;\n top: number;\n // rotate?: number;\n direction?: 'horizontal' | 'vertical';\n // bounds?: Bounds;\n widthOrigin?: number;\n heightOrigin?: number;\n textBaseline?: CanvasTextBaseline;\n\n ellipsis: 'normal' | 'add' | 'replace' | 'hide';\n ellipsisStr: string;\n ellipsisWidth: number;\n ellipsisOtherParagraphWidth: number;\n verticalEllipsis?: boolean;\n overflow?: boolean;\n\n constructor(text: string, newLine: boolean, character: IRichTextParagraphCharacter) {\n // 测量文字\n this.fontSize = character.fontSize || 16;\n this.textBaseline = character.textBaseline || 'alphabetic';\n\n // 处理行高:\n // lineHeight为数字时,大于fontSize取lineHeight,小于fontSize时取fontSize\n // lineHeight不为数字时,统一认为lineHeight为'normal',值取1.2 * fontSize\n const lineHeight = calculateLineHeight(character.lineHeight, this.fontSize);\n if (typeof lineHeight === 'number') {\n this.lineHeight = lineHeight > this.fontSize ? lineHeight : this.fontSize;\n } else {\n this.lineHeight = Math.floor(1.2 * this.fontSize);\n }\n\n this.height = this.lineHeight;\n\n const { ascent, height, descent, width } = measureTextCanvas(text, character);\n\n let halfDetaHeight = 0;\n let deltaAscent = 0;\n let deltaDescent = 0;\n if (this.height > height) {\n // measureTextCanvas测量出的是纯文字高度,this.height是考虑行高后的高度\n // 如果this.height > height,将超过的高度平均分配到ascent和descent上\n halfDetaHeight = (this.height - height) / 2;\n deltaAscent = Math.ceil(halfDetaHeight);\n deltaDescent = Math.floor(halfDetaHeight);\n }\n\n if (this.textBaseline === 'top') {\n this.ascent = halfDetaHeight;\n this.descent = height - halfDetaHeight;\n } else if (this.textBaseline === 'bottom') {\n this.ascent = height - halfDetaHeight;\n this.descent = halfDetaHeight;\n } else if (this.textBaseline === 'middle') {\n this.ascent = this.height / 2;\n this.descent = this.height / 2;\n } else {\n this.ascent = ascent + deltaAscent;\n this.descent = descent + deltaDescent;\n }\n\n this.length = text.length;\n this.width = width || 0;\n this.text = text || '';\n this.newLine = newLine || false;\n this.character = character;\n\n this.left = 0;\n this.top = 0;\n\n this.ellipsis = 'normal';\n this.ellipsisWidth = 0;\n this.ellipsisOtherParagraphWidth = 0;\n\n // 处理旋转\n if (character.direction === 'vertical') {\n this.direction = character.direction;\n this.widthOrigin = this.width;\n this.heightOrigin = this.height;\n // const bounds = new Bounds();\n // bounds.set(0, 0, this.width, this.height);\n // bounds.rotate(Math.PI / 2, this.width / 2, this.height / 2);\n // this.bounds = bounds;\n // this.width = bounds.width();\n // this.height = bounds.height();\n this.width = this.heightOrigin;\n this.height = this.widthOrigin;\n this.lineHeight = this.height;\n }\n this.ellipsisStr = '...';\n }\n\n updateWidth() {\n const { width } = measureTextCanvas(this.text, this.character);\n this.width = width;\n if (this.direction === 'vertical') {\n this.widthOrigin = this.width;\n this.width = this.heightOrigin;\n this.height = this.widthOrigin;\n }\n }\n\n draw(\n ctx: IContext2d,\n top: number,\n ascent: number,\n deltaLeft: number,\n isLineFirst: boolean,\n textAlign: string,\n lineHeight: number\n ) {\n let baseline = top + ascent;\n let text = this.text;\n let left = this.left + deltaLeft;\n baseline += this.top;\n let direction = this.direction;\n\n if (this.verticalEllipsis) {\n text = this.ellipsisStr;\n direction = 'vertical';\n baseline -= this.ellipsisWidth / 2;\n } else if (this.ellipsis === 'hide') {\n return;\n } else if (this.ellipsis === 'add') {\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n left -= this.ellipsisWidth;\n }\n } else if (this.ellipsis === 'replace') {\n // 找到需要截断的字符长度\n // const index = getStrByWith(text, this.width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.style, text.length - 1);\n const index = getStrByWithCanvas(\n text,\n (direction === 'vertical' ? this.height : this.width) - this.ellipsisWidth + this.ellipsisOtherParagraphWidth,\n this.character,\n text.length - 1\n );\n text = text.slice(0, index);\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n const { width } = measureTextCanvas(this.text.slice(index), this.character);\n if (direction === 'vertical') {\n // baseline -= this.ellipsisWidth - width;\n } else {\n left -= this.ellipsisWidth - width;\n }\n }\n }\n\n // prepareContext(ctx);\n switch (this.character.script) {\n case 'super':\n baseline -= this.ascent * (1 / 3);\n break;\n case 'sub':\n baseline += this.descent / 2;\n break;\n }\n\n // if (isLineFirst) {\n // const result = regFirstSpace.exec(text);\n // if (result?.index !== 0) {\n // text = text.slice(result?.index);\n // }\n // }\n\n // 处理旋转\n if (direction === 'vertical') {\n ctx.save();\n ctx.rotateAbout(Math.PI / 2, left, baseline);\n ctx.translate(-(this.heightOrigin as number) || -this.lineHeight / 2, -this.descent / 2);\n ctx.translate(left, baseline);\n left = 0;\n baseline = 0;\n }\n\n if (this.character.fill) {\n if (this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0)) {\n const fillStyle = ctx.fillStyle;\n const globalAlpha = ctx.globalAlpha;\n ctx.fillStyle = this.character.background;\n if (this.character.backgroundOpacity !== void 0) {\n ctx.globalAlpha = this.character.backgroundOpacity;\n }\n // 背景稍微扩充一些buf,否则会出现白线\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + lineHeight;\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n ctx.fillStyle = fillStyle;\n ctx.globalAlpha = globalAlpha;\n }\n }\n\n const { lineWidth = 1 } = this.character;\n if (this.character.stroke && lineWidth) {\n ctx.strokeText(text, left, baseline);\n }\n\n if (this.character.fill) {\n ctx.fillText(text, left, baseline);\n }\n\n if (this.character.fill) {\n if (this.character.lineThrough || this.character.underline) {\n if (this.character.underline) {\n const top = 1 + baseline;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n if (this.character.lineThrough) {\n const top = 1 + baseline - this.ascent / 2;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n } else if (this.character.textDecoration === 'underline') {\n const top = 1 + baseline;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n } else if (this.character.textDecoration === 'line-through') {\n const top = 1 + baseline - this.ascent / 2;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n }\n\n if (direction === 'vertical') {\n ctx.restore();\n }\n }\n\n getWidthWithEllips(direction: string): number {\n let text = this.text;\n // const direction = this.direction;\n const width = direction === 'vertical' ? this.height : this.width;\n // const height = direction === 'vertical' ? this.width: this.height;\n\n if (this.ellipsis === 'hide') {\n return width;\n } else if (this.ellipsis === 'add') {\n return width + this.ellipsisWidth;\n } else if (this.ellipsis === 'replace') {\n // 找到需要截断的字符长度\n // const index = getStrByWith(text, width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.style, text.length - 1);\n const index = getStrByWithCanvas(\n text,\n width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth,\n this.character,\n text.length - 1\n );\n text = text.slice(0, index);\n text += this.ellipsisStr;\n\n const { width: measureWidth } = measureTextCanvas(this.text.slice(index), this.character);\n return width + this.ellipsisWidth - measureWidth;\n }\n return width;\n }\n}\n\nexport function seperateParagraph(paragraph: Paragraph, index: number) {\n const text1 = paragraph.text.slice(0, index);\n const text2 = paragraph.text.slice(index);\n const p1 = new Paragraph(text1, paragraph.newLine, paragraph.character);\n const p2 = new Paragraph(text2, true, paragraph.character);\n\n return [p1, p2];\n}\n"]}
1
+ {"version":3,"sources":["../src/graphic/richtext/paragraph.ts"],"names":[],"mappings":"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","file":"paragraph.js","sourcesContent":["import { calculateLineHeight } from '../../common/utils';\nimport type { IContext2d, IRichTextParagraphCharacter } from '../../interface';\nimport { measureTextCanvas, getStrByWithCanvas } from './utils';\n\nfunction getFixedLRTB(left: number, right: number, top: number, bottom: number) {\n const leftInt = Math.round(left);\n const topInt = Math.round(top);\n const rightInt = Math.round(right);\n const bottomInt = Math.round(bottom);\n const _left = left > leftInt ? leftInt : leftInt - 0.5;\n const _top = top > topInt ? topInt : topInt - 0.5;\n const _right = rightInt > right ? rightInt : rightInt + 0.5;\n const _bottom = bottomInt > bottom ? bottomInt : bottomInt + 0.5;\n return {\n left: _left,\n top: _top,\n right: _right,\n bottom: _bottom\n };\n}\n\n/**\n * 部分代码参考 https://github.com/danielearwicker/carota/\n * The MIT License (MIT)\n\n \"Carota\" - Copyright (c) 2013 Daniel Earwicker\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n */\n\n// 文字段\n// 参考carota\n// https://github.com/danielearwicker/carota/blob/master/src/text.js\nexport default class Paragraph {\n text: string;\n ascent: number;\n descent: number;\n width: number;\n height: number;\n lineHeight: number;\n fontSize: number;\n length: number;\n newLine: boolean;\n character: IRichTextParagraphCharacter;\n left: number;\n top: number;\n // rotate?: number;\n direction?: 'horizontal' | 'vertical';\n // bounds?: Bounds;\n widthOrigin?: number;\n heightOrigin?: number;\n textBaseline?: CanvasTextBaseline;\n\n ellipsis: 'normal' | 'add' | 'replace' | 'hide';\n ellipsisStr: string;\n ellipsisWidth: number;\n ellipsisOtherParagraphWidth: number;\n verticalEllipsis?: boolean;\n overflow?: boolean;\n\n constructor(text: string, newLine: boolean, character: IRichTextParagraphCharacter) {\n // 测量文字\n this.fontSize = character.fontSize || 16;\n this.textBaseline = character.textBaseline || 'alphabetic';\n\n // 处理行高:\n // lineHeight为数字时,大于fontSize取lineHeight,小于fontSize时取fontSize\n // lineHeight不为数字时,统一认为lineHeight为'normal',值取1.2 * fontSize\n const lineHeight = calculateLineHeight(character.lineHeight, this.fontSize);\n if (typeof lineHeight === 'number') {\n this.lineHeight = lineHeight > this.fontSize ? lineHeight : this.fontSize;\n } else {\n this.lineHeight = Math.floor(1.2 * this.fontSize);\n }\n\n this.height = this.lineHeight;\n\n const { ascent, height, descent, width } = measureTextCanvas(text, character);\n\n let halfDetaHeight = 0;\n let deltaAscent = 0;\n let deltaDescent = 0;\n if (this.height > height) {\n // measureTextCanvas测量出的是纯文字高度,this.height是考虑行高后的高度\n // 如果this.height > height,将超过的高度平均分配到ascent和descent上\n halfDetaHeight = (this.height - height) / 2;\n deltaAscent = Math.ceil(halfDetaHeight);\n deltaDescent = Math.floor(halfDetaHeight);\n }\n\n if (this.textBaseline === 'top') {\n this.ascent = halfDetaHeight;\n this.descent = height - halfDetaHeight;\n } else if (this.textBaseline === 'bottom') {\n this.ascent = height - halfDetaHeight;\n this.descent = halfDetaHeight;\n } else if (this.textBaseline === 'middle') {\n this.ascent = this.height / 2;\n this.descent = this.height / 2;\n } else {\n this.ascent = ascent + deltaAscent;\n this.descent = descent + deltaDescent;\n }\n\n this.length = text.length;\n this.width = width || 0;\n this.text = text || '';\n this.newLine = newLine || false;\n this.character = character;\n\n this.left = 0;\n this.top = 0;\n\n this.ellipsis = 'normal';\n this.ellipsisWidth = 0;\n this.ellipsisOtherParagraphWidth = 0;\n\n // 处理旋转\n if (character.direction === 'vertical') {\n this.direction = character.direction;\n this.widthOrigin = this.width;\n this.heightOrigin = this.height;\n // const bounds = new Bounds();\n // bounds.set(0, 0, this.width, this.height);\n // bounds.rotate(Math.PI / 2, this.width / 2, this.height / 2);\n // this.bounds = bounds;\n // this.width = bounds.width();\n // this.height = bounds.height();\n this.width = this.heightOrigin;\n this.height = this.widthOrigin;\n this.lineHeight = this.height;\n }\n this.ellipsisStr = '...';\n }\n\n updateWidth() {\n const { width } = measureTextCanvas(this.text, this.character);\n this.width = width;\n if (this.direction === 'vertical') {\n this.widthOrigin = this.width;\n this.width = this.heightOrigin;\n this.height = this.widthOrigin;\n }\n }\n\n drawBackground(\n ctx: IContext2d,\n top: number,\n ascent: number,\n deltaLeft: number,\n isLineFirst: boolean,\n textAlign: string,\n lineHeight: number\n ) {\n if (!(this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0))) {\n return;\n }\n let baseline = top + ascent;\n let text = this.text;\n let left = this.left + deltaLeft;\n baseline += this.top;\n let direction = this.direction;\n\n if (this.verticalEllipsis) {\n text = this.ellipsisStr;\n direction = 'vertical';\n baseline -= this.ellipsisWidth / 2;\n } else if (this.ellipsis === 'hide') {\n return;\n } else if (this.ellipsis === 'add') {\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n left -= this.ellipsisWidth;\n }\n } else if (this.ellipsis === 'replace') {\n // 找到需要截断的字符长度\n // const index = getStrByWith(text, this.width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.style, text.length - 1);\n const index = getStrByWithCanvas(\n text,\n (direction === 'vertical' ? this.height : this.width) - this.ellipsisWidth + this.ellipsisOtherParagraphWidth,\n this.character,\n text.length - 1\n );\n text = text.slice(0, index);\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n const { width } = measureTextCanvas(this.text.slice(index), this.character);\n if (direction === 'vertical') {\n // baseline -= this.ellipsisWidth - width;\n } else {\n left -= this.ellipsisWidth - width;\n }\n }\n }\n\n // prepareContext(ctx);\n switch (this.character.script) {\n case 'super':\n baseline -= this.ascent * (1 / 3);\n break;\n case 'sub':\n baseline += this.descent / 2;\n break;\n }\n\n // 处理旋转\n if (direction === 'vertical') {\n ctx.save();\n ctx.rotateAbout(Math.PI / 2, left, baseline);\n ctx.translate(-(this.heightOrigin as number) || -this.lineHeight / 2, -this.descent / 2);\n ctx.translate(left, baseline);\n left = 0;\n baseline = 0;\n }\n\n const fillStyle = ctx.fillStyle;\n const globalAlpha = ctx.globalAlpha;\n ctx.fillStyle = this.character.background;\n if (this.character.backgroundOpacity !== void 0) {\n ctx.globalAlpha = this.character.backgroundOpacity;\n }\n // 背景稍微扩充一些buf,否则会出现白线\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + lineHeight;\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n ctx.fillStyle = fillStyle;\n ctx.globalAlpha = globalAlpha;\n }\n\n draw(\n ctx: IContext2d,\n top: number,\n ascent: number,\n deltaLeft: number,\n isLineFirst: boolean,\n textAlign: string,\n lineHeight: number\n ) {\n let baseline = top + ascent;\n let text = this.text;\n let left = this.left + deltaLeft;\n baseline += this.top;\n let direction = this.direction;\n\n if (this.verticalEllipsis) {\n text = this.ellipsisStr;\n direction = 'vertical';\n baseline -= this.ellipsisWidth / 2;\n } else if (this.ellipsis === 'hide') {\n return;\n } else if (this.ellipsis === 'add') {\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n left -= this.ellipsisWidth;\n }\n } else if (this.ellipsis === 'replace') {\n // 找到需要截断的字符长度\n // const index = getStrByWith(text, this.width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.style, text.length - 1);\n const index = getStrByWithCanvas(\n text,\n (direction === 'vertical' ? this.height : this.width) - this.ellipsisWidth + this.ellipsisOtherParagraphWidth,\n this.character,\n text.length - 1\n );\n text = text.slice(0, index);\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n const { width } = measureTextCanvas(this.text.slice(index), this.character);\n if (direction === 'vertical') {\n // baseline -= this.ellipsisWidth - width;\n } else {\n left -= this.ellipsisWidth - width;\n }\n }\n }\n\n // prepareContext(ctx);\n switch (this.character.script) {\n case 'super':\n baseline -= this.ascent * (1 / 3);\n break;\n case 'sub':\n baseline += this.descent / 2;\n break;\n }\n\n // if (isLineFirst) {\n // const result = regFirstSpace.exec(text);\n // if (result?.index !== 0) {\n // text = text.slice(result?.index);\n // }\n // }\n\n // 处理旋转\n if (direction === 'vertical') {\n ctx.save();\n ctx.rotateAbout(Math.PI / 2, left, baseline);\n ctx.translate(-(this.heightOrigin as number) || -this.lineHeight / 2, -this.descent / 2);\n ctx.translate(left, baseline);\n left = 0;\n baseline = 0;\n }\n\n // if (this.character.fill) {\n // if (this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0)) {\n // const fillStyle = ctx.fillStyle;\n // const globalAlpha = ctx.globalAlpha;\n // ctx.fillStyle = this.character.background;\n // if (this.character.backgroundOpacity !== void 0) {\n // ctx.globalAlpha = this.character.backgroundOpacity;\n // }\n // // 背景稍微扩充一些buf,否则会出现白线\n // const right = left + (this.widthOrigin || this.width);\n // const bottom = top + lineHeight;\n // const lrtb = getFixedLRTB(left, right, top, bottom);\n // ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n // ctx.fillStyle = fillStyle;\n // ctx.globalAlpha = globalAlpha;\n // }\n // }\n\n const { lineWidth = 1 } = this.character;\n if (this.character.stroke && lineWidth) {\n ctx.strokeText(text, left, baseline);\n }\n\n if (this.character.fill) {\n ctx.fillText(text, left, baseline);\n }\n\n if (this.character.fill) {\n if (this.character.lineThrough || this.character.underline) {\n if (this.character.underline) {\n const top = 1 + baseline;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n if (this.character.lineThrough) {\n const top = 1 + baseline - this.ascent / 2;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n } else if (this.character.textDecoration === 'underline') {\n const top = 1 + baseline;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n } else if (this.character.textDecoration === 'line-through') {\n const top = 1 + baseline - this.ascent / 2;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n }\n\n if (direction === 'vertical') {\n ctx.restore();\n }\n }\n\n getWidthWithEllips(direction: string): number {\n let text = this.text;\n // const direction = this.direction;\n const width = direction === 'vertical' ? this.height : this.width;\n // const height = direction === 'vertical' ? this.width: this.height;\n\n if (this.ellipsis === 'hide') {\n return width;\n } else if (this.ellipsis === 'add') {\n return width + this.ellipsisWidth;\n } else if (this.ellipsis === 'replace') {\n // 找到需要截断的字符长度\n // const index = getStrByWith(text, width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.style, text.length - 1);\n const index = getStrByWithCanvas(\n text,\n width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth,\n this.character,\n text.length - 1\n );\n text = text.slice(0, index);\n text += this.ellipsisStr;\n\n const { width: measureWidth } = measureTextCanvas(this.text.slice(index), this.character);\n return width + this.ellipsisWidth - measureWidth;\n }\n return width;\n }\n}\n\nexport function seperateParagraph(paragraph: Paragraph, index: number) {\n const text1 = paragraph.text.slice(0, index);\n const text2 = paragraph.text.slice(index);\n const p1 = new Paragraph(text1, paragraph.newLine, paragraph.character);\n const p2 = new Paragraph(text2, true, paragraph.character);\n\n return [p1, p2];\n}\n"]}
@@ -179,10 +179,10 @@ function measureTextCanvas(text, character) {
179
179
  descent: 0,
180
180
  width: 0
181
181
  };
182
- return "number" != typeof measurement.actualBoundingBoxAscent || "number" != typeof measurement.actualBoundingBoxDescent ? (result.width = Math.floor(measurement.width),
183
- result.height = character.fontSize || 0, result.ascent = result.height, result.descent = 0) : (result.width = Math.floor(measurement.width),
184
- result.height = Math.floor(measurement.actualBoundingBoxAscent + measurement.actualBoundingBoxDescent),
185
- result.ascent = Math.floor(measurement.actualBoundingBoxAscent), result.descent = result.height - result.ascent),
182
+ return "number" != typeof measurement.fontBoundingBoxAscent || "number" != typeof measurement.fontBoundingBoxDescent ? (result.width = measurement.width,
183
+ result.height = character.fontSize || 0, result.ascent = result.height, result.descent = 0) : (result.width = measurement.width,
184
+ result.height = Math.floor(measurement.fontBoundingBoxAscent + measurement.fontBoundingBoxDescent),
185
+ result.ascent = Math.floor(measurement.fontBoundingBoxAscent), result.descent = result.height - result.ascent),
186
186
  result;
187
187
  }
188
188
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/graphic/richtext/utils.ts"],"names":[],"mappings":"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","file":"utils.js","sourcesContent":["import type { IBoundsLike } from '@visactor/vutils';\nimport { application } from '../../application';\nimport { createColor } from '../../common/canvas-utils';\nimport type { IContext2d, ITextStyleParams, IRichTextParagraphCharacter } from '../../interface';\nimport { DEFAULT_TEXT_FONT_FAMILY } from '../../constants';\n\nexport const DIRECTION_KEY = {\n horizontal: {\n width: 'width',\n height: 'height',\n left: 'left',\n top: 'top',\n x: 'x',\n y: 'y',\n bottom: 'bottom'\n },\n vertical: {\n width: 'height',\n height: 'width',\n left: 'top',\n top: 'left',\n x: 'y',\n y: 'x',\n bottom: 'right'\n }\n};\n\nconst defaultFormatting = {\n fontSize: 16,\n fontFamily: DEFAULT_TEXT_FONT_FAMILY,\n fill: true,\n stroke: false,\n fontWeight: 'normal',\n lineHeight: 'normal',\n fontStyle: 'normal', // normal, italic, oblique\n textDecoration: 'none', // none, underline, line-through\n textAlign: 'left', // left, right, center\n script: 'normal' // normal, sub, super\n};\nconst nbsp = String.fromCharCode(160);\n\nexport const regLetter = /\\w|\\(|\\)|-/;\nconst regPunctuation = /[.?!,;:/,。?!、;:]/;\nexport const regFirstSpace = /\\S/;\n\nconst setTextStyle = (ctx: IContext2d, character: IRichTextParagraphCharacter) => {\n let fontSize = character.fontSize || 16;\n switch (character.script) {\n case 'super':\n case 'sub':\n fontSize *= 0.8;\n break;\n }\n\n ctx.setTextStyle({\n textAlign: 'left',\n textBaseline: character.textBaseline || 'alphabetic',\n fontStyle: character.fontStyle || '',\n fontWeight: character.fontWeight || '',\n fontSize,\n fontFamily: character.fontFamily\n } as ITextStyleParams);\n};\n\n// Applies the style of a run to the canvas context\nexport function applyFillStyle(ctx: IContext2d, character: IRichTextParagraphCharacter, b?: IBoundsLike) {\n const fillStyle = (character && (character.fill as string)) || defaultFormatting.fill;\n if (!fillStyle) {\n ctx.globalAlpha = 0;\n return;\n }\n\n const { fillOpacity = 1, opacity = 1 } = character;\n\n ctx.globalAlpha = fillOpacity * opacity;\n ctx.fillStyle = b ? createColor(ctx, fillStyle, { AABBBounds: b }) : (fillStyle as string);\n\n setTextStyle(ctx, character);\n}\n\nexport function applyStrokeStyle(ctx: IContext2d, character: IRichTextParagraphCharacter) {\n const strokeStyle = (character && (character.stroke as string)) || (defaultFormatting.stroke as any);\n if (!strokeStyle) {\n ctx.globalAlpha = 0;\n return;\n }\n\n const { strokeOpacity = 1, opacity = 1 } = character;\n\n ctx.globalAlpha = strokeOpacity * opacity;\n ctx.lineWidth = character && typeof character.lineWidth === 'number' ? character.lineWidth : 1;\n ctx.strokeStyle = strokeStyle as string;\n\n setTextStyle(ctx, character);\n}\n\nexport function prepareContext(ctx: IContext2d) {\n ctx.setTextStyle({\n textAlign: 'left',\n textBaseline: 'bottom'\n });\n}\n\n// 确认达到availableWidth的字符串截取index\nexport function getStrByWithDom(\n desc: string,\n width: number,\n style: string,\n guessIndex: number,\n needTestLetter?: boolean\n): number {\n desc = desc.replace(/\\s/g, nbsp);\n\n // 测量用DOM\n const span = document.createElement('span');\n span.setAttribute('style', style);\n span.style.visibility = 'hidden';\n span.style.whiteSpace = 'nowrap';\n document.body.appendChild(span);\n\n // 测量从头到当前位置宽度以及从头到下一个字符位置宽度\n let index = guessIndex;\n let temp = desc.slice(0, index);\n span.innerText = temp;\n let tempWidth = span.offsetWidth;\n\n let tempNext = desc.slice(0, index + 1);\n span.innerText = tempNext;\n let tempWidthNext = span.offsetWidth;\n\n // 到当前位置宽度 < width && 到下一个字符位置宽度 > width时,认为找到准确阶段位置\n while (tempWidth > width || tempWidthNext <= width) {\n if (tempWidth > width) {\n index--;\n } else {\n index++;\n }\n\n temp = desc.slice(0, index);\n span.innerText = temp;\n tempWidth = span.offsetWidth;\n\n tempNext = desc.slice(0, index + 1);\n span.innerText = tempNext;\n tempWidthNext = span.offsetWidth;\n }\n\n // 处理特殊情况\n if (needTestLetter) {\n index = testLetter(desc, index);\n }\n\n document.body.removeChild(span);\n return index;\n}\nexport function getStrByWithCanvas(\n desc: string,\n width: number,\n character: IRichTextParagraphCharacter,\n // ctx: IContext2d,\n guessIndex: number,\n needTestLetter?: boolean\n): number {\n if (!width || width <= 0) {\n return 0;\n }\n const textMeasure = application.graphicUtil.textMeasure;\n // const measurement = textMeasure.measureText(text, character);\n\n // 测量从头到当前位置宽度以及从头到下一个字符位置宽度\n let index = guessIndex;\n let temp = desc.slice(0, index);\n let tempWidth = Math.floor(textMeasure.measureText(temp, character as any).width);\n\n let tempNext = desc.slice(0, index + 1);\n let tempWidthNext = Math.floor(textMeasure.measureText(tempNext, character as any).width);\n\n // 到当前位置宽度 < width && 到下一个字符位置宽度 > width时,认为找到准确阶段位置\n while (tempWidth > width || tempWidthNext <= width) {\n if (tempWidth > width) {\n index--;\n } else {\n index++;\n }\n\n if (index > desc.length) {\n index = desc.length;\n break;\n } else if (index < 0) {\n index = 0;\n break;\n }\n\n temp = desc.slice(0, index);\n tempWidth = Math.floor(textMeasure.measureText(temp, character as any).width);\n\n tempNext = desc.slice(0, index + 1);\n tempWidthNext = Math.floor(textMeasure.measureText(tempNext, character as any).width);\n }\n\n // 处理特殊情况\n if (needTestLetter) {\n index = testLetter(desc, index);\n }\n\n return index;\n}\n\nexport function getWordStartEndIdx(string: string, index: number) {\n let startIdx = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[startIdx - 1]) && regLetter.test(string[startIdx])) ||\n // 行首标点符号处理\n regPunctuation.test(string[startIdx])\n ) {\n startIdx--;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (startIdx <= 0) {\n break;\n }\n }\n\n let endIdx = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[endIdx + 1]) && regLetter.test(string[endIdx])) ||\n // 行首标点符号处理\n regPunctuation.test(string[endIdx])\n ) {\n endIdx++;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (endIdx >= string.length) {\n break;\n }\n }\n endIdx = Math.min(endIdx + 1, string.length);\n\n return {\n startIdx,\n endIdx\n };\n}\n\n/**\n * 向前找到单词结尾处换行\n * @param string\n * @param index\n * @param negativeWrongMatch 如果为true,那么如果无法匹配就会向后找到单词的结尾,否则就直接返回index\n * @returns\n */\nexport function testLetter(string: string, index: number, negativeWrongMatch: boolean = false): number {\n let i = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[i - 1]) && regLetter.test(string[i])) ||\n // 行首标点符号处理\n regPunctuation.test(string[i])\n ) {\n i--;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (i <= 0) {\n return negativeWrongMatch ? testLetter2(string, index) : index;\n }\n }\n return i;\n}\n\n/**\n * 向后找到单词结尾处换行\n * @param string\n * @param index\n * @returns\n */\nexport function testLetter2(string: string, index: number) {\n let i = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[i + 1]) && regLetter.test(string[i])) ||\n // 行首标点符号处理\n regPunctuation.test(string[i])\n ) {\n i++;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (i >= string.length) {\n return i;\n }\n }\n return i + 1;\n}\n\n// 测量文字详细信息\nexport function measureTextDom(\n text: string,\n style: string\n): { ascent?: number; height?: number; descent?: number; width?: number } {\n let div;\n\n const span = document.createElement('span');\n const block = document.createElement('div');\n div = document.createElement('div');\n\n block.style.display = 'inline-block';\n block.style.width = '1px';\n block.style.height = '0';\n\n div.style.visibility = 'hidden';\n div.style.position = 'absolute';\n div.style.top = '0';\n div.style.left = '0';\n div.style.width = '500px';\n div.style.height = '200px';\n div.style.whiteSpace = 'nowrap';\n\n div.appendChild(span);\n div.appendChild(block);\n document.body.appendChild(div);\n\n const result: { ascent?: number; height?: number; descent?: number; width?: number } = {};\n try {\n span.setAttribute('style', style);\n span.style.whiteSpace = 'nowrap';\n span.style.display = 'inline-block';\n\n span.innerHTML = '';\n span.appendChild(document.createTextNode(text.replace(/\\s/g, nbsp)));\n\n block.style.verticalAlign = 'baseline';\n result.ascent = block.offsetTop - span.offsetTop;\n block.style.verticalAlign = 'bottom';\n result.height = block.offsetTop - span.offsetTop;\n result.descent = result.height - result.ascent;\n result.width = span.offsetWidth;\n } finally {\n div.parentNode?.removeChild(div);\n div = null;\n }\n return result;\n}\n\n// 测量文字详细信息\nexport function measureTextCanvas(\n text: string,\n character: IRichTextParagraphCharacter\n): { ascent: number; height: number; descent: number; width: number } {\n const textMeasure = application.graphicUtil.textMeasure;\n const measurement = textMeasure.measureText(text, character as any) as TextMetrics;\n const result: { ascent: number; height: number; descent: number; width: number } = {\n ascent: 0,\n height: 0,\n descent: 0,\n width: 0\n };\n if (\n typeof measurement.actualBoundingBoxAscent !== 'number' ||\n typeof measurement.actualBoundingBoxDescent !== 'number'\n ) {\n result.width = Math.floor(measurement.width);\n result.height = character.fontSize || 0;\n result.ascent = result.height;\n result.descent = 0;\n } else {\n result.width = Math.floor(measurement.width);\n result.height = Math.floor(measurement.actualBoundingBoxAscent + measurement.actualBoundingBoxDescent);\n result.ascent = Math.floor(measurement.actualBoundingBoxAscent);\n result.descent = result.height - result.ascent;\n }\n return result;\n}\n\nexport function getFontString(character: IRichTextParagraphCharacter, ctx: IContext2d | null) {\n let fontSize = (character && character.fontSize) || defaultFormatting.fontSize;\n\n if (character) {\n switch (character.script) {\n case 'super':\n case 'sub':\n fontSize *= 0.8;\n break;\n }\n }\n\n return (\n ((character && character.fontStyle) || '') +\n ' ' +\n ((character && character.fontWeight) || '') +\n ' ' +\n (fontSize || 12) +\n 'px ' +\n ((character && character.fontFamily) || defaultFormatting.fontFamily)\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/graphic/richtext/utils.ts"],"names":[],"mappings":"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","file":"utils.js","sourcesContent":["import type { IBoundsLike } from '@visactor/vutils';\nimport { application } from '../../application';\nimport { createColor } from '../../common/canvas-utils';\nimport type { IContext2d, ITextStyleParams, IRichTextParagraphCharacter } from '../../interface';\nimport { DEFAULT_TEXT_FONT_FAMILY } from '../../constants';\n\nexport const DIRECTION_KEY = {\n horizontal: {\n width: 'width',\n height: 'height',\n left: 'left',\n top: 'top',\n x: 'x',\n y: 'y',\n bottom: 'bottom'\n },\n vertical: {\n width: 'height',\n height: 'width',\n left: 'top',\n top: 'left',\n x: 'y',\n y: 'x',\n bottom: 'right'\n }\n};\n\nconst defaultFormatting = {\n fontSize: 16,\n fontFamily: DEFAULT_TEXT_FONT_FAMILY,\n fill: true,\n stroke: false,\n fontWeight: 'normal',\n lineHeight: 'normal',\n fontStyle: 'normal', // normal, italic, oblique\n textDecoration: 'none', // none, underline, line-through\n textAlign: 'left', // left, right, center\n script: 'normal' // normal, sub, super\n};\nconst nbsp = String.fromCharCode(160);\n\nexport const regLetter = /\\w|\\(|\\)|-/;\nconst regPunctuation = /[.?!,;:/,。?!、;:]/;\nexport const regFirstSpace = /\\S/;\n\nconst setTextStyle = (ctx: IContext2d, character: IRichTextParagraphCharacter) => {\n let fontSize = character.fontSize || 16;\n switch (character.script) {\n case 'super':\n case 'sub':\n fontSize *= 0.8;\n break;\n }\n\n ctx.setTextStyle({\n textAlign: 'left',\n textBaseline: character.textBaseline || 'alphabetic',\n fontStyle: character.fontStyle || '',\n fontWeight: character.fontWeight || '',\n fontSize,\n fontFamily: character.fontFamily\n } as ITextStyleParams);\n};\n\n// Applies the style of a run to the canvas context\nexport function applyFillStyle(ctx: IContext2d, character: IRichTextParagraphCharacter, b?: IBoundsLike) {\n const fillStyle = (character && (character.fill as string)) || defaultFormatting.fill;\n if (!fillStyle) {\n ctx.globalAlpha = 0;\n return;\n }\n\n const { fillOpacity = 1, opacity = 1 } = character;\n\n ctx.globalAlpha = fillOpacity * opacity;\n ctx.fillStyle = b ? createColor(ctx, fillStyle, { AABBBounds: b }) : (fillStyle as string);\n\n setTextStyle(ctx, character);\n}\n\nexport function applyStrokeStyle(ctx: IContext2d, character: IRichTextParagraphCharacter) {\n const strokeStyle = (character && (character.stroke as string)) || (defaultFormatting.stroke as any);\n if (!strokeStyle) {\n ctx.globalAlpha = 0;\n return;\n }\n\n const { strokeOpacity = 1, opacity = 1 } = character;\n\n ctx.globalAlpha = strokeOpacity * opacity;\n ctx.lineWidth = character && typeof character.lineWidth === 'number' ? character.lineWidth : 1;\n ctx.strokeStyle = strokeStyle as string;\n\n setTextStyle(ctx, character);\n}\n\nexport function prepareContext(ctx: IContext2d) {\n ctx.setTextStyle({\n textAlign: 'left',\n textBaseline: 'bottom'\n });\n}\n\n// 确认达到availableWidth的字符串截取index\nexport function getStrByWithDom(\n desc: string,\n width: number,\n style: string,\n guessIndex: number,\n needTestLetter?: boolean\n): number {\n desc = desc.replace(/\\s/g, nbsp);\n\n // 测量用DOM\n const span = document.createElement('span');\n span.setAttribute('style', style);\n span.style.visibility = 'hidden';\n span.style.whiteSpace = 'nowrap';\n document.body.appendChild(span);\n\n // 测量从头到当前位置宽度以及从头到下一个字符位置宽度\n let index = guessIndex;\n let temp = desc.slice(0, index);\n span.innerText = temp;\n let tempWidth = span.offsetWidth;\n\n let tempNext = desc.slice(0, index + 1);\n span.innerText = tempNext;\n let tempWidthNext = span.offsetWidth;\n\n // 到当前位置宽度 < width && 到下一个字符位置宽度 > width时,认为找到准确阶段位置\n while (tempWidth > width || tempWidthNext <= width) {\n if (tempWidth > width) {\n index--;\n } else {\n index++;\n }\n\n temp = desc.slice(0, index);\n span.innerText = temp;\n tempWidth = span.offsetWidth;\n\n tempNext = desc.slice(0, index + 1);\n span.innerText = tempNext;\n tempWidthNext = span.offsetWidth;\n }\n\n // 处理特殊情况\n if (needTestLetter) {\n index = testLetter(desc, index);\n }\n\n document.body.removeChild(span);\n return index;\n}\nexport function getStrByWithCanvas(\n desc: string,\n width: number,\n character: IRichTextParagraphCharacter,\n // ctx: IContext2d,\n guessIndex: number,\n needTestLetter?: boolean\n): number {\n if (!width || width <= 0) {\n return 0;\n }\n const textMeasure = application.graphicUtil.textMeasure;\n // const measurement = textMeasure.measureText(text, character);\n\n // 测量从头到当前位置宽度以及从头到下一个字符位置宽度\n let index = guessIndex;\n let temp = desc.slice(0, index);\n let tempWidth = Math.floor(textMeasure.measureText(temp, character as any).width);\n\n let tempNext = desc.slice(0, index + 1);\n let tempWidthNext = Math.floor(textMeasure.measureText(tempNext, character as any).width);\n\n // 到当前位置宽度 < width && 到下一个字符位置宽度 > width时,认为找到准确阶段位置\n while (tempWidth > width || tempWidthNext <= width) {\n if (tempWidth > width) {\n index--;\n } else {\n index++;\n }\n\n if (index > desc.length) {\n index = desc.length;\n break;\n } else if (index < 0) {\n index = 0;\n break;\n }\n\n temp = desc.slice(0, index);\n tempWidth = Math.floor(textMeasure.measureText(temp, character as any).width);\n\n tempNext = desc.slice(0, index + 1);\n tempWidthNext = Math.floor(textMeasure.measureText(tempNext, character as any).width);\n }\n\n // 处理特殊情况\n if (needTestLetter) {\n index = testLetter(desc, index);\n }\n\n return index;\n}\n\nexport function getWordStartEndIdx(string: string, index: number) {\n let startIdx = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[startIdx - 1]) && regLetter.test(string[startIdx])) ||\n // 行首标点符号处理\n regPunctuation.test(string[startIdx])\n ) {\n startIdx--;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (startIdx <= 0) {\n break;\n }\n }\n\n let endIdx = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[endIdx + 1]) && regLetter.test(string[endIdx])) ||\n // 行首标点符号处理\n regPunctuation.test(string[endIdx])\n ) {\n endIdx++;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (endIdx >= string.length) {\n break;\n }\n }\n endIdx = Math.min(endIdx + 1, string.length);\n\n return {\n startIdx,\n endIdx\n };\n}\n\n/**\n * 向前找到单词结尾处换行\n * @param string\n * @param index\n * @param negativeWrongMatch 如果为true,那么如果无法匹配就会向后找到单词的结尾,否则就直接返回index\n * @returns\n */\nexport function testLetter(string: string, index: number, negativeWrongMatch: boolean = false): number {\n let i = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[i - 1]) && regLetter.test(string[i])) ||\n // 行首标点符号处理\n regPunctuation.test(string[i])\n ) {\n i--;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (i <= 0) {\n return negativeWrongMatch ? testLetter2(string, index) : index;\n }\n }\n return i;\n}\n\n/**\n * 向后找到单词结尾处换行\n * @param string\n * @param index\n * @returns\n */\nexport function testLetter2(string: string, index: number) {\n let i = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[i + 1]) && regLetter.test(string[i])) ||\n // 行首标点符号处理\n regPunctuation.test(string[i])\n ) {\n i++;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (i >= string.length) {\n return i;\n }\n }\n return i + 1;\n}\n\n// 测量文字详细信息\nexport function measureTextDom(\n text: string,\n style: string\n): { ascent?: number; height?: number; descent?: number; width?: number } {\n let div;\n\n const span = document.createElement('span');\n const block = document.createElement('div');\n div = document.createElement('div');\n\n block.style.display = 'inline-block';\n block.style.width = '1px';\n block.style.height = '0';\n\n div.style.visibility = 'hidden';\n div.style.position = 'absolute';\n div.style.top = '0';\n div.style.left = '0';\n div.style.width = '500px';\n div.style.height = '200px';\n div.style.whiteSpace = 'nowrap';\n\n div.appendChild(span);\n div.appendChild(block);\n document.body.appendChild(div);\n\n const result: { ascent?: number; height?: number; descent?: number; width?: number } = {};\n try {\n span.setAttribute('style', style);\n span.style.whiteSpace = 'nowrap';\n span.style.display = 'inline-block';\n\n span.innerHTML = '';\n span.appendChild(document.createTextNode(text.replace(/\\s/g, nbsp)));\n\n block.style.verticalAlign = 'baseline';\n result.ascent = block.offsetTop - span.offsetTop;\n block.style.verticalAlign = 'bottom';\n result.height = block.offsetTop - span.offsetTop;\n result.descent = result.height - result.ascent;\n result.width = span.offsetWidth;\n } finally {\n div.parentNode?.removeChild(div);\n div = null;\n }\n return result;\n}\n\n// 测量文字详细信息\nexport function measureTextCanvas(\n text: string,\n character: IRichTextParagraphCharacter\n): { ascent: number; height: number; descent: number; width: number } {\n const textMeasure = application.graphicUtil.textMeasure;\n const measurement = textMeasure.measureText(text, character as any) as TextMetrics;\n const result: { ascent: number; height: number; descent: number; width: number } = {\n ascent: 0,\n height: 0,\n descent: 0,\n width: 0\n };\n if (typeof measurement.fontBoundingBoxAscent !== 'number' || typeof measurement.fontBoundingBoxDescent !== 'number') {\n result.width = measurement.width;\n result.height = character.fontSize || 0;\n result.ascent = result.height;\n result.descent = 0;\n } else {\n result.width = measurement.width;\n result.height = Math.floor(measurement.fontBoundingBoxAscent + measurement.fontBoundingBoxDescent);\n result.ascent = Math.floor(measurement.fontBoundingBoxAscent);\n result.descent = result.height - result.ascent;\n }\n return result;\n}\n\nexport function getFontString(character: IRichTextParagraphCharacter, ctx: IContext2d | null) {\n let fontSize = (character && character.fontSize) || defaultFormatting.fontSize;\n\n if (character) {\n switch (character.script) {\n case 'super':\n case 'sub':\n fontSize *= 0.8;\n break;\n }\n }\n\n return (\n ((character && character.fontStyle) || '') +\n ' ' +\n ((character && character.fontWeight) || '') +\n ' ' +\n (fontSize || 12) +\n 'px ' +\n ((character && character.fontFamily) || defaultFormatting.fontFamily)\n );\n}\n"]}
package/dist/index.es.js CHANGED
@@ -3931,17 +3931,16 @@ function measureTextCanvas(text, character) {
3931
3931
  descent: 0,
3932
3932
  width: 0
3933
3933
  };
3934
- if (typeof measurement.actualBoundingBoxAscent !== 'number' ||
3935
- typeof measurement.actualBoundingBoxDescent !== 'number') {
3936
- result.width = Math.floor(measurement.width);
3934
+ if (typeof measurement.fontBoundingBoxAscent !== 'number' || typeof measurement.fontBoundingBoxDescent !== 'number') {
3935
+ result.width = measurement.width;
3937
3936
  result.height = character.fontSize || 0;
3938
3937
  result.ascent = result.height;
3939
3938
  result.descent = 0;
3940
3939
  }
3941
3940
  else {
3942
- result.width = Math.floor(measurement.width);
3943
- result.height = Math.floor(measurement.actualBoundingBoxAscent + measurement.actualBoundingBoxDescent);
3944
- result.ascent = Math.floor(measurement.actualBoundingBoxAscent);
3941
+ result.width = measurement.width;
3942
+ result.height = Math.floor(measurement.fontBoundingBoxAscent + measurement.fontBoundingBoxDescent);
3943
+ result.ascent = Math.floor(measurement.fontBoundingBoxAscent);
3945
3944
  result.descent = result.height - result.ascent;
3946
3945
  }
3947
3946
  return result;
@@ -17918,7 +17917,10 @@ class Paragraph {
17918
17917
  this.height = this.widthOrigin;
17919
17918
  }
17920
17919
  }
17921
- draw(ctx, top, ascent, deltaLeft, isLineFirst, textAlign, lineHeight) {
17920
+ drawBackground(ctx, top, ascent, deltaLeft, isLineFirst, textAlign, lineHeight) {
17921
+ if (!(this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0))) {
17922
+ return;
17923
+ }
17922
17924
  let baseline = top + ascent;
17923
17925
  let text = this.text;
17924
17926
  let left = this.left + deltaLeft;
@@ -17966,22 +17968,67 @@ class Paragraph {
17966
17968
  left = 0;
17967
17969
  baseline = 0;
17968
17970
  }
17969
- if (this.character.fill) {
17970
- if (this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0)) {
17971
- const fillStyle = ctx.fillStyle;
17972
- const globalAlpha = ctx.globalAlpha;
17973
- ctx.fillStyle = this.character.background;
17974
- if (this.character.backgroundOpacity !== void 0) {
17975
- ctx.globalAlpha = this.character.backgroundOpacity;
17971
+ const fillStyle = ctx.fillStyle;
17972
+ const globalAlpha = ctx.globalAlpha;
17973
+ ctx.fillStyle = this.character.background;
17974
+ if (this.character.backgroundOpacity !== void 0) {
17975
+ ctx.globalAlpha = this.character.backgroundOpacity;
17976
+ }
17977
+ const right = left + (this.widthOrigin || this.width);
17978
+ const bottom = top + lineHeight;
17979
+ const lrtb = getFixedLRTB(left, right, top, bottom);
17980
+ ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);
17981
+ ctx.fillStyle = fillStyle;
17982
+ ctx.globalAlpha = globalAlpha;
17983
+ }
17984
+ draw(ctx, top, ascent, deltaLeft, isLineFirst, textAlign, lineHeight) {
17985
+ let baseline = top + ascent;
17986
+ let text = this.text;
17987
+ let left = this.left + deltaLeft;
17988
+ baseline += this.top;
17989
+ let direction = this.direction;
17990
+ if (this.verticalEllipsis) {
17991
+ text = this.ellipsisStr;
17992
+ direction = 'vertical';
17993
+ baseline -= this.ellipsisWidth / 2;
17994
+ }
17995
+ else if (this.ellipsis === 'hide') {
17996
+ return;
17997
+ }
17998
+ else if (this.ellipsis === 'add') {
17999
+ text += this.ellipsisStr;
18000
+ if (textAlign === 'right' || textAlign === 'end') {
18001
+ left -= this.ellipsisWidth;
18002
+ }
18003
+ }
18004
+ else if (this.ellipsis === 'replace') {
18005
+ const index = getStrByWithCanvas(text, (direction === 'vertical' ? this.height : this.width) - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.character, text.length - 1);
18006
+ text = text.slice(0, index);
18007
+ text += this.ellipsisStr;
18008
+ if (textAlign === 'right' || textAlign === 'end') {
18009
+ const { width } = measureTextCanvas(this.text.slice(index), this.character);
18010
+ if (direction === 'vertical') ;
18011
+ else {
18012
+ left -= this.ellipsisWidth - width;
17976
18013
  }
17977
- const right = left + (this.widthOrigin || this.width);
17978
- const bottom = top + lineHeight;
17979
- const lrtb = getFixedLRTB(left, right, top, bottom);
17980
- ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);
17981
- ctx.fillStyle = fillStyle;
17982
- ctx.globalAlpha = globalAlpha;
17983
18014
  }
17984
18015
  }
18016
+ switch (this.character.script) {
18017
+ case 'super':
18018
+ baseline -= this.ascent * (1 / 3);
18019
+ break;
18020
+ case 'sub':
18021
+ baseline += this.descent / 2;
18022
+ break;
18023
+ }
18024
+ if (direction === 'vertical') {
18025
+ ctx.save();
18026
+ ctx.rotateAbout(Math.PI / 2, left, baseline);
18027
+ ctx.translate(-this.heightOrigin || -this.lineHeight / 2, -this.descent / 2);
18028
+ ctx.translate(left, baseline);
18029
+ left = 0;
18030
+ baseline = 0;
18031
+ }
17985
18032
  const { lineWidth = 1 } = this.character;
17986
18033
  if (this.character.stroke && lineWidth) {
17987
18034
  ctx.strokeText(text, left, baseline);
@@ -18357,6 +18404,12 @@ class Line {
18357
18404
  }
18358
18405
  }
18359
18406
  }
18407
+ this.paragraphs.forEach((paragraph, index) => {
18408
+ if (paragraph instanceof RichTextIcon) {
18409
+ return;
18410
+ }
18411
+ paragraph.drawBackground(ctx, y, this.ascent, x, index === 0, this.textAlign, this.height);
18412
+ });
18360
18413
  this.paragraphs.forEach((paragraph, index) => {
18361
18414
  if (paragraph instanceof RichTextIcon) {
18362
18415
  paragraph.setAttributes({
@@ -68,6 +68,8 @@ export default class Line {
68
68
  }
69
69
  }
70
70
  this.paragraphs.forEach(((paragraph, index) => {
71
+ paragraph instanceof RichTextIcon || paragraph.drawBackground(ctx, y, this.ascent, x, 0 === index, this.textAlign, this.height);
72
+ })), this.paragraphs.forEach(((paragraph, index) => {
71
73
  if (paragraph instanceof RichTextIcon) return paragraph.setAttributes({
72
74
  x: x + paragraph._x,
73
75
  y: y + paragraph._y
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/graphic/richtext/line.ts"],"names":[],"mappings":"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","file":"line.js","sourcesContent":["// import { IContext2d } from '../../IContext';\nimport type { IContext2d, IRichTextIcon } from '../../interface';\nimport { RichTextIcon } from './icon';\nimport Paragraph from './paragraph';\nimport { applyFillStyle, applyStrokeStyle, DIRECTION_KEY, measureTextCanvas, regFirstSpace } from './utils';\n\n/**\n * 部分代码参考 https://github.com/danielearwicker/carota/\n * The MIT License (MIT)\n\n \"Carota\" - Copyright (c) 2013 Daniel Earwicker\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n */\n\n// 行\n// 参考carota\n// https://github.com/danielearwicker/carota/blob/master/src/line.js\nexport default class Line {\n left: number;\n top: number;\n width: number;\n height: number;\n baseline: number;\n ascent: number;\n descent: number;\n paragraphs: (Paragraph | RichTextIcon)[];\n actualWidth: number;\n blankWidth: number;\n textAlign: string;\n direction: 'horizontal' | 'vertical';\n directionKey: { width: string; height: string; left: string; x: string; y: string };\n\n constructor(\n left: number,\n width: number,\n baseline: number,\n ascent: number,\n descent: number,\n lineBuffer: (Paragraph | RichTextIcon)[],\n direction: 'horizontal' | 'vertical',\n isWidthMax: boolean\n ) {\n this.left = left;\n this.width = width;\n this.baseline = baseline;\n this.ascent = ascent;\n this.descent = descent;\n // this.height = ascent + descent;\n this.top = baseline - ascent;\n this.paragraphs = lineBuffer.map(p => p);\n this.textAlign =\n (this.paragraphs[0] instanceof RichTextIcon\n ? this.paragraphs[0].attribute.textAlign\n : this.paragraphs[0].character.textAlign) || 'left'; // 对齐方式选择第一个paragraph属性\n this.direction = direction;\n this.directionKey = DIRECTION_KEY[this.direction];\n\n this.actualWidth = 0;\n let maxHeight = 0;\n this.paragraphs.forEach((word, index) => {\n // 每行中第一个字符不能是空格\n if (index === 0 && word instanceof Paragraph) {\n const result = regFirstSpace.exec(word.text);\n if (result?.index !== 0) {\n word.text = word.text.slice(result?.index);\n word.updateWidth();\n }\n }\n this.actualWidth += word[this.directionKey.width];\n maxHeight = Math.max(word[this.directionKey.height], maxHeight);\n });\n this.height = maxHeight;\n\n this.blankWidth = !isWidthMax ? this.width - this.actualWidth : 0;\n\n this.calcOffset(width, isWidthMax);\n }\n\n calcOffset(width: number, isWidthMax: boolean) {\n // 处理对齐方式,计算左侧偏移距离和字符之间间距\n const directionKey = this.directionKey;\n const maxHeight = this.height;\n let x = this.left;\n let spacing = 0;\n if (this.actualWidth < width && !isWidthMax) {\n if (this.textAlign === 'right' || this.textAlign === 'end') {\n x = width - this.actualWidth;\n } else if (this.textAlign === 'center') {\n x = (width - this.actualWidth) / 2;\n } else if (this.textAlign === 'justify') {\n if (this.paragraphs.length < 2) {\n // 只有一个paragraph两端对齐居中显示\n x = (width - this.actualWidth) / 2;\n } else {\n spacing = (width - this.actualWidth) / (this.paragraphs.length - 1);\n }\n }\n }\n\n this.paragraphs.map(function (paragraph) {\n if (paragraph instanceof RichTextIcon) {\n // paragraph.setAttribute(directionKey.x, x);\n paragraph['_' + directionKey.x] = x;\n x += paragraph[directionKey.width] + spacing;\n // 处理纵向对齐\n paragraph['_' + directionKey.y] =\n paragraph.attribute.textBaseline === 'top'\n ? 0\n : paragraph.attribute.textBaseline === 'bottom'\n ? maxHeight - paragraph.height\n : (maxHeight - paragraph.height) / 2;\n } else {\n paragraph[directionKey.left] = x;\n x += paragraph[directionKey.width] + spacing;\n }\n });\n }\n\n draw(\n ctx: IContext2d,\n lastLine: boolean,\n x: number,\n y: number,\n drawEllipsis: boolean | string,\n drawIcon: (icon: IRichTextIcon, context: IContext2d, x: number, y: number, baseline: number) => void\n ) {\n if (drawEllipsis && (lastLine || this.paragraphs.some(p => (p as Paragraph).overflow))) {\n // 检测是否需要省略号,因为会有多行同时省略的情况\n let emptyOverflow = true;\n let skipEllipsis = false;\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if ((paragraph as Paragraph).overflow) {\n emptyOverflow = emptyOverflow && (paragraph as Paragraph).text === '';\n } else {\n if (emptyOverflow) {\n skipEllipsis = true;\n break;\n }\n }\n }\n\n // 处理省略号\n let otherParagraphWidth = 0;\n if (!skipEllipsis) {\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if ((paragraph as Paragraph).overflow) {\n if ((paragraph as Paragraph).text === '') {\n break;\n }\n continue;\n }\n if (paragraph instanceof RichTextIcon) {\n break; // todo: 处理最后为图标,显示省略号的情况\n }\n if (this.direction === 'vertical' && paragraph.direction !== 'vertical') {\n paragraph.verticalEllipsis = true;\n break;\n }\n const ellipsis = drawEllipsis === true ? '...' : drawEllipsis || '';\n paragraph.ellipsisStr = ellipsis;\n // const { width } = measureText('...', paragraph.style);\n const { width } = measureTextCanvas(ellipsis, paragraph.character);\n const ellipsisWidth = width || 0;\n if (ellipsisWidth <= this.blankWidth + otherParagraphWidth) {\n // 省略号可以直接接在后面paragraph\n lastLine && (paragraph.ellipsis = 'add');\n\n break;\n } else if (ellipsisWidth <= this.blankWidth + otherParagraphWidth + paragraph.width) {\n // 省略号需要替换paragraph中的字符\n paragraph.ellipsis = 'replace';\n paragraph.ellipsisWidth = ellipsisWidth;\n paragraph.ellipsisOtherParagraphWidth = this.blankWidth + otherParagraphWidth;\n\n break;\n } else {\n // 省略号需要的width大于paragraph的width,隐藏paragraph,向前搜索\n paragraph.ellipsis = 'hide';\n otherParagraphWidth += paragraph.width;\n }\n }\n }\n }\n\n // 正常绘制\n this.paragraphs.forEach((paragraph, index) => {\n if (paragraph instanceof RichTextIcon) {\n // 更新icon位置\n paragraph.setAttributes({\n x: x + paragraph._x,\n y: y + paragraph._y\n });\n\n // 绘制icon\n drawIcon(paragraph, ctx, x + paragraph._x, y + paragraph._y, this.ascent);\n return;\n }\n const b = {\n x1: this.left,\n y1: this.top,\n x2: this.left + this.actualWidth,\n y2: this.top + this.height\n };\n applyStrokeStyle(ctx, paragraph.character);\n // 下面绘制underline和line-through时需要设置FillStyle\n applyFillStyle(ctx, paragraph.character, b);\n paragraph.draw(ctx, y, this.ascent, x, index === 0, this.textAlign, this.height);\n });\n }\n\n getWidthWithEllips(ellipsis: string) {\n // 处理省略号\n let otherParagraphWidth = 0;\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if (paragraph instanceof RichTextIcon) {\n break; // todo: 处理最后为图标,显示省略号的情况\n }\n\n const { width } = measureTextCanvas(ellipsis, paragraph.character);\n const ellipsisWidth = width || 0;\n if (ellipsisWidth <= this.blankWidth + otherParagraphWidth) {\n // 省略号可以直接接在后面paragraph\n paragraph.ellipsis = 'add';\n paragraph.ellipsisWidth = ellipsisWidth;\n break;\n } else if (ellipsisWidth <= this.blankWidth + otherParagraphWidth + paragraph.width) {\n // 省略号需要替换paragraph中的字符\n paragraph.ellipsis = 'replace';\n paragraph.ellipsisWidth = ellipsisWidth;\n paragraph.ellipsisOtherParagraphWidth = this.blankWidth + otherParagraphWidth;\n\n break;\n } else {\n // 省略号需要的width大于paragraph的width,隐藏paragraph,向前搜索\n paragraph.ellipsis = 'hide';\n otherParagraphWidth += paragraph.width;\n }\n }\n\n let width = 0;\n // 正常绘制\n this.paragraphs.forEach((paragraph, index) => {\n if (paragraph instanceof RichTextIcon) {\n width += paragraph.width; // todo: 处理direction\n } else {\n width += paragraph.getWidthWithEllips(this.direction);\n }\n });\n\n return width;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/graphic/richtext/line.ts"],"names":[],"mappings":"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","file":"line.js","sourcesContent":["// import { IContext2d } from '../../IContext';\nimport type { IContext2d, IRichTextIcon } from '../../interface';\nimport { RichTextIcon } from './icon';\nimport Paragraph from './paragraph';\nimport { applyFillStyle, applyStrokeStyle, DIRECTION_KEY, measureTextCanvas, regFirstSpace } from './utils';\n\n/**\n * 部分代码参考 https://github.com/danielearwicker/carota/\n * The MIT License (MIT)\n\n \"Carota\" - Copyright (c) 2013 Daniel Earwicker\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n */\n\n// 行\n// 参考carota\n// https://github.com/danielearwicker/carota/blob/master/src/line.js\nexport default class Line {\n left: number;\n top: number;\n width: number;\n height: number;\n baseline: number;\n ascent: number;\n descent: number;\n paragraphs: (Paragraph | RichTextIcon)[];\n actualWidth: number;\n blankWidth: number;\n textAlign: string;\n direction: 'horizontal' | 'vertical';\n directionKey: { width: string; height: string; left: string; x: string; y: string };\n\n constructor(\n left: number,\n width: number,\n baseline: number,\n ascent: number,\n descent: number,\n lineBuffer: (Paragraph | RichTextIcon)[],\n direction: 'horizontal' | 'vertical',\n isWidthMax: boolean\n ) {\n this.left = left;\n this.width = width;\n this.baseline = baseline;\n this.ascent = ascent;\n this.descent = descent;\n // this.height = ascent + descent;\n this.top = baseline - ascent;\n this.paragraphs = lineBuffer.map(p => p);\n this.textAlign =\n (this.paragraphs[0] instanceof RichTextIcon\n ? this.paragraphs[0].attribute.textAlign\n : this.paragraphs[0].character.textAlign) || 'left'; // 对齐方式选择第一个paragraph属性\n this.direction = direction;\n this.directionKey = DIRECTION_KEY[this.direction];\n\n this.actualWidth = 0;\n let maxHeight = 0;\n this.paragraphs.forEach((word, index) => {\n // 每行中第一个字符不能是空格\n if (index === 0 && word instanceof Paragraph) {\n const result = regFirstSpace.exec(word.text);\n if (result?.index !== 0) {\n word.text = word.text.slice(result?.index);\n word.updateWidth();\n }\n }\n this.actualWidth += word[this.directionKey.width];\n maxHeight = Math.max(word[this.directionKey.height], maxHeight);\n });\n this.height = maxHeight;\n\n this.blankWidth = !isWidthMax ? this.width - this.actualWidth : 0;\n\n this.calcOffset(width, isWidthMax);\n }\n\n calcOffset(width: number, isWidthMax: boolean) {\n // 处理对齐方式,计算左侧偏移距离和字符之间间距\n const directionKey = this.directionKey;\n const maxHeight = this.height;\n let x = this.left;\n let spacing = 0;\n if (this.actualWidth < width && !isWidthMax) {\n if (this.textAlign === 'right' || this.textAlign === 'end') {\n x = width - this.actualWidth;\n } else if (this.textAlign === 'center') {\n x = (width - this.actualWidth) / 2;\n } else if (this.textAlign === 'justify') {\n if (this.paragraphs.length < 2) {\n // 只有一个paragraph两端对齐居中显示\n x = (width - this.actualWidth) / 2;\n } else {\n spacing = (width - this.actualWidth) / (this.paragraphs.length - 1);\n }\n }\n }\n\n this.paragraphs.map(function (paragraph) {\n if (paragraph instanceof RichTextIcon) {\n // paragraph.setAttribute(directionKey.x, x);\n paragraph['_' + directionKey.x] = x;\n x += paragraph[directionKey.width] + spacing;\n // 处理纵向对齐\n paragraph['_' + directionKey.y] =\n paragraph.attribute.textBaseline === 'top'\n ? 0\n : paragraph.attribute.textBaseline === 'bottom'\n ? maxHeight - paragraph.height\n : (maxHeight - paragraph.height) / 2;\n } else {\n paragraph[directionKey.left] = x;\n x += paragraph[directionKey.width] + spacing;\n }\n });\n }\n\n draw(\n ctx: IContext2d,\n lastLine: boolean,\n x: number,\n y: number,\n drawEllipsis: boolean | string,\n drawIcon: (icon: IRichTextIcon, context: IContext2d, x: number, y: number, baseline: number) => void\n ) {\n if (drawEllipsis && (lastLine || this.paragraphs.some(p => (p as Paragraph).overflow))) {\n // 检测是否需要省略号,因为会有多行同时省略的情况\n let emptyOverflow = true;\n let skipEllipsis = false;\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if ((paragraph as Paragraph).overflow) {\n emptyOverflow = emptyOverflow && (paragraph as Paragraph).text === '';\n } else {\n if (emptyOverflow) {\n skipEllipsis = true;\n break;\n }\n }\n }\n\n // 处理省略号\n let otherParagraphWidth = 0;\n if (!skipEllipsis) {\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if ((paragraph as Paragraph).overflow) {\n if ((paragraph as Paragraph).text === '') {\n break;\n }\n continue;\n }\n if (paragraph instanceof RichTextIcon) {\n break; // todo: 处理最后为图标,显示省略号的情况\n }\n if (this.direction === 'vertical' && paragraph.direction !== 'vertical') {\n paragraph.verticalEllipsis = true;\n break;\n }\n const ellipsis = drawEllipsis === true ? '...' : drawEllipsis || '';\n paragraph.ellipsisStr = ellipsis;\n // const { width } = measureText('...', paragraph.style);\n const { width } = measureTextCanvas(ellipsis, paragraph.character);\n const ellipsisWidth = width || 0;\n if (ellipsisWidth <= this.blankWidth + otherParagraphWidth) {\n // 省略号可以直接接在后面paragraph\n lastLine && (paragraph.ellipsis = 'add');\n\n break;\n } else if (ellipsisWidth <= this.blankWidth + otherParagraphWidth + paragraph.width) {\n // 省略号需要替换paragraph中的字符\n paragraph.ellipsis = 'replace';\n paragraph.ellipsisWidth = ellipsisWidth;\n paragraph.ellipsisOtherParagraphWidth = this.blankWidth + otherParagraphWidth;\n\n break;\n } else {\n // 省略号需要的width大于paragraph的width,隐藏paragraph,向前搜索\n paragraph.ellipsis = 'hide';\n otherParagraphWidth += paragraph.width;\n }\n }\n }\n }\n\n // 绘制背景\n this.paragraphs.forEach((paragraph, index) => {\n if (paragraph instanceof RichTextIcon) {\n return;\n }\n paragraph.drawBackground(ctx, y, this.ascent, x, index === 0, this.textAlign, this.height);\n });\n // 正常绘制\n this.paragraphs.forEach((paragraph, index) => {\n if (paragraph instanceof RichTextIcon) {\n // 更新icon位置\n paragraph.setAttributes({\n x: x + paragraph._x,\n y: y + paragraph._y\n });\n\n // 绘制icon\n drawIcon(paragraph, ctx, x + paragraph._x, y + paragraph._y, this.ascent);\n return;\n }\n const b = {\n x1: this.left,\n y1: this.top,\n x2: this.left + this.actualWidth,\n y2: this.top + this.height\n };\n applyStrokeStyle(ctx, paragraph.character);\n // 下面绘制underline和line-through时需要设置FillStyle\n applyFillStyle(ctx, paragraph.character, b);\n paragraph.draw(ctx, y, this.ascent, x, index === 0, this.textAlign, this.height);\n });\n }\n\n getWidthWithEllips(ellipsis: string) {\n // 处理省略号\n let otherParagraphWidth = 0;\n for (let i = this.paragraphs.length - 1; i >= 0; i--) {\n const paragraph = this.paragraphs[i];\n if (paragraph instanceof RichTextIcon) {\n break; // todo: 处理最后为图标,显示省略号的情况\n }\n\n const { width } = measureTextCanvas(ellipsis, paragraph.character);\n const ellipsisWidth = width || 0;\n if (ellipsisWidth <= this.blankWidth + otherParagraphWidth) {\n // 省略号可以直接接在后面paragraph\n paragraph.ellipsis = 'add';\n paragraph.ellipsisWidth = ellipsisWidth;\n break;\n } else if (ellipsisWidth <= this.blankWidth + otherParagraphWidth + paragraph.width) {\n // 省略号需要替换paragraph中的字符\n paragraph.ellipsis = 'replace';\n paragraph.ellipsisWidth = ellipsisWidth;\n paragraph.ellipsisOtherParagraphWidth = this.blankWidth + otherParagraphWidth;\n\n break;\n } else {\n // 省略号需要的width大于paragraph的width,隐藏paragraph,向前搜索\n paragraph.ellipsis = 'hide';\n otherParagraphWidth += paragraph.width;\n }\n }\n\n let width = 0;\n // 正常绘制\n this.paragraphs.forEach((paragraph, index) => {\n if (paragraph instanceof RichTextIcon) {\n width += paragraph.width; // todo: 处理direction\n } else {\n width += paragraph.getWidthWithEllips(this.direction);\n }\n });\n\n return width;\n }\n}\n"]}
@@ -24,6 +24,7 @@ export default class Paragraph {
24
24
  overflow?: boolean;
25
25
  constructor(text: string, newLine: boolean, character: IRichTextParagraphCharacter);
26
26
  updateWidth(): void;
27
+ drawBackground(ctx: IContext2d, top: number, ascent: number, deltaLeft: number, isLineFirst: boolean, textAlign: string, lineHeight: number): void;
27
28
  draw(ctx: IContext2d, top: number, ascent: number, deltaLeft: number, isLineFirst: boolean, textAlign: string, lineHeight: number): void;
28
29
  getWidthWithEllips(direction: string): number;
29
30
  }
@@ -36,7 +36,8 @@ export default class Paragraph {
36
36
  this.width = width, "vertical" === this.direction && (this.widthOrigin = this.width,
37
37
  this.width = this.heightOrigin, this.height = this.widthOrigin);
38
38
  }
39
- draw(ctx, top, ascent, deltaLeft, isLineFirst, textAlign, lineHeight) {
39
+ drawBackground(ctx, top, ascent, deltaLeft, isLineFirst, textAlign, lineHeight) {
40
+ if (!this.character.background || this.character.backgroundOpacity && !(this.character.backgroundOpacity > 0)) return;
40
41
  let baseline = top + ascent, text = this.text, left = this.left + deltaLeft;
41
42
  baseline += this.top;
42
43
  let direction = this.direction;
@@ -58,15 +59,40 @@ export default class Paragraph {
58
59
  case "sub":
59
60
  baseline += this.descent / 2;
60
61
  }
61
- if ("vertical" === direction && (ctx.save(), ctx.rotateAbout(Math.PI / 2, left, baseline),
62
+ "vertical" === direction && (ctx.save(), ctx.rotateAbout(Math.PI / 2, left, baseline),
62
63
  ctx.translate(-this.heightOrigin || -this.lineHeight / 2, -this.descent / 2), ctx.translate(left, baseline),
63
- left = 0, baseline = 0), this.character.fill && this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0)) {
64
- const fillStyle = ctx.fillStyle, globalAlpha = ctx.globalAlpha;
65
- ctx.fillStyle = this.character.background, void 0 !== this.character.backgroundOpacity && (ctx.globalAlpha = this.character.backgroundOpacity);
66
- const lrtb = getFixedLRTB(left, left + (this.widthOrigin || this.width), top, top + lineHeight);
67
- ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top),
68
- ctx.fillStyle = fillStyle, ctx.globalAlpha = globalAlpha;
64
+ left = 0, baseline = 0);
65
+ const fillStyle = ctx.fillStyle, globalAlpha = ctx.globalAlpha;
66
+ ctx.fillStyle = this.character.background, void 0 !== this.character.backgroundOpacity && (ctx.globalAlpha = this.character.backgroundOpacity);
67
+ const lrtb = getFixedLRTB(left, left + (this.widthOrigin || this.width), top, top + lineHeight);
68
+ ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top),
69
+ ctx.fillStyle = fillStyle, ctx.globalAlpha = globalAlpha;
70
+ }
71
+ draw(ctx, top, ascent, deltaLeft, isLineFirst, textAlign, lineHeight) {
72
+ let baseline = top + ascent, text = this.text, left = this.left + deltaLeft;
73
+ baseline += this.top;
74
+ let direction = this.direction;
75
+ if (this.verticalEllipsis) text = this.ellipsisStr, direction = "vertical", baseline -= this.ellipsisWidth / 2; else {
76
+ if ("hide" === this.ellipsis) return;
77
+ if ("add" === this.ellipsis) text += this.ellipsisStr, "right" !== textAlign && "end" !== textAlign || (left -= this.ellipsisWidth); else if ("replace" === this.ellipsis) {
78
+ const index = getStrByWithCanvas(text, ("vertical" === direction ? this.height : this.width) - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.character, text.length - 1);
79
+ if (text = text.slice(0, index), text += this.ellipsisStr, "right" === textAlign || "end" === textAlign) {
80
+ const {width: width} = measureTextCanvas(this.text.slice(index), this.character);
81
+ "vertical" === direction || (left -= this.ellipsisWidth - width);
82
+ }
83
+ }
84
+ }
85
+ switch (this.character.script) {
86
+ case "super":
87
+ baseline -= this.ascent * (1 / 3);
88
+ break;
89
+
90
+ case "sub":
91
+ baseline += this.descent / 2;
69
92
  }
93
+ "vertical" === direction && (ctx.save(), ctx.rotateAbout(Math.PI / 2, left, baseline),
94
+ ctx.translate(-this.heightOrigin || -this.lineHeight / 2, -this.descent / 2), ctx.translate(left, baseline),
95
+ left = 0, baseline = 0);
70
96
  const {lineWidth: lineWidth = 1} = this.character;
71
97
  if (this.character.stroke && lineWidth && ctx.strokeText(text, left, baseline),
72
98
  this.character.fill && ctx.fillText(text, left, baseline), this.character.fill) if (this.character.lineThrough || this.character.underline) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/graphic/richtext/paragraph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAEhE,SAAS,YAAY,CAAC,IAAY,EAAE,KAAa,EAAE,GAAW,EAAE,MAAc;IAC5E,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC;IACvD,MAAM,IAAI,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC;IAClD,MAAM,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC;IAC5D,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC;IACjE,OAAO;QACL,IAAI,EAAE,KAAK;QACX,GAAG,EAAE,IAAI;QACT,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,OAAO;KAChB,CAAC;AACJ,CAAC;AA8BD,MAAM,CAAC,OAAO,OAAO,SAAS;IA2B5B,YAAY,IAAY,EAAE,OAAgB,EAAE,SAAsC;QAEhF,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAC;QACzC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC,YAAY,IAAI,YAAY,CAAC;QAK3D,MAAM,UAAU,GAAG,mBAAmB,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5E,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE;YAClC,IAAI,CAAC,UAAU,GAAG,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;SAC3E;aAAM;YACL,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;SACnD;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;QAE9B,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAE9E,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,EAAE;YAGxB,cAAc,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YAC5C,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACxC,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;SAC3C;QAED,IAAI,IAAI,CAAC,YAAY,KAAK,KAAK,EAAE;YAC/B,IAAI,CAAC,MAAM,GAAG,cAAc,CAAC;YAC7B,IAAI,CAAC,OAAO,GAAG,MAAM,GAAG,cAAc,CAAC;SACxC;aAAM,IAAI,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE;YACzC,IAAI,CAAC,MAAM,GAAG,MAAM,GAAG,cAAc,CAAC;YACtC,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC;SAC/B;aAAM,IAAI,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE;YACzC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;SAChC;aAAM;YACL,IAAI,CAAC,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC;YACnC,IAAI,CAAC,OAAO,GAAG,OAAO,GAAG,YAAY,CAAC;SACvC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,KAAK,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAE3B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;QAEb,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,2BAA2B,GAAG,CAAC,CAAC;QAGrC,IAAI,SAAS,CAAC,SAAS,KAAK,UAAU,EAAE;YACtC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;YACrC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC;YAC9B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC;YAOhC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC;YAC/B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC;YAC/B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;SAC/B;QACD,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC3B,CAAC;IAED,WAAW;QACT,MAAM,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,IAAI,CAAC,SAAS,KAAK,UAAU,EAAE;YACjC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC;YAC9B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC;YAC/B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC;SAChC;IACH,CAAC;IAED,IAAI,CACF,GAAe,EACf,GAAW,EACX,MAAc,EACd,SAAiB,EACjB,WAAoB,EACpB,SAAiB,EACjB,UAAkB;QAElB,IAAI,QAAQ,GAAG,GAAG,GAAG,MAAM,CAAC;QAC5B,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACrB,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;QACjC,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC;QACrB,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAE/B,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACzB,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;YACxB,SAAS,GAAG,UAAU,CAAC;YACvB,QAAQ,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;SACpC;aAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,EAAE;YACnC,OAAO;SACR;aAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,EAAE;YAClC,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC;YAEzB,IAAI,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK,KAAK,EAAE;gBAChD,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC;aAC5B;SACF;aAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE;YAGtC,MAAM,KAAK,GAAG,kBAAkB,CAC9B,IAAI,EACJ,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,2BAA2B,EAC7G,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,MAAM,GAAG,CAAC,CAChB,CAAC;YACF,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YAC5B,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC;YAEzB,IAAI,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK,KAAK,EAAE;gBAChD,MAAM,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC5E,IAAI,SAAS,KAAK,UAAU,EAAE;iBAE7B;qBAAM;oBACL,IAAI,IAAI,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;iBACpC;aACF;SACF;QAGD,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE;YAC7B,KAAK,OAAO;gBACV,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClC,MAAM;YACR,KAAK,KAAK;gBACR,QAAQ,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;gBAC7B,MAAM;SACT;QAUD,IAAI,SAAS,KAAK,UAAU,EAAE;YAC5B,GAAG,CAAC,IAAI,EAAE,CAAC;YACX,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC7C,GAAG,CAAC,SAAS,CAAC,CAAE,IAAI,CAAC,YAAuB,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;YACzF,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC9B,IAAI,GAAG,CAAC,CAAC;YACT,QAAQ,GAAG,CAAC,CAAC;SACd;QAED,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;YACvB,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,IAAI,IAAI,CAAC,SAAS,CAAC,iBAAiB,GAAG,CAAC,CAAC,EAAE;gBAC5G,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC;gBAChC,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;gBACpC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;gBAC1C,IAAI,IAAI,CAAC,SAAS,CAAC,iBAAiB,KAAK,KAAK,CAAC,EAAE;oBAC/C,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC;iBACpD;gBAED,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;gBACtD,MAAM,MAAM,GAAG,GAAG,GAAG,UAAU,CAAC;gBAChC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;gBACpD,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;gBAClF,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;gBAC1B,GAAG,CAAC,WAAW,GAAG,WAAW,CAAC;aAC/B;SACF;QAED,MAAM,EAAE,SAAS,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;QACzC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,SAAS,EAAE;YACtC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;SACtC;QAED,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;YACvB,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;SACpC;QAED,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;YACvB,IAAI,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE;gBAC1D,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE;oBAC5B,MAAM,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;oBACzB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;oBACtD,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC3G,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;oBACpD,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;iBACnF;gBACD,IAAI,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;oBAC9B,MAAM,GAAG,GAAG,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;oBAC3C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;oBACtD,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC3G,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;oBACpD,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;iBACnF;aACF;iBAAM,IAAI,IAAI,CAAC,SAAS,CAAC,cAAc,KAAK,WAAW,EAAE;gBACxD,MAAM,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;gBACzB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;gBACtD,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3G,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;gBACpD,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;aACnF;iBAAM,IAAI,IAAI,CAAC,SAAS,CAAC,cAAc,KAAK,cAAc,EAAE;gBAC3D,MAAM,GAAG,GAAG,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC3C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;gBACtD,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3G,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;gBACpD,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;aACnF;SACF;QAED,IAAI,SAAS,KAAK,UAAU,EAAE;YAC5B,GAAG,CAAC,OAAO,EAAE,CAAC;SACf;IACH,CAAC;IAED,kBAAkB,CAAC,SAAiB;QAClC,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QAErB,MAAM,KAAK,GAAG,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;QAGlE,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,EAAE;YAC5B,OAAO,KAAK,CAAC;SACd;aAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,EAAE;YAClC,OAAO,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC;SACnC;aAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE;YAGtC,MAAM,KAAK,GAAG,kBAAkB,CAC9B,IAAI,EACJ,KAAK,GAAG,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,2BAA2B,EAC7D,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,MAAM,GAAG,CAAC,CAChB,CAAC;YACF,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YAC5B,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC;YAEzB,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1F,OAAO,KAAK,GAAG,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;SAClD;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAoB,EAAE,KAAa;IACnE,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACxE,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAE3D,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC","file":"paragraph.js","sourcesContent":["import { calculateLineHeight } from '../../common/utils';\nimport type { IContext2d, IRichTextParagraphCharacter } from '../../interface';\nimport { measureTextCanvas, getStrByWithCanvas } from './utils';\n\nfunction getFixedLRTB(left: number, right: number, top: number, bottom: number) {\n const leftInt = Math.round(left);\n const topInt = Math.round(top);\n const rightInt = Math.round(right);\n const bottomInt = Math.round(bottom);\n const _left = left > leftInt ? leftInt : leftInt - 0.5;\n const _top = top > topInt ? topInt : topInt - 0.5;\n const _right = rightInt > right ? rightInt : rightInt + 0.5;\n const _bottom = bottomInt > bottom ? bottomInt : bottomInt + 0.5;\n return {\n left: _left,\n top: _top,\n right: _right,\n bottom: _bottom\n };\n}\n\n/**\n * 部分代码参考 https://github.com/danielearwicker/carota/\n * The MIT License (MIT)\n\n \"Carota\" - Copyright (c) 2013 Daniel Earwicker\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n */\n\n// 文字段\n// 参考carota\n// https://github.com/danielearwicker/carota/blob/master/src/text.js\nexport default class Paragraph {\n text: string;\n ascent: number;\n descent: number;\n width: number;\n height: number;\n lineHeight: number;\n fontSize: number;\n length: number;\n newLine: boolean;\n character: IRichTextParagraphCharacter;\n left: number;\n top: number;\n // rotate?: number;\n direction?: 'horizontal' | 'vertical';\n // bounds?: Bounds;\n widthOrigin?: number;\n heightOrigin?: number;\n textBaseline?: CanvasTextBaseline;\n\n ellipsis: 'normal' | 'add' | 'replace' | 'hide';\n ellipsisStr: string;\n ellipsisWidth: number;\n ellipsisOtherParagraphWidth: number;\n verticalEllipsis?: boolean;\n overflow?: boolean;\n\n constructor(text: string, newLine: boolean, character: IRichTextParagraphCharacter) {\n // 测量文字\n this.fontSize = character.fontSize || 16;\n this.textBaseline = character.textBaseline || 'alphabetic';\n\n // 处理行高:\n // lineHeight为数字时,大于fontSize取lineHeight,小于fontSize时取fontSize\n // lineHeight不为数字时,统一认为lineHeight为'normal',值取1.2 * fontSize\n const lineHeight = calculateLineHeight(character.lineHeight, this.fontSize);\n if (typeof lineHeight === 'number') {\n this.lineHeight = lineHeight > this.fontSize ? lineHeight : this.fontSize;\n } else {\n this.lineHeight = Math.floor(1.2 * this.fontSize);\n }\n\n this.height = this.lineHeight;\n\n const { ascent, height, descent, width } = measureTextCanvas(text, character);\n\n let halfDetaHeight = 0;\n let deltaAscent = 0;\n let deltaDescent = 0;\n if (this.height > height) {\n // measureTextCanvas测量出的是纯文字高度,this.height是考虑行高后的高度\n // 如果this.height > height,将超过的高度平均分配到ascent和descent上\n halfDetaHeight = (this.height - height) / 2;\n deltaAscent = Math.ceil(halfDetaHeight);\n deltaDescent = Math.floor(halfDetaHeight);\n }\n\n if (this.textBaseline === 'top') {\n this.ascent = halfDetaHeight;\n this.descent = height - halfDetaHeight;\n } else if (this.textBaseline === 'bottom') {\n this.ascent = height - halfDetaHeight;\n this.descent = halfDetaHeight;\n } else if (this.textBaseline === 'middle') {\n this.ascent = this.height / 2;\n this.descent = this.height / 2;\n } else {\n this.ascent = ascent + deltaAscent;\n this.descent = descent + deltaDescent;\n }\n\n this.length = text.length;\n this.width = width || 0;\n this.text = text || '';\n this.newLine = newLine || false;\n this.character = character;\n\n this.left = 0;\n this.top = 0;\n\n this.ellipsis = 'normal';\n this.ellipsisWidth = 0;\n this.ellipsisOtherParagraphWidth = 0;\n\n // 处理旋转\n if (character.direction === 'vertical') {\n this.direction = character.direction;\n this.widthOrigin = this.width;\n this.heightOrigin = this.height;\n // const bounds = new Bounds();\n // bounds.set(0, 0, this.width, this.height);\n // bounds.rotate(Math.PI / 2, this.width / 2, this.height / 2);\n // this.bounds = bounds;\n // this.width = bounds.width();\n // this.height = bounds.height();\n this.width = this.heightOrigin;\n this.height = this.widthOrigin;\n this.lineHeight = this.height;\n }\n this.ellipsisStr = '...';\n }\n\n updateWidth() {\n const { width } = measureTextCanvas(this.text, this.character);\n this.width = width;\n if (this.direction === 'vertical') {\n this.widthOrigin = this.width;\n this.width = this.heightOrigin;\n this.height = this.widthOrigin;\n }\n }\n\n draw(\n ctx: IContext2d,\n top: number,\n ascent: number,\n deltaLeft: number,\n isLineFirst: boolean,\n textAlign: string,\n lineHeight: number\n ) {\n let baseline = top + ascent;\n let text = this.text;\n let left = this.left + deltaLeft;\n baseline += this.top;\n let direction = this.direction;\n\n if (this.verticalEllipsis) {\n text = this.ellipsisStr;\n direction = 'vertical';\n baseline -= this.ellipsisWidth / 2;\n } else if (this.ellipsis === 'hide') {\n return;\n } else if (this.ellipsis === 'add') {\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n left -= this.ellipsisWidth;\n }\n } else if (this.ellipsis === 'replace') {\n // 找到需要截断的字符长度\n // const index = getStrByWith(text, this.width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.style, text.length - 1);\n const index = getStrByWithCanvas(\n text,\n (direction === 'vertical' ? this.height : this.width) - this.ellipsisWidth + this.ellipsisOtherParagraphWidth,\n this.character,\n text.length - 1\n );\n text = text.slice(0, index);\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n const { width } = measureTextCanvas(this.text.slice(index), this.character);\n if (direction === 'vertical') {\n // baseline -= this.ellipsisWidth - width;\n } else {\n left -= this.ellipsisWidth - width;\n }\n }\n }\n\n // prepareContext(ctx);\n switch (this.character.script) {\n case 'super':\n baseline -= this.ascent * (1 / 3);\n break;\n case 'sub':\n baseline += this.descent / 2;\n break;\n }\n\n // if (isLineFirst) {\n // const result = regFirstSpace.exec(text);\n // if (result?.index !== 0) {\n // text = text.slice(result?.index);\n // }\n // }\n\n // 处理旋转\n if (direction === 'vertical') {\n ctx.save();\n ctx.rotateAbout(Math.PI / 2, left, baseline);\n ctx.translate(-(this.heightOrigin as number) || -this.lineHeight / 2, -this.descent / 2);\n ctx.translate(left, baseline);\n left = 0;\n baseline = 0;\n }\n\n if (this.character.fill) {\n if (this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0)) {\n const fillStyle = ctx.fillStyle;\n const globalAlpha = ctx.globalAlpha;\n ctx.fillStyle = this.character.background;\n if (this.character.backgroundOpacity !== void 0) {\n ctx.globalAlpha = this.character.backgroundOpacity;\n }\n // 背景稍微扩充一些buf,否则会出现白线\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + lineHeight;\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n ctx.fillStyle = fillStyle;\n ctx.globalAlpha = globalAlpha;\n }\n }\n\n const { lineWidth = 1 } = this.character;\n if (this.character.stroke && lineWidth) {\n ctx.strokeText(text, left, baseline);\n }\n\n if (this.character.fill) {\n ctx.fillText(text, left, baseline);\n }\n\n if (this.character.fill) {\n if (this.character.lineThrough || this.character.underline) {\n if (this.character.underline) {\n const top = 1 + baseline;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n if (this.character.lineThrough) {\n const top = 1 + baseline - this.ascent / 2;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n } else if (this.character.textDecoration === 'underline') {\n const top = 1 + baseline;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n } else if (this.character.textDecoration === 'line-through') {\n const top = 1 + baseline - this.ascent / 2;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n }\n\n if (direction === 'vertical') {\n ctx.restore();\n }\n }\n\n getWidthWithEllips(direction: string): number {\n let text = this.text;\n // const direction = this.direction;\n const width = direction === 'vertical' ? this.height : this.width;\n // const height = direction === 'vertical' ? this.width: this.height;\n\n if (this.ellipsis === 'hide') {\n return width;\n } else if (this.ellipsis === 'add') {\n return width + this.ellipsisWidth;\n } else if (this.ellipsis === 'replace') {\n // 找到需要截断的字符长度\n // const index = getStrByWith(text, width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.style, text.length - 1);\n const index = getStrByWithCanvas(\n text,\n width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth,\n this.character,\n text.length - 1\n );\n text = text.slice(0, index);\n text += this.ellipsisStr;\n\n const { width: measureWidth } = measureTextCanvas(this.text.slice(index), this.character);\n return width + this.ellipsisWidth - measureWidth;\n }\n return width;\n }\n}\n\nexport function seperateParagraph(paragraph: Paragraph, index: number) {\n const text1 = paragraph.text.slice(0, index);\n const text2 = paragraph.text.slice(index);\n const p1 = new Paragraph(text1, paragraph.newLine, paragraph.character);\n const p2 = new Paragraph(text2, true, paragraph.character);\n\n return [p1, p2];\n}\n"]}
1
+ {"version":3,"sources":["../src/graphic/richtext/paragraph.ts"],"names":[],"mappings":"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","file":"paragraph.js","sourcesContent":["import { calculateLineHeight } from '../../common/utils';\nimport type { IContext2d, IRichTextParagraphCharacter } from '../../interface';\nimport { measureTextCanvas, getStrByWithCanvas } from './utils';\n\nfunction getFixedLRTB(left: number, right: number, top: number, bottom: number) {\n const leftInt = Math.round(left);\n const topInt = Math.round(top);\n const rightInt = Math.round(right);\n const bottomInt = Math.round(bottom);\n const _left = left > leftInt ? leftInt : leftInt - 0.5;\n const _top = top > topInt ? topInt : topInt - 0.5;\n const _right = rightInt > right ? rightInt : rightInt + 0.5;\n const _bottom = bottomInt > bottom ? bottomInt : bottomInt + 0.5;\n return {\n left: _left,\n top: _top,\n right: _right,\n bottom: _bottom\n };\n}\n\n/**\n * 部分代码参考 https://github.com/danielearwicker/carota/\n * The MIT License (MIT)\n\n \"Carota\" - Copyright (c) 2013 Daniel Earwicker\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n */\n\n// 文字段\n// 参考carota\n// https://github.com/danielearwicker/carota/blob/master/src/text.js\nexport default class Paragraph {\n text: string;\n ascent: number;\n descent: number;\n width: number;\n height: number;\n lineHeight: number;\n fontSize: number;\n length: number;\n newLine: boolean;\n character: IRichTextParagraphCharacter;\n left: number;\n top: number;\n // rotate?: number;\n direction?: 'horizontal' | 'vertical';\n // bounds?: Bounds;\n widthOrigin?: number;\n heightOrigin?: number;\n textBaseline?: CanvasTextBaseline;\n\n ellipsis: 'normal' | 'add' | 'replace' | 'hide';\n ellipsisStr: string;\n ellipsisWidth: number;\n ellipsisOtherParagraphWidth: number;\n verticalEllipsis?: boolean;\n overflow?: boolean;\n\n constructor(text: string, newLine: boolean, character: IRichTextParagraphCharacter) {\n // 测量文字\n this.fontSize = character.fontSize || 16;\n this.textBaseline = character.textBaseline || 'alphabetic';\n\n // 处理行高:\n // lineHeight为数字时,大于fontSize取lineHeight,小于fontSize时取fontSize\n // lineHeight不为数字时,统一认为lineHeight为'normal',值取1.2 * fontSize\n const lineHeight = calculateLineHeight(character.lineHeight, this.fontSize);\n if (typeof lineHeight === 'number') {\n this.lineHeight = lineHeight > this.fontSize ? lineHeight : this.fontSize;\n } else {\n this.lineHeight = Math.floor(1.2 * this.fontSize);\n }\n\n this.height = this.lineHeight;\n\n const { ascent, height, descent, width } = measureTextCanvas(text, character);\n\n let halfDetaHeight = 0;\n let deltaAscent = 0;\n let deltaDescent = 0;\n if (this.height > height) {\n // measureTextCanvas测量出的是纯文字高度,this.height是考虑行高后的高度\n // 如果this.height > height,将超过的高度平均分配到ascent和descent上\n halfDetaHeight = (this.height - height) / 2;\n deltaAscent = Math.ceil(halfDetaHeight);\n deltaDescent = Math.floor(halfDetaHeight);\n }\n\n if (this.textBaseline === 'top') {\n this.ascent = halfDetaHeight;\n this.descent = height - halfDetaHeight;\n } else if (this.textBaseline === 'bottom') {\n this.ascent = height - halfDetaHeight;\n this.descent = halfDetaHeight;\n } else if (this.textBaseline === 'middle') {\n this.ascent = this.height / 2;\n this.descent = this.height / 2;\n } else {\n this.ascent = ascent + deltaAscent;\n this.descent = descent + deltaDescent;\n }\n\n this.length = text.length;\n this.width = width || 0;\n this.text = text || '';\n this.newLine = newLine || false;\n this.character = character;\n\n this.left = 0;\n this.top = 0;\n\n this.ellipsis = 'normal';\n this.ellipsisWidth = 0;\n this.ellipsisOtherParagraphWidth = 0;\n\n // 处理旋转\n if (character.direction === 'vertical') {\n this.direction = character.direction;\n this.widthOrigin = this.width;\n this.heightOrigin = this.height;\n // const bounds = new Bounds();\n // bounds.set(0, 0, this.width, this.height);\n // bounds.rotate(Math.PI / 2, this.width / 2, this.height / 2);\n // this.bounds = bounds;\n // this.width = bounds.width();\n // this.height = bounds.height();\n this.width = this.heightOrigin;\n this.height = this.widthOrigin;\n this.lineHeight = this.height;\n }\n this.ellipsisStr = '...';\n }\n\n updateWidth() {\n const { width } = measureTextCanvas(this.text, this.character);\n this.width = width;\n if (this.direction === 'vertical') {\n this.widthOrigin = this.width;\n this.width = this.heightOrigin;\n this.height = this.widthOrigin;\n }\n }\n\n drawBackground(\n ctx: IContext2d,\n top: number,\n ascent: number,\n deltaLeft: number,\n isLineFirst: boolean,\n textAlign: string,\n lineHeight: number\n ) {\n if (!(this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0))) {\n return;\n }\n let baseline = top + ascent;\n let text = this.text;\n let left = this.left + deltaLeft;\n baseline += this.top;\n let direction = this.direction;\n\n if (this.verticalEllipsis) {\n text = this.ellipsisStr;\n direction = 'vertical';\n baseline -= this.ellipsisWidth / 2;\n } else if (this.ellipsis === 'hide') {\n return;\n } else if (this.ellipsis === 'add') {\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n left -= this.ellipsisWidth;\n }\n } else if (this.ellipsis === 'replace') {\n // 找到需要截断的字符长度\n // const index = getStrByWith(text, this.width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.style, text.length - 1);\n const index = getStrByWithCanvas(\n text,\n (direction === 'vertical' ? this.height : this.width) - this.ellipsisWidth + this.ellipsisOtherParagraphWidth,\n this.character,\n text.length - 1\n );\n text = text.slice(0, index);\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n const { width } = measureTextCanvas(this.text.slice(index), this.character);\n if (direction === 'vertical') {\n // baseline -= this.ellipsisWidth - width;\n } else {\n left -= this.ellipsisWidth - width;\n }\n }\n }\n\n // prepareContext(ctx);\n switch (this.character.script) {\n case 'super':\n baseline -= this.ascent * (1 / 3);\n break;\n case 'sub':\n baseline += this.descent / 2;\n break;\n }\n\n // 处理旋转\n if (direction === 'vertical') {\n ctx.save();\n ctx.rotateAbout(Math.PI / 2, left, baseline);\n ctx.translate(-(this.heightOrigin as number) || -this.lineHeight / 2, -this.descent / 2);\n ctx.translate(left, baseline);\n left = 0;\n baseline = 0;\n }\n\n const fillStyle = ctx.fillStyle;\n const globalAlpha = ctx.globalAlpha;\n ctx.fillStyle = this.character.background;\n if (this.character.backgroundOpacity !== void 0) {\n ctx.globalAlpha = this.character.backgroundOpacity;\n }\n // 背景稍微扩充一些buf,否则会出现白线\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + lineHeight;\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n ctx.fillStyle = fillStyle;\n ctx.globalAlpha = globalAlpha;\n }\n\n draw(\n ctx: IContext2d,\n top: number,\n ascent: number,\n deltaLeft: number,\n isLineFirst: boolean,\n textAlign: string,\n lineHeight: number\n ) {\n let baseline = top + ascent;\n let text = this.text;\n let left = this.left + deltaLeft;\n baseline += this.top;\n let direction = this.direction;\n\n if (this.verticalEllipsis) {\n text = this.ellipsisStr;\n direction = 'vertical';\n baseline -= this.ellipsisWidth / 2;\n } else if (this.ellipsis === 'hide') {\n return;\n } else if (this.ellipsis === 'add') {\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n left -= this.ellipsisWidth;\n }\n } else if (this.ellipsis === 'replace') {\n // 找到需要截断的字符长度\n // const index = getStrByWith(text, this.width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.style, text.length - 1);\n const index = getStrByWithCanvas(\n text,\n (direction === 'vertical' ? this.height : this.width) - this.ellipsisWidth + this.ellipsisOtherParagraphWidth,\n this.character,\n text.length - 1\n );\n text = text.slice(0, index);\n text += this.ellipsisStr;\n\n if (textAlign === 'right' || textAlign === 'end') {\n const { width } = measureTextCanvas(this.text.slice(index), this.character);\n if (direction === 'vertical') {\n // baseline -= this.ellipsisWidth - width;\n } else {\n left -= this.ellipsisWidth - width;\n }\n }\n }\n\n // prepareContext(ctx);\n switch (this.character.script) {\n case 'super':\n baseline -= this.ascent * (1 / 3);\n break;\n case 'sub':\n baseline += this.descent / 2;\n break;\n }\n\n // if (isLineFirst) {\n // const result = regFirstSpace.exec(text);\n // if (result?.index !== 0) {\n // text = text.slice(result?.index);\n // }\n // }\n\n // 处理旋转\n if (direction === 'vertical') {\n ctx.save();\n ctx.rotateAbout(Math.PI / 2, left, baseline);\n ctx.translate(-(this.heightOrigin as number) || -this.lineHeight / 2, -this.descent / 2);\n ctx.translate(left, baseline);\n left = 0;\n baseline = 0;\n }\n\n // if (this.character.fill) {\n // if (this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0)) {\n // const fillStyle = ctx.fillStyle;\n // const globalAlpha = ctx.globalAlpha;\n // ctx.fillStyle = this.character.background;\n // if (this.character.backgroundOpacity !== void 0) {\n // ctx.globalAlpha = this.character.backgroundOpacity;\n // }\n // // 背景稍微扩充一些buf,否则会出现白线\n // const right = left + (this.widthOrigin || this.width);\n // const bottom = top + lineHeight;\n // const lrtb = getFixedLRTB(left, right, top, bottom);\n // ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n // ctx.fillStyle = fillStyle;\n // ctx.globalAlpha = globalAlpha;\n // }\n // }\n\n const { lineWidth = 1 } = this.character;\n if (this.character.stroke && lineWidth) {\n ctx.strokeText(text, left, baseline);\n }\n\n if (this.character.fill) {\n ctx.fillText(text, left, baseline);\n }\n\n if (this.character.fill) {\n if (this.character.lineThrough || this.character.underline) {\n if (this.character.underline) {\n const top = 1 + baseline;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n if (this.character.lineThrough) {\n const top = 1 + baseline - this.ascent / 2;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n } else if (this.character.textDecoration === 'underline') {\n const top = 1 + baseline;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n } else if (this.character.textDecoration === 'line-through') {\n const top = 1 + baseline - this.ascent / 2;\n const right = left + (this.widthOrigin || this.width);\n const bottom = top + (this.character.fontSize ? Math.max(1, Math.floor(this.character.fontSize / 10)) : 1);\n const lrtb = getFixedLRTB(left, right, top, bottom);\n ctx.fillRect(lrtb.left, lrtb.top, lrtb.right - lrtb.left, lrtb.bottom - lrtb.top);\n }\n }\n\n if (direction === 'vertical') {\n ctx.restore();\n }\n }\n\n getWidthWithEllips(direction: string): number {\n let text = this.text;\n // const direction = this.direction;\n const width = direction === 'vertical' ? this.height : this.width;\n // const height = direction === 'vertical' ? this.width: this.height;\n\n if (this.ellipsis === 'hide') {\n return width;\n } else if (this.ellipsis === 'add') {\n return width + this.ellipsisWidth;\n } else if (this.ellipsis === 'replace') {\n // 找到需要截断的字符长度\n // const index = getStrByWith(text, width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth, this.style, text.length - 1);\n const index = getStrByWithCanvas(\n text,\n width - this.ellipsisWidth + this.ellipsisOtherParagraphWidth,\n this.character,\n text.length - 1\n );\n text = text.slice(0, index);\n text += this.ellipsisStr;\n\n const { width: measureWidth } = measureTextCanvas(this.text.slice(index), this.character);\n return width + this.ellipsisWidth - measureWidth;\n }\n return width;\n }\n}\n\nexport function seperateParagraph(paragraph: Paragraph, index: number) {\n const text1 = paragraph.text.slice(0, index);\n const text2 = paragraph.text.slice(index);\n const p1 = new Paragraph(text1, paragraph.newLine, paragraph.character);\n const p2 = new Paragraph(text2, true, paragraph.character);\n\n return [p1, p2];\n}\n"]}
@@ -177,10 +177,10 @@ export function measureTextCanvas(text, character) {
177
177
  descent: 0,
178
178
  width: 0
179
179
  };
180
- return "number" != typeof measurement.actualBoundingBoxAscent || "number" != typeof measurement.actualBoundingBoxDescent ? (result.width = Math.floor(measurement.width),
181
- result.height = character.fontSize || 0, result.ascent = result.height, result.descent = 0) : (result.width = Math.floor(measurement.width),
182
- result.height = Math.floor(measurement.actualBoundingBoxAscent + measurement.actualBoundingBoxDescent),
183
- result.ascent = Math.floor(measurement.actualBoundingBoxAscent), result.descent = result.height - result.ascent),
180
+ return "number" != typeof measurement.fontBoundingBoxAscent || "number" != typeof measurement.fontBoundingBoxDescent ? (result.width = measurement.width,
181
+ result.height = character.fontSize || 0, result.ascent = result.height, result.descent = 0) : (result.width = measurement.width,
182
+ result.height = Math.floor(measurement.fontBoundingBoxAscent + measurement.fontBoundingBoxDescent),
183
+ result.ascent = Math.floor(measurement.fontBoundingBoxAscent), result.descent = result.height - result.ascent),
184
184
  result;
185
185
  }
186
186
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/graphic/richtext/utils.ts"],"names":[],"mappings":"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","file":"utils.js","sourcesContent":["import type { IBoundsLike } from '@visactor/vutils';\nimport { application } from '../../application';\nimport { createColor } from '../../common/canvas-utils';\nimport type { IContext2d, ITextStyleParams, IRichTextParagraphCharacter } from '../../interface';\nimport { DEFAULT_TEXT_FONT_FAMILY } from '../../constants';\n\nexport const DIRECTION_KEY = {\n horizontal: {\n width: 'width',\n height: 'height',\n left: 'left',\n top: 'top',\n x: 'x',\n y: 'y',\n bottom: 'bottom'\n },\n vertical: {\n width: 'height',\n height: 'width',\n left: 'top',\n top: 'left',\n x: 'y',\n y: 'x',\n bottom: 'right'\n }\n};\n\nconst defaultFormatting = {\n fontSize: 16,\n fontFamily: DEFAULT_TEXT_FONT_FAMILY,\n fill: true,\n stroke: false,\n fontWeight: 'normal',\n lineHeight: 'normal',\n fontStyle: 'normal', // normal, italic, oblique\n textDecoration: 'none', // none, underline, line-through\n textAlign: 'left', // left, right, center\n script: 'normal' // normal, sub, super\n};\nconst nbsp = String.fromCharCode(160);\n\nexport const regLetter = /\\w|\\(|\\)|-/;\nconst regPunctuation = /[.?!,;:/,。?!、;:]/;\nexport const regFirstSpace = /\\S/;\n\nconst setTextStyle = (ctx: IContext2d, character: IRichTextParagraphCharacter) => {\n let fontSize = character.fontSize || 16;\n switch (character.script) {\n case 'super':\n case 'sub':\n fontSize *= 0.8;\n break;\n }\n\n ctx.setTextStyle({\n textAlign: 'left',\n textBaseline: character.textBaseline || 'alphabetic',\n fontStyle: character.fontStyle || '',\n fontWeight: character.fontWeight || '',\n fontSize,\n fontFamily: character.fontFamily\n } as ITextStyleParams);\n};\n\n// Applies the style of a run to the canvas context\nexport function applyFillStyle(ctx: IContext2d, character: IRichTextParagraphCharacter, b?: IBoundsLike) {\n const fillStyle = (character && (character.fill as string)) || defaultFormatting.fill;\n if (!fillStyle) {\n ctx.globalAlpha = 0;\n return;\n }\n\n const { fillOpacity = 1, opacity = 1 } = character;\n\n ctx.globalAlpha = fillOpacity * opacity;\n ctx.fillStyle = b ? createColor(ctx, fillStyle, { AABBBounds: b }) : (fillStyle as string);\n\n setTextStyle(ctx, character);\n}\n\nexport function applyStrokeStyle(ctx: IContext2d, character: IRichTextParagraphCharacter) {\n const strokeStyle = (character && (character.stroke as string)) || (defaultFormatting.stroke as any);\n if (!strokeStyle) {\n ctx.globalAlpha = 0;\n return;\n }\n\n const { strokeOpacity = 1, opacity = 1 } = character;\n\n ctx.globalAlpha = strokeOpacity * opacity;\n ctx.lineWidth = character && typeof character.lineWidth === 'number' ? character.lineWidth : 1;\n ctx.strokeStyle = strokeStyle as string;\n\n setTextStyle(ctx, character);\n}\n\nexport function prepareContext(ctx: IContext2d) {\n ctx.setTextStyle({\n textAlign: 'left',\n textBaseline: 'bottom'\n });\n}\n\n// 确认达到availableWidth的字符串截取index\nexport function getStrByWithDom(\n desc: string,\n width: number,\n style: string,\n guessIndex: number,\n needTestLetter?: boolean\n): number {\n desc = desc.replace(/\\s/g, nbsp);\n\n // 测量用DOM\n const span = document.createElement('span');\n span.setAttribute('style', style);\n span.style.visibility = 'hidden';\n span.style.whiteSpace = 'nowrap';\n document.body.appendChild(span);\n\n // 测量从头到当前位置宽度以及从头到下一个字符位置宽度\n let index = guessIndex;\n let temp = desc.slice(0, index);\n span.innerText = temp;\n let tempWidth = span.offsetWidth;\n\n let tempNext = desc.slice(0, index + 1);\n span.innerText = tempNext;\n let tempWidthNext = span.offsetWidth;\n\n // 到当前位置宽度 < width && 到下一个字符位置宽度 > width时,认为找到准确阶段位置\n while (tempWidth > width || tempWidthNext <= width) {\n if (tempWidth > width) {\n index--;\n } else {\n index++;\n }\n\n temp = desc.slice(0, index);\n span.innerText = temp;\n tempWidth = span.offsetWidth;\n\n tempNext = desc.slice(0, index + 1);\n span.innerText = tempNext;\n tempWidthNext = span.offsetWidth;\n }\n\n // 处理特殊情况\n if (needTestLetter) {\n index = testLetter(desc, index);\n }\n\n document.body.removeChild(span);\n return index;\n}\nexport function getStrByWithCanvas(\n desc: string,\n width: number,\n character: IRichTextParagraphCharacter,\n // ctx: IContext2d,\n guessIndex: number,\n needTestLetter?: boolean\n): number {\n if (!width || width <= 0) {\n return 0;\n }\n const textMeasure = application.graphicUtil.textMeasure;\n // const measurement = textMeasure.measureText(text, character);\n\n // 测量从头到当前位置宽度以及从头到下一个字符位置宽度\n let index = guessIndex;\n let temp = desc.slice(0, index);\n let tempWidth = Math.floor(textMeasure.measureText(temp, character as any).width);\n\n let tempNext = desc.slice(0, index + 1);\n let tempWidthNext = Math.floor(textMeasure.measureText(tempNext, character as any).width);\n\n // 到当前位置宽度 < width && 到下一个字符位置宽度 > width时,认为找到准确阶段位置\n while (tempWidth > width || tempWidthNext <= width) {\n if (tempWidth > width) {\n index--;\n } else {\n index++;\n }\n\n if (index > desc.length) {\n index = desc.length;\n break;\n } else if (index < 0) {\n index = 0;\n break;\n }\n\n temp = desc.slice(0, index);\n tempWidth = Math.floor(textMeasure.measureText(temp, character as any).width);\n\n tempNext = desc.slice(0, index + 1);\n tempWidthNext = Math.floor(textMeasure.measureText(tempNext, character as any).width);\n }\n\n // 处理特殊情况\n if (needTestLetter) {\n index = testLetter(desc, index);\n }\n\n return index;\n}\n\nexport function getWordStartEndIdx(string: string, index: number) {\n let startIdx = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[startIdx - 1]) && regLetter.test(string[startIdx])) ||\n // 行首标点符号处理\n regPunctuation.test(string[startIdx])\n ) {\n startIdx--;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (startIdx <= 0) {\n break;\n }\n }\n\n let endIdx = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[endIdx + 1]) && regLetter.test(string[endIdx])) ||\n // 行首标点符号处理\n regPunctuation.test(string[endIdx])\n ) {\n endIdx++;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (endIdx >= string.length) {\n break;\n }\n }\n endIdx = Math.min(endIdx + 1, string.length);\n\n return {\n startIdx,\n endIdx\n };\n}\n\n/**\n * 向前找到单词结尾处换行\n * @param string\n * @param index\n * @param negativeWrongMatch 如果为true,那么如果无法匹配就会向后找到单词的结尾,否则就直接返回index\n * @returns\n */\nexport function testLetter(string: string, index: number, negativeWrongMatch: boolean = false): number {\n let i = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[i - 1]) && regLetter.test(string[i])) ||\n // 行首标点符号处理\n regPunctuation.test(string[i])\n ) {\n i--;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (i <= 0) {\n return negativeWrongMatch ? testLetter2(string, index) : index;\n }\n }\n return i;\n}\n\n/**\n * 向后找到单词结尾处换行\n * @param string\n * @param index\n * @returns\n */\nexport function testLetter2(string: string, index: number) {\n let i = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[i + 1]) && regLetter.test(string[i])) ||\n // 行首标点符号处理\n regPunctuation.test(string[i])\n ) {\n i++;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (i >= string.length) {\n return i;\n }\n }\n return i + 1;\n}\n\n// 测量文字详细信息\nexport function measureTextDom(\n text: string,\n style: string\n): { ascent?: number; height?: number; descent?: number; width?: number } {\n let div;\n\n const span = document.createElement('span');\n const block = document.createElement('div');\n div = document.createElement('div');\n\n block.style.display = 'inline-block';\n block.style.width = '1px';\n block.style.height = '0';\n\n div.style.visibility = 'hidden';\n div.style.position = 'absolute';\n div.style.top = '0';\n div.style.left = '0';\n div.style.width = '500px';\n div.style.height = '200px';\n div.style.whiteSpace = 'nowrap';\n\n div.appendChild(span);\n div.appendChild(block);\n document.body.appendChild(div);\n\n const result: { ascent?: number; height?: number; descent?: number; width?: number } = {};\n try {\n span.setAttribute('style', style);\n span.style.whiteSpace = 'nowrap';\n span.style.display = 'inline-block';\n\n span.innerHTML = '';\n span.appendChild(document.createTextNode(text.replace(/\\s/g, nbsp)));\n\n block.style.verticalAlign = 'baseline';\n result.ascent = block.offsetTop - span.offsetTop;\n block.style.verticalAlign = 'bottom';\n result.height = block.offsetTop - span.offsetTop;\n result.descent = result.height - result.ascent;\n result.width = span.offsetWidth;\n } finally {\n div.parentNode?.removeChild(div);\n div = null;\n }\n return result;\n}\n\n// 测量文字详细信息\nexport function measureTextCanvas(\n text: string,\n character: IRichTextParagraphCharacter\n): { ascent: number; height: number; descent: number; width: number } {\n const textMeasure = application.graphicUtil.textMeasure;\n const measurement = textMeasure.measureText(text, character as any) as TextMetrics;\n const result: { ascent: number; height: number; descent: number; width: number } = {\n ascent: 0,\n height: 0,\n descent: 0,\n width: 0\n };\n if (\n typeof measurement.actualBoundingBoxAscent !== 'number' ||\n typeof measurement.actualBoundingBoxDescent !== 'number'\n ) {\n result.width = Math.floor(measurement.width);\n result.height = character.fontSize || 0;\n result.ascent = result.height;\n result.descent = 0;\n } else {\n result.width = Math.floor(measurement.width);\n result.height = Math.floor(measurement.actualBoundingBoxAscent + measurement.actualBoundingBoxDescent);\n result.ascent = Math.floor(measurement.actualBoundingBoxAscent);\n result.descent = result.height - result.ascent;\n }\n return result;\n}\n\nexport function getFontString(character: IRichTextParagraphCharacter, ctx: IContext2d | null) {\n let fontSize = (character && character.fontSize) || defaultFormatting.fontSize;\n\n if (character) {\n switch (character.script) {\n case 'super':\n case 'sub':\n fontSize *= 0.8;\n break;\n }\n }\n\n return (\n ((character && character.fontStyle) || '') +\n ' ' +\n ((character && character.fontWeight) || '') +\n ' ' +\n (fontSize || 12) +\n 'px ' +\n ((character && character.fontFamily) || defaultFormatting.fontFamily)\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/graphic/richtext/utils.ts"],"names":[],"mappings":"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","file":"utils.js","sourcesContent":["import type { IBoundsLike } from '@visactor/vutils';\nimport { application } from '../../application';\nimport { createColor } from '../../common/canvas-utils';\nimport type { IContext2d, ITextStyleParams, IRichTextParagraphCharacter } from '../../interface';\nimport { DEFAULT_TEXT_FONT_FAMILY } from '../../constants';\n\nexport const DIRECTION_KEY = {\n horizontal: {\n width: 'width',\n height: 'height',\n left: 'left',\n top: 'top',\n x: 'x',\n y: 'y',\n bottom: 'bottom'\n },\n vertical: {\n width: 'height',\n height: 'width',\n left: 'top',\n top: 'left',\n x: 'y',\n y: 'x',\n bottom: 'right'\n }\n};\n\nconst defaultFormatting = {\n fontSize: 16,\n fontFamily: DEFAULT_TEXT_FONT_FAMILY,\n fill: true,\n stroke: false,\n fontWeight: 'normal',\n lineHeight: 'normal',\n fontStyle: 'normal', // normal, italic, oblique\n textDecoration: 'none', // none, underline, line-through\n textAlign: 'left', // left, right, center\n script: 'normal' // normal, sub, super\n};\nconst nbsp = String.fromCharCode(160);\n\nexport const regLetter = /\\w|\\(|\\)|-/;\nconst regPunctuation = /[.?!,;:/,。?!、;:]/;\nexport const regFirstSpace = /\\S/;\n\nconst setTextStyle = (ctx: IContext2d, character: IRichTextParagraphCharacter) => {\n let fontSize = character.fontSize || 16;\n switch (character.script) {\n case 'super':\n case 'sub':\n fontSize *= 0.8;\n break;\n }\n\n ctx.setTextStyle({\n textAlign: 'left',\n textBaseline: character.textBaseline || 'alphabetic',\n fontStyle: character.fontStyle || '',\n fontWeight: character.fontWeight || '',\n fontSize,\n fontFamily: character.fontFamily\n } as ITextStyleParams);\n};\n\n// Applies the style of a run to the canvas context\nexport function applyFillStyle(ctx: IContext2d, character: IRichTextParagraphCharacter, b?: IBoundsLike) {\n const fillStyle = (character && (character.fill as string)) || defaultFormatting.fill;\n if (!fillStyle) {\n ctx.globalAlpha = 0;\n return;\n }\n\n const { fillOpacity = 1, opacity = 1 } = character;\n\n ctx.globalAlpha = fillOpacity * opacity;\n ctx.fillStyle = b ? createColor(ctx, fillStyle, { AABBBounds: b }) : (fillStyle as string);\n\n setTextStyle(ctx, character);\n}\n\nexport function applyStrokeStyle(ctx: IContext2d, character: IRichTextParagraphCharacter) {\n const strokeStyle = (character && (character.stroke as string)) || (defaultFormatting.stroke as any);\n if (!strokeStyle) {\n ctx.globalAlpha = 0;\n return;\n }\n\n const { strokeOpacity = 1, opacity = 1 } = character;\n\n ctx.globalAlpha = strokeOpacity * opacity;\n ctx.lineWidth = character && typeof character.lineWidth === 'number' ? character.lineWidth : 1;\n ctx.strokeStyle = strokeStyle as string;\n\n setTextStyle(ctx, character);\n}\n\nexport function prepareContext(ctx: IContext2d) {\n ctx.setTextStyle({\n textAlign: 'left',\n textBaseline: 'bottom'\n });\n}\n\n// 确认达到availableWidth的字符串截取index\nexport function getStrByWithDom(\n desc: string,\n width: number,\n style: string,\n guessIndex: number,\n needTestLetter?: boolean\n): number {\n desc = desc.replace(/\\s/g, nbsp);\n\n // 测量用DOM\n const span = document.createElement('span');\n span.setAttribute('style', style);\n span.style.visibility = 'hidden';\n span.style.whiteSpace = 'nowrap';\n document.body.appendChild(span);\n\n // 测量从头到当前位置宽度以及从头到下一个字符位置宽度\n let index = guessIndex;\n let temp = desc.slice(0, index);\n span.innerText = temp;\n let tempWidth = span.offsetWidth;\n\n let tempNext = desc.slice(0, index + 1);\n span.innerText = tempNext;\n let tempWidthNext = span.offsetWidth;\n\n // 到当前位置宽度 < width && 到下一个字符位置宽度 > width时,认为找到准确阶段位置\n while (tempWidth > width || tempWidthNext <= width) {\n if (tempWidth > width) {\n index--;\n } else {\n index++;\n }\n\n temp = desc.slice(0, index);\n span.innerText = temp;\n tempWidth = span.offsetWidth;\n\n tempNext = desc.slice(0, index + 1);\n span.innerText = tempNext;\n tempWidthNext = span.offsetWidth;\n }\n\n // 处理特殊情况\n if (needTestLetter) {\n index = testLetter(desc, index);\n }\n\n document.body.removeChild(span);\n return index;\n}\nexport function getStrByWithCanvas(\n desc: string,\n width: number,\n character: IRichTextParagraphCharacter,\n // ctx: IContext2d,\n guessIndex: number,\n needTestLetter?: boolean\n): number {\n if (!width || width <= 0) {\n return 0;\n }\n const textMeasure = application.graphicUtil.textMeasure;\n // const measurement = textMeasure.measureText(text, character);\n\n // 测量从头到当前位置宽度以及从头到下一个字符位置宽度\n let index = guessIndex;\n let temp = desc.slice(0, index);\n let tempWidth = Math.floor(textMeasure.measureText(temp, character as any).width);\n\n let tempNext = desc.slice(0, index + 1);\n let tempWidthNext = Math.floor(textMeasure.measureText(tempNext, character as any).width);\n\n // 到当前位置宽度 < width && 到下一个字符位置宽度 > width时,认为找到准确阶段位置\n while (tempWidth > width || tempWidthNext <= width) {\n if (tempWidth > width) {\n index--;\n } else {\n index++;\n }\n\n if (index > desc.length) {\n index = desc.length;\n break;\n } else if (index < 0) {\n index = 0;\n break;\n }\n\n temp = desc.slice(0, index);\n tempWidth = Math.floor(textMeasure.measureText(temp, character as any).width);\n\n tempNext = desc.slice(0, index + 1);\n tempWidthNext = Math.floor(textMeasure.measureText(tempNext, character as any).width);\n }\n\n // 处理特殊情况\n if (needTestLetter) {\n index = testLetter(desc, index);\n }\n\n return index;\n}\n\nexport function getWordStartEndIdx(string: string, index: number) {\n let startIdx = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[startIdx - 1]) && regLetter.test(string[startIdx])) ||\n // 行首标点符号处理\n regPunctuation.test(string[startIdx])\n ) {\n startIdx--;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (startIdx <= 0) {\n break;\n }\n }\n\n let endIdx = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[endIdx + 1]) && regLetter.test(string[endIdx])) ||\n // 行首标点符号处理\n regPunctuation.test(string[endIdx])\n ) {\n endIdx++;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (endIdx >= string.length) {\n break;\n }\n }\n endIdx = Math.min(endIdx + 1, string.length);\n\n return {\n startIdx,\n endIdx\n };\n}\n\n/**\n * 向前找到单词结尾处换行\n * @param string\n * @param index\n * @param negativeWrongMatch 如果为true,那么如果无法匹配就会向后找到单词的结尾,否则就直接返回index\n * @returns\n */\nexport function testLetter(string: string, index: number, negativeWrongMatch: boolean = false): number {\n let i = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[i - 1]) && regLetter.test(string[i])) ||\n // 行首标点符号处理\n regPunctuation.test(string[i])\n ) {\n i--;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (i <= 0) {\n return negativeWrongMatch ? testLetter2(string, index) : index;\n }\n }\n return i;\n}\n\n/**\n * 向后找到单词结尾处换行\n * @param string\n * @param index\n * @returns\n */\nexport function testLetter2(string: string, index: number) {\n let i = index;\n // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行\n while (\n (regLetter.test(string[i + 1]) && regLetter.test(string[i])) ||\n // 行首标点符号处理\n regPunctuation.test(string[i])\n ) {\n i++;\n // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环\n if (i >= string.length) {\n return i;\n }\n }\n return i + 1;\n}\n\n// 测量文字详细信息\nexport function measureTextDom(\n text: string,\n style: string\n): { ascent?: number; height?: number; descent?: number; width?: number } {\n let div;\n\n const span = document.createElement('span');\n const block = document.createElement('div');\n div = document.createElement('div');\n\n block.style.display = 'inline-block';\n block.style.width = '1px';\n block.style.height = '0';\n\n div.style.visibility = 'hidden';\n div.style.position = 'absolute';\n div.style.top = '0';\n div.style.left = '0';\n div.style.width = '500px';\n div.style.height = '200px';\n div.style.whiteSpace = 'nowrap';\n\n div.appendChild(span);\n div.appendChild(block);\n document.body.appendChild(div);\n\n const result: { ascent?: number; height?: number; descent?: number; width?: number } = {};\n try {\n span.setAttribute('style', style);\n span.style.whiteSpace = 'nowrap';\n span.style.display = 'inline-block';\n\n span.innerHTML = '';\n span.appendChild(document.createTextNode(text.replace(/\\s/g, nbsp)));\n\n block.style.verticalAlign = 'baseline';\n result.ascent = block.offsetTop - span.offsetTop;\n block.style.verticalAlign = 'bottom';\n result.height = block.offsetTop - span.offsetTop;\n result.descent = result.height - result.ascent;\n result.width = span.offsetWidth;\n } finally {\n div.parentNode?.removeChild(div);\n div = null;\n }\n return result;\n}\n\n// 测量文字详细信息\nexport function measureTextCanvas(\n text: string,\n character: IRichTextParagraphCharacter\n): { ascent: number; height: number; descent: number; width: number } {\n const textMeasure = application.graphicUtil.textMeasure;\n const measurement = textMeasure.measureText(text, character as any) as TextMetrics;\n const result: { ascent: number; height: number; descent: number; width: number } = {\n ascent: 0,\n height: 0,\n descent: 0,\n width: 0\n };\n if (typeof measurement.fontBoundingBoxAscent !== 'number' || typeof measurement.fontBoundingBoxDescent !== 'number') {\n result.width = measurement.width;\n result.height = character.fontSize || 0;\n result.ascent = result.height;\n result.descent = 0;\n } else {\n result.width = measurement.width;\n result.height = Math.floor(measurement.fontBoundingBoxAscent + measurement.fontBoundingBoxDescent);\n result.ascent = Math.floor(measurement.fontBoundingBoxAscent);\n result.descent = result.height - result.ascent;\n }\n return result;\n}\n\nexport function getFontString(character: IRichTextParagraphCharacter, ctx: IContext2d | null) {\n let fontSize = (character && character.fontSize) || defaultFormatting.fontSize;\n\n if (character) {\n switch (character.script) {\n case 'super':\n case 'sub':\n fontSize *= 0.8;\n break;\n }\n }\n\n return (\n ((character && character.fontStyle) || '') +\n ' ' +\n ((character && character.fontWeight) || '') +\n ' ' +\n (fontSize || 12) +\n 'px ' +\n ((character && character.fontFamily) || defaultFormatting.fontFamily)\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visactor/vrender-core",
3
- "version": "0.22.0-vstory.2",
3
+ "version": "0.22.0-vstory.5",
4
4
  "description": "",
5
5
  "sideEffects": [
6
6
  "./src/modules.ts",