RTF_Picture.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. using FastReport.Utils;
  2. using System;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.IO;
  6. using System.Text;
  7. namespace FastReport.RichTextParser
  8. {
  9. internal class RTF_Picture : RTF_CommonRichElement
  10. {
  11. internal Picture picture = new Picture();
  12. internal long metamapmode;
  13. public RTF_Picture()
  14. {
  15. picture.scalex = 100;
  16. picture.scaley = 100;
  17. subdata_counter = 1;
  18. }
  19. internal override RichObject RichObject
  20. {
  21. get
  22. {
  23. RichObject rich = new RichObject();
  24. rich.type = RichObject.Type.Picture;
  25. rich.picture = picture;
  26. rich.size = picture.size;
  27. return rich;
  28. }
  29. }
  30. private enum State { PictHeader, BlipImage, BlipMetafile };
  31. private State state = State.PictHeader;
  32. int subdata_counter;
  33. internal void CreateImage(byte[] streamArray)
  34. {
  35. switch (state)
  36. {
  37. case State.PictHeader:
  38. throw new NotImplementedException("Image format not supported (yet)");
  39. case State.BlipImage:
  40. picture.image = ImageHelper.Load(streamArray);
  41. picture.width = picture.image.Width;
  42. picture.height = picture.image.Height;
  43. break;
  44. case State.BlipMetafile:
  45. #if true
  46. //picture.image = new Metafile(stream);
  47. picture.image = new Bitmap(new MemoryStream(streamArray));
  48. if (metamapmode == 8)
  49. {
  50. picture.width = picture.image.Width;
  51. picture.height = picture.image.Height;
  52. if (picture.desired_height != 0)
  53. picture.height = Twips2Pixels(picture.desired_height);
  54. if (picture.desired_width != 0)
  55. picture.height = Twips2Pixels(picture.desired_width);
  56. }
  57. #elif false
  58. using (var fileStream = File.Create("my.wmf"))
  59. {
  60. stream.Seek(0, SeekOrigin.Begin);
  61. stream.CopyTo(fileStream);
  62. }
  63. #else
  64. picture.image = new Bitmap(32, 32, PixelFormat.Format32bppArgb);
  65. using (Graphics graphics = Graphics.FromImage(picture.image))
  66. {
  67. graphics.FillEllipse(Brushes.Brown, new Rectangle(new Point(0, 0), picture.image.Size));
  68. }
  69. #endif
  70. break;
  71. }
  72. }
  73. private byte CharToHex(char ch)
  74. {
  75. if (char.IsDigit(ch))
  76. return (byte)(ch - '0');
  77. if (ch >= 'A' && ch <= 'F')
  78. return (byte)(10 + ch - 'A');
  79. if (ch >= 'a' && ch <= 'f')
  80. return (byte)(10 + ch - 'a');
  81. return 0;
  82. }
  83. internal bool ParseBlip(RTF_Parser parser, RTF_Header header)
  84. {
  85. int i, j;
  86. int len = parser.Text.Length;
  87. byte h = 0, l;
  88. byte[] raw_pict = new byte[len >> 1];
  89. for (i = j = 0; i < len; i++)
  90. {
  91. if ((i & 1) == 0)
  92. {
  93. h = CharToHex(parser.Text[i]);
  94. }
  95. else
  96. {
  97. l = CharToHex(parser.Text[i]);
  98. raw_pict[j++] = (byte)((h << 4) | l);
  99. }
  100. }
  101. try
  102. {
  103. CreateImage(raw_pict);
  104. }
  105. catch (Exception e)
  106. {
  107. if (picture.desired_height != 0)
  108. picture.height = Twips2Pixels(picture.desired_height);
  109. if (picture.desired_width != 0)
  110. picture.width = Twips2Pixels(picture.desired_width);
  111. picture.image = new Bitmap(picture.width, picture.height);
  112. Graphics g = Graphics.FromImage(picture.image);
  113. g.DrawString("Unable load bitmap", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Red), 5, 5); ;
  114. g.DrawString(e.Message, new Font(FontFamily.GenericMonospace, 8), new SolidBrush(Color.Red), 5, 20); ;
  115. }
  116. return false;
  117. }
  118. internal override bool Parse(RTF_Parser parser, RTF_Header header)
  119. {
  120. if (parser.Status == ParserStatus.OpenBlock)
  121. {
  122. subdata_counter++;
  123. }
  124. if (parser.Status == ParserStatus.CloseBlock)
  125. // if (parser.Status == ParserStatus.OpenBlock)
  126. {
  127. subdata_counter--;
  128. picture.horizontalAlign = parser.current_paragraph_format.align;
  129. }
  130. switch (parser.Control)
  131. {
  132. case "picw":
  133. picture.width = (int)parser.Number;
  134. break;
  135. case "pich":
  136. picture.height = (int)parser.Number;
  137. break;
  138. case "picscalex":
  139. picture.scalex = (int)parser.Number;
  140. break;
  141. case "picscaley":
  142. picture.scaley = (int)parser.Number;
  143. break;
  144. case "pngblip":
  145. state = State.BlipImage;
  146. break;
  147. case "jpegblip":
  148. state = State.BlipImage;
  149. break;
  150. case "piccropt":
  151. picture.crop_top = Twips2Pixels(parser.Number);
  152. break;
  153. case "piccropl":
  154. picture.crop_left = Twips2Pixels(parser.Number);
  155. break;
  156. case "piccropb":
  157. picture.crop_bottom = Twips2Pixels(parser.Number);
  158. break;
  159. case "piccropr":
  160. picture.crop_right = Twips2Pixels(parser.Number);
  161. break;
  162. case "picprop":
  163. picture.picprop = true;
  164. break;
  165. case "picwgoal":
  166. case "picwGoal":
  167. picture.desired_width = (int)parser.Number;
  168. break;
  169. case "pichgoal":
  170. case "pichGoal":
  171. picture.desired_height = (int)parser.Number;
  172. break;
  173. case "wmetafile":
  174. state = State.BlipMetafile;
  175. metamapmode = parser.Number;
  176. break;
  177. case "emfblip":
  178. state = State.BlipMetafile;
  179. metamapmode = parser.Number;
  180. break;
  181. case "bliptag":
  182. picture.tag = (int)parser.Number;
  183. break;
  184. case "blipupi":
  185. picture.units_per_inch = (int)parser.Number;
  186. break;
  187. case "blipuid":
  188. ;
  189. break;
  190. case "":
  191. if (parser.Status == ParserStatus.CloseBlock)
  192. {
  193. if (parser.Text.Length != 0)
  194. {
  195. if (subdata_counter <= 0)
  196. return ParseBlip(parser, header);
  197. }
  198. }
  199. break;
  200. case "sp":
  201. // Word-2007 shape property
  202. break;
  203. case "sn":
  204. // Word-2007 shape property name
  205. break;
  206. case "sv":
  207. // Word-2007 shape property value
  208. break;
  209. default:
  210. #if DEBUG_RTF
  211. throw new NotImplementedException(parser.Control);
  212. #else
  213. break;
  214. #endif
  215. }
  216. return true;
  217. }
  218. }
  219. }