[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.2' - 7 commits - oox/source sw/qa sw/source writerfilter/source xmloff/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Thu Jul 4 13:52:22 UTC 2019


 oox/source/shape/WpsContext.cxx                          |   72 +++++----------
 sw/qa/extras/layout/layout.cxx                           |   31 ++++++
 sw/qa/extras/odfexport/data/btlr-frame.odt               |binary
 sw/qa/extras/odfexport/odfexport.cxx                     |   12 ++
 sw/qa/extras/ooxmlexport/data/tbrl-textbox.docx          |binary
 sw/qa/extras/ooxmlexport/ooxmlexport10.cxx               |   12 ++
 sw/qa/extras/ooxmlexport/ooxmlexport13.cxx               |   10 ++
 sw/qa/extras/rtfexport/data/btlr-cell.rtf                |    9 +
 sw/qa/extras/rtfexport/rtfexport3.cxx                    |   18 +++
 sw/qa/extras/uiwriter/data2/tdf124261.docx               |binary
 sw/qa/extras/uiwriter/uiwriter2.cxx                      |   37 +++++++
 sw/qa/extras/ww8export/data/btlr-cell.doc                |binary
 sw/qa/extras/ww8export/ww8export3.cxx                    |   20 ++++
 sw/source/core/doc/textboxhelper.cxx                     |   62 ++++++++----
 sw/source/core/text/frmpaint.cxx                         |    2 
 sw/source/core/text/txtfrm.cxx                           |   20 +++-
 sw/source/filter/ww8/rtfattributeoutput.cxx              |    7 +
 sw/source/filter/ww8/wrtww8.cxx                          |   18 +++
 sw/source/filter/ww8/ww8par2.cxx                         |   23 ----
 sw/source/filter/ww8/ww8par2.hxx                         |    2 
 writerfilter/source/dmapper/DomainMapperTableHandler.cxx |   17 ---
 writerfilter/source/dmapper/DomainMapperTableManager.cxx |    7 -
 writerfilter/source/dmapper/PropertyIds.cxx              |    1 
 writerfilter/source/dmapper/PropertyIds.hxx              |    1 
 xmloff/source/style/prhdlfac.cxx                         |    1 
 xmloff/source/style/xmlexppr.cxx                         |   15 ++-
 xmloff/source/text/txtprmap.cxx                          |    1 
 27 files changed, 274 insertions(+), 124 deletions(-)

New commits:
commit ebe59762e87f3a9334af3db4bea5d99c850c79c8
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon Apr 29 20:01:21 2019 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jul 4 15:51:45 2019 +0200

    sw btlr writing mode: implement ODF filter for textframes
    
    Layout is still not yet correct right after the import, though.
    
    Change-Id: Icdba2e8d608f35b6b5b43b88ffb223f779af1b89
    Reviewed-on: https://gerrit.libreoffice.org/71552
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    (cherry picked from commit cd2a7acd789297e613424a59b2fe24cedd9a72b6)

diff --git a/sw/qa/extras/odfexport/data/btlr-frame.odt b/sw/qa/extras/odfexport/data/btlr-frame.odt
new file mode 100644
index 000000000000..31cb03849c53
Binary files /dev/null and b/sw/qa/extras/odfexport/data/btlr-frame.odt differ
diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx
index a47028c91b73..d132ea24544e 100644
--- a/sw/qa/extras/odfexport/odfexport.cxx
+++ b/sw/qa/extras/odfexport/odfexport.cxx
@@ -1411,6 +1411,18 @@ DECLARE_ODFEXPORT_TEST(testBtlrCell, "btlr-cell.odt")
     CPPUNIT_ASSERT_EQUAL(text::WritingMode2::TB_RL, getProperty<sal_Int16>(xC1, "WritingMode"));
 }
 
+DECLARE_ODFEXPORT_TEST(testBtlrFrame, "btlr-frame.odt")
+{
+    // Without the accompanying fix in place, this test would have failed, as
+    // the btlr text direction in the text frame was lost on ODF import and
+    // export.
+    uno::Reference<beans::XPropertySet> xTextFrame(getShape(1), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xTextFrame.is());
+
+    auto nActual = getProperty<sal_Int16>(xTextFrame, "WritingMode");
+    CPPUNIT_ASSERT_EQUAL(text::WritingMode2::BT_LR, nActual);
+}
+
 DECLARE_ODFEXPORT_TEST(testFdo86963, "fdo86963.odt")
 {
     // Export of this document failed with beans::UnknownPropertyException.
diff --git a/xmloff/source/style/prhdlfac.cxx b/xmloff/source/style/prhdlfac.cxx
index 539967955d77..fdafb8dc38de 100644
--- a/xmloff/source/style/prhdlfac.cxx
+++ b/xmloff/source/style/prhdlfac.cxx
@@ -90,6 +90,7 @@ static SvXMLEnumMapEntry<sal_uInt16> const aXML_WritingDirection_Enum[] =
     { XML_RL_TB,    text::WritingMode2::RL_TB },
     { XML_TB_RL,    text::WritingMode2::TB_RL },
     { XML_TB_LR,    text::WritingMode2::TB_LR },
+    { XML_BT_LR,    text::WritingMode2::BT_LR },
 
     // alternative names of the above, as accepted by XSL
     { XML_LR,       text::WritingMode2::LR_TB },
diff --git a/xmloff/source/style/xmlexppr.cxx b/xmloff/source/style/xmlexppr.cxx
index fc05262c9845..f573516b1d9a 100644
--- a/xmloff/source/style/xmlexppr.cxx
+++ b/xmloff/source/style/xmlexppr.cxx
@@ -974,7 +974,7 @@ void SvXMLExportPropertyMapper::_exportXML(
     else if ((mpImpl->mxPropMapper->GetEntryFlags(rProperty.mnIndex) & MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0)
     {
         OUString aValue;
-        const OUString sName = rNamespaceMap.GetQNameByKey(
+        OUString sName = rNamespaceMap.GetQNameByKey(
             mpImpl->mxPropMapper->GetEntryNameSpace(rProperty.mnIndex),
             mpImpl->mxPropMapper->GetEntryXMLName(rProperty.mnIndex));
 
@@ -989,6 +989,19 @@ void SvXMLExportPropertyMapper::_exportXML(
         {
             if( bRemove )
                 rAttrList.RemoveAttribute( sName );
+
+            if (IsXMLToken(mpImpl->mxPropMapper->GetEntryXMLName(rProperty.mnIndex), XML_WRITING_MODE))
+            {
+                // We don't seem to have a generic mechanism to write an attribute in the extension
+                // namespace in case of certain attribute values only, so do this manually.
+                if (IsXMLToken(aValue, XML_BT_LR))
+                {
+                    sName = rNamespaceMap.GetQNameByKey(
+                            XML_NAMESPACE_LO_EXT,
+                            mpImpl->mxPropMapper->GetEntryXMLName(rProperty.mnIndex));
+                }
+            }
+
             rAttrList.AddAttribute( sName, aValue );
         }
     }
diff --git a/xmloff/source/text/txtprmap.cxx b/xmloff/source/text/txtprmap.cxx
index bcb54cf63086..7908dd5bd90c 100644
--- a/xmloff/source/text/txtprmap.cxx
+++ b/xmloff/source/text/txtprmap.cxx
@@ -849,6 +849,7 @@ XMLPropertyMapEntry const aXMLFramePropMap[] =
     // RES_GRFATR_DRAWMODE
     MG_E( "GraphicColorMode", DRAW, COLOR_MODE,         XML_TYPE_COLOR_MODE, 0 ),
     MG_E( "WritingMode",      STYLE, WRITING_MODE,       XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT, 0 ),
+    MAP_EXT_I("WritingMode", XML_NAMESPACE_LO_EXT, XML_WRITING_MODE, XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT|XML_TYPE_PROP_GRAPHIC, 0),
     // RES_FOLLOW_TEXT_FLOW - DVO #i18732#
     MG_E( "IsFollowingTextFlow", DRAW, FLOW_WITH_TEXT,      XML_TYPE_BOOL|MID_FLAG_SPECIAL_ITEM_EXPORT, CTF_OLD_FLOW_WITH_TEXT ),
     MG_E( "IsFollowingTextFlow", STYLE, FLOW_WITH_TEXT,     XML_TYPE_BOOL, 0 ),
commit e8a37aa36fe0910ca319862b01fa31facc3c555b
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Apr 25 21:05:43 2019 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jul 4 15:51:45 2019 +0200

    sw btlr writing mode: implement DOCX shape import for tbrl
    
    Now that the btlr writing mode works reasonably well in table cells, the
    next context is shape text. But turns out that DOCX shape text lacked
    support in the easier tbrl case, so add that first.
    
    Also remove the char-level text rotation code in oox, that is
    effectively dead code since we import drawingML shapes as shape +
    Writer TextBox.
    
    (cherry picked from commit ff17478e069cc82681df62514876c06365dd5cd6)
    
    Conflicts:
            oox/source/shape/WpsContext.cxx
            sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
    
    Change-Id: I30c7793221cc3aceedfcfd9e4e1725634ebb3309

diff --git a/oox/source/shape/WpsContext.cxx b/oox/source/shape/WpsContext.cxx
index 2b2ad8b2b1b7..52c82541c6a9 100644
--- a/oox/source/shape/WpsContext.cxx
+++ b/oox/source/shape/WpsContext.cxx
@@ -64,53 +64,35 @@ oox::core::ContextHandlerRef WpsContext::onCreateContext(sal_Int32 nElementToken
         {
             uno::Reference<lang::XServiceInfo> xServiceInfo(mxShape, uno::UNO_QUERY);
             uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY);
-            OptValue<OUString> oVert = rAttribs.getString(XML_vert);
-            if (oVert.has() && oVert.get() == "vert270")
+            sal_Int32 nVert = rAttribs.getToken(XML_vert, XML_horz);
+            if (nVert != XML_horz)
             {
-                if (xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
-                {
-                    // No support for this in core, work around by char rotation, as we do so for table cells already.
-                    uno::Reference<text::XText> xText(mxShape, uno::UNO_QUERY);
-                    uno::Reference<text::XTextCursor> xTextCursor = xText->createTextCursor();
-                    xTextCursor->gotoStart(false);
-                    xTextCursor->gotoEnd(true);
-                    uno::Reference<beans::XPropertyState> xPropertyState(xTextCursor, uno::UNO_QUERY);
-                    beans::PropertyState aState = xPropertyState->getPropertyState("CharRotation");
-                    if (aState == beans::PropertyState_DEFAULT_VALUE)
-                    {
-                        uno::Reference<beans::XPropertySet> xTextCursorPropertySet(xTextCursor, uno::UNO_QUERY);
-                        xTextCursorPropertySet->setPropertyValue("CharRotation", uno::makeAny(sal_Int16(900)));
-                    }
-                }
-                else
-                {
-                    // Get the existing rotation of the shape.
-                    drawing::HomogenMatrix3 aMatrix;
-                    xPropertySet->getPropertyValue("Transformation") >>= aMatrix;
-                    basegfx::B2DHomMatrix aTransformation;
-                    aTransformation.set(0, 0, aMatrix.Line1.Column1);
-                    aTransformation.set(0, 1, aMatrix.Line1.Column2);
-                    aTransformation.set(0, 2, aMatrix.Line1.Column3);
-                    aTransformation.set(1, 0, aMatrix.Line1.Column1);
-                    aTransformation.set(1, 1, aMatrix.Line2.Column2);
-                    aTransformation.set(1, 2, aMatrix.Line3.Column3);
-                    aTransformation.set(2, 0, aMatrix.Line1.Column1);
-                    aTransformation.set(2, 1, aMatrix.Line2.Column2);
-                    aTransformation.set(2, 2, aMatrix.Line3.Column3);
-                    basegfx::B2DTuple aScale;
-                    basegfx::B2DTuple aTranslate;
-                    double fRotate = 0;
-                    double fShearX = 0;
-                    aTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
+                // Get the existing rotation of the shape.
+                drawing::HomogenMatrix3 aMatrix;
+                xPropertySet->getPropertyValue("Transformation") >>= aMatrix;
+                basegfx::B2DHomMatrix aTransformation;
+                aTransformation.set(0, 0, aMatrix.Line1.Column1);
+                aTransformation.set(0, 1, aMatrix.Line1.Column2);
+                aTransformation.set(0, 2, aMatrix.Line1.Column3);
+                aTransformation.set(1, 0, aMatrix.Line1.Column1);
+                aTransformation.set(1, 1, aMatrix.Line2.Column2);
+                aTransformation.set(1, 2, aMatrix.Line3.Column3);
+                aTransformation.set(2, 0, aMatrix.Line1.Column1);
+                aTransformation.set(2, 1, aMatrix.Line2.Column2);
+                aTransformation.set(2, 2, aMatrix.Line3.Column3);
+                basegfx::B2DTuple aScale;
+                basegfx::B2DTuple aTranslate;
+                double fRotate = 0;
+                double fShearX = 0;
+                aTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
 
-                    // If the text is not rotated the way the shape wants it already, set the angle.
-                    const sal_Int32 nRotation = -270;
-                    if (static_cast<long>(basegfx::rad2deg(fRotate)) != NormAngle36000(static_cast<long>(nRotation) * 100) / 100)
-                    {
-                        comphelper::SequenceAsHashMap aCustomShapeGeometry(xPropertySet->getPropertyValue("CustomShapeGeometry"));
-                        aCustomShapeGeometry["TextPreRotateAngle"] <<= nRotation;
-                        xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(aCustomShapeGeometry.getAsConstPropertyValueList()));
-                    }
+                // If the text is not rotated the way the shape wants it already, set the angle.
+                const sal_Int32 nRotation = nVert == XML_vert270 ? -270 : -90;
+                if (static_cast<long>(basegfx::rad2deg(fRotate)) != NormAngle36000(static_cast<long>(nRotation) * 100) / 100)
+                {
+                    comphelper::SequenceAsHashMap aCustomShapeGeometry(xPropertySet->getPropertyValue("CustomShapeGeometry"));
+                    aCustomShapeGeometry["TextPreRotateAngle"] <<= nRotation;
+                    xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(aCustomShapeGeometry.getAsConstPropertyValueList()));
                 }
             }
 
diff --git a/sw/qa/extras/ooxmlexport/data/tbrl-textbox.docx b/sw/qa/extras/ooxmlexport/data/tbrl-textbox.docx
new file mode 100644
index 000000000000..bdfcc5fff19a
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tbrl-textbox.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
index 204738056b9d..3e3af3560797 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -61,6 +61,16 @@ DECLARE_OOXMLEXPORT_TEST(testTdf121867, "tdf121867.odt")
     CPPUNIT_ASSERT_EQUAL(SvxZoomType::PAGEWIDTH, pEditShell->GetViewOptions()->GetZoomType());
 }
 
+DECLARE_OOXMLEXPORT_TEST(testTbrlTextbox, "tbrl-textbox.docx")
+{
+    uno::Reference<beans::XPropertySet> xPropertySet(getShape(1), uno::UNO_QUERY);
+    comphelper::SequenceAsHashMap aGeometry(xPropertySet->getPropertyValue("CustomShapeGeometry"));
+    // Without the accompanying fix in place, this test would have failed with 'Expected: -90;
+    // Actual: 0', i.e. tbRl writing direction was imported as lrTb.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-90),
+                         aGeometry["TextPreRotateAngle"].get<sal_Int32>());
+}
+
 DECLARE_OOXMLEXPORT_TEST(testFrameSizeExport, "floating-tables-anchor.docx")
 {
     // Make sure the table width is 4000
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 686485ff33e5..70c0c887e6a3 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -43,6 +43,7 @@
 #include <com/sun/star/text/WrapTextMode.hpp>
 #include <com/sun/star/text/XTextDocument.hpp>
 #include <com/sun/star/table/BorderLine2.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
 
 using namespace com::sun::star;
 
@@ -342,29 +343,49 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, const OUString& rPrope
                 uno::makeAny(static_cast<sal_Int32>(convertTwipToMm100(aRectangle.Top()))));
         }
 
-        if (SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
+        SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT);
+        if (!pFormat)
+            return;
+
+        comphelper::SequenceAsHashMap aCustomShapeGeometry(rValue);
+        auto it = aCustomShapeGeometry.find("TextPreRotateAngle");
+        if (it != aCustomShapeGeometry.end())
         {
-            comphelper::SequenceAsHashMap aCustomShapeGeometry(rValue);
-            // That would be the btLr text direction which we don't support at a frame level, so do it at a character level.
-            if (aCustomShapeGeometry.find("TextPreRotateAngle") != aCustomShapeGeometry.end()
-                && aCustomShapeGeometry["TextPreRotateAngle"].get<sal_Int32>() == -270)
+            auto nTextPreRotateAngle = it->second.get<sal_Int32>();
+            if (nTextPreRotateAngle == -270)
             {
-                if (const SwNodeIndex* pNodeIndex = pFormat->GetContent().GetContentIdx())
+                // That would be the btLr text direction which we don't support at a frame level, so
+                // do it at a character level.
+                const SwNodeIndex* pNodeIndex = pFormat->GetContent().GetContentIdx();
+                if (!pNodeIndex)
+                    return;
+
+                SwPaM aPaM(*pFormat->GetDoc()->GetNodes()[pNodeIndex->GetIndex() + 1], 0);
+                aPaM.SetMark();
+                if (SwTextNode* pMark
+                    = pFormat->GetDoc()
+                          ->GetNodes()[pNodeIndex->GetNode().EndOfSectionIndex() - 1]
+                          ->GetTextNode())
                 {
-                    SwPaM aPaM(*pFormat->GetDoc()->GetNodes()[pNodeIndex->GetIndex() + 1], 0);
-                    aPaM.SetMark();
-                    if (SwTextNode* pMark
-                        = pFormat->GetDoc()
-                              ->GetNodes()[pNodeIndex->GetNode().EndOfSectionIndex() - 1]
-                              ->GetTextNode())
-                    {
-                        aPaM.GetMark()->nNode = *pMark;
-                        aPaM.GetMark()->nContent.Assign(pMark, pMark->GetText().getLength());
-                        SvxCharRotateItem aItem(900, false, RES_CHRATR_ROTATE);
-                        pFormat->GetDoc()->getIDocumentContentOperations().InsertPoolItem(aPaM,
-                                                                                          aItem);
-                    }
+                    aPaM.GetMark()->nNode = *pMark;
+                    aPaM.GetMark()->nContent.Assign(pMark, pMark->GetText().getLength());
+                    SvxCharRotateItem aItem(900, false, RES_CHRATR_ROTATE);
+                    pFormat->GetDoc()->getIDocumentContentOperations().InsertPoolItem(aPaM, aItem);
                 }
+                return;
+            }
+
+            sal_Int16 nDirection = 0;
+            switch (nTextPreRotateAngle)
+            {
+                case -90:
+                    nDirection = text::WritingMode2::TB_RL;
+                    break;
+            }
+
+            if (nDirection)
+            {
+                syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(nDirection));
             }
         }
     }
@@ -541,6 +562,9 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u
             case RES_OPAQUE:
                 aPropertyName = UNO_NAME_OPAQUE;
                 break;
+            case RES_FRAMEDIR:
+                aPropertyName = UNO_NAME_WRITING_MODE;
+                break;
         }
 
         if (!aPropertyName.isEmpty())
commit f3f321fcb0c0ae6922f3c0b5a904e043adb3ef23
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon Apr 15 21:01:11 2019 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jul 4 15:51:45 2019 +0200

    tdf#124521 sw btlr writing mode render: fix paint rectangle on scroll
    
    By implementing btlr support in
    SwTextFrame::SwitchVerticalToHorizontal(SwRect), so not only
    invalidation but paint rectangle is also correct, which means actual
    text painting happens.
    
    Change-Id: I4215799ff63c93b300e4e8f97c6824f75d7c5401
    Reviewed-on: https://gerrit.libreoffice.org/70797
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    (cherry picked from commit 8072a926da2a02dfaf3fa848a2976634641a594f)

diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index 39984fb26031..7090f76d5360 100644
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -22,6 +22,7 @@
 #include <wrtsh.hxx>
 #include <edtwin.hxx>
 #include <view.hxx>
+#include <txtfrm.hxx>
 
 static char const DATA_DIRECTORY[] = "/sw/qa/extras/layout/data/";
 
@@ -2873,6 +2874,36 @@ void SwLayoutWriter::testBtlrCell()
         ss << "selection rectangle " << rRect << " is not inside cell rectangle " << aCellRect;
         CPPUNIT_ASSERT_MESSAGE(ss.str(), aCellRect.IsInside(rRect));
     }
