PDFExportOutline.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using FastReport.Utils;
  5. namespace FastReport.Export.Pdf
  6. {
  7. public partial class PDFExport : ExportBase
  8. {
  9. private class PDFOutlineNode
  10. {
  11. public string text;
  12. public int page;
  13. public float offset;
  14. public long number;
  15. public int countTree;
  16. public int count;
  17. public PDFOutlineNode first;
  18. public PDFOutlineNode last;
  19. public PDFOutlineNode parent;
  20. public PDFOutlineNode prev;
  21. public PDFOutlineNode next;
  22. public PDFOutlineNode()
  23. {
  24. text = String.Empty;
  25. offset = -1;
  26. number = 0;
  27. count = 0;
  28. countTree = 0;
  29. }
  30. }
  31. private PDFOutlineNode outlineTree;
  32. private long BuildOutline(PDFOutlineNode node, XmlItem xml)
  33. {
  34. PDFOutlineNode prev = null;
  35. PDFOutlineNode current = null;
  36. long currNumber = node.number;
  37. for (int i = 0; i < xml.Count; i++)
  38. {
  39. int page = 0;
  40. float offset = 0f;
  41. string s = xml[i].GetProp("Page");
  42. if (s != "")
  43. {
  44. page = int.Parse(s);
  45. s = xml[i].GetProp("Offset");
  46. if (s != "")
  47. offset = (float)Converter.FromString(typeof(float), s) * PDF_DIVIDER;
  48. }
  49. // add check of page range
  50. current = new PDFOutlineNode();
  51. current.text = xml[i].GetProp("Text");
  52. current.page = page;
  53. current.offset = offset;
  54. current.prev = prev;
  55. if (prev != null)
  56. prev.next = current;
  57. else
  58. node.first = current;
  59. prev = current;
  60. current.parent = node;
  61. current.number = currNumber + 1;
  62. currNumber = BuildOutline(current, xml[i]);
  63. node.count++;
  64. node.countTree += current.countTree + 1;
  65. }
  66. node.last = current;
  67. return currNumber;
  68. }
  69. private void WriteOutline(PDFOutlineNode item)
  70. {
  71. long number;
  72. if (item.parent != null)
  73. number = UpdateXRef();
  74. else
  75. number = item.number;
  76. StringBuilder sb = new StringBuilder();
  77. sb.AppendLine(ObjNumber(number));
  78. sb.AppendLine("<<");
  79. if (item.text != String.Empty)
  80. {
  81. sb.Append("/Title ");
  82. PrepareString(item.text, encKey, encrypted, number, sb);
  83. sb.AppendLine();
  84. }
  85. if (item.parent != null)
  86. sb.Append("/Parent ").AppendLine(ObjNumberRef(item.parent.number));
  87. if (item.count > 0)
  88. sb.Append("/Count ").AppendLine(item.count.ToString());
  89. if (item.first != null)
  90. sb.Append("/First ").AppendLine(ObjNumberRef(item.first.number));
  91. if (item.last != null)
  92. sb.Append("/Last ").AppendLine(ObjNumberRef(item.last.number));
  93. if (item.prev != null)
  94. sb.Append("/Prev ").AppendLine(ObjNumberRef(item.prev.number));
  95. if (item.next != null)
  96. sb.Append("/Next ").AppendLine(ObjNumberRef(item.next.number));
  97. if (item.page < pagesRef.Count)
  98. {
  99. sb.Append("/Dest [");
  100. sb.Append(ObjNumberRef(pagesRef[item.page]));
  101. sb.Append(" /XYZ 0 ");
  102. sb.Append(Math.Round(pagesHeights[item.page] - item.offset).ToString());
  103. sb.Append(" 0]");
  104. }
  105. sb.AppendLine(">>");
  106. sb.AppendLine("endobj");
  107. WriteLn(pdf, sb.ToString());
  108. if (item.first != null)
  109. WriteOutline(item.first);
  110. if (item.next != null)
  111. WriteOutline(item.next);
  112. }
  113. }
  114. }