var AddToDOM = require('../../../dom/AddToDOM'); var CanvasPool = require('../../../display/canvas/CanvasPool'); var Class = require('../../../utils/Class'); var Components = require('../../components'); var CONST = require('../../../const'); var GameObject = require('../../GameObject'); var GetTextSize = require('../GetTextSize'); var GetValue = require('../../../utils/object/GetValue'); var RemoveFromDOM = require('../../../dom/RemoveFromDOM'); var TextRender = require('./TextRender'); var TextStyle = require('../TextStyle'); var Text = new Class({ Extends: GameObject, Mixins: [Components.Alpha, Components.BlendMode, Components.ComputedSize, Components.Crop, Components.Depth, Components.Flip, Components.GetBounds, Components.Mask, Components.Origin, Components.Pipeline, Components.ScaleMode, Components.ScrollFactor, Components.Tint, Components.Transform, Components.Visible, TextRender] , initialize: function Text(scene, x, y, text, style){ if (x === undefined) { x = 0; } if (y === undefined) { y = 0; } GameObject.call(this, scene, 'Text'); this.renderer = scene.sys.game.renderer; this.setPosition(x, y); this.setOrigin(0, 0); this.initPipeline(); this.canvas = CanvasPool.create(this); this.context = this.canvas.getContext('2d'); this.style = new TextStyle(this, style); this.autoRound = true ; this.splitRegExp = /(?:\r\n|\r|\n)/; this._text = ''; this.padding = { left: 0, right: 0, top: 0, bottom: 0} ; this.width = 1; this.height = 1; this.lineSpacing = 0; this.dirty = false ; if (this.style.resolution === 0) { this.style.resolution = scene.sys.game.config.resolution; } this._crop = this.resetCropObject(); this.texture = scene.sys.textures.addCanvas(null , this.canvas, true ); this.frame = this.texture.get(); this.frame.source.resolution = this.style.resolution; if (this.renderer && this.renderer.gl) { this.renderer.deleteTexture(this.frame.source.glTexture); this.frame.source.glTexture = null ; } this.initRTL(); if (style && style.padding) { this.setPadding(style.padding); } if (style && style.lineSpacing) { this.lineSpacing = style.lineSpacing; } this.setText(text); if (scene.sys.game.config.renderType === CONST.WEBGL) { scene.sys.game.renderer.onContextRestored(function (){ this.dirty = true ; } , this); } } , initRTL: function (){ if (!this.style.rtl) { return ; } this.canvas.dir = 'rtl'; this.context.direction = 'rtl'; this.canvas.style.display = 'none'; AddToDOM(this.canvas, this.scene.sys.canvas); this.originX = 1; } , runWordWrap: function (text){ var style = this.style; if (style.wordWrapCallback) { var wrappedLines = style.wordWrapCallback.call(style.wordWrapCallbackScope, text, this); if (Array.isArray(wrappedLines)) { wrappedLines = wrappedLines.join('\n'); } return wrappedLines; } else if (style.wordWrapWidth) { if (style.wordWrapUseAdvanced) { return this.advancedWordWrap(text, this.context, this.style.wordWrapWidth); } else { return this.basicWordWrap(text, this.context, this.style.wordWrapWidth); } } else { return text; } } , advancedWordWrap: function (text, context, wordWrapWidth){ var output = ''; var lines = _AN_Call_replace('replace', text, / +/gi, ' ').split(this.splitRegExp); var linesCount = _AN_Read_length('length', lines); for (var i = 0; i < linesCount; i++ ){ var line = lines[i]; var out = ''; line = _AN_Call_replace('replace', line, /^ *|\s*$/gi, ''); var lineWidth = context.measureText(line).width; if (lineWidth < wordWrapWidth) { output += line + '\n'; continue ; } var currentLineWidth = wordWrapWidth; var words = line.split(' '); for (var j = 0; j < (_AN_Read_length('length', words)); j++ ){ var word = words[j]; var wordWithSpace = word + ' '; var wordWidth = context.measureText(wordWithSpace).width; if (wordWidth > currentLineWidth) { if (j === 0) { var newWord = wordWithSpace; while (newWord.length){ newWord = newWord.slice(0, -1); wordWidth = context.measureText(newWord).width; if (wordWidth <= currentLineWidth) { break ; } } if (!(_AN_Read_length('length', newWord))) { throw new Error('This text\'s wordWrapWidth setting is less than a single character!') } var secondPart = word.substr(_AN_Read_length('length', newWord)); words[j] = secondPart; out += newWord; } var offset = (_AN_Read_length('length', words[j]))? j: j + 1; var remainder = _AN_Call_replace('replace', words.slice(offset).join(' '), /[ \n]*$/gi, ''); lines[i + 1] = remainder + ' ' + (lines[i + 1] || ''); linesCount = _AN_Read_length('length', lines); break ; } else { out += wordWithSpace; currentLineWidth -= wordWidth; } } output += _AN_Call_replace('replace', out, /[ \n]*$/gi, '') + '\n'; } output = _AN_Call_replace('replace', output, /[\s|\n]*$/gi, ''); return output; } , basicWordWrap: function (text, context, wordWrapWidth){ var result = ''; var lines = text.split(this.splitRegExp); for (var i = 0; i < (_AN_Read_length('length', lines)); i++ ){ var spaceLeft = wordWrapWidth; var words = lines[i].split(' '); for (var j = 0; j < (_AN_Read_length('length', words)); j++ ){ var wordWidth = context.measureText(words[j]).width; var wordWidthWithSpace = wordWidth + context.measureText(' ').width; if (wordWidthWithSpace > spaceLeft) { if (j > 0) { result += '\n'; } result += words[j] + ' '; spaceLeft = wordWrapWidth - wordWidth; } else { spaceLeft -= wordWidthWithSpace; result += words[j]; if (j < ((_AN_Read_length('length', words)) - 1)) { result += ' '; } } } if (i < (_AN_Read_length('length', lines)) - 1) { result += '\n'; } } return result; } , getWrappedText: function (text){ if (text === undefined) { text = this._text; } this.style.syncFont(this.canvas, this.context); var wrappedLines = this.runWordWrap(text); return wrappedLines.split(this.splitRegExp); } , setText: function (value){ if (!value && value !== 0) { value = ''; } if (Array.isArray(value)) { value = value.join('\n'); } if (value !== this._text) { this._text = value.toString(); this.updateText(); } return this; } , setStyle: function (style){ return this.style.setStyle(style); } , setFont: function (font){ return this.style.setFont(font); } , setFontFamily: function (family){ return this.style.setFontFamily(family); } , setFontSize: function (size){ return this.style.setFontSize(size); } , setFontStyle: function (style){ return this.style.setFontStyle(style); } , setFixedSize: function (width, height){ return this.style.setFixedSize(width, height); } , setBackgroundColor: function (color){ return this.style.setBackgroundColor(color); } , setFill: function (fillStyle){ return this.style.setFill(fillStyle); } , setColor: function (color){ return this.style.setColor(color); } , setStroke: function (color, thickness){ return this.style.setStroke(color, thickness); } , setShadow: function (x, y, color, blur, shadowStroke, shadowFill){ return this.style.setShadow(x, y, color, blur, shadowStroke, shadowFill); } , setShadowOffset: function (x, y){ return this.style.setShadowOffset(x, y); } , setShadowColor: function (color){ return this.style.setShadowColor(color); } , setShadowBlur: function (blur){ return this.style.setShadowBlur(blur); } , setShadowStroke: function (enabled){ return this.style.setShadowStroke(enabled); } , setShadowFill: function (enabled){ return this.style.setShadowFill(enabled); } , setWordWrapWidth: function (width, useAdvancedWrap){ return this.style.setWordWrapWidth(width, useAdvancedWrap); } , setWordWrapCallback: function (callback, scope){ return this.style.setWordWrapCallback(callback, scope); } , setAlign: function (align){ return this.style.setAlign(align); } , setResolution: function (value){ return this.style.setResolution(value); } , setLineSpacing: function (value){ this.lineSpacing = value; return this.updateText(); } , setPadding: function (left, top, right, bottom){ if (typeof left === 'object') { var config = left; var x = GetValue(config, 'x', null ); if (x !== null ) { left = x; right = x; } else { left = GetValue(config, 'left', 0); right = GetValue(config, 'right', left); } var y = GetValue(config, 'y', null ); if (y !== null ) { top = y; bottom = y; } else { top = GetValue(config, 'top', 0); bottom = GetValue(config, 'bottom', top); } } else { if (left === undefined) { left = 0; } if (top === undefined) { top = left; } if (right === undefined) { right = left; } if (bottom === undefined) { bottom = top; } } this.padding.left = left; this.padding.top = top; this.padding.right = right; this.padding.bottom = bottom; return this.updateText(); } , setMaxLines: function (max){ return this.style.setMaxLines(max); } , updateText: function (){ var canvas = this.canvas; var context = this.context; var style = this.style; var resolution = style.resolution; var size = style.metrics; style.syncFont(canvas, context); var outputText = this._text; if (style.wordWrapWidth || style.wordWrapCallback) { outputText = this.runWordWrap(this._text); } var lines = outputText.split(this.splitRegExp); var textSize = GetTextSize(this, size, lines); var padding = this.padding; var w = textSize.width + padding.left + padding.right; var h = textSize.height + padding.top + padding.bottom; if (style.fixedWidth === 0) { this.width = w; } if (style.fixedHeight === 0) { this.height = h; } this.updateDisplayOrigin(); w *= resolution; h *= resolution; w = Math.max(w, 1); h = Math.max(h, 1); if (canvas.width !== w || canvas.height !== h) { canvas.width = w; canvas.height = h; this.frame.setSize(w, h); style.syncFont(canvas, context); } else { context.clearRect(0, 0, w, h); } context.save(); context.scale(resolution, resolution); if (style.backgroundColor) { context.fillStyle = style.backgroundColor; context.fillRect(0, 0, w, h); } style.syncStyle(canvas, context); context.textBaseline = 'alphabetic'; context.translate(padding.left, padding.top); var linePositionX; var linePositionY; for (var i = 0; i < textSize.lines; i++ ){ linePositionX = style.strokeThickness / 2; linePositionY = (style.strokeThickness / 2 + i * textSize.lineHeight) + size.ascent; if (i > 0) { linePositionY += (textSize.lineSpacing * i); } if (style.rtl) { linePositionX = w - linePositionX; } else if (style.align === 'right') { linePositionX += textSize.width - textSize.lineWidths[i]; } else if (style.align === 'center') { linePositionX += (textSize.width - textSize.lineWidths[i]) / 2; } if (this.autoRound) { linePositionX = Math.round(linePositionX); linePositionY = Math.round(linePositionY); } if (style.strokeThickness) { this.style.syncShadow(context, style.shadowStroke); context.strokeText(lines[i], linePositionX, linePositionY); } if (style.color) { this.style.syncShadow(context, style.shadowFill); context.fillText(lines[i], linePositionX, linePositionY); } } context.restore(); if (this.renderer.gl) { this.frame.source.glTexture = this.renderer.canvasToTexture(canvas, this.frame.source.glTexture, true ); this.frame.glTexture = this.frame.source.glTexture; } this.dirty = true ; return this; } , getTextMetrics: function (){ return this.style.getTextMetrics(); } , text: { get: function (){ return this._text; } , set: function (value){ this.setText(value); } } , toJSON: function (){ var out = Components.ToJSON(this); var data = { autoRound: this.autoRound, text: this._text, style: this.style.toJSON(), padding: { left: this.padding.left, right: this.padding.right, top: this.padding.top, bottom: this.padding.bottom} } ; out.data = data; return out; } , preDestroy: function (){ if (this.style.rtl) { RemoveFromDOM(this.canvas); } CanvasPool.remove(this.canvas); this.texture.destroy(); } } ); module.exports = Text;