Skip to content

Commit a81f386

Browse files
committed
972107: Added proper code example.
1 parent 83aaf6b commit a81f386

File tree

7 files changed

+70
-144
lines changed

7 files changed

+70
-144
lines changed

Bookmarks/Multi-PDF-merger-with-paginated-TOC/.NET/Multi-PDF-merger-with-paginated-TOC/Program.cs

Lines changed: 70 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -3,203 +3,129 @@
33
using Syncfusion.Pdf.Graphics;
44
using Syncfusion.Pdf.Interactive;
55
using Syncfusion.Pdf.Parsing;
6-
using System.Collections.Generic;
7-
86
class Program
97
{
108
public static PdfDocument document;
119
public static PdfFont font;
1210

1311
static void Main(string[] args)
1412
{
15-
// Load source PDFs using file streams
16-
using (FileStream fsharpStream = new FileStream(Path.GetFullPath(@"Data/Fsharp_Succinctly.pdf"), FileMode.Open, FileAccess.Read))
17-
using (PdfLoadedDocument fsharpDoc = new PdfLoadedDocument(fsharpStream))
18-
19-
using (FileStream httpStream = new FileStream(Path.GetFullPath(@"Data/HTTP_Succinctly.pdf"), FileMode.Open, FileAccess.Read))
20-
using (PdfLoadedDocument httpDoc = new PdfLoadedDocument(httpStream))
21-
22-
using (FileStream windowsStoreStream = new FileStream(Path.GetFullPath(@"Data/WindowsStoreApps_Succinctly.pdf"), FileMode.Open, FileAccess.Read))
23-
using (PdfLoadedDocument windowsStoreDoc = new PdfLoadedDocument(windowsStoreStream))
13+
// Load the PDF documents
14+
PdfLoadedDocument doc1 = new PdfLoadedDocument(Path.GetFullPath(@"Data/Input1.pdf"));
15+
PdfLoadedDocument doc2 = new PdfLoadedDocument(Path.GetFullPath(@"Data/Input2.pdf"));
16+
PdfLoadedDocument doc3 = new PdfLoadedDocument(Path.GetFullPath(@"Data/Input3.pdf"));
17+
object[] documentsToMerge = { doc1, doc2, doc3 };
18+
19+
// Create a new PDF document
20+
using (document = new PdfDocument())
2421
{
22+
document.PageSettings.Size = doc1.Pages[0].Graphics.Size;
2523

26-
// Store all loaded documents in an array
27-
PdfLoadedDocument[] docs = { fsharpDoc, httpDoc, windowsStoreDoc };
28-
29-
// Create new document
30-
document = new PdfDocument();
31-
document.PageSettings.Size = fsharpDoc.Pages[0].Size;
32-
33-
// Estimate TOC pages needed
34-
int totalEntries = 60;
35-
int entriesPerPage = 30;
36-
int tocPages = (int)Math.Ceiling(totalEntries / (double)entriesPerPage);
24+
// Add initial TOC page
25+
PdfPage tocPage = document.Pages.Add();
26+
font = new PdfStandardFont(PdfFontFamily.Helvetica, 10f);
3727

38-
// Add TOC pages
39-
List<PdfPage> tocPagesList = new List<PdfPage>();
40-
for (int i = 0; i < tocPages; i++)
41-
{
42-
PdfPage tocPage = document.Pages.Add();
43-
tocPagesList.Add(tocPage);
44-
if (i == 0)
45-
{
46-
font = new PdfStandardFont(PdfFontFamily.Helvetica, 10f);
47-
PdfStringFormat format = new PdfStringFormat(PdfTextAlignment.Center, PdfVerticalAlignment.Middle);
48-
tocPage.Graphics.DrawString("Table Of Contents", font, PdfBrushes.Black,
49-
new RectangleF(PointF.Empty, new SizeF(tocPage.Graphics.ClientSize.Width, 20)), format);
50-
}
51-
}
28+
// Draw TOC title
29+
PdfStringFormat format = new PdfStringFormat(PdfTextAlignment.Center, PdfVerticalAlignment.Middle);
30+
tocPage.Graphics.DrawString("Table Of Contents", font, PdfBrushes.Black,
31+
new RectangleF(PointF.Empty, new SizeF(tocPage.Graphics.ClientSize.Width, 20)), format);
5232

53-
// Merge PDFs after TOC pages
54-
PdfDocument.Merge(document, docs);
33+
// Merge the loaded documents into the new document
34+
PdfDocument.Merge(document, documentsToMerge);
5535

56-
// Define TOC entries (title and corresponding page index)
57-
List<(string Title, int PageIndex)> tocEntries = GetTocEntries();
58-
// Adjust TOC entries
59-
tocEntries = AdjustTOCEntriesWithOffset(tocEntries, tocPages);
60-
// Draw TOC entries
36+
// Initialize TOC entry layout
6137
float currentY = 30;
62-
int tocPageIndex = 0;
63-
PdfPage currentTocPage = tocPagesList[tocPageIndex];
64-
foreach (var (title, pageIndex) in tocEntries)
38+
int totalEntries = 30;
39+
int pageOffset = 1;
40+
// Generate TOC entries dynamically
41+
for (int i = 0; i < totalEntries; i++)
6542
{
66-
if (currentY > currentTocPage.Graphics.ClientSize.Height - 50)
43+
// If current Y exceeds page height, add a new TOC page
44+
if (currentY > tocPage.Graphics.ClientSize.Height - 50)
6745
{
68-
tocPageIndex++;
69-
currentTocPage = tocPagesList[tocPageIndex];
46+
int currentPageIndex = document.Pages.IndexOf(tocPage);
47+
tocPage = document.Pages.Add();
48+
document.Pages.Insert(currentPageIndex + 1, tocPage);
7049
currentY = 30;
7150
}
7251

73-
currentY = AddBookmark(document.Pages[pageIndex], currentTocPage, title, currentY);
74-
}
75-
76-
//Create file stream.
77-
using (FileStream outputFileStream = new FileStream(Path.GetFullPath(@"Output/Output.pdf"), FileMode.Create, FileAccess.ReadWrite))
78-
{
79-
//Save the PDF document to file stream.
80-
document.Save(outputFileStream);
81-
}
82-
//Close the document
83-
document.Close(true);
84-
}
85-
}
52+
// Calculate page index for bookmark
53+
int pageIndex = Math.Min(document.Pages.Count - 1, pageOffset + i);
8654

87-
// Generates a list of Table of Contents (TOC) entries with titles and corresponding page indices.
88-
static List<(string Title, int PageIndex)> GetTocEntries()
89-
{
90-
List<(string Title, int PageIndex)> entries = new List<(string, int)>();
55+
// Simulate long TOC entry title
56+
string longTitle = $"Chapter {i + 1} - This is a very long table of contents entry designed to test how the text wrapping functionality behaves when the content exceeds the width of the page layout in the PDF document.";
9157

92-
for (int i = 1; i <= 60; i++)
93-
{
94-
// Pages 1–20: F# document
95-
if (i <= 20)
96-
{
97-
entries.Add(($"F# - This is first document {i}", i));
98-
}
99-
// Pages 21–40: HTTP document
100-
else if (i > 20 && i <= 40)
101-
{
102-
entries.Add(($"HTTP - This is second document {i}", i));
103-
}
104-
// Pages 41–60: Windows Store Apps document
105-
else
106-
{
107-
entries.Add(($"Windows Store Apps - This is third document {i}", i));
58+
// Add bookmark and TOC entry
59+
currentY = AddBookmark(document.Pages[pageIndex], tocPage, longTitle, currentY);
10860
}
109-
}
110-
111-
return entries;
112-
}
11361

114-
//Adjusts the page indices of the Table of Contents (TOC) entries by adding an offset.
115-
public static List<(string Title, int PageIndex)> AdjustTOCEntriesWithOffset(List<(string Title, int PageIndex)> tocEntries, int tocPages)
116-
{
117-
List<(string, int)> adjustedList = new List<(string, int)>();
118-
119-
// Loop through each TOC entry and add the TOC page count to its page index
120-
foreach (var (title, pageIndex) in tocEntries)
121-
{
122-
adjustedList.Add((title, pageIndex + tocPages));
62+
// Save the final PDF
63+
document.Save(Path.GetFullPath(@"Output/Output.pdf"));
12364
}
124-
125-
return adjustedList;
12665
}
12766

128-
// Adding bookmarks and drawing TOC entries
129-
private static float AddBookmark(PdfPage page, PdfPage toc, string content, float currentY)
67+
// Adds a bookmark and corresponding TOC entry to the document.
68+
private static float AddBookmark(PdfPage targetPage, PdfPage tocPage, string title, float currentY)
13069
{
131-
// Add a new bookmark to the document with the given title
132-
PdfBookmark bookmark = document.Bookmarks.Add(content);
70+
// Create bookmark
71+
PdfBookmark bookmark = document.Bookmarks.Add(title);
13372

134-
// Draw the TOC entry text on the TOC page and get the updated Y-position
135-
float newY = AddTableOfContent(page, toc, content, new PointF(0, currentY));
73+
// Add TOC entry and get updated Y position
74+
float newY = AddTableOfContent(targetPage, tocPage, title, new PointF(0, currentY));
13675

137-
// Create a named destination pointing to the specified page and location
138-
PdfNamedDestination namedDestination = new PdfNamedDestination(content)
76+
// Create named destination for navigation
77+
PdfNamedDestination namedDestination = new PdfNamedDestination(title)
13978
{
140-
Destination = new PdfDestination(page, new PointF(0, currentY))
79+
Destination = new PdfDestination(targetPage, new PointF(0, currentY))
14180
{
142-
Mode = PdfDestinationMode.FitToPage // Ensures the destination fits the entire page in view
81+
Mode = PdfDestinationMode.FitToPage
14382
}
14483
};
14584

146-
// Add the named destination to the document's collection
14785
document.NamedDestinationCollection.Add(namedDestination);
148-
149-
// Link the bookmark to the named destination
15086
bookmark.NamedDestination = namedDestination;
15187

152-
// Return the updated Y-position for the next TOC entry
15388
return newY;
15489
}
15590

156-
//Draws a TOC entry on the specified page, adds the corresponding page number, and creates a clickable link that navigates to the target content page.
157-
private static float AddTableOfContent(PdfPage page, PdfPage toc, string content, PointF point)
91+
// Draws TOC entry text, page number, and adds clickable link annotation.
92+
private static float AddTableOfContent(PdfPage targetPage, PdfPage tocPage, string title, PointF position)
15893
{
159-
// Define the width available for the TOC entry text
160-
float textWidth = toc.Graphics.ClientSize.Width - 60;
161-
162-
// Define the bounds where the TOC entry will be drawn
163-
RectangleF textBounds = new RectangleF(point.X, point.Y, textWidth, 100);
94+
float textWidth = tocPage.Graphics.ClientSize.Width - 60;
95+
RectangleF textBounds = new RectangleF(position.X, position.Y, textWidth, 100);
16496

165-
// Create a text element for the TOC entry
166-
PdfTextElement element = new PdfTextElement(content, font, PdfBrushes.Blue);
167-
168-
// Set layout format to fit within the page and allow pagination if needed
169-
PdfLayoutFormat format = new PdfLayoutFormat
97+
// Draw TOC entry text
98+
PdfTextElement textElement = new PdfTextElement(title, font, PdfBrushes.Blue);
99+
PdfLayoutFormat layoutFormat = new PdfLayoutFormat
170100
{
171101
Break = PdfLayoutBreakType.FitPage,
172102
Layout = PdfLayoutType.Paginate
173103
};
174104

175-
// Draw the TOC entry text and get the layout result
176-
PdfLayoutResult result = element.Draw(toc, textBounds, format);
105+
PdfLayoutResult layoutResult = textElement.Draw(tocPage, textBounds, layoutFormat);
177106

178-
// Draw the corresponding page number on the right side of the TOC page
179-
string pageNum = (document.Pages.IndexOf(page) + 1).ToString();
180-
PdfTextElement pageNumber = new PdfTextElement(pageNum, font, PdfBrushes.Black);
181-
pageNumber.Draw(toc, new PointF(toc.Graphics.ClientSize.Width - 40, point.Y));
107+
// Draw page number
108+
string pageNumberText = (document.Pages.IndexOf(targetPage) + 1).ToString();
109+
PdfTextElement pageNumberElement = new PdfTextElement(pageNumberText, font, PdfBrushes.Black);
110+
pageNumberElement.Draw(tocPage, new PointF(tocPage.Graphics.ClientSize.Width - 40, position.Y));
182111

183-
// Create a clickable link annotation over the TOC entry text
184-
RectangleF bounds = result.Bounds;
112+
// Add clickable link annotation
113+
RectangleF bounds = layoutResult.Bounds;
185114
bounds.Width = textWidth;
186115

187-
PdfDocumentLinkAnnotation documentLinkAnnotation = new PdfDocumentLinkAnnotation(bounds)
116+
PdfDocumentLinkAnnotation linkAnnotation = new PdfDocumentLinkAnnotation(bounds)
188117
{
189118
AnnotationFlags = PdfAnnotationFlags.NoRotate,
190-
Text = content,
191-
Color = Color.Transparent, // Invisible clickable area
192-
Destination = new PdfDestination(page),
193-
Border = new PdfAnnotationBorder(0) // No visible border
119+
Text = title,
120+
Color = Color.Transparent,
121+
Destination = new PdfDestination(targetPage),
122+
Border = new PdfAnnotationBorder(0)
194123
};
195124

196-
// Set the destination location on the target page
197-
documentLinkAnnotation.Destination.Location = point;
198-
199-
// Add the link annotation to the TOC page
200-
toc.Annotations.Add(documentLinkAnnotation);
125+
linkAnnotation.Destination.Location = position;
126+
tocPage.Annotations.Add(linkAnnotation);
201127

202-
// Return the updated Y-position for the next TOC entry
203-
return result.Bounds.Bottom + 10;
128+
// Return updated Y position for next entry
129+
return layoutResult.Bounds.Bottom + 10;
204130
}
205-
}
131+
}

0 commit comments

Comments
 (0)