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 b50384cf6c0bf387c3d5b0bd85cf60c5443db815
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Apr 17 08:14:12 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Apr 20 08:28:13 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.
    
    (cherry picked from commit 3cd14725b6a16d7e6cc328aef3d1d9a9a6649634)
    
    Change-Id: Id534c1497eb56f9268bf49d2a19764051397bb18
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150536
    Tested-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/extras/ww8export/ww8export2.cxx 
b/sw/qa/extras/ww8export/ww8export2.cxx
index 863c2c1ccbad..5e5e0d83ef4b 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 3b6f4c2b47ed..02eaf8be275d 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>
 
@@ -3449,7 +3450,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 625583ee179f..adc4461660ca 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 e139ae71f906..b983f49e9570 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