Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / oox / source / export / ThemeExport.cxx
blob87cb5f2bc0bc892b46e815a53928c1dbc70ebc62
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
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>
26 namespace oox
28 namespace
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);
79 mpFS->endDocument();
82 namespace
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
90 return;
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);
146 return true;
149 namespace
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);
283 //XML_lastClr
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:
301 break;
302 case model::ColorType::RGB:
303 writeColorRGB(rComplexColor);
304 break;
305 case model::ColorType::CRGB:
306 writeColorCRGB(rComplexColor);
307 break;
308 case model::ColorType::HSL:
309 writeColorHSL(rComplexColor);
310 break;
311 case model::ColorType::Scheme:
312 writeColorScheme(rComplexColor);
313 break;
314 case model::ColorType::Palette:
315 break;
316 case model::ColorType::System:
317 writeColorSystem(rComplexColor);
318 break;
319 case model::ColorType::Placeholder:
320 writeColorPlaceholder(rComplexColor);
321 break;
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");
351 else
353 OString sPathType;
354 switch (rGradientFill.meGradientType)
356 case model::GradientType::Circle:
357 sPathType = "circle";
358 break;
359 case model::GradientType::Rectangle:
360 sPathType = "rect";
361 break;
362 case model::GradientType::Shape:
363 sPathType = "shape";
364 break;
365 default:
366 break;
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)
382 OString sPresetType;
383 switch (rPatternFill.mePatternPreset)
385 case model::PatternPreset::Percent_5:
386 sPresetType = "pct5";
387 break;
388 case model::PatternPreset::Percent_10:
389 sPresetType = "pct10";
390 break;
391 case model::PatternPreset::Percent_20:
392 sPresetType = "pct20";
393 break;
394 case model::PatternPreset::Percent_25:
395 sPresetType = "pct25";
396 break;
397 case model::PatternPreset::Percent_30:
398 sPresetType = "pct30";
399 break;
400 case model::PatternPreset::Percent_40:
401 sPresetType = "pct40";
402 break;
403 case model::PatternPreset::Percent_50:
404 sPresetType = "pct50";
405 break;
406 case model::PatternPreset::Percent_60:
407 sPresetType = "pct60";
408 break;
409 case model::PatternPreset::Percent_70:
410 sPresetType = "pct70";
411 break;
412 case model::PatternPreset::Percent_75:
413 sPresetType = "pct75";
414 break;
415 case model::PatternPreset::Percent_80:
416 sPresetType = "pct80";
417 break;
418 case model::PatternPreset::Percent_90:
419 sPresetType = "pct90";
420 break;
421 case model::PatternPreset::Horizontal:
422 sPresetType = "horz";
423 break;
424 case model::PatternPreset::Vertical:
425 sPresetType = "vert";
426 break;
427 case model::PatternPreset::LightHorizontal:
428 sPresetType = "ltHorz";
429 break;
430 case model::PatternPreset::LightVertical:
431 sPresetType = "ltVert";
432 break;
433 case model::PatternPreset::DarkHorizontal:
434 sPresetType = "dkHorz";
435 break;
436 case model::PatternPreset::DarkVertical:
437 sPresetType = "dkVert";
438 break;
439 case model::PatternPreset::NarrowHorizontal:
440 sPresetType = "narHorz";
441 break;
442 case model::PatternPreset::NarrowVertical:
443 sPresetType = "narVert";
444 break;
445 case model::PatternPreset::DashedHorizontal:
446 sPresetType = "dashHorz";
447 break;
448 case model::PatternPreset::DashedVertical:
449 sPresetType = "dashVert";
450 break;
451 case model::PatternPreset::Cross:
452 sPresetType = "cross";
453 break;
454 case model::PatternPreset::DownwardDiagonal:
455 sPresetType = "dnDiag";
456 break;
457 case model::PatternPreset::UpwardDiagonal:
458 sPresetType = "upDiag";
459 break;
460 case model::PatternPreset::LightDownwardDiagonal:
461 sPresetType = "ltDnDiag";
462 break;
463 case model::PatternPreset::LightUpwardDiagonal:
464 sPresetType = "ltUpDiag";
465 break;
466 case model::PatternPreset::DarkDownwardDiagonal:
467 sPresetType = "dkDnDiag";
468 break;
469 case model::PatternPreset::DarkUpwardDiagonal:
470 sPresetType = "dkUpDiag";
471 break;
472 case model::PatternPreset::WideDownwardDiagonal:
473 sPresetType = "wdDnDiag";
474 break;
475 case model::PatternPreset::WideUpwardDiagonal:
476 sPresetType = "wdUpDiag";
477 break;
478 case model::PatternPreset::DashedDownwardDiagonal:
479 sPresetType = "dashDnDiag";
480 break;
481 case model::PatternPreset::DashedUpwardDiagonal:
482 sPresetType = "dashUpDiag";
483 break;
484 case model::PatternPreset::DiagonalCross:
485 sPresetType = "diagCross";
486 break;
487 case model::PatternPreset::SmallCheckerBoard:
488 sPresetType = "smCheck";
489 break;
490 case model::PatternPreset::LargeCheckerBoard:
491 sPresetType = "lgCheck";
492 break;
493 case model::PatternPreset::SmallGrid:
494 sPresetType = "smGrid";
495 break;
496 case model::PatternPreset::LargeGrid:
497 sPresetType = "lgGrid";
498 break;
499 case model::PatternPreset::DottedGrid:
500 sPresetType = "dotGrid";
501 break;
502 case model::PatternPreset::SmallConfetti:
503 sPresetType = "smConfetti";
504 break;
505 case model::PatternPreset::LargeConfetti:
506 sPresetType = "lgConfetti";
507 break;
508 case model::PatternPreset::HorizontalBrick:
509 sPresetType = "horzBrick";
510 break;
511 case model::PatternPreset::DiagonalBrick:
512 sPresetType = "diagBrick";
513 break;
514 case model::PatternPreset::SolidDiamond:
515 sPresetType = "solidDmnd";
516 break;
517 case model::PatternPreset::OpenDiamond:
518 sPresetType = "openDmnd";
519 break;
520 case model::PatternPreset::DottedDiamond:
521 sPresetType = "dotDmnd";
522 break;
523 case model::PatternPreset::Plaid:
524 sPresetType = "plaid";
525 break;
526 case model::PatternPreset::Sphere:
527 sPresetType = "sphere";
528 break;
529 case model::PatternPreset::Weave:
530 sPresetType = "weave";
531 break;
532 case model::PatternPreset::Divot:
533 sPresetType = "divot";
534 break;
535 case model::PatternPreset::Shingle:
536 sPresetType = "shingle";
537 break;
538 case model::PatternPreset::Wave:
539 sPresetType = "wave";
540 break;
541 case model::PatternPreset::Trellis:
542 sPresetType = "trellis";
543 break;
544 case model::PatternPreset::ZigZag:
545 sPresetType = "zigZag";
546 break;
547 default:
548 break;
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);
567 namespace
569 OString convertFlipMode(model::FlipMode eFlipMode)
571 switch (eFlipMode)
573 case model::FlipMode::X:
574 return "x";
575 case model::FlipMode::Y:
576 return "y";
577 case model::FlipMode::XY:
578 return "xy";
579 case model::FlipMode::None:
580 return "none";
582 return "none";
585 OString convertRectangleAlignment(model::RectangleAlignment eFlipMode)
587 switch (eFlipMode)
589 case model::RectangleAlignment::TopLeft:
590 return "tl";
591 case model::RectangleAlignment::Top:
592 return "t";
593 case model::RectangleAlignment::TopRight:
594 return "tr";
595 case model::RectangleAlignment::Left:
596 return "l";
597 case model::RectangleAlignment::Center:
598 return "ctr";
599 case model::RectangleAlignment::Right:
600 return "r";
601 case model::RectangleAlignment::BottomLeft:
602 return "bl";
603 case model::RectangleAlignment::Bottom:
604 return "b";
605 case model::RectangleAlignment::BottomRight:
606 return "br";
607 case model::RectangleAlignment::Unset:
608 break;
610 return {};
612 } // end anonymous ns
614 void ThemeExport::writeBlip(model::BlipFill const& rBlipFill)
616 if (!rBlipFill.mxGraphic.is())
617 return;
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"
627 /*XML_dpi*/);
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,
642 aAlignment);
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);
665 break;
666 case model::FillType::Gradient:
668 auto* pGradientFill = static_cast<model::GradientFill*>(rFillStyle.mpFill.get());
669 writeGradientFill(*pGradientFill);
671 break;
672 case model::FillType::Pattern:
674 auto* pPatternFill = static_cast<model::PatternFill*>(rFillStyle.mpFill.get());
675 writePatternFill(*pPatternFill);
677 break;
678 case model::FillType::Blip:
680 auto* pBlipFill = static_cast<model::BlipFill*>(rFillStyle.mpFill.get());
681 writeBlipFill(*pBlipFill);
683 break;
687 void ThemeExport::writeBackgroundFillStyle(model::FillStyle const& rFillStyle)
689 writeFillStyle(rFillStyle);
692 void ThemeExport::writeLineStyle(model::LineStyle const& rLineStyle)
694 OString sCap;
695 switch (rLineStyle.meCapType)
697 case model::CapType::Flat:
698 sCap = "flat";
699 break;
700 case model::CapType::Round:
701 sCap = "rnd";
702 break;
703 case model::CapType::Square:
704 sCap = "sq";
705 break;
706 case model::CapType::Unset:
707 break;
710 OString sPenAlign;
711 switch (rLineStyle.mePenAlignment)
713 case model::PenAlignmentType::Center:
714 sPenAlign = "ctr";
715 break;
716 case model::PenAlignmentType::Inset:
717 sPenAlign = "in";
718 break;
719 case model::PenAlignmentType::Unset:
720 break;
723 OString sCompoundLine;
724 switch (rLineStyle.meCompoundLineType)
726 case model::CompoundLineType::Single:
727 sCompoundLine = "sng";
728 break;
729 case model::CompoundLineType::Double:
730 sCompoundLine = "dbl";
731 break;
732 case model::CompoundLineType::ThickThin_Double:
733 sCompoundLine = "thickThin";
734 break;
735 case model::CompoundLineType::ThinThick_Double:
736 sCompoundLine = "thinThick";
737 break;
738 case model::CompoundLineType::Triple:
739 sCompoundLine = "tri";
740 break;
741 case model::CompoundLineType::Unset:
742 break;
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)
752 OString sPresetType;
753 switch (rLineStyle.maLineDash.mePresetType)
755 case model::PresetDashType::Dot:
756 sPresetType = "dot";
757 break;
758 case model::PresetDashType::Dash:
759 sPresetType = "dash";
760 break;
761 case model::PresetDashType::LargeDash:
762 sPresetType = "lgDash";
763 break;
764 case model::PresetDashType::DashDot:
765 sPresetType = "dashDot";
766 break;
767 case model::PresetDashType::LargeDashDot:
768 sPresetType = "lgDashDot";
769 break;
770 case model::PresetDashType::LargeDashDotDot:
771 sPresetType = "lgDashDotDot";
772 break;
773 case model::PresetDashType::Solid:
774 sPresetType = "solid";
775 break;
776 case model::PresetDashType::SystemDash:
777 sPresetType = "sysDash";
778 break;
779 case model::PresetDashType::SystemDot:
780 sPresetType = "sysDot";
781 break;
782 case model::PresetDashType::SystemDashDot:
783 sPresetType = "sysDashDot";
784 break;
785 case model::PresetDashType::SystemDashDotDot:
786 sPresetType = "sysDashDotDot";
787 break;
788 case model::PresetDashType::Unset:
789 break;
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);
800 break;
801 case model::LineJoinType::Bevel:
802 mpFS->singleElementNS(XML_a, XML_bevel);
803 break;
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));
811 break;
812 case model::LineJoinType::Unset:
813 break;
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
831 // Fill Style List
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);
840 // Line Style List
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);
849 // Effect Style List
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);
869 return true;
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();
879 if (!pColorSet)
880 return false;
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);
895 return true;
898 } // end namespace oox
900 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */