FontFamily.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. #pragma warning disable
  7. namespace Svg.Text
  8. {
  9. /// <summary>
  10. /// http://stackoverflow.com/questions/3633000/net-enumerate-winforms-font-styles
  11. /// </summary>
  12. public class FontFamily
  13. {
  14. #region InstalledFont Parameters
  15. string _fontName = string.Empty;
  16. string _fontSubFamily = string.Empty;
  17. string _fontPath = string.Empty;
  18. #endregion
  19. #region InstalledFont Constructor
  20. private FontFamily(string fontName, string fontSubFamily, string fontPath)
  21. {
  22. _fontName = fontName;
  23. _fontSubFamily = fontSubFamily;
  24. _fontPath = fontPath;
  25. }
  26. #endregion
  27. #region InstalledFont Properties
  28. public string FontName { get { return _fontName; } set { _fontName = value; } }
  29. public string FontSubFamily { get { return _fontSubFamily; } set { _fontSubFamily = value; } }
  30. public string FontPath { get { return _fontPath; } set { _fontPath = value; } }
  31. #endregion
  32. static public FontFamily FromPath(string fontFilePath)
  33. {
  34. string FontName = string.Empty;
  35. string FontSubFamily = string.Empty;
  36. string encStr = "UTF-8";
  37. string strRet = string.Empty;
  38. using (FileStream fs = new FileStream(fontFilePath, FileMode.Open, FileAccess.Read))
  39. {
  40. TT_OFFSET_TABLE ttOffsetTable = new TT_OFFSET_TABLE()
  41. {
  42. uMajorVersion = ReadUShort(fs),
  43. uMinorVersion = ReadUShort(fs),
  44. uNumOfTables = ReadUShort(fs),
  45. uSearchRange = ReadUShort(fs),
  46. uEntrySelector = ReadUShort(fs),
  47. uRangeShift = ReadUShort(fs),
  48. };
  49. TT_TABLE_DIRECTORY tblDir = new TT_TABLE_DIRECTORY();
  50. bool found = false;
  51. for (int i = 0; i <= ttOffsetTable.uNumOfTables; i++)
  52. {
  53. tblDir = new TT_TABLE_DIRECTORY();
  54. tblDir.Initialize();
  55. fs.Read(tblDir.szTag, 0, tblDir.szTag.Length);
  56. tblDir.uCheckSum = ReadULong(fs);
  57. tblDir.uOffset = ReadULong(fs);
  58. tblDir.uLength = ReadULong(fs);
  59. Encoding enc = Encoding.GetEncoding(encStr);
  60. string s = enc.GetString(tblDir.szTag);
  61. if (s.CompareTo("name") == 0)
  62. {
  63. found = true;
  64. break;
  65. }
  66. }
  67. if (!found) return null;
  68. fs.Seek(tblDir.uOffset, SeekOrigin.Begin);
  69. TT_NAME_TABLE_HEADER ttNTHeader = new TT_NAME_TABLE_HEADER
  70. {
  71. uFSelector = ReadUShort(fs),
  72. uNRCount = ReadUShort(fs),
  73. uStorageOffset = ReadUShort(fs)
  74. };
  75. TT_NAME_RECORD ttRecord = new TT_NAME_RECORD();
  76. for (int j = 0; j <= ttNTHeader.uNRCount; j++)
  77. {
  78. ttRecord = new TT_NAME_RECORD()
  79. {
  80. uPlatformID = ReadUShort(fs),
  81. uEncodingID = ReadUShort(fs),
  82. uLanguageID = ReadUShort(fs),
  83. uNameID = ReadUShort(fs),
  84. uStringLength = ReadUShort(fs),
  85. uStringOffset = ReadUShort(fs)
  86. };
  87. if (ttRecord.uNameID > 2) { break; }
  88. long nPos = fs.Position;
  89. fs.Seek(tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset, SeekOrigin.Begin);
  90. byte[] buf = new byte[ttRecord.uStringLength];
  91. fs.Read(buf, 0, ttRecord.uStringLength);
  92. Encoding enc;
  93. if (ttRecord.uEncodingID == 3 || ttRecord.uEncodingID == 1)
  94. {
  95. enc = Encoding.BigEndianUnicode;
  96. }
  97. else
  98. {
  99. enc = Encoding.UTF8;
  100. }
  101. strRet = enc.GetString(buf);
  102. if (ttRecord.uNameID == 1) { FontName = strRet; }
  103. if (ttRecord.uNameID == 2) { FontSubFamily = strRet; }
  104. fs.Seek(nPos, SeekOrigin.Begin);
  105. }
  106. return new FontFamily(FontName, FontSubFamily, fontFilePath);
  107. }
  108. }
  109. [CLSCompliant(false)]
  110. public struct TT_OFFSET_TABLE
  111. {
  112. public ushort uMajorVersion;
  113. public ushort uMinorVersion;
  114. public ushort uNumOfTables;
  115. public ushort uSearchRange;
  116. public ushort uEntrySelector;
  117. public ushort uRangeShift;
  118. }
  119. [CLSCompliant(false)]
  120. public struct TT_TABLE_DIRECTORY
  121. {
  122. public byte[] szTag;
  123. public UInt32 uCheckSum;
  124. public UInt32 uOffset;
  125. public UInt32 uLength;
  126. public void Initialize()
  127. {
  128. szTag = new byte[4];
  129. }
  130. }
  131. [CLSCompliant(false)]
  132. public struct TT_NAME_TABLE_HEADER
  133. {
  134. public ushort uFSelector;
  135. public ushort uNRCount;
  136. public ushort uStorageOffset;
  137. }
  138. [CLSCompliant(false)]
  139. public struct TT_NAME_RECORD
  140. {
  141. public ushort uPlatformID;
  142. public ushort uEncodingID;
  143. public ushort uLanguageID;
  144. public ushort uNameID;
  145. public ushort uStringLength;
  146. public ushort uStringOffset;
  147. }
  148. static private UInt16 ReadChar(FileStream fs, int characters)
  149. {
  150. string[] s = new string[characters];
  151. byte[] buf = new byte[Convert.ToByte(s.Length)];
  152. buf = ReadAndSwap(fs, buf.Length);
  153. return BitConverter.ToUInt16(buf, 0);
  154. }
  155. static private UInt16 ReadByte(FileStream fs)
  156. {
  157. byte[] buf = new byte[11];
  158. buf = ReadAndSwap(fs, buf.Length);
  159. return BitConverter.ToUInt16(buf, 0);
  160. }
  161. static private UInt16 ReadUShort(FileStream fs)
  162. {
  163. byte[] buf = new byte[2];
  164. buf = ReadAndSwap(fs, buf.Length);
  165. return BitConverter.ToUInt16(buf, 0);
  166. }
  167. static private UInt32 ReadULong(FileStream fs)
  168. {
  169. byte[] buf = new byte[4];
  170. buf = ReadAndSwap(fs, buf.Length);
  171. return BitConverter.ToUInt32(buf, 0);
  172. }
  173. static private byte[] ReadAndSwap(FileStream fs, int size)
  174. {
  175. byte[] buf = new byte[size];
  176. fs.Read(buf, 0, buf.Length);
  177. Array.Reverse(buf);
  178. return buf;
  179. }
  180. }
  181. class Program
  182. {
  183. //static void Main(string[] args)
  184. //{
  185. // System.Drawing.FontFamily fam;
  186. // var allInstalledFonts = from e in Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", false).GetValueNames()
  187. // select Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts").GetValue(e);
  188. // var ttfFonts = from e in allInstalledFonts.Where(e => (e.ToString().EndsWith(".ttf") || e.ToString().EndsWith(".otf"))) select e;
  189. // var ttfFontsPaths = from e in ttfFonts.Select(e => (Path.GetPathRoot(e.ToString()) == "") ? Environment.GetFolderPath(Environment.SpecialFolder.Fonts) + "\\" + e.ToString() : e.ToString()) select e;
  190. // var fonts = from e in ttfFontsPaths.Select(e => GetFontDetails(e.ToString())) select e;
  191. // foreach (InstalledFont f in fonts)
  192. // {
  193. // if (f != null)
  194. // Console.WriteLine("Name: " + f.FontName + ", SubFamily: " + f.FontSubFamily + ", Path: " + f.FontPath);
  195. // }
  196. // Console.ReadLine();
  197. //}
  198. }
  199. }
  200. #pragma warning restore