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 | 210 ++++++++++++++++++------ 9 files changed, 294 insertions(+), 53 deletions(-)
New commits: commit c99f02e17f436a5887578f0da55e4daae78a2ca6 Author: Szymon KÅos <szymon.k...@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 <c...@libreoffice.org> Reviewed-by: Szymon KÅos <szymon.k...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/44321 Reviewed-by: Andras Timar <andras.ti...@collabora.com> Tested-by: Andras Timar <andras.ti...@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 c1187b634419..b0a8fe5cafb9 100644 --- a/include/oox/export/utils.hxx +++ b/include/oox/export/utils.hxx @@ -30,7 +30,7 @@ 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 7a142d9ed8bc..686c8b3c8549 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -2904,7 +2904,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 41a283a445d1..6b157877db9a 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& 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..b23de21776a2 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 6f3897ec9ecc..2b2235c621f0 100644 --- a/sd/qa/unit/export-tests-ooxml2.cxx +++ b/sd/qa/unit/export-tests-ooxml2.cxx @@ -120,6 +120,7 @@ public: void testTdf112086(); void testTdf104788(); void testSmartartRotation2(); + void testAccentColor(); CPPUNIT_TEST_SUITE(SdOOXMLExportTest2); @@ -161,6 +162,7 @@ public: CPPUNIT_TEST(testTdf112086); CPPUNIT_TEST(testTdf104788); CPPUNIT_TEST(testSmartartRotation2); + CPPUNIT_TEST(testAccentColor); CPPUNIT_TEST_SUITE_END(); @@ -1051,6 +1053,23 @@ void SdOOXMLExportTest2::testSmartartRotation2() assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[3]/p:txBody/a:bodyPr", "rot", "10800000"); } +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 52241d2d4949..7c4ab7a9580a 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 74c1086d6633..d7c449c642bc 100644 --- a/sd/source/filter/eppt/pptx-epptooxml.cxx +++ b/sd/source/filter/eppt/pptx-epptooxml.cxx @@ -20,6 +20,8 @@ #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/ole/vbaproject.hxx> #include <epptooxml.hxx> @@ -2251,46 +2253,14 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape( const Reference< XSha 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\"/>\ @@ -2467,25 +2437,163 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape( const Reference< XSha </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( (sal_Int32) nThemeNum + 1 ) - .append( ".xml" ) - .makeStringAndClear(), - "application/vnd.openxmlformats-officedocument.theme+xml" ); - - pFS->startElementNS( XML_a, XML_theme, - FSNS( XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main", - XML_name, "Office Theme", - FSEND ); + 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, + FSNS(XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main", + 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->write( MINIMAL_THEME ); - pFS->endElementNS( XML_a, XML_theme ); + pFS->endElementNS(XML_a, XML_themeElements); + pFS->endElementNS(XML_a, XML_theme); } bool PowerPointExport::ImplCreateDocument()
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits