private Rectangle RenderHelper(SpriteList spriteList, ICaretPosition caret) { var lines = SplitText(DisplayText); if (TrimWhitespaces) { TrimLinesWhitespaces(lines); } var pos = new Vector2(0, Padding.Top + CalcVerticalTextPosition(lines)); caret.StartSync(); if (String.IsNullOrEmpty(DisplayText)) { pos.X = CalcXByAlignment(lineWidth: 0); caret.EmptyText(pos); return(Rectangle.Empty); } caret.ClampTextPos(DisplayText.Length); caret.ClampLine(lines.Count); Rectangle rect = new Rectangle(Vector2.PositiveInfinity, Vector2.NegativeInfinity); int i = 0; foreach (var line in lines) { bool lastLine = ++i == lines.Count; caret.ClampCol(line.Length - (lastLine ? 0 : 1)); float lineWidth = MeasureTextLine(line).X; pos.X = CalcXByAlignment(lineWidth); if (spriteList != null) { Renderer.DrawTextLine( Font, pos, line, Color4.White, FontHeight, 0, line.Length, letterSpacing, spriteList, caret.Sync, -1); } Rectangle lineRect = new Rectangle(pos.X, pos.Y, pos.X + lineWidth, pos.Y + FontHeight); if (lastLine) { // There is no end-of-text character, so simulate it. caret.Sync(line.Length, new Vector2(lineRect.Right, lineRect.Top), Vector2.Down * fontHeight); } pos.Y += Spacing + FontHeight; caret.NextLine(); rect = Rectangle.Bounds(rect, lineRect); } caret.FinishSync(); return(rect); }
private void EnsureSpriteLists() { if (spriteLists == null) { PrepareRenderer(); spriteLists = new SpriteList[renderer.Styles.Count]; for (int i = 0; i < spriteLists.Length; i++) { spriteLists[i] = new SpriteList(); } renderer.Render(spriteLists, Size, HAlignment, VAlignment, maxDisplayCharacters); gradientMapIndices = new int[renderer.Styles.Count]; for (var i = 0; i < gradientMapIndices.Length; i++) { gradientMapIndices[i] = renderer.Styles[i].GradientMapIndex; } } }
private void PrepareSpriteListAndExtent() { if (spriteList != null) { return; } if (OverflowMode == TextOverflowMode.Minify) { var savedSpacing = spacing; var savedHeight = fontHeight; FitTextInsideWidgetArea(); spriteList = new SpriteList(); extent = RenderHelper(spriteList, Caret); spacing = savedSpacing; fontHeight = savedHeight; } else { spriteList = new SpriteList(); extent = RenderHelper(spriteList, Caret); } }
protected override void OnRelease() { SpriteList = null; base.OnRelease(); }
public static void DrawTextLine( IFont font, Vector2 position, string text, Color4 color, float fontHeight, int start, int length, float letterSpacing, SpriteList list, Action <int, Vector2, Vector2> onDrawChar = null, int tag = -1) { int j = 0; if (list != null) { for (int i = 0; i < length; i++) { char ch = text[i + start]; if (ch != '\n' && ch != '\r' && font.CharSource.Get(ch, fontHeight) != FontChar.Null) { ++j; } } } // Use array instead of list to reduce memory consumption. var chars = new SpriteList.CharDef[j]; j = 0; FontChar prevChar = null; var halfLetterSpacing = letterSpacing * .5f; float savedX = position.X; for (int i = 0; i < length; i++) { char ch = text[i + start]; if (ch == '\n') { onDrawChar?.Invoke(i, position, Vector2.Down * fontHeight); position.X = savedX; position.Y += fontHeight; prevChar = null; continue; } else if (ch == '\r') { continue; } FontChar fontChar = font.CharSource.Get(ch, fontHeight); if (fontChar == FontChar.Null) { onDrawChar?.Invoke(i, position, Vector2.Down * fontHeight); continue; } var scale = fontChar.Height != 0.0f ? fontHeight / fontChar.Height : 0.0f; // Pen Position + Bearing + Kerning gives a proper letter position // but we have to subtract left padding in order to avoid extra spacing position.X += scale * (fontChar.ACWidths.X + fontChar.Kerning(prevChar) + halfLetterSpacing - fontChar.Padding); var size = new Vector2(scale * fontChar.PaddedWidth, fontHeight + scale * (fontChar.PaddedHeight - fontChar.VerticalOffset)); var charPosition = new Vector2(position.X, position.Y + scale * (fontChar.VerticalOffset - fontChar.Padding)); if (font.RoundCoordinates) { charPosition = new Vector2(charPosition.X.Round(), charPosition.Y.Round()); } onDrawChar?.Invoke(i, charPosition, size); chars[j].FontChar = fontChar; chars[j].Position = charPosition; ++j; // We have to add left padding to get actual letter position // Width + (Horizontal Advance - Bearing) will give a proper pen position for next letter position.X += scale * (fontChar.Width + fontChar.ACWidths.Y + halfLetterSpacing + fontChar.Padding); prevChar = fontChar; } list.Add(font, color, fontHeight, chars, tag); }
public static void DrawTextLine( IFont font, Vector2 position, string text, Color4 color, float fontHeight, int start, int length, float letterSpacing, SpriteList list, Action <int, Vector2, Vector2> onDrawChar = null, int tag = -1) { int j = 0; if (list != null) { for (int i = 0; i < length; i++) { char ch = text[i + start]; if (ch != '\n' && ch != '\r' && font.Chars.Get(ch, fontHeight) != FontChar.Null) { ++j; } } } // Use array instead of list to reduce memory consumption. var chars = new SpriteList.CharDef[j]; j = 0; FontChar prevChar = null; float savedX = position.X; for (int i = 0; i < length; i++) { char ch = text[i + start]; if (ch == '\n') { onDrawChar?.Invoke(i, position, Vector2.Down * fontHeight); position.X = savedX; position.Y += fontHeight; prevChar = null; continue; } else if (ch == '\r') { continue; } FontChar fontChar = font.Chars.Get(ch, fontHeight); if (fontChar == FontChar.Null) { onDrawChar?.Invoke(i, position, Vector2.Down * fontHeight); continue; } float scale = fontChar.Height != 0.0f ? fontHeight / fontChar.Height : 0.0f; var xDelta = scale * (fontChar.ACWidths.X + fontChar.Kerning(prevChar) + letterSpacing); position.X += xDelta; var size = new Vector2(scale * fontChar.Width, fontHeight - fontChar.VerticalOffset); Vector2 roundPos; if (font.RoundCoordinates) { roundPos = new Vector2(position.X.Round(), position.Y.Round() + fontChar.VerticalOffset); onDrawChar?.Invoke(i, new Vector2((position.X - xDelta).Round(), position.Y.Round()), size); } else { roundPos = new Vector2(position.X, position.Y + fontChar.VerticalOffset); onDrawChar?.Invoke(i, new Vector2(position.X - xDelta, position.Y), size); } chars[j].FontChar = fontChar; chars[j].Position = roundPos; ++j; position.X += scale * (fontChar.Width + fontChar.ACWidths.Y); prevChar = fontChar; } list.Add(font, color, fontHeight, chars, tag); }