summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2023-03-23 11:37:40 +0900
committerTomaž Vajngerl <quikee@gmail.com>2023-04-24 23:49:57 +0200
commitc3f7720ff13c34b9cf2c90d9c9b6dcc3d8f4c7a5 (patch)
tree98b24e4e90c0d858307b58bcd09c9b2d590893e8
parent09cdcb5f37bb4e42da7b28db6e757b9f2affed14 (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.hxx132
-rw-r--r--include/docmodel/theme/Theme.hxx23
-rw-r--r--include/oox/export/ThemeExport.hxx4
-rw-r--r--oox/source/export/ThemeExport.cxx757
-rw-r--r--sd/qa/filter/eppt/eppt.cxx85
-rw-r--r--sd/source/filter/eppt/epptooxml.hxx7
-rw-r--r--sd/source/filter/eppt/pptx-epptooxml.cxx316
-rw-r--r--svx/source/svdraw/svdpage.cxx4
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)
{