sw/qa/extras/ww8export/ww8export2.cxx       |   58 ++++++--------
 sw/source/filter/ww8/wrtw8nds.cxx           |   17 ++++
 sw/source/filter/ww8/wrtww8.cxx             |  112 ++++++++++++++++++++++++++++
 sw/source/filter/ww8/ww8attributeoutput.hxx |    1 
 4 files changed, 155 insertions(+), 33 deletions(-)

New commits:
commit 3cd14725b6a16d7e6cc328aef3d1d9a9a6649634
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Apr 17 08:14:12 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Apr 17 09:01:31 2023 +0200

    sw floatable: teach the DOC export about SwFormatFlySplit
    
    Floating tables were always written back as a shape, containing a table,
    which can't split over pages, not even in Word.
    
    Now that we have split flys, we know that floating tables are mapped to
    split flys, so we can map split flys back to floating tables on export.
    
    The following SPRMs need writing, which are more or less the equivalent
    to DOCX's <w:tblpPr> attributes:
    
    - sprmTPc: relation orient for positioning the table
    - sprmTDyaFromText, sprmTDyaFromTextBottom: top/bottom margin
    - sprmTDxaFromText, sprmTDxaFromTextRight: left/right margin
    - sprmTDxaAbs: horizontal orientation
    - sprmTDyaAbs: vertical orientation
    
    With this, testTdf107773 passes in the SW_FORCE_FLY_SPLIT=1 case, while
    previously only the import side worked.
    
    Change-Id: Id534c1497eb56f9268bf49d2a19764051397bb18
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150464
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/extras/ww8export/ww8export2.cxx 
b/sw/qa/extras/ww8export/ww8export2.cxx
index 4f1f6d4afd6d..8252f63504f0 100644
--- a/sw/qa/extras/ww8export/ww8export2.cxx
+++ b/sw/qa/extras/ww8export/ww8export2.cxx
@@ -332,42 +332,36 @@ DECLARE_WW8EXPORT_TEST(testTdf99197_defaultLTR, 
"tdf99197_defaultLTR.doc")
         text::WritingMode2::LR_TB, getProperty<sal_Int16>(getParagraph(2), 
"WritingMode") );
 }
 
-DECLARE_WW8EXPORT_TEST(testTdf107773, "tdf107773.doc")
-{
-    // This was 1, multi-page table was imported as a floating one.
-    CPPUNIT_ASSERT_EQUAL(0, getShapes());
-
-    // tdf#80635 - transfer the float orientation to the table.
-    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, 
uno::UNO_QUERY);
-    uno::Reference<container::XIndexAccess> 
xTables(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY);
-    uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), 
uno::UNO_QUERY);
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Horizontal Orientation", 
text::HoriOrientation::CENTER, getProperty<sal_Int16>(xTable, "HoriOrient"));
-}
-
-CPPUNIT_TEST_FIXTURE(Test, testTdf107773SplitFly)
+CPPUNIT_TEST_FIXTURE(Test, testTdf107773)
 {
     SwModelTestBase::FlySplitGuard aGuard;
 
+    auto verify = [this]() {
+        // This failed, multi-page table was imported as a non-split frame.
+        SwDoc* pDoc = getSwDoc();
+        SwRootFrame* pLayout = 
pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+        auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
+        CPPUNIT_ASSERT(pPage1);
+        // pPage1 has no sorted (floating) objections.
+        CPPUNIT_ASSERT(pPage1->GetSortedObjs());
+        const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+        CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
+        auto pPage1Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage1Objs[0]);
+        CPPUNIT_ASSERT(pPage1Fly);
+        auto pTab1 = dynamic_cast<SwTabFrame*>(pPage1Fly->GetLower());
+        CPPUNIT_ASSERT(pTab1);
+        // This failed, the split fly containing a table was exported back to 
DOC as shape+table,
+        // which can't split.
+        CPPUNIT_ASSERT(pTab1->HasFollow());
+
+        // tdf#80635 - assert the horizontal orientation.
+        const SwFormatHoriOrient& rFormatHoriOrient = 
pPage1Fly->GetFormat()->GetHoriOrient();
+        CPPUNIT_ASSERT_EQUAL(css::text::HoriOrientation::CENTER, 
rFormatHoriOrient.GetHoriOrient());
+    };
     createSwDoc("tdf107773.doc");
