From 3cd867e656bd63470bd2ba0616631fafe8629d13 Mon Sep 17 00:00:00 2001 From: Roberto Fernandez Bautista Date: Thu, 23 Jun 2022 23:29:48 +0100 Subject: [PATCH] WIP - add hyperlinks to pages within pdf --- common/plotters/PDF_plotter.cpp | 48 ++++++++++++++++++++++++++++-- include/plotters/plotters_pslike.h | 7 ++++- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/common/plotters/PDF_plotter.cpp b/common/plotters/PDF_plotter.cpp index c022503789..e738a1eb27 100644 --- a/common/plotters/PDF_plotter.cpp +++ b/common/plotters/PDF_plotter.cpp @@ -720,6 +720,7 @@ void PDF_PLOTTER::ClosePage() std::vector hyperlinkHandles; // Write out all hyperlinks for the page as annotation links + /* for( const std::pair& linkPair : m_urlHyperlinks ) { const BOX2I& box = linkPair.first; @@ -738,8 +739,27 @@ void PDF_PLOTTER::ClosePage() bottomLeft.x, bottomLeft.y, topRight.x, topRight.y, encodeStringForPlotter( url ).c_str() ); closePdfObject(); - } + }*/ + // Write out all "goto" hyperlinks for the page as link annotations (compatible with pdf 1.0) + for( const std::pair& linkPair : m_urlHyperlinksInPage ) + { + const BOX2I& box = linkPair.first; + const wxString& url = linkPair.second; + + VECTOR2D bottomLeft = iuToPdfUserSpace( box.GetPosition() ); + VECTOR2D topRight = iuToPdfUserSpace( box.GetEnd() ); + + BOX2D userSpaceBox; + userSpaceBox.SetOrigin( bottomLeft ); + userSpaceBox.SetEnd( topRight ); + + hyperlinkHandles.push_back( startPdfObject() ); + + m_urlHyperlinksHandles.insert( { hyperlinkHandles.back(), { userSpaceBox, url } } ); + } + // + // TODO use allocPdfObject() !! int hyperLinkArrayHandle = -1; // If we have added any annotation links, create an array containing all the objects @@ -786,6 +806,9 @@ void PDF_PLOTTER::ClosePage() // Mark the page stream as idle m_pageStreamHandle = 0; + + // + m_urlHyperlinksInPage.clear(); } @@ -796,6 +819,8 @@ bool PDF_PLOTTER::StartPlot() // First things first: the customary null object m_xrefTable.clear(); m_xrefTable.push_back( 0 ); + m_urlHyperlinksInPage.clear(); + m_urlHyperlinksHandles.clear(); /* The header (that's easy!). The second line is binary junk required to make the file binary from the beginning (the important thing is @@ -870,6 +895,25 @@ bool PDF_PLOTTER::EndPlot() fputs( ">>\n", m_outputFile ); closePdfObject(); + for( const std::pair>& handlePair : m_urlHyperlinksHandles ) + { + const int& linkhandle = handlePair.first; + const std::pair& linkpair = handlePair.second; + const BOX2D& box = linkpair.first; + const wxString& url = linkpair.second; + + startPdfObject( linkhandle ); + + fprintf( m_outputFile, + "<< /Type /Annot\n" + " /Subtype /Link\n" + " /Rect[%g %g %g %g] /Border[16 16 1]\n" + " /Dest [%d 0 R] >>\n" // /D [3 0 R /FitR –4 399 199 533] + ">>\n", + box.GetLeft(), box.GetBottom(), box.GetRight(), box.GetTop(), m_pageHandles[0] ); + closePdfObject(); + } + /* The page tree: it's a B-tree but luckily we only have few pages! So we use just an array... The handle was allocated at the beginning, now we instantiate the corresponding object */ @@ -1014,6 +1058,6 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos, void PDF_PLOTTER::HyperlinkBoxURL( const BOX2I& aBox, const wxString& aDestinationURL ) { - m_urlHyperlinks.push_back( std::make_pair( aBox, aDestinationURL ) ); + m_urlHyperlinksInPage.push_back( std::make_pair( aBox, aDestinationURL ) ); } diff --git a/include/plotters/plotters_pslike.h b/include/plotters/plotters_pslike.h index ddbc2ed8cd..1c784bb46b 100644 --- a/include/plotters/plotters_pslike.h +++ b/include/plotters/plotters_pslike.h @@ -416,7 +416,12 @@ protected: wxString m_workFilename; FILE* m_workFile; ///< Temporary file to construct the stream before zipping std::vector m_xrefTable; ///< The PDF xref offset table - std::vector> m_urlHyperlinks; ///< List of loaded URLs so far + + ///< List of loaded URLs in current page + std::vector> m_urlHyperlinksInPage; + + ///< Handles for all the hyperlink objects that will be deferred + std::map> m_urlHyperlinksHandles; };