include/oox/export/drawingml.hxx     |    2 +
 include/unotest/macros_test.hxx      |    9 +++++
 oox/qa/unit/data/refer-to-theme.pptx |binary
 oox/qa/unit/export.cxx               |   45 ++++++++++++++---------------
 oox/source/export/drawingml.cxx      |   54 ++++++++++++++++++++++++++++++++++-
 sd/qa/unit/sdmodeltestbase.hxx       |   11 -------
 unotest/Library_unotest.mk           |    1 
 unotest/source/cpp/macros_test.cxx   |   17 +++++++++++
 8 files changed, 105 insertions(+), 34 deletions(-)

New commits:
commit f36767fde87191258ea21f3faac0be6ad79328e0
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Dec 2 08:45:26 2021 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Dec 2 17:26:33 2021 +0100

    PPTX export: handle theme colors from the doc model for shape text
    
    As a start, do this only in case there are no effects used. If there is
    no theme color or there are effects, fall back to the old code.
    
    Also move parseExportStream() from SdModelTestBaseXML up to MacrosTest,
    so oox/ test code can use it as well.
    
    Change-Id: Ia76581dcef110341f6c3e60f22c34818ed0dcabc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126215
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index 4af628a289f9..516287293580 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -222,6 +222,8 @@ public:
     void WriteLineArrow( const css::uno::Reference< css::beans::XPropertySet 
>& rXPropSet, bool bLineStart );
     void WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, 
sal_Int32 nStartID, sal_Int32 nEndID );
 
+    bool WriteCharColor(const css::uno::Reference<css::beans::XPropertySet>& 
xPropertySet);
+
     void WriteSolidFill( ::Color nColor, sal_Int32 nAlpha = MAX_PERCENT );
     void WriteSolidFill( const OUString& sSchemeName, const 
css::uno::Sequence< css::beans::PropertyValue >& aTransformations, sal_Int32 
nAlpha = MAX_PERCENT );
     void WriteSolidFill( const ::Color nColor, const css::uno::Sequence< 
css::beans::PropertyValue >& aTransformations, sal_Int32 nAlpha = MAX_PERCENT );
diff --git a/include/unotest/macros_test.hxx b/include/unotest/macros_test.hxx
index 14917794d38d..ed879b835a55 100644
--- a/include/unotest/macros_test.hxx
+++ b/include/unotest/macros_test.hxx
@@ -28,11 +28,16 @@ struct TestMacroInfo
 };
 
 class BasicDLL;
+class SvStream;
 
 namespace test
 {
 class Directories;
 }
+namespace utl
+{
+class TempFile;
+}
 
 namespace unotest
 {
@@ -76,6 +81,10 @@ public:
                     const OUString& rCommand,
                     const css::uno::Sequence<css::beans::PropertyValue>& 
rPropertyValues);
 
+    /// Opens rStreamName from rTempFile, assuming it's a ZIP storage.
+    static std::unique_ptr<SvStream> parseExportStream(const utl::TempFile& 
rTempFile,
+                                                       const OUString& 
rStreamName);
+
     void setUpNssGpg(const test::Directories& rDirectories, const OUString& 
rTestName);
     void tearDownNssGpg();
 
diff --git a/oox/qa/unit/data/refer-to-theme.pptx 
b/oox/qa/unit/data/refer-to-theme.pptx
new file mode 100644
index 000000000000..9a45799ab977
Binary files /dev/null and b/oox/qa/unit/data/refer-to-theme.pptx differ
diff --git a/oox/qa/unit/export.cxx b/oox/qa/unit/export.cxx
index b649d546ead9..fee130d77971 100644
--- a/oox/qa/unit/export.cxx
+++ b/oox/qa/unit/export.cxx
@@ -13,11 +13,9 @@
 
 #include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/frame/XStorable.hpp>
-#include <com/sun/star/packages/zip/ZipFileAccess.hpp>
 
 #include <unotools/mediadescriptor.hxx>
 #include <unotools/tempfile.hxx>
-#include <unotools/ucbstreamhelper.hxx>
 
 using namespace ::com::sun::star;
 
@@ -86,11 +84,7 @@ CPPUNIT_TEST_FIXTURE(Test, testPolylineConnectorPosition)
     loadAndSave(aURL, "Office Open XML Text");
 
     // Then make sure polyline and connector have the correct position.
-    uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
-        = packages::zip::ZipFileAccess::createWithURL(mxComponentContext, 
getTempFile().GetURL());
-    uno::Reference<io::XInputStream> 
xInputStream(xNameAccess->getByName("word/document.xml"),
-                                                  uno::UNO_QUERY);
-    std::unique_ptr<SvStream> 
pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+    std::unique_ptr<SvStream> pStream = parseExportStream(getTempFile(), 
"word/document.xml");
     xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
 
     // For child elements of groups in Writer the position has to be adapted 
to be relative
@@ -117,11 +111,7 @@ CPPUNIT_TEST_FIXTURE(Test, testRotatedShapePosition)
     loadAndSave(aURL, "Office Open XML Text");
 
     // Then make sure the rotated child shape has the correct position.
