1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <oox/export/ThemeExport.hxx>
12 #include <oox/token/namespaces.hxx>
13 #include <oox/token/properties.hxx>
14 #include <oox/token/tokens.hxx>
15 #include <oox/export/utils.hxx>
16 #include <docmodel/theme/Theme.hxx>
17 #include <docmodel/theme/FormatScheme.hxx>
18 #include <sax/fshelper.hxx>
19 #include <sax/fastattribs.hxx>
20 #include <unordered_map>
21 #include <oox/export/drawingml.hxx>
22 #include <frozen/bits/defines.h>
23 #include <frozen/bits/elsa_std.h>
24 #include <frozen/unordered_map.h>
30 void writeRelativeRectangle(sax_fastparser::FSHelperPtr pFS
, sal_Int32 nToken
,
31 model::RelativeRectangle
const& rRelativeRectangle
)
33 pFS
->singleElementNS(XML_a
, nToken
, XML_l
, OString::number(rRelativeRectangle
.mnLeft
), XML_t
,
34 OString::number(rRelativeRectangle
.mnTop
), XML_r
,
35 OString::number(rRelativeRectangle
.mnRight
), XML_b
,
36 OString::number(rRelativeRectangle
.mnBottom
));
38 } // end anonymous namespace
40 ThemeExport::ThemeExport(oox::core::XmlFilterBase
* pFilterBase
,
41 oox::drawingml::DocumentType eDocumentType
)
42 : mpFilterBase(pFilterBase
)
43 , meDocumentType(eDocumentType
)
47 void ThemeExport::write(OUString
const& rPath
, model::Theme
const& rTheme
)
49 mpFS
= mpFilterBase
->openFragmentStreamWithSerializer(
50 rPath
, "application/vnd.openxmlformats-officedocument.theme+xml");
52 OUString aThemeName
= rTheme
.GetName();
54 mpFS
->startElementNS(XML_a
, XML_theme
, FSNS(XML_xmlns
, XML_a
),
55 mpFilterBase
->getNamespaceURL(OOX_NS(dml
)), FSNS(XML_xmlns
, XML_r
),
56 mpFilterBase
->getNamespaceURL(OOX_NS(officeRel
)), XML_name
, aThemeName
);
58 mpFS
->startElementNS(XML_a
, XML_themeElements
);
60 const auto pColorSet
= rTheme
.getColorSet();
62 mpFS
->startElementNS(XML_a
, XML_clrScheme
, XML_name
, pColorSet
->getName());
63 writeColorSet(rTheme
);
64 mpFS
->endElementNS(XML_a
, XML_clrScheme
);
66 model::FontScheme
const& rFontScheme
= rTheme
.getFontScheme();
67 mpFS
->startElementNS(XML_a
, XML_fontScheme
, XML_name
, rFontScheme
.getName());
68 writeFontScheme(rFontScheme
);
69 mpFS
->endElementNS(XML_a
, XML_fontScheme
);
71 model::FormatScheme
const& rFormatScheme
= rTheme
.getFormatScheme();
72 mpFS
->startElementNS(XML_a
, XML_fmtScheme
);
73 writeFormatScheme(rFormatScheme
);
74 mpFS
->endElementNS(XML_a
, XML_fmtScheme
);
76 mpFS
->endElementNS(XML_a
, XML_themeElements
);
77 mpFS
->endElementNS(XML_a
, XML_theme
);
84 void fillAttrList(rtl::Reference
<sax_fastparser::FastAttributeList
> const& pAttrList
,
85 model::ThemeFont
const& rThemeFont
)
87 if (rThemeFont
.maTypeface
.isEmpty())
89 pAttrList
->add(XML_typeface
, ""); // 'typeface' attribute is mandatory
93 pAttrList
->add(XML_typeface
, rThemeFont
.maTypeface
);
95 if (!rThemeFont
.maPanose
.isEmpty())
96 pAttrList
->add(XML_panose
, rThemeFont
.maPanose
);
98 pAttrList
->add(XML_pitchFamily
, OString::number(rThemeFont
.getPitchFamily()));
99 pAttrList
->add(XML_charset
, OString::number(rThemeFont
.maCharset
));
102 } // end anonymous ns
104 bool ThemeExport::writeFontScheme(model::FontScheme
const& rFontScheme
)
106 mpFS
->startElementNS(XML_a
, XML_majorFont
);
109 auto aAttrList
= sax_fastparser::FastSerializerHelper::createAttrList();
110 fillAttrList(aAttrList
, rFontScheme
.getMajorLatin());
111 mpFS
->singleElementNS(XML_a
, XML_latin
, aAttrList
);
114 auto aAttrList
= sax_fastparser::FastSerializerHelper::createAttrList();
115 fillAttrList(aAttrList
, rFontScheme
.getMajorAsian());
116 mpFS
->singleElementNS(XML_a
, XML_ea
, aAttrList
);
119 auto aAttrList
= sax_fastparser::FastSerializerHelper::createAttrList();
120 fillAttrList(aAttrList
, rFontScheme
.getMajorComplex());
121 mpFS
->singleElementNS(XML_a
, XML_cs
, aAttrList
);
124 mpFS
->endElementNS(XML_a
, XML_majorFont
);
126 mpFS
->startElementNS(XML_a
, XML_minorFont
);
129 auto aAttrList
= sax_fastparser::FastSerializerHelper::createAttrList();
130 fillAttrList(aAttrList
, rFontScheme
.getMinorLatin());
131 mpFS
->singleElementNS(XML_a
, XML_latin
, aAttrList
);
134 auto aAttrList
= sax_fastparser::FastSerializerHelper::createAttrList();
135 fillAttrList(aAttrList
, rFontScheme
.getMinorAsian());
136 mpFS
->singleElementNS(XML_a
, XML_ea
, aAttrList
);
139 auto aAttrList
= sax_fastparser::FastSerializerHelper::createAttrList();
140 fillAttrList(aAttrList
, rFontScheme
.getMinorComplex());
141 mpFS
->singleElementNS(XML_a
, XML_cs
, aAttrList
);
144 mpFS
->endElementNS(XML_a
, XML_minorFont
);
151 constexpr frozen::unordered_map
<model::TransformationType
, sal_Int32
, 4> constTransformTypeTokenMap
{
152 { model::TransformationType::Tint
, XML_tint
},
153 { model::TransformationType::Shade
, XML_shade
},
154 { model::TransformationType::LumMod
, XML_lumMod
},
155 { model::TransformationType::LumOff
, XML_lumOff
},
158 constexpr frozen::unordered_map
<model::ThemeColorType
, const char*, 12> constThemeColorTypeTokenMap
{
159 { model::ThemeColorType::Dark1
, "dk1" },
160 { model::ThemeColorType::Light1
, "lt1" },
161 { model::ThemeColorType::Dark2
, "dk2" },
162 { model::ThemeColorType::Light2
, "lt2" },
163 { model::ThemeColorType::Accent1
, "accent1" },
164 { model::ThemeColorType::Accent2
, "accent2" },
165 { model::ThemeColorType::Accent3
, "accent3" },
166 { model::ThemeColorType::Accent4
, "accent4" },
167 { model::ThemeColorType::Accent5
, "accent5" },
168 { model::ThemeColorType::Accent6
, "accent6" },
169 { model::ThemeColorType::Hyperlink
, "hlink" },
170 { model::ThemeColorType::FollowedHyperlink
, "folHlink" }
173 constexpr frozen::unordered_map
<model::SystemColorType
, const char*, 30>
174 constSystemColorTypeTokenMap
{
175 { model::SystemColorType::DarkShadow3D
, "3dDkShadow" },
176 { model::SystemColorType::Light3D
, "3dLight" },
177 { model::SystemColorType::ActiveBorder
, "activeBorder" },
178 { model::SystemColorType::ActiveCaption
, "activeCaption" },
179 { model::SystemColorType::AppWorkspace
, "appWorkspace" },
180 { model::SystemColorType::Background
, "background" },
181 { model::SystemColorType::ButtonFace
, "btnFace" },
182 { model::SystemColorType::ButtonHighlight
, "btnHighlight" },
183 { model::SystemColorType::ButtonShadow
, "btnShadow" },
184 { model::SystemColorType::ButtonText
, "btnText" },
185 { model::SystemColorType::CaptionText
, "captionText" },
186 { model::SystemColorType::GradientActiveCaption
, "gradientActiveCaption" },
187 { model::SystemColorType::GradientInactiveCaption
, "gradientInactiveCaption" },
188 { model::SystemColorType::GrayText
, "grayText" },
189 { model::SystemColorType::Highlight
, "highlight" },
190 { model::SystemColorType::HighlightText
, "highlightText" },
191 { model::SystemColorType::HotLight
, "hotLight" },
192 { model::SystemColorType::InactiveBorder
, "inactiveBorder" },
193 { model::SystemColorType::InactiveCaption
, "inactiveCaption" },
194 { model::SystemColorType::InactiveCaptionText
, "inactiveCaptionText" },
195 { model::SystemColorType::InfoBack
, "infoBk" },
196 { model::SystemColorType::InfoText
, "infoText" },
197 { model::SystemColorType::Menu
, "menu" },
198 { model::SystemColorType::MenuBar
, "menuBar" },
199 { model::SystemColorType::MenuHighlight
, "menuHighlight" },
200 { model::SystemColorType::MenuText
, "menuText" },
201 { model::SystemColorType::ScrollBar
, "scrollBar" },
202 { model::SystemColorType::Window
, "window" },
203 { model::SystemColorType::WindowFrame
, "windowFrame" },
204 { model::SystemColorType::WindowText
, "windowText" }
207 constexpr frozen::unordered_map
<sal_Int32
, model::ThemeColorType
, 12> constTokenMap
{
208 { XML_dk1
, model::ThemeColorType::Dark1
},
209 { XML_lt1
, model::ThemeColorType::Light1
},
210 { XML_dk2
, model::ThemeColorType::Dark2
},
211 { XML_lt2
, model::ThemeColorType::Light2
},
212 { XML_accent1
, model::ThemeColorType::Accent1
},
213 { XML_accent2
, model::ThemeColorType::Accent2
},
214 { XML_accent3
, model::ThemeColorType::Accent3
},
215 { XML_accent4
, model::ThemeColorType::Accent4
},
216 { XML_accent5
, model::ThemeColorType::Accent5
},
217 { XML_accent6
, model::ThemeColorType::Accent6
},
218 { XML_hlink
, model::ThemeColorType::Hyperlink
},
219 { XML_folHlink
, model::ThemeColorType::FollowedHyperlink
}
222 } // end anonymous ns
224 void ThemeExport::writeColorTransformations(
225 std::vector
<model::Transformation
> const& rTransformations
)
227 for (model::Transformation
const& rTransformation
: rTransformations
)
229 auto iterator
= constTransformTypeTokenMap
.find(rTransformation
.meType
);
230 if (iterator
!= constTransformTypeTokenMap
.end())
232 sal_Int32 nToken
= iterator
->second
;
233 mpFS
->singleElementNS(XML_a
, nToken
, XML_val
,
234 OString::number(rTransformation
.mnValue
* 10));
239 void ThemeExport::writeColorRGB(model::ComplexColor
const& rComplexColor
)
241 auto aColor
= rComplexColor
.getRGBColor();
242 mpFS
->startElementNS(XML_a
, XML_srgbClr
, XML_val
, I32SHEX(sal_Int32(aColor
)));
243 mpFS
->endElementNS(XML_a
, XML_srgbClr
);
246 void ThemeExport::writeColorCRGB(model::ComplexColor
const& rComplexColor
)
248 mpFS
->startElementNS(XML_a
, XML_scrgbClr
, XML_r
, OString::number(rComplexColor
.mnComponent1
),
249 XML_g
, OString::number(rComplexColor
.mnComponent2
), XML_b
,
250 OString::number(rComplexColor
.mnComponent3
));
251 writeColorTransformations(rComplexColor
.maTransformations
);
252 mpFS
->endElementNS(XML_a
, XML_scrgbClr
);
255 void ThemeExport::writeColorHSL(model::ComplexColor
const& rComplexColor
)
257 mpFS
->startElementNS(XML_a
, XML_hslClr
, XML_hue
, OString::number(rComplexColor
.mnComponent1
),
258 XML_sat
, OString::number(rComplexColor
.mnComponent2
), XML_lum
,
259 OString::number(rComplexColor
.mnComponent3
));
260 writeColorTransformations(rComplexColor
.maTransformations
);
261 mpFS
->endElementNS(XML_a
, XML_hslClr
);
264 void ThemeExport::writeColorScheme(model::ComplexColor
const& rComplexColor
)
266 auto iterator
= constThemeColorTypeTokenMap
.find(rComplexColor
.meSchemeType
);
267 if (iterator
!= constThemeColorTypeTokenMap
.end())
269 const char* sValue
= iterator
->second
;
270 mpFS
->startElementNS(XML_a
, XML_schemeClr
, XML_val
, sValue
);
271 writeColorTransformations(rComplexColor
.maTransformations
);
272 mpFS
->endElementNS(XML_a
, XML_schemeClr
);
276 void ThemeExport::writeColorSystem(model::ComplexColor
const& rComplexColor
)
278 auto iterator
= constSystemColorTypeTokenMap
.find(rComplexColor
.meSystemColorType
);
279 if (iterator
!= constSystemColorTypeTokenMap
.end())
281 const char* sValue
= iterator
->second
;
282 mpFS
->startElementNS(XML_a
, XML_sysClr
, XML_val
, sValue
);
284 writeColorTransformations(rComplexColor
.maTransformations
);
285 mpFS
->endElementNS(XML_a
, XML_schemeClr
);
289 void ThemeExport::writeColorPlaceholder(model::ComplexColor
const& rComplexColor
)
291 mpFS
->startElementNS(XML_a
, XML_schemeClr
, XML_val
, "phClr");
292 writeColorTransformations(rComplexColor
.maTransformations
);
293 mpFS
->endElementNS(XML_a
, XML_schemeClr
);
296 void ThemeExport::writeComplexColor(model::ComplexColor
const& rComplexColor
)
298 switch (rComplexColor
.meType
)
300 case model::ColorType::Unused
:
302 case model::ColorType::RGB
:
303 writeColorRGB(rComplexColor
);
305 case model::ColorType::CRGB
:
306 writeColorCRGB(rComplexColor
);
308 case model::ColorType::HSL
:
309 writeColorHSL(rComplexColor
);
311 case model::ColorType::Scheme
:
312 writeColorScheme(rComplexColor
);
314 case model::ColorType::Palette
:
316 case model::ColorType::System
:
317 writeColorSystem(rComplexColor
);
319 case model::ColorType::Placeholder
:
320 writeColorPlaceholder(rComplexColor
);
325 void ThemeExport::writeSolidFill(model::SolidFill
const& rSolidFill
)
327 mpFS
->startElementNS(XML_a
, XML_solidFill
);
328 writeComplexColor(rSolidFill
.maColor
);
329 mpFS
->endElementNS(XML_a
, XML_solidFill
);
332 void ThemeExport::writeGradientFill(model::GradientFill
const& rGradientFill
)
334 mpFS
->startElementNS(XML_a
, XML_gradFill
);
335 mpFS
->startElementNS(XML_a
, XML_gsLst
);
336 for (auto const& rStop
: rGradientFill
.maGradientStops
)
338 mpFS
->startElementNS(XML_a
, XML_gs
, XML_pos
,
339 OString::number(sal_Int32(rStop
.mfPosition
* 100000.0)));
340 writeComplexColor(rStop
.maColor
);
341 mpFS
->endElementNS(XML_a
, XML_gs
);
343 mpFS
->endElementNS(XML_a
, XML_gsLst
);
345 if (rGradientFill
.meGradientType
== model::GradientType::Linear
)
347 mpFS
->singleElementNS(XML_a
, XML_lin
, XML_ang
,
348 OString::number(rGradientFill
.maLinearGradient
.mnAngle
), XML_scaled
,
349 rGradientFill
.maLinearGradient
.mbScaled
? "1" : "0");
354 switch (rGradientFill
.meGradientType
)
356 case model::GradientType::Circle
:
357 sPathType
= "circle";
359 case model::GradientType::Rectangle
:
362 case model::GradientType::Shape
:
369 if (!sPathType
.isEmpty())
371 mpFS
->startElementNS(XML_a
, XML_path
, XML_path
, sPathType
);
372 writeRelativeRectangle(mpFS
, XML_fillToRect
, rGradientFill
.maFillToRectangle
);
373 mpFS
->endElementNS(XML_a
, XML_path
);
376 writeRelativeRectangle(mpFS
, XML_tileRect
, rGradientFill
.maTileRectangle
);
377 mpFS
->endElementNS(XML_a
, XML_gradFill
);
380 void ThemeExport::writePatternFill(model::PatternFill
const& rPatternFill
)
383 switch (rPatternFill
.mePatternPreset
)
385 case model::PatternPreset::Percent_5
:
386 sPresetType
= "pct5";
388 case model::PatternPreset::Percent_10
:
389 sPresetType
= "pct10";
391 case model::PatternPreset::Percent_20
:
392 sPresetType
= "pct20";
394 case model::PatternPreset::Percent_25
:
395 sPresetType
= "pct25";
397 case model::PatternPreset::Percent_30
:
398 sPresetType
= "pct30";
400 case model::PatternPreset::Percent_40
:
401 sPresetType
= "pct40";
403 case model::PatternPreset::Percent_50
:
404 sPresetType
= "pct50";
406 case model::PatternPreset::Percent_60
:
407 sPresetType
= "pct60";
409 case model::PatternPreset::Percent_70
:
410 sPresetType
= "pct70";
412 case model::PatternPreset::Percent_75
:
413 sPresetType
= "pct75";
415 case model::PatternPreset::Percent_80
:
416 sPresetType
= "pct80";
418 case model::PatternPreset::Percent_90
:
419 sPresetType
= "pct90";
421 case model::PatternPreset::Horizontal
:
422 sPresetType
= "horz";
424 case model::PatternPreset::Vertical
:
425 sPresetType
= "vert";
427 case model::PatternPreset::LightHorizontal
:
428 sPresetType
= "ltHorz";
430 case model::PatternPreset::LightVertical
:
431 sPresetType
= "ltVert";
433 case model::PatternPreset::DarkHorizontal
:
434 sPresetType
= "dkHorz";
436 case model::PatternPreset::DarkVertical
:
437 sPresetType
= "dkVert";
439 case model::PatternPreset::NarrowHorizontal
:
440 sPresetType
= "narHorz";
442 case model::PatternPreset::NarrowVertical
:
443 sPresetType
= "narVert";
445 case model::PatternPreset::DashedHorizontal
:
446 sPresetType
= "dashHorz";
448 case model::PatternPreset::DashedVertical
:
449 sPresetType
= "dashVert";
451 case model::PatternPreset::Cross
:
452 sPresetType
= "cross";
454 case model::PatternPreset::DownwardDiagonal
:
455 sPresetType
= "dnDiag";
457 case model::PatternPreset::UpwardDiagonal
:
458 sPresetType
= "upDiag";
460 case model::PatternPreset::LightDownwardDiagonal
:
461 sPresetType
= "ltDnDiag";
463 case model::PatternPreset::LightUpwardDiagonal
:
464 sPresetType
= "ltUpDiag";
466 case model::PatternPreset::DarkDownwardDiagonal
:
467 sPresetType
= "dkDnDiag";
469 case model::PatternPreset::DarkUpwardDiagonal
:
470 sPresetType
= "dkUpDiag";
472 case model::PatternPreset::WideDownwardDiagonal
:
473 sPresetType
= "wdDnDiag";
475 case model::PatternPreset::WideUpwardDiagonal
:
476 sPresetType
= "wdUpDiag";
478 case model::PatternPreset::DashedDownwardDiagonal
:
479 sPresetType
= "dashDnDiag";
481 case model::PatternPreset::DashedUpwardDiagonal
:
482 sPresetType
= "dashUpDiag";
484 case model::PatternPreset::DiagonalCross
:
485 sPresetType
= "diagCross";
487 case model::PatternPreset::SmallCheckerBoard
:
488 sPresetType
= "smCheck";
490 case model::PatternPreset::LargeCheckerBoard
:
491 sPresetType
= "lgCheck";
493 case model::PatternPreset::SmallGrid
:
494 sPresetType
= "smGrid";
496 case model::PatternPreset::LargeGrid
:
497 sPresetType
= "lgGrid";
499 case model::PatternPreset::DottedGrid
:
500 sPresetType
= "dotGrid";
502 case model::PatternPreset::SmallConfetti
:
503 sPresetType
= "smConfetti";
505 case model::PatternPreset::LargeConfetti
:
506 sPresetType
= "lgConfetti";
508 case model::PatternPreset::HorizontalBrick
:
509 sPresetType
= "horzBrick";
511 case model::PatternPreset::DiagonalBrick
:
512 sPresetType
= "diagBrick";
514 case model::PatternPreset::SolidDiamond
:
515 sPresetType
= "solidDmnd";
517 case model::PatternPreset::OpenDiamond
:
518 sPresetType
= "openDmnd";
520 case model::PatternPreset::DottedDiamond
:
521 sPresetType
= "dotDmnd";
523 case model::PatternPreset::Plaid
:
524 sPresetType
= "plaid";
526 case model::PatternPreset::Sphere
:
527 sPresetType
= "sphere";
529 case model::PatternPreset::Weave
:
530 sPresetType
= "weave";
532 case model::PatternPreset::Divot
:
533 sPresetType
= "divot";
535 case model::PatternPreset::Shingle
:
536 sPresetType
= "shingle";
538 case model::PatternPreset::Wave
:
539 sPresetType
= "wave";
541 case model::PatternPreset::Trellis
:
542 sPresetType
= "trellis";
544 case model::PatternPreset::ZigZag
:
545 sPresetType
= "zigZag";
551 if (!sPresetType
.isEmpty())
553 mpFS
->startElementNS(XML_a
, XML_pattFill
, XML_prst
, sPresetType
);
555 mpFS
->startElementNS(XML_a
, XML_fgClr
);
556 writeComplexColor(rPatternFill
.maForegroundColor
);
557 mpFS
->endElementNS(XML_a
, XML_fgClr
);
559 mpFS
->startElementNS(XML_a
, XML_bgClr
);
560 writeComplexColor(rPatternFill
.maBackgroundColor
);
561 mpFS
->endElementNS(XML_a
, XML_bgClr
);
563 mpFS
->endElementNS(XML_a
, XML_pattFill
);
569 OString
convertFlipMode(model::FlipMode eFlipMode
)
573 case model::FlipMode::X
:
575 case model::FlipMode::Y
:
577 case model::FlipMode::XY
:
579 case model::FlipMode::None
:
585 OString
convertRectangleAlignment(model::RectangleAlignment eFlipMode
)
589 case model::RectangleAlignment::TopLeft
:
591 case model::RectangleAlignment::Top
:
593 case model::RectangleAlignment::TopRight
:
595 case model::RectangleAlignment::Left
:
597 case model::RectangleAlignment::Center
:
599 case model::RectangleAlignment::Right
:
601 case model::RectangleAlignment::BottomLeft
:
603 case model::RectangleAlignment::Bottom
:
605 case model::RectangleAlignment::BottomRight
:
607 case model::RectangleAlignment::Unset
:
612 } // end anonymous ns
614 void ThemeExport::writeBlip(model::BlipFill
const& rBlipFill
)
616 if (!rBlipFill
.mxGraphic
.is())
618 oox::drawingml::GraphicExport
aExporter(mpFS
, mpFilterBase
, meDocumentType
);
619 Graphic
aGraphic(rBlipFill
.mxGraphic
);
620 aExporter
.writeBlip(aGraphic
, rBlipFill
.maBlipEffects
, false);
623 void ThemeExport::writeBlipFill(model::BlipFill
const& rBlipFill
)
625 mpFS
->startElementNS(XML_a
, XML_blipFill
, XML_rotWithShape
,
626 rBlipFill
.mbRotateWithShape
? "1" : "0"
629 writeBlip(rBlipFill
);
631 writeRelativeRectangle(mpFS
, XML_srcRect
, rBlipFill
.maClipRectangle
);
633 if (rBlipFill
.meMode
== model::BitmapMode::Tile
)
635 OString aFlipMode
= convertFlipMode(rBlipFill
.meTileFlipMode
);
636 OString aAlignment
= convertRectangleAlignment(rBlipFill
.meTileAlignment
);
638 mpFS
->startElementNS(XML_a
, XML_tile
, XML_tx
, OString::number(rBlipFill
.mnTileOffsetX
),
639 XML_ty
, OString::number(rBlipFill
.mnTileOffsetY
), XML_sx
,
640 OString::number(rBlipFill
.mnTileScaleX
), XML_sy
,
641 OString::number(rBlipFill
.mnTileScaleY
), XML_flip
, aFlipMode
, XML_algn
,
643 mpFS
->endElementNS(XML_a
, XML_tile
);
645 else if (rBlipFill
.meMode
== model::BitmapMode::Stretch
)
647 mpFS
->startElementNS(XML_a
, XML_stretch
);
648 writeRelativeRectangle(mpFS
, XML_fillRect
, rBlipFill
.maFillRectangle
);
649 mpFS
->endElementNS(XML_a
, XML_stretch
);
652 mpFS
->endElementNS(XML_a
, XML_blipFill
);
655 void ThemeExport::writeFillStyle(model::FillStyle
const& rFillStyle
)
657 switch (rFillStyle
.mpFill
->meType
)
659 case model::FillType::None
:
660 case model::FillType::Solid
:
662 auto* pSolidFill
= static_cast<model::SolidFill
*>(rFillStyle
.mpFill
.get());
663 writeSolidFill(*pSolidFill
);
666 case model::FillType::Gradient
:
668 auto* pGradientFill
= static_cast<model::GradientFill
*>(rFillStyle
.mpFill
.get());
669 writeGradientFill(*pGradientFill
);
672 case model::FillType::Pattern
:
674 auto* pPatternFill
= static_cast<model::PatternFill
*>(rFillStyle
.mpFill
.get());
675 writePatternFill(*pPatternFill
);
678 case model::FillType::Blip
:
680 auto* pBlipFill
= static_cast<model::BlipFill
*>(rFillStyle
.mpFill
.get());
681 writeBlipFill(*pBlipFill
);
687 void ThemeExport::writeBackgroundFillStyle(model::FillStyle
const& rFillStyle
)
689 writeFillStyle(rFillStyle
);
692 void ThemeExport::writeLineStyle(model::LineStyle
const& rLineStyle
)
695 switch (rLineStyle
.meCapType
)
697 case model::CapType::Flat
:
700 case model::CapType::Round
:
703 case model::CapType::Square
:
706 case model::CapType::Unset
:
711 switch (rLineStyle
.mePenAlignment
)
713 case model::PenAlignmentType::Center
:
716 case model::PenAlignmentType::Inset
:
719 case model::PenAlignmentType::Unset
:
723 OString sCompoundLine
;
724 switch (rLineStyle
.meCompoundLineType
)
726 case model::CompoundLineType::Single
:
727 sCompoundLine
= "sng";
729 case model::CompoundLineType::Double
:
730 sCompoundLine
= "dbl";
732 case model::CompoundLineType::ThickThin_Double
:
733 sCompoundLine
= "thickThin";
735 case model::CompoundLineType::ThinThick_Double
:
736 sCompoundLine
= "thinThick";
738 case model::CompoundLineType::Triple
:
739 sCompoundLine
= "tri";
741 case model::CompoundLineType::Unset
:
745 mpFS
->startElementNS(XML_a
, XML_ln
, XML_w
, OString::number(rLineStyle
.mnWidth
), XML_cap
,
746 sax_fastparser::UseIf(sCap
, !sCap
.isEmpty()), XML_cmpd
,
747 sax_fastparser::UseIf(sCompoundLine
, !sCompoundLine
.isEmpty()), XML_algn
,
748 sax_fastparser::UseIf(sPenAlign
, !sPenAlign
.isEmpty()));
750 if (rLineStyle
.maLineDash
.mePresetType
!= model::PresetDashType::Unset
)
753 switch (rLineStyle
.maLineDash
.mePresetType
)
755 case model::PresetDashType::Dot
:
758 case model::PresetDashType::Dash
:
759 sPresetType
= "dash";
761 case model::PresetDashType::LargeDash
:
762 sPresetType
= "lgDash";
764 case model::PresetDashType::DashDot
:
765 sPresetType
= "dashDot";
767 case model::PresetDashType::LargeDashDot
:
768 sPresetType
= "lgDashDot";
770 case model::PresetDashType::LargeDashDotDot
:
771 sPresetType
= "lgDashDotDot";
773 case model::PresetDashType::Solid
:
774 sPresetType
= "solid";
776 case model::PresetDashType::SystemDash
:
777 sPresetType
= "sysDash";
779 case model::PresetDashType::SystemDot
:
780 sPresetType
= "sysDot";
782 case model::PresetDashType::SystemDashDot
:
783 sPresetType
= "sysDashDot";
785 case model::PresetDashType::SystemDashDotDot
:
786 sPresetType
= "sysDashDotDot";
788 case model::PresetDashType::Unset
:
791 mpFS
->singleElementNS(XML_a
, XML_prstDash
, XML_val
, sPresetType
);
794 if (rLineStyle
.maLineJoin
.meType
!= model::LineJoinType::Unset
)
796 switch (rLineStyle
.maLineJoin
.meType
)
798 case model::LineJoinType::Round
:
799 mpFS
->singleElementNS(XML_a
, XML_round
);
801 case model::LineJoinType::Bevel
:
802 mpFS
->singleElementNS(XML_a
, XML_bevel
);
804 case model::LineJoinType::Miter
:
806 sal_Int32 nMiterLimit
= rLineStyle
.maLineJoin
.mnMiterLimit
;
807 mpFS
->singleElementNS(
808 XML_a
, XML_miter
, XML_lim
,
809 sax_fastparser::UseIf(OString::number(nMiterLimit
), nMiterLimit
> 0));
812 case model::LineJoinType::Unset
:
817 mpFS
->endElementNS(XML_a
, XML_ln
);
820 void ThemeExport::writeEffectStyle(model::EffectStyle
const& /*rEffectStyle*/)
822 mpFS
->startElementNS(XML_a
, XML_effectStyle
);
823 mpFS
->singleElementNS(XML_a
, XML_effectLst
);
824 mpFS
->endElementNS(XML_a
, XML_effectStyle
);
827 bool ThemeExport::writeFormatScheme(model::FormatScheme
const& rFormatScheme
)
829 // Format Scheme: 3 or more per list but only 3 will be used currently
832 rFormatScheme
.ensureFillStyleList();
833 mpFS
->startElementNS(XML_a
, XML_fillStyleLst
);
834 for (auto const& rFillStyle
: rFormatScheme
.getFillStyleList())
836 writeFillStyle(rFillStyle
);
838 mpFS
->endElementNS(XML_a
, XML_fillStyleLst
);
841 rFormatScheme
.ensureLineStyleList();
842 mpFS
->startElementNS(XML_a
, XML_lnStyleLst
);
843 for (auto const& rLineStyle
: rFormatScheme
.getLineStyleList())
845 writeLineStyle(rLineStyle
);
847 mpFS
->endElementNS(XML_a
, XML_lnStyleLst
);
850 rFormatScheme
.ensureEffectStyleList();
851 mpFS
->startElementNS(XML_a
, XML_effectStyleLst
);
853 for (auto const& rEffectStyle
: rFormatScheme
.getEffectStyleList())
855 writeEffectStyle(rEffectStyle
);
858 mpFS
->endElementNS(XML_a
, XML_effectStyleLst
);
860 // Background Fill Style List
861 rFormatScheme
.ensureBackgroundFillStyleList();
862 mpFS
->startElementNS(XML_a
, XML_bgFillStyleLst
);
863 for (auto const& rFillStyle
: rFormatScheme
.getBackgroundFillStyleList())
865 writeBackgroundFillStyle(rFillStyle
);
867 mpFS
->endElementNS(XML_a
, XML_bgFillStyleLst
);
872 bool ThemeExport::writeColorSet(model::Theme
const& rTheme
)
874 static const constexpr std::array
<sal_Int32
, 12> constTokenArray
875 = { XML_dk1
, XML_lt1
, XML_dk2
, XML_lt2
, XML_accent1
, XML_accent2
,
876 XML_accent3
, XML_accent4
, XML_accent5
, XML_accent6
, XML_hlink
, XML_folHlink
};
878 const auto pColorSet
= rTheme
.getColorSet();
882 for (auto nToken
: constTokenArray
)
884 auto iterator
= constTokenMap
.find(nToken
);
885 if (iterator
!= constTokenMap
.end())
887 model::ThemeColorType eColorType
= iterator
->second
;
888 Color aColor
= pColorSet
->getColor(eColorType
);
889 mpFS
->startElementNS(XML_a
, nToken
);
890 mpFS
->singleElementNS(XML_a
, XML_srgbClr
, XML_val
, I32SHEX(sal_Int32(aColor
)));
891 mpFS
->endElementNS(XML_a
, nToken
);
898 } // end namespace oox
900 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */