RTFExport.cs 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Drawing;
  5. using System.IO;
  6. using FastReport.Utils;
  7. using FastReport.RichTextParser;
  8. using System.Globalization;
  9. namespace FastReport.Export.RichText
  10. {
  11. /// <summary>
  12. /// Specifies the image format in RTF export.
  13. /// </summary>
  14. public enum RTFImageFormat
  15. {
  16. /// <summary>
  17. /// Specifies the .png format.
  18. /// </summary>
  19. Png,
  20. /// <summary>
  21. /// Specifies the .jpg format.
  22. /// </summary>
  23. Jpeg,
  24. /// <summary>
  25. /// Specifies the .emf format.
  26. /// </summary>
  27. Metafile
  28. }
  29. /// <summary>
  30. /// Represents the RTF export filter.
  31. /// </summary>
  32. public partial class RTFExport : ExportBase
  33. {
  34. #region Constants
  35. const float Xdivider = 15.05F;
  36. const float Ydivider1 = 14.8F;
  37. const float Ydivider2 = 14.8F;
  38. const float Ydivider3 = 14.7F;
  39. const float MargDivider = 56.904405f; // 3.793627f * 15 | PxInMm * TwipsInPX
  40. const float FONT_DIVIDER = 15F;
  41. const float IMAGE_DIVIDER = 25.3F;
  42. const int PIC_BUFF_SIZE = 512;
  43. #endregion
  44. #region Private fields
  45. private List<string> colorTable;
  46. private bool pageBreaks;
  47. private List<string> fontTable;
  48. private ExportMatrix matrix;
  49. private bool wysiwyg;
  50. private bool printOptimized;
  51. private string creator;
  52. private bool autoSize;
  53. private MyRes res;
  54. private RTFImageFormat imageFormat;
  55. private bool pictures;
  56. private string tempFile;
  57. private int jpegQuality;
  58. private float dpiFactor;
  59. private float yDiv;
  60. private Color textColor;
  61. private bool keepRichText;
  62. private CultureInfo localization;
  63. private bool exportLocale;
  64. #endregion
  65. #region Properties
  66. /// <summary>
  67. /// Gets or sets the quality of Jpeg images in RTF file.
  68. /// </summary>
  69. /// <remarks>
  70. /// Default value is 90. This property will be used if you select Jpeg
  71. /// in the <see cref="ImageFormat"/> property.
  72. /// </remarks>
  73. public int JpegQuality
  74. {
  75. get { return jpegQuality; }
  76. set { jpegQuality = value; }
  77. }
  78. /// <summary>
  79. /// Gets or sets the image format that will be used to save pictures in RTF file.
  80. /// </summary>
  81. /// <remarks>
  82. /// Default value is <b>Metafile</b>. This format is better for exporting such objects as
  83. /// <b>MSChartObject</b> and <b>ShapeObject</b>.
  84. /// </remarks>
  85. public RTFImageFormat ImageFormat
  86. {
  87. get { return imageFormat; }
  88. set { imageFormat = value; }
  89. }
  90. /// <summary>
  91. /// Gets or sets a value indicating that pictures are enabled.
  92. /// </summary>
  93. public bool Pictures
  94. {
  95. get { return pictures; }
  96. set { pictures = value; }
  97. }
  98. /// <summary>
  99. /// Gets or sets a value indicating that page breaks are enabled.
  100. /// </summary>
  101. public bool PageBreaks
  102. {
  103. get { return pageBreaks; }
  104. set { pageBreaks = value; }
  105. }
  106. /// <summary>
  107. /// Get or set a locale for all document.
  108. /// </summary>
  109. public CultureInfo Locale
  110. {
  111. get { return localization; }
  112. set { localization = value; }
  113. }
  114. /// <summary>
  115. /// Gets or sets a value indicating that locale export are enabled.
  116. /// </summary>
  117. public bool ExportLocale
  118. {
  119. get { return exportLocale; }
  120. set { exportLocale = value; }
  121. }
  122. /// <summary>
  123. /// Gets or sets a value that determines whether the wysiwyg mode should be used
  124. /// for better results.
  125. /// </summary>
  126. /// <remarks>
  127. /// Default value is <b>true</b>. In wysiwyg mode, the resulting rtf file will look
  128. /// as close as possible to the prepared report. On the other side, it may have a lot
  129. /// of small rows/columns, which will make it less editable. If you set this property
  130. /// to <b>false</b>, the number of rows/columns in the resulting file will be decreased.
  131. /// You will get less wysiwyg, but more editable file.
  132. /// </remarks>
  133. public bool Wysiwyg
  134. {
  135. get { return wysiwyg; }
  136. set { wysiwyg = value; }
  137. }
  138. /// <summary>
  139. /// Gets or sets the PrintOptimized.
  140. /// </summary>
  141. public bool PrintOptimized
  142. {
  143. get { return printOptimized; }
  144. set { printOptimized = value; }
  145. }
  146. /// <summary>
  147. /// Gets or sets the creator of the document.
  148. /// </summary>
  149. public string Creator
  150. {
  151. get { return creator; }
  152. set { creator = value; }
  153. }
  154. /// <summary>
  155. /// Gets or sets a value that determines whether the rows in the resulting table
  156. /// should calculate its height automatically.
  157. /// </summary>
  158. /// <remarks>
  159. /// Default value for this property is <b>false</b>. In this mode, each row in the
  160. /// resulting table has fixed height to get maximum wysiwyg. If you set it to <b>true</b>,
  161. /// the height of resulting table will be calculated automatically by the Word processor.
  162. /// The document will be more editable, but less wysiwyg.
  163. /// </remarks>
  164. public bool AutoSize
  165. {
  166. get { return autoSize; }
  167. set { autoSize = value; }
  168. }
  169. /// <summary>
  170. /// Gets or sets a value that determines whether the repot's RichObject will be
  171. /// translated as picture or joined to generated RTF.
  172. /// </summary>
  173. /// <remarks>
  174. /// Default value for this property is <b>false</b>. In this mode, each RichObject
  175. /// will be embedded as a picture. This is default behavior. If you set it to <b>true</b>,
  176. /// the RichObject will be incorporated as a navive part of document. This is experimetal
  177. /// feature.
  178. /// </remarks>
  179. public bool EmbedRichObject
  180. {
  181. get { return keepRichText; }
  182. set { keepRichText = value; }
  183. }
  184. #endregion
  185. #region Private Methods
  186. private string GetRTFBorders(ExportIEMStyle Style)
  187. {
  188. //// +debug
  189. //Style.Border.Lines = BorderLines.All;
  190. //Style.Border.Width = 1;
  191. //// -debug
  192. StringBuilder result = new StringBuilder(256);
  193. // top
  194. if ((Style.Border.Lines & BorderLines.Top) > 0)
  195. result.Append("\\clbrdrt").
  196. Append(GetRTFLineStyle(Style.Border.TopLine.Style)).
  197. Append("\\brdrw").
  198. Append(((int)Math.Round(Style.Border.TopLine.Width * 20)).ToString()).
  199. Append("\\brdrcf").
  200. Append(GetRTFColorFromTable(GetRTFColor(Style.Border.TopLine.Color)));
  201. // left
  202. if ((Style.Border.Lines & BorderLines.Left) > 0)
  203. result.Append("\\clbrdrl").
  204. Append(GetRTFLineStyle(Style.Border.LeftLine.Style)).
  205. Append("\\brdrw").
  206. Append(((int)Math.Round(Style.Border.LeftLine.Width * 20)).ToString()).
  207. Append("\\brdrcf").
  208. Append(GetRTFColorFromTable(GetRTFColor(Style.Border.LeftLine.Color)));
  209. // bottom
  210. if ((Style.Border.Lines & BorderLines.Bottom) > 0)
  211. result.Append("\\clbrdrb").
  212. Append(GetRTFLineStyle(Style.Border.BottomLine.Style)).
  213. Append("\\brdrw").
  214. Append(((int)Math.Round(Style.Border.BottomLine.Width * 20)).ToString()).
  215. Append("\\brdrcf").
  216. Append(GetRTFColorFromTable(GetRTFColor(Style.Border.BottomLine.Color)));
  217. // right
  218. if ((Style.Border.Lines & BorderLines.Right) > 0)
  219. result.Append("\\clbrdrr").
  220. Append(GetRTFLineStyle(Style.Border.RightLine.Style)).
  221. Append("\\brdrw").
  222. Append(((int)Math.Round(Style.Border.RightLine.Width * 20)).ToString()).
  223. Append("\\brdrcf").
  224. Append(GetRTFColorFromTable(GetRTFColor(Style.Border.RightLine.Color)));
  225. return result.ToString();
  226. }
  227. private string GetRTFLineStyle(LineStyle lineStyle)
  228. {
  229. switch (lineStyle)
  230. {
  231. case LineStyle.Dash:
  232. return "\\brdrdash";
  233. case LineStyle.DashDot:
  234. return "\\brdrdashd";
  235. case LineStyle.DashDotDot:
  236. return "\\brdrdashdd";
  237. case LineStyle.Dot:
  238. return "\\brdrdot";
  239. case LineStyle.Double:
  240. return "\\brdrdb";
  241. default:
  242. return "\\brdrs";
  243. }
  244. }
  245. private string GetRTFColor(Color c)
  246. {
  247. StringBuilder result = new StringBuilder(64);
  248. result.Append("\\red").Append(Convert.ToString(c.R)).
  249. Append("\\green").Append(Convert.ToString(c.G)).
  250. Append("\\blue").Append(Convert.ToString(c.B)).Append(";");
  251. return result.ToString();
  252. }
  253. private string GetRTFFontStyle(FontStyle f)
  254. {
  255. StringBuilder result = new StringBuilder(8);
  256. if ((f & FontStyle.Italic) != 0)
  257. result.Append("\\i");
  258. if ((f & FontStyle.Bold) != 0)
  259. result.Append("\\b");
  260. if ((f & FontStyle.Underline) != 0)
  261. result.Append("\\ul");
  262. return result.ToString();
  263. }
  264. private string GetRTFColorFromTable(string f)
  265. {
  266. string Result;
  267. int i = colorTable.IndexOf(f);
  268. if (i != -1)
  269. Result = (i + 1).ToString();
  270. else
  271. {
  272. colorTable.Add(f);
  273. Result = colorTable.Count.ToString();
  274. }
  275. return Result;
  276. }
  277. private string GetRTFFontName(string f)
  278. {
  279. string Result;
  280. int i = fontTable.IndexOf(f);
  281. if (i != -1)
  282. Result = (i).ToString();
  283. else
  284. {
  285. fontTable.Add(f);
  286. Result = (fontTable.Count - 1).ToString();
  287. }
  288. return Result;
  289. }
  290. private string GetRTFHAlignment(HorzAlign HAlign)
  291. {
  292. switch (HAlign)
  293. {
  294. case HorzAlign.Right:
  295. return "\\qr";
  296. case HorzAlign.Center:
  297. return "\\qc";
  298. case HorzAlign.Justify:
  299. return "\\qj";
  300. default:
  301. return "\\ql";
  302. }
  303. }
  304. private string GetRTFVAlignment(VertAlign VAlign)
  305. {
  306. switch (VAlign)
  307. {
  308. case VertAlign.Top:
  309. return "\\clvertalt";
  310. case VertAlign.Center:
  311. return "\\clvertalc";
  312. default:
  313. return "\\clvertalb";
  314. }
  315. }
  316. private string StrToRTFSlash(string Value)
  317. {
  318. StringBuilder Result = new StringBuilder();
  319. for (int i = 0; i < Value.Length; i++)
  320. {
  321. if (Value[i] == '\\')
  322. Result.Append("\\\\");
  323. else if (Value[i] == '{')
  324. Result.Append("\\{");
  325. else if (Value[i] == '}')
  326. Result.Append("\\}");
  327. else if ((Value[i] == '\r') && (i < (Value.Length - 1)) && (Value[i + 1] == '\n'))
  328. {
  329. Result.Append("\\line\r\n");
  330. i++;
  331. }
  332. else
  333. Result.Append(Value[i]);
  334. }
  335. return Result.ToString();
  336. }
  337. private string ParseHtmlTags(string s)
  338. {
  339. int Index = 0;
  340. int Begin = 0;
  341. int End = 0;
  342. string Tag;
  343. string Text;
  344. string result;
  345. string TagClose = "";
  346. CurrentStyle current_style = new CurrentStyle();
  347. CurrentStyle previos_style;
  348. current_style.Size = 10;
  349. current_style.Bold = false;
  350. current_style.Italic = false;
  351. current_style.Underline = false;
  352. current_style.Colour = Color.FromName("Black");
  353. current_style.Strike = false;
  354. current_style.Sub = false;
  355. current_style.Sup = false;
  356. Stack<CurrentStyle> style_stack = new Stack<CurrentStyle>();
  357. Begin = s.IndexOfAny(new char[1] { '<' }, Index);
  358. if (Begin == -1) result = s;
  359. else
  360. {
  361. result = "";
  362. while (Begin != -1)
  363. {
  364. if (Begin != 0 && Index == 0)
  365. {
  366. if (Index == 0)
  367. {
  368. result += s.Substring(Index, Begin);
  369. }
  370. }
  371. End = s.IndexOfAny(new char[1] { '>' }, Begin + 1);
  372. if (End == -1) break;
  373. Tag = s.Substring(Begin + 1, End - Begin - 1);
  374. bool CloseTag = Tag.StartsWith("/");
  375. if (CloseTag) Tag = Tag.Remove(0, 1);
  376. string[] items = Tag.Split(' ');
  377. Tag = items[0].ToUpper();
  378. TagClose = "";
  379. bool PutOnStack = true;
  380. if (!CloseTag)
  381. {
  382. current_style.LastTag = Tag;
  383. switch (Tag)
  384. {
  385. case "B":
  386. current_style.Bold = true;
  387. TagClose = "\\b ";
  388. break;
  389. case "I":
  390. current_style.Italic = true;
  391. TagClose = "\\i ";
  392. break;
  393. case "U":
  394. current_style.Underline = true;
  395. TagClose = "\\ul ";
  396. break;
  397. case "STRIKE":
  398. current_style.Strike = true;
  399. TagClose = "\\strike ";
  400. break;
  401. case "SUB":
  402. current_style.Sub = true;
  403. TagClose = "\\sub ";
  404. break;
  405. case "SUP":
  406. current_style.Sup = true;
  407. TagClose = "\\super ";
  408. break;
  409. case "BR":
  410. current_style.Sup = true;
  411. TagClose = "\\line ";
  412. break;
  413. case "FONT":
  414. {
  415. if (items.Length > 1)
  416. {
  417. string[] attrs = items[1].Split('=');
  418. if (attrs[0] == "color")
  419. {
  420. TagClose = "\\cf" + GetRTFColorFromTable(GetRTFColor(System.Drawing.ColorTranslator.FromHtml(attrs[1].Replace("\"", "")))) + " ";
  421. }
  422. }
  423. }
  424. /*current_style.Font = items[1];*/
  425. // ParseFont(items[1], current_style, out current_style);
  426. break;
  427. default:
  428. TagClose = Tag;
  429. PutOnStack = false;
  430. break;
  431. }
  432. if (PutOnStack) style_stack.Push(current_style);
  433. }
  434. else
  435. {
  436. if (style_stack.Count > 0)
  437. {
  438. previos_style = style_stack.Pop();
  439. #if false
  440. if (previos_style.LastTag != Tag)
  441. {
  442. throw new Exception("Unaligned HTML TAGS");
  443. }
  444. #endif
  445. switch (Tag)
  446. {
  447. case "B": TagClose = "\\b0 "; break;
  448. case "I": TagClose = "\\i0 "; break;
  449. case "U": TagClose = "\\ul0 "; break;
  450. case "STRIKE": TagClose = "\\strike0 "; break;
  451. case "SUB": TagClose = "\\nosupersub "; break;
  452. case "SUP": TagClose = "\\nosupersub "; break;
  453. case "FONT":
  454. TagClose = "\\cf" + GetRTFColorFromTable(GetRTFColor((textColor))) + " ";
  455. /*current_style.Font = items[1];*/
  456. // ParseFont(items[1], current_style, out current_style);
  457. break;
  458. default:
  459. throw new Exception("Unsupported HTML TAG");
  460. }
  461. current_style = previos_style;
  462. }
  463. }
  464. Index = End + 1;
  465. Begin = s.IndexOfAny(new char[1] { '<' }, Index);
  466. if (Begin == -1)
  467. {
  468. Text = s.Substring(Index);
  469. }
  470. else
  471. {
  472. Text = s.Substring(Index, Begin - Index);
  473. }
  474. result += TagClose + Text;
  475. }
  476. }
  477. return result;
  478. }
  479. private string StrToRTFUnicodeEx(string Value, TextRenderType textRenderType)
  480. {
  481. Value = StrToRTFUnicode(StrToRTFSlash(Value));
  482. switch (textRenderType)
  483. {
  484. case TextRenderType.HtmlParagraph:
  485. //TODO DETRAV RTF
  486. break;
  487. case TextRenderType.HtmlTags:
  488. Value = ParseHtmlTags(Value);
  489. break;
  490. }
  491. return Value;
  492. }
  493. private string StrToRTFUnicode(string Value)
  494. {
  495. StringBuilder Result = new StringBuilder(128);
  496. foreach (UInt16 c in Value)
  497. {
  498. if (c > 127)
  499. Result.Append("\\u").Append(c.ToString()).Append("\\'3f");
  500. else
  501. Result.Append((char)c);
  502. }
  503. return Result.ToString();
  504. }
  505. private void Prepare()
  506. {
  507. int i;
  508. ExportIEMObject Obj;
  509. for (int y = 0; y < matrix.Height; y++)
  510. for (int x = 0; x < matrix.Width; x++)
  511. {
  512. i = matrix.Cell(x, y);
  513. if (i != -1)
  514. {
  515. Obj = matrix.ObjectById(i);
  516. if (Obj.Counter != -1)
  517. {
  518. Obj.Counter = -1;
  519. if (Obj.Style != null)
  520. {
  521. GetRTFColorFromTable(GetRTFColor(Obj.Style.FillColor));
  522. GetRTFColorFromTable(GetRTFColor(Obj.Style.Border.LeftLine.Color));
  523. GetRTFColorFromTable(GetRTFColor(Obj.Style.Border.RightLine.Color));
  524. GetRTFColorFromTable(GetRTFColor(Obj.Style.Border.TopLine.Color));
  525. GetRTFColorFromTable(GetRTFColor(Obj.Style.Border.BottomLine.Color));
  526. GetRTFColorFromTable(GetRTFColor(Obj.Style.TextColor));
  527. GetRTFFontName(Obj.Style.Font.Name);
  528. }
  529. }
  530. }
  531. }
  532. }
  533. private string SetPageProp(int Page)
  534. {
  535. StringBuilder result = new StringBuilder(64);
  536. result.Append("\\pgwsxn").
  537. Append(((int)Math.Round(matrix.PageWidth(Page) * MargDivider)).ToString()).
  538. Append("\\pghsxn").
  539. Append(((int)Math.Round(matrix.PageHeight(Page) * MargDivider)).ToString()).
  540. Append("\\marglsxn").
  541. Append(((int)Math.Round(matrix.PageLMargin(Page) * MargDivider)).ToString()).
  542. Append("\\margrsxn").
  543. Append(((int)Math.Round(matrix.PageRMargin(Page) * MargDivider)).ToString()).
  544. Append("\\margtsxn").
  545. Append(((int)Math.Round(matrix.PageTMargin(Page) * MargDivider)).ToString()).
  546. Append("\\margbsxn").
  547. Append(((int)Math.Round(matrix.PageBMargin(Page) * MargDivider)).ToString()).
  548. Append(matrix.Landscape(Page) ? "\\lndscpsxn" : String.Empty);
  549. return result.ToString();
  550. }
  551. private void Write(Stream stream, string str)
  552. {
  553. byte[] buff = Converter.StringToByteArray(str);
  554. stream.Write(buff, 0, buff.Length);
  555. }
  556. private void WriteLine(Stream stream, string str)
  557. {
  558. Write(stream, str);
  559. Write(stream, "\r\n");
  560. }
  561. private Stream GetTempFileStream()
  562. {
  563. tempFile = Path.Combine(Config.GetTempFolder(), Path.GetRandomFileName());
  564. return new FileStream(tempFile, FileMode.Create);
  565. }
  566. private void DeleteTempFile()
  567. {
  568. if (File.Exists(tempFile))
  569. File.Delete(tempFile);
  570. }
  571. private string GetRTFString(ExportIEMObject obj, float drow)
  572. {
  573. ExportIEMStyle style = obj.Style;
  574. string text = obj.Text;
  575. TextRenderType textRenderType = obj.TextRenderType;
  576. StringBuilder CellsStream = new StringBuilder();
  577. CellsStream.Append(GetRTFHAlignment(style.HAlign));
  578. if (!String.IsNullOrEmpty(obj.URL))
  579. {
  580. CellsStream.Append("{\\field{\\*\\fldinst HYPERLINK \"" + obj.URL + "\"}{\\fldrslt");
  581. }
  582. else
  583. {
  584. CellsStream.Append("{");
  585. }
  586. CellsStream.Append("\\f").Append(GetRTFFontName(style.Font.Name));
  587. string s = StrToRTFUnicodeEx(ExportUtils.TruncReturns(text), textRenderType);
  588. double fh = style.Font.Height * dpiFactor * yDiv * 0.98;
  589. double lh = style.LineHeight * 8.0;
  590. if (s.Length > 0)
  591. {
  592. CellsStream.Append("\\fs").Append((Math.Round(style.Font.Size * 2)).ToString());
  593. CellsStream.Append(GetRTFFontStyle(style.Font.Style)).Append("\\cf");
  594. CellsStream.Append(GetRTFColorFromTable(GetRTFColor((style.TextColor))));
  595. CellsStream.Append(style.RTL ? "\\rtlch" : String.Empty);
  596. CellsStream.Append("\\sb").
  597. Append(((int)Math.Round(style.Padding.Top * yDiv)).ToString()).
  598. Append("\\sa").
  599. Append(((int)Math.Round(style.Padding.Bottom * yDiv)).ToString()).
  600. Append("\\li").
  601. Append(((int)Math.Round((style.Padding.Left) * Xdivider)).ToString()).
  602. Append("\\ri").
  603. Append(((int)Math.Round((style.Padding.Right) * Xdivider)).ToString()).
  604. Append("\\sl-").
  605. Append(((int)Math.Round((fh + lh))).ToString()).
  606. Append("\\slmult0 ");
  607. if (s.StartsWith("\t") && style.FirstTabOffset != 0)
  608. {
  609. // replace first tab symbol with \\fi
  610. s = "\\fi" + ((int)Math.Round((style.FirstTabOffset) * Xdivider)).ToString() + " " + s.Remove(0, 1);
  611. // convert multiline text to rtf paragraphs. \\fi can be applied to a paragraph only
  612. s = s.Replace("\\line\r\n\t", "\\par ");
  613. }
  614. CellsStream.Append(s);
  615. }
  616. else
  617. {
  618. int j = (int)(drow / FONT_DIVIDER);
  619. j = j > 20 ? 20 : j;
  620. CellsStream.Append("\\fs").Append(j.ToString());
  621. }
  622. if (!String.IsNullOrEmpty(obj.URL))
  623. {
  624. CellsStream.Append("}");
  625. }
  626. CellsStream.Append("\\cell}");
  627. return CellsStream.ToString();
  628. }
  629. private string GetRTFMetafile(ExportIEMObject Obj)
  630. {
  631. byte[] picbuff = new Byte[PIC_BUFF_SIZE];
  632. string scale = ((int)(100 / dpiFactor)).ToString();
  633. StringBuilder CellsStream = new StringBuilder(256);
  634. if (!String.IsNullOrEmpty(Obj.URL))
  635. {
  636. CellsStream.Append("{\\field{\\*\\fldinst HYPERLINK \"" + Obj.URL + "\"}{\\fldrslt");
  637. }
  638. else
  639. {
  640. CellsStream.Append("{");
  641. }
  642. Obj.PictureStream.Position = 0;
  643. if (pictures && Config.FullTrust && (imageFormat == RTFImageFormat.Metafile))
  644. {
  645. scale = (int.Parse(scale) * dpiFactor).ToString();
  646. CellsStream.Append("\\sb0\\li0\\sl0\\slmult0\\qc\\clvertalc {");
  647. float dx = Obj.Width * 15;
  648. float dy = Obj.Height * 15;
  649. CellsStream.Append("\\pict\\picw").Append(dx.ToString());
  650. CellsStream.Append("\\pich").Append(dy.ToString());
  651. CellsStream.Append("\\picscalex").Append(scale);
  652. CellsStream.Append("\\picscaley").Append(scale);
  653. CellsStream.Append("\\picwGoal").Append(Convert.ToString(dx));
  654. CellsStream.Append("\\pichGoal").Append(Convert.ToString(dy));
  655. CellsStream.Append("\\emfblip\r\n");
  656. int n;
  657. do
  658. {
  659. n = Obj.PictureStream.Read(picbuff, 0, PIC_BUFF_SIZE);
  660. for (int z = 0; z < n; z++)
  661. {
  662. CellsStream.Append(ExportUtils.XCONV[picbuff[z] >> 4]);
  663. CellsStream.Append(ExportUtils.XCONV[picbuff[z] & 0xF]);
  664. }
  665. CellsStream.Append("\r\n");
  666. }
  667. while (n == PIC_BUFF_SIZE);
  668. CellsStream.Append("}");
  669. }
  670. else if (pictures && (imageFormat != RTFImageFormat.Metafile))
  671. {
  672. CellsStream.Append("\\sb0\\li0\\sl0\\slmult0\\qc\\clvertalc {");
  673. float dx = (int)Obj.Width;
  674. float dy = (int)Obj.Height;
  675. CellsStream.Append("\\pict\\picw").Append(dx.ToString());
  676. CellsStream.Append("\\pich").Append(dy.ToString());
  677. CellsStream.Append("\\picscalex").Append(scale);
  678. CellsStream.Append("\\picscaley").Append(scale);
  679. CellsStream.Append("\\");
  680. CellsStream.Append(imageFormat == RTFImageFormat.Jpeg ? "jpegblip\r\n" : "pngblip\r\n");
  681. int n;
  682. do
  683. {
  684. n = Obj.PictureStream.Read(picbuff, 0, PIC_BUFF_SIZE);
  685. for (int z = 0; z < n; z++)
  686. {
  687. CellsStream.Append(ExportUtils.XCONV[picbuff[z] >> 4]);
  688. CellsStream.Append(ExportUtils.XCONV[picbuff[z] & 0xF]);
  689. }
  690. CellsStream.Append("\r\n");
  691. }
  692. while (n == PIC_BUFF_SIZE);
  693. CellsStream.Append("}");
  694. }
  695. if (!String.IsNullOrEmpty(Obj.URL))
  696. {
  697. CellsStream.Append("}");
  698. }
  699. CellsStream.Append("\\cell}\r\n");
  700. return CellsStream.ToString();
  701. }
  702. private string GetRTFHeader()
  703. {
  704. StringBuilder sb = new StringBuilder();
  705. sb.Append("{\\rtf1\\ansi");
  706. sb.Append("{\\fonttbl");
  707. for (int i = 0; i < fontTable.Count; i++)
  708. sb.Append("{\\f" + Convert.ToString(i) + " " + fontTable[i] + "}");
  709. sb.Append("}");
  710. sb.Append("{\\colortbl;");
  711. for (int i = 0; i < colorTable.Count; i++)
  712. sb.Append(colorTable[i]);
  713. sb.Append("}");
  714. return sb.ToString();
  715. }
  716. private string GetRTFMetaInfo()
  717. {
  718. StringBuilder buf = new StringBuilder(256);
  719. buf.Append("{\\info{\\title ").Append(StrToRTFUnicodeEx(Report.ReportInfo.Name, TextRenderType.Default)).
  720. Append("}{\\author ").Append(StrToRTFUnicodeEx(creator, TextRenderType.Default)).
  721. Append("}{\\creatim\\yr").Append(String.Format("{0:yyyy}", SystemFake.DateTime.Now)).
  722. Append("\\mo").Append(String.Format("{0:MM}", SystemFake.DateTime.Now)).
  723. Append("\\dy").Append(String.Format("{0:dd}", SystemFake.DateTime.Now)).
  724. Append("\\hr").Append(String.Format("{0:HH}", SystemFake.DateTime.Now)).
  725. Append("\\min").Append(String.Format("{0:mm}", SystemFake.DateTime.Now)).AppendLine("}}");
  726. return buf.ToString();
  727. }
  728. struct CurrentStyle
  729. {
  730. public int Size;
  731. public bool Bold;
  732. public bool Italic;
  733. public bool Underline;
  734. public bool Strike;
  735. public bool Sub;
  736. public bool Sup;
  737. public Color Colour;
  738. public string LastTag;
  739. };
  740. #region Export RichObject to RTF
  741. private RichDocument rtf;
  742. private RunFormat current_format;
  743. private RichTextParser.ParagraphFormat.HorizontalAlign prev_align = RichTextParser.ParagraphFormat.HorizontalAlign.Left;
  744. private string HorizontalAlignCode(RichTextParser.ParagraphFormat.HorizontalAlign align)
  745. {
  746. switch (align)
  747. {
  748. case RichTextParser.ParagraphFormat.HorizontalAlign.Centered: return "\\qc";
  749. case RichTextParser.ParagraphFormat.HorizontalAlign.Left: return "\\ql";
  750. case RichTextParser.ParagraphFormat.HorizontalAlign.Right: return "\\qr";
  751. case RichTextParser.ParagraphFormat.HorizontalAlign.Justified: return "\\qj";
  752. case RichTextParser.ParagraphFormat.HorizontalAlign.Distributed: return "\\qd";
  753. case RichTextParser.ParagraphFormat.HorizontalAlign.Kashida: return "\\qk";
  754. case RichTextParser.ParagraphFormat.HorizontalAlign.Thai: return "\\qt";
  755. default: return "";
  756. }
  757. }
  758. private string VerticalAlignCode(Column.VertAlign valign)
  759. {
  760. switch (valign)
  761. {
  762. case Column.VertAlign.Top: return "\\clvertalt";
  763. case Column.VertAlign.Center: return "\\clvertalc";
  764. case Column.VertAlign.Bottom: return "\\clvertalb";
  765. default: return "";
  766. }
  767. }
  768. private void SavePargraph(StringBuilder s, RichTextParser.Paragraph par, bool InTable, float Left)
  769. {
  770. char lineBreakSumb = ' ';
  771. bool skipSpace = false;
  772. if (par.runs.Count == 0)
  773. {
  774. if (!InTable)
  775. s.Append("\\pard\\par\n");
  776. else
  777. s.Append("\\pard\\intbl\\cell\n");
  778. }
  779. else
  780. {
  781. if (InTable)
  782. s.Append("\\intbl\n");
  783. if (par.format.align != prev_align)
  784. {
  785. s.AppendFormat("{0} ", HorizontalAlignCode(par.format.align));
  786. prev_align = par.format.align;
  787. }
  788. // add tab stops with taking into consideration left padding of object
  789. if (par.format.tab_positions != null && par.format.tab_positions.Count > 0)
  790. {
  791. foreach (float tab in par.format.tab_positions)
  792. s.Append($"\\tx{Math.Round(tab + Left * Xdivider)}");
  793. }
  794. foreach (Run r in par.runs)
  795. {
  796. RunFormat fmt = r.format;
  797. if (current_format.bold != fmt.bold)
  798. {
  799. s.Append(fmt.bold ? "\\b" : "\\b0");
  800. current_format.bold = fmt.bold;
  801. }
  802. if (current_format.strike != fmt.strike)
  803. {
  804. s.Append(fmt.strike ? "\\strike" : "\\strike0");
  805. current_format.strike = fmt.strike;
  806. }
  807. if (current_format.underline != fmt.underline)
  808. {
  809. s.Append(fmt.underline ? "\\ul" : "\\ulnone");
  810. current_format.underline = fmt.underline;
  811. }
  812. if (current_format.italic != fmt.italic)
  813. {
  814. s.Append(fmt.italic ? "\\i" : "\\i0");
  815. current_format.italic = fmt.italic;
  816. }
  817. if (current_format.color.ToArgb() != fmt.color.ToArgb())
  818. {
  819. string color_def = GetRTFColor(fmt.color);
  820. int i = colorTable.IndexOf(color_def);
  821. if (i != -1)
  822. {
  823. s.AppendFormat("\\cf{0}", i + 1);
  824. }
  825. else
  826. {
  827. colorTable.Add(color_def);
  828. s.AppendFormat("\\cf{0}", colorTable.Count);
  829. }
  830. current_format.color = fmt.color;
  831. }
  832. if (current_format.font_size != fmt.font_size)
  833. {
  834. s.AppendFormat("\\fs{0}", fmt.font_size);
  835. current_format.font_size = fmt.font_size;
  836. }
  837. if (current_format.font_idx != fmt.font_idx)
  838. {
  839. string font_name = rtf.font_list[(int)fmt.font_idx].FontName;
  840. int i = fontTable.IndexOf(font_name);
  841. if (i != -1)
  842. {
  843. s.AppendFormat("\\f{0}", i);
  844. }
  845. else
  846. {
  847. fontTable.Add(font_name);
  848. s.AppendFormat("\\f{0}", (fontTable.Count - 1));
  849. }
  850. current_format.font_idx = fmt.font_idx;
  851. }
  852. // avoid line break second symbol \r\n
  853. if ((r.text == "\r" || r.text == "\n") && (lineBreakSumb == r.text[0] || lineBreakSumb == ' '))
  854. {
  855. s.Append("\\par ");
  856. lineBreakSumb = r.text[0];
  857. skipSpace = true;
  858. }
  859. else if (r.text == "\t")
  860. {
  861. s.Append("\\tab ");
  862. skipSpace = true;
  863. }
  864. else
  865. {
  866. if (!skipSpace)
  867. s.Append(" ");
  868. s.Append(StrToRTFUnicode(r.text));
  869. skipSpace = false;
  870. }
  871. }
  872. if (!InTable)
  873. s.Append("\\par\n");
  874. else
  875. s.Append("\\cell\n");
  876. }
  877. }
  878. private void SaveColumn(StringBuilder s, Column col)
  879. {
  880. // "clcbpat" - background color
  881. s.AppendFormat("{0}\\cellx{1}", VerticalAlignCode(col.valign), col.Width);
  882. }
  883. private void SaveRow(StringBuilder s, TableRow row, bool InTable)
  884. {
  885. s.AppendFormat("\\trgaph{0}\\trrh{1}\\trpaddl{2}\\trpaddr{3}",
  886. row.trgaph, row.height, row.default_pad_left, row.default_pad_right);
  887. foreach (RichObjectSequence seq in row.cells)
  888. {
  889. SaveSequence(s, seq, true, 0f);
  890. if (!InTable)
  891. s.AppendLine("\\cell");
  892. else
  893. s.AppendLine("\\nestcell");
  894. }
  895. if (!InTable)
  896. s.Append("\\row");
  897. else
  898. s.Append("\\nestrow");
  899. }
  900. private void SaveTable(StringBuilder s, RichTextParser.Table tbl, bool InTable)
  901. {
  902. s.Append("\\trowd");
  903. foreach (Column col in tbl.columns)
  904. SaveColumn(s, col);
  905. foreach (TableRow row in tbl.rows)
  906. SaveRow(s, row, InTable);
  907. }
  908. private void SavePicture(StringBuilder CellsStream, Picture pic, bool InTable)
  909. {
  910. CellsStream.Append("\\sb0\\li0\\sl0\\slmult0\\qc\\clvertalc {");
  911. float dx = (int)pic.width;
  912. float dy = (int)pic.height;
  913. CellsStream.Append("\\pict\\picw").Append(dx.ToString());
  914. CellsStream.Append("\\pich").Append(dy.ToString());
  915. CellsStream.Append("\\picscalex").Append(pic.scalex);
  916. CellsStream.Append("\\picscaley").Append(pic.scaley);
  917. System.Drawing.Imaging.ImageFormat format;
  918. if (imageFormat == RTFImageFormat.Jpeg)
  919. {
  920. CellsStream.Append("\\jpegblip\r\n");
  921. format = System.Drawing.Imaging.ImageFormat.Jpeg;
  922. }
  923. else
  924. {
  925. CellsStream.Append("\\pngblip\r\n");
  926. format = System.Drawing.Imaging.ImageFormat.Png;
  927. }
  928. int n;
  929. byte[] picbuff = new Byte[PIC_BUFF_SIZE];
  930. MemoryStream pic_stream = new MemoryStream();
  931. pic.image.Save(pic_stream, format);
  932. pic_stream.Seek(0, SeekOrigin.Begin);
  933. do
  934. {
  935. n = pic_stream.Read(picbuff, 0, PIC_BUFF_SIZE);
  936. for (int z = 0; z < n; z++)
  937. {
  938. CellsStream.Append(ExportUtils.XCONV[picbuff[z] >> 4]);
  939. CellsStream.Append(ExportUtils.XCONV[picbuff[z] & 0xF]);
  940. }
  941. CellsStream.Append("\r\n");
  942. }
  943. while (n == PIC_BUFF_SIZE);
  944. CellsStream.Append("}");
  945. }
  946. private void SaveSequence(StringBuilder s, RichObjectSequence seq, bool InTable, float Left)
  947. {
  948. for (int i = 0; i < seq.objects.Count; i++)
  949. {
  950. if (!InTable && i == seq.objects.Count - 1)
  951. InTable = true;
  952. switch (seq.objects[i].type)
  953. {
  954. case RichTextParser.RichObject.Type.Paragraph:
  955. SavePargraph(s, seq.objects[i].paragraph, InTable, Left);
  956. break;
  957. case RichTextParser.RichObject.Type.Picture:
  958. SavePicture(s, seq.objects[i].picture, InTable);
  959. break;
  960. case RichTextParser.RichObject.Type.Table:
  961. SaveTable(s, seq.objects[i].table, InTable);
  962. break;
  963. }
  964. }
  965. }
  966. private void TranslateEmbeddedRTF(ExportIEMObject Obj, StringBuilder CellsStream)
  967. {
  968. current_format.color = Color.FromArgb(0, 0, 0, 0);
  969. current_format.BColor = Color.FromArgb(0, 0, 0, 0);
  970. current_format.FillColor = Color.FromArgb(0, 0, 0, 0);
  971. current_format.bold = false;
  972. current_format.strike = false;
  973. current_format.italic = false;
  974. current_format.underline = false;
  975. current_format.font_size = 0;
  976. current_format.font_idx = 65536;
  977. current_format.script_type = RunFormat.ScriptType.PlainText;
  978. using (RTF_DocumentParser parser = new RTF_DocumentParser())
  979. {
  980. parser.Load(Obj.Text);
  981. rtf = parser.Document;
  982. }
  983. foreach (Page page in rtf.pages)
  984. {
  985. CellsStream.AppendFormat(@"\margl{0}\margr{1}\margt{2}\margb{3}",
  986. 200, // page.margin_left,
  987. page.margin_right,
  988. 600, // page.margin_top,
  989. page.margin_bottom);
  990. CellsStream.Append($"\\li{Math.Round(Obj.Left * Xdivider)}");
  991. SaveSequence(CellsStream, page.sequence, false, Obj.Left);
  992. }
  993. }
  994. private void AddWatermark(Stream stream)
  995. {
  996. Watermark watermark = Report.PreparedPages.GetPage(0).Watermark;
  997. if (watermark.Text != "")
  998. {
  999. int OLEColor = watermark.TextObject.TextColor.R + (watermark.TextObject.TextColor.G * 256) + (watermark.TextObject.TextColor.B * 256 * 256);
  1000. double height = watermark.Font.SizeInPoints * 19;
  1001. double width = 0;
  1002. int rotation = 0;
  1003. bool needSwapHeigtAndWidth = false;
  1004. int countUpperLetter = 0;
  1005. foreach (var c in watermark.Text)
  1006. {
  1007. if (char.IsUpper(c))
  1008. countUpperLetter++;
  1009. }
  1010. width = (watermark.Text.Length - countUpperLetter) * (height / 2.5) + countUpperLetter * (height / 2 * 1.28);
  1011. switch (watermark.TextRotation)
  1012. {
  1013. case WatermarkTextRotation.Horizontal:
  1014. {
  1015. rotation = 0;
  1016. break;
  1017. }
  1018. case WatermarkTextRotation.Vertical:
  1019. {
  1020. rotation = -5900000;
  1021. needSwapHeigtAndWidth = true;
  1022. break;
  1023. }
  1024. case WatermarkTextRotation.ForwardDiagonal:
  1025. {
  1026. if (matrix.Landscape(1))
  1027. rotation = -2400000;
  1028. else
  1029. {
  1030. rotation = -3600000;
  1031. needSwapHeigtAndWidth = true;
  1032. }
  1033. break;
  1034. }
  1035. case WatermarkTextRotation.BackwardDiagonal:
  1036. {
  1037. if (!matrix.Landscape(1))
  1038. {
  1039. rotation = 3600000;
  1040. needSwapHeigtAndWidth = true;
  1041. }
  1042. else
  1043. rotation = 2250000;
  1044. break;
  1045. }
  1046. }
  1047. if (needSwapHeigtAndWidth)
  1048. {
  1049. double temp = height;
  1050. height = width;
  1051. width = temp;
  1052. }
  1053. Write(stream,
  1054. @"\headery0{\header\pard\plain\itap0\s0\aspalpha\aspnum\adjustright\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\afs24\ltrch\fs24{\rtlch\afs24\ltrch\fs2" + "\n" +
  1055. @"{\shp{\*\shpinst\shplid2051\shpleft0\shpright" + width + @"\shptop0\shpbottom" + height + @"\shpfhdr1\shpz2\shpfblwtxt0" + "\n" +
  1056. @"\shpbxmargin\shpbxignore\shpbymargin\shpbyignore\shpwr3\shpwrk0{\sp{\sn fLayoutInCell}" + "\n" +
  1057. @"{\sv 1}" + "\n" +
  1058. @"}" + "\n" +
  1059. @"{\sp{\sn rotation}" + "\n" +
  1060. @"{\sv " + rotation + @"}" + "\n" +
  1061. @"}" + "\n" +
  1062. @"{\sp{\sn fFlipH}" + "\n" +
  1063. @"{\sv 0}" + "\n" +
  1064. @"}" + "\n" +
  1065. @"{\sp{\sn fFlipV}" + "\n" +
  1066. @"{\sv 0}" + "\n" +
  1067. @"}" + "\n" +
  1068. @"{\sp{\sn gtextUNICODE}" + "\n" +
  1069. @"{\sv " + StrToRTFUnicodeEx(ExportUtils.TruncReturns(watermark.Text), TextRenderType.Default) + @"}" + "\n" +
  1070. @"}" + "\n" +
  1071. @"{\sp{\sn gtextSize}" + "\n" +
  1072. @"{\sv 123932160}" + "\n" +
  1073. @"}" + "\n" +
  1074. @"{\sp{\sn gtextFont}" + "\n" +
  1075. @"{\sv " + watermark.Font.Name + @"}" + "\n" +
  1076. @"}" + "\n" +
  1077. @"{\sp{\sn fGtext}" + "\n" +
  1078. @"{\sv 1}" + "\n" +
  1079. @"}" + "\n" +
  1080. @"{\sp{\sn fillColor}" + "\n" +
  1081. @"{\sv " + OLEColor + @"}" + "\n" +
  1082. @"}" + "\n" +
  1083. @"{\sp{\sn fillOpacity}" + "\n" +
  1084. @"{\sv 32768}" + "\n" +
  1085. @"}" + "\n" +
  1086. @"{\sp{\sn fFilled}" + "\n" +
  1087. @"{\sv 1}" + "\n" +
  1088. @"}" + "\n" +
  1089. @"{\sp{\sn fLine}" + "\n" +
  1090. @"{\sv 0}" + "\n" +
  1091. @"}" + "\n" +
  1092. @"{\sp{\sn wzName}" + "\n" +
  1093. @"{\sv PowerPlusWaterMarkObject100001}" + "\n" +
  1094. @"}" + "\n" +
  1095. @"{\sp{\sn posh}" + "\n" +
  1096. @"{\sv 2}" + "\n" +
  1097. @"}" + "\n" +
  1098. @"{\sp{\sn posrelh}" + "\n" +
  1099. @"{\sv 0}" + "\n" +
  1100. @"}" + "\n" +
  1101. @"{\sp{\sn posv}" + "\n" +
  1102. @"{\sv 2}" + "\n" +
  1103. @"}" + "\n" +
  1104. @"{\sp{\sn posrelv}" + "\n" +
  1105. @"{\sv 0}" + "\n" +
  1106. @"}" + "\n" +
  1107. @"{\sp{\sn shapeType}" + "\n" +
  1108. @"{\sv 136}" + "\n" +
  1109. @"}" + "\n" +
  1110. @"}" + "\n" +
  1111. @"{\shprslt\par\pard" + "\n" +
  1112. @"\par}" + "\n" +
  1113. @"}" + "\n" +
  1114. @"}" + "\n" +
  1115. @"{\rtlch\afs24\ltrch\fs24\par}" + "\n" +
  1116. @"}"
  1117. );
  1118. }
  1119. else if (watermark.Image != null)
  1120. {
  1121. byte[] buffer;
  1122. int pictureContrast = 60000;
  1123. int pictureBrightness = -20000;
  1124. using (var memStream = new MemoryStream())
  1125. {
  1126. watermark.Image.Save(memStream, watermark.PictureObject.ImageFormat);
  1127. buffer = memStream.ToArray();
  1128. }
  1129. string hex = BitConverter.ToString(buffer, 0).Replace("-", string.Empty);
  1130. string picture = @"{\sv{\pict\picscalex382\picscaley382\piccropl0\piccropr0\piccropt0\piccropb0";
  1131. float widthPic = (float)watermark.Image.Width / watermark.Image.HorizontalResolution;
  1132. float heightPic = (float)watermark.Image.Height / watermark.Image.VerticalResolution;
  1133. picture += @"\picw" + (int)(widthPic * 2540);
  1134. picture += @"\pich" + (int)(heightPic * 2540);
  1135. picture += @"\picwgoal" + (int)(widthPic * 1440);
  1136. picture += @"\pichgoal" + (int)(heightPic * 1440);
  1137. if (watermark.PictureObject.ImageFormat == System.Drawing.Imaging.ImageFormat.Jpeg)
  1138. {
  1139. picture += @"\jpegblip";
  1140. }
  1141. else if (watermark.PictureObject.ImageFormat == System.Drawing.Imaging.ImageFormat.Png)
  1142. picture += @"\pngblip";
  1143. int width;
  1144. int height;
  1145. switch (watermark.ImageSize)
  1146. {
  1147. case WatermarkImageSize.Zoom:
  1148. float scaleX = matrix.PageWidth(0) / (watermark.Image.Width / 3.8f);
  1149. float scaleY = matrix.PageHeight(0) / (watermark.Image.Height / 3.8f);
  1150. width = (int)(watermark.Image.Width / 3.8f * Math.Min(scaleY, scaleX) * MargDivider);
  1151. height = (int)(watermark.Image.Height / 3.8f * Math.Min(scaleY, scaleX) * MargDivider);
  1152. break;
  1153. case WatermarkImageSize.Stretch:
  1154. width = (int)((matrix.PageWidth(0) - matrix.PageLMargin(0) - matrix.PageRMargin(0)) * MargDivider);
  1155. height = (int)((matrix.PageHeight(0) - matrix.PageTMargin(0) - matrix.PageBMargin(0)) * MargDivider);
  1156. break;
  1157. default:
  1158. width = (int)(watermark.Image.Width / 3.8f * MargDivider);
  1159. height = (int)(watermark.Image.Height / 3.8f * MargDivider);
  1160. break;
  1161. }
  1162. pictureContrast -= (int)(watermark.ImageTransparency * 100 * 600);
  1163. pictureBrightness += (int)(watermark.ImageTransparency * 100 * 600);
  1164. WriteLine(stream,
  1165. @"\headery0{\header\pard\plain\itap0\s0\aspalpha\aspnum\adjustright\ltrpar\li0\lin0\ri0\rin0\ql\faauto\rtlch\afs24\ltrch\fs24{\rtlch\afs24\ltrch\fs2" + "\n" +
  1166. @"{\shp{\*\shpinst\shpleft-0\shptop-0\shpright" + width + @"\shpbottom" + height + @"\shpfhdr1\shpbxcolumn\shpbxignore\shpbypara\shpbyignore\shpwr3\shpwrk0\shpfblwtxt1\shpz2\shplid2054{\sp{\sn shapeType}" + "\n" +
  1167. @"{\sv 75}" + "\n" +
  1168. @"}" + "\n" +
  1169. @"{\sp{\sn fFlipH}" + "\n" +
  1170. @"{\sv 0}" + "\n" +
  1171. @"}" + "\n" +
  1172. @"{\sp{\sn fFlipV}" + "\n" +
  1173. @"{\sv 0}" + "\n" +
  1174. @"}" + "\n" +
  1175. @"{\sp{\sn pib}" + "\n"
  1176. );
  1177. WriteLine(stream, picture + @"\bliptag-1263442625{\*\blipuid b4b1653f1c65f1c28791719870001760}");
  1178. WriteLine(stream, hex + "}");
  1179. WriteLine(stream,
  1180. @"}" + "\n" +
  1181. @"}" + "\n" +
  1182. @"{\sp{\sn pibFlags}" + "\n" +
  1183. @"\sv 2}" + "\n" +
  1184. @"}" + "\n" +
  1185. @"{\sp{\sn pictureContrast}" + "\n" +
  1186. @"{\sv " + pictureContrast + "}" + "\n" +
  1187. @"}" + "\n" +
  1188. @"{\sp{\sn pictureBrightness}" + "\n" +
  1189. @"{\sv " + pictureBrightness + "}" + "\n" +
  1190. @"}" + "\n" +
  1191. @"{\sp{\sn fLine}" + "\n" +
  1192. @"{\sv 0}" + "\n" +
  1193. @"}" + "\n" +
  1194. @"{\sp{\sn wzName}" + "\n" +
  1195. @"{\sv WordPictureWatermark85221080}" + "\n" +
  1196. @"}" + "\n" +
  1197. @"{\sp{\sn posh}" + "\n" +
  1198. @"{\sv 2}" + "\n" +
  1199. @"}" + "\n" +
  1200. @"{\sp{\sn posrelh}" + "\n" +
  1201. @"{\sv 0}" + "\n" +
  1202. @"}" + "\n" +
  1203. @"{\sp{\sn posv}" + "\n" +
  1204. @"{\sv 2}" + "\n" +
  1205. @"}" + "\n" +
  1206. @"{\sp{\sn posrelv}" + "\n" +
  1207. @"{\sv 0}" + "\n" +
  1208. @"}" + "\n" +
  1209. @"{\sp{\sn dhgt}" + "\n" +
  1210. @"{\sv 251660288}" + "\n" +
  1211. @"}" + "\n" +
  1212. @"{\sp{\sn fLayoutInCell}" + "\n" +
  1213. @"{\sv 0}" + "\n" +
  1214. @"}" + "\n" +
  1215. @"{\sp{\sn fBehindDocument}" + "\n" +
  1216. @"{\sv 1}" + "\n" +
  1217. @"}" + "\n" +
  1218. @"{\sp{\sn fLayoutInCell}" + "\n" +
  1219. @"{\sv 0}" + "\n" +
  1220. @"}" + "\n" +
  1221. @"}" + "\n" +
  1222. @"{\shprslt" + "\n" +
  1223. @"}" + "\n" +
  1224. @"}" + "\n" +
  1225. @"{\rtlch\afs24\ltrch\fs24\par}" + "\n" +
  1226. @"}"
  1227. );
  1228. }
  1229. }
  1230. #endregion
  1231. private void ExportRTF(Stream stream)
  1232. {
  1233. int i, j, x, fx, fy, dx, dy, pbk;
  1234. int dcol, drow, xoffs;
  1235. ExportIEMObject Obj;
  1236. Prepare();
  1237. //Write a header is below now
  1238. pbk = 0;
  1239. Write(stream, SetPageProp(pbk));
  1240. if (Report.PreparedPages.GetPage(0).Watermark.Enabled)
  1241. AddWatermark(stream);
  1242. if (ShowProgress)
  1243. Config.ReportSettings.OnProgress(Report, res.Get("SavePage") + " " + (pbk + 1).ToString());
  1244. for (int y = 0; y < matrix.Height - 1; y++)
  1245. {
  1246. if (pageBreaks)
  1247. if (pbk < matrix.PagesCount)
  1248. if (matrix.PageBreak(pbk) <= matrix.YPosById(y))
  1249. {
  1250. // WriteLine(stream, "\\pagebb\\sect");
  1251. WriteLine(stream, "\\pard\\sect");
  1252. pbk++;
  1253. if (pbk < matrix.PagesCount)
  1254. Write(stream, SetPageProp(pbk));
  1255. if (ShowProgress)
  1256. Config.ReportSettings.OnProgress(Report,
  1257. res.Get("SavePage") + " " + (pbk + 1).ToString());
  1258. }
  1259. if (pbk == matrix.PagesCount - 1)
  1260. yDiv = Ydivider3;
  1261. else if (pbk > 0)
  1262. yDiv = Ydivider1;
  1263. else
  1264. yDiv = Ydivider2;
  1265. drow = (int)Math.Round((matrix.YPosById(y + 1) - matrix.YPosById(y)) * 14.90);
  1266. StringBuilder buff = new StringBuilder(512);
  1267. buff.Append(autoSize ? "\\trrh" : "\\trrh-" + (drow).ToString() + "\\trgaph15");
  1268. if (exportLocale)
  1269. {
  1270. if (localization != null)
  1271. buff.Append($"\\lang{localization.LCID}");
  1272. else
  1273. buff.Append($"\\lang{CultureInfo.GetCultureInfoByIetfLanguageTag(Res.LocaleName.Substring(0, 2)).LCID}");
  1274. }
  1275. xoffs = (int)Math.Round(matrix.XPosById(0));
  1276. StringBuilder CellsStream = new StringBuilder();
  1277. for (x = 0; x <= matrix.Width - 2; x++)
  1278. {
  1279. i = matrix.Cell(x, y);
  1280. if (i != -1)
  1281. {
  1282. Obj = matrix.ObjectById(i);
  1283. matrix.ObjectPos(i, out fx, out fy, out dx, out dy);
  1284. if (Obj.Counter == -1)
  1285. {
  1286. if (dy > 1)
  1287. buff.Append("\\clvmgf");
  1288. if (Obj.Style != null)
  1289. {
  1290. if (Obj.Style.FillColor != Color.Transparent)
  1291. buff.Append("\\clcbpat").Append(GetRTFColorFromTable(GetRTFColor(Obj.Style.FillColor)));
  1292. buff.Append(GetRTFVAlignment(Obj.Style.VAlign)).Append(GetRTFBorders(Obj.Style))
  1293. .Append("\\cltxlrtb");
  1294. if (Obj.Style.Angle == 90)
  1295. buff.Append(" \\cltxtbrl ");
  1296. else if (Obj.Style.Angle == 270)
  1297. buff.Append(" \\cltxbtlr ");
  1298. }
  1299. dcol = (int)Math.Round((Obj.Left + Obj.Width - xoffs) * Xdivider);
  1300. buff.Append("\\cellx").Append(dcol.ToString());
  1301. if (Obj.IsText)
  1302. {
  1303. if (Obj.IsRichText)
  1304. {
  1305. // Write a rich text
  1306. StringBuilder EmneddedRichStream = new StringBuilder();
  1307. TranslateEmbeddedRTF(Obj, EmneddedRichStream);
  1308. string debug = EmneddedRichStream.ToString();
  1309. CellsStream.Append(EmneddedRichStream);
  1310. }
  1311. else
  1312. {
  1313. // Write a text
  1314. textColor = Obj.Style.TextColor;
  1315. CellsStream.AppendLine(GetRTFString(Obj, drow));
  1316. }
  1317. }
  1318. else
  1319. {
  1320. // Write a picture
  1321. CellsStream.Append(GetRTFMetafile(Obj));
  1322. }
  1323. Obj.Counter = y + 1;
  1324. }
  1325. else
  1326. {
  1327. if ((dy > 1) && (Obj.Counter != y + 1))
  1328. {
  1329. buff.Append("\\clvmrg").
  1330. Append((Obj.Style != null) ? GetRTFBorders(Obj.Style) : String.Empty).
  1331. Append("\\cltxlrtb");
  1332. dcol = (int)Math.Round((Obj.Left + Obj.Width - xoffs) * Xdivider);
  1333. buff.Append("\\cellx").Append(dcol.ToString());
  1334. j = (int)(drow / FONT_DIVIDER);
  1335. j = j > 20 ? 20 : j;
  1336. CellsStream.Append("{\\fs").Append(j.ToString());
  1337. CellsStream.AppendLine("\\cell}");
  1338. Obj.Counter = y + 1;
  1339. }
  1340. }
  1341. }
  1342. }
  1343. if (CellsStream.Length > 0)
  1344. {
  1345. WriteLine(stream, "\\trowd");
  1346. WriteLine(stream, buff.ToString());
  1347. WriteLine(stream, "\\pard\\intbl");
  1348. WriteLine(stream, CellsStream.ToString());
  1349. WriteLine(stream, "\\pard\\intbl{\\trowd");
  1350. WriteLine(stream, buff.ToString());
  1351. WriteLine(stream, "\\row}");
  1352. }
  1353. }
  1354. WriteLine(stream, "\\pard\\fs2\\par}"); //insert empty text with minimum size for avoiding creating a new page
  1355. WriteLine(stream, "}");
  1356. #region Write a header
  1357. byte[] b = new byte[stream.Length];
  1358. stream.Position = 0;
  1359. stream.Read(b, 0, (int)stream.Length);
  1360. stream.SetLength(0);
  1361. WriteLine(stream, GetRTFHeader());
  1362. WriteLine(stream, GetRTFMetaInfo());
  1363. stream.Write(b, 0, b.Length);
  1364. #endregion
  1365. stream.Flush();
  1366. }
  1367. #endregion
  1368. #region Protected Methods
  1369. /// <inheritdoc/>
  1370. protected override string GetFileFilter()
  1371. {
  1372. return new MyRes("FileFilters").Get("RtfFile");
  1373. }
  1374. /// <inheritdoc/>
  1375. protected override void Start()
  1376. {
  1377. base.Start();
  1378. colorTable = new List<string>();
  1379. fontTable = new List<string>();
  1380. matrix = new ExportMatrix();
  1381. if (wysiwyg)
  1382. matrix.Inaccuracy = 0.5f;
  1383. else
  1384. matrix.Inaccuracy = 10;
  1385. matrix.RotatedAsImage = false;
  1386. matrix.PlainRich = false;
  1387. matrix.AreaFill = true;
  1388. matrix.CropAreaFill = false;
  1389. matrix.ShowProgress = ShowProgress;
  1390. matrix.Report = Report;
  1391. if (printOptimized)
  1392. matrix.PrintOptimized = printOptimized;
  1393. if (imageFormat != RTFImageFormat.Metafile)
  1394. {
  1395. matrix.FullTrust = false;
  1396. matrix.ImageFormat = imageFormat == RTFImageFormat.Jpeg ?
  1397. System.Drawing.Imaging.ImageFormat.Jpeg : System.Drawing.Imaging.ImageFormat.Png;
  1398. matrix.JpegQuality = jpegQuality;
  1399. }
  1400. matrix.KeepRichText = keepRichText;
  1401. }
  1402. /// <inheritdoc/>
  1403. protected override void ExportPageBegin(ReportPage page)
  1404. {
  1405. base.ExportPageBegin(page);
  1406. matrix.AddPageBegin(page);
  1407. }
  1408. /// <inheritdoc/>
  1409. protected override void ExportBand(BandBase band)
  1410. {
  1411. base.ExportBand(band);
  1412. matrix.AddBand(band, this);
  1413. }
  1414. /// <inheritdoc/>
  1415. protected override void ExportPageEnd(ReportPage page)
  1416. {
  1417. matrix.AddPageEnd(page);
  1418. }
  1419. /// <inheritdoc/>
  1420. protected override void Finish()
  1421. {
  1422. matrix.Prepare();
  1423. ExportRTF(Stream);
  1424. }
  1425. #endregion
  1426. /// <inheritdoc/>
  1427. public override void Serialize(FRWriter writer)
  1428. {
  1429. base.Serialize(writer);
  1430. writer.WriteBool("Wysiwyg", Wysiwyg);
  1431. writer.WriteBool("PageBreaks", PageBreaks);
  1432. writer.WriteBool("Pictures", Pictures);
  1433. writer.WriteValue("ImageFormat", ImageFormat);
  1434. writer.WriteValue("KeeoRich", EmbedRichObject);
  1435. writer.WriteValue("Locale", Locale);
  1436. writer.WriteBool("ExportLocale", ExportLocale);
  1437. }
  1438. /// <summary>
  1439. /// Initializes a new instance of the <see cref="RTFExport"/> class.
  1440. /// </summary>
  1441. public RTFExport()
  1442. {
  1443. dpiFactor = 96f / DrawUtils.ScreenDpi;
  1444. pageBreaks = true;
  1445. wysiwyg = true;
  1446. printOptimized = false;
  1447. autoSize = false;
  1448. pictures = true;
  1449. imageFormat = RTFImageFormat.Metafile;
  1450. jpegQuality = 90;
  1451. ExportLocale = false;
  1452. creator = "FastReport";
  1453. res = new MyRes("Export,Misc");
  1454. }
  1455. }
  1456. }