Rich2ReportObject.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. using FastReport.Table;
  2. using FastReport.Utils;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Windows.Forms;
  10. namespace FastReport.RichTextParser
  11. {
  12. class RichText2ReportObject : IDisposable
  13. {
  14. static int DpiX = 96;
  15. Font default_font = new Font(FontFamily.GenericSerif, 12, FontStyle.Regular);
  16. RunFormat current_format;
  17. bool usePadding = false; // Control page margins
  18. private static int Twips2Pixels(int twips)
  19. {
  20. return (int)(((double)twips) * (1.0 / 1440.0) * DpiX);
  21. }
  22. private static int GetSpaceBefore(ParagraphFormat pfmt)
  23. {
  24. return pfmt.disable_space_before ? 0 : Twips2Pixels(pfmt.space_before);
  25. }
  26. private static int GetSpaceAfter(ParagraphFormat pfmt)
  27. {
  28. return pfmt.disable_space_after ? 0 : Twips2Pixels(pfmt.space_after);
  29. }
  30. public void Dispose()
  31. {
  32. }
  33. private string GetRawText(Paragraph paragraph)
  34. {
  35. StringBuilder sb = new StringBuilder();
  36. foreach (Run run in paragraph.runs)
  37. sb.Append(run.text);
  38. return sb.ToString();
  39. }
  40. private void GetHTMLText(FastReport.RichObject rich, ref TextObject clone, RichDocument rtf, int position, Paragraph paragraph)
  41. {
  42. int run_num = 0;
  43. bool span_condition = false;
  44. StringBuilder sb = new StringBuilder();
  45. RunFormat format = new RunFormat();
  46. string colorname = String.Empty;
  47. string fontname = String.Empty;
  48. string fontsize = String.Empty;
  49. string backcolor = String.Empty;
  50. string URL = String.Empty;
  51. Font current_font = clone.Font;
  52. int len;
  53. foreach (Run run in paragraph.runs)
  54. {
  55. if (run.text.StartsWith("HYPERLINK "))
  56. {
  57. URL = run.text.Substring(9);
  58. continue;
  59. }
  60. len = run.text != "\r" ? run.text.Length : 1;
  61. if (rich.ActualTextStart != 0 && position + len <= rich.ActualTextStart)
  62. {
  63. position += len;
  64. continue;
  65. }
  66. format = run.format;
  67. if (run_num == 0)
  68. {
  69. current_format = run.format;
  70. clone.Font = GetFontFromRichStyle(rtf, current_format);
  71. current_font = clone.Font;
  72. clone.TextColor = current_format.color;
  73. if (format.underline)
  74. {
  75. sb.Append("<u>");
  76. current_format.underline = true;
  77. }
  78. if (format.bold)
  79. {
  80. sb.Append("<b>");
  81. current_format.bold = true;
  82. }
  83. if (format.italic)
  84. {
  85. sb.Append("<i>");
  86. current_format.italic = true;
  87. }
  88. if (format.strike)
  89. {
  90. sb.Append("<strike>");
  91. current_format.strike = true;
  92. }
  93. if (format.script_type == RunFormat.ScriptType.Subscript)
  94. {
  95. sb.Append("<sub>");
  96. }
  97. if (format.script_type == RunFormat.ScriptType.Superscript)
  98. {
  99. sb.Append("<sup>");
  100. }
  101. // if (current_format.BColor != null)
  102. {
  103. if (current_format.BColor != Color.White && current_format.BColor != Color.Empty)
  104. backcolor = string.Format("background-color:#{0:X2}{1:X2}{2:X2}", format.BColor.R, format.BColor.G, format.BColor.B);
  105. }
  106. if (backcolor.Length > 0)
  107. {
  108. sb.Append("<span style=\"");
  109. sb.Append(backcolor);
  110. sb.Append("\">");
  111. span_condition = true;
  112. }
  113. }
  114. else
  115. {
  116. if (current_format.underline != format.underline && !format.underline)
  117. {
  118. sb.Append("</u>");
  119. current_format.underline = format.underline;
  120. }
  121. if (current_format.italic != format.italic && !format.italic)
  122. {
  123. sb.Append("</i>");
  124. current_format.italic = format.italic;
  125. }
  126. if (current_format.bold != format.bold && !format.bold)
  127. {
  128. sb.Append("</b>");
  129. current_format.bold = format.bold;
  130. }
  131. if (current_format.strike != format.strike && !format.strike)
  132. {
  133. sb.Append("</strike>");
  134. current_format.strike = format.strike;
  135. }
  136. if (current_format.strike != format.strike && format.strike)
  137. {
  138. sb.Append("<strike>");
  139. current_format.strike = format.strike;
  140. }
  141. if (current_format.bold != format.bold && format.bold)
  142. {
  143. sb.Append("<b>");
  144. current_format.bold = format.bold;
  145. }
  146. if (current_format.italic != format.italic && format.italic)
  147. {
  148. sb.Append("<i>");
  149. current_format.italic = format.italic;
  150. }
  151. if (current_format.underline != format.underline && format.underline)
  152. {
  153. sb.Append("<u>");
  154. current_format.underline = format.underline;
  155. }
  156. if (current_format.script_type != format.script_type)
  157. {
  158. if (current_format.script_type == RunFormat.ScriptType.Subscript)
  159. sb.Append("</sub>");
  160. else if (current_format.script_type == RunFormat.ScriptType.Superscript)
  161. sb.Append("</sup>");
  162. if (format.script_type == RunFormat.ScriptType.Subscript)
  163. sb.Append("<sub>");
  164. else if (format.script_type == RunFormat.ScriptType.Superscript)
  165. sb.Append("<sup>");
  166. current_format.script_type = format.script_type;
  167. }
  168. if (current_format.color != format.color)
  169. {
  170. colorname = string.Format("color:#{0:X2}{1:X2}{2:X2};", format.color.R, format.color.G, format.color.B);
  171. current_format.color = format.color;
  172. }
  173. if (format.BColor != Color.Empty && format.BColor != Color.White)
  174. backcolor = string.Format("background-color:#{0:X2}{1:X2}{2:X2}", format.BColor.R, format.BColor.G, format.BColor.B);
  175. else
  176. backcolor = string.Empty;
  177. if (current_format.font_size != format.font_size)
  178. {
  179. int fs = run.format.font_size / 2;
  180. fontsize = string.Format("font-size:{0}pt;", fs);
  181. //#ifIGNORE_SPAN
  182. current_format.font_size = format.font_size;
  183. //#endif
  184. }
  185. Font fnt = GetFontFromRichStyle(rtf, format);
  186. if (!current_font.FontFamily.Equals(fnt.FontFamily))
  187. {
  188. fontname = string.Format("font-family:{0};", fnt.FontFamily.Name);
  189. #if IGNORE_SPAN
  190. current_font = fnt;
  191. #endif
  192. }
  193. else
  194. fontname = string.Empty;
  195. if (colorname.Length > 0 || fontsize.Length > 0 || fontname.Length > 0 || backcolor.Length > 0)
  196. {
  197. sb.Append("<span style=\"");
  198. if (colorname.Length > 0)
  199. sb.Append(colorname);
  200. if (fontsize.Length > 0)
  201. sb.Append(fontsize);
  202. if (fontname.Length > 0)
  203. sb.Append(fontname);
  204. if (backcolor.Length > 0)
  205. sb.Append(backcolor);
  206. sb.Append("\">");
  207. span_condition = true;
  208. }
  209. }
  210. if (run.text != "\r")
  211. sb.Append(run.text);
  212. else
  213. sb.Append("<br>");
  214. position += len;
  215. if (rich.ActualTextLength != 0 && position >= rich.ActualTextStart + rich.ActualTextLength)
  216. break;
  217. if (span_condition)
  218. {
  219. sb.Append("</span>");
  220. span_condition = false;
  221. }
  222. URL = String.Empty;
  223. run_num++;
  224. }
  225. // adding a closing tag to the end of the text
  226. if (current_format.script_type == RunFormat.ScriptType.Subscript)
  227. {
  228. sb.Append("</sub>");
  229. }
  230. else if (current_format.script_type == RunFormat.ScriptType.Superscript)
  231. {
  232. sb.Append("</sup>");
  233. }
  234. if (current_format.underline)
  235. {
  236. sb.Append("</u>");
  237. }
  238. if (current_format.italic)
  239. {
  240. sb.Append("</i>");
  241. }
  242. if (current_format.bold)
  243. {
  244. sb.Append("</b>");
  245. }
  246. if (current_format.strike)
  247. {
  248. sb.Append("</strike>");
  249. }
  250. clone.Text = sb.ToString();
  251. clone.RightToLeft = paragraph.format.text_direction == ParagraphFormat.Direction.RighgToLeft;
  252. }
  253. private FastReport.BorderLine TranslateBorderLine(BorderLine rtf_border_line)
  254. {
  255. FastReport.BorderLine border_line = new FastReport.BorderLine();
  256. switch (rtf_border_line.style)
  257. {
  258. case BorderLine.Style.Thin:
  259. border_line.Style = LineStyle.Solid;
  260. break;
  261. case BorderLine.Style.Thick:
  262. border_line.Style = LineStyle.Solid;
  263. break;
  264. case BorderLine.Style.Double:
  265. border_line.Style = LineStyle.Double;
  266. break;
  267. case BorderLine.Style.Dotted:
  268. border_line.Style = LineStyle.Dot;
  269. break;
  270. default:
  271. border_line.Style = LineStyle.Solid;
  272. break;
  273. }
  274. border_line.Color = rtf_border_line.color;
  275. border_line.Width = Twips2Pixels((int)rtf_border_line.width);
  276. return border_line;
  277. }
  278. private FastReport.Border TranslateBorders(Column rtf_column)
  279. {
  280. FastReport.Border border = new Border();
  281. border.Lines = BorderLines.None;
  282. if (rtf_column.border_top.width > 0)
  283. {
  284. border.TopLine = TranslateBorderLine(rtf_column.border_top);
  285. border.Lines |= BorderLines.Top;
  286. }
  287. if (rtf_column.border_right.width > 0)
  288. {
  289. border.RightLine = TranslateBorderLine(rtf_column.border_right);
  290. border.Lines |= BorderLines.Right;
  291. }
  292. if (rtf_column.border_left.width > 0)
  293. {
  294. border.LeftLine = TranslateBorderLine(rtf_column.border_left);
  295. border.Lines |= BorderLines.Left;
  296. }
  297. if (rtf_column.border_bottom.width > 0)
  298. {
  299. border.BottomLine = TranslateBorderLine(rtf_column.border_bottom);
  300. border.Lines |= BorderLines.Bottom;
  301. }
  302. return border;
  303. }
  304. private Font GetFontFromRichStyle(RichDocument rtf, RunFormat format)
  305. {
  306. int font_idx = (int)format.font_idx;
  307. if (font_idx < rtf.font_list.Count)
  308. {
  309. RFont rf = rtf.font_list[font_idx];
  310. string Name = rf.FontName;
  311. #if false // Broke PDF export
  312. FontStyle style = format.bold ? FontStyle.Bold : FontStyle.Regular;
  313. #else
  314. FontStyle style = FontStyle.Regular;
  315. #endif
  316. return new Font(rf.FontName, format.font_size / 2, style);
  317. }
  318. else
  319. return default_font;
  320. }
  321. internal TextObject Paragraph2ReportObjects(FastReport.RichObject rich, RichDocument rtf, int position, Paragraph paragraph)
  322. {
  323. TextObject clone = new TextObject();
  324. clone.TextRenderType = TextRenderType.HtmlParagraph;
  325. clone.CanShrink = rich.CanShrink;
  326. clone.CanGrow = rich.CanGrow;
  327. clone.CanBreak = rich.CanBreak;
  328. clone.Left = 0; // Will set in another place
  329. clone.GrowToBottom = false; // Can't be set here;
  330. clone.ClientSize = rich.ClientSize;
  331. clone.TextColor = Color.Black;
  332. clone.FirstTabOffset = Twips2Pixels((int) rtf.default_tab_width);
  333. clone.TabWidth = Twips2Pixels((int)rtf.default_tab_width);
  334. clone.Bookmark = rich.Bookmark;
  335. clone.Hyperlink = rich.Hyperlink;
  336. clone.FillColor = rich.FillColor;
  337. if (paragraph.runs.Count > 0)
  338. {
  339. if (paragraph.format.tab_positions != null)
  340. {
  341. int count = paragraph.format.tab_positions.Count;
  342. if (count > 0)
  343. {
  344. // It is necessary to reduce the first tab width by the value that will go to the left of the object,
  345. // since it will not be taken into account when splitting into HTMLParagrphRenderer paragraphs.
  346. // The remaining tab positions will be relative to the previous tab stop.
  347. clone.FirstTabOffset = Twips2Pixels(paragraph.format.tab_positions[0]) - Twips2Pixels(Math.Min(paragraph.format.left_indent + paragraph.format.first_line_indent, paragraph.format.left_indent));
  348. if (count > 1)
  349. clone.TabWidth = Twips2Pixels(paragraph.format.tab_positions[1]) - clone.FirstTabOffset;
  350. if (count > 2)
  351. for (int i = 1; i < paragraph.format.tab_positions.Count; i++)
  352. clone.TabPositions.Add((int)(Twips2Pixels(paragraph.format.tab_positions[i]) - Twips2Pixels(paragraph.format.tab_positions[i - 1])));
  353. }
  354. }
  355. GetHTMLText(rich, ref clone, rtf, position, paragraph);
  356. }
  357. else
  358. clone.Font = default_font;
  359. switch (paragraph.format.align)
  360. {
  361. case ParagraphFormat.HorizontalAlign.Right:
  362. clone.HorzAlign = paragraph.format.text_direction == ParagraphFormat.Direction.LeftToRight ?
  363. HorzAlign.Right : HorzAlign.Left;
  364. break;
  365. case ParagraphFormat.HorizontalAlign.Centered:
  366. clone.HorzAlign = HorzAlign.Center;
  367. break;
  368. case ParagraphFormat.HorizontalAlign.Justified:
  369. clone.HorzAlign = HorzAlign.Justify;
  370. break;
  371. default:
  372. clone.HorzAlign = paragraph.format.text_direction == ParagraphFormat.Direction.LeftToRight ?
  373. HorzAlign.Left : HorzAlign.Right;
  374. break;
  375. }
  376. switch (paragraph.format.Valign)
  377. {
  378. case ParagraphFormat.VerticalAlign.Top:
  379. clone.VertAlign = VertAlign.Top;
  380. break;
  381. case ParagraphFormat.VerticalAlign.Center:
  382. clone.VertAlign = VertAlign.Center;
  383. break;
  384. case ParagraphFormat.VerticalAlign.Bottom:
  385. clone.VertAlign = VertAlign.Bottom;
  386. break;
  387. default:
  388. clone.VertAlign = VertAlign.Top;
  389. break;
  390. }
  391. clone.Border.Lines = BorderLines.None;
  392. float lineheight = paragraph.format.line_spacing;
  393. if (lineheight == 0)
  394. clone.LineHeight = (float)Math.Ceiling(clone.Font.Height * DrawUtils.ScreenDpiFX);
  395. else
  396. {
  397. switch (paragraph.format.lnspcmult)
  398. {
  399. case ParagraphFormat.LnSpcMult.Exactly:
  400. lineheight = Twips2Pixels((int)lineheight);
  401. break;
  402. case ParagraphFormat.LnSpcMult.Multiply:
  403. lineheight = (int)(lineheight / 240f);
  404. break;
  405. }
  406. lineheight = lineheight < 0 ? -lineheight : lineheight >= clone.Font.Height * DrawUtils.ScreenDpiFX ? lineheight : clone.Font.Height * DrawUtils.ScreenDpiFX;
  407. clone.ParagraphFormat.LineSpacingType = LineSpacingType.Exactly;
  408. clone.ParagraphFormat.LineSpacing = (lineheight)/* * DrawUtils.ScreenDpiFX */;
  409. clone.LineHeight = lineheight;
  410. }
  411. clone.Padding = new Padding(rich.Padding.Left, 0, rich.Padding.Right, 0);
  412. clone.SetReport(rich.Report);
  413. return clone;
  414. }
  415. internal TableObject Table2ReportObjects(FastReport.RichObject rich, RichDocument rtf, Table rtf_table)
  416. {
  417. TableObject table = new TableObject();
  418. int idx = 0;
  419. uint prev_width = 0;
  420. IList<TranslationPropeties> row_properties = new List<TranslationPropeties>();
  421. foreach (Column rtf_column in rtf_table.columns)
  422. {
  423. TableColumn column = new TableColumn();
  424. column.Width = Twips2Pixels((int)(rtf_column.Width - prev_width));
  425. prev_width = rtf_column.Width;
  426. column.SetIndex(idx);
  427. TranslationPropeties prop = new TranslationPropeties(
  428. TranslateBorders(rtf_column),
  429. rtf_column.back_color);
  430. row_properties.Add(prop);
  431. table.Columns.Add(column);
  432. idx++;
  433. }
  434. foreach (TableRow rtf_row in rtf_table.rows)
  435. {
  436. int height = rtf_row.height;
  437. if (height < 0)
  438. height = -height;
  439. FastReport.Table.TableRow row = new FastReport.Table.TableRow();
  440. int cell_idx = 0;
  441. float x_pos = 0;
  442. foreach (RichObjectSequence sequence in rtf_row.cells)
  443. {
  444. float top = 0;
  445. TableColumn rtf_column = table.Columns[cell_idx];
  446. TableCell cell = new TableCell();
  447. TranslationPropeties prop = row_properties[cell_idx];
  448. cell.Border = prop.border;
  449. cell.FillColor = prop.background_color;
  450. foreach (RichObject obj in sequence.objects)
  451. {
  452. switch (obj.type)
  453. {
  454. case RichObject.Type.Paragraph:
  455. TextObject text_paragraph = Paragraph2ReportObjects(rich, rtf, 0, obj.paragraph); // TODO: Fix "pos" argument
  456. text_paragraph.Width = rtf_column.Width;
  457. Padding p = text_paragraph.Padding;
  458. p.Top = GetSpaceBefore(obj.paragraph.format);
  459. p.Bottom = GetSpaceAfter(obj.paragraph.format);
  460. p.Left = Twips2Pixels((int)obj.paragraph.format.left_indent);
  461. p.Right = Twips2Pixels((int)obj.paragraph.format.right_indent);
  462. if (p.Left == 0)
  463. p.Left = 3;
  464. text_paragraph.Padding = p;
  465. if (obj.paragraph.runs.Count > 0)
  466. text_paragraph.Height = text_paragraph.CalcHeight() + 3.0f;
  467. else
  468. text_paragraph.Height = height;
  469. text_paragraph.Top = top;
  470. top += text_paragraph.Height;
  471. text_paragraph.Parent = cell;
  472. break;
  473. case RichObject.Type.Picture:
  474. PictureObject picture = Picture2ReportObject(rtf, obj.picture);
  475. picture.Top = top;
  476. top += picture.Height;
  477. picture.Parent = cell;
  478. break;
  479. case RichObject.Type.Table:
  480. TableObject subtable = Table2ReportObjects(rich, rtf, obj.table);
  481. subtable.Top = top;
  482. top += subtable.Height;
  483. table.Parent = cell;
  484. break;
  485. }
  486. cell.Left = x_pos;
  487. cell.Height = top; // height;
  488. }
  489. row.Height = (row.Height > cell.Height) ? row.Height : cell.Height;
  490. row.AddChild(cell);
  491. x_pos += rtf_column.Width;
  492. cell_idx++;
  493. }
  494. table.Rows.Add(row);
  495. table.Height += row.Height;
  496. }
  497. return table;
  498. }
  499. internal PictureObject Picture2ReportObject(RichDocument rtf, Picture rtf_picture)
  500. {
  501. PictureObject picture = new PictureObject();
  502. picture.Image = rtf_picture.image;
  503. if (rtf_picture.desired_width != 0)
  504. {
  505. if (rtf_picture.scalex == 0)
  506. picture.Width = Twips2Pixels(rtf_picture.desired_width);
  507. else
  508. picture.Width = Twips2Pixels(rtf_picture.desired_width * rtf_picture.scalex / 100);
  509. }
  510. else
  511. picture.Width = Twips2Pixels(rtf_picture.width);
  512. if (rtf_picture.desired_height != 0)
  513. {
  514. if (rtf_picture.scaley != 0)
  515. picture.Height = Twips2Pixels(rtf_picture.desired_height);
  516. else
  517. picture.Height = Twips2Pixels(rtf_picture.desired_height * rtf_picture.scaley / 100);
  518. }
  519. else
  520. picture.Height = Twips2Pixels(rtf_picture.height);
  521. return picture;
  522. }
  523. internal List<ComponentBase> Page2ReportObjects(FastReport.RichObject rich, RichDocument rtf, Page page, int start_text_index, out float page_height)
  524. {
  525. int object_counter = 0;
  526. page_height = 0;
  527. int empty_paragraph_height = 0;
  528. float object_vertical_position = rich.Padding.Top; // Twips2Pixels(page.margin_top); //
  529. List<ComponentBase> clone_list = new List<ComponentBase>();
  530. foreach (RichObject obj in page.sequence.objects)
  531. {
  532. TextObject left_label = null;
  533. if (rich.ActualTextStart != 0 && start_text_index + obj.size <= rich.ActualTextStart)
  534. {
  535. start_text_index += (int)obj.size;
  536. continue;
  537. }
  538. bool backindent = false;
  539. Padding p = new Padding();
  540. switch (obj.type)
  541. {
  542. case RichObject.Type.Paragraph:
  543. p.Top = GetSpaceBefore(obj.paragraph.format);
  544. p.Bottom = GetSpaceAfter(obj.paragraph.format);
  545. p.Right = Twips2Pixels((int)obj.paragraph.format.right_indent);
  546. p.Left = 0; // Twips2Pixels((int)obj.paragraph.format.left_indent);
  547. if (obj.paragraph.runs.Count == 0)
  548. {
  549. start_text_index++; // TODO: Check position increment size
  550. ParagraphFormat format = obj.paragraph.format;
  551. int lnspc;
  552. int line_height = 17; // Not calculated yet
  553. if (format.lnspcmult == ParagraphFormat.LnSpcMult.Multiply)
  554. lnspc = (int)(format.line_spacing / 240f);
  555. else
  556. lnspc = Twips2Pixels(format.line_spacing);
  557. empty_paragraph_height = lnspc < 0 ? -lnspc : lnspc >= line_height ? lnspc : line_height;
  558. empty_paragraph_height += GetSpaceBefore(format) + GetSpaceAfter(format);
  559. object_vertical_position += empty_paragraph_height;
  560. TextObject empty_paragraph = Paragraph2ReportObjects(rich, rtf, start_text_index, obj.paragraph);
  561. empty_paragraph.Top = object_vertical_position;
  562. empty_paragraph.Height = empty_paragraph_height;
  563. empty_paragraph.CanShrink = false;
  564. ++object_counter;
  565. clone_list.Add(empty_paragraph);
  566. continue;
  567. }
  568. empty_paragraph_height = 0;
  569. TextObject list_label = null;
  570. if (obj.paragraph.format.list_id != null && obj.paragraph.format.list_id.Count != 0)
  571. {
  572. ++object_counter;
  573. list_label = new TextObject();
  574. Run run = obj.paragraph.format.list_id[0];
  575. #if ! DONT_SUBSTITUTE_INTERPUNCT
  576. if (run.text[0] == 183)
  577. list_label.Text = "•"; // "●";
  578. else
  579. #endif
  580. list_label.Text = run.text;
  581. clone_list.Add(list_label);
  582. }
  583. TextObject text_paragraph = Paragraph2ReportObjects(rich, rtf, start_text_index, obj.paragraph);
  584. if (list_label != null)
  585. {
  586. list_label.Font = text_paragraph.Font;
  587. list_label.VertAlign = text_paragraph.VertAlign;
  588. list_label.LineHeight = text_paragraph.LineHeight;
  589. list_label.HorzAlign = HorzAlign.Left;
  590. list_label.FillColor = rich.FillColor;
  591. list_label.SetReport(rich.Report);
  592. list_label.Width = Twips2Pixels(obj.paragraph.format.left_indent);
  593. list_label.RightToLeft = text_paragraph.RightToLeft;
  594. if (!text_paragraph.RightToLeft)
  595. {
  596. list_label.Left = rich.Left + Twips2Pixels(obj.paragraph.format.left_indent +
  597. obj.paragraph.format.first_line_indent) * DrawUtils.ScreenDpiFX;
  598. text_paragraph.Width = rich.Right - text_paragraph.Left;
  599. text_paragraph.Left = list_label.Right;
  600. }
  601. else
  602. {
  603. text_paragraph.Width = rich.Right - list_label.Width;
  604. p.Left = p.Right = 0;
  605. list_label.Left = text_paragraph.Right;
  606. }
  607. }
  608. else
  609. {
  610. text_paragraph.Left = rich.Left;
  611. int ftb = text_paragraph.Text.IndexOf('\t');
  612. backindent = ftb >= 0 && obj.paragraph.format.first_line_indent < 0 &&
  613. -obj.paragraph.format.first_line_indent <= obj.paragraph.format.left_indent;
  614. text_paragraph.Width = rich.Width;
  615. if (backindent)
  616. {
  617. string left_text = text_paragraph.Text.Substring(0, ftb);
  618. ++object_counter;
  619. left_label = new TextObject();
  620. left_label.Text = left_text;
  621. left_label.FillColor = rich.FillColor;
  622. left_label.Top = object_vertical_position;
  623. left_label.HorzAlign = HorzAlign.Left;
  624. left_label.VertAlign = text_paragraph.VertAlign;
  625. if (obj.paragraph.format.left_indent != 0)
  626. {
  627. left_label.Width = Twips2Pixels(obj.paragraph.format.left_indent);
  628. }
  629. else
  630. {
  631. left_label.Width = Twips2Pixels(obj.paragraph.format.tab_positions[0]);
  632. }
  633. left_label.Left = text_paragraph.RightToLeft ? rich.Right - left_label.Width : rich.Left;
  634. left_label.Height = (float)Math.Ceiling(left_label.Font.Height * DrawUtils.ScreenDpiFX); // * 1.2f;
  635. left_label.TextRenderType = TextRenderType.HtmlParagraph;
  636. clone_list.Add(left_label);
  637. int charcount = text_paragraph.Text.Length - ftb - 1;
  638. if (charcount > 0)
  639. {
  640. text_paragraph.Text = text_paragraph.Text.Substring(ftb + 1, charcount);
  641. }
  642. }
  643. else
  644. {
  645. text_paragraph.ParagraphFormat.FirstLineIndent = Twips2Pixels(obj.paragraph.format.first_line_indent);
  646. }
  647. }
  648. ++object_counter;
  649. if (backindent)
  650. {
  651. if(text_paragraph.RightToLeft)
  652. {
  653. text_paragraph.Width -= (left_label.Width + 0.01f);
  654. left_label.HorzAlign = HorzAlign.Center;
  655. }
  656. else
  657. {
  658. p.Left = 0;
  659. text_paragraph.Left += left_label.Right + 0.01f;
  660. text_paragraph.Width -= left_label.Right + 0.01F;
  661. }
  662. }
  663. else if (text_paragraph.HorzAlign != HorzAlign.Center)
  664. {
  665. p.Left += list_label != null ? 0 : (int)(Twips2Pixels(Math.Min(obj.paragraph.format.left_indent + obj.paragraph.format.first_line_indent, obj.paragraph.format.left_indent)));
  666. }
  667. else
  668. {
  669. p.Left = (int)(Twips2Pixels(obj.paragraph.format.left_indent));
  670. }
  671. text_paragraph.Padding = p;
  672. text_paragraph.Top = object_vertical_position;
  673. // text_paragraph.PreserveLastLineSpace = true;
  674. text_paragraph.Height = text_paragraph.CalcHeight() + p.Vertical;
  675. if (backindent)
  676. {
  677. left_label.Height = text_paragraph.Height;
  678. left_label.Padding = new Padding(0, p.Top, 0, p.Bottom);
  679. }
  680. if(list_label != null)
  681. {
  682. list_label.Height = text_paragraph.Height;
  683. list_label.Padding = new Padding(0, p.Top, 0, p.Bottom);
  684. list_label.Top = text_paragraph.Top;
  685. }
  686. object_vertical_position += text_paragraph.Height;
  687. clone_list.Add(text_paragraph);
  688. break;
  689. case RichObject.Type.Picture:
  690. {
  691. PictureObject pict = Picture2ReportObject(rtf, obj.picture);
  692. if (obj.picture.horizontalAlign == ParagraphFormat.HorizontalAlign.Centered)
  693. pict.Left = rich.Left + (rich.Width / 2) - (pict.Width / 2);
  694. else if (obj.picture.horizontalAlign == ParagraphFormat.HorizontalAlign.Right)
  695. pict.Left = rich.Right - pict.Width;
  696. else
  697. pict.Left = rich.Left;
  698. pict.Top = object_vertical_position;
  699. object_vertical_position += pict.Height;
  700. clone_list.Add(pict);
  701. }
  702. break;
  703. case RichObject.Type.Table:
  704. {
  705. TableObject tbl = Table2ReportObjects(rich, rtf, obj.table);
  706. tbl.Left = rich.Left;
  707. tbl.Top = object_vertical_position;
  708. object_vertical_position += tbl.Height;
  709. clone_list.Add(tbl);
  710. }
  711. break;
  712. }
  713. start_text_index += (int)obj.size;
  714. if (rich.ActualTextLength != 0 && start_text_index >= rich.ActualTextStart + rich.ActualTextLength)
  715. break;
  716. }
  717. int idx = 1;
  718. foreach (ComponentBase obj in clone_list)
  719. {
  720. obj.SetName(rich.Name + "_" + idx.ToString());
  721. idx++;
  722. obj.SetReport(rich.Report);
  723. page_height += obj.Height;
  724. }
  725. return clone_list;
  726. }
  727. private float AssingClones(FastReport.RichObject rich, List<ComponentBase> clone_list)
  728. {
  729. float bottom = rich.Bottom;
  730. foreach (ComponentBase clone in clone_list)
  731. {
  732. clone.SetReport(rich.Report);
  733. bottom = clone.Bottom;
  734. }
  735. return bottom + (usePadding ? rich.Padding.Top + rich.Padding.Bottom : 0);
  736. }
  737. internal List<ComponentBase> RichObject2ReportObjects(FastReport.RichObject rich, ref RichDocument rtf, out float total_height)
  738. {
  739. List<ComponentBase> clone_list = new List<ComponentBase>();
  740. int position = 0;
  741. float vertical_shift = 0;
  742. total_height = 0;
  743. if (rtf.pages != null)
  744. {
  745. bool page_break = false;
  746. foreach (Page page in rtf.pages)
  747. {
  748. if (position + page.size < rich.ActualTextStart)
  749. {
  750. position += (int)page.size;
  751. continue;
  752. }
  753. float page_height;
  754. List<ComponentBase> virtual_object_list = Page2ReportObjects(rich, rtf, page, position, out page_height);
  755. foreach (ComponentBase obj in virtual_object_list)
  756. {
  757. if (page_break)
  758. {
  759. BreakableComponent breaking = obj as BreakableComponent;
  760. if (breaking != null)
  761. breaking.PageBreak = true;
  762. page_break = false;
  763. }
  764. if (obj is TextObject)
  765. {
  766. TextObject text_object = obj as TextObject;
  767. text_object.Top += vertical_shift;
  768. if (total_height < text_object.Bottom)
  769. total_height = text_object.Bottom;
  770. clone_list.Add(obj);
  771. }
  772. else if (obj is PictureObject)
  773. {
  774. PictureObject pic = obj as PictureObject;
  775. pic.Top += vertical_shift;
  776. total_height += pic.Height;
  777. clone_list.Add(obj);
  778. }
  779. else if (obj is TableObject)
  780. {
  781. TableObject tbl = obj as TableObject;
  782. tbl.Top += vertical_shift;
  783. total_height += tbl.Height;
  784. clone_list.Add(obj);
  785. }
  786. else
  787. {
  788. throw new Exception("Rich2ReportObject.cs: object type not supported");
  789. }
  790. }
  791. position += (int)page.size;
  792. vertical_shift = total_height;
  793. page_break = true;
  794. if (rich.ActualTextLength != 0 && position >= rich.ActualTextStart + rich.ActualTextLength)
  795. break;
  796. }
  797. }
  798. total_height = AssingClones(rich, clone_list);
  799. return clone_list;
  800. }
  801. }
  802. #if READONLY_STRUCTS
  803. internal readonly struct TranslationPropeties
  804. #else
  805. internal struct TranslationPropeties
  806. #endif
  807. {
  808. internal readonly Border border;
  809. internal readonly Color background_color;
  810. public TranslationPropeties(Border border, Color background_color)
  811. {
  812. this.border = border;
  813. this.background_color = background_color;
  814. }
  815. }
  816. }