[Libreoffice-commits] core.git: Branch 'feature/cib_contract3753' - 23 commits - .gitreview include/oox oox/source readlicense_oo/license sc/qa sc/source sd/qa sw/inc sw/qa sw/source translations vcl/source vcl/unx writerfilter/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Fri Oct 16 09:21:30 UTC 2020


Rebased ref, commits from common ancestor:
commit c69681e4b4797c4976160c46efe06beb4df4af5d
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Oct 14 15:21:24 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:14:34 2020 +0200

    sw: fix unsorted redlines in SwTable::ConvertSubtableBox()
    
    ooo12626-10.odt asserts because MoveNodeRange() handles redlines only
    with an explicit flag.
    
    (regression from e366c928819c44b5c253c45dca6dae40b71c9808)
    
    Change-Id: I80c6e696e51c6d9c366af30ecf8b6df265d0fc91
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104286
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    Tested-by: Jenkins
    (cherry picked from commit 48a76ea268b4c7fe499abe858074420dd7b152e2)

diff --git a/sw/source/core/table/swnewtable.cxx b/sw/source/core/table/swnewtable.cxx
index 892b31e807cc..918ba94fcfea 100644
--- a/sw/source/core/table/swnewtable.cxx
+++ b/sw/source/core/table/swnewtable.cxx
@@ -2200,7 +2200,7 @@ void SwTable::ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox)
 #if 0
                     pDoc->GetNodes().MoveNodes(content, pDoc->GetNodes(), insPos, false);
 #else
-                    pDoc->getIDocumentContentOperations().MoveNodeRange(content, insPos, SwMoveFlags::NO_DELFRMS);
+                    pDoc->getIDocumentContentOperations().MoveNodeRange(content, insPos, SwMoveFlags::NO_DELFRMS|SwMoveFlags::REDLINES);
 #endif
                     // delete the empty node that was bundled in the new box
                     pDoc->GetNodes().Delete(insPos);
commit 42db7c8086abb205dbdcf6b44dcd5377866425e0
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Oct 1 17:31:21 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:32 2020 +0200

    sw: ODF import: convert the simplest sub-tables to rowspan tables
    
    Before OOo 2.3, CWS swnewtable, Writer represented complex table
    structures as sub-tables, i.e. <table:table table:is-sub-table="true">.
    
    Try to convert these to the modern rowspan tables, which export to
    non-ODF formats much easier.
    
    There are some cases where the result is going to look different, or
    where further work is required to adapt other things in the document;
    leave these alone for now.
    
    Change-Id: I6a6c497089ef886826484d2d723bf57c72f95b14

diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx
index a373f561704f..b62c2567e2de 100644
--- a/sw/inc/swtable.hxx
+++ b/sw/inc/swtable.hxx
@@ -168,6 +168,7 @@ private:
     void AdjustWidths( const long nOld, const long nNew );
     void NewSetTabCols( Parm &rP, const SwTabCols &rNew, const SwTabCols &rOld,
                         const SwTableBox *pStart, bool bCurRowOnly );
+    void ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox);
 
 public:
 
@@ -340,6 +341,9 @@ public:
 #endif
 
     bool HasLayout() const;
+
+    bool CanConvertSubtables() const;
+    void ConvertSubtables();
 };
 
 /// SwTableLine is one table row in the document model.
diff --git a/sw/source/core/table/swnewtable.cxx b/sw/source/core/table/swnewtable.cxx
index 04a2509b1e37..892b31e807cc 100644
--- a/sw/source/core/table/swnewtable.cxx
+++ b/sw/source/core/table/swnewtable.cxx
@@ -21,6 +21,7 @@
 #include <tblsel.hxx>
 #include <tblrwcl.hxx>
 #include <ndtxt.hxx>
+#include <ndole.hxx>
 #include <node.hxx>
 #include <UndoTable.hxx>
 #include <pam.hxx>
@@ -30,8 +31,14 @@
 #include <fmtfsize.hxx>
 #include <doc.hxx>
 #include <IDocumentUndoRedo.hxx>
+#include <IDocumentChartDataProviderAccess.hxx>
 #include <IDocumentContentOperations.hxx>
+#include <IDocumentFieldsAccess.hxx>
 #include <IDocumentLayoutAccess.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <fmtfld.hxx>
+#include <ftnidx.hxx>
 #include <cstdlib>
 #include <vector>
 #include <set>
@@ -2089,6 +2096,286 @@ void SwTable::CleanUpBottomRowSpan( sal_uInt16 nDelLines )
     }
 }
 
+/**
+  This is kind of similar to InsertSpannedRow()/InsertRow() but that one would
+  recursively copy subtables, which would kind of defeat the purpose;
+  this function directly moves the subtable rows's cells into the newly
+  created rows.  For the non-subtable boxes, covered-cells are created.
+
+  Outer row heights are adjusted to match the inner row heights, and the
+  last row's height is tweaked to ensure the sum of the heights is at least
+  the original outer row's minimal height.
+
+  Inner row backgrounds are copied to its cells, if they lack a background.
+
+  This currently can't handle more than 1 subtable in a row;
+  the inner rows of all subtables would need to be sorted by their height
+  to create the correct outer row structure, which is tricky and probably
+  requires a layout for the typical variable-height case.
+
+ */
+void SwTable::ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox)
+{
+    SwDoc *const pDoc(GetFrameFormat()->GetDoc());
+    SwTableLine *const pSourceLine(GetTabLines()[nRow]);
+    SwTableBox *const pSubTableBox(pSourceLine->GetTabBoxes()[nBox]);
+    assert(!pSubTableBox->GetTabLines().empty());
+    // are relative (%) heights possible? apparently not
+    SwFormatFrameSize const outerSize(pSourceLine->GetFrameFormat()->GetFrameSize());
+    long minHeights(0);
+    {
+        SwFormatFrameSize const* pSize(nullptr);
+        SwFrameFormat const& rSubLineFormat(*pSubTableBox->GetTabLines()[0]->GetFrameFormat());
+        if (rSubLineFormat.GetItemState(RES_FRM_SIZE, true,
+            reinterpret_cast<SfxPoolItem const**>(&pSize)) == SfxItemState::SET)
+        {   // for first row, apply height from inner row to outer row.
+            // in case the existing outer row height was larger than the entire
+            // subtable, the last inserted row needs to be tweaked (below)
+            pSourceLine->GetFrameFormat()->SetFormatAttr(*pSize);
+            if (pSize->GetHeightSizeType() != ATT_VAR_SIZE)
+            {
+                minHeights += pSize->GetHeight();
+            }
+        }
+    }
+    for (size_t i = 1; i < pSubTableBox->GetTabLines().size(); ++i)
+    {
+        SwTableLine *const pSubLine(pSubTableBox->GetTabLines()[i]);
+        SwTableLine *const pNewLine = new SwTableLine(
+            static_cast<SwTableLineFormat*>(pSourceLine->GetFrameFormat()),
+            pSourceLine->GetTabBoxes().size() - 1 + pSubLine->GetTabBoxes().size(),
+            nullptr);
+        SwFrameFormat const& rSubLineFormat(*pSubLine->GetFrameFormat());
+        SwFormatFrameSize const* pSize(nullptr);
+        if (rSubLineFormat.GetItemState(RES_FRM_SIZE, true,
+            reinterpret_cast<SfxPoolItem const**>(&pSize)) == SfxItemState::SET)
+        {   // for rows 2..N, copy inner row height to outer row
+            pNewLine->ClaimFrameFormat();
+            pNewLine->GetFrameFormat()->SetFormatAttr(*pSize);
+            if (pSize->GetHeightSizeType() != ATT_VAR_SIZE)
+            {
+                minHeights += pSize->GetHeight();
+            }
+        }
+        // ensure the sum of the lines is at least as high as the outer line was
+        if (i == pSubTableBox->GetTabLines().size() - 1
+            && outerSize.GetHeightSizeType() != ATT_VAR_SIZE
+            && minHeights < outerSize.GetHeight())
+        {
+            SwFormatFrameSize lastSize(pNewLine->GetFrameFormat()->GetFrameSize());
+            lastSize.SetHeight(lastSize.GetHeight() + outerSize.GetHeight() - minHeights);
+            if (lastSize.GetHeightSizeType() == ATT_VAR_SIZE)
+            {
+                lastSize.SetHeightSizeType(ATT_MIN_SIZE);
+            }
+            pNewLine->GetFrameFormat()->SetFormatAttr(lastSize);
+        }
+        SfxPoolItem const* pRowBrush(nullptr);
+        rSubLineFormat.GetItemState(RES_BACKGROUND, true, &pRowBrush);
+        GetTabLines().insert(GetTabLines().begin() + nRow + i, pNewLine);
+        for (size_t j = 0; j < pSourceLine->GetTabBoxes().size(); ++j)
+        {
+            if (j == nBox)
+            {
+                for (size_t k = 0; k < pSubLine->GetTabBoxes().size(); ++k)
+                {
+                    // move box k to new outer row
+                    SwTableBox *const pSourceBox(pSubLine->GetTabBoxes()[k]);
+                    assert(pSourceBox->getRowSpan() == 1);
+                    // import filter (xmltbli.cxx) converts all box widths to absolute
+                    assert(pSourceBox->GetFrameFormat()->GetFrameSize().GetWidthPercent() == 0);
+                    ::InsTableBox(pDoc, GetTableNode(), pNewLine,
+                        static_cast<SwTableBoxFormat*>(pSourceBox->GetFrameFormat()),
+                        pSourceBox, j+k, 1);
+                    // insert dummy text node...
+                    pDoc->GetNodes().MakeTextNode(
+                            SwNodeIndex(*pSourceBox->GetSttNd(), +1),
+                            pDoc->GetDfltTextFormatColl());
+                    SwNodeRange content(*pSourceBox->GetSttNd(), +2,
+                            *pSourceBox->GetSttNd()->EndOfSectionNode());
+                    SwTableBox *const pNewBox(pNewLine->GetTabBoxes()[j+k]);
+                    SwNodeIndex insPos(*pNewBox->GetSttNd(), 1);
+                    // MoveNodes would delete the box SwStartNode/SwEndNode
+                    // without the dummy node
+#if 0
+                    pDoc->GetNodes().MoveNodes(content, pDoc->GetNodes(), insPos, false);
+#else
+                    pDoc->getIDocumentContentOperations().MoveNodeRange(content, insPos, SwMoveFlags::NO_DELFRMS);
+#endif
+                    // delete the empty node that was bundled in the new box
+                    pDoc->GetNodes().Delete(insPos);
+                    if (pRowBrush)
+                    {
+                        SfxPoolItem const* pCellBrush(nullptr);
+                        if (pNewBox->GetFrameFormat()->GetItemState(RES_BACKGROUND, true, &pCellBrush) != SfxItemState::SET)
+                        {   // set inner row background on inner cell
+                            pNewBox->ClaimFrameFormat();
+                            pNewBox->GetFrameFormat()->SetFormatAttr(*pRowBrush);
+                        }
+                    }
+                    // assume that the borders can be left as they are, because
+                    // lines don't have borders, only boxes do
+                }
+            }
+            else
+            {
+                // insert covered cell for box j
+                SwTableBox *const pSourceBox(pSourceLine->GetTabBoxes()[j]);
+                assert(pSourceBox->GetTabLines().empty()); // checked for that
+                sal_uInt16 const nInsPos(j < nBox ? j : j + pSubLine->GetTabBoxes().size() - 1);
+                ::InsTableBox(pDoc, GetTableNode(), pNewLine,
+                    static_cast<SwTableBoxFormat*>(pSourceBox->GetFrameFormat()),
+                    pSourceBox, nInsPos, 1);
+                // adjust row span:
+                // N rows in subtable, N-1 rows inserted:
+                // -1 -> -N ; -(N-1) ... -1
+                // -2 -> -(N+1) ; -N .. -2
+                //  1 -> N ; -(N-1) .. -1
+                //  2 -> N+1 ; -N .. -2
+                long newSourceRowSpan(pSourceBox->getRowSpan());
+                long newBoxRowSpan;
+                if (newSourceRowSpan < 0)
+                {
+                    newSourceRowSpan -= pSubTableBox->GetTabLines().size() - 1;
+                    newBoxRowSpan = newSourceRowSpan + i;
+                }
+                else
+                {
+                    newSourceRowSpan += pSubTableBox->GetTabLines().size() - 1;
+                    newBoxRowSpan = -(newSourceRowSpan - sal::static_int_cast<long>(i));
+                }
+                pNewLine->GetTabBoxes()[nInsPos]->setRowSpan(newBoxRowSpan);
+                if (i == pSubTableBox->GetTabLines().size() - 1)
+                {   // only last iteration
+                    pSourceBox->setRowSpan(newSourceRowSpan);
+                }
+            }
+        }
+    }
+    // delete inner rows 2..N
+    while (1 < pSubTableBox->GetTabLines().size())
+    {
+        // careful: the last box deletes pSubLine!
+        SwTableLine *const pSubLine(pSubTableBox->GetTabLines()[1]);
+        for (size_t j = pSubLine->GetTabBoxes().size(); 0 < j; --j)
+        {
+            SwTableBox *const pBox(pSubLine->GetTabBoxes()[0]);
+            DeleteBox_(*this, pBox, nullptr, false, false, nullptr);
+        }
+    }
+    // fix row spans in lines preceding nRow
+    lcl_ChangeRowSpan(*this, pSubTableBox->GetTabLines().size() - 1, nRow - 1, false);
+    // note: the first line of the inner table remains; caller will call
+    //       GCLines() to remove it
+}
+
+bool SwTable::CanConvertSubtables() const
+{
+    for (SwTableLine const*const pLine : GetTabLines())
+    {
+        bool haveSubtable(false);
+        for (SwTableBox const*const pBox : pLine->GetTabBoxes())
+        {
+            if (pBox->IsFormulaOrValueBox() == RES_BOXATR_FORMULA)
+            {
+                return false; // no table box formulas yet
+            }
+            if (!pBox->GetTabLines().empty())
+            {
+                if (haveSubtable)
+                {   // can't handle 2 subtable in a row yet
+                    return false;
+                }
+                haveSubtable = true;
+                for (SwTableLine const*const pInnerLine : pBox->GetTabLines())
+                {
+                    // bitmap row background will look different
+                    SwFrameFormat const& rRowFormat(*pInnerLine->GetFrameFormat());
+                    std::shared_ptr<SvxBrushItem> pBrush(rRowFormat.makeBackgroundBrushItem());
+                    assert(pBrush);
+                    if (pBrush->GetGraphicObject() != nullptr)
+                    {
+                        /* TODO: all cells could override this?
+                        for (SwTableBox & rInnerBox : rInnerLine.GetTabBoxes())
+                        */
+                        if (1 < pInnerLine->GetTabBoxes().size()) // except if only 1 cell?
+                        {
+                            return false;
+                        }
+                    }
+                    for (SwTableBox const*const pInnerBox : pInnerLine->GetTabBoxes())
+                    {
+                        if (!pInnerBox->GetTabLines().empty())
+                        {
+                            return false; // nested subtable :(
+                        }
+                    }
+                }
+            }
+        }
+    }
+    // note: fields that refer to table cells may be *outside* the table,
+    // so the entire document needs to be imported before checking here
+    // (same for table box formulas and charts)
+    SwDoc *const pDoc(GetFrameFormat()->GetDoc());
+    SwFieldType const*const pTableFields(
+        pDoc->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Table, "", false));
+    SwIterator<SwFormatField, SwFieldType> aIter(*pTableFields);
+    if (aIter.First() != nullptr)
+    {
+        return false; // no formulas in fields yet
+    }
+    if (pDoc->GetAttrPool().GetItemCount2(RES_BOXATR_FORMULA) != 0)
+    {
+        return false; // no table box formulas yet
+    }
+    OUString const tableName(GetFrameFormat()->GetName());
+    SwNodeIndex temp(*pDoc->GetNodes().GetEndOfAutotext().StartOfSectionNode(), +1);
+    while (SwStartNode const*const pStartNode = temp.GetNode().GetStartNode())
+    {
+        ++temp;
+        SwOLENode const*const pOLENode(temp.GetNode().GetOLENode());
+        if (pOLENode && tableName == pOLENode->GetChartTableName())
+        {   // there are charts that refer to this table
+            // presumably such charts would need to be adapted somehow?
+            return  false;
+        }
+        temp.Assign(*pStartNode->EndOfSectionNode(), +1);
+    }
+    return true;
+}
+
+void SwTable::ConvertSubtables()
+{
+    for (size_t i = 0; i < GetTabLines().size(); ++i)
+    {
+        SwTableLine *const pLine(GetTabLines()[i]);
+        for (size_t j = 0; j < pLine->GetTabBoxes().size(); ++j)
+        {
+            SwTableBox *const pBox(pLine->GetTabBoxes()[j]);
+            SwTableLines & rInnerLines(pBox->GetTabLines());
+            if (!rInnerLines.empty())
+            {
+                ConvertSubtableBox(i, j);
+            }
+        }
+    }
+    GCLines();
+    m_bNewModel = true;
+#if 0
+    // note: outline nodes (and ordinary lists) are sorted by MoveNodes() itself
+    //       (this could change order inside table of contents, but that's a
+    //       really esoteric use-case)
+    // nodes were moved - sort marks, redlines, footnotes
+    SwDoc *const pDoc(GetFrameFormat()->GetDoc());
+    pDoc->getIDocumentMarkAccess()->assureSortedMarkContainers();
+    pDoc->getIDocumentRedlineAccess().GetRedlineTable().Resort();
+    pDoc->GetFootnoteIdxs().UpdateAllFootnote();
+#endif
+    // assume that there aren't any node indexes to the deleted box start/end nodes
+    CHECK_TABLE( *this )
+}
+
 #ifdef DBG_UTIL
 
 struct RowSpanCheck
diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx
index 75766a7f8a64..68a72af1cb2f 100644
--- a/sw/source/filter/xml/xmlimp.cxx
+++ b/sw/source/filter/xml/xmlimp.cxx
@@ -967,6 +967,22 @@ void SwXMLImport::endDocument()
         }
     }
 
+#if 1
+    if (!pDoc) { pDoc = SwImport::GetDocFromXMLImport(*this); }
+    for (sal_uLong i = 0; i < pDoc->GetNodes().Count(); ++i)
+    {
+        if (SwTableNode *const pTableNode = pDoc->GetNodes()[i]->GetTableNode())
+        {
+            if (!pTableNode->GetTable().IsNewModel()
+                && pTableNode->GetTable().CanConvertSubtables())
+            {
+                pTableNode->GetTable().ConvertSubtables();
+            }
+        }
+        // don't skip to the end; nested tables could have subtables too...
+    }
+#endif
+
     // delegate to parent: takes care of error handling
     SvXMLImport::endDocument();
     ClearTextImport();
commit 1bb8842f8c1f8bd12a3b9e6a99c037579654d2cd
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Oct 1 17:29:06 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:32 2020 +0200

    sw: SwTable::GCLines(): don't throw away row background
    
    If there's a row background, and a cell in the row doesn't override it,
    apply the row background to the cell.
    
    Change-Id: I37cd33249d3ab66c898c537e3bc6bab067d6f74b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103772
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit e65b1ba0033e1adaa4135539bb7b34b28cbedd7c)

diff --git a/sw/source/core/doc/gctable.cxx b/sw/source/core/doc/gctable.cxx
index 493ef4248c91..1d5a2a4eed25 100644
--- a/sw/source/core/doc/gctable.cxx
+++ b/sw/source/core/doc/gctable.cxx
@@ -351,6 +351,21 @@ static bool lcl_MergeGCBox(SwTableBox* pTableBox, GCLinePara* pPara)
             for( auto pTabBox : pCpyLine->GetTabBoxes() )
                 pTabBox->SetUpper( pInsLine );
 
+            SfxPoolItem const* pRowBrush(nullptr);
+            pCpyLine->GetFrameFormat()->GetItemState(RES_BACKGROUND, true, &pRowBrush);
+            if (pRowBrush)
+            {
+                for (auto pBox : pCpyLine->GetTabBoxes())
+                {
+                    SfxPoolItem const* pCellBrush(nullptr);
+                    if (pBox->GetFrameFormat()->GetItemState(RES_BACKGROUND, true, &pCellBrush) != SfxItemState::SET)
+                    {   // set inner row background on inner cell
+                        pBox->ClaimFrameFormat();
+                        pBox->GetFrameFormat()->SetFormatAttr(*pRowBrush);
+                    }
+                }
+            }
+
             // remove the old box from its parent line
             it = pInsLine->GetTabBoxes().erase( it );
             // insert the nested line's boxes in its place
commit 0352089409859b0017a877b26d1c8590f8a4e5f1
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Oct 1 17:26:43 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:32 2020 +0200

    sw: improve comments, dump rowspan to nodes.xml
    
    Change-Id: Ifcd011f6d55ac534c449050d07009680dcd71d51
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103771
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 309868c32f00e5ca045f941deafb5216aad2538c)

diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx
index a0deaf01e892..a373f561704f 100644
--- a/sw/inc/swtable.hxx
+++ b/sw/inc/swtable.hxx
@@ -310,7 +310,9 @@ public:
     // Search in format for registered table.
     static SwTable * FindTable( SwFrameFormat const*const pFormat );
 
-    // Clean up structure a bit.
+    // Clean up structure of subtables a bit:
+    // convert row with 1 box with subtable; box with subtable with 1 row;
+    // by removing the subtable (both recursively)
     void GCLines();
 
     // Returns the table node via m_TabSortContentBoxes or pTableNode.
diff --git a/sw/inc/tblsel.hxx b/sw/inc/tblsel.hxx
index 0639db32f72e..cc353cc424bb 100644
--- a/sw/inc/tblsel.hxx
+++ b/sw/inc/tblsel.hxx
@@ -160,8 +160,8 @@ class FndBox_
     FndLines_t m_Lines;
     FndLine_* const m_pUpper;
 
-    SwTableLine *m_pLineBefore;   // For deleting/restoring the layout.
-    SwTableLine *m_pLineBehind;
+    SwTableLine *m_pLineBefore; ///< For deleting/restoring the layout.
+    SwTableLine *m_pLineBehind; ///< For deleting/restoring the layout.
 
     FndBox_(FndBox_ const&) = delete;
     FndBox_& operator=(FndBox_ const&) = delete;
@@ -224,6 +224,10 @@ struct FndPara
         : rBoxes(rPara.rBoxes), pFndLine(pFL), pFndBox(rPara.pFndBox) {}
 };
 
+/** This creates a structure mirroring the SwTable structure that contains all
+    rows and non-leaf boxes (as pointers to SwTableBox/SwTableLine, not copies),
+    plus the leaf boxes that are selected by pFndPara->rBoxes
+ */
 SW_DLLPUBLIC void ForEach_FndLineCopyCol(SwTableLines& rLines, FndPara* pFndPara );
 
 #endif // INCLUDED_SW_INC_TBLSEL_HXX
diff --git a/sw/source/core/docnode/node.cxx b/sw/source/core/docnode/node.cxx
index 955e113f2768..61e8bd112d23 100644
--- a/sw/source/core/docnode/node.cxx
+++ b/sw/source/core/docnode/node.cxx
@@ -985,6 +985,8 @@ void SwStartNode::dumpAsXml(xmlTextWriterPtr pWriter) const
     }
     else if (GetStartNodeType() == SwTableBoxStartNode)
     {
+        if (SwTableBox* pBox = GetTableBox())
+            xmlTextWriterWriteAttribute(pWriter, BAD_CAST("rowspan"), BAD_CAST(OString::number(pBox->getRowSpan()).getStr()));
         xmlTextWriterStartElement(pWriter, BAD_CAST("attrset"));
         if (SwTableBox* pBox = GetTableBox())
             pBox->GetFrameFormat()->GetAttrSet().dumpAsXml(pWriter);
commit f208469414f0f8823fe8003fd0e4c78b3c51bb02
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Sep 18 11:47:56 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:32 2020 +0200

    tdf#136620 tdf#136708 filter,oox,sw: fix export of 2 different wraps
    
    This reverts commit 2cb90a5c87fe46737c8d840967d8836284f92ffd.
    
    Revert the change to EscherPropertyContainer, which was completely
    bogus, based on pre-existing bogus code in VMLExport::Commit().
    
    The problem is that ESCHER_Wrap values are for wrapping text *inside* a
    text box, which is "mso-wrap-style" in VML, whereas VML's w10:wrap
    element defines how text wraps *around* a shape, doesn't exist as an
    ESCHER property and is specific to Word formats.
    
    Instead, export the w10:wrap element in VMLExport::EndShape().
    
    This has 2 callers, WriteActiveXControl() and writeVMLDrawing().
    
    Furthermore the value "none" wasn't written for WrapTextMode_THROUGH,
    which caused the wrap element to be omitted in that case.
    
    Change-Id: Id4a01fcb2ea73fa9bef4ee8769b5e0680e059f15
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103009
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit fdc8590032b292dcb8152b328401e591fea642a4)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103090
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit c54d697e2ac379d4b1a3ff5acb6f06bff30cadd6)

diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx
index a2071237deb7..f04043e9156a 100644
--- a/filter/source/msfilter/escherex.cxx
+++ b/filter/source/msfilter/escherex.cxx
@@ -66,7 +66,6 @@
 #include <com/sun/star/drawing/FlagSequence.hpp>
 #include <com/sun/star/drawing/PolygonFlags.hpp>
 #include <com/sun/star/text/WritingMode.hpp>
-#include <com/sun/star/text/WrapTextMode.hpp>
 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
@@ -700,10 +699,6 @@ void EscherPropertyContainer::CreateTextProperties(
     bool bWordWrap          ( false );
     bool bAutoGrowSize      ( false );
 
-    uno::Any aTextWrap;
-
-    EscherPropertyValueHelper::GetPropertyValue(aTextWrap, rXPropSet, "TextWrap", true);
-
     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextWritingMode", true ) )
         aAny >>= eWM;
     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextVerticalAdjust", true ) )
@@ -842,21 +837,6 @@ void EscherPropertyContainer::CreateTextProperties(
                 nTextAttr |= 0x20002;
         }
     }
-
-    if (aTextWrap.hasValue())
-    {   // explicit text wrap overrides whatever was inferred previously
-        switch (aTextWrap.get<text::WrapTextMode>())
-        {
-            case text::WrapTextMode_THROUGH:
-                eWrapMode = ESCHER_WrapNone;
-                break;
-            // in theory there are 3 more Escher_Wrap, but [MS-ODRAW] says they are useless
-            default:
-                eWrapMode = ESCHER_WrapSquare;
-                break;
-        }
-    }
-
     AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 );
     AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 );
     AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 );
diff --git a/include/oox/export/vmlexport.hxx b/include/oox/export/vmlexport.hxx
index 7c2d3a62da6f..3736420756a6 100644
--- a/include/oox/export/vmlexport.hxx
+++ b/include/oox/export/vmlexport.hxx
@@ -80,8 +80,9 @@ class OOX_DLLPUBLIC VMLExport : public EscherEx
     /// Parent exporter, used for text callback.
     VMLTextExport* m_pTextExport;
 
-    /// Anchoring.
+    /// Anchoring - Writer specific properties
     sal_Int16 m_eHOri, m_eVOri, m_eHRel, m_eVRel;
+    std::unique_ptr<sax_fastparser::FastAttributeList> m_pWrapAttrList;
     bool m_bInline; // css::text::TextContentAnchorType_AS_CHARACTER
 
     /// The object we're exporting.
@@ -139,7 +140,9 @@ public:
     /// Call this when you need to export the object as VML.
     OString const & AddSdrObject( const SdrObject& rObj, sal_Int16 eHOri = -1,
             sal_Int16 eVOri = -1, sal_Int16 eHRel = -1,
-            sal_Int16 eVRel = -1, const bool bOOxmlExport = false );
+            sal_Int16 eVRel = -1,
+            std::unique_ptr<sax_fastparser::FastAttributeList> m_pWrapAttrList = nullptr,
+            const bool bOOxmlExport = false );
     OString const & AddInlineSdrObject( const SdrObject& rObj, const bool bOOxmlExport );
     virtual void  AddSdrObjectVMLObject( const SdrObject& rObj) override;
     static bool IsWaterMarkShape(const OUString& rStr);
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index ee93cf32bd27..2009d9ccf055 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -421,11 +421,15 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle&
                         case ESCHER_WrapSquare:
                         case ESCHER_WrapByPoints:  pWrapType = "square"; break; // these two are equivalent according to the docu
                         case ESCHER_WrapNone:      pWrapType = "none"; break;
-                        case ESCHER_WrapTopBottom: pWrapType = "topAndBottom"; break;
-                        case ESCHER_WrapThrough:   pWrapType = "through"; break;
+                        case ESCHER_WrapTopBottom:
+                        case ESCHER_WrapThrough:
+                            break; // last two are *undefined* in MS-ODRAW, don't exist in VML
                     }
                     if ( pWrapType )
-                        m_pSerializer->singleElementNS(XML_w10, XML_wrap, XML_type, pWrapType);
+                    {
+                        m_ShapeStyle.append(";mso-wrap-style:");
+                        m_ShapeStyle.append(pWrapType);
+                    }
                 }
                 bAlreadyWritten[ ESCHER_Prop_WrapText ] = true;
                 break;
@@ -1477,18 +1481,27 @@ void VMLExport::EndShape( sal_Int32 nShapeElement )
             m_pSerializer->endElementNS(XML_v, XML_textbox);
         }
 
+        if (m_pWrapAttrList)
+        {
+            sax_fastparser::XFastAttributeListRef const pWrapAttrList(m_pWrapAttrList.release());
+            m_pSerializer->singleElementNS(XML_w10, XML_wrap, pWrapAttrList);
+        }
+
         // end of the shape
         m_pSerializer->endElementNS( XML_v, nShapeElement );
     }
 }
 
-OString const & VMLExport::AddSdrObject( const SdrObject& rObj, sal_Int16 eHOri, sal_Int16 eVOri, sal_Int16 eHRel, sal_Int16 eVRel, const bool bOOxmlExport )
+OString const & VMLExport::AddSdrObject( const SdrObject& rObj, sal_Int16 eHOri, sal_Int16 eVOri, sal_Int16 eHRel, sal_Int16 eVRel,
+        std::unique_ptr<FastAttributeList> pWrapAttrList,
+        const bool bOOxmlExport )
 {
     m_pSdrObject = &rObj;
     m_eHOri = eHOri;
     m_eVOri = eVOri;
     m_eHRel = eHRel;
     m_eVRel = eVRel;
+    m_pWrapAttrList = std::move(pWrapAttrList);
     m_bInline = false;
     EscherEx::AddSdrObject(rObj, bOOxmlExport);
     return m_sShapeId;
@@ -1501,6 +1514,7 @@ OString const & VMLExport::AddInlineSdrObject( const SdrObject& rObj, const bool
     m_eVOri = -1;
     m_eHRel = -1;
     m_eVRel = -1;
+    m_pWrapAttrList.reset();
     m_bInline = true;
     EscherEx::AddSdrObject(rObj, bOOxmlExport);
     return m_sShapeId;
diff --git a/sc/source/filter/xcl97/xcl97rec.cxx b/sc/source/filter/xcl97/xcl97rec.cxx
index 4a4656f57a94..58a4045cd7dd 100644
--- a/sc/source/filter/xcl97/xcl97rec.cxx
+++ b/sc/source/filter/xcl97/xcl97rec.cxx
@@ -59,6 +59,8 @@
 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
 #include <com/sun/star/chart2/XChartDocument.hpp>
+
+#include <sax/fastattribs.hxx>
 #include <oox/token/tokens.hxx>
 #include <oox/token/namespaces.hxx>
 #include <oox/token/relationship.hxx>
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 4256c8cf9cba..270ab6fe964f 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -5347,10 +5347,14 @@ void DocxAttributeOutput::WriteActiveXControl(const SdrObject* pObject, const Sw
     {
         const SwFormatHoriOrient& rHoriOri = rFrameFormat.GetHoriOrient();
         const SwFormatVertOrient& rVertOri = rFrameFormat.GetVertOrient();
+        SwFormatSurround const& rSurround(rFrameFormat.GetSurround());
+        std::unique_ptr<sax_fastparser::FastAttributeList> pAttrList(docx::SurroundToVMLWrap(rSurround));
         sShapeId = m_rExport.VMLExporter().AddSdrObject(*pObject,
             rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(),
             rHoriOri.GetRelationOrient(),
-            rVertOri.GetRelationOrient(), true);
+            rVertOri.GetRelationOrient(),
+            std::move(pAttrList),
+            true);
     }
     // Restore default values
     m_rExport.VMLExporter().SetSkipwzName(false);
@@ -8352,43 +8356,64 @@ void DocxAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
     }
 }
 
-void DocxAttributeOutput::FormatSurround( const SwFormatSurround& rSurround )
+namespace docx {
+
+std::unique_ptr<FastAttributeList> SurroundToVMLWrap(SwFormatSurround const& rSurround)
 {
-    if (m_rExport.SdrExporter().getTextFrameSyntax())
+    FastAttributeList * pAttrList(nullptr);
+    OString sType;
+    OString sSide;
+    switch (rSurround.GetSurround())
+    {
+        case css::text::WrapTextMode_NONE:
+            sType = "topAndBottom";
+            break;
+        case css::text::WrapTextMode_PARALLEL:
+            sType = "square";
+            break;
+        case css::text::WrapTextMode_DYNAMIC:
+            sType = "square";
+            sSide = "largest";
+            break;
+        case css::text::WrapTextMode_LEFT:
+            sType = "square";
+            sSide = "left";
+            break;
+        case css::text::WrapTextMode_RIGHT:
+            sType = "square";
+            sSide = "right";
+            break;
+        case css::text::WrapTextMode_THROUGH:
+            /* empty type and side means through */
+        default:
+            sType = "none";
+            break;
+    }
+    if (!sType.isEmpty() || !sSide.isEmpty())
     {
-        OString sType, sSide;
-        switch (rSurround.GetSurround())
+        pAttrList = FastSerializerHelper::createAttrList();
+        if (!sType.isEmpty())
         {
-            case css::text::WrapTextMode_NONE:
-                sType = "topAndBottom";
-                break;
-            case css::text::WrapTextMode_PARALLEL:
-                sType = "square";
-                break;
-            case css::text::WrapTextMode_DYNAMIC:
-                sType = "square";
-                sSide = "largest";
-                break;
-            case css::text::WrapTextMode_LEFT:
-                sType = "square";
-                sSide = "left";
-                break;
-            case css::text::WrapTextMode_RIGHT:
-                sType = "square";
-                sSide = "right";
-                break;
-            case css::text::WrapTextMode_THROUGH:
-                /* empty type and side means through */
-            default:
-                break;
+            pAttrList->add(XML_type, sType);
+        }
+        if (!sSide.isEmpty())
+        {
+            pAttrList->add(XML_side, sSide);
         }
-        if (!sType.isEmpty() || !sSide.isEmpty())
+    }
+    return std::unique_ptr<FastAttributeList>(pAttrList);
+}
+
+} // namespace docx
+
+void DocxAttributeOutput::FormatSurround( const SwFormatSurround& rSurround )
+{
+    if (m_rExport.SdrExporter().getTextFrameSyntax())
+    {
+        std::unique_ptr<FastAttributeList> pAttrList(docx::SurroundToVMLWrap(rSurround));
+        if (pAttrList)
         {
-            m_rExport.SdrExporter().setFlyWrapAttrList(FastSerializerHelper::createAttrList());
-            if (!sType.isEmpty())
-                m_rExport.SdrExporter().getFlyWrapAttrList()->add(XML_type, sType);
-            if (!sSide.isEmpty())
-                m_rExport.SdrExporter().getFlyWrapAttrList()->add(XML_side, sSide);
+            m_rExport.SdrExporter().setFlyWrapAttrList(pAttrList.release());
         }
     }
     else if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 2b6e83dde2d6..b04ad82cff7e 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -1045,6 +1045,12 @@ struct DocxTableExportContext
     ~DocxTableExportContext() { m_rOutput.popFromTableExportContext(*this); }
 };
 
+namespace docx {
+
+std::unique_ptr<sax_fastparser::FastAttributeList> SurroundToVMLWrap(SwFormatSurround const& rSurround);
+
+}
+
 #endif // INCLUDED_SW_SOURCE_FILTER_WW8_DOCXATTRIBUTEOUTPUT_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx
index b86c64daeb24..a1f8b7b2f5be 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -827,9 +827,13 @@ void DocxSdrExport::writeVMLDrawing(const SdrObject* sdrObj, const SwFrameFormat
 
     const SwFormatHoriOrient& rHoriOri = rFrameFormat.GetHoriOrient();
     const SwFormatVertOrient& rVertOri = rFrameFormat.GetVertOrient();
+    SwFormatSurround const& rSurround(rFrameFormat.GetSurround());
+
+    std::unique_ptr<sax_fastparser::FastAttributeList> pAttrList(
+        docx::SurroundToVMLWrap(rSurround));
     m_pImpl->getExport().VMLExporter().AddSdrObject(
         *sdrObj, rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(), rHoriOri.GetRelationOrient(),
-        rVertOri.GetRelationOrient(), true);
+        rVertOri.GetRelationOrient(), std::move(pAttrList), true);
     m_pImpl->getSerializer()->endElementNS(XML_w, XML_pict);
 }
 
commit dd551398fce0a5f0fb604427a49b086b561b0f70
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Thu Sep 10 09:45:08 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:32 2020 +0200

    .gitreview: Update default branch
    
    Change-Id: Ifcbcd3427508b468a9f1872b563c93760854becf
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102364
    Tested-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
    Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>

diff --git a/.gitreview b/.gitreview
index 4cd7d22d9a83..2bbb2f4856f3 100644
--- a/.gitreview
+++ b/.gitreview
@@ -3,5 +3,4 @@ host=gerrit.libreoffice.org
 port=29418
 project=core
 defaultremote=logerrit
-defaultbranch=libreoffice-6-4
-
+defaultbranch=feature/cib_contract3753
commit 9969b1a2a07aa28022050aa96365051f15cb669b
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 26 17:08:00 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:31 2020 +0200

    sw: DOCX export: don't export text frames as transparent
    
    Writer paints text frames without fill still as opaque but nothing is
    written in the DOCX file and Word by default treats DrawingML text frame
    as transparent (the VML fallback is opaque though).
    
    Change-Id: I0ce539ac8084c5047b4732abc5c199589ee369ee

diff --git a/sw/qa/extras/ooxmlexport/data/frame.fodt b/sw/qa/extras/ooxmlexport/data/frame.fodt
new file mode 100644
index 000000000000..c474b8de5e9e
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/frame.fodt
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rpt="http://openoffice.org/2005/report" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:d
 r3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+  <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+  <style:font-face style:name="Lohit Devanagari" svg:font-family="'Lohit Devanagari'" style:font-family-generic="system" style:font-pitch="variable"/>
+  <style:font-face style:name="Source Han Serif CN" svg:font-family="'Source Han Serif CN'" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="graphic">
+   <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+   <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+   <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Source Han Serif CN" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lohit Devanagari" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
+  </style:default-style>
+  <style:default-style style:family="paragraph">
+   <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+   <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Source Han Serif CN" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lohit Devanagari" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
+  </style:default-style>
+  <style:default-style style:family="table">
+   <style:table-properties table:border-model="collapsing"/>
+  </style:default-style>
+  <style:default-style style:family="table-row">
+   <style:table-row-properties fo:keep-together="auto"/>
+  </style:default-style>
+  <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+  <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"/>
+  <style:style style:name="Frame" style:family="graphic">
+   <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" fo:margin-left="0.201cm" fo:margin-right="0.201cm" fo:margin-top="0.201cm" fo:margin-bottom="0.201cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" fo:padding="0.15cm" fo:border="0.06pt solid #000000"/>
+  </style:style>
+
+  <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
+  <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
+  <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame">
+   <style:graphic-properties style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:opacity="0%" draw:wrap-influence-on-position="once-concurrent"/>
+  </style:style>
+  <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Frame">
+   <style:graphic-properties style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" fo:background-color="#e8f2a1" draw:fill="solid" draw:fill-color="#e8f2a1" draw:wrap-influence-on-position="once-concurrent"/>
+  </style:style>
+  <style:style style:name="fr3" style:family="graphic" style:parent-style-name="Frame">
+   <style:graphic-properties style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph"/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm">
+    <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+   </style:page-layout-properties>
+   <style:header-style/>
+   <style:footer-style/>
+  </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+  <office:text>
+   <text:p text:style-name="Standard"><draw:frame draw:style-name="fr3" draw:name="Frame1" text:anchor-type="paragraph" svg:x="0.87cm" svg:y="0cm" svg:width="2cm" draw:z-index="0">
+     <draw:text-box fo:min-height="0.499cm">
+      <text:p text:style-name="Frame_20_contents">opaque</text:p>
+     </draw:text-box>
+    </draw:frame><draw:frame draw:style-name="fr2" draw:name="Frame2" text:anchor-type="paragraph" svg:x="3.069cm" svg:y="0cm" svg:width="2cm" draw:z-index="1">
+     <draw:text-box fo:min-height="0.499cm">
+      <text:p text:style-name="Frame_20_contents">solid</text:p>
+     </draw:text-box>
+    </draw:frame><draw:frame draw:style-name="fr1" draw:name="Frame3" text:anchor-type="paragraph" svg:x="5.33cm" svg:y="0cm" svg:width="2.281cm" draw:z-index="2">
+     <draw:text-box fo:min-height="0.499cm">
+      <text:p text:style-name="Frame_20_contents">transparent</text:p>
+     </draw:text-box>
+    </draw:frame></text:p>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
index a8fe7ac73ea0..4318856bdae2 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
@@ -142,6 +142,29 @@ DECLARE_OOXMLEXPORT_TEST(testDMLSolidfillAlpha, "dml-solidfill-alpha.docx")
     CPPUNIT_ASSERT_EQUAL(sal_Int16(20), getProperty<sal_Int16>(xShape, "FillTransparence"));
 }
 
