FontImages.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // ***********************************************************************
  2. // Assembly : HZH_Controls
  3. // Created : 2019-09-11
  4. //
  5. // ***********************************************************************
  6. // <copyright file="FontImages.cs">
  7. // Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
  8. // </copyright>
  9. //
  10. // Blog: https://www.cnblogs.com/bfyx
  11. // GitHub:https://github.com/kwwwvagaa/NetWinformControl
  12. // gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
  13. //
  14. // If you use this code, please keep this note.
  15. // ***********************************************************************
  16. using System;
  17. using System.Collections.Generic;
  18. using System.Drawing;
  19. using System.Drawing.Drawing2D;
  20. using System.Drawing.Imaging;
  21. using System.Drawing.Text;
  22. using System.IO;
  23. namespace HZH_Controls
  24. {
  25. /// <summary>
  26. /// 字体图标图片,awesome字体默认加载,elegant字体在使用时延迟加载
  27. /// 图标示例 http://www.fontawesome.com.cn/faicons/?tdsourcetag=s_pcqq_aiomsg
  28. /// 图标示例 https://www.elegantthemes.com/blog/resources/elegant-icon-font
  29. /// </summary>
  30. public static class FontImages
  31. {
  32. /// <summary>
  33. /// The m font collection
  34. /// </summary>
  35. private static readonly PrivateFontCollection m_fontCollection = new PrivateFontCollection();
  36. /// <summary>
  37. /// The m fonts awesome
  38. /// </summary>
  39. private static readonly Dictionary<string, Font> m_fontsAwesome = new Dictionary<string, Font>();
  40. /// <summary>
  41. /// The m fonts elegant
  42. /// </summary>
  43. private static readonly Dictionary<string, Font> m_fontsElegant = new Dictionary<string, Font>();
  44. /// <summary>
  45. /// The m cache maximum size
  46. /// </summary>
  47. private static Dictionary<int, float> m_cacheMaxSize = new Dictionary<int, float>();
  48. /// <summary>
  49. /// The minimum font size
  50. /// </summary>
  51. private const int MinFontSize = 8;
  52. /// <summary>
  53. /// The maximum font size
  54. /// </summary>
  55. private const int MaxFontSize = 43;
  56. /// <summary>
  57. /// 构造函数
  58. /// </summary>
  59. /// <exception cref="FileNotFoundException">Font file not found</exception>
  60. static FontImages()
  61. {
  62. string strPath = System.Reflection.Assembly.GetExecutingAssembly().CodeBase.ToLower().Replace("file:///", "");
  63. string strDir = System.IO.Path.GetDirectoryName(strPath);
  64. if (!Directory.Exists(Path.Combine(strDir, "IconFont")))
  65. {
  66. Directory.CreateDirectory(Path.Combine(strDir, "IconFont"));
  67. }
  68. string strFile = Path.Combine(strDir, "IconFont\\FontAwesome.ttf");
  69. if (!File.Exists(strFile))
  70. {
  71. var fs = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("HZH_Controls.IconFont.FontAwesome.ttf");
  72. FileStream sw = new FileStream(strFile, FileMode.Create, FileAccess.Write);
  73. fs.CopyTo(sw);
  74. sw.Close();
  75. fs.Close();
  76. }
  77. m_fontCollection.AddFontFile(strFile);
  78. float size = MinFontSize;
  79. for (int i = 0; i <= (MaxFontSize - MinFontSize) * 2; i++)
  80. {
  81. m_fontsAwesome.Add(size.ToString("F2"), new Font(m_fontCollection.Families[0], size, FontStyle.Regular, GraphicsUnit.Point));
  82. size += 0.5f;
  83. }
  84. }
  85. /// <summary>
  86. /// Gets the font awesome.
  87. /// </summary>
  88. /// <value>The font awesome.</value>
  89. public static FontFamily FontAwesome
  90. {
  91. get
  92. {
  93. for (int i = 0; i < m_fontCollection.Families.Length; i++)
  94. {
  95. if (m_fontCollection.Families[i].Name == "FontAwesome")
  96. {
  97. return m_fontCollection.Families[i];
  98. }
  99. }
  100. return m_fontCollection.Families[0];
  101. }
  102. }
  103. /// <summary>
  104. /// Gets the elegant icons.
  105. /// </summary>
  106. /// <value>The elegant icons.</value>
  107. /// <exception cref="FileNotFoundException">Font file not found</exception>
  108. public static FontFamily ElegantIcons
  109. {
  110. get
  111. {
  112. if (m_fontsElegant.Count <= 0)
  113. {
  114. lock (m_fontsElegant)
  115. {
  116. if (m_fontsElegant.Count <= 0)
  117. {
  118. string strPath = System.Reflection.Assembly.GetExecutingAssembly().CodeBase.ToLower().Replace("file:///", "");
  119. string strDir = System.IO.Path.GetDirectoryName(strPath);
  120. if (!Directory.Exists(Path.Combine(strDir, "IconFont")))
  121. {
  122. Directory.CreateDirectory(Path.Combine(strDir, "IconFont"));
  123. }
  124. string strFile = Path.Combine(strDir, "IconFont\\ElegantIcons.ttf");
  125. if (!File.Exists(strFile))
  126. {
  127. var fs = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("HZH_Controls.IconFont.ElegantIcons.ttf");
  128. FileStream sw = new FileStream(strFile, FileMode.Create, FileAccess.Write);
  129. fs.CopyTo(sw);
  130. sw.Close();
  131. fs.Close();
  132. }
  133. m_fontCollection.AddFontFile(strFile);
  134. float size = MinFontSize;
  135. for (int i = 0; i <= (MaxFontSize - MinFontSize) * 2; i++)
  136. {
  137. m_fontsElegant.Add(size.ToString("F2"), new Font(m_fontCollection.Families[0], size, FontStyle.Regular, GraphicsUnit.Point));
  138. size += 0.5f;
  139. }
  140. }
  141. }
  142. }
  143. for (int i = 0; i < m_fontCollection.Families.Length; i++)
  144. {
  145. if (m_fontCollection.Families[i].Name == "ElegantIcons")
  146. {
  147. return m_fontCollection.Families[i];
  148. }
  149. }
  150. return m_fontCollection.Families[0];
  151. }
  152. }
  153. /// <summary>
  154. /// 获取图标
  155. /// </summary>
  156. /// <param name="iconText">图标名称</param>
  157. /// <param name="imageSize">图标大小</param>
  158. /// <param name="foreColor">前景色</param>
  159. /// <param name="backColor">背景色</param>
  160. /// <returns>图标</returns>
  161. public static Icon GetIcon(FontIcons iconText, int imageSize = 32, Color? foreColor = null, Color? backColor = null)
  162. {
  163. Bitmap image = GetImage(iconText, imageSize, foreColor, backColor);
  164. return image != null ? ToIcon(image, imageSize) : null;
  165. }
  166. /// <summary>
  167. /// 获取图标.
  168. /// </summary>
  169. /// <param name="iconText">图标名称.</param>
  170. /// <param name="imageSize">图标大小.</param>
  171. /// <param name="foreColor">前景色</param>
  172. /// <param name="backColor">背景色.</param>
  173. /// <returns>Bitmap.</returns>
  174. /// <exception cref="FileNotFoundException">Font file not found</exception>
  175. public static Bitmap GetImage(FontIcons iconText, int imageSize = 32, Color? foreColor = null, Color? backColor = null)
  176. {
  177. Dictionary<string, Font> _fs;
  178. if (iconText.ToString().StartsWith("A_"))
  179. _fs = m_fontsAwesome;
  180. else
  181. {
  182. if (m_fontsElegant.Count <= 0)
  183. {
  184. lock (m_fontsElegant)
  185. {
  186. if (m_fontsElegant.Count <= 0)
  187. {
  188. string strPath = System.Reflection.Assembly.GetExecutingAssembly().CodeBase.ToLower().Replace("file:///", "");
  189. string strDir = System.IO.Path.GetDirectoryName(strPath);
  190. if (!Directory.Exists(Path.Combine(strDir, "IconFont")))
  191. {
  192. Directory.CreateDirectory(Path.Combine(strDir, "IconFont"));
  193. }
  194. string strFile = Path.Combine(strDir, "IconFont\\ElegantIcons.ttf");
  195. if (!File.Exists(strFile))
  196. {
  197. var fs = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("HZH_Controls.IconFont.ElegantIcons.ttf");
  198. FileStream sw = new FileStream(strFile, FileMode.Create, FileAccess.Write);
  199. fs.CopyTo(sw);
  200. sw.Close();
  201. fs.Close();
  202. }
  203. m_fontCollection.AddFontFile(strFile);
  204. float size = MinFontSize;
  205. for (int i = 0; i <= (MaxFontSize - MinFontSize) * 2; i++)
  206. {
  207. m_fontsElegant.Add(size.ToString("F2"), new Font(m_fontCollection.Families[0], size, FontStyle.Regular, GraphicsUnit.Point));
  208. size += 0.5f;
  209. }
  210. }
  211. }
  212. }
  213. _fs = m_fontsElegant;
  214. }
  215. if (!foreColor.HasValue)
  216. foreColor = Color.Black;
  217. Font imageFont = _fs[MinFontSize.ToString("F2")];
  218. SizeF textSize = new SizeF(imageSize, imageSize);
  219. using (Bitmap bitmap = new Bitmap(48, 48))
  220. using (Graphics graphics = Graphics.FromImage(bitmap))
  221. {
  222. //float size = MaxFontSize;
  223. float fltMaxSize = MaxFontSize;
  224. if (m_cacheMaxSize.ContainsKey(imageSize))
  225. {
  226. fltMaxSize = Math.Max(MaxFontSize, m_cacheMaxSize[imageSize] + 5);
  227. }
  228. while (fltMaxSize >= MinFontSize)
  229. {
  230. Font font = _fs[fltMaxSize.ToString("F2")];
  231. SizeF sf = GetIconSize(iconText, graphics, font);
  232. if (sf.Width < imageSize && sf.Height < imageSize)
  233. {
  234. imageFont = font;
  235. textSize = sf;
  236. break;
  237. }
  238. fltMaxSize -= 0.5f;
  239. }
  240. if (!m_cacheMaxSize.ContainsKey(imageSize) || (m_cacheMaxSize.ContainsKey(imageSize) && m_cacheMaxSize[imageSize] < fltMaxSize))
  241. {
  242. m_cacheMaxSize[imageSize] = fltMaxSize;
  243. }
  244. }
  245. Bitmap srcImage = new Bitmap(imageSize, imageSize);
  246. using (Graphics graphics = Graphics.FromImage(srcImage))
  247. {
  248. if (backColor.HasValue && backColor.Value != Color.Empty && backColor.Value != Color.Transparent)
  249. graphics.Clear(backColor.Value);
  250. string s = char.ConvertFromUtf32((int)iconText);
  251. graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
  252. graphics.SetGDIHigh();
  253. using (Brush brush2 = new SolidBrush(foreColor.Value))
  254. {
  255. graphics.DrawString(s, imageFont, brush2, new PointF((imageSize - textSize.Width) / 2.0f + 1, (imageSize - textSize.Height) / 2.0f + 1));
  256. }
  257. }
  258. return srcImage;
  259. }
  260. /// <summary>
  261. /// Gets the size of the icon.
  262. /// </summary>
  263. /// <param name="iconText">The icon text.</param>
  264. /// <param name="graphics">The graphics.</param>
  265. /// <param name="font">The font.</param>
  266. /// <returns>Size.</returns>
  267. private static Size GetIconSize(FontIcons iconText, Graphics graphics, Font font)
  268. {
  269. string text = char.ConvertFromUtf32((int)iconText);
  270. return graphics.MeasureString(text, font).ToSize();
  271. }
  272. /// <summary>
  273. /// Converts to icon.
  274. /// </summary>
  275. /// <param name="srcBitmap">The source bitmap.</param>
  276. /// <param name="size">The size.</param>
  277. /// <returns>Icon.</returns>
  278. /// <exception cref="ArgumentNullException">srcBitmap</exception>
  279. private static Icon ToIcon(Bitmap srcBitmap, int size)
  280. {
  281. if (srcBitmap == null)
  282. {
  283. throw new ArgumentNullException("srcBitmap");
  284. }
  285. Icon icon;
  286. using (MemoryStream memoryStream = new MemoryStream())
  287. {
  288. new Bitmap(srcBitmap, new Size(size, size)).Save(memoryStream, ImageFormat.Png);
  289. Stream stream = new MemoryStream();
  290. BinaryWriter binaryWriter = new BinaryWriter(stream);
  291. if (stream.Length <= 0L)
  292. {
  293. return null;
  294. }
  295. binaryWriter.Write((byte)0);
  296. binaryWriter.Write((byte)0);
  297. binaryWriter.Write((short)1);
  298. binaryWriter.Write((short)1);
  299. binaryWriter.Write((byte)size);
  300. binaryWriter.Write((byte)size);
  301. binaryWriter.Write((byte)0);
  302. binaryWriter.Write((byte)0);
  303. binaryWriter.Write((short)0);
  304. binaryWriter.Write((short)32);
  305. binaryWriter.Write((int)memoryStream.Length);
  306. binaryWriter.Write(22);
  307. binaryWriter.Write(memoryStream.ToArray());
  308. binaryWriter.Flush();
  309. binaryWriter.Seek(0, SeekOrigin.Begin);
  310. icon = new Icon(stream);
  311. stream.Dispose();
  312. }
  313. return icon;
  314. }
  315. }
  316. }