sw/source/core/text/EnhancedPDFExportHelper.cxx                |   32 ++-
 vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odt |binary
 vcl/qa/cppunit/pdfexport/pdfexport.cxx                         |  102 
++++++++++
 3 files changed, 131 insertions(+), 3 deletions(-)

New commits:
commit 0d59eebe858d0d3e5d2260691f245940757deacd
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Nov 24 13:17:56 2022 +0100
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Sat Dec 3 21:02:13 2022 +0000

    tdf#57423 sw: PDF/UA export: Alt texts for SwNoTextNode
    
    * Specification: ISO 14289-1:2014, Clause: 7.3, Test number: 1
    Figure tags shall include an alternative representation or replacement
    text that represents the contents marked with the Figure tag as noted in
    ISO 32000-1:2008, 14.7.2, Table 323
    
    This was broken by the previous commit, which tied ObjectInfoPrimitive2D
    evaluation to StructureTagPrimitive2D, and is restored now, perhaps
    less elegantly.
    
    * Specification: ISO 14289-1:2014, Clause: 7.7, Test number: 1
    All mathematical expressions shall be enclosed within a Formula tag as
    detailed in ISO 32000-1:2008, 14.8.4.5 and shall have Alt or ActualText
    attributes
    
    Haven't checked but it's possible that this worked before commit
    2840352ba56a212d191cc16e08378c87672d7b73 - for SwOLENode embedded
    objects, no ObjectInfoPrimitive2D is created apparently.
    
    Change-Id: Ia0077199601f39f666012d31883f63cff115716f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143247
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 122b4264d23df8b11419839ba700b88c4f936a6c)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143292
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx 
b/sw/source/core/text/EnhancedPDFExportHelper.cxx
index 6afa8648947c..9f0b028258f4 100644
--- a/sw/source/core/text/EnhancedPDFExportHelper.cxx
+++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx
@@ -526,6 +526,7 @@ void SwTaggedPDFHelper::SetAttributes( 
vcl::PDFWriter::StructElement eType )
         bool bHeight = false;
         bool bBox = false;
         bool bRowSpan = false;
+        bool bAltText = false;
 
         // Check which attributes to set:
 
@@ -586,11 +587,20 @@ void SwTaggedPDFHelper::SetAttributes( 
vcl::PDFWriter::StructElement eType )
 
             case vcl::PDFWriter::Formula :
             case vcl::PDFWriter::Figure :
+                bAltText =
                 bPlacement =
                 bWidth =
                 bHeight =
                 bBox = true;
                 break;
+
+            case vcl::PDFWriter::Division:
+                if (pFrame->IsFlyFrame()) // this can be something else too
+                {
+                    bAltText = true;
+                }
+                break;
+
             default :
                 break;
         }
@@ -676,9 +686,25 @@ void SwTaggedPDFHelper::SetAttributes( 
vcl::PDFWriter::StructElement eType )
             }
         }
 