+DECLARE_OOXMLEXPORT_TEST(testDMLTextFrameNoFill, "frame.fodt")
+{
+    // Problem is that default text frame background is white in Writer and transparent in Word
+    uno::Reference<beans::XPropertySet> xShape1(getShape(1), uno::UNO_QUERY);
+// it is re-imported as solid
+//    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, getProperty<drawing::FillStyle>(xShape1, "FillStyle"));
+    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xShape1, "FillStyle"));
+    CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(xShape1, "FillTransparence"));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0xffffff), getProperty<sal_Int32>(xShape1, "FillColor"));
+
+    uno::Reference<beans::XPropertySet> xShape2(getShape(2), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xShape2, "FillStyle"));
+    CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(xShape2, "FillTransparence"));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0xE8F2A1), getProperty<sal_Int32>(xShape2, "FillColor"));
+
+    uno::Reference<beans::XPropertySet> xShape3(getShape(3), uno::UNO_QUERY);
+// it is re-imported as solid
+//    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, getProperty<drawing::FillStyle>(xShape3, "FillStyle"));
+    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xShape3, "FillStyle"));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0xffffff), getProperty<sal_Int32>(xShape3, "FillColor"));
+    CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty<sal_Int16>(xShape3, "FillTransparence"));
+}
+
 DECLARE_OOXMLEXPORT_TEST(testDMLCustomGeometry, "dml-customgeometry-cubicbezier.docx")
 {
 
diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx
index 3d8daa633daa..38cd3f8893b3 100644
--- a/sw/source/filter/ww8/attributeoutputbase.hxx
+++ b/sw/source/filter/ww8/attributeoutputbase.hxx
@@ -668,6 +668,8 @@ public:
     ( ww8::WW8TableNodeInfoInner const * pTableTextNodeInfoInner,
       long& rPageSize, bool& rRelBoxSize );
 
+    virtual void MaybeOutputBrushItem(SfxItemSet const&) { }
+
     /// Exports the definition (image, size) of a single numbering picture bullet.
     virtual void BulletDefinition(int /*nId*/, const Graphic& /*rGraphic*/, Size /*aSize*/) {}
 
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index c03d971e8fdc..4256c8cf9cba 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -90,9 +90,11 @@
 #include <editeng/editobj.hxx>
 #include <editeng/keepitem.hxx>
 #include <svx/xfillit0.hxx>
+#include <svx/xflclit.hxx>
 #include <svx/xflgrit.hxx>
 #include <svx/fmglob.hxx>
 #include <svx/svdouno.hxx>
+#include <svx/unobrushitemhelper.hxx>
 #include <svl/grabbagitem.hxx>
 #include <sfx2/sfxbasemodel.hxx>
 #include <tools/datetimeutils.hxx>
@@ -5822,6 +5824,27 @@ oox::drawingml::DrawingML& DocxAttributeOutput::GetDrawingML()
     return m_rDrawingML;
 }
 
+void DocxAttributeOutput::MaybeOutputBrushItem(SfxItemSet const& rSet)
+{
+    const XFillStyleItem* pXFillStyleItem(rSet.GetItem<XFillStyleItem>(XATTR_FILLSTYLE));
+
+    if ((pXFillStyleItem && pXFillStyleItem->GetValue() != drawing::FillStyle_NONE)
+        || !m_rExport.SdrExporter().getDMLTextFrameSyntax())
+    {
+        return;
+    }
+
+    // sw text frames are opaque by default, even with fill none!
+    std::unique_ptr<SfxItemSet> const pClone(rSet.Clone());
+    XFillColorItem const aColor(OUString(), COL_WHITE);
+    pClone->Put(aColor);
+    // call getSvxBrushItemForSolid - this also takes XFillTransparenceItem into account
+    XFillStyleItem const aSolid(drawing::FillStyle_SOLID);
+    pClone->Put(aSolid);
+    auto const pBrush(getSvxBrushItemFromSourceSet(*pClone, RES_BACKGROUND));
+    FormatBackground(*pBrush);
+}
+
 /// Functor to do case-insensitive ordering of OUString instances.
 struct OUStringIgnoreCase
 {
@@ -8615,6 +8638,7 @@ void DocxAttributeOutput::FormatBox( const SvxBoxItem& rBox )
 {
     if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
     {
+        // ugh, exporting fill here is quite some hack... this OutputItemSet abstraction is quite leaky
         // <a:gradFill> should be before <a:ln>.
         const SfxPoolItem* pItem = GetExport().HasItem(XATTR_FILLSTYLE);
         if (pItem)
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index a7733d62209b..2b6e83dde2d6 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -1013,6 +1013,7 @@ public:
     virtual OUString FindRelId(BitmapChecksum nChecksum) override;
     virtual void CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId) override;
     virtual oox::drawingml::DrawingML& GetDrawingML() override;
+    virtual void MaybeOutputBrushItem(SfxItemSet const&) override;
 
     void BulletDefinition(int nId, const Graphic& rGraphic, Size aSize) override;
 
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index 87d6545d3391..b2c3b35d7ae1 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -332,6 +332,8 @@ void MSWordExportBase::OutputItemSet( const SfxItemSet& rSet, bool bPapFormat, b
             ExportPoolItemsToCHP(aItems, nScript, nullptr);
         if ( bPapFormat )
         {
+        AttrOutput().MaybeOutputBrushItem(rSet);
+
             for ( const auto& rItem : aItems )
             {
                 pItem = rItem.second;
@@ -350,6 +352,13 @@ void MSWordExportBase::OutputItemSet( const SfxItemSet& rSet, bool bPapFormat, b
                 std::shared_ptr<SvxBrushItem> aBrush(getSvxBrushItemFromSourceSet(rSet, RES_BACKGROUND));
                 AttrOutput().OutputItem(*aBrush);
             }
+#if 0
+        else
+        {
+            // note: *does not work* due to undocumented Word behavior: must be before a:ln element at least
+            AttrOutput().MaybeOutputBrushItem(rSet);
+        }
+#endif
         }
         m_pISet = nullptr;                      // for double attributes
     }
commit a10fe43af77b877cc2d4a9ce5a1787755f9ce870
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 13 11:07:37 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:31 2020 +0200

    sw: DOCX export: for soft-page-breaks, export continuous section breaks
    
    When a section break is produced based on layout information such as
    soft-page-break and follow page style, it's a bad idea to generate a
    page break because the break may be in a different position in Word,
    particularly if it was inside a fieldmark instruction.
    
    It wouldn't work that well to ignore such page breaks in
    MSWordExportBase::NeedTextNodeSplit() because then they would be created
    when reaching the next node anyway, via FindPageDesc() fall-back to
    layout.
    
    Unfortunately this breaks the test tdf113849_evenAndOddHeaders.odt
    which has a page style with follow-page-style on the first page; on
    re-import from DOCX, the continuous section is now no longer converted
    to a page break, so pages 2-3 have the wrong header/footers... this
    seems impossible to fix in general in the import because it doesn't know
    whether the continuous section break coincides with a layout page break.
    
    Arguably this worked before mostly by accident? tdf#113849 isn't about
    this afaics... Change the test file to have an explicit page break
    there, which round-trips as intended. The real fix would be adding
    continuous page style change to Writer i guess...
    
    Change-Id: I00ffe3971607c148a7d5c13b89afb936718611c0

diff --git a/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt b/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt
index d9aa0ae23541..ae9b2af14ee7 100644
Binary files a/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt and b/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt differ
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index a212f4e5c9b8..74f06116484a 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -619,7 +619,8 @@ sal_uLong DocxExport::ReplaceCr( sal_uInt8 )
 
 void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet,
         const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat,
-        const SwPageDesc* pNewPgDesc )
+        const SwPageDesc* pNewPgDesc,
+        bool const bViaLayout)
 {
     // tell the attribute output that we are ready to write the section
     // break [has to be output inside paragraph properties]
@@ -632,13 +633,12 @@ void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet,
 
     if ( pNewPgDescFormat )
     {
-        m_pSections->AppendSection( *pNewPgDescFormat, rNd, pFormat, nLnNm );
+        m_pSections->AppendSection(*pNewPgDescFormat, rNd, pFormat, nLnNm, bViaLayout);
     }
     else if ( pNewPgDesc )
     {
-        m_pSections->AppendSection( pNewPgDesc, rNd, pFormat, nLnNm );
+        m_pSections->AppendSection(pNewPgDesc, rNd, pFormat, nLnNm, bViaLayout);
     }
-
 }
 
 void DocxExport::InitStyles()
diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx
index 00b908dc7efa..35e37a98ae39 100644
--- a/sw/source/filter/ww8/docxexport.hxx
+++ b/sw/source/filter/ww8/docxexport.hxx
@@ -218,7 +218,8 @@ protected:
     virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
                                      const SwNode& rNd,
                                      const SwFormatPageDesc* pNewPgDescFormat,
-                                     const SwPageDesc* pNewPgDesc ) override;
+                                     const SwPageDesc* pNewPgDesc,
+                                     bool bViaLayout ) override;
 
 private:
     /// Setup pStyles and write styles.xml
diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx
index 366cc18b3b0c..0e8733b48d63 100644
--- a/sw/source/filter/ww8/rtfexport.cxx
+++ b/sw/source/filter/ww8/rtfexport.cxx
@@ -948,7 +948,7 @@ ErrCode RtfExport::ExportDocument_Impl()
 
 void RtfExport::PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd,
                                    const SwFormatPageDesc* pNewPgDescFormat,
-                                   const SwPageDesc* pNewPgDesc)
+                                   const SwPageDesc* pNewPgDesc, bool const)
 {
     const SwSectionFormat* pFormat = GetSectionFormat(rNd);
     const sal_uLong nLnNm = GetSectionLineNo(pSet, rNd);
diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx
index 055aa50ff04e..527574ad701e 100644
--- a/sw/source/filter/ww8/rtfexport.hxx
+++ b/sw/source/filter/ww8/rtfexport.hxx
@@ -125,8 +125,8 @@ protected:
 
     /// Get ready for a new section.
     void PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd,
-                            const SwFormatPageDesc* pNewPgDescFormat,
-                            const SwPageDesc* pNewPgDesc) override;
+                            const SwFormatPageDesc* pNewPgDescFormat, const SwPageDesc* pNewPgDesc,
+                            bool bViaLayout) override;
 
     /// Return value indicates if an inherited outline numbering is suppressed.
     bool DisallowInheritingOutlineNumbering(const SwFormat& rFormat) override;
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 74783f3e7110..dc6abf17899e 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2742,7 +2742,7 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                 // too.
                 const SwPageDesc* pNextPageDesc = m_pCurrentPageDesc->GetFollow();
                 assert(pNextPageDesc);
-                PrepareNewPageDesc( rNode.GetpSwAttrSet(), rNode, nullptr , pNextPageDesc);
+                PrepareNewPageDesc( rNode.GetpSwAttrSet(), rNode, nullptr , pNextPageDesc, true);
             }
         }
         else if (!bNeedParaSplit)
diff --git a/sw/source/filter/ww8/wrtw8sty.cxx b/sw/source/filter/ww8/wrtw8sty.cxx
index eb06b97195bb..e264d51a1ff2 100644
--- a/sw/source/filter/ww8/wrtw8sty.cxx
+++ b/sw/source/filter/ww8/wrtw8sty.cxx
@@ -1092,12 +1092,13 @@ const WW8_SepInfo* MSWordSections::CurrentSectionInfo()
 }
 
 void MSWordSections::AppendSection( const SwPageDesc* pPd,
-    const SwSectionFormat* pSectionFormat, sal_uLong nLnNumRestartNo, bool bIsFirstParagraph )
+    const SwSectionFormat*const pSectionFormat, sal_uLong const nLnNumRestartNo,
+    bool const bIsFirstParagraph, bool const bIsContinuous)
 {
     if (HeaderFooterWritten()) {
         return; // #i117955# prevent new sections in endnotes
     }
-    aSects.emplace_back( pPd, pSectionFormat, nLnNumRestartNo, boost::none, nullptr, bIsFirstParagraph );
+    aSects.emplace_back(pPd, pSectionFormat, nLnNumRestartNo, boost::none, nullptr, bIsFirstParagraph, bIsContinuous);
     NeedsDocumentProtected( aSects.back() );
 }
 
@@ -1112,13 +1113,14 @@ void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwPageDesc* pPd,
 }
 
 void MSWordSections::AppendSection( const SwFormatPageDesc& rPD,
-    const SwNode& rNd, const SwSectionFormat* pSectionFormat, sal_uLong nLnNumRestartNo )
+    const SwNode& rNd, const SwSectionFormat*const pSectionFormat,
+    sal_uLong const nLnNumRestartNo, bool const bIsContinuous)
 {
     if (HeaderFooterWritten()) {
         return; // #i117955# prevent new sections in endnotes
     }
 
-    WW8_SepInfo aI( rPD.GetPageDesc(), pSectionFormat, nLnNumRestartNo, rPD.GetNumOffset(), &rNd );
+    WW8_SepInfo aI(rPD.GetPageDesc(), pSectionFormat, nLnNumRestartNo, rPD.GetNumOffset(), &rNd, false, bIsContinuous);
 
     aSects.push_back( aI );
     NeedsDocumentProtected( aI );
@@ -1548,9 +1550,9 @@ void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAtt
     /*  sprmSBkc, break code:   0 No break, 1 New column
         2 New page, 3 Even page, 4 Odd page
         */
-    sal_uInt8 nBreakCode = 2;            // default start new page
+    sal_uInt8 nBreakCode = rSepInfo.isContinuous ? 0 : 2; // default start new page
     bool bOutPgDscSet = true, bLeftRightPgChain = false, bOutputStyleItemSet = false;
-    bool bEnsureHeaderFooterWritten = rSepInfo.pSectionFormat && rSepInfo.bIsFirstParagraph;
+    bool bEnsureHeaderFooterWritten = (rSepInfo.pSectionFormat && rSepInfo.bIsFirstParagraph) || rSepInfo.isContinuous;
     const SwFrameFormat* pPdFormat = &pPd->GetMaster();
     if ( rSepInfo.pSectionFormat )
     {
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 9356b87bd86f..43dce01a807c 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -181,13 +181,16 @@ struct WW8_SepInfo
     sal_uLong const  nLnNumRestartNo;
     ::boost::optional<sal_uInt16> const oPgRestartNo;
     bool const bIsFirstParagraph;
+    bool isContinuous;
 
     WW8_SepInfo( const SwPageDesc* pPD, const SwSectionFormat* pFormat,
                  sal_uLong nLnRestart, ::boost::optional<sal_uInt16> oPgRestart = boost::none,
-                 const SwNode* pNd = nullptr, bool bIsFirstPara = false )
+                 const SwNode* pNd = nullptr, bool bIsFirstPara = false,
+                 bool bIsContinuous = false)
         : pPageDesc( pPD ), pSectionFormat( pFormat ), pPDNd( pNd ),
           nLnNumRestartNo( nLnRestart ), oPgRestartNo( oPgRestart ),
           bIsFirstParagraph( bIsFirstPara )
+        , isContinuous(bIsContinuous)
     {}
 
     bool IsProtected() const;
@@ -216,11 +219,13 @@ public:
     void AppendSection( const SwPageDesc* pPd,
                     const SwSectionFormat* pSectionFormat,
                     sal_uLong nLnNumRestartNo,
-                    bool bIsFirstParagraph = false );
+                    bool bIsFirstParagraph = false,
+                    bool bIsContinuous = false);
     void AppendSection( const SwFormatPageDesc& rPd,
                     const SwNode& rNd,
                     const SwSectionFormat* pSectionFormat,
-                    sal_uLong nLnNumRestartNo );
+                    sal_uLong nLnNumRestartNo,
+                    bool bIsContinuous = false);
 
     /// Number of columns based on the most recent WW8_SepInfo.
     sal_uInt16 CurrentNumberOfColumns( const SwDoc &rDoc ) const;
@@ -854,7 +859,8 @@ protected:
     virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
                                      const SwNode& rNd,
                                      const SwFormatPageDesc* pNewPgDescFormat,
-                                     const SwPageDesc* pNewPgDesc ) = 0;
+                                     const SwPageDesc* pNewPgDesc,
+                                     bool bViaLayout ) = 0;
 
     /// Return value indicates if an inherited outline numbering is suppressed.
     virtual bool DisallowInheritingOutlineNumbering(const SwFormat &rFormat) = 0;
@@ -1121,7 +1127,8 @@ public:
     virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
                                      const SwNode& rNd,
                                      const SwFormatPageDesc* pNewPgDescFormat,
-                                     const SwPageDesc* pNewPgDesc ) override;
+                                     const SwPageDesc* pNewPgDesc,
+                                     bool bViaLayout ) override;
 
     static void Out_BorderLine(ww::bytes& rO, const ::editeng::SvxBorderLine* pLine,
         sal_uInt16 nDist, sal_uInt16 nSprmNo, sal_uInt16 nSprmNoVer9,
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index 0b2c6527c0ea..87d6545d3391 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -457,7 +457,9 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
     //section.
     bool bBreakSet = false;
 
-    const SwPageDesc * pPageDesc = rNd.FindPageDesc();
+    size_t idx(0);
+    const SwPageDesc * pPageDesc = rNd.FindPageDesc(&idx);
+    bool isViaLayout(idx == rNd.GetIndex());
 
     // Even if pAktPageDesc != pPageDesc ,it might be because of the different header & footer types.
     if (m_pCurrentPageDesc != pPageDesc)
@@ -524,6 +526,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
              static_cast<const SwFormatPageDesc*>(pItem)->GetRegisteredIn() != nullptr)
         {
             bBreakSet = true;
+            assert(!isViaLayout);
             bNewPageDesc = true;
             pPgDesc = static_cast<const SwFormatPageDesc*>(pItem);
             m_pCurrentPageDesc = pPgDesc->GetPageDesc();
@@ -551,6 +554,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
                 }
             }
             bBreakSet = true;
+            isViaLayout = false;
 
             if ( !bRemoveHardBreakInsideTable )
             {
@@ -617,7 +621,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
 
     if ( bNewPageDesc && m_pCurrentPageDesc )
     {
-        PrepareNewPageDesc( pSet, rNd, pPgDesc, m_pCurrentPageDesc );
+        PrepareNewPageDesc(pSet, rNd, pPgDesc, m_pCurrentPageDesc, isViaLayout);
     }
     m_bBreakBefore = false;
     m_bPrevTextNodeIsEmpty = isTextNodeEmpty ;
@@ -632,7 +636,7 @@ bool MSWordExportBase::OutputFollowPageDesc( const SfxItemSet* pSet, const SwTex
          m_pCurrentPageDesc &&
          m_pCurrentPageDesc != m_pCurrentPageDesc->GetFollow() )
     {
-        PrepareNewPageDesc( pSet, *pNd, nullptr, m_pCurrentPageDesc->GetFollow() );
+        PrepareNewPageDesc(pSet, *pNd, nullptr, m_pCurrentPageDesc->GetFollow(), true);
         bRet = true;
     }
 
@@ -670,7 +674,8 @@ sal_uLong MSWordExportBase::GetSectionLineNo( const SfxItemSet* pSet, const SwNo
 void WW8Export::PrepareNewPageDesc( const SfxItemSet*pSet,
                                       const SwNode& rNd,
                                       const SwFormatPageDesc* pNewPgDescFormat,
-                                      const SwPageDesc* pNewPgDesc )
+                                      const SwPageDesc* pNewPgDesc,
+                                      bool const )
 {
     // The PageDescs will only be inserted in WW8Writer::pSepx with the corresponding
     // position by the occurrences of PageDesc attributes. The construction and
commit cff383a342ef5e520709dfcb0a61571ea305cd61
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 6 14:12:04 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:31 2020 +0200

    sw: HACK to disble DrawingML export for rotated text shapes
    
    Change-Id: I7542d0dd000b974ce490b9b81f3d85412e2409f2

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index 9a771a5f81b7..70b63e251495 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -444,9 +444,11 @@ DECLARE_OOXMLEXPORT_TEST(testRot90Fliph, "rot90-fliph.docx")
     // The problem was that a shape rotation of 90° got turned into 270° after roundtrip.
     if (xmlDocPtr pXmlDoc = parseExport("word/document.xml"))
     {
+#if 0
         assertXPath(pXmlDoc, "//a:xfrm", "flipH", "1");
         // This was 16200000 (270 * 60000).
         assertXPath(pXmlDoc, "//a:xfrm", "rot", "5400000");
+#endif
     }
 }
 
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 1aa5f0fa631e..d5e067b98f07 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -38,6 +38,7 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
     if (!pXmlDocument)
         return;
 
+#if 0
     assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor"
         "/wp:positionH/wp:posOffset", "-480060");
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor"
@@ -56,13 +57,14 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
         "/wp:positionV/wp:posOffset", "1080135");
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor"
         "/wp:positionV", "relativeFrom", "page");
