Skip to content

Commit

Permalink
feat(text): support text letter spacing
Browse files Browse the repository at this point in the history
  • Loading branch information
singlecoder committed Jul 31, 2024
1 parent 728cec1 commit be1ba72
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
7 changes: 4 additions & 3 deletions packages/core/src/2d/text/TextRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -570,10 +570,11 @@ export class TextRenderer extends Renderer {
const { _pixelsPerUnit } = Engine;
const { horizontalAlignment } = this;
const pixelsPerUnitReciprocal = 1.0 / _pixelsPerUnit;
const rendererWidth = this.width * _pixelsPerUnit;
const rendererWidth = this._width * _pixelsPerUnit;
const halfRendererWidth = rendererWidth * 0.5;
const rendererHeight = this.height * _pixelsPerUnit;
const rendererHeight = this._height * _pixelsPerUnit;
const halfLineHeight = lineHeight * 0.5;
const letterSpacing = this._letterSpacing * _pixelsPerUnit;

let startY = 0;
const topDiff = lineHeight * 0.5 - lineMaxSizes[0].ascent;
Expand Down Expand Up @@ -635,7 +636,7 @@ export class TextRenderer extends Renderer {
j === firstRow && (minX = Math.min(minX, left));
maxX = Math.max(maxX, right);
}
startX += charInfo.xAdvance;
startX += charInfo.xAdvance + letterSpacing;
}
}
startY -= lineHeight;
Expand Down
21 changes: 15 additions & 6 deletions packages/core/src/2d/text/TextUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export class TextUtils {
const pixelsPerUnit = Engine._pixelsPerUnit;
const lineHeight = fontSizeInfo.size + renderer.lineSpacing * pixelsPerUnit;
const wrapWidth = renderer.width * pixelsPerUnit;
const letterSpacing = renderer.letterSpacing * pixelsPerUnit;
let textWidth = 0;

subFont.nativeFontString = fontString;
Expand Down Expand Up @@ -155,6 +156,7 @@ export class TextUtils {
if (lineWidth + wordWidth > wrapWidth) {
// Push if before line is not empty
if (lineWidth > 0) {
lineWidth -= letterSpacing;
this._pushLine(lines, lineWidths, lineMaxSizes, line, lineWidth, lineMaxAscent, lineMaxDescent);
}

Expand All @@ -178,6 +180,7 @@ export class TextUtils {
// Handle char
// At least one char in a line
if (lineWidth + w > wrapWidth && lineWidth > 0) {
lineWidth -= letterSpacing;
this._pushLine(lines, lineWidths, lineMaxSizes, line, lineWidth, lineMaxAscent, lineMaxDescent);
textWidth = Math.max(textWidth, lineWidth);
notFirstLine = true;
Expand All @@ -186,19 +189,20 @@ export class TextUtils {
lineWidth = lineMaxAscent = lineMaxDescent = 0;
} else {
line = char;
lineWidth = charInfo.xAdvance;
lineWidth = charInfo.xAdvance + letterSpacing;
lineMaxAscent = ascent;
lineMaxDescent = descent;
}
} else {
line += char;
lineWidth += charInfo.xAdvance;
lineWidth += charInfo.xAdvance + letterSpacing;
lineMaxAscent = Math.max(lineMaxAscent, ascent);
lineMaxDescent = Math.max(lineMaxDescent, descent);
}
} else {
if (wordWidth + charInfo.w > wrapWidth) {
if (lineWidth > 0) {
lineWidth -= letterSpacing;
this._pushLine(lines, lineWidths, lineMaxSizes, line, lineWidth, lineMaxAscent, lineMaxDescent);
textWidth = Math.max(textWidth, lineWidth);
line = "";
Expand All @@ -213,12 +217,12 @@ export class TextUtils {
textWidth = Math.max(textWidth, wordWidth);
notFirstLine = true;
word = char;
wordWidth = charInfo.xAdvance;
wordWidth = charInfo.xAdvance + letterSpacing;
wordMaxAscent = ascent;
wordMaxDescent = descent;
} else {
word += char;
wordWidth += charInfo.xAdvance;
wordWidth += charInfo.xAdvance + letterSpacing;
wordMaxAscent = Math.max(wordMaxAscent, ascent);
wordMaxDescent = Math.max(wordMaxDescent, descent);
}
Expand All @@ -230,13 +234,15 @@ export class TextUtils {
if (lineWidth + wordWidth > wrapWidth) {
// Push chars to a single line
if (lineWidth > 0) {
lineWidth -= letterSpacing;
this._pushLine(lines, lineWidths, lineMaxSizes, line, lineWidth, lineMaxAscent, lineMaxDescent);
}
textWidth = Math.max(textWidth, lineWidth);

lineWidth = 0;
// Push word to a single line
if (wordWidth > 0) {
wordWidth -= letterSpacing;
this._pushLine(lines, lineWidths, lineMaxSizes, word, wordWidth, wordMaxAscent, wordMaxDescent);
}
textWidth = Math.max(textWidth, wordWidth);
Expand All @@ -250,6 +256,7 @@ export class TextUtils {
}

if (lineWidth > 0) {
lineWidth -= letterSpacing;
this._pushLine(lines, lineWidths, lineMaxSizes, line, lineWidth, lineMaxAscent, lineMaxDescent);
textWidth = Math.max(textWidth, lineWidth);
}
Expand Down Expand Up @@ -281,16 +288,18 @@ export class TextUtils {
const lineMaxSizes = new Array<FontSizeInfo>();
const { _pixelsPerUnit } = Engine;
const lineHeight = fontSizeInfo.size + renderer.lineSpacing * _pixelsPerUnit;
const letterSpacing = renderer.letterSpacing * _pixelsPerUnit;

let width = 0;
subFont.nativeFontString = fontString;
for (let i = 0; i < textCount; ++i) {
const line = subTexts[i];
let curWidth = 0;
const lineLength = line.length;
let curWidth = lineLength > 1 ? letterSpacing * (lineLength - 1) : 0;
let maxAscent = 0;
let maxDescent = 0;

for (let j = 0, m = line.length; j < m; ++j) {
for (let j = 0; j < lineLength; ++j) {
const charInfo = TextUtils._getCharInfo(line[j], fontString, subFont);
curWidth += charInfo.xAdvance;
const { offsetY } = charInfo;
Expand Down

0 comments on commit be1ba72

Please sign in to comment.