diff options
Diffstat (limited to 'oox/source/export/ThemeExport.cxx')
-rw-r--r-- | oox/source/export/ThemeExport.cxx | 902 |
1 files changed, 902 insertions, 0 deletions
diff --git a/oox/source/export/ThemeExport.cxx b/oox/source/export/ThemeExport.cxx new file mode 100644 index 0000000000..6e0efb341a --- /dev/null +++ b/oox/source/export/ThemeExport.cxx @@ -0,0 +1,902 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <oox/export/ThemeExport.hxx> + +#include <oox/token/namespaces.hxx> +#include <oox/token/properties.hxx> +#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> +#include <oox/export/drawingml.hxx> +#include <frozen/bits/defines.h> +#include <frozen/bits/elsa_std.h> +#include <frozen/unordered_map.h> + +namespace oox +{ +namespace +{ +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)); +} +} // end anonymous namespace + +ThemeExport::ThemeExport(oox::core::XmlFilterBase* pFilterBase, + oox::drawingml::DocumentType eDocumentType) + : mpFilterBase(pFilterBase) + , meDocumentType(eDocumentType) +{ +} + +void ThemeExport::write(OUString const& rPath, model::Theme const& rTheme) +{ + mpFS = mpFilterBase->openFragmentStreamWithSerializer( + rPath, "application/vnd.openxmlformats-officedocument.theme+xml"); + + OUString aThemeName = rTheme.GetName(); + + mpFS->startElementNS(XML_a, XML_theme, FSNS(XML_xmlns, XML_a), + mpFilterBase->getNamespaceURL(OOX_NS(dml)), FSNS(XML_xmlns, XML_r), + mpFilterBase->getNamespaceURL(OOX_NS(officeRel)), XML_name, aThemeName); + + mpFS->startElementNS(XML_a, XML_themeElements); + + const auto pColorSet = rTheme.getColorSet(); + + mpFS->startElementNS(XML_a, XML_clrScheme, XML_name, pColorSet->getName()); + writeColorSet(rTheme); + mpFS->endElementNS(XML_a, XML_clrScheme); + + model::FontScheme const& rFontScheme = rTheme.getFontScheme(); + mpFS->startElementNS(XML_a, XML_fontScheme, XML_name, rFontScheme.getName()); + writeFontScheme(rFontScheme); + mpFS->endElementNS(XML_a, XML_fontScheme); + + model::FormatScheme const& rFormatScheme = rTheme.getFormatScheme(); + mpFS->startElementNS(XML_a, XML_fmtScheme); + writeFormatScheme(rFormatScheme); + mpFS->endElementNS(XML_a, XML_fmtScheme); + + mpFS->endElementNS(XML_a, XML_themeElements); + mpFS->endElementNS(XML_a, XML_theme); + + mpFS->endDocument(); +} + +namespace +{ +void fillAttrList(rtl::Reference<sax_fastparser::FastAttributeList> const& pAttrList, + model::ThemeFont const& rThemeFont) +{ + if (rThemeFont.maTypeface.isEmpty()) + { + pAttrList->add(XML_typeface, ""); // 'typeface' attribute is mandatory + return; + } + + pAttrList->add(XML_typeface, rThemeFont.maTypeface); + + 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)); +} + +} // end anonymous ns + +bool ThemeExport::writeFontScheme(model::FontScheme const& rFontScheme) +{ + mpFS->startElementNS(XML_a, XML_majorFont); + + { + auto aAttrList = sax_fastparser::FastSerializerHelper::createAttrList(); + fillAttrList(aAttrList, rFontScheme.getMajorLatin()); + mpFS->singleElementNS(XML_a, XML_latin, aAttrList); + } + { + auto aAttrList = sax_fastparser::FastSerializerHelper::createAttrList(); + fillAttrList(aAttrList, rFontScheme.getMajorAsian()); + mpFS->singleElementNS(XML_a, XML_ea, aAttrList); + } + { + auto aAttrList = sax_fastparser::FastSerializerHelper::createAttrList(); + fillAttrList(aAttrList, rFontScheme.getMajorComplex()); + mpFS->singleElementNS(XML_a, XML_cs, aAttrList); + } + + mpFS->endElementNS(XML_a, XML_majorFont); + + mpFS->startElementNS(XML_a, XML_minorFont); + + { + auto aAttrList = sax_fastparser::FastSerializerHelper::createAttrList(); + fillAttrList(aAttrList, rFontScheme.getMinorLatin()); + mpFS->singleElementNS(XML_a, XML_latin, aAttrList); + } + { + auto aAttrList = sax_fastparser::FastSerializerHelper::createAttrList(); + fillAttrList(aAttrList, rFontScheme.getMinorAsian()); + mpFS->singleElementNS(XML_a, XML_ea, aAttrList); + } + { + auto aAttrList = sax_fastparser::FastSerializerHelper::createAttrList(); + fillAttrList(aAttrList, rFontScheme.getMinorComplex()); + mpFS->singleElementNS(XML_a, XML_cs, aAttrList); + } + + mpFS->endElementNS(XML_a, XML_minorFont); + + return true; +} + +namespace +{ +constexpr frozen::unordered_map<model::TransformationType, sal_Int32, 4> constTransformTypeTokenMap{ + { model::TransformationType::Tint, XML_tint }, + { model::TransformationType::Shade, XML_shade }, + { model::TransformationType::LumMod, XML_lumMod }, + { model::TransformationType::LumOff, XML_lumOff }, +}; + +constexpr frozen::unordered_map<model::ThemeColorType, const char*, 12> 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" } +}; + +constexpr frozen::unordered_map<model::SystemColorType, const char*, 30> + constSystemColorTypeTokenMap{ + { 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" } + }; + +constexpr frozen::unordered_map<sal_Int32, model::ThemeColorType, 12> constTokenMap{ + { XML_dk1, model::ThemeColorType::Dark1 }, + { XML_lt1, model::ThemeColorType::Light1 }, + { XML_dk2, model::ThemeColorType::Dark2 }, + { XML_lt2, model::ThemeColorType::Light2 }, + { XML_accent1, model::ThemeColorType::Accent1 }, + { XML_accent2, model::ThemeColorType::Accent2 }, + { XML_accent3, model::ThemeColorType::Accent3 }, + { XML_accent4, model::ThemeColorType::Accent4 }, + { XML_accent5, model::ThemeColorType::Accent5 }, + { XML_accent6, model::ThemeColorType::Accent6 }, + { XML_hlink, model::ThemeColorType::Hyperlink }, + { XML_folHlink, model::ThemeColorType::FollowedHyperlink } +}; + +} // end anonymous ns + +void ThemeExport::writeColorTransformations( + std::vector<model::Transformation> const& rTransformations) +{ + for (model::Transformation const& rTransformation : rTransformations) + { + auto iterator = constTransformTypeTokenMap.find(rTransformation.meType); + if (iterator != constTransformTypeTokenMap.end()) + { + sal_Int32 nToken = iterator->second; + mpFS->singleElementNS(XML_a, nToken, XML_val, + OString::number(rTransformation.mnValue * 10)); + } + } +} + +void ThemeExport::writeColorRGB(model::ComplexColor const& rComplexColor) +{ + auto aColor = rComplexColor.getRGBColor(); + mpFS->startElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(sal_Int32(aColor))); + mpFS->endElementNS(XML_a, XML_srgbClr); +} + +void ThemeExport::writeColorCRGB(model::ComplexColor const& rComplexColor) +{ + mpFS->startElementNS(XML_a, XML_scrgbClr, XML_r, + OString::number(sal_Int32(rComplexColor.getRed())), XML_g, + OString::number(sal_Int32(rComplexColor.getGreen())), XML_b, + OString::number(sal_Int32(rComplexColor.getBlue()))); + writeColorTransformations(rComplexColor.getTransformations()); + mpFS->endElementNS(XML_a, XML_scrgbClr); +} + +void ThemeExport::writeColorHSL(model::ComplexColor const& rComplexColor) +{ + mpFS->startElementNS(XML_a, XML_hslClr, XML_hue, + OString::number(sal_Int32(rComplexColor.getRed())), XML_sat, + OString::number(sal_Int32(rComplexColor.getGreen())), XML_lum, + OString::number(sal_Int32(rComplexColor.getBlue()))); + writeColorTransformations(rComplexColor.getTransformations()); + mpFS->endElementNS(XML_a, XML_hslClr); +} + +void ThemeExport::writeColorTheme(model::ComplexColor const& rComplexColor) +{ + auto iterator = constThemeColorTypeTokenMap.find(rComplexColor.getThemeColorType()); + if (iterator != constThemeColorTypeTokenMap.end()) + { + const char* sValue = iterator->second; + mpFS->startElementNS(XML_a, XML_schemeClr, XML_val, sValue); + writeColorTransformations(rComplexColor.getTransformations()); + mpFS->endElementNS(XML_a, XML_schemeClr); + } +} + +void ThemeExport::writeColorSystem(model::ComplexColor const& rComplexColor) +{ + auto iterator = constSystemColorTypeTokenMap.find(rComplexColor.getSystemColorType()); + if (iterator != constSystemColorTypeTokenMap.end()) + { + const char* sValue = iterator->second; + mpFS->startElementNS(XML_a, XML_sysClr, XML_val, sValue); + //XML_lastClr + writeColorTransformations(rComplexColor.getTransformations()); + mpFS->endElementNS(XML_a, XML_schemeClr); + } +} + +void ThemeExport::writeColorPlaceholder(model::ComplexColor const& rComplexColor) +{ + mpFS->startElementNS(XML_a, XML_schemeClr, XML_val, "phClr"); + writeColorTransformations(rComplexColor.getTransformations()); + mpFS->endElementNS(XML_a, XML_schemeClr); +} + +void ThemeExport::writeComplexColor(model::ComplexColor const& rComplexColor) +{ + switch (rComplexColor.getType()) + { + case model::ColorType::Unused: + break; + case model::ColorType::RGB: + writeColorRGB(rComplexColor); + break; + case model::ColorType::CRGB: + writeColorCRGB(rComplexColor); + break; + case model::ColorType::HSL: + writeColorHSL(rComplexColor); + break; + case model::ColorType::Theme: + writeColorTheme(rComplexColor); + break; + case model::ColorType::Palette: + break; + case model::ColorType::System: + writeColorSystem(rComplexColor); + break; + case model::ColorType::Placeholder: + writeColorPlaceholder(rComplexColor); + break; + } +} + +void ThemeExport::writeSolidFill(model::SolidFill const& rSolidFill) +{ + mpFS->startElementNS(XML_a, XML_solidFill); + writeComplexColor(rSolidFill.maColor); + mpFS->endElementNS(XML_a, XML_solidFill); +} + +void ThemeExport::writeGradientFill(model::GradientFill const& rGradientFill) +{ + mpFS->startElementNS(XML_a, XML_gradFill); + mpFS->startElementNS(XML_a, XML_gsLst); + for (auto const& rStop : rGradientFill.maGradientStops) + { + mpFS->startElementNS(XML_a, XML_gs, XML_pos, + OString::number(sal_Int32(rStop.mfPosition * 100000.0))); + writeComplexColor(rStop.maColor); + mpFS->endElementNS(XML_a, XML_gs); + } + mpFS->endElementNS(XML_a, XML_gsLst); + + if (rGradientFill.meGradientType == model::GradientType::Linear) + { + mpFS->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"_ostr; + break; + case model::GradientType::Rectangle: + sPathType = "rect"_ostr; + break; + case model::GradientType::Shape: + sPathType = "shape"_ostr; + break; + default: + break; + } + + if (!sPathType.isEmpty()) + { + mpFS->startElementNS(XML_a, XML_path, XML_path, sPathType); + writeRelativeRectangle(mpFS, XML_fillToRect, rGradientFill.maFillToRectangle); + mpFS->endElementNS(XML_a, XML_path); + } + } + writeRelativeRectangle(mpFS, XML_tileRect, rGradientFill.maTileRectangle); + mpFS->endElementNS(XML_a, XML_gradFill); +} + +void ThemeExport::writePatternFill(model::PatternFill const& rPatternFill) +{ + OString sPresetType; + switch (rPatternFill.mePatternPreset) + { + case model::PatternPreset::Percent_5: + sPresetType = "pct5"_ostr; + break; + case model::PatternPreset::Percent_10: + sPresetType = "pct10"_ostr; + break; + case model::PatternPreset::Percent_20: + sPresetType = "pct20"_ostr; + break; + case model::PatternPreset::Percent_25: + sPresetType = "pct25"_ostr; + break; + case model::PatternPreset::Percent_30: + sPresetType = "pct30"_ostr; + break; + case model::PatternPreset::Percent_40: + sPresetType = "pct40"_ostr; + break; + case model::PatternPreset::Percent_50: + sPresetType = "pct50"_ostr; + break; + case model::PatternPreset::Percent_60: + sPresetType = "pct60"_ostr; + break; + case model::PatternPreset::Percent_70: + sPresetType = "pct70"_ostr; + break; + case model::PatternPreset::Percent_75: + sPresetType = "pct75"_ostr; + break; + case model::PatternPreset::Percent_80: + sPresetType = "pct80"_ostr; + break; + case model::PatternPreset::Percent_90: + sPresetType = "pct90"_ostr; + break; + case model::PatternPreset::Horizontal: + sPresetType = "horz"_ostr; + break; + case model::PatternPreset::Vertical: + sPresetType = "vert"_ostr; + break; + case model::PatternPreset::LightHorizontal: + sPresetType = "ltHorz"_ostr; + break; + case model::PatternPreset::LightVertical: + sPresetType = "ltVert"_ostr; + break; + case model::PatternPreset::DarkHorizontal: + sPresetType = "dkHorz"_ostr; + break; + case model::PatternPreset::DarkVertical: + sPresetType = "dkVert"_ostr; + break; + case model::PatternPreset::NarrowHorizontal: + sPresetType = "narHorz"_ostr; + break; + case model::PatternPreset::NarrowVertical: + sPresetType = "narVert"_ostr; + break; + case model::PatternPreset::DashedHorizontal: + sPresetType = "dashHorz"_ostr; + break; + case model::PatternPreset::DashedVertical: + sPresetType = "dashVert"_ostr; + break; + case model::PatternPreset::Cross: + sPresetType = "cross"_ostr; + break; + case model::PatternPreset::DownwardDiagonal: + sPresetType = "dnDiag"_ostr; + break; + case model::PatternPreset::UpwardDiagonal: + sPresetType = "upDiag"_ostr; + break; + case model::PatternPreset::LightDownwardDiagonal: + sPresetType = "ltDnDiag"_ostr; + break; + case model::PatternPreset::LightUpwardDiagonal: + sPresetType = "ltUpDiag"_ostr; + break; + case model::PatternPreset::DarkDownwardDiagonal: + sPresetType = "dkDnDiag"_ostr; + break; + case model::PatternPreset::DarkUpwardDiagonal: + sPresetType = "dkUpDiag"_ostr; + break; + case model::PatternPreset::WideDownwardDiagonal: + sPresetType = "wdDnDiag"_ostr; + break; + case model::PatternPreset::WideUpwardDiagonal: + sPresetType = "wdUpDiag"_ostr; + break; + case model::PatternPreset::DashedDownwardDiagonal: + sPresetType = "dashDnDiag"_ostr; + break; + case model::PatternPreset::DashedUpwardDiagonal: + sPresetType = "dashUpDiag"_ostr; + break; + case model::PatternPreset::DiagonalCross: + sPresetType = "diagCross"_ostr; + break; + case model::PatternPreset::SmallCheckerBoard: + sPresetType = "smCheck"_ostr; + break; + case model::PatternPreset::LargeCheckerBoard: + sPresetType = "lgCheck"_ostr; + break; + case model::PatternPreset::SmallGrid: + sPresetType = "smGrid"_ostr; + break; + case model::PatternPreset::LargeGrid: + sPresetType = "lgGrid"_ostr; + break; + case model::PatternPreset::DottedGrid: + sPresetType = "dotGrid"_ostr; + break; + case model::PatternPreset::SmallConfetti: + sPresetType = "smConfetti"_ostr; + break; + case model::PatternPreset::LargeConfetti: + sPresetType = "lgConfetti"_ostr; + break; + case model::PatternPreset::HorizontalBrick: + sPresetType = "horzBrick"_ostr; + break; + case model::PatternPreset::DiagonalBrick: + sPresetType = "diagBrick"_ostr; + break; + case model::PatternPreset::SolidDiamond: + sPresetType = "solidDmnd"_ostr; + break; + case model::PatternPreset::OpenDiamond: + sPresetType = "openDmnd"_ostr; + break; + case model::PatternPreset::DottedDiamond: + sPresetType = "dotDmnd"_ostr; + break; + case model::PatternPreset::Plaid: + sPresetType = "plaid"_ostr; + break; + case model::PatternPreset::Sphere: + sPresetType = "sphere"_ostr; + break; + case model::PatternPreset::Weave: + sPresetType = "weave"_ostr; + break; + case model::PatternPreset::Divot: + sPresetType = "divot"_ostr; + break; + case model::PatternPreset::Shingle: + sPresetType = "shingle"_ostr; + break; + case model::PatternPreset::Wave: + sPresetType = "wave"_ostr; + break; + case model::PatternPreset::Trellis: + sPresetType = "trellis"_ostr; + break; + case model::PatternPreset::ZigZag: + sPresetType = "zigZag"_ostr; + break; + default: + break; + } + + if (!sPresetType.isEmpty()) + { + mpFS->startElementNS(XML_a, XML_pattFill, XML_prst, sPresetType); + + mpFS->startElementNS(XML_a, XML_fgClr); + writeComplexColor(rPatternFill.maForegroundColor); + mpFS->endElementNS(XML_a, XML_fgClr); + + mpFS->startElementNS(XML_a, XML_bgClr); + writeComplexColor(rPatternFill.maBackgroundColor); + mpFS->endElementNS(XML_a, XML_bgClr); + + mpFS->endElementNS(XML_a, XML_pattFill); + } +} + +namespace +{ +OString convertFlipMode(model::FlipMode eFlipMode) +{ + switch (eFlipMode) + { + case model::FlipMode::X: + return "x"_ostr; + case model::FlipMode::Y: + return "y"_ostr; + case model::FlipMode::XY: + return "xy"_ostr; + case model::FlipMode::None: + return "none"_ostr; + } + return "none"_ostr; +} + +OString convertRectangleAlignment(model::RectangleAlignment eFlipMode) +{ + switch (eFlipMode) + { + case model::RectangleAlignment::TopLeft: + return "tl"_ostr; + case model::RectangleAlignment::Top: + return "t"_ostr; + case model::RectangleAlignment::TopRight: + return "tr"_ostr; + case model::RectangleAlignment::Left: + return "l"_ostr; + case model::RectangleAlignment::Center: + return "ctr"_ostr; + case model::RectangleAlignment::Right: + return "r"_ostr; + case model::RectangleAlignment::BottomLeft: + return "bl"_ostr; + case model::RectangleAlignment::Bottom: + return "b"_ostr; + case model::RectangleAlignment::BottomRight: + return "br"_ostr; + case model::RectangleAlignment::Unset: + break; + } + return {}; +} +} // end anonymous ns + +void ThemeExport::writeBlip(model::BlipFill const& rBlipFill) +{ + if (!rBlipFill.mxGraphic.is()) + return; + oox::drawingml::GraphicExport aExporter(mpFS, mpFilterBase, meDocumentType); + Graphic aGraphic(rBlipFill.mxGraphic); + aExporter.writeBlip(aGraphic, rBlipFill.maBlipEffects, false); +} + +void ThemeExport::writeBlipFill(model::BlipFill const& rBlipFill) +{ + mpFS->startElementNS(XML_a, XML_blipFill, XML_rotWithShape, + rBlipFill.mbRotateWithShape ? "1" : "0" + /*XML_dpi*/); + + writeBlip(rBlipFill); + + writeRelativeRectangle(mpFS, XML_srcRect, rBlipFill.maClipRectangle); + + if (rBlipFill.meMode == model::BitmapMode::Tile) + { + OString aFlipMode = convertFlipMode(rBlipFill.meTileFlipMode); + OString aAlignment = convertRectangleAlignment(rBlipFill.meTileAlignment); + + mpFS->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); + mpFS->endElementNS(XML_a, XML_tile); + } + else if (rBlipFill.meMode == model::BitmapMode::Stretch) + { + mpFS->startElementNS(XML_a, XML_stretch); + writeRelativeRectangle(mpFS, XML_fillRect, rBlipFill.maFillRectangle); + mpFS->endElementNS(XML_a, XML_stretch); + } + + mpFS->endElementNS(XML_a, XML_blipFill); +} + +void ThemeExport::writeFillStyle(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(*pSolidFill); + } + break; + case model::FillType::Gradient: + { + auto* pGradientFill = static_cast<model::GradientFill*>(rFillStyle.mpFill.get()); + writeGradientFill(*pGradientFill); + } + break; + case model::FillType::Pattern: + { + auto* pPatternFill = static_cast<model::PatternFill*>(rFillStyle.mpFill.get()); + writePatternFill(*pPatternFill); + } + break; + case model::FillType::Blip: + { + auto* pBlipFill = static_cast<model::BlipFill*>(rFillStyle.mpFill.get()); + writeBlipFill(*pBlipFill); + } + break; + } +} + +void ThemeExport::writeBackgroundFillStyle(model::FillStyle const& rFillStyle) +{ + writeFillStyle(rFillStyle); +} + +void ThemeExport::writeLineStyle(model::LineStyle const& rLineStyle) +{ + OString sCap; + switch (rLineStyle.meCapType) + { + case model::CapType::Flat: + sCap = "flat"_ostr; + break; + case model::CapType::Round: + sCap = "rnd"_ostr; + break; + case model::CapType::Square: + sCap = "sq"_ostr; + break; + case model::CapType::Unset: + break; + } + + OString sPenAlign; + switch (rLineStyle.mePenAlignment) + { + case model::PenAlignmentType::Center: + sPenAlign = "ctr"_ostr; + break; + case model::PenAlignmentType::Inset: + sPenAlign = "in"_ostr; + break; + case model::PenAlignmentType::Unset: + break; + } + + OString sCompoundLine; + switch (rLineStyle.meCompoundLineType) + { + case model::CompoundLineType::Single: + sCompoundLine = "sng"_ostr; + break; + case model::CompoundLineType::Double: + sCompoundLine = "dbl"_ostr; + break; + case model::CompoundLineType::ThickThin_Double: + sCompoundLine = "thickThin"_ostr; + break; + case model::CompoundLineType::ThinThick_Double: + sCompoundLine = "thinThick"_ostr; + break; + case model::CompoundLineType::Triple: + sCompoundLine = "tri"_ostr; + break; + case model::CompoundLineType::Unset: + break; + } + + mpFS->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"_ostr; + break; + case model::PresetDashType::Dash: + sPresetType = "dash"_ostr; + break; + case model::PresetDashType::LargeDash: + sPresetType = "lgDash"_ostr; + break; + case model::PresetDashType::DashDot: + sPresetType = "dashDot"_ostr; + break; + case model::PresetDashType::LargeDashDot: + sPresetType = "lgDashDot"_ostr; + break; + case model::PresetDashType::LargeDashDotDot: + sPresetType = "lgDashDotDot"_ostr; + break; + case model::PresetDashType::Solid: + sPresetType = "solid"_ostr; + break; + case model::PresetDashType::SystemDash: + sPresetType = "sysDash"_ostr; + break; + case model::PresetDashType::SystemDot: + sPresetType = "sysDot"_ostr; + break; + case model::PresetDashType::SystemDashDot: + sPresetType = "sysDashDot"_ostr; + break; + case model::PresetDashType::SystemDashDotDot: + sPresetType = "sysDashDotDot"_ostr; + break; + case model::PresetDashType::Unset: + break; + } + mpFS->singleElementNS(XML_a, XML_prstDash, XML_val, sPresetType); + } + + if (rLineStyle.maLineJoin.meType != model::LineJoinType::Unset) + { + switch (rLineStyle.maLineJoin.meType) + { + case model::LineJoinType::Round: + mpFS->singleElementNS(XML_a, XML_round); + break; + case model::LineJoinType::Bevel: + mpFS->singleElementNS(XML_a, XML_bevel); + break; + case model::LineJoinType::Miter: + { + sal_Int32 nMiterLimit = rLineStyle.maLineJoin.mnMiterLimit; + mpFS->singleElementNS( + XML_a, XML_miter, XML_lim, + sax_fastparser::UseIf(OString::number(nMiterLimit), nMiterLimit > 0)); + } + break; + case model::LineJoinType::Unset: + break; + } + } + + mpFS->endElementNS(XML_a, XML_ln); +} + +void ThemeExport::writeEffectStyle(model::EffectStyle const& /*rEffectStyle*/) +{ + mpFS->startElementNS(XML_a, XML_effectStyle); + mpFS->singleElementNS(XML_a, XML_effectLst); + mpFS->endElementNS(XML_a, XML_effectStyle); +} + +bool ThemeExport::writeFormatScheme(model::FormatScheme const& rFormatScheme) +{ + // Format Scheme: 3 or more per list but only 3 will be used currently + + // Fill Style List + rFormatScheme.ensureFillStyleList(); + mpFS->startElementNS(XML_a, XML_fillStyleLst); + for (auto const& rFillStyle : rFormatScheme.getFillStyleList()) + { + writeFillStyle(rFillStyle); + } + mpFS->endElementNS(XML_a, XML_fillStyleLst); + + // Line Style List + rFormatScheme.ensureLineStyleList(); + mpFS->startElementNS(XML_a, XML_lnStyleLst); + for (auto const& rLineStyle : rFormatScheme.getLineStyleList()) + { + writeLineStyle(rLineStyle); + } + mpFS->endElementNS(XML_a, XML_lnStyleLst); + + // Effect Style List + rFormatScheme.ensureEffectStyleList(); + mpFS->startElementNS(XML_a, XML_effectStyleLst); + { + for (auto const& rEffectStyle : rFormatScheme.getEffectStyleList()) + { + writeEffectStyle(rEffectStyle); + } + } + mpFS->endElementNS(XML_a, XML_effectStyleLst); + + // Background Fill Style List + rFormatScheme.ensureBackgroundFillStyleList(); + mpFS->startElementNS(XML_a, XML_bgFillStyleLst); + for (auto const& rFillStyle : rFormatScheme.getBackgroundFillStyleList()) + { + writeBackgroundFillStyle(rFillStyle); + } + mpFS->endElementNS(XML_a, XML_bgFillStyleLst); + + return true; +} + +bool ThemeExport::writeColorSet(model::Theme const& rTheme) +{ + static const constexpr std::array<sal_Int32, 12> constTokenArray + = { XML_dk1, XML_lt1, XML_dk2, XML_lt2, XML_accent1, XML_accent2, + XML_accent3, XML_accent4, XML_accent5, XML_accent6, XML_hlink, XML_folHlink }; + + const auto pColorSet = rTheme.getColorSet(); + if (!pColorSet) + return false; + + for (auto nToken : constTokenArray) + { + auto iterator = constTokenMap.find(nToken); + if (iterator != constTokenMap.end()) + { + model::ThemeColorType eColorType = iterator->second; + Color aColor = pColorSet->getColor(eColorType); + mpFS->startElementNS(XML_a, nToken); + mpFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(sal_Int32(aColor))); + mpFS->endElementNS(XML_a, nToken); + } + } + + return true; +} + +} // end namespace oox + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |