FontStream.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. //using System.Runtime.InteropServices;
  2. using System.IO;
  3. using System;
  4. #pragma warning disable CS3001, CS3002, CS3003, CS1591
  5. namespace FastReport.Fonts
  6. {
  7. public class FontStream : IDisposable
  8. {
  9. private readonly byte[] _buffer;
  10. private bool _leaveOpen;
  11. private bool _disposedValue;
  12. private readonly Stream _stream;
  13. private string _fast_name;
  14. /// <summary>
  15. /// Creates a new instance of the <see cref="FontStream"/> class.
  16. /// </summary>
  17. /// <param name="stream">TrueType raw data stream</param>
  18. /// <param name="leaveOpen">Keep open raw data stream after disposing FontStream</param>
  19. public FontStream(Stream stream, bool leaveOpen = false)
  20. {
  21. this._stream = stream;
  22. this._buffer = new byte[16];
  23. this._leaveOpen = leaveOpen;
  24. // Trace.WriteLine.WriteLine("FontStream constructor");
  25. }
  26. public bool CanRead => _stream.CanRead;
  27. public bool CanSeek => _stream.CanSeek;
  28. public long Length => _stream.Length;
  29. public long Position
  30. {
  31. get => _stream.Position;
  32. set => _stream.Position = value;
  33. }
  34. /// <summary>
  35. /// FastName of font stream
  36. /// </summary>
  37. internal string StreamFontFastName
  38. {
  39. get => _fast_name;
  40. set => _fast_name = value;
  41. }
  42. internal bool LeaveOpen
  43. {
  44. set => _leaveOpen = value;
  45. }
  46. public long Seek(long offset, SeekOrigin origin)
  47. {
  48. return _stream.Seek(offset, origin);
  49. }
  50. internal void Read(byte[] data, int length)
  51. {
  52. _stream.Read(data, 0, length);
  53. }
  54. internal void Write(byte[] data, int length)
  55. {
  56. _stream.Write(data, 0, length);
  57. }
  58. protected virtual void Dispose(bool disposing)
  59. {
  60. #if SAVE_COPY_OF_SUBSETTET_FONT_TO_FILE
  61. if (_stream.CanWrite)
  62. {
  63. _stream.Position = 0;
  64. FileStream debug = File.OpenWrite("FONT-" + DateTime.Now.Ticks + ".ttf");
  65. if (debug != null && debug.CanWrite)
  66. {
  67. _stream.CopyTo(debug);
  68. debug.Close();
  69. }
  70. }
  71. #endif
  72. if (!_disposedValue)
  73. {
  74. if (!_leaveOpen)
  75. _stream.Dispose();
  76. _disposedValue = true;
  77. }
  78. }
  79. public void Dispose()
  80. {
  81. // DO NOT CHANGE THIS CODE! If you need clenup code - put it into "Dispose(bool disposing)" method.
  82. Dispose(disposing: true);
  83. GC.SuppressFinalize(this);
  84. }
  85. private void ReadInternal(int size)
  86. {
  87. int n;
  88. if (size == 1)
  89. {
  90. n = _stream.ReadByte();
  91. if (n == -1)
  92. throw new EndOfStreamException();
  93. _buffer[0] = (byte)n;
  94. return;
  95. }
  96. int bytesRead = 0;
  97. do
  98. {
  99. n = _stream.Read(_buffer, bytesRead, size - bytesRead);
  100. if (n == 0)
  101. {
  102. throw new EndOfStreamException();
  103. }
  104. bytesRead += n;
  105. } while (bytesRead < size);
  106. }
  107. public uint ReadUInt32()
  108. {
  109. ReadInternal(4);
  110. if (BitConverter.IsLittleEndian)
  111. return (uint)(_buffer[3] | _buffer[2] << 8 | _buffer[1] << 16 | _buffer[0] << 24);
  112. else
  113. return (uint)(_buffer[0] | _buffer[1] << 8 | _buffer[2] << 16 | _buffer[3] << 24);
  114. }
  115. internal void WriteUInt32(uint word)
  116. {
  117. byte[] holder = new byte[4];
  118. if (BitConverter.IsLittleEndian)
  119. {
  120. holder[3] = (byte)(word);
  121. holder[2] = (byte)(word >> 8);
  122. holder[1] = (byte)(word >> 16);
  123. holder[0] = (byte)(word >> 24);
  124. }
  125. else
  126. {
  127. holder[0] = (byte)(word);
  128. holder[1] = (byte)(word >> 8);
  129. holder[2] = (byte)(word >> 16);
  130. holder[3] = (byte)(word >> 24);
  131. }
  132. _stream.Write(holder, 0, 4);
  133. }
  134. public int ReadInt32()
  135. {
  136. ReadInternal(4);
  137. if (BitConverter.IsLittleEndian)
  138. return (int)(_buffer[3] | _buffer[2] << 8 | _buffer[1] << 16 | _buffer[0] << 24);
  139. else
  140. return (int)(_buffer[0] | _buffer[1] << 8 | _buffer[2] << 16 | _buffer[3] << 24);
  141. }
  142. public byte ReadByte()
  143. {
  144. int b = _stream.ReadByte();
  145. if (b == -1)
  146. throw new EndOfStreamException();
  147. return (byte)b;
  148. }
  149. public virtual sbyte ReadSByte()
  150. {
  151. ReadInternal(1);
  152. return (sbyte)(_buffer[0]);
  153. }
  154. public ushort ReadUInt16()
  155. {
  156. ReadInternal(2);
  157. if (BitConverter.IsLittleEndian)
  158. return (ushort)(_buffer[1] | _buffer[0] << 8);
  159. else
  160. return (ushort)(_buffer[0] | _buffer[1] << 8);
  161. }
  162. public short ReadInt16()
  163. {
  164. ReadInternal(2);
  165. if (BitConverter.IsLittleEndian)
  166. return (short)(_buffer[1] | _buffer[0] << 8);
  167. else
  168. return (short)(_buffer[0] | _buffer[1] << 8);
  169. }
  170. public ulong ReadUInt64()
  171. {
  172. uint hi, lo;
  173. ReadInternal(8);
  174. if (BitConverter.IsLittleEndian)
  175. {
  176. lo = (uint)(_buffer[7] | _buffer[6] << 8 | _buffer[5] << 16 | _buffer[4] << 24);
  177. hi = (uint)(_buffer[3] | _buffer[2] << 8 | _buffer[1] << 16 | _buffer[0] << 24);
  178. }
  179. else
  180. {
  181. lo = (uint)(_buffer[0] | _buffer[1] << 8 | _buffer[2] << 16 | _buffer[3] << 24);
  182. hi = (uint)(_buffer[4] | _buffer[5] << 8 | _buffer[6] << 16 | _buffer[7] << 24);
  183. }
  184. return ((ulong)hi) << 32 | lo;
  185. }
  186. public virtual long ReadInt64()
  187. {
  188. uint hi, lo;
  189. ReadInternal(8);
  190. if (BitConverter.IsLittleEndian)
  191. {
  192. lo = (uint)(_buffer[7] | _buffer[6] << 8 | _buffer[5] << 16 | _buffer[4] << 24);
  193. hi = (uint)(_buffer[3] | _buffer[2] << 8 | _buffer[1] << 16 | _buffer[0] << 24);
  194. }
  195. else
  196. {
  197. lo = (uint)(_buffer[0] | _buffer[1] << 8 | _buffer[2] << 16 | _buffer[3] << 24);
  198. hi = (uint)(_buffer[4] | _buffer[5] << 8 | _buffer[6] << 16 | _buffer[7] << 24);
  199. }
  200. return (long)((ulong)hi) << 32 | lo;
  201. }
  202. internal void WriteUInt16(ushort data16)
  203. {
  204. byte[] data8 = new byte[2];
  205. if (BitConverter.IsLittleEndian)
  206. {
  207. data8[1] = (byte)(data16);
  208. data8[0] = (byte)(data16 >> 8);
  209. }
  210. else
  211. {
  212. data8[0] = (byte)(data16);
  213. data8[1] = (byte)(data16 >> 8);
  214. }
  215. _stream.Write(data8, 0, 2);
  216. }
  217. internal void WriteInt16(short ascender)
  218. {
  219. WriteUInt16((ushort)ascender);
  220. }
  221. internal void WriteByte(byte data8)
  222. {
  223. _stream.WriteByte(data8);
  224. }
  225. internal void WriteUInt64(ulong data64)
  226. {
  227. Byte[] bytes = BitConverter.GetBytes(data64);
  228. if (BitConverter.IsLittleEndian)
  229. Array.Reverse(bytes);
  230. _stream.Write(bytes, 0, 8);
  231. }
  232. internal void WriteInt32(uint data4)
  233. {
  234. WriteUInt32((uint)data4);
  235. }
  236. }
  237. }
  238. #pragma warning restore