TextChunk.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. using System;
  2. using System.Collections.Generic;
  3. #if MONOGAME || FNA
  4. using Microsoft.Xna.Framework;
  5. #elif STRIDE
  6. using Stride.Core.Mathematics;
  7. #else
  8. using System.Drawing;
  9. using System.Numerics;
  10. using Color = Veldrid.RgbaFloat;
  11. #endif
  12. namespace FontStashSharp.RichText
  13. {
  14. public class TextChunk : BaseChunk
  15. {
  16. protected string _text;
  17. protected readonly SpriteFontBase _font;
  18. protected Point _size;
  19. public List<TextChunkGlyph> Glyphs { get; } = new List<TextChunkGlyph>();
  20. public int Count { get { return _text.Length(); } }
  21. public string Text { get { return _text; } }
  22. public override Point Size { get { return _size; } }
  23. public SpriteFontBase Font => _font;
  24. public TextStyle Style { get; set; }
  25. public TextChunk(SpriteFontBase font, string text, Point size, Point? startPos)
  26. {
  27. if (font == null)
  28. {
  29. throw new ArgumentNullException("font");
  30. }
  31. _font = font;
  32. _text = text;
  33. _size = size;
  34. if (startPos != null)
  35. {
  36. CalculateGlyphs(startPos.Value);
  37. }
  38. }
  39. private void CalculateGlyphs(Point startPos)
  40. {
  41. if (string.IsNullOrEmpty(_text))
  42. {
  43. return;
  44. }
  45. var glyphs = _font.GetGlyphs(_text, Vector2.Zero);
  46. Glyphs.Clear();
  47. for (var i = 0; i < glyphs.Count; ++i)
  48. {
  49. var glyph = glyphs[i];
  50. var bounds = glyph.Bounds;
  51. bounds.Offset(startPos);
  52. Glyphs.Add(new TextChunkGlyph
  53. {
  54. TextChunk = this,
  55. LineTop = startPos.Y,
  56. Index = glyph.Index,
  57. Codepoint = glyph.Codepoint,
  58. Bounds = bounds,
  59. XAdvance = glyph.XAdvance
  60. });
  61. }
  62. }
  63. public TextChunkGlyph? GetGlyphInfoByIndex(int index)
  64. {
  65. if (string.IsNullOrEmpty(_text) || index < 0 || index >= _text.Length)
  66. {
  67. return null;
  68. }
  69. return Glyphs[index];
  70. }
  71. public int? GetGlyphIndexByX(int x)
  72. {
  73. if (Glyphs.Count == 0 || x < 0)
  74. {
  75. return null;
  76. }
  77. var i = 0;
  78. for (; i < Glyphs.Count; ++i)
  79. {
  80. var glyph = Glyphs[i];
  81. var width = glyph.XAdvance;
  82. var right = glyph.Bounds.X + width;
  83. if (glyph.Bounds.X <= x && x <= right)
  84. {
  85. if (x - glyph.Bounds.X >= width / 2)
  86. {
  87. ++i;
  88. }
  89. break;
  90. }
  91. }
  92. if (i - 1 >= 0 && i - 1 < Glyphs.Count && Glyphs[i - 1].Codepoint == '\n')
  93. {
  94. --i;
  95. }
  96. return i;
  97. }
  98. public override void Draw(FSRenderContext context, Vector2 position, Color color)
  99. {
  100. context.DrawText(Text, Font, position, color, Style);
  101. }
  102. }
  103. }