33using Syncfusion . Pdf . Graphics ;
44using Syncfusion . Pdf . Interactive ;
55using Syncfusion . Pdf . Parsing ;
6- using System . Collections . Generic ;
7-
86class 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