sw/qa/extras/rtfimport/data/tdf158044.rtf      |   20 +++++
 sw/qa/extras/rtfimport/rtfimport.cxx           |   54 +++++++++++++++
 sw/source/filter/ww8/rtfattributeoutput.cxx    |   37 ----------
 writerfilter/source/dmapper/DomainMapper.cxx   |   89 +++++++++++++++++++++++++
 writerfilter/source/rtftok/rtfdocumentimpl.cxx |    1 
 writerfilter/source/rtftok/rtfsprm.cxx         |    9 +-
 6 files changed, 172 insertions(+), 38 deletions(-)

New commits:
commit b6aaddde6e283cb43c79e64fa924ea1d95143b93
Author:     Vasily Melenchuk <vasily.melenc...@cib.de>
AuthorDate: Thu Oct 26 17:09:44 2023 +0300
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Sat Nov 11 21:44:44 2023 +0100

    tdf#104288: rtf export: drop \nonshppict on export
    
    - these days hard to find a reader not able to read shapes
    
    - RTF file will became compact without pictures duplication
    
    - WordPad nowadays is able to display shape pict, no reason
    for fallback
    
    - Fixing possible rtf file bloat on exporting some WMFs
    
    Change-Id: Icc8b60da6541acef939f42021d8d5e81bbcd1ae4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158507
    Tested-by: Jenkins
    Reviewed-by: Vasily Melenchuk <vasily.melenc...@cib.de>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159313
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx 
b/sw/source/filter/ww8/rtfattributeoutput.cxx
index 5c20be552480..c8ac5b4cadf4 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -4459,21 +4459,8 @@ void RtfAttributeOutput::FlyFrameGraphic(const 
SwFlyFrameFormat* pFlyFrameFormat
         }
     }
 
-    /*
-       If the graphic is not of type WMF then we will have to store two
-       graphics, one in the native format wrapped in shppict, and the other in
-       the wmf format wrapped in nonshppict, so as to keep wordpad happy. If 
it's
-       a wmf already then we don't need any such wrapping
-       */
-    bool bIsWMF = pBLIPType && std::strcmp(pBLIPType, 
OOO_STRING_SVTOOLS_RTF_WMETAFILE) == 0;
     const SwAttrSet* pAttrSet = pGrfNode->GetpSwAttrSet();
