Skip to content

Commit

Permalink
fix: multi-line text wrapping exception (#1887)
Browse files Browse the repository at this point in the history
  • Loading branch information
wang1212 authored Jan 2, 2025
1 parent e6c803d commit 9d6fd39
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/popular-items-wave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@antv/g-lite': patch
---

fix: multi-line text wrapping exception
33 changes: 32 additions & 1 deletion __tests__/demos/bugfix/textWordWrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export async function textWordWrap(context: { canvas: Canvas }) {
textBaseline: 'top',
textOverflow: 'ellipsis',
wordWrap: true,
wordWrapWidth: 30,
wordWrapWidth: 84,
},
});
const rect2 = new Rect({
Expand All @@ -103,12 +103,43 @@ export async function textWordWrap(context: { canvas: Canvas }) {
},
});

const text3 = new Text({
style: {
x: 300,
y: 300,
wordWrap: true,
wordWrapWidth: 2,
maxLines: 5,
textOverflow: 'ellipsis',
fontFamily: 'Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif',
fontSize: 12,
fontWeight: 700,
fill: '#000000',
opacity: 1,
textAlign: 'center',
textBaseline: 'middle',
linkTextFill: '#326EF4',
text: '千亿数据',
},
});
const rect3 = new Rect({
style: {
x: text3.style.x,
y: text3.style.y,
width: text3.style.wordWrapWidth,
height: +text3.style.fontSize * text3.style.maxLines,
stroke: '#000000',
},
});

canvas.appendChild(text0);
canvas.appendChild(rect0);
canvas.appendChild(text1);
canvas.appendChild(rect1);
canvas.appendChild(text2);
canvas.appendChild(rect2);
canvas.appendChild(text3);
canvas.appendChild(rect3);

// benchmark
// ----------
Expand Down
48 changes: 29 additions & 19 deletions packages/g-lite/src/services/TextService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ export class TextService {
let lines: string[] = [];
let currentLineIndex = 0;
let currentLineWidth = 0;
let prevLineLastCharIndex = 0;

const cache: { [key in string]: number } = {};
const calcWidth = (txt: string): number => {
Expand All @@ -377,32 +378,37 @@ export class TextService {
*
* @see https://github.com/antvis/G/issues/1833
*
* @param txt - Current line of text
* @param textCharIndex - The index of the last character of the current line in the entire text
* @param lineTxt - Current line of text
* @param txtLastCharIndex - The index of the last character of the current line in the entire text
* @param txtStartCharIndex - The index of the start character of the current line in the entire text
*/
function findCharIndexClosestWidthThreshold(
txt: string,
textCharIndex: number,
lineTxt: string,
txtLastCharIndex: number,
txtStartCharIndex: number,
widthThreshold: number,
) {
while (
calcWidth(txt) < widthThreshold &&
textCharIndex < chars.length - 1
calcWidth(lineTxt) < widthThreshold &&
txtLastCharIndex < chars.length - 1
) {
if (self.isNewline(chars[textCharIndex + 1])) {
if (self.isNewline(chars[txtLastCharIndex + 1])) {
break;
}
textCharIndex += 1;
txt += chars[textCharIndex];
txtLastCharIndex += 1;
lineTxt += chars[txtLastCharIndex];
}
while (calcWidth(txt) > widthThreshold && textCharIndex > 0) {
textCharIndex -= 1;
txt = txt.slice(0, -1);
while (
calcWidth(lineTxt) > widthThreshold &&
txtLastCharIndex > txtStartCharIndex
) {
txtLastCharIndex -= 1;
lineTxt = lineTxt.slice(0, -1);
}

return {
txt,
textCharIndex,
lineTxt,
txtLastCharIndex,
};
}

Expand All @@ -422,10 +428,11 @@ export class TextService {
const result = findCharIndexClosestWidthThreshold(
lines[lineIndex],
textCharIndex,
prevLineLastCharIndex + 1,
maxWidth - ellipsisWidth,
);

lines[lineIndex] = result.txt + ellipsis;
lines[lineIndex] = result.lineTxt + ellipsis;
}

for (let i = 0; i < chars.length; i++) {
Expand All @@ -446,6 +453,7 @@ export class TextService {
break;
}

prevLineLastCharIndex = i - 1;
currentLineIndex += 1;
currentLineWidth = 0;
lines[currentLineIndex] = '';
Expand All @@ -457,16 +465,17 @@ export class TextService {
const result = findCharIndexClosestWidthThreshold(
lines[currentLineIndex],
i - 1,
prevLineLastCharIndex + 1,
maxWidth,
);
if (result.textCharIndex !== i - 1) {
lines[currentLineIndex] = result.txt;
if (result.txtLastCharIndex !== i - 1) {
lines[currentLineIndex] = result.lineTxt;

if (result.textCharIndex === chars.length - 1) {
if (result.txtLastCharIndex === chars.length - 1) {
break;
}

i = result.textCharIndex + 1;
i = result.txtLastCharIndex + 1;
char = chars[i];
prevChar = chars[i - 1];
nextChar = chars[i + 1];
Expand All @@ -481,6 +490,7 @@ export class TextService {
break;
}

prevLineLastCharIndex = i - 1;
currentLineIndex += 1;
currentLineWidth = 0;
lines[currentLineIndex] = '';
Expand Down

0 comments on commit 9d6fd39

Please sign in to comment.