-    uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
-        = packages::zip::ZipFileAccess::createWithURL(mxComponentContext, 
getTempFile().GetURL());
-    uno::Reference<io::XInputStream> 
xInputStream(xNameAccess->getByName("word/document.xml"),
-                                                  uno::UNO_QUERY);
-    std::unique_ptr<SvStream> 
pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+    std::unique_ptr<SvStream> pStream = parseExportStream(getTempFile(), 
"word/document.xml");
     xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
 
     // For a group itself and for shapes outside of groups, the position 
calculation is done in
@@ -142,11 +132,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDmlGroupshapePolygon)
 
     // Then make sure that the group shape, the group shape's child size and 
the child shape's size
     // match:
-    uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
-        = packages::zip::ZipFileAccess::createWithURL(mxComponentContext, 
getTempFile().GetURL());
-    uno::Reference<io::XInputStream> 
xInputStream(xNameAccess->getByName("word/document.xml"),
-                                                  uno::UNO_QUERY);
-    std::unique_ptr<SvStream> 
pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+    std::unique_ptr<SvStream> pStream = parseExportStream(getTempFile(), 
"word/document.xml");
     xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
     assertXPath(pXmlDoc, "//wpg:grpSpPr/a:xfrm/a:ext", "cx", "5328360");
     // Without the accompanying fix in place, this test would have failed, the 
<a:chExt> element was
@@ -163,11 +149,7 @@ CPPUNIT_TEST_FIXTURE(Test, testCustomShapeArrowExport)
     loadAndSave(aURL, "Office Open XML Text");
 
     // Then the shapes should retain their correct control values.
-    uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
-        = packages::zip::ZipFileAccess::createWithURL(mxComponentContext, 
getTempFile().GetURL());
-    uno::Reference<io::XInputStream> 
xInputStream(xNameAccess->getByName("word/document.xml"),
-                                                  uno::UNO_QUERY);
-    std::unique_ptr<SvStream> 
pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+    std::unique_ptr<SvStream> pStream = parseExportStream(getTempFile(), 
"word/document.xml");
     xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
 
     // Without the fix the output OOXML would have no <a:prstGeom> tags in it.
@@ -344,6 +326,25 @@ CPPUNIT_TEST_FIXTURE(Test, testCustomShapeArrowExport)
                 "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[4]",
                 "fmla", "val 66660");
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testReferToTheme)
+{
+    // Given a PPTX file that contains references to a theme:
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"refer-to-theme.pptx";
+
+    // When saving that document:
+    loadAndSave(aURL, "Impress Office Open XML");
+
+    std::unique_ptr<SvStream> pStream = parseExportStream(getTempFile(), 
"ppt/slides/slide1.xml");
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+    // Then make sure the shape text color is a scheme color:
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1
+    // - Actual  : 0
+    // - XPath '//p:sp/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr' number 
of nodes is incorrect
+    // i.e. the <a:schemeClr> element was not written.
+    assertXPath(pXmlDoc, 
"//p:sp/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr", "val", "accent1");
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index fbe13359dd9b..7217efe0e5c9 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -152,6 +152,21 @@ sal_Int32 GetAlphaFromTransparenceGradient(const 
awt::Gradient& rGradient, bool
     // drawingML alpha is a percentage on a 0..100000 scale.
     return (255 - nRed) * oox::drawingml::MAX_PERCENT / 255;
 }
+
+const char* g_aPredefinedClrNames[] = {
+    "dk1",
+    "lt1",
+    "dk2",
+    "lt2",
+    "accent1",
+    "accent2",
+    "accent3",
+    "accent4",
+    "accent5",
+    "accent6",
+    "hlink",
+    "folHlink",
+};
 }
 
 namespace oox::drawingml {
@@ -400,6 +415,40 @@ void DrawingML::WriteColorTransformations( const Sequence< 
PropertyValue >& aTra
     }
 }
 
+bool DrawingML::WriteCharColor(const 
css::uno::Reference<css::beans::XPropertySet>& xPropertySet)
+{
+    if 
(!xPropertySet->getPropertySetInfo()->hasPropertyByName("CharColorTheme"))
+    {
+        return false;
+    }
+
+    sal_Int32 nCharColorTheme = -1;
+    xPropertySet->getPropertyValue("CharColorTheme") >>= nCharColorTheme;
+    if (nCharColorTheme < 0 || nCharColorTheme > 11)
+    {
+        return false;
+    }
+
+    const char* pColorName = g_aPredefinedClrNames[nCharColorTheme];
+
+    sal_Int32 nCharColorLumMod{};
+    xPropertySet->getPropertyValue("CharColorLumMod") >>= nCharColorLumMod;
+    sal_Int32 nCharColorLumOff{};
+    xPropertySet->getPropertyValue("CharColorLumOff") >>= nCharColorLumOff;
+    sal_Int32 nCharColorTintOrShade{};
+    xPropertySet->getPropertyValue("CharColorTintOrShade") >>= 
nCharColorTintOrShade;
+    if (nCharColorLumMod != 10000 || nCharColorLumOff != 0 || 
nCharColorTintOrShade != 0)
+    {
+        return false;
+    }
+
+    mpFS->startElementNS(XML_a, XML_solidFill);
+    mpFS->singleElementNS(XML_a, XML_schemeClr, XML_val, pColorName);
+    mpFS->endElementNS(XML_a, XML_solidFill);
+
+    return true;
+}
+
 void DrawingML::WriteSolidFill( ::Color nColor, sal_Int32 nAlpha )
 {
     mpFS->startElementNS(XML_a, XML_solidFill);
@@ -2146,7 +2195,10 @@ void DrawingML::WriteRunProperties( const Reference< 
XPropertySet >& rRun, bool
             {
                 color.SetAlpha(255);
                 // TODO: special handle embossed/engraved
-                WriteSolidFill(color, nTransparency);
+                if (!WriteCharColor(rXPropSet))
+                {
+                    WriteSolidFill(color, nTransparency);
+                }
             }
         }
     }
