oox/source/drawingml/textcharacterproperties.cxx |    8 +-
 oox/source/export/drawingml.cxx                  |   24 +++++-
 sd/qa/unit/uiimpress.cxx                         |   91 +++++++++++++++++++++--
 3 files changed, 117 insertions(+), 6 deletions(-)

New commits:
commit 678790f292b63c9def1f0427df20028a1f734c15
Author:     Tünde Tóth <toth.tu...@nisz.hu>
AuthorDate: Thu Dec 16 15:10:33 2021 +0100
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Mon Jan 3 14:40:09 2022 +0100

    tdf#127696 PPTX export: fix lost outline character formatting
    
    Now outline font property export is supported partially in PPTX
    export and in text shape export in other OOXML formats.
    
    Note: OOXML/MSO has customizable Text Fill and Text Outline in
    Format Text Effects, while LO has only simple and buggy outline
    character formatting property, showing only white or completely
    transparent outline fill color. Transparency issues and the buggy
    outline font handling of LO (e.g. 1% font color (line) transparency
    results 100% fill transparency of the outline text) haven't been
    handled yet.
    
    Change-Id: Ic34bce4efd4a544d799b1d89af1107c4918061d8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126996
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/oox/source/drawingml/textcharacterproperties.cxx 
b/oox/source/drawingml/textcharacterproperties.cxx
index 7ffeaeba8da2..9d568cd5cabb 100644
--- a/oox/source/drawingml/textcharacterproperties.cxx
+++ b/oox/source/drawingml/textcharacterproperties.cxx
@@ -111,6 +111,7 @@ void TextCharacterProperties::pushToPropMap( PropertyMap& 
rPropMap, const XmlFil
     if ( maFillProperties.moFillType.has() )
     {
         Color aColor = maFillProperties.getBestSolidColor();
+        bool bContoured = false;
 
         // noFill doesn't exist for characters. Map noFill to 99% transparency
         if (maFillProperties.moFillType.get() == XML_noFill)
@@ -124,7 +125,11 @@ void TextCharacterProperties::pushToPropMap( PropertyMap& 
rPropMap, const XmlFil
         {
             Color aLineColor = 
moTextOutlineProperties.get().maLineFill.getBestSolidColor();
             sal_Int16 nLineTransparency = aLineColor.getTransparency();
-            if (nLineTransparency < aColor.getTransparency())
+
+            // tdf#127696 If the text color is white (and the outline color 
doesn't dominate),
+            //            then this is contoured text in LO.
+            if (nLineTransparency < aColor.getTransparency()
+                || (bContoured = aColor.getColor(rFilter.getGraphicHelper()) 
== COL_WHITE))
                 aColor = aLineColor;
         }
         rPropMap.setProperty(PROP_CharColor, 
aColor.getColor(rFilter.getGraphicHelper()));
@@ -133,6 +138,7 @@ void TextCharacterProperties::pushToPropMap( PropertyMap& 
rPropMap, const XmlFil
         rPropMap.setProperty(PROP_CharColorTintOrShade, 
aColor.getTintOrShade());
         rPropMap.setProperty(PROP_CharColorLumMod, aColor.getLumMod());
         rPropMap.setProperty(PROP_CharColorLumOff, aColor.getLumOff());
+        rPropMap.setProperty(PROP_CharContoured, bContoured);
 
         if (aColor.hasTransparency())
         {
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 8581535357a0..d87c6cccddee 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2201,9 +2201,31 @@ void DrawingML::WriteRunProperties( const Reference< 
XPropertySet >& rRun, bool
                 nTransparency = MAX_PERCENT - (nTransparency * PER_PERCENT);
             }
 
+            bool bContoured = false;
+            if (GetProperty(rXPropSet, "CharContoured"))
+                bContoured = *o3tl::doAccess<bool>(mAny);
+
+            // tdf#127696 If the CharContoured is true, then the text color is 
white and the outline color is the CharColor.
+            if (bContoured)
+            {
+                mpFS->startElementNS(XML_a, XML_ln);
+                if (color == COL_AUTO)
+                {
+                    mbIsBackgroundDark ? WriteSolidFill(COL_WHITE) : 
WriteSolidFill(COL_BLACK);
+                }
+                else
+                {
+                    color.SetAlpha(255);
+                    if (!WriteCharColor(rXPropSet))
+                        WriteSolidFill(color, nTransparency);
+                }
+                mpFS->endElementNS(XML_a, XML_ln);
+
+                WriteSolidFill(COL_WHITE);
+            }
             // tdf#104219 In LibreOffice and MS Office, there are two types of 
colors:
             // Automatic and Fixed. OOXML is setting automatic color, by not 
providing color.
-            if( color != COL_AUTO )
+            else if( color != COL_AUTO )
             {
                 color.SetAlpha(255);
                 // TODO: special handle embossed/engraved
diff --git a/sd/qa/unit/uiimpress.cxx b/sd/qa/unit/uiimpress.cxx
index 2ea61ea63e94..5a773aa8ced6 100644
--- a/sd/qa/unit/uiimpress.cxx
+++ b/sd/qa/unit/uiimpress.cxx
@@ -7,8 +7,7 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include <test/bootstrapfixture.hxx>
-#include <unotest/macros_test.hxx>
+#include "sdmodeltestbase.hxx"
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 
 #include <com/sun/star/beans/XPropertySet.hpp>
@@ -45,10 +44,8 @@
 #include <vcl/scheduler.hxx>
 #include <comphelper/propertyvalue.hxx>
 
-#include <DrawDocShell.hxx>
 #include <ViewShell.hxx>
 #include <app.hrc>
-#include <drawdoc.hxx>
 #include <sdpage.hxx>
 #include <unomodel.hxx>
 #include <osl/thread.hxx>
@@ -69,6 +66,8 @@ public:
     void checkCurrentPageNumber(sal_uInt16 nNum);
     void insertStringToObject(sal_uInt16 nObj, const std::string& rStr, bool 
bUseEscape);
     sd::slidesorter::SlideSorterViewShell* getSlideSorterViewShell();
+    FileFormat* getFormat(sal_Int32 nExportType);
+    void save(sd::DrawDocShell* pShell, FileFormat const* pFormat, 
utl::TempFile const& rTempFile);
 };
 
 void SdUiImpressTest::setUp()
@@ -150,6 +149,46 @@ sd::slidesorter::SlideSorterViewShell* 
SdUiImpressTest::getSlideSorterViewShell(
     return pSSVS;
 }
 
+FileFormat* SdUiImpressTest::getFormat(sal_Int32 nExportType)
+{
+    FileFormat* pFormat = &aFileFormats[0];
+    if (o3tl::make_unsigned(nExportType) < SAL_N_ELEMENTS(aFileFormats))
+        pFormat = &aFileFormats[nExportType];
+    return pFormat;
+}
+
+void SdUiImpressTest::save(sd::DrawDocShell* pShell, FileFormat const* pFormat,
+                           utl::TempFile const& rTempFile)
+{
+    SfxMedium aStoreMedium(rTempFile.GetURL(), StreamMode::STD_WRITE);
+    if (std::strcmp(pFormat->pName, "odg") == 0)
+    { // Draw
+        SotClipboardFormatId nExportFormat = SotClipboardFormatId::NONE;
+        if (pFormat->nFormatType == ODG_FORMAT_TYPE)
+            nExportFormat = SotClipboardFormatId::STARDRAW_8;
+        auto pExportFilter = std::make_shared<SfxFilter>(
+            OUString::createFromAscii(pFormat->pFilterName), OUString(), 
pFormat->nFormatType,
+            nExportFormat, OUString::createFromAscii(pFormat->pTypeName), 
OUString(),
+            OUString::createFromAscii(pFormat->pUserData), 
"private:factory/sdraw*");
+        pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
+        aStoreMedium.SetFilter(pExportFilter);
+    }
+    else // Impress
+    {
+        SotClipboardFormatId nExportFormat = SotClipboardFormatId::NONE;
+        if (pFormat->nFormatType == ODP_FORMAT_TYPE)
+            nExportFormat = SotClipboardFormatId::STARCHART_8;
+        auto pExportFilter = std::make_shared<SfxFilter>(
+            OUString::createFromAscii(pFormat->pFilterName), OUString(), 
pFormat->nFormatType,
+            nExportFormat, OUString::createFromAscii(pFormat->pTypeName), 
OUString(),
+            OUString::createFromAscii(pFormat->pUserData), 
"private:factory/simpress*");
+        pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
+        aStoreMedium.SetFilter(pExportFilter);
+    }
+    pShell->DoSaveAs(aStoreMedium);
+    pShell->DoClose();
+}
+
 CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf111522)
 {
     // Load the document and create two new windows.
@@ -880,6 +919,50 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testCharColorTheme)
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(8000), nCharColorLumOff);
 }
 
+CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf127696)
+{
+    mxComponent = loadFromDesktop("private:factory/simpress",
+                                  
"com.sun.star.presentation.PresentationDocument");
+
+    dispatchCommand(mxComponent, ".uno:InsertPage", {});
+    Scheduler::ProcessEventsToIdle();
+
+    insertStringToObject(0, "Test", /*bUseEscape*/ false);
+    dispatchCommand(mxComponent, ".uno:SelectAll", {});
+    dispatchCommand(mxComponent, ".uno:OutlineFont", {});
+
+    // Save it as PPTX and load it again.
+    utl::TempFile aTempFile;
+    save(dynamic_cast<SdXImpressDocument*>(mxComponent.get())->GetDocShell(), 
getFormat(PPTX),
+         aTempFile);
+    mxComponent = loadFromDesktop(aTempFile.GetURL());
+
+    uno::Reference<drawing::XDrawPagesSupplier> 
xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPage> 
xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(1),
+                                                 uno::UNO_QUERY);
+
+    uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), 
uno::UNO_QUERY);
+
+    uno::Reference<text::XText> xText
+        = uno::Reference<text::XTextRange>(xShape, 
uno::UNO_QUERY_THROW)->getText();
+    CPPUNIT_ASSERT_MESSAGE("Not a text shape", xText.is());
+
+    uno::Reference<container::XEnumerationAccess> paraEnumAccess(xText, 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> 
paraEnum(paraEnumAccess->createEnumeration());
+
+    uno::Reference<text::XTextRange> xParagraph(paraEnum->nextElement(), 
uno::UNO_QUERY_THROW);
+
+    uno::Reference<container::XEnumerationAccess> runEnumAccess(xParagraph, 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> runEnum = 
runEnumAccess->createEnumeration();
+
+    uno::Reference<text::XTextRange> xRun(runEnum->nextElement(), 
uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY_THROW);
+
+    bool bContoured = false;
+    xPropSet->getPropertyValue("CharContoured") >>= bContoured;
+    CPPUNIT_ASSERT(bContoured);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to