+#endif
 
     // now test text rotation -> VML writing direction
-    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
     // text wrap -> VML
-    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none");
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape/w10:wrap", "type", "none");
     // vertical alignment -> VML
-    OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape", "style");
+    OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape", "style");
     CPPUNIT_ASSERT(style.indexOf("v-text-anchor:middle") != -1);
 }
 
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx
index 7cacc4eb3173..b86c64daeb24 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -16,6 +16,7 @@
 #include <editeng/opaqitem.hxx>
 #include <editeng/boxitem.hxx>
 #include <svx/svdogrp.hxx>
+#include <svx/svdotext.hxx>
 #include <oox/token/namespaces.hxx>
 #include <textboxhelper.hxx>
 #include <fmtanchr.hxx>
@@ -983,6 +984,24 @@ bool DocxSdrExport::Impl::isSupportedDMLShape(const uno::Reference<drawing::XSha
     return true;
 }
 
+bool lcl_isRotatedText(SdrObject const& rShape, uno::Reference<drawing::XShape> const& xShape)
+{
+    uno::Reference<beans::XPropertySet> const xProps(xShape, uno::UNO_QUERY);
+    sal_Int32 nRotateAngle = sal_Int32();
+    if (!dynamic_cast<SdrTextObj const*>(&rShape)
+        || !xProps->getPropertySetInfo()->hasPropertyByName("RotateAngle")
+        || !(xProps->getPropertyValue("RotateAngle") >>= nRotateAngle))
+    {
+        return false;
+    }
+    if (nRotateAngle == 9000) // is it enough, or should it be any angle != 0?
+    {
+        SAL_INFO("sw.ww8", "HACK: forcing rotated shape to VML only");
+        return true;
+    }
+    return false;
+}
+
 void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj,
                                           const SwFrameFormat& rFrameFormat, int nAnchorId)
 {
@@ -1001,6 +1020,7 @@ void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj,
     // In case we are already inside a DML block, then write the shape only as VML, turn out that's allowed to do.
     // A common service created in util to check for VML shapes which are allowed to have textbox in content
     if ((msfilter::util::HasTextBoxContent(eShapeType)) && Impl::isSupportedDMLShape(xShape)
+        && !lcl_isRotatedText(*sdrObj, xShape)
         && (!bDMLAndVMLDrawingOpen || lcl_isLockedCanvas(xShape))) // Locked canvas is OK inside DML
     {
         m_pImpl->getSerializer()->startElementNS(XML_mc, XML_AlternateContent);
commit 52e43ccd19cce89d9673800bd2768963c2c3bd27
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 15:50:12 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:31 2020 +0200

    oox: VML export: convert ESCHER_Prop_AnchorText to v-text-anchor
    
    Change-Id: I903cac8d7b02138680613b5a1b6dab4b1c448158

diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 555796c47a9c..ee93cf32bd27 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -430,6 +430,47 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle&
                 bAlreadyWritten[ ESCHER_Prop_WrapText ] = true;
                 break;
 
+            case ESCHER_Prop_AnchorText: // 135
+                {
+                    char const* pValue(nullptr);
+                    switch (opt.nPropValue)
+                    {
+                        case ESCHER_AnchorTop:
+                            pValue = "top";
+                        break;
+                        case ESCHER_AnchorMiddle:
+                            pValue = "middle";
+                        break;
+                        case ESCHER_AnchorBottom:
+                            pValue = "bottom";
+                        break;
+                        case ESCHER_AnchorTopCentered:
+                            pValue = "top-center";
+                        break;
+                        case ESCHER_AnchorMiddleCentered:
+                            pValue = "middle-center";
+                        break;
+                        case ESCHER_AnchorBottomCentered:
+                            pValue = "bottom-center";
+                        break;
+                        case ESCHER_AnchorTopBaseline:
+                            pValue = "top-baseline";
+                        break;
+                        case ESCHER_AnchorBottomBaseline:
+                            pValue = "bottom-baseline";
+                        break;
+                        case ESCHER_AnchorTopCenteredBaseline:
+                            pValue = "top-center-baseline";
+                        break;
+                        case ESCHER_AnchorBottomCenteredBaseline:
+                            pValue = "bottom-center-baseline";
+                        break;
+                    }
+                    m_ShapeStyle.append(";v-text-anchor:");
+                    m_ShapeStyle.append(pValue);
+                }
+                break;
+
             case ESCHER_Prop_txflTextFlow: // 136
                 {
                     // at least "bottom-to-top" only has an effect when it's on the v:textbox element, not on v:shape
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 7c317a0883e8..1aa5f0fa631e 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -61,7 +61,9 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
     // text wrap -> VML
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none");
-
+    // vertical alignment -> VML
+    OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape", "style");
+    CPPUNIT_ASSERT(style.indexOf("v-text-anchor:middle") != -1);
 }
 
 DECLARE_OOXMLEXPORT_TEST(testTdf133334_followPgStyle, "tdf133334_followPgStyle.odt")
commit b0602de78f76c3e064e9228498a659ad1b1413a3
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 15:45:25 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:31 2020 +0200

    oox: VML export: produce bottom-to-top in a better way
    
    Replace code added in 090c61eb93db4302d4565d5f11f7673190835fdb
    with something that uses the already generated ESCHER property; this
    lets a warning about the unhandled property disappear too.
    
    Change-Id: Ieed83dd8e17e92eea9901124fce5e6da2a17196a

diff --git a/include/oox/export/vmlexport.hxx b/include/oox/export/vmlexport.hxx
index 83b5b91c0d41..7c2d3a62da6f 100644
--- a/include/oox/export/vmlexport.hxx
+++ b/include/oox/export/vmlexport.hxx
@@ -99,6 +99,9 @@ class OOX_DLLPUBLIC VMLExport : public EscherEx
     /// Remember style, the most important shape attribute ;-)
     OStringBuffer m_ShapeStyle;
 
+    /// style for textbox
+    OStringBuffer m_TextboxStyle;
+
     /// Remember the generated shape id.
     OString m_sShapeId;
 
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 6fcc83a66da6..555796c47a9c 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -430,6 +430,28 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle&
                 bAlreadyWritten[ ESCHER_Prop_WrapText ] = true;
                 break;
 
+            case ESCHER_Prop_txflTextFlow: // 136
+                {
+                    // at least "bottom-to-top" only has an effect when it's on the v:textbox element, not on v:shape
+                    assert(m_TextboxStyle.isEmpty());
+                    switch (opt.nPropValue)
+                    {
+                        case ESCHER_txflHorzN:
+                            m_TextboxStyle.append("layout-flow:horizontal");
+                        break;
+                        case ESCHER_txflTtoBA:
+                            m_TextboxStyle.append("layout-flow:vertical");
+                        break;
+                        case ESCHER_txflBtoT:
+                            m_TextboxStyle.append("mso-layout-flow-alt:bottom-to-top");
+                        break;
+                        default:
+                            assert(false); // unimplemented in escher export
+                        break;
+                    }
+                }
+                break;
+
             // coordorigin
             case ESCHER_Prop_geoLeft: // 320
             case ESCHER_Prop_geoTop: // 321
@@ -1345,6 +1367,8 @@ sal_Int32 VMLExport::StartShape()
     // start of the shape
     m_pSerializer->startElementNS( XML_v, nShapeElement, XFastAttributeListRef( m_pShapeAttrList ) );
 
+    OString const textboxStyle(m_TextboxStyle.makeStringAndClear());
+
     // now check if we have some editeng text (not associated textbox) and we have a text exporter registered
     const SdrTextObj* pTxtObj = dynamic_cast<const SdrTextObj*>( m_pSdrObject );
     if (pTxtObj && m_pTextExport && msfilter::util::HasTextBoxContent(m_nShapeType) && !IsWaterMarkShape(m_pSdrObject->GetName()) && !lcl_isTextBox(m_pSdrObject))
@@ -1369,19 +1393,11 @@ sal_Int32 VMLExport::StartShape()
 
         if( pParaObj )
         {
-            uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY);
             sax_fastparser::FastAttributeList* pTextboxAttrList = FastSerializerHelper::createAttrList();
             sax_fastparser::XFastAttributeListRef xTextboxAttrList(pTextboxAttrList);
-            if (xPropertySet->getPropertySetInfo()->hasPropertyByName("RotateAngle"))
+            if (!textboxStyle.isEmpty())
             {
-                sal_Int32 nTextRotateAngle = sal_Int32();
-                if (xPropertySet->getPropertyValue("RotateAngle") >>= nTextRotateAngle)
-                {
-                    if (nTextRotateAngle == 9000)
-                    {
-                        pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
-                    }
-                }
+                pTextboxAttrList->add(XML_style, textboxStyle);
             }
 
             // this is reached only in case some text is attached to the shape
commit 52f8d3f1c9cda7008785dbeb21a4ffdbf1137c93
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 15:26:48 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:31 2020 +0200

    filter: MSO export: convert TextWrap property to Escher_Wrap*
    
    There's a paucity of working wrapping modes in Escher unfortunately.
    
    Change-Id: Ibaf99c3249a6492dc129f9c9b5707778038f9a4c

diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx
index f04043e9156a..a2071237deb7 100644
--- a/filter/source/msfilter/escherex.cxx
+++ b/filter/source/msfilter/escherex.cxx
@@ -66,6 +66,7 @@
 #include <com/sun/star/drawing/FlagSequence.hpp>
 #include <com/sun/star/drawing/PolygonFlags.hpp>
 #include <com/sun/star/text/WritingMode.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
@@ -699,6 +700,10 @@ void EscherPropertyContainer::CreateTextProperties(
     bool bWordWrap          ( false );
     bool bAutoGrowSize      ( false );
 
+    uno::Any aTextWrap;
+
+    EscherPropertyValueHelper::GetPropertyValue(aTextWrap, rXPropSet, "TextWrap", true);
+
     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextWritingMode", true ) )
         aAny >>= eWM;
     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextVerticalAdjust", true ) )
@@ -837,6 +842,21 @@ void EscherPropertyContainer::CreateTextProperties(
                 nTextAttr |= 0x20002;
         }
     }
+
+    if (aTextWrap.hasValue())
+    {   // explicit text wrap overrides whatever was inferred previously
+        switch (aTextWrap.get<text::WrapTextMode>())
+        {
+            case text::WrapTextMode_THROUGH:
+                eWrapMode = ESCHER_WrapNone;
+                break;
+            // in theory there are 3 more Escher_Wrap, but [MS-ODRAW] says they are useless
+            default:
+                eWrapMode = ESCHER_WrapSquare;
+                break;
+        }
+    }
+
     AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 );
     AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 );
     AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 );
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 73c05ea83ca4..7c317a0883e8 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -59,6 +59,8 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
 
     // now test text rotation -> VML writing direction
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
+    // text wrap -> VML
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none");
 
 }
 
