diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2023-03-23 11:37:40 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2023-04-24 23:49:57 +0200 |
commit | c3f7720ff13c34b9cf2c90d9c9b6dcc3d8f4c7a5 (patch) | |
tree | 98b24e4e90c0d858307b58bcd09c9b2d590893e8 | |
parent | 09cdcb5f37bb4e42da7b28db6e757b9f2affed14 (diff) |
oox: extend ThemeExport to export font and format scheme of a theme
Also use the ThemeExport when exporting PPTX documents and remove
all the hard-coded theme bits.
Change-Id: I03791e23d6ac4023748b5a553e4824b72ed63a93
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149363
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r-- | include/docmodel/theme/FormatScheme.hxx | 132 | ||||
-rw-r--r-- | include/docmodel/theme/Theme.hxx | 23 | ||||
-rw-r--r-- | include/oox/export/ThemeExport.hxx | 4 | ||||
-rw-r--r-- | oox/source/export/ThemeExport.cxx | 757 | ||||
-rw-r--r-- | sd/qa/filter/eppt/eppt.cxx | 85 | ||||
-rw-r--r-- | sd/source/filter/eppt/epptooxml.hxx | 7 | ||||
-rw-r--r-- | sd/source/filter/eppt/pptx-epptooxml.cxx | 316 | ||||
-rw-r--r-- | svx/source/svdraw/svdpage.cxx | 4 |
8 files changed, 892 insertions, 436 deletions
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) { |