fix: preserve trailing spaces in word wrap
This commit is contained in:
parent
5ddb28d378
commit
caf0a904db
@ -384,7 +384,7 @@ export const getApproxMinLineHeight = (
|
|||||||
|
|
||||||
let canvas: HTMLCanvasElement | undefined;
|
let canvas: HTMLCanvasElement | undefined;
|
||||||
|
|
||||||
const getLineWidth = (text: string, font: FontString) => {
|
export const getLineWidth = (text: string, font: FontString) => {
|
||||||
if (!canvas) {
|
if (!canvas) {
|
||||||
canvas = document.createElement("canvas");
|
canvas = document.createElement("canvas");
|
||||||
}
|
}
|
||||||
@ -444,10 +444,9 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => {
|
|||||||
if (!Number.isFinite(maxWidth) || maxWidth < 0) {
|
if (!Number.isFinite(maxWidth) || maxWidth < 0) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
console.log("TEXT =", text, maxWidth);
|
||||||
const lines: Array<string> = [];
|
const lines: Array<string> = [];
|
||||||
const originalLines = text.split("\n");
|
const originalLines = text.split("\n");
|
||||||
const spaceWidth = getLineWidth(" ", font);
|
|
||||||
|
|
||||||
let currentLine = "";
|
let currentLine = "";
|
||||||
let currentLineWidthTillNow = 0;
|
let currentLineWidthTillNow = 0;
|
||||||
@ -463,7 +462,7 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => {
|
|||||||
currentLineWidthTillNow = 0;
|
currentLineWidthTillNow = 0;
|
||||||
};
|
};
|
||||||
originalLines.forEach((originalLine) => {
|
originalLines.forEach((originalLine) => {
|
||||||
const currentLineWidth = getTextWidth(originalLine, font);
|
const currentLineWidth = getLineWidth(originalLine, font);
|
||||||
|
|
||||||
// Push the line if its <= maxWidth
|
// Push the line if its <= maxWidth
|
||||||
if (currentLineWidth <= maxWidth) {
|
if (currentLineWidth <= maxWidth) {
|
||||||
@ -472,6 +471,7 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const words = parseTokens(originalLine);
|
const words = parseTokens(originalLine);
|
||||||
|
console.log(words, "words");
|
||||||
resetParams();
|
resetParams();
|
||||||
|
|
||||||
let index = 0;
|
let index = 0;
|
||||||
@ -511,23 +511,25 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// push current line if appending space exceeds max width
|
// push current line if appending space exceeds max width
|
||||||
if (currentLineWidthTillNow + spaceWidth >= maxWidth) {
|
if (currentLineWidthTillNow >= maxWidth) {
|
||||||
push(currentLine);
|
push(currentLine);
|
||||||
resetParams();
|
resetParams();
|
||||||
// space needs to be appended before next word
|
// space needs to be appended before next word
|
||||||
// as currentLine contains chars which couldn't be appended
|
// as currentLine contains chars which couldn't be appended
|
||||||
// to previous line unless the line ends with hyphen to sync
|
// to previous line unless the line ends with hyphen to sync
|
||||||
// with css word-wrap
|
// with css word-wrap
|
||||||
} else if (!currentLine.endsWith("-")) {
|
} else if (!currentLine.endsWith("-") && index < words.length) {
|
||||||
currentLine += " ";
|
currentLine += " ";
|
||||||
currentLineWidthTillNow += spaceWidth;
|
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
} else {
|
} else {
|
||||||
// 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 = getLineWidth(currentLine + word, font);
|
currentLineWidthTillNow = getLineWidth(
|
||||||
|
`${currentLine + word}`.trimEnd(),
|
||||||
|
font,
|
||||||
|
);
|
||||||
|
|
||||||
if (currentLineWidthTillNow > maxWidth) {
|
if (currentLineWidthTillNow > maxWidth) {
|
||||||
push(currentLine);
|
push(currentLine);
|
||||||
@ -535,36 +537,44 @@ export const wrapText = (text: string, font: FontString, maxWidth: number) => {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
index++;
|
|
||||||
|
|
||||||
// if word ends with "-" then we don't need to add space
|
// if word ends with "-" then we don't need to add space
|
||||||
// to sync with css word-wrap
|
// to sync with css word-wrap
|
||||||
const shouldAppendSpace = !word.endsWith("-");
|
const shouldAppendSpace = !word.endsWith("-");
|
||||||
currentLine += word;
|
currentLine += word;
|
||||||
|
|
||||||
if (shouldAppendSpace) {
|
if (shouldAppendSpace && index < words.length) {
|
||||||
currentLine += " ";
|
currentLine += " ";
|
||||||
}
|
}
|
||||||
|
console.log("currentLine", currentLine, currentLine.length, index);
|
||||||
|
index++;
|
||||||
|
|
||||||
// Push the word if appending space exceeds max width
|
// Push the word if appending space exceeds max width
|
||||||
if (currentLineWidthTillNow + spaceWidth >= maxWidth) {
|
if (currentLineWidthTillNow >= maxWidth) {
|
||||||
if (shouldAppendSpace) {
|
// if (
|
||||||
lines.push(currentLine.slice(0, -1));
|
// currentLineWidthTillNow + spaceWidth === maxWidth &&
|
||||||
} else {
|
// index < words.length &&
|
||||||
|
// words[index] === ""
|
||||||
|
// ) {
|
||||||
|
// currentLine += " ";
|
||||||
|
// index++;
|
||||||
|
// }
|
||||||
|
|
||||||
lines.push(currentLine);
|
lines.push(currentLine);
|
||||||
}
|
|
||||||
resetParams();
|
resetParams();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log("currentLine", currentLine);
|
||||||
if (currentLine.slice(-1) === " ") {
|
if (currentLine.slice(-1) === " ") {
|
||||||
// only remove last trailing space which we have added when joining words
|
// only remove last trailing space which we have added when joining words
|
||||||
currentLine = currentLine.slice(0, -1);
|
currentLine = currentLine.slice(0, -1);
|
||||||
push(currentLine);
|
push(currentLine);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
console.log("TEXT Words", lines);
|
||||||
return lines.join("\n");
|
return lines.join("\n");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,17 +37,21 @@ import {
|
|||||||
MAX_DECIMALS_FOR_SVG_EXPORT,
|
MAX_DECIMALS_FOR_SVG_EXPORT,
|
||||||
MIME_TYPES,
|
MIME_TYPES,
|
||||||
SVG_NS,
|
SVG_NS,
|
||||||
|
TEXT_ALIGN,
|
||||||
} from "../constants";
|
} from "../constants";
|
||||||
import { getStroke, StrokeOptions } from "perfect-freehand";
|
import { getStroke, StrokeOptions } from "perfect-freehand";
|
||||||
import {
|
import {
|
||||||
getBoundTextElement,
|
getBoundTextElement,
|
||||||
|
getBoundTextElementOffset,
|
||||||
getContainerCoords,
|
getContainerCoords,
|
||||||
getContainerElement,
|
getContainerElement,
|
||||||
getLineHeightInPx,
|
getLineHeightInPx,
|
||||||
|
getLineWidth,
|
||||||
getMaxContainerHeight,
|
getMaxContainerHeight,
|
||||||
getMaxContainerWidth,
|
getMaxContainerWidth,
|
||||||
} from "../element/textElement";
|
} from "../element/textElement";
|
||||||
import { LinearElementEditor } from "../element/linearElementEditor";
|
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||||
|
import heILJsonE0bd304682986695208c from "../packages/excalidraw/dist/excalidraw-assets-dev/locales/he-IL-json-e0bd304682986695208c";
|
||||||
|
|
||||||
// using a stronger invert (100% vs our regular 93%) and saturate
|
// using a stronger invert (100% vs our regular 93%) and saturate
|
||||||
// as a temp hack to make images in dark theme look closer to original
|
// as a temp hack to make images in dark theme look closer to original
|
||||||
@ -319,13 +323,17 @@ const drawElementOnCanvas = (
|
|||||||
}
|
}
|
||||||
context.canvas.setAttribute("dir", rtl ? "rtl" : "ltr");
|
context.canvas.setAttribute("dir", rtl ? "rtl" : "ltr");
|
||||||
context.save();
|
context.save();
|
||||||
context.font = getFontString(element);
|
const font = getFontString(element);
|
||||||
|
context.font = font;
|
||||||
context.fillStyle = element.strokeColor;
|
context.fillStyle = element.strokeColor;
|
||||||
context.textAlign = element.textAlign as CanvasTextAlign;
|
context.textAlign = element.textAlign as CanvasTextAlign;
|
||||||
|
|
||||||
|
context.fillStyle = "yellow";
|
||||||
|
context.fillRect(0, 0, element.width, element.height);
|
||||||
|
context.fillStyle = element.strokeColor;
|
||||||
|
|
||||||
// Canvas does not support multiline text by default
|
// Canvas does not support multiline text by default
|
||||||
const lines = element.text.replace(/\r\n?/g, "\n").split("\n");
|
const lines = element.text.replace(/\r\n?/g, "\n").split("\n");
|
||||||
|
|
||||||
const horizontalOffset =
|
const horizontalOffset =
|
||||||
element.textAlign === "center"
|
element.textAlign === "center"
|
||||||
? element.width / 2
|
? element.width / 2
|
||||||
@ -336,11 +344,35 @@ const drawElementOnCanvas = (
|
|||||||
element.fontSize,
|
element.fontSize,
|
||||||
element.lineHeight,
|
element.lineHeight,
|
||||||
);
|
);
|
||||||
|
const container = getContainerElement(element);
|
||||||
|
if (container) {
|
||||||
|
console.log(
|
||||||
|
"Element width = ",
|
||||||
|
element.width,
|
||||||
|
getMaxContainerWidth(container),
|
||||||
|
);
|
||||||
|
}
|
||||||
const verticalOffset = element.height - element.baseline;
|
const verticalOffset = element.height - element.baseline;
|
||||||
for (let index = 0; index < lines.length; index++) {
|
for (let index = 0; index < lines.length; index++) {
|
||||||
|
const trailingSpacesWidth =
|
||||||
|
getLineWidth(lines[index], font) -
|
||||||
|
getLineWidth(lines[index].trimEnd(), font);
|
||||||
|
console.log(trailingSpacesWidth, "width");
|
||||||
|
const maxWidth = container
|
||||||
|
? getMaxContainerWidth(container)
|
||||||
|
: element.width;
|
||||||
|
const availableWidth =
|
||||||
|
maxWidth - getLineWidth(lines[index].trimEnd(), font);
|
||||||
|
let spacesOffset = 0;
|
||||||
|
if (element.textAlign === TEXT_ALIGN.CENTER) {
|
||||||
|
spacesOffset = -trailingSpacesWidth / 2;
|
||||||
|
} else if (element.textAlign === TEXT_ALIGN.RIGHT) {
|
||||||
|
spacesOffset = -Math.min(availableWidth, trailingSpacesWidth);
|
||||||
|
}
|
||||||
|
console.log(spacesOffset, "spacesOffset", trailingSpacesWidth);
|
||||||
context.fillText(
|
context.fillText(
|
||||||
lines[index],
|
lines[index].trimEnd(),
|
||||||
horizontalOffset,
|
horizontalOffset + spacesOffset,
|
||||||
(index + 1) * lineHeightPx - verticalOffset,
|
(index + 1) * lineHeightPx - verticalOffset,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user