include/oox/drawingml/theme.hxx | 12 +- include/svx/ColorSets.hxx | 149 ++++++++++++++++++++++++++ oox/inc/drawingml/textfont.hxx | 3 oox/source/drawingml/textfont.cxx | 9 + oox/source/drawingml/theme.cxx | 69 +++++++++++- oox/source/drawingml/themeelementscontext.cxx | 23 ++-- svx/CppunitTest_svx_unit.mk | 1 svx/qa/unit/ThemeTest.cxx | 40 ++++++ 8 files changed, 295 insertions(+), 11 deletions(-)
New commits: commit d5a71bc6a28f8a3d726b2ac4688c7cef9d77ddf0 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Mon Dec 12 22:12:58 2022 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Sun Jan 1 23:34:32 2023 +0000 oox: add support for importing font scheme into a svx::Theme Change-Id: I862256a17ce84c85174678f3fd03c8ef6661f2c5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143995 Tested-by: Tomaž Vajngerl <qui...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/include/oox/drawingml/theme.hxx b/include/oox/drawingml/theme.hxx index f7b4a262ffb8..ebd05957bf3b 100644 --- a/include/oox/drawingml/theme.hxx +++ b/include/oox/drawingml/theme.hxx @@ -35,8 +35,12 @@ namespace com::sun::star { namespace drawing { class XDrawPage; } namespace xml::dom { class XDocument; } } +namespace svx { + class Theme; +} -namespace oox::drawingml { +namespace oox::drawingml +{ struct EffectProperties; struct FillProperties; @@ -82,6 +86,10 @@ public: FontScheme& getFontScheme() { return maFontScheme; } const FontScheme& getFontScheme() const { return maFontScheme; } + + std::map<sal_Int32, std::vector<std::pair<OUString, OUString>>>& getSupplementalFontMap() { return maSupplementalFontMap; } + std::map<sal_Int32, std::vector<std::pair<OUString, OUString>>> const& getSupplementalFontMap() const { return maSupplementalFontMap; } + /** Returns theme font properties by scheme type (major/minor). */ const TextCharacterProperties* getFontStyle( sal_Int32 nSchemeType ) const; /** Returns theme font by placeholder name, e.g. the major latin theme font for the font name '+mj-lt'. */ @@ -99,6 +107,7 @@ public: const css::uno::Reference<css::xml::dom::XDocument>& getFragment() const { return mxFragment; } void setFragment( const css::uno::Reference< css::xml::dom::XDocument>& xRef ) { mxFragment=xRef; } + std::unique_ptr<svx::Theme> createSvxTheme() const; void addTheme(const css::uno::Reference<css::drawing::XDrawPage>& xDrawPage) const; private: @@ -111,6 +120,7 @@ private: LineStyleList maLineStyleList; EffectStyleList maEffectStyleList; FontScheme maFontScheme; + std::map<sal_Int32, std::vector<std::pair<OUString, OUString>>> maSupplementalFontMap; Shape maSpDef; Shape maLnDef; Shape maTxDef; diff --git a/include/svx/ColorSets.hxx b/include/svx/ColorSets.hxx index 47e1d8866e5d..718b79b3e66c 100644 --- a/include/svx/ColorSets.hxx +++ b/include/svx/ColorSets.hxx @@ -101,6 +101,146 @@ public: const ColorSet& getColorSet(std::u16string_view rName); }; +struct SVXCORE_DLLPUBLIC ThemeSupplementalFont +{ + OUString maScript; + OUString maTypeface; +}; + +struct SVXCORE_DLLPUBLIC ThemeFont +{ + OUString maTypeface; + OUString maPanose; + sal_Int16 maPitch; + sal_Int16 maFamily; + sal_Int32 maCharset; + + sal_Int16 getPitchFamily() const + { + return (maPitch & 0x0F) | (maFamily & 0x0F) << 4; + } +}; + +class SVXCORE_DLLPUBLIC FontScheme +{ +private: + OUString maName; + + ThemeFont maMinorLatin; + ThemeFont maMinorAsian; + ThemeFont maMinorComplex; + + ThemeFont maMajorLatin; + ThemeFont maMajorAsian; + ThemeFont maMajorComplex; + + std::vector<ThemeSupplementalFont> maMinorSupplementalFontList; + std::vector<ThemeSupplementalFont> maMajorSupplementalFontList; + +public: + FontScheme() = default; + FontScheme(OUString const& rName) + : maName(rName) + {} + + const OUString& getName() const + { + return maName; + } + + ThemeFont const& getMinorLatin() const + { + return maMinorLatin; + } + void setMinorLatin(ThemeFont const& aMinor) + { + maMinorLatin = aMinor; + } + + ThemeFont const& getMinorAsian() const + { + return maMinorAsian; + } + void setMinorAsian(ThemeFont const& aMinor) + { + maMinorAsian = aMinor; + } + + ThemeFont const& getMinorComplex() const + { + return maMinorComplex; + } + void setMinorComplex(ThemeFont const& aMinor) + { + maMinorComplex = aMinor; + } + + ThemeFont const& getMajorLatin() const + { + return maMajorLatin; + } + void setMajorLatin(ThemeFont const& aMajor) + { + maMajorLatin = aMajor; + } + + ThemeFont const& getMajorAsian() const + { + return maMajorAsian; + } + void setMajorAsian(ThemeFont const& aMajor) + { + maMajorAsian = aMajor; + } + + ThemeFont const& getMajorComplex() const + { + return maMajorComplex; + } + void setMajorComplex(ThemeFont const& aMajor) + { + maMajorComplex = aMajor; + } + + OUString findMinorSupplementalTypeface(std::u16string_view rScript) const + { + for (auto const& rSupplementalFont : maMinorSupplementalFontList) + { + if (rSupplementalFont.maScript == rScript) + return rSupplementalFont.maTypeface; + } + return OUString(); + } + + std::vector<ThemeSupplementalFont> const& getMinorSupplementalFontList() const + { + return maMinorSupplementalFontList; + } + void setMinorSupplementalFontList(std::vector<ThemeSupplementalFont> const& rSupplementalFont) + { + maMinorSupplementalFontList = rSupplementalFont; + } + + OUString findMajorSupplementalTypeface(std::u16string_view rScript) const + { + for (auto const& rSupplementalFont : maMajorSupplementalFontList) + { + if (rSupplementalFont.maScript == rScript) + return rSupplementalFont.maTypeface; + } + return OUString(); + } + + std::vector<ThemeSupplementalFont> const& getMajorSupplementalFontList() const + { + return maMajorSupplementalFontList; + } + void setMajorSupplementalFontList(std::vector<ThemeSupplementalFont> const& rSupplementalFont) + { + maMajorSupplementalFontList = rSupplementalFont; + } +}; + /// A named theme has a named color set. class SVXCORE_DLLPUBLIC Theme { @@ -108,9 +248,18 @@ private: OUString maName; std::unique_ptr<ColorSet> mpColorSet; + FontScheme maFontScheme; + public: Theme(OUString const& rName); + void setFontScheme(FontScheme const& rFontScheme) + { + maFontScheme = rFontScheme; + } + + FontScheme const& getFontScheme() const { return maFontScheme; } + void SetColorSet(std::unique_ptr<ColorSet> pColorSet); const ColorSet* GetColorSet() const; ColorSet* GetColorSet(); diff --git a/oox/inc/drawingml/textfont.hxx b/oox/inc/drawingml/textfont.hxx index 231b18cffecb..3847ed8c61be 100644 --- a/oox/inc/drawingml/textfont.hxx +++ b/oox/inc/drawingml/textfont.hxx @@ -24,6 +24,7 @@ namespace oox { class AttributeList; } namespace oox::core { class XmlFilterBase; } +namespace svx { struct ThemeFont; } namespace oox::drawingml { @@ -51,6 +52,8 @@ public: sal_Int16& rnFontFamily, const ::oox::core::XmlFilterBase& rFilter ) const; + void fillThemeFont(svx::ThemeFont& rThemeFont) const; + static void resolvePitch(sal_Int32 nOoxPitch, sal_Int16& rnFontPitch, sal_Int16& rnFontFamily); private: diff --git a/oox/source/drawingml/textfont.cxx b/oox/source/drawingml/textfont.cxx index e5899780ad2c..c531ef7ffba6 100644 --- a/oox/source/drawingml/textfont.cxx +++ b/oox/source/drawingml/textfont.cxx @@ -24,6 +24,7 @@ #include <oox/core/xmlfilterbase.hxx> #include <oox/helper/attributelist.hxx> #include <oox/token/tokens.hxx> +#include <svx/ColorSets.hxx> using ::oox::core::XmlFilterBase; @@ -90,6 +91,14 @@ bool TextFont::implGetFontData( OUString& rFontName, sal_Int16& rnFontPitch, sal return !rFontName.isEmpty(); } +void TextFont::fillThemeFont(svx::ThemeFont& rThemeFont) const +{ + rThemeFont.maTypeface = maTypeface; + rThemeFont.maPanose = maPanose; + rThemeFont.maCharset = mnCharset; + resolvePitch(mnPitchFamily, rThemeFont.maPitch, rThemeFont.maFamily); +} + void TextFont::resolvePitch(sal_Int32 nOoxPitchFamily, sal_Int16& rnFontPitch, sal_Int16& rnFontFamily) { rnFontPitch = lclGetFontPitch(extractValue<sal_Int16>(nOoxPitchFamily, 0, 4)); diff --git a/oox/source/drawingml/theme.cxx b/oox/source/drawingml/theme.cxx index 885d87b1bb0f..dfa81feaff0d 100644 --- a/oox/source/drawingml/theme.cxx +++ b/oox/source/drawingml/theme.cxx @@ -108,6 +108,70 @@ const TextFont* Theme::resolveFont( std::u16string_view rName ) const return nullptr; } +std::unique_ptr<svx::Theme> Theme::createSvxTheme() const +{ + auto pTheme = std::make_unique<svx::Theme>(maThemeName); + auto pColorSet = std::make_unique<svx::ColorSet>(maClrScheme.GetName()); + maClrScheme.fill(*pColorSet); + pTheme->SetColorSet(std::move(pColorSet)); + + svx::FontScheme aFontScheme(maFontSchemeName); + + if (auto* pCharProps = getFontStyle(XML_minor)) + { + svx::ThemeFont aMinorLatin; + pCharProps->maLatinFont.fillThemeFont(aMinorLatin); + aFontScheme.setMinorLatin(aMinorLatin); + + svx::ThemeFont aMinorAsian; + pCharProps->maAsianFont.fillThemeFont(aMinorAsian); + aFontScheme.setMinorAsian(aMinorAsian); + + svx::ThemeFont aMinorComplex; + pCharProps->maComplexFont.fillThemeFont(aMinorComplex); + aFontScheme.setMinorComplex(aMinorComplex); + } + + if (auto* pCharProps = getFontStyle(XML_major)) + { + svx::ThemeFont aMajorLatin; + pCharProps->maLatinFont.fillThemeFont(aMajorLatin); + aFontScheme.setMajorLatin(aMajorLatin); + + svx::ThemeFont aMajorAsian; + pCharProps->maAsianFont.fillThemeFont(aMajorAsian); + aFontScheme.setMajorAsian(aMajorAsian); + + svx::ThemeFont aMajorComplex; + pCharProps->maComplexFont.fillThemeFont(aMajorComplex); + aFontScheme.setMajorComplex(aMajorComplex); + } + + if (maSupplementalFontMap.find(XML_minor) != maSupplementalFontMap.cend()) + { + std::vector<svx::ThemeSupplementalFont> aList; + for (auto const& [rScript, rTypeface] : maSupplementalFontMap.at(XML_minor)) + { + aList.push_back(svx::ThemeSupplementalFont{rScript, rTypeface}); + } + aFontScheme.setMinorSupplementalFontList(aList); + } + + if (maSupplementalFontMap.find(XML_major) != maSupplementalFontMap.cend()) + { + std::vector<svx::ThemeSupplementalFont> aList; + for (auto const& [rScript, rTypeface] : maSupplementalFontMap.at(XML_major)) + { + aList.push_back(svx::ThemeSupplementalFont{rScript, rTypeface}); + } + aFontScheme.setMajorSupplementalFontList(aList); + } + + pTheme->setFontScheme(aFontScheme); + + return pTheme; +} + void Theme::addTheme(const css::uno::Reference<css::drawing::XDrawPage>& xDrawPage) const { SAL_WARN_IF(!xDrawPage.is(), "oox", "DrawPage is not set"); @@ -119,10 +183,7 @@ void Theme::addTheme(const css::uno::Reference<css::drawing::XDrawPage>& xDrawPa if (!pPage) return; - auto pTheme = std::make_unique<svx::Theme>(maThemeName); - auto pColorSet = std::make_unique<svx::ColorSet>(maClrScheme.GetName()); - maClrScheme.fill(*pColorSet); - pTheme->SetColorSet(std::move(pColorSet)); + std::unique_ptr<svx::Theme> pTheme = createSvxTheme(); pPage->getSdrPageProperties().SetTheme(std::move(pTheme)); } diff --git a/oox/source/drawingml/themeelementscontext.cxx b/oox/source/drawingml/themeelementscontext.cxx index 2cb9d12ab020..cb62f4ef0a70 100644 --- a/oox/source/drawingml/themeelementscontext.cxx +++ b/oox/source/drawingml/themeelementscontext.cxx @@ -145,20 +145,25 @@ namespace { class FontSchemeContext : public ContextHandler2 { public: - FontSchemeContext( ContextHandler2Helper const & rParent, FontScheme& rFontScheme ); + FontSchemeContext(ContextHandler2Helper const & rParent, FontScheme& rFontScheme, + std::map<sal_Int32, std::vector<std::pair<OUString, OUString>>>& rSupplementalFontMap); virtual ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) override; virtual void onEndElement() override; private: FontScheme& mrFontScheme; TextCharacterPropertiesPtr mxCharProps; + std::map<sal_Int32, std::vector<std::pair<OUString, OUString>>>& mrSupplementalFontMap; + sal_Int32 maCurrentFont = 0; }; } -FontSchemeContext::FontSchemeContext( ContextHandler2Helper const & rParent, FontScheme& rFontScheme ) : - ContextHandler2( rParent ), - mrFontScheme( rFontScheme ) +FontSchemeContext::FontSchemeContext(ContextHandler2Helper const & rParent, FontScheme& rFontScheme, + std::map<sal_Int32, std::vector<std::pair<OUString, OUString>>>& rSupplementalFontMap) + : ContextHandler2(rParent) + , mrFontScheme(rFontScheme) + , mrSupplementalFontMap(rSupplementalFontMap) { } @@ -169,12 +174,13 @@ ContextHandlerRef FontSchemeContext::onCreateContext( sal_Int32 nElement, const case A_TOKEN( majorFont ): mxCharProps = std::make_shared<TextCharacterProperties>(); mrFontScheme[ XML_major ] = mxCharProps; + maCurrentFont = XML_major; return this; case A_TOKEN( minorFont ): mxCharProps = std::make_shared<TextCharacterProperties>(); mrFontScheme[ XML_minor ] = mxCharProps; + maCurrentFont = XML_minor; return this; - case A_TOKEN( latin ): if( mxCharProps ) mxCharProps->maLatinFont.setAttributes( rAttribs ); @@ -187,6 +193,11 @@ ContextHandlerRef FontSchemeContext::onCreateContext( sal_Int32 nElement, const if( mxCharProps ) mxCharProps->maComplexFont.setAttributes( rAttribs ); break; + case A_TOKEN(font): + OUString aScript = rAttribs.getStringDefaulted(XML_script); + OUString aTypeface = rAttribs.getStringDefaulted(XML_typeface); + mrSupplementalFontMap[maCurrentFont].emplace_back(std::pair<OUString, OUString>{aScript, aTypeface}); + break; } return nullptr; } @@ -223,7 +234,7 @@ ContextHandlerRef ThemeElementsContext::onCreateContext( sal_Int32 nElement, con { if (rAttribs.hasAttribute(XML_name)) mrTheme.setFontSchemeName(rAttribs.getStringDefaulted(XML_name)); - return new FontSchemeContext(*this, mrTheme.getFontScheme()); + return new FontSchemeContext(*this, mrTheme.getFontScheme(), mrTheme.getSupplementalFontMap()); } case A_TOKEN( fmtScheme ): // CT_StyleMatrix diff --git a/svx/CppunitTest_svx_unit.mk b/svx/CppunitTest_svx_unit.mk index 9f22c2adba11..678a27322e02 100644 --- a/svx/CppunitTest_svx_unit.mk +++ b/svx/CppunitTest_svx_unit.mk @@ -33,6 +33,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,svx_unit, \ svx/qa/unit/xoutdev \ svx/qa/unit/xml \ svx/qa/unit/XTableImportExportTest \ + svx/qa/unit/ThemeTest \ )) $(eval $(call gb_CppunitTest_use_libraries,svx_unit, \ diff --git a/svx/qa/unit/ThemeTest.cxx b/svx/qa/unit/ThemeTest.cxx new file mode 100644 index 000000000000..757561b1bd17 --- /dev/null +++ b/svx/qa/unit/ThemeTest.cxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <config_features.h> + +#include <svx/ColorSets.hxx> + +namespace +{ +class ThemeTest : public CppUnit::TestFixture +{ +}; + +CPPUNIT_TEST_FIXTURE(ThemeTest, testPitchFamilyConversion) +{ + svx::ThemeFont aFont; + aFont.maPitch = 2; + aFont.maFamily = 1; + + CPPUNIT_ASSERT_EQUAL(sal_Int16(0x12), aFont.getPitchFamily()); + + aFont.maPitch = sal_Int16(0x7FF2); // only lower 4-bit + aFont.maFamily = sal_Int16(0x7FF3); // only lower 4-bit + + CPPUNIT_ASSERT_EQUAL(sal_Int16(0x32), aFont.getPitchFamily()); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */