GraphemeBreakClassTrieGenerator.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Net.Http;
  5. using System.Text.RegularExpressions;
  6. using Avalonia.Media.TextFormatting.Unicode;
  7. namespace Avalonia.Visuals.UnitTests.Media.TextFormatting
  8. {
  9. public static class GraphemeBreakClassTrieGenerator
  10. {
  11. public static void Execute()
  12. {
  13. if (!Directory.Exists("Generated"))
  14. {
  15. Directory.CreateDirectory("Generated");
  16. }
  17. using (var stream = File.Create("Generated\\GraphemeBreak.trie"))
  18. {
  19. var trie = GenerateBreakTypeTrie();
  20. trie.Save(stream);
  21. }
  22. }
  23. private static UnicodeTrie GenerateBreakTypeTrie()
  24. {
  25. var trieBuilder = new UnicodeTrieBuilder();
  26. var graphemeBreakData = ReadBreakData(Path.Combine(UnicodeDataGenerator.Ucd, "auxiliary/GraphemeBreakProperty.txt"));
  27. var emojiBreakData = ReadBreakData(Path.Combine(UnicodeDataGenerator.Ucd, "emoji/emoji-data.txt"));
  28. foreach (var breakData in new [] { graphemeBreakData, emojiBreakData })
  29. {
  30. foreach (var (start, end, graphemeBreakType) in breakData)
  31. {
  32. if (!Enum.TryParse<GraphemeBreakClass>(graphemeBreakType, out var value))
  33. {
  34. continue;
  35. }
  36. if (start == end)
  37. {
  38. trieBuilder.Set(start, (uint)value);
  39. }
  40. else
  41. {
  42. trieBuilder.SetRange(start, end, (uint)value);
  43. }
  44. }
  45. }
  46. return trieBuilder.Freeze();
  47. }
  48. public static List<(int, int, string)> ReadBreakData(string file)
  49. {
  50. var data = new List<(int, int, string)>();
  51. var rx = new Regex(@"([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s*;\s*(\w+)\s*#.*", RegexOptions.Compiled);
  52. using (var client = new HttpClient())
  53. {
  54. using (var result = client.GetAsync(file).GetAwaiter().GetResult())
  55. {
  56. if (!result.IsSuccessStatusCode)
  57. {
  58. return data;
  59. }
  60. using (var stream = result.Content.ReadAsStreamAsync().GetAwaiter().GetResult())
  61. using (var reader = new StreamReader(stream))
  62. {
  63. while (!reader.EndOfStream)
  64. {
  65. var line = reader.ReadLine();
  66. if (string.IsNullOrEmpty(line))
  67. {
  68. continue;
  69. }
  70. var match = rx.Match(line);
  71. if (!match.Success)
  72. {
  73. continue;
  74. }
  75. var start = Convert.ToInt32(match.Groups[1].Value, 16);
  76. var end = start;
  77. if (!string.IsNullOrEmpty(match.Groups[2].Value))
  78. {
  79. end = Convert.ToInt32(match.Groups[2].Value, 16);
  80. }
  81. var breakType = match.Groups[3].Value;
  82. data.Add((start, end, breakType));
  83. }
  84. }
  85. }
  86. }
  87. return data;
  88. }
  89. }
  90. }