Skip to content

Commit 5b14011

Browse files
committed
Working through BitmapText wrapping
1 parent adad830 commit 5b14011

4 files changed

Lines changed: 286 additions & 3 deletions

File tree

src/gameobjects/bitmaptext/GetBitmapTextSize.js

Lines changed: 208 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,17 @@ var GetBitmapTextSize = function (src, round, out)
4444
lines: {
4545
shortest: 0,
4646
longest: 0,
47-
lengths: null
48-
}
47+
lengths: null,
48+
height: 0
49+
},
50+
words: [],
51+
maxWidth: 0
4952
};
5053
}
5154

5255
var text = src.text;
5356
var textLength = text.length;
57+
var maxWidth = src.maxWidth;
5458

5559
var bx = Number.MAX_VALUE;
5660
var by = Number.MAX_VALUE;
@@ -61,6 +65,8 @@ var GetBitmapTextSize = function (src, round, out)
6165
var lineHeight = src.fontData.lineHeight;
6266
var letterSpacing = src.letterSpacing;
6367

68+
out.lines.height = lineHeight;
69+
6470
var xAdvance = 0;
6571
var yAdvance = 0;
6672

@@ -83,16 +89,183 @@ var GetBitmapTextSize = function (src, round, out)
8389
var currentLine = 0;
8490
var currentLineWidth = 0;
8591

86-
for (var i = 0; i < textLength; i++)
92+
var words = [];
93+
var current = null;
94+
95+
// Scan for breach of maxWidth and insert carriage-returns
96+
if (maxWidth > 0 && out.maxWidth !== maxWidth)
97+
{
98+
for (var i = 0; i < textLength; i++)
99+
{
100+
charCode = text.charCodeAt(i);
101+
102+
if (charCode === 10)
103+
{
104+
if (current !== null)
105+
{
106+
// This time it doesn't include the scale x/y modifiers,
107+
// as we're comparing against an unscaled pixel value.
108+
words.push({
109+
word: current.word,
110+
i: current.i,
111+
x: current.x,
112+
y: current.y,
113+
w: current.w,
114+
h: current.h
115+
});
116+
117+
current = null;
118+
}
119+
120+
xAdvance = 0;
121+
yAdvance += lineHeight;
122+
lastGlyph = null;
123+
124+
continue;
125+
}
126+
127+
glyph = chars[charCode];
128+
129+
if (!glyph)
130+
{
131+
continue;
132+
}
133+
134+
if (lastGlyph !== null)
135+
{
136+
var glyphKerningOffset = glyph.kerning[lastCharCode];
137+
}
138+
139+
if (charCode === 32)
140+
{
141+
if (current !== null)
142+
{
143+
words.push({
144+
word: current.word,
145+
i: current.i,
146+
x: current.x,
147+
y: current.y,
148+
w: current.w,
149+
h: current.h
150+
});
151+
152+
current = null;
153+
}
154+
}
155+
else
156+
{
157+
if (current === null)
158+
{
159+
// We're starting a new word, recording the starting index, etc
160+
current = { word: '', i: i, x: xAdvance, y: yAdvance, w: 0, h: lineHeight };
161+
}
162+
163+
current.word = current.word.concat(text[i]);
164+
current.w += glyph.xOffset + glyph.xAdvance + ((glyphKerningOffset !== undefined) ? glyphKerningOffset : 0);
165+
}
166+
167+
xAdvance += glyph.xAdvance + letterSpacing;
168+
lastGlyph = glyph;
169+
lastCharCode = charCode;
170+
}
171+
172+
// Last word
173+
if (current !== null)
174+
{
175+
words.push({
176+
word: current.word,
177+
i: current.i,
178+
x: current.x,
179+
y: current.y,
180+
w: current.w,
181+
h: current.h
182+
});
183+
}
184+
185+
// Reset for the next loop
186+
xAdvance = 0;
187+
yAdvance = 0;
188+
lastGlyph = null;
189+
lastCharCode = 0;
190+
191+
// Loop through the words array and see if we've got any > maxWidth
192+
console.log('maxWidth words array');
193+
console.log(words);
194+
195+
var offset = 0;
196+
var line = 0;
197+
var crs = [];
198+
199+
for (i = 0; i < words.length; i++)
200+
{
201+
var entry = words[i];
202+
var checkX = (entry.x - line - offset) + entry.w;
203+
204+
console.log(entry.word, '=', checkX);
205+
206+
if (checkX > maxWidth)
207+
{
208+
// CR needed
209+
console.log('CR needed before', entry.word);
210+
211+
crs.push({ word: entry.word, index: entry.i - 1 });
212+
213+
offset = entry.w;
214+
line += maxWidth;
215+
}
216+
}
217+
218+
var stringInsert = function (str, index, value)
219+
{
220+
return str.substr(0, index) + value + str.substr(index);
221+
};
222+
223+
for (i = crs.length - 1; i >= 0; i--)
224+
{
225+
console.log('injecting at', crs[i]);
226+
227+
// eslint-disable-next-line quotes
228+
text = stringInsert(text, crs[i].index, "\n");
229+
}
230+
231+
console.log(text);
232+
233+
out.maxWidth = maxWidth;
234+
235+
src._text = text;
236+
textLength = text.length;
237+
238+
// Recalculated in the next loop
239+
words = [];
240+
current = { word: '', x: 0, y: 0, w: 0, h: lineHeight };
241+
}
242+
else
243+
{
244+
current = { word: '', x: 0, y: 0, w: 0, h: lineHeight };
245+
}
246+
247+
// TODO: Needs modifying to use the current = null approach above
248+
249+
for (i = 0; i < textLength; i++)
87250
{
88251
charCode = text.charCodeAt(i);
89252

90253
if (charCode === 10)
91254
{
255+
words.push({
256+
word: current.word,
257+
x: current.x * sx,
258+
y: current.y * sy,
259+
w: current.w * sx,
260+
h: current.h * sy
261+
});
262+
92263
xAdvance = 0;
93264
yAdvance += lineHeight;
94265
lastGlyph = null;
95266

267+
current = { word: '', x: xAdvance, y: yAdvance, w: 0, h: lineHeight };
268+
96269
lineWidths[currentLine] = currentLineWidth;
97270

98271
if (currentLineWidth > longestLine)
@@ -153,6 +326,36 @@ var GetBitmapTextSize = function (src, round, out)
153326
lastGlyph = glyph;
154327
lastCharCode = charCode;
155328
currentLineWidth = gw * scale;
329+
330+
if (charCode === 32)
331+
{
332+
words.push({
333+
word: current.word,
334+
x: current.x * sx,
335+
y: current.y * sy,
336+
w: current.w * sx,
337+
h: current.h * sy
338+
});
339+
340+
current = { word: '', x: xAdvance, y: yAdvance, w: 0, h: lineHeight };
341+
}
342+
else
343+
{
344+
current.word = current.word.concat(text[i]);
345+
current.w += glyph.xOffset + glyph.xAdvance + ((kerningOffset !== undefined) ? kerningOffset : 0);
346+
}
347+
}
348+
349+
// Last word
350+
if (current !== null)
351+
{
352+
words.push({
353+
word: current.word,
354+
x: current.x * sx,
355+
y: current.y * sy,
356+
w: current.w * sx,
357+
h: current.h * sy
358+
});
156359
}
157360

158361
lineWidths[currentLine] = currentLineWidth;
@@ -201,6 +404,8 @@ var GetBitmapTextSize = function (src, round, out)
201404
lines.longest = Math.round(longestLine);
202405
}
203406

