cui/source/tabpages/numpages.cxx                  |    8 
 hwpfilter/source/hwpreader.cxx                    |   12 
 include/oox/export/drawingml.hxx                  |    5 
 include/svx/EnhancedCustomShape2d.hxx             |    2 
 oox/qa/unit/data/FaultyPathStart.odp              |binary
 oox/qa/unit/data/tdf109169_OctagonBevel.odt       |binary
 oox/qa/unit/export.cxx                            |   41 +
 oox/source/drawingml/fillproperties.cxx           |    6 
 oox/source/drawingml/graphicshapecontext.cxx      |   32 -
 oox/source/drawingml/textparagraphproperties.cxx  |    3 
 oox/source/export/drawingml.cxx                   |  678 ++++++++++------------
 sd/qa/unit/data/pptx/tdf147586.pptx               |binary
 sd/qa/unit/export-tests-ooxml2.cxx                |   19 
 sd/qa/unit/export-tests-ooxml3.cxx                |   22 
 sd/source/ui/slideshow/slideshowimpl.cxx          |    2 
 svtools/source/control/ctrlbox.cxx                |   28 
 svx/qa/unit/customshapes.cxx                      |   58 +
 svx/qa/unit/data/tdf148501_OctagonBevel.odp       |binary
 svx/source/customshapes/EnhancedCustomShape2d.cxx |   18 
 sw/CppunitTest_sw_core_text.mk                    |    1 
 sw/qa/core/text/text.cxx                          |   46 +
 sw/qa/extras/ooxmlexport/data/tdf139948.docx      |binary
 sw/qa/extras/ooxmlexport/ooxmlexport17.cxx        |   26 
 sw/qa/extras/rtfexport/data/tdf139948.rtf         |    8 
 sw/qa/extras/rtfexport/data/tdf148515.rtf         |   14 
 sw/qa/extras/rtfexport/rtfexport4.cxx             |   51 +
 sw/qa/extras/uiwriter/uiwriter.cxx                |   51 +
 sw/qa/extras/uiwriter/uiwriter3.cxx               |  204 ++++++
 sw/source/core/frmedt/fecopy.cxx                  |   14 
 sw/source/core/text/itrcrsr.cxx                   |    4 
 sw/source/core/txtnode/ndtxt.cxx                  |    5 
 sw/source/uibase/dochdl/swdtflvr.cxx              |   26 
 sw/source/uibase/shells/tabsh.cxx                 |   46 +
 vcl/source/outdev/textline.cxx                    |    2 
 writerfilter/source/dmapper/DomainMapper.cxx      |   11 
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |   25 
 writerfilter/source/dmapper/DomainMapper_Impl.hxx |    3 
 writerfilter/source/dmapper/PropertyIds.cxx       |    1 
 writerfilter/source/dmapper/PropertyIds.hxx       |    1 
 writerfilter/source/rtftok/rtfdispatchflag.cxx    |    4 
 writerfilter/source/rtftok/rtfdocumentimpl.cxx    |    5 
 writerfilter/source/rtftok/rtfsprm.cxx            |    2 
 42 files changed, 1084 insertions(+), 400 deletions(-)

New commits:
commit b1dce5778af2343d5029034a6690b55993d7cfe5
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Tue Apr 26 12:29:29 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:02 2022 +0200

    tdf#148791 tdf#64902 tdf#127759 sw: fix row insert/paste
    
    Table insertion mode and Paste as Rows Above inserted
    only a single row above, and overwrite the next ones in
    the following cases (instead of inserting/pasting rows
    above according to the clipboard table content):
    
    The table stored in the clipboard
    
    – has centered, right or not paragraph starting alignment;
    
    – or its resource table has a table header with 2 or more
      repeating rows, and the clipboard content contains the
      same amount or less rows (it doesn't matter, that
      the copied rows weren't header rows originally).
    
    The reason was that parsing of the HTML clipboard content
    which is used for counting the row count of the clipboard
    content hadn't handle the following cases:
    
    – different table aligment results <tr> elements with
      greater indentation level in the HTML extract, according
      to the new root element <center>, <div> or <dl>;
    
    – copying rows from a table with row header always starts
      with <thead> in the HTML extract, i.e. detecting <tbody>
      can fail, because there could be only <thead> in the
      HTML extract (see Case 2 above).
    
    Follow-up to commit 0c8b1efbad48fa9697c0b1afbe4753bbbc3c4c5c
    "tdf#127759 Writer: add table row/column insert mode" and
    commit 7efae60f3625a58f8a617c80f2a55a695fbaef36
    "tdf#64902 Writer table: Paste Special->Rows Above".
    
    Change-Id: I466cea20705bc5dd5455e22842da7dfa6631ba81
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133445
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit 2fbf0f418ccb25010add33449d4e42b8b3f7fd0b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133411
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx 
b/sw/qa/extras/uiwriter/uiwriter3.cxx
index 26ca4e8db96f..3c453ab313da 100644
--- a/sw/qa/extras/uiwriter/uiwriter3.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter3.cxx
@@ -2267,6 +2267,119 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf141391)
     assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/txt/Text", 
"Portion", "hello");
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf148791)
+{
+    // test Paste as Rows Above with centered table alignment
+
+    // load a 2-row table
+    SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf116789.fodt");
+    CPPUNIT_ASSERT(pDoc);
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+
+    // select and copy the table, and Paste As Rows Above
+
+    dispatchCommand(mxComponent, ".uno:SelectTable", {});
+    dispatchCommand(mxComponent, ".uno:Copy", {});
+    // remove the selection and positionate the cursor at beginning of A2
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    pWrtShell->Up(/*bSelect=*/false);
+    dispatchCommand(mxComponent, ".uno:PasteRowsBefore", {});
+    Scheduler::ProcessEventsToIdle();
+
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+    // Paste as Rows Above results 4-row table with default table aligment
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 4);
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[1]/cell[1]/txt/Text", 
"Portion", "hello");
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[3]/cell[1]/txt/Text", 
"Portion", "hello");
+
+    // set table alignment to center, select and copy the table again
+    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> 
xIndexAccess(xTextTablesSupplier->getTextTables(),
+                                                         uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
+
+    uno::Reference<text::XTextTable> xTextTable(xIndexAccess->getByIndex(0), 
uno::UNO_QUERY);
+
+    // Default table alignment
+    CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::FULL,
+                         getProperty<sal_Int16>(xTextTable, "HoriOrient"));
+
+    //CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xTextTable, 
"TableTemplateName"));
+    uno::Reference<beans::XPropertySet> xTableProps(xTextTable, 
uno::UNO_QUERY_THROW);
+
+    xTableProps->setPropertyValue("HoriOrient", 
uno::makeAny(text::HoriOrientation::CENTER));
+
+    CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::CENTER,
+                         getProperty<sal_Int16>(xTextTable, "HoriOrient"));
+
+    dispatchCommand(mxComponent, ".uno:SelectTable", {});
+    dispatchCommand(mxComponent, ".uno:Copy", {});
+    // remove the selection and positionate the cursor at beginning of A2
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    pWrtShell->Up(/*bSelect=*/false);
+    pWrtShell->Up(/*bSelect=*/false);
+    pWrtShell->Up(/*bSelect=*/false);
+    dispatchCommand(mxComponent, ".uno:PasteRowsBefore", {});
+    Scheduler::ProcessEventsToIdle();
+
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    // This was 5 (inserting only a single row for the 4-row clipboard 
content, and
+    // overwriting 3 existing rows)
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 8);
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[1]/cell[1]/txt/Text", 
"Portion", "hello");
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[3]/cell[1]/txt/Text", 
"Portion", "hello");
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[5]/cell[1]/txt/Text", 
"Portion", "hello");
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[7]/cell[1]/txt/Text", 
"Portion", "hello");
+
+    // tdf#64902 add a test case for nested tables
+
+    // insert a nested table, and copy as paste as rows above the whole table 
with it
+    dispatchCommand(mxComponent, ".uno:PasteNestedTable", {});
+    dispatchCommand(mxComponent, ".uno:SelectTable", {});
+    dispatchCommand(mxComponent, ".uno:Copy", {});
+    // remove the selection and positionate the cursor at beginning of A2
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    // skip 7 table rows plus 4 rows of the nested table
+    for (int i = 0; i < 7 + 4; ++i)
+        pWrtShell->Up(/*bSelect=*/false);
+    dispatchCommand(mxComponent, ".uno:PasteRowsBefore", {});
+    Scheduler::ProcessEventsToIdle();
+
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    // rows of the nested table doesn't effect row number of the main table
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 16);
+    // there are two nested tables after the paste
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row/cell/tab", 2);
+
+    // tdf#64902 add a test case for repeated table headings
+
+    xTableProps->setPropertyValue("RepeatHeadline", uno::makeAny(true));
+    CPPUNIT_ASSERT(getProperty<bool>(xTextTable, "RepeatHeadline"));
+
+    xTableProps->setPropertyValue("HeaderRowCount", 
uno::makeAny(sal_Int32(3)));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getProperty<sal_Int32>(xTextTable, 
"HeaderRowCount"));
+
+    dispatchCommand(mxComponent, ".uno:SelectTable", {});
+    dispatchCommand(mxComponent, ".uno:Copy", {});
+    // remove the selection and positionate the cursor at beginning of A2
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    // skip 15 table rows plus 4 * 2 rows of the nested tables
+    for (int i = 0; i < 15 + 4 * 2; ++i)
+        pWrtShell->Up(/*bSelect=*/false);
+    dispatchCommand(mxComponent, ".uno:PasteRowsBefore", {});
+    Scheduler::ProcessEventsToIdle();
+
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    // repeating table header (and its thead/tbody indentation) doesn't effect 
row number
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 32);
+    // there are two nested tables after the paste
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row/cell/tab", 4);
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf135014)
 {
     createSwDoc();
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx 
b/sw/source/uibase/dochdl/swdtflvr.cxx
index 0ba19a1ec537..45b74a55773b 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -1454,6 +1454,18 @@ void 
SwTransferable::SelectPasteFormat(TransferableDataHelper& rData, sal_uInt8&
     nFormat = SotClipboardFormatId::EMBED_SOURCE;
 }
 
+// get HTML indentation level by counting tabulator characters before the index
+// (also index value -1 returns with 0)
+static sal_Int32 lcl_getLevel(OUString& sText, sal_Int32 nIdx)
+{
+    sal_Int32 nRet = 0;
+    while ( nIdx-- > 0 && sText[nIdx] == '\t' )
+    {
+        nRet++;
+    }
+    return nRet;
+}
+
 bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, 
RndStdIds nAnchorType, bool bIgnoreComments, PasteTableType ePasteTable)
 {
     SwPasteContext aPasteContext(rSh);
@@ -1568,16 +1580,22 @@ bool SwTransferable::Paste(SwWrtShell& rSh, 
TransferableDataHelper& rData, RndSt
         bool bRowMode = rSh.GetTableInsertMode() == SwTable::SEARCH_ROW || 
ePasteTable == PasteTableType::PASTE_ROW;
         if( rData.GetString( SotClipboardFormatId::HTML, aExpand ) && (nIdx = 
aExpand.indexOf("<table")) > -1 )
         {
-            // table rows with span use also tbody
-            bool bShifted = aExpand.indexOf("<tbody>") > -1;
+            // calculate table row/column count by analysing indentation of 
the HTML table extract
+
+            // calculate indentation level of <table>, which is the base of 
the next calculations
+            // (tdf#148791 table alignment can enlarge it using first level 
<center>, <div> or <dl>)
+            sal_Int32 nTableLevel = lcl_getLevel(aExpand, nIdx);
+            // table rows repeated heading use extra indentation, too:
+            // <thead> is always used here, and the first table with <thead> 
is not nested,
+            // if its indentation level is greater only by 1, than intentation 
level of the table
+            bool bShifted = lcl_getLevel(aExpand, aExpand.indexOf("<thead")) 
== nTableLevel + 1;
             // calculate count of selected rows or columns
             sal_Int32 nSelectedRowsOrCols = 0;
             const OUString sSearchRowOrCol = bRowMode ? OUString("</tr>") : 
OUString("<col ");
             while((nIdx = aExpand.indexOf(sSearchRowOrCol, nIdx)) > -1)
             {
                 // skip rows/columns of nested tables, based on HTML 
indentation
-                if ( nIdx > 3 && (aExpand[nIdx-1] != '\t' || aExpand[nIdx-2] 
!= '\t' ||
-                    ( bShifted && aExpand[nIdx-3] != '\t') ) &&
+                if ( lcl_getLevel(aExpand, nIdx) == nTableLevel + (bShifted ? 
2 : 1) &&
                     // skip also strange hidden empty rows <tr></tr>
                     !aExpand.match("<tr></tr>", nIdx - 4) )
                 {
commit 272a1403164cdd236e33af8e72fbecae23907d91
Author:     Tünde Tóth <toth.tu...@nisz.hu>
AuthorDate: Wed Apr 6 16:18:29 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:02 2022 +0200

    tdf#53970 PPTX: fix import of linked media files
    
    Linked media files were imported as images in documents
    created with Impress after PPTX export.
    
    Change-Id: If4920c2e40f45fff73eca4a5fa987d524177597e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132635
    Tested-by: Jenkins
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit 9564747d2fd5d2c859a359dd7fa6242c6859c0d7)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133410
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/oox/source/drawingml/fillproperties.cxx 
b/oox/source/drawingml/fillproperties.cxx
index 2b682bcd1b99..e3830618522b 100644
--- a/oox/source/drawingml/fillproperties.cxx
+++ b/oox/source/drawingml/fillproperties.cxx
@@ -954,11 +954,11 @@ void GraphicProperties::pushToPropMap( PropertyMap& 
rPropMap, const GraphicHelpe
         rPropMap.setProperty(PROP_AdjustContrast, nContrast);
 
     // Media content
-    assert(m_xMediaStream.is() != m_sMediaPackageURL.isEmpty());
-    if (m_xMediaStream.is() && !m_sMediaPackageURL.isEmpty())
+    if (!m_sMediaPackageURL.isEmpty())
     {
-        rPropMap.setProperty(PROP_PrivateStream, m_xMediaStream);
         rPropMap.setProperty(PROP_MediaURL, m_sMediaPackageURL);
+        if (m_xMediaStream.is())
+            rPropMap.setProperty(PROP_PrivateStream, m_xMediaStream);
     }
 }
 
diff --git a/oox/source/drawingml/graphicshapecontext.cxx 
b/oox/source/drawingml/graphicshapecontext.cxx
index 3ed00edfd28c..d90980a87824 100644
--- a/oox/source/drawingml/graphicshapecontext.cxx
+++ b/oox/source/drawingml/graphicshapecontext.cxx
@@ -84,10 +84,12 @@ ContextHandlerRef GraphicShapeContext::onCreateContext( 
sal_Int32 aElementToken,
     case XML_wavAudioFile:
         {
             OUString const path(getEmbeddedWAVAudioFile(getRelations(), 
rAttribs));
-            mpShapePtr->getGraphicProperties().m_xMediaStream =
-                lcl_GetMediaStream(path, getFilter());
-            mpShapePtr->getGraphicProperties().m_sMediaPackageURL =
-                lcl_GetMediaReference(path);
+            Reference<XInputStream> xMediaStream = lcl_GetMediaStream(path, 
getFilter());
+            if (xMediaStream.is())
+            {
+                mpShapePtr->getGraphicProperties().m_xMediaStream = 
xMediaStream;
+                mpShapePtr->getGraphicProperties().m_sMediaPackageURL = 
lcl_GetMediaReference(path);
+            }
         }
         break;
     case XML_audioFile:
@@ -95,10 +97,24 @@ ContextHandlerRef GraphicShapeContext::onCreateContext( 
sal_Int32 aElementToken,
         {
             OUString rPath = getRelations().getFragmentPathFromRelId(
                     rAttribs.getString(R_TOKEN(link)).get() );
-            mpShapePtr->getGraphicProperties().m_xMediaStream =
-                lcl_GetMediaStream(rPath, getFilter());
-            mpShapePtr->getGraphicProperties().m_sMediaPackageURL =
-                lcl_GetMediaReference(rPath);
+            if (!rPath.isEmpty())
+            {
+                Reference<XInputStream> xMediaStream = 
lcl_GetMediaStream(rPath, getFilter());
+                if (xMediaStream.is()) // embedded media file
+                {
+                    mpShapePtr->getGraphicProperties().m_xMediaStream = 
xMediaStream;
+                    mpShapePtr->getGraphicProperties().m_sMediaPackageURL
+                        = lcl_GetMediaReference(rPath);
+                }
+            }
+            else
+            {
+                rPath = getRelations().getExternalTargetFromRelId(
+                    rAttribs.getString(R_TOKEN(link)).get());
+                if (!rPath.isEmpty()) // linked media file
+                    mpShapePtr->getGraphicProperties().m_sMediaPackageURL
+                        = getFilter().getAbsoluteUrl(rPath);
+            }
         }
         break;
     }
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx 
b/sd/qa/unit/export-tests-ooxml2.cxx
index dc6498ec614d..0b244bc76233 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -1832,11 +1832,28 @@ void SdOOXMLExportTest2::testTdf53970()
             
m_directories.getURLFromSrc(u"/sd/qa/unit/data/odp/tdf53970_linked.odp"), ODP);
         utl::TempFile tempFile;
         xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
-        xDocShRef->DoClose();
 
         xmlDocUniquePtr pXmlRels = parseExport(tempFile, 
"ppt/slides/_rels/slide1.xml.rels");
         CPPUNIT_ASSERT(pXmlRels);
         assertXPath(pXmlRels, 
"/rels:Relationships/rels:Relationship[@TargetMode='External']", 2);
+
+        uno::Reference<beans::XPropertySet> xShape(getShape(0, getPage(0, 
xDocShRef)));
+        CPPUNIT_ASSERT(xShape.is());
+        OUString sVideoURL;
+
+        // Without fix in place, the media shape was imported as an image 
after export.
+        try
+        {
+            CPPUNIT_ASSERT_MESSAGE("MediaURL property is not set",
+                                   xShape->getPropertyValue("MediaURL") >>= 
sVideoURL);
+        }
+        catch (const beans::UnknownPropertyException&)
+        {
+            CPPUNIT_FAIL("Error: MediaURL is unknown property");
+        }
+        CPPUNIT_ASSERT_MESSAGE("MediaURL is empty", !sVideoURL.isEmpty());
+
+        xDocShRef->DoClose();
     }
 }
 
commit 124de76ff63dfd0393ff3fa038ad0bc594ad3ff8
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Tue Apr 26 16:51:01 2022 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:02 2022 +0200

    ofz#47042 previous use of static variable affecting later runs
    
    Change-Id: I64fb184e43fb025798781c85c9a0a8e0354b21b0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133453
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/hwpfilter/source/hwpreader.cxx b/hwpfilter/source/hwpreader.cxx
index 1bd12242b436..d5a73be7e623 100644
--- a/hwpfilter/source/hwpreader.cxx
+++ b/hwpfilter/source/hwpreader.cxx
@@ -71,7 +71,6 @@ constexpr OUStringLiteral sXML_CDATA = u"CDATA";
     rendEl("text:span"); \
     tstart = false
 
-static hchar *field = nullptr;
 static char buf[1024];
 
 namespace
@@ -97,12 +96,13 @@ struct HwpReaderPrivate
         bInHeader = false;
         nPnPos = 0;
         pPn = nullptr;
-
+        pField = nullptr;
     }
     bool bFirstPara;
     bool bInBody;
     bool bInHeader;
     ShowPageNum *pPn;
+    hchar *pField;
     int nPnPos;
 };
 
@@ -2933,7 +2933,7 @@ void HwpReader::make_text_p3(HWPPara * para,bool 
bParaStart)
                 firstspace = 1;
                 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
                 {
-                     field = hbox->str3.get();
+                     d->pField = hbox->str3.get();
                 }
                 else{
                      makeFieldCode(str, hbox);
@@ -2946,7 +2946,7 @@ void HwpReader::make_text_p3(HWPPara * para,bool 
bParaStart)
                 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
                 {
                      makeFieldCode(str, hbox);
-                     field = nullptr;
+                     d->pField = nullptr;
                 }
                 infield = false;
                 str.clear();
@@ -3114,8 +3114,8 @@ void HwpReader::makeFieldCode(hchar_string const & rStr, 
FieldCode const *hbox)
     if( hbox->type[0] == 4 && hbox->type[1] == 0 )
     {
         padd("text:placeholder-type", sXML_CDATA, "text");
-        if( field )
-              padd("text:description", sXML_CDATA, 
fromHcharStringToOUString(hstr2ucsstr(field)));
+        if (d->pField)
+            padd("text:description", sXML_CDATA, 
fromHcharStringToOUString(hstr2ucsstr(d->pField)));
         rstartEl( "text:placeholder", mxList);
         mxList->clear();
         rchars( fromHcharStringToOUString(rStr) );
commit 16793d3f597fff2d62f55c13931a7d7104a2059f
Author:     Vasily Melenchuk <vasily.melenc...@cib.de>
AuthorDate: Thu Apr 21 10:04:50 2022 +0300
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:02 2022 +0200

    tdf#148515: RTF filter: do not use char prop defaults for tables
    
    During deduplication of table row (when nStyleType == 0) we should
    not deduplicate character properties against default style: this
    leads to invalid default settings for table rows/cells.
    
    Attempts to do so are already made during \pard processing when
    default style is checked if it is paragraph style. But this is
    not enough: style definition can contain paragraph and character
    properties as well.
    
    Change-Id: If520c5a248897728b7de08a017136ca1a01a5f13
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132943
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    (cherry picked from commit 3a05acb8f0d94728ea6cbfd7a69dac6ffa7ffc68)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133477
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/extras/rtfexport/data/tdf148515.rtf 
b/sw/qa/extras/rtfexport/data/tdf148515.rtf
new file mode 100644
index 000000000000..f8e27e577425
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf148515.rtf
@@ -0,0 +1,14 @@
+{\rtf1\ansi
+{\fonttbl
+{\f1 Impact;}
+}
+
+{\stylesheet
+{\fs20\f1\af1 Normal;}
+}
+
+\trowd\cellx5000\cellx10000
+\pard\intbl\f1\fs10 XXXXXX\cell
+\pard\intbl\cell
+\row
+}
diff --git a/sw/qa/extras/rtfexport/rtfexport4.cxx 
b/sw/qa/extras/rtfexport/rtfexport4.cxx
index 98bf1042b212..3c898337f92d 100644
--- a/sw/qa/extras/rtfexport/rtfexport4.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport4.cxx
@@ -635,6 +635,25 @@ DECLARE_RTFEXPORT_TEST(testTdf139948, "tdf139948.rtf")
         sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(5), 
"BottomBorder").LineWidth);
 }
 
+DECLARE_RTFEXPORT_TEST(testTdf148515, "tdf148515.rtf")
+{
+    uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), 
uno::UNO_QUERY);
+
+    uno::Reference<text::XTextRange> xCell1(xTable->getCellByName("A1"), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("XXXXXX"), xCell1->getString());
+    CPPUNIT_ASSERT_EQUAL(
+        5.0f,
+        getProperty<float>(getRun(getParagraphOfText(1, xCell1->getText()), 
1), "CharHeight"));
+
+    uno::Reference<text::XTextRange> xCell2(xTable->getCellByName("B1"), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString(""), xCell2->getString());
+    CPPUNIT_ASSERT_EQUAL(
+        5.0f,
+        getProperty<float>(getRun(getParagraphOfText(1, xCell2->getText()), 
1), "CharHeight"));
+
+    CPPUNIT_ASSERT_EQUAL(10.f, getProperty<float>(getRun(getParagraph(2), 1), 
"CharHeight"));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/rtftok/rtfsprm.cxx 
b/writerfilter/source/rtftok/rtfsprm.cxx
index 04df49bc0287..2edfec829edf 100644
--- a/writerfilter/source/rtftok/rtfsprm.cxx
+++ b/writerfilter/source/rtftok/rtfsprm.cxx
@@ -159,7 +159,7 @@ void RTFSprms::eraseLast(Id nKeyword)
 
 static RTFValue::Pointer_t getDefaultSPRM(Id const id, Id nStyleType)
 {
-    if (!nStyleType || nStyleType == NS_ooxml::LN_Value_ST_StyleType_character)
+    if (nStyleType == NS_ooxml::LN_Value_ST_StyleType_character)
     {
         switch (id)
         {
commit ee9d26032f8f6dd43f3914d43d608eb6748406c4
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Apr 26 15:40:44 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:02 2022 +0200

    sw: fix double-click opening frame dialog, not graphic dialog on images
    
    The user-visible problem was that once a user clicks on an image a lot
    (e.g. 5 times), then the slot ID dispatched on double-click in
    SwEditWin::MouseButtonDown() is no longer FN_FORMAT_GRAFIC_DLG, but it's
    FN_FORMAT_FRAME_DLG.
    
    This is already inconsistent, but it's especially problematic in case an
    UNO client intercepts only the first UNO command, but not the second
    one.
    
    The other inconsistency is that in practice this only happens for
    as-char images, at-char anchored images work fine.
    
    The reason for this seems to be how we get the doc model position for a
    twips view point. At-char anchored images are handled at
    lcl_GetModelPositionForViewPoint_Objects(), and there we return the
    SwGrfNode in case the view point is inside the frame of the matching fly
    frame. SwTextCursor::GetModelPositionForViewPoint() restricted the same
    to as-char fly frames which have text or layout frame children.
    
    Fix the problem by allowing non-text frame children for as-char images.
    
    Change-Id: If08e7dd2a72f46ebcfb8c6ddf110703eaeb7df6d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133443
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133462

diff --git a/sw/CppunitTest_sw_core_text.mk b/sw/CppunitTest_sw_core_text.mk
index 6f19ff690f5a..19d8cd422edc 100644
--- a/sw/CppunitTest_sw_core_text.mk
+++ b/sw/CppunitTest_sw_core_text.mk
@@ -23,6 +23,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_core_text, \
     cppuhelper \
     sal \
     sfx \
+    svl \
     sw \
        swqahelper \
     test \
diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx
index 3d2c91f2b131..0cd732c4a4af 100644
--- a/sw/qa/core/text/text.cxx
+++ b/sw/qa/core/text/text.cxx
@@ -28,6 +28,9 @@
 #include <porlay.hxx>
 #include <pormulti.hxx>
 #include <formatlinebreak.hxx>
+#include <sortedobjs.hxx>
+#include <anchoredobject.hxx>
+#include <fmtcntnt.hxx>
 
 constexpr OUStringLiteral DATA_DIRECTORY = u"/sw/qa/core/text/data/";
 
@@ -361,6 +364,49 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, 
testClearingLineBreakHeader)
     assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout[1]", "height", "276");
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testAsCharImageDocModelFromViewPoint)
+{
+    // Given a document with an as-char image:
+    SwDoc* pDoc = createSwDoc();
+    uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xTextGraphic(
+        xFactory->createInstance("com.sun.star.text.TextGraphicObject"), 
uno::UNO_QUERY);
+    // Only set the anchor type, the actual bitmap content is not interesting.
+    xTextGraphic->setPropertyValue("AnchorType",
+                                   
uno::makeAny(text::TextContentAnchorType_AS_CHARACTER));
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xBodyText = xTextDocument->getText();
+    uno::Reference<text::XTextCursor> xCursor(xBodyText->createTextCursor());
+    uno::Reference<text::XTextContent> xTextContent(xTextGraphic, 
uno::UNO_QUERY);
+    xBodyText->insertTextContent(xCursor, xTextContent, false);
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    SwRootFrame* pRootFrame = pWrtShell->GetLayout();
+    SwFrame* pPageFrame = pRootFrame->GetLower();
+    SwFrame* pBodyFrame = pPageFrame->GetLower();
+    SwFrame* pTextFrame = pBodyFrame->GetLower();
+    const SwSortedObjs& rSortedObjs = *pTextFrame->GetDrawObjs();
+    const SwAnchoredObject* pAnchoredObject = rSortedObjs[0];
+    // The content points to the start node, the next node is the graphic node.
+    SwNodeIndex aGraphicNode = 
*pAnchoredObject->GetFrameFormat().GetContent().GetContentIdx();
+    ++aGraphicNode;
+    tools::Rectangle aFlyFrame = 
pAnchoredObject->GetDrawObj()->GetLastBoundRect();
+    Point aDocPos = aFlyFrame.Center();
+
+    // When translating the view point to the model position:
+    pWrtShell->SttCursorMove();
+    pWrtShell->CallSetCursor(&aDocPos, /*bOnlyText=*/false);
+    pWrtShell->EndCursorMove();
+
+    // Then make sure that we find the graphic node, and not its anchor:
+    SwShellCursor* pShellCursor = pWrtShell->getShellCursor(/*bBlock=*/false);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: SwNodeIndex (node 6)
+    // - Actual  : SwNodeIndex (node 12)
+    // i.e. the cursor position was the text node hosting the as-char image, 
not the graphic node of
+    // the image.
+    CPPUNIT_ASSERT_EQUAL(aGraphicNode, pShellCursor->GetMark()->nNode);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
index d9d87aaa713c..f6c8ed380107 100644
--- a/sw/source/core/text/itrcrsr.cxx
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -1761,8 +1761,10 @@ TextFrameIndex 
SwTextCursor::GetModelPositionForViewPoint( SwPosition *pPos, con
                 //              (BugId: 9692 + Change in feshview)
                 SwFlyInContentFrame *pTmp = pFlyPor->GetFlyFrame();
                 SwFrame* pLower = pTmp->GetLower();
+                // Allow non-text-frames to get SwGrfNode for as-char anchored 
images into pPos
+                // instead of the closest SwTextNode, to be consistent with 
at-char behavior.
                 bool bChgNodeInner = pLower
-                    && (pLower->IsTextFrame() || pLower->IsLayoutFrame());
+                    && (pLower->IsTextFrame() || pLower->IsLayoutFrame() || 
pLower->IsNoTextFrame());
                 Point aTmpPoint( rPoint );
 
                 if ( m_pFrame->IsRightToLeft() )
commit cf19ed587de53a3d4c737c01d9bb1ad570843a38
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Wed Apr 20 18:16:50 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:02 2022 +0200

    tdf#109169 export Type encoded shading to OOXML
    
    A shape might have the shading information not in commands in the
    enhanced-path, but generated in ctor of EnhancedCustomShape2d from the
    Type value of the shape. This shading information is a 32 bit value
    with first the number of the shadings and then the shadings. A shading
    is encoded with 1,2,3,4,5,6,7 for lighten 10 to 70 and 8,9,a,b,c,d,e,f
    for darken -80 to -10.
    
    To get this information from EnhanceCustomShape2d I have made its
    method GetLuminanceChange() public.
    
    Because OOXML only has darken, darkenLess, lighten and lightenLess our
    values are mapped:
    -10, -20, -30 to darkenLess
    -40, -50, -60, -70, -80 to darken
    10, 20, 30 to lightenLess
    40, 50, 60, 70 to lighten
    
    The bupreport mentions only 'Octagon Bevel' and 'Diamond Bevel'. But
    the patch fixes missing shading for shapes of Types 'ActionButton*'
    as well. Such shapes come in from MS binary import.
    
    Change-Id: I03f19496b915f3ced6346222e8806832b4ee2827
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133220
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <rb.hensc...@t-online.de>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133366

diff --git a/include/svx/EnhancedCustomShape2d.hxx 
b/include/svx/EnhancedCustomShape2d.hxx
index 18ce21437bcc..abe9319407ff 100644
--- a/include/svx/EnhancedCustomShape2d.hxx
+++ b/include/svx/EnhancedCustomShape2d.hxx
@@ -127,7 +127,6 @@ class SVXCORE_DLLPUBLIC EnhancedCustomShape2d final : 
public SfxItemSet
         Degree100               nRotateAngle;
 
         SAL_DLLPRIVATE bool     SetAdjustValueAsDouble( const double& rValue, 
const sal_Int32 nIndex );
-        SAL_DLLPRIVATE sal_Int32 GetLuminanceChange( sal_uInt32 nIndex ) const;
         SAL_DLLPRIVATE Color    GetColorData( const Color& rFillColor, 
sal_uInt32 nIndex, double dBrightness ) const;
         SAL_DLLPRIVATE void AdaptObjColor(
             SdrPathObj& rObj,
@@ -183,6 +182,7 @@ class SVXCORE_DLLPUBLIC EnhancedCustomShape2d final : 
public SfxItemSet
             }
         };
 
+        sal_Int32 GetLuminanceChange( sal_uInt32 nIndex ) const;
         SAL_DLLPRIVATE bool     IsFlipVert() const { return bFlipV; };
         SAL_DLLPRIVATE bool     IsFlipHorz() const { return bFlipH; };
         SAL_DLLPRIVATE Degree100 GetRotateAngle() const { return nRotateAngle; 
};
diff --git a/oox/qa/unit/data/tdf109169_OctagonBevel.odt 
b/oox/qa/unit/data/tdf109169_OctagonBevel.odt
new file mode 100644
index 000000000000..2ba39b102e1e
Binary files /dev/null and b/oox/qa/unit/data/tdf109169_OctagonBevel.odt differ
diff --git a/oox/qa/unit/export.cxx b/oox/qa/unit/export.cxx
index 26d1a0e973bb..62988f7fd3bf 100644
--- a/oox/qa/unit/export.cxx
+++ b/oox/qa/unit/export.cxx
@@ -530,6 +530,27 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf147978_subpath)
     assertXPath(pXmlDoc, "//a:pathLst/a:path[4]", "h", "80");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf109169_OctagonBevel)