+
+    // Make sure that the correct rectangle gets repainted on scroll.
+    SwFrame* pPageFrame = pLayout->GetLower();
+    CPPUNIT_ASSERT(pPageFrame->IsPageFrame());
+
+    SwFrame* pBodyFrame = pPageFrame->GetLower();
+    CPPUNIT_ASSERT(pBodyFrame->IsBodyFrame());
+
+    SwFrame* pTabFrame = pBodyFrame->GetLower();
+    CPPUNIT_ASSERT(pTabFrame->IsTabFrame());
+
+    SwFrame* pRowFrame = pTabFrame->GetLower();
+    CPPUNIT_ASSERT(pRowFrame->IsRowFrame());
+
+    SwFrame* pCellFrame = pRowFrame->GetLower();
+    CPPUNIT_ASSERT(pCellFrame->IsCellFrame());
+
+    SwFrame* pFrame = pCellFrame->GetLower();
+    CPPUNIT_ASSERT(pFrame->IsTextFrame());
+
+    SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pFrame);
+    pTextFrame->SwapWidthAndHeight();
+    // Mimic what normally SwTextFrame::PaintSwFrame() does:
+    SwRect aRect(4207, 2273, 269, 572);
+    pTextFrame->SwitchVerticalToHorizontal(aRect);
+    // Without the accompanying fix in place, this test would have failed with:
+    // Expected: 572x269@(1691,4217)
+    // Actual  : 572x269@(2263,4217)
+    // i.e. the paint rectangle position was incorrect, text was not painted on scrolling up.
+    CPPUNIT_ASSERT_EQUAL(SwRect(1691, 4217, 572, 269), aRect);
 #endif
 }
 
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index aa4c92cae7cc..10acbec02f5a 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -597,7 +597,18 @@ void SwTextFrame::SwitchVerticalToHorizontal( SwRect& rRect ) const
             nOfstX = getFrameArea().Left() + getFrameArea().Width() - ( rRect.Left() + rRect.Width() );
     }
 
-    const long nOfstY = rRect.Top() - getFrameArea().Top();
+    long nOfstY;
+    if (IsVertLRBT())
+    {
+        // Note that mbIsSwapped only affects the frame area, not rRect, so rRect.Height() is used
+        // here unconditionally.
+        if (mbIsSwapped)
+            nOfstY = getFrameArea().Top() + getFrameArea().Width() - (rRect.Top() + rRect.Height());
+        else
+            nOfstY = getFrameArea().Top() + getFrameArea().Height() - (rRect.Top() + rRect.Height());
+    }
+    else
+        nOfstY = rRect.Top() - getFrameArea().Top();
     const long nWidth = rRect.Height();
     const long nHeight = rRect.Width();
 
