HarfbuzzTextShaperTests.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using System;
  2. using System.Linq;
  3. using Avalonia.Base.UnitTests.Media.Fonts.Tables;
  4. using Avalonia.Harfbuzz;
  5. using Avalonia.Media;
  6. using Avalonia.Media.TextFormatting;
  7. using Avalonia.Platform;
  8. using Avalonia.UnitTests;
  9. using Xunit;
  10. namespace Avalonia.Base.UnitTests.Media.TextFormatting;
  11. public class HarfBuzzTextShaperTests
  12. {
  13. private static readonly string s_InterFontUri =
  14. "resm:Avalonia.Base.UnitTests.Assets.Inter-Regular.ttf?assembly=Avalonia.Base.UnitTests";
  15. private readonly HarfBuzzTextShaper _shaper;
  16. private TestServices Services => TestServices.MockThreadingInterface.With(
  17. textShaperImpl: _shaper);
  18. public HarfBuzzTextShaperTests()
  19. {
  20. _shaper = new HarfBuzzTextShaper();
  21. }
  22. [Fact]
  23. public void ShapeText_WithValidInput_ReturnsShapedBuffer()
  24. {
  25. using (UnitTestApplication.Start(Services))
  26. {
  27. var text = "Hello World".AsMemory();
  28. var options = CreateTextShaperOptions();
  29. var result = _shaper.ShapeText(text, options);
  30. Assert.NotNull(result);
  31. Assert.Equal(text.Length, result.Length);
  32. }
  33. }
  34. [Fact]
  35. public void ShapeText_WithEmptyString_ReturnsEmptyShapedBuffer()
  36. {
  37. using (UnitTestApplication.Start(Services))
  38. {
  39. var text = "".AsMemory();
  40. var options = CreateTextShaperOptions();
  41. var result = _shaper.ShapeText(text, options);
  42. Assert.NotNull(result);
  43. Assert.Equal(0, result.Length);
  44. }
  45. }
  46. [Fact]
  47. public void ShapeText_WithTabCharacter_ReplacesWithSpace()
  48. {
  49. using (UnitTestApplication.Start(Services))
  50. {
  51. var text = "Hello\tWorld".AsMemory();
  52. var options = CreateTextShaperOptions();
  53. var result = _shaper.ShapeText(text, options);
  54. Assert.NotNull(result);
  55. Assert.True(result.Length == 11);
  56. }
  57. }
  58. [Fact]
  59. public void ShapeText_WithCRLF_MergesBreakPair()
  60. {
  61. using (UnitTestApplication.Start(Services))
  62. {
  63. var text = "Line1\r\nLine2".AsMemory();
  64. var options = CreateTextShaperOptions();
  65. var result = _shaper.ShapeText(text, options);
  66. Assert.NotNull(result);
  67. Assert.NotEqual(0.0, result[5].GlyphAdvance);
  68. }
  69. }
  70. [Fact]
  71. public void ShapeText_EndWithCRLF_MergesBreakPair()
  72. {
  73. using (UnitTestApplication.Start(Services))
  74. {
  75. var text = "Line1\r\n".AsMemory();
  76. var options = CreateTextShaperOptions();
  77. var result = _shaper.ShapeText(text, options);
  78. Assert.NotNull(result);
  79. Assert.Equal(0.0, result[5].GlyphAdvance);
  80. }
  81. }
  82. [Fact]
  83. public void ShapeText_WithSlicedMemory_ClusterValuesAreSliceRelative()
  84. {
  85. using (UnitTestApplication.Start(Services))
  86. {
  87. var fullString = new string('A', 1000) + "Hello" + new string('B', 1000);
  88. var sliced = fullString.AsMemory().Slice(1000, 5);
  89. var options = CreateTextShaperOptions();
  90. var result = _shaper.ShapeText(sliced, options);
  91. Assert.NotNull(result);
  92. Assert.Equal(5, result.Length);
  93. for (var i = 0; i < result.Length; i++)
  94. {
  95. Assert.True(result[i].GlyphCluster >= 0 && result[i].GlyphCluster < 5,
  96. $"Glyph cluster at index {i} was {result[i].GlyphCluster}, expected a value in [0, 5).");
  97. }
  98. }
  99. }
  100. private TextShaperOptions CreateTextShaperOptions(
  101. sbyte bidiLevel = 0,
  102. double letterSpacing = 0,
  103. double fontSize = 16)
  104. {
  105. var assetLoader = new StandardAssetLoader();
  106. using var stream = assetLoader.Open(new Uri(s_InterFontUri));
  107. var typeface = new GlyphTypeface(new CustomPlatformTypeface(stream));
  108. return new TextShaperOptions(
  109. typeface,
  110. fontSize,
  111. bidiLevel,
  112. letterSpacing: letterSpacing);
  113. }
  114. }