-        // Formerly here bAlternateText was triggered for PDF export, but this
-        // was moved for more general use to primitives and usage in
-        // VclMetafileProcessor2D (see processGraphicPrimitive2D).
+        // ISO 14289-1:2014, Clause: 7.3
+        // ISO 14289-1:2014, Clause: 7.7
+        // For images (but not embedded objects), an ObjectInfoPrimitive2D is
+        // created, but it's not evaluated by VclMetafileProcessor2D any more;
+        // that would require producing StructureTagPrimitive2D here but that
+        // looks impossible so instead duplicate the code that sets the Alt
+        // text here again.
+        if (bAltText)
+        {
+            SwFlyFrameFormat const& rFly(*static_cast<SwFlyFrame 
const*>(pFrame)->GetFormat());
+            OUString const sep(
+                (rFly.GetObjTitle().isEmpty() || 
rFly.GetObjDescription().isEmpty())
+                ? OUString() : OUString(" - "));
+            OUString const altText(rFly.GetObjTitle() + sep + 
rFly.GetObjDescription());
+            if (!altText.isEmpty())
+            {
+                mpPDFExtOutDevData->SetAlternateText(altText);
+            }
+        }
 
         if ( bWidth )
         {
diff --git a/vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odt 
b/vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odt
new file mode 100644
index 000000000000..78f05b09e9e9
Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/Description PDF 
Export test .odt differ
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx 
b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index 6b0f90a0581f..461bb937f81d 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -3241,6 +3241,108 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf135638)
     CPPUNIT_ASSERT_EQUAL(int(2), nFigure);
 }
 
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf57423)
+{
+    aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+    // Enable PDF/UA
+    uno::Sequence<beans::PropertyValue> aFilterData(
+        comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) 
} }));
+    aMediaDescriptor["FilterData"] <<= aFilterData;
+    saveAsPDF(u"Description PDF Export test .odt");
+
+    vcl::filter::PDFDocument aDocument;
+    SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+    CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+    // The document has one page.
+    std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+    int nFigure(0);
+    int nFormula(0);
+    int nDiv(0);
+    for (const auto& rDocElement : aDocument.GetElements())
+    {
+        auto pObject = 
dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get());
+        if (!pObject)
+            continue;
+        auto pType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"));
+        if (pType && pType->GetValue() == "StructElem")
+        {
+            auto pS = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("S"));
+            if (pS && pS->GetValue() == "Figure")
+            {
+                switch (nFigure)
+                {
+                    case 0:
+                        CPPUNIT_ASSERT_EQUAL(OUString(u"QR Code - Tells how to 
get to Mosegaard"),
+                                             
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+                                                 
*dynamic_cast<vcl::filter::PDFHexStringElement*>(
+                                                     pObject->Lookup("Alt"))));
+                        break;
+                    case 1:
+                        CPPUNIT_ASSERT_EQUAL(OUString(u"Title: Arrows - 
Description:  Explains the "
+                                                      u"different arrow 
appearances"),
+                                             
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+                                                 
*dynamic_cast<vcl::filter::PDFHexStringElement*>(
+                                                     pObject->Lookup("Alt"))));
+                        break;
+                    case 2:
+                        CPPUNIT_ASSERT_EQUAL(
+                            OUString(u"My blue triangle - Does not need 
further description"),
+                            ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+                                
*dynamic_cast<vcl::filter::PDFHexStringElement*>(
+                                    pObject->Lookup("Alt"))));
+                        break;
+                }
+                ++nFigure;
+            }
+            if (pS && pS->GetValue() == "Formula")
+            {
+                CPPUNIT_ASSERT_EQUAL(
+                    OUString(u"Equation 1 - Now we give the full description 
of eq 1 here"),
+                    ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+                        
*dynamic_cast<vcl::filter::PDFHexStringElement*>(pObject->Lookup("Alt"))));
+                ++nFormula;
+            }
+            if (pS && pS->GetValue() == "Div")
+            {
+                switch (nDiv)
+                {
+                    case 0:
+                        CPPUNIT_ASSERT_EQUAL(OUString(u"This frame has a 
description"),
+                                             
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+                                                 
*dynamic_cast<vcl::filter::PDFHexStringElement*>(
+                                                     pObject->Lookup("Alt"))));
+                        break;
+                    case 1:
+                        // no properties set on this
+                        CPPUNIT_ASSERT(!pObject->Lookup("Alt"));
+                        break;
+                    case 2:
+                        CPPUNIT_ASSERT_EQUAL(OUString(u"My textbox - Has a 
light background"),
+                                             
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+                                                 
*dynamic_cast<vcl::filter::PDFHexStringElement*>(
+                                                     pObject->Lookup("Alt"))));
+                        break;
+                    case 3:
+                        CPPUNIT_ASSERT_EQUAL(OUString(u"Hey!  There is no 
alternate text for Frame "
+                                                      u"// but maybe not 
needed?"),
+                                             
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+                                                 
*dynamic_cast<vcl::filter::PDFHexStringElement*>(
+                                                     pObject->Lookup("Alt"))));
+                        break;
+                }
+                ++nDiv;
+            }
+        }
+    }
+    CPPUNIT_ASSERT_EQUAL(int(3), nFigure);
+    CPPUNIT_ASSERT_EQUAL(int(1), nFormula);
+    CPPUNIT_ASSERT_EQUAL(int(4), nDiv);
+}
+
 CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142129)
 {
     OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "master.odm";

Reply via email to