commit a76d936e8c50197fa7542ac579034c846f422682
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Apr 11 21:37:16 2019 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jul 4 15:51:44 2019 +0200

    tdf#124344 sw btlr writing mode, DOCX import: fix vertical alignment
    
    The hack added in commit 3325e0f206ce864730468c3556ce06760042c157
    (bnc#865381 DOCX import: handle w:jc=center inside w:textDirection=btLr,
    2014-07-02) is no longer needed, actually just reverting it fixes the
    problem, as then layout does the right thing.
    
    No need to center paragraph adjustment to any kind of vertical
    orientation, now that we have proper layout support.
    
    Change-Id: I6aa74f5289a014c148fbd7c7ab03ec885d931daf
    Reviewed-on: https://gerrit.libreoffice.org/70610
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    (cherry picked from commit 0013f21ecd918e0541f165c3526a58f42dd75481)

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
index 0a947b055abd..0f26299e1d6b 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
@@ -693,11 +693,19 @@ DECLARE_OOXMLEXPORT_TEST(testFootnote, "footnote.docx")
 
 DECLARE_OOXMLEXPORT_TEST(testTableBtlrCenter, "table-btlr-center.docx")
 {
+    // Note that this is btLr text, so layout and doc model horizontal/vertical is the opposite of
+    // each other.
     uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
     uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
     uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
-    // Cell vertical alignment was NONE, should be CENTER.
-    CPPUNIT_ASSERT_EQUAL(text::VertOrientation::CENTER, getProperty<sal_Int16>(xTable->getCellByName("A2"), "VertOrient"));
+    uno::Reference<table::XCell> xCell = xTable->getCellByName("A2");
+    // Cell vertical alignment was CENTER, should be NONE.
+    CPPUNIT_ASSERT_EQUAL(text::VertOrientation::NONE, getProperty<sal_Int16>(xCell, "VertOrient"));
+
+    // Cell horizontal alignment should be CENTER.
+    uno::Reference<text::XText> xCellText(xCell, uno::UNO_QUERY);
+    auto nActual = getProperty<sal_Int32>(getParagraphOfText(1, xCellText), "ParaAdjust");
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(style::ParagraphAdjust_CENTER), nActual);
 }
 
 DECLARE_OOXMLEXPORT_TEST(testFdo80555, "fdo80555.docx")
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index 01c7f59fc314..cf36a7abd1c7 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -29,9 +29,7 @@
 #include <com/sun/star/text/HoriOrientation.hpp>
 #include <com/sun/star/text/RelOrientation.hpp>
 #include <com/sun/star/text/SizeType.hpp>
-#include <com/sun/star/text/VertOrientation.hpp>
 #include <com/sun/star/text/XTextRangeCompare.hpp>
-#include <com/sun/star/style/ParagraphAdjust.hpp>
 #include "TablePositionHandler.hxx"
 #include "ConversionHelper.hxx"
 #include "util.hxx"
@@ -848,21 +846,6 @@ CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(Tabl
                     }
                     (*aCellIterator)->Erase(PROP_HORIZONTAL_MERGE);
                 }
-
-                // Cell direction is not an UNO Property, either.
-                const boost::optional<PropertyMap::Property> aCellDirectionVal = (*aCellIterator)->getProperty(PROP_CELL_DIRECTION);
-                if (aCellDirectionVal)
-                {
-                    if (aCellDirectionVal->second.get<sal_Int32>() == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_TextDirection_btLr))
-                    {
-                        // btLr, so map ParagraphAdjust_CENTER to VertOrientation::CENTER.
-                        uno::Reference<beans::XPropertySet> xPropertySet(m_aTableRanges[nRow][nCell][0], uno::UNO_QUERY);
-                        if (xPropertySet.is() && xPropertySet->getPropertyValue("ParaAdjust").get<sal_Int16>() == sal_Int16(style::ParagraphAdjust_CENTER))
-                            (*aCellIterator)->Insert(PROP_VERT_ORIENT, uno::makeAny(text::VertOrientation::CENTER));
-                    }
-                    (*aCellIterator)->Erase(PROP_CELL_DIRECTION);
-                }
-
                 pSingleCellProperties[nCell] = (*aCellIterator)->GetPropertyValues();
 #ifdef DEBUG_WRITERFILTER
                 TagLogger::getInstance().endElement();
diff --git a/writerfilter/source/dmapper/DomainMapperTableManager.cxx b/writerfilter/source/dmapper/DomainMapperTableManager.cxx
index f7538768360f..4eaa51823c24 100644
--- a/writerfilter/source/dmapper/DomainMapperTableManager.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableManager.cxx
@@ -281,13 +281,6 @@ bool DomainMapperTableManager::sprm(Sprm & rSprm)
             case NS_ooxml::LN_CT_TcPrBase_textDirection:
             {
                 TablePropertyMapPtr pPropMap( new TablePropertyMap );
-
-                // Remember the cell direction, so later in
-                // DomainMapperTableHandler::endTableGetCellProperties() can we
-                // handle the combination of the cell direction and paragraph
-                // alignment as necessary.
-                pPropMap->Insert(PROP_CELL_DIRECTION, uno::Any(nIntValue));
-
                 bool bInsertCellProps = true;
                 switch ( nIntValue )
                 {
diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx
index b11b27ce7bcb..8faa6f63508c 100644
--- a/writerfilter/source/dmapper/PropertyIds.cxx
+++ b/writerfilter/source/dmapper/PropertyIds.cxx
@@ -338,7 +338,6 @@ OUString getPropertyName( PropertyIds eId )
         case PROP_CELL_INTEROP_GRAB_BAG          :   sName = "CellInteropGrabBag"; break;
         case PROP_TABLE_INTEROP_GRAB_BAG         :   sName = "TableInteropGrabBag"; break;
         case PROP_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING : sName = "ApplyParagraphMarkFormatToNumbering"; break;
-        case PROP_CELL_DIRECTION: sName = "CellDirection"; break;
         case PROP_SDT_END_BEFORE: sName = "SdtEndBefore"; break;
         case PROP_PARA_SDT_END_BEFORE: sName = "ParaSdtEndBefore"; break;
         case META_PROP_TABLE_LOOK: sName = "TableStyleLook"; break;
diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx
index a936b93d6470..ca2c4b6d5498 100644
--- a/writerfilter/source/dmapper/PropertyIds.hxx
+++ b/writerfilter/source/dmapper/PropertyIds.hxx
@@ -336,7 +336,6 @@ enum PropertyIds
         ,PROP_TABLE_INTEROP_GRAB_BAG
         ,PROP_INDEX_ENTRY_TYPE
         ,PROP_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING
-        ,PROP_CELL_DIRECTION
         ,PROP_SDT_END_BEFORE
         ,PROP_PARA_SDT_END_BEFORE
         ,META_PROP_TABLE_LOOK
commit e99aac63fc406775707ad4e92bc4349981538fd6
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Apr 4 21:34:31 2019 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jul 4 15:51:44 2019 +0200

    sw btlr writing mode: implement RTF export
    
    Note that we can't work with the table box (and frame format) of
    pTableTextNodeInfoInner in RtfAttributeOutput::TableVerticalCell(). This
    is because cell definitions are written in
    RtfAttributeOutput::TableDefinition(), and the loop only calls
    setCell(), i.e. the cell index is updated in the node info, but the
    table box is not.
    
    Import was already working as-is.
    
    Reviewed-on: https://gerrit.libreoffice.org/70269
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    (cherry picked from commit b62bfda66c1499806bfa35c26fdc05f76f8a4db2)
    
    Conflicts:
            sw/qa/extras/rtfexport/rtfexport4.cxx
    
    Change-Id: Ia089c42b3a49f1a8f012a8cadaa8bcad16128c3e

diff --git a/sw/qa/extras/rtfexport/data/btlr-cell.rtf b/sw/qa/extras/rtfexport/data/btlr-cell.rtf
new file mode 100644
index 000000000000..2a2117358cbb
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/btlr-cell.rtf
@@ -0,0 +1,9 @@
+{\rtf1
+\trowd\trrh1500\cltxbtlr\cellx3000\cellx6000\cltxtbrl\cellx9000
+\intbl
+AAA1.\par AAA2.\cell
+BBB1.\par BBB2.\cell
+CCC1.\par CCC2.\cell
+\pard \intbl\row
+\pard \par
+}
diff --git a/sw/qa/extras/rtfexport/rtfexport3.cxx b/sw/qa/extras/rtfexport/rtfexport3.cxx
index 85dbb38413ba..a254fa618bfe 100644
--- a/sw/qa/extras/rtfexport/rtfexport3.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport3.cxx
@@ -232,6 +232,24 @@ DECLARE_RTFEXPORT_TEST(testTdf123393, "tdf123393.rtf")
         7.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()), 1), "CharHeight"));
 }
 
