BIFF8_MSODrawing.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Collections;
  5. namespace FastReport.Export.BIFF8
  6. {
  7. class BIFF8_ShapeProp
  8. {
  9. UInt16 complex;
  10. UInt32 union;
  11. Byte[] data;
  12. // UInt32 Id;
  13. internal UInt32 ReadProperty(StreamHelper stream)
  14. {
  15. complex = stream.ReadUshort();
  16. union = stream.ReadUint();
  17. if ((complex & 0x8000) == 0)
  18. {
  19. return 6;
  20. }
  21. else
  22. {
  23. return 6 + union;
  24. }
  25. }
  26. internal void ReadPayload(StreamHelper stream)
  27. {
  28. if ((complex & 0x8000) != 0)
  29. {
  30. data = stream.ReadBytes((int)union);
  31. }
  32. }
  33. internal void WriteProperty(StreamHelper stream)
  34. {
  35. stream.WriteUshort(complex);
  36. stream.WriteUint(union);
  37. }
  38. internal void WritePayload(StreamHelper stream)
  39. {
  40. if ((complex & 0x8000) != 0)
  41. {
  42. stream.WriteBytes(data);
  43. }
  44. }
  45. public BIFF8_ShapeProp()
  46. {
  47. }
  48. public BIFF8_ShapeProp(UInt16 Complex, UInt32 Union)
  49. {
  50. this.complex = Complex;
  51. this.union = Union;
  52. }
  53. public BIFF8_ShapeProp(UInt16 Complex, UInt32 Union, Byte[] Data)
  54. {
  55. this.complex = Complex;
  56. this.union = Union;
  57. this.data = Data;
  58. }
  59. public BIFF8_ShapeProp(UInt16 Complex, string value)
  60. {
  61. this.complex = (ushort)(Complex | 0xc000);
  62. data = new byte[value.Length * 2 + 2];
  63. int i = 0;
  64. foreach (char ch in value)
  65. {
  66. data[i++] = (byte)ch;
  67. data[i++] = (byte)((ushort)ch >> 8);
  68. }
  69. data[i++] = 0;
  70. data[i] = 0;
  71. this.union = (uint)(this.data.Length);
  72. }
  73. }
  74. class BIFF8_ExcelDrawing
  75. {
  76. // msofbtSp
  77. UInt32 spid;
  78. UInt32 grfPersistent;
  79. // msofbtClientAnchor
  80. UInt16 unknown;
  81. UInt16 left_col;
  82. UInt16 left_off;
  83. UInt16 top_row;
  84. UInt16 top_off;
  85. UInt16 right_col;
  86. UInt16 right_off;
  87. UInt16 bottom_row;
  88. UInt16 bottom_off;
  89. // ftCmo: Common object data
  90. UInt16 objectType;
  91. UInt16 objectID;
  92. UInt16 optionFlags;
  93. // ftCf: Clipboard format
  94. UInt16 ftCf;
  95. // ftPioGrbit: Picture option flags
  96. UInt16 ftPioGrbit;
  97. ArrayList prop_list = new ArrayList();
  98. UInt32 first_shape_id = 1024;
  99. /// <summary>
  100. /// Related to DRAWING group. Used once
  101. /// </summary>
  102. UInt32 csp; // The number of shapes in this drawing
  103. UInt32 spidCur; // The last MSOSPID given to an SP in this DG
  104. internal long total_spgr_size_position;
  105. internal long total_dg_size_position;
  106. private void ReadSpgrContainer(StreamHelper stream, uint dg_record_size)
  107. {
  108. while (dg_record_size > 0)
  109. {
  110. UInt16 _packed_data = stream.ReadUshort();
  111. UInt16 _fbt = stream.ReadUshort();
  112. UInt32 _total_record_size = stream.ReadUint();
  113. if (_fbt != 0xf004) throw new Exception("Group container format error");
  114. ReadSpContainer(stream, _total_record_size);
  115. dg_record_size -= _total_record_size + 8;
  116. }
  117. }
  118. private void ReadDgContainer(StreamHelper stream, UInt32 container_size)
  119. {
  120. while (container_size > 0)
  121. {
  122. UInt16 dg_packed_data = stream.ReadUshort();
  123. UInt16 dg_fbt = stream.ReadUshort();
  124. UInt32 dg_record_size = stream.ReadUint();
  125. switch (dg_fbt)
  126. {
  127. case 0xf008: // msofbtDg
  128. csp = stream.ReadUint(); // The number of shapes in this drawing
  129. spidCur = stream.ReadUint(); // The last MSOSPID given to an SP in this DG
  130. break;
  131. case 0xf003: // msofbtSpgrContainer
  132. dg_record_size = container_size - 8;
  133. ReadSpgrContainer(stream, dg_record_size);
  134. break;
  135. }
  136. container_size -= dg_record_size + 8;
  137. }
  138. }
  139. private void ReadSpContainer(StreamHelper stream, UInt32 container_size)
  140. {
  141. while (container_size > 0)
  142. {
  143. UInt16 sp_packed_data = stream.ReadUshort();
  144. UInt16 sp_fbt = stream.ReadUshort();
  145. UInt32 sp_record_size = stream.ReadUint();
  146. switch (sp_fbt)
  147. {
  148. case 0xf009: // msofbtSpgr
  149. UInt32 x = stream.ReadUint();
  150. UInt32 y = stream.ReadUint();
  151. UInt32 dx = stream.ReadUint();
  152. UInt32 dy = stream.ReadUint();
  153. break;
  154. case 0xf00a: // msofbtSp
  155. spid = stream.ReadUint();
  156. grfPersistent = stream.ReadUint();
  157. break;
  158. case 0xf00b: // msofbtOPT
  159. UInt32 local_size = sp_record_size;
  160. while (local_size > 0)
  161. {
  162. BIFF8_ShapeProp prop = new BIFF8_ShapeProp();
  163. UInt32 prop_size = prop.ReadProperty(stream);
  164. prop_list.Add(prop);
  165. local_size -= prop_size;
  166. }
  167. foreach (BIFF8_ShapeProp prop in prop_list)
  168. {
  169. prop.ReadPayload(stream);
  170. }
  171. break;
  172. case 0xf010: // msofbtClientAnchor
  173. unknown = stream.ReadUshort();
  174. left_col = stream.ReadUshort();
  175. left_off = stream.ReadUshort();
  176. top_row = stream.ReadUshort();
  177. top_off = stream.ReadUshort();
  178. right_col = stream.ReadUshort();
  179. right_off = stream.ReadUshort();
  180. bottom_row = stream.ReadUshort();
  181. bottom_off = stream.ReadUshort();
  182. break;
  183. case 0xf011: // msofbtClientData
  184. stream.SkipBytes((int)sp_record_size);
  185. break;
  186. default:
  187. throw new Exception("Sp container format error");
  188. }
  189. container_size -= sp_record_size + 8;
  190. }
  191. }
  192. internal void Read(StreamHelper stream, UInt32 record_size)
  193. {
  194. UInt16 packed_data = stream.ReadUshort();
  195. UInt16 fbt = stream.ReadUshort();
  196. UInt32 total_record_size = stream.ReadUint();
  197. record_size -= 8;
  198. switch (fbt)
  199. {
  200. case 0xf002: // DgContainer
  201. ReadDgContainer(stream, record_size);
  202. break;
  203. case 0xf004: // SpContainer
  204. ReadSpContainer(stream, record_size);
  205. break;
  206. default:
  207. throw new Exception("Drawing structure error");
  208. }
  209. }
  210. internal void Read_GraphicsObject(StreamHelper stream, UInt32 RecordSize)
  211. {
  212. for (UInt16 sub_size = (UInt16)RecordSize; sub_size > 0;)
  213. {
  214. UInt16 SubRecordID = stream.ReadUshort();
  215. UInt16 SubRecordSize = stream.ReadUshort();
  216. switch (SubRecordID)
  217. {
  218. case 0x0015: // ftCmo: Common object data
  219. objectType = stream.ReadUshort();
  220. objectID = stream.ReadUshort();
  221. optionFlags = stream.ReadUshort();
  222. stream.SkipBytes(12);
  223. break;
  224. case 0x0007: // ftCf: Clipboard format
  225. ftCf = stream.ReadUshort();
  226. break;
  227. case 0x0008: // ftPioGrbit: Picture option flags
  228. ftPioGrbit = stream.ReadUshort();
  229. break;
  230. case 0x0000: // ftEnd: The ftEnd file type marks the end of an OBJ record.
  231. if (SubRecordSize != 0)
  232. {
  233. throw new Exception("Bad forrmat of ftEnd record");
  234. }
  235. break;
  236. default:
  237. throw new Exception("Unknown subrecord type in 005dh record");
  238. }
  239. sub_size -= (ushort)(SubRecordSize + sizeof(UInt16) + sizeof(UInt16));
  240. }
  241. }
  242. internal void Write_GraphicsObject(StreamHelper stream)
  243. {
  244. stream.WriteUshort(0x005d); // GOBJ
  245. stream.WriteUshort(38);
  246. stream.WriteUshort(0x0015); // GOBJ::ftCmo
  247. stream.WriteUshort(18);
  248. stream.WriteUshort(objectType);
  249. stream.WriteUshort(objectID);
  250. stream.WriteUshort(optionFlags);
  251. stream.SkipBytes(12);
  252. stream.WriteUshort(0x0007); // GOBJ::ftCf
  253. stream.WriteUshort(2);
  254. stream.WriteUshort(ftCf);
  255. stream.WriteUshort(0x0008); // GOBJ::ftPioGrbit
  256. stream.WriteUshort(2);
  257. stream.WriteUshort(ftPioGrbit);
  258. stream.WriteUshort(0x0000); // GOBJ::ftEnd
  259. stream.WriteUshort(0);
  260. }
  261. private void WriteSpOptions(StreamHelper stream)
  262. {
  263. stream.WriteUshort(0x00b3);
  264. stream.WriteUshort(0xf00b);
  265. long opt_size_position = stream.Position;
  266. stream.WriteUint(0x0000);
  267. foreach (BIFF8_ShapeProp prop in prop_list) prop.WriteProperty(stream);
  268. foreach (BIFF8_ShapeProp prop in prop_list) prop.WritePayload(stream);
  269. // Fix options size
  270. long curr_position = stream.Position;
  271. stream.Position = opt_size_position;
  272. opt_size_position = curr_position - opt_size_position - sizeof(UInt32);
  273. stream.WriteUint((ushort)opt_size_position);
  274. stream.Position = curr_position;
  275. }
  276. private uint Write_SpContainer(StreamHelper stream)
  277. {
  278. stream.WriteUshort(0x000f);
  279. stream.WriteUshort(0xf004); // SpContainer
  280. long container_size_position = stream.Position;
  281. stream.WriteUint(0x0000);
  282. // SP
  283. stream.WriteUshort(0x04b2);
  284. stream.WriteUshort(0xf00a);
  285. stream.WriteUint(0x0008);
  286. stream.WriteUint(spid);
  287. stream.WriteUint(grfPersistent);
  288. // OPT
  289. WriteSpOptions(stream);
  290. // ClientAnchor
  291. stream.WriteUshort(0x0000);
  292. stream.WriteUshort(0xf010);
  293. stream.WriteUint(0x0012);
  294. stream.WriteUshort(unknown);
  295. stream.WriteUshort(left_col);
  296. stream.WriteUshort(left_off);
  297. stream.WriteUshort(top_row);
  298. stream.WriteUshort(top_off);
  299. stream.WriteUshort(right_col);
  300. stream.WriteUshort(right_off);
  301. stream.WriteUshort(bottom_row);
  302. stream.WriteUshort(bottom_off);
  303. // ClientData
  304. stream.WriteUshort(0x0000);
  305. stream.WriteUshort(0xf011);
  306. stream.WriteUint(0x0000);
  307. long curr_position = stream.Position;
  308. stream.Position = container_size_position;
  309. container_size_position = curr_position - container_size_position - sizeof(UInt32);
  310. stream.WriteUint((ushort)container_size_position);
  311. stream.Position = curr_position;
  312. return (uint)(container_size_position + 8);
  313. }
  314. private uint Write_SpgrContainer(StreamHelper stream)
  315. {
  316. stream.WriteUshort(0x000f); // SPGR
  317. stream.WriteUshort(0xf003);
  318. total_spgr_size_position = stream.Position;
  319. stream.WriteUint(0x0000);
  320. stream.WriteUshort(0x000f); // SpContainer
  321. stream.WriteUshort(0xf004);
  322. stream.WriteUint(0x0028);
  323. stream.WriteUshort(0x0001); // msofbtSpgr
  324. stream.WriteUshort(0xf009);
  325. stream.WriteUint(0x0010);
  326. stream.WriteUint(0); // x
  327. stream.WriteUint(0); // y
  328. stream.WriteUint(0); // dx
  329. stream.WriteUint(0); // dy
  330. // SP
  331. stream.WriteUshort(0x0002);
  332. stream.WriteUshort(0xf00a);
  333. stream.WriteUint(0x0008);
  334. stream.WriteUint(first_shape_id /*1024*/); // First shape ID 1024
  335. stream.WriteUint(5); // Bitfield for root record.
  336. uint container_size = Write_SpContainer(stream);
  337. return container_size + 48;
  338. }
  339. internal uint Write(StreamHelper stream, bool drawing_group)
  340. {
  341. uint multiple_sp_size = 0;
  342. stream.WriteUshort(0x00ec); // DRAWING
  343. long drawing_size_position = stream.Position;
  344. stream.WriteUshort(0x0000);
  345. if (drawing_group)
  346. {
  347. // DG container
  348. stream.WriteUshort(0x000f);
  349. stream.WriteUshort(0xf002);
  350. total_dg_size_position = stream.Position;
  351. stream.WriteUint(0x0000);
  352. // DG
  353. stream.WriteUshort(0x0010);
  354. stream.WriteUshort(0xf008); // DG
  355. stream.WriteUint(0x0008);
  356. stream.WriteUint(csp + 1); // The number of shapes in this drawing
  357. stream.WriteUint(spidCur); // The last MSOSPID given to an SP in this DG
  358. multiple_sp_size += Write_SpgrContainer(stream);
  359. }
  360. else
  361. {
  362. multiple_sp_size += Write_SpContainer(stream);
  363. }
  364. long curr_position = stream.Position;
  365. stream.Position = drawing_size_position;
  366. drawing_size_position = curr_position - drawing_size_position - sizeof(UInt16);
  367. stream.WriteUshort((ushort)drawing_size_position);
  368. stream.Position = curr_position;
  369. return multiple_sp_size;
  370. }
  371. internal void AddPicureToSheet(
  372. FastReport.Export.ExportIEMObject Obj, int index, int x, int y, int dx, int dy)
  373. {
  374. this.csp = (uint)(index + 1);
  375. this.spidCur = this.csp + first_shape_id;
  376. this.unknown = 2;
  377. this.left_col = (ushort)x;
  378. this.left_off = 0;
  379. this.top_row = (ushort)y;
  380. this.top_off = 0;
  381. this.right_col = (ushort)(x + dx);
  382. this.right_off = 0;
  383. this.bottom_row = (ushort)(y + dy);
  384. this.bottom_off = 0;
  385. this.right_off = 3; // 256;
  386. this.bottom_off = 3; // 205;
  387. this.spid = spidCur;
  388. this.grfPersistent = 0xa00;
  389. // ftCmo: Common object data
  390. this.objectType = 0x0008;
  391. this.objectID = (ushort)csp; // 0x002a;
  392. this.optionFlags = 0x6011;
  393. this.ftCf = 0xffff;
  394. this.ftPioGrbit = 0x0001;
  395. prop_list.Add(new BIFF8_ShapeProp(127, 0x01fb0080)); // fLockAgainstGrouping
  396. prop_list.Add(new BIFF8_ShapeProp(191, 0x00040004)); // fFitTextToShape
  397. prop_list.Add(new BIFF8_ShapeProp(260 | 0x4000, csp)); // fFitTextToShape
  398. prop_list.Add(new BIFF8_ShapeProp(261, "pib" + csp.ToString() + ".png")); // pibName
  399. prop_list.Add(new BIFF8_ShapeProp(319, 0x00060000)); // pictureActive
  400. prop_list.Add(new BIFF8_ShapeProp(447, 0x00110000)); // fNoFillHitTest
  401. prop_list.Add(new BIFF8_ShapeProp(511, 0x00180010)); // fNoLineDrawDash
  402. prop_list.Add(new BIFF8_ShapeProp(831, 0x00180010)); // fBackground
  403. prop_list.Add(new BIFF8_ShapeProp(896, "pic" + csp.ToString())); // wzName
  404. prop_list.Add(new BIFF8_ShapeProp(897, "")); // wzDescription is empty
  405. prop_list.Add(new BIFF8_ShapeProp(959, 0x00020000)); // ??
  406. }
  407. internal BIFF8_ExcelDrawing()
  408. {
  409. }
  410. }
  411. }