From e00cc6de005819f60b60d4ffba43b642a2619795 Mon Sep 17 00:00:00 2001 From: "J.C" Date: Fri, 10 Nov 2017 19:14:17 +0800 Subject: [PATCH] fix bug for GTextField: 1, text align does not work while it's being moving. 2, TextMetrics.wordWrap from official code adds extra useless blank to the head of the first text line, see issue: https://github.com/pixijs/pixi.js/issues/4251, and this is the hot fix for it. I've pushed this patch to the official Guithub as a pull-request already, once they merge it, I'll clear my code again. fix bug for GTextInput.ts 1, text align does not work. --- src/GTextField.ts | 34 +++++++++--- src/PIXI/extras/Text.ts | 106 +++++++++++++++++++++++++++++++++++++ src/display/UITextField.ts | 4 +- 3 files changed, 135 insertions(+), 9 deletions(-) create mode 100644 src/PIXI/extras/Text.ts diff --git a/src/GTextField.ts b/src/GTextField.ts index 35f0149..9e84dd2 100644 --- a/src/GTextField.ts +++ b/src/GTextField.ts @@ -50,7 +50,7 @@ namespace fgui { protected $style: PIXI.TextStyle; protected $verticalAlign: VertAlignType = VertAlignType.Top; - protected $alignYOffset: number = 0; + protected $offset: PIXI.Point = new PIXI.Point(); protected $color: number; protected $singleLine:boolean = true; @@ -399,7 +399,7 @@ namespace fgui { this.applyStyle(); this.$textField.$updateMinHeight(); - let wordWrap = (!this.$widthAutoSize && !this.$singleLine && this.autoSize != AutoSizeType.Shrink); + let wordWrap = !this.$widthAutoSize && this.multipleLine; this.$textField.width = this.$textField.style.wordWrapWidth = wordWrap ? Math.ceil(this.width) : 10000; this.$textField.style.wordWrap = wordWrap; this.$textField.style.breakWords = wordWrap; @@ -691,10 +691,23 @@ namespace fgui { charX += letterSpacing; } } - }); } + public localToGlobal(ax: number = 0, ay: number = 0, resultPoint?: PIXI.Point): PIXI.Point { + let r = super.localToGlobal(ax, ay, resultPoint); + r.x -= this.$offset.x; + r.y -= this.$offset.y; + return r; + } + + public globalToLocal(ax: number = 0, ay: number = 0, resultPoint?: PIXI.Point): PIXI.Point { + let r = super.globalToLocal(ax, ay, resultPoint); + r.x -= this.$offset.x; + r.y -= this.$offset.y; + return r; + } + protected handleSizeChanged(): void { if (this.$updatingSize) return; @@ -740,13 +753,13 @@ namespace fgui { th *= this.displayObject.scale.y; } if (this.$verticalAlign == VertAlignType.Top || th == 0) - this.$alignYOffset = GTextField.GUTTER_Y; + this.$offset.y = GTextField.GUTTER_Y; else { let dh: number = Math.max(0, this.height - th); if (this.$verticalAlign == VertAlignType.Middle) - this.$alignYOffset = dh * .5; + this.$offset.y = dh * .5; else if(this.$verticalAlign == VertAlignType.Bottom) - this.$alignYOffset = dh; + this.$offset.y = dh; } let xPos = 0; @@ -759,14 +772,19 @@ namespace fgui { xPos = this.width - tw; break; } + this.$offset.x = xPos; + + this.updatePosition(); + } - this.displayObject.position.set(Math.floor(this.x + xPos), Math.floor(this.y + this.$alignYOffset)); + private updatePosition():void { + this.displayObject.position.set(Math.floor(this.x + this.$offset.x), Math.floor(this.y + this.$offset.y)); } protected handleXYChanged(): void { super.handleXYChanged(); if (this.$displayObject) - this.$displayObject.y += this.$alignYOffset; + this.updatePosition(); } public setupBeforeAdd(xml: utils.XmlNode): void { diff --git a/src/PIXI/extras/Text.ts b/src/PIXI/extras/Text.ts new file mode 100644 index 0000000..78cf0b5 --- /dev/null +++ b/src/PIXI/extras/Text.ts @@ -0,0 +1,106 @@ +/*this class is temporarily for the bug fixing purpose only, so once PIXI releases a new version, this class will be removed */ + +namespace PIXI.extras { + + export class Text extends PIXI.Text { + + private static __init:boolean = false; + + public constructor(text?:string, style?:PIXI.TextStyle, canvas?:HTMLCanvasElement) { + super(text, style, canvas); + + if(!PIXI.extras.Text.__init) { + PIXI.extras.Text.__init = true; + + //override + PIXI.TextMetrics.wordWrap = function(text, style, canvas) + { + if(!canvas) canvas = (PIXI.TextMetrics as any)["_canvas"]; + + const context = canvas.getContext('2d'); + + // Greedy wrapping algorithm that will wrap words as the line grows longer + // than its horizontal bounds. + let result = ''; + let firstChar = text.charAt(0); + const lines = text.split('\n'); + const wordWrapWidth = style.wordWrapWidth; + const characterCache:{ [char:string] : number } = {}; + + for (let i = 0; i < lines.length; i++) + { + let spaceLeft = wordWrapWidth; + const words = lines[i].split(' '); + + for (let j = 0; j < words.length; j++) + { + const wordWidth = context.measureText(words[j]).width; + + if (style.breakWords && wordWidth > wordWrapWidth) + { + // Word should be split in the middle + const characters = words[j].split(''); + + for (let c = 0; c < characters.length; c++) + { + const character = characters[c]; + let characterWidth = characterCache[character]; + + if (characterWidth === undefined) + { + characterWidth = context.measureText(character).width; + characterCache[character] = characterWidth; + } + + if (characterWidth > spaceLeft) + { + result += `\n${character}`; + spaceLeft = wordWrapWidth - characterWidth; + } + else + { + if (c === 0 && (j > 0 || firstChar == ' ')) + { + result += ' '; + } + + result += character; + spaceLeft -= characterWidth; + } + } + } + else + { + const wordWidthWithSpace = wordWidth + context.measureText(' ').width; + + if (j === 0 || wordWidthWithSpace > spaceLeft) + { + // Skip printing the newline if it's the first word of the line that is + // greater than the word wrap width. + if (j > 0) + { + result += '\n'; + } + result += words[j]; + spaceLeft = wordWrapWidth - wordWidth; + } + else + { + spaceLeft -= wordWidthWithSpace; + result += ` ${words[j]}`; + } + } + } + + if (i < lines.length - 1) + { + result += '\n'; + } + } + + return result; + } + } + } + } +} diff --git a/src/display/UITextField.ts b/src/display/UITextField.ts index 86a3872..4b14756 100644 --- a/src/display/UITextField.ts +++ b/src/display/UITextField.ts @@ -1,6 +1,8 @@ +/// + namespace fgui { - export class UITextField extends PIXI.Text implements IUIObject { + export class UITextField extends PIXI.extras.Text implements IUIObject { public UIOwner:GObject;