[Libreoffice-commits] core.git: include/oox oox/source sd/qa sd/source

Szymon Kłos szymon.klos at collabora.com
Thu Oct 19 19:02:33 UTC 2017


 include/oox/drawingml/clrscheme.hxx             |   33 ++++
 include/oox/export/utils.hxx                    |    2 
 include/oox/ppt/presentationfragmenthandler.hxx |    1 
 oox/source/export/drawingml.cxx                 |    2 
 oox/source/ppt/presentationfragmenthandler.cxx  |   76 +++++++++
 sd/qa/unit/data/pptx/accent-color.pptx          |binary
 sd/qa/unit/export-tests-ooxml2.cxx              |   19 ++
 sd/source/filter/eppt/epptooxml.hxx             |    4 
 sd/source/filter/eppt/pptx-epptooxml.cxx        |  193 ++++++++++++++++++------
 9 files changed, 285 insertions(+), 45 deletions(-)

New commits:
commit 98133504fde1e1b235c39e4bb3b72bb2ee0b7819
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Tue Oct 17 22:14:38 2017 +0200

    PPTX export: remember color schemes in theme
    
    Remember color scheme from loaded pptx file
    or use default values.
    
    Change-Id: Icb69c51603afc5f332c20c75e4ed5f659f4b5614
    Reviewed-on: https://gerrit.libreoffice.org/43470
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>

diff --git a/include/oox/drawingml/clrscheme.hxx b/include/oox/drawingml/clrscheme.hxx
index ccb1517e44eb..ccf918d7ba74 100644
--- a/include/oox/drawingml/clrscheme.hxx
+++ b/include/oox/drawingml/clrscheme.hxx
@@ -28,9 +28,42 @@
 
 #include <oox/dllapi.h>
 #include <sal/types.h>
