drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx |   10 -
 sw/source/core/text/EnhancedPDFExportHelper.cxx            |   10 +
 vcl/qa/cppunit/pdfexport/pdfexport.cxx                     |   77 ++++++++++++-
 vcl/source/gdi/pdfextoutdevdata.cxx                        |    3 
 4 files changed, 91 insertions(+), 9 deletions(-)

New commits:
commit a8f522f4257729ea11178ebf165fdd3a2b7be240
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Mon Oct 2 20:33:42 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Oct 4 11:42:58 2023 +0200

    vcl,drawinglayer,sw: PDF/UA export: footnote-container-in-list problem
    
    The problem is that if there is a footnote in a list, the footnote
    container becomes a child of the LI element that contains the footnote
    anchor, which is of course nonsense.
    
    This is because SwTaggedPDFHelper::CheckReopenTag() stopped using
    SetCurrentStructureElement(), but unfortunately it's required so that
    once the list ends, the correct parent element is restored for whatever
    follows the list.
    
    There is a similar problem in VclMetafileProcessor2D.
    
    (regression from commit d467f1aa3d028f399826c97e2eecedcd79efcf65)
    
    Change-Id: I03dee5dc2e11accb97279e5f325808c5b85507a1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157501
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index 1a7beb8affc6..d87c70c7e772 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -2527,7 +2527,7 @@ void 
VclMetafileProcessor2D::processStructureTagPrimitive2D(
     // structured tag primitive
     const vcl::PDFWriter::StructElement& 
rTagElement(rStructureTagCandidate.getStructureElement());
     bool bTagUsed((vcl::PDFWriter::NonStructElement != rTagElement));
-    bool bNeedEndAnchor(false);
+    ::std::optional<sal_Int32> oAnchorParent;
 
     if (!rStructureTagCandidate.isTaggedSdrObject())
     {
@@ -2543,8 +2543,8 @@ void 
VclMetafileProcessor2D::processStructureTagPrimitive2D(
             {
                 sal_Int32 const id = 
mpPDFExtOutDevData->EnsureStructureElement(
                     rStructureTagCandidate.GetAnchorStructureElementKey());
-                mpPDFExtOutDevData->BeginStructureElement(id);
-                bNeedEndAnchor = true;
+                
oAnchorParent.emplace(mpPDFExtOutDevData->GetCurrentStructureElement());
+                mpPDFExtOutDevData->SetCurrentStructureElement(id);
             }
             mpPDFExtOutDevData->WrapBeginStructureElement(rTagElement);
             switch (rTagElement)
@@ -2620,9 +2620,9 @@ void 
VclMetafileProcessor2D::processStructureTagPrimitive2D(
     {
         // write end tag
         mpPDFExtOutDevData->EndStructureElement();
-        if (bNeedEndAnchor)
+        if (oAnchorParent)
         {
-            mpPDFExtOutDevData->EndStructureElement();
+            mpPDFExtOutDevData->SetCurrentStructureElement(*oAnchorParent);
         }
     }
 }
diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx 
b/sw/source/core/text/EnhancedPDFExportHelper.cxx
index 3103b3fe9ef8..9ebc233dc687 100644
--- a/sw/source/core/text/EnhancedPDFExportHelper.cxx
+++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx
@@ -458,7 +458,15 @@ bool SwTaggedPDFHelper::CheckReopenTag()
 
     if (pReopenKey)
     {
-        OpenTagImpl(pReopenKey);
+        // note: it would be possible to get rid of the 
SetCurrentStructureElement()
+        // - which is quite ugly - for most cases by recreating the parents 
until the
+        // current ancestor, but there are special cases cell frame rowspan > 
1 follow
+        // and footnote frame follow where the parent of the follow is 
different from
+        // the parent of the first one, and so in PDFExtOutDevData the wrong 
parent
+        // would be restored and used for next elements.
+        m_nRestoreCurrentTag = 
mpPDFExtOutDevData->GetCurrentStructureElement();
+        sal_Int32 const id = 
mpPDFExtOutDevData->EnsureStructureElement(pReopenKey);
+        mpPDFExtOutDevData->SetCurrentStructureElement(id);
 
         bRet = true;
     }
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx 
b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index a07ceeb53eae..9709d9c57313 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -3733,7 +3733,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testSpans)
                 CPPUNIT_ASSERT(pKids1);
                 // assume there are no MCID ref at this level
                 auto vKids1 = pKids1->GetElements();
-                CPPUNIT_ASSERT_EQUAL(size_t(1), vKids1.size());
+                CPPUNIT_ASSERT_EQUAL(size_t(2), vKids1.size());
                 auto pRefKid10 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(vKids1[0]);
                 CPPUNIT_ASSERT(pRefKid10);
                 auto pObject10 = pRefKid10->LookupObject();
@@ -3868,8 +3868,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testSpans)
                 CPPUNIT_ASSERT(pKids1011);
                 // assume there are no MCID ref at this level
                 auto vKids1011 = pKids1011->GetElements();
-                //CPPUNIT_ASSERT_EQUAL(size_t(1), vKids1011.size());
-                //FIXME Div ???
+                CPPUNIT_ASSERT_EQUAL(size_t(1), vKids1011.size());
 
                 auto pRefKid10110 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(vKids1011[0]);
                 CPPUNIT_ASSERT(pRefKid10110);
@@ -4077,6 +4076,78 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testSpans)
                                          
