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