-    if (!pFrame || pFrame->IsInline())
-    {
-        if (!bIsWMF)
-            m_rExport.Strm().WriteOString(
-                "{" OOO_STRING_SVTOOLS_RTF_IGNORE 
OOO_STRING_SVTOOLS_RTF_SHPPICT);
-    }
-    else
+    if (pFrame && !pFrame->IsInline())
     {
         m_rExport.Strm().WriteOString(
             "{" OOO_STRING_SVTOOLS_RTF_SHP
@@ -4566,27 +4553,7 @@ void RtfAttributeOutput::FlyFrameGraphic(const 
SwFlyFrameFormat* pFlyFrameFormat
                    m_rExport, &m_rExport.Strm(), bWritePicProp, pAttrSet);
     }
 
-    if (!pFrame || pFrame->IsInline())
-    {
-        if (!bIsWMF)
-        {
-            m_rExport.Strm().WriteOString("}"
-                                          "{" 
OOO_STRING_SVTOOLS_RTF_NONSHPPICT);
-
-            aStream.Seek(0);
-            if (GraphicConverter::Export(aStream, rGraphic, 
ConvertDataFormat::WMF) != ERRCODE_NONE)
-                SAL_WARN("sw.rtf", "failed to export the graphic");
-            pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
-            nSize = aStream.TellEnd();
-            pGraphicAry = static_cast<sal_uInt8 const*>(aStream.GetData());
-
-            ExportPICT(pFlyFrameFormat, aSize, aRendered, aMapped, rCr, 
pBLIPType, pGraphicAry,
-                       nSize, m_rExport, &m_rExport.Strm());
-
-            m_rExport.Strm().WriteChar('}');
-        }
-    }
-    else
+    if (pFrame && !pFrame->IsInline())
         m_rExport.Strm().WriteOString("}}}}"); // Close SV, SP, SHPINST and 
SHP.
 
     m_rExport.Strm().WriteOString(SAL_NEWLINE_STRING);
commit 72a9b16c5c618e475757121e6771f381e5953190
Author:     Oliver Specht <oliver.spe...@cib.de>
AuthorDate: Thu Nov 2 16:34:50 2023 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Sat Nov 11 20:54:55 2023 +0100

    tdf#158044 handling of paragraph attributes in RTF import
    
    style attributes need to be repeated at the paragraph
    if not repeated then defaults have to be applied
    
    This includes:
      Fix Windows 64-bit build using VS 2022
    
      Change-Id: Id976fe515287a4aa12d7ff8ca0ca09c31c65309f
      Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159316
    
    and
      Make the unit test linear and more explicit
    
      Change-Id: Ic28d059ed41f88c9264743034a5ce5397fff0b2c
      Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159317
    
    Change-Id: I4ee567e8006c240c046b7e7bb75eae92e5563776
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158839
    Tested-by: Jenkins
    Co-authored-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159328

diff --git a/sw/qa/extras/rtfimport/data/tdf158044.rtf 
b/sw/qa/extras/rtfimport/data/tdf158044.rtf
new file mode 100755
index 000000000000..65e687f25d39
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/tdf158044.rtf
@@ -0,0 +1,20 @@
+{\rtf1\ansi
+{\colortbl;\red0\green0\blue0;\red0\green0\blue255;
+\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;
+\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red0\green0\blue0;\red0\green0\blue0;}
+
+{\stylesheet
+{\fs24\sa3200 Normal;}
+{\s97\tx1701\tx2835 StyleTabstops;}
+{\s98\cbpat6  StyleRed;}
+{\s99\qc SyleCentered;}
+}
+
+
+{\s97 Paragraph without tabstops\par}
+{\s98 Pargraph without color \par}
+{\s99 Paragraph without center\par}
+{\s97\tx1701\tx2835 Paragraph with tabstops\par}
+{\s98\cbpat6  Pargraph with color \par}
+{\s99\qc Paragraph with center\par}
+}
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx 
b/sw/qa/extras/rtfimport/rtfimport.cxx
index 4ae5e90043f4..7dd9aa43877f 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -1716,6 +1716,60 @@ CPPUNIT_TEST_FIXTURE(Test, testParaStyleBottomMargin)
                          getProperty<style::LineSpacing>(xPara, 
"ParaLineSpacing").Height);
 }
 
+CPPUNIT_TEST_FIXTURE(Test, test158044Tdf)
+{
+    createSwDoc("tdf158044.rtf");
+
+    {
+        auto xPara(getParagraph(1));
+        auto tabStops = getProperty<uno::Sequence<style::TabStop>>(xPara, 
"ParaTabStops");
+
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(0), tabStops.getLength());
+    }
+
+    {
+        auto xPara(getParagraph(2));
+        auto fillColor = getProperty<Color>(xPara, "FillColor");
+        auto fillStyle = getProperty<drawing::FillStyle>(xPara, "FillStyle");
+
+        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, fillStyle);
+        CPPUNIT_ASSERT_EQUAL(Color(0xffffff), fillColor);
+    }
+
+    {
+        auto xPara(getParagraph(3));
+        auto adjust = getProperty<sal_Int16>(xPara, "ParaAdjust");
+
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(0), adjust);
+    }
+
+    {
+        auto xPara(getParagraph(4));
+        auto tabStops = getProperty<uno::Sequence<style::TabStop>>(xPara, 
"ParaTabStops");
+
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), tabStops.getLength());
+    }
+
+    {
+        auto xPara(getParagraph(5));
+        auto fillColor = getProperty<Color>(xPara, "FillColor");
+        auto fillStyle = getProperty<drawing::FillStyle>(xPara, "FillStyle");
+        auto tabStops = getProperty<uno::Sequence<style::TabStop>>(xPara, 
"ParaTabStops");
+
+        CPPUNIT_ASSERT_LESS(sal_Int32(2), tabStops.getLength());
+        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, fillStyle);
+        CPPUNIT_ASSERT_EQUAL(Color(0xff0000), fillColor);
+    }
+
+    {
+        auto xPara(getParagraph(6));
+        auto fillStyle = getProperty<drawing::FillStyle>(xPara, "FillStyle");
+        auto tabStops = getProperty<uno::Sequence<style::TabStop>>(xPara, 
"ParaTabStops");
+
+        CPPUNIT_ASSERT_LESS(sal_Int32(2), tabStops.getLength());
+        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, fillStyle);
+    }
+}
 // tests should only be added to rtfIMPORT *if* they fail round-tripping in 