-
-    // This failed, multi-page table was imported as a non-split frame.
-    SwDoc* pDoc = getSwDoc();
-    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
-    auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
-    CPPUNIT_ASSERT(pPage1);
-    // pPage1 has no sorted (floating) objections.
-    CPPUNIT_ASSERT(pPage1->GetSortedObjs());
-    const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
-    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
-    auto pPage1Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage1Objs[0]);
-    CPPUNIT_ASSERT(pPage1Fly);
-    auto pTab1 = dynamic_cast<SwTabFrame*>(pPage1Fly->GetLower());
-    CPPUNIT_ASSERT(pTab1);
-    CPPUNIT_ASSERT(pTab1->HasFollow());
-
-    // tdf#80635 - assert the horizontal orientation.
-    const SwFormatHoriOrient& rFormatHoriOrient = 
pPage1Fly->GetFormat()->GetHoriOrient();
-    CPPUNIT_ASSERT_EQUAL(css::text::HoriOrientation::CENTER, 
rFormatHoriOrient.GetHoriOrient());
+    verify();
+    reload(mpFilter, "tdf107773.doc");
+    verify();
 }
 
 DECLARE_WW8EXPORT_TEST(testTdf112074_RTLtableJustification, 
"tdf112074_RTLtableJustification.doc")
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx 
b/sw/source/filter/ww8/wrtw8nds.cxx
index 61d73c32f242..71f33f3a7d14 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -99,6 +99,7 @@
 
 #include <ndgrf.hxx>
 #include <ndole.hxx>
+#include <formatflysplit.hxx>
 
 #include <cstdio>
 