pDictA103101->LookupElement("TextDecorationType"))
                                          ->GetValue());
 
+                // now the footnote container - following the list
+                auto pRefKid11 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(vKids1[1]);
+                CPPUNIT_ASSERT(pRefKid11);
+                auto pObject11 = pRefKid11->LookupObject();
+                CPPUNIT_ASSERT(pObject11);
+                auto pType11
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject11->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("StructElem"), 
pType11->GetValue());
+                auto pS11 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject11->Lookup("S"));
+                CPPUNIT_ASSERT_EQUAL(OString("Div"), pS11->GetValue());
+
+                auto pKids11 = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pObject11->Lookup("K"));
+                CPPUNIT_ASSERT(pKids11);
+                // assume there are no MCID ref at this level
+                auto vKids11 = pKids11->GetElements();
+                CPPUNIT_ASSERT_EQUAL(size_t(1), vKids11.size());
+
+                auto pRefKid110 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(vKids11[0]);
+                CPPUNIT_ASSERT(pRefKid110);
+                auto pObject110 = pRefKid110->LookupObject();
+                CPPUNIT_ASSERT(pObject110);
+                auto pType110
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject110->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("StructElem"), 
pType110->GetValue());
+                auto pS110 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject110->Lookup("S"));
+                CPPUNIT_ASSERT_EQUAL(OString("Note"), pS110->GetValue());
+
+                auto pKids110
+                    = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pObject110->Lookup("K"));
+                CPPUNIT_ASSERT(pKids110);
+                // assume there are no MCID ref at this level
+                auto vKids110 = pKids110->GetElements();
+                CPPUNIT_ASSERT_EQUAL(size_t(2), vKids110.size());
+
+                auto pRefKid1100 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(vKids110[0]);
+                CPPUNIT_ASSERT(pRefKid1100);
+                auto pObject1100 = pRefKid1100->LookupObject();
+                CPPUNIT_ASSERT(pObject1100);
+                auto pType1100
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject1100->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("StructElem"), 
pType1100->GetValue());
+                auto pS1100 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject1100->Lookup("S"));
+                CPPUNIT_ASSERT_EQUAL(OString("Lbl"), pS1100->GetValue());
+
+                auto pKids1100
+                    = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pObject1100->Lookup("K"));
+                CPPUNIT_ASSERT(pKids1100);
+                // assume there are no MCID ref at this level
+                auto vKids1100 = pKids1100->GetElements();
+                CPPUNIT_ASSERT_EQUAL(size_t(1), vKids1100.size());
+
+                auto pRefKid11000 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(vKids1100[0]);
+                CPPUNIT_ASSERT(pRefKid11000);
+                auto pObject11000 = pRefKid11000->LookupObject();
+                CPPUNIT_ASSERT(pObject11000);
+                auto pType11000
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject11000->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("StructElem"), 
pType11000->GetValue());
+                auto pS11000
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject11000->Lookup("S"));
+                CPPUNIT_ASSERT_EQUAL(OString("Link"), pS11000->GetValue());
+
+                auto pRefKid1101 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(vKids110[1]);
+                CPPUNIT_ASSERT(pRefKid1101);
+                auto pObject1101 = pRefKid1101->LookupObject();
+                CPPUNIT_ASSERT(pObject1101);
+                auto pType1101
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject1101->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("StructElem"), 
pType1101->GetValue());
+                auto pS1101 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject1101->Lookup("S"));
+                CPPUNIT_ASSERT_EQUAL(OString("Footnote"), pS1101->GetValue());
+
                 ++nDoc;
             }
         }
diff --git a/vcl/source/gdi/pdfextoutdevdata.cxx 
b/vcl/source/gdi/pdfextoutdevdata.cxx
index b110557e67d7..7719d6bb97d1 100644
--- a/vcl/source/gdi/pdfextoutdevdata.cxx
+++ b/vcl/source/gdi/pdfextoutdevdata.cxx
@@ -828,6 +828,9 @@ void PDFExtOutDevData::InitStructureElement(sal_Int32 const 
id,
     mpPageSyncData->mParaInts.push_back(id);
     mpPageSyncData->mParaStructElements.push_back( eType );
     mpPageSyncData->mParaOUStrings.push_back( rAlias );
+    // update parent: required for hell fly anchor frames in sw, so that on 
the actual
+    // anchor frame EndStructureElement() resets mCurrentStructElement 
properly.
+    mpGlobalSyncData->mStructParents[id] = 
mpGlobalSyncData->mCurrentStructElement;
 }
 
 void PDFExtOutDevData::BeginStructureElement(sal_Int32 const id)

Reply via email to