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>
diff --git a/include/docmodel/theme/FormatScheme.hxx b/include/docmodel/theme/FormatScheme.hxx
index feec16e..420d5c1 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 70766a8..9a5c9fe 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 1889709..8e35b80 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 3abc2cb..b198aae 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
{
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)
{
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));
}
}
}
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);
}
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);
}
}
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())
{
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);
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;
}
if (!sPathType.isEmpty())
{
pFS->startElementNS(XML_a, XML_path, XML_path, sPathType);
writeRelativeRectangle(pFS, XML_fillToRect, rGradientFill.maFillToRectangle);
pFS->endElementNS(XML_a, XML_path);
}
}
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_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:
{
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;
}
OString sPenAlign;
switch (rLineStyle.mePenAlignment)
{
case model::PenAlignmentType::Center:
sPenAlign = "ctr";
break;
case model::PenAlignmentType::Inset:
sPenAlign = "in";
break;
case model::PenAlignmentType::Unset:
break;
}
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->singleElementNS(XML_a, XML_prstDash, XML_val, sPresetType);
}
if (rLineStyle.maLineJoin.meType != model::LineJoinType::Unset)
{
switch (rLineStyle.maLineJoin.meType)
{
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->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())
{
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);
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())
{
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);
pFS->singleElementNS(XML_a, XML_prstDash, XML_val, "solid");
pFS->singleElementNS(XML_a, XML_miter);
}
pFS->endElementNS(XML_a, XML_ln);
}
{
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);
pFS->singleElementNS(XML_a, XML_prstDash, XML_val, "solid");
pFS->singleElementNS(XML_a, XML_miter);
}
pFS->endElementNS(XML_a, XML_ln);
}
{
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);
pFS->singleElementNS(XML_a, XML_prstDash, XML_val, "solid");
pFS->singleElementNS(XML_a, XML_miter);
}
pFS->endElementNS(XML_a, XML_ln);
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 32d9b33..f5420a6 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);
{
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));
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)));
xMasterPage->setPropertyValue("Theme", uno::Any(model::theme::createXTheme(pTheme)));
}
// When exporting to PPTX:
save("Impress Office Open XML");
// Export to PPTX and load again:
saveAndReload("Impress Office Open XML");
// Then verify that this color is not lost:
// 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 48c928d..0c7644c 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 c0215ec..9e207ba 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");
oox::ThemeExport aThemeExport(this);
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);
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 235fc58..e685c40 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)
{