diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2017-10-17 22:14:38 +0200 |
---|---|---|
committer | Szymon Kłos <szymon.klos@collabora.com> | 2017-10-19 21:02:07 +0200 |
commit | 98133504fde1e1b235c39e4bb3b72bb2ee0b7819 (patch) | |
tree | a40a89027bf64ac74fa9a3a76b0989e8bd679c7f | |
parent | 278bdbca318defa3bb862e0422cff2492ef46705 (diff) |
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@libreoffice.org>
Reviewed-by: Szymon Kłos <szymon.klos@collabora.com>
-rw-r--r-- | include/oox/drawingml/clrscheme.hxx | 33 | ||||
-rw-r--r-- | include/oox/export/utils.hxx | 2 | ||||
-rw-r--r-- | include/oox/ppt/presentationfragmenthandler.hxx | 1 | ||||
-rw-r--r-- | oox/source/export/drawingml.cxx | 2 | ||||
-rw-r--r-- | oox/source/ppt/presentationfragmenthandler.cxx | 76 | ||||
-rwxr-xr-x | sd/qa/unit/data/pptx/accent-color.pptx | bin | 0 -> 1079347 bytes | |||
-rw-r--r-- | sd/qa/unit/export-tests-ooxml2.cxx | 19 | ||||
-rw-r--r-- | sd/source/filter/eppt/epptooxml.hxx | 4 | ||||
-rw-r--r-- | sd/source/filter/eppt/pptx-epptooxml.cxx | 193 |
9 files changed, 285 insertions, 45 deletions
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 Binary files differnew file mode 100755 index 000000000000..59591606e546 --- /dev/null +++ b/sd/qa/unit/data/pptx/accent-color.pptx 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); } |