+{
+    // The odp file contains an "Octagon Bevel" shape. Such has shading not in 
commands H,I,J,K
+    // but shading is generated in ctor of EnhancedCustomShape2d from the Type 
value.
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"tdf109169_OctagonBevel.odt";
+
+    // Export to docx had not written a:fill or a:stroke attributes at all.
+    loadAndSave(aURL, "Office Open XML Text");
+
+    // Verify the markup:
+    std::unique_ptr<SvStream> pStream = parseExportStream(getTempFile(), 
"word/document.xml");
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+    // File should have six subpaths, one with stroke and five with fill
+    assertXPath(pXmlDoc, "//a:pathLst/a:path[1]", "stroke", "0");
+    assertXPath(pXmlDoc, "//a:pathLst/a:path[2]", "fill", "darkenLess");
+    assertXPath(pXmlDoc, "//a:pathLst/a:path[3]", "fill", "darken");
+    assertXPath(pXmlDoc, "//a:pathLst/a:path[4]", "fill", "darken");
+    assertXPath(pXmlDoc, "//a:pathLst/a:path[5]", "fill", "lightenLess");
+    assertXPath(pXmlDoc, "//a:pathLst/a:path[6]", "fill", "lighten");
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testFaultyPathCommandsAWT)
 {
     // The odp file contains shapes whose path starts with command A, W, T or 
L. That is a faulty
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index c2bdf39042a4..2a11fa507959 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -3898,6 +3898,7 @@ bool DrawingML::WriteCustomGeometry(
     sal_Int32 nPairIndex = 0; // index over "Coordinates"
     sal_Int32 nPathSizeIndex = 0; // index over "SubViewSize"
     sal_Int32 nSubpathStartIndex(0); // index over "Segments"
+    sal_Int32 nSubPathIndex(0); // serial number of current subpath
     do
     {
         bool bOK(true); // catch faulty paths were commands do not correspond 
to points
@@ -3920,6 +3921,19 @@ bool DrawingML::WriteCustomGeometry(
         else if (HasCommandInSubPath(LIGHTENLESS, nSubpathStartIndex, 
nNextNcommandIndex - 1,
                                      aSegments))
             sFill = "lightenLess";
+        else
+        {
+            // shading info might be in object type, e.g. "Octagon Bevel".
+            sal_Int32 
nLuminanceChange(aCustomShape2d.GetLuminanceChange(nSubPathIndex));
+            if (nLuminanceChange <= -40)
+                sFill = "darken";
+            else if (nLuminanceChange <= -10)
+                sFill = "darkenLess";
+            else if (nLuminanceChange >= 40)
+                sFill = "lighten";
+            else if (nLuminanceChange >= 10)
+                sFill = "lightenLess";
+        }
         // NOSTROKE
         std::optional<OString> sStroke;
         if (HasCommandInSubPath(NOSTROKE, nSubpathStartIndex, 
nNextNcommandIndex - 1, aSegments))
@@ -3964,6 +3978,7 @@ bool DrawingML::WriteCustomGeometry(
         // step forward to next subpath
         nSubpathStartIndex = nNextNcommandIndex + 1;
         nPathSizeIndex++;
+        nSubPathIndex++;
     } while (nSubpathStartIndex < aSegments.getLength());
 
     mpFS->endElementNS(XML_a, XML_pathLst);
commit d0e60c6f815de9b066c0697aabec87a776952f51
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Mon Apr 18 19:31:26 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:01 2022 +0200

    tdf#148501 color shades only for filled PolyPolygons
    
    For shading parts of a shape not of Type 'ooxml-*', ColorData is used,
    introduced about 2005. For 'mso_spt*' shapes they are set directly,
    for others they are encoded as 'col-********' into the Type value.
    During OOo time two changes were made, resulting in the bugs, that
    colors are assigned to wrong segments and that shadings are too dark.
    More details are in the bug report.
    
    With this patch the colors are assigned to the correct segments again.
    The too dark colors are visible in our preset shapes 'Octagon Bevel'.
    The shape 'Diamond Bevel' with corrected color assignment is also
    affected. Both need new ColorData. Since it is important for
    Libreoffice to have good compatibility with OOXML, I have decided to
    use only the four shading values available in OOXML. In the long run,
    these shapes should be replaced by ones that contain the shading
    information inside the <enhanced-path> element.
    
    Change-Id: I4b8323c45bf702fc371d6e6c82dd9102d0fd9929
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133132
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133153

diff --git a/svx/qa/unit/customshapes.cxx b/svx/qa/unit/customshapes.cxx
index ca6ece320afa..690d6c02aa45 100644
--- a/svx/qa/unit/customshapes.cxx
+++ b/svx/qa/unit/customshapes.cxx
@@ -18,6 +18,7 @@
 #include <basegfx/polygon/b2dpolypolygon.hxx>
 #include <basegfx/polygon/b2dpolygon.hxx>
 #include <basegfx/point/b2dpoint.hxx>
+#include <comphelper/propertyvalue.hxx>
 #include <sfx2/request.hxx>
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/viewsh.hxx>
@@ -31,12 +32,15 @@
 #include <svx/unoapi.hxx>
 #include <unotools/mediadescriptor.hxx>
 #include <unotools/tempfile.hxx>
+#include <vcl/filter/PngImageReader.hxx>
+#include <vcl/BitmapReadAccess.hxx>
 
 #include <cppunit/TestAssert.h>
 
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
 #include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/drawing/GraphicExportFilter.hpp>
 #include <com/sun/star/awt/Rectangle.hpp>
 #include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/frame/XStorable.hpp>
@@ -1156,6 +1160,60 @@ CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf136176)
         }
     }
 }
+
+CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf148501_OctagonBevel)
+{
+    // The document contains a shape "Octagon Bevel". It should use shadings 
40%, 20%, -20%, -40%
+    // from left-top to bottom-right. The test examines actual color, not the 
geometry.
+    // Load document
+    OUString aURL = m_directories.getURLFromSrc(sDataDirectory) + 
"tdf148501_OctagonBevel.odp";
+    mxComponent = loadFromDesktop(aURL, 
"com.sun.star.presentation.PresentationDocument");
+
+    // Generate bitmap from shape
+    uno::Reference<drawing::XShape> xShape = getShape(0);
+    utl::TempFile aTempFile;
+    aTempFile.EnableKillingFile();
+
+    uno::Reference<uno::XComponentContext> xContext = getComponentContext();
+    CPPUNIT_ASSERT(xContext.is());
+    uno::Reference<drawing::XGraphicExportFilter> xGraphicExporter
+        = drawing::GraphicExportFilter::create(xContext);
+
+    uno::Sequence<beans::PropertyValue> aDescriptor{
+        comphelper::makePropertyValue("URL", aTempFile.GetURL()),
+        comphelper::makePropertyValue("FilterName", OUString("PNG"))
+    };
+
+    uno::Reference<lang::XComponent> xSourceDocument(xShape, 
uno::UNO_QUERY_THROW);
+    xGraphicExporter->setSourceDocument(xSourceDocument);
+    xGraphicExporter->filter(aDescriptor);
+
+    // Read bitmap and test color
+    // expected in order top-left, top, top-right, right, bottom-right:
+    // RGB(165|195|266), RGB(139|176|217), RGB(91|127|166), RGB(68|95|124), 
RGB(68|95|124)
+    // Without applied patch the colors were:
+    // RGB(193|214,236), RGB(193|214,236), RGB(80|111|145), RGB(23|32|41), 
RGB(193|214|236)
+    // So we test segments top, right and bottom-right.
+    SvFileStream aFileStream(aTempFile.GetURL(), StreamMode::READ);
+    vcl::PngImageReader aPNGReader(aFileStream);
+    BitmapEx aBMPEx = aPNGReader.read();
+    Bitmap aBMP = aBMPEx.GetBitmap();
+    Bitmap::ScopedReadAccess pRead(aBMP);
+    Size aSize = aBMP.GetSizePixel();
+
+    // GetColor(Y,X). The chosen threshold for the ColorDistance can be 
adapted if necessary.
+    Color aActualColor = pRead->GetColor(aSize.Height() * 0.17, aSize.Width() 
* 0.5); // top
+    Color aExpectedColor(139, 176, 217);
+    sal_uInt16 nColorDistance = aExpectedColor.GetColorError(aActualColor);
+    CPPUNIT_ASSERT_LESS(sal_uInt16(6), nColorDistance);
+    aActualColor = pRead->GetColor(aSize.Height() * 0.5, aSize.Width() * 
0.83); // right
+    aExpectedColor = Color(68, 95, 124); // same for right and bottom-right
+    nColorDistance = aExpectedColor.GetColorError(aActualColor);
+    CPPUNIT_ASSERT_LESS(sal_uInt16(6), nColorDistance);
+    aActualColor = pRead->GetColor(aSize.Height() * 0.75, aSize.Width() * 
0.75); // bottom-right
+    nColorDistance = aExpectedColor.GetColorError(aActualColor);
+    CPPUNIT_ASSERT_LESS(sal_uInt16(6), nColorDistance);
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/qa/unit/data/tdf148501_OctagonBevel.odp 
b/svx/qa/unit/data/tdf148501_OctagonBevel.odp
new file mode 100644
index 000000000000..9dafaf7c2624
Binary files /dev/null and b/svx/qa/unit/data/tdf148501_OctagonBevel.odp differ
diff --git a/svx/source/customshapes/EnhancedCustomShape2d.cxx 
b/svx/source/customshapes/EnhancedCustomShape2d.cxx
index 1f05a3782a7c..14f054ddce73 100644
--- a/svx/source/customshapes/EnhancedCustomShape2d.cxx
+++ b/svx/source/customshapes/EnhancedCustomShape2d.cxx
@@ -777,8 +777,19 @@ 
EnhancedCustomShape2d::EnhancedCustomShape2d(SdrObjCustomShape& rSdrObjCustomSha
         case mso_sptSmileyFace :                nColorData = 0x20e00000; break;
         case mso_sptNil :
         {
-            if( sShapeType.getLength() > 4 &&
-                sShapeType.match( "col-" ))
+            // Because calculation method has changed in #i102797 original 
color encoding for
+            // Octagon Bevel and Diamond Bevel can no longer be used. We keep 
the color coding
+            // only for self-created shapes, as authors may have already 
considered the change.
+            // We use ColorData compatible to OOXML.
+            if (sShapeType == "col-60da8460") // Octagon Bevel
+            {
+                nColorData = 0x60ecc240;
+            }
+            else if (sShapeType == "col-502ad400") // Diamond Bevel
+            {
+                nColorData = 0x502ce400;
+            }
+            else if (sShapeType.getLength() > 4 && sShapeType.match( "col-" ))
             {
                 nColorData = sShapeType.copy( 4 ).toUInt32( 16 );
             }
@@ -2755,6 +2766,9 @@ void EnhancedCustomShape2d::AdaptObjColor(
         return;
 
     const drawing::FillStyle eFillStyle = 
rObj.GetMergedItem(XATTR_FILLSTYLE).GetValue();
+    if (eFillStyle == drawing::FillStyle_NONE)
+        return;
+
     switch( eFillStyle )
     {
         default:
commit 19cc327fa6cf91e123be5b97267202fdb08d0aa4
Author:     Xisco Fauli <xiscofa...@libreoffice.org>
AuthorDate: Tue Apr 26 00:00:18 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:01 2022 +0200

    tdf#147586: Initialize mbBulletColorFollowText to false
    
    Otherwise, once it's set to true, it's never reset
    
    Change-Id: Ie8a752da4162775f40c2f84f480e6a103eb55942
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133422
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    (cherry picked from commit a0bae88a9cd47185a71cbfd4c86bbd86ae44d30e)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133404
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/oox/source/drawingml/textparagraphproperties.cxx 
b/oox/source/drawingml/textparagraphproperties.cxx
index 70f1ac0c937b..07624e83d1fa 100644
--- a/oox/source/drawingml/textparagraphproperties.cxx
+++ b/oox/source/drawingml/textparagraphproperties.cxx
@@ -57,7 +57,8 @@ using ::com::sun::star::awt::FontDescriptor;
 namespace oox::drawingml {
 
 BulletList::BulletList( )
-: maBulletColorPtr( std::make_shared<Color>() )
+: maBulletColorPtr( std::make_shared<Color>() ),
+  mbBulletColorFollowText ( false )
 {
 }
 
diff --git a/sd/qa/unit/data/pptx/tdf147586.pptx 
b/sd/qa/unit/data/pptx/tdf147586.pptx
new file mode 100644
index 000000000000..723facf82071
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf147586.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml3.cxx 
b/sd/qa/unit/export-tests-ooxml3.cxx
index 96642cdc73ec..84366e1be9f3 100644
--- a/sd/qa/unit/export-tests-ooxml3.cxx
+++ b/sd/qa/unit/export-tests-ooxml3.cxx
@@ -55,6 +55,7 @@ class SdOOXMLExportTest3 : public SdModelTestBaseXML
 public:
     void testTdf129430();
     void testTdf114848();
+    void testTdf147586();
     void testTdf68759();
     void testTdf127901();
     void testTdf48735();
@@ -135,6 +136,7 @@ public:
 
     CPPUNIT_TEST(testTdf129430);
     CPPUNIT_TEST(testTdf114848);
+    CPPUNIT_TEST(testTdf147586);
     CPPUNIT_TEST(testTdf68759);
     CPPUNIT_TEST(testTdf127901);
     CPPUNIT_TEST(testTdf48735);
@@ -246,6 +248,26 @@ void SdOOXMLExportTest3::testTdf114848()
                 "1f497d");
 }
 
+void SdOOXMLExportTest3::testTdf147586()
+{
+    ::sd::DrawDocShellRef xDocShRef
+        = 
loadURL(m_directories.getURLFromSrc(u"sd/qa/unit/data/pptx/tdf147586.pptx"), 
PPTX);
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+    xDocShRef->DoClose();
+
+    xmlDocUniquePtr pXmlDocContent = parseExport(tempFile, 
"ppt/slides/slide1.xml");
+    // Without the fix in place, this test would have failed with
+    // - Expected: 227fc7
+    // - Actual  : 4f4f4f
+    assertXPath(pXmlDocContent,
+                
"/p:sld/p:cSld/p:spTree/p:sp[1]/p:txBody/a:p[1]/a:pPr/a:buClr/a:srgbClr", "val",
+                "227fc7");
+    assertXPath(pXmlDocContent,
+                
"/p:sld/p:cSld/p:spTree/p:sp[1]/p:txBody/a:p[2]/a:pPr/a:buClr/a:srgbClr", "val",
+                "227fc7");
+}
+
 void SdOOXMLExportTest3::testTdf68759()
 {
     ::sd::DrawDocShellRef xDocShRef
commit 8c5238c7a80e2be45a326afd0b751c9aa00f51bd
Author:     Vasily Melenchuk <vasily.melenc...@cib.de>
AuthorDate: Fri Apr 1 16:35:40 2022 +0300
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:01 2022 +0200

    tdf#139948: docx and rtf import: emulate border in between
    
    Writer does not support border in between available in all MS
    formats. Since this feature is missing in core it will be
    better to emulate it with top borders than to ignore it
    completely.
    
    Change-Id: I4e5a99cde5908066c4bb483136cfe9a1316df53c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132429
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit e3a996bf72a16f5b22e6ff021745af5cec70a632)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132594
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf139948.docx 
b/sw/qa/extras/ooxmlexport/data/tdf139948.docx
new file mode 100644
index 000000000000..1b3f7df00031
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf139948.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index d0e3c151282b..b72a470978cc 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -327,6 +327,32 @@ DECLARE_OOXMLEXPORT_TEST(testTdf81507, "tdf81507.docx")
     xmlXPathFreeObject(pXmlObj);
 }
 
+DECLARE_OOXMLEXPORT_TEST(testTdf139948, "tdf139948.docx")
+{
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(1, "No border"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(2, "Border below"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(88),
+        getProperty<table::BorderLine2>(getParagraph(3, "Borders below and 
above"), "TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(88),
+        getProperty<table::BorderLine2>(getParagraph(4, "Border above"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(5, "No border"), 
"TopBorder").LineWidth);
+
+
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(1), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(2), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(3), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(4), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(5), 
"BottomBorder").LineWidth);
+}
+
 DECLARE_OOXMLEXPORT_TEST(testTdf144563, "tdf144563.docx")
 {
     uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, 
uno::UNO_QUERY);
diff --git a/sw/qa/extras/rtfexport/data/tdf139948.rtf 
b/sw/qa/extras/rtfexport/data/tdf139948.rtf
new file mode 100644
index 000000000000..0b601a764adf
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf139948.rtf
@@ -0,0 +1,8 @@
+{\rtf1\ansi
+No border\par
+\pard\brdrbtw\brdrs\brdrw50 
+Border below\par
+Borders below and above\par
+Border above\par
+\pard No border\par
+}
\ No newline at end of file
diff --git a/sw/qa/extras/rtfexport/rtfexport4.cxx 
b/sw/qa/extras/rtfexport/rtfexport4.cxx
index 36c908c222bd..98bf1042b212 100644
--- a/sw/qa/extras/rtfexport/rtfexport4.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport4.cxx
@@ -603,6 +603,38 @@ CPPUNIT_TEST_FIXTURE(Test, testClearingBreak)
     verify();
 }
 
+DECLARE_RTFEXPORT_TEST(testTdf139948, "tdf139948.rtf")
+{
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(1, "No border"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(2, "Border below"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(88),
+        getProperty<table::BorderLine2>(getParagraph(3, "Borders below and 
above"), "TopBorder")
+            .LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(88),
+        getProperty<table::BorderLine2>(getParagraph(4, "Border above"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(5, "No border"), 
"TopBorder").LineWidth);
+
+    // And let's ensure that there are no other horizontal borders
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(1), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(2), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(3), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(4), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(5), 
"BottomBorder").LineWidth);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index 2ae843c9834f..59215a9d6aa5 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -1492,7 +1492,16 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
                 eBorderDistId = PROP_RIGHT_BORDER_DISTANCE ;
                 break;
             case NS_ooxml::LN_CT_PBdr_between:
-                //not supported
+                if (m_pImpl->handlePreviousParagraphBorderInBetween())
+                {
+                    // If previous paragraph also had border in between 
property
+                    // then it is possible to emulate this border as top border
+                    // for current paragraph
+                    eBorderId = PROP_TOP_BORDER;
+                    eBorderDistId = PROP_TOP_BORDER_DISTANCE;
+                }
+                // Since there are borders in between, each paragraph will 
have own borders. No more joining
+                rContext->Insert(PROP_PARA_CONNECT_BORDERS, 
uno::makeAny(false));
                 break;
             default:;
             }
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 1e9d8f55c587..3edffc00121f 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -8410,6 +8410,31 @@ void DomainMapper_Impl::commentProps(const OUString& 
sId, const CommentPropertie
     m_aCommentProps[sId] = rProps;
 }
 
+
+bool DomainMapper_Impl::handlePreviousParagraphBorderInBetween() const
+{
+    if (!m_xPreviousParagraph.is())
+        return false;
+
+    // Connected borders ("ParaIsConnectBorder") are always on by default
+    // and never changed by DomainMapper. Except one case when border in
+    // between is used. So this is not the best, but easiest way to check
+    // is previous paragraph has border in between.
+    bool bConnectBorders = true;
+    
m_xPreviousParagraph->getPropertyValue(getPropertyName(PROP_PARA_CONNECT_BORDERS))
 >>= bConnectBorders;
+
+    if (bConnectBorders)
+        return false;
+
+    // Previous paragraph has border in between. Current one also has (since 
this
+    // method is called). So current paragraph will get border above, but
+    // also need to ensure, that no unexpected bottom border are remaining in 
previous
+    // paragraph: since ParaIsConnectBorder=false it will be displayed in 
unexpected way.
+    
m_xPreviousParagraph->setPropertyValue(getPropertyName(PROP_BOTTOM_BORDER), 
uno::makeAny(table::BorderLine2()));
+
+    return true;
+}
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index fcd410c6ce9d..3b4602f252b5 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -1153,6 +1153,9 @@ public:
     /// start/end node.
     void ClearPreviousParagraph();
 
+    /// Check if previous paragraph has borders in between and do the border 
magic to it if so
+    bool handlePreviousParagraphBorderInBetween() const;
+
     /// Handle redline text portions in a frame, footnotes and redlines:
     /// store their data, and create them after frame creation or 
footnote/endnote copying
     bool m_bIsActualParagraphFramed;
diff --git a/writerfilter/source/dmapper/PropertyIds.cxx 
b/writerfilter/source/dmapper/PropertyIds.cxx
index b339a83f8ae6..1189bc0b1410 100644
--- a/writerfilter/source/dmapper/PropertyIds.cxx
+++ b/writerfilter/source/dmapper/PropertyIds.cxx
@@ -364,6 +364,7 @@ OUString getPropertyName( PropertyIds eId )
             sName = "RtlGutter";
             break;
         case PROP_CURSOR_NOT_IGNORE_TABLES_IN_HF: sName = 
"CursorNotIgnoreTables"; break;
+        case PROP_PARA_CONNECT_BORDERS: sName= "ParaIsConnectBorder"; break;
     }
     assert(sName.getLength()>0);
     return sName;
diff --git a/writerfilter/source/dmapper/PropertyIds.hxx 
b/writerfilter/source/dmapper/PropertyIds.hxx
index b09170d2da36..7b6fe9a05275 100644
--- a/writerfilter/source/dmapper/PropertyIds.hxx
+++ b/writerfilter/source/dmapper/PropertyIds.hxx
@@ -361,6 +361,7 @@ enum PropertyIds
         ,PROP_GUTTER_MARGIN
         ,PROP_RTL_GUTTER
         ,PROP_CURSOR_NOT_IGNORE_TABLES_IN_HF
+        ,PROP_PARA_CONNECT_BORDERS
     };
 
 //Returns the UNO string equivalent to eId.
diff --git a/writerfilter/source/rtftok/rtfdispatchflag.cxx 
b/writerfilter/source/rtftok/rtfdispatchflag.cxx
index 3aee1e1dda75..9d891384360c 100644
--- a/writerfilter/source/rtftok/rtfdispatchflag.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchflag.cxx
@@ -672,6 +672,7 @@ RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
         case RTFKeyword::BRDRL:
         case RTFKeyword::BRDRB:
         case RTFKeyword::BRDRR:
+        case RTFKeyword::BRDRBTW:
         {
             RTFSprms aAttributes;
             RTFSprms aSprms;
@@ -690,6 +691,9 @@ RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
                 case RTFKeyword::BRDRR:
                     nParam = getParagraphBorder(3);
                     break;
+                case RTFKeyword::BRDRBTW:
+                    nParam = getParagraphBorder(4);
+                    break;
                 default:
                     break;
             }
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx 
b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 9e77cbf4602e..0aa22aa96f55 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -81,8 +81,9 @@ namespace writerfilter::rtftok
 {
 Id getParagraphBorder(sal_uInt32 nIndex)
 {
-    static const Id aBorderIds[] = { NS_ooxml::LN_CT_PBdr_top, 
NS_ooxml::LN_CT_PBdr_left,
-                                     NS_ooxml::LN_CT_PBdr_bottom, 
NS_ooxml::LN_CT_PBdr_right };
+    static const Id aBorderIds[]
+        = { NS_ooxml::LN_CT_PBdr_top, NS_ooxml::LN_CT_PBdr_left, 
NS_ooxml::LN_CT_PBdr_bottom,
+            NS_ooxml::LN_CT_PBdr_right, NS_ooxml::LN_CT_PBdr_between };
 
     return aBorderIds[nIndex];
 }
commit 9e7ce733b83efd9780b8847baa882e3a5377e900
Author:     Julien Nabet <serval2...@yahoo.fr>
AuthorDate: Sat Apr 23 18:17:57 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:01 2022 +0200

    tdf#136429: use FieldUnit value for min/max of some fields of numbering 
dialog
    
    Change-Id: I01428703a7bdb2090fd145e5373c37aff0d386ac
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133348
    (cherry picked from commit 176021427fece6363df56022b63813e93505fdc2)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133399
    Tested-by: Jenkins
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/cui/source/tabpages/numpages.cxx b/cui/source/tabpages/numpages.cxx
index ade080a1436a..7d2683ab3ed4 100644
--- a/cui/source/tabpages/numpages.cxx
+++ b/cui/source/tabpages/numpages.cxx
@@ -29,6 +29,7 @@
 #include <svl/eitem.hxx>
 #include <vcl/svapp.hxx>
 #include <svx/colorbox.hxx>
+#include <svx/dlgutil.hxx>
 #include <svx/strarray.hxx>
 #include <svx/gallery.hxx>
 #include <editeng/brushitem.hxx>
@@ -2506,6 +2507,13 @@ 
SvxNumPositionTabPage::SvxNumPositionTabPage(weld::Container* pPage, weld::Dialo
 {
     SetExchangeSupport();
 
+    // set metric
+    FieldUnit eFUnit = GetModuleFieldUnit(rSet);
+
+    SetFieldUnit( *m_xDistBorderMF, eFUnit );
+    SetFieldUnit( *m_xIndentMF, eFUnit );
+    SetFieldUnit( *m_xDistNumMF, eFUnit );
+
     m_xAlignedAtMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE);
     m_xListtabMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE);
     m_xIndentAtMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE);
commit 3c5646e3468c3d0bfbbd5b6b208e97c3864010dc
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Fri Apr 22 13:23:55 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:01 2022 +0200

    tdf#147453 sw: disable Delete Table functions on tracked deletions
    
    In Show Changes mode, disable "Delete Selected Rows" icons
    and the same menu options in the following cases:
    
    - no table selection, but the text cursor in a deleted table row;
    
    - with table selection, all selected cells in deleted table rows.
    
    Disable also "Deleted Selected Columns" and "Delete Table"
    icons and the same menu options, when the cursor is there
    in a deleted table.
    
    Follow-up to commit c4f6fee3bea0d8618b5815e60304ff9359ccd21c
    "tdf#147435 sw: enable Accept Change for table selection".
    
    Change-Id: Ic6781ccee794c7458e6979f2e981840339cd3883
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133320
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit 0204c00f241313e1d292b4c3ea117d42af7dec69)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133292
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/source/uibase/shells/tabsh.cxx 
b/sw/source/uibase/shells/tabsh.cxx
index 7798b6c0da9c..84a090b111fd 100644
--- a/sw/source/uibase/shells/tabsh.cxx
+++ b/sw/source/uibase/shells/tabsh.cxx
@@ -55,6 +55,7 @@
 #include <fmtfsize.hxx>
 #include <swmodule.hxx>
 #include <wrtsh.hxx>
+#include <rootfrm.hxx>
 #include <wview.hxx>
 #include <frmatr.hxx>
 #include <uitool.hxx>
@@ -445,6 +446,43 @@ static void lcl_TabGetMaxLineWidth(const SvxBorderLine* 
pBorderLine, SvxBorderLi
     rBorderLine.SetColor(pBorderLine->GetColor());
 }
 
+static bool lcl_BoxesInDeletedRows(SwWrtShell &rSh, const SwSelBoxes& rBoxes)
+{
+    // cursor and selection are there only in deleted rows in Show Changes mode
+    if ( rSh.GetLayout()->IsHideRedlines() )
+        return false;
+
+    // not selected or all selected rows are deleted
+    bool bRet = true;
+    SwRedlineTable::size_type nRedlinePos = 0;
+    if ( rBoxes.empty() )
+        bRet = 
rSh.GetCursor()->GetNode().GetTableBox()->GetUpper()->IsDeleted(nRedlinePos);
+    else
+    {
+        tools::Long nBoxes = rBoxes.size();
+        SwTableLine* pPrevLine = nullptr;
+        for ( tools::Long i = 0; i < nBoxes; i++ )
+        {
+            SwTableLine* pLine = rBoxes[i]->GetUpper();
+            if ( pLine != pPrevLine )
+                bRet &= pLine->IsDeleted(nRedlinePos);
+            pPrevLine = pLine;
+        }
+    }
+
+    return bRet;
+}
+
+static bool lcl_CursorInDeletedTable(SwWrtShell &rSh)
+{
+    // cursor and selection are there only in deleted table in Show Changes 
mode
+    if ( rSh.GetLayout()->IsHideRedlines() )
+        return false;
+
+    SwTableNode* pTableNd = 
rSh.GetCursor()->GetPoint()->nNode.GetNode().FindTableNode();
+    return pTableNd && pTableNd->GetTable().IsDeleted();
+}
+
 void SwTableShell::Execute(SfxRequest &rReq)
 {
     const SfxItemSet* pArgs = rReq.GetArgs();
@@ -1381,7 +1419,7 @@ void SwTableShell::GetState(SfxItemSet &rSet)
                 {
                     SwSelBoxes aBoxes;
                     ::GetTableSel( rSh, aBoxes, SwTableSearchType::Row );
-                    if( ::HasProtectedCells( aBoxes ))
+                    if( ::HasProtectedCells( aBoxes ) || 
lcl_BoxesInDeletedRows( rSh, aBoxes ) )
                         rSet.DisableItem( nSlot );
                 }
                 break;
@@ -1389,10 +1427,14 @@ void SwTableShell::GetState(SfxItemSet &rSet)
                 {
                     SwSelBoxes aBoxes;
                     ::GetTableSel( rSh, aBoxes, SwTableSearchType::Col );
-                    if( ::HasProtectedCells( aBoxes ))
+                    if( ::HasProtectedCells( aBoxes ) || 
lcl_CursorInDeletedTable( rSh ) )
                         rSet.DisableItem( nSlot );
                 }
                 break;
+            case FN_TABLE_DELETE_TABLE:
+                if( lcl_CursorInDeletedTable( rSh ) )
+                    rSet.DisableItem( nSlot );
+                break;
 
             case FN_TABLE_UNSET_READ_ONLY_CELLS:
                 // disable in readonly sections, but enable in protected cells
commit e590b2ad63eaf35b3377815c922bce25b15c238c
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Mon Apr 25 12:34:53 2022 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:01 2022 +0200

    tdf#148654 stop playing sound with presentation ends
    
    Change-Id: I74aa4cd966b6966f7826d241fcf9bb9d64955464
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133394
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sd/source/ui/slideshow/slideshowimpl.cxx 
b/sd/source/ui/slideshow/slideshowimpl.cxx
index 0c775d275913..ecb9663ed8ba 100644
--- a/sd/source/ui/slideshow/slideshowimpl.cxx
+++ b/sd/source/ui/slideshow/slideshowimpl.cxx
@@ -1350,6 +1350,8 @@ IMPL_LINK_NOARG(SlideshowImpl, endPresentationHdl, void*, 
void)
 {
     mnEndShowEvent = nullptr;
 
+    stopSound();
+
     if( mxPresentation.is() )
         mxPresentation->end();
 }
commit ac13cd2323fcd0fe1d84ed9c2ec749991d284358
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Fri Apr 22 20:34:32 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:00 2022 +0200

    tdf#141391 sw: don't paste as nested table in first cell paragraph
    
    Paste table content overwrote cells of the row(s) only if the text
    cursor was at the beginning of the table cell, otherwise the table
    cells on the clipboard were inserted as a nested table.
    
    This was a UX regression from commit 
7600a2942ce2b9dac66836105bed6620d55abec2
    "fdo#37156 insert table copy as nested table in non-starting cell position"
    especially when the user clicked not exactly at the beginning of a
    cell, which containing a 1-line text or data.
    
    Since commit 1e278d1d0cfb1d5375195aa764739f00633f21e8
    "tdf#37156 Writer menu: Paste as Nested table" it's possible to
    force nesting (but not overwriting yet), this commit revert partially
    commit 7600a2942ce2b9dac66836105bed6620d55abec2: if the text cursor
    is there in the first paragraph of the cell, Paste table content
    overwrites the row, not embedding a nested table in the cell
    at the cursor position. This change results also better interoperability
    with the existing document editors.
    
    Note: table and text selection were checked with the change, too.
    
    Details:
    
    Heuristics to allow copying table rows or nesting tables
    without using Edit -> Paste Special -> Paste as Nested Table:
    
    At "table selection" (i.e. when cell(s) completely selected),
    or if the text selection starts in the first paragraph, or if
    there is no selection and the text cursor is there in the first
    paragraph, overwrite content of the cell(s). Otherwise insert
    a nested table, i.e. if nothing selected and the cursor is not
    in the first paragraph, or the selected text doesn't contain
    the first paragraph of the cell.
    
    Change-Id: I7746c6a464123bef6fb7dbff415ff0414e48365d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133377
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit b97116791047f89b768ab4aa8126e543df826be3)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133402
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx 
b/sw/qa/extras/uiwriter/uiwriter3.cxx
index 03b2bc92b307..26ca4e8db96f 100644
--- a/sw/qa/extras/uiwriter/uiwriter3.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter3.cxx
@@ -2176,6 +2176,97 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf148345)
     assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 2);
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf141391)
+{
+    // table insertion in the first paragraph of the cell
+    // overwrites the row content, instead of inserting a nested table
+
+    // load a 2-row table
+    SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf116789.fodt");
+    CPPUNIT_ASSERT(pDoc);
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+
+    // select the table, and copy it into at paragraph start of cell "A2"
+
+    dispatchCommand(mxComponent, ".uno:SelectTable", {});
+    dispatchCommand(mxComponent, ".uno:Copy", {});
+    // remove the selection and positionate the cursor at beginning of A2
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    dispatchCommand(mxComponent, ".uno:Paste", {});
+    Scheduler::ProcessEventsToIdle();
+
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+    // 3-row, overwriting cells of the second row and inserting a new row
+    // with the 2-row clipboard table content
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 3);
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/txt/Text", 
"Portion", "hello");
+
+    // Undo
+
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    // 2 rows again, no copied text content
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 2);
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/Text", 0);
+
+    // insert the 2-row table into the second paragraph of cell "A2" as a 
nested table
+    // For this it's enough to positionate the text cursor not in the first 
paragraph
+
+    // insert some text and an empty paragraph
+    pWrtShell->Insert("Some text...");
+    pWrtShell->SplitNode();
+    Scheduler::ProcessEventsToIdle();
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 2);
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/txt", 2);
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/txt[1]/Text", 
"Portion",
+                "Some text...");
+    // the empty paragraph in A2
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/txt[2]/Text", 
0);
+
+    // insert the table, as a nested one in cell "A2"
+    dispatchCommand(mxComponent, ".uno:Paste", {});
+    Scheduler::ProcessEventsToIdle();
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 2);
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/tab", 1);
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/tab/row", 2);
+
+    // Undo
+
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+    Scheduler::ProcessEventsToIdle();
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    // 2 rows again, no copied text content
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 2);
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/txt[1]/Text", 
"Portion",
+                "Some text...");
+
+    // copy the 2-row table into the fist paragraph of cell "A2",
+    // but not at paragraph start (changed behaviour)
+
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    pWrtShell->Insert("and some text again in the first paragraph to be 
sure...");
+    dispatchCommand(mxComponent, ".uno:Paste", {});
+    Scheduler::ProcessEventsToIdle();
+
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+
+    // 3-row, overwriting cells of the second row and inserting a new row
+    // with the 2-row clipboard table content
+
+    // This was 2 (nested table)
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row", 3);
+    // This was "Some text..." with a nested table
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[2]/cell[1]/txt/Text", 
"Portion", "hello");
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf135014)
 {
     createSwDoc();
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index 7a57c5f4e709..b7a12a828b90 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -966,11 +966,15 @@ bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable)
             if (pSrcNd && nullptr != pDestNd &&
                 // not a forced nested table insertion
                 !bNestedTable &&
-                // are we at the beginning of the cell? (if not, we will 
insert a nested table)
-                // first paragraph of the cell?
-                rPaM.GetNode().GetIndex() == 
rPaM.GetNode().FindTableBoxStartNode()->GetIndex()+1 &&
-                // beginning of the paragraph?
-                !rPaM.GetPoint()->nContent.GetIndex())
+                // Heuristics to allow copying table rows or nesting tables 
without
+                // using Edit -> Paste Special -> Paste as Nested Table:
+                // Using table cursor, or if the text selection starts in the
+                // first paragraph, or if there is no selection and the text 
cursor
+                // is there in the first paragraph, overwrite content of the 
cell(s)
+                // (else insert a nested table later, i.e. if nothing selected 
and
+                // the cursor is not in the first paragraph, or the selected 
text
+                // doesn't contain the first paragraph of the cell)
+                rPaM.GetNode().GetIndex() == 
rPaM.GetNode().FindTableBoxStartNode()->GetIndex() + 1)
             {
                 SwPosition aDestPos( *rPaM.GetPoint() );
 
commit 2b223e0a1ed529b95f095725b356f5fa91551209
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Mon Apr 25 15:55:31 2022 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:00 2022 +0200

    Resolves: tdf#141441 get and set selected entry when "unfrozen"
    
    Change-Id: I4229460fb27ae3dc133c0f6a53c7792a87bf4db3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133396
    Tested-by: Jenkins
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/svtools/source/control/ctrlbox.cxx 
b/svtools/source/control/ctrlbox.cxx
index 72b995d5ad83..0b1c67e31980 100644
--- a/svtools/source/control/ctrlbox.cxx
+++ b/svtools/source/control/ctrlbox.cxx
@@ -844,9 +844,10 @@ FontStyleBox::FontStyleBox(std::unique_ptr<weld::ComboBox> 
p)
 
 void FontStyleBox::Fill( const OUString& rName, const FontList* pList )
 {
-    m_xComboBox->freeze();
     OUString aOldText = m_xComboBox->get_active_text();
     int nPos = m_xComboBox->get_active();
+
+    m_xComboBox->freeze();
     m_xComboBox->clear();
 
     // does a font with this name already exist?
@@ -949,19 +950,6 @@ void FontStyleBox::Fill( const OUString& rName, const 
FontList* pList )
             if ( bNormal || bItalic || bBold )
                 m_xComboBox->append_text(pList->GetBoldItalicStr());
         }
-        if (!aOldText.isEmpty())
-        {
-            int nFound = m_xComboBox->find_text(aOldText);
-            if (nFound != -1)
-                m_xComboBox->set_active(nFound);
-            else
-            {
-                if (nPos >= m_xComboBox->get_count())
-                    m_xComboBox->set_active(0);
-                else
-                    m_xComboBox->set_active(nPos);
-            }
-        }
     }
     else
     {
@@ -970,7 +958,16 @@ void FontStyleBox::Fill( const OUString& rName, const 
FontList* pList )
         m_xComboBox->append_text(pList->GetItalicStr());
         m_xComboBox->append_text(pList->GetBoldStr());
         m_xComboBox->append_text(pList->GetBoldItalicStr());
-        if (!aOldText.isEmpty())
+    }
+
+    m_xComboBox->thaw();
+
+    if (!aOldText.isEmpty())
+    {
+        int nFound = m_xComboBox->find_text(aOldText);
+        if (nFound != -1)
+            m_xComboBox->set_active(nFound);
+        else
         {
             if (nPos >= m_xComboBox->get_count())
                 m_xComboBox->set_active(0);
@@ -978,7 +975,6 @@ void FontStyleBox::Fill( const OUString& rName, const 
FontList* pList )
                 m_xComboBox->set_active(nPos);
         }
     }
