include/docmodel/theme/FormatScheme.hxx  |  132 ++++-
 include/docmodel/theme/Theme.hxx         |   23 
 include/oox/export/ThemeExport.hxx       |    4 
 include/oox/export/drawingml.hxx         |   94 +++
 oox/source/export/ThemeExport.cxx        |  757 ++++++++++++++++++++++++++++---
 oox/source/export/drawingml.cxx          |   90 +--
 sc/source/filter/excel/xestream.cxx      |    7 
 sd/qa/filter/eppt/eppt.cxx               |   85 ++-
 sd/source/filter/eppt/epptooxml.hxx      |    7 
 sd/source/filter/eppt/pptx-epptooxml.cxx |  324 -------------
 svx/source/svdraw/svdpage.cxx            |    4 
 sw/source/filter/ww8/docxexport.cxx      |    7 
 12 files changed, 1028 insertions(+), 506 deletions(-)

New commits:
commit 0ee38e7e061f764b5e21487da090620ed93bb260
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Mon Apr 10 12:15:19 2023 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Mon Apr 24 23:50:05 2023 +0200

    oox: combine graphic cache into GraphicExportCache class
    
    We cache graphics to not export the same graphic multiple times
    if this can be avoided. The cache was integrated into DrawingML
    but we need access to it in different places, so this change
    extracts it into its own class.
    
    Change-Id: I71e3b67906f2948ca00c2ef7ca857bf80ab6a737
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150258
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index 946afbf5d57b..8fb8d6ba2e52 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -139,16 +139,99 @@ protected:
     virtual ~DMLTextExport() {}
 };
 
+class OOX_DLLPUBLIC GraphicExportCache
+{
+private:
+    std::stack<sal_Int32> mnImageCounter;
+    std::stack<std::unordered_map<BitmapChecksum, OUString>> maExportGraphics;
+    std::stack<sal_Int32> mnWdpImageCounter;
+    std::stack<std::map<OUString, OUString>> maWdpCache;
+
+    GraphicExportCache() = default;
+public:
+    static GraphicExportCache& get();
+
+    void push()
+    {
+        mnImageCounter.push(1);
+        maExportGraphics.emplace();
+        mnWdpImageCounter.push(1);
+        maWdpCache.emplace();
+    }
+
+    void pop()
+    {
+        mnImageCounter.pop();
+        maExportGraphics.pop();
+        mnWdpImageCounter.pop();
+        maWdpCache.pop();
+    }
+
+    bool hasExportGraphics()
+    {
+        return !maExportGraphics.empty();
+    }
+
+    void addExportGraphics(BitmapChecksum aChecksum, OUString const& sPath)
+    {
+        maExportGraphics.top()[aChecksum] = sPath;
+    }
+
+    OUString findExportGraphics(BitmapChecksum aChecksum)
+    {
+        OUString sPath;
+        if (!hasExportGraphics())
+            return sPath;
+
+        auto aIterator = maExportGraphics.top().find(aChecksum);
+        if (aIterator != maExportGraphics.top().end())
+            sPath = aIterator->second;
+        return sPath;
+    }
+
+    sal_Int32 nextImageCount()
+    {
+        sal_Int32 nCount = mnImageCounter.top();
+        mnImageCounter.top()++;
+        return nCount;
+    }
+
+    bool hasWdpCache()
+    {
+        return !maWdpCache.empty();
+    }
+
+    OUString findWdpID(OUString const& rFileId)
+    {
+        OUString aPath;
+        if (!hasWdpCache())
+            return aPath;
+        auto aCachedItem = maWdpCache.top().find(rFileId);
+        if (aCachedItem != maWdpCache.top().end())
+            aPath = aCachedItem->second;
+        return aPath;
+    }
+
+    void addToWdpCache(OUString const& rFileId, OUString const& rId)
+    {
+        if (hasWdpCache())
+            maWdpCache.top()[rFileId] = rId;
+    }
+
+    sal_Int32 nextWdpImageCount()
+    {
+        sal_Int32 nCount = mnWdpImageCounter.top();
+        mnWdpImageCounter.top()++;
+        return nCount;
+    }
+};
+
 class OOX_DLLPUBLIC DrawingML
 {
 
 private:
-    static std::stack<sal_Int32> mnImageCounter;
-    static std::stack<sal_Int32> mnWdpImageCounter;
-    static std::stack<std::map<OUString, OUString>> maWdpCache;
     static sal_Int32 mnDrawingMLCount;
     static sal_Int32 mnVmlCount;
-    static std::stack<std::unordered_map<BitmapChecksum, OUString>> 
maExportGraphics;
 
     /// To specify where write eg. the images to (like 'ppt', or 'word' - 
according to the OPC).
     DocumentType meDocumentType;
@@ -371,9 +454,6 @@ public:
 
     static void ResetMlCounters();
 
-    static void PushExportGraphics();
-    static void PopExportGraphics();
-
     static sal_Int32 getNewDrawingUniqueId() { return ++mnDrawingMLCount; }
     static sal_Int32 getNewVMLUniqueId() { return ++mnVmlCount; }
     static sal_Int32 getNewChartUniqueId() { return ++mnChartCount; }
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 75541b084e3b..773aa6c4ae0c 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -209,6 +209,12 @@ bool URLTransformer::isExternalURL(const OUString& rURL) 
const
     return bExternal;
 }
 
