Skip to content

Commit 0c3f144

Browse files
committed
Port v2 text wrapping functions to Text
1 parent 7aa519c commit 0c3f144

1 file changed

Lines changed: 199 additions & 0 deletions

File tree

  • v3/src/gameobjects/text/static

v3/src/gameobjects/text/static/Text.js

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,205 @@ var Text = new Class({
124124
this.originX = 1;
125125
},
126126

127+
/**
128+
* Greedy wrapping algorithm that will wrap words as the line grows longer than its horizontal
129+
* bounds.
130+
*
131+
* @param {string} text - The text to perform word wrap detection against.
132+
*/
133+
runWordWrap: function (text)
134+
{
135+
var style = this.style;
136+
if (style.wordWrapCallback)
137+
{
138+
var wrappedLines = style.wordWrapCallback.call(style.wordWrapCallbackScope, text, this);
139+
if (Array.isArray(wrappedLines))
140+
{
141+
wrappedLines = wrappedLines.join('\n');
142+
}
143+
return wrappedLines;
144+
}
145+
else if (style.wordWrapWidth)
146+
{
147+
if (style.wordWrapUseAdvanced)
148+
{
149+
return this.advancedWordWrap(text);
150+
}
151+
else
152+
{
153+
return this.basicWordWrap(text);
154+
}
155+
}
156+
else
157+
{
158+
return text;
159+
}
160+
},
161+
162+
/**
163+
* Advanced wrapping algorithm that will wrap words as the line grows longer than its horizontal
164+
* bounds. White space is condensed (e.g., consecutive spaces are replaced with one). Lines are
165+
* trimmed of white space before processing. Throws an error if the user was smart enough to
166+
* specify a wordWrapWidth less than a single character.
167+
*
168+
* @param {string} text - The text to perform word wrap detection against.
169+
*/
170+
advancedWordWrap: function (text)
171+
{
172+
var context = this.context;
173+
var wordWrapWidth = this.style.wordWrapWidth;
174+
var output = '';
175+
176+
// condense consecutive spaces and split into lines
177+
var lines = text
178+
.replace(/ +/gi, ' ')
179+
.split(/\r?\n/gi);
180+
181+
var linesCount = lines.length;
182+
183+
for (var i = 0; i < linesCount; i++)
184+
{
185+
var line = lines[i];
186+
var out = '';
187+
188+
// trim whitespace
189+
line = line.replace(/^ *|\s*$/gi, '');
190+
191+
// if entire line is less than wordWrapWidth append the entire line and exit early
192+
var lineWidth = context.measureText(line).width;
193+
194+
if (lineWidth < wordWrapWidth)
195+
{
196+
output += line + '\n';
197+
continue;
198+
}
199+
200+
// otherwise, calculate new lines
201+
var currentLineWidth = wordWrapWidth;
202+
203+
// split into words
204+
var words = line.split(' ');
205+
206+
for (var j = 0; j < words.length; j++)
207+
{
208+
var word = words[j];
209+
var wordWithSpace = word + ' ';
210+
var wordWidth = context.measureText(wordWithSpace).width;
211+
212+
if (wordWidth > currentLineWidth)
213+
{
214+
// break word
215+
if (j === 0)
216+
{
217+
// shave off letters from word until it's small enough
218+
var newWord = wordWithSpace;
219+
220+
while (newWord.length)
221+
{
222+
newWord = newWord.slice(0, -1);
223+
wordWidth = context.measureText(newWord).width;
224+
225+
if (wordWidth <= currentLineWidth)
226+
{
227+
break;
228+
}
229+
}
230+
231+
// if wordWrapWidth is too small for even a single letter, shame user
232+
// failure with a fatal error
233+
if (!newWord.length)
234+
{
235+
throw new Error('This text\'s wordWrapWidth setting is less than a single character!');
236+
}
237+
238+
// replace current word in array with remainder
239+
var secondPart = word.substr(newWord.length);
240+
241+
words[j] = secondPart;
242+
243+
// append first piece to output
244+
out += newWord;
245+
}
246+
247+
// if existing word length is 0, don't include it
248+
var offset = (words[j].length) ? j : j + 1;
249+
250+
// collapse rest of sentence and remove any trailing white space
251+
var remainder = words.slice(offset).join(' ')
252+
.replace(/[ \n]*$/gi, '');
253+
254+
// prepend remainder to next line
255+
lines[i + 1] = remainder + ' ' + (lines[i + 1] || '');
256+
linesCount = lines.length;
257+
258+
break; // processing on this line
259+
260+
// append word with space to output
261+
}
262+
else
263+
{
264+
out += wordWithSpace;
265+
currentLineWidth -= wordWidth;
266+
}
267+
}
268+
269+
// append processed line to output
270+
output += out.replace(/[ \n]*$/gi, '') + '\n';
271+
}
272+
273+
// trim the end of the string
274+
output = output.replace(/[\s|\n]*$/gi, '');
275+
276+
return output;
277+
},
278+
279+
/**
280+
* Greedy wrapping algorithm that will wrap words as the line grows longer than its horizontal
281+
* bounds.
282+
*
283+
* @param {string} text - The text to perform word wrap detection against.
284+
*/
285+
basicWordWrap: function (text)
286+
{
287+
var result = '';
288+
var lines = text.split('\n');
289+
290+
for (var i = 0; i < lines.length; i++)
291+
{
292+
var spaceLeft = this.style.wordWrapWidth;
293+
var words = lines[i].split(' ');
294+
295+
for (var j = 0; j < words.length; j++)
296+
{
297+
var wordWidth = this.context.measureText(words[j]).width;
298+
var wordWidthWithSpace = wordWidth + this.context.measureText(' ').width;
299+
300+
if (wordWidthWithSpace > spaceLeft)
301+
{
302+
// Skip printing the newline if it's the first word of the line that is greater
303+
// than the word wrap width.
304+
if (j > 0)
305+
{
306+
result += '\n';
307+
}
308+
result += words[j] + ' ';
309+
spaceLeft = this.style.wordWrapWidth - wordWidth;
310+
}
311+
else
312+
{
313+
spaceLeft -= wordWidthWithSpace;
314+
result += words[j] + ' ';
315+
}
316+
}
317+
318+
if (i < lines.length - 1)
319+
{
320+
result += '\n';
321+
}
322+
}
323+
324+
return result;
325+
},
127326
setText: function (value)
128327
{
129328
if (Array.isArray(value))

0 commit comments

Comments
 (0)