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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/text/XTextDocument.hpp>
21 #include <xmloff/xmlnamespace.hxx>
22 #include "xmlexpit.hxx"
23 #include <xmloff/namespacemap.hxx>
24 #include <xmloff/XMLTextListAutoStylePool.hxx>
25 #include <xmloff/XMLTextMasterPageExport.hxx>
26 #include <xmloff/table/XMLTableExport.hxx>
28 #include <xmloff/txtprmap.hxx>
29 #include <xmloff/xmlaustp.hxx>
30 #include <xmloff/families.hxx>
31 #include <xmloff/maptype.hxx>
33 #include <fmtpdsc.hxx>
34 #include <pagedesc.hxx>
35 #include <cellatr.hxx>
36 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/util/Color.hpp>
40 #include <SwStyleNameMapper.hxx>
41 #include <osl/diagnose.h>
42 #include <comphelper/sequenceashashmap.hxx>
43 #include <sax/tools/converter.hxx>
45 #include <o3tl/enumrange.hxx>
46 #include <svx/unoapi.hxx>
47 #include <svx/svdpage.hxx>
48 #include <docmodel/theme/ThemeColorType.hxx>
49 #include <docmodel/theme/Theme.hxx>
52 using namespace ::com::sun::star::beans
;
53 using namespace ::com::sun::star::uno
;
54 using namespace ::com::sun::star::text
;
55 using namespace ::com::sun::star::drawing
;
56 using namespace ::com::sun::star::lang
;
57 using namespace ::xmloff::token
;
59 void SwXMLExport::ExportFormat(const SwFormat
& rFormat
, enum XMLTokenEnum eFamily
,
60 ::std::optional
<OUString
> const oStyleName
)
66 OSL_ENSURE( RES_FRMFMT
==rFormat
.Which(), "frame format expected" );
67 if( RES_FRMFMT
!= rFormat
.Which() )
69 OSL_ENSURE( eFamily
!= XML_TOKEN_INVALID
, "family must be specified" );
71 assert(oStyleName
|| (eFamily
!= XML_TABLE_ROW
&& eFamily
!= XML_TABLE_CELL
));
72 bool bEncoded
= false;
73 OUString
const name(oStyleName
? *oStyleName
: rFormat
.GetName());
74 AddAttribute(XML_NAMESPACE_STYLE
, XML_NAME
, EncodeStyleName(name
, &bEncoded
));
77 AddAttribute(XML_NAMESPACE_STYLE
, XML_DISPLAY_NAME
, name
);
80 if( eFamily
!= XML_TOKEN_INVALID
)
81 AddAttribute( XML_NAMESPACE_STYLE
, XML_FAMILY
, eFamily
);
83 #if OSL_DEBUG_LEVEL > 0
84 // style:parent-style-name="..." (if it's not the default only)
85 const SwFormat
* pParent
= rFormat
.DerivedFrom();
86 // Only adopt parent name, if it's not the default
87 OSL_ENSURE( !pParent
|| pParent
->IsDefault(), "unexpected parent" );
89 OSL_ENSURE( USHRT_MAX
== rFormat
.GetPoolFormatId(), "pool ids aren't supported" );
90 OSL_ENSURE( USHRT_MAX
== rFormat
.GetPoolHelpId(), "help ids aren't supported" );
91 OSL_ENSURE( USHRT_MAX
== rFormat
.GetPoolHelpId() ||
92 UCHAR_MAX
== rFormat
.GetPoolHlpFileId(), "help file ids aren't supported" );
95 // style:master-page-name
96 if( RES_FRMFMT
== rFormat
.Which() && XML_TABLE
== eFamily
)
98 if( const SwFormatPageDesc
* pItem
= rFormat
.GetAttrSet().GetItemIfSet( RES_PAGEDESC
,
102 const SwPageDesc
*pPageDesc
= pItem
->GetPageDesc();
104 SwStyleNameMapper::FillProgName(
105 pPageDesc
->GetName(),
107 SwGetPoolIdFromName::PageDesc
);
108 AddAttribute( XML_NAMESPACE_STYLE
, XML_MASTER_PAGE_NAME
,
109 EncodeStyleName( sName
) );
113 if( XML_TABLE_CELL
== eFamily
)
115 OSL_ENSURE(RES_FRMFMT
== rFormat
.Which(), "only frame format");
117 if( const SwTableBoxNumFormat
*pItem
=
118 rFormat
.GetAttrSet().GetItemIfSet( RES_BOXATR_FORMAT
, false ) )
120 sal_Int32 nFormat
= static_cast<sal_Int32
>(pItem
->GetValue());
122 if ( (nFormat
!= -1) && (nFormat
!= static_cast<sal_Int32
>(getSwDefaultTextFormat())) )
124 // if we have a format, register and then export
125 // (Careful: here we assume that data styles will be
126 // written after cell styles)
127 addDataStyle(nFormat
);
128 OUString sDataStyleName
= getDataStyleName(nFormat
);
129 if( !sDataStyleName
.isEmpty() )
130 AddAttribute( XML_NAMESPACE_STYLE
, XML_DATA_STYLE_NAME
,
137 SvXMLElementExport
aElem( *this, XML_NAMESPACE_STYLE
, XML_STYLE
,
140 SvXMLItemMapEntriesRef xItemMap
;
141 XMLTokenEnum ePropToken
= XML_TABLE_PROPERTIES
;
142 if( XML_TABLE
== eFamily
)
144 xItemMap
= m_xTableItemMap
;
146 else if( XML_TABLE_ROW
== eFamily
)
148 xItemMap
= m_xTableRowItemMap
;
149 ePropToken
= XML_TABLE_ROW_PROPERTIES
;
151 else if( XML_TABLE_CELL
== eFamily
)
153 xItemMap
= m_xTableCellItemMap
;
154 ePropToken
= XML_TABLE_CELL_PROPERTIES
;
159 m_pTableItemMapper
->setMapEntries( xItemMap
);
160 m_pTableItemMapper
->exportXML( *this,
161 rFormat
.GetAttrSet(),
162 GetTwipUnitConverter(),
168 void SwXMLExport::ExportStyles_( bool bUsed
)
170 SvXMLExport::ExportStyles_( bUsed
);
173 GetShapeExport()->ExportGraphicDefaults();
175 GetTextParagraphExport()->exportTextStyles( bUsed
178 collectDataStyles(true);
180 GetShapeExport()->GetShapeTableExport()->exportTableStyles();
182 GetPageExport()->exportDefaultStyle();
185 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(GetModel(), UNO_QUERY
);
186 if (xDrawPageSupplier
.is())
188 uno::Reference
<drawing::XDrawPage
> xPage
= xDrawPageSupplier
->getDrawPage();
190 ExportThemeElement(xPage
);
194 void SwXMLExport::ExportThemeElement(const uno::Reference
<drawing::XDrawPage
>& xDrawPage
)
196 if ((getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
) == 0)
198 // Do not export in standard ODF 1.3 or older.
202 SdrPage
* pPage
= GetSdrPageFromXDrawPage(xDrawPage
);
203 SAL_WARN_IF(!pPage
, "oox", "Can't get SdrPage from XDrawPage");
208 auto const& pTheme
= pPage
->getSdrPageProperties().GetTheme();
212 if (!pTheme
->GetName().isEmpty())
213 AddAttribute(XML_NAMESPACE_LO_EXT
, XML_NAME
, pTheme
->GetName());
214 SvXMLElementExport
aTheme(*this, XML_NAMESPACE_LO_EXT
, XML_THEME
, true, true);
216 auto pColorSet
= pTheme
->getColorSet();
217 if (!pColorSet
->getName().isEmpty())
218 AddAttribute(XML_NAMESPACE_LO_EXT
, XML_NAME
, pColorSet
->getName());
219 SvXMLElementExport
aColorTable(*this, XML_NAMESPACE_LO_EXT
, XML_THEME_COLORS
, true, true);
221 static const XMLTokenEnum aColorTokens
[] =
224 XML_LIGHT1
, // Background 1
226 XML_LIGHT2
, // Background 2
233 XML_HYPERLINK
, // Hyperlink
234 XML_FOLLOWED_HYPERLINK
, // Followed hyperlink
237 for (auto eThemeColorType
: o3tl::enumrange
<model::ThemeColorType
>())
239 if (eThemeColorType
== model::ThemeColorType::Unknown
)
242 auto nColor
= size_t(eThemeColorType
);
243 AddAttribute(XML_NAMESPACE_LO_EXT
, XML_NAME
, GetXMLToken(aColorTokens
[nColor
]));
244 OUStringBuffer sValue
;
245 sax::Converter::convertColor(sValue
, pColorSet
->getColor(eThemeColorType
));
246 AddAttribute(XML_NAMESPACE_LO_EXT
, XML_COLOR
, sValue
.makeStringAndClear());
247 SvXMLElementExport
aColor(*this, XML_NAMESPACE_LO_EXT
, XML_COLOR
, true, true);
251 void SwXMLExport::collectAutoStyles()
253 SvXMLExport::collectAutoStyles();
255 if (mbAutoStylesCollected
)
258 // The order in which styles are collected *MUST* be the same as
259 // the order in which they are exported. Otherwise, caching will
261 if( getExportFlags() & (SvXMLExportFlags::MASTERSTYLES
|SvXMLExportFlags::CONTENT
) )
263 if( !(getExportFlags() & SvXMLExportFlags::CONTENT
) )
265 // only master pages are exported => styles for frames bound
266 // to frames (but none for frames bound to pages) need to be
268 // TODO: exclude PageBoundFrames on export
272 // exported in _ExportMasterStyles
273 if( getExportFlags() & SvXMLExportFlags::MASTERSTYLES
)
274 GetPageExport()->collectAutoStyles( false );
277 // exported in ExportContent_
278 if( getExportFlags() & SvXMLExportFlags::CONTENT
)
280 // collect form autostyle
281 // (do this before collectTextAutoStyles, 'cause the shapes need the results of the work
282 // done by examineForms)
283 Reference
<XDrawPageSupplier
> xDrawPageSupplier( GetModel(), UNO_QUERY
);
284 if (xDrawPageSupplier
.is() && GetFormExport().is())
286 Reference
<XDrawPage
> xPage
= xDrawPageSupplier
->getDrawPage();
288 GetFormExport()->examineForms(xPage
);
291 GetTextParagraphExport()->collectTextAutoStylesOptimized( m_bShowProgress
);
294 mbAutoStylesCollected
= true;
297 void SwXMLExport::ExportAutoStyles_()
301 // if we don't export styles (i.e. in content stream only, but not
302 // in single-stream case), then we can save ourselves a bit of
303 // work and memory by not collecting field masters
304 if( !(getExportFlags() & SvXMLExportFlags::STYLES
) )
305 GetTextParagraphExport()->exportUsedDeclarations();
307 // exported in ExportContent_
308 if( getExportFlags() & SvXMLExportFlags::CONTENT
)
310 GetTextParagraphExport()->exportTrackedChanges( true );
313 GetTextParagraphExport()->exportTextAutoStyles();
314 GetShapeExport()->exportAutoStyles();
315 if( getExportFlags() & SvXMLExportFlags::MASTERSTYLES
)
316 GetPageExport()->exportAutoStyles();
318 // we rely on data styles being written after cell styles in the
319 // ExportFormat() method; so be careful when changing order.
320 exportAutoDataStyles();
322 SvXMLExportFlags nContentAutostyles
= SvXMLExportFlags::CONTENT
| SvXMLExportFlags::AUTOSTYLES
;
323 if ( ( getExportFlags() & nContentAutostyles
) == nContentAutostyles
)
324 GetFormExport()->exportAutoStyles();
327 XMLPageExport
* SwXMLExport::CreatePageExport()
329 return new XMLTextMasterPageExport( *this );
332 void SwXMLExport::ExportMasterStyles_()
334 // export master styles
335 GetPageExport()->exportMasterStyles( false );
340 class SwXMLAutoStylePoolP
: public SvXMLAutoStylePoolP
342 SvXMLExport
& m_rExport
;
343 const OUString m_sListStyleName
;
344 const OUString m_sMasterPageName
;
348 virtual void exportStyleAttributes(
349 comphelper::AttributeList
& rAttrList
,
350 XmlStyleFamily nFamily
,
351 const std::vector
< XMLPropertyState
>& rProperties
,
352 const SvXMLExportPropertyMapper
& rPropExp
353 , const SvXMLUnitConverter
& rUnitConverter
,
354 const SvXMLNamespaceMap
& rNamespaceMap
358 explicit SwXMLAutoStylePoolP( SvXMLExport
& rExport
);
363 void SwXMLAutoStylePoolP::exportStyleAttributes(
364 comphelper::AttributeList
& rAttrList
,
365 XmlStyleFamily nFamily
,
366 const std::vector
< XMLPropertyState
>& rProperties
,
367 const SvXMLExportPropertyMapper
& rPropExp
368 , const SvXMLUnitConverter
& rUnitConverter
,
369 const SvXMLNamespaceMap
& rNamespaceMap
372 SvXMLAutoStylePoolP::exportStyleAttributes( rAttrList
, nFamily
, rProperties
, rPropExp
, rUnitConverter
, rNamespaceMap
);
374 if( XmlStyleFamily::TEXT_PARAGRAPH
!= nFamily
)
377 for( const auto& rProperty
: rProperties
)
379 if (rProperty
.mnIndex
!= -1) // #i26762#
381 switch( rPropExp
.getPropertySetMapper()->
382 GetEntryContextId( rProperty
.mnIndex
) )
384 case CTF_NUMBERINGSTYLENAME
:
387 rProperty
.maValue
>>= sStyleName
;
388 // #i70748# - export also empty list styles
389 if( !sStyleName
.isEmpty() )
391 OUString sTmp
= m_rExport
.GetTextParagraphExport()->GetListAutoStylePool().Find( sStyleName
);
392 if( !sTmp
.isEmpty() )
395 GetExport().AddAttribute( XML_NAMESPACE_STYLE
,
397 GetExport().EncodeStyleName( sStyleName
) );
400 case CTF_PAGEDESCNAME
:
403 rProperty
.maValue
>>= sStyleName
;
404 GetExport().AddAttribute( XML_NAMESPACE_STYLE
,
406 GetExport().EncodeStyleName( sStyleName
) );
414 SwXMLAutoStylePoolP::SwXMLAutoStylePoolP(SvXMLExport
& rExp
) :
415 SvXMLAutoStylePoolP( rExp
),
417 m_sListStyleName( GetXMLToken( XML_LIST_STYLE_NAME
) ),
418 m_sMasterPageName( GetXMLToken( XML_MASTER_PAGE_NAME
) )
422 SvXMLAutoStylePoolP
* SwXMLExport::CreateAutoStylePool()
424 return new SwXMLAutoStylePoolP( *this );
427 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */