Skip to content

Commit a299f28

Browse files
authored
Merge pull request #381 from Dessia-tech/fix/text
Fix/text
2 parents a0c17e0 + 77749ff commit a299f28

7 files changed

Lines changed: 55 additions & 33 deletions

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [0.25.0]
99
### Add
1010
- Shapes: all shapes can now be set as not interacting with mouse
11+
-
12+
### Fix
13+
- Text: Fix text drawing when font is less than 1
1114

1215
## [0.24.0]
1316
### Add
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading

src/shapes.ts

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,21 @@ export class Text extends Shape {
152152
]
153153
}
154154

155+
private computeFontSize(text: string, defaultFontSize: number, context: CanvasRenderingContext2D): number {
156+
let defaultTextWidth = 0;
157+
if (defaultFontSize < 1) {
158+
context.font = Text.buildFont(this.style, 1, this.font);
159+
defaultTextWidth = context.measureText(text).width * defaultFontSize;
160+
} else defaultTextWidth = context.measureText(text).width;
161+
if (defaultTextWidth >= this.boundingBox.size.x) return defaultFontSize * this.boundingBox.size.x / defaultTextWidth;
162+
return defaultFontSize
163+
}
164+
155165
private automaticFontSize(context: CanvasRenderingContext2D): number {
156166
let fontsize = Math.min(this.boundingBox.size.y ?? Number.POSITIVE_INFINITY, this.fontsize ?? Number.POSITIVE_INFINITY);
157167
if (fontsize == Number.POSITIVE_INFINITY) fontsize = C.DEFAULT_FONTSIZE;
158168
context.font = Text.buildFont(this.style, fontsize, this.font);
159-
if (context.measureText(this.text).width >= this.boundingBox.size.x) fontsize = fontsize * this.boundingBox.size.x / context.measureText(this.text).width;
160-
return fontsize
169+
return this.computeFontSize(this.text, fontsize, context)
161170
}
162171

