|
@@ -271,9 +271,12 @@ export const measureText = (
|
|
container.style.whiteSpace = "pre";
|
|
container.style.whiteSpace = "pre";
|
|
container.style.font = font;
|
|
container.style.font = font;
|
|
container.style.minHeight = "1em";
|
|
container.style.minHeight = "1em";
|
|
|
|
+ const textWidth = getTextWidth(text, font);
|
|
|
|
+
|
|
if (maxWidth) {
|
|
if (maxWidth) {
|
|
const lineHeight = getApproxLineHeight(font);
|
|
const lineHeight = getApproxLineHeight(font);
|
|
- container.style.width = `${String(maxWidth + 1)}px`;
|
|
|
|
|
|
+ container.style.width = `${String(Math.min(textWidth, maxWidth) + 1)}px`;
|
|
|
|
+
|
|
container.style.overflow = "hidden";
|
|
container.style.overflow = "hidden";
|
|
container.style.wordBreak = "break-word";
|
|
container.style.wordBreak = "break-word";
|
|
container.style.lineHeight = `${String(lineHeight)}px`;
|
|
container.style.lineHeight = `${String(lineHeight)}px`;
|
|
@@ -291,7 +294,10 @@ export const measureText = (
|
|
// Baseline is important for positioning text on canvas
|
|
// Baseline is important for positioning text on canvas
|
|
const baseline = span.offsetTop + span.offsetHeight;
|
|
const baseline = span.offsetTop + span.offsetHeight;
|
|
// Since span adds 1px extra width to the container
|
|
// Since span adds 1px extra width to the container
|
|
- const width = container.offsetWidth - 1;
|
|
|
|
|
|
+ let width = container.offsetWidth;
|
|
|
|
+ if (maxWidth && textWidth > maxWidth) {
|
|
|
|
+ width = width - 1;
|
|
|
|
+ }
|
|
const height = container.offsetHeight;
|
|
const height = container.offsetHeight;
|
|
document.body.removeChild(container);
|
|
document.body.removeChild(container);
|
|
if (isTestEnv()) {
|
|
if (isTestEnv()) {
|
|
@@ -312,7 +318,7 @@ export const getApproxLineHeight = (font: FontString) => {
|
|
};
|
|
};
|
|
|
|
|
|
let canvas: HTMLCanvasElement | undefined;
|
|
let canvas: HTMLCanvasElement | undefined;
|
|
-const getTextWidth = (text: string, font: FontString) => {
|
|
|
|
|
|
+const getLineWidth = (text: string, font: FontString) => {
|
|
if (!canvas) {
|
|
if (!canvas) {
|
|
canvas = document.createElement("canvas");
|
|
canvas = document.createElement("canvas");
|
|
}
|
|
}
|
|
@@ -330,10 +336,18 @@ const getTextWidth = (text: string, font: FontString) => {
|
|
return metrics.width;
|
|
return metrics.width;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+export const getTextWidth = (text: string, font: FontString) => {
|
|
|
|
+ const lines = text.split("\n");
|
|
|
|
+ let width = 0;
|
|
|
|
+ lines.forEach((line) => {
|
|
|
|
+ width = Math.max(width, getLineWidth(line, font));
|
|
|
|
+ });
|
|
|
|
+ return width;
|
|
|
|
+};
|
|
export const wrapText = (text: string, font: FontString, maxWidth: number) => {
|
|
export const wrapText = (text: string, font: FontString, maxWidth: number) => {
|
|
const lines: Array<string> = [];
|
|
const lines: Array<string> = [];
|
|
const originalLines = text.split("\n");
|
|
const originalLines = text.split("\n");
|
|
- const spaceWidth = getTextWidth(" ", font);
|
|
|
|
|
|
+ const spaceWidth = getLineWidth(" ", font);
|
|
|
|
|
|
const push = (str: string) => {
|
|
const push = (str: string) => {
|
|
if (str.trim()) {
|
|
if (str.trim()) {
|
|
@@ -351,7 +365,7 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => {
|
|
|
|
|
|
let index = 0;
|
|
let index = 0;
|
|
while (index < words.length) {
|
|
while (index < words.length) {
|
|
- const currentWordWidth = getTextWidth(words[index], font);
|
|
|
|
|
|
+ const currentWordWidth = getLineWidth(words[index], font);
|
|
|
|
|
|
// Start breaking longer words exceeding max width
|
|
// Start breaking longer words exceeding max width
|
|
if (currentWordWidth >= maxWidth) {
|
|
if (currentWordWidth >= maxWidth) {
|
|
@@ -400,7 +414,7 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => {
|
|
// Start appending words in a line till max width reached
|
|
// Start appending words in a line till max width reached
|
|
while (currentLineWidthTillNow < maxWidth && index < words.length) {
|
|
while (currentLineWidthTillNow < maxWidth && index < words.length) {
|
|
const word = words[index];
|
|
const word = words[index];
|
|
- currentLineWidthTillNow = getTextWidth(currentLine + word, font);
|
|
|
|
|
|
+ currentLineWidthTillNow = getLineWidth(currentLine + word, font);
|
|
|
|
|
|
if (currentLineWidthTillNow >= maxWidth) {
|
|
if (currentLineWidthTillNow >= maxWidth) {
|
|
push(currentLine);
|
|
push(currentLine);
|
|
@@ -448,7 +462,7 @@ export const charWidth = (() => {
|
|
cachedCharWidth[font] = [];
|
|
cachedCharWidth[font] = [];
|
|
}
|
|
}
|
|
if (!cachedCharWidth[font][ascii]) {
|
|
if (!cachedCharWidth[font][ascii]) {
|
|
- const width = getTextWidth(char, font);
|
|
|
|
|
|
+ const width = getLineWidth(char, font);
|
|
cachedCharWidth[font][ascii] = width;
|
|
cachedCharWidth[font][ascii] = width;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -508,7 +522,7 @@ export const getApproxCharsToFitInWidth = (font: FontString, width: number) => {
|
|
while (widthTillNow <= width) {
|
|
while (widthTillNow <= width) {
|
|
const batch = dummyText.substr(index, index + batchLength);
|
|
const batch = dummyText.substr(index, index + batchLength);
|
|
str += batch;
|
|
str += batch;
|
|
- widthTillNow += getTextWidth(str, font);
|
|
|
|
|
|
+ widthTillNow += getLineWidth(str, font);
|
|
if (index === dummyText.length - 1) {
|
|
if (index === dummyText.length - 1) {
|
|
index = 0;
|
|
index = 0;
|
|
}
|
|
}
|
|
@@ -517,7 +531,7 @@ export const getApproxCharsToFitInWidth = (font: FontString, width: number) => {
|
|
|
|
|
|
while (widthTillNow > width) {
|
|
while (widthTillNow > width) {
|
|
str = str.substr(0, str.length - 1);
|
|
str = str.substr(0, str.length - 1);
|
|
- widthTillNow = getTextWidth(str, font);
|
|
|
|
|
|
+ widthTillNow = getLineWidth(str, font);
|
|
}
|
|
}
|
|
return str.length;
|
|
return str.length;
|
|
};
|
|
};
|