summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzymon Kłos <szymon.klos@collabora.com>2017-10-17 22:14:38 +0200
committerSzymon Kłos <szymon.klos@collabora.com>2017-10-31 13:52:34 +0100
commitc344d74a6961ec39685d718fbb7c29dd186ca0a4 (patch)
treef89560e389198cf614558da0fdd2229db27a141d
parent54293c1fae0c774c72a8564a25844aecf6d40f7f (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> Reviewed-on: https://gerrit.libreoffice.org/44081 Reviewed-by: Andras Timar <andras.timar@collabora.com>
-rw-r--r--include/oox/drawingml/clrscheme.hxx33
-rw-r--r--include/oox/export/utils.hxx15
-rw-r--r--include/oox/ppt/presentationfragmenthandler.hxx1
-rw-r--r--oox/source/export/drawingml.cxx2
-rw-r--r--oox/source/ppt/presentationfragmenthandler.cxx76
-rwxr-xr-xsd/qa/unit/data/pptx/accent-color.pptxbin0 -> 73227 bytes
-rw-r--r--sd/qa/unit/export-tests-ooxml2.cxx19
-rw-r--r--sd/source/filter/eppt/epptooxml.hxx4
-rw-r--r--sd/source/filter/eppt/pptx-epptooxml.cxx212
9 files changed, 308 insertions, 54 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 599e45ee55f8..9f13cf87c4c8 100644
--- a/include/oox/export/utils.hxx
+++ b/include/oox/export/utils.hxx
@@ -24,8 +24,19 @@
#include <rtl/textenc.h>
#include <sal/types.h>
-#define I32S(x) OString::number( (sal_Int32) x ).getStr()
-#define I64S(x) OString::number( (sal_Int64) x ).getStr()
+inline OString I32S_(sal_Int32 x) { return OString::number(x); }
+inline OString I32SHEX_(sal_Int32 x)
+{
+ OString aStr = OString::number(x, 16);
+ while (aStr.getLength() < 6)
+ aStr = OString("0") + aStr;
+ return aStr.getStr();
+}
+inline OString I64S_(sal_Int64 x) { return OString::number(x); }
+inline OString DS_(double x) { return OString::number(x); }
+#define I32S(x) I32S_(x).getStr()
+#define I32SHEX(x) I32SHEX_(x).getStr()
+#define I64S(x) I64S_(x).getStr()
#define IS(x) OString::number( x ).getStr()
#define BS(x) (x ? "1":"0")
#define USS(x) OUStringToOString( x, RTL_TEXTENCODING_UTF8 ).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 14f7c363ec4b..e33dca9f5fe6 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2790,7 +2790,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 b67eb8b56817..3aa58f62c7bd 100644
--- a/oox/source/ppt/presentationfragmenthandler.cxx
+++ b/oox/source/ppt/presentationfragmenthandler.cxx
@@ -61,6 +61,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 )
@@ -140,6 +156,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() );
@@ -229,6 +304,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
--- /dev/null
+++ b/sd/qa/unit/data/pptx/accent-color.pptx
Binary files differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 12cdd1580806..edac049c2ba7 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -109,6 +109,7 @@ public:
void testTdf112552();
void testTdf112647();
void testSmartartRotation2();
+ void testAccentColor();
CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
@@ -139,6 +140,7 @@ public:
CPPUNIT_TEST(testTdf112552);
CPPUNIT_TEST(testTdf112647);
CPPUNIT_TEST(testSmartartRotation2);
+ CPPUNIT_TEST(testAccentColor);
CPPUNIT_TEST_SUITE_END();
@@ -840,6 +842,23 @@ void SdOOXMLExportTest2::testSmartartRotation2()
assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/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 178261b7e449..c38be6881d2c 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;
@@ -92,6 +94,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);
+ static 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 03ddcd056e3f..0ac4d87f6dbf 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>
@@ -28,6 +30,7 @@
#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/factory.hxx>
+#include <comphelper/sequenceashashmap.hxx>
#include <sax/fshelper.hxx>
#include <rtl/ustrbuf.hxx>
#include <filter/msfilter/escherex.hxx>
@@ -67,6 +70,7 @@
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
// presentation namespaces
+#define DMLNS "http://schemas.openxmlformats.org/drawingml/2006/main"
#define PNMSS FSNS(XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main", \
FSNS(XML_xmlns, XML_p), "http://schemas.openxmlformats.org/presentationml/2006/main", \
FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships", \
@@ -1958,46 +1962,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\"/>\
@@ -2174,25 +2146,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), OString(DMLNS),
+ 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()