1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <memory>
21 #include "xmlExport.hxx"
22 #include "xmlAutoStyle.hxx"
23 #include <xmloff/ProgressBarHelper.hxx>
24 #include <xmloff/xmltoken.hxx>
25 #include <xmloff/txtimp.hxx>
26 #include <xmloff/xmlnmspe.hxx>
27 #include <xmloff/xmluconv.hxx>
28 #include <xmloff/nmspmap.hxx>
29 #include <comphelper/types.hxx>
30 #include "xmlEnums.hxx"
31 #include <xmloff/txtprmap.hxx>
32 #include <xmloff/numehelp.hxx>
33 #include "xmlHelper.hxx"
34 #include <strings.hxx>
35 #include "xmlPropertyHandler.hxx"
36 #include <sax/tools/converter.hxx>
37 #include <com/sun/star/awt/ImagePosition.hpp>
38 #include <com/sun/star/util/NumberFormat.hpp>
39 #include <com/sun/star/util/MeasureUnit.hpp>
40 #include <com/sun/star/style/ParagraphAdjust.hpp>
41 #include <com/sun/star/awt/TextAlign.hpp>
42 #include <com/sun/star/report/GroupOn.hpp>
43 #include <com/sun/star/report/XFixedText.hpp>
44 #include <com/sun/star/report/XImageControl.hpp>
45 #include <com/sun/star/report/XShape.hpp>
46 #include <com/sun/star/drawing/XShape.hpp>
47 #include <com/sun/star/drawing/XShapes.hpp>
48 #include <com/sun/star/report/XFunction.hpp>
49 #include <com/sun/star/awt/FontDescriptor.hpp>
50 #include <com/sun/star/text/TextContentAnchorType.hpp>
51 #include <com/sun/star/table/BorderLine2.hpp>
52 #include <com/sun/star/table/BorderLineStyle.hpp>
53 #include <com/sun/star/report/XFixedLine.hpp>
54 #include <RptDef.hxx>
55 #include <vcl/svapp.hxx>
56 #include <sal/macros.h>
57 
58 #include <iterator>
59 
60 #define DEFAULT_LINE_WIDTH 2
61 
62 namespace rptxml
63 {
64     using namespace xmloff;
65     using namespace comphelper;
66     using namespace ::com::sun::star;
67     using namespace ::com::sun::star::report;
68     using namespace ::com::sun::star::uno;
69     using namespace ::com::sun::star::util;
70     using namespace ::com::sun::star::xml;
71 
72 
create(Reference<XComponentContext> const & xContext)73     Reference< XInterface > ORptExportHelper::create(Reference< XComponentContext > const & xContext)
74     {
75         return static_cast< XServiceInfo* >(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::SETTINGS ));
76     }
77 
getImplementationName_Static()78     OUString ORptExportHelper::getImplementationName_Static(  )
79     {
80         return "com.sun.star.comp.report.XMLSettingsExporter";
81     }
82 
getSupportedServiceNames_Static()83     Sequence< OUString > ORptExportHelper::getSupportedServiceNames_Static(  )
84     {
85         Sequence< OUString > aSupported { "com.sun.star.document.ExportFilter" };
86         return aSupported;
87     }
88 
create(Reference<XComponentContext> const & xContext)89     Reference< XInterface > ORptContentExportHelper::create(Reference< XComponentContext > const & xContext)
90     {
91         return static_cast< XServiceInfo* >(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::CONTENT ));
92     }
93 
getImplementationName_Static()94     OUString ORptContentExportHelper::getImplementationName_Static(  )
95     {
96         return "com.sun.star.comp.report.XMLContentExporter";
97     }
98 
getSupportedServiceNames_Static()99     Sequence< OUString > ORptContentExportHelper::getSupportedServiceNames_Static(  )
100     {
101         Sequence< OUString > aSupported { "com.sun.star.document.ExportFilter" };
102         return aSupported;
103     }
104 
105 
create(Reference<XComponentContext> const & xContext)106     Reference< XInterface > ORptStylesExportHelper::create(Reference< XComponentContext > const & xContext)
107     {
108         return static_cast< XServiceInfo* >(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::STYLES | SvXMLExportFlags::MASTERSTYLES | SvXMLExportFlags::AUTOSTYLES |
109             SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS ));
110     }
111 
getImplementationName_Static()112     OUString ORptStylesExportHelper::getImplementationName_Static(  )
113     {
114         return "com.sun.star.comp.report.XMLStylesExporter";
115     }
116 
getSupportedServiceNames_Static()117     Sequence< OUString > ORptStylesExportHelper::getSupportedServiceNames_Static(  )
118     {
119         Sequence< OUString > aSupported { "com.sun.star.document.ExportFilter" };
120         return aSupported;
121     }
122 
123 
create(Reference<XComponentContext> const & xContext)124     Reference< XInterface > ORptMetaExportHelper::create(Reference< XComponentContext > const & xContext)
125     {
126         return static_cast< XServiceInfo* >(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::META ));
127     }
128 
getImplementationName_Static()129     OUString ORptMetaExportHelper::getImplementationName_Static(  )
130     {
131         return "com.sun.star.comp.report.XMLMetaExporter";
132     }
133 
getSupportedServiceNames_Static()134     Sequence< OUString > ORptMetaExportHelper::getSupportedServiceNames_Static(  )
135     {
136         Sequence< OUString > aSupported { "com.sun.star.document.ExportFilter" };
137         return aSupported;
138     }
139 
140 
create(Reference<XComponentContext> const & xContext)141     Reference< XInterface > ODBFullExportHelper::create(Reference< XComponentContext > const & xContext)
142     {
143         return static_cast< XServiceInfo* >(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::ALL));
144     }
145 
getImplementationName_Static()146     OUString ODBFullExportHelper::getImplementationName_Static(  )
147     {
148         return "com.sun.star.comp.report.XMLFullExporter";
149     }
150 
getSupportedServiceNames_Static()151     Sequence< OUString > ODBFullExportHelper::getSupportedServiceNames_Static(  )
152     {
153         Sequence< OUString > aSupported { "com.sun.star.document.ExportFilter" };
154         return aSupported;
155     }
156 
157 
158     class OSpecialHandleXMLExportPropertyMapper : public SvXMLExportPropertyMapper
159     {
160     public:
OSpecialHandleXMLExportPropertyMapper(const rtl::Reference<XMLPropertySetMapper> & rMapper)161         explicit OSpecialHandleXMLExportPropertyMapper(const rtl::Reference< XMLPropertySetMapper >& rMapper) : SvXMLExportPropertyMapper(rMapper )
162         {
163         }
164         /** this method is called for every item that has the
165         MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
handleSpecialItem(SvXMLAttributeList &,const XMLPropertyState &,const SvXMLUnitConverter &,const SvXMLNamespaceMap &,const::std::vector<XMLPropertyState> * =nullptr,sal_uInt32=0) const166         virtual void handleSpecialItem(
167                 SvXMLAttributeList& /*rAttrList*/,
168                 const XMLPropertyState& /*rProperty*/,
169                 const SvXMLUnitConverter& /*rUnitConverter*/,
170                 const SvXMLNamespaceMap& /*rNamespaceMap*/,
171                 const ::std::vector< XMLPropertyState >* /*pProperties*/ = nullptr,
172                 sal_uInt32 /*nIdx*/ = 0 ) const override
173         {
174             // nothing to do here
175         }
176     };
177 
lcl_adjustColumnSpanOverRows(ORptExport::TSectionsGrid & _rGrid)178 static void lcl_adjustColumnSpanOverRows(ORptExport::TSectionsGrid& _rGrid)
179 {
180     for (auto& rEntry : _rGrid)
181     {
182         ORptExport::TGrid::iterator aRowIter = rEntry.second.begin();
183         ORptExport::TGrid::const_iterator aRowEnd = rEntry.second.end();
184         for (; aRowIter != aRowEnd; ++aRowIter)
185         {
186             if ( aRowIter->first )
187             {
188                 sal_Int32 nColIndex = 0;
189                 for (const auto& rCell : aRowIter->second)
190                 {
191                     if ( rCell.nRowSpan > 1 )
192                     {
193                         sal_Int32 nColSpan = rCell.nColSpan;
194                         for (sal_Int32 i = 1; i < rCell.nRowSpan; ++i)
195                         {
196                             (aRowIter+i)->second[nColIndex].nColSpan = nColSpan;
197                         }
198                     }
199                     ++nColIndex;
200                 }
201             }
202         }
203     }
204 }
205 
ORptExport(const Reference<XComponentContext> & _rxContext,OUString const & implementationName,SvXMLExportFlags nExportFlag)206 ORptExport::ORptExport(const Reference< XComponentContext >& _rxContext, OUString const & implementationName, SvXMLExportFlags nExportFlag)
207 : SvXMLExport( util::MeasureUnit::MM_100TH, _rxContext, implementationName, XML_REPORT, SvXMLExportFlags::OASIS)
208 ,m_bAllreadyFilled(false)
209 {
210     setExportFlags( SvXMLExportFlags::OASIS | nExportFlag);
211     GetMM100UnitConverter().SetCoreMeasureUnit(css::util::MeasureUnit::MM_100TH);
212     GetMM100UnitConverter().SetXMLMeasureUnit(css::util::MeasureUnit::CM);
213 
214     // (getExportFlags() & EXPORT_CONTENT) != 0 ? : XML_N_OOO
215     GetNamespaceMap_().Add( GetXMLToken(XML_NP_OFFICE), GetXMLToken(XML_N_OFFICE ), XML_NAMESPACE_OFFICE );
216     GetNamespaceMap_().Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
217 
218     GetNamespaceMap_().Add( GetXMLToken(XML_NP_RPT), GetXMLToken(XML_N_RPT), XML_NAMESPACE_REPORT );
219     GetNamespaceMap_().Add( GetXMLToken(XML_NP_SVG), GetXMLToken(XML_N_SVG_COMPAT),  XML_NAMESPACE_SVG );
220     GetNamespaceMap_().Add( GetXMLToken(XML_NP_FORM), GetXMLToken(XML_N_FORM), XML_NAMESPACE_FORM );
221     GetNamespaceMap_().Add( GetXMLToken(XML_NP_DRAW), GetXMLToken(XML_N_DRAW), XML_NAMESPACE_DRAW );
222     GetNamespaceMap_().Add( GetXMLToken(XML_NP_TEXT), GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT );
223 
224 
225     if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS) )
226         GetNamespaceMap_().Add( GetXMLToken(XML_NP_FO), GetXMLToken(XML_N_FO_COMPAT), XML_NAMESPACE_FO );
227 
228     if( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::SETTINGS) )
229     {
230         GetNamespaceMap_().Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
231     }
232     if( getExportFlags() & SvXMLExportFlags::SETTINGS )
233     {
234         GetNamespaceMap_().Add( GetXMLToken(XML_NP_CONFIG), GetXMLToken(XML_N_CONFIG), XML_NAMESPACE_CONFIG );
235     }
236 
237     if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::FONTDECLS) )
238     {
239         GetNamespaceMap_().Add( GetXMLToken(XML_NP_STYLE), GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE );
240     }
241     // RDFa: needed for content and header/footer styles
242     if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
243     {
244         GetNamespaceMap_().Add( GetXMLToken(XML_NP_XHTML),GetXMLToken(XML_N_XHTML), XML_NAMESPACE_XHTML );
245         // loext, needed for paragraphs inside shapes
246         if (getDefaultVersion() > SvtSaveOptions::ODFVER_012)
247         {
248             GetNamespaceMap_().Add(
249                 GetXMLToken(XML_NP_LO_EXT), GetXMLToken(XML_N_LO_EXT),
250                 XML_NAMESPACE_LO_EXT);
251         }
252     }
253     // GRDDL: to convert RDFa and meta.xml to RDF
254     if( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
255     {
256         GetNamespaceMap_().Add( GetXMLToken(XML_NP_GRDDL),GetXMLToken(XML_N_GRDDL), XML_NAMESPACE_GRDDL );
257     }
258 
259     GetNamespaceMap_().Add( GetXMLToken(XML_NP_TABLE), GetXMLToken(XML_N_TABLE), XML_NAMESPACE_TABLE );
260     GetNamespaceMap_().Add( GetXMLToken(XML_NP_NUMBER), GetXMLToken(XML_N_NUMBER), XML_NAMESPACE_NUMBER );
261 
262     m_sTableStyle = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_STYLE_NAME) );
263     m_sCellStyle = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_REPORT, GetXMLToken(XML_STYLE_NAME) );
264 
265 
266     m_xPropHdlFactory = new OXMLRptPropHdlFactory();
267     rtl::Reference < XMLPropertyHandlerFactory> xFac = new ::xmloff::OControlPropertyHandlerFactory();
268     rtl::Reference < XMLPropertySetMapper > xTableStylesPropertySetMapper1 = new XMLPropertySetMapper(OXMLHelper::GetTableStyleProps(),xFac, true);
269     rtl::Reference < XMLPropertySetMapper > xTableStylesPropertySetMapper2 = new XMLTextPropertySetMapper(TextPropMap::TABLE_DEFAULTS, true );
270     xTableStylesPropertySetMapper1->AddMapperEntry(xTableStylesPropertySetMapper2);
271 
272     m_xTableStylesExportPropertySetMapper = new SvXMLExportPropertyMapper(xTableStylesPropertySetMapper1);
273 
274     m_xCellStylesPropertySetMapper = OXMLHelper::GetCellStylePropertyMap( false, true);
275     m_xCellStylesExportPropertySetMapper = new OSpecialHandleXMLExportPropertyMapper(m_xCellStylesPropertySetMapper);
276     m_xCellStylesExportPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(*this));
277 
278     rtl::Reference < XMLPropertySetMapper > xColumnStylesPropertySetMapper = new XMLPropertySetMapper(OXMLHelper::GetColumnStyleProps(), m_xPropHdlFactory, true);
279     m_xColumnStylesExportPropertySetMapper = new OSpecialHandleXMLExportPropertyMapper(xColumnStylesPropertySetMapper);
280 
281     rtl::Reference < XMLPropertySetMapper > xRowStylesPropertySetMapper = new XMLPropertySetMapper(OXMLHelper::GetRowStyleProps(), m_xPropHdlFactory, true);
282     m_xRowStylesExportPropertySetMapper = new OSpecialHandleXMLExportPropertyMapper(xRowStylesPropertySetMapper);
283 
284     rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
285     m_xParaPropMapper = new OSpecialHandleXMLExportPropertyMapper( xPropMapper);
286 
287     const OUString& sFamily( GetXMLToken(XML_PARAGRAPH) );
288     OUString aPrefix( 'P');
289     GetAutoStylePool()->AddFamily( XML_STYLE_FAMILY_TEXT_PARAGRAPH, sFamily,
290                               m_xParaPropMapper, aPrefix );
291 
292     GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_CELL, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME,
293         m_xCellStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX);
294     GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_COLUMN, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME,
295         m_xColumnStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
296     GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_ROW, XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME,
297         m_xRowStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
298     GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_TABLE, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME,
299         m_xTableStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_PREFIX);
300 }
301 
create(Reference<XComponentContext> const & xContext)302 Reference< XInterface > ORptExport::create(Reference< XComponentContext > const & xContext)
303 {
304     return *(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::CONTENT | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::FONTDECLS));
305 }
306 
307 
getImplementationName_Static()308 OUString ORptExport::getImplementationName_Static(  )
309 {
310     return "com.sun.star.comp.report.ExportFilter";
311 }
312 
313 
getSupportedServiceNames_Static()314 uno::Sequence< OUString > ORptExport::getSupportedServiceNames_Static(  )
315 {
316     uno::Sequence< OUString > aServices { "com.sun.star.document.ExportFilter" };
317 
318     return aServices;
319 }
320 
321 
exportFunctions(const Reference<XIndexAccess> & _xFunctions)322 void ORptExport::exportFunctions(const Reference<XIndexAccess>& _xFunctions)
323 {
324     const sal_Int32 nCount = _xFunctions->getCount();
325     for (sal_Int32 i = 0; i< nCount; ++i)
326     {
327         uno::Reference< report::XFunction> xFunction(_xFunctions->getByIndex(i),uno::UNO_QUERY_THROW);
328         exportFunction(xFunction);
329     }
330 }
331 
exportFunction(const uno::Reference<XFunction> & _xFunction)332 void ORptExport::exportFunction(const uno::Reference< XFunction>& _xFunction)
333 {
334     exportFormula(XML_FORMULA,_xFunction->getFormula());
335     beans::Optional< OUString> aInitial = _xFunction->getInitialFormula();
336     if ( aInitial.IsPresent && !aInitial.Value.isEmpty() )
337         exportFormula(XML_INITIAL_FORMULA ,aInitial.Value );
338     AddAttribute( XML_NAMESPACE_REPORT, XML_NAME , _xFunction->getName() );
339     if ( _xFunction->getPreEvaluated() )
340         AddAttribute( XML_NAMESPACE_REPORT, XML_PRE_EVALUATED , XML_TRUE );
341     if ( _xFunction->getDeepTraversing() )
342         AddAttribute( XML_NAMESPACE_REPORT, XML_DEEP_TRAVERSING , XML_TRUE );
343 
344     SvXMLElementExport aFunction(*this,XML_NAMESPACE_REPORT, XML_FUNCTION, true, true);
345 }
346 
exportMasterDetailFields(const Reference<XReportComponent> & _xReportComponet)347 void ORptExport::exportMasterDetailFields(const Reference<XReportComponent>& _xReportComponet)
348 {
349     const uno::Sequence< OUString> aMasterFields = _xReportComponet->getMasterFields();
350     if ( aMasterFields.hasElements() )
351     {
352         SvXMLElementExport aElement(*this,XML_NAMESPACE_REPORT, XML_MASTER_DETAIL_FIELDS, true, true);
353         const uno::Sequence< OUString> aDetailFields = _xReportComponet->getDetailFields();
354 
355         OSL_ENSURE(aDetailFields.getLength() == aMasterFields.getLength(),"not equal length for master and detail fields!");
356 
357         const OUString* pDetailFieldsIter = aDetailFields.getConstArray();
358         for(const OUString& rMasterField : aMasterFields)
359         {
360             AddAttribute( XML_NAMESPACE_REPORT, XML_MASTER , rMasterField );
361             if ( !pDetailFieldsIter->isEmpty() )
362                 AddAttribute( XML_NAMESPACE_REPORT, XML_DETAIL , *pDetailFieldsIter );
363             SvXMLElementExport aPair(*this,XML_NAMESPACE_REPORT, XML_MASTER_DETAIL_FIELD, true, true);
364             ++pDetailFieldsIter;
365         }
366     }
367 }
368 
exportReport(const Reference<XReportDefinition> & _xReportDefinition)369 void ORptExport::exportReport(const Reference<XReportDefinition>& _xReportDefinition)
370 {
371     if ( _xReportDefinition.is() )
372     {
373         exportFunctions(_xReportDefinition->getFunctions().get());
374         exportGroupsExpressionAsFunction(_xReportDefinition->getGroups());
375 
376         if ( _xReportDefinition->getReportHeaderOn() )
377         {
378             SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_REPORT_HEADER, true, true);
379             exportSection(_xReportDefinition->getReportHeader());
380         }
381         if ( _xReportDefinition->getPageHeaderOn() )
382         {
383             OUStringBuffer sValue;
384             sal_Int16 nRet = _xReportDefinition->getPageHeaderOption();
385             const SvXMLEnumMapEntry<sal_Int16>* aXML_EnumMap = OXMLHelper::GetReportPrintOptions();
386             if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
387                 AddAttribute(XML_NAMESPACE_REPORT, XML_PAGE_PRINT_OPTION,sValue.makeStringAndClear());
388 
389             SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_PAGE_HEADER, true, true);
390             exportSection(_xReportDefinition->getPageHeader(),true);
391         }
392 
393         exportGroup(_xReportDefinition,0);
394 
395         if ( _xReportDefinition->getPageFooterOn() )
396         {
397             OUStringBuffer sValue;
398             sal_Int16 nRet = _xReportDefinition->getPageFooterOption();
399             const SvXMLEnumMapEntry<sal_Int16>* aXML_EnumMap = OXMLHelper::GetReportPrintOptions();
400             if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
401                 AddAttribute(XML_NAMESPACE_REPORT, XML_PAGE_PRINT_OPTION,sValue.makeStringAndClear());
402             SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_PAGE_FOOTER, true, true);
403             exportSection(_xReportDefinition->getPageFooter(),true);
404         }
405         if ( _xReportDefinition->getReportFooterOn() )
406         {
407             SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_REPORT_FOOTER, true, true);
408             exportSection(_xReportDefinition->getReportFooter());
409         }
410     }
411 }
412 
exportComponent(const Reference<XReportComponent> & _xReportComponent)413 void ORptExport::exportComponent(const Reference<XReportComponent>& _xReportComponent)
414 {
415     OSL_ENSURE(_xReportComponent.is(),"No component interface!");
416     if ( !_xReportComponent.is() )
417         return;
418 
419     AddAttribute(XML_NAMESPACE_DRAW, XML_NAME,_xReportComponent->getName());
420 
421     SvXMLElementExport aElem(*this,XML_NAMESPACE_REPORT, XML_REPORT_COMPONENT, false, false);
422 }
423 
exportFormatConditions(const Reference<XReportControlModel> & _xReportElement)424 void ORptExport::exportFormatConditions(const Reference<XReportControlModel>& _xReportElement)
425 {
426     OSL_ENSURE(_xReportElement.is(),"_xReportElement is NULL -> GPF");
427     const sal_Int32 nCount = _xReportElement->getCount();
428     try
429     {
430         for (sal_Int32 i = 0; i < nCount ; ++i)
431         {
432             uno::Reference< report::XFormatCondition > xCond(_xReportElement->getByIndex(i),uno::UNO_QUERY);
433             if ( !xCond->getEnabled() )
434                 AddAttribute(XML_NAMESPACE_REPORT, XML_ENABLED,XML_FALSE);
435 
436             AddAttribute(XML_NAMESPACE_REPORT, XML_FORMULA,xCond->getFormula());
437 
438             exportStyleName(xCond.get(),GetAttrList(),m_sCellStyle);
439             SvXMLElementExport aElem(*this,XML_NAMESPACE_REPORT, XML_FORMAT_CONDITION, true, true);
440         }
441     }
442     catch(uno::Exception&)
443     {
444         OSL_FAIL("Can not access format condition!");
445     }
446 }
447 
exportReportElement(const Reference<XReportControlModel> & _xReportElement)448 void ORptExport::exportReportElement(const Reference<XReportControlModel>& _xReportElement)
449 {
450     OSL_ENSURE(_xReportElement.is(),"_xReportElement is NULL -> GPF");
451     if ( !_xReportElement->getPrintWhenGroupChange() )
452         AddAttribute(XML_NAMESPACE_REPORT, XML_PRINT_WHEN_GROUP_CHANGE, XML_FALSE );
453 
454     if ( !_xReportElement->getPrintRepeatedValues() )
455         AddAttribute(XML_NAMESPACE_REPORT, XML_PRINT_REPEATED_VALUES,XML_FALSE);
456 
457     SvXMLElementExport aElem(*this,XML_NAMESPACE_REPORT, XML_REPORT_ELEMENT, true, true);
458     if ( _xReportElement->getCount() )
459     {
460         exportFormatConditions(_xReportElement);
461     }
462 
463     OUString sExpr = _xReportElement->getConditionalPrintExpression();
464     if ( !sExpr.isEmpty() )
465     {
466         exportFormula(XML_FORMULA,sExpr);
467         SvXMLElementExport aPrintExpr(*this,XML_NAMESPACE_REPORT, XML_CONDITIONAL_PRINT_EXPRESSION, true, true);
468     }
469 
470     // only export when parent exists
471     uno::Reference< report::XSection> xParent(_xReportElement->getParent(),uno::UNO_QUERY);
472     if ( xParent.is() )
473         exportComponent(_xReportElement.get());
474 }
475 
lcl_calculate(const::std::vector<sal_Int32> & _aPosX,const::std::vector<sal_Int32> & _aPosY,ORptExport::TGrid & _rColumns)476 static void lcl_calculate(const ::std::vector<sal_Int32>& _aPosX,const ::std::vector<sal_Int32>& _aPosY,ORptExport::TGrid& _rColumns)
477 {
478     sal_Int32 nCountX = _aPosX.size() - 1;
479     sal_Int32 nCountY = _aPosY.size() - 1;
480     for (sal_Int32 j = 0; j < nCountY; ++j)
481     {
482         sal_Int32 nHeight = _aPosY[j+1] - _aPosY[j];
483         if ( nHeight )
484             for (sal_Int32 i = 0; i < nCountX ; ++i)
485             {
486                 _rColumns[j].second[i] = ORptExport::TCell(1,1);
487                 _rColumns[j].second[i].bSet = true;
488             }
489     }
490 }
491 
collectStyleNames(sal_Int32 _nFamily,const::std::vector<sal_Int32> & _aSize,std::vector<OUString> & _rStyleNames)492 void ORptExport::collectStyleNames(sal_Int32 _nFamily,const ::std::vector< sal_Int32>& _aSize, std::vector<OUString>& _rStyleNames)
493 {
494     ::std::vector< XMLPropertyState > aPropertyStates;
495     aPropertyStates.emplace_back(0);
496     ::std::vector<sal_Int32>::const_iterator aIter = _aSize.begin();
497     ::std::vector<sal_Int32>::const_iterator aIter2 = aIter + 1;
498     ::std::vector<sal_Int32>::const_iterator aEnd = _aSize.end();
499     for (;aIter2 != aEnd ; ++aIter,++aIter2)
500     {
501         sal_Int32 nValue = static_cast<sal_Int32>(*aIter2 - *aIter);
502         aPropertyStates[0].maValue <<= nValue;
503         _rStyleNames.push_back(GetAutoStylePool()->Add(_nFamily, aPropertyStates ));
504     }
505 }
506 
collectStyleNames(sal_Int32 _nFamily,const::std::vector<sal_Int32> & _aSize,const::std::vector<sal_Int32> & _aSizeAutoGrow,std::vector<OUString> & _rStyleNames)507 void ORptExport::collectStyleNames(sal_Int32 _nFamily, const ::std::vector< sal_Int32>& _aSize, const ::std::vector< sal_Int32>& _aSizeAutoGrow, std::vector<OUString>& _rStyleNames)
508 {
509     ::std::vector< XMLPropertyState > aPropertyStates;
510     aPropertyStates.emplace_back(0);
511     ::std::vector<sal_Int32>::const_iterator aIter = _aSize.begin();
512     ::std::vector<sal_Int32>::const_iterator aIter2 = aIter + 1;
513     ::std::vector<sal_Int32>::const_iterator aEnd = _aSize.end();
514     for (;aIter2 != aEnd; ++aIter, ++aIter2)
515     {
516         sal_Int32 nValue = static_cast<sal_Int32>(*aIter2 - *aIter);
517         aPropertyStates[0].maValue <<= nValue;
518         // note: there cannot be 0-height rows, because a call to std::unique has removed them
519         // it cannot be predicted that the size of _aSizeAutoGrow has any relation to the size of
520         // _aSize, because of the same std::unique operation (and _aSizeAutoGrow wasn't even the same
521         // size before that), so the matching element in _aSizeAutoGrow has to be found by lookup.
522         ::std::vector<sal_Int32>::const_iterator aAutoGrow = ::std::find(_aSizeAutoGrow.begin(), _aSizeAutoGrow.end(), *aIter2);
523         bool bAutoGrow = aAutoGrow != _aSizeAutoGrow.end();
524         // the mnIndex is into the array returned by OXMLHelper::GetRowStyleProps()
525         aPropertyStates[0].mnIndex = bAutoGrow ? 1 : 0;
526         _rStyleNames.push_back(GetAutoStylePool()->Add(_nFamily, aPropertyStates));
527     }
528 }
529 
exportSectionAutoStyle(const Reference<XSection> & _xProp)530 void ORptExport::exportSectionAutoStyle(const Reference<XSection>& _xProp)
531 {
532     OSL_ENSURE(_xProp != nullptr,"Section is NULL -> GPF");
533     exportAutoStyle(_xProp);
534 
535     Reference<XReportDefinition> xReport = _xProp->getReportDefinition();
536     const awt::Size aSize   = rptui::getStyleProperty<awt::Size>(xReport,PROPERTY_PAPERSIZE);
537     const sal_Int32 nOffset = rptui::getStyleProperty<sal_Int32>(xReport,PROPERTY_LEFTMARGIN);
538     const sal_Int32 nCount  = _xProp->getCount();
539 
540     ::std::vector<sal_Int32> aColumnPos;
541     aColumnPos.reserve(2*(nCount + 1));
542     aColumnPos.push_back(nOffset);
543     aColumnPos.push_back(aSize.Width - rptui::getStyleProperty<sal_Int32>(xReport,PROPERTY_RIGHTMARGIN));
544 
545     ::std::vector<sal_Int32> aRowPos;
546     aRowPos.reserve(2*(nCount + 1));
547     aRowPos.push_back(0);
548     aRowPos.push_back(_xProp->getHeight());
549 
550 
551     ::std::vector<sal_Int32> aRowPosAutoGrow;
552     aRowPosAutoGrow.reserve(2 * (nCount + 1));
553 
554 
555     sal_Int32 i;
556     for (i = 0 ; i< nCount ; ++i)
557     {
558         Reference<XReportComponent> xReportElement(_xProp->getByIndex(i),uno::UNO_QUERY);
559         uno::Reference< XShape> xShape(xReportElement,uno::UNO_QUERY);
560         if ( xShape.is() )
561             continue;
562         OSL_ENSURE( xReportElement.is(),"NULL Element in Section!" );
563         if ( !xReportElement.is() )
564             continue;
565         sal_Int32 nX = xReportElement->getPositionX();
566         aColumnPos.push_back(nX);
567         Reference<XFixedLine> xFixedLine(xReportElement,uno::UNO_QUERY);
568         if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical
569         {
570             sal_Int32 nWidth = static_cast<sal_Int32>(xReportElement->getWidth()*0.5);
571             nX += nWidth;
572             aColumnPos.push_back(nX);
573             nX += xReportElement->getWidth() - nWidth;
574         }
575         else
576             nX += xReportElement->getWidth();
577         aColumnPos.push_back(nX); // --nX why?
578 
579         sal_Int32 nY = xReportElement->getPositionY();
580         aRowPos.push_back(nY);
581         nY += xReportElement->getHeight();
582         aRowPos.push_back(nY); // --nY why?
583         bool bAutoGrow = xReportElement->getAutoGrow();
584         if (bAutoGrow)
585         {
586             // the resulting table row ending at nY should auto-grow
587             aRowPosAutoGrow.push_back(nY);
588         }
589     }
590 
591     ::std::sort(aColumnPos.begin(),aColumnPos.end(),::std::less<sal_Int32>());
592     aColumnPos.erase(::std::unique(aColumnPos.begin(),aColumnPos.end()),aColumnPos.end());
593 
594     // note: the aRowPos contains top and bottom position of every report control; we now compute the
595     // top of every row in the resulting table, by sorting and eliminating unnecessary duplicate
596     // positions. (the same for the columns in the preceding lines.)
597     ::std::sort(aRowPos.begin(),aRowPos.end(),::std::less<sal_Int32>());
598     aRowPos.erase(::std::unique(aRowPos.begin(),aRowPos.end()),aRowPos.end());
599 
600     TSectionsGrid::iterator aInsert = m_aSectionsGrid.emplace(
601                                     _xProp.get(),
602                                     TGrid(aRowPos.size() - 1,TGrid::value_type(false,TRow(aColumnPos.size() - 1)))
603         ).first;
604     lcl_calculate(aColumnPos,aRowPos,aInsert->second);
605 
606     TGridStyleMap::iterator aPos = m_aColumnStyleNames.emplace(_xProp.get(),std::vector<OUString>()).first;
607     collectStyleNames(XML_STYLE_FAMILY_TABLE_COLUMN,aColumnPos,aPos->second);
608     aPos = m_aRowStyleNames.emplace(_xProp.get(),std::vector<OUString>()).first;
609     collectStyleNames(XML_STYLE_FAMILY_TABLE_ROW, aRowPos, aRowPosAutoGrow, aPos->second);
610 
611     sal_Int32 x1 = 0;
612     sal_Int32 y1 = 0;
613     sal_Int32 x2 = 0;
614     sal_Int32 y2 = 0;
615     sal_Int32 xi = 0;
616     sal_Int32 yi = 0;
617     bool isOverlap = false;
618 
619     for (i = 0 ; i< nCount ; ++i)
620     {
621         Reference<XReportComponent> xReportElement(_xProp->getByIndex(i),uno::UNO_QUERY);
622         uno::Reference< XShape> xShape(xReportElement,uno::UNO_QUERY);
623         if ( xShape.is() )
624             continue;
625         sal_Int32 nPos = xReportElement->getPositionX();
626         x1 = (::std::find(aColumnPos.begin(),aColumnPos.end(),nPos) - aColumnPos.begin());
627         Reference<XFixedLine> xFixedLine(xReportElement,uno::UNO_QUERY);
628         if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical
629             nPos += static_cast<sal_Int32>(xReportElement->getWidth()*0.5);
630         else
631             nPos += xReportElement->getWidth(); // -1 why
632         x2 = (::std::find(aColumnPos.begin(),aColumnPos.end(),nPos) - aColumnPos.begin());
633 
634         nPos = xReportElement->getPositionY();
635         y1 = (::std::find(aRowPos.begin(),aRowPos.end(),nPos) - aRowPos.begin());
636         nPos += xReportElement->getHeight(); // -1 why?
637         y2 = (::std::find(aRowPos.begin(),aRowPos.end(),nPos) - aRowPos.begin());
638 
639         isOverlap = false;
640         yi = y1;
641         while(yi < y2 && !isOverlap) // find overlapping controls
642         {
643             xi = x1;
644             while(xi < x2 && !isOverlap)
645             {
646                 if ( aInsert->second[yi].second[xi].xElement.is() )
647                 {
648                     isOverlap = true;
649                 }
650                 ++xi;
651             }
652             ++yi;
653         }
654 
655         if (!isOverlap)
656         {
657             yi = y1;
658             while(yi < y2)
659             {
660                 xi = x1;
661                 while(xi < x2)
662                 {
663                     aInsert->second[yi].second[xi] = TCell();
664                     ++xi;
665                 }
666                 aInsert->second[yi].first = true;
667                 ++yi;
668             }
669 
670             if (x2 - x1 != 0 && y2 - y1 != 0)
671             {
672                 sal_Int32 nColSpan = x2 - x1;
673                 sal_Int32 nRowSpan = y2 - y1;
674                 aInsert->second[y1].second[x1] =
675                     TCell(
676                         nColSpan,
677                         nRowSpan,
678                         xReportElement
679                         );
680             }
681         }
682     }
683 
684     lcl_adjustColumnSpanOverRows(m_aSectionsGrid);
685     exportReportComponentAutoStyles(_xProp);
686 }
687 
exportReportComponentAutoStyles(const Reference<XSection> & _xProp)688 void ORptExport::exportReportComponentAutoStyles(const Reference<XSection>& _xProp)
689 {
690     const sal_Int32 nCount = _xProp->getCount();
691     for (sal_Int32 i = 0 ; i< nCount ; ++i)
692     {
693         const Reference<XReportComponent> xReportElement(_xProp->getByIndex(i),uno::UNO_QUERY);
694         const Reference< report::XShape > xShape(xReportElement,uno::UNO_QUERY);
695         if ( xShape.is() )
696         {
697             rtl::Reference< XMLShapeExport > xShapeExport = GetShapeExport();
698             xShapeExport->seekShapes(_xProp.get());
699             SolarMutexGuard aGuard;
700             xShapeExport->collectShapeAutoStyles(xShape.get());
701         }
702         else
703         {
704             exportAutoStyle(xReportElement.get());
705 
706             Reference<XFormattedField> xFormattedField(xReportElement,uno::UNO_QUERY);
707             if ( xFormattedField.is() )
708             {
709                 try
710                 {
711                     const sal_Int32 nFormatCount = xFormattedField->getCount();
712                     for (sal_Int32 j = 0; j < nFormatCount ; ++j)
713                     {
714                         uno::Reference< report::XFormatCondition > xCond(xFormattedField->getByIndex(j),uno::UNO_QUERY);
715                         exportAutoStyle(xCond.get(),xFormattedField);
716                     }
717                 }
718                 catch(uno::Exception&)
719                 {
720                     OSL_FAIL("Can not access format condition!");
721                 }
722             }
723         }
724     }
725 }
726 
exportSection(const Reference<XSection> & _xSection,bool bHeader)727 void ORptExport::exportSection(const Reference<XSection>& _xSection,bool bHeader)
728 {
729     OSL_ENSURE(_xSection.is(),"Section is NULL -> GPF");
730     OUStringBuffer sValue;
731     AddAttribute(XML_NAMESPACE_TABLE, XML_NAME,_xSection->getName());
732 
733     if ( !_xSection->getVisible() )
734         AddAttribute(XML_NAMESPACE_REPORT, XML_VISIBLE,XML_FALSE);
735 
736     if ( !bHeader )
737     {
738         sal_Int16 nRet = _xSection->getForceNewPage();
739         const SvXMLEnumMapEntry<sal_Int16>* aXML_EnumMap = OXMLHelper::GetForceNewPageOptions();
740         if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
741             AddAttribute(XML_NAMESPACE_REPORT, XML_FORCE_NEW_PAGE,sValue.makeStringAndClear());
742 
743         nRet = _xSection->getNewRowOrCol();
744         if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
745             AddAttribute(XML_NAMESPACE_REPORT, XML_FORCE_NEW_COLUMN,sValue.makeStringAndClear());
746         if ( _xSection->getKeepTogether() )
747             AddAttribute(XML_NAMESPACE_REPORT, XML_KEEP_TOGETHER, XML_TRUE );
748     }
749 
750     exportStyleName(_xSection.get(),GetAttrList(),m_sTableStyle);
751 
752     /// TODO export as table layout
753     SvXMLElementExport aComponents(*this,XML_NAMESPACE_TABLE, XML_TABLE, true, true);
754 
755     OUString sExpr = _xSection->getConditionalPrintExpression();
756     if ( !sExpr.isEmpty() )
757     {
758         exportFormula(XML_FORMULA,sExpr);
759         SvXMLElementExport aPrintExpr(*this,XML_NAMESPACE_REPORT, XML_CONDITIONAL_PRINT_EXPRESSION, true, false);
760     }
761 
762     exportContainer(_xSection);
763 }
764 
exportTableColumns(const Reference<XSection> & _xSection)765 void ORptExport::exportTableColumns(const Reference< XSection>& _xSection)
766 {
767     SvXMLElementExport aColumns(*this,XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, true, true);
768     TGridStyleMap::const_iterator aColFind = m_aColumnStyleNames.find(_xSection.get());
769     OSL_ENSURE(aColFind != m_aColumnStyleNames.end(),"ORptExport::exportTableColumns: Section not found in m_aColumnStyleNames!");
770     if ( aColFind == m_aColumnStyleNames.end() )
771         return;
772 
773     for (auto& aCol : aColFind->second)
774     {
775         AddAttribute(m_sTableStyle, aCol);
776         SvXMLElementExport aColumn(*this,XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true);
777     }
778 }
779 
exportContainer(const Reference<XSection> & _xSection)780 void ORptExport::exportContainer(const Reference< XSection>& _xSection)
781 {
782     OSL_ENSURE(_xSection.is(),"Section is NULL -> GPF");
783 
784     exportTableColumns(_xSection);
785 
786     TSectionsGrid::const_iterator aFind = m_aSectionsGrid.find(_xSection.get());
787     OSL_ENSURE(aFind != m_aSectionsGrid.end(),"ORptExport::exportContainer: Section not found in grid!");
788     if ( aFind == m_aSectionsGrid.end() )
789         return;
790     TGrid::const_iterator aRowIter = aFind->second.begin();
791     TGrid::const_iterator aRowEnd = aFind->second.end();
792 
793     TGridStyleMap::const_iterator aRowFind = m_aRowStyleNames.find(_xSection.get());
794     auto aHeightIter = aRowFind->second.cbegin();
795     OSL_ENSURE(aRowFind->second.size() == aFind->second.size(),"Different count for rows");
796 
797     bool bShapeHandled = false;
798     ::std::map<sal_Int32,sal_Int32> aRowSpan;
799     for (sal_Int32 j = 0; aRowIter != aRowEnd; ++aRowIter,++j,++aHeightIter)
800     {
801         AddAttribute( m_sTableStyle,*aHeightIter );
802         SvXMLElementExport aRow(*this,XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
803         if ( aRowIter->first )
804         {
805             ::std::vector< TCell >::const_iterator aColIter = aRowIter->second.begin();
806             ::std::vector< TCell >::const_iterator aColEnd = aRowIter->second.end();
807             sal_Int32 nEmptyCellColSpan = 0;
808             for (; aColIter != aColEnd; ++aColIter)
809             {
810                 bool bCoveredCell = false;
811                 sal_Int32 nColSpan = 0;
812                 sal_Int32 nColIndex = aColIter - aRowIter->second.begin();
813                 ::std::map<sal_Int32,sal_Int32>::iterator aRowSpanFind = aRowSpan.find(nColIndex);
814                 if ( aRowSpanFind != aRowSpan.end() )
815                 {
816                     nColSpan = 1;
817                     if ( !--(aRowSpanFind->second) )
818                         aRowSpan.erase(aRowSpanFind);
819 
820                     if ( aColIter->nColSpan > 1 )
821                         nColSpan += aColIter->nColSpan - 1;
822 
823                     bCoveredCell = true;
824                     aColIter = aColIter + (aColIter->nColSpan - 1);
825                 }
826                 else if ( aColIter->bSet )
827                 {
828                     if ( nEmptyCellColSpan > 0 )
829                     {
830                         AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nEmptyCellColSpan) );
831                         bCoveredCell = true;
832                         nColSpan = nEmptyCellColSpan - 1;
833                         nEmptyCellColSpan = 0;
834                     }
835                     sal_Int32 nSpan = aColIter->nColSpan;
836                     if ( nSpan > 1 )
837                     {
838                         AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nSpan) );
839                         nColSpan = nSpan - 1;
840                         bCoveredCell = true;
841                     }
842                     nSpan = aColIter->nRowSpan;
843                     if ( nSpan > 1 )
844                     {
845                         AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_ROWS_SPANNED, OUString::number(nSpan) );
846                         aRowSpan[nColIndex] = nSpan - 1;
847                     }
848                     if ( aColIter->xElement.is() )
849                         exportStyleName(aColIter->xElement.get(),GetAttrList(),m_sTableStyle);
850 
851                     // start <table:table-cell>
852                     Reference<XFormattedField> xFormattedField(aColIter->xElement,uno::UNO_QUERY);
853                     if ( xFormattedField.is() )
854                     {
855                         sal_Int32 nFormatKey = xFormattedField->getFormatKey();
856                         XMLNumberFormatAttributesExportHelper aHelper(GetNumberFormatsSupplier(),*this);
857                         bool bIsStandard = false;
858                         sal_Int16 nCellType = aHelper.GetCellType(nFormatKey,bIsStandard);
859                         // "Standard" means "no format set, value could be anything",
860                         // so don't set a format attribute in this case.
861                         // P.S.: "Standard" is called "General" in some languages
862                         if (!bIsStandard)
863                         {
864                             if ( nCellType == util::NumberFormat::TEXT )
865                                 aHelper.SetNumberFormatAttributes("", "");
866                             else
867                                 aHelper.SetNumberFormatAttributes(nFormatKey, 0.0, false);
868                         }
869                     }
870                     SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, false);
871 
872                     if ( aColIter->xElement.is() )
873                     {
874                         // start <text:p>
875                         SvXMLElementExport aParagraphContent(*this,XML_NAMESPACE_TEXT, XML_P, true, false);
876                         Reference<XServiceInfo> xElement(aColIter->xElement,uno::UNO_QUERY);
877 
878                         if ( !bShapeHandled )
879                         {
880                             bShapeHandled = true;
881                             exportShapes(_xSection,false);
882                         }
883                         uno::Reference< XShape > xShape(xElement,uno::UNO_QUERY);
884                         uno::Reference< XFixedLine > xFixedLine(xElement,uno::UNO_QUERY);
885                         if ( !xShape.is() && !xFixedLine.is() )
886                         {
887                             Reference<XReportControlModel> xReportElement(xElement,uno::UNO_QUERY);
888                             Reference<XReportDefinition> xReportDefinition(xElement,uno::UNO_QUERY);
889                             Reference< XImageControl > xImage(xElement,uno::UNO_QUERY);
890                             Reference<XSection> xSection(xElement,uno::UNO_QUERY);
891 
892                             XMLTokenEnum eToken = XML_SECTION;
893                             bool bExportData = false;
894                             if ( xElement->supportsService(SERVICE_FIXEDTEXT) )
895                             {
896                                 eToken = XML_FIXED_CONTENT;
897                             }
898                             else if ( xElement->supportsService(SERVICE_FORMATTEDFIELD) )
899                             {
900                                 eToken = XML_FORMATTED_TEXT;
901                                 bExportData = true;
902                             }
903                             else if ( xElement->supportsService(SERVICE_IMAGECONTROL) )
904                             {
905                                 eToken = XML_IMAGE;
906                                 OUString sTargetLocation = xImage->getImageURL();
907                                 if ( !sTargetLocation.isEmpty() )
908                                 {
909                                     sTargetLocation = GetRelativeReference(sTargetLocation);
910                                     AddAttribute(XML_NAMESPACE_FORM, XML_IMAGE_DATA,sTargetLocation);
911                                 }
912                                 bExportData = true;
913                                 OUStringBuffer sValue;
914                                 const SvXMLEnumMapEntry<sal_Int16>* aXML_ImageScaleEnumMap = OXMLHelper::GetImageScaleOptions();
915                                 if ( SvXMLUnitConverter::convertEnum( sValue, xImage->getScaleMode(),aXML_ImageScaleEnumMap ) )
916                                     AddAttribute(XML_NAMESPACE_REPORT, XML_SCALE, sValue.makeStringAndClear() );
917                             }
918                             else if ( xReportDefinition.is() )
919                             {
920                                 eToken = XML_SUB_DOCUMENT;
921                             }
922 
923                             if ( bExportData )
924                             {
925                                 const bool bPageSet = exportFormula(XML_FORMULA,xReportElement->getDataField());
926                                 if ( bPageSet )
927                                     eToken = XML_FIXED_CONTENT;
928                                 else if ( eToken == XML_IMAGE )
929                                     AddAttribute(XML_NAMESPACE_REPORT, XML_PRESERVE_IRI, xImage->getPreserveIRI() ? XML_TRUE : XML_FALSE );
930                             }
931 
932                             {
933                                 // start <report:eToken>
934                                 SvXMLElementExport aComponents(*this,XML_NAMESPACE_REPORT, eToken, false, false);
935                                 if ( eToken == XML_FIXED_CONTENT )
936                                     exportParagraph(xReportElement);
937                                 if ( xReportElement.is() )
938                                     exportReportElement(xReportElement);
939 
940                                 if (eToken == XML_SUB_DOCUMENT && xReportDefinition.is())
941                                 {
942                                     SvXMLElementExport aOfficeElement( *this, XML_NAMESPACE_OFFICE, XML_BODY, true, true );
943                                     SvXMLElementExport aElem( *this, true,
944                                                             XML_NAMESPACE_OFFICE, XML_REPORT,
945                                                               true, true );
946 
947                                     exportReportAttributes(xReportDefinition);
948                                     exportReport(xReportDefinition);
949                                 }
950                                 else if ( xSection.is() )
951                                     exportSection(xSection);
952                             }
953                         }
954                     }
955                     else if ( !bShapeHandled )
956                     {
957                         bShapeHandled = true;
958                         exportShapes(_xSection);
959                     }
960                     aColIter = aColIter + (aColIter->nColSpan - 1);
961                 }
962                 else
963                     ++nEmptyCellColSpan;
964                 if ( bCoveredCell )
965                 {
966                     for (sal_Int32 k = 0; k < nColSpan; ++k)
967                     {
968                         SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_COVERED_TABLE_CELL, true, true);
969                     }
970 
971                 }
972             }
973             if ( nEmptyCellColSpan )
974             {
975                 {
976                     AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nEmptyCellColSpan) );
977                     SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
978                     if ( !bShapeHandled )
979                     {
980                         bShapeHandled = true;
981                         exportShapes(_xSection);
982                     }
983                 }
984                 for (sal_Int32 k = 0; k < nEmptyCellColSpan; ++k)
985                 {
986                     SvXMLElementExport aCoveredCell(*this,XML_NAMESPACE_TABLE, XML_COVERED_TABLE_CELL, true, true);
987                 }
988             }
989         }
990         else
991         { // empty rows
992             sal_Int32 nEmptyCellColSpan = aRowIter->second.size();
993             if ( nEmptyCellColSpan )
994             {
995                 {
996                     AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nEmptyCellColSpan) );
997                     SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
998                     if ( !bShapeHandled )
999                     {
1000                         bShapeHandled = true;
1001                         exportShapes(_xSection);
1002                     }
1003                 }
1004                 for (sal_Int32 k = 1; k < nEmptyCellColSpan; ++k)
1005                 {
1006                     SvXMLElementExport aCoveredCell(*this,XML_NAMESPACE_TABLE, XML_COVERED_TABLE_CELL, true, true);
1007                 }
1008             }
1009         }
1010     }
1011 }
1012 
convertFormula(const OUString & _sFormula)1013 OUString ORptExport::convertFormula(const OUString& _sFormula)
1014 {
1015     OUString sFormula = _sFormula;
1016     if ( _sFormula == "rpt:" )
1017         sFormula.clear();
1018     return sFormula;
1019 }
1020 
exportFormula(enum::xmloff::token::XMLTokenEnum eName,const OUString & _sFormula)1021 bool ORptExport::exportFormula(enum ::xmloff::token::XMLTokenEnum eName,const OUString& _sFormula)
1022 {
1023     const OUString sFieldData = convertFormula(_sFormula);
1024     sal_Int32 nPageNumberIndex = sFieldData.indexOf("PageNumber()");
1025     sal_Int32 nPageCountIndex = sFieldData.indexOf("PageCount()");
1026     bool bRet = nPageNumberIndex != -1 || nPageCountIndex != -1;
1027     if ( !bRet )
1028         AddAttribute(XML_NAMESPACE_REPORT, eName,sFieldData);
1029 
1030     return bRet;
1031 }
1032 
exportStyleName(XPropertySet * _xProp,SvXMLAttributeList & _rAtt,const OUString & _sName)1033 void ORptExport::exportStyleName(XPropertySet* _xProp,SvXMLAttributeList& _rAtt,const OUString& _sName)
1034 {
1035     Reference<XPropertySet> xFind(_xProp);
1036     TPropertyStyleMap::const_iterator aFind = m_aAutoStyleNames.find(xFind);
1037     if ( aFind != m_aAutoStyleNames.end() )
1038     {
1039         _rAtt.AddAttribute( _sName,
1040                             aFind->second );
1041         m_aAutoStyleNames.erase(aFind);
1042     }
1043 }
1044 
exportGroup(const Reference<XReportDefinition> & _xReportDefinition,sal_Int32 _nPos,bool _bExportAutoStyle)1045 void ORptExport::exportGroup(const Reference<XReportDefinition>& _xReportDefinition,sal_Int32 _nPos,bool _bExportAutoStyle)
1046 {
1047     if ( _xReportDefinition.is() )
1048     {
1049         Reference< XGroups > xGroups = _xReportDefinition->getGroups();
1050         if ( xGroups.is() )
1051         {
1052             sal_Int32 nCount = xGroups->getCount();
1053             if ( _nPos >= 0 && _nPos < nCount )
1054             {
1055                 Reference<XGroup> xGroup(xGroups->getByIndex(_nPos),uno::UNO_QUERY);
1056                 OSL_ENSURE(xGroup.is(),"No Group prepare for GPF");
1057                 if ( _bExportAutoStyle )
1058                 {
1059                     if ( xGroup->getHeaderOn() )
1060                         exportSectionAutoStyle(xGroup->getHeader());
1061                     exportGroup(_xReportDefinition,_nPos+1,_bExportAutoStyle);
1062                     if ( xGroup->getFooterOn() )
1063                         exportSectionAutoStyle(xGroup->getFooter());
1064                 }
1065                 else
1066                 {
1067                     if ( xGroup->getSortAscending() )
1068                         AddAttribute(XML_NAMESPACE_REPORT, XML_SORT_ASCENDING, XML_TRUE );
1069 
1070                     if ( xGroup->getStartNewColumn() )
1071                         AddAttribute(XML_NAMESPACE_REPORT, XML_START_NEW_COLUMN, XML_TRUE);
1072                     if ( xGroup->getResetPageNumber() )
1073                         AddAttribute(XML_NAMESPACE_REPORT, XML_RESET_PAGE_NUMBER, XML_TRUE );
1074 
1075                     const OUString sField = xGroup->getExpression();
1076                     OUString sExpression  = sField;
1077                     if ( !sExpression.isEmpty() )
1078                     {
1079                         sal_Int32 nIndex = sExpression.indexOf('"');
1080                         while ( nIndex > -1 )
1081                         {
1082                             sExpression = sExpression.replaceAt(nIndex, 1, "\"\"");
1083                             nIndex = sExpression.indexOf('"',nIndex+2);
1084                         }
1085 
1086                         TGroupFunctionMap::const_iterator aGroupFind = m_aGroupFunctionMap.find(xGroup);
1087                         if ( aGroupFind != m_aGroupFunctionMap.end() )
1088                             sExpression = aGroupFind->second->getName();
1089                         sExpression = "rpt:HASCHANGED(\"" + sExpression + "\")";
1090                     }
1091                     AddAttribute(XML_NAMESPACE_REPORT, XML_SORT_EXPRESSION, sField);
1092                     AddAttribute(XML_NAMESPACE_REPORT, XML_GROUP_EXPRESSION,sExpression);
1093                     sal_Int16 nRet = xGroup->getKeepTogether();
1094                     OUStringBuffer sValue;
1095                     const SvXMLEnumMapEntry<sal_Int16>* aXML_KeepTogetherEnumMap = OXMLHelper::GetKeepTogetherOptions();
1096                     if ( SvXMLUnitConverter::convertEnum( sValue, nRet, aXML_KeepTogetherEnumMap ) )
1097                         AddAttribute(XML_NAMESPACE_REPORT, XML_KEEP_TOGETHER,sValue.makeStringAndClear());
1098 
1099                     SvXMLElementExport aGroup(*this,XML_NAMESPACE_REPORT, XML_GROUP, true, true);
1100                     exportFunctions(xGroup->getFunctions().get());
1101                     if ( xGroup->getHeaderOn() )
1102                     {
1103                         Reference<XSection> xSection = xGroup->getHeader();
1104                         if ( xSection->getRepeatSection() )
1105                             AddAttribute(XML_NAMESPACE_REPORT, XML_REPEAT_SECTION,XML_TRUE );
1106                         SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_GROUP_HEADER, true, true);
1107                         exportSection(xSection);
1108                     }
1109                     exportGroup(_xReportDefinition,_nPos+1,_bExportAutoStyle);
1110                     if ( xGroup->getFooterOn() )
1111                     {
1112                         Reference<XSection> xSection = xGroup->getFooter();
1113                         if ( xSection->getRepeatSection() )
1114                             AddAttribute(XML_NAMESPACE_REPORT, XML_REPEAT_SECTION,XML_TRUE );
1115                         SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_GROUP_FOOTER, true, true);
1116                         exportSection(xSection);
1117                     }
1118                 }
1119             }
1120             else if ( _bExportAutoStyle )
1121             {
1122                 exportSectionAutoStyle(_xReportDefinition->getDetail());
1123             }
1124             else
1125             {
1126                 SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_DETAIL, true, true);
1127                 exportSection(_xReportDefinition->getDetail());
1128             }
1129         }
1130     }
1131 }
1132 
exportAutoStyle(XPropertySet * _xProp,const Reference<XFormattedField> & _xParentFormattedField)1133 void ORptExport::exportAutoStyle(XPropertySet* _xProp,const Reference<XFormattedField>& _xParentFormattedField)
1134 {
1135     const uno::Reference<report::XReportControlFormat> xFormat(_xProp,uno::UNO_QUERY);
1136     if ( xFormat.is() )
1137     {
1138         try
1139         {
1140             const awt::FontDescriptor aFont = xFormat->getFontDescriptor();
1141             OSL_ENSURE(!aFont.Name.isEmpty(),"No Font Name !");
1142             GetFontAutoStylePool()->Add(aFont.Name,aFont.StyleName,static_cast<FontFamily>(aFont.Family),
1143                 static_cast<FontPitch>(aFont.Pitch),aFont.CharSet );
1144         }
1145         catch(beans::UnknownPropertyException&)
1146         {
1147             // not interested in
1148         }
1149     }
1150     const uno::Reference< report::XShape> xShape(_xProp,uno::UNO_QUERY);
1151     if ( xShape.is() )
1152     {
1153         ::std::vector< XMLPropertyState > aPropertyStates( m_xParaPropMapper->Filter(_xProp) );
1154         if ( !aPropertyStates.empty() )
1155             m_aAutoStyleNames.emplace( _xProp,GetAutoStylePool()->Add( XML_STYLE_FAMILY_TEXT_PARAGRAPH, aPropertyStates ));
1156     }
1157     ::std::vector< XMLPropertyState > aPropertyStates( m_xCellStylesExportPropertySetMapper->Filter(_xProp) );
1158     Reference<XFixedLine> xFixedLine(_xProp,uno::UNO_QUERY);
1159     if ( xFixedLine.is() )
1160     {
1161         uno::Reference<beans::XPropertySet> xBorderProp = OXMLHelper::createBorderPropertySet();
1162         table::BorderLine2 aValue;
1163         aValue.Color = sal_uInt32(COL_BLACK);
1164         aValue.InnerLineWidth = aValue.LineDistance = 0;
1165         aValue.OuterLineWidth = DEFAULT_LINE_WIDTH;
1166         aValue.LineStyle = table::BorderLineStyle::SOLID;
1167         aValue.LineWidth = DEFAULT_LINE_WIDTH;
1168 
1169         awt::Point aPos = xFixedLine->getPosition();
1170         awt::Size aSize = xFixedLine->getSize();
1171         sal_Int32 nSectionHeight = xFixedLine->getSection()->getHeight();
1172 
1173         OUString sBorderProp;
1174         ::std::vector< OUString> aProps;
1175         if ( xFixedLine->getOrientation() == 1 ) // vertical
1176         {
1177             // check if border should be left
1178             if ( !aPos.X )
1179             {
1180                 sBorderProp = PROPERTY_BORDERLEFT;
1181                 aProps.emplace_back(PROPERTY_BORDERRIGHT);
1182             }
1183             else
1184             {
1185                 sBorderProp = PROPERTY_BORDERRIGHT;
1186                 aProps.emplace_back(PROPERTY_BORDERLEFT);
1187             }
1188             aProps.emplace_back(PROPERTY_BORDERTOP);
1189             aProps.emplace_back(PROPERTY_BORDERBOTTOM);
1190         }
1191         else // horizontal
1192         {
1193             // check if border should be bottom
1194             if ( (aPos.Y + aSize.Height) == nSectionHeight )
1195             {
1196                 sBorderProp = PROPERTY_BORDERBOTTOM;
1197                 aProps.emplace_back(PROPERTY_BORDERTOP);
1198             }
1199             else
1200             {
1201                 sBorderProp = PROPERTY_BORDERTOP;
1202                 aProps.emplace_back(PROPERTY_BORDERBOTTOM);
1203             }
1204             aProps.emplace_back(PROPERTY_BORDERRIGHT);
1205             aProps.emplace_back(PROPERTY_BORDERLEFT);
1206         }
1207 
1208         xBorderProp->setPropertyValue(sBorderProp,uno::makeAny(aValue));
1209 
1210         aValue.Color = aValue.OuterLineWidth = aValue.LineWidth = 0;
1211         aValue.LineStyle = table::BorderLineStyle::NONE;
1212         uno::Any aEmpty;
1213         aEmpty <<= aValue;
1214         for (auto const& it : aProps)
1215         {
1216             xBorderProp->setPropertyValue(it, aEmpty);
1217         }
1218 
1219         ::std::vector< XMLPropertyState > aBorderStates(m_xCellStylesExportPropertySetMapper->Filter(xBorderProp));
1220         ::std::copy(aBorderStates.begin(),aBorderStates.end(),::std::back_inserter(aPropertyStates));
1221     }
1222     else
1223     {
1224         const Reference<XFormattedField> xFormattedField(_xProp,uno::UNO_QUERY);
1225         if ( (_xParentFormattedField.is() || xFormattedField.is()) && !aPropertyStates.empty() )
1226         {
1227             sal_Int32 nNumberFormat = 0;
1228             if ( _xParentFormattedField.is() )
1229                 nNumberFormat = _xParentFormattedField->getFormatKey();
1230             else
1231                 nNumberFormat = xFormattedField->getFormatKey();
1232             {
1233                 sal_Int32 nStyleMapIndex = m_xCellStylesExportPropertySetMapper->getPropertySetMapper()->FindEntryIndex( CTF_RPT_NUMBERFORMAT );
1234                 addDataStyle(nNumberFormat);
1235                 XMLPropertyState aNumberStyleState( nStyleMapIndex, uno::makeAny( getDataStyleName(nNumberFormat) ) );
1236                 auto const iter(::std::find_if(
1237                     aPropertyStates.begin(), aPropertyStates.end(),
1238                     [nStyleMapIndex] (XMLPropertyState const& rItem)
1239                         { return rItem.mnIndex == nStyleMapIndex; } ));
1240                 if (iter == aPropertyStates.end())
1241                 {
1242                     aPropertyStates.push_back( aNumberStyleState );
1243                 }
1244                 else
1245                 {   // there is already a property but it has the wrong type
1246                     // (integer not string); TODO: can we prevent it
1247                     // getting added earlier?
1248                     (*iter) = aNumberStyleState;
1249                 }
1250             }
1251         }
1252     }
1253 
1254     if ( !aPropertyStates.empty() )
1255         m_aAutoStyleNames.emplace( _xProp,GetAutoStylePool()->Add( XML_STYLE_FAMILY_TABLE_CELL, aPropertyStates ));
1256 }
1257 
exportAutoStyle(const Reference<XSection> & _xProp)1258 void ORptExport::exportAutoStyle(const Reference<XSection>& _xProp)
1259 {
1260     ::std::vector< XMLPropertyState > aPropertyStates( m_xTableStylesExportPropertySetMapper->Filter(_xProp.get()) );
1261     if ( !aPropertyStates.empty() )
1262         m_aAutoStyleNames.emplace( _xProp.get(),GetAutoStylePool()->Add( XML_STYLE_FAMILY_TABLE_TABLE, aPropertyStates ));
1263 }
1264 
SetBodyAttributes()1265 void ORptExport::SetBodyAttributes()
1266 {
1267     Reference<XReportDefinition> xProp(getReportDefinition());
1268     exportReportAttributes(xProp);
1269 }
1270 
exportReportAttributes(const Reference<XReportDefinition> & _xReport)1271 void ORptExport::exportReportAttributes(const Reference<XReportDefinition>& _xReport)
1272 {
1273     if ( _xReport.is() )
1274     {
1275         OUStringBuffer sValue;
1276         const SvXMLEnumMapEntry<sal_Int32>* aXML_CommnadTypeEnumMap = OXMLHelper::GetCommandTypeOptions();
1277         if ( SvXMLUnitConverter::convertEnum( sValue, _xReport->getCommandType(), aXML_CommnadTypeEnumMap ) )
1278             AddAttribute(XML_NAMESPACE_REPORT, XML_COMMAND_TYPE,sValue.makeStringAndClear());
1279 
1280         OUString sComamnd = _xReport->getCommand();
1281         if ( !sComamnd.isEmpty() )
1282             AddAttribute(XML_NAMESPACE_REPORT, XML_COMMAND, sComamnd);
1283 
1284         OUString sFilter( _xReport->getFilter() );
1285         if ( !sFilter.isEmpty() )
1286             AddAttribute( XML_NAMESPACE_REPORT, XML_FILTER, sFilter );
1287 
1288         AddAttribute(XML_NAMESPACE_OFFICE, XML_MIMETYPE,_xReport->getMimeType());
1289 
1290         bool bEscapeProcessing( _xReport->getEscapeProcessing() );
1291         if ( !bEscapeProcessing )
1292             AddAttribute( XML_NAMESPACE_REPORT, XML_ESCAPE_PROCESSING, ::xmloff::token::GetXMLToken( XML_FALSE ) );
1293 
1294         OUString sName = _xReport->getCaption();
1295         if ( !sName.isEmpty() )
1296             AddAttribute(XML_NAMESPACE_OFFICE, XML_CAPTION,sName);
1297         sName = _xReport->getName();
1298         if ( !sName.isEmpty() )
1299             AddAttribute(XML_NAMESPACE_DRAW, XML_NAME,sName);
1300     }
1301 }
1302 
ExportContent_()1303 void ORptExport::ExportContent_()
1304 {
1305     exportReport(getReportDefinition());
1306 }
1307 
ExportMasterStyles_()1308 void ORptExport::ExportMasterStyles_()
1309 {
1310     GetPageExport()->exportMasterStyles( true );
1311 }
1312 
collectComponentStyles()1313 void ORptExport::collectComponentStyles()
1314 {
1315     if ( m_bAllreadyFilled )
1316         return;
1317 
1318     m_bAllreadyFilled = true;
1319     Reference<XReportDefinition> xProp(getReportDefinition());
1320     if ( xProp.is() )
1321     {
1322         uno::Reference< report::XSection> xParent(xProp->getParent(),uno::UNO_QUERY);
1323         if ( xParent.is() )
1324             exportAutoStyle(xProp.get());
1325 
1326         if ( xProp->getReportHeaderOn() )
1327             exportSectionAutoStyle(xProp->getReportHeader());
1328         if ( xProp->getPageHeaderOn() )
1329             exportSectionAutoStyle(xProp->getPageHeader());
1330 
1331         exportGroup(xProp,0,true);
1332 
1333         if ( xProp->getPageFooterOn() )
1334             exportSectionAutoStyle(xProp->getPageFooter());
1335         if ( xProp->getReportFooterOn() )
1336             exportSectionAutoStyle(xProp->getReportFooter());
1337     }
1338 }
1339 
ExportAutoStyles_()1340 void ORptExport::ExportAutoStyles_()
1341 {
1342     // there are no styles that require their own autostyles
1343     if ( getExportFlags() & SvXMLExportFlags::CONTENT )
1344     {
1345         collectComponentStyles();
1346         GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_TABLE);
1347         GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_COLUMN);
1348         GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_ROW);
1349         GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_CELL);
1350         exportDataStyles();
1351         GetShapeExport()->exportAutoStyles();
1352     }
1353     // exported in _ExportMasterStyles
1354     if( getExportFlags() & SvXMLExportFlags::MASTERSTYLES )
1355         GetPageExport()->collectAutoStyles( false );
1356     if( getExportFlags() & SvXMLExportFlags::MASTERSTYLES )
1357         GetPageExport()->exportAutoStyles();
1358 }
1359 
ExportStyles_(bool bUsed)1360 void ORptExport::ExportStyles_(bool bUsed)
1361 {
1362     SvXMLExport::ExportStyles_(bUsed);
1363 
1364     // write draw:style-name for object graphic-styles
1365     GetShapeExport()->ExportGraphicDefaults();
1366 }
1367 
CreateAutoStylePool()1368 SvXMLAutoStylePoolP* ORptExport::CreateAutoStylePool()
1369 {
1370     return new OXMLAutoStylePoolP(*this);
1371 }
1372 
setSourceDocument(const Reference<XComponent> & xDoc)1373 void SAL_CALL ORptExport::setSourceDocument( const Reference< XComponent >& xDoc )
1374 {
1375     m_xReportDefinition.set(xDoc,UNO_QUERY_THROW);
1376     SvXMLExport::setSourceDocument(xDoc);
1377 }
1378 
ExportFontDecls_()1379 void ORptExport::ExportFontDecls_()
1380 {
1381     GetFontAutoStylePool(); // make sure the pool is created
1382     collectComponentStyles();
1383     SvXMLExport::ExportFontDecls_();
1384 }
1385 
exportParagraph(const Reference<XReportControlModel> & _xReportElement)1386 void ORptExport::exportParagraph(const Reference< XReportControlModel >& _xReportElement)
1387 {
1388     OSL_PRECOND(_xReportElement.is(),"Element is null!");
1389     // start <text:p>
1390     SvXMLElementExport aParagraphContent(*this,XML_NAMESPACE_TEXT, XML_P, false, false);
1391     if ( Reference<XFormattedField>(_xReportElement,uno::UNO_QUERY).is() )
1392     {
1393         OUString sFieldData = _xReportElement->getDataField();
1394         static const char s_sPageNumber[] = "PageNumber()";
1395         static const char s_sReportPrefix[] = "rpt:";
1396         sFieldData = sFieldData.copy(strlen(s_sReportPrefix));
1397         sal_Int32 nPageNumberIndex = sFieldData.indexOf(s_sPageNumber);
1398         if ( nPageNumberIndex != -1 )
1399         {
1400             sal_Int32 nIndex = 0;
1401             do
1402             {
1403                 OUString sToken = sFieldData.getToken( 0, '&', nIndex );
1404                 sToken = sToken.trim();
1405                 if ( !sToken.isEmpty() )
1406                 {
1407                     if ( sToken == s_sPageNumber )
1408                     {
1409                         AddAttribute(XML_NAMESPACE_TEXT, XML_SELECT_PAGE, "current" );
1410                         SvXMLElementExport aPageNumber(*this,XML_NAMESPACE_TEXT, XML_PAGE_NUMBER, false, false);
1411                         Characters("1");
1412                     }
1413                     else if ( sToken == "PageCount()" )
1414                     {
1415                         SvXMLElementExport aPageNumber(*this,XML_NAMESPACE_TEXT, XML_PAGE_COUNT, false, false);
1416                         Characters("1");
1417                     }
1418                     else
1419                     {
1420 
1421                         if ( sToken.startsWith("\"") && sToken.endsWith("\"") )
1422                             sToken = sToken.copy(1,sToken.getLength()-2);
1423 
1424                         bool bPrevCharIsSpace = false;
1425                         GetTextParagraphExport()->exportCharacterData(sToken, bPrevCharIsSpace);
1426                     }
1427                 }
1428             }
1429             while ( nIndex >= 0 );
1430         }
1431     }
1432     Reference< XFixedText > xFT(_xReportElement,UNO_QUERY);
1433     if ( xFT.is() )
1434     {
1435         OUString sExpr = xFT->getLabel();
1436         bool bPrevCharIsSpace = false; // FIXME this looks quite broken - does the corresponding import filter do whitespace collapsing at all?
1437         GetTextParagraphExport()->exportCharacterData(sExpr, bPrevCharIsSpace);
1438     }
1439 }
1440 
CreateShapeExport()1441 XMLShapeExport* ORptExport::CreateShapeExport()
1442 {
1443     XMLShapeExport* pShapeExport = new XMLShapeExport( *this, XMLTextParagraphExport::CreateShapeExtPropMapper( *this ) );
1444     return pShapeExport;
1445 }
1446 
exportShapes(const Reference<XSection> & _xSection,bool _bAddParagraph)1447 void ORptExport::exportShapes(const Reference< XSection>& _xSection,bool _bAddParagraph)
1448 {
1449     rtl::Reference< XMLShapeExport > xShapeExport = GetShapeExport();
1450     xShapeExport->seekShapes(_xSection.get());
1451     const sal_Int32 nCount = _xSection->getCount();
1452     ::std::unique_ptr<SvXMLElementExport> pParagraphContent;
1453     if ( _bAddParagraph )
1454         pParagraphContent.reset(new SvXMLElementExport(*this,XML_NAMESPACE_TEXT, XML_P, true, false));
1455 
1456     awt::Point aRefPoint;
1457     aRefPoint.X = rptui::getStyleProperty<sal_Int32>(_xSection->getReportDefinition(),PROPERTY_LEFTMARGIN);
1458     for (sal_Int32 i = 0; i < nCount; ++i)
1459     {
1460         uno::Reference< XShape > xShape(_xSection->getByIndex(i),uno::UNO_QUERY);
1461         if ( xShape.is() )
1462         {
1463             ::std::unique_ptr<SvXMLElementExport> pSubDocument;
1464             uno::Reference< frame::XModel> xModel(xShape->getPropertyValue("Model"),uno::UNO_QUERY);
1465             if ( xModel.is() ) // special handling for chart object
1466             {
1467                 pSubDocument.reset(new SvXMLElementExport(*this,XML_NAMESPACE_REPORT, XML_SUB_DOCUMENT, false, false));
1468                 exportMasterDetailFields(xShape.get());
1469                 exportReportElement(xShape.get());
1470             }
1471 
1472             AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, XML_PARAGRAPH );
1473             xShapeExport->exportShape(xShape.get(), SEF_DEFAULT|XMLShapeExportFlags::NO_WS,&aRefPoint);
1474         }
1475     }
1476 }
1477 
exportGroupsExpressionAsFunction(const Reference<XGroups> & _xGroups)1478 void ORptExport::exportGroupsExpressionAsFunction(const Reference< XGroups>& _xGroups)
1479 {
1480     if ( _xGroups.is() )
1481     {
1482         uno::Reference< XFunctions> xFunctions = _xGroups->getReportDefinition()->getFunctions();
1483         const sal_Int32 nCount = _xGroups->getCount();
1484         for (sal_Int32 i = 0; i < nCount; ++i)
1485         {
1486             uno::Reference< XGroup> xGroup(_xGroups->getByIndex(i),uno::UNO_QUERY_THROW);
1487             const ::sal_Int16 nGroupOn = xGroup->getGroupOn();
1488             if ( nGroupOn != report::GroupOn::DEFAULT )
1489             {
1490                 uno::Reference< XFunction> xFunction = xFunctions->createFunction();
1491                 OUString sFunction,sPrefix,sPostfix;
1492                 OUString sExpression = xGroup->getExpression();
1493                 OUString sFunctionName;
1494                 OUString sInitialFormula;
1495                 switch(nGroupOn)
1496                 {
1497                     case report::GroupOn::PREFIX_CHARACTERS:
1498                         sFunction = "LEFT";
1499                         sPrefix = ";" + OUString::number(xGroup->getGroupInterval());
1500                         break;
1501                     case report::GroupOn::YEAR:
1502                         sFunction = "YEAR";
1503                         break;
1504                     case report::GroupOn::QUARTAL:
1505                         sFunction   = "INT((MONTH";
1506                         sPostfix    = "-1)/3)+1";
1507                         sFunctionName = "QUARTAL_" + sExpression;
1508                         break;
1509                     case report::GroupOn::MONTH:
1510                         sFunction = "MONTH";
1511                         break;
1512                     case report::GroupOn::WEEK:
1513                         sFunction = "WEEK";
1514                         break;
1515                     case report::GroupOn::DAY:
1516                         sFunction = "DAY";
1517                         break;
1518                     case report::GroupOn::HOUR:
1519                         sFunction = "HOUR";
1520                         break;
1521                     case report::GroupOn::MINUTE:
1522                         sFunction = "MINUTE";
1523                         break;
1524                     case report::GroupOn::INTERVAL:
1525                         {
1526                             sFunction = "INT";
1527                             uno::Reference< XFunction> xCountFunction = xFunctions->createFunction();
1528                             xCountFunction->setInitialFormula(beans::Optional< OUString>(true,OUString("rpt:0")));
1529                             OUString sCountName = sFunction + "_count_" + sExpression;
1530                             xCountFunction->setName(sCountName);
1531                             xCountFunction->setFormula( "rpt:[" + sCountName + "] + 1" );
1532                             exportFunction(xCountFunction);
1533                             sExpression = sCountName;
1534                             // The reference to sCountName in the formula of sFunctionName refers to the *old* value
1535                             // so we need to expand the formula of sCountName
1536                             sPrefix = " + 1) / " + OUString::number(xGroup->getGroupInterval());
1537                             sFunctionName = sFunction + "_" + sExpression;
1538                             sFunction += "(";
1539                             sInitialFormula = "rpt:0";
1540                         }
1541                         break;
1542                     default:
1543                         ;
1544                 }
1545                 if ( sFunctionName.isEmpty() )
1546                     sFunctionName = sFunction + "_" + sExpression;
1547                 if ( !sFunction.isEmpty() )
1548                 {
1549                     const sal_Unicode pReplaceChars[] = { '(',')',';',',','+','-','[',']','/','*'};
1550                     for(sal_Unicode ch : pReplaceChars)
1551                         sFunctionName = sFunctionName.replace(ch,'_');
1552 
1553                     xFunction->setName(sFunctionName);
1554                     if ( !sInitialFormula.isEmpty() )
1555                         xFunction->setInitialFormula(beans::Optional< OUString>(true, sInitialFormula));
1556                     sFunction = "rpt:" + sFunction + "([" + sExpression + "]";
1557 
1558                     if ( !sPrefix.isEmpty() )
1559                         sFunction += sPrefix;
1560                     sFunction += ")";
1561                     if ( !sPostfix.isEmpty() )
1562                         sFunction += sPostfix;
1563                     xFunction->setFormula(sFunction);
1564                     exportFunction(xFunction);
1565                     m_aGroupFunctionMap.emplace(xGroup,xFunction);
1566                 }
1567             }
1568         }
1569     }
1570 }
1571 
1572 
1573 }// rptxml
1574 
1575 
1576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1577