rtfEXPORT
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index 148bb98eaf42..adf956653071 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -34,6 +34,7 @@
 #include <oox/drawingml/drawingmltypes.hxx>
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
 #include <com/sun/star/document/XOOXMLDocumentPropertiesImporter.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
 #include <com/sun/star/table/BorderLineStyle.hpp>
 #include <com/sun/star/table/ShadowFormat.hpp>
@@ -3843,6 +3844,35 @@ void DomainMapper::lcl_endCharacterGroup()
     m_pImpl->PopProperties(CONTEXT_CHARACTER);
 }
 
+//copied from rtfsprm
+/// Is it problematic to deduplicate this SPRM?
+static bool isSPRMDeduplicateDenylist(PropertyIds nId, PropertyMapPtr pContext)
+{
+    switch (nId)
+    {
+        // See the NS_ooxml::LN_CT_PPrBase_tabs handler in DomainMapper,
+        // deduplication is explicitly not wanted for these tokens.
+    case PROP_PARA_TAB_STOPS:
+    case PROP_PARA_LINE_SPACING:
+        return true;
+    case PROP_TOP_BORDER:
+    case PROP_LEFT_BORDER:
+    case PROP_BOTTOM_BORDER:
+    case PROP_RIGHT_BORDER:
+    case META_PROP_HORIZONTAL_BORDER:
+    case META_PROP_VERTICAL_BORDER:
+        return true;
+        // Removing \fi and \li if the style has the same value would mean 
taking these values from
+        // \ls, while deduplication would be done to take the values from the 
style.
+    case PROP_PARA_FIRST_LINE_INDENT:
+    case PROP_PARA_LEFT_MARGIN:
+        return pContext && pContext->getProperty(PROP_NUMBERING_RULES);
+
+    default:
+        return false;
+    }
+}
+
 void DomainMapper::lcl_text(const sal_uInt8 * data_, size_t len)
 {
     //TODO: Determine the right text encoding (FIB?)
@@ -3893,6 +3923,65 @@ void DomainMapper::lcl_text(const sal_uInt8 * data_, 
size_t len)
                         pContext->Insert(PROP_BREAK_TYPE, 
uno::Any(style::BreakType_COLUMN_BEFORE));
                         m_pImpl->clearDeferredBreak(COLUMN_BREAK);
                     }
+                    if (IsRTFImport() && pContext) {
+                        //reset paragraph style properties not repeated at the 
paragraph
+                        std::optional<PropertyMap::Property> paraStyleName = 
pContext->getProperty(PROP_PARA_STYLE_NAME);
+                        if (paraStyleName.has_value()) {
+                            OUString uStyleName;
+                            paraStyleName->second >>= uStyleName;
+                            StyleSheetEntryPtr pStyleSheet = 
m_pImpl->GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(uStyleName);
+                            if (pStyleSheet != nullptr)
+                            {
+                                std::vector< PropertyIds > stylePropertyIds = 
pStyleSheet->m_pProperties->GetPropertyIds();
+                                std::vector< PropertyIds >::iterator 
stylePropertyIdsIt = stylePropertyIds.begin();
+                                while (stylePropertyIdsIt != 
stylePropertyIds.end())
+                                {
+                                    PropertyIds ePropertyId = 
*stylePropertyIdsIt;
+                                    std::optional< PropertyMap::Property > 
styleProperty = pStyleSheet->m_pProperties->getProperty(ePropertyId);
+                                    std::optional< PropertyMap::Property > 
paragraphProperty = pContext->getProperty(ePropertyId);
+                                    if (paragraphProperty.has_value()) {
+                                        if (paragraphProperty->second == 
styleProperty->second &&
+                                            
!isSPRMDeduplicateDenylist(ePropertyId, pContext))
+                                        {
+                                            pContext->Erase(ePropertyId);
+                                        }
+                                    }
+                                    else
+                                    {
+                                        switch (ePropertyId)
+                                        {
+                                        case PROP_PARA_LEFT_MARGIN:
+                                            if 
(!pContext->getProperty(PROP_NUMBERING_RULES))
+                                            {
+                                                pContext->Insert(ePropertyId, 
uno::Any(0l));
+                                            }
+                                            break;
+                                        case PROP_PARA_RIGHT_MARGIN:
+                                            pContext->Insert(ePropertyId, 
uno::Any(0l));
+                                            break;
+                                        case PROP_PARA_LAST_LINE_ADJUST:
+                                        case PROP_PARA_ADJUST:
+                                            pContext->Insert(ePropertyId, 
uno::Any(style::ParagraphAdjust_LEFT));
+                                            break;
+                                        case PROP_PARA_TAB_STOPS:
+                                            pContext->Insert(ePropertyId, 
uno::Any(uno::Sequence< style::TabStop >()));
+                                            break;
+                                        case PROP_FILL_STYLE:
+                                            pContext->Insert(ePropertyId, 
uno::Any(drawing::FillStyle_NONE));
+                                            break;
+                                        case PROP_FILL_COLOR:
+                                            pContext->Insert(ePropertyId, 
uno::Any(sal_Int32(COL_TRANSPARENT)));
+                                            break;
+                                        case INVALID:
+                                        default:
+                                            break;
+                                        }
+                                    }
+                                    ++stylePropertyIdsIt;
+                                }
+                            }
+                        }
+                    }
                     finishParagraph();
                     return;
                 }
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx 
b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 11e251b0828a..45f49553b26b 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -558,7 +558,6 @@ RTFDocumentImpl::getProperties(const RTFSprms& rAttributes, 
RTFSprms const& rSpr
             }
         }
 
-        // Get rid of direct formatting what is already in the style.
         RTFSprms sprms(aSprms.cloneAndDeduplicate(aStyleSprms, nStyleType, 
true, &aSprms));
         RTFSprms attributes(rAttributes.cloneAndDeduplicate(aStyleAttributes, 
nStyleType, true));
         return new RTFReferenceProperties(std::move(attributes), 
std::move(sprms));
diff --git a/writerfilter/source/rtftok/rtfsprm.cxx 
b/writerfilter/source/rtftok/rtfsprm.cxx
index 3efb60eb29d8..d98ea74abd55 100644
--- a/writerfilter/source/rtftok/rtfsprm.cxx
+++ b/writerfilter/source/rtftok/rtfsprm.cxx
@@ -290,9 +290,14 @@ static void cloneAndDeduplicateSprm(std::pair<Id, 
RTFValue::Pointer_t> const& rS
     {
         if (rSprm.second->equals(*pValue))
         {
-            if (!isSPRMDeduplicateDenylist(rSprm.first, pDirect))
+            //this removes properties that are equal at the style and at the 
sprm
+            //don't do that for paragraph styles
+            if (nStyleType != NS_ooxml::LN_Value_ST_StyleType_paragraph)
             {
-                ret.erase(rSprm.first); // duplicate to style
+                if (!isSPRMDeduplicateDenylist(rSprm.first, pDirect))
+                {
+                    ret.erase(rSprm.first); // duplicate to style
+                }
             }
         }
         else if (!rSprm.second->getSprms().empty() || 
!rSprm.second->getAttributes().empty())

Reply via email to