NameTableClass.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. #pragma warning disable CS3001, CS3002, CS3003, CS1591
  7. namespace FastReport.Fonts
  8. {
  9. /// <summary>
  10. /// Name table keep human friendly description about font properties, including font names, author and copyright notes
  11. /// </summary>
  12. public class NameTableClass : TrueTypeTable, ICollection
  13. {
  14. #region "Structure dfinition"
  15. public enum NameID
  16. {
  17. CopyrightNotice = 0,
  18. FamilyName = 1,
  19. SubFamilyName = 2,
  20. UniqueID = 3,
  21. FullName = 4,
  22. Version = 5,
  23. PostscriptName = 6,
  24. Trademark = 7,
  25. Manufacturer = 8,
  26. Designer = 9,
  27. Description = 10,
  28. URL_Vendor = 11,
  29. URL_Designer = 12,
  30. LicenseDescription = 13,
  31. LicenseInfoURL = 14,
  32. PreferredFamily = 16,
  33. PreferredSubFamily = 17,
  34. CompatibleFull = 18,
  35. SampleText = 19,
  36. PostscriptCID = 20,
  37. WWS_Family_Name = 21,
  38. WWS_SubFamily_Name = 22
  39. }
  40. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  41. public struct NamingTableHeader
  42. {
  43. [FieldOffset(0)]
  44. public ushort TableVersion;
  45. [FieldOffset(2)]
  46. public ushort Count;
  47. [FieldOffset(4)]
  48. public ushort stringOffset;
  49. }
  50. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  51. public struct NamingRecord
  52. {
  53. [FieldOffset(0)]
  54. public ushort PlatformID;
  55. [FieldOffset(2)]
  56. public ushort EncodingID;
  57. [FieldOffset(4)]
  58. public ushort LanguageID;
  59. [FieldOffset(6)]
  60. public ushort NameID;
  61. [FieldOffset(8)]
  62. public ushort Length;
  63. [FieldOffset(10)]
  64. public ushort Offset;
  65. }
  66. #endregion
  67. NamingTableHeader name_header;
  68. IntPtr namerecord_ptr;
  69. IntPtr string_storage_ptr;
  70. Dictionary<NameID, List<string>> names = new Dictionary<NameID, List<string>>();
  71. public Dictionary<NameID, List<string>> NamesDict
  72. {
  73. get
  74. {
  75. return names;
  76. }
  77. }
  78. public int Count
  79. {
  80. get
  81. {
  82. return name_header.Count;
  83. }
  84. }
  85. public object SyncRoot
  86. {
  87. get
  88. {
  89. return null; // Names.SyncRoot;
  90. }
  91. }
  92. public bool IsSynchronized
  93. {
  94. get
  95. {
  96. return true; // Names.IsSynchronized;
  97. }
  98. }
  99. private void ChangeEndian()
  100. {
  101. name_header.TableVersion = SwapUInt16(name_header.TableVersion);
  102. name_header.Count = SwapUInt16(name_header.Count);
  103. name_header.stringOffset = SwapUInt16(name_header.stringOffset);
  104. }
  105. internal override void Load(IntPtr font)
  106. {
  107. IntPtr nameheader_ptr = Increment(font, (int)this.Offset);
  108. name_header = (NamingTableHeader)Marshal.PtrToStructure(nameheader_ptr, typeof(NamingTableHeader));
  109. ChangeEndian();
  110. namerecord_ptr = Increment(nameheader_ptr, Marshal.SizeOf(name_header));
  111. string_storage_ptr = Increment(nameheader_ptr, (int)name_header.stringOffset);
  112. // Parse table to local storage
  113. IntPtr record_ptr = namerecord_ptr;
  114. for (int i = 0; i < name_header.Count; i++)
  115. {
  116. NamingRecord name_rec = (NamingRecord)Marshal.PtrToStructure(record_ptr, typeof(NamingRecord));
  117. record_ptr = Increment(record_ptr, Marshal.SizeOf(name_rec));
  118. name_rec.PlatformID = SwapUInt16(name_rec.PlatformID);
  119. name_rec.EncodingID = SwapUInt16(name_rec.EncodingID);
  120. name_rec.LanguageID = SwapUInt16(name_rec.LanguageID);
  121. name_rec.NameID = SwapUInt16(name_rec.NameID);
  122. name_rec.Length = SwapUInt16(name_rec.Length);
  123. name_rec.Offset = SwapUInt16(name_rec.Offset);
  124. byte[] Temp = new byte[name_rec.Length];
  125. IntPtr string_ptr = Increment(string_storage_ptr, name_rec.Offset);
  126. Marshal.Copy(string_ptr, Temp, 0, (int)Temp.Length);
  127. string value;
  128. if (name_rec.PlatformID == 1)
  129. {
  130. value = Encoding.GetEncoding("utf-8").GetString(Temp);
  131. }
  132. else
  133. {
  134. value = Encoding.GetEncoding(1201).GetString(Temp);
  135. }
  136. NameID id = (NameID)name_rec.NameID;
  137. List<string> values;
  138. if (!names.ContainsKey(id))
  139. {
  140. values = new List<string>();
  141. names.Add(id, values);
  142. }
  143. else
  144. {
  145. values = (List<string>)names[id];
  146. }
  147. if (!values.Contains(value))
  148. {
  149. values.Add(value);
  150. }
  151. #if _DEBUG
  152. else
  153. {
  154. Debug.WriteLine("Skip duplicated name: " + value);
  155. }
  156. #endif
  157. }
  158. }
  159. public void CopyTo(Array array, int index)
  160. {
  161. throw new NotImplementedException();
  162. }
  163. public IEnumerator GetEnumerator()
  164. {
  165. return names.Keys.GetEnumerator();
  166. }
  167. public ICollection this[NameID Index]
  168. {
  169. get
  170. {
  171. #if true
  172. ICollection rec = null;
  173. if (names.ContainsKey(Index))
  174. {
  175. rec = names[Index] as ICollection;
  176. }
  177. return rec;
  178. #else
  179. IntPtr record_ptr = namerecord_ptr;
  180. for (int i = 0; i < name_header.Count; i++)
  181. {
  182. NamingRecord name_rec = (NamingRecord)Marshal.PtrToStructure(record_ptr, typeof(NamingRecord));
  183. record_ptr = Increment(record_ptr, Marshal.SizeOf(name_rec));
  184. name_rec.PlatformID = SwapUInt16(name_rec.PlatformID);
  185. name_rec.EncodingID = SwapUInt16(name_rec.EncodingID);
  186. name_rec.LanguageID = SwapUInt16(name_rec.LanguageID);
  187. name_rec.NameID = SwapUInt16(name_rec.NameID);
  188. name_rec.Length = SwapUInt16(name_rec.Length);
  189. name_rec.Offset = SwapUInt16(name_rec.Offset);
  190. if (((name_rec.PlatformID == 3 && name_rec.EncodingID == 1) || name_rec.PlatformID == 0) &&
  191. (NameID)name_rec.NameID == Index)
  192. {
  193. byte[] Temp = new byte[name_rec.Length];
  194. IntPtr string_ptr = Increment(string_storage_ptr, name_rec.Offset);
  195. Marshal.Copy(string_ptr, Temp, 0, (int)Temp.Length);
  196. return Encoding.GetEncoding(1201).GetString(Temp);
  197. }
  198. }
  199. #if !DEBUG_TABLE
  200. record_ptr = namerecord_ptr;
  201. for (int i = 0; i < name_header.Count; i++)
  202. {
  203. NamingRecord name_rec = (NamingRecord)Marshal.PtrToStructure(record_ptr, typeof(NamingRecord));
  204. record_ptr = Increment(record_ptr, Marshal.SizeOf(name_rec));
  205. name_rec.PlatformID = SwapUInt16(name_rec.PlatformID);
  206. name_rec.EncodingID = SwapUInt16(name_rec.EncodingID);
  207. name_rec.LanguageID = SwapUInt16(name_rec.LanguageID);
  208. name_rec.NameID = SwapUInt16(name_rec.NameID);
  209. name_rec.Length = SwapUInt16(name_rec.Length);
  210. name_rec.Offset = SwapUInt16(name_rec.Offset);
  211. if ((NameID)name_rec.NameID == Index)
  212. {
  213. continue;
  214. }
  215. }
  216. #endif
  217. return null;
  218. #endif
  219. }
  220. }
  221. public NameTableClass(TrueTypeTable src) : base(src) { }
  222. }
  223. }
  224. #pragma warning restore