+#include <rtl/ustring.hxx>
 
 namespace oox { namespace drawingml {
 
+enum PredefinedClrSchemeId {
+    //dk1,
+    //lt1,
+    dk2 = 0,
+    lt2,
+    accent1,
+    accent2,
+    accent3,
+    accent4,
+    accent5,
+    accent6,
+    hlink,
+    folHlink,
+    Count
+};
+
+static std::map<PredefinedClrSchemeId, rtl::OUString> PredefinedClrNames =
+{
+    //{ dk1,  "dk1" },
+    //{ lt1, "lt1" },
+    { dk2, "dk2" },
+    { lt2, "lt2" },
+    { accent1, "accent1" },
+    { accent2, "accent2" },
+    { accent3, "accent3" },
+    { accent4, "accent4" },
+    { accent5, "accent5" },
+    { accent6, "accent6" },
+    { hlink, "hlink" },
+    { folHlink, "folHlink" }
+};
+
 class ClrMap
 {
     std::map < sal_Int32, sal_Int32 > maClrMap;
diff --git a/include/oox/export/utils.hxx b/include/oox/export/utils.hxx
index 6bca2edcbd16..74e78a37da33 100644
--- a/include/oox/export/utils.hxx
+++ b/include/oox/export/utils.hxx
@@ -28,7 +28,7 @@ inline OString I32S_(sal_Int32 x) { return OString::number(x); }
 inline OString I32SHEX_(sal_Int32 x)
 {
     OString aStr = OString::number(x, 16);
-    if (aStr.getLength() % 2 != 0)
+    while (aStr.getLength() < 6)
         aStr = OString("0") + aStr;
     return aStr.getStr();
 }
diff --git a/include/oox/ppt/presentationfragmenthandler.hxx b/include/oox/ppt/presentationfragmenthandler.hxx
index aeda119cd2f1..637e70643be7 100644
--- a/include/oox/ppt/presentationfragmenthandler.hxx
+++ b/include/oox/ppt/presentationfragmenthandler.hxx
@@ -53,6 +53,7 @@ protected:
 private:
 
     void importSlide(sal_uInt32 nSlide, bool bFirstSlide, bool bImportNotes);
+    void saveThemeToGrabBag(oox::drawingml::ThemePtr pThemePtr, const OUString& sTheme);
 
     std::vector< OUString > maSlideMasterVector;
     std::vector< OUString > maSlidesVector;
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 306e884fc0f3..953c16467596 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2943,7 +2943,7 @@ void DrawingML::WriteStyleProperties( sal_Int32 nTokenId, const Sequence< Proper
                 aProperties[i].Value >>= aTransformations;
         }
         mpFS->startElementNS( XML_a, nTokenId, XML_idx, I32S( nIdx ), FSEND );
-        WriteColor( sSchemeClr, aTransformations );
+        WriteColor(sSchemeClr, aTransformations);
         mpFS->endElementNS( XML_a, nTokenId );
     }
     else
diff --git a/oox/source/ppt/presentationfragmenthandler.cxx b/oox/source/ppt/presentationfragmenthandler.cxx
index 07433617b612..f78e75c1bc00 100644
--- a/oox/source/ppt/presentationfragmenthandler.cxx
+++ b/oox/source/ppt/presentationfragmenthandler.cxx
@@ -64,6 +64,22 @@ using namespace ::com::sun::star::xml::sax;
 
 namespace oox { namespace ppt {
 
+static std::map<PredefinedClrSchemeId, sal_Int32> PredefinedClrTokens =
+{
+    //{ dk1, XML_dk1 },
+    //{ lt1, XML_lt1 },
+    { dk2, XML_dk2 },
+    { lt2, XML_lt2 },
+    { accent1, XML_accent1 },
+    { accent2, XML_accent2 },
+    { accent3, XML_accent3 },
+    { accent4, XML_accent4 },
+    { accent5, XML_accent5 },
+    { accent6, XML_accent6 },
+    { hlink, XML_hlink },
+    { folHlink, XML_folHlink }
+};
+
 PresentationFragmentHandler::PresentationFragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath ) throw()
 : FragmentHandler2( rFilter, rFragmentPath )
 , mpTextListStyle( new TextListStyle )
@@ -143,6 +159,65 @@ void ResolveTextFields( XmlFilterBase const & rFilter )
     }
 }
 
+void PresentationFragmentHandler::saveThemeToGrabBag(oox::drawingml::ThemePtr pThemePtr, const OUString& sTheme)
+{
+    if (!pThemePtr)
+        return;
+
+    try
+    {
+        uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY);
+        if (xDocProps.is())
+        {
+            uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();
+
+            const OUString aGrabBagPropName = "InteropGrabBag";
+            if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName))
+            {
+                // get existing grab bag
+                comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName));
+
+                uno::Sequence<beans::PropertyValue> aTheme(1);
+                comphelper::SequenceAsHashMap aThemesHashMap;
+
+                // create current theme
+                uno::Sequence<beans::PropertyValue> aCurrentTheme(PredefinedClrSchemeId::Count);
+
+                ClrScheme rClrScheme = pThemePtr->getClrScheme();
+                for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
+                {
+                    sal_uInt32 nToken = PredefinedClrTokens[static_cast<PredefinedClrSchemeId>(nId)];
+                    const OUString& sName = PredefinedClrNames[static_cast<PredefinedClrSchemeId>(nId)];
+                    sal_Int32 nColor = 0;
+
+                    rClrScheme.getColor(nToken, nColor);
+                    const uno::Any& rColor = uno::makeAny(nColor);
+
+                    aCurrentTheme[nId].Name = sName;
+                    aCurrentTheme[nId].Value = rColor;
+                }
+
+                // add new theme to the sequence
+                aTheme[0].Name = sTheme;
+                const uno::Any& rCurrentTheme = makeAny(aCurrentTheme);
+                aTheme[0].Value = rCurrentTheme;
+
+                aThemesHashMap << aTheme;
+
+                // put the new items
+                aGrabBag.update(aThemesHashMap);
+
+                // put it back to the document
+                xDocProps->setPropertyValue(aGrabBagPropName, uno::Any(aGrabBag.getAsConstPropertyValueList()));
+            }
+        }
+    }
+    catch (const uno::Exception&)
+    {
+        SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveThemeToGrabBag, Failed to save grab bag");
+    }
+}
+
 void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, bool bFirstPage, bool bImportNotesPage)
 {
     PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() );