163172
private setRectOffsetX(): number {
@@ -225,7 +234,13 @@ export class Text extends Shape {
225234
context.resetTransform();
226235
context.translate(origin.x, origin.y);
227236
context.rotate(Math.PI / 180 * this.orientation);
228-
if (this.isScaled) context.scale(Math.abs(contextMatrix.a), Math.abs(contextMatrix.d));
237+
if (this.isScaled) {
238+
if (this.fontsize < 1) {
239+
context.scale(Math.abs(contextMatrix.a * this.fontsize), Math.abs(contextMatrix.d * this.fontsize));
240+
context.font = Text.buildFont(this.style, 1, this.font);
241+
}
242+
else context.scale(Math.abs(contextMatrix.a), Math.abs(contextMatrix.d));
243+
}
229244
this.write(this.writtenText, context);
230245
}
231246

@@ -263,10 +278,11 @@ export class Text extends Shape {
263278

264279
private multiLineWrite(writtenText: string[], middleFactor: number, context: CanvasRenderingContext2D): void {
265280
const nRows = writtenText.length - 1;
281+
const fontsize = Math.max(this.fontsize, 1);
266282
writtenText.forEach((row, index) => {
267283
["top", "hanging"].includes(this.baseline)
268-
? context.fillText(index == 0 ? Text.capitalize(row) : row, 0, index * this.fontsize + this.offset)
269-
: context.fillText(index == 0 ? Text.capitalize(row) : row, 0, (index - nRows / middleFactor) * this.fontsize + this.offset);
284+
? context.fillText(index == 0 ? Text.capitalize(row) : row, 0, index * fontsize + this.offset)
285+
: context.fillText(index == 0 ? Text.capitalize(row) : row, 0, (index - nRows / middleFactor) * fontsize + this.offset);
270286
});
271287
}
272288

@@ -319,7 +335,7 @@ export class Text extends Shape {
319335
const [writtenText, fontsize] = this.formatInBoundingBox(context);
320336
this.fontsize = Math.abs(fontsize);
321337
this.height = writtenText.length * this.fontsize;
322-
this.width = this.getLongestRow(context, writtenText);
338+
this.width = this.fontsize > 1 ? this.getLongestRow(context, writtenText) : this.boundingBox.size.x ?? this.getLongestRow(context, writtenText);
323339
this.rowIndices = this.computeRowIndices(writtenText);
324340
return writtenText
325341
}
@@ -330,7 +346,7 @@ export class Text extends Shape {
330346
if (oneRowLength < this.boundingBox.size.x) {
331347
return [[this.text.trimStart()], fontsize > this.boundingBox.size.y ? this.boundingBox.size.y ?? fontsize : fontsize];
332348
}
333-
if (!this.boundingBox.size.y) return [this.fixedFontSplit(context), fontsize];
349+
if (!this.boundingBox.size.y) return this.fixedFontSplit(fontsize, context)
334350
return this.autoFontSplit(fontsize, context);
335351
}
336352

@@ -339,14 +355,11 @@ export class Text extends Shape {
339355
return this.splitInWords();
340356
}
341357

342-
private pushSeparatorInWords(pickedChars: number): [string, number] {
343-
return [this.text[pickedChars], pickedChars + 1]
344-
}
345-
346358
private buildWord(pickedChars: number, word: string): [string, number] {
347-
while (!C.TEXT_SEPARATORS.includes(this.text[pickedChars]) && pickedChars < this.text.length) {
359+
while (pickedChars < this.text.length) {
348360
word += this.text[pickedChars];
349361
pickedChars++;
362+
if (C.TEXT_SEPARATORS.includes(word[word.length - 1])) break;
350363
}
351364
return [word, pickedChars]
352365
}
@@ -356,8 +369,7 @@ export class Text extends Shape {
356369
let pickedChars = 0;
357370
while (pickedChars < this.text.length) {
358371
let word = "";
359-
if (C.TEXT_SEPARATORS.includes(this.text[pickedChars])) [word, pickedChars] = this.pushSeparatorInWords(pickedChars)
360-
else [word, pickedChars] = this.buildWord(pickedChars, word);
372+
[word, pickedChars] = this.buildWord(pickedChars, word);
361373
words.push(word);
362374
}
363375
return words.length > 1 ? words : this.text.split("")
@@ -376,23 +388,30 @@ export class Text extends Shape {
376388
return [row + this.words[pickedWords], pickedWords + 1]
377389
}
378390

379-
private computeNewRow(context: CanvasRenderingContext2D, pickedWords: number, rows: string[]): [string[], number] {
391+
private computeNewRow(context: CanvasRenderingContext2D, pickedWords: number, rows: string[], fontsize: number): [string[], number, number] {
380392
let newRow = '';
381393
while (context.measureText(newRow).width < this.boundingBox.size.x && pickedWords < this.words.length) {
382-
if (this.isTextTooWide(context, newRow + this.words[pickedWords]) && newRow != '') break
383-
else [newRow, pickedWords] = this.addPickedWordToRow(newRow, pickedWords);
394+
if (this.isTextTooWide(context, newRow + this.words[pickedWords])) {
395+
if (newRow != '') break
396+
}
397+
[newRow, pickedWords] = this.addPickedWordToRow(newRow, pickedWords);
384398
}
385399
if (newRow.length != 0) rows.push(newRow);
386-
return [rows, pickedWords]
400+
return [rows, pickedWords, fontsize]
387401
}
388402

389-
private fixedFontSplit(context: CanvasRenderingContext2D): string[] {
403+
private fixedFontSplit(fontsize: number, context: CanvasRenderingContext2D): [string[], number] {
390404
let rows: string[] = [];
391405
let pickedWords = 0;
392-
while (pickedWords < this.words.length) [rows, pickedWords] = this.computeNewRow(context, pickedWords, rows);
393-
return rows
406+
while (pickedWords < this.words.length) {
407+
[rows, pickedWords, fontsize] = this.computeNewRow(context, pickedWords, rows, fontsize);
408+
if (this.isTextTooWide(context, rows[rows.length - 1])) {
409+
fontsize = this.computeFontSize(rows[rows.length - 1], fontsize, context);
410+
context.font = Text.buildFont(this.style, fontsize, this.font);
411+
}
412+
}
413+
return [rows, fontsize]
394414
}
395-
396415
private cleanStartAllRows(rows: string[]): string[] { return rows.map(row => row.trimStart()) }
397416

398417
private checkWordsLength(context: CanvasRenderingContext2D): boolean {
@@ -404,7 +423,7 @@ export class Text extends Shape {
404423

405424
private computeTextHeight(fontsize: number, textHeight: number, rows: string[], context: CanvasRenderingContext2D): [string[], number] {
406425
if (this.checkWordsLength(context)) {
407-
rows = this.fixedFontSplit(context);
426+
rows = this.fixedFontSplit(fontsize, context)[0];
408427
textHeight = fontsize * rows.length;
409428
}
410429
return [rows, textHeight]

0 commit comments

Comments
 (0)