/SpoolFileReader/Emf/EMFSpoolFile.cs

# · C# · 235 lines · 208 code · 25 blank · 2 comment · 23 complexity · 89b24f6734a722561710789653799720 MD5 · raw file

  1. #region References
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.IO;
  7. using System.Text;
  8. using SpoolFileLibrary.Reader.Winspool;
  9. #endregion
  10. namespace SpoolFileLibrary.Reader.Emf {
  11. internal class EmfSpoolFile : ISpoolFile {
  12. private readonly BinaryReader binaryReader;
  13. private readonly IList<IPage> pages;
  14. private DeviceMode deviceMode;
  15. public EmfSpoolFile(Stream stream) {
  16. if(stream == null) {
  17. throw new ArgumentNullException("stream");
  18. }
  19. stream.Seek(0, SeekOrigin.Begin);
  20. this.binaryReader = new BinaryReader(stream, Encoding.Unicode);
  21. this.pages = new List<IPage>();
  22. }
  23. #region ISpoolFile Members
  24. public bool Parse(bool parsePages, int scaleFactor) {
  25. HeaderRecord headerRecord = this.ParseHeaderRecord();
  26. List<DataRecord> dataRecords = this.ParseDataRecords();
  27. if(parsePages) {
  28. for(int i = 0; i < dataRecords.Count; i++) {
  29. var pageContentRecord = dataRecords[i] as PageContentRecord;
  30. if(pageContentRecord != null) {
  31. var memoryStream = new MemoryStream(pageContentRecord.EmfMetaFile);
  32. var metaFile = new Metafile(memoryStream);
  33. Image image = metaFile.GetThumbnailImage(metaFile.Width/scaleFactor, metaFile.Height/scaleFactor, null, IntPtr.Zero);
  34. var emfPage = new EmfPage(image, image.Size);
  35. this.pages.Add(emfPage);
  36. }
  37. var devmodeRecord = dataRecords[i] as EMRI_DEVMODERecord;
  38. if(devmodeRecord != null) {
  39. this.deviceMode = devmodeRecord.Devmode;
  40. }
  41. }
  42. }
  43. return true;
  44. }
  45. public SpoolFileFormat SpoolFileFormat {
  46. get { return Reader.SpoolFileFormat.EMF; }
  47. }
  48. public PrintjobLanguage PrintjobLanguage {
  49. get { return PrintjobLanguage.UNKNOWN; }
  50. }
  51. public bool Parse() {
  52. return this.Parse(false, 0);
  53. }
  54. public IList<IPage> Pages {
  55. get { return this.pages; }
  56. }
  57. public int PageCount {
  58. get { return this.pages.Count; }
  59. }
  60. public int Copies {
  61. get { return this.deviceMode.Copies; }
  62. }
  63. public bool Color {
  64. get { return this.deviceMode.Color; }
  65. }
  66. public int PaperLength {
  67. get { return this.deviceMode.PaperLength; }
  68. }
  69. public int PaperWidth {
  70. get { return this.deviceMode.PaperWidth; }
  71. }
  72. public bool Landscape {
  73. get { return this.deviceMode.Orientation == Orientation.Landscape; }
  74. }
  75. public IDeviceMode DeviceMode {
  76. get { return this.deviceMode; }
  77. }
  78. public byte[] RawData {
  79. get { return null; }
  80. }
  81. #endregion
  82. private List<DataRecord> ParseDataRecords() {
  83. var dataRecords = new List<DataRecord>();
  84. while(true) {
  85. long pos = this.binaryReader.BaseStream.Position;
  86. bool eof = (pos == this.binaryReader.BaseStream.Length);
  87. if(eof) {
  88. break;
  89. }
  90. uint ulID = this.binaryReader.ReadUInt32();
  91. if(ulID == 0x00000000) {
  92. //Don't know why. Sometimes 0x0 is too early.
  93. //So we need read it again.
  94. ulID = this.binaryReader.ReadUInt32();
  95. }
  96. var dataRecord = new DataRecord();
  97. dataRecord.ulID = ulID;
  98. dataRecord.cjSize = this.binaryReader.ReadUInt32();
  99. if(!Enum.IsDefined(typeof(RecordType), dataRecord.ulID)) {
  100. this.binaryReader.ReadBytes((int)dataRecord.cjSize); // Read unknown data block
  101. continue;
  102. }
  103. switch(dataRecord.ulID) {
  104. case (uint) RecordType.EMRI_METAFILE: {
  105. var pageContentRecord = new PageContentRecord(dataRecord);
  106. pageContentRecord.EmfMetaFile = this.binaryReader.ReadBytes((int) pageContentRecord.cjSize);
  107. dataRecords.Add(pageContentRecord);
  108. }
  109. break;
  110. case (uint) RecordType.EMRI_ENGINE_FONT:
  111. break;
  112. case (uint) RecordType.EMRI_DEVMODE: {
  113. var devmodeRecord = new EMRI_DEVMODERecord(dataRecord);
  114. byte[] buffer = this.binaryReader.ReadBytes((int) devmodeRecord.cjSize);
  115. this.deviceMode = new DeviceMode(new DEVMODE(buffer));
  116. devmodeRecord.Devmode = this.deviceMode;
  117. dataRecords.Add(devmodeRecord);
  118. }
  119. break;
  120. case (uint) RecordType.EMRI_TYPE1_FONT:
  121. break;
  122. case (uint) RecordType.EMRI_PRESTARTPAGE:
  123. break;
  124. case (uint) RecordType.EMRI_DESIGNVECTOR:
  125. break;
  126. case (uint) RecordType.EMRI_SUBSET_FONT:
  127. break;
  128. case (uint) RecordType.EMRI_DELTA_FONT:
  129. break;
  130. case (uint) RecordType.EMRI_FORM_METAFILE:
  131. break;
  132. case (uint) RecordType.EMRI_BW_METAFILE:
  133. break;
  134. case (uint) RecordType.EMRI_BW_FORM_METAFILE:
  135. break;
  136. case (uint) RecordType.EMRI_METAFILE_DATA: {
  137. var pageContentRecord = new PageContentRecord(dataRecord);
  138. pageContentRecord.EmfMetaFile = this.binaryReader.ReadBytes((int) dataRecord.cjSize);
  139. dataRecords.Add(pageContentRecord);
  140. }
  141. break;
  142. case (uint) RecordType.EMRI_METAFILE_EXT:
  143. case (uint) RecordType.EMRI_BW_METAFILE_EXT: {
  144. var pageOffsetRecord = new PageOffsetRecord(dataRecord);
  145. var offsets = new ulong[pageOffsetRecord.cjSize/sizeof(ulong)];
  146. for(int i = 0; i < offsets.Length; i++) {
  147. offsets[i] = this.binaryReader.ReadUInt64();
  148. }
  149. dataRecords.Add(pageOffsetRecord);
  150. }
  151. break;
  152. case (uint) RecordType.EMRI_ENGINE_FONT_EXT:
  153. break;
  154. case (uint) RecordType.EMRI_TYPE1_FONT_EXT:
  155. break;
  156. case (uint) RecordType.EMRI_DESIGNVECTOR_EXT:
  157. break;
  158. case (uint) RecordType.EMRI_SUBSET_FONT_EXT:
  159. break;
  160. case (uint) RecordType.EMRI_DELTA_FONT_EXT:
  161. break;
  162. case (uint) RecordType.EMRI_PS_JOB_DATA:
  163. break;
  164. case (uint) RecordType.EMRI_EMBED_FONT_EXT:
  165. break;
  166. }
  167. }
  168. return dataRecords;
  169. }
  170. private HeaderRecord ParseHeaderRecord() {
  171. var headerRecord = new HeaderRecord();
  172. headerRecord.dwVersion = this.binaryReader.ReadUInt32();
  173. headerRecord.cjSize = this.binaryReader.ReadUInt32();
  174. headerRecord.dpszDocName = this.binaryReader.ReadUInt32();
  175. headerRecord.dpszOutput = this.binaryReader.ReadUInt32();
  176. if(headerRecord.dpszDocName != 0) {
  177. this.binaryReader.BaseStream.Seek(headerRecord.dpszDocName, SeekOrigin.Begin);
  178. var docNameStringBuilder = new StringBuilder();
  179. while(this.binaryReader.PeekChar() != 0) {
  180. docNameStringBuilder.Append(this.binaryReader.ReadChar());
  181. }
  182. headerRecord.DocName = docNameStringBuilder.ToString();
  183. }
  184. this.Ensure32BitAlignment();
  185. if(headerRecord.dpszOutput != 0) {
  186. this.binaryReader.BaseStream.Seek(headerRecord.dpszOutput, SeekOrigin.Begin);
  187. var outputDeviceStringBuilder = new StringBuilder();
  188. while(this.binaryReader.PeekChar() != 0) {
  189. outputDeviceStringBuilder.Append(this.binaryReader.ReadChar());
  190. }
  191. headerRecord.OutputDevice = outputDeviceStringBuilder.ToString();
  192. }
  193. this.Ensure32BitAlignment();
  194. this.EnsurePosition(headerRecord.cjSize);
  195. return headerRecord;
  196. }
  197. private void EnsurePosition(uint size)
  198. {
  199. this.binaryReader.BaseStream.Seek(size, SeekOrigin.Begin);
  200. }
  201. private void Ensure32BitAlignment() {
  202. long pos = this.binaryReader.BaseStream.Position;
  203. long currentAlignment = pos%4;
  204. if(currentAlignment == 0) {
  205. return;
  206. }
  207. this.binaryReader.BaseStream.Seek(currentAlignment, SeekOrigin.Current);
  208. }
  209. }
  210. }