Skip to content

Commit 5c836c4

Browse files
Fix printing string when words are longer than max-width (#1313)
1 parent 9828a2f commit 5c836c4

3 files changed

+46
-0
lines changed

plugins/plugin-print/src/index.node.test.ts

+18
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,24 @@ describe("Write text over image", function () {
109109
expect(output).toMatchImageSnapshot();
110110
});
111111

112+
test("Max width works without spaces", async () => {
113+
const font = await loadFont(
114+
"https://raw.githubusercontent.com/jimp-dev/jimp/main/plugins/plugin-print/fonts/open-sans/open-sans-16-black/open-sans-16-black.fnt"
115+
);
116+
const image = new Jimp({ width: 300, height: 100, color: 0xff8800ff });
117+
const output = await image
118+
.print({
119+
font,
120+
x: 150,
121+
y: 50,
122+
text: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
123+
maxWidth: 100,
124+
})
125+
.getBuffer("image/png");
126+
127+
expect(output).toMatchImageSnapshot();
128+
});
129+
112130
test("Jimp renders ? for unknown characters", async () => {
113131
const font = await loadFont(fonts.SANS_16_BLACK);
114132
const image = new Jimp({ width: 300, height: 100, color: 0xff8800ff });

plugins/plugin-print/src/measure-text.ts

+28
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,34 @@ export function splitLines(font: BmFont, text: string, maxWidth: number) {
3030
let longestLine = 0;
3131

3232
words.forEach((word) => {
33+
const wordWidth = measureText(font, word + (words.length > 1 ? " " : ""));
34+
35+
// If a word is longer than the allowable width we need to split it across lines.
36+
if (wordWidth > maxWidth) {
37+
const characterIterator = word[Symbol.iterator]();
38+
39+
let current = "";
40+
41+
for (const char of characterIterator) {
42+
const nextLine = [...currentLine, current + char].join(" ");
43+
const length = measureText(font, nextLine);
44+
45+
if (length < maxWidth) {
46+
current += char;
47+
} else if (length > maxWidth) {
48+
lines.push([...currentLine, current]);
49+
currentLine = [];
50+
current = char;
51+
} else {
52+
lines.push([...currentLine, current + char]);
53+
currentLine = [];
54+
current = "";
55+
}
56+
}
57+
58+
return;
59+
}
60+
3361
const line = [...currentLine, word].join(" ");
3462
const length = measureText(font, line);
3563

0 commit comments

Comments
 (0)