+DECLARE_RTFEXPORT_TEST(testBtlrCell, "btlr-cell.rtf")
+{
+    // Without the accompanying fix in place, this test would have failed, as
+    // the btlr text direction in the A1 cell was lost.
+    uno::Reference<text::XTextTablesSupplier> xSupplier(mxComponent, uno::UNO_QUERY);
+    uno::Reference<container::XNameAccess> xTables = xSupplier->getTextTables();
+    uno::Reference<text::XTextTable> xTable(xTables->getByName("Table1"), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xA1(xTable->getCellByName("A1"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(text::WritingMode2::BT_LR, getProperty<sal_Int16>(xA1, "WritingMode"));
+
+    uno::Reference<beans::XPropertySet> xB1(xTable->getCellByName("B1"), uno::UNO_QUERY);
+    auto nActual = getProperty<sal_Int16>(xB1, "WritingMode");
+    CPPUNIT_ASSERT(nActual == text::WritingMode2::LR_TB || nActual == text::WritingMode2::CONTEXT);
+
+    uno::Reference<beans::XPropertySet> xC1(xTable->getCellByName("C1"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(text::WritingMode2::TB_RL, getProperty<sal_Int16>(xC1, "WritingMode"));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx
index aad9b6a9e21d..44958af03f25 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -847,6 +847,13 @@ void RtfAttributeOutput::TableVerticalCell(
     const SwWriteTableCell* const pCell
         = pRow->GetCells()[pTableTextNodeInfoInner->getCell()].get();
     const SwFrameFormat* pCellFormat = pCell->GetBox()->GetFrameFormat();
+
+    // Text direction.
+    if (SvxFrameDirection::Vertical_RL_TB == m_rExport.TrueFrameDirection(*pCellFormat))
+        m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLTXTBRL);
+    else if (SvxFrameDirection::Vertical_LR_BT == m_rExport.TrueFrameDirection(*pCellFormat))
+        m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLTXBTLR);
+
     const SfxPoolItem* pItem;
 
     // vertical merges
commit ad109d2423a5e0ace2c0bae0faca9e013191f063
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon Apr 1 21:34:50 2019 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jul 4 15:51:44 2019 +0200

    tdf#124261 sw btlr writing mode render: fix invalidation rectangle
    
    SwTextFrame::SwitchHorizontalToVertical(SwRect) did not handle the non-swapped
    case, also the text frame took the tblr codepath when determining the
    invalidation rectangle of the layout frame, but that special-case is not
    needed for the btlr direction.
    
    Typing into the cell of the bugdoc now determines the paint rectangle
    correctly, so the typed letters show up right after typing.
    
    Reviewed-on: https://gerrit.libreoffice.org/70087
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit e651a4f45b310f9890ffbf712b9970d4c452ecec)
    
    Conflicts:
            sw/qa/extras/uiwriter/uiwriter2.cxx
    
    Change-Id: I48c75603963868591d72bf4d0e8dbba679f3b5e9

diff --git a/sw/qa/extras/uiwriter/data2/tdf124261.docx b/sw/qa/extras/uiwriter/data2/tdf124261.docx
new file mode 100644
index 000000000000..1d3efa5276f4
Binary files /dev/null and b/sw/qa/extras/uiwriter/data2/tdf124261.docx differ
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index bdc9aad54853..2d8eb8049e3a 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -41,6 +41,7 @@
 #include <fmtornt.hxx>
 #include <xmloff/odffields.hxx>
 #include <com/sun/star/frame/DispatchHelper.hpp>
+#include <txtfrm.hxx>
 
 namespace
 {
@@ -79,6 +80,7 @@ public:
     void testMixedFormFieldInsertion();
     void testImageComment();
     void testImageCommentAtChar();
+    void testTdf124261();
 
     CPPUNIT_TEST_SUITE(SwUiWriterTest2);
     CPPUNIT_TEST(testRedlineMoveInsertInDelete);
@@ -108,6 +110,7 @@ public:
     CPPUNIT_TEST(testMixedFormFieldInsertion);
     CPPUNIT_TEST(testImageComment);
     CPPUNIT_TEST(testImageCommentAtChar);
+    CPPUNIT_TEST(testTdf124261);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -1168,6 +1171,40 @@ void SwUiWriterTest2::testImageCommentAtChar()
                          getProperty<OUString>(getRun(xPara, 5), "TextPortionType"));
 }
 
+void SwUiWriterTest2::testTdf124261()
+{
+#if !defined(WNT)
+    // Make sure that pressing a key in a btlr cell frame causes an immediate, correct repaint.
+    SwDoc* pDoc = createDoc("tdf124261.docx");
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    SwFrame* pPageFrame = pLayout->GetLower();
+    CPPUNIT_ASSERT(pPageFrame->IsPageFrame());
+
+    SwFrame* pBodyFrame = pPageFrame->GetLower();
+    CPPUNIT_ASSERT(pBodyFrame->IsBodyFrame());
+
+    SwFrame* pTabFrame = pBodyFrame->GetLower();
+    CPPUNIT_ASSERT(pTabFrame->IsTabFrame());
+
+    SwFrame* pRowFrame = pTabFrame->GetLower();
+    CPPUNIT_ASSERT(pRowFrame->IsRowFrame());
+
+    SwFrame* pCellFrame = pRowFrame->GetLower();
+    CPPUNIT_ASSERT(pCellFrame->IsCellFrame());
+
+    SwFrame* pFrame = pCellFrame->GetLower();
+    CPPUNIT_ASSERT(pFrame->IsTextFrame());
+
+    // Make sure that the text frame's area and the paint rectangle match.
+    // Without the accompanying fix in place, this test would have failed with 'Expected: 1721;
+    // Actual: 1547', i.e. an area other than the text frame was invalidated for a single-line
+    // paragraph.
+    SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pFrame);
+    SwRect aRect = pTextFrame->GetPaintSwRect();
+    CPPUNIT_ASSERT_EQUAL(pTextFrame->getFrameArea().Top(), aRect.Top());
+#endif
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest2);
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/frmpaint.cxx b/sw/source/core/text/frmpaint.cxx
index d459595c8a06..d4d3e0402647 100644
--- a/sw/source/core/text/frmpaint.cxx
+++ b/sw/source/core/text/frmpaint.cxx
@@ -420,7 +420,7 @@ SwRect SwTextFrame::GetPaintSwRect()
         SwRepaint& rRepaint = GetPara()->GetRepaint();
         long l;
 
-        if ( IsVertLR() ) // mba: the following line was added, but we don't need it for the existing directions; kept for IsVertLR(), but should be checked
+        if ( IsVertLR() && !IsVertLRBT()) // mba: the following line was added, but we don't need it for the existing directions; kept for IsVertLR(), but should be checked
             rRepaint.Chg( GetUpper()->getFrameArea().Pos() + GetUpper()->getFramePrintArea().Pos(), GetUpper()->getFramePrintArea().SSize() );
 
         if( rRepaint.GetOfst() )
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 847d49a0bc1c..aa4c92cae7cc 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -518,9 +518,10 @@ void SwTextFrame::SwitchHorizontalToVertical( SwRect& rRect ) const
 
     if (IsVertLRBT())
     {
-        SAL_WARN_IF(!mbIsSwapped, "sw.core",
-                    "SwTextFrame::SwitchHorizontalToVertical, IsVertLRBT, not swapped");
-        rRect.Top(getFrameArea().Top() + getFrameArea().Width() - nOfstX);
+        if (mbIsSwapped)
+            rRect.Top(getFrameArea().Top() + getFrameArea().Width() - nOfstX);
+        else
+            rRect.Top(getFrameArea().Top() + getFrameArea().Height() - nOfstX);
     }
     else
         rRect.Top(getFrameArea().Top() + nOfstX);
commit 04aff3d8df7ac7fdd8abdad8cacde62656a090ab
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Mar 28 21:27:40 2019 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jul 4 15:51:44 2019 +0200

    sw btlr writing mode: implement DOC filter
    
    Replace WW8TabDesc::Start/EndMiserableHackForUnsupportedDirection()
    added in commit 69ba46df8be261e665214390cd57a141ad65c210 (INTEGRATION:
    CWS vertcell (1.95.32); FILE MERGED, 2004-04-21) with the usage of the
    new writing direction. Adapt export accordingly.
    
    Change-Id: Ic85b69c806fbd1c1b4eb21cff3ee46dd5da497e8
    Reviewed-on: https://gerrit.libreoffice.org/69901
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    (cherry picked from commit 89e5b431d468745da3a1eff14d48296107b9101b)

diff --git a/sw/qa/extras/ww8export/data/btlr-cell.doc b/sw/qa/extras/ww8export/data/btlr-cell.doc
new file mode 100644
index 000000000000..f99e9e67e4e9
Binary files /dev/null and b/sw/qa/extras/ww8export/data/btlr-cell.doc differ
diff --git a/sw/qa/extras/ww8export/ww8export3.cxx b/sw/qa/extras/ww8export/ww8export3.cxx
index 955093393ed3..ba99e05deb36 100644
--- a/sw/qa/extras/ww8export/ww8export3.cxx
+++ b/sw/qa/extras/ww8export/ww8export3.cxx
@@ -16,6 +16,7 @@
 #include <com/sun/star/text/XTextFramesSupplier.hpp>
 #include <com/sun/star/text/XTextTable.hpp>
 #include <com/sun/star/text/XTextTablesSupplier.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
 
 #include <drawdoc.hxx>
 #include <svx/xfillit0.hxx>
@@ -203,6 +204,25 @@ DECLARE_WW8EXPORT_TEST(testTdf120711_joinedParagraphWithChangeTracking, "tdf1207
     CPPUNIT_ASSERT(style::NumberingType::CHAR_SPECIAL != numFormat);
 }
 
+DECLARE_WW8EXPORT_TEST(testBtlrCell, "btlr-cell.doc")
+{
+    // Without the accompanying fix in place, this test would have failed, as
+    // the btlr text direction in the A1 cell was lost on DOC import and
+    // export.
+    uno::Reference<text::XTextTablesSupplier> xSupplier(mxComponent, uno::UNO_QUERY);
+    uno::Reference<container::XNameAccess> xTables = xSupplier->getTextTables();
+    uno::Reference<text::XTextTable> xTable(xTables->getByName("Table1"), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xA1(xTable->getCellByName("A1"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(text::WritingMode2::BT_LR, getProperty<sal_Int16>(xA1, "WritingMode"));
+
+    uno::Reference<beans::XPropertySet> xB1(xTable->getCellByName("B1"), uno::UNO_QUERY);
+    auto nActual = getProperty<sal_Int16>(xB1, "WritingMode");
+    CPPUNIT_ASSERT(nActual == text::WritingMode2::LR_TB || nActual == text::WritingMode2::CONTEXT);
+
+    uno::Reference<beans::XPropertySet> xC1(xTable->getCellByName("C1"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(text::WritingMode2::TB_RL, getProperty<sal_Int16>(xC1, "WritingMode"));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
index 1ff54d4bfd92..8d41ab508441 100644
--- a/sw/source/filter/ww8/wrtww8.cxx
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -2135,12 +2135,26 @@ void WW8AttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_
         const SwTableBox * pTabBox1 = rTableBoxes[n];
         const SwFrameFormat * pFrameFormat = pTabBox1->GetFrameFormat();
 
-        if ( SvxFrameDirection::Vertical_RL_TB == m_rWW8Export.TrueFrameDirection( *pFrameFormat ) )
+        // Map from our SvxFrameDirection to WW8 TextFlow.
+        sal_uInt16 nTextFlow = 0;
+        switch (m_rWW8Export.TrueFrameDirection(*pFrameFormat))
+        {
+            case SvxFrameDirection::Vertical_RL_TB:
+                nTextFlow = 5;
+                break;
+            case SvxFrameDirection::Vertical_LR_BT:
+                nTextFlow = 3;
+                break;
+            default:
+                break;
+        }
+
+        if (nTextFlow != 0)
         {
             m_rWW8Export.InsUInt16( NS_sprm::sprmTTextFlow );
             m_rWW8Export.pO->push_back( n );                   //start range
             m_rWW8Export.pO->push_back( sal_uInt8(n + 1) );    //end range
-            m_rWW8Export.InsUInt16( 5 ); //Equals vertical writing
+            m_rWW8Export.InsUInt16(nTextFlow);
         }
     }
 }
diff --git a/sw/source/filter/ww8/ww8par2.cxx b/sw/source/filter/ww8/ww8par2.cxx
index f123fb2d207f..bba263a00c64 100644
--- a/sw/source/filter/ww8/ww8par2.cxx
+++ b/sw/source/filter/ww8/ww8par2.cxx
@@ -2883,23 +2883,6 @@ bool WW8TabDesc::InFirstParaInCell() const
     return m_pIo->m_pPaM->GetPoint()->nNode == m_pTabBox->GetSttIdx() + 1;
 }
 
-void WW8TabDesc::StartMiserableHackForUnsupportedDirection(short nWwCol)
-{
-    OSL_ENSURE(m_pActBand, "Impossible");
-    if (m_pActBand && nWwCol <= MAX_COL && m_pActBand->maDirections[nWwCol] == 3)
-    {
-        m_pIo->m_xCtrlStck->NewAttr(*m_pIo->m_pPaM->GetPoint(),
-            SvxCharRotateItem(900, false, RES_CHRATR_ROTATE));
-    }
-}
-
-void WW8TabDesc::EndMiserableHackForUnsupportedDirection(short nWwCol)
-{
-    OSL_ENSURE(m_pActBand, "Impossible");
-    if (m_pActBand && nWwCol <= MAX_COL && m_pActBand->maDirections[nWwCol] == 3)
-        m_pIo->m_xCtrlStck->SetAttr(*m_pIo->m_pPaM->GetPoint(), RES_CHRATR_ROTATE);
-}
-
 void WW8TabDesc::SetPamInCell(short nWwCol, bool bPam)
 {
     OSL_ENSURE( m_pActBand, "pActBand is 0" );
@@ -3003,8 +2986,6 @@ void WW8TabDesc::SetPamInCell(short nWwCol, bool bPam)
                 m_pIo->m_xCtrlStck->SetAttr(*pGridPos, RES_PARATR_SNAPTOGRID);
             }
         }
-
-        StartMiserableHackForUnsupportedDirection(nWwCol);
     }
 }
 
@@ -3113,7 +3094,7 @@ static SvxFrameDirection MakeDirection(sal_uInt16 nCode, bool bIsBiDi)
             OSL_ENSURE(eDir == SvxFrameDirection::Environment, "unknown direction code, maybe it's a bitfield");
             SAL_FALLTHROUGH;
         case 3:
-            eDir = bIsBiDi ? SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB; // #i38158# - Consider RTL tables
+            eDir = SvxFrameDirection::Vertical_LR_BT;
             break;
         case 5:
             eDir = SvxFrameDirection::Vertical_RL_TB;
@@ -3273,8 +3254,6 @@ void WW8TabDesc::TableCellEnd()
 {
     ::SetProgressState(m_pIo->m_nProgress, m_pIo->m_pDocShell);   // Update
 
-    EndMiserableHackForUnsupportedDirection(m_nCurrentCol);
-
     // new line/row
     if( m_pIo->m_bWasTabRowEnd )
     {
diff --git a/sw/source/filter/ww8/ww8par2.hxx b/sw/source/filter/ww8/ww8par2.hxx
index 16b4f58c0800..4875270e6e27 100644
--- a/sw/source/filter/ww8/ww8par2.hxx
+++ b/sw/source/filter/ww8/ww8par2.hxx
@@ -259,8 +259,6 @@ class WW8TabDesc
     // (the merge groups are processed later at once)
     void UpdateTableMergeGroup(WW8_TCell const & rCell,
         WW8SelBoxInfo* pActGroup, SwTableBox* pActBox, sal_uInt16 nCol  );
-    void StartMiserableHackForUnsupportedDirection(short nWwCol);
-    void EndMiserableHackForUnsupportedDirection(short nWwCol);
 
     WW8TabDesc(WW8TabDesc const&) = delete;
     WW8TabDesc& operator=(WW8TabDesc const&) = delete;


More information about the Libreoffice-commits mailing list