-    m_xComboBox->thaw();
 }
 
 FontSizeBox::FontSizeBox(std::unique_ptr<weld::ComboBox> p)
commit e9786a1439db437cc378f426c7cb496db20959fd
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Sat Apr 23 21:52:29 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:00 2022 +0200

    Do not start a:path with lnTo in export to OOXML
    
    This is a follow up to commit 2029b2f6dd0109c5892e5ac5640022b31fe42fd2
    
    The commands A, W, T or L of a draw:enhanced-path draw a line from
    current point to start of the arc or end of line, respectivly. If
    there is no current point the path is faulty and behavior is not
    defined in ODF.
    
    LibreOffice is tolerant and makes a move to the start point of the
    arc or to the end point of the line. With this patch we do the same
    now in export to OOXML, so the user gets the same shape geometry as in
    LO. If a path starts with lnTo, MS Office will show nothing.
    
    I wouldn't care about user-created faulty paths, but LO produces such
    faulty path when an EllipseRibbon shape from binary MS Office is
    imported. Even when that will be fixed, we need the fix here, because
    the faulty path had been written to document markup and will be used
    when such document is opened.
    
    Change-Id: Ic52ec3bc78231b26efb592ddadee2e3042fdc065
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133349
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <rb.hensc...@t-online.de>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133370