@@ -232,6 +307,7 @@ void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, bool bFirstPage
                                         UNO_QUERY_THROW));
                                 rThemes[ aThemeFragmentPath ] = pThemePtr;
                                 pThemePtr->setFragment(xDoc);
+                                saveThemeToGrabBag(pThemePtr, aThemeFragmentPath);
                             }
                             else
                             {
diff --git a/sd/qa/unit/data/pptx/accent-color.pptx b/sd/qa/unit/data/pptx/accent-color.pptx
new file mode 100755
index 000000000000..59591606e546
Binary files /dev/null and b/sd/qa/unit/data/pptx/accent-color.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 25a1963c8e75..586700e39863 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -120,6 +120,7 @@ public:
     void testGroupRotation();
     void testTdf104788();
     void testSmartartRotation2();
+    void testAccentColor();
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
 
@@ -165,6 +166,7 @@ public:
     CPPUNIT_TEST(testGroupRotation);
     CPPUNIT_TEST(testTdf104788);
     CPPUNIT_TEST(testSmartartRotation2);
+    CPPUNIT_TEST(testAccentColor);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -1255,6 +1257,23 @@ void SdOOXMLExportTest2::testSmartartRotation2()
     assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[1]/p:spPr/a:xfrm/a:off", "y", "719640");
 }
 
+void SdOOXMLExportTest2::testAccentColor()
+{
+    ::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptx/accent-color.pptx"), PPTX);
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+    xDocShRef->DoClose();
+
+    xmlDocPtr pXmlDocContent1 = parseExport(tempFile, "ppt/slides/slide1.xml");
+    assertXPath(pXmlDocContent1, "/p:sld/p:cSld/p:spTree/p:sp/p:style/a:fillRef/a:schemeClr", "val", "accent6");
+    xmlDocPtr pXmlDocContent2 = parseExport(tempFile, "ppt/slides/slide2.xml");
+    assertXPath(pXmlDocContent2, "/p:sld/p:cSld/p:spTree/p:sp/p:style/a:fillRef/a:schemeClr", "val", "accent6");
+    xmlDocPtr pXmlDocTheme1 = parseExport(tempFile, "ppt/theme/theme1.xml");
+    assertXPath(pXmlDocTheme1, "/a:theme/a:themeElements/a:clrScheme/a:accent6/a:srgbClr", "val", "70ad47");
+    xmlDocPtr pXmlDocTheme2 = parseExport(tempFile, "ppt/theme/theme2.xml");
+    assertXPath(pXmlDocTheme2, "/a:theme/a:themeElements/a:clrScheme/a:accent6/a:srgbClr", "val", "deb340");
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/filter/eppt/epptooxml.hxx b/sd/source/filter/eppt/epptooxml.hxx
index 1d98b541a688..05a9bd2d3bbc 100644
--- a/sd/source/filter/eppt/epptooxml.hxx
+++ b/sd/source/filter/eppt/epptooxml.hxx
@@ -26,6 +26,8 @@
 #include <oox/export/shapes.hxx>
 #include "epptbase.hxx"
 
+using ::sax_fastparser::FSHelperPtr;
+
 namespace com { namespace sun { namespace star {
     namespace animations {
         class XAnimate;
@@ -90,6 +92,8 @@ protected:
     virtual void ImplWriteSlideMaster( sal_uInt32 nPageNum, css::uno::Reference< css::beans::XPropertySet > const & aXBackgroundPropSet ) override;
     virtual void ImplWriteLayout( sal_Int32 nOffset, sal_uInt32 nMasterNum ) override;
     void ImplWritePPTXLayout( sal_Int32 nOffset, sal_uInt32 nMasterNum );
+    bool WriteColorSchemes(FSHelperPtr pFS, const OUString& rThemePath);
+    void WriteDefaultColorSchemes(FSHelperPtr pFS);
     void WriteTheme( sal_Int32 nThemeNum );
 
     virtual bool ImplCreateDocument() override;
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index a1bd8619fd88..ae8a631003ab 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <o3tl/any.hxx>
 #include <oox/drawingml/chart/chartconverter.hxx>
+#include <oox/drawingml/clrscheme.hxx>
 #include <oox/token/namespaces.hxx>
 #include <oox/token/tokens.hxx>
 #include <oox/token/relationship.hxx>
@@ -2341,46 +2342,14 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap
     return *this;
 }
 
-#define MINIMAL_THEME "  <a:themeElements>\
-    <a:clrScheme name=\"Office\">\
-      <a:dk1>\
+#define SYS_COLOR_SCHEMES "      <a:dk1>\
         <a:sysClr val=\"windowText\" lastClr=\"000000\"/>\
       </a:dk1>\
       <a:lt1>\
         <a:sysClr val=\"window\" lastClr=\"FFFFFF\"/>\
-      </a:lt1>\
-      <a:dk2>\
-        <a:srgbClr val=\"1F497D\"/>\
-      </a:dk2>\
-      <a:lt2>\
-        <a:srgbClr val=\"EEECE1\"/>\
-      </a:lt2>\
-      <a:accent1>\
-        <a:srgbClr val=\"4F81BD\"/>\
-      </a:accent1>\
-      <a:accent2>\
-        <a:srgbClr val=\"C0504D\"/>\
-      </a:accent2>\
-      <a:accent3>\
-        <a:srgbClr val=\"9BBB59\"/>\
-      </a:accent3>\
-      <a:accent4>\
-        <a:srgbClr val=\"8064A2\"/>\
-      </a:accent4>\
-      <a:accent5>\
-        <a:srgbClr val=\"4BACC6\"/>\
-      </a:accent5>\
-      <a:accent6>\
-        <a:srgbClr val=\"F79646\"/>\
-      </a:accent6>\
-      <a:hlink>\
-        <a:srgbClr val=\"0000FF\"/>\
-      </a:hlink>\
-      <a:folHlink>\
-        <a:srgbClr val=\"800080\"/>\
-      </a:folHlink>\
-    </a:clrScheme>\
-    <a:fontScheme name=\"Office\">\
+      </a:lt1>"
+
+#define MINIMAL_THEME "    <a:fontScheme name=\"Office\">\
       <a:majorFont>\
         <a:latin typeface=\"Arial\"/>\
         <a:ea typeface=\"DejaVu Sans\"/>\
@@ -2557,16 +2526,138 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap
           </a:path>\
         </a:gradFill>\
       </a:bgFillStyleLst>\
-    </a:fmtScheme>\
-  </a:themeElements>"
+    </a:fmtScheme>"
+
+void PowerPointExport::WriteDefaultColorSchemes(FSHelperPtr pFS)
+{
+    for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
+    {
+        OUString sName = PredefinedClrNames[static_cast<PredefinedClrSchemeId>(nId)];
+        sal_Int32 nColor = 0;
+
+        switch (nId)
+        {
+        case PredefinedClrSchemeId::dk2:
+            nColor = 0x1F497D;
+            break;
+        case PredefinedClrSchemeId::lt2:
+            nColor = 0xEEECE1;
+            break;
+        case PredefinedClrSchemeId::accent1:
+            nColor = 0x4F81BD;
+            break;
+        case PredefinedClrSchemeId::accent2:
+            nColor = 0xC0504D;
+            break;
+        case PredefinedClrSchemeId::accent3:
+            nColor = 0x9BBB59;
+            break;
+        case PredefinedClrSchemeId::accent4:
+            nColor = 0x8064A2;
+            break;
+        case PredefinedClrSchemeId::accent5:
+            nColor = 0x4BACC6;
+            break;
+        case PredefinedClrSchemeId::accent6:
+            nColor = 0xF79646;
+            break;
+        case PredefinedClrSchemeId::hlink:
+            nColor = 0x0000FF;
+            break;
+        case PredefinedClrSchemeId::folHlink:
+            nColor = 0x800080;
+            break;
+        }
+
+        OUString sOpenColorScheme = OUStringBuffer()
+            .append("<a:")
+            .append(sName)
+            .append(">")
+            .makeStringAndClear();
+        pFS->write(sOpenColorScheme);
+
+        pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor), FSEND);
+
+        OUString sCloseColorScheme = OUStringBuffer()
+            .append("</a:")
+            .append(sName)
+            .append(">")
+            .makeStringAndClear();
+        pFS->write(sCloseColorScheme);
+    }
+}
+
+bool PowerPointExport::WriteColorSchemes(FSHelperPtr pFS, const OUString& rThemePath)
+{
+    try
+    {
+        uno::Reference<beans::XPropertySet> xDocProps(getModel(), uno::UNO_QUERY);
+        if (xDocProps.is())
+        {
+            uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();
+
+            const OUString aGrabBagPropName = "InteropGrabBag";
+            if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName))
+            {
+                comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName));
+                uno::Sequence<beans::PropertyValue> aCurrentTheme;
+
+                aGrabBag.getValue(rThemePath) >>= aCurrentTheme;
+
+                // Order is important
+                for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
+                {
+                    OUString sName = PredefinedClrNames[static_cast<PredefinedClrSchemeId>(nId)];
+                    sal_Int32 nColor = 0;
+
+                    for (auto aIt = aCurrentTheme.begin(); aIt != aCurrentTheme.end(); aIt++)
+                    {
+                        if (aIt->Name == sName)
+                        {
+                            aIt->Value >>= nColor;
+                            break;
+                        }
+                    }
+
+                    OUString sOpenColorScheme = OUStringBuffer()
+                        .append("<a:")
+                        .append(sName)
+                        .append(">")
+                        .makeStringAndClear();
+                    pFS->write(sOpenColorScheme);
+
+                    pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor), FSEND);
+
+                    OUString sCloseColorScheme = OUStringBuffer()
+                        .append("</a:")
+                        .append(sName)
+                        .append(">")
+                        .makeStringAndClear();
+                    pFS->write(sCloseColorScheme);
+                }
+
+                // TODO: write complete color schemes & only if successful, protection against partial export
+                return true;
+            }
+        }
+    }
+    catch (const uno::Exception&)
+    {
+        SAL_WARN("writerfilter", "Failed to save documents grab bag");
+    }
+
+    return false;
+}
 
 void PowerPointExport::WriteTheme(sal_Int32 nThemeNum)
 {
-    FSHelperPtr pFS = openFragmentStreamWithSerializer(OUStringBuffer()
-                      .append("ppt/theme/theme")
-                      .append(nThemeNum + 1)
-                      .append(".xml")
-                      .makeStringAndClear(),
+    OUString sThemePath = OUStringBuffer()
+        .append("ppt/theme/theme")
+        .append(nThemeNum + 1)
+        .append(".xml")
+        .makeStringAndClear();
+
+    FSHelperPtr pFS = openFragmentStreamWithSerializer(sThemePath,
                       "application/vnd.openxmlformats-officedocument.theme+xml");
 
     pFS->startElementNS(XML_a, XML_theme,
@@ -2574,7 +2665,23 @@ void PowerPointExport::WriteTheme(sal_Int32 nThemeNum)
                         XML_name, "Office Theme",
                         FSEND);
 
+    pFS->startElementNS(XML_a, XML_themeElements, FSEND);
+    pFS->startElementNS(XML_a, XML_clrScheme, XML_name, "Office", FSEND);
+
+    pFS->write(SYS_COLOR_SCHEMES);
+
+    if (!WriteColorSchemes(pFS, sThemePath))
+    {
+        // color schemes are required - use default values
+        WriteDefaultColorSchemes(pFS);
+    }
+
+    pFS->endElementNS(XML_a, XML_clrScheme);
+
+    // export remaining part
     pFS->write(MINIMAL_THEME);
+
+    pFS->endElementNS(XML_a, XML_themeElements);
     pFS->endElementNS(XML_a, XML_theme);
 }
 


More information about the Libreoffice-commits mailing list