//this is rather complex :-) private void Build(Vector2 pixelArea) { if (font == null) { throw new InvalidOperationException("TextElementRect.Font"); } sprite.SetTextureAndClear(font.textureValue); Vector2 position = new Vector2(); bool flag = true; int index; int periodIndex; int beginWord = 0; int beginLine = 0; int beginWordIndex = 0; int beginWordLength = 0; int spriceCount = 0; int lastIndex = -1; float beginX = 0; if (!font.TryGetCharacterIndex('.', out periodIndex)) { periodIndex = -1; } if (textAlign == TextHorizontalAlignment.Justified && spaces == null) { spaces = new List <int>(); } StringBuilder text = this.text.value; uint insertedElementIndex = children.ResetInsertIndex(); uint lineInsertedElementCount = 0; if (text.Length > 0 && pixelArea.X > 1) { for (int i = 0; i < text.Length; i++) { if (i == insertedElementIndex) { float width; //update the inserted element children.SetInsertedElementLayout(ref position, out width); position.X += width; insertedElementIndex = children.GetNextInsertedIndex(); } char c = text[i]; switch (c) { case '\r': break; case '\n': if (textAlign == TextHorizontalAlignment.Right || textAlign == TextHorizontalAlignment.Centre) { Vector2 delta = new Vector2(pixelArea.X - position.X, 0); if (textAlign == TextHorizontalAlignment.Centre) { delta.X *= 0.5f; } delta.X = (float)Math.Floor(delta.X); for (int n = beginLine; n < sprite.InstanceCount; n++) { sprite.MoveSprite(n, ref delta); } children.MoveRange(ref delta, lineInsertedElementCount); } if (textAlign == TextHorizontalAlignment.Justified) { spaces.Clear(); } flag = true; position.X = 0; position.Y -= font.lineSpacingF; beginWord = -1; beginX = 0; beginLine = sprite.InstanceCount; lineInsertedElementCount = children.GetInsertedCount(); break; case '\t': beginWord = -1; if (font.TryGetCharacterIndex(' ', out index)) { Vector3 kerning = font.kerning[index]; float width = ((kerning.Y + kerning.Z)) * 4; position.X = (float)(Math.Floor(position.X / width) + 1) * width; if (textAlign == TextHorizontalAlignment.Justified) { spaces.Add(sprite.InstanceCount); } } break; default: if (c == ' ' && textAlign == TextHorizontalAlignment.Justified) { spaces.Add(sprite.InstanceCount); } if (beginWord == -1 || !(char.IsLetterOrDigit(c) || c == '_')) { beginWord = lastIndex; beginWordIndex = i; beginWordLength = spriceCount; beginX = position.X; } if (font.TryGetCharacterIndex(c, out index)) { Vector3 kerning = font.kerning[index]; if (flag) { kerning.X = Math.Max(kerning.X, 0f); } position.X += (kerning.X); Vector4 crop = font.croppingDataV4[index]; if (!char.IsWhiteSpace(c) && position.X + font.glyphWidth[index] > pixelArea.X) { //wrap to new line bool tooLong = false; if (beginWord != -1) { //find out how long this word is... float length = 0; for (int n = i; n < text.Length; n++) { if (!(char.IsLetterOrDigit(text[n]) || text[n] == '_')) { break; } int nindex = 0; if (font.TryGetCharacterIndex(text[n], out nindex)) { length += font.glyphWidth[nindex]; if ((position.X - beginX + length) > pixelArea.X) { //word is too long to be broken onto multiple lines tooLong = true; break; } } } if (!tooLong) { sprite.RemoveLastSprite(spriceCount - beginWordLength); i = beginWordIndex; spriceCount = beginWordLength; position.X = beginX; if (textAlign == TextHorizontalAlignment.Justified && spaces.Count > 0) { spaces.RemoveAt(spaces.Count - 1); } } } if (textAlign == TextHorizontalAlignment.Right || textAlign == TextHorizontalAlignment.Centre) { Vector2 delta = new Vector2(pixelArea.X - position.X, 0); if (textAlign == TextHorizontalAlignment.Centre) { delta.X *= 0.5f; } delta.X = (float)Math.Floor(delta.X); delta.Y = (float)Math.Floor(delta.Y); for (int n = beginLine; n < sprite.InstanceCount; n++) { sprite.MoveSprite(n, ref delta); } children.MoveRange(ref delta, lineInsertedElementCount); } if (textAlign == TextHorizontalAlignment.Justified && spaces.Count > 0) { float gap = (pixelArea.X - position.X) / (spaces.Count); float deltaf = 0; Vector2 delta = new Vector2(0, 0); int spaceIndex; if (font.TryGetCharacterIndex(' ', out spaceIndex)) { Vector3 spaceSize = font.kerning[spaceIndex]; if (gap > ((spaceSize.Y + spaceSize.Z)) * 40) { gap = 0; } } spaceIndex = 0; for (int n = beginLine; n < sprite.InstanceCount; n++) { if (spaceIndex != spaces.Count && n == spaces[spaceIndex]) { spaceIndex++; deltaf += gap; delta.X = (float)Math.Floor(deltaf); } sprite.MoveSprite(n, ref delta); children.MoveRangeUptoIndex(ref delta, ref lineInsertedElementCount, n); } children.MoveRangeUptoIndex(ref delta, ref lineInsertedElementCount, i + 1); spaces.Clear(); } beginLine = sprite.InstanceCount; position.X = Math.Max(kerning.X, 0f); position.Y -= font.lineSpacingF; beginX = 0; if (!char.IsWhiteSpace(text[i])) { i--; } lineInsertedElementCount = children.GetInsertedCount(); continue; } Vector2 pos = position; if (!sizeToVertical && periodIndex != -1 && -position.Y > pixelArea.Y - font.lineSpacingF * 2 && position.X + font.glyphWidth[index] > pixelArea.X - 3 * font.glyphWidth[periodIndex]) { if (pixelArea.X > 3 * font.glyphWidth[periodIndex]) { //add an elipsis ... crop = font.croppingDataV4[periodIndex]; kerning = font.kerning[periodIndex]; pos.Y -= crop.Y + font.glyphSize[periodIndex].Y; pos.X += crop.X; for (int n = 0; n < 3; n++) { sprite.AddSprite(ref pos, ref font.glyphSize[periodIndex], ref colour, ref font.glyphDataV4[periodIndex]); spriceCount++; pos.X += kerning.X + kerning.Y + kerning.Z; } i = text.Length; break; } } pos.X += crop.X; pos.Y -= crop.Y + font.glyphSize[index].Y; lastIndex = sprite.AddSprite(ref pos, ref font.glyphSize[index], ref colour, ref font.glyphDataV4[index]); spriceCount++; flag = false; position.X += ((kerning.Y + kerning.Z)); } break; } } } if (textAlign == TextHorizontalAlignment.Right || textAlign == TextHorizontalAlignment.Centre) { Vector2 delta = new Vector2(pixelArea.X - position.X, 0); if (textAlign == TextHorizontalAlignment.Centre) { delta.X = (float)Math.Floor(delta.X * 0.5f); } delta.X = (float)Math.Floor(delta.X); for (int n = beginLine; n < sprite.InstanceCount; n++) { sprite.MoveSprite(n, ref delta); } children.MoveRange(ref delta, lineInsertedElementCount); } if (sizeToVertical) { this.Size = new Vector2(this.Size.X, font.lineSpacingF - position.Y); } else { if (textVAlign == VerticalAlignment.Centre || textVAlign == VerticalAlignment.Bottom) { float height = pixelArea.Y - (font.lineSpacingF - position.Y); if (height > 0) { if (textVAlign == VerticalAlignment.Centre) { height *= 0.5f; } height = (float)Math.Floor(height); Vector2 delta = new Vector2(0, -height); delta.Y = (float)Math.Floor(delta.Y); for (int n = 0; n < sprite.InstanceCount; n++) { sprite.MoveSprite(n, ref delta); } children.MoveRange(ref delta, 0); } } } }
private void Build() { if (this.font == null) { throw new InvalidOperationException("TextElement.Font == null"); } sprite.SetTextureAndClear(font.textureValue); Vector2 position = new Vector2(); bool flag = true; int index; uint insertedElementIndex = children.ResetInsertIndex(); StringBuilder text = this.text.value; if (text.Length > 0) { for (int i = 0; i < text.Length; i++) { if (i == insertedElementIndex) { float width; //update the inserted element children.SetInsertedElementLayout(ref position, out width); position.X += width; insertedElementIndex = children.GetNextInsertedIndex(); } char c = text[i]; switch (c) { case '\r': break; case '\n': flag = true; position.X = 0; position.Y -= font.lineSpacingF; break; case '\t': if (font.TryGetCharacterIndex(' ', out index)) { Vector3 kerning = font.kerning[index]; float width = ((kerning.Y + kerning.Z)) * 4; position.X = (float)(Math.Floor(position.X / width) + 1) * width; } break; default: if (font.TryGetCharacterIndex(c, out index)) { Vector3 kerning = font.kerning[index]; if (flag) { kerning.X = Math.Max(kerning.X, 0f); } position.X += (kerning.X); Vector4 crop = font.croppingDataV4[index]; Vector2 pos = position; pos.X += crop.X; pos.Y -= crop.Y + font.glyphSize[index].Y; sprite.AddSprite(ref pos, ref font.glyphSize[index], ref colour, ref font.glyphDataV4[index]); flag = false; position.X += ((kerning.Y + kerning.Z)); } break; } } } }