FontManager.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.Text;
  5. using System.Linq;
  6. namespace FastReport
  7. {
  8. /// <summary>
  9. /// Contains font management methods and properties.
  10. /// </summary>
  11. public static partial class FontManager
  12. {
  13. // NOT THREAD SAFE!
  14. private static PrivateFontCollection PrivateFontCollection { get; } = new PrivateFontCollection();
  15. // NOT THREAD SAFE!
  16. // Do not update PrivateFontCollection at realtime, you must update property value then dispose previous.
  17. private static PrivateFontCollection TemporaryFontCollection { get; set; } = null;
  18. private static InstalledFontCollection InstalledFontCollection { get; } = new InstalledFontCollection();
  19. private static List<FontSubstitute> SubstituteFonts { get; } = new List<FontSubstitute>();
  20. /// <summary>
  21. /// Gets all installed font families.
  22. /// </summary>
  23. /// <remarks>
  24. /// This method enumerates all font collections (PrivateFontCollection, TemporaryFontCollection, InstalledFontCollection)
  25. /// and sorts the result.
  26. /// </remarks>
  27. public static FontFamily[] AllFamilies
  28. {
  29. get
  30. {
  31. var families = new List<FontFamily>();
  32. families.AddRange(InstalledFontCollection.Families);
  33. families.AddRange(PrivateFontCollection.Families);
  34. if (TemporaryFontCollection != null)
  35. {
  36. families.AddRange(TemporaryFontCollection.Families);
  37. }
  38. families.Sort((x, y) => x.Name.CompareTo(y.Name));
  39. return families.ToArray();
  40. }
  41. }
  42. /// <summary>
  43. /// Adds a new substitute font item.
  44. /// </summary>
  45. /// <param name="originalFontName">The original font name, e.g. "Arial"</param>
  46. /// <param name="substituteFonts">The alternatives list, e.g. "Ubuntu Sans", "Liberation Sans", "Helvetica"</param>
  47. /// <remarks>
  48. /// Substitute font replaces the original font if it is not present on a machine.
  49. /// For example, you may define "Helvetica Neue" substitute for "Arial".
  50. /// </remarks>
  51. public static void AddSubstituteFont(string originalFontName, params string[] substituteFonts)
  52. {
  53. SubstituteFonts.Add(new FontSubstitute(originalFontName, substituteFonts));
  54. }
  55. /// <summary>
  56. /// Removes substitute fonts for the given font.
  57. /// </summary>
  58. /// <param name="originalFontName">The original font name, e.g. "Arial"</param>
  59. public static void RemoveSubstituteFont(string originalFontName)
  60. {
  61. for (int i = 0; i < SubstituteFonts.Count; i++)
  62. {
  63. if (SubstituteFonts[i].Name == originalFontName)
  64. {
  65. SubstituteFonts.RemoveAt(i);
  66. i--;
  67. }
  68. }
  69. }
  70. /// <summary>
  71. /// Clears all substitute fonts.
  72. /// </summary>
  73. public static void ClearSubstituteFonts()
  74. {
  75. SubstituteFonts.Clear();
  76. }
  77. /// <summary>
  78. /// Finds a FontFamily by its name in specified font collections.
  79. /// </summary>
  80. /// <param name="name">The family name, e.g. "Arial".</param>
  81. /// <param name="searchScope">Search scope.</param>
  82. /// <returns>The FontFamily instance if found; otherwise null.</returns>
  83. private static FontFamily FindFontFamily(string name, SearchScope searchScope = SearchScope.All)
  84. {
  85. FontFamily family = null;
  86. if ((searchScope & SearchScope.Temporary) != 0)
  87. {
  88. family = Find(TemporaryFontCollection);
  89. }
  90. if ((searchScope & SearchScope.Private) != 0)
  91. {
  92. family ??= Find(PrivateFontCollection);
  93. }
  94. if ((searchScope & SearchScope.Installed) != 0)
  95. {
  96. family ??= Find(InstalledFontCollection);
  97. }
  98. return family;
  99. FontFamily Find(FontCollection collection) =>
  100. collection?.Families.Where(f => f.Name.Equals(name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
  101. }
  102. /// <summary>
  103. /// Finds a FontFamily by its name.
  104. /// </summary>
  105. /// <param name="name">The family name, e.g. "Arial".</param>
  106. /// <returns>The FontFamily instance if found; otherwise default FontFamily.GenericSansSerif.</returns>
  107. internal static FontFamily GetFontFamilyOrDefault(string name)
  108. {
  109. var fontFamily = FindFontFamily(name);
  110. if (fontFamily == null)
  111. {
  112. // try to substitute
  113. foreach (var item in SubstituteFonts)
  114. {
  115. if (item.Name == name)
  116. {
  117. // may be null!
  118. fontFamily = item.SubstituteFamily;
  119. break;
  120. }
  121. }
  122. }
  123. // return default if not found
  124. return fontFamily ?? FontFamily.GenericSansSerif;
  125. }
  126. }
  127. }