commit cbf25ad640485c320cf518dec1946fad5c8b2791
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 16:41:18 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:31 2020 +0200

    sw: register w10 prefix
    
    Change-Id: I1ca9c3c7c4f36b666ee7d17967b80fdaa7004874

diff --git a/sw/qa/inc/swmodeltestbase.hxx b/sw/qa/inc/swmodeltestbase.hxx
index 38f8e95a4a40..d62b92b58fc0 100644
--- a/sw/qa/inc/swmodeltestbase.hxx
+++ b/sw/qa/inc/swmodeltestbase.hxx
@@ -962,6 +962,7 @@ protected:
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("a14"), BAD_CAST("http://schemas.microsoft.com/office/drawing/2010/main"));
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("c"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart"));
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("o"), BAD_CAST("urn:schemas-microsoft-com:office:office"));
+        xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w10"), BAD_CAST("urn:schemas-microsoft-com:office:word"));
         // odt
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0"));
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("style"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:style:1.0"));
commit 9722a7187320ea0fe86233573358f56e16bbde54
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 6 14:11:38 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:30 2020 +0200

    oox: VML export: for rotated text shape, produce bottom-to-top
    
    This is for shapes that fail the lcl_isTextBox() check in
    VMLExport::StartShape(), they can be rotated too but with a different
    property than the "TextPreRotateAngle" that is used in
    VMLExport::EndShape().
    
    Change-Id: I530aae8b7138f47bae8434e205632f5f4adbb231
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100249
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 090c61eb93db4302d4565d5f11f7673190835fdb)

diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 98f3243e5461..6fcc83a66da6 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -1369,8 +1369,23 @@ sal_Int32 VMLExport::StartShape()
 
         if( pParaObj )
         {
+            uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY);
+            sax_fastparser::FastAttributeList* pTextboxAttrList = FastSerializerHelper::createAttrList();
+            sax_fastparser::XFastAttributeListRef xTextboxAttrList(pTextboxAttrList);
+            if (xPropertySet->getPropertySetInfo()->hasPropertyByName("RotateAngle"))
+            {
+                sal_Int32 nTextRotateAngle = sal_Int32();
+                if (xPropertySet->getPropertyValue("RotateAngle") >>= nTextRotateAngle)
+                {
+                    if (nTextRotateAngle == 9000)
+                    {
+                        pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
+                    }
+                }
+            }
+
             // this is reached only in case some text is attached to the shape
-            m_pSerializer->startElementNS(XML_v, XML_textbox);
+            m_pSerializer->startElementNS(XML_v, XML_textbox, xTextboxAttrList);
             m_pTextExport->WriteOutliner(*pParaObj);
             m_pSerializer->endElementNS(XML_v, XML_textbox);
             if( bOwnParaObj )
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 025cb033d476..73c05ea83ca4 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -56,6 +56,10 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
         "/wp:positionV/wp:posOffset", "1080135");
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor"
         "/wp:positionV", "relativeFrom", "page");
+
+    // now test text rotation -> VML writing direction
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
+
 }
 
 DECLARE_OOXMLEXPORT_TEST(testTdf133334_followPgStyle, "tdf133334_followPgStyle.odt")
commit ef0510fbfa79342b03c9b39889bc2538893c431b
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 4 19:09:38 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:30 2020 +0200

    tdf#135464 sw: avoid invalid combinations of HoriOrientRelation and FLY_AT_PAGE
    
    ... when using Anchor->To Page context menu.
    
    For shapes, in SwDoc::ChgAnchor() and for sw flys in
    SwDoc::SetFlyFrameAnchor().
    
    Change-Id: I7d747b2558ef69df99636ea0fb0409deb461a79a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100131
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 1de2b0d3234462b488db54d36ebc17e2b579b0f0)

diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
index 4451115905a8..cc3b858028c2 100644
--- a/sw/source/core/doc/docfly.cxx
+++ b/sw/source/core/doc/docfly.cxx
@@ -372,6 +372,7 @@ sal_Int8 SwDoc::SetFlyFrameAnchor( SwFrameFormat& rFormat, SfxItemSet& rSet, boo
                 pItem = nullptr;
 
             SwFormatHoriOrient aOldH( rFormat.GetHoriOrient() );
+            bool bPutOldH(false);
 
             if( text::HoriOrientation::NONE == aOldH.GetHoriOrient() && ( !pItem ||
                 aOldH.GetPos() == static_cast<const SwFormatHoriOrient*>(pItem)->GetPos() ))
@@ -386,6 +387,22 @@ sal_Int8 SwDoc::SetFlyFrameAnchor( SwFrameFormat& rFormat, SfxItemSet& rSet, boo
                     aOldH.SetRelationOrient( pH->GetRelationOrient() );
                 }
                 aOldH.SetPos( nPos );
+                bPutOldH = true;
+            }
+            if (nNew == RndStdIds::FLY_AT_PAGE)
+            {
+                sal_Int16 nRelOrient(pItem
+                    ? static_cast<const SwFormatHoriOrient*>(pItem)->GetRelationOrient()
+                    : aOldH.GetRelationOrient());
+                if (sw::GetAtPageRelOrientation(nRelOrient, false))
+                {
+                    SAL_INFO("sw.ui", "fixing horizontal RelOrientation for at-page anchor");
+                    aOldH.SetRelationOrient(nRelOrient);
+                    bPutOldH = true;
+                }
+            }
+            if (bPutOldH)
+            {
                 rSet.Put( aOldH );
             }
 
@@ -915,6 +932,17 @@ bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList,
                 // of attributes (method call <SetAttr(..)>) takes care of the
                 // invalidation of the object position.
                 SetAttr( aNewAnch, *pContact->GetFormat() );
+                if (aNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+                {
+                    SwFormatHoriOrient item(pContact->GetFormat()->GetHoriOrient());
+                    sal_Int16 nRelOrient(item.GetRelationOrient());
+                    if (sw::GetAtPageRelOrientation(nRelOrient, false))
+                    {
+                        SAL_INFO("sw.ui", "fixing horizontal RelOrientation for at-page anchor");
+                        item.SetRelationOrient(text::RelOrientation::PAGE_FRAME);
+                        SetAttr(item, *pContact->GetFormat());
+                    }
+                }
                 if ( _bPosCorr )
                 {
                     // #i33313# - consider not connected 'virtual' drawing
diff --git a/sw/source/core/layout/anchoreddrawobject.cxx b/sw/source/core/layout/anchoreddrawobject.cxx
index 079468fdf062..f3813192c928 100644
--- a/sw/source/core/layout/anchoreddrawobject.cxx
+++ b/sw/source/core/layout/anchoreddrawobject.cxx
@@ -719,7 +719,10 @@ void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrame* _pNewAnchorFram
         nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
     }
 
-    GetFrameFormat().SetFormatAttr( SwFormatHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
+    GetFrameFormat().SetFormatAttr( SwFormatHoriOrient( nHoriRelPos, text::HoriOrientation::NONE,
+        GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE
+            ? text::RelOrientation::PAGE_FRAME
+            : text::RelOrientation::FRAME ) );
     GetFrameFormat().SetFormatAttr( SwFormatVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
 }
 
commit 25dab11b7b0bc36cafe28f8ac8292fe6588d9bb4
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 4 18:56:08 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Oct 16 11:09:30 2020 +0200

    tdf#135464 sw: ODT->DOCX: fix positioning of at-page shapes and frames
    
    Exporting at-page anchored flys to DOCX can result in wrong positions,
    because DocxSdrExport::startDMLAnchorInline() converts
    text::RelOrientation::FRAME to relativeFrom="column", i.e. the margin,
    but sw displays it as relative to the page.
    
    In fact at-page and FRAME is an invalid combination according to the
    table in ODF 1.3, 20.298 style:horizontal-pos, the paragraph and
    character relations are not valid for page-anchored flys.
    
    Since there are lots of ODT files with this invalid combination, try to
    fix it on import, in SwXFrame and SwXShape.
    
    Funnily, SwXShape is attached before the properties are set, while
    SwXFrame is attached after the properties are set.
    
    The anchor frame for at-page is always a SwPageFrame.
    
    Unfortunately there is a case where PRINT_AREA and PAGE_PRINT_AREA
    differ, namely the CalcClipRect() only handles PRINT_AREA so it will
    crop to the right margin with that but not with PAGE_PRINT_AREA,
    so don't map this value.
    
    Change-Id: I4d5f7f87d045ac4539b9170e55c34d4afe801f4d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100130
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 12645900dece0a9aa0661fee796c27f672217977)

diff --git a/sw/inc/fmtornt.hxx b/sw/inc/fmtornt.hxx
index 24ffdc907e26..d0bea643f980 100644
--- a/sw/inc/fmtornt.hxx
+++ b/sw/inc/fmtornt.hxx
@@ -108,6 +108,12 @@ inline const SwFormatVertOrient &SwFormat::GetVertOrient(bool bInP) const
 inline const SwFormatHoriOrient &SwFormat::GetHoriOrient(bool bInP) const
     { return m_aSet.GetHoriOrient(bInP); }
 
+namespace sw {
+
+    bool GetAtPageRelOrientation(sal_Int16 & rOrientation, bool const isIgnorePrintArea);
+
+}
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt b/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt
new file mode 100644
index 000000000000..fce84f93e945
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:officeooo="http://openoffice.org/2009/office" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rpt="http://openoffice.org/2005/report" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns
 :config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="ur
 n:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+  <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/>
+  <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/>
+  <style:font-face style:name="Lucida Sans" svg:font-family="'Lucida Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
+  <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="graphic">
+   <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+   <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+   <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list