diff --git a/oox/qa/unit/data/FaultyPathStart.odp 
b/oox/qa/unit/data/FaultyPathStart.odp
new file mode 100644
index 000000000000..219795ffa58b
Binary files /dev/null and b/oox/qa/unit/data/FaultyPathStart.odp differ
diff --git a/oox/qa/unit/export.cxx b/oox/qa/unit/export.cxx
index e104b4effdd7..26d1a0e973bb 100644
--- a/oox/qa/unit/export.cxx
+++ b/oox/qa/unit/export.cxx
@@ -529,6 +529,26 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf147978_subpath)
     assertXPath(pXmlDoc, "//a:pathLst/a:path[4]", "w", "80");
     assertXPath(pXmlDoc, "//a:pathLst/a:path[4]", "h", "80");
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testFaultyPathCommandsAWT)
+{
+    // The odp file contains shapes whose path starts with command A, W, T or 
L. That is a faulty
+    // path. LO is tolerant and renders it so that is makes a moveTo to the 
start point of the arc or
+    // the end of the line respectively. Export to OOXML does the same now and 
writes a moveTo
+    // instead of the normally used lnTo. If a lnTo is written, MS Office 
shows nothing of the shape.
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"FaultyPathStart.odp";
+
+    loadAndSave(aURL, "Impress Office Open XML");
+
+    // Verify the markup:
+    std::unique_ptr<SvStream> pStream = parseExportStream(getTempFile(), 
"ppt/slides/slide1.xml");
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+    // First child of a:path should be a moveTo in all four shapes.
+    assertXPath(pXmlDoc, 
"//p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo");
+    assertXPath(pXmlDoc, 
"//p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo");
+    assertXPath(pXmlDoc, 
"//p:spTree/p:sp[3]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo");
+    assertXPath(pXmlDoc, 
"//p:spTree/p:sp[4]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo");
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 311669bd5cbe..c2bdf39042a4 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -3997,10 +3997,21 @@ bool DrawingML::WriteCustomGeometrySegment(
         {
             if (rnPairIndex >= rPairs.getLength())
                 return false;
-
-            mpFS->startElementNS(XML_a, XML_lnTo);
-            WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d);
-            mpFS->endElementNS(XML_a, XML_lnTo);
+            // LINETO without valid current point is a faulty path. LO is 
tolerant and makes a
+            // moveTo instead. Do the same on export. MS OFFICE requires a 
current point for lnTo,
+            // otherwise it shows nothing of the shape.
+            if (rbCurrentValid)
+            {
+                mpFS->startElementNS(XML_a, XML_lnTo);
+                WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d);
+                mpFS->endElementNS(XML_a, XML_lnTo);
+            }
+            else
+            {
+                mpFS->startElementNS(XML_a, XML_moveTo);
+                WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d);
+                mpFS->endElementNS(XML_a, XML_moveTo);
+            }
             rCustomShape2d.GetParameter(rfCurrentX, rPairs[rnPairIndex].First, 
false, false);
             rCustomShape2d.GetParameter(rfCurrentY, 
rPairs[rnPairIndex].Second, false, false);
             rbCurrentValid = true;