@@ -3464,7 +3465,21 @@ void WW8AttributeOutput::OutputFlyFrame_Impl( const 
ww8::Frame& rFormat, const P
     if (bUseEscher)
     {
         // write as escher
-        m_rWW8Export.AppendFlyInFlys(rFormat, rNdTopLeft);
+        if (rFrameFormat.GetFlySplit().GetValue())
+        {
+            // The frame can split: this was originally from a floating table, 
write it back as
+            // such.
+            const SwNodeIndex* pNodeIndex = 
rFrameFormat.GetContent().GetContentIdx();
+            SwNodeOffset nStt = pNodeIndex ? pNodeIndex->GetIndex() + 1 : 
SwNodeOffset(0);
+            SwNodeOffset nEnd = pNodeIndex ? 
pNodeIndex->GetNode().EndOfSectionIndex() : SwNodeOffset(0);
+            m_rWW8Export.SaveData(nStt, nEnd);
+            GetExport().WriteText();
+            m_rWW8Export.RestoreData();
+        }
+        else
+        {
+            m_rWW8Export.AppendFlyInFlys(rFormat, rNdTopLeft);
+        }
     }
     else
     {
diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
index c9415747cefd..6c26910af08f 100644
--- a/sw/source/filter/ww8/wrtww8.cxx
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -87,6 +87,7 @@
 #include <strings.hrc>
 #include <fmtline.hxx>
 #include <fmtfsize.hxx>
+#include <formatflysplit.hxx>
 #include "sprmids.hxx"
 
 #include <comphelper/sequenceashashmap.hxx>
@@ -2297,6 +2298,114 @@ void 
WW8AttributeOutput::TableSpacing(ww8::WW8TableNodeInfoInner::Pointer_t pTab
     }
 }
 
+void WW8AttributeOutput::TablePositioning(SwFrameFormat* pFlyFormat)
+{
+    if (!pFlyFormat || !pFlyFormat->GetFlySplit().GetValue())
+    {
+        return;
+    }
+
+    sal_uInt8 nPcVert = 0;
+    switch (pFlyFormat->GetVertOrient().GetRelationOrient())
+    {
+        case text::RelOrientation::PAGE_PRINT_AREA:
+            // relative to margin
+            nPcVert = 0;
+            break;
+        case text::RelOrientation::PAGE_FRAME:
+            // relative to page
+            nPcVert = 1;
+            break;
+        default:
+            // text::RelOrientation::FRAME
+            // relative to text
+            nPcVert = 2;
+            break;
+    }
+    sal_uInt8 nPcHorz = 0;
+    switch (pFlyFormat->GetHoriOrient().GetRelationOrient())
+    {
+        case text::RelOrientation::FRAME:
+            // relative to column
+            nPcHorz = 0;
+            break;
+        case text::RelOrientation::PAGE_PRINT_AREA:
+            // relative to margin
+            nPcHorz = 1;
+            break;
+        default:
+            // text::RelOrientation::PAGE_FRAME
+            // relative to page
+            nPcHorz = 2;
+            break;
+    }
+    sal_uInt8 nTPc = (nPcVert << 4) | (nPcHorz << 6);
+    m_rWW8Export.InsUInt16(NS_sprm::TPc::val);
+    m_rWW8Export.m_pO->push_back(nTPc);
+
+    // Similar to WW8AttributeOutput::FormatHorizOrientation(), but for tables.
+    sal_Int16 nTDxaAbs = 0;
+    switch (pFlyFormat->GetHoriOrient().GetHoriOrient())
+    {
+        case text::HoriOrientation::LEFT:
+            // left
+            nTDxaAbs = 0;
+            break;
+        case text::HoriOrientation::CENTER:
+            // centered
+            nTDxaAbs = -4;
+            break;
+        case text::HoriOrientation::RIGHT:
+            // right
+            nTDxaAbs = -8;
+            break;
+        default:
+            nTDxaAbs = pFlyFormat->GetHoriOrient().GetPos();
+            break;
+    }
+    m_rWW8Export.InsUInt16(NS_sprm::TDxaAbs::val);
+    m_rWW8Export.InsInt16(nTDxaAbs);
+
+    // Similar to WW8AttributeOutput::FormatVertOrientation(), but for tables.
+    sal_Int16 nTDyaAbs = 0;
+    switch (pFlyFormat->GetVertOrient().GetVertOrient())
+    {
+        case text::VertOrientation::TOP:
+            // up
+            nTDyaAbs = -4;
+            break;
+        case text::VertOrientation::CENTER:
+            // centered
+            nTDyaAbs = -8;
+            break;
+        case text::VertOrientation::BOTTOM:
+            // down
+            nTDyaAbs = -12;
+            break;
+        default:
+            nTDyaAbs = pFlyFormat->GetVertOrient().GetPos();
+            break;
+    }
+    m_rWW8Export.InsUInt16(NS_sprm::TDyaAbs::val);
+    m_rWW8Export.InsInt16(nTDyaAbs);
+
+    // Similar to WW8AttributeOutput::FormatULSpace(), but for tables.
+    sal_uInt16 nDyaFromText = pFlyFormat->GetULSpace().GetUpper();
+    m_rWW8Export.InsUInt16(NS_sprm::TDyaFromText::val);
+    m_rWW8Export.InsUInt16(nDyaFromText);
+    sal_uInt16 nDyaFromTextBottom = pFlyFormat->GetULSpace().GetLower();
+    m_rWW8Export.InsUInt16(NS_sprm::TDyaFromTextBottom::val);
+    m_rWW8Export.InsUInt16(nDyaFromTextBottom);
+
+    // Similar to WW8AttributeOutput::FormatLRSpace(), but for tables.
+    sal_uInt16 nDxaFromText = pFlyFormat->GetLRSpace().GetLeft();
+    m_rWW8Export.InsUInt16(NS_sprm::TDxaFromText::val);
+    m_rWW8Export.InsUInt16(nDxaFromText);
+    sal_uInt16 nDxaFromTextRight = pFlyFormat->GetLRSpace().GetRight();
+    m_rWW8Export.InsUInt16(NS_sprm::TDxaFromTextRight::val);
+    m_rWW8Export.InsUInt16(nDxaFromTextRight);
+}
+
 void WW8AttributeOutput::TableDefinition( 
ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
 {
     const SwTable * pTable = pTableTextNodeInfoInner->getTable();
@@ -2426,6 +2535,9 @@ void WW8AttributeOutput::TableDefinition( 
ww8::WW8TableNodeInfoInner::Pointer_t
         m_rWW8Export.m_pO->push_back( sal_uInt8/*ftsPercent*/ (2) );
         m_rWW8Export.InsUInt16( o3tl::narrowing<sal_uInt16>(nWidthPercent) * 
50 );
     }
+
+    // Write table positioning properties in case this is a floating table.
+    TablePositioning(pTable->GetTableNode()->GetFlyFormat());
 }
 
 ww8::GridColsPtr AttributeOutputBase::GetGridCols( 
ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner )
diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx 
b/sw/source/filter/ww8/ww8attributeoutput.hxx
index a36d7481acb2..c67adba187a6 100644
--- a/sw/source/filter/ww8/ww8attributeoutput.hxx
+++ b/sw/source/filter/ww8/ww8attributeoutput.hxx
@@ -102,6 +102,7 @@ public:
     virtual void TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t 
pTableTextNodeInfo ) override;
     virtual void TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t 
pTableTextNodeInfo ) override;
     virtual void TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t 
pTableTextNodeInfo ) override;
+    void TablePositioning(SwFrameFormat* pFlyFormat);
     virtual void TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t 
pTableTextNodeInfo ) override;
     virtual void TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t 
pTableTextNodeInfo ) override;
     virtual void TableRowRedline( ww8::WW8TableNodeInfoInner::Pointer_t 
pTableTextNodeInfo ) override;

Reply via email to