Skip to content

Commit 5bcfa08

Browse files
committed
Text.useAdvancedWrap allows you to swap between the Basic and the Advanced word wrapping functions. In Advanced it will wrap long-words and condense and trim excess white space (thanks @soldoutactivist phaserjs#1811)
1 parent da8fa83 commit 5bcfa08

3 files changed

Lines changed: 160 additions & 1 deletion

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ If you are an exceptional JavaScript developer and would like to join the Phaser
275275
* Text.precalculateWordWrap allows you to run your text through the Text word wrap function, which is handy if you need to handle pagination on longer pieces of text (thanks @slashman #2277)
276276
* Sprite (and all Game Objects) have a new argument in their destroy method: `destroyTexture`. This boolean (which is false by default) controls if the BaseTexture of the Game Object should be destroyed or not. This is extremely useful in situations where you've got a lot of dynamic assets you no longer need, such as textures created from BitmapDatas. You must set the `destroyTexture` argument yourself. This can be done in a custom Game Object destroy method or as part of your state shutdown (#2261)
277277
* The Health Game Object component has a new method: `setHealth` which allows you to set the exact health amount. This is now used by the `revive` function.
278+
* Text.useAdvancedWrap allows you to swap between the Basic and the Advanced word wrapping functions. In Advanced it will wrap long-words and condense and trim excess white space (thanks @soldoutactivist #1811)
278279

279280
### Updates
280281

@@ -337,7 +338,7 @@ Please note that Phaser uses a custom build of Pixi and always has done. The fol
337338
* We have replaced the PolyK Triangulation calls within Pixi with EarCut 2.0.8. This allows for faster polygon triangulation, and also deals with more complex polygons that PolyK would crash on.
338339
* Graphics.arc has a new argument `segments` that allows you to control how many segments are created when the arc is drawn. The default is 40. Use a higher number for more fidelity, i.e. if you find that reversed arcs are not joining up fully (#2064)
339340
* PIXI.WebGLMaskManager.pushMask and popMask are now more robust in checking that they have been given valid mask data (#2152)
340-
* PIXI.WebGLGraphics.stencilBufferLimit is a new integer that allows you to define how many points exist in a Graphics object before Pixi swaps to using the Stencil Buffer to render it. The default is now 64 (originally 6). This fixes issues with things like Quadratic curves not rendering as masks in WebGL.
341+
* PIXI.WebGLGraphics.stencilBufferLimit is a new integer that allows you to define how many points exist in a Graphics object before Pixi swaps to using the Stencil Buffer to render it. The default is 6 but can be increased. This fixes issues with things like Quadratic curves not rendering as masks in WebGL.
341342

342343
For changes in previous releases please see the extensive [Version History](https://github.com/photonstorm/phaser/blob/master/CHANGELOG.md).
343344

src/gameobjects/Text.js

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,19 @@ Phaser.Text = function (game, x, y, text, style) {
117117
*/
118118
this.autoRound = false;
119119

120+
/**
121+
* Will this Text object use Basic or Advanced Word Wrapping?
122+
*
123+
* Advanced wrapping breaks long words if they are the first of a line, and repeats the process as necessary.
124+
* White space is condensed (e.g., consecutive spaces are replaced with one).
125+
* Lines are trimmed of white space before processing.
126+
*
127+
* It throws an error if wordWrapWidth is less than a single character.
128+
* @property {boolean} useAdvancedWrap
129+
* @default
130+
*/
131+
this.useAdvancedWrap = false;
132+
120133
/**
121134
* @property {number} _res - Internal canvas resolution var.
122135
* @private
@@ -836,6 +849,150 @@ Phaser.Text.prototype.precalculateWordWrap = function (text) {
836849
*/
837850
Phaser.Text.prototype.runWordWrap = function (text) {
838851

852+
if (this.useAdvancedWrap)
853+
{
854+
return this.advancedWordWrap(text);
855+
}
856+
else
857+
{
858+
return this.basicWordWrap(text);
859+
}
860+
861+
};
862+
863+
/**
864+
* Advanced wrapping algorithm that will wrap words as the line grows longer than its horizontal bounds.
865+
* White space is condensed (e.g., consecutive spaces are replaced with one).
866+
* Lines are trimmed of white space before processing.
867+
* Throws an error if the user was smart enough to specify a wordWrapWidth less than a single character.
868+
*
869+
* @method Phaser.Text#advancedWordWrap
870+
* @param {string} text - The text to perform word wrap detection against.
871+
* @private
872+
*/
873+
Phaser.Text.prototype.advancedWordWrap = function (text) {
874+
875+
var context = this.context;
876+
var wordWrapWidth = this.style.wordWrapWidth;
877+
878+
var output = '';
879+
880+
// (1) condense whitespace
881+
// (2) split into lines
882+
var lines = text
883+
.replace(/ +/gi, ' ')
884+
.split(/\r?\n/gi);
885+
886+
var linesCount = lines.length;
887+
888+
for (var i = 0; i < linesCount; i++)
889+
{
890+
var line = lines[i];
891+
var out = '';
892+
893+
// trim whitespace
894+
line = line.replace(/^ *|\s*$/gi, '');
895+
896+
// if entire line is less than wordWrapWidth
897+
// append the entire line and exit early
898+
var lineWidth = context.measureText(line).width;
899+
900+
if (lineWidth < wordWrapWidth)
901+
{
902+
output += line + '\n';
903+
continue;
904+
}
905+
906+
// otherwise, calculate new lines
907+
var currentLineWidth = wordWrapWidth;
908+
909+
// split into words
910+
var words = line.split(' ');
911+
912+
for (var j = 0; j < words.length; j++)
913+
{
914+
var word = words[j];
915+
var wordWithSpace = word + ' ';
916+
var wordWidth = context.measureText(wordWithSpace).width;
917+
918+
if (wordWidth > currentLineWidth)
919+
{
920+
// break word
921+
if (j === 0)
922+
{
923+
// shave off letters from word until it's small enough
924+
var newWord = wordWithSpace;
925+
926+
while (newWord.length)
927+
{
928+
newWord = newWord.slice(0, -1);
929+
wordWidth = context.measureText(newWord).width;
930+
931+
if (wordWidth <= currentLineWidth)
932+
{
933+
break;
934+
}
935+
}
936+
937+
// if wordWrapWidth is too small for even a single
938+
// letter, shame user failure with a fatal error
939+
if (!newWord.length)
940+
{
941+
throw new Error('This text\'s wordWrapWidth setting is less than a single character!');
942+
}
943+
944+
// replace current word in array with remainder
945+
var secondPart = word.substr(newWord.length);
946+
947+
words[j] = secondPart;
948+
949+
// append first piece to output
950+
out += newWord;
951+
}
952+
953+
// if existing word length is 0, don't include it
954+
var offset = (words[j].length) ? j : j + 1;
955+
956+
// collapse rest of sentence
957+
var remainder = words.slice(offset).join(' ')
958+
// remove any trailing white space
959+
.replace(/[ \n]*$/gi, '');
960+
961+
// prepend remainder to next line
962+
lines[i + 1] = remainder + ' ' + (lines[i + 1] || '');
963+
linesCount = lines.length;
964+
965+
break; // processing on this line
966+
967+
// append word with space to output
968+
}
969+
else
970+
{
971+
out += wordWithSpace;
972+
currentLineWidth -= wordWidth;
973+
}
974+
}
975+
976+
// append processed line to output
977+
output += out.replace(/[ \n]*$/gi, '') + '\n';
978+
}
979+
980+
// trim the end of the string
981+
output = output.replace(/[\s|\n]*$/gi, '');
982+
983+
return output;
984+
985+
};
986+
987+
/**
988+
* Greedy wrapping algorithm that will wrap words as the line grows longer than its horizontal bounds.
989+
*
990+
* @method Phaser.Text#basicWordWrap
991+
* @param {string} text - The text to perform word wrap detection against.
992+
* @private
993+
*/
994+
Phaser.Text.prototype.basicWordWrap = function (text) {
995+
839996
var result = '';
840997
var lines = text.split('\n');
841998

typescript/phaser.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4778,6 +4778,7 @@ declare module Phaser {
47784778
text: string;
47794779
textBounds: Phaser.Rectangle;
47804780
type: number;
4781+
useAdvancedWrap: boolean;
47814782
world: Phaser.Point;
47824783
wordWrap: boolean;
47834784
wordWrapWidth: number;

0 commit comments

Comments
 (0)