+GraphicExportCache& GraphicExportCache::get()
+{
+    static GraphicExportCache staticGraphicExportCache;
+    return staticGraphicExportCache;
+}
+
 static css::uno::Any getLineDash( const 
css::uno::Reference<css::frame::XModel>& xModel, const OUString& rDashName )
     {
         css::uno::Reference<css::lang::XMultiServiceFactory> xFact(xModel, 
css::uno::UNO_QUERY);
@@ -253,13 +259,9 @@ void WriteGradientPath(const awt::Gradient2& rGradient, 
const FSHelperPtr& pFS,
 }
 
 // not thread safe
-std::stack<sal_Int32> DrawingML::mnImageCounter;
-std::stack<sal_Int32> DrawingML::mnWdpImageCounter;
-std::stack<std::map<OUString, OUString>> DrawingML::maWdpCache;
 sal_Int32 DrawingML::mnDrawingMLCount = 0;
 sal_Int32 DrawingML::mnVmlCount = 0;
 sal_Int32 DrawingML::mnChartCount = 0;
-std::stack<std::unordered_map<BitmapChecksum, OUString>> 
DrawingML::maExportGraphics;
 
 sal_Int16 DrawingML::GetScriptType(const OUString& rStr)
 {
@@ -292,24 +294,6 @@ void DrawingML::ResetMlCounters()
     mnChartCount = 0;
 }
 
-void DrawingML::PushExportGraphics()
-{
-    mnImageCounter.push(1);
-    maExportGraphics.emplace();
-
-    mnWdpImageCounter.push(1);
-    maWdpCache.emplace();
-}
-
-void DrawingML::PopExportGraphics()
-{
-    mnImageCounter.pop();
-    maExportGraphics.pop();
-
-    mnWdpImageCounter.pop();
-    maWdpCache.pop();
-}
-
 bool DrawingML::GetProperty( const Reference< XPropertySet >& rXPropertySet, 
const OUString& aName )
 {
     try
@@ -1515,12 +1499,8 @@ OUString DrawingML::WriteImage( const Graphic& rGraphic 
, bool bRelPathToMedia )
     OUString sPath;
 
     // tdf#74670 tdf#91286 Save image only once
-    if (!maExportGraphics.empty())
-    {
-        auto aIterator = maExportGraphics.top().find(aChecksum);
-        if (aIterator != maExportGraphics.top().end())
-            sPath = aIterator->second;
-    }
+    GraphicExportCache& rGraphicExportCache = GraphicExportCache::get();
+    sPath = rGraphicExportCache.findExportGraphics(aChecksum);
 
     if (sPath.isEmpty())
     {
@@ -1605,10 +1585,11 @@ OUString DrawingML::WriteImage( const Graphic& rGraphic 
, bool bRelPathToMedia )
             }
         }
 
+        sal_Int32 nImageCount = rGraphicExportCache.nextImageCount();
         Reference<XOutputStream> xOutStream = mpFB->openFragmentStream(
             OUStringBuffer()
                 .appendAscii(GetComponentDir())
-                .append("/media/image" + 
OUString::number(mnImageCounter.top()))
+                .append("/media/image" + OUString::number(nImageCount))
                 .appendAscii(pExtension)
                 .makeStringAndClear(),
             sMediaType);
@@ -1624,12 +1605,11 @@ OUString DrawingML::WriteImage( const Graphic& rGraphic 
, bool bRelPathToMedia )
         sPath = OUStringBuffer()
                     .appendAscii(sRelationCompPrefix.getStr())
                     .appendAscii(sRelPathToMedia.getStr())
-                    .append(static_cast<sal_Int32>(mnImageCounter.top()++))
+                    .append(nImageCount)
                     .appendAscii(pExtension)
                     .makeStringAndClear();
 
-        if (!maExportGraphics.empty())
-            maExportGraphics.top()[aChecksum] = sPath;
+        rGraphicExportCache.addExportGraphics(aChecksum, sPath);
     }
 
     sRelId = mpFB->addRelation( mpFS->getOutputStream(),
@@ -1704,14 +1684,15 @@ void DrawingML::WriteMediaNonVisualProperties(const 
css::uno::Reference<css::dra
 
     if (bEmbed)
     {
+        sal_Int32  nImageCount = GraphicExportCache::get().nextImageCount();
+
+        OUString sFileName = OUStringBuffer()
+            .appendAscii(GetComponentDir())
+            .append("/media/media" + OUString::number(nImageCount) + 
aExtension)
+            .makeStringAndClear();
+
         // copy the video stream
-        Reference<XOutputStream> xOutStream = 
mpFB->openFragmentStream(OUStringBuffer()
-                                                                       
.appendAscii(GetComponentDir())
-                                                                       
.append("/media/media" +
-                                                                            
OUString::number(mnImageCounter.top()) +
-                                                                            
aExtension)
-                                                                       
.makeStringAndClear(),
-                                                                       
aMimeType);
+        Reference<XOutputStream> xOutStream = 
mpFB->openFragmentStream(sFileName, aMimeType);
 
         uno::Reference<io::XInputStream> 
xInputStream(pMediaObj->GetInputStream());
         comphelper::OStorageHelper::CopyInputToOutput(xInputStream, 
xOutStream);
@@ -1720,7 +1701,7 @@ void DrawingML::WriteMediaNonVisualProperties(const 
css::uno::Reference<css::dra
 
         // create the relation
         OUString aPath = OUStringBuffer().appendAscii(GetRelationCompPrefix())
-                                         .append("media/media" + 
OUString::number(mnImageCounter.top()++) + aExtension)
+                                         .append("media/media" + 
OUString::number(nImageCount) + aExtension)
                                          .makeStringAndClear();
         aVideoFileRelId = mpFB->addRelation(mpFS->getOutputStream(), 
oox::getRelationship(eMediaType), aPath);
         aMediaRelId = mpFB->addRelation(mpFS->getOutputStream(), 
oox::getRelationship(Relationship::MEDIA), aPath);
@@ -6212,33 +6193,28 @@ void DrawingML::WriteArtisticEffect( const Reference< 
XPropertySet >& rXPropSet
 
 OString DrawingML::WriteWdpPicture( const OUString& rFileId, const Sequence< 
sal_Int8 >& rPictureData )
 {
-    if (!maWdpCache.empty())
-    {
-        std::map<OUString, OUString>::iterator aCachedItem = 
maWdpCache.top().find(rFileId);
-        if (aCachedItem != maWdpCache.top().end())
-            return OUStringToOString(aCachedItem->second, 
RTL_TEXTENCODING_UTF8);
-    }
+    auto& rGraphicExportCache = GraphicExportCache::get();
+
+    OUString aId = rGraphicExportCache.findWdpID(rFileId);
+    if (!aId.isEmpty())
+        return OUStringToOString(aId, RTL_TEXTENCODING_UTF8);
 
-    OUString sFileName = "media/hdphoto" + OUString::number( 
mnWdpImageCounter.top()++ ) + ".wdp";
-    Reference< XOutputStream > xOutStream = mpFB->openFragmentStream( 
OUStringBuffer()
-                                                                      
.appendAscii( GetComponentDir() )
-                                                                      .append( 
"/" + sFileName )
-                                                                      
.makeStringAndClear(),
-                                                                      
"image/vnd.ms-photo" );
-    OUString sId;
+    sal_Int32 nWdpImageCount = rGraphicExportCache.nextWdpImageCount();
+    OUString sFileName = "media/hdphoto" + OUString::number(nWdpImageCount) + 
".wdp";
+    OUString sFragment = 
OUStringBuffer().appendAscii(GetComponentDir()).append( "/" + 
sFileName).makeStringAndClear();
+    Reference< XOutputStream > xOutStream = 
mpFB->openFragmentStream(sFragment, "image/vnd.ms-photo");
     xOutStream->writeBytes( rPictureData );
     xOutStream->closeOutput();
 
-    sId = mpFB->addRelation( mpFS->getOutputStream(),
+    aId = mpFB->addRelation( mpFS->getOutputStream(),
                              oox::getRelationship(Relationship::HDPHOTO),
                              OUStringBuffer()
                              .appendAscii( GetRelationCompPrefix() )
                              .append( sFileName ) );
 
-    if (!maWdpCache.empty())
-        maWdpCache.top()[rFileId] = sId;
+    rGraphicExportCache.addToWdpCache(rFileId, aId);
 
-    return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
+    return OUStringToOString(aId, RTL_TEXTENCODING_UTF8);
 }
 
 void DrawingML::WriteDiagram(const css::uno::Reference<css::drawing::XShape>& 
rXShape, int nDiagramId)
diff --git a/sc/source/filter/excel/xestream.cxx 
b/sc/source/filter/excel/xestream.cxx
index 75f03dfde94d..8d31023e4a57 100644
--- a/sc/source/filter/excel/xestream.cxx
+++ b/sc/source/filter/excel/xestream.cxx
@@ -1026,7 +1026,10 @@ bool XclExpXmlStream::exportDocument()
     // Instead, write via XOutputStream instance.
     tools::SvRef<SotStorage> rStorage = static_cast<SotStorage*>(nullptr);
     drawingml::DrawingML::ResetMlCounters();
-    drawingml::DrawingML::PushExportGraphics();
+
+    auto& rGraphicExportCache = drawingml::GraphicExportCache::get();
+
+    rGraphicExportCache.push();
 
     XclExpRootData aData(
         EXC_BIFF8, *pShell->GetMedium (), rStorage, rDoc,
@@ -1145,7 +1148,7 @@ bool XclExpXmlStream::exportDocument()
         xStatusIndicator->end();
     mpRoot = nullptr;
 
-    drawingml::DrawingML::PopExportGraphics();
+    rGraphicExportCache.pop();
 
     return true;
 }
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx 
b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 9e207baf1be6..a8dca7463fdd 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -431,7 +431,10 @@ bool PowerPointExport::importDocument() noexcept
 bool PowerPointExport::exportDocument()
 {
     drawingml::DrawingML::ResetMlCounters();
-    DrawingML::PushExportGraphics();
+    auto& rGraphicExportCache = drawingml::GraphicExportCache::get();
+
+    rGraphicExportCache.push();
+
     maShapeMap.clear();
 
     mXModel = getModel();
@@ -515,7 +518,8 @@ bool PowerPointExport::exportDocument()
 
     commitStorage();
 
-    DrawingML::PopExportGraphics();
+    rGraphicExportCache.pop();
+
     maShapeMap.clear();
     maAuthors.clear();
     maRelId.clear();
diff --git a/sw/source/filter/ww8/docxexport.cxx 
b/sw/source/filter/ww8/docxexport.cxx
index 2fdcadce6dd9..59b91603acc1 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -526,8 +526,10 @@ ErrCode DocxExport::ExportDocument_Impl()
     // init sections
     m_pSections.reset(new MSWordSections( *this ));
 
+    auto& rGraphicExportCache = oox::drawingml::GraphicExportCache::get();
+
     // Make sure images are counted from one, even when exporting multiple 
documents.
-    oox::drawingml::DrawingML::PushExportGraphics();
+    rGraphicExportCache.push();
 
     WriteMainText();
 
@@ -555,7 +557,8 @@ ErrCode DocxExport::ExportDocument_Impl()
     m_aLinkedTextboxesHelper.clear();   //final cleanup
     m_pStyles.reset();
     m_pSections.reset();
-    oox::drawingml::DrawingML::PopExportGraphics();
+
+    rGraphicExportCache.pop();
 
     return ERRCODE_NONE;
 }
commit c3f7720ff13c34b9cf2c90d9c9b6dcc3d8f4c7a5
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Thu Mar 23 11:37:40 2023 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Mon Apr 24 23:49:57 2023 +0200

    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 <qui...@gmail.com>

diff --git a/include/docmodel/theme/FormatScheme.hxx 
b/include/docmodel/theme/FormatScheme.hxx
index feec16ee187f..420d5c1b7584 100644
--- a/include/docmodel/theme/FormatScheme.hxx
+++ b/include/docmodel/theme/FormatScheme.hxx
@@ -79,6 +79,8 @@ struct DOCMODEL_DLLPUBLIC ColorDefinition
     ThemeColorType meSchemeType = ThemeColorType::Unknown;
     std::vector<Transformation> maTransformations;
 
+    Color getRGBColor() const { return Color(mnComponent1, mnComponent2, 
mnComponent3); }
+
     void setCRGB(sal_Int32 nR, sal_Int32 nG, sal_Int32 nB)
     {
         mnComponent1 = nR;
@@ -436,9 +438,9 @@ enum class LineEndLength
 
 struct DOCMODEL_DLLPUBLIC LineEnd
 {
-    LineEndType meType;
-    LineEndWidth meWidth;
-    LineEndLength meLength;
+    LineEndType meType = LineEndType::None;
+    LineEndWidth meWidth = LineEndWidth::Unset;
+    LineEndLength meLength = LineEndLength::Unset;
 };
 
 struct DOCMODEL_DLLPUBLIC DashStop
@@ -527,6 +529,42 @@ public:
 
     const OUString& getName() const { return maName; }
 
+    std::vector<FillStyle> const& getFillStyleList() const { return 
maFillStyleList; }
+
+    FillStyle* addFillStyle()
+    {
+        if (maFillStyleList.size() > 3)
+            return nullptr;
+        auto& rFillStyle = maFillStyleList.emplace_back();
+        return &rFillStyle;
+    }
+
+    void ensureFillStyleList() const
+    {
+        if (!maFillStyleList.empty())
+            return;
+
+        auto* pThis = const_cast<FormatScheme*>(this);
+        {
+            FillStyle* pFillStyle = pThis->addFillStyle();
+            auto pFill = std::make_shared<SolidFill>();
+            pFill->maColorDefinition.meType = model::ColorType::Placeholder;
+            pFillStyle->mpFill = pFill;
+        }
+        {
+            FillStyle* pFillStyle = pThis->addFillStyle();
+            auto pFill = std::make_shared<SolidFill>();
+            pFill->maColorDefinition.meType = model::ColorType::Placeholder;
+            pFillStyle->mpFill = pFill;
+        }
+        {
+            FillStyle* pFillStyle = pThis->addFillStyle();
+            auto pFill = std::make_shared<SolidFill>();
+            pFill->maColorDefinition.meType = model::ColorType::Placeholder;
+            pFillStyle->mpFill = pFill;
+        }
+    }
+
     std::vector<LineStyle> const& getLineStyleList() const { return 
maLineStyleList; }
 
     LineStyle* addLineStyle()
@@ -537,6 +575,51 @@ public:
         return &rLineStyle;
     }
 
+    void ensureLineStyleList() const
+    {
+        if (!maLineStyleList.empty())
+            return;
+
+        auto* pThis = const_cast<FormatScheme*>(this);
+
+        {
+            LineStyle* pLineStyle = pThis->addLineStyle();
+            pLineStyle->mnWidth = 6350;
+            pLineStyle->meCapType = CapType::Flat;
+            pLineStyle->mePenAlignment = PenAlignmentType::Center;
+            pLineStyle->meCompoundLineType = CompoundLineType::Single;
+            pLineStyle->maLineDash.mePresetType = PresetDashType::Solid;
+            pLineStyle->maLineJoin.meType = LineJoinType::Miter;
+            auto pFill = std::make_shared<SolidFill>();
+            pFill->maColorDefinition.meType = model::ColorType::Placeholder;
+            pLineStyle->maLineFillStyle.mpFill = pFill;
+        }
+        {
+            LineStyle* pLineStyle = pThis->addLineStyle();
+            pLineStyle->mnWidth = 6350;
+            pLineStyle->meCapType = CapType::Flat;
+            pLineStyle->mePenAlignment = PenAlignmentType::Center;
+            pLineStyle->meCompoundLineType = CompoundLineType::Single;
+            pLineStyle->maLineDash.mePresetType = PresetDashType::Solid;
+            pLineStyle->maLineJoin.meType = LineJoinType::Miter;
+            auto pFill = std::make_shared<SolidFill>();
+            pFill->maColorDefinition.meType = model::ColorType::Placeholder;
+            pLineStyle->maLineFillStyle.mpFill = pFill;
+        }
+        {
+            LineStyle* pLineStyle = pThis->addLineStyle();
+            pLineStyle->mnWidth = 6350;
+            pLineStyle->meCapType = CapType::Flat;
+            pLineStyle->mePenAlignment = PenAlignmentType::Center;
+            pLineStyle->meCompoundLineType = CompoundLineType::Single;
+            pLineStyle->maLineDash.mePresetType = PresetDashType::Solid;
+            pLineStyle->maLineJoin.meType = LineJoinType::Miter;
+            auto pFill = std::make_shared<SolidFill>();
+            pFill->maColorDefinition.meType = model::ColorType::Placeholder;
+            pLineStyle->maLineFillStyle.mpFill = pFill;
+        }
+    }
+
     std::vector<EffectStyle> const& getEffectStyleList() const { return 
maEffectStyleList; }
 
     EffectStyle* addEffectStyle()
@@ -547,14 +630,16 @@ public:
         return &rEffectStyle;
     }
 
-    std::vector<FillStyle> const& getFillStyleList() const { return 
maFillStyleList; }
-
-    FillStyle* addFillStyle()
+    void ensureEffectStyleList() const
     {
-        if (maFillStyleList.size() > 3)
-            return nullptr;
-        auto& rFillStyle = maFillStyleList.emplace_back();
-        return &rFillStyle;
+        if (!maEffectStyleList.empty())
+            return;
+
+        auto* pThis = const_cast<FormatScheme*>(this);
+
+        pThis->addEffectStyle();
+        pThis->addEffectStyle();
+        pThis->addEffectStyle();
     }
 
     std::vector<FillStyle> const& getBackgroundFillStyleList() const
@@ -569,6 +654,33 @@ public:
         auto& rBackgroundFillStyle = maBackgroundFillStyleList.emplace_back();
         return &rBackgroundFillStyle;
     }
+
+    void ensureBackgroundFillStyleList() const
+    {
+        if (!maBackgroundFillStyleList.empty())
+            return;
+
+        auto* pThis = const_cast<FormatScheme*>(this);
+
+        {
+            FillStyle* pFillStyle = pThis->addBackgroundFillStyle();
+            auto pFill = std::make_shared<SolidFill>();
+            pFill->maColorDefinition.meType = model::ColorType::Placeholder;
+            pFillStyle->mpFill = pFill;
+        }
+        {
+            FillStyle* pFillStyle = pThis->addBackgroundFillStyle();
+            auto pFill = std::make_shared<SolidFill>();
+            pFill->maColorDefinition.meType = model::ColorType::Placeholder;
+            pFillStyle->mpFill = pFill;
+        }
+        {
+            FillStyle* pFillStyle = pThis->addBackgroundFillStyle();
+            auto pFill = std::make_shared<SolidFill>();
+            pFill->maColorDefinition.meType = model::ColorType::Placeholder;
+            pFillStyle->mpFill = pFill;
+        }
+    }
 };
 
 } // end of namespace svx
diff --git a/include/docmodel/theme/Theme.hxx b/include/docmodel/theme/Theme.hxx
index 70766a8488ae..9a5c9fe6ed5a 100644
--- a/include/docmodel/theme/Theme.hxx
+++ b/include/docmodel/theme/Theme.hxx
@@ -37,7 +37,7 @@ struct DOCMODEL_DLLPUBLIC ThemeFont
     OUString maPanose;
     sal_Int16 maPitch = 0;
     sal_Int16 maFamily = 0;
-    sal_Int32 maCharset = 0;
+    sal_Int32 maCharset = 1;
 
     sal_Int16 getPitchFamily() const { return (maPitch & 0x0F) | (maFamily & 
0x0F) << 4; }
 };
@@ -59,12 +59,29 @@ private:
     std::vector<ThemeSupplementalFont> maMajorSupplementalFontList;
 
 public:
-    FontScheme() = default;
+    FontScheme()
+        : maName("Office")
+    {
+    }
+
     FontScheme(OUString const& rName)
         : maName(rName)
     {
     }
 
+    static FontScheme getDefault()
+    {
+        FontScheme aDefault;
+        aDefault.maMinorLatin.maTypeface = "Arial";
+        aDefault.maMinorAsian.maTypeface = "DejaVu Sans";
+        aDefault.maMinorComplex.maTypeface = "DejaVu Sans";
+
+        aDefault.maMajorLatin.maTypeface = "Arial";
+        aDefault.maMajorAsian.maTypeface = "DejaVu Sans";
+        aDefault.maMajorComplex.maTypeface = "DejaVu Sans";
+        return aDefault;
+    }
+
     const OUString& getName() const { return maName; }
 
     ThemeFont const& getMinorLatin() const { return maMinorLatin; }
@@ -143,7 +160,7 @@ private:
     OUString maName;
     std::unique_ptr<model::ColorSet> mpColorSet;
 
-    FontScheme maFontScheme;
+    FontScheme maFontScheme = FontScheme::getDefault();
     FormatScheme maFormatScheme;
 
 public:
diff --git a/include/oox/export/ThemeExport.hxx 
b/include/oox/export/ThemeExport.hxx
index 1889709ab352..8e35b80ca09a 100644
--- a/include/oox/export/ThemeExport.hxx
+++ b/include/oox/export/ThemeExport.hxx
@@ -17,6 +17,7 @@ namespace model
 {
 class Theme;
 class FontScheme;
+class FormatScheme;
 }
 
 namespace oox
@@ -35,7 +36,8 @@ private:
     static bool writeColorSet(sax_fastparser::FSHelperPtr pFS, model::Theme 
const& rTheme);
     static bool writeFontScheme(sax_fastparser::FSHelperPtr pFS,
                                 model::FontScheme const& rFontScheme);
-    static bool writeFormatScheme(sax_fastparser::FSHelperPtr pFS);
+    static bool writeFormatScheme(sax_fastparser::FSHelperPtr pFS,
+                                  model::FormatScheme const& rFormatScheme);
 };
 
 } // end namespace oox
diff --git a/oox/source/export/ThemeExport.cxx 
b/oox/source/export/ThemeExport.cxx
index 3abc2cb1adb6..b198aae62fe2 100644
--- a/oox/source/export/ThemeExport.cxx
+++ b/oox/source/export/ThemeExport.cxx
@@ -14,6 +14,7 @@
 #include <oox/token/tokens.hxx>
 #include <oox/export/utils.hxx>
 #include <docmodel/theme/Theme.hxx>
+#include <docmodel/theme/FormatScheme.hxx>
 #include <sax/fshelper.hxx>
 #include <sax/fastattribs.hxx>
 #include <unordered_map>
@@ -49,8 +50,9 @@ void ThemeExport::write(OUString const& rPath, model::Theme 
const& rTheme)
     writeFontScheme(pFS, rFontScheme);
     pFS->endElementNS(XML_a, XML_fontScheme);
 
+    model::FormatScheme const& rFormatScheme = rTheme.getFormatScheme();
     pFS->startElementNS(XML_a, XML_fmtScheme);
-    writeFormatScheme(pFS);
+    writeFormatScheme(pFS, rFormatScheme);
     pFS->endElementNS(XML_a, XML_fmtScheme);
 
     pFS->endElementNS(XML_a, XML_themeElements);
@@ -64,8 +66,14 @@ namespace
 void fillAttrList(rtl::Reference<sax_fastparser::FastAttributeList> const& 
pAttrList,
                   model::ThemeFont const& rThemeFont)
 {
+    if (rThemeFont.maTypeface.isEmpty())
+        return;
+
     pAttrList->add(XML_typeface, rThemeFont.maTypeface);
-    pAttrList->add(XML_panose, rThemeFont.maPanose);
+
+    if (!rThemeFont.maPanose.isEmpty())
+        pAttrList->add(XML_panose, rThemeFont.maPanose);
+
     pAttrList->add(XML_pitchFamily, 
OString::number(rThemeFont.getPitchFamily()));
     pAttrList->add(XML_charset, OString::number(rThemeFont.maCharset));
 }
