diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2023-03-23 11:37:40 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2023-04-24 23:49:57 +0200 |
commit | c3f7720ff13c34b9cf2c90d9c9b6dcc3d8f4c7a5 (patch) | |
tree | 98b24e4e90c0d858307b58bcd09c9b2d590893e8 /sd | |
parent | 09cdcb5f37bb4e42da7b28db6e757b9f2affed14 (diff) |
oox: extend ThemeExport to export font and format scheme of a theme
Also use the ThemeExport when exporting PPTX documents and remove
all the hard-coded theme bits.
Change-Id: I03791e23d6ac4023748b5a553e4824b72ed63a93
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149363
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'sd')
-rw-r--r-- | sd/qa/filter/eppt/eppt.cxx | 85 | ||||
-rw-r--r-- | sd/source/filter/eppt/epptooxml.hxx | 7 | ||||
-rw-r--r-- | sd/source/filter/eppt/pptx-epptooxml.cxx | 316 |
3 files changed, 58 insertions, 350 deletions
diff --git a/sd/qa/filter/eppt/eppt.cxx b/sd/qa/filter/eppt/eppt.cxx index 32d9b330a1dc..f5420a637751 100644 --- a/sd/qa/filter/eppt/eppt.cxx +++ b/sd/qa/filter/eppt/eppt.cxx @@ -12,6 +12,8 @@ #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/drawing/XDrawPagesSupplier.hpp> #include <com/sun/star/drawing/XMasterPageTarget.hpp> +#include <com/sun/star/util/Color.hpp> +#include <com/sun/star/util/XTheme.hpp> #include <test/xmldocptr.hxx> #include <docmodel/uno/UnoTheme.hxx> @@ -56,40 +58,57 @@ CPPUNIT_TEST_FIXTURE(Test, testThemeExport) { // Given a document with a master slide and a theme, lt1 is set to 0x000002: mxComponent = loadFromDesktop("private:factory/simpress"); - uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<drawing::XMasterPageTarget> xDrawPage( - xDrawPagesSupplier->getDrawPages()->getByIndex(0), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> xMasterPage(xDrawPage->getMasterPage(), uno::UNO_QUERY); - - auto pTheme = std::make_shared<model::Theme>("mytheme"); - std::unique_ptr<model::ColorSet> pColorSet(new model::ColorSet("mycolorscheme")); - pColorSet->add(model::ThemeColorType::Dark1, 0x1); - pColorSet->add(model::ThemeColorType::Light1, 0x2); - pColorSet->add(model::ThemeColorType::Dark2, 0x3); - pColorSet->add(model::ThemeColorType::Light2, 0x4); - pColorSet->add(model::ThemeColorType::Accent1, 0x5); - pColorSet->add(model::ThemeColorType::Accent2, 0x6); - pColorSet->add(model::ThemeColorType::Accent3, 0x7); - pColorSet->add(model::ThemeColorType::Accent4, 0x8); - pColorSet->add(model::ThemeColorType::Accent5, 0x9); - pColorSet->add(model::ThemeColorType::Accent6, 0xa); - pColorSet->add(model::ThemeColorType::Hyperlink, 0xb); - pColorSet->add(model::ThemeColorType::FollowedHyperlink, 0xc); - pTheme->SetColorSet(std::move(pColorSet)); - - xMasterPage->setPropertyValue("Theme", uno::Any(model::theme::createXTheme(pTheme))); - - // When exporting to PPTX: - save("Impress Office Open XML"); - - // Then verify that this color is not lost: + { + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<drawing::XMasterPageTarget> xDrawPage( + xDrawPagesSupplier->getDrawPages()->getByIndex(0), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xMasterPage(xDrawPage->getMasterPage(), uno::UNO_QUERY); + + auto pTheme = std::make_shared<model::Theme>("mytheme"); + std::unique_ptr<model::ColorSet> pColorSet(new model::ColorSet("mycolorscheme")); + pColorSet->add(model::ThemeColorType::Dark1, 0x111111); + pColorSet->add(model::ThemeColorType::Light1, 0x222222); + pColorSet->add(model::ThemeColorType::Dark2, 0x333333); + pColorSet->add(model::ThemeColorType::Light2, 0x444444); + pColorSet->add(model::ThemeColorType::Accent1, 0x555555); + pColorSet->add(model::ThemeColorType::Accent2, 0x666666); + pColorSet->add(model::ThemeColorType::Accent3, 0x777777); + pColorSet->add(model::ThemeColorType::Accent4, 0x888888); + pColorSet->add(model::ThemeColorType::Accent5, 0x999999); + pColorSet->add(model::ThemeColorType::Accent6, 0xaaaaaa); + pColorSet->add(model::ThemeColorType::Hyperlink, 0xbbbbbb); + pColorSet->add(model::ThemeColorType::FollowedHyperlink, 0xcccccc); + pTheme->SetColorSet(std::move(pColorSet)); + + xMasterPage->setPropertyValue("Theme", uno::Any(model::theme::createXTheme(pTheme))); + } + + // Export to PPTX and load again: + saveAndReload("Impress Office Open XML"); + + // Verify that this color is not lost: xmlDocUniquePtr pXmlDoc = parseExport("ppt/theme/theme1.xml"); - assertXPath(pXmlDoc, "//a:clrScheme/a:lt1/a:srgbClr", "val", "000002"); - // Without the fix in place, this test would have failed with: - // - Expected: 1 - // - Actual : 0 - // - XPath '//a:clrScheme/a:lt1/a:srgbClr' number of nodes is incorrect - // i.e. the RGB color was lost on export. + assertXPath(pXmlDoc, "//a:clrScheme/a:lt1/a:srgbClr", "val", + "222222"); // expected color 22-22-22 + + // Check the theme after loading again + { + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<drawing::XMasterPageTarget> xDrawPage( + xDrawPagesSupplier->getDrawPages()->getByIndex(0), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xMasterPage(xDrawPage->getMasterPage(), uno::UNO_QUERY); + uno::Reference<util::XTheme> xTheme(xMasterPage->getPropertyValue("Theme"), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(true, xTheme.is()); + + auto* pUnoTheme = dynamic_cast<UnoTheme*>(xTheme.get()); + CPPUNIT_ASSERT(pUnoTheme); + auto pTheme = pUnoTheme->getTheme(); + + CPPUNIT_ASSERT_EQUAL(OUString("mytheme"), pTheme->GetName()); + CPPUNIT_ASSERT_EQUAL(OUString("mycolorscheme"), pTheme->GetColorSet()->getName()); + CPPUNIT_ASSERT_EQUAL(OUString("Office"), pTheme->getFontScheme().getName()); + CPPUNIT_ASSERT_EQUAL(OUString(""), pTheme->getFormatScheme().getName()); + } } CPPUNIT_TEST_FIXTURE(Test, testLoopingFromAnimation) diff --git a/sd/source/filter/eppt/epptooxml.hxx b/sd/source/filter/eppt/epptooxml.hxx index 48c928d60abb..0c7644c72b3d 100644 --- a/sd/source/filter/eppt/epptooxml.hxx +++ b/sd/source/filter/eppt/epptooxml.hxx @@ -90,13 +90,6 @@ private: virtual void ImplWriteNotes( sal_uInt32 nPageNum ) override; virtual void ImplWriteSlideMaster( sal_uInt32 nPageNum, css::uno::Reference< css::beans::XPropertySet > const & aXBackgroundPropSet ) override; void ImplWritePPTXLayout( sal_Int32 nOffset, sal_uInt32 nMasterNum ); - - /// Export the color set part of a theme. - static bool WriteColorSets(const FSHelperPtr& pFS, model::Theme* pTheme); - - /// Same as WriteColorSets(), but works from a grab-bag. - bool WriteColorSchemes(const FSHelperPtr& pFS, const OUString& rThemePath); - static void WriteDefaultColorSchemes(const FSHelperPtr& pFS); void WriteTheme( sal_Int32 nThemeNum, model::Theme* pTheme ); diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx index c0215ecca162..9e207baf1be6 100644 --- a/sd/source/filter/eppt/pptx-epptooxml.cxx +++ b/sd/source/filter/eppt/pptx-epptooxml.cxx @@ -56,6 +56,7 @@ #include <comphelper/diagnose_ex.hxx> #include <oox/export/utils.hxx> +#include <oox/export/ThemeExport.hxx> #include <docmodel/theme/Theme.hxx> #include "pptx-animations.hxx" @@ -1938,172 +1939,6 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderReferenceTextBody( return *this; } -#define SYS_COLOR_SCHEMES " <a:dk1>\ - <a:sysClr val=\"windowText\" lastClr=\"000000\"/>\ - </a:dk1>\ - <a:lt1>\ - <a:sysClr val=\"window\" lastClr=\"FFFFFF\"/>\ - </a:lt1>" - -#define MINIMAL_THEME " <a:fontScheme name=\"Office\">\ - <a:majorFont>\ - <a:latin typeface=\"Arial\"/>\ - <a:ea typeface=\"DejaVu Sans\"/>\ - <a:cs typeface=\"DejaVu Sans\"/>\ - </a:majorFont>\ - <a:minorFont>\ - <a:latin typeface=\"Arial\"/>\ - <a:ea typeface=\"DejaVu Sans\"/>\ - <a:cs typeface=\"DejaVu Sans\"/>\ - </a:minorFont>\ - </a:fontScheme>\ - <a:fmtScheme name=\"Office\">\ - <a:fillStyleLst>\ - <a:solidFill>\ - <a:schemeClr val=\"phClr\"/>\ - </a:solidFill>\ - <a:gradFill rotWithShape=\"1\">\ - <a:gsLst>\ - <a:gs pos=\"0\">\ - <a:schemeClr val=\"phClr\">\ - <a:tint val=\"50000\"/>\ - <a:satMod val=\"300000\"/>\ - </a:schemeClr>\ - </a:gs>\ - <a:gs pos=\"35000\">\ - <a:schemeClr val=\"phClr\">\ - <a:tint val=\"37000\"/>\ - <a:satMod val=\"300000\"/>\ - </a:schemeClr>\ - </a:gs>\ - <a:gs pos=\"100000\">\ - <a:schemeClr val=\"phClr\">\ - <a:tint val=\"15000\"/>\ - <a:satMod val=\"350000\"/>\ - </a:schemeClr>\ - </a:gs>\ - </a:gsLst>\ - <a:lin ang=\"16200000\" scaled=\"1\"/>\ - </a:gradFill>\ - <a:gradFill rotWithShape=\"1\">\ - <a:gsLst>\ - <a:gs pos=\"0\">\ - <a:schemeClr val=\"phClr\">\ - <a:shade val=\"51000\"/>\ - <a:satMod val=\"130000\"/>\ - </a:schemeClr>\ - </a:gs>\ - <a:gs pos=\"80000\">\ - <a:schemeClr val=\"phClr\">\ - <a:shade val=\"93000\"/>\ - <a:satMod val=\"130000\"/>\ - </a:schemeClr>\ - </a:gs>\ - <a:gs pos=\"100000\">\ - <a:schemeClr val=\"phClr\">\ - <a:shade val=\"94000\"/>\ - <a:satMod val=\"135000\"/>\ - </a:schemeClr>\ - </a:gs>\ - </a:gsLst>\ - <a:lin ang=\"16200000\" scaled=\"0\"/>\ - </a:gradFill>\ - </a:fillStyleLst>\ - <a:lnStyleLst>\ - <a:ln w=\"6350\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\ - <a:solidFill>\ - <a:schemeClr val=\"phClr\">\ - <a:shade val=\"95000\"/>\ - <a:satMod val=\"105000\"/>\ - </a:schemeClr>\ - </a:solidFill>\ - <a:prstDash val=\"solid\"/>\ - <a:miter/>\ - </a:ln>\ - <a:ln w=\"12700\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\ - <a:solidFill>\ - <a:schemeClr val=\"phClr\"/>\ - </a:solidFill>\ - <a:prstDash val=\"solid\"/>\ - <a:miter/>\ - </a:ln>\ - <a:ln w=\"19050\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\ - <a:solidFill>\ - <a:schemeClr val=\"phClr\"/>\ - </a:solidFill>\ - <a:prstDash val=\"solid\"/>\ - <a:miter/>\ - </a:ln>\ - </a:lnStyleLst>\ - <a:effectStyleLst>\ - <a:effectStyle>\ - <a:effectLst/>\ - </a:effectStyle>\ - <a:effectStyle>\ - <a:effectLst/>\ - </a:effectStyle>\ - <a:effectStyle>\ - <a:effectLst>\ - <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\ - <a:srgbClr val=\"000000\">\ - <a:alpha val=\"35000\"/>\ - </a:srgbClr>\ - </a:outerShdw>\ - </a:effectLst>\ - </a:effectStyle>\ - </a:effectStyleLst>\ - <a:bgFillStyleLst>\ - <a:solidFill>\ - <a:schemeClr val=\"phClr\"/>\ - </a:solidFill>\ - <a:gradFill rotWithShape=\"1\">\ - <a:gsLst>\ - <a:gs pos=\"0\">\ - <a:schemeClr val=\"phClr\">\ - <a:tint val=\"40000\"/>\ - <a:satMod val=\"350000\"/>\ - </a:schemeClr>\ - </a:gs>\ - <a:gs pos=\"40000\">\ - <a:schemeClr val=\"phClr\">\ - <a:tint val=\"45000\"/>\ - <a:shade val=\"99000\"/>\ - <a:satMod val=\"350000\"/>\ - </a:schemeClr>\ - </a:gs>\ - <a:gs pos=\"100000\">\ - <a:schemeClr val=\"phClr\">\ - <a:shade val=\"20000\"/>\ - <a:satMod val=\"255000\"/>\ - </a:schemeClr>\ - </a:gs>\ - </a:gsLst>\ - <a:path path=\"circle\">\ - <a:fillToRect l=\"50000\" t=\"-80000\" r=\"50000\" b=\"180000\"/>\ - </a:path>\ - </a:gradFill>\ - <a:gradFill rotWithShape=\"1\">\ - <a:gsLst>\ - <a:gs pos=\"0\">\ - <a:schemeClr val=\"phClr\">\ - <a:tint val=\"80000\"/>\ - <a:satMod val=\"300000\"/>\ - </a:schemeClr>\ - </a:gs>\ - <a:gs pos=\"100000\">\ - <a:schemeClr val=\"phClr\">\ - <a:shade val=\"30000\"/>\ - <a:satMod val=\"200000\"/>\ - </a:schemeClr>\ - </a:gs>\ - </a:gsLst>\ - <a:path path=\"circle\">\ - <a:fillToRect l=\"50000\" t=\"50000\" r=\"50000\" b=\"50000\"/>\ - </a:path>\ - </a:gradFill>\ - </a:bgFillStyleLst>\ - </a:fmtScheme>" - void PowerPointExport::WriteDefaultColorSchemes(const FSHelperPtr& pFS) { for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++) @@ -2155,155 +1990,15 @@ void PowerPointExport::WriteDefaultColorSchemes(const FSHelperPtr& pFS) } } -bool PowerPointExport::WriteColorSets(const FSHelperPtr& pFS, model::Theme* pTheme) -{ - static std::map<PredefinedClrSchemeId, sal_Int32> aPredefinedClrTokens = - { - { 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 } - }; - - if (!pTheme) - { - return false; - } - - model::ColorSet* pColorSet = pTheme->GetColorSet(); - if (!pColorSet) - { - return false; - } - - for (int nId = PredefinedClrSchemeId::dk1; nId < PredefinedClrSchemeId::Count; nId++) - { - sal_Int32 nToken = aPredefinedClrTokens[static_cast<PredefinedClrSchemeId>(nId)]; - pFS->startElementNS(XML_a, nToken); - model::ThemeColorType eType = model::convertToThemeColorType(nId); - pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(static_cast<sal_Int32>(pColorSet->getColor(eType)))); - pFS->endElementNS(XML_a, nToken); - } - - return true; -} - -bool PowerPointExport::WriteColorSchemes(const 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(); - - static const OUStringLiteral aGrabBagPropName = u"InteropGrabBag"; - if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName)) - { - comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName)); - uno::Sequence<beans::PropertyValue> aCurrentTheme; - - aGrabBag.getValue(rThemePath) >>= aCurrentTheme; - - if (!aCurrentTheme.hasElements()) - return false; - - // 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 = std::cbegin(aCurrentTheme); aIt != std::cend(aCurrentTheme); aIt++) - { - if (aIt->Name == sName) - { - aIt->Value >>= nColor; - break; - } - } - - OUString sOpenColorScheme ="<a:" + sName + ">"; - pFS->write(sOpenColorScheme); - - pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor)); - - OUString sCloseColorScheme = "</a:" + sName + ">"; - 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, model::Theme* pTheme) { + if (!pTheme) + return; OUString sThemePath = "ppt/theme/theme" + OUString::number(nThemeNum + 1) + ".xml"; - FSHelperPtr pFS = openFragmentStreamWithSerializer(sThemePath, - "application/vnd.openxmlformats-officedocument.theme+xml"); - - OUString aThemeName("Office Theme"); - if (pTheme) - { - aThemeName = pTheme->GetName(); - } - pFS->startElementNS(XML_a, XML_theme, - FSNS(XML_xmlns, XML_a), this->getNamespaceURL(OOX_NS(dml)), - XML_name, aThemeName); - - pFS->startElementNS(XML_a, XML_themeElements); - OUString aColorSchemeName("Office"); - if (pTheme) - { - model::ColorSet* pColorSet = pTheme->GetColorSet(); - if (pColorSet) - { - aColorSchemeName = pColorSet->getName(); - } - } - pFS->startElementNS(XML_a, XML_clrScheme, XML_name, aColorSchemeName); + oox::ThemeExport aThemeExport(this); - if (!WriteColorSets(pFS, pTheme)) - { - pFS->write(SYS_COLOR_SCHEMES); - if (!WriteColorSchemes(pFS, sThemePath)) - { - // if style is not defined, try to use first one - if (!WriteColorSchemes(pFS, "ppt/theme/theme1.xml")) - { - // 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); - - pFS->endDocument(); + aThemeExport.write(sThemePath, *pTheme); } bool PowerPointExport::ImplCreateDocument() @@ -2344,6 +2039,7 @@ void PowerPointExport::WriteNotesMaster() openFragmentStreamWithSerializer("ppt/notesMasters/notesMaster1.xml", "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml"); // write theme per master + WriteTheme(mnMasterPages, nullptr); // add implicit relation to the presentation theme |