@@ -4063,7 +4074,8 @@ bool DrawingML::WriteCustomGeometrySegment(
             getEllipsePointFromViewAngle(fSx, fSy, fWR, fHR, fCx, fCy, 
fStartAngle);
 
             // write markup for going to start point
-            if (eCommand == ANGLEELLIPSETO)
+            // lnTo requires a valid current point
+            if (eCommand == ANGLEELLIPSETO && rbCurrentValid)
             {
                 mpFS->startElementNS(XML_a, XML_lnTo);
                 mpFS->singleElementNS(XML_a, XML_pt, XML_x, 
OString::number(std::lround(fSx)),
@@ -4126,7 +4138,8 @@ bool DrawingML::WriteCustomGeometrySegment(
             getEllipsePointAndAngleFromRayPoint(fStartAngle, fPx, fPy, fWR, 
fHR, fCx, fCy, fX3,
                                                 fY3);
             // markup for going to start point
-            if (eCommand == ARCTO || eCommand == CLOCKWISEARCTO)
+            // lnTo requires a valid current point.
+            if ((eCommand == ARCTO || eCommand == CLOCKWISEARCTO) && 
rbCurrentValid)
             {
                 mpFS->startElementNS(XML_a, XML_lnTo);
                 mpFS->singleElementNS(XML_a, XML_pt, XML_x, 
OString::number(std::lround(fPx)),
commit d00bcd99a01e09259afa3c2ef17424aa2282a48b
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Mon Apr 25 11:09:07 2022 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 27 13:20:00 2022 +0200

    Extract 'switch' block out of WriteCustomGeometry
    
    This is a follow up to commit 2029b2f6dd0109c5892e5ac5640022b31fe42fd2.
    That commit has increased the line count of WriteCustomGeometry to more
    than 500. This patch splits it to a main part of about 230 lines and
    a new method for the previous 'switch' block of about 300 lines. That
    makes the loops in the main part better readable.
    
    Change-Id: Ied4378f54e7c8dc7965a5b1db15baf0b35f63f59
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132274
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133369

diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index 7fbb015b4ce4..dc01e20f9199 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -201,6 +201,11 @@ protected:
     void WriteSoftEdgeEffect(const 
css::uno::Reference<css::beans::XPropertySet>& rXPropSet);
     void WriteCustomGeometryPoint(const 
css::drawing::EnhancedCustomShapeParameterPair& rParamPair,
                                   const EnhancedCustomShape2d& rCustomShape2d);
+    bool WriteCustomGeometrySegment(
+        const sal_Int16 eCommand, const sal_Int32 nCount,
+        const 
css::uno::Sequence<css::drawing::EnhancedCustomShapeParameterPair>& rPairs,
+        sal_Int32& rnPairIndex, double& rfCurrentX, double& rfCurrentY, bool& 
rbCurrentValid,
+        const EnhancedCustomShape2d& rCustomShape2d);
 
 public:
     DrawingML( ::sax_fastparser::FSHelperPtr pFS, ::oox::core::XmlFilterBase* 
pFB, DocumentType eDocumentType = DOCUMENT_PPTX, DMLTextExport* pTextExport = 
nullptr )
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index d4dbef899b96..311669bd5cbe 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -3951,352 +3951,9 @@ bool DrawingML::WriteCustomGeometry(
             }
             for (sal_Int32 k = 0; k < rSegment.Count && bOK; ++k)
             {
-                switch (rSegment.Command)
-                {
-                    case MOVETO:
-                    {
-                        if (nPairIndex >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            mpFS->startElementNS(XML_a, XML_moveTo);
-                            WriteCustomGeometryPoint(aPairs[nPairIndex], 
aCustomShape2d);
-                            mpFS->endElementNS(XML_a, XML_moveTo);
-                            aCustomShape2d.GetParameter(fCurrentX, 
aPairs[nPairIndex].First, false,
-                                                        false);
-                            aCustomShape2d.GetParameter(fCurrentY, 
aPairs[nPairIndex].Second, false,
-                                                        false);
-                            bCurrentValid = true;
-                            nPairIndex++;
-                        }
-                        break;
-                    }
-                    case LINETO:
-                    {
-                        if (nPairIndex >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            mpFS->startElementNS(XML_a, XML_lnTo);
-                            WriteCustomGeometryPoint(aPairs[nPairIndex], 
aCustomShape2d);
-                            mpFS->endElementNS(XML_a, XML_lnTo);
-                            aCustomShape2d.GetParameter(fCurrentX, 
aPairs[nPairIndex].First, false,
-                                                        false);
-                            aCustomShape2d.GetParameter(fCurrentY, 
aPairs[nPairIndex].Second, false,
-                                                        false);
-                            bCurrentValid = true;
-                            nPairIndex++;
-                        }
-                        break;
-                    }
-                    case CURVETO:
-                    {
-                        if (nPairIndex + 2 >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            mpFS->startElementNS(XML_a, XML_cubicBezTo);
-                            for (sal_uInt8 l = 0; l <= 2; ++l)
-                            {
-                                WriteCustomGeometryPoint(aPairs[nPairIndex + 
l], aCustomShape2d);
-                            }
-                            mpFS->endElementNS(XML_a, XML_cubicBezTo);
-                            aCustomShape2d.GetParameter(fCurrentX, 
aPairs[nPairIndex + 2].First,
-                                                        false, false);
-                            aCustomShape2d.GetParameter(fCurrentY, 
aPairs[nPairIndex + 2].Second,
-                                                        false, false);
-                            bCurrentValid = true;
-                            nPairIndex += 3;
-                        }
-                        break;
-                    }
-                    case ANGLEELLIPSETO:
-                    case ANGLEELLIPSE:
-                    {
-                        if (nPairIndex + 2 >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            // Read parameters
-                            double fCx = 0.0;
-                            aCustomShape2d.GetParameter(fCx, 
aPairs[nPairIndex].First, false,
-                                                        false);
-                            double fCy = 0.0;
-                            aCustomShape2d.GetParameter(fCy, 
aPairs[nPairIndex].Second, false,
-                                                        false);
-                            double fWR = 0.0;
-                            aCustomShape2d.GetParameter(fWR, aPairs[nPairIndex 
+ 1].First, false,
-                                                        false);
-                            double fHR = 0.0;
-                            aCustomShape2d.GetParameter(fHR, aPairs[nPairIndex 
+ 1].Second, false,
-                                                        false);
-                            double fStartAngle = 0.0;
-                            aCustomShape2d.GetParameter(fStartAngle, 
aPairs[nPairIndex + 2].First,
-                                                        false, false);
-                            double fEndAngle = 0.0;
-                            aCustomShape2d.GetParameter(fEndAngle, 
aPairs[nPairIndex + 2].Second,
-                                                        false, false);
-
-                            // Prepare start and swing angle
-                            sal_Int32 nStartAng(std::lround(fStartAngle * 
60000));
-                            sal_Int32 nSwingAng = 0;
-                            if (basegfx::fTools::equalZero(fStartAngle)
-                                && basegfx::fTools::equalZero(fEndAngle - 
360.0))
-                                nSwingAng = 360 * 60000; // special case full 
circle
-                            else
-                            {
-                                nSwingAng = std::lround((fEndAngle - 
fStartAngle) * 60000);
-                                if (nSwingAng < 0)
-                                    nSwingAng += 360 * 60000;
-                            }
-
-                            // calculate start point on ellipse
-                            double fSx = 0.0;
-                            double fSy = 0.0;
-                            getEllipsePointFromViewAngle(fSx, fSy, fWR, fHR, 
fCx, fCy, fStartAngle);
-
-                            // write markup for going to start point
-                            if (rSegment.Command == ANGLEELLIPSETO)
-                            {
-                                mpFS->startElementNS(XML_a, XML_lnTo);
-                                mpFS->singleElementNS(XML_a, XML_pt, XML_x,
-                                                      
OString::number(std::lround(fSx)), XML_y,
-                                                      
OString::number(std::lround(fSy)));
-                                mpFS->endElementNS(XML_a, XML_lnTo);
-                            }
-                            else
-                            {
-                                mpFS->startElementNS(XML_a, XML_moveTo);
-                                mpFS->singleElementNS(XML_a, XML_pt, XML_x,
-                                                      
OString::number(std::lround(fSx)), XML_y,
-                                                      
OString::number(std::lround(fSy)));
-                                mpFS->endElementNS(XML_a, XML_moveTo);
-                            }
-                            // write markup for arcTo
-                            if (!basegfx::fTools::equalZero(fWR)
-                                && !basegfx::fTools::equalZero(fHR))
-                                mpFS->singleElement(FSNS(XML_a, XML_arcTo), 
XML_wR,
-                                                    
OString::number(std::lround(fWR)), XML_hR,
-                                                    
OString::number(std::lround(fHR)), XML_stAng,
-                                                    
OString::number(nStartAng), XML_swAng,
-                                                    
OString::number(nSwingAng));
-
-                            getEllipsePointFromViewAngle(fCurrentX, fCurrentY, 
fWR, fHR, fCx, fCy,
-                                                         fEndAngle);
-                            bCurrentValid = true;
-                            nPairIndex += 3;
-                        }
-                        break;
-                    }
-                    case ARCTO:
-                    case ARC:
-                    case CLOCKWISEARCTO:
-                    case CLOCKWISEARC:
-                    {
-                        if (nPairIndex + 3 >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            // read parameters
-                            double fX1 = 0.0;
-                            aCustomShape2d.GetParameter(fX1, 
aPairs[nPairIndex].First, false,
-                                                        false);
-                            double fY1 = 0.0;
-                            aCustomShape2d.GetParameter(fY1, 
aPairs[nPairIndex].Second, false,
-                                                        false);
-                            double fX2 = 0.0;
-                            aCustomShape2d.GetParameter(fX2, aPairs[nPairIndex 
+ 1].First, false,
-                                                        false);
-                            double fY2 = 0.0;
-                            aCustomShape2d.GetParameter(fY2, aPairs[nPairIndex 
+ 1].Second, false,
-                                                        false);
-                            double fX3 = 0.0;
-                            aCustomShape2d.GetParameter(fX3, aPairs[nPairIndex 
+ 2].First, false,
-                                                        false);
-                            double fY3 = 0.0;
-                            aCustomShape2d.GetParameter(fY3, aPairs[nPairIndex 
+ 2].Second, false,
-                                                        false);
-                            double fX4 = 0.0;
-                            aCustomShape2d.GetParameter(fX4, aPairs[nPairIndex 
+ 3].First, false,
-                                                        false);
-                            double fY4 = 0.0;
-                            aCustomShape2d.GetParameter(fY4, aPairs[nPairIndex 
+ 3].Second, false,
-                                                        false);
-                            // calculate ellipse parameter
-                            const double fWR = (fX2 - fX1) / 2.0;
-                            const double fHR = (fY2 - fY1) / 2.0;
-                            const double fCx = (fX1 + fX2) / 2.0;
-                            const double fCy = (fY1 + fY2) / 2.0;
-                            // calculate start angle
-                            double fStartAngle = 0.0;
-                            double fPx = 0.0;
-                            double fPy = 0.0;
-                            getEllipsePointAndAngleFromRayPoint(fStartAngle, 
fPx, fPy, fWR, fHR,
-                                                                fCx, fCy, fX3, 
fY3);
-                            // markup for going to start point
-                            if (rSegment.Command == ARCTO || rSegment.Command 
== CLOCKWISEARCTO)
-                            {
-                                mpFS->startElementNS(XML_a, XML_lnTo);
-                                mpFS->singleElementNS(XML_a, XML_pt, XML_x,
-                                                      
OString::number(std::lround(fPx)), XML_y,
-                                                      
OString::number(std::lround(fPy)));
-                                mpFS->endElementNS(XML_a, XML_lnTo);
-                            }
-                            else
-                            {
-                                mpFS->startElementNS(XML_a, XML_moveTo);
-                                mpFS->singleElementNS(XML_a, XML_pt, XML_x,
-                                                      
OString::number(std::lround(fPx)), XML_y,
-                                                      
OString::number(std::lround(fPy)));
-                                mpFS->endElementNS(XML_a, XML_moveTo);
-                            }
-                            // calculate swing angle
-                            double fEndAngle = 0.0;
-                            getEllipsePointAndAngleFromRayPoint(fEndAngle, 
fPx, fPy, fWR, fHR, fCx,
-                                                                fCy, fX4, fY4);
-                            double fSwingAngle(fEndAngle - fStartAngle);
-                            const bool bIsClockwise(rSegment.Command == 
CLOCKWISEARCTO
-                                                    || rSegment.Command == 
CLOCKWISEARC);
-                            if (bIsClockwise && fSwingAngle < 0)
-                                fSwingAngle += 360.0;
-                            else if (!bIsClockwise && fSwingAngle > 0)
-                                fSwingAngle -= 360.0;
-                            // markup for arcTo
-                            // ToDo: write markup for case zero width or 
height of ellipse
-                            const sal_Int32 nStartAng(std::lround(fStartAngle 
* 60000));
-                            const sal_Int32 nSwingAng(std::lround(fSwingAngle 
* 60000));
-                            mpFS->singleElement(
-                                FSNS(XML_a, XML_arcTo), XML_wR, 
OString::number(std::lround(fWR)),
-                                XML_hR, OString::number(std::lround(fHR)), 
XML_stAng,
-                                OString::number(nStartAng), XML_swAng, 
OString::number(nSwingAng));
-                            fCurrentX = fPx;
-                            fCurrentY = fPy;
-                            bCurrentValid = true;
-                            nPairIndex += 4;
-                        }
-                        break;
-                    }
-                    case ELLIPTICALQUADRANTX:
-                    case ELLIPTICALQUADRANTY:
-                    {
-                        if (nPairIndex >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            // read parameters
-                            double fX = 0.0;
-                            aCustomShape2d.GetParameter(fX, 
aPairs[nPairIndex].First, false, false);
-                            double fY = 0.0;
-                            aCustomShape2d.GetParameter(fY, 
aPairs[nPairIndex].Second, false,
-                                                        false);
-
-                            // Prepare parameters for arcTo
-                            if (bCurrentValid)
-                            {
-                                double fWR = std::abs(fCurrentX - fX);
-                                double fHR = std::abs(fCurrentY - fY);
-                                double fStartAngle(0.0);
-                                double fSwingAngle(0.0);
-                                // The starting direction of the arc toggles 
beween X and Y
-                                if ((rSegment.Command == ELLIPTICALQUADRANTX 
&& !(k % 2))
-                                    || (rSegment.Command == 
ELLIPTICALQUADRANTY && (k % 2)))
-                                {
-                                    // arc starts horizontal
-                                    fStartAngle = fY < fCurrentY ? 90.0 : 
270.0;
-                                    const bool bClockwise = (fX < fCurrentX && 
fY < fCurrentY)
-                                                            || (fX > fCurrentX 
&& fY > fCurrentY);
-                                    fSwingAngle = bClockwise ? 90.0 : -90.0;
-                                }
-                                else
-                                {
-                                    // arc starts vertical
-                                    fStartAngle = fX < fCurrentX ? 0.0 : 180.0;
-                                    const bool bClockwise = (fX < fCurrentX && 
fY > fCurrentY)
-                                                            || (fX > fCurrentX 
&& fY < fCurrentY);
-                                    fSwingAngle = bClockwise ? 90.0 : -90.0;
-                                }

... etc. - the rest is truncated

Reply via email to