drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx | 4 editeng/source/editeng/impedit3.cxx | 2 include/editeng/flditem.hxx | 14 ++- sc/source/ui/view/output2.cxx | 2 sd/source/ui/func/fuinsert.cxx | 2 sd/source/ui/inc/DrawViewShell.hxx | 2 sd/source/ui/view/drviews2.cxx | 4 sd/source/ui/view/drviews4.cxx | 2 sd/source/ui/view/drviewse.cxx | 12 +- sd/source/ui/view/drviewsf.cxx | 1 sd/source/ui/view/sdview2.cxx | 2 svx/source/svdraw/svdotextdecomposition.cxx | 1 sw/source/core/access/AccessibilityCheck.cxx | 35 +++++++- sw/source/core/access/AccessibilityIssue.cxx | 41 +++++++--- sw/source/core/inc/AccessibilityCheck.hxx | 2 sw/source/core/inc/AccessibilityIssue.hxx | 1 sw/source/core/text/EnhancedPDFExportHelper.cxx | 21 ++--- sw/source/core/txtnode/OnlineAccessibilityCheck.cxx | 4 vcl/qa/cppunit/pdfexport/data/LinkPages.fodt | 4 vcl/qa/cppunit/pdfexport/data/LinkWithFly.fodt | 4 vcl/qa/cppunit/pdfexport/data/PDF_export_with_formcontrol.fodt | 4 vcl/qa/cppunit/pdfexport/pdfexport.cxx | 34 ++++---- vcl/qa/cppunit/pdfexport/pdfexport2.cxx | 14 +-- vcl/source/gdi/pdfwriter_impl.cxx | 7 + 24 files changed, 135 insertions(+), 84 deletions(-)
New commits: commit f4b09d869f1844738a744209bc7744396ccc3baf Author: Michael Stahl <[email protected]> AuthorDate: Thu Mar 6 18:53:35 2025 +0100 Commit: Christian Lohmaier <[email protected]> CommitDate: Fri Mar 7 17:07:07 2025 +0100 tdf#161583 vcl,sc,sw: PDF/UA export: fix Contents of Link annotations In ISO 14289-2:2024 the requirement was changed from "shall" to "should": Link annotations should include a Contents entry to enrich information available to assistive technology. There is also now a Well-Tagged PDF (WTPDF) Version 1.0.0, which says: 8.9.2.4.2 Link Link annotations should include a Contents entry to enrich information available to assistive technology. NOTE 1 Link annotations are often accessed out of context; the Contents entry provides optional additional information. The Contents entry is also particularly valuable in the context of link targets that are not intended to be human-readable. EXAMPLE — A link over the text “click here” is improved by a Contents entry to advise the user regarding the link’s target. So adapt PDFWriterImpl::emitLinkAnnotations() to produce "Contents" only if there is some alt text. The sw a11y check will already warn if the alt text/"name" is missing on a hyperlink in a SwTextNode, and a previous commit added a warning if it is missing on a hyperlink in a SwFlyFrameFormat. Contents should in any case not contain the textual representation of the hyperlinks, that was a misunderstanding, but describe the target of the link. This requires adapting numerous unit tests. (regression from commit fa3f04bdd4f73a1b3be70dfb709c44638ef7e3d9) Change-Id: I88a7ae83d17d781115c93152d267ddb57208c200 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182600 Reviewed-by: Michael Stahl <[email protected]> Tested-by: Jenkins (cherry picked from commit 9cef7e5ba50b483cd84682528c7ef503965b6104) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182614 Reviewed-by: Christian Lohmaier <[email protected]> diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index 421edaafcc5f..5980a1abf75b 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -888,7 +888,7 @@ static void lcl_DoHyperlinkResult( const OutputDevice* pDev, const tools::Rectan if ( !aURL.isEmpty() && pPDFData ) { vcl::PDFExtOutDevBookmarkEntry aBookmark; - aBookmark.nLinkId = pPDFData->CreateLink(rRect, aCellText); + aBookmark.nLinkId = pPDFData->CreateLink(rRect, u""_ustr); aBookmark.aBookmark = aURL; std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks(); rBookmarks.push_back( aBookmark ); diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx b/sw/source/core/text/EnhancedPDFExportHelper.cxx index ee221ccb66bf..3d17d536e09c 100644 --- a/sw/source/core/text/EnhancedPDFExportHelper.cxx +++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx @@ -2301,8 +2301,6 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe SwRects const aTmp(GetCursorRectsContainingText(mrSh)); OSL_ENSURE( !aTmp.empty(), "Enhanced pdf export - rectangles are missing" ); OUString altText(p->rINetAttr.GetINetFormat().GetName()); - if (altText.isEmpty()) - altText = mrSh.GetSelText(); const SwPageFrame* pSelectionPage = static_cast<const SwPageFrame*>( mrSh.GetLayout()->Lower() ); @@ -2426,7 +2424,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe { Point aNullPt; const SwRect aLinkRect = pFrameFormat->FindLayoutRect( false, &aNullPt ); - OUString const formatName(pFrameFormat->GetName()); + OUString const linkName(pItem->GetName()); // Link PageNums std::vector<sal_Int32> aLinkPageNums = CalcOutputPageNums( aLinkRect ); @@ -2435,7 +2433,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe { tools::Rectangle aRect(SwRectToPDFRect(pCurrPage, aLinkRect.SVRect())); const sal_Int32 nLinkId = - pPDFExtOutDevData->CreateLink(aRect, formatName, aLinkPageNum); + pPDFExtOutDevData->CreateLink(aRect, linkName, aLinkPageNum); // Store link info for tagged pdf output: const IdMapEntry aLinkEntry(aLinkRect, nLinkId); @@ -2456,7 +2454,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe { const SwTextNode* pTNd = pAnchorNode->GetTextNode(); if ( pTNd ) - MakeHeaderFooterLinks(*pPDFExtOutDevData, *pTNd, aLinkRect, nDestId, aURL, bInternal, formatName); + MakeHeaderFooterLinks(*pPDFExtOutDevData, *pTNd, aLinkRect, nDestId, aURL, bInternal, linkName); } } } @@ -2555,7 +2553,6 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe // #i44368# Links in Header/Footer const bool bHeaderFooter = pDoc->IsInHeaderFooter( *pTNd ); - OUString const content(pField->ExpandField(true, mrSh.GetLayout())); // Create links for all selected rectangles: const size_t nNumOfRects = aTmp.size(); @@ -2572,7 +2569,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe // Link Export aRect = SwRectToPDFRect(pCurrPage, rLinkRect.SVRect()); const sal_Int32 nLinkId = - pPDFExtOutDevData->CreateLink(aRect, content, aLinkPageNum); + pPDFExtOutDevData->CreateLink(aRect, rRefName, aLinkPageNum); // Store link info for tagged pdf output: const IdMapEntry aLinkEntry( rLinkRect, nLinkId ); @@ -2584,7 +2581,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe // #i44368# Links in Header/Footer if ( bHeaderFooter ) { - MakeHeaderFooterLinks(*pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, u""_ustr, true, content); + MakeHeaderFooterLinks(*pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, u""_ustr, true, rRefName); } } } @@ -2669,7 +2666,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe OUString const numStrRef(pTextFootnote->GetFootnote().GetViewNumStr(*pDoc, mrSh.GetLayout(), false)); // Export back link - const sal_Int32 nBackLinkId = pPDFExtOutDevData->CreateLink(aFootnoteSymbolRect, numStrSymbol, nDestPageNum); + const sal_Int32 nBackLinkId = pPDFExtOutDevData->CreateLink(aFootnoteSymbolRect, numStrRef, nDestPageNum); // Destination Export const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest(aRect, nDestPageNum); mrSh.GotoFootnoteAnchor(); @@ -2678,7 +2675,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe pCurrPage = static_cast<const SwPageFrame*>( mrSh.GetLayout()->Lower() ); // Link Export aRect = SwRectToPDFRect(pCurrPage, aLinkRect.SVRect()); - const sal_Int32 nLinkId = pPDFExtOutDevData->CreateLink(aRect, numStrRef, aLinkPageNum); + const sal_Int32 nLinkId = pPDFExtOutDevData->CreateLink(aRect, numStrSymbol, aLinkPageNum); // Back link destination Export const sal_Int32 nBackDestId = pPDFExtOutDevData->CreateDest(aRect, aLinkPageNum); // Store link info for tagged pdf output: @@ -3020,7 +3017,7 @@ void SwEnhancedPDFExportHelper::ExportAuthorityEntryLinks() continue; } - OUString const content(rAuthorityField.ExpandField(true, mrSh.GetLayout())); + OUString const content(rAuthorityField.GetAuthority(mrSh.GetLayout())); // Select the field. mrSh.SwCursorShell::SetMark(); @@ -3071,7 +3068,7 @@ void SwEnhancedPDFExportHelper::ExportAuthorityEntryLinks() continue; } - OUString const content(rAuthorityField.ExpandField(true, mrSh.GetLayout())); + OUString const content(rAuthorityField.GetAuthority(mrSh.GetLayout())); // Select the field. mrSh.SwCursorShell::SetMark(); diff --git a/vcl/qa/cppunit/pdfexport/data/LinkPages.fodt b/vcl/qa/cppunit/pdfexport/data/LinkPages.fodt index 50fff8bea4fc..50958d3b193c 100644 --- a/vcl/qa/cppunit/pdfexport/data/LinkPages.fodt +++ b/vcl/qa/cppunit/pdfexport/data/LinkPages.fodt @@ -131,8 +131,8 @@ <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> </text:sequence-decls> - <text:h text:style-name="P3" text:outline-level="1"><text:a xlink:type="simple" xlink:href="http://example.com/" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link"><text:bookmark-start text:name="__RefHeading___Toc17_3815242785"/><text:span text:style-name="T6">foo foo </text:span><text:soft-page-break/><text:span text:style-name="T6">foo foo</text:span></text:a><text:bookmark-end text:name="__RefHeading___Toc17_3815242785"/></text:h> + <text:h text:style-name="P3" text:outline-level="1"><text:a xlink:type="simple" xlink:href="http://example.com/" office:name="quadfoo" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link"><text:bookmark-start text:name="__RefHeading___Toc17_3815242785"/><text:span text:style-name="T6">foo foo </text:span><text:soft-page-break/><text:span text:style-name="T6">foo foo</text:span></text:a><text:bookmark-end text:name="__RefHeading___Toc17_3815242785"/></text:h> <text:p text:style-name="Text_20_body"><text:soft-page-break/><text:span text:style-name="T4"><text:bookmark-ref text:reference-format="text" text:ref-name="__RefHeading___Toc17_3815242785">foo foo foo foo</text:bookmark-ref></text:span><text:soft-page-break/></text:p> </office:text> </office:body> -</office:document> \ No newline at end of file +</office:document> diff --git a/vcl/qa/cppunit/pdfexport/data/LinkWithFly.fodt b/vcl/qa/cppunit/pdfexport/data/LinkWithFly.fodt index 5c14cee1f28c..881ef60da399 100644 --- a/vcl/qa/cppunit/pdfexport/data/LinkWithFly.fodt +++ b/vcl/qa/cppunit/pdfexport/data/LinkWithFly.fodt @@ -117,7 +117,7 @@ <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> </text:sequence-decls> - <text:p text:style-name="Standard"><text:a xlink:type="simple" xlink:href="https://www.mozilla.org/en-US/firefox/119.0/releasenotes/" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">https://www.mozilla.org/en-US<draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="char" svg:x="5.318cm" svg:y="0.056cm" svg:width="6.364cm" svg:height="6.364cm" draw:z-index="0"><draw:image draw:mime-type="image/png"> + <text:p text:style-name="Standard"><text:a xlink:type="simple" xlink:href="https://www.mozilla.org/en-US/firefox/119.0/releasenotes/" office:name="Firefox119" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">https://www.mozilla.org/en-US<draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="char" svg:x="5.318cm" svg:y="0.056cm" svg:width="6.364cm" svg:height="6.364cm" draw:z-index="0"><draw:image draw:mime-type="image/png"> <office:binary-data>iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABGdBTUEAANbY1E9YMgAAABl0 RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFpSURBVHjaYvz//z8DtQBAADER o+jjZGuibAQIICZiDOK/cgzFwEnrV/4HYXS1AAHERIxBR58yMiAb2DtzM1b1AAHERIxBIIBu @@ -131,7 +131,7 @@ </draw:image> <svg:title>house</svg:title> </draw:frame>/firefox/119.0/releasenotes/</text:a></text:p> - <text:p text:style-name="P1"><text:a xlink:type="simple" xlink:href="https://www.mozilla.org/en-US/firefox/118.0/releasenotes/" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">https://www.mozilla.org/en-US/firefox/118.0/releasenotes/</text:a></text:p> + <text:p text:style-name="P1"><text:a xlink:type="simple" xlink:href="https://www.mozilla.org/en-US/firefox/118.0/releasenotes/" office:name="Firefox118" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">https://www.mozilla.org/en-US/firefox/118.0/releasenotes/</text:a></text:p> </office:text> </office:body> </office:document> diff --git a/vcl/qa/cppunit/pdfexport/data/PDF_export_with_formcontrol.fodt b/vcl/qa/cppunit/pdfexport/data/PDF_export_with_formcontrol.fodt index eda699e27f02..6498ed2e0b47 100644 --- a/vcl/qa/cppunit/pdfexport/data/PDF_export_with_formcontrol.fodt +++ b/vcl/qa/cppunit/pdfexport/data/PDF_export_with_formcontrol.fodt @@ -162,9 +162,9 @@ </text:sequence-decls> <text:p text:style-name="P15">This <text:span text:style-name="T1">t</text:span>ext document contains some links and a text control.</text:p> <text:p text:style-name="P13"><text:span text:style-name="T1">When exporting the document to PDF in LO 7.5.</text:span><text:span text:style-name="T6">3.2</text:span><text:span text:style-name="T1"> or newer the links won't have the right target any more. First link to "Kläranlage" will open last link to "#pano=24", </text:span><text:span text:style-name="T5">second link won't open anything and third link will open "Mechanische Vorreinigung"</text:span></text:p> - <text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="https://klexikon.zum.de/wiki/Kläranlage" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">https://klexikon.zum.de/wiki/Kläranlage</text:a></text:p> + <text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="https://klexikon.zum.de/wiki/Kläranlage" office:name="wiki-seite" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">https://klexikon.zum.de/wiki/Kläranlage</text:a></text:p> <text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="https://de.wikipedia.org/wiki/Kläranlage#Mechanische_Vorreinigung" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">https://de.wikipedia.org/wiki/Kläranlage#Mechanische_Vorreinigung</text:a></text:p> - <text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="https://vr-easy.com/tour/usr/220113-virtuellerschulausflug/#pano=24" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">https://vr-easy.com/tour/usr/220113-virtuellerschulausflug/#pano=24</text:a></text:p> + <text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="https://vr-easy.com/tour/usr/220113-virtuellerschulausflug/#pano=24" office:name="tour" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">https://vr-easy.com/tour/usr/220113-virtuellerschulausflug/#pano=24</text:a></text:p> <text:p text:style-name="Text_20_body">Here a form control for getting possibility to input content.</text:p> <text:p text:style-name="Text_20_body"><draw:control text:anchor-type="as-char" svg:y="-0.3146in" draw:z-index="0" draw:name="Form1" draw:style-name="gr1" draw:text-style-name="P28" svg:width="6.3776in" svg:height="1.7717in" draw:control="control1"/></text:p> <text:p text:style-name="Text_20_body">When deleting the form control links will work as expected.</text:p> diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx index c49c01aa7133..58232d8fbc65 100644 --- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx +++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx @@ -2303,7 +2303,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"Error: Reference source not found"_ustr, + u"__RefHeading___Toc1501_2152971747"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -2370,7 +2370,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"Error: Reference source not found"_ustr, + u"__RefHeading___Toc1501_2152971747"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -2436,7 +2436,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"Error: Reference source not found"_ustr, + u"__RefHeading___Toc1501_2152971747"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -2502,7 +2502,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"Error: Reference source not found"_ustr, + u"__RefHeading___Toc1501_2152971747"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -2568,7 +2568,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"Error: Reference source not found"_ustr, + u"__RefHeading___Toc1501_2152971747"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -2693,7 +2693,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816Link) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"https://www.mozilla.org/en-US/firefox/119.0/releasenotes/"_ustr, + u"Firefox119"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -2760,7 +2760,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816Link) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"https://www.mozilla.org/en-US/firefox/119.0/releasenotes/"_ustr, + u"Firefox119"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -2849,7 +2849,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816Link) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"https://www.mozilla.org/en-US/firefox/118.0/releasenotes/"_ustr, + u"Firefox118"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -2916,7 +2916,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816Link) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"https://www.mozilla.org/en-US/firefox/118.0/releasenotes/"_ustr, + u"Firefox118"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -3072,7 +3072,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142806) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"foo foo foo foo"_ustr, + u"quadfoo"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -3138,7 +3138,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142806) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"foo foo foo foo"_ustr, + u"quadfoo"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -3204,7 +3204,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142806) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"foo foo foo foo"_ustr, + u"quadfoo"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -3270,7 +3270,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142806) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"foo foo foo foo"_ustr, + u"quadfoo"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -3348,7 +3348,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142806) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"foo foo foo foo"_ustr, + u"__RefHeading___Toc17_3815242785"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -3414,7 +3414,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142806) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"foo foo foo foo"_ustr, + u"__RefHeading___Toc17_3815242785"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -3480,7 +3480,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142806) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"foo foo foo foo"_ustr, + u"__RefHeading___Toc17_3815242785"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); @@ -3546,7 +3546,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142806) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"foo foo foo foo"_ustr, + u"__RefHeading___Toc17_3815242785"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); auto pStructParent = dynamic_cast<vcl::filter::PDFNumberElement*>( pAnnot->Lookup("StructParent"_ostr)); diff --git a/vcl/qa/cppunit/pdfexport/pdfexport2.cxx b/vcl/qa/cppunit/pdfexport/pdfexport2.cxx index 75e9b7a602cf..203b9cebc1df 100644 --- a/vcl/qa/cppunit/pdfexport/pdfexport2.cxx +++ b/vcl/qa/cppunit/pdfexport/pdfexport2.cxx @@ -2989,7 +2989,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf157397) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"https://klexikon.zum.de/wiki/Kläranlage"_ustr, + u"wiki-seite"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); auto pAA @@ -3062,9 +3062,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf157397) CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); - CPPUNIT_ASSERT_EQUAL( - u"https://de.wikipedia.org/wiki/Kläranlage#Mechanische_Vorreinigung"_ustr, - ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + CPPUNIT_ASSERT(!pAContents); CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); auto pAA = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pAnnot->Lookup("A"_ostr)); @@ -3138,8 +3136,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf157397) auto pAContents = dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)); CPPUNIT_ASSERT_EQUAL( - u"https://vr-easy.com/tour/usr/220113-virtuellerschulausflug/#pano=24"_ustr, - ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + u"tour"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); auto pAA = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pAnnot->Lookup("A"_ostr)); @@ -3733,7 +3730,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testFlyFrameHyperlinkAnnot) auto pContents = dynamic_cast<vcl::filter::PDFHexStringElement*>(pAnnot->Lookup("Contents"_ostr)); - CPPUNIT_ASSERT_EQUAL(u"Image2"_ustr, + CPPUNIT_ASSERT_EQUAL(u"Ship to Bugzilla"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pContents)); auto pStructParent @@ -4302,6 +4299,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testURIs) xCursor->gotoEnd(/*bExpand=*/true); uno::Reference<beans::XPropertySet> xCursorProps(xCursor, uno::UNO_QUERY); xCursorProps->setPropertyValue(u"HyperLinkURL"_ustr, uno::Any(URIs[i].in)); + xCursorProps->setPropertyValue(u"HyperLinkName"_ustr, uno::Any(u"Testname"_ustr)); // Save as PDF. aMediaDescriptor[u"FilterName"_ustr] <<= u"writer_pdf_Export"_ustr; @@ -4344,7 +4342,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testURIs) // Check it matches CPPUNIT_ASSERT_EQUAL(URIs[i].out, pURIElem->GetValue()); // tdf#148934 check a11y - CPPUNIT_ASSERT_EQUAL(u"Test pdf"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + CPPUNIT_ASSERT_EQUAL(u"Testname"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( *dynamic_cast<vcl::filter::PDFHexStringElement*>( pAnnot->Lookup("Contents"_ostr)))); } diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index b86e84c03e79..b271cbad29d9 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -3816,8 +3816,11 @@ bool PDFWriterImpl::emitLinkAnnotations() 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_AltText.isEmpty()) + { + aLine.append("/Contents"); + appendUnicodeTextStringEncrypt(rLink.m_AltText, rLink.m_nObject, aLine); + } if( rLink.m_nDest >= 0 ) { aLine.append( "/Dest" ); commit a65d8b7b6f5a98f2688bcd83fb49ee998d492f87 Author: Michael Stahl <[email protected]> AuthorDate: Thu Mar 6 17:39:58 2025 +0100 Commit: Christian Lohmaier <[email protected]> CommitDate: Fri Mar 7 17:07:02 2025 +0100 tdf#161583 drawinglayer,editeng,svx,sd: add "Name" to SvxURLField ... ... and use for PDF export, instead of the representation, which appears to be wrong. Strangely the Hyperlink dialog already allowed to insert a Name, but it was not actually set in the document. (regression from commit fa3f04bdd4f73a1b3be70dfb709c44638ef7e3d9) Change-Id: Ic21bbe8ead9f85dfbe0827b0051ecb68aeff0beb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182597 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> (cherry picked from commit 8bf8873f3091f131f6b4067d5a5f868882949114) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182613 Reviewed-by: Christian Lohmaier <[email protected]> diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index fdb98edceff2..d31dd244e2ad 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -1309,8 +1309,8 @@ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D( static_cast<sal_Int32>(ceil(aViewRange.getMaxX())), static_cast<sal_Int32>(ceil(aViewRange.getMaxY()))); vcl::PDFExtOutDevBookmarkEntry aBookmark; - OUString const content(rFieldPrimitive.getValue(u"Representation"_ustr)); - aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic, content); + OUString const altText(rFieldPrimitive.getValue(u"AltText"_ustr)); + aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic, altText); 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 068a6b56aa0f..fc2763b7cc8b 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -3931,7 +3931,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po tools::Rectangle aRect(aTopLeft, rTextPortion.GetSize()); vcl::PDFExtOutDevBookmarkEntry aBookmark; - aBookmark.nLinkId = pPDFExtOutDevData->CreateLink(aRect, pUrlField->GetRepresentation()); + aBookmark.nLinkId = pPDFExtOutDevData->CreateLink(aRect, pUrlField->GetName()); aBookmark.aBookmark = pUrlField->GetURL(); std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks(); rBookmarks.push_back(aBookmark); diff --git a/include/editeng/flditem.hxx b/include/editeng/flditem.hxx index a20692982752..397e9bd516d5 100644 --- a/include/editeng/flditem.hxx +++ b/include/editeng/flditem.hxx @@ -137,9 +137,9 @@ public: enum class SvxURLFormat { - AppDefault = 0, // Set as in App - Url, // Represent URL - Repr // Constitute representation + AppDefault = 0, // App setting + Url, // Show URL + Repr // Show representation }; class EDITENG_DLLPUBLIC SvxURLField final : public SvxFieldData @@ -147,8 +147,9 @@ class EDITENG_DLLPUBLIC SvxURLField final : public SvxFieldData private: SvxURLFormat eFormat; OUString aURL; // URL-Address - OUString aRepresentation; // What is shown - OUString aTargetFrame; // In what Frame + OUString aRepresentation; // Text shown in document + OUString aTargetFrame; // Frame to open in + OUString m_Name; // Alt-text public: static constexpr auto CLASS_ID = css::text::textfield::Type::URL; @@ -163,6 +164,9 @@ public: const OUString& GetRepresentation() const { return aRepresentation; } void SetRepresentation( const OUString& rRep ) { aRepresentation= rRep; } + OUString const& GetName() const { return m_Name; } + void SetName(OUString const& rName) { m_Name = rName; } + const OUString& GetTargetFrame() const { return aTargetFrame; } void SetTargetFrame( const OUString& rFrm ) { aTargetFrame = rFrm; } diff --git a/sd/source/ui/func/fuinsert.cxx b/sd/source/ui/func/fuinsert.cxx index c2f9d7ea1022..a6e3a1cc04dd 100644 --- a/sd/source/ui/func/fuinsert.cxx +++ b/sd/source/ui/func/fuinsert.cxx @@ -271,7 +271,7 @@ void FuInsertClipboard::DoExecute( SfxRequest& ) ( aDataHelper.HasFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) && aDataHelper.GetINetBookmark( SotClipboardFormatId::UNIFORMRESOURCELOCATOR, aINetBookmark ) ) ) { - pDrViewSh->InsertURLField( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), u""_ustr ); + pDrViewSh->InsertURLField(aINetBookmark.GetURL(), aINetBookmark.GetDescription(), u""_ustr, u""_ustr); } } diff --git a/sd/source/ui/inc/DrawViewShell.hxx b/sd/source/ui/inc/DrawViewShell.hxx index f382eff431d3..e2f9296c1ce7 100644 --- a/sd/source/ui/inc/DrawViewShell.hxx +++ b/sd/source/ui/inc/DrawViewShell.hxx @@ -133,7 +133,7 @@ public: virtual void SetZoom( ::tools::Long nZoom ) override; virtual void SetZoomRect( const ::tools::Rectangle& rZoomRect ) override; - void InsertURLField(const OUString& rURL, const OUString& rText, const OUString& rTarget); + void InsertURLField(const OUString& rURL, const OUString& rText, const OUString& rTarget, OUString const& rAltText); void InsertURLButton(const OUString& rURL, const OUString& rText, const OUString& rTarget, const Point* pPos); diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx index fc011865e7fa..18a32fdb4c2c 100644 --- a/sd/source/ui/view/drviews2.cxx +++ b/sd/source/ui/view/drviews2.cxx @@ -2295,7 +2295,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) if (pHLItem->GetInsertMode() == HLINK_FIELD) { InsertURLField(pHLItem->GetURL(), pHLItem->GetName(), - pHLItem->GetTargetFrame()); + pHLItem->GetTargetFrame(), pHLItem->GetIntName()); } else if (pHLItem->GetInsertMode() == HLINK_BUTTON) { @@ -2309,7 +2309,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) if (pOlView || comphelper::LibreOfficeKit::isActive()) { InsertURLField(pHLItem->GetURL(), pHLItem->GetName(), - pHLItem->GetTargetFrame()); + pHLItem->GetTargetFrame(), pHLItem->GetIntName()); } else { diff --git a/sd/source/ui/view/drviews4.cxx b/sd/source/ui/view/drviews4.cxx index 55204c760178..764eef122571 100644 --- a/sd/source/ui/view/drviews4.cxx +++ b/sd/source/ui/view/drviews4.cxx @@ -552,7 +552,7 @@ void DrawViewShell::Command(const CommandEvent& rCEvt, ::sd::Window* pWin) ( aDataHelper.HasFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) && aDataHelper.GetINetBookmark( SotClipboardFormatId::UNIFORMRESOURCELOCATOR, aINetBookmark ) ) ) { - InsertURLField( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), u""_ustr ); + InsertURLField(aINetBookmark.GetURL(), aINetBookmark.GetDescription(), u""_ustr, u""_ustr); } } } diff --git a/sd/source/ui/view/drviewse.cxx b/sd/source/ui/view/drviewse.cxx index 2b354a104556..5d7dadf351b7 100644 --- a/sd/source/ui/view/drviewse.cxx +++ b/sd/source/ui/view/drviewse.cxx @@ -989,7 +989,7 @@ void DrawViewShell::FuSupport(SfxRequest& rReq) ( aDataHelper.HasFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) && aDataHelper.GetINetBookmark( SotClipboardFormatId::UNIFORMRESOURCELOCATOR, aINetBookmark ) ) ) { - InsertURLField( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), u""_ustr ); + InsertURLField(aINetBookmark.GetURL(), aINetBookmark.GetDescription(), u""_ustr, u""_ustr); } } } @@ -1491,14 +1491,18 @@ void DrawViewShell::FuSupportRotate(SfxRequest const &rReq) } void DrawViewShell::InsertURLField(const OUString& rURL, const OUString& rText, - const OUString& rTarget) + const OUString& rTarget, OUString const& rAltText) { OutlinerView* pOLV = mpDrawView->GetTextEditOutlinerView(); + SvxURLField aURLField(rURL, rText, SvxURLFormat::Repr); + aURLField.SetTargetFrame(rTarget); + aURLField.SetName(rAltText); + if (pOLV) { ESelection aSel( pOLV->GetSelection() ); - SvxFieldItem aURLItem( SvxURLField( rURL, rText, SvxURLFormat::Repr ), EE_FEATURE_FIELD ); + SvxFieldItem const aURLItem(aURLField, EE_FEATURE_FIELD); pOLV->InsertField( aURLItem ); if (aSel.start.nIndex <= aSel.end.nIndex) aSel.end.nIndex = aSel.start.nIndex + 1; @@ -1512,8 +1516,6 @@ void DrawViewShell::InsertURLField(const OUString& rURL, const OUString& rText, pOutl->Init( OutlinerMode::TextObject ); OutlinerMode nOutlMode = pOutl->GetOutlinerMode(); - SvxURLField aURLField(rURL, rText, SvxURLFormat::Repr); - aURLField.SetTargetFrame(rTarget); SvxFieldItem aURLItem(aURLField, EE_FEATURE_FIELD); pOutl->QuickInsertField( aURLItem, ESelection() ); std::optional<OutlinerParaObject> pOutlParaObject = pOutl->CreateParaObject(); diff --git a/sd/source/ui/view/drviewsf.cxx b/sd/source/ui/view/drviewsf.cxx index d864a3c1ecd0..917a21e14ece 100644 --- a/sd/source/ui/view/drviewsf.cxx +++ b/sd/source/ui/view/drviewsf.cxx @@ -95,6 +95,7 @@ void DrawViewShell::GetCtrlState(SfxItemSet &rSet) aHLinkItem.SetName(pUrlField->GetRepresentation()); aHLinkItem.SetURL(pUrlField->GetURL()); aHLinkItem.SetTargetFrame(pUrlField->GetTargetFrame()); + aHLinkItem.SetIntName(pUrlField->GetName()); } else { diff --git a/sd/source/ui/view/sdview2.cxx b/sd/source/ui/view/sdview2.cxx index 8f5937172c0c..b571625484f0 100644 --- a/sd/source/ui/view/sdview2.cxx +++ b/sd/source/ui/view/sdview2.cxx @@ -337,7 +337,7 @@ void View::DoPaste (::sd::Window* pWindow) ( aDataHelper.HasFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) && aDataHelper.GetINetBookmark( SotClipboardFormatId::UNIFORMRESOURCELOCATOR, aINetBookmark ) ) ) { - pDrViewSh->InsertURLField( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), u""_ustr ); + pDrViewSh->InsertURLField(aINetBookmark.GetURL(), aINetBookmark.GetDescription(), u""_ustr, u""_ustr); } } } diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx index 31273bc42f35..3fc554792f65 100644 --- a/svx/source/svdraw/svdotextdecomposition.cxx +++ b/svx/source/svdraw/svdotextdecomposition.cxx @@ -624,6 +624,7 @@ namespace meValues.emplace_back("URL", pURLField->GetURL()); meValues.emplace_back("Representation", pURLField->GetRepresentation()); meValues.emplace_back("TargetFrame", pURLField->GetTargetFrame()); + meValues.emplace_back("AltText", pURLField->GetName()); meValues.emplace_back("SvxURLFormat", OUString::number(static_cast<sal_uInt16>(pURLField->GetFormat()))); xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_URL, &meValues); } commit 222e6a558497b7132cade966eda01f88cd945e70 Author: Michael Stahl <[email protected]> AuthorDate: Thu Mar 6 10:43:23 2025 +0100 Commit: Christian Lohmaier <[email protected]> CommitDate: Fri Mar 7 17:06:57 2025 +0100 tdf#161583 sw: a11y check: warn about flys with RES_URL with no "name" Fly frames can have hyperlinks too. Change-Id: I80da4b53e44e6f82a4f37f4b2aa859b8475b452a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182577 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> (cherry picked from commit 5445e9de41b1330fa27e07d46eaa4babe956645f) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182612 Reviewed-by: Christian Lohmaier <[email protected]> diff --git a/sw/source/core/access/AccessibilityCheck.cxx b/sw/source/core/access/AccessibilityCheck.cxx index 9434f5318fff..3985683f65ff 100644 --- a/sw/source/core/access/AccessibilityCheck.cxx +++ b/sw/source/core/access/AccessibilityCheck.cxx @@ -44,6 +44,7 @@ #include <o3tl/vector_utils.hxx> #include <svx/swframetypes.hxx> #include <fmtanchr.hxx> +#include <fmturl.hxx> #include <dcontact.hxx> #include <unotext.hxx> #include <svx/svdoashp.hxx> @@ -2613,13 +2614,39 @@ public: } // end anonymous namespace // Check Shapes, TextBox -void AccessibilityCheck::checkObject(SwNode* pCurrent, SdrObject* pObject) +void AccessibilityCheck::checkObject(SwNode* pCurrent, SwFrameFormat const& rFrameFormat) { + SdrObject const* const pObject{ rFrameFormat.FindSdrObject() }; if (!pObject) return; + // check hyperlink + if (SwFormatURL const* const pItem{ rFrameFormat.GetItemIfSet(RES_URL, false) }) + { + OUString const sHyperlink{ pItem->GetURL() }; + if (!sHyperlink.isEmpty() && pItem->GetName().isEmpty()) + { + INetURLObject const aHyperlink(sHyperlink); + if (aHyperlink.GetProtocol() != INetProtocol::NotValid) + { + std::shared_ptr<sw::AccessibilityIssue> pNameIssue + = lclAddIssue(m_aIssueCollection, SwResId(STR_HYPERLINK_NO_NAME), + sfx::AccessibilityIssueID::HYPERLINK_NO_NAME, + sfx::AccessibilityIssueLevel::WARNLEV); + + if (pNameIssue) + { + pNameIssue->setIssueObject(IssueObject::HYPERLINKFLY); + pNameIssue->setObjectID(rFrameFormat.GetName()); + pNameIssue->setNode(pCurrent); + pNameIssue->setDoc(*m_pDoc); + } + } + } + } + // Check for fontworks. - if (SdrObjCustomShape* pCustomShape = dynamic_cast<SdrObjCustomShape*>(pObject)) + if (SdrObjCustomShape const* pCustomShape = dynamic_cast<SdrObjCustomShape const*>(pObject)) { const SdrCustomShapeGeometryItem& rGeometryItem = pCustomShape->GetMergedItem(SDRATTR_CUSTOMSHAPE_GEOMETRY); @@ -2764,9 +2791,7 @@ void AccessibilityCheck::check() for (SwFrameFormat* const& pFrameFormat : pNode->GetAnchoredFlys()) { - SdrObject* pObject = pFrameFormat->FindSdrObject(); - if (pObject) - checkObject(pNode, pObject); + checkObject(pNode, *pFrameFormat); } } } diff --git a/sw/source/core/access/AccessibilityIssue.cxx b/sw/source/core/access/AccessibilityIssue.cxx index 2aabb968bb0a..3f38ee653428 100644 --- a/sw/source/core/access/AccessibilityIssue.cxx +++ b/sw/source/core/access/AccessibilityIssue.cxx @@ -29,6 +29,7 @@ #include <svx/svdview.hxx> #include <flyfrm.hxx> +#include <fmturl.hxx> #include <unotextrange.hxx> #include <txatbase.hxx> #include <txtfrm.hxx> @@ -83,6 +84,7 @@ void AccessibilityIssue::gotoIssue() const case IssueObject::GRAPHIC: case IssueObject::OLE: case IssueObject::TEXTFRAME: + case IssueObject::HYPERLINKFLY: { bool bSelected = pWrtShell->GotoFly(TempIssueObject.m_sObjectID, FLYCNTTYPE_ALL, true); @@ -245,6 +247,7 @@ bool AccessibilityIssue::canQuickFixIssue() const || m_eIssueObject == IssueObject::DOCUMENT_TITLE || m_eIssueObject == IssueObject::DOCUMENT_BACKGROUND || m_eIssueObject == IssueObject::LANGUAGE_NOT_SET + || m_eIssueObject == IssueObject::HYPERLINKFLY || m_eIssueObject == IssueObject::HYPERLINKTEXT; } @@ -332,6 +335,7 @@ void AccessibilityIssue::quickFixIssue() const } break; case IssueObject::HYPERLINKTEXT: + case IssueObject::HYPERLINKFLY: { SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); SwWrtShell* pWrtShell = pShell->GetWrtShell(); @@ -340,18 +344,35 @@ void AccessibilityIssue::quickFixIssue() const SwResId(STR_HYPERLINK_NO_NAME_DLG))); if (aNameDialog->Execute() == RET_OK) { - SwContentNode* pContentNode = m_pNode->GetContentNode(); - SwPosition aStart(*pContentNode, m_nStart); - SwPosition aEnd(*pContentNode, m_nEnd); - uno::Reference<text::XTextRange> xRun - = SwXTextRange::CreateXTextRange(*m_pDoc, aStart, &aEnd); - if (xRun.is()) + if (m_eIssueObject == IssueObject::HYPERLINKTEXT) { - uno::Reference<beans::XPropertySet> xProperties(xRun, uno::UNO_QUERY); - if (xProperties->getPropertySetInfo()->hasPropertyByName(u"HyperLinkName"_ustr)) + SwContentNode* pContentNode = m_pNode->GetContentNode(); + SwPosition aStart(*pContentNode, m_nStart); + SwPosition aEnd(*pContentNode, m_nEnd); + uno::Reference<text::XTextRange> xRun + = SwXTextRange::CreateXTextRange(*m_pDoc, aStart, &aEnd); + if (xRun.is()) { - xProperties->setPropertyValue(u"HyperLinkName"_ustr, - uno::Any(aNameDialog->GetName())); + uno::Reference<beans::XPropertySet> xProperties(xRun, uno::UNO_QUERY); + if (xProperties->getPropertySetInfo()->hasPropertyByName( + u"HyperLinkName"_ustr)) + { + xProperties->setPropertyValue(u"HyperLinkName"_ustr, + uno::Any(aNameDialog->GetName())); + } + } + } + else + { + SwFlyFrameFormat* const pFlyFormat{ const_cast<SwFlyFrameFormat*>( + m_pDoc->FindFlyByName(m_sObjectID)) }; + if (pFlyFormat) + { + SwFormatURL item{ pFlyFormat->GetURL() }; + item.SetName(aNameDialog->GetName()); + SwAttrSet set{ m_pDoc->GetAttrPool(), svl::Items<RES_URL, RES_URL> }; + set.Put(item); + m_pDoc->SetFlyFrameAttr(*pFlyFormat, set); } } pWrtShell->SetModified(); diff --git a/sw/source/core/inc/AccessibilityCheck.hxx b/sw/source/core/inc/AccessibilityCheck.hxx index caaff1944842..30fb75246481 100644 --- a/sw/source/core/inc/AccessibilityCheck.hxx +++ b/sw/source/core/inc/AccessibilityCheck.hxx @@ -49,7 +49,7 @@ public: } void check() override; - void checkObject(SwNode* pNode, SdrObject* pObject); + void checkObject(SwNode* pNode, SwFrameFormat const&); void checkNode(SwNode* pNode); void checkDocumentProperties(); }; diff --git a/sw/source/core/inc/AccessibilityIssue.hxx b/sw/source/core/inc/AccessibilityIssue.hxx index 647d51b66da7..1d8afcfc5e36 100644 --- a/sw/source/core/inc/AccessibilityIssue.hxx +++ b/sw/source/core/inc/AccessibilityIssue.hxx @@ -27,6 +27,7 @@ enum class IssueObject TABLE, TEXT, HYPERLINKTEXT, + HYPERLINKFLY, DOCUMENT_TITLE, DOCUMENT_BACKGROUND, LANGUAGE_NOT_SET, diff --git a/sw/source/core/txtnode/OnlineAccessibilityCheck.cxx b/sw/source/core/txtnode/OnlineAccessibilityCheck.cxx index d861084d7018..235a7b5b4545 100644 --- a/sw/source/core/txtnode/OnlineAccessibilityCheck.cxx +++ b/sw/source/core/txtnode/OnlineAccessibilityCheck.cxx @@ -140,9 +140,7 @@ void OnlineAccessibilityCheck::runAccessibilityCheck(SwNode* pNode) for (SwFrameFormat* const& pFrameFormat : pNode->GetAnchoredFlys()) { - SdrObject* pObject = pFrameFormat->FindSdrObject(); - if (pObject) - m_aAccessibilityCheck.checkObject(pNode, pObject); + m_aAccessibilityCheck.checkObject(pNode, *pFrameFormat); } auto aCollection = m_aAccessibilityCheck.getIssueCollection();
