RTF_Picture.cs 7.8 KB

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