drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx | 3 - editeng/source/editeng/impedit3.cxx | 2 include/vcl/pdfextoutdevdata.hxx | 5 + include/vcl/pdfwriter.hxx | 2 sc/source/filter/excel/xecontent.cxx | 3 - sc/source/filter/excel/xestring.cxx | 3 - sc/source/ui/view/output2.cxx | 4 - sd/source/ui/dlg/tpaction.cxx | 21 ------- sd/source/ui/inc/tpaction.hxx | 4 - sd/source/ui/unoidl/unomodel.cxx | 35 ++++++++++--- sw/inc/EnhancedPDFExportHelper.hxx | 3 - sw/source/core/text/EnhancedPDFExportHelper.cxx | 32 +++++++---- vcl/inc/pdf/pdfwriter_impl.hxx | 6 +- vcl/qa/cppunit/pdfexport/pdfexport.cxx | 8 ++ vcl/source/gdi/pdfextoutdevdata.cxx | 6 +- vcl/source/gdi/pdfwriter.cxx | 4 - vcl/source/gdi/pdfwriter_impl.cxx | 13 ++++ 17 files changed, 96 insertions(+), 58 deletions(-)
New commits: commit 992529ad3c143a7a95124851da6a712cb3d65605 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Tue Oct 25 14:16:48 2022 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Tue Nov 1 11:14:38 2022 +0100 tdf#151484 Data Validity list looses separation when saving as XLS regression from commit fbb41798b86c5ed35eb80aa07a5ee7c9866ac4e8 Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Fri Mar 18 09:46:52 2022 +0200 tdf#133603 remove some string copying Change-Id: Ie241a7d5e54673b35c643c7c20dc100ba7925647 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141808 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> (cherry picked from commit 9ff56812741029ad17204cff53357751687d9b6c) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141834 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sc/source/filter/excel/xecontent.cxx b/sc/source/filter/excel/xecontent.cxx index f116e0e497f0..65f8bb2f435e 100644 --- a/sc/source/filter/excel/xecontent.cxx +++ b/sc/source/filter/excel/xecontent.cxx @@ -1775,7 +1775,8 @@ XclExpDV::XclExpDV( const XclExpRoot& rRoot, sal_uLong nScHandle ) : sFormulaBuf.append( aToken ); if (nStringIx<0) break; - mxString1->Append(u"\0"); + sal_Unicode cUnicodeChar = 0; + mxString1->Append( std::u16string_view(&cUnicodeChar, 1) ); sFormulaBuf.append( ',' ); sListBuf.append( ',' ); } diff --git a/sc/source/filter/excel/xestring.cxx b/sc/source/filter/excel/xestring.cxx index cb76518e6b41..295f37709594 100644 --- a/sc/source/filter/excel/xestring.cxx +++ b/sc/source/filter/excel/xestring.cxx @@ -148,7 +148,8 @@ void XclExpString::AppendByte( sal_Unicode cChar, rtl_TextEncoding eTextEnc ) { if( !cChar ) { - BuildAppend( "\0" ); + char cByteChar = 0; + BuildAppend( std::string_view(&cByteChar, 1) ); } else { commit c5a8728d8f9e943bad4bb55dbde30ae9eceefecf Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Tue Oct 25 13:41:05 2022 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Tue Nov 1 11:14:20 2022 +0100 tdf#148934 PDF/UA export: add Contents entry to Link annotations * Specification: ISO 14289-1:2014, Clause: 7.18.5, Test number: 2 Links shall contain an alternate description via their Contents key as described in ISO 32000-1:2008, 14.9.3. These links are created all over the code, in some cases it's a bit dubious what the content/alt-text should be, but let's try to use the most suitable looking bit of text in whatever the context is. * Specification: ISO 14289-1:2014, Clause: 7.18.3, Test number: 1 Every page on which there is an annotation shall contain in its page dictionary the key Tabs, and its value shall be S. Change-Id: I7b63feb759f0c75047f854ed9997918f829a537e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141826 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> (cherry picked from commit fa3f04bdd4f73a1b3be70dfb709c44638ef7e3d9) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141873 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index de95df83dc8d..f8ea72174d8f 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -1252,7 +1252,8 @@ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D( static_cast<sal_Int32>(ceil(aViewRange.getMaxX())), static_cast<sal_Int32>(ceil(aViewRange.getMaxY()))); vcl::PDFExtOutDevBookmarkEntry aBookmark; - aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic); + OUString const content(rFieldPrimitive.getValue("Representation")); + aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic, content); aBookmark.aBookmark = aURL; std::vector<vcl::PDFExtOutDevBookmarkEntry>& rBookmarks = mpPDFExtOutDevData->GetBookmarks(); rBookmarks.push_back(aBookmark); diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index e73bf2aff9c8..f0f6c0e728d1 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -3684,7 +3684,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po tools::Rectangle aRect( aTopLeft, rTextPortion.GetSize() ); vcl::PDFExtOutDevBookmarkEntry aBookmark; - aBookmark.nLinkId = pPDFExtOutDevData->CreateLink( aRect ); + aBookmark.nLinkId = pPDFExtOutDevData->CreateLink(aRect, pUrlField->GetRepresentation()); aBookmark.aBookmark = pUrlField->GetURL(); std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks(); rBookmarks.push_back( aBookmark ); diff --git a/include/vcl/pdfextoutdevdata.hxx b/include/vcl/pdfextoutdevdata.hxx index 39a8bbb30d56..45cb71682f12 100644 --- a/include/vcl/pdfextoutdevdata.hxx +++ b/include/vcl/pdfextoutdevdata.hxx @@ -252,11 +252,14 @@ public: number of page the link is on (as returned by NewPage) or -1 in which case the current page is used + @param rAltText + Alt text for the link + @returns the link id (to be used in SetLinkDest, SetLinkURL) or -1 if page id does not exist */ - sal_Int32 CreateLink( const tools::Rectangle& rRect, sal_Int32 nPageNr = -1 ); + sal_Int32 CreateLink(const tools::Rectangle& rRect, OUString const& rAltText, sal_Int32 nPageNr = -1); /// Create a Screen annotation. sal_Int32 CreateScreen(const tools::Rectangle& rRect, sal_Int32 nPageNr); diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx index 8764f3f49c8e..1aaea5a7c3f8 100644 --- a/include/vcl/pdfwriter.hxx +++ b/include/vcl/pdfwriter.hxx @@ -916,7 +916,7 @@ The following structure describes the permissions used in PDF security the link id (to be used in SetLinkDest, SetLinkURL) or -1 if page id does not exist */ - sal_Int32 CreateLink( const tools::Rectangle& rRect, sal_Int32 nPageNr ); + sal_Int32 CreateLink(const tools::Rectangle& rRect, sal_Int32 nPageNr, OUString const& rAltText); /// Creates a screen annotation. sal_Int32 CreateScreen(const tools::Rectangle& rRect, sal_Int32 nPageNr); diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index cdd9329d3fcb..5c234df7953e 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -862,10 +862,10 @@ static void lcl_DoHyperlinkResult( const OutputDevice* pDev, const tools::Rectan vcl::PDFExtOutDevData* pPDFData = dynamic_cast< vcl::PDFExtOutDevData* >( pDev->GetExtOutDevData() ); OUString aURL; + OUString aCellText; if (rCell.meType == CELLTYPE_FORMULA) { ScFormulaCell* pFCell = rCell.mpFormula; - OUString aCellText; if ( pFCell->IsHyperLinkCell() ) pFCell->GetURLResult( aURL, aCellText ); } @@ -873,7 +873,7 @@ static void lcl_DoHyperlinkResult( const OutputDevice* pDev, const tools::Rectan if ( !aURL.isEmpty() && pPDFData ) { vcl::PDFExtOutDevBookmarkEntry aBookmark; - aBookmark.nLinkId = pPDFData->CreateLink( rRect ); + aBookmark.nLinkId = pPDFData->CreateLink(rRect, aCellText); aBookmark.aBookmark = aURL; std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks(); rBookmarks.push_back( aBookmark ); diff --git a/sd/source/ui/dlg/tpaction.cxx b/sd/source/ui/dlg/tpaction.cxx index c5ccd758a321..f89fa51f5b5d 100644 --- a/sd/source/ui/dlg/tpaction.cxx +++ b/sd/source/ui/dlg/tpaction.cxx @@ -798,25 +798,4 @@ OUString SdTPAction::GetEditText( bool bFullDocDestination ) return aStr; } -TranslateId SdTPAction::GetClickActionSdResId( presentation::ClickAction eCA ) -{ - switch( eCA ) - { - case presentation::ClickAction_NONE: return STR_CLICK_ACTION_NONE; - case presentation::ClickAction_PREVPAGE: return STR_CLICK_ACTION_PREVPAGE; - case presentation::ClickAction_NEXTPAGE: return STR_CLICK_ACTION_NEXTPAGE; - case presentation::ClickAction_FIRSTPAGE: return STR_CLICK_ACTION_FIRSTPAGE; - case presentation::ClickAction_LASTPAGE: return STR_CLICK_ACTION_LASTPAGE; - case presentation::ClickAction_BOOKMARK: return STR_CLICK_ACTION_BOOKMARK; - case presentation::ClickAction_DOCUMENT: return STR_CLICK_ACTION_DOCUMENT; - case presentation::ClickAction_PROGRAM: return STR_CLICK_ACTION_PROGRAM; - case presentation::ClickAction_MACRO: return STR_CLICK_ACTION_MACRO; - case presentation::ClickAction_SOUND: return STR_CLICK_ACTION_SOUND; - case presentation::ClickAction_VERB: return STR_CLICK_ACTION_VERB; - case presentation::ClickAction_STOPPRESENTATION: return STR_CLICK_ACTION_STOPPRESENTATION; - default: OSL_FAIL( "No StringResource for ClickAction available!" ); - } - return {}; -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/inc/tpaction.hxx b/sd/source/ui/inc/tpaction.hxx index f04f50fddfce..893192d256f2 100644 --- a/sd/source/ui/inc/tpaction.hxx +++ b/sd/source/ui/inc/tpaction.hxx @@ -82,9 +82,9 @@ private: void SetActualClickAction( css::presentation::ClickAction eCA ); void SetEditText( OUString const & rStr ); OUString GetEditText( bool bURL = false ); - static TranslateId GetClickActionSdResId(css::presentation::ClickAction eCA); - public: + SD_DLLPUBLIC static TranslateId GetClickActionSdResId(css::presentation::ClickAction eCA); + SdTPAction(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); virtual ~SdTPAction() override; diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index ff66696d7d8f..b316f9f1f4da 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -44,6 +44,7 @@ #include <sal/log.hxx> #include <editeng/unofield.hxx> #include <notifydocumentevent.hxx> +#include <tpaction.hxx> #include <unomodel.hxx> #include "unopool.hxx" #include <sfx2/lokhelper.hxx> @@ -135,6 +136,27 @@ using namespace ::cppu; using namespace ::com::sun::star; using namespace ::sd; +TranslateId SdTPAction::GetClickActionSdResId( presentation::ClickAction eCA ) +{ + switch( eCA ) + { + case presentation::ClickAction_NONE: return STR_CLICK_ACTION_NONE; + case presentation::ClickAction_PREVPAGE: return STR_CLICK_ACTION_PREVPAGE; + case presentation::ClickAction_NEXTPAGE: return STR_CLICK_ACTION_NEXTPAGE; + case presentation::ClickAction_FIRSTPAGE: return STR_CLICK_ACTION_FIRSTPAGE; + case presentation::ClickAction_LASTPAGE: return STR_CLICK_ACTION_LASTPAGE; + case presentation::ClickAction_BOOKMARK: return STR_CLICK_ACTION_BOOKMARK; + case presentation::ClickAction_DOCUMENT: return STR_CLICK_ACTION_DOCUMENT; + case presentation::ClickAction_PROGRAM: return STR_CLICK_ACTION_PROGRAM; + case presentation::ClickAction_MACRO: return STR_CLICK_ACTION_MACRO; + case presentation::ClickAction_SOUND: return STR_CLICK_ACTION_SOUND; + case presentation::ClickAction_VERB: return STR_CLICK_ACTION_VERB; + case presentation::ClickAction_STOPPRESENTATION: return STR_CLICK_ACTION_STOPPRESENTATION; + default: OSL_FAIL( "No StringResource for ClickAction available!" ); + } + return {}; +} + namespace { class SdUnoForbiddenCharsTable : public SvxUnoForbiddenCharsTable, @@ -1643,20 +1665,21 @@ static void ImplPDFExportShapeInteraction( const uno::Reference< drawing::XShape uno::Any aAny( xShapePropSet->getPropertyValue( "OnClick" ) ); if ( aAny >>= eCa ) { + OUString const actionName(SdResId(SdTPAction::GetClickActionSdResId(eCa))); switch ( eCa ) { case presentation::ClickAction_LASTPAGE : { sal_Int32 nCount = rDoc.GetSdPageCount( PageKind::Standard ); sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nCount - 1, vcl::PDFWriter::DestAreaType::FitRectangle ); - sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink( aLinkRect ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); } break; case presentation::ClickAction_FIRSTPAGE : { sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, 0, vcl::PDFWriter::DestAreaType::FitRectangle ); - sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink( aLinkRect ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); } break; @@ -1666,7 +1689,7 @@ static void ImplPDFExportShapeInteraction( const uno::Reference< drawing::XShape if ( nDestPage ) nDestPage--; sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nDestPage, vcl::PDFWriter::DestAreaType::FitRectangle ); - sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink( aLinkRect ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); } break; @@ -1677,7 +1700,7 @@ static void ImplPDFExportShapeInteraction( const uno::Reference< drawing::XShape if ( nDestPage > nLastPage ) nDestPage = nLastPage; sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nDestPage, vcl::PDFWriter::DestAreaType::FitRectangle ); - sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink( aLinkRect ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); } break; @@ -1695,7 +1718,7 @@ static void ImplPDFExportShapeInteraction( const uno::Reference< drawing::XShape case presentation::ClickAction_DOCUMENT : case presentation::ClickAction_PROGRAM : { - sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink( aLinkRect ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkURL( nLinkId, aBookmark ); } break; @@ -1705,7 +1728,7 @@ static void ImplPDFExportShapeInteraction( const uno::Reference< drawing::XShape if ( nPage != -1 ) { sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle ); - sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink( aLinkRect ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); } } diff --git a/sw/inc/EnhancedPDFExportHelper.hxx b/sw/inc/EnhancedPDFExportHelper.hxx index eb813773abb3..8b72001f0fb7 100644 --- a/sw/inc/EnhancedPDFExportHelper.hxx +++ b/sw/inc/EnhancedPDFExportHelper.hxx @@ -228,7 +228,8 @@ class SwEnhancedPDFExportHelper void MakeHeaderFooterLinks( vcl::PDFExtOutDevData& rPDFExtOutDevData, const SwTextNode& rTNd, const SwRect& rLinkRect, - sal_Int32 nDestId, const OUString& rURL, bool bIntern ) const; + sal_Int32 nDestId, const OUString& rURL, + bool bIntern, OUString const& rContent) const; public: diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx b/sw/source/core/text/EnhancedPDFExportHelper.cxx index ccec950bb954..f0dd67d305fa 100644 --- a/sw/source/core/text/EnhancedPDFExportHelper.cxx +++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx @@ -1651,6 +1651,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() SwRects aTmp; aTmp.insert( aTmp.begin(), mrSh.SwCursorShell::GetCursor_()->begin(), mrSh.SwCursorShell::GetCursor_()->end() ); OSL_ENSURE( !aTmp.empty(), "Enhanced pdf export - rectangles are missing" ); + OUString const altText(mrSh.GetSelText()); const SwPageFrame* pSelectionPage = static_cast<const SwPageFrame*>( mrSh.GetLayout()->Lower() ); @@ -1704,7 +1705,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() // Link Export tools::Rectangle aRect(SwRectToPDFRect(pSelectionPage, rLinkRect.SVRect())); const sal_Int32 nLinkId = - pPDFExtOutDevData->CreateLink(aRect, aLinkPageNum); + pPDFExtOutDevData->CreateLink(aRect, altText, aLinkPageNum); // Store link info for tagged pdf output: const IdMapEntry aLinkEntry( rLinkRect, nLinkId ); @@ -1718,7 +1719,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() // #i44368# Links in Header/Footer if ( bHeaderFooter ) - MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, aURL, bIntern ); + MakeHeaderFooterLinks(*pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, aURL, bIntern, altText); } } } @@ -1778,7 +1779,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() { Point aNullPt; const SwRect aLinkRect = pFrameFormat->FindLayoutRect( false, &aNullPt ); - + OUString const formatName(pFrameFormat->GetName()); // Link PageNums std::vector<sal_Int32> aLinkPageNums = CalcOutputPageNums( aLinkRect ); @@ -1787,7 +1788,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() { tools::Rectangle aRect(SwRectToPDFRect(pCurrPage, aLinkRect.SVRect())); const sal_Int32 nLinkId = - pPDFExtOutDevData->CreateLink(aRect, aLinkPageNum); + pPDFExtOutDevData->CreateLink(aRect, formatName, aLinkPageNum); // Connect Link and Destination: if ( bIntern ) @@ -1804,7 +1805,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() { const SwTextNode* pTNd = pPosition->nNode.GetNode().GetTextNode(); if ( pTNd ) - MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, aLinkRect, nDestId, aURL, bIntern ); + MakeHeaderFooterLinks(*pPDFExtOutDevData, *pTNd, aLinkRect, nDestId, aURL, bIntern, formatName); } } } @@ -1894,6 +1895,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() // #i44368# Links in Header/Footer const SwPosition aPos( *pTNd ); const bool bHeaderFooter = pDoc->IsInHeaderFooter( aPos.nNode ); + OUString const content(pField->ExpandField(true, mrSh.GetLayout())); // Create links for all selected rectangles: const size_t nNumOfRects = aTmp.size(); @@ -1910,7 +1912,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() // Link Export aRect = SwRectToPDFRect(pCurrPage, rLinkRect.SVRect()); const sal_Int32 nLinkId = - pPDFExtOutDevData->CreateLink(aRect, aLinkPageNum); + pPDFExtOutDevData->CreateLink(aRect, content, aLinkPageNum); // Store link info for tagged pdf output: const IdMapEntry aLinkEntry( rLinkRect, nLinkId ); @@ -1922,7 +1924,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() // #i44368# Links in Header/Footer if ( bHeaderFooter ) { - MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, "", true ); + MakeHeaderFooterLinks(*pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, "", true, content); } } } @@ -2004,8 +2006,11 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() } tools::Rectangle aFootnoteSymbolRect = SwRectToPDFRect(pCurrPage, fnSymbolRect.SVRect()); + OUString const numStrSymbol(pTextFootnote->GetFootnote().GetViewNumStr(*pDoc, mrSh.GetLayout(), true)); + OUString const numStrRef(pTextFootnote->GetFootnote().GetViewNumStr(*pDoc, mrSh.GetLayout(), false)); + // Export back link - const sal_Int32 nBackLinkId = pPDFExtOutDevData->CreateLink(aFootnoteSymbolRect, nDestPageNum); + const sal_Int32 nBackLinkId = pPDFExtOutDevData->CreateLink(aFootnoteSymbolRect, numStrSymbol, nDestPageNum); // Destination Export const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest(aRect, nDestPageNum); mrSh.GotoFootnoteAnchor(); @@ -2014,7 +2019,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() pCurrPage = static_cast<const SwPageFrame*>( mrSh.GetLayout()->Lower() ); // Link Export aRect = SwRectToPDFRect(pCurrPage, aLinkRect.SVRect()); - const sal_Int32 nLinkId = pPDFExtOutDevData->CreateLink(aRect, aLinkPageNum); + const sal_Int32 nLinkId = pPDFExtOutDevData->CreateLink(aRect, numStrRef, aLinkPageNum); // Back link destination Export const sal_Int32 nBackDestId = pPDFExtOutDevData->CreateDest(aRect, aLinkPageNum); // Store link info for tagged pdf output: @@ -2229,6 +2234,8 @@ void SwEnhancedPDFExportHelper::ExportAuthorityEntryLinks() continue; } + OUString const content(rAuthorityField.ExpandField(true, mrSh.GetLayout())); + // Select the field. mrSh.SwCursorShell::SetMark(); mrSh.SwCursorShell::Right(1, CRSR_SKIP_CHARS); @@ -2239,7 +2246,7 @@ void SwEnhancedPDFExportHelper::ExportAuthorityEntryLinks() for (const auto& rLinkPageNum : CalcOutputPageNums(rLinkRect)) { tools::Rectangle aRect(SwRectToPDFRect(pPageFrame, rLinkRect.SVRect())); - sal_Int32 nLinkId = pPDFExtOutDevData->CreateLink(aRect, rLinkPageNum); + sal_Int32 nLinkId = pPDFExtOutDevData->CreateLink(aRect, content, rLinkPageNum); IdMapEntry aLinkEntry(rLinkRect, nLinkId); s_aLinkIdMap.push_back(aLinkEntry); pPDFExtOutDevData->SetLinkURL(nLinkId, rURL); @@ -2323,7 +2330,8 @@ void SwEnhancedPDFExportHelper::MakeHeaderFooterLinks( vcl::PDFExtOutDevData& rP const SwRect& rLinkRect, sal_Int32 nDestId, const OUString& rURL, - bool bIntern ) const + bool bIntern, + OUString const& rContent) const { // We assume, that the primary link has just been exported. Therefore // the offset of the link rectangle calculates as follows: @@ -2350,7 +2358,7 @@ void SwEnhancedPDFExportHelper::MakeHeaderFooterLinks( vcl::PDFExtOutDevData& rP // Link Export tools::Rectangle aRect(SwRectToPDFRect(pPageFrame, aHFLinkRect.SVRect())); const sal_Int32 nHFLinkId = - rPDFExtOutDevData.CreateLink(aRect, aHFLinkPageNum); + rPDFExtOutDevData.CreateLink(aRect, rContent, aHFLinkPageNum); // Connect Link and Destination: if ( bIntern ) diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx index 0919414c4dc5..274f65f23a64 100644 --- a/vcl/inc/pdf/pdfwriter_impl.hxx +++ b/vcl/inc/pdf/pdfwriter_impl.hxx @@ -394,10 +394,12 @@ struct PDFLink : public PDFAnnotation sal_Int32 m_nDest; // set to -1 for URL, to a dest else OUString m_aURL; sal_Int32 m_nStructParent; // struct parent entry + OUString m_AltText; - PDFLink() + PDFLink(OUString const& rAltText) : m_nDest( -1 ), m_nStructParent( -1 ) + , m_AltText(rAltText) {} }; @@ -1240,7 +1242,7 @@ public: sal_Int32 emitDocumentMetadata(); // links - sal_Int32 createLink( const tools::Rectangle& rRect, sal_Int32 nPageNr ); + sal_Int32 createLink(const tools::Rectangle& rRect, sal_Int32 nPageNr, OUString const& rAltText); sal_Int32 createDest( const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType ); sal_Int32 registerDestReference( sal_Int32 nDestId, const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType ); void setLinkDest( sal_Int32 nLinkId, sal_Int32 nDestId ); diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx index 51d5e93b9529..df88c65882cf 100644 --- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx +++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx @@ -3465,6 +3465,9 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testURIs) CPPUNIT_ASSERT_EQUAL( OString("Annot"), static_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Type"))->GetValue()); + CPPUNIT_ASSERT_EQUAL( + OString("Link"), + static_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Subtype"))->GetValue()); auto pAction = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pAnnot->Lookup("A")); CPPUNIT_ASSERT(pAction); auto pURIElem @@ -3472,6 +3475,11 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testURIs) CPPUNIT_ASSERT(pURIElem); // Check it matches CPPUNIT_ASSERT_EQUAL(URIs[i].out, pURIElem->GetValue()); + // tdf#148934 check a11y + CPPUNIT_ASSERT_EQUAL( + OUString("Test pdf"), + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast<vcl::filter::PDFHexStringElement*>(pAnnot->Lookup("Contents")))); } } diff --git a/vcl/source/gdi/pdfextoutdevdata.cxx b/vcl/source/gdi/pdfextoutdevdata.cxx index 96a77a15d94d..00e4f4a9c1bd 100644 --- a/vcl/source/gdi/pdfextoutdevdata.cxx +++ b/vcl/source/gdi/pdfextoutdevdata.cxx @@ -181,11 +181,12 @@ void GlobalSyncData::PlayGlobalActions( PDFWriter& rWriter ) rWriter.Push( PushFlags::MAPMODE ); rWriter.SetMapMode( mParaMapModes.front() ); mParaMapModes.pop_front(); - mParaIds.push_back( rWriter.CreateLink( mParaRects.front(), mParaInts.front() ) ); + mParaIds.push_back( rWriter.CreateLink(mParaRects.front(), mParaInts.front(), mParaOUStrings.front()) ); // resolve LinkAnnotation structural attribute rWriter.SetLinkPropertyID( mParaIds.back(), sal_Int32(mParaIds.size()-1) ); mParaRects.pop_front(); mParaInts.pop_front(); + mParaOUStrings.pop_front(); rWriter.Pop(); } break; @@ -659,12 +660,13 @@ sal_Int32 PDFExtOutDevData::CreateDest( const tools::Rectangle& rRect, sal_Int32 mpGlobalSyncData->mParaDestAreaTypes.push_back( eType ); return mpGlobalSyncData->mCurId++; } -sal_Int32 PDFExtOutDevData::CreateLink( const tools::Rectangle& rRect, sal_Int32 nPageNr ) +sal_Int32 PDFExtOutDevData::CreateLink(const tools::Rectangle& rRect, OUString const& rAltText, sal_Int32 nPageNr) { mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::CreateLink ); mpGlobalSyncData->mParaRects.push_back( rRect ); mpGlobalSyncData->mParaMapModes.push_back( mrOutDev.GetMapMode() ); mpGlobalSyncData->mParaInts.push_back( nPageNr == -1 ? mnPage : nPageNr ); + mpGlobalSyncData->mParaOUStrings.push_back(rAltText); return mpGlobalSyncData->mCurId++; } diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx index 1a8d407c7247..70b6a2345417 100644 --- a/vcl/source/gdi/pdfwriter.cxx +++ b/vcl/source/gdi/pdfwriter.cxx @@ -329,9 +329,9 @@ void PDFWriter::DrawJPGBitmap( SvStream& rStreamData, bool bIsTrueColor, const S xImplementation->drawJPGBitmap( rStreamData, bIsTrueColor, rSrcSizePixel, rTargetArea, rAlphaMask, rGraphic ); } -sal_Int32 PDFWriter::CreateLink( const tools::Rectangle& rRect, sal_Int32 nPageNr ) +sal_Int32 PDFWriter::CreateLink(const tools::Rectangle& rRect, sal_Int32 nPageNr, OUString const& rAltText) { - return xImplementation->createLink( rRect, nPageNr ); + return xImplementation->createLink(rRect, nPageNr, rAltText); } sal_Int32 PDFWriter::CreateScreen(const tools::Rectangle& rRect, sal_Int32 nPageNr) diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index e28f1fa75997..e8a66f05516f 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -740,6 +740,12 @@ bool PDFPage::emit(sal_Int32 nParentObject ) aLine.append( ((i+1)%15) ? " " : "\n" ); } aLine.append( "]\n" ); + if (m_pWriter->m_aContext.Version != PDFWriter::PDFVersion::PDF_A_1 + && PDFWriter::PDFVersion::PDF_1_5 <= m_pWriter->m_aContext.Version) + { + // ISO 14289-1:2014, Clause: 7.18.3 + aLine.append( "/Tabs(S)\n" ); + } } if( !m_aMCIDParents.empty() ) { @@ -3251,6 +3257,9 @@ bool PDFWriterImpl::emitLinkAnnotations() aLine.append( ' ' ); appendFixedInt( rLink.m_aRect.Bottom(), aLine ); aLine.append( "]" ); + // ISO 14289-1:2014, Clause: 7.18.5 + aLine.append("/Contents"); + appendUnicodeTextStringEncrypt(rLink.m_AltText, rLink.m_nObject, aLine); if( rLink.m_nDest >= 0 ) { aLine.append( "/Dest" ); @@ -9841,7 +9850,7 @@ void PDFWriterImpl::createNote( const tools::Rectangle& rRect, const PDFNote& rN m_aPages[nPageNr].m_aAnnotations.push_back(rNoteEntry.m_aPopUpAnnotation.m_nObject); } -sal_Int32 PDFWriterImpl::createLink( const tools::Rectangle& rRect, sal_Int32 nPageNr ) +sal_Int32 PDFWriterImpl::createLink(const tools::Rectangle& rRect, sal_Int32 nPageNr, OUString const& rAltText) { if( nPageNr < 0 ) nPageNr = m_nCurrentPage; @@ -9851,7 +9860,7 @@ sal_Int32 PDFWriterImpl::createLink( const tools::Rectangle& rRect, sal_Int32 nP sal_Int32 nRet = m_aLinks.size(); - m_aLinks.emplace_back( ); + m_aLinks.emplace_back(rAltText); m_aLinks.back().m_nObject = createObject(); m_aLinks.back().m_nPage = nPageNr; m_aLinks.back().m_aRect = rRect;