@@ -118,105 +126,714 @@ bool 
ThemeExport::writeFontScheme(sax_fastparser::FSHelperPtr pFS,
     return true;
 }
 
-bool ThemeExport::writeFormatScheme(sax_fastparser::FSHelperPtr pFS)
+namespace
 {
-    // Format Scheme: 3 or more per list but only 3 will be used currently
-    pFS->startElementNS(XML_a, XML_fillStyleLst);
+void writeColorTransformations(sax_fastparser::FSHelperPtr pFS,
+                               std::vector<model::Transformation> const& 
rTransformations)
+{
+    static std::unordered_map<model::TransformationType, sal_Int32> 
constTransformationTypeTokenMap
+        = {
+              { model::TransformationType::Tint, XML_tint },
+              { model::TransformationType::Shade, XML_shade },
+              { model::TransformationType::LumMod, XML_lumMod },
+              { model::TransformationType::LumOff, XML_lumOff },
+          };
+
+    for (model::Transformation const& rTransformation : rTransformations)
     {
-        pFS->startElementNS(XML_a, XML_solidFill);
-        pFS->singleElementNS(XML_a, XML_schemeClr, XML_val, "phClr");
-        pFS->endElementNS(XML_a, XML_solidFill);
+        auto iterator = 
constTransformationTypeTokenMap.find(rTransformation.meType);
+        if (iterator != constTransformationTypeTokenMap.end())
+        {
+            sal_Int32 nToken = iterator->second;
+            pFS->singleElementNS(XML_a, nToken, XML_val,
+                                 OString::number(rTransformation.mnValue * 
10));
+        }
+    }
+}
 
-        pFS->startElementNS(XML_a, XML_solidFill);
-        pFS->singleElementNS(XML_a, XML_schemeClr, XML_val, "phClr");
-        pFS->endElementNS(XML_a, XML_solidFill);
+void writeColorRGB(sax_fastparser::FSHelperPtr pFS, model::ColorDefinition 
const& rColorDefinition)
+{
+    auto aColor = rColorDefinition.getRGBColor();
+    pFS->startElementNS(XML_a, XML_srgbClr, XML_val, 
I32SHEX(sal_Int32(aColor)));
+    pFS->endElementNS(XML_a, XML_srgbClr);
+}
 
-        pFS->startElementNS(XML_a, XML_solidFill);
-        pFS->singleElementNS(XML_a, XML_schemeClr, XML_val, "phClr");
-        pFS->endElementNS(XML_a, XML_solidFill);
+void writeColorCRGB(sax_fastparser::FSHelperPtr pFS, model::ColorDefinition 
const& rColorDefinition)
+{
+    pFS->startElementNS(XML_a, XML_scrgbClr, XML_r, 
OString::number(rColorDefinition.mnComponent1),
+                        XML_g, OString::number(rColorDefinition.mnComponent2), 
XML_b,
+                        OString::number(rColorDefinition.mnComponent3));
+    writeColorTransformations(pFS, rColorDefinition.maTransformations);
+    pFS->endElementNS(XML_a, XML_scrgbClr);
+}
+
+void writeColorHSL(sax_fastparser::FSHelperPtr pFS, model::ColorDefinition 
const& rColorDefinition)
+{
+    pFS->startElementNS(XML_a, XML_hslClr, XML_hue, 
OString::number(rColorDefinition.mnComponent1),
+                        XML_sat, 
OString::number(rColorDefinition.mnComponent2), XML_lum,
+                        OString::number(rColorDefinition.mnComponent3));
+    writeColorTransformations(pFS, rColorDefinition.maTransformations);
+    pFS->endElementNS(XML_a, XML_hslClr);
+}
+
+void writeColorScheme(sax_fastparser::FSHelperPtr pFS,
+                      model::ColorDefinition const& rColorDefinition)
+{
+    static std::unordered_map<model::ThemeColorType, const char*> 
constThemeColorTypeTokenMap
+        = { { model::ThemeColorType::Dark1, "dk1" },
+            { model::ThemeColorType::Light1, "lt1" },
+            { model::ThemeColorType::Dark2, "dk2" },
+            { model::ThemeColorType::Light2, "lt2" },
+            { model::ThemeColorType::Accent1, "accent1" },
+            { model::ThemeColorType::Accent2, "accent2" },
+            { model::ThemeColorType::Accent3, "accent3" },
+            { model::ThemeColorType::Accent4, "accent4" },
+            { model::ThemeColorType::Accent5, "accent5" },
+            { model::ThemeColorType::Accent6, "accent6" },
+            { model::ThemeColorType::Hyperlink, "hlink" },
+            { model::ThemeColorType::FollowedHyperlink, "folHlink" } };
+    auto iterator = 
constThemeColorTypeTokenMap.find(rColorDefinition.meSchemeType);
+    if (iterator != constThemeColorTypeTokenMap.end())
+    {
+        const char* sValue = iterator->second;
+        pFS->startElementNS(XML_a, XML_schemeClr, XML_val, sValue);
+        writeColorTransformations(pFS, rColorDefinition.maTransformations);
+        pFS->endElementNS(XML_a, XML_schemeClr);
     }
-    pFS->endElementNS(XML_a, XML_fillStyleLst);
+}
 
-    pFS->startElementNS(XML_a, XML_lnStyleLst);
+void writeColorSystem(sax_fastparser::FSHelperPtr pFS,
+                      model::ColorDefinition const& rColorDefinition)
+{
+    static std::unordered_map<model::SystemColorType, const char*> 
constThemeColorTypeTokenMap = {
+        { model::SystemColorType::DarkShadow3D, "3dDkShadow" },
+        { model::SystemColorType::Light3D, "3dLight" },
+        { model::SystemColorType::ActiveBorder, "activeBorder" },
+        { model::SystemColorType::ActiveCaption, "activeCaption" },
+        { model::SystemColorType::AppWorkspace, "appWorkspace" },
+        { model::SystemColorType::Background, "background" },
+        { model::SystemColorType::ButtonFace, "btnFace" },
+        { model::SystemColorType::ButtonHighlight, "btnHighlight" },
+        { model::SystemColorType::ButtonShadow, "btnShadow" },
+        { model::SystemColorType::ButtonText, "btnText" },
+        { model::SystemColorType::CaptionText, "captionText" },
+        { model::SystemColorType::GradientActiveCaption, 
"gradientActiveCaption" },
+        { model::SystemColorType::GradientInactiveCaption, 
"gradientInactiveCaption" },
+        { model::SystemColorType::GrayText, "grayText" },
+        { model::SystemColorType::Highlight, "highlight" },
+        { model::SystemColorType::HighlightText, "highlightText" },
+        { model::SystemColorType::HotLight, "hotLight" },
+        { model::SystemColorType::InactiveBorder, "inactiveBorder" },
+        { model::SystemColorType::InactiveCaption, "inactiveCaption" },
+        { model::SystemColorType::InactiveCaptionText, "inactiveCaptionText" },
+        { model::SystemColorType::InfoBack, "infoBk" },
+        { model::SystemColorType::InfoText, "infoText" },
+        { model::SystemColorType::Menu, "menu" },
+        { model::SystemColorType::MenuBar, "menuBar" },
+        { model::SystemColorType::MenuHighlight, "menuHighlight" },
+        { model::SystemColorType::MenuText, "menuText" },
+        { model::SystemColorType::ScrollBar, "scrollBar" },
+        { model::SystemColorType::Window, "window" },
+        { model::SystemColorType::WindowFrame, "windowFrame" },
+        { model::SystemColorType::WindowText, "windowText" },
+    };
+    auto iterator = 
constThemeColorTypeTokenMap.find(rColorDefinition.meSystemColorType);
+    if (iterator != constThemeColorTypeTokenMap.end())
     {
-        pFS->startElementNS(XML_a, XML_ln, XML_w, "6350", XML_cap, "flat", 
XML_cmpd, "sng",
-                            XML_algn, "ctr");
-        {
-            pFS->startElementNS(XML_a, XML_solidFill);
-            pFS->startElementNS(XML_a, XML_schemeClr, XML_val, "phClr");
-            pFS->singleElementNS(XML_a, XML_shade, XML_val, "95000");
-            pFS->endElementNS(XML_a, XML_schemeClr);
-            pFS->endElementNS(XML_a, XML_solidFill);
+        const char* sValue = iterator->second;
+        pFS->startElementNS(XML_a, XML_sysClr, XML_val, sValue);
+        //XML_lastClr
+        writeColorTransformations(pFS, rColorDefinition.maTransformations);
+        pFS->endElementNS(XML_a, XML_schemeClr);
+    }
+}
+
+void writeColorPlaceholder(sax_fastparser::FSHelperPtr pFS,
+                           model::ColorDefinition const& rColorDefinition)
+{
+    pFS->startElementNS(XML_a, XML_schemeClr, XML_val, "phClr");
+    writeColorTransformations(pFS, rColorDefinition.maTransformations);
+    pFS->endElementNS(XML_a, XML_schemeClr);
+}
+
+void writeColorDefinition(sax_fastparser::FSHelperPtr pFS,
+                          model::ColorDefinition const& rColorDefinition)
+{
+    switch (rColorDefinition.meType)
+    {
+        case model::ColorType::Unused:
+            break;
+        case model::ColorType::RGB:
+            writeColorRGB(pFS, rColorDefinition);
+            break;
+        case model::ColorType::CRGB:
+            writeColorCRGB(pFS, rColorDefinition);
+            break;
+        case model::ColorType::HSL:
+            writeColorHSL(pFS, rColorDefinition);
+            break;
+        case model::ColorType::Scheme:
+            writeColorScheme(pFS, rColorDefinition);
+            break;
+        case model::ColorType::Palette:
+            break;
+        case model::ColorType::System:
+            writeColorSystem(pFS, rColorDefinition);
+            break;
+        case model::ColorType::Placeholder:
+            writeColorPlaceholder(pFS, rColorDefinition);
+            break;
+    }
+}
+
+void writeSolidFill(sax_fastparser::FSHelperPtr pFS, model::SolidFill const& 
rSolidFill)
+{
+    pFS->startElementNS(XML_a, XML_solidFill);
+    writeColorDefinition(pFS, rSolidFill.maColorDefinition);
+    pFS->endElementNS(XML_a, XML_solidFill);
+}
+
+void writeRelativeRectangle(sax_fastparser::FSHelperPtr pFS, sal_Int32 nToken,
+                            model::RelativeRectangle const& rRelativeRectangle)
+{
+    pFS->singleElementNS(XML_a, nToken, XML_l, 
OString::number(rRelativeRectangle.mnLeft), XML_t,
+                         OString::number(rRelativeRectangle.mnTop), XML_r,
+                         OString::number(rRelativeRectangle.mnRight), XML_b,
+                         OString::number(rRelativeRectangle.mnBottom));
+}
+
+void writeGradientFill(sax_fastparser::FSHelperPtr pFS, model::GradientFill 
const& rGradientFill)
+{
+    pFS->startElementNS(XML_a, XML_gradFill);
+    pFS->startElementNS(XML_a, XML_gsLst);
+    for (auto const& rStop : rGradientFill.maGradientStops)
+    {
+        pFS->startElementNS(XML_a, XML_gs, XML_pos,
+                            OString::number(sal_Int32(rStop.mfPosition * 
100000.0)));
+        writeColorDefinition(pFS, rStop.maColor);
+        pFS->endElementNS(XML_a, XML_gs);
+    }
+    pFS->endElementNS(XML_a, XML_gsLst);
 
-            pFS->singleElementNS(XML_a, XML_prstDash, XML_val, "solid");
+    if (rGradientFill.meGradientType == model::GradientType::Linear)
+    {
+        pFS->singleElementNS(XML_a, XML_lin, XML_ang,
+                             
OString::number(rGradientFill.maLinearGradient.mnAngle), XML_scaled,
+                             rGradientFill.maLinearGradient.mbScaled ? "1" : 
"0");
+    }
+    else
+    {
+        OString sPathType;
+        switch (rGradientFill.meGradientType)
+        {
+            case model::GradientType::Circle:
+                sPathType = "circle";
+                break;
+            case model::GradientType::Rectangle:
+                sPathType = "rect";
+                break;
+            case model::GradientType::Shape:
+                sPathType = "shape";
+                break;
+            default:
+                break;
+        }
 
-            pFS->singleElementNS(XML_a, XML_miter);
+        if (!sPathType.isEmpty())
+        {
+            pFS->startElementNS(XML_a, XML_path, XML_path, sPathType);
+            writeRelativeRectangle(pFS, XML_fillToRect, 
rGradientFill.maFillToRectangle);
+            pFS->endElementNS(XML_a, XML_path);
         }
-        pFS->endElementNS(XML_a, XML_ln);
     }
+    writeRelativeRectangle(pFS, XML_tileRect, rGradientFill.maTileRectangle);
+    pFS->endElementNS(XML_a, XML_gradFill);
+}
+
+void writePatternFill(sax_fastparser::FSHelperPtr pFS, model::PatternFill 
const& rPatternFill)
+{
+    OString sPresetType;
+    switch (rPatternFill.mePatternPreset)
+    {
+        case model::PatternPreset::Percent_5:
+            sPresetType = "pct5";
+            break;
+        case model::PatternPreset::Percent_10:
+            sPresetType = "pct10";
+            break;
+        case model::PatternPreset::Percent_20:
+            sPresetType = "pct20";
+            break;
+        case model::PatternPreset::Percent_25:
+            sPresetType = "pct25";
+            break;
+        case model::PatternPreset::Percent_30:
+            sPresetType = "pct30";
+            break;
+        case model::PatternPreset::Percent_40:
+            sPresetType = "pct40";
+            break;
+        case model::PatternPreset::Percent_50:
+            sPresetType = "pct50";
+            break;
+        case model::PatternPreset::Percent_60:
+            sPresetType = "pct60";
+            break;
+        case model::PatternPreset::Percent_70:
+            sPresetType = "pct70";
+            break;
+        case model::PatternPreset::Percent_75:
+            sPresetType = "pct75";
+            break;
+        case model::PatternPreset::Percent_80:
+            sPresetType = "pct80";
+            break;
+        case model::PatternPreset::Percent_90:
+            sPresetType = "pct90";
+            break;
+        case model::PatternPreset::Horizontal:
+            sPresetType = "horz";
+            break;
+        case model::PatternPreset::Vertical:
+            sPresetType = "vert";
+            break;
+        case model::PatternPreset::LightHorizontal:
+            sPresetType = "ltHorz";
+            break;
+        case model::PatternPreset::LightVertical:
+            sPresetType = "ltVert";
+            break;
+        case model::PatternPreset::DarkHorizontal:
+            sPresetType = "dkHorz";
+            break;
+        case model::PatternPreset::DarkVertical:
+            sPresetType = "dkVert";
+            break;
+        case model::PatternPreset::NarrowHorizontal:
+            sPresetType = "narHorz";
+            break;
+        case model::PatternPreset::NarrowVertical:
+            sPresetType = "narVert";
+            break;
+        case model::PatternPreset::DashedHorizontal:
+            sPresetType = "dashHorz";
+            break;
+        case model::PatternPreset::DashedVertical:
+            sPresetType = "dashVert";
+            break;
+        case model::PatternPreset::Cross:
+            sPresetType = "cross";
+            break;
+        case model::PatternPreset::DownwardDiagonal:
+            sPresetType = "dnDiag";
+            break;
+        case model::PatternPreset::UpwardDiagonal:
+            sPresetType = "upDiag";
+            break;
+        case model::PatternPreset::LightDownwardDiagonal:
+            sPresetType = "ltDnDiag";
+            break;
+        case model::PatternPreset::LightUpwardDiagonal:
+            sPresetType = "ltUpDiag";
+            break;
+        case model::PatternPreset::DarkDownwardDiagonal:
+            sPresetType = "dkDnDiag";
+            break;
+        case model::PatternPreset::DarkUpwardDiagonal:
+            sPresetType = "dkUpDiag";
+            break;
+        case model::PatternPreset::WideDownwardDiagonal:
+            sPresetType = "wdDnDiag";
+            break;
+        case model::PatternPreset::WideUpwardDiagonal:
+            sPresetType = "wdUpDiag";
+            break;
+        case model::PatternPreset::DashedDownwardDiagonal:
+            sPresetType = "dashDnDiag";
+            break;
+        case model::PatternPreset::DashedUpwardDiagonal:
+            sPresetType = "dashUpDiag";
+            break;
+        case model::PatternPreset::DiagonalCross:
+            sPresetType = "diagCross";
+            break;
+        case model::PatternPreset::SmallCheckerBoard:
+            sPresetType = "smCheck";
+            break;
+        case model::PatternPreset::LargeCheckerBoard:
+            sPresetType = "lgCheck";
+            break;
+        case model::PatternPreset::SmallGrid:
+            sPresetType = "smGrid";
+            break;
+        case model::PatternPreset::LargeGrid:
+            sPresetType = "lgGrid";
+            break;
+        case model::PatternPreset::DottedGrid:
+            sPresetType = "dotGrid";
+            break;
+        case model::PatternPreset::SmallConfetti:
+            sPresetType = "smConfetti";
+            break;
+        case model::PatternPreset::LargeConfetti:
+            sPresetType = "lgConfetti";
+            break;
+        case model::PatternPreset::HorizontalBrick:
+            sPresetType = "horzBrick";
+            break;
+        case model::PatternPreset::DiagonalBrick:
+            sPresetType = "diagBrick";
+            break;
+        case model::PatternPreset::SolidDiamond:
+            sPresetType = "solidDmnd";
+            break;
+        case model::PatternPreset::OpenDiamond:
+            sPresetType = "openDmnd";
+            break;
+        case model::PatternPreset::DottedDiamond:
+            sPresetType = "dotDmnd";
+            break;
+        case model::PatternPreset::Plaid:
+            sPresetType = "plaid";
+            break;
+        case model::PatternPreset::Sphere:
+            sPresetType = "sphere";
+            break;
+        case model::PatternPreset::Weave:
+            sPresetType = "weave";
+            break;
+        case model::PatternPreset::Divot:
+            sPresetType = "divot";
+            break;
+        case model::PatternPreset::Shingle:
+            sPresetType = "shingle";
+            break;
+        case model::PatternPreset::Wave:
+            sPresetType = "wave";
+            break;
+        case model::PatternPreset::Trellis:
+            sPresetType = "trellis";
+            break;
+        case model::PatternPreset::ZigZag:
+            sPresetType = "zigZag";
+            break;
+        default:
+            break;
+    }
+
+    if (!sPresetType.isEmpty())
+    {
+        pFS->startElementNS(XML_a, XML_pattFill, XML_prst, sPresetType);
+
+        pFS->startElementNS(XML_a, XML_fgClr);
+        writeColorDefinition(pFS, rPatternFill.maForegroundColor);
+        pFS->endElementNS(XML_a, XML_fgClr);
+
+        pFS->startElementNS(XML_a, XML_bgClr);
+        writeColorDefinition(pFS, rPatternFill.maBackgroundColor);
+        pFS->endElementNS(XML_a, XML_bgClr);
+
+        pFS->endElementNS(XML_a, XML_pattFill);
+    }
+}
+
+OString convertFlipMode(model::FlipMode eFlipMode)
+{
+    switch (eFlipMode)
+    {
+        case model::FlipMode::X:
+            return "x";
+        case model::FlipMode::Y:
+            return "y";
+        case model::FlipMode::XY:
+            return "xy";
+        case model::FlipMode::None:
+            return "none";
+    }
+    return "none";
+}
+
+OString convertRectangleAlignment(model::RectangleAlignment eFlipMode)
+{
+    switch (eFlipMode)
+    {
+        case model::RectangleAlignment::TopLeft:
+            return "tl";
+        case model::RectangleAlignment::Top:
+            return "t";
+        case model::RectangleAlignment::TopRight:
+            return "tr";
+        case model::RectangleAlignment::Left:
+            return "l";
+        case model::RectangleAlignment::Center:
+            return "ctr";
+        case model::RectangleAlignment::Right:
+            return "r";
+        case model::RectangleAlignment::BottomLeft:
+            return "bl";
+        case model::RectangleAlignment::Bottom:
+            return "b";
+        case model::RectangleAlignment::BottomRight:
+            return "br";
+        case model::RectangleAlignment::Unset:
+            break;
+    }
+    return {};
+}
+
+void writeBlip(sax_fastparser::FSHelperPtr pFS, model::BlipFill const& 
/*rBlipFill*/)
+{
+    // TODO - reuse WriteXGraphicBlip
+    pFS->startElementNS(XML_a, XML_blip);
+    pFS->endElementNS(XML_a, XML_blip);
+}
+
+void writeBlipFill(sax_fastparser::FSHelperPtr pFS, model::BlipFill const& 
rBlipFill)
+{
+    pFS->startElementNS(XML_a, XML_blipFill, XML_rotWithShape,
+                        rBlipFill.mbRotateWithShape ? "1" : "0"
+                        /*XML_dpi*/);
+
+    writeBlip(pFS, rBlipFill);
+
+    writeRelativeRectangle(pFS, XML_srcRect, rBlipFill.maClipRectangle);
+
+    if (rBlipFill.meMode == model::BitmapMode::Tile)
+    {
+        OString aFlipMode = convertFlipMode(rBlipFill.meTileFlipMode);
+        OString aAlignment = 
convertRectangleAlignment(rBlipFill.meTileAlignment);
+
+        pFS->startElementNS(XML_a, XML_tile, XML_tx, 
OString::number(rBlipFill.mnTileOffsetX),
+                            XML_ty, OString::number(rBlipFill.mnTileOffsetY), 
XML_sx,
+                            OString::number(rBlipFill.mnTileScaleX), XML_sy,
+                            OString::number(rBlipFill.mnTileScaleY), XML_flip, 
aFlipMode, XML_algn,
+                            aAlignment);
+        pFS->endElementNS(XML_a, XML_tile);
+    }
+    else if (rBlipFill.meMode == model::BitmapMode::Stretch)
     {
-        pFS->startElementNS(XML_a, XML_ln, XML_w, "6350", XML_cap, "flat", 
XML_cmpd, "sng",
-                            XML_algn, "ctr");
+        pFS->startElementNS(XML_a, XML_stretch);
+        writeRelativeRectangle(pFS, XML_fillRect, rBlipFill.maFillRectangle);
+        pFS->endElementNS(XML_a, XML_stretch);
+    }
+
+    pFS->endElementNS(XML_a, XML_blipFill);
+}
+
+void writeFillStyle(sax_fastparser::FSHelperPtr pFS, model::FillStyle const& 
rFillStyle)
+{
+    switch (rFillStyle.mpFill->meType)
+    {
+        case model::FillType::None:
+        case model::FillType::Solid:
         {
-            pFS->startElementNS(XML_a, XML_solidFill);
-            pFS->startElementNS(XML_a, XML_schemeClr, XML_val, "phClr");
-            pFS->singleElementNS(XML_a, XML_shade, XML_val, "95000");
-            pFS->endElementNS(XML_a, XML_schemeClr);
-            pFS->endElementNS(XML_a, XML_solidFill);
+            auto* pSolidFill = 
static_cast<model::SolidFill*>(rFillStyle.mpFill.get());
+            writeSolidFill(pFS, *pSolidFill);
+        }
+        break;
+        case model::FillType::Gradient:
+        {
+            auto* pGradientFill = 
static_cast<model::GradientFill*>(rFillStyle.mpFill.get());
+            writeGradientFill(pFS, *pGradientFill);
+        }
+        break;
+        case model::FillType::Pattern:
+        {
+            auto* pPatternFill = 
static_cast<model::PatternFill*>(rFillStyle.mpFill.get());
+            writePatternFill(pFS, *pPatternFill);
+        }
+        break;
+        case model::FillType::Blip:
+        {
+            auto* pBlipFill = 
static_cast<model::BlipFill*>(rFillStyle.mpFill.get());
+            writeBlipFill(pFS, *pBlipFill);
+        }
+        break;
+    }
+}
+
+void writeBackgroundFillStyle(sax_fastparser::FSHelperPtr pFS, 
model::FillStyle const& rFillStyle)
+{
+    writeFillStyle(pFS, rFillStyle);
+}
+
+void writeLineStyle(sax_fastparser::FSHelperPtr pFS, model::LineStyle const& 
rLineStyle)
+{
+    OString sCap;
+    switch (rLineStyle.meCapType)
+    {
+        case model::CapType::Flat:
+            sCap = "flat";
+            break;
+        case model::CapType::Round:
+            sCap = "rnd";
+            break;
+        case model::CapType::Square:
+            sCap = "sq";
+            break;
+        case model::CapType::Unset:
+            break;
+    }
 
-            pFS->singleElementNS(XML_a, XML_prstDash, XML_val, "solid");
+    OString sPenAlign;
+    switch (rLineStyle.mePenAlignment)
+    {
+        case model::PenAlignmentType::Center:
+            sPenAlign = "ctr";
+            break;
+        case model::PenAlignmentType::Inset:
+            sPenAlign = "in";
+            break;
+        case model::PenAlignmentType::Unset:
+            break;
+    }
 
-            pFS->singleElementNS(XML_a, XML_miter);
+    OString sCompoundLine;
+    switch (rLineStyle.meCompoundLineType)
+    {
+        case model::CompoundLineType::Single:
+            sCompoundLine = "sng";
+            break;
+        case model::CompoundLineType::Double:
+            sCompoundLine = "dbl";
+            break;
+        case model::CompoundLineType::ThickThin_Double:
+            sCompoundLine = "thickThin";
+            break;
+        case model::CompoundLineType::ThinThick_Double:
+            sCompoundLine = "thinThick";
+            break;
+        case model::CompoundLineType::Triple:
+            sCompoundLine = "tri";
+            break;
+        case model::CompoundLineType::Unset:
+            break;
+    }
+
+    pFS->startElementNS(XML_a, XML_ln, XML_w, 
OString::number(rLineStyle.mnWidth), XML_cap,
+                        sax_fastparser::UseIf(sCap, !sCap.isEmpty()), XML_cmpd,
+                        sax_fastparser::UseIf(sCompoundLine, 
!sCompoundLine.isEmpty()), XML_algn,
+                        sax_fastparser::UseIf(sPenAlign, 
!sPenAlign.isEmpty()));
+
+    if (rLineStyle.maLineDash.mePresetType != model::PresetDashType::Unset)
+    {
+        OString sPresetType;
+        switch (rLineStyle.maLineDash.mePresetType)
+        {
+            case model::PresetDashType::Dot:
+                sPresetType = "dot";
+                break;
+            case model::PresetDashType::Dash:
+                sPresetType = "dash";
+                break;
+            case model::PresetDashType::LargeDash:
+                sPresetType = "lgDash";
+                break;
+            case model::PresetDashType::DashDot:
+                sPresetType = "dashDot";
+                break;
+            case model::PresetDashType::LargeDashDot:
+                sPresetType = "lgDashDot";
+                break;
+            case model::PresetDashType::LargeDashDotDot:
+                sPresetType = "lgDashDotDot";
+                break;
+            case model::PresetDashType::Solid:
+                sPresetType = "solid";
+                break;
+            case model::PresetDashType::SystemDash:
+                sPresetType = "sysDash";
+                break;
+            case model::PresetDashType::SystemDot:
+                sPresetType = "sysDot";
+                break;
+            case model::PresetDashType::SystemDashDot:
+                sPresetType = "sysDashDot";
+                break;
+            case model::PresetDashType::SystemDashDotDot:
+                sPresetType = "sysDashDotDot";
+                break;
+            case model::PresetDashType::Unset:
+                break;
         }
-        pFS->endElementNS(XML_a, XML_ln);
+        pFS->singleElementNS(XML_a, XML_prstDash, XML_val, sPresetType);
     }
+
+    if (rLineStyle.maLineJoin.meType != model::LineJoinType::Unset)
     {
-        pFS->startElementNS(XML_a, XML_ln, XML_w, "6350", XML_cap, "flat", 
XML_cmpd, "sng",
-                            XML_algn, "ctr");
+        switch (rLineStyle.maLineJoin.meType)
         {
-            pFS->startElementNS(XML_a, XML_solidFill);
-            pFS->startElementNS(XML_a, XML_schemeClr, XML_val, "phClr");
-            pFS->singleElementNS(XML_a, XML_shade, XML_val, "95000");
-            pFS->endElementNS(XML_a, XML_schemeClr);
-            pFS->endElementNS(XML_a, XML_solidFill);
+            case model::LineJoinType::Round:
+                pFS->singleElementNS(XML_a, XML_round);
+                break;
+            case model::LineJoinType::Bevel:
+                pFS->singleElementNS(XML_a, XML_bevel);
+                break;
+            case model::LineJoinType::Miter:
+            {
+                sal_Int32 nMiterLimit = rLineStyle.maLineJoin.mnMiterLimit;
+                pFS->singleElementNS(
+                    XML_a, XML_miter, XML_lim,
+                    sax_fastparser::UseIf(OString::number(nMiterLimit), 
nMiterLimit > 0));
+            }
+            break;
+            case model::LineJoinType::Unset:
+                break;
+        }
+    }
 
-            pFS->singleElementNS(XML_a, XML_prstDash, XML_val, "solid");
+    pFS->endElementNS(XML_a, XML_ln);
+}
 
-            pFS->singleElementNS(XML_a, XML_miter);
-        }
-        pFS->endElementNS(XML_a, XML_ln);
+void writeEffectStyle(sax_fastparser::FSHelperPtr pFS, model::EffectStyle 
const& /*rEffectStyle*/)
+{
+    pFS->startElementNS(XML_a, XML_effectStyle);
+    pFS->singleElementNS(XML_a, XML_effectLst);
+    pFS->endElementNS(XML_a, XML_effectStyle);
+}
+
+} // end anonymous ns
+
+bool ThemeExport::writeFormatScheme(sax_fastparser::FSHelperPtr pFS,
+                                    model::FormatScheme const& rFormatScheme)
+{
+    // Format Scheme: 3 or more per list but only 3 will be used currently
+
+    // Fill Style List
+    rFormatScheme.ensureFillStyleList();
+    pFS->startElementNS(XML_a, XML_fillStyleLst);
+    for (auto const& rFillStyle : rFormatScheme.getFillStyleList())
+    {
+        writeFillStyle(pFS, rFillStyle);
+    }
+    pFS->endElementNS(XML_a, XML_fillStyleLst);
+
+    // Line Style List
+    rFormatScheme.ensureLineStyleList();
+    pFS->startElementNS(XML_a, XML_lnStyleLst);
+    for (auto const& rLineStyle : rFormatScheme.getLineStyleList())
+    {
+        writeLineStyle(pFS, rLineStyle);
     }
     pFS->endElementNS(XML_a, XML_lnStyleLst);
 
+    // Effect Style List
+    rFormatScheme.ensureEffectStyleList();
     pFS->startElementNS(XML_a, XML_effectStyleLst);
     {
-        pFS->startElementNS(XML_a, XML_effectStyle);
-        pFS->singleElementNS(XML_a, XML_effectLst);
-        pFS->endElementNS(XML_a, XML_effectStyle);
-
-        pFS->startElementNS(XML_a, XML_effectStyle);
-        pFS->singleElementNS(XML_a, XML_effectLst);
-        pFS->endElementNS(XML_a, XML_effectStyle);
-
-        pFS->startElementNS(XML_a, XML_effectStyle);
-        pFS->singleElementNS(XML_a, XML_effectLst);
-        pFS->endElementNS(XML_a, XML_effectStyle);
+        for (auto const& rEffectStyle : rFormatScheme.getEffectStyleList())
+        {
+            writeEffectStyle(pFS, rEffectStyle);
+        }
     }
     pFS->endElementNS(XML_a, XML_effectStyleLst);
 
+    // Background Fill Style List
+    rFormatScheme.ensureBackgroundFillStyleList();
     pFS->startElementNS(XML_a, XML_bgFillStyleLst);
+    for (auto const& rFillStyle : rFormatScheme.getBackgroundFillStyleList())
     {
-        pFS->startElementNS(XML_a, XML_solidFill);
-        pFS->singleElementNS(XML_a, XML_schemeClr, XML_val, "phClr");
-        pFS->endElementNS(XML_a, XML_solidFill);
-
-        pFS->startElementNS(XML_a, XML_solidFill);
-        pFS->singleElementNS(XML_a, XML_schemeClr, XML_val, "phClr");
-        pFS->endElementNS(XML_a, XML_solidFill);
-
-        pFS->startElementNS(XML_a, XML_solidFill);
-        pFS->singleElementNS(XML_a, XML_schemeClr, XML_val, "phClr");
-        pFS->endElementNS(XML_a, XML_solidFill);
+        writeBackgroundFillStyle(pFS, rFillStyle);
     }
     pFS->endElementNS(XML_a, XML_bgFillStyleLst);
 
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
diff --git a/svx/source/svdraw/svdpage.cxx b/svx/source/svdraw/svdpage.cxx
index 235fc58da508..e685c40c89a5 100644
--- a/svx/source/svdraw/svdpage.cxx
+++ b/svx/source/svdraw/svdpage.cxx
@@ -1223,9 +1223,9 @@ SdrPageProperties::SdrPageProperties(SdrPage& rSdrPage)
         maProperties.Put(XFillStyleItem(drawing::FillStyle_NONE));
     }
 
-    if (rSdrPage.getSdrModelFromSdrPage().IsWriter())
+    if (rSdrPage.getSdrModelFromSdrPage().IsWriter() || 
rSdrPage.IsMasterPage())
     {
-        mpTheme.reset(new model::Theme("Office"));
+        mpTheme.reset(new model::Theme("Office Theme"));
         auto const* pColorSet = 
svx::ColorSets::get().getColorSet(u"LibreOffice");
         if (pColorSet)
         {

Reply via email to