diff --git a/sd/qa/unit/sdmodeltestbase.hxx b/sd/qa/unit/sdmodeltestbase.hxx
index 74e25b1f1aba..03b087f8b88a 100644
--- a/sd/qa/unit/sdmodeltestbase.hxx
+++ b/sd/qa/unit/sdmodeltestbase.hxx
@@ -444,17 +444,6 @@ class SdModelTestBaseXML
 {
 
 public:
-    std::unique_ptr<SvStream> parseExportStream(utl::TempFile const & 
rTempFile, const OUString& rStreamName)
-    {
-        // Read the stream we're interested in.
-        OUString const url(rTempFile.GetURL());
-        uno::Reference<packages::zip::XZipFileAccess2> const 
xZipNames(packages::zip::ZipFileAccess::createWithURL(
-                                                                        
comphelper::getComponentContext(m_xSFactory), url));
-        uno::Reference<io::XInputStream> const 
xInputStream(xZipNames->getByName(rStreamName), uno::UNO_QUERY);
-        std::unique_ptr<SvStream> 
pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
-        return pStream;
-    }
-
     xmlDocUniquePtr parseExport(utl::TempFile const & rTempFile, OUString 
const& rStreamName)
     {
         std::unique_ptr<SvStream> const pStream(parseExportStream(rTempFile, 
rStreamName));
diff --git a/unotest/Library_unotest.mk b/unotest/Library_unotest.mk
index ea697699ee82..3acfe2f69ed9 100644
--- a/unotest/Library_unotest.mk
+++ b/unotest/Library_unotest.mk
@@ -22,6 +22,7 @@ $(eval $(call gb_Library_use_libraries,unotest,\
        cppuhelper \
        sal \
        sb \
+       utl \
 ))
 
 $(eval $(call gb_Library_use_externals,unotest,\
diff --git a/unotest/source/cpp/macros_test.cxx 
b/unotest/source/cpp/macros_test.cxx
index ab15518e4c9c..718c0b1b8954 100644
--- a/unotest/source/cpp/macros_test.cxx
+++ b/unotest/source/cpp/macros_test.cxx
@@ -14,6 +14,7 @@
 #include <com/sun/star/document/MacroExecMode.hpp>
 #include <com/sun/star/uno/XComponentContext.hpp>
 #include <com/sun/star/frame/DispatchHelper.hpp>
+#include <com/sun/star/packages/zip/ZipFileAccess.hpp>
 
 #include <basic/basrdll.hxx>
 #include <cppunit/TestAssert.h>
@@ -23,6 +24,8 @@
 #include <osl/file.hxx>
 #include <osl/process.h>
 #include <osl/thread.h>
+#include <unotools/tempfile.hxx>
+#include <unotools/ucbstreamhelper.hxx>
 
 using namespace css;
 
@@ -85,6 +88,20 @@ void MacrosTest::dispatchCommand(const 
uno::Reference<lang::XComponent>& xCompon
     xDispatchHelper->executeDispatch(xFrame, rCommand, OUString(), 0, 
rPropertyValues);
 }
 
+std::unique_ptr<SvStream> MacrosTest::parseExportStream(const utl::TempFile& 
rTempFile,
+                                                        const OUString& 
rStreamName)
+{
+    const OUString aUrl = rTempFile.GetURL();
+    uno::Reference<uno::XComponentContext> xComponentContext
+        = comphelper::getProcessComponentContext();
+    uno::Reference<packages::zip::XZipFileAccess2> const xZipNames(
+        packages::zip::ZipFileAccess::createWithURL(xComponentContext, aUrl));
+    uno::Reference<io::XInputStream> const 
xInputStream(xZipNames->getByName(rStreamName),
+                                                        uno::UNO_QUERY);
+    std::unique_ptr<SvStream> 
pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+    return pStream;
+}
+
 void MacrosTest::setUpNssGpg(const test::Directories& rDirectories, const 
OUString& rTestName)
 {
     OUString aSourceDir = rDirectories.getURLFromSrc(u"/test/signing-keys/");

Reply via email to