407+
out.words = words;
408+
204409
return out;
205410
};
206411

src/gameobjects/bitmaptext/static/BitmapText.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ var BitmapText = new Class({
111111
*/
112112
this.fontData = entry.data;
113113

114+
/**
115+
* @property {number} _maxWidth - Internal cache var.
116+
* @private
117+
* @since 3.21.0
118+
*/
119+
this._maxWidth = 0;
120+
114121
/**
115122
* The text that this Bitmap Text object displays.
116123
*
@@ -351,6 +358,15 @@ var BitmapText = new Class({
351358
if (this._dirty)
352359
{
353360
GetBitmapTextSize(this, round, this._bounds);
361+
362+
if (this._bounds.reset)
363+
{
364+
this._bounds.reset = false;
365+
366+
this.updateDisplayOrigin();
367+
}
368+
369+
this._dirty = false;
354370
}
355371

356372
return this._bounds;
@@ -396,6 +412,31 @@ var BitmapText = new Class({
396412
return this;
397413
},
398414

415+
/**
416+
* Sets the maximum display width of this BitmapText in pixels.
417+
*
418+
* If `BitmapText.text` is longer than `maxWidth` then the lines will be automatically wrapped
419+
* based on the previous whitespace character found in the line.
420+
*
421+
* If no whitespace was found then no wrapping will take place and consequently the `maxWidth` value will not be honored.
422+
*
423+
* Disable maxWidth by setting the value to 0.
424+
*
425+
* @method Phaser.GameObjects.BitmapText#setMaxWidth
426+
* @since 3.21.0
427+
*
428+
* @param {number} value - The maximum display width of this BitmapText in pixels. Set to zero to disable.
429+
*
430+
* @return {this} This BitmapText Object.
431+
*/
432+
setMaxWidth: function (value)
433+
{
434+
this._maxWidth = value;
435+
this._dirty = true;
436+
437+
return this;
438+
},
439+
399440
/**
400441
* Controls the alignment of each line of text in this BitmapText object.
401442
*
@@ -502,6 +543,35 @@ var BitmapText = new Class({
502543

503544
},
504545

546+
/**
547+
* The maximum display width of this BitmapText in pixels.
548+
*
549+
* If BitmapText.text is longer than maxWidth then the lines will be automatically wrapped
550+
* based on the last whitespace character found in the line.
551+
*
552+
* If no whitespace was found then no wrapping will take place and consequently the maxWidth value will not be honored.
553+
*
554+
* Disable maxWidth by setting the value to 0.
555+
*
556+
* @name Phaser.GameObjects.BitmapText#maxWidth
557+
* @type {number}
558+
* @since 3.21.0
559+
*/
560+
maxWidth: {
561+
562+
set: function (value)
563+
{
564+
this._maxWidth = value;
565+
this._dirty = true;
566+
},
567+
568+
get: function ()
569+
{
570+
return this._maxWidth;
571+
}
572+
573+
},
574+
505575
/**
506576
* The width of this Bitmap Text.
507577
*

src/gameobjects/bitmaptext/static/BitmapTextCanvasRenderer.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ var BitmapTextCanvasRenderer = function (renderer, src, interpolationPercentage,
7070
// Update the bounds - skipped internally if not dirty
7171
src.getTextBounds(false);
7272

73+
// In case the method above changed it (word wrapping)
74+
text = src._text;
75+
textLength = text.length;
76+
7377
var lineData = src._bounds.lines;
7478

7579
if (align === 1)

src/gameobjects/bitmaptext/static/BitmapTextWebGLRenderer.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ var BitmapTextWebGLRenderer = function (renderer, src, interpolationPercentage,
103103
// Update the bounds - skipped internally if not dirty
104104
src.getTextBounds(false);
105105

106+
// In case the method above changed it (word wrapping)
107+
text = src._text;
108+
textLength = text.length;
109+
106110
var lineData = src._bounds.lines;
107111

108112
if (align === 1)

0 commit comments

Comments
 (0)