LCOV - code coverage report
Current view: top level - oox/source/export - chartexport.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1688 1925 87.7 %
Date: 2015-06-13 12:38:46 Functions: 83 86 96.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <oox/token/tokens.hxx>
      21             : #include "oox/core/xmlfilterbase.hxx"
      22             : #include "oox/export/chartexport.hxx"
      23             : #include "oox/export/utils.hxx"
      24             : #include "drawingml/chart/typegroupconverter.hxx"
      25             : 
      26             : #include <cstdio>
      27             : 
      28             : #include <com/sun/star/awt/Gradient.hpp>
      29             : #include <com/sun/star/chart/XChartDocument.hpp>
      30             : #include <com/sun/star/chart/ChartLegendPosition.hpp>
      31             : #include <com/sun/star/chart/XTwoAxisXSupplier.hpp>
      32             : #include <com/sun/star/chart/XTwoAxisYSupplier.hpp>
      33             : #include <com/sun/star/chart/XAxisZSupplier.hpp>
      34             : #include <com/sun/star/chart/XChartDataArray.hpp>
      35             : #include <com/sun/star/chart/ChartDataRowSource.hpp>
      36             : #include <com/sun/star/chart/ChartAxisAssign.hpp>
      37             : #include <com/sun/star/chart/ChartSeriesAddress.hpp>
      38             : #include <com/sun/star/chart/X3DDisplay.hpp>
      39             : #include <com/sun/star/chart/XStatisticDisplay.hpp>
      40             : #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
      41             : #include <com/sun/star/chart/ChartSymbolType.hpp>
      42             : #include <com/sun/star/chart/ChartAxisMarks.hpp>
      43             : #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
      44             : #include <com/sun/star/chart/ChartAxisPosition.hpp>
      45             : #include <com/sun/star/chart/ChartSolidType.hpp>
      46             : #include <com/sun/star/chart/DataLabelPlacement.hpp>
      47             : #include <com/sun/star/chart/ErrorBarStyle.hpp>
      48             : #include <com/sun/star/chart/MissingValueTreatment.hpp>
      49             : 
      50             : #include <com/sun/star/chart2/XChartDocument.hpp>
      51             : #include <com/sun/star/chart2/XDiagram.hpp>
      52             : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
      53             : #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
      54             : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
      55             : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
      56             : #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
      57             : #include <com/sun/star/chart2/DataPointLabel.hpp>
      58             : #include <com/sun/star/chart2/Symbol.hpp>
      59             : #include <com/sun/star/chart2/data/XDataSource.hpp>
      60             : #include <com/sun/star/chart2/data/XDataSink.hpp>
      61             : #include <com/sun/star/chart2/data/XDataReceiver.hpp>
      62             : #include <com/sun/star/chart2/data/XDataProvider.hpp>
      63             : #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
      64             : #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
      65             : #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
      66             : #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
      67             : 
      68             : #include <com/sun/star/beans/XPropertySet.hpp>
      69             : #include <com/sun/star/beans/XPropertyState.hpp>
      70             : #include <com/sun/star/container/XEnumerationAccess.hpp>
      71             : #include <com/sun/star/drawing/XShape.hpp>
      72             : #include <com/sun/star/drawing/FillStyle.hpp>
      73             : #include <com/sun/star/drawing/BitmapMode.hpp>
      74             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      75             : #include <com/sun/star/lang/XServiceName.hpp>
      76             : 
      77             : #include <com/sun/star/table/CellAddress.hpp>
      78             : #include <com/sun/star/sheet/XFormulaParser.hpp>
      79             : #include <com/sun/star/sheet/XFormulaTokens.hpp>
      80             : #include <com/sun/star/sheet/FormulaToken.hpp>
      81             : #include <com/sun/star/sheet/AddressConvention.hpp>
      82             : 
      83             : #include <com/sun/star/text/WritingMode.hpp>
      84             : #include <com/sun/star/container/XNamed.hpp>
      85             : #include <com/sun/star/embed/XVisualObject.hpp>
      86             : #include <com/sun/star/embed/Aspects.hpp>
      87             : 
      88             : #include <comphelper/processfactory.hxx>
      89             : #include <comphelper/random.hxx>
      90             : #include <xmloff/SchXMLSeriesHelper.hxx>
      91             : #include "ColorPropertySet.hxx"
      92             : #include <set>
      93             : #include <unordered_set>
      94             : 
      95             : #include <rtl/math.hxx>
      96             : 
      97             : using namespace css;
      98             : using namespace css::uno;
      99             : using namespace css::drawing;
     100             : using namespace ::oox::core;
     101             : using css::beans::PropertyState;
     102             : using css::beans::PropertyValue;
     103             : using css::beans::XPropertySet;
     104             : using css::beans::XPropertyState;
     105             : using css::container::XEnumeration;
     106             : using css::container::XEnumerationAccess;
     107             : using css::container::XIndexAccess;
     108             : using css::container::XNamed;
     109             : using css::io::XOutputStream;
     110             : using css::table::CellAddress;
     111             : using css::sheet::XFormulaParser;
     112             : using css::sheet::XFormulaTokens;
     113             : using ::oox::core::XmlFilterBase;
     114             : using ::sax_fastparser::FSHelperPtr;
     115             : 
     116             : namespace cssc = css::chart;
     117             : 
     118             : namespace oox { namespace drawingml {
     119             : 
     120             : namespace {
     121             : 
     122         121 : sal_Int32 translateFromChart2AxisIndexToOox(sal_Int32 nIndex)
     123             : {
     124             :     assert(nIndex == 0 || nIndex == 1);
     125         121 :     if (nIndex == 1)
     126           4 :         return AXIS_SECONDARY_Y;
     127         117 :     return AXIS_PRIMARY_Y;
     128             : }
     129             : 
     130             : }
     131             : 
     132         309 : class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
     133             : {
     134             : public:
     135         143 :     explicit lcl_MatchesRole( const OUString & aRole ) :
     136         143 :             m_aRole( aRole )
     137         143 :     {}
     138             : 
     139         301 :     bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
     140             :     {
     141         301 :         if( !xSeq.is() )
     142           0 :             return  false;
     143         301 :         Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
     144         602 :         OUString aRole;
     145             : 
     146         903 :         return ( xProp.is() &&
     147         301 :                  (xProp->getPropertyValue(
     148        2107 :                      OUString(  "Role" ) ) >>= aRole ) &&
     149         903 :                  m_aRole.equals( aRole ));
     150             :     }
     151             : 
     152             : private:
     153             :     OUString m_aRole;
     154             : };
     155             : 
     156             : template< typename T >
     157         122 :     void lcl_SequenceToVectorAppend( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
     158             : {
     159         122 :     rDestination.reserve( rDestination.size() + rSource.getLength());
     160         122 :     ::std::copy( rSource.begin(), rSource.end(),
     161         122 :                  ::std::back_inserter( rDestination ));
     162         122 : }
     163             : 
     164          97 : Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram )
     165             : {
     166          97 :     Reference< chart2::data::XLabeledDataSequence >  xResult;
     167             :     try
     168             :     {
     169             :         Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
     170          97 :             xDiagram, uno::UNO_QUERY_THROW );
     171             :         Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
     172         194 :             xCooSysCnt->getCoordinateSystems());
     173         194 :         for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
     174             :         {
     175          97 :             Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[i] );
     176             :             OSL_ASSERT( xCooSys.is());
     177         414 :             for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
     178             :             {
     179         220 :                 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
     180         373 :                 for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
     181             :                 {
     182         227 :                     Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN, nI );
     183             :                     OSL_ASSERT( xAxis.is());
     184         227 :                     if( xAxis.is())
     185             :                     {
     186         227 :                         chart2::ScaleData aScaleData = xAxis->getScaleData();
     187         227 :                         if( aScaleData.Categories.is())
     188             :                         {
     189          74 :                             xResult.set( aScaleData.Categories );
     190          74 :                             break;
     191         153 :                         }
     192             :                     }
     193         153 :                 }
     194             :             }
     195         194 :         }
     196             :     }
     197           0 :     catch( const uno::Exception & ex )
     198             :     {
     199             :         (void)ex; // avoid warning for pro build
     200             :         OSL_FAIL( OUStringToOString(
     201             :                         "Exception caught. Type: " +
     202             :                         OUString::createFromAscii( typeid( ex ).name()) +
     203             :                         ", Message: " +
     204             :                         ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
     205             :     }
     206             : 
     207          97 :     return xResult;
     208             : }
     209             : 
     210          60 : Reference< chart2::data::XDataSource > lcl_createDataSource(
     211             :     const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aData )
     212             : {
     213             :     Reference< uno::XComponentContext > xContext(
     214          60 :         comphelper::getProcessComponentContext() );
     215             :     Reference< chart2::data::XDataSink > xSink(
     216         120 :         xContext->getServiceManager()->createInstanceWithContext(
     217          60 :             "com.sun.star.chart2.data.DataSource", xContext ),
     218         120 :         uno::UNO_QUERY_THROW );
     219          60 :     if( xSink.is())
     220          60 :         xSink->setData( aData );
     221             : 
     222         120 :     return Reference< chart2::data::XDataSource >( xSink, uno::UNO_QUERY );
     223             : }
     224             : 
     225          60 : Sequence< Reference< chart2::data::XLabeledDataSequence > > lcl_getAllSeriesSequences( const Reference< chart2::XChartDocument >& xChartDoc )
     226             : {
     227          60 :     ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aContainer;
     228          60 :     if( xChartDoc.is() )
     229             :     {
     230          60 :         Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
     231         120 :         ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram ));
     232         546 :         for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() )
     233         364 :             ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt )
     234             :         {
     235         122 :             Reference< chart2::data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY );
     236         122 :             if( !xDataSource.is() )
     237           0 :                 continue;
     238         244 :             uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
     239         122 :             lcl_SequenceToVectorAppend( aDataSequences, aContainer );
     240         182 :         }
     241             :     }
     242             : 
     243          60 :     Sequence< Reference< chart2::data::XLabeledDataSequence > > aRet( aContainer.size());
     244          60 :     ::std::copy( aContainer.begin(), aContainer.end(), aRet.getArray());
     245             : 
     246          60 :     return aRet;
     247             : }
     248             : 
     249             : Reference< chart2::data::XLabeledDataSequence >
     250          83 :     lcl_getDataSequenceByRole(
     251             :         const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aLabeledSeq,
     252             :         const OUString & rRole )
     253             : {
     254          83 :     Reference< chart2::data::XLabeledDataSequence > aNoResult;
     255             : 
     256          83 :     const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
     257          83 :     const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
     258             :     const Reference< chart2::data::XLabeledDataSequence > * pMatch =
     259          83 :         ::std::find_if( pBegin, pEnd, lcl_MatchesRole( rRole ));
     260             : 
     261          83 :     if( pMatch != pEnd )
     262          29 :         return *pMatch;
     263             : 
     264          54 :     return aNoResult;
     265             : }
     266             : 
     267          60 : Reference< chart2::data::XDataSource > lcl_pressUsedDataIntoRectangularFormat( const Reference< chart2::XChartDocument >& xChartDoc, bool& rOutSourceHasCategoryLabels )
     268             : {
     269          60 :     ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeqVector;
     270             : 
     271             :     //categories are always the first sequence
     272         120 :     Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
     273         120 :     Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) );
     274          60 :     if( xCategories.is() )
     275          37 :         aLabeledSeqVector.push_back( xCategories );
     276          60 :     rOutSourceHasCategoryLabels = xCategories.is();
     277             : 
     278             :     Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeriesSeqVector(
     279         120 :             lcl_getAllSeriesSequences( xChartDoc ) );
     280             : 
     281             :     //the first x-values is always the next sequence //todo ... other x-values get lost for old format
     282             :     Reference< chart2::data::XLabeledDataSequence > xXValues(
     283         120 :         lcl_getDataSequenceByRole( aSeriesSeqVector, OUString("values-x") ) );
     284          60 :     if( xXValues.is() )
     285           9 :         aLabeledSeqVector.push_back( xXValues );
     286             : 
     287             :     //add all other sequences now without x-values
     288         120 :     lcl_MatchesRole aHasXValues( OUString("values-x") );
     289         200 :     for( sal_Int32 nN=0; nN<aSeriesSeqVector.getLength(); nN++ )
     290             :     {
     291         140 :         if( !aHasXValues( aSeriesSeqVector[nN] ) )
     292         127 :             aLabeledSeqVector.push_back( aSeriesSeqVector[nN] );
     293             :     }
     294             : 
     295         120 :     Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( aLabeledSeqVector.size() );
     296          60 :     ::std::copy( aLabeledSeqVector.begin(), aLabeledSeqVector.end(), aSeq.getArray() );
     297             : 
     298         120 :     return lcl_createDataSource( aSeq );
     299             : }
     300             : 
     301           1 : bool lcl_isSeriesAttachedToFirstAxis(
     302             :     const Reference< chart2::XDataSeries > & xDataSeries )
     303             : {
     304           1 :     bool bResult=true;
     305             : 
     306             :     try
     307             :     {
     308           1 :         sal_Int32 nAxisIndex = 0;
     309           1 :         Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
     310           1 :         if( xProp.is() )
     311           1 :             xProp->getPropertyValue("AttachedAxisIndex") >>= nAxisIndex;
     312           1 :         bResult = (0==nAxisIndex);
     313             :     }
     314           0 :     catch( const uno::Exception & ex )
     315             :     {
     316             :         (void)ex; // avoid warning for pro build
     317             :         OSL_FAIL( OUStringToOString(
     318             :                         "Exception caught. Type: " +
     319             :                         OUString::createFromAscii( typeid( ex ).name()) +
     320             :                         ", Message: " +
     321             :                         ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
     322             :     }
     323             : 
     324           1 :     return bResult;
     325             : }
     326             : 
     327         121 : OUString lcl_flattenStringSequence( const Sequence< OUString > & rSequence )
     328             : {
     329         121 :     OUStringBuffer aResult;
     330         121 :     bool bPrecedeWithSpace = false;
     331         242 :     for( sal_Int32 nIndex=0; nIndex<rSequence.getLength(); ++nIndex )
     332             :     {
     333         121 :         if( !rSequence[nIndex].isEmpty())
     334             :         {
     335         119 :             if( bPrecedeWithSpace )
     336           0 :                 aResult.append( ' ' );
     337         119 :             aResult.append( rSequence[nIndex] );
     338         119 :             bPrecedeWithSpace = true;
     339             :         }
     340             :     }
     341         121 :     return aResult.makeStringAndClear();
     342             : }
     343             : 
     344         121 : OUString lcl_getLabelString( const Reference< chart2::data::XDataSequence > & xLabelSeq )
     345             : {
     346         121 :     Sequence< OUString > aLabels;
     347             : 
     348         242 :     uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xLabelSeq, uno::UNO_QUERY );
     349         121 :     if( xTextualDataSequence.is())
     350             :     {
     351         121 :         aLabels = xTextualDataSequence->getTextualData();
     352             :     }
     353           0 :     else if( xLabelSeq.is())
     354             :     {
     355           0 :         Sequence< uno::Any > aAnies( xLabelSeq->getData());
     356           0 :         aLabels.realloc( aAnies.getLength());
     357           0 :         for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
     358           0 :             aAnies[i] >>= aLabels[i];
     359             :     }
     360             : 
     361         242 :     return lcl_flattenStringSequence( aLabels );
     362             : }
     363             : 
     364          81 : void lcl_fillCategoriesIntoStringVector(
     365             :     const Reference< chart2::data::XDataSequence > & xCategories,
     366             :     ::std::vector< OUString > & rOutCategories )
     367             : {
     368             :     OSL_ASSERT( xCategories.is());
     369          81 :     if( !xCategories.is())
     370          81 :         return;
     371          81 :     Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xCategories, uno::UNO_QUERY );
     372          81 :     if( xTextualDataSequence.is())
     373             :     {
     374          81 :         rOutCategories.clear();
     375          81 :         Sequence< OUString > aTextData( xTextualDataSequence->getTextualData());
     376             :         ::std::copy( aTextData.begin(), aTextData.end(),
     377          81 :                      ::std::back_inserter( rOutCategories ));
     378             :     }
     379             :     else
     380             :     {
     381           0 :         Sequence< uno::Any > aAnies( xCategories->getData());
     382           0 :         rOutCategories.resize( aAnies.getLength());
     383           0 :         for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
     384           0 :             aAnies[i] >>= rOutCategories[i];
     385          81 :     }
     386             : }
     387             : 
     388         140 : ::std::vector< double > lcl_getAllValuesFromSequence( const Reference< chart2::data::XDataSequence > & xSeq )
     389             : {
     390         140 :     double fNan = 0.0;
     391         140 :     ::rtl::math::setNan( &fNan );
     392         140 :     ::std::vector< double > aResult;
     393             : 
     394         280 :     Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY );
     395         140 :     if( xNumSeq.is())
     396             :     {
     397         140 :         Sequence< double > aValues( xNumSeq->getNumericalData());
     398             :         ::std::copy( aValues.begin(), aValues.end(),
     399         140 :                      ::std::back_inserter( aResult ));
     400             :     }
     401           0 :     else if( xSeq.is())
     402             :     {
     403           0 :         Sequence< uno::Any > aAnies( xSeq->getData());
     404           0 :         aResult.resize( aAnies.getLength(), fNan );
     405           0 :         for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
     406           0 :             aAnies[i] >>= aResult[i];
     407             :     }
     408         280 :     return aResult;
     409             : }
     410             : 
     411         214 : sal_Int32 lcl_getChartType( const OUString& sChartType )
     412             : {
     413         214 :     chart::TypeId eChartTypeId = chart::TYPEID_UNKNOWN;
     414         428 :     if( sChartType == "com.sun.star.chart.BarDiagram"
     415         214 :         || sChartType == "com.sun.star.chart2.ColumnChartType" )
     416         109 :         eChartTypeId = chart::TYPEID_BAR;
     417         210 :     else if( sChartType == "com.sun.star.chart.AreaDiagram"
     418         105 :              || sChartType == "com.sun.star.chart2.AreaChartType" )
     419           6 :         eChartTypeId = chart::TYPEID_AREA;
     420         198 :     else if( sChartType == "com.sun.star.chart.LineDiagram"
     421          99 :              || sChartType == "com.sun.star.chart2.LineChartType" )
     422          30 :         eChartTypeId = chart::TYPEID_LINE;
     423         138 :     else if( sChartType == "com.sun.star.chart.PieDiagram"
     424          69 :              || sChartType == "com.sun.star.chart2.PieChartType" )
     425          26 :         eChartTypeId = chart::TYPEID_PIE;
     426          86 :     else if( sChartType == "com.sun.star.chart.DonutDiagram"
     427          43 :              || sChartType == "com.sun.star.chart2.DonutChartType" )
     428           4 :         eChartTypeId = chart::TYPEID_DOUGHNUT;
     429          78 :     else if( sChartType == "com.sun.star.chart.XYDiagram"
     430          39 :              || sChartType == "com.sun.star.chart2.ScatterChartType" )
     431          29 :         eChartTypeId = chart::TYPEID_SCATTER;
     432          20 :     else if( sChartType == "com.sun.star.chart.NetDiagram"
     433          10 :              || sChartType == "com.sun.star.chart2.NetChartType" )
     434           0 :         eChartTypeId = chart::TYPEID_RADARLINE;
     435          20 :     else if( sChartType == "com.sun.star.chart.FilledNetDiagram"
     436          10 :              || sChartType == "com.sun.star.chart2.FilledNetChartType" )
     437           4 :         eChartTypeId = chart::TYPEID_RADARAREA;
     438          12 :     else if( sChartType == "com.sun.star.chart.StockDiagram"
     439           6 :              || sChartType == "com.sun.star.chart2.CandleStickChartType" )
     440           3 :         eChartTypeId = chart::TYPEID_STOCK;
     441           6 :     else if( sChartType == "com.sun.star.chart.BubbleDiagram"
     442           3 :              || sChartType == "com.sun.star.chart2.BubbleChartType" )
     443           3 :         eChartTypeId = chart::TYPEID_BUBBLE;
     444             : 
     445         214 :     return eChartTypeId;
     446             : }
     447             : 
     448         116 : sal_Int32 lcl_generateRandomValue()
     449             : {
     450         116 :     return comphelper::rng::uniform_int_distribution(0, 100000000-1);
     451             : }
     452             : 
     453          60 : ChartExport::ChartExport( sal_Int32 nXmlNamespace, FSHelperPtr pFS, Reference< frame::XModel >& xModel, XmlFilterBase* pFB, DocumentType eDocumentType )
     454             :     : DrawingML( pFS, pFB, eDocumentType )
     455             :     , mnXmlNamespace( nXmlNamespace )
     456             :     , mnSeriesCount(0)
     457             :     , mxChartModel( xModel )
     458             :     , mbHasCategoryLabels( false )
     459             :     , mbHasZAxis( false )
     460             :     , mbIs3DChart( false )
     461             :     , mbStacked(false)
     462          60 :     , mbPercent(false)
     463             : {
     464          60 : }
     465             : 
     466          24 : sal_Int32 ChartExport::GetChartID( )
     467             : {
     468          24 :     sal_Int32 nID = GetFB()->GetUniqueId();
     469          24 :     return nID;
     470             : }
     471             : 
     472          86 : sal_Int32 ChartExport::getChartType( )
     473             : {
     474          86 :     OUString sChartType = mxDiagram->getDiagramType();
     475          86 :     return lcl_getChartType( sChartType );
     476             : }
     477             : 
     478         342 : OUString ChartExport::parseFormula( const OUString& rRange )
     479             : {
     480         342 :     OUString aResult;
     481         684 :     Reference< XFormulaParser > xParser;
     482         684 :     uno::Reference< lang::XMultiServiceFactory > xSF( GetFB()->getModelFactory(), uno::UNO_QUERY );
     483         342 :     if( xSF.is() )
     484             :     {
     485             :         try
     486             :         {
     487         342 :             xParser.set( xSF->createInstance("com.sun.star.sheet.FormulaParser"), UNO_QUERY );
     488             :         }
     489         252 :         catch( Exception& )
     490             :         {
     491             :         }
     492             :     }
     493             : 
     494             :     SAL_WARN_IF(!xParser.is(), "oox", "creating formula parser failed");
     495             : 
     496         342 :     if( xParser.is() )
     497             :     {
     498          90 :         Reference< XPropertySet > xParserProps( xParser, uno::UNO_QUERY );
     499          90 :         if( xParserProps.is() )
     500             :         {
     501          90 :             xParserProps->setPropertyValue("FormulaConvention", uno::makeAny(css::sheet::AddressConvention::OOO) );
     502             :         }
     503         180 :         uno::Sequence<sheet::FormulaToken> aTokens = xParser->parseFormula( rRange, CellAddress( 0, 0, 0 ) );
     504          90 :         if( xParserProps.is() )
     505             :         {
     506          90 :             xParserProps->setPropertyValue("FormulaConvention", uno::makeAny(css::sheet::AddressConvention::XL_OOX) );
     507             :         }
     508         180 :         aResult = xParser->printFormula( aTokens, CellAddress( 0, 0, 0 ) );
     509             :     }
     510             :     else
     511             :     {
     512             :         //FIXME: currently just using simple converter, e.g $Sheet1.$A$1:$C$1 -> Sheet1!$A$1:$C$1
     513         252 :         OUString aRange( rRange );
     514         252 :         if( aRange.startsWith("$") )
     515           0 :             aRange = aRange.copy(1);
     516         252 :         aRange = aRange.replaceAll(".$", "!$" );
     517         252 :         aResult = aRange;
     518             :     }
     519             : 
     520         684 :     return aResult;
     521             : }
     522             : 
     523          24 : ChartExport& ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 nChartCount )
     524             : {
     525          24 :     FSHelperPtr pFS = GetFS();
     526             : 
     527          24 :     pFS->startElementNS( mnXmlNamespace, XML_graphicFrame, FSEND );
     528             : 
     529          24 :     pFS->startElementNS( mnXmlNamespace, XML_nvGraphicFramePr, FSEND );
     530             : 
     531             :     // TODO: get the correct chart name chart id
     532          48 :     OUString sName = "Object 1";
     533          48 :     Reference< XNamed > xNamed( xShape, UNO_QUERY );
     534          24 :     if (xNamed.is())
     535          24 :         sName = xNamed->getName();
     536             : 
     537          24 :     sal_Int32 nID = GetChartID();
     538             : 
     539             :     pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
     540             :                           XML_id,     I32S( nID ),
     541             :                           XML_name,   USS( sName ),
     542          24 :                           FSEND );
     543             : 
     544             :     pFS->singleElementNS( mnXmlNamespace, XML_cNvGraphicFramePr,
     545          24 :                           FSEND );
     546             : 
     547          24 :     if( GetDocumentType() == DOCUMENT_PPTX )
     548             :         pFS->singleElementNS( mnXmlNamespace, XML_nvPr,
     549           0 :                           FSEND );
     550          24 :     pFS->endElementNS( mnXmlNamespace, XML_nvGraphicFramePr );
     551             : 
     552             :     // visual chart properties
     553          24 :     WriteShapeTransformation( xShape, mnXmlNamespace );
     554             : 
     555             :     // writer chart object
     556          24 :     pFS->startElement( FSNS( XML_a, XML_graphic ), FSEND );
     557             :     pFS->startElement( FSNS( XML_a, XML_graphicData ),
     558             :                        XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/chart",
     559          24 :                        FSEND );
     560          48 :     OUString sId;
     561          24 :     const char* sFullPath = NULL;
     562          24 :     const char* sRelativePath = NULL;
     563          24 :     switch( GetDocumentType() )
     564             :     {
     565             :         case DOCUMENT_DOCX:
     566             :         {
     567           0 :             sFullPath = "word/charts/chart";
     568           0 :             sRelativePath = "charts/chart";
     569           0 :             break;
     570             :         }
     571             :         case DOCUMENT_PPTX:
     572             :         {
     573           0 :             sFullPath = "ppt/charts/chart";
     574           0 :             sRelativePath = "../charts/chart";
     575           0 :             break;
     576             :         }
     577             :         case DOCUMENT_XLSX:
     578             :         {
     579          24 :             sFullPath = "xl/charts/chart";
     580          24 :             sRelativePath = "../charts/chart";
     581          24 :             break;
     582             :         }
     583             :         default:
     584             :         {
     585           0 :             sFullPath = "charts/chart";
     586           0 :             sRelativePath = "charts/chart";
     587           0 :             break;
     588             :         }
     589             :     }
     590             :     OUString sFullStream = OUStringBuffer()
     591          48 :                             .appendAscii(sFullPath)
     592          24 :                             .append(nChartCount)
     593          24 :                             .appendAscii( ".xml" )
     594          24 :                             .makeStringAndClear();
     595             :     OUString sRelativeStream = OUStringBuffer()
     596          48 :                             .appendAscii(sRelativePath)
     597          24 :                             .append(nChartCount)
     598          24 :                             .appendAscii( ".xml" )
     599          48 :                             .makeStringAndClear();
     600             :     FSHelperPtr pChart = CreateOutputStream(
     601             :             sFullStream,
     602             :             sRelativeStream,
     603             :             pFS->getOutputStream(),
     604             :             "application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
     605             :             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
     606          48 :             &sId );
     607             : 
     608             :     pFS->singleElement(  FSNS( XML_c, XML_chart ),
     609             :             FSNS( XML_xmlns, XML_c ), "http://schemas.openxmlformats.org/drawingml/2006/chart",
     610             :             FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
     611             :             FSNS( XML_r, XML_id ), USS( sId ),
     612          24 :             FSEND );
     613             : 
     614          24 :     pFS->endElement( FSNS( XML_a, XML_graphicData ) );
     615          24 :     pFS->endElement( FSNS( XML_a, XML_graphic ) );
     616          24 :     pFS->endElementNS( mnXmlNamespace, XML_graphicFrame );
     617             : 
     618          24 :     SetFS( pChart );
     619          24 :     ExportContent();
     620             : 
     621          72 :     return *this;
     622             : }
     623             : 
     624          60 : void ChartExport::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
     625             : {
     626          60 :     if( xChartDoc.is())
     627             :         try
     628             :         {
     629          60 :             Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
     630             :             OSL_ENSURE( xDataProvider.is(), "No DataProvider" );
     631          60 :             if( xDataProvider.is())
     632             :             {
     633          60 :                 Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
     634         120 :                 Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
     635         120 :                 OUString sCellRange, sBrokenRange;
     636          60 :                 bool bBrokenRangeAvailable = false;
     637         324 :                 for( sal_Int32 i=0; i<aArgs.getLength(); ++i )
     638             :                 {
     639         264 :                     if ( aArgs[i].Name == "CellRangeRepresentation" )
     640          60 :                         aArgs[i].Value >>= sCellRange;
     641         204 :                     else if ( aArgs[i].Name == "BrokenCellRangeForExport" )
     642             :                     {
     643           0 :                         if( aArgs[i].Value >>= sBrokenRange )
     644           0 :                             bBrokenRangeAvailable = true;
     645             :                     }
     646         204 :                     else if ( aArgs[i].Name == "SequenceMapping" )
     647           0 :                         aArgs[i].Value >>= maSequenceMapping;
     648             :                 }
     649             : 
     650             :                 // #i79009# For Writer we have to export a broken version of the
     651             :                 // range, where every row number is noe too large, so that older
     652             :                 // version can correctly read those files.
     653          60 :                 msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
     654          60 :                 if( !msChartAddress.isEmpty() )
     655             :                 {
     656             :                     // convert format to XML-conform one
     657          60 :                     Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
     658          60 :                     if( xConversion.is())
     659          60 :                         msChartAddress = xConversion->convertRangeToXML( msChartAddress );
     660          60 :                 }
     661          60 :             }
     662             :         }
     663           0 :         catch( const uno::Exception & ex )
     664             :         {
     665             :             (void)ex; // avoid warning for pro build
     666             :             OSL_FAIL( OUStringToOString(
     667             :                             "Exception caught. Type: " +
     668             :                             OUString::createFromAscii( typeid( ex ).name()) +
     669             :                             ", Message: " +
     670             :                             ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
     671             :         }
     672          60 : }
     673             : 
     674          60 : void ChartExport::ExportContent()
     675             : {
     676          60 :     Reference< chart2::XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY );
     677             :     OSL_ASSERT( xChartDoc.is() );
     678          60 :     if( !xChartDoc.is() )
     679          60 :         return;
     680          60 :     InitRangeSegmentationProperties( xChartDoc );
     681             :     // TODO: export chart
     682          60 :     _ExportContent( );
     683             : }
     684             : 
     685          60 : void ChartExport::_ExportContent()
     686             : {
     687          60 :     Reference< css::chart::XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY );
     688          60 :     if( xChartDoc.is())
     689             :     {
     690             :         // determine if data comes from the outside
     691          60 :         bool bIncludeTable = true;
     692             : 
     693          60 :         Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
     694          60 :         if( xNewDoc.is())
     695             :         {
     696             :             // check if we have own data.  If so we must not export the complete
     697             :             // range string, as this is our only indicator for having own or
     698             :             // external data. @todo: fix this in the file format!
     699          60 :             Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
     700          60 :             if( ! (xDPServiceInfo.is() && xDPServiceInfo->getImplementationName() == "com.sun.star.comp.chart.InternalDataProvider" ))
     701             :             {
     702          24 :                 bIncludeTable = false;
     703          60 :             }
     704             :         }
     705             :         else
     706             :         {
     707           0 :             Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
     708           0 :             if( xServ.is())
     709             :             {
     710           0 :                 if( xServ->supportsService(
     711           0 :                         OUString("com.sun.star.chart.ChartTableAddressSupplier")))
     712             :                 {
     713           0 :                     Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
     714           0 :                     if( xProp.is())
     715             :                     {
     716           0 :                         Any aAny;
     717             :                         try
     718             :                         {
     719           0 :                             OUString sChartAddress;
     720           0 :                             aAny = xProp->getPropertyValue(
     721           0 :                                 OUString("ChartRangeAddress"));
     722           0 :                             aAny >>= msChartAddress;
     723             :                             //maExportHelper.SetChartRangeAddress( sChartAddress );
     724             : 
     725             :                             //maExportHelper.SetTableNumberList( sTableNumberList );
     726             : 
     727             :                             // do not include own table if there are external addresses
     728           0 :                             bIncludeTable = sChartAddress.isEmpty();
     729             :                         }
     730           0 :                         catch( beans::UnknownPropertyException & )
     731             :                         {
     732             :                             OSL_FAIL( "Property ChartRangeAddress not supported by ChartDocument" );
     733           0 :                         }
     734           0 :                     }
     735             :                 }
     736           0 :             }
     737             :         }
     738          60 :         exportChartSpace( xChartDoc, bIncludeTable );
     739             :     }
     740             :     else
     741             :     {
     742             :         OSL_FAIL( "Couldn't export chart due to wrong XModel" );
     743          60 :     }
     744          60 : }
     745             : 
     746          60 : void ChartExport::exportChartSpace( Reference< css::chart::XChartDocument > xChartDoc,
     747             :                                       bool bIncludeTable )
     748             : {
     749          60 :     FSHelperPtr pFS = GetFS();
     750             :     pFS->startElement( FSNS( XML_c, XML_chartSpace ),
     751             :             FSNS( XML_xmlns, XML_c ), "http://schemas.openxmlformats.org/drawingml/2006/chart",
     752             :             FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
     753             :             FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
     754          60 :             FSEND );
     755             :     // TODO: get the correct editing lanauge
     756             :     pFS->singleElement( FSNS( XML_c, XML_lang ),
     757             :             XML_val, "en-US",
     758          60 :             FSEND );
     759             : 
     760             :     pFS->singleElement(FSNS( XML_c, XML_roundedCorners),
     761             :             XML_val, "0",
     762          60 :             FSEND);
     763             : 
     764          60 :     if( !bIncludeTable )
     765             :     {
     766             :         // TODO:external data
     767             :     }
     768             :     //XML_chart
     769          60 :     exportChart(xChartDoc);
     770             : 
     771             :     // TODO: printSettings
     772             :     // TODO: style
     773             :     // TODO: text properties
     774             :     // TODO: shape properties
     775         120 :     Reference< XPropertySet > xPropSet( xChartDoc->getArea(), uno::UNO_QUERY );
     776          60 :     if( xPropSet.is() )
     777          60 :         exportShapeProps( xPropSet );
     778             : 
     779             :     //XML_externalData
     780          60 :     exportExternalData(xChartDoc);
     781             : 
     782         120 :     pFS->endElement( FSNS( XML_c, XML_chartSpace ) );
     783          60 : }
     784             : 
     785          60 : void ChartExport::exportExternalData( Reference< css::chart::XChartDocument > xChartDoc )
     786             : {
     787             :     // Embedded external data is grab bagged for docx file hence adding export part of
     788             :     // external data for docx files only.
     789          60 :     if(GetDocumentType() != DOCUMENT_DOCX)
     790          84 :         return;
     791             : 
     792          36 :     OUString externalDataPath;
     793          72 :     Reference< beans::XPropertySet > xDocPropSet( xChartDoc->getDiagram(), uno::UNO_QUERY );
     794          36 :     if( xDocPropSet.is())
     795             :     {
     796             :         try
     797             :         {
     798          36 :             Any aAny( xDocPropSet->getPropertyValue(
     799          36 :                 OUString(  "ExternalData" )));
     800          36 :             aAny >>= externalDataPath;
     801             :         }
     802           0 :         catch( beans::UnknownPropertyException & )
     803             :         {
     804             :             SAL_WARN("oox", "Required property not found in ChartDocument");
     805             :         }
     806             :     }
     807          36 :     if(!externalDataPath.isEmpty())
     808             :     {
     809             :         // Here adding external data entry to relationship.
     810          33 :         OUString relationPath = externalDataPath;
     811             :         // Converting absolute path to relative path.
     812          33 :         if( externalDataPath[ 0 ] != '.' && externalDataPath[ 1 ] != '.')
     813             :         {
     814          33 :             sal_Int32 nStartPos = 0;
     815          33 :             sal_Int32 nSepPos = externalDataPath.indexOf( '/', nStartPos );
     816          33 :             if( nSepPos > 0)
     817             :             {
     818          33 :                 relationPath = relationPath.copy( nSepPos,  ::std::max< sal_Int32 >( externalDataPath.getLength(), 0 ) -  nSepPos );
     819          33 :                 relationPath = OUStringBuffer( ".." ).append( relationPath ).makeStringAndClear();
     820             :             }
     821             :         }
     822          66 :         FSHelperPtr pFS = GetFS();
     823          66 :         OUString type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
     824          33 :         if (relationPath.endsWith(OUString(".bin")))
     825           0 :             type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
     826             : 
     827             :         OUString sRelId = GetFB()->addRelation(pFS->getOutputStream(),
     828             :                         type,
     829          66 :                         relationPath);
     830             :         pFS->singleElementNS( XML_c, XML_externalData,
     831             :                 FSNS(XML_r, XML_id), OUStringToOString(sRelId, RTL_TEXTENCODING_UTF8),
     832          66 :                 FSEND);
     833          36 :     }
     834             : }
     835             : 
     836          60 : void ChartExport::exportChart( Reference< css::chart::XChartDocument > xChartDoc )
     837             : {
     838          60 :     Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
     839          60 :     mxDiagram.set( xChartDoc->getDiagram() );
     840          60 :     if( xNewDoc.is())
     841          60 :         mxNewDiagram.set( xNewDoc->getFirstDiagram());
     842             : 
     843             :     // get Properties of ChartDocument
     844          60 :     bool bHasMainTitle = false;
     845          60 :     bool bHasSubTitle = false;
     846          60 :     bool bHasLegend = false;
     847         120 :     Reference< beans::XPropertySet > xDocPropSet( xChartDoc, uno::UNO_QUERY );
     848          60 :     if( xDocPropSet.is())
     849             :     {
     850             :         try
     851             :         {
     852          60 :             Any aAny( xDocPropSet->getPropertyValue(
     853          60 :                 OUString(  "HasMainTitle" )));
     854          60 :             aAny >>= bHasMainTitle;
     855         180 :             aAny = xDocPropSet->getPropertyValue(
     856         120 :                 OUString(  "HasSubTitle" ));
     857          60 :             aAny >>= bHasSubTitle;
     858         180 :             aAny = xDocPropSet->getPropertyValue(
     859         120 :                 OUString(  "HasLegend" ));
     860          60 :             aAny >>= bHasLegend;
     861             :         }
     862           0 :         catch( beans::UnknownPropertyException & )
     863             :         {
     864             :             SAL_WARN("oox", "Required property not found in ChartDocument");
     865             :         }
     866             :     } // if( xDocPropSet.is())
     867             : 
     868             :     // chart element
     869             : 
     870         120 :     FSHelperPtr pFS = GetFS();
     871             :     pFS->startElement( FSNS( XML_c, XML_chart ),
     872          60 :             FSEND );
     873             : 
     874             :     // title
     875          60 :     if( bHasMainTitle )
     876             :     {
     877          27 :         Reference< drawing::XShape > xShape = xChartDoc->getTitle();
     878          27 :         if( xShape.is() )
     879             :         {
     880          27 :             exportTitle( xShape );
     881             :             pFS->singleElement( FSNS(XML_c, XML_autoTitleDeleted),
     882             :                     XML_val, "0",
     883          27 :                     FSEND);
     884          27 :         }
     885             :     }
     886          60 :     InitPlotArea( );
     887          60 :     if( mbIs3DChart )
     888             :     {
     889          13 :         exportView3D();
     890             : 
     891             :         // floor
     892          13 :         Reference< beans::XPropertySet > xFloor( mxNewDiagram->getFloor(), uno::UNO_QUERY );
     893          13 :         if( xFloor.is() )
     894             :         {
     895             :             pFS->startElement( FSNS( XML_c, XML_floor ),
     896          13 :                 FSEND );
     897          13 :             exportShapeProps( xFloor );
     898          13 :             pFS->endElement( FSNS( XML_c, XML_floor ) );
     899             :         }
     900             : 
     901             :         // sideWall
     902             : 
     903             :         // backWall
     904          26 :         Reference< beans::XPropertySet > xBackWall( mxNewDiagram->getWall(), uno::UNO_QUERY );
     905          13 :         if( xBackWall.is() )
     906             :         {
     907             :             pFS->startElement( FSNS( XML_c, XML_backWall ),
     908          13 :                 FSEND );
     909          13 :             exportShapeProps( xBackWall );
     910          13 :             pFS->endElement( FSNS( XML_c, XML_backWall ) );
     911          13 :         }
     912             : 
     913             :     }
     914             :     // plot area
     915          60 :     exportPlotArea( );
     916             :     // legend
     917          60 :     if( bHasLegend )
     918          49 :         exportLegend( xChartDoc );
     919             : 
     920         120 :     uno::Reference<beans::XPropertySet> xDiagramPropSet(xChartDoc->getDiagram(), uno::UNO_QUERY);
     921         120 :     uno::Any aPlotVisOnly = xDiagramPropSet->getPropertyValue("IncludeHiddenCells");
     922          60 :     bool bIncludeHiddenCells = false;
     923          60 :     aPlotVisOnly >>= bIncludeHiddenCells;
     924             :     pFS->singleElement( FSNS( XML_c, XML_plotVisOnly ),
     925          60 :             XML_val, BS(!bIncludeHiddenCells),
     926          60 :             FSEND );
     927             : 
     928          60 :     exportMissingValueTreatment(Reference<beans::XPropertySet>(mxDiagram, uno::UNO_QUERY));
     929             : 
     930         120 :     pFS->endElement( FSNS( XML_c, XML_chart ) );
     931          60 : }
     932             : 
     933          60 : void ChartExport::exportMissingValueTreatment(uno::Reference<beans::XPropertySet> xPropSet)
     934             : {
     935          60 :     if (!xPropSet.is())
     936           1 :         return;
     937             : 
     938          60 :     sal_Int32 nVal = 0;
     939          60 :     uno::Any aAny = xPropSet->getPropertyValue("MissingValueTreatment");
     940          60 :     if (!(aAny >>= nVal))
     941           1 :         return;
     942             : 
     943          59 :     const char* pVal = NULL;
     944          59 :     switch (nVal)
     945             :     {
     946             :         case cssc::MissingValueTreatment::LEAVE_GAP:
     947          49 :             pVal = "gap";
     948          49 :         break;
     949             :         case cssc::MissingValueTreatment::USE_ZERO:
     950           6 :             pVal = "zero";
     951           6 :         break;
     952             :         case cssc::MissingValueTreatment::CONTINUE:
     953           4 :             pVal = "span";
     954           4 :         break;
     955             :         default:
     956             :             SAL_WARN("oox", "unknown MissingValueTreatment value");
     957           0 :         break;
     958             :     }
     959             : 
     960          59 :     FSHelperPtr pFS = GetFS();
     961             :     pFS->singleElement( FSNS(XML_c, XML_dispBlanksAs),
     962             :             XML_val, pVal,
     963          59 :             FSEND);
     964             : }
     965             : 
     966          49 : void ChartExport::exportLegend( Reference< css::chart::XChartDocument > xChartDoc )
     967             : {
     968          49 :     FSHelperPtr pFS = GetFS();
     969             :     pFS->startElement( FSNS( XML_c, XML_legend ),
     970          49 :             FSEND );
     971             : 
     972          98 :     Reference< beans::XPropertySet > xProp( xChartDoc->getLegend(), uno::UNO_QUERY );
     973          49 :     if( xProp.is() )
     974             :     {
     975             :         // position
     976          49 :         css::chart::ChartLegendPosition aLegendPos = css::chart::ChartLegendPosition_NONE;
     977             :         try
     978             :         {
     979          49 :             Any aAny( xProp->getPropertyValue(
     980          49 :                 OUString(  "Alignment" )));
     981          49 :                 aAny >>= aLegendPos;
     982             :         }
     983           0 :         catch( beans::UnknownPropertyException & )
     984             :         {
     985             :             SAL_WARN("oox", "Property Align not found in ChartLegend");
     986             :         }
     987             : 
     988          49 :         const char* strPos = NULL;
     989          49 :         switch( aLegendPos )
     990             :         {
     991             :             case css::chart::ChartLegendPosition_LEFT:
     992           1 :                 strPos = "l";
     993           1 :                 break;
     994             :             case css::chart::ChartLegendPosition_RIGHT:
     995          36 :                 strPos = "r";
     996          36 :                 break;
     997             :             case css::chart::ChartLegendPosition_TOP:
     998           1 :                 strPos = "t";
     999           1 :                 break;
    1000             :             case css::chart::ChartLegendPosition_BOTTOM:
    1001          10 :                 strPos = "b";
    1002          10 :                 break;
    1003             :             case css::chart::ChartLegendPosition_NONE:
    1004             :             case css::chart::ChartLegendPosition_MAKE_FIXED_SIZE:
    1005             :                 // nothing
    1006           1 :                 break;
    1007             :         }
    1008             : 
    1009          49 :         if( strPos != NULL )
    1010             :         {
    1011             :             pFS->singleElement( FSNS( XML_c, XML_legendPos ),
    1012             :                 XML_val, strPos,
    1013          48 :                 FSEND );
    1014             :         }
    1015             : 
    1016          49 :         uno::Any aRelativePos = xProp->getPropertyValue("RelativePosition");
    1017          49 :         if (aRelativePos.hasValue())
    1018             :         {
    1019           2 :             chart2::RelativePosition aPos = aRelativePos.get<chart2::RelativePosition>();
    1020           2 :             pFS->startElement(FSNS(XML_c, XML_layout), FSEND);
    1021           2 :             pFS->startElement(FSNS(XML_c, XML_manualLayout), FSEND);
    1022             : 
    1023             :             pFS->singleElement(FSNS(XML_c, XML_xMode),
    1024             :                     XML_val, "edge",
    1025           2 :                     FSEND);
    1026             :             pFS->singleElement(FSNS(XML_c, XML_yMode),
    1027             :                     XML_val, "edge",
    1028           2 :                     FSEND);
    1029             : 
    1030           2 :             double x = aPos.Primary;
    1031           2 :             double y = aPos.Secondary;
    1032             : 
    1033             :             pFS->singleElement(FSNS(XML_c, XML_x),
    1034             :                     XML_val, IS(x),
    1035           2 :                     FSEND);
    1036             :             pFS->singleElement(FSNS(XML_c, XML_y),
    1037             :                     XML_val, IS(y),
    1038           2 :                     FSEND);
    1039             :             SAL_WARN_IF(aPos.Anchor != 0, "oox.chart", "unsupported anchor position");
    1040             : 
    1041           2 :             pFS->endElement(FSNS(XML_c, XML_manualLayout));
    1042           2 :             pFS->endElement(FSNS(XML_c, XML_layout));
    1043             :         }
    1044             : 
    1045          49 :         if (strPos != NULL)
    1046             :         {
    1047             :             pFS->singleElement( FSNS( XML_c, XML_overlay ),
    1048             :                     XML_val, "0",
    1049          48 :                     FSEND );
    1050             :         }
    1051             : 
    1052             :         // shape properties
    1053          49 :         exportShapeProps( xProp );
    1054             :     }
    1055             : 
    1056             :     // legendEntry
    1057             : 
    1058          98 :     pFS->endElement( FSNS( XML_c, XML_legend ) );
    1059          49 : }
    1060             : 
    1061             : namespace {
    1062             : 
    1063             : /**
    1064             :  * nRotation is a 100th of a degree and the return value is
    1065             :  * in a 60,000th of a degree
    1066             :  *
    1067             :  * Also rotation is in opposite directions so multiply with -1
    1068             :  */
    1069          39 : OString calcRotationValue(sal_Int32 nRotation)
    1070             : {
    1071          39 :     if (nRotation > 18000) // 180 degree
    1072             :     {
    1073           1 :         nRotation -= 36000;
    1074             :     }
    1075          39 :     nRotation *= -600;
    1076          39 :     return OString::number(nRotation);
    1077             : }
    1078             : 
    1079             : }
    1080             : 
    1081          39 : void ChartExport::exportTitle( Reference< XShape > xShape )
    1082             : {
    1083          39 :     OUString sText;
    1084          78 :     Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
    1085          39 :     if( xPropSet.is())
    1086             :     {
    1087          39 :         xPropSet->getPropertyValue("String") >>= sText;
    1088             :     }
    1089          39 :     if( sText.isEmpty() )
    1090          39 :         return;
    1091             : 
    1092          78 :     FSHelperPtr pFS = GetFS();
    1093             :     pFS->startElement( FSNS( XML_c, XML_title ),
    1094          39 :             FSEND );
    1095             : 
    1096             :     pFS->startElement( FSNS( XML_c, XML_tx ),
    1097          39 :             FSEND );
    1098             :     pFS->startElement( FSNS( XML_c, XML_rich ),
    1099          39 :             FSEND );
    1100             : 
    1101             :     // TODO: bodyPr
    1102          39 :     const char* sWritingMode = NULL;
    1103          39 :     bool bVertical = false;
    1104          39 :     xPropSet->getPropertyValue("StackedText") >>= bVertical;
    1105          39 :     if( bVertical )
    1106           0 :         sWritingMode = "wordArtVert";
    1107             : 
    1108          39 :     sal_Int32 nRotation = 0;
    1109          39 :     xPropSet->getPropertyValue("TextRotation") >>= nRotation;
    1110             : 
    1111             :     pFS->singleElement( FSNS( XML_a, XML_bodyPr ),
    1112             :             XML_vert, sWritingMode,
    1113             :             XML_rot, calcRotationValue(nRotation).getStr(),
    1114          39 :             FSEND );
    1115             :     // TODO: lstStyle
    1116             :     pFS->singleElement( FSNS( XML_a, XML_lstStyle ),
    1117          39 :             FSEND );
    1118             :     // FIXME: handle multipul paragraphs to parse aText
    1119             :     pFS->startElement( FSNS( XML_a, XML_p ),
    1120          39 :             FSEND );
    1121             : 
    1122             :     pFS->startElement( FSNS( XML_a, XML_pPr ),
    1123          39 :             FSEND );
    1124             : 
    1125          39 :     WriteRunProperties(xPropSet, false, XML_defRPr);
    1126             : 
    1127          39 :     pFS->endElement( FSNS( XML_a, XML_pPr ) );
    1128             : 
    1129             :     pFS->startElement( FSNS( XML_a, XML_r ),
    1130          39 :             FSEND );
    1131          39 :     WriteRunProperties( xPropSet, false );
    1132             :     pFS->startElement( FSNS( XML_a, XML_t ),
    1133          39 :             FSEND );
    1134          39 :     pFS->writeEscaped( sText );
    1135          39 :     pFS->endElement( FSNS( XML_a, XML_t ) );
    1136          39 :     pFS->endElement( FSNS( XML_a, XML_r ) );
    1137             : 
    1138          39 :     pFS->endElement( FSNS( XML_a, XML_p ) );
    1139             : 
    1140          39 :     pFS->endElement( FSNS( XML_c, XML_rich ) );
    1141          39 :     pFS->endElement( FSNS( XML_c, XML_tx ) );
    1142             : 
    1143          78 :     uno::Any aManualLayout = xPropSet->getPropertyValue("RelativePosition");
    1144          39 :     if (aManualLayout.hasValue())
    1145             :     {
    1146           1 :         pFS->startElement(FSNS( XML_c, XML_layout ), FSEND);
    1147           1 :         pFS->startElement(FSNS(XML_c, XML_manualLayout), FSEND);
    1148             :         pFS->singleElement(FSNS(XML_c, XML_xMode),
    1149             :                 XML_val, "edge",
    1150           1 :                 FSEND);
    1151             :         pFS->singleElement(FSNS(XML_c, XML_yMode),
    1152             :                 XML_val, "edge",
    1153           1 :                 FSEND);
    1154             : 
    1155           1 :         Reference<embed::XVisualObject> xVisObject(mxChartModel, uno::UNO_QUERY);
    1156           1 :         awt::Size aPageSize = xVisObject->getVisualAreaSize(embed::Aspects::MSOLE_CONTENT);
    1157             : 
    1158             :         // awt::Size aSize = xShape->getSize();
    1159           1 :         awt::Point aPos2 = xShape->getPosition();
    1160           1 :         double x = (double)aPos2.X / (double) aPageSize.Width;
    1161           1 :         double y = (double)aPos2.Y / (double) aPageSize.Height;
    1162             :         /*
    1163             :         pFS->singleElement(FSNS(XML_c, XML_wMode),
    1164             :                 XML_val, "edge",
    1165             :                 FSEND);
    1166             :         pFS->singleElement(FSNS(XML_c, XML_hMode),
    1167             :                 XML_val, "edge",
    1168             :                 FSEND);
    1169             :                 */
    1170             :         pFS->singleElement(FSNS(XML_c, XML_x),
    1171             :                 XML_val, IS(x),
    1172           1 :                 FSEND);
    1173             :         pFS->singleElement(FSNS(XML_c, XML_y),
    1174             :                 XML_val, IS(y),
    1175           1 :                 FSEND);
    1176             :         /*
    1177             :         pFS->singleElement(FSNS(XML_c, XML_w),
    1178             :                 XML_val, "",
    1179             :                 FSEND);
    1180             :         pFS->singleElement(FSNS(XML_c, XML_h),
    1181             :                 XML_val, "",
    1182             :                 FSEND);
    1183             :                 */
    1184           1 :         pFS->endElement(FSNS(XML_c, XML_manualLayout));
    1185           1 :         pFS->endElement(FSNS(XML_c, XML_layout));
    1186             :     }
    1187             : 
    1188             :     pFS->singleElement( FSNS(XML_c, XML_overlay),
    1189             :             XML_val, "0",
    1190          39 :             FSEND);
    1191             : 
    1192          78 :     pFS->endElement( FSNS( XML_c, XML_title ) );
    1193             : }
    1194             : 
    1195          60 : void ChartExport::exportPlotArea( )
    1196             : {
    1197          60 :     Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( mxNewDiagram, uno::UNO_QUERY );
    1198          60 :     if( ! xBCooSysCnt.is())
    1199           0 :         return;
    1200             : 
    1201             :     // plot-area element
    1202             : 
    1203         120 :     FSHelperPtr pFS = GetFS();
    1204             :     pFS->startElement( FSNS( XML_c, XML_plotArea ),
    1205          60 :             FSEND );
    1206             : 
    1207         120 :     Reference<beans::XPropertySet> xWall(mxNewDiagram, uno::UNO_QUERY);
    1208          60 :     if( xWall.is() )
    1209             :     {
    1210          60 :         uno::Any aAny = xWall->getPropertyValue("RelativePosition");
    1211          60 :         if (aAny.hasValue())
    1212             :         {
    1213           1 :             chart2::RelativePosition aPos = aAny.get<chart2::RelativePosition>();
    1214           1 :             aAny = xWall->getPropertyValue("RelativeSize");
    1215           1 :             chart2::RelativeSize aSize = aAny.get<chart2::RelativeSize>();
    1216           1 :             exportManualLayout(aPos, aSize);
    1217          60 :         }
    1218             :     }
    1219             : 
    1220             :     // chart type
    1221             :     Sequence< Reference< chart2::XCoordinateSystem > >
    1222         120 :         aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
    1223         120 :     for( sal_Int32 nCSIdx=0; nCSIdx<aCooSysSeq.getLength(); ++nCSIdx )
    1224             :     {
    1225             : 
    1226          60 :         Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCSIdx], uno::UNO_QUERY );
    1227          60 :         if( ! xCTCnt.is())
    1228           0 :             continue;
    1229          60 :         mnSeriesCount=0;
    1230         120 :         Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
    1231         124 :         for( sal_Int32 nCTIdx=0; nCTIdx<aCTSeq.getLength(); ++nCTIdx )
    1232             :         {
    1233          64 :             Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nCTIdx], uno::UNO_QUERY );
    1234          64 :             if( ! xDSCnt.is())
    1235           0 :                 return;
    1236         128 :             Reference< chart2::XChartType > xChartType( aCTSeq[nCTIdx], uno::UNO_QUERY );
    1237          64 :             if( ! xChartType.is())
    1238           0 :                 continue;
    1239             :             // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
    1240         128 :             OUString aChartType( xChartType->getChartType());
    1241          64 :             sal_Int32 eChartType = lcl_getChartType( aChartType );
    1242          64 :             switch( eChartType )
    1243             :             {
    1244             :                 case chart::TYPEID_BAR:
    1245             :                     {
    1246          32 :                         exportBarChart( xChartType );
    1247          32 :                         break;
    1248             :                     }
    1249             :                 case chart::TYPEID_AREA:
    1250             :                     {
    1251           2 :                         exportAreaChart( xChartType );
    1252           2 :                         break;
    1253             :                     }
    1254             :                 case chart::TYPEID_LINE:
    1255             :                     {
    1256          11 :                         exportLineChart( xChartType );
    1257          11 :                         break;
    1258             :                     }
    1259             :                 case chart::TYPEID_BUBBLE:
    1260             :                     {
    1261           1 :                         exportBubbleChart( xChartType );
    1262           1 :                         break;
    1263             :                     }
    1264             :                 case chart::TYPEID_OFPIE:
    1265             :                     {
    1266           0 :                         break;
    1267             :                     }
    1268             :                 case chart::TYPEID_DOUGHNUT:
    1269             :                 case chart::TYPEID_PIE:
    1270             :                     {
    1271           7 :                         exportPieChart( xChartType );
    1272           7 :                         break;
    1273             :                     }
    1274             :                 case chart::TYPEID_RADARLINE:
    1275             :                 case chart::TYPEID_RADARAREA:
    1276             :                     {
    1277           1 :                         exportRadarChart( xChartType );
    1278           1 :                         break;
    1279             :                     }
    1280             :                 case chart::TYPEID_SCATTER:
    1281             :                     {
    1282           9 :                         exportScatterChart( xChartType );
    1283           9 :                         break;
    1284             :                     }
    1285             :                 case chart::TYPEID_STOCK:
    1286             :                     {
    1287           1 :                         exportStockChart( xChartType );
    1288           1 :                         break;
    1289             :                     }
    1290             :                 case chart::TYPEID_SURFACE:
    1291             :                     {
    1292           0 :                         exportSurfaceChart( xChartType );
    1293           0 :                         break;
    1294             :                     }
    1295             :                 default:
    1296             :                     {
    1297             :                         SAL_WARN("oox", "ChartExport::exportPlotArea -- not support chart type");
    1298           0 :                         break;
    1299             :                     }
    1300             :             }
    1301             : 
    1302          64 :         }
    1303          60 :     }
    1304             :     //Axis Data
    1305          60 :     exportAxes( );
    1306             :     // Data Table
    1307          60 :     exportDataTable();
    1308             : 
    1309             :     // shape properties
    1310             :     /*
    1311             :      * Export the Plot area Shape Properties
    1312             :      * eg: Fill and Outline
    1313             :      */
    1314          60 :     Reference< css::chart::X3DDisplay > xWallFloorSupplier( mxDiagram, uno::UNO_QUERY );
    1315          60 :     if( xWallFloorSupplier.is() )
    1316             :     {
    1317          60 :         Reference< beans::XPropertySet > xWallPropSet( xWallFloorSupplier->getWall(), uno::UNO_QUERY );
    1318          60 :         if( xWallPropSet.is() )
    1319             :         {
    1320          60 :             exportPlotAreaShapeProps( xWallPropSet );
    1321          60 :         }
    1322             :     }
    1323             : 
    1324         120 :     pFS->endElement( FSNS( XML_c, XML_plotArea ) );
    1325             : 
    1326             : }
    1327             : 
    1328           1 : void ChartExport::exportManualLayout(const css::chart2::RelativePosition& rPos, const css::chart2::RelativeSize& rSize)
    1329             : {
    1330           1 :     FSHelperPtr pFS = GetFS();
    1331           1 :     pFS->startElement(FSNS(XML_c, XML_layout), FSEND);
    1332           1 :     pFS->startElement(FSNS(XML_c, XML_manualLayout), FSEND);
    1333             :     pFS->singleElement(FSNS(XML_c, XML_layoutTarget),
    1334             :             XML_val, "inner",
    1335           1 :             FSEND);
    1336             :     pFS->singleElement(FSNS(XML_c, XML_xMode),
    1337             :             XML_val, "edge",
    1338           1 :             FSEND);
    1339             :     pFS->singleElement(FSNS(XML_c, XML_yMode),
    1340             :             XML_val, "edge",
    1341           1 :             FSEND);
    1342             : 
    1343           1 :     double x = rPos.Primary;
    1344           1 :     double y = rPos.Secondary;
    1345           1 :     double w = rSize.Primary;
    1346           1 :     double h = rSize.Secondary;
    1347           1 :     switch (rPos.Anchor)
    1348             :     {
    1349             :         case drawing::Alignment_LEFT:
    1350           0 :             y -= (h/2);
    1351           0 :         break;
    1352             :         case drawing::Alignment_TOP_LEFT:
    1353           1 :         break;
    1354             :         case drawing::Alignment_BOTTOM_LEFT:
    1355           0 :             y -= h;
    1356           0 :         break;
    1357             :         case drawing::Alignment_TOP:
    1358           0 :             x -= (w/2);
    1359           0 :         break;
    1360             :         case drawing::Alignment_CENTER:
    1361           0 :             x -= (w/2);
    1362           0 :             y -= (h/2);
    1363           0 :         break;
    1364             :         case drawing::Alignment_BOTTOM:
    1365           0 :             x -= (w/2);
    1366           0 :             y -= h;
    1367           0 :         break;
    1368             :         case drawing::Alignment_TOP_RIGHT:
    1369           0 :             x -= w;
    1370           0 :         break;
    1371             :         case drawing::Alignment_BOTTOM_RIGHT:
    1372           0 :             x -= w;
    1373           0 :             y -= h;
    1374           0 :         break;
    1375             :         case drawing::Alignment_RIGHT:
    1376           0 :             y -= (h/2);
    1377           0 :             x -= w;
    1378           0 :         break;
    1379             :         default:
    1380             :             SAL_WARN("oox.chart", "unhandled alignment case for manual layout export");
    1381             :     }
    1382             : 
    1383             :     pFS->singleElement(FSNS(XML_c, XML_x),
    1384             :             XML_val, IS(x),
    1385           1 :             FSEND);
    1386             : 
    1387             :     pFS->singleElement(FSNS(XML_c, XML_y),
    1388             :             XML_val, IS(y),
    1389           1 :             FSEND);
    1390             : 
    1391             :     pFS->singleElement(FSNS(XML_c, XML_w),
    1392             :             XML_val, IS(w),
    1393           1 :             FSEND);
    1394             : 
    1395             :     pFS->singleElement(FSNS(XML_c, XML_h),
    1396             :             XML_val, IS(h),
    1397           1 :             FSEND);
    1398             : 
    1399           1 :     pFS->endElement(FSNS(XML_c, XML_manualLayout));
    1400           1 :     pFS->endElement(FSNS(XML_c, XML_layout));
    1401           1 : }
    1402             : 
    1403          60 : void ChartExport::exportPlotAreaShapeProps( Reference< XPropertySet > xPropSet )
    1404             : {
    1405          60 :     FSHelperPtr pFS = GetFS();
    1406             :     pFS->startElement( FSNS( XML_c, XML_spPr ),
    1407          60 :             FSEND );
    1408             : 
    1409          60 :     exportFill( xPropSet );
    1410          60 :     WriteOutline( xPropSet );
    1411             : 
    1412          60 :     pFS->endElement( FSNS( XML_c, XML_spPr ) );
    1413          60 : }
    1414             : 
    1415          60 : void ChartExport::exportFill( Reference< XPropertySet > xPropSet )
    1416             : {
    1417          60 :     if ( !GetProperty( xPropSet, "FillStyle" ) )
    1418          60 :         return;
    1419          60 :     FillStyle aFillStyle( FillStyle_NONE );
    1420          60 :     xPropSet->getPropertyValue( "FillStyle" ) >>= aFillStyle;
    1421          60 :     switch( aFillStyle )
    1422             :     {
    1423             :         case FillStyle_GRADIENT :
    1424           0 :             exportGradientFill( xPropSet );
    1425           0 :             break;
    1426             :         case FillStyle_BITMAP :
    1427           1 :             exportBitmapFill( xPropSet );
    1428           1 :             break;
    1429             :         default:
    1430          59 :             WriteFill( xPropSet );
    1431             :     }
    1432             : }
    1433             : 
    1434           1 : void ChartExport::exportBitmapFill( Reference< XPropertySet > xPropSet )
    1435             : {
    1436           1 :     if( xPropSet.is() )
    1437             :      {
    1438           1 :         OUString sFillBitmapName;
    1439           1 :         xPropSet->getPropertyValue("FillBitmapName") >>= sFillBitmapName;
    1440             : 
    1441           2 :         uno::Reference< lang::XMultiServiceFactory > xFact( getModel(), uno::UNO_QUERY );
    1442             :         try
    1443             :         {
    1444           1 :             uno::Reference< container::XNameAccess > xBitmap( xFact->createInstance("com.sun.star.drawing.BitmapTable"), uno::UNO_QUERY );
    1445           2 :             uno::Any rValue = xBitmap->getByName( sFillBitmapName );
    1446           2 :             OUString sBitmapURL;
    1447           1 :             if( (rValue >>= sBitmapURL) )
    1448             :             {
    1449           1 :                 WriteBlipFill( xPropSet, sBitmapURL, XML_a, true, true );
    1450           1 :             }
    1451             :         }
    1452           0 :         catch (const uno::Exception & rEx)
    1453             :         {
    1454             :             SAL_INFO("oox", "ChartExport::exportBitmapFill " << rEx.Message);
    1455           1 :         }
    1456             : 
    1457             :     }
    1458           1 : }
    1459             : 
    1460           0 : void ChartExport::exportGradientFill( Reference< XPropertySet > xPropSet )
    1461             : {
    1462           0 :     if( xPropSet.is() )
    1463             :      {
    1464           0 :         OUString sFillGradientName;
    1465           0 :         xPropSet->getPropertyValue("FillGradientName") >>= sFillGradientName;
    1466             : 
    1467           0 :         awt::Gradient aGradient;
    1468           0 :         uno::Reference< lang::XMultiServiceFactory > xFact( getModel(), uno::UNO_QUERY );
    1469             :         try
    1470             :         {
    1471           0 :             uno::Reference< container::XNameAccess > xGradient( xFact->createInstance("com.sun.star.drawing.GradientTable"), uno::UNO_QUERY );
    1472           0 :             uno::Any rValue = xGradient->getByName( sFillGradientName );
    1473           0 :             if( (rValue >>= aGradient) )
    1474             :             {
    1475           0 :                 mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
    1476           0 :                 WriteGradientFill( aGradient );
    1477           0 :                 mpFS->endElementNS( XML_a, XML_gradFill );
    1478           0 :             }
    1479             :         }
    1480           0 :         catch (const uno::Exception & rEx)
    1481             :         {
    1482             :             SAL_INFO("oox",
    1483             :                 "ChartExport::exportGradientFill " << rEx.Message);
    1484           0 :         }
    1485             : 
    1486             :     }
    1487           0 : }
    1488             : 
    1489          60 : void ChartExport::exportDataTable( )
    1490             : {
    1491          60 :     FSHelperPtr pFS = GetFS();
    1492         120 :     Reference< beans::XPropertySet > aPropSet( mxDiagram, uno::UNO_QUERY );
    1493             : 
    1494          60 :     bool bShowVBorder = false;
    1495          60 :     bool bShowHBorder = false;
    1496          60 :     bool bShowOutline = false;
    1497             : 
    1498          60 :     if (GetProperty( aPropSet, "DataTableHBorder"))
    1499          60 :         mAny >>= bShowHBorder;
    1500          60 :     if (GetProperty( aPropSet, "DataTableVBorder"))
    1501          60 :         mAny >>= bShowVBorder;
    1502          60 :     if (GetProperty( aPropSet, "DataTableOutline"))
    1503          60 :         mAny >>= bShowOutline;
    1504             : 
    1505          60 :     if (bShowVBorder || bShowHBorder || bShowOutline)
    1506             :     {
    1507             :         pFS->startElement( FSNS( XML_c, XML_dTable),
    1508           6 :                 FSEND );
    1509           6 :         if (bShowHBorder)
    1510             :             pFS->singleElement( FSNS( XML_c, XML_showHorzBorder ),
    1511             :                             XML_val, "1",
    1512           6 :                             FSEND );
    1513           6 :         if (bShowVBorder)
    1514             :             pFS->singleElement( FSNS( XML_c, XML_showVertBorder ),
    1515             :                             XML_val, "1",
    1516           6 :                             FSEND );
    1517           6 :         if (bShowOutline)
    1518             :             pFS->singleElement( FSNS( XML_c, XML_showOutline ),
    1519             :                             XML_val, "1",
    1520           6 :                             FSEND );
    1521             : 
    1522           6 :         pFS->endElement(  FSNS( XML_c, XML_dTable));
    1523          60 :     }
    1524             : 
    1525          60 : }
    1526           2 : void ChartExport::exportAreaChart( Reference< chart2::XChartType > xChartType )
    1527             : {
    1528           2 :     FSHelperPtr pFS = GetFS();
    1529           2 :     sal_Int32 nTypeId = XML_areaChart;
    1530           2 :     if( mbIs3DChart )
    1531           0 :         nTypeId = XML_area3DChart;
    1532             :     pFS->startElement( FSNS( XML_c, nTypeId ),
    1533           2 :             FSEND );
    1534             : 
    1535           2 :     exportGrouping( );
    1536           2 :     sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
    1537           2 :     exportAllSeries( xChartType, nAttachedAxis );
    1538           2 :     exportAxesId( nAttachedAxis );
    1539             : 
    1540           2 :     pFS->endElement( FSNS( XML_c, nTypeId ) );
    1541           2 : }
    1542             : 
    1543          32 : void ChartExport::exportBarChart( Reference< chart2::XChartType > xChartType )
    1544             : {
    1545          32 :     sal_Int32 nTypeId = XML_barChart;
    1546          32 :     if( mbIs3DChart )
    1547          11 :         nTypeId = XML_bar3DChart;
    1548          32 :     FSHelperPtr pFS = GetFS();
    1549             :     pFS->startElement( FSNS( XML_c, nTypeId ),
    1550          32 :             FSEND );
    1551             :     // bar direction
    1552          32 :     bool bVertical = false;
    1553          64 :     Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
    1554          32 :     if( GetProperty( xPropSet, "Vertical" ) )
    1555          32 :         mAny >>= bVertical;
    1556             : 
    1557          32 :     const char* bardir = bVertical? "bar":"col";
    1558             :     pFS->singleElement( FSNS( XML_c, XML_barDir ),
    1559             :             XML_val, bardir,
    1560          32 :             FSEND );
    1561             : 
    1562          32 :     exportGrouping( true );
    1563             : 
    1564          32 :     const char* varyColors = "0";
    1565             :     pFS->singleElement( FSNS( XML_c, XML_varyColors ),
    1566             :             XML_val, varyColors,
    1567          32 :             FSEND );
    1568             : 
    1569          32 :     sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
    1570          32 :     exportAllSeries( xChartType, nAttachedAxis );
    1571             : 
    1572          64 :     Reference< XPropertySet > xTypeProp( xChartType, uno::UNO_QUERY );
    1573             : 
    1574          32 :     if( xTypeProp.is() && GetProperty( xTypeProp, "GapwidthSequence") )
    1575             :     {
    1576          32 :         uno::Sequence< sal_Int32 > aBarPositionSequence;
    1577          32 :         mAny >>= aBarPositionSequence;
    1578          32 :         if( aBarPositionSequence.getLength() )
    1579             :         {
    1580          32 :             sal_Int32 nGapWidth = aBarPositionSequence[0];
    1581             :             pFS->singleElement( FSNS( XML_c, XML_gapWidth ),
    1582             :                 XML_val, I32S( nGapWidth ),
    1583          32 :                 FSEND );
    1584          32 :         }
    1585             :     }
    1586             : 
    1587          32 :     if( mbIs3DChart )
    1588             :     {
    1589             :         // Shape
    1590             :         namespace cssc = css::chart;
    1591          11 :         sal_Int32 nGeom3d = cssc::ChartSolidType::RECTANGULAR_SOLID;
    1592          11 :         if( xPropSet.is() && GetProperty( xPropSet, "SolidType") )
    1593          11 :             mAny >>= nGeom3d;
    1594          11 :         const char* sShapeType = NULL;
    1595          11 :         switch( nGeom3d )
    1596             :         {
    1597             :             case cssc::ChartSolidType::RECTANGULAR_SOLID:
    1598           5 :                 sShapeType = "box";
    1599           5 :                 break;
    1600             :             case cssc::ChartSolidType::CONE:
    1601           4 :                 sShapeType = "cone";
    1602           4 :                 break;
    1603             :             case cssc::ChartSolidType::CYLINDER:
    1604           2 :                 sShapeType = "cylinder";
    1605           2 :                 break;
    1606             :             case cssc::ChartSolidType::PYRAMID:
    1607           0 :                 sShapeType = "pyramid";
    1608           0 :                 break;
    1609             :         }
    1610             :         pFS->singleElement( FSNS( XML_c, XML_shape ),
    1611             :             XML_val, sShapeType,
    1612          11 :             FSEND );
    1613             :     }
    1614             : 
    1615             :     //overlap
    1616          32 :     if( !mbIs3DChart && xTypeProp.is() && GetProperty( xTypeProp, "OverlapSequence") )
    1617             :     {
    1618          21 :         uno::Sequence< sal_Int32 > aBarPositionSequence;
    1619          21 :         mAny >>= aBarPositionSequence;
    1620          21 :         if( aBarPositionSequence.getLength() )
    1621             :         {
    1622          21 :             sal_Int32 nOverlap = aBarPositionSequence[0];
    1623             :             pFS->singleElement( FSNS( XML_c, XML_overlap ),
    1624             :                     XML_val, I32S( nOverlap ),
    1625          21 :                     FSEND );
    1626          21 :         }
    1627             :     }
    1628             : 
    1629          32 :     exportAxesId( nAttachedAxis );
    1630             : 
    1631          64 :     pFS->endElement( FSNS( XML_c, nTypeId ) );
    1632          32 : }
    1633             : 
    1634           1 : void ChartExport::exportBubbleChart( Reference< chart2::XChartType > xChartType )
    1635             : {
    1636           1 :     FSHelperPtr pFS = GetFS();
    1637             :     pFS->startElement( FSNS( XML_c, XML_bubbleChart ),
    1638           1 :             FSEND );
    1639             : 
    1640           1 :     const char* varyColors = "0";
    1641             :     pFS->singleElement( FSNS( XML_c, XML_varyColors ),
    1642             :             XML_val, varyColors,
    1643           1 :             FSEND );
    1644             : 
    1645           1 :     sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
    1646           1 :     exportAllSeries( xChartType, nAttachedAxis );
    1647             : 
    1648             :     pFS->singleElement(FSNS(XML_c, XML_bubble3D),
    1649             :             XML_val, "0",
    1650           1 :             FSEND);
    1651             : 
    1652           1 :     exportAxesId( nAttachedAxis );
    1653             : 
    1654           1 :     pFS->endElement( FSNS( XML_c, XML_bubbleChart ) );
    1655           1 : }
    1656             : 
    1657           2 : void ChartExport::exportDoughnutChart( Reference< chart2::XChartType > xChartType )
    1658             : {
    1659           2 :     FSHelperPtr pFS = GetFS();
    1660             :     pFS->startElement( FSNS( XML_c, XML_doughnutChart ),
    1661           2 :             FSEND );
    1662             : 
    1663           2 :     sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
    1664           2 :     exportAllSeries( xChartType, nAttachedAxis );
    1665             :     // firstSliceAng
    1666           2 :     exportFirstSliceAng( );
    1667             :     //FIXME: holeSize
    1668           2 :     sal_Int32 nHoleSize = 50;
    1669             :     pFS->singleElement( FSNS( XML_c, XML_holeSize ),
    1670             :             XML_val, I32S( nHoleSize ),
    1671           2 :             FSEND );
    1672             : 
    1673           2 :     pFS->endElement( FSNS( XML_c, XML_doughnutChart ) );
    1674           2 : }
    1675             : 
    1676             : namespace {
    1677             : 
    1678          20 : std::vector<Sequence<Reference<chart2::XDataSeries> > > splitDataSeriesByAxis(Reference< chart2::XChartType > xChartType)
    1679             : {
    1680          20 :     std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitSeries;
    1681          40 :     std::map<sal_Int32, size_t> aMapAxisToIndex;
    1682             : 
    1683          40 :     Reference< chart2::XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY );
    1684          20 :     if(xDSCnt.is())
    1685             :     {
    1686          20 :         Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
    1687          55 :         for (sal_Int32 nIndex = 0, nEnd = aSeriesSeq.getLength(); nIndex < nEnd; ++nIndex)
    1688             :         {
    1689          35 :             uno::Reference<chart2::XDataSeries> xSeries = aSeriesSeq[nIndex];
    1690          70 :             Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY);
    1691          35 :             if (!xPropSet.is())
    1692           0 :                 continue;
    1693             : 
    1694          35 :             sal_Int32 nAxisIndex = -1;
    1695          70 :             uno::Any aAny = xPropSet->getPropertyValue("AttachedAxisIndex");
    1696          35 :             aAny >>= nAxisIndex;
    1697          35 :             size_t nVectorPos = 0;
    1698             : 
    1699          35 :             auto it = aMapAxisToIndex.find(nAxisIndex);
    1700          35 :             if (it == aMapAxisToIndex.end())
    1701             :             {
    1702          21 :                 aSplitSeries.push_back(Sequence<Reference<chart2::XDataSeries> >());
    1703          21 :                 nVectorPos = aSplitSeries.size() - 1;
    1704          21 :                 aMapAxisToIndex.insert(std::pair<sal_Int32, size_t>(nAxisIndex, nVectorPos));
    1705             :             }
    1706             : 
    1707          35 :             uno::Sequence<Reference<chart2::XDataSeries> >& rAxisSeriesSeq = aSplitSeries[nVectorPos];
    1708          35 :             sal_Int32 nLength = rAxisSeriesSeq.getLength();
    1709          35 :             rAxisSeriesSeq.realloc(nLength + 1);
    1710          35 :             rAxisSeriesSeq[nLength] = xSeries;
    1711          55 :         }
    1712             :     }
    1713             : 
    1714          40 :     return aSplitSeries;
    1715             : }
    1716             : 
    1717             : }
    1718             : 
    1719          11 : void ChartExport::exportLineChart( Reference< chart2::XChartType > xChartType )
    1720             : {
    1721          11 :     FSHelperPtr pFS = GetFS();
    1722          22 :     std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
    1723          22 :     for (auto itr = aSplitDataSeries.begin(), itrEnd = aSplitDataSeries.end();
    1724             :             itr != itrEnd; ++itr)
    1725             :     {
    1726          11 :         if (itr->getLength() == 0)
    1727           0 :             continue;
    1728             : 
    1729          11 :         sal_Int32 nTypeId = XML_lineChart;
    1730          11 :         if( mbIs3DChart )
    1731           0 :             nTypeId = XML_line3DChart;
    1732             :         pFS->startElement( FSNS( XML_c, nTypeId ),
    1733          11 :                 FSEND );
    1734             : 
    1735          11 :         exportGrouping( );
    1736             :         // TODO: show marker symbol in series?
    1737          11 :         sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
    1738          11 :         exportSeries( xChartType, *itr, nAttachedAxis );
    1739             : 
    1740             :         // show marker?
    1741          11 :         sal_Int32 nSymbolType = css::chart::ChartSymbolType::NONE;
    1742          11 :         Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
    1743          11 :         if( GetProperty( xPropSet, "SymbolType" ) )
    1744          11 :             mAny >>= nSymbolType;
    1745             : 
    1746          11 :         if( !mbIs3DChart )
    1747             :         {
    1748          11 :             exportHiLowLines();
    1749          11 :             exportUpDownBars(xChartType);
    1750          11 :             const char* marker = nSymbolType == css::chart::ChartSymbolType::NONE? "0":"1";
    1751             :             pFS->singleElement( FSNS( XML_c, XML_marker ),
    1752             :                     XML_val, marker,
    1753          11 :                     FSEND );
    1754             :         }
    1755             : 
    1756          11 :         exportAxesId( nAttachedAxis );
    1757             : 
    1758          11 :         pFS->endElement( FSNS( XML_c, nTypeId ) );
    1759          22 :     }
    1760          11 : }
    1761             : 
    1762           7 : void ChartExport::exportPieChart( Reference< chart2::XChartType > xChartType )
    1763             : {
    1764           7 :     sal_Int32 eChartType = getChartType( );
    1765           7 :     if(eChartType == chart::TYPEID_DOUGHNUT)
    1766             :     {
    1767           2 :         exportDoughnutChart( xChartType );
    1768           9 :         return;
    1769             :     }
    1770           5 :     FSHelperPtr pFS = GetFS();
    1771           5 :     sal_Int32 nTypeId = XML_pieChart;
    1772           5 :     if( mbIs3DChart )
    1773           2 :         nTypeId = XML_pie3DChart;
    1774             :     pFS->startElement( FSNS( XML_c, nTypeId ),
    1775           5 :             FSEND );
    1776             :     // TODO: varyColors
    1777           5 :     const char* varyColors = "1";
    1778             :     pFS->singleElement( FSNS( XML_c, XML_varyColors ),
    1779             :             XML_val, varyColors,
    1780           5 :             FSEND );
    1781             : 
    1782           5 :     sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
    1783           5 :     exportAllSeries( xChartType, nAttachedAxis );
    1784             : 
    1785           5 :     if( !mbIs3DChart )
    1786             :     {
    1787             :         // firstSliceAng
    1788           3 :         exportFirstSliceAng( );
    1789             :     }
    1790             : 
    1791           5 :     pFS->endElement( FSNS( XML_c, nTypeId ) );
    1792             : }
    1793             : 
    1794           1 : void ChartExport::exportRadarChart( Reference< chart2::XChartType > xChartType)
    1795             : {
    1796           1 :     FSHelperPtr pFS = GetFS();
    1797             :     pFS->startElement( FSNS( XML_c, XML_radarChart ),
    1798           1 :             FSEND );
    1799             : 
    1800             :     // radarStyle
    1801           1 :     sal_Int32 eChartType = getChartType( );
    1802           1 :     const char* radarStyle = NULL;
    1803           1 :     if( eChartType == chart::TYPEID_RADARAREA )
    1804           1 :         radarStyle = "filled";
    1805             :     else
    1806           0 :         radarStyle = "marker";
    1807             :     pFS->singleElement( FSNS( XML_c, XML_radarStyle ),
    1808             :             XML_val, radarStyle,
    1809           1 :             FSEND );
    1810           1 :     sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
    1811           1 :     exportAllSeries( xChartType, nAttachedAxis );
    1812           1 :     exportAxesId( nAttachedAxis );
    1813             : 
    1814           1 :     pFS->endElement( FSNS( XML_c, XML_radarChart ) );
    1815           1 : }
    1816             : 
    1817           9 : void ChartExport::exportScatterChart( Reference< chart2::XChartType > xChartType )
    1818             : {
    1819           9 :     FSHelperPtr pFS = GetFS();
    1820          18 :     std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
    1821          19 :     for (auto itr = aSplitDataSeries.begin(), itrEnd = aSplitDataSeries.end();
    1822             :             itr != itrEnd; ++itr)
    1823             :     {
    1824          10 :         if (itr->getLength() == 0)
    1825           0 :             continue;
    1826             : 
    1827             :         pFS->startElement( FSNS( XML_c, XML_scatterChart ),
    1828          10 :                 FSEND );
    1829             :         // TODO:scatterStyle
    1830             : 
    1831          10 :         sal_Int32 nSymbolType = css::chart::ChartSymbolType::NONE;
    1832          10 :         Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
    1833          10 :         if( GetProperty( xPropSet, "SymbolType" ) )
    1834          10 :             mAny >>= nSymbolType;
    1835             : 
    1836          10 :         const char* scatterStyle = "lineMarker";
    1837          10 :         if (nSymbolType == css::chart::ChartSymbolType::NONE)
    1838             :         {
    1839           0 :             scatterStyle = "line";
    1840             :         }
    1841             : 
    1842             :         pFS->singleElement( FSNS( XML_c, XML_scatterStyle ),
    1843             :                 XML_val, scatterStyle,
    1844          10 :                 FSEND );
    1845             : 
    1846             :         pFS->singleElement( FSNS( XML_c, XML_varyColors ),
    1847             :                 XML_val, "0",
    1848          10 :                 FSEND );
    1849             : 
    1850             :         // FIXME: should export xVal and yVal
    1851          10 :         sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
    1852          10 :         exportSeries( xChartType, *itr, nAttachedAxis );
    1853          10 :         exportAxesId( nAttachedAxis );
    1854             : 
    1855          10 :         pFS->endElement( FSNS( XML_c, XML_scatterChart ) );
    1856          19 :     }
    1857           9 : }
    1858             : 
    1859           1 : void ChartExport::exportStockChart( Reference< chart2::XChartType > xChartType )
    1860             : {
    1861           1 :     FSHelperPtr pFS = GetFS();
    1862             :     pFS->startElement( FSNS( XML_c, XML_stockChart ),
    1863           1 :             FSEND );
    1864             : 
    1865           1 :     sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
    1866             : 
    1867           1 :     bool bJapaneseCandleSticks = false;
    1868           2 :     Reference< beans::XPropertySet > xCTProp( xChartType, uno::UNO_QUERY );
    1869           1 :     if( xCTProp.is())
    1870           1 :         xCTProp->getPropertyValue("Japanese") >>= bJapaneseCandleSticks;
    1871             : 
    1872           2 :     Reference< chart2::XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY );
    1873           1 :     if(xDSCnt.is())
    1874             :         exportCandleStickSeries(
    1875           1 :                 xDSCnt->getDataSeries(), bJapaneseCandleSticks, nAttachedAxis );
    1876             : 
    1877             :     // export stock properties
    1878           2 :     Reference< css::chart::XStatisticDisplay > xStockPropProvider( mxDiagram, uno::UNO_QUERY );
    1879           1 :     if( xStockPropProvider.is())
    1880             :     {
    1881           1 :         exportHiLowLines();
    1882           1 :         exportUpDownBars(xChartType);
    1883             :     }
    1884             : 
    1885           1 :     exportAxesId( nAttachedAxis );
    1886             : 
    1887           2 :     pFS->endElement( FSNS( XML_c, XML_stockChart ) );
    1888           1 : }
    1889             : 
    1890          12 : void ChartExport::exportHiLowLines()
    1891             : {
    1892          12 :     FSHelperPtr pFS = GetFS();
    1893             :     // export the chart property
    1894          24 :     Reference< css::chart::XStatisticDisplay > xChartPropProvider( mxDiagram, uno::UNO_QUERY );
    1895             : 
    1896          12 :     if (!xChartPropProvider.is())
    1897           0 :         return;
    1898             : 
    1899          24 :     Reference< beans::XPropertySet > xStockPropSet = xChartPropProvider->getMinMaxLine();
    1900          12 :     if( !xStockPropSet.is() )
    1901           0 :         return;
    1902             : 
    1903             :     pFS->startElement( FSNS( XML_c, XML_hiLowLines ),
    1904          12 :             FSEND );
    1905          12 :     exportShapeProps( xStockPropSet );
    1906          24 :     pFS->endElement( FSNS( XML_c, XML_hiLowLines ) );
    1907             : }
    1908             : 
    1909          12 : void ChartExport::exportUpDownBars( Reference< chart2::XChartType > xChartType)
    1910             : {
    1911          12 :     if(xChartType->getChartType() != "com.sun.star.chart2.CandleStickChartType")
    1912          23 :         return;
    1913             : 
    1914           1 :     FSHelperPtr pFS = GetFS();
    1915             :     // export the chart property
    1916           2 :     Reference< css::chart::XStatisticDisplay > xChartPropProvider( mxDiagram, uno::UNO_QUERY );
    1917           1 :     if(xChartPropProvider.is())
    1918             :     {
    1919             :         //  updownbar
    1920             :         pFS->startElement( FSNS( XML_c, XML_upDownBars ),
    1921           1 :                 FSEND );
    1922             :         // TODO: gapWidth
    1923           1 :         sal_Int32 nGapWidth = 150;
    1924             :         pFS->singleElement( FSNS( XML_c, XML_gapWidth ),
    1925             :                 XML_val, I32S( nGapWidth ),
    1926           1 :                     FSEND );
    1927             : 
    1928           1 :         Reference< beans::XPropertySet > xChartPropSet = xChartPropProvider->getUpBar();
    1929           1 :         if( xChartPropSet.is() )
    1930             :         {
    1931             :             pFS->startElement( FSNS( XML_c, XML_upBars ),
    1932           1 :                     FSEND );
    1933             :             // For Linechart with UpDownBars, spPr is not getting imported
    1934             :             // so no need to call the exportShapeProps() for LineChart
    1935           1 :             if(xChartType->getChartType() == "com.sun.star.chart2.CandleStickChartType")
    1936             :             {
    1937           1 :                 exportShapeProps(xChartPropSet);
    1938             :             }
    1939           1 :             pFS->endElement( FSNS( XML_c, XML_upBars ) );
    1940             :         }
    1941           1 :         xChartPropSet = xChartPropProvider->getDownBar();
    1942           1 :         if( xChartPropSet.is() )
    1943             :         {
    1944             :             pFS->startElement( FSNS( XML_c, XML_downBars ),
    1945           1 :                     FSEND );
    1946           1 :             if(xChartType->getChartType() == "com.sun.star.chart2.CandleStickChartType")
    1947             :             {
    1948           1 :                 exportShapeProps(xChartPropSet);
    1949             :             }
    1950           1 :             pFS->endElement( FSNS( XML_c, XML_downBars ) );
    1951             :         }
    1952           1 :         pFS->endElement( FSNS( XML_c, XML_upDownBars ) );
    1953           1 :     }
    1954             : }
    1955             : 
    1956           0 : void ChartExport::exportSurfaceChart( Reference< chart2::XChartType > xChartType )
    1957             : {
    1958           0 :     FSHelperPtr pFS = GetFS();
    1959           0 :     sal_Int32 nTypeId = XML_surfaceChart;
    1960           0 :     if( mbIs3DChart )
    1961           0 :         nTypeId = XML_surface3DChart;
    1962             :     pFS->startElement( FSNS( XML_c, nTypeId ),
    1963           0 :             FSEND );
    1964           0 :     sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
    1965           0 :     exportAllSeries( xChartType, nAttachedAxis );
    1966           0 :     exportAxesId( nAttachedAxis );
    1967             : 
    1968           0 :     pFS->endElement( FSNS( XML_c, nTypeId ) );
    1969           0 : }
    1970             : 
    1971          43 : void ChartExport::exportAllSeries(Reference<chart2::XChartType> xChartType, sal_Int32& rAttachedAxis)
    1972             : {
    1973          43 :     Reference< chart2::XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY );
    1974          43 :     if( ! xDSCnt.is())
    1975          43 :         return;
    1976             : 
    1977             :     // export dataseries for current chart-type
    1978          86 :     Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
    1979          86 :     exportSeries(xChartType, aSeriesSeq, rAttachedAxis);
    1980             : }
    1981             : 
    1982          64 : void ChartExport::exportSeries( Reference<chart2::XChartType> xChartType,
    1983             :         Sequence<Reference<chart2::XDataSeries> >& rSeriesSeq, sal_Int32& rAttachedAxis )
    1984             : {
    1985          64 :     OUString aLabelRole = xChartType->getRoleOfSequenceForSeriesLabel();
    1986         128 :     OUString aChartType( xChartType->getChartType());
    1987          64 :     sal_Int32 eChartType = lcl_getChartType( aChartType );
    1988             : 
    1989         185 :     for( sal_Int32 nSeriesIdx=0; nSeriesIdx<rSeriesSeq.getLength(); ++nSeriesIdx )
    1990             :     {
    1991             :         // export series
    1992         121 :         Reference< chart2::data::XDataSource > xSource( rSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
    1993         121 :         if( xSource.is())
    1994             :         {
    1995         121 :             Reference< chart2::XDataSeries > xDataSeries( xSource, uno::UNO_QUERY );
    1996             :             Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
    1997         242 :                 xSource->getDataSequences());
    1998             :             // search for main sequence and create a series element
    1999             :             {
    2000         121 :                 sal_Int32 nMainSequenceIndex = -1;
    2001         121 :                 sal_Int32 nSeriesLength = 0;
    2002         121 :                 Reference< chart2::data::XDataSequence > xValuesSeq;
    2003         242 :                 Reference< chart2::data::XDataSequence > xLabelSeq;
    2004         121 :                 sal_Int32 nSeqIdx=0;
    2005         257 :                 for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
    2006             :                 {
    2007         136 :                     OUString aRole;
    2008         272 :                     Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
    2009         136 :                     if( nMainSequenceIndex==-1 )
    2010             :                     {
    2011         132 :                         Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
    2012         132 :                         if( xSeqProp.is())
    2013         132 :                             xSeqProp->getPropertyValue("Role") >>= aRole;
    2014             :                         // "main" sequence
    2015         132 :                         if( aRole.equals( aLabelRole ))
    2016             :                         {
    2017         120 :                             xValuesSeq.set( xTempValueSeq );
    2018         120 :                             xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
    2019         120 :                             nMainSequenceIndex = nSeqIdx;
    2020         132 :                         }
    2021             :                     }
    2022         136 :                     sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
    2023         136 :                     if( nSeriesLength < nSequenceLength )
    2024         121 :                         nSeriesLength = nSequenceLength;
    2025         136 :                 }
    2026             : 
    2027             :                 // have found the main sequence, then xValuesSeq and
    2028             :                 // xLabelSeq contain those.  Otherwise both are empty
    2029             :                 {
    2030         121 :                     FSHelperPtr pFS = GetFS();
    2031             :                     pFS->startElement( FSNS( XML_c, XML_ser ),
    2032         121 :                         FSEND );
    2033             : 
    2034             :                     // TODO: idx and order
    2035             :                     pFS->singleElement( FSNS( XML_c, XML_idx ),
    2036             :                         XML_val, I32S(mnSeriesCount),
    2037         121 :                         FSEND );
    2038             :                     pFS->singleElement( FSNS( XML_c, XML_order ),
    2039             :                         XML_val, I32S(mnSeriesCount++),
    2040         121 :                         FSEND );
    2041             : 
    2042             :                     // export label
    2043         121 :                     if( xLabelSeq.is() )
    2044         117 :                         exportSeriesText( xLabelSeq );
    2045             : 
    2046         242 :                     Reference<XPropertySet> xPropSet(xDataSeries, UNO_QUERY_THROW);
    2047         121 :                     if( GetProperty( xPropSet, "AttachedAxisIndex") )
    2048             :                     {
    2049         121 :                         sal_Int32 nLocalAttachedAxis = 0;
    2050         121 :                         mAny >>= nLocalAttachedAxis;
    2051         121 :                         rAttachedAxis = translateFromChart2AxisIndexToOox(nLocalAttachedAxis);
    2052             :                     }
    2053             : 
    2054             :                     // export shape properties
    2055             :                     Reference< XPropertySet > xOldPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet(
    2056         242 :                         rSeriesSeq[nSeriesIdx], getModel() );
    2057         121 :                     if( xOldPropSet.is() )
    2058             :                     {
    2059         121 :                         exportShapeProps( xOldPropSet );
    2060             :                     }
    2061             : 
    2062         121 :                     switch( eChartType )
    2063             :                     {
    2064             :                         case chart::TYPEID_BUBBLE:
    2065             :                         case chart::TYPEID_HORBAR:
    2066             :                         case chart::TYPEID_BAR:
    2067             :                         {
    2068             :                             pFS->singleElement(FSNS(XML_c, XML_invertIfNegative),
    2069             :                                         XML_val, "0",
    2070          74 :                                         FSEND);
    2071             :                         }
    2072          74 :                         break;
    2073             :                         case chart::TYPEID_LINE:
    2074             :                         {
    2075          22 :                             exportMarker(xDataSeries);
    2076          22 :                             break;
    2077             :                         }
    2078             :                         case chart::TYPEID_PIE:
    2079             :                         case chart::TYPEID_DOUGHNUT:
    2080             :                         {
    2081           7 :                             if( xOldPropSet.is() && GetProperty( xOldPropSet, "SegmentOffset") )
    2082             :                             {
    2083           7 :                                 sal_Int32 nOffset = 0;
    2084           7 :                                 mAny >>= nOffset;
    2085             :                                 pFS->singleElement( FSNS( XML_c, XML_explosion ),
    2086             :                                     XML_val, I32S( nOffset ),
    2087           7 :                                     FSEND );
    2088             :                             }
    2089           7 :                             break;
    2090             :                         }
    2091             :                         case chart::TYPEID_SCATTER:
    2092             :                         {
    2093          13 :                             exportMarker(xDataSeries);
    2094          13 :                             break;
    2095             :                         }
    2096             :                         case chart::TYPEID_RADARLINE:
    2097             :                         {
    2098           0 :                             exportMarker(xDataSeries);
    2099           0 :                             break;
    2100             :                         }
    2101             :                     }
    2102             : 
    2103             :                     // export data points
    2104         121 :                     exportDataPoints( uno::Reference< beans::XPropertySet >( rSeriesSeq[nSeriesIdx], uno::UNO_QUERY ), nSeriesLength );
    2105             : 
    2106             :                     // export data labels
    2107         121 :                     exportDataLabels(rSeriesSeq[nSeriesIdx], nSeriesLength, eChartType);
    2108             : 
    2109         121 :                     exportTrendlines( rSeriesSeq[nSeriesIdx] );
    2110             : 
    2111         121 :                     if( eChartType != chart::TYPEID_PIE &&
    2112             :                             eChartType != chart::TYPEID_RADARLINE )
    2113             :                     {
    2114             :                         //export error bars here
    2115         114 :                         Reference< XPropertySet > xSeriesPropSet( xSource, uno::UNO_QUERY );
    2116         228 :                         Reference< XPropertySet > xErrorBarYProps;
    2117         114 :                         xSeriesPropSet->getPropertyValue("ErrorBarY") >>= xErrorBarYProps;
    2118         114 :                         if(xErrorBarYProps.is())
    2119           1 :                             exportErrorBar(xErrorBarYProps, true);
    2120         114 :                         if (eChartType != chart::TYPEID_BAR &&
    2121             :                                 eChartType != chart::TYPEID_HORBAR)
    2122             :                         {
    2123          43 :                             Reference< XPropertySet > xErrorBarXProps;
    2124          43 :                             xSeriesPropSet->getPropertyValue("ErrorBarX") >>= xErrorBarXProps;
    2125          43 :                             if(xErrorBarXProps.is())
    2126           0 :                                 exportErrorBar(xErrorBarXProps, false);
    2127         114 :                         }
    2128             :                     }
    2129             : 
    2130             :                     // export categories
    2131         121 :                     if( eChartType != chart::TYPEID_SCATTER && mxCategoriesValues.is() )
    2132          77 :                         exportSeriesCategory( mxCategoriesValues );
    2133             : 
    2134         121 :                     if( (eChartType == chart::TYPEID_SCATTER)
    2135         108 :                         || (eChartType == chart::TYPEID_BUBBLE) )
    2136             :                     {
    2137             :                         // export xVal
    2138          16 :                         Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString("values-x") ) );
    2139          16 :                         if( xSequence.is() )
    2140             :                         {
    2141          13 :                             Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
    2142          13 :                             if( xValues.is() )
    2143          13 :                                 exportSeriesValues( xValues, XML_xVal );
    2144          16 :                         }
    2145             :                     }
    2146             : 
    2147         121 :                     if( eChartType == chart::TYPEID_BUBBLE )
    2148             :                     {
    2149             :                         // export yVal
    2150           3 :                         Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString("values-y") ) );
    2151           3 :                         if( xSequence.is() )
    2152             :                         {
    2153           3 :                             Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
    2154           3 :                             if( xValues.is() )
    2155           3 :                                 exportSeriesValues( xValues, XML_yVal );
    2156           3 :                         }
    2157             :                     }
    2158             : 
    2159             :                     // export values
    2160         121 :                     if( xValuesSeq.is() )
    2161             :                     {
    2162         120 :                         sal_Int32 nYValueType = XML_val;
    2163         120 :                         if( eChartType == chart::TYPEID_SCATTER )
    2164          13 :                             nYValueType = XML_yVal;
    2165         107 :                         else if( eChartType == chart::TYPEID_BUBBLE )
    2166           2 :                             nYValueType = XML_bubbleSize;
    2167         120 :                         exportSeriesValues( xValuesSeq, nYValueType );
    2168             :                     }
    2169             : 
    2170         121 :                     if( eChartType == chart::TYPEID_SCATTER
    2171         108 :                             || eChartType == chart::TYPEID_LINE )
    2172          35 :                         exportSmooth();
    2173             : 
    2174         242 :                     pFS->endElement( FSNS( XML_c, XML_ser ) );
    2175         121 :                 }
    2176         121 :             }
    2177             :         }
    2178         185 :     }
    2179          64 : }
    2180             : 
    2181           1 : void ChartExport::exportCandleStickSeries(
    2182             :     const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq,
    2183             :     bool /*bJapaneseCandleSticks*/,
    2184             :     sal_Int32& rAttachedAxis )
    2185             : {
    2186           2 :     for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
    2187             :     {
    2188           1 :         Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx] );
    2189           1 :         rAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries ) ? AXIS_PRIMARY_Y : AXIS_SECONDARY_Y;
    2190             : 
    2191           2 :         Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
    2192           1 :         if( xSource.is())
    2193             :         {
    2194             :             // export series in correct order (as we don't store roles)
    2195             :             // with japanese candlesticks: open, low, high, close
    2196             :             // otherwise: low, high, close
    2197             :             Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
    2198           1 :                 xSource->getDataSequences());
    2199             : 
    2200           2 :             Reference< chart2::XChartDocument > xNewDoc( getModel(), uno::UNO_QUERY );
    2201           1 :             const char* sSeries[] = {"values-first","values-max","values-min","values-last",0};
    2202             : 
    2203           5 :             for( sal_Int32 idx = 0; sSeries[idx] != 0 ; idx++ )
    2204             :             {
    2205           4 :                 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( lcl_getDataSequenceByRole( aSeqCnt, OUString::createFromAscii(sSeries[idx]) ) );
    2206           4 :                 if( xLabeledSeq.is())
    2207             :                 {
    2208           4 :                     Reference< chart2::data::XDataSequence > xLabelSeq( xLabeledSeq->getLabel());
    2209           8 :                     Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues());
    2210             :                     {
    2211           4 :                         FSHelperPtr pFS = GetFS();
    2212             :                         pFS->startElement( FSNS( XML_c, XML_ser ),
    2213           4 :                                 FSEND );
    2214             : 
    2215             :                         // TODO: idx and order
    2216             :                         // idx attribute should start from 1 and not from 0.
    2217             :                         pFS->singleElement( FSNS( XML_c, XML_idx ),
    2218             :                                 XML_val, I32S(idx+1),
    2219           4 :                                 FSEND );
    2220             :                         pFS->singleElement( FSNS( XML_c, XML_order ),
    2221             :                                 XML_val, I32S(idx+1),
    2222           4 :                                 FSEND );
    2223             : 
    2224             :                         // export label
    2225           4 :                         if( xLabelSeq.is() )
    2226           4 :                             exportSeriesText( xLabelSeq );
    2227             : 
    2228             :                         // TODO:export shape properties
    2229             : 
    2230             :                         // export categories
    2231           4 :                         if( mxCategoriesValues.is() )
    2232           4 :                             exportSeriesCategory( mxCategoriesValues );
    2233             : 
    2234             :                         // export values
    2235           4 :                         if( xValueSeq.is() )
    2236           4 :                             exportSeriesValues( xValueSeq );
    2237             : 
    2238           4 :                         pFS->endElement( FSNS( XML_c, XML_ser ) );
    2239           4 :                     }
    2240             :                 }
    2241           5 :             }
    2242             :         }
    2243           1 :     }
    2244           1 : }
    2245             : 
    2246         121 : void ChartExport::exportSeriesText( const Reference< chart2::data::XDataSequence > & xValueSeq )
    2247             : {
    2248         121 :     FSHelperPtr pFS = GetFS();
    2249         242 :     Reference< chart2::XChartDocument > xNewDoc( getModel(), uno::UNO_QUERY );
    2250             :     pFS->startElement( FSNS( XML_c, XML_tx ),
    2251         121 :             FSEND );
    2252             : 
    2253         242 :     OUString aCellRange =  xValueSeq->getSourceRangeRepresentation();
    2254         121 :     aCellRange = parseFormula( aCellRange );
    2255             :     pFS->startElement( FSNS( XML_c, XML_strRef ),
    2256         121 :             FSEND );
    2257             : 
    2258             :     pFS->startElement( FSNS( XML_c, XML_f ),
    2259         121 :             FSEND );
    2260         121 :     pFS->writeEscaped( aCellRange );
    2261         121 :     pFS->endElement( FSNS( XML_c, XML_f ) );
    2262             : 
    2263         242 :     OUString aLabelString = lcl_getLabelString( xValueSeq );
    2264             :     pFS->startElement( FSNS( XML_c, XML_strCache ),
    2265         121 :             FSEND );
    2266             :     pFS->singleElement( FSNS( XML_c, XML_ptCount ),
    2267             :             XML_val, "1",
    2268         121 :             FSEND );
    2269             :     pFS->startElement( FSNS( XML_c, XML_pt ),
    2270             :             XML_idx, "0",
    2271         121 :             FSEND );
    2272             :     pFS->startElement( FSNS( XML_c, XML_v ),
    2273         121 :             FSEND );
    2274         121 :     pFS->writeEscaped( aLabelString );
    2275         121 :     pFS->endElement( FSNS( XML_c, XML_v ) );
    2276         121 :     pFS->endElement( FSNS( XML_c, XML_pt ) );
    2277         121 :     pFS->endElement( FSNS( XML_c, XML_strCache ) );
    2278         121 :     pFS->endElement( FSNS( XML_c, XML_strRef ) );
    2279         242 :     pFS->endElement( FSNS( XML_c, XML_tx ) );
    2280         121 : }
    2281             : 
    2282          81 : void ChartExport::exportSeriesCategory( const Reference< chart2::data::XDataSequence > & xValueSeq )
    2283             : {
    2284          81 :     FSHelperPtr pFS = GetFS();
    2285         162 :     Reference< chart2::XChartDocument > xNewDoc( getModel(), uno::UNO_QUERY );
    2286             :     pFS->startElement( FSNS( XML_c, XML_cat ),
    2287          81 :             FSEND );
    2288             : 
    2289         162 :     OUString aCellRange = xValueSeq.is() ? xValueSeq->getSourceRangeRepresentation() : OUString();
    2290          81 :     aCellRange = parseFormula( aCellRange );
    2291             :     // TODO: need to handle XML_multiLvlStrRef according to aCellRange
    2292             :     pFS->startElement( FSNS( XML_c, XML_strRef ),
    2293          81 :             FSEND );
    2294             : 
    2295             :     pFS->startElement( FSNS( XML_c, XML_f ),
    2296          81 :             FSEND );
    2297          81 :     pFS->writeEscaped( aCellRange );
    2298          81 :     pFS->endElement( FSNS( XML_c, XML_f ) );
    2299             : 
    2300         162 :     ::std::vector< OUString > aCategories;
    2301          81 :     lcl_fillCategoriesIntoStringVector( xValueSeq, aCategories );
    2302          81 :     sal_Int32 ptCount = aCategories.size();
    2303             :     pFS->startElement( FSNS( XML_c, XML_strCache ),
    2304          81 :             FSEND );
    2305             :     pFS->singleElement( FSNS( XML_c, XML_ptCount ),
    2306             :             XML_val, I32S( ptCount ),
    2307          81 :             FSEND );
    2308         481 :     for( sal_Int32 i = 0; i < ptCount; i++ )
    2309             :     {
    2310             :         pFS->startElement( FSNS( XML_c, XML_pt ),
    2311             :             XML_idx, I32S( i ),
    2312         400 :             FSEND );
    2313             :         pFS->startElement( FSNS( XML_c, XML_v ),
    2314         400 :             FSEND );
    2315         400 :         pFS->writeEscaped( aCategories[i] );
    2316         400 :         pFS->endElement( FSNS( XML_c, XML_v ) );
    2317         400 :         pFS->endElement( FSNS( XML_c, XML_pt ) );
    2318             :     }
    2319             : 
    2320          81 :     pFS->endElement( FSNS( XML_c, XML_strCache ) );
    2321          81 :     pFS->endElement( FSNS( XML_c, XML_strRef ) );
    2322         162 :     pFS->endElement( FSNS( XML_c, XML_cat ) );
    2323          81 : }
    2324             : 
    2325         140 : void ChartExport::exportSeriesValues( const Reference< chart2::data::XDataSequence > & xValueSeq, sal_Int32 nValueType )
    2326             : {
    2327         140 :     FSHelperPtr pFS = GetFS();
    2328         280 :     Reference< chart2::XChartDocument > xNewDoc( getModel(), uno::UNO_QUERY );
    2329             :     pFS->startElement( FSNS( XML_c, nValueType ),
    2330         140 :             FSEND );
    2331             : 
    2332         280 :     OUString aCellRange = xValueSeq.is() ? xValueSeq->getSourceRangeRepresentation() : OUString();
    2333         140 :     aCellRange = parseFormula( aCellRange );
    2334             :     // TODO: need to handle XML_multiLvlStrRef according to aCellRange
    2335             :     pFS->startElement( FSNS( XML_c, XML_numRef ),
    2336         140 :             FSEND );
    2337             : 
    2338             :     pFS->startElement( FSNS( XML_c, XML_f ),
    2339         140 :             FSEND );
    2340         140 :     pFS->writeEscaped( aCellRange );
    2341         140 :     pFS->endElement( FSNS( XML_c, XML_f ) );
    2342             : 
    2343         280 :     ::std::vector< double > aValues;
    2344         140 :     aValues = lcl_getAllValuesFromSequence( xValueSeq );
    2345         140 :     sal_Int32 ptCount = aValues.size();
    2346             :     pFS->startElement( FSNS( XML_c, XML_numCache ),
    2347         140 :             FSEND );
    2348             :     pFS->startElement( FSNS( XML_c, XML_formatCode ),
    2349         140 :             FSEND );
    2350             :     // TODO: what format code?
    2351         140 :     pFS->writeEscaped( "General" );
    2352         140 :     pFS->endElement( FSNS( XML_c, XML_formatCode ) );
    2353             :     pFS->singleElement( FSNS( XML_c, XML_ptCount ),
    2354             :             XML_val, I32S( ptCount ),
    2355         140 :             FSEND );
    2356             : 
    2357         140 :     bool bIsNumberValue = true;
    2358         140 :     bool bXSeriesValue = false;
    2359         140 :     double Value = 1.0;
    2360             : 
    2361         140 :     if(nValueType == XML_xVal)
    2362          13 :         bXSeriesValue = true;
    2363             : 
    2364         745 :     for( sal_Int32 i = 0; i < ptCount; i++ )
    2365             :     {
    2366             :         pFS->startElement( FSNS( XML_c, XML_pt ),
    2367             :             XML_idx, I32S( i ),
    2368         605 :             FSEND );
    2369             :         pFS->startElement( FSNS( XML_c, XML_v ),
    2370         605 :             FSEND );
    2371         605 :         if (bIsNumberValue && !rtl::math::isNan(aValues[i]))
    2372         587 :             pFS->write( aValues[i] );
    2373          18 :         else if(bXSeriesValue)
    2374             :         {
    2375             :             //In Case aValues is not a number for X Values...We write X values as 1,2,3....MS Word does the same thing.
    2376          10 :             pFS->write( Value );
    2377          10 :             Value = Value + 1;
    2378          10 :             bIsNumberValue = false;
    2379             :         }
    2380         605 :         pFS->endElement( FSNS( XML_c, XML_v ) );
    2381         605 :         pFS->endElement( FSNS( XML_c, XML_pt ) );
    2382             :     }
    2383             : 
    2384         140 :     pFS->endElement( FSNS( XML_c, XML_numCache ) );
    2385         140 :     pFS->endElement( FSNS( XML_c, XML_numRef ) );
    2386         280 :     pFS->endElement( FSNS( XML_c, nValueType ) );
    2387         140 : }
    2388             : 
    2389         489 : void ChartExport::exportShapeProps( Reference< XPropertySet > xPropSet )
    2390             : {
    2391         489 :     FSHelperPtr pFS = GetFS();
    2392             :     pFS->startElement( FSNS( XML_c, XML_spPr ),
    2393         489 :             FSEND );
    2394             : 
    2395         489 :     WriteFill( xPropSet );
    2396         489 :     WriteOutline( xPropSet );
    2397             : 
    2398         489 :     pFS->endElement( FSNS( XML_c, XML_spPr ) );
    2399         489 : }
    2400             : 
    2401         116 : void ChartExport::exportTextProps(Reference<XPropertySet> xPropSet)
    2402             : {
    2403         116 :     FSHelperPtr pFS = GetFS();
    2404         116 :     pFS->startElement(FSNS(XML_c, XML_txPr), FSEND);
    2405             : 
    2406         116 :     pFS->startElement(FSNS(XML_a, XML_bodyPr), FSEND);
    2407         116 :     pFS->endElement(FSNS(XML_a, XML_bodyPr));
    2408             : 
    2409         116 :     pFS->startElement(FSNS(XML_a, XML_p), FSEND);
    2410         116 :     pFS->startElement(FSNS(XML_a, XML_pPr), FSEND);
    2411             : 
    2412         116 :     WriteRunProperties(xPropSet, false, XML_defRPr);
    2413             : 
    2414         116 :     pFS->endElement(FSNS(XML_a, XML_pPr));
    2415         116 :     pFS->endElement(FSNS(XML_a, XML_p));
    2416             : 
    2417         116 :     pFS->endElement(FSNS(XML_c, XML_txPr));
    2418         116 : }
    2419             : 
    2420          60 : void ChartExport::InitPlotArea( )
    2421             : {
    2422          60 :     Reference< XPropertySet > xDiagramProperties (mxDiagram, uno::UNO_QUERY);
    2423             : 
    2424             :     //    Check for supported services and then the properties provided by this service.
    2425         120 :     Reference<lang::XServiceInfo> xServiceInfo (mxDiagram, uno::UNO_QUERY);
    2426          60 :     if (xServiceInfo.is())
    2427             :     {
    2428         180 :         if (xServiceInfo->supportsService(
    2429         120 :             OUString("com.sun.star.chart.ChartAxisZSupplier")))
    2430             :         {
    2431          60 :             xDiagramProperties->getPropertyValue(
    2432         120 :                 OUString("HasZAxis")) >>= mbHasZAxis;
    2433             :         }
    2434             :     }
    2435             : 
    2436          60 :     xDiagramProperties->getPropertyValue(
    2437         120 :         OUString ("Dim3D")) >>=  mbIs3DChart;
    2438             : 
    2439         120 :     Reference< chart2::XChartDocument > xNewDoc( getModel(), uno::UNO_QUERY );
    2440          60 :     if( mbHasCategoryLabels && mxNewDiagram.is())
    2441             :     {
    2442          37 :         Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( mxNewDiagram ) );
    2443          37 :         if( xCategories.is() )
    2444             :         {
    2445          37 :             mxCategoriesValues.set( xCategories->getValues() );
    2446          37 :         }
    2447          60 :     }
    2448          60 : }
    2449             : 
    2450          60 : void ChartExport::exportAxes( )
    2451             : {
    2452          60 :     sal_Int32 nSize = maAxes.size();
    2453         176 :     for( sal_Int32 nIdx = 0; nIdx < nSize; nIdx++ )
    2454             :     {
    2455         116 :         exportAxis( maAxes[nIdx] );
    2456             :     }
    2457          60 : }
    2458             : 
    2459         116 : void ChartExport::exportAxis(const AxisIdPair& rAxisIdPair)
    2460             : {
    2461             :     // get some properties from document first
    2462         116 :     bool bHasXAxisTitle = false,
    2463         116 :         bHasYAxisTitle = false,
    2464         116 :         bHasZAxisTitle = false,
    2465         116 :         bHasSecondaryXAxisTitle = false,
    2466         116 :         bHasSecondaryYAxisTitle = false;
    2467         116 :     bool bHasXAxisMajorGrid = false,
    2468         116 :         bHasXAxisMinorGrid = false,
    2469         116 :         bHasYAxisMajorGrid = false,
    2470         116 :         bHasYAxisMinorGrid = false,
    2471         116 :         bHasZAxisMajorGrid = false,
    2472         116 :         bHasZAxisMinorGrid = false;
    2473             : 
    2474         116 :        Reference< XPropertySet > xDiagramProperties (mxDiagram, uno::UNO_QUERY);
    2475             : 
    2476         116 :     xDiagramProperties->getPropertyValue(
    2477         116 :         OUString ("HasXAxisTitle")) >>= bHasXAxisTitle;
    2478         116 :     xDiagramProperties->getPropertyValue(
    2479         116 :         OUString ("HasYAxisTitle")) >>= bHasYAxisTitle;
    2480         116 :     xDiagramProperties->getPropertyValue(
    2481         116 :         OUString ("HasZAxisTitle")) >>= bHasZAxisTitle;
    2482         116 :     xDiagramProperties->getPropertyValue(
    2483         116 :         OUString ("HasSecondaryXAxisTitle")) >>=  bHasSecondaryXAxisTitle;
    2484         116 :     xDiagramProperties->getPropertyValue(
    2485         116 :         OUString ("HasSecondaryYAxisTitle")) >>=  bHasSecondaryYAxisTitle;
    2486             : 
    2487         116 :     xDiagramProperties->getPropertyValue(
    2488         116 :         OUString ("HasXAxisGrid")) >>=  bHasXAxisMajorGrid;
    2489         116 :     xDiagramProperties->getPropertyValue(
    2490         116 :         OUString ("HasYAxisGrid")) >>=  bHasYAxisMajorGrid;
    2491         116 :     xDiagramProperties->getPropertyValue(
    2492         116 :         OUString ("HasZAxisGrid")) >>=  bHasZAxisMajorGrid;
    2493             : 
    2494         116 :     xDiagramProperties->getPropertyValue(
    2495         116 :         OUString ("HasXAxisHelpGrid")) >>=  bHasXAxisMinorGrid;
    2496         116 :     xDiagramProperties->getPropertyValue(
    2497         116 :         OUString ("HasYAxisHelpGrid")) >>=  bHasYAxisMinorGrid;
    2498         116 :     xDiagramProperties->getPropertyValue(
    2499         116 :         OUString ("HasZAxisHelpGrid")) >>=  bHasZAxisMinorGrid;
    2500             : 
    2501         232 :     Reference< XPropertySet > xAxisProp;
    2502         232 :     Reference< drawing::XShape > xAxisTitle;
    2503         232 :     Reference< beans::XPropertySet > xMajorGrid;
    2504         232 :     Reference< beans::XPropertySet > xMinorGrid;
    2505         116 :     sal_Int32 nAxisType = XML_catAx;
    2506         116 :     const char* sAxPos = NULL;
    2507             : 
    2508         116 :     switch( rAxisIdPair.nAxisType )
    2509             :     {
    2510             :         case AXIS_PRIMARY_X:
    2511             :         {
    2512          58 :             Reference< css::chart::XAxisXSupplier > xAxisXSupp( mxDiagram, uno::UNO_QUERY );
    2513          58 :             if( xAxisXSupp.is())
    2514          58 :                 xAxisProp = xAxisXSupp->getXAxis();
    2515          58 :             if( bHasXAxisTitle )
    2516           5 :                 xAxisTitle.set( xAxisXSupp->getXAxisTitle(), uno::UNO_QUERY );
    2517          58 :             if( bHasXAxisMajorGrid )
    2518           7 :                 xMajorGrid.set( xAxisXSupp->getXMainGrid(), uno::UNO_QUERY );
    2519          58 :             if( bHasXAxisMinorGrid )
    2520           0 :                 xMinorGrid.set( xAxisXSupp->getXHelpGrid(), uno::UNO_QUERY );
    2521             : 
    2522          58 :             sal_Int32 eChartType = getChartType( );
    2523          58 :             if( (eChartType == chart::TYPEID_SCATTER)
    2524          48 :                 || (eChartType == chart::TYPEID_BUBBLE) )
    2525          11 :                 nAxisType = XML_valAx;
    2526          47 :             else if( eChartType == chart::TYPEID_STOCK )
    2527           2 :                 nAxisType = XML_dateAx;
    2528             :             // FIXME: axPos, need to check axis direction
    2529          58 :             sAxPos = "b";
    2530          58 :             break;
    2531             :         }
    2532             :         case AXIS_PRIMARY_Y:
    2533             :         {
    2534          54 :             Reference< css::chart::XAxisYSupplier > xAxisYSupp( mxDiagram, uno::UNO_QUERY );
    2535          54 :             if( xAxisYSupp.is())
    2536          54 :                 xAxisProp = xAxisYSupp->getYAxis();
    2537          54 :             if( bHasYAxisTitle )
    2538           7 :                 xAxisTitle.set( xAxisYSupp->getYAxisTitle(), uno::UNO_QUERY );
    2539          54 :             if( bHasYAxisMajorGrid )
    2540          52 :                 xMajorGrid.set( xAxisYSupp->getYMainGrid(), uno::UNO_QUERY );
    2541          54 :             if( bHasYAxisMinorGrid )
    2542           5 :                 xMinorGrid.set( xAxisYSupp->getYHelpGrid(), uno::UNO_QUERY );
    2543             : 
    2544          54 :             nAxisType = XML_valAx;
    2545             :             // FIXME: axPos, need to check axis direction
    2546          54 :             sAxPos = "l";
    2547          54 :             break;
    2548             :         }
    2549             :         case AXIS_PRIMARY_Z:
    2550             :         {
    2551           0 :             Reference< css::chart::XAxisZSupplier > xAxisZSupp( mxDiagram, uno::UNO_QUERY );
    2552           0 :             if( xAxisZSupp.is())
    2553           0 :                 xAxisProp = xAxisZSupp->getZAxis();
    2554           0 :             if( bHasZAxisTitle )
    2555           0 :                 xAxisTitle.set( xAxisZSupp->getZAxisTitle(), uno::UNO_QUERY );
    2556           0 :             if( bHasZAxisMajorGrid )
    2557           0 :                 xMajorGrid.set( xAxisZSupp->getZMainGrid(), uno::UNO_QUERY );
    2558           0 :             if( bHasZAxisMinorGrid )
    2559           0 :                 xMinorGrid.set( xAxisZSupp->getZHelpGrid(), uno::UNO_QUERY );
    2560             : 
    2561           0 :             sal_Int32 eChartType = getChartType( );
    2562           0 :             if( (eChartType == chart::TYPEID_SCATTER)
    2563           0 :                 || (eChartType == chart::TYPEID_BUBBLE) )
    2564           0 :                 nAxisType = XML_valAx;
    2565           0 :             else if( eChartType == chart::TYPEID_STOCK )
    2566           0 :                 nAxisType = XML_dateAx;
    2567             :             // FIXME: axPos, need to check axis direction
    2568           0 :             sAxPos = "b";
    2569           0 :             break;
    2570             :         }
    2571             :         case AXIS_SECONDARY_Y:
    2572             :         {
    2573           4 :             Reference< css::chart::XTwoAxisYSupplier > xAxisTwoYSupp( mxDiagram, uno::UNO_QUERY );
    2574           4 :             if( xAxisTwoYSupp.is())
    2575           4 :                 xAxisProp = xAxisTwoYSupp->getSecondaryYAxis();
    2576           4 :             if( bHasSecondaryYAxisTitle )
    2577             :             {
    2578           0 :                 Reference< css::chart::XSecondAxisTitleSupplier > xAxisSupp( mxDiagram, uno::UNO_QUERY );
    2579           0 :                 xAxisTitle.set( xAxisSupp->getSecondYAxisTitle(), uno::UNO_QUERY );
    2580             :             }
    2581             : 
    2582           4 :             nAxisType = XML_valAx;
    2583             :             // FIXME: axPos, need to check axis direction
    2584           4 :             sAxPos = "r";
    2585           4 :             break;
    2586             :         }
    2587             :     }
    2588             : 
    2589         232 :     _exportAxis(xAxisProp, xAxisTitle, xMajorGrid, xMinorGrid, nAxisType, sAxPos, rAxisIdPair);
    2590         116 : }
    2591             : 
    2592         116 : void ChartExport::_exportAxis(
    2593             :     const Reference< XPropertySet >& xAxisProp,
    2594             :     const Reference< drawing::XShape >& xAxisTitle,
    2595             :     const Reference< XPropertySet >& xMajorGrid,
    2596             :     const Reference< XPropertySet >& xMinorGrid,
    2597             :     sal_Int32 nAxisType,
    2598             :     const char* sAxisPos,
    2599             :     const AxisIdPair& rAxisIdPair )
    2600             : {
    2601         116 :     FSHelperPtr pFS = GetFS();
    2602             :     pFS->startElement( FSNS( XML_c, nAxisType ),
    2603         116 :             FSEND );
    2604             :     pFS->singleElement( FSNS( XML_c, XML_axId ),
    2605             :             XML_val, I32S( rAxisIdPair.nAxisId ),
    2606         116 :             FSEND );
    2607             : 
    2608             :     pFS->startElement( FSNS( XML_c, XML_scaling ),
    2609         116 :             FSEND );
    2610             : 
    2611             :     // logBase, min, max
    2612         116 :     if(GetProperty( xAxisProp, "Logarithmic" ) )
    2613             :     {
    2614         116 :         bool bLogarithmic = false;
    2615         116 :         mAny >>= bLogarithmic;
    2616         116 :         if( bLogarithmic )
    2617             :         {
    2618             :             // default value is 10?
    2619           1 :             sal_Int32 nLogBase = 10;
    2620             :             pFS->singleElement( FSNS( XML_c, XML_logBase ),
    2621             :                 XML_val, I32S( nLogBase ),
    2622           1 :                 FSEND );
    2623             :         }
    2624             :     }
    2625             : 
    2626             :     // orientation: minMax, maxMin
    2627         116 :     bool bReverseDirection = false;
    2628         116 :     if(GetProperty( xAxisProp, "ReverseDirection" ) )
    2629         116 :         mAny >>= bReverseDirection;
    2630             : 
    2631         116 :     const char* orientation = bReverseDirection ? "maxMin":"minMax";
    2632             :     pFS->singleElement( FSNS( XML_c, XML_orientation ),
    2633             :             XML_val, orientation,
    2634         116 :             FSEND );
    2635             : 
    2636         116 :     bool bAutoMax = false;
    2637         116 :     if(GetProperty( xAxisProp, "AutoMax" ) )
    2638         116 :         mAny >>= bAutoMax;
    2639             : 
    2640         116 :     if( !bAutoMax && (GetProperty( xAxisProp, "Max" ) ) )
    2641             :     {
    2642           1 :         double dMax = 0;
    2643           1 :         mAny >>= dMax;
    2644             :         pFS->singleElement( FSNS( XML_c, XML_max ),
    2645             :             XML_val, IS( dMax ),
    2646           1 :             FSEND );
    2647             :     }
    2648             : 
    2649         116 :     bool bAutoMin = false;
    2650         116 :     if(GetProperty( xAxisProp, "AutoMin" ) )
    2651         116 :         mAny >>= bAutoMin;
    2652             : 
    2653         116 :     if( !bAutoMin && (GetProperty( xAxisProp, "Min" ) ) )
    2654             :     {
    2655           2 :         double dMin = 0;
    2656           2 :         mAny >>= dMin;
    2657             :         pFS->singleElement( FSNS( XML_c, XML_min ),
    2658             :             XML_val, IS( dMin ),
    2659           2 :             FSEND );
    2660             :     }
    2661             : 
    2662         116 :     pFS->endElement( FSNS( XML_c, XML_scaling ) );
    2663             : 
    2664         116 :     bool bVisible = true;
    2665         116 :     if( xAxisProp.is() )
    2666             :     {
    2667         116 :         xAxisProp->getPropertyValue(
    2668         116 :             OUString ("Visible")) >>=  bVisible;
    2669             :     }
    2670             : 
    2671             :     // only export each axis only once non-deleted
    2672             :     bool bDeleted = std::find(maExportedAxis.begin(),
    2673         116 :             maExportedAxis.end(), rAxisIdPair.nAxisType) != maExportedAxis.end();
    2674             : 
    2675         116 :     if (!bDeleted)
    2676         110 :         maExportedAxis.insert(rAxisIdPair.nAxisType);
    2677             : 
    2678             :     pFS->singleElement( FSNS( XML_c, XML_delete ),
    2679         226 :             XML_val, !bDeleted && bVisible ? "0" : "1",
    2680         225 :             FSEND );
    2681             : 
    2682             :     // FIXME: axPos, need to check the property "ReverseDirection"
    2683             :     pFS->singleElement( FSNS( XML_c, XML_axPos ),
    2684             :             XML_val, sAxisPos,
    2685         116 :             FSEND );
    2686             :     // major grid line
    2687         116 :     if( xMajorGrid.is())
    2688             :     {
    2689             :         pFS->startElement( FSNS( XML_c, XML_majorGridlines ),
    2690          59 :             FSEND );
    2691          59 :         exportShapeProps( xMajorGrid );
    2692          59 :         pFS->endElement( FSNS( XML_c, XML_majorGridlines ) );
    2693             :     }
    2694             : 
    2695             :     // minor grid line
    2696         116 :     if( xMinorGrid.is())
    2697             :     {
    2698             :         pFS->startElement( FSNS( XML_c, XML_minorGridlines ),
    2699           5 :             FSEND );
    2700           5 :         exportShapeProps( xMinorGrid );
    2701           5 :         pFS->endElement( FSNS( XML_c, XML_minorGridlines ) );
    2702             :     }
    2703             : 
    2704             :     // title
    2705         116 :     if( xAxisTitle.is() )
    2706          12 :         exportTitle( xAxisTitle );
    2707             : 
    2708         116 :     bool bLinkedNumFmt = true;
    2709         116 :     if (GetProperty(xAxisProp, "LinkNumberFormatToSource"))
    2710         116 :         mAny >>= bLinkedNumFmt;
    2711             : 
    2712         232 :     OUString aNumberFormatString("General");
    2713         116 :     if (GetProperty(xAxisProp, "NumberFormat"))
    2714             :     {
    2715         116 :         sal_Int32 nKey = 0;
    2716         116 :         mAny >>= nKey;
    2717         116 :         aNumberFormatString = getNumberFormatCode(nKey);
    2718             :     }
    2719             : 
    2720         232 :     OString sNumberFormatString = OUStringToOString(aNumberFormatString, RTL_TEXTENCODING_UTF8);
    2721             :     pFS->singleElement(FSNS(XML_c, XML_numFmt),
    2722             :             XML_formatCode, sNumberFormatString.getStr(),
    2723             :             XML_sourceLinked, bLinkedNumFmt ? "1" : "0",
    2724         116 :             FSEND);
    2725             : 
    2726             :     // majorTickMark
    2727         116 :     sal_Int32 nValue = 0;
    2728         116 :     if(GetProperty( xAxisProp, "Marks" ) )
    2729             :     {
    2730         116 :         mAny >>= nValue;
    2731         116 :         bool bInner = nValue & css::chart::ChartAxisMarks::INNER;
    2732         116 :         bool bOuter = nValue & css::chart::ChartAxisMarks::OUTER;
    2733         116 :         const char* majorTickMark = NULL;
    2734         116 :         if( bInner && bOuter )
    2735           1 :             majorTickMark = "cross";
    2736         115 :         else if( bInner )
    2737           0 :             majorTickMark = "in";
    2738         115 :         else if( bOuter )
    2739          73 :             majorTickMark = "out";
    2740             :         else
    2741          42 :             majorTickMark = "none";
    2742             :         pFS->singleElement( FSNS( XML_c, XML_majorTickMark ),
    2743             :             XML_val, majorTickMark,
    2744         116 :             FSEND );
    2745             :     }
    2746             :     // minorTickMark
    2747         116 :     if(GetProperty( xAxisProp, "HelpMarks" ) )
    2748             :     {
    2749         116 :         mAny >>= nValue;
    2750         116 :         bool bInner = nValue & css::chart::ChartAxisMarks::INNER;
    2751         116 :         bool bOuter = nValue & css::chart::ChartAxisMarks::OUTER;
    2752         116 :         const char* minorTickMark = NULL;
    2753         116 :         if( bInner && bOuter )
    2754           0 :             minorTickMark = "cross";
    2755         116 :         else if( bInner )
    2756           0 :             minorTickMark = "in";
    2757         116 :         else if( bOuter )
    2758           0 :             minorTickMark = "out";
    2759             :         else
    2760         116 :             minorTickMark = "none";
    2761             :         pFS->singleElement( FSNS( XML_c, XML_minorTickMark ),
    2762             :             XML_val, minorTickMark,
    2763         116 :             FSEND );
    2764             :     }
    2765             :     // tickLblPos
    2766         116 :     const char* sTickLblPos = NULL;
    2767         116 :     bool bDisplayLabel = true;
    2768         116 :     if(GetProperty( xAxisProp, "DisplayLabels" ) )
    2769         116 :         mAny >>= bDisplayLabel;
    2770         116 :     if( bDisplayLabel && (GetProperty( xAxisProp, "LabelPosition" ) ) )
    2771             :     {
    2772         115 :         css::chart::ChartAxisLabelPosition eLabelPosition = css::chart::ChartAxisLabelPosition_NEAR_AXIS;
    2773         115 :         mAny >>= eLabelPosition;
    2774         115 :         switch( eLabelPosition )
    2775             :         {
    2776             :             case css::chart::ChartAxisLabelPosition_NEAR_AXIS:
    2777             :             case css::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE:
    2778         115 :                 sTickLblPos = "nextTo";
    2779         115 :                 break;
    2780             :             case css::chart::ChartAxisLabelPosition_OUTSIDE_START:
    2781           0 :                 sTickLblPos = "low";
    2782           0 :                 break;
    2783             :             case css::chart::ChartAxisLabelPosition_OUTSIDE_END:
    2784           0 :                 sTickLblPos = "high";
    2785           0 :                 break;
    2786             :             default:
    2787           0 :                 sTickLblPos = "nextTo";
    2788           0 :                 break;
    2789             :         }
    2790             :     }
    2791             :     else
    2792             :     {
    2793           1 :         sTickLblPos = "none";
    2794             :     }
    2795             :     pFS->singleElement( FSNS( XML_c, XML_tickLblPos ),
    2796             :             XML_val, sTickLblPos,
    2797         116 :             FSEND );
    2798             : 
    2799             :     // shape properties
    2800         116 :     exportShapeProps( xAxisProp );
    2801             : 
    2802         116 :     exportTextProps(xAxisProp);
    2803             : 
    2804             :     pFS->singleElement( FSNS( XML_c, XML_crossAx ),
    2805             :             XML_val, I32S( rAxisIdPair.nCrossAx ),
    2806         116 :             FSEND );
    2807             : 
    2808             :     // crosses & crossesAt
    2809         116 :     bool bCrossesValue = false;
    2810         116 :     const char* sCrosses = NULL;
    2811         116 :     if(GetProperty( xAxisProp, "CrossoverPosition" ) )
    2812             :     {
    2813         116 :         css::chart::ChartAxisPosition ePosition( css::chart::ChartAxisPosition_ZERO );
    2814         116 :         mAny >>= ePosition;
    2815         116 :         switch( ePosition )
    2816             :         {
    2817             :             case css::chart::ChartAxisPosition_START:
    2818           0 :                 sCrosses = "min";
    2819           0 :                 break;
    2820             :             case css::chart::ChartAxisPosition_END:
    2821           4 :                 sCrosses = "max";
    2822           4 :                 break;
    2823             :             case css::chart::ChartAxisPosition_ZERO:
    2824         112 :                 sCrosses = "autoZero";
    2825         112 :                 break;
    2826             :             default:
    2827           0 :                 bCrossesValue = true;
    2828           0 :                 break;
    2829             :         }
    2830             :     }
    2831             : 
    2832         116 :     if( bCrossesValue && GetProperty( xAxisProp, "CrossoverValue" ) )
    2833             :     {
    2834           0 :         double dValue = 0;
    2835           0 :         mAny >>= dValue;
    2836             :         pFS->singleElement( FSNS( XML_c, XML_crossesAt ),
    2837             :             XML_val, IS( dValue ),
    2838           0 :             FSEND );
    2839             :     }
    2840             :     else
    2841             :     {
    2842             :         pFS->singleElement( FSNS( XML_c, XML_crosses ),
    2843             :             XML_val, sCrosses,
    2844         116 :             FSEND );
    2845             :     }
    2846             : 
    2847         116 :     if( ( nAxisType == XML_catAx )
    2848          71 :         || ( nAxisType == XML_dateAx ) )
    2849             :     {
    2850             :         // FIXME: seems not support? use default value,
    2851          47 :         const char* isAuto = "1";
    2852             :         pFS->singleElement( FSNS( XML_c, XML_auto ),
    2853             :             XML_val, isAuto,
    2854          47 :             FSEND );
    2855             : 
    2856          47 :         if( nAxisType == XML_catAx )
    2857             :         {
    2858             :             // FIXME: seems not support? lblAlgn
    2859          45 :             const char* sLblAlgn = "ctr";
    2860             :             pFS->singleElement( FSNS( XML_c, XML_lblAlgn ),
    2861             :                     XML_val, sLblAlgn,
    2862          45 :                     FSEND );
    2863             :         }
    2864             : 
    2865             :         // FIXME: seems not support? lblOffset
    2866          47 :         sal_Int32 nLblOffset = 100;
    2867             :         pFS->singleElement( FSNS( XML_c, XML_lblOffset ),
    2868             :             XML_val, I32S( nLblOffset ),
    2869          47 :             FSEND );
    2870             :     }
    2871             : 
    2872             :     // majorUnit
    2873         116 :     bool bAutoStepMain = false;
    2874         116 :     if(GetProperty( xAxisProp, "AutoStepMain" ) )
    2875         116 :         mAny >>= bAutoStepMain;
    2876             : 
    2877         116 :     if( !bAutoStepMain && (GetProperty( xAxisProp, "StepMain" ) ) )
    2878             :     {
    2879           1 :         double dMajorUnit = 0;
    2880           1 :         mAny >>= dMajorUnit;
    2881             :         pFS->singleElement( FSNS( XML_c, XML_majorUnit ),
    2882             :             XML_val, IS( dMajorUnit ),
    2883           1 :             FSEND );
    2884             :     }
    2885             :     // minorUnit
    2886         116 :     bool bAutoStepHelp = false;
    2887         116 :     if(GetProperty( xAxisProp, "AutoStepHelp" ) )
    2888         116 :         mAny >>= bAutoStepHelp;
    2889             : 
    2890         116 :     if( !bAutoStepHelp && (GetProperty( xAxisProp, "StepHelp" ) ) )
    2891             :     {
    2892           0 :         double dMinorUnit = 0;
    2893           0 :         mAny >>= dMinorUnit;
    2894             :         pFS->singleElement( FSNS( XML_c, XML_minorUnit ),
    2895             :             XML_val, IS( dMinorUnit ),
    2896           0 :             FSEND );
    2897             :     }
    2898             : 
    2899         116 :     if( nAxisType == XML_valAx && GetProperty( xAxisProp, "DisplayUnits" ) )
    2900             :     {
    2901          69 :         bool bDisplayUnits = false;
    2902          69 :         mAny >>= bDisplayUnits;
    2903          69 :         if(bDisplayUnits)
    2904             :         {
    2905           1 :             OUString aVal;
    2906           1 :             if(GetProperty( xAxisProp, "BuiltInUnit" ))
    2907             :             {
    2908           1 :                 mAny >>= aVal;
    2909           1 :                 if(!aVal.isEmpty())
    2910             :                 {
    2911             :                     pFS->startElement( FSNS( XML_c, XML_dispUnits ),
    2912           1 :                             FSEND );
    2913             : 
    2914           1 :                     OString aBuiltInUnit = OUStringToOString(aVal, RTL_TEXTENCODING_UTF8);
    2915             :                     pFS->singleElement( FSNS( XML_c, XML_builtInUnit ),
    2916             :                             XML_val, aBuiltInUnit.getStr(),
    2917           1 :                             FSEND );
    2918             : 
    2919           1 :                     pFS->singleElement(FSNS( XML_c, XML_dispUnitsLbl ),FSEND);
    2920           1 :                     pFS->endElement( FSNS( XML_c, XML_dispUnits ) );
    2921             :                 }
    2922           1 :              }
    2923             :         }
    2924             :     }
    2925             :     // TODO: text properties
    2926             : 
    2927         232 :     pFS->endElement( FSNS( XML_c, nAxisType ) );
    2928         116 : }
    2929             : 
    2930             : namespace {
    2931             : 
    2932         121 : struct LabelPlacementParam
    2933             : {
    2934             :     bool mbExport;
    2935             :     sal_Int32 meDefault;
    2936             : 
    2937             :     std::unordered_set<sal_Int32> maAllowedValues;
    2938             : 
    2939         121 :     LabelPlacementParam() :
    2940             :         mbExport(true),
    2941         121 :         meDefault(css::chart::DataLabelPlacement::OUTSIDE) {}
    2942             : 
    2943         121 :     void allowAll()
    2944             :     {
    2945         121 :         maAllowedValues.insert(css::chart::DataLabelPlacement::OUTSIDE);
    2946         121 :         maAllowedValues.insert(css::chart::DataLabelPlacement::INSIDE);
    2947         121 :         maAllowedValues.insert(css::chart::DataLabelPlacement::CENTER);
    2948         121 :         maAllowedValues.insert(css::chart::DataLabelPlacement::NEAR_ORIGIN);
    2949         121 :         maAllowedValues.insert(css::chart::DataLabelPlacement::TOP);
    2950         121 :         maAllowedValues.insert(css::chart::DataLabelPlacement::BOTTOM);
    2951         121 :         maAllowedValues.insert(css::chart::DataLabelPlacement::LEFT);
    2952         121 :         maAllowedValues.insert(css::chart::DataLabelPlacement::RIGHT);
    2953         121 :         maAllowedValues.insert(css::chart::DataLabelPlacement::AVOID_OVERLAP);
    2954         121 :     }
    2955             : };
    2956             : 
    2957         111 : const char* toOOXMLPlacement( sal_Int32 nPlacement )
    2958             : {
    2959         111 :     switch (nPlacement)
    2960             :     {
    2961          42 :         case css::chart::DataLabelPlacement::OUTSIDE:       return "outEnd";
    2962           1 :         case css::chart::DataLabelPlacement::INSIDE:        return "inEnd";
    2963           5 :         case css::chart::DataLabelPlacement::CENTER:        return "ctr";
    2964           2 :         case css::chart::DataLabelPlacement::NEAR_ORIGIN:   return "inBase";
    2965           0 :         case css::chart::DataLabelPlacement::TOP:           return "t";
    2966           0 :         case css::chart::DataLabelPlacement::BOTTOM:        return "b";
    2967           0 :         case css::chart::DataLabelPlacement::LEFT:          return "l";
    2968          28 :         case css::chart::DataLabelPlacement::RIGHT:         return "r";
    2969          33 :         case css::chart::DataLabelPlacement::AVOID_OVERLAP: return "bestFit";
    2970             :         default:
    2971             :             ;
    2972             :     }
    2973             : 
    2974           0 :     return "outEnd";
    2975             : }
    2976             : 
    2977         176 : void writeLabelProperties(
    2978             :     FSHelperPtr pFS, const uno::Reference<beans::XPropertySet>& xPropSet, const LabelPlacementParam& rLabelParam )
    2979             : {
    2980         176 :     if (!xPropSet.is())
    2981         176 :         return;
    2982             : 
    2983         176 :     chart2::DataPointLabel aLabel;
    2984         176 :     sal_Int32 nLabelBorderWidth = 0;
    2985         176 :     sal_Int32 nLabelBorderColor = 0x00FFFFFF;
    2986             : 
    2987         176 :     xPropSet->getPropertyValue("Label") >>= aLabel;
    2988         176 :     xPropSet->getPropertyValue("LabelBorderWidth") >>= nLabelBorderWidth;
    2989         176 :     xPropSet->getPropertyValue("LabelBorderColor") >>= nLabelBorderColor;
    2990             : 
    2991         176 :     if (nLabelBorderWidth > 0)
    2992             :     {
    2993           4 :         pFS->startElement(FSNS(XML_c, XML_spPr), FSEND);
    2994           4 :         pFS->startElement(FSNS(XML_a, XML_ln), XML_w, IS(convertHmmToEmu(nLabelBorderWidth)), FSEND);
    2995           4 :         if (nLabelBorderColor != -1)
    2996             :         {
    2997           4 :             pFS->startElement(FSNS(XML_a, XML_solidFill), FSEND);
    2998             : 
    2999           4 :             OString aStr = OString::number(nLabelBorderColor, 16).toAsciiUpperCase();
    3000           4 :             pFS->singleElement(FSNS(XML_a, XML_srgbClr), XML_val, aStr.getStr(), FSEND);
    3001             : 
    3002           4 :             pFS->endElement(FSNS(XML_a, XML_solidFill));
    3003             :         }
    3004           4 :         pFS->endElement(FSNS(XML_a, XML_ln));
    3005           4 :         pFS->endElement(FSNS(XML_c, XML_spPr));
    3006             :     }
    3007             : 
    3008         176 :     if (rLabelParam.mbExport)
    3009             :     {
    3010         124 :         sal_Int32 nLabelPlacement = rLabelParam.meDefault;
    3011         124 :         if (xPropSet->getPropertyValue("LabelPlacement") >>= nLabelPlacement)
    3012             :         {
    3013         111 :             if (!rLabelParam.maAllowedValues.count(nLabelPlacement))
    3014          14 :                 nLabelPlacement = rLabelParam.meDefault;
    3015         111 :             pFS->singleElement(FSNS(XML_c, XML_dLblPos), XML_val, toOOXMLPlacement(nLabelPlacement), FSEND);
    3016             :         }
    3017             :     }
    3018             : 
    3019         176 :     pFS->singleElement(FSNS(XML_c, XML_showLegendKey), XML_val, BS(aLabel.ShowLegendSymbol), FSEND);
    3020         176 :     pFS->singleElement(FSNS(XML_c, XML_showVal), XML_val, BS(aLabel.ShowNumber), FSEND);
    3021         176 :     pFS->singleElement(FSNS(XML_c, XML_showCatName), XML_val, BS(aLabel.ShowCategoryName), FSEND);
    3022         176 :     pFS->singleElement(FSNS(XML_c, XML_showSerName), XML_val, BS(false), FSEND);
    3023         176 :     pFS->singleElement(FSNS(XML_c, XML_showPercent), XML_val, BS(aLabel.ShowNumberInPercent), FSEND);
    3024             : }
    3025             : 
    3026             : }
    3027             : 
    3028         121 : void ChartExport::exportDataLabels(
    3029             :     const uno::Reference<chart2::XDataSeries> & xSeries, sal_Int32 nSeriesLength, sal_Int32 eChartType )
    3030             : {
    3031         121 :     if (!xSeries.is() || nSeriesLength <= 0)
    3032           0 :         return;
    3033             : 
    3034         121 :     uno::Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY);
    3035         121 :     if (!xPropSet.is())
    3036           0 :         return;
    3037             : 
    3038         242 :     FSHelperPtr pFS = GetFS();
    3039         121 :     pFS->startElement(FSNS(XML_c, XML_dLbls), FSEND);
    3040             : 
    3041         242 :     uno::Sequence<sal_Int32> aAttrLabelIndices;
    3042         121 :     xPropSet->getPropertyValue("AttributedDataPoints") >>= aAttrLabelIndices;
    3043             : 
    3044             :     // We must not export label placement property when the chart type doesn't
    3045             :     // support this option in MS Office, else MS Office would think the file
    3046             :     // is corrupt & refuse to open it.
    3047             : 
    3048         121 :     const chart::TypeGroupInfo& rInfo = chart::GetTypeGroupInfo(static_cast<chart::TypeId>(eChartType));
    3049         242 :     LabelPlacementParam aParam;
    3050         121 :     aParam.mbExport = !mbIs3DChart;
    3051         121 :     aParam.meDefault = rInfo.mnDefLabelPos;
    3052         121 :     aParam.allowAll();
    3053         121 :     switch (eChartType) // diagram chart type
    3054             :     {
    3055             :         case chart::TYPEID_PIE:
    3056           7 :             if(getChartType() == chart::TYPEID_DOUGHNUT)
    3057           2 :                 aParam.mbExport = false;
    3058             :             else
    3059             :             // All pie charts support label placement.
    3060           5 :             aParam.mbExport = true;
    3061           7 :         break;
    3062             :         case chart::TYPEID_AREA:
    3063             :         case chart::TYPEID_RADARLINE:
    3064             :         case chart::TYPEID_RADARAREA:
    3065             :             // These chart types don't support label placement.
    3066           5 :             aParam.mbExport = false;
    3067           5 :         break;
    3068             :         case chart::TYPEID_BAR:
    3069          71 :             if (mbStacked || mbPercent)
    3070             :             {
    3071          20 :                 aParam.maAllowedValues.clear();
    3072          20 :                 aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::CENTER);
    3073          20 :                 aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::INSIDE);
    3074          20 :                 aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::NEAR_ORIGIN);
    3075          20 :                 aParam.meDefault = css::chart::DataLabelPlacement::CENTER;
    3076             :             }
    3077             :             else  // Clustered bar chart
    3078             :             {
    3079          51 :                 aParam.maAllowedValues.clear();
    3080          51 :                 aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::CENTER);
    3081          51 :                 aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::INSIDE);
    3082          51 :                 aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::OUTSIDE);
    3083          51 :                 aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::NEAR_ORIGIN);
    3084          51 :                 aParam.meDefault = css::chart::DataLabelPlacement::OUTSIDE;
    3085             :             }
    3086          71 :         break;
    3087             :         default:
    3088             :             ;
    3089             :     }
    3090             : 
    3091         121 :     const sal_Int32* p = aAttrLabelIndices.getConstArray();
    3092         121 :     const sal_Int32* pEnd = p + aAttrLabelIndices.getLength();
    3093         176 :     for (; p != pEnd; ++p)
    3094             :     {
    3095          55 :         sal_Int32 nIdx = *p;
    3096          55 :         uno::Reference<beans::XPropertySet> xLabelPropSet = xSeries->getDataPointByIndex(nIdx);
    3097          55 :         if (!xLabelPropSet.is())
    3098           0 :             continue;
    3099             : 
    3100             :         // Individual label property that overwrites the baseline.
    3101          55 :         pFS->startElement(FSNS(XML_c, XML_dLbl), FSEND);
    3102          55 :         pFS->singleElement(FSNS(XML_c, XML_idx), XML_val, I32S(nIdx), FSEND);
    3103          55 :         writeLabelProperties(pFS, xLabelPropSet, aParam);
    3104          55 :         pFS->endElement(FSNS(XML_c, XML_dLbl));
    3105          55 :     }
    3106             : 
    3107             :     // Baseline label properties for all labels.
    3108         121 :     writeLabelProperties(pFS, xPropSet, aParam);
    3109             : 
    3110             :     pFS->singleElement(FSNS(XML_c, XML_showLeaderLines),
    3111             :             XML_val, "0",
    3112         121 :             FSEND);
    3113             : 
    3114         242 :     pFS->endElement(FSNS(XML_c, XML_dLbls));
    3115             : }
    3116             : 
    3117         121 : void ChartExport::exportDataPoints(
    3118             :     const uno::Reference< beans::XPropertySet > & xSeriesProperties,
    3119             :     sal_Int32 nSeriesLength )
    3120             : {
    3121         121 :     uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );
    3122         121 :     bool bVaryColorsByPoint = false;
    3123         242 :     Sequence< sal_Int32 > aDataPointSeq;
    3124         121 :     if( xSeriesProperties.is())
    3125             :     {
    3126         121 :         Any aAny = xSeriesProperties->getPropertyValue(
    3127         121 :             OUString(  "AttributedDataPoints" ));
    3128         121 :         aAny >>= aDataPointSeq;
    3129         121 :         xSeriesProperties->getPropertyValue(
    3130         121 :             OUString(  "VaryColorsByPoint" )) >>= bVaryColorsByPoint;
    3131             :     }
    3132             : 
    3133         121 :     const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
    3134             :     sal_Int32 nElement;
    3135         242 :     Reference< chart2::XColorScheme > xColorScheme;
    3136         121 :     if( mxNewDiagram.is())
    3137         121 :         xColorScheme.set( mxNewDiagram->getDefaultColorScheme());
    3138             : 
    3139         121 :     if( bVaryColorsByPoint && xColorScheme.is() )
    3140             :     {
    3141           7 :         ::std::set< sal_Int32 > aAttrPointSet;
    3142           7 :         ::std::copy( pPoints, pPoints + aDataPointSeq.getLength(),
    3143          14 :                     ::std::inserter( aAttrPointSet, aAttrPointSet.begin()));
    3144           7 :         const ::std::set< sal_Int32 >::const_iterator aEndIt( aAttrPointSet.end());
    3145          43 :         for( nElement = 0; nElement < nSeriesLength; ++nElement )
    3146             :         {
    3147          36 :             uno::Reference< beans::XPropertySet > xPropSet;
    3148          36 :             if( aAttrPointSet.find( nElement ) != aEndIt )
    3149             :             {
    3150             :                 try
    3151             :                 {
    3152          72 :                     xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
    3153          36 :                             xSeries, nElement, getModel() );
    3154             :                 }
    3155           0 :                 catch( const uno::Exception & rEx )
    3156             :                 {
    3157             :                     SAL_WARN( "oox", "Exception caught during Export of data point: " << rEx.Message );
    3158             :                 }
    3159             :             }
    3160             :             else
    3161             :             {
    3162             :                 // property set only containing the color
    3163           0 :                 xPropSet.set( new ColorPropertySet( xColorScheme->getColorByIndex( nElement )));
    3164             :             }
    3165             : 
    3166          36 :             if( xPropSet.is() )
    3167             :             {
    3168          36 :                 FSHelperPtr pFS = GetFS();
    3169             :                 pFS->startElement( FSNS( XML_c, XML_dPt ),
    3170          36 :                     FSEND );
    3171             :                 pFS->singleElement( FSNS( XML_c, XML_idx ),
    3172             :                     XML_val, I32S(nElement),
    3173          36 :                     FSEND );
    3174          36 :                 exportShapeProps( xPropSet );
    3175             : 
    3176          36 :                 pFS->endElement( FSNS( XML_c, XML_dPt ) );
    3177             :             }
    3178          43 :         }
    3179         121 :     }
    3180         121 : }
    3181             : 
    3182          58 : void ChartExport::exportAxesId( sal_Int32 nAttachedAxis )
    3183             : {
    3184          58 :     sal_Int32 nAxisIdx = lcl_generateRandomValue();
    3185          58 :     sal_Int32 nAxisIdy = lcl_generateRandomValue();
    3186          58 :     maAxes.push_back( AxisIdPair( AXIS_PRIMARY_X, nAxisIdx, nAxisIdy ) );
    3187          58 :     maAxes.push_back( AxisIdPair( nAttachedAxis, nAxisIdy, nAxisIdx ) );
    3188          58 :     FSHelperPtr pFS = GetFS();
    3189             :     pFS->singleElement( FSNS( XML_c, XML_axId ),
    3190             :             XML_val, I32S( nAxisIdx ),
    3191          58 :             FSEND );
    3192             :     pFS->singleElement( FSNS( XML_c, XML_axId ),
    3193             :             XML_val, I32S( nAxisIdy ),
    3194          58 :             FSEND );
    3195          58 :     if( mbHasZAxis )
    3196             :     {
    3197          11 :         sal_Int32 nAxisIdz = 0;
    3198          11 :         if( isDeep3dChart() )
    3199             :         {
    3200           0 :             nAxisIdz = lcl_generateRandomValue();
    3201           0 :             maAxes.push_back( AxisIdPair( AXIS_PRIMARY_Z, nAxisIdz, nAxisIdy ) );
    3202             :         }
    3203             :         pFS->singleElement( FSNS( XML_c, XML_axId ),
    3204             :             XML_val, I32S( nAxisIdz ),
    3205          11 :             FSEND );
    3206          58 :     }
    3207          58 : }
    3208             : 
    3209          45 : void ChartExport::exportGrouping( bool isBar )
    3210             : {
    3211          45 :     FSHelperPtr pFS = GetFS();
    3212          90 :     Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
    3213             :     // grouping
    3214          45 :     if( GetProperty( xPropSet, "Stacked" ) )
    3215          45 :         mAny >>= mbStacked;
    3216          45 :     if( GetProperty( xPropSet, "Percent" ) )
    3217          45 :         mAny >>= mbPercent;
    3218             : 
    3219          45 :     const char* grouping = NULL;
    3220          45 :     if (mbStacked)
    3221           4 :         grouping = "stacked";
    3222          41 :     else if (mbPercent)
    3223           4 :         grouping = "percentStacked";
    3224             :     else
    3225             :     {
    3226          37 :         if( isBar && !isDeep3dChart() )
    3227             :         {
    3228          26 :             grouping = "clustered";
    3229             :         }
    3230             :         else
    3231          11 :             grouping = "standard";
    3232             :     }
    3233             :     pFS->singleElement( FSNS( XML_c, XML_grouping ),
    3234             :             XML_val, grouping,
    3235          90 :             FSEND );
    3236          45 : }
    3237             : 
    3238         121 : void ChartExport::exportTrendlines( Reference< chart2::XDataSeries > xSeries )
    3239             : {
    3240         121 :     FSHelperPtr pFS = GetFS();
    3241         242 :     Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xSeries, UNO_QUERY );
    3242         121 :     if( xRegressionCurveContainer.is() )
    3243             :     {
    3244         121 :         Sequence< Reference< chart2::XRegressionCurve > > aRegCurveSeq = xRegressionCurveContainer->getRegressionCurves();
    3245         121 :         const Reference< chart2::XRegressionCurve >* pBeg = aRegCurveSeq.getConstArray();
    3246         121 :         const Reference< chart2::XRegressionCurve >* pEnd = pBeg + aRegCurveSeq.getLength();
    3247         124 :         for( const Reference< chart2::XRegressionCurve >* pIt = pBeg; pIt != pEnd; ++pIt )
    3248             :         {
    3249           3 :             Reference< chart2::XRegressionCurve > xRegCurve = *pIt;
    3250           3 :             if (!xRegCurve.is())
    3251           0 :                 continue;
    3252             : 
    3253           6 :             Reference< XPropertySet > xProperties( xRegCurve , uno::UNO_QUERY );
    3254             : 
    3255           6 :             OUString aService;
    3256           6 :             Reference< lang::XServiceName > xServiceName( xProperties, UNO_QUERY );
    3257           3 :             if( !xServiceName.is() )
    3258           0 :                 continue;
    3259             : 
    3260           3 :             aService = xServiceName->getServiceName();
    3261             : 
    3262           8 :             if(aService != "com.sun.star.chart2.LinearRegressionCurve" &&
    3263           4 :                     aService != "com.sun.star.chart2.ExponentialRegressionCurve" &&
    3264           4 :                     aService != "com.sun.star.chart2.LogarithmicRegressionCurve" &&
    3265           4 :                     aService != "com.sun.star.chart2.PotentialRegressionCurve" &&
    3266           6 :                     aService != "com.sun.star.chart2.PolynomialRegressionCurve" &&
    3267           1 :                     aService != "com.sun.star.chart2.MovingAverageRegressionCurve")
    3268           0 :                 continue;
    3269             : 
    3270           3 :             pFS->startElement( FSNS( XML_c, XML_trendline ), FSEND );
    3271             : 
    3272           6 :             OUString aName;
    3273           3 :             xProperties->getPropertyValue("CurveName") >>= aName;
    3274           3 :             if(!aName.isEmpty())
    3275             :             {
    3276           3 :                 pFS->startElement( FSNS( XML_c, XML_name), FSEND);
    3277           3 :                 pFS->writeEscaped(aName);
    3278           3 :                 pFS->endElement( FSNS( XML_c, XML_name) );
    3279             :             }
    3280             : 
    3281           3 :             exportShapeProps( xProperties );
    3282             : 
    3283           3 :             if( aService == "com.sun.star.chart2.LinearRegressionCurve" )
    3284             :             {
    3285             :                 pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
    3286             :                     XML_val, "linear",
    3287           1 :                     FSEND );
    3288             :             }
    3289           2 :             else if( aService == "com.sun.star.chart2.ExponentialRegressionCurve" )
    3290             :             {
    3291             :                 pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
    3292             :                     XML_val, "exp",
    3293           0 :                     FSEND );
    3294             :             }
    3295           2 :             else if( aService == "com.sun.star.chart2.LogarithmicRegressionCurve" )
    3296             :             {
    3297             :                 pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
    3298             :                     XML_val, "log",
    3299           0 :                     FSEND );
    3300             :             }
    3301           2 :             else if( aService == "com.sun.star.chart2.PotentialRegressionCurve" )
    3302             :             {
    3303             :                 pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
    3304             :                     XML_val, "power",
    3305           0 :                     FSEND );
    3306             :             }
    3307           2 :             else if( aService == "com.sun.star.chart2.PolynomialRegressionCurve" )
    3308             :             {
    3309             :                 pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
    3310             :                     XML_val, "poly",
    3311           1 :                     FSEND );
    3312             : 
    3313           1 :                 sal_Int32 aDegree = 2;
    3314           1 :                 xProperties->getPropertyValue( "PolynomialDegree") >>= aDegree;
    3315             :                 pFS->singleElement( FSNS( XML_c, XML_order ),
    3316             :                     XML_val, I32S(aDegree),
    3317           1 :                     FSEND );
    3318             :             }
    3319           1 :             else if( aService == "com.sun.star.chart2.MovingAverageRegressionCurve" )
    3320             :             {
    3321             :                 pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
    3322             :                     XML_val, "movingAvg",
    3323           1 :                     FSEND );
    3324             : 
    3325           1 :                 sal_Int32 aPeriod = 2;
    3326           1 :                 xProperties->getPropertyValue( "MovingAveragePeriod") >>= aPeriod;
    3327             : 
    3328             :                 pFS->singleElement( FSNS( XML_c, XML_period ),
    3329             :                     XML_val, I32S(aPeriod),
    3330           1 :                     FSEND );
    3331             :             }
    3332             :             else
    3333             :             {
    3334             :                 // should never happen
    3335             :                 // This would produce invalid OOXML files so we check earlier for the type
    3336             :                 assert(false);
    3337             :             }
    3338             : 
    3339           3 :             double fExtrapolateForward = 0.0;
    3340           3 :             double fExtrapolateBackward = 0.0;
    3341             : 
    3342           3 :             xProperties->getPropertyValue("ExtrapolateForward") >>= fExtrapolateForward;
    3343           3 :             xProperties->getPropertyValue("ExtrapolateBackward") >>= fExtrapolateBackward;
    3344             : 
    3345             :             pFS->singleElement( FSNS( XML_c, XML_forward ),
    3346             :                     XML_val, OString::number(fExtrapolateForward).getStr(),
    3347           3 :                     FSEND );
    3348             : 
    3349             :             pFS->singleElement( FSNS( XML_c, XML_backward ),
    3350             :                     XML_val, OString::number(fExtrapolateBackward).getStr(),
    3351           3 :                     FSEND );
    3352             : 
    3353           3 :             bool bForceIntercept = false;
    3354           3 :             xProperties->getPropertyValue("ForceIntercept") >>= bForceIntercept;
    3355             : 
    3356           3 :             if (bForceIntercept)
    3357             :             {
    3358           1 :                 double fInterceptValue = 0.0;
    3359           1 :                 xProperties->getPropertyValue("InterceptValue") >>= fInterceptValue;
    3360             : 
    3361             :                 pFS->singleElement( FSNS( XML_c, XML_intercept ),
    3362             :                     XML_val, OString::number(fInterceptValue).getStr(),
    3363           1 :                     FSEND );
    3364             :             }
    3365             : 
    3366             :             // Equation properties
    3367           6 :             Reference< XPropertySet > xEquationProperties( xRegCurve->getEquationProperties() );
    3368             : 
    3369             :             // Show Equation
    3370           3 :             bool bShowEquation = false;
    3371           3 :             xEquationProperties->getPropertyValue("ShowEquation") >>= bShowEquation;
    3372             : 
    3373             :             // Show R^2
    3374           3 :             bool bShowCorrelationCoefficient = false;
    3375           3 :             xEquationProperties->getPropertyValue("ShowCorrelationCoefficient") >>= bShowCorrelationCoefficient;
    3376             : 
    3377             :             pFS->singleElement( FSNS( XML_c, XML_dispRSqr ),
    3378             :                     XML_val, bShowCorrelationCoefficient ? "1" : "0",
    3379           3 :                     FSEND );
    3380             : 
    3381             :             pFS->singleElement( FSNS( XML_c, XML_dispEq ),
    3382             :                     XML_val, bShowEquation ? "1" : "0",
    3383           3 :                     FSEND );
    3384             : 
    3385           3 :             pFS->endElement( FSNS( XML_c, XML_trendline ) );
    3386         124 :         }
    3387         121 :     }
    3388         121 : }
    3389             : 
    3390          35 : void ChartExport::exportMarker(Reference< chart2::XDataSeries > xSeries)
    3391             : {
    3392          35 :     Reference< XPropertySet > xPropSet( xSeries, uno::UNO_QUERY );
    3393          70 :     chart2::Symbol aSymbol;
    3394          35 :     if( GetProperty( xPropSet, "Symbol" ) )
    3395          35 :         mAny >>= aSymbol;
    3396             : 
    3397          35 :     if(aSymbol.Style != chart2::SymbolStyle_STANDARD && aSymbol.Style != chart2::SymbolStyle_AUTO && aSymbol.Style != chart2::SymbolStyle_NONE)
    3398          35 :         return;
    3399             : 
    3400          70 :     FSHelperPtr pFS = GetFS();
    3401             :     pFS->startElement( FSNS( XML_c, XML_marker ),
    3402          35 :             FSEND );
    3403             : 
    3404          35 :     sal_Int32 nSymbol = aSymbol.StandardSymbol;
    3405             :     // TODO: more properties support for marker
    3406          35 :     const char* pSymbolType = NULL;
    3407          35 :     switch( nSymbol )
    3408             :     {
    3409             :         case 0:
    3410          27 :             pSymbolType = "square";
    3411          27 :             break;
    3412             :         case 1:
    3413           2 :             pSymbolType = "diamond";
    3414           2 :             break;
    3415             :         case 2:
    3416             :         case 3:
    3417             :         case 4:
    3418             :         case 5:
    3419           0 :             pSymbolType = "triangle";
    3420           0 :             break;
    3421             :         case 8:
    3422           2 :             pSymbolType = "circle";
    3423           2 :             break;
    3424             :         case 9:
    3425           0 :             pSymbolType = "star";
    3426           0 :             break;
    3427             :         case 10:
    3428           3 :             pSymbolType = "x"; // in MS office 2010 built in symbol marker 'X' is represented as 'x'
    3429           3 :             break;
    3430             :         case 11:
    3431           0 :             pSymbolType = "plus";
    3432           0 :             break;
    3433             :         case 13:
    3434           0 :             pSymbolType = "dash";
    3435           0 :             break;
    3436             :         default:
    3437           1 :             pSymbolType = "square";
    3438           1 :             break;
    3439             :     }
    3440             : 
    3441          35 :     bool bSkipFormatting = false;
    3442          35 :     if (aSymbol.Style == chart2::SymbolStyle_NONE)
    3443             :     {
    3444          17 :         bSkipFormatting = true;
    3445          17 :         pSymbolType = "none";
    3446             :     }
    3447             : 
    3448          35 :     if( pSymbolType )
    3449             :     {
    3450             :         pFS->singleElement( FSNS( XML_c, XML_symbol ),
    3451             :             XML_val, pSymbolType,
    3452          35 :             FSEND );
    3453             :     }
    3454             : 
    3455          35 :     if (!bSkipFormatting)
    3456             :     {
    3457          18 :         awt::Size aSymbolSize = aSymbol.Size;
    3458          18 :         sal_Int32 nSize = std::max( aSymbolSize.Width, aSymbolSize.Height );
    3459             : 
    3460          18 :         nSize = nSize/250.0*7.0 + 1; // just guessed based on some test cases,
    3461             :         //the value is always 1 less than the actual value.
    3462          18 :         nSize = std::min<sal_Int32>( 72, std::max<sal_Int32>( 2, nSize ) );
    3463             :         pFS->singleElement( FSNS( XML_c, XML_size),
    3464             :                 XML_val, I32S(nSize),
    3465          18 :                 FSEND );
    3466             : 
    3467             :         pFS->startElement( FSNS( XML_c, XML_spPr ),
    3468          18 :                 FSEND );
    3469             : 
    3470          18 :         util::Color aColor = aSymbol.FillColor;
    3471          18 :         if (GetProperty(xPropSet, "Color"))
    3472          18 :             mAny >>= aColor;
    3473             : 
    3474          18 :         if (aColor == -1)
    3475             :         {
    3476           0 :             pFS->singleElement(FSNS(XML_a, XML_noFill), FSEND);
    3477             :         }
    3478             :         else
    3479          18 :             WriteSolidFill(aColor);
    3480             : 
    3481          18 :         pFS->endElement( FSNS( XML_c, XML_spPr ) );
    3482             :     }
    3483             : 
    3484          70 :     pFS->endElement( FSNS( XML_c, XML_marker ) );
    3485             : }
    3486             : 
    3487          35 : void ChartExport::exportSmooth()
    3488             : {
    3489          35 :     FSHelperPtr pFS = GetFS();
    3490          70 :     Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY );
    3491          35 :     sal_Int32 nSplineType = 0;
    3492          35 :     if( GetProperty( xPropSet, "SplineType" ) )
    3493          35 :         mAny >>= nSplineType;
    3494          35 :     const char* pVal = nSplineType != 0 ? "1" : "0";
    3495             :     pFS->singleElement( FSNS( XML_c, XML_smooth ),
    3496             :             XML_val, pVal,
    3497          70 :             FSEND );
    3498          35 : }
    3499             : 
    3500           5 : void ChartExport::exportFirstSliceAng( )
    3501             : {
    3502           5 :     FSHelperPtr pFS = GetFS();
    3503           5 :     sal_Int32 nStartingAngle = 0;
    3504          10 :     Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
    3505           5 :     if( GetProperty( xPropSet, "StartingAngle" ) )
    3506           5 :         mAny >>= nStartingAngle;
    3507             : 
    3508             :     // convert to ooxml angle
    3509           5 :     nStartingAngle = (450 - nStartingAngle ) % 360;
    3510             :     pFS->singleElement( FSNS( XML_c, XML_firstSliceAng ),
    3511             :             XML_val, I32S( nStartingAngle ),
    3512          10 :             FSEND );
    3513           5 : }
    3514             : 
    3515             : namespace {
    3516             : 
    3517           1 : const char* getErrorBarStyle(sal_Int32 nErrorBarStyle)
    3518             : {
    3519           1 :     switch(nErrorBarStyle)
    3520             :     {
    3521             :         case cssc::ErrorBarStyle::NONE:
    3522           0 :             return NULL;
    3523             :         case cssc::ErrorBarStyle::VARIANCE:
    3524           0 :             break;
    3525             :         case cssc::ErrorBarStyle::STANDARD_DEVIATION:
    3526           0 :             return "stdDev";
    3527             :         case cssc::ErrorBarStyle::ABSOLUTE:
    3528           0 :             return "fixedVal";
    3529             :         case cssc::ErrorBarStyle::RELATIVE:
    3530           1 :             return "percentage";
    3531             :         case cssc::ErrorBarStyle::ERROR_MARGIN:
    3532           0 :             break;
    3533             :         case cssc::ErrorBarStyle::STANDARD_ERROR:
    3534           0 :             return "stdErr";
    3535             :         case cssc::ErrorBarStyle::FROM_DATA:
    3536           0 :             return "cust";
    3537             :         default:
    3538             :             assert(false && "can't happen");
    3539             :     }
    3540           0 :     return NULL;
    3541             : }
    3542             : 
    3543           0 : Reference< chart2::data::XDataSequence>  getLabeledSequence(
    3544             :         const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > >& aSequences,
    3545             :         bool bPositive )
    3546             : {
    3547           0 :     const OUString aRolePrefix( "error-bars" );
    3548           0 :     OUString aDirection;
    3549           0 :     if(bPositive)
    3550           0 :         aDirection = "positive";
    3551             :     else
    3552           0 :         aDirection = "negative";
    3553             : 
    3554           0 :     for( sal_Int32 nI=0; nI< aSequences.getLength(); ++nI )
    3555             :     {
    3556           0 :         if( aSequences[nI].is())
    3557             :         {
    3558           0 :             uno::Reference< chart2::data::XDataSequence > xSequence( aSequences[nI]->getValues());
    3559           0 :             uno::Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
    3560           0 :             OUString aRole;
    3561           0 :             if( ( xSeqProp->getPropertyValue(
    3562           0 :                             OUString( "Role" )) >>= aRole ) &&
    3563           0 :                     aRole.match( aRolePrefix ) && aRole.indexOf(aDirection) >= 0 )
    3564             :             {
    3565           0 :                 return xSequence;
    3566           0 :             }
    3567             :         }
    3568             :     }
    3569             : 
    3570           0 :     return Reference< chart2::data::XDataSequence > ();
    3571             : }
    3572             : 
    3573             : }
    3574             : 
    3575           1 : void ChartExport::exportErrorBar(Reference< XPropertySet> xErrorBarProps, bool bYError)
    3576             : {
    3577           1 :     sal_Int32 nErrorBarStyle = cssc::ErrorBarStyle::NONE;
    3578           1 :     xErrorBarProps->getPropertyValue("ErrorBarStyle") >>= nErrorBarStyle;
    3579           1 :     const char* pErrorBarStyle = getErrorBarStyle(nErrorBarStyle);
    3580           1 :     if(!pErrorBarStyle)
    3581           1 :         return;
    3582             : 
    3583           1 :     FSHelperPtr pFS = GetFS();
    3584             :     pFS->startElement( FSNS( XML_c, XML_errBars ),
    3585           1 :             FSEND );
    3586             :     pFS->singleElement( FSNS( XML_c, XML_errDir ),
    3587             :             XML_val, bYError ? "y" : "x",
    3588           1 :             FSEND );
    3589           1 :     bool bPositive = false, bNegative = false;
    3590           1 :     xErrorBarProps->getPropertyValue("ShowPositiveError") >>= bPositive;
    3591           1 :     xErrorBarProps->getPropertyValue("ShowNegativeError") >>= bNegative;
    3592             :     const char* pErrBarType;
    3593           1 :     if(bPositive && bNegative)
    3594           1 :         pErrBarType = "both";
    3595           0 :     else if(bPositive)
    3596           0 :         pErrBarType = "plus";
    3597           0 :     else if(bNegative)
    3598           0 :         pErrBarType = "minus";
    3599             :     else
    3600             :     {
    3601             :         // what the hell should we do now?
    3602             :         // at least this makes the file valid
    3603           0 :         pErrBarType = "both";
    3604             :     }
    3605             :     pFS->singleElement( FSNS( XML_c, XML_errBarType ),
    3606             :             XML_val, pErrBarType,
    3607           1 :             FSEND );
    3608             :     pFS->singleElement( FSNS( XML_c, XML_errValType ),
    3609             :             XML_val, pErrorBarStyle,
    3610           1 :             FSEND );
    3611             :     pFS->singleElement( FSNS( XML_c, XML_noEndCap ),
    3612             :             XML_val, "0",
    3613           1 :             FSEND );
    3614           1 :     if(nErrorBarStyle == cssc::ErrorBarStyle::FROM_DATA)
    3615             :     {
    3616           0 :         uno::Reference< chart2::data::XDataSource > xDataSource(xErrorBarProps, uno::UNO_QUERY);
    3617             :         Sequence< Reference < chart2::data::XLabeledDataSequence > > aSequences =
    3618           0 :             xDataSource->getDataSequences();
    3619             : 
    3620           0 :         if(bPositive)
    3621             :         {
    3622           0 :             exportSeriesValues(getLabeledSequence(aSequences, true), XML_plus);
    3623             :         }
    3624             : 
    3625           0 :         if(bNegative)
    3626             :         {
    3627           0 :             exportSeriesValues(getLabeledSequence(aSequences, false), XML_minus);
    3628           0 :         }
    3629             :     }
    3630             :     else
    3631             :     {
    3632           1 :         double nVal = 0.0;
    3633           1 :         if(nErrorBarStyle == cssc::ErrorBarStyle::STANDARD_DEVIATION)
    3634             :         {
    3635           0 :             xErrorBarProps->getPropertyValue("Weight") >>= nVal;
    3636             :         }
    3637             :         else
    3638             :         {
    3639           1 :             if(bPositive)
    3640           1 :                 xErrorBarProps->getPropertyValue("PositiveError") >>= nVal;
    3641             :             else
    3642           0 :                 xErrorBarProps->getPropertyValue("NegativeError") >>= nVal;
    3643             :         }
    3644             : 
    3645           1 :         OString aVal = OString::number(nVal);
    3646             : 
    3647             :         pFS->singleElement( FSNS( XML_c, XML_val ),
    3648             :                 XML_val, aVal.getStr(),
    3649           1 :                 FSEND );
    3650             :     }
    3651             : 
    3652           1 :     pFS->endElement( FSNS( XML_c, XML_errBars) );
    3653             : }
    3654             : 
    3655          13 : void ChartExport::exportView3D()
    3656             : {
    3657          13 :     Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
    3658          13 :     if( !xPropSet.is() )
    3659          13 :         return;
    3660          26 :     FSHelperPtr pFS = GetFS();
    3661             :     pFS->startElement( FSNS( XML_c, XML_view3D ),
    3662          13 :             FSEND );
    3663          13 :     sal_Int32 eChartType = getChartType( );
    3664             :     // rotX
    3665          13 :     if( GetProperty( xPropSet, "RotationHorizontal" ) )
    3666             :     {
    3667          13 :         sal_Int32 nRotationX = 0;
    3668          13 :         mAny >>= nRotationX;
    3669          13 :         if( nRotationX < 0 )
    3670             :         {
    3671           2 :             if(eChartType == chart::TYPEID_PIE)
    3672             :             {
    3673             :             /* In OOXML we get value in 0..90 range for pie chart X rotation , whereas we expect it to be in -90..90 range,
    3674             :                so we conver that during import. It  is modified in View3DConverter::convertFromModel()
    3675             :                here we convert it back to 0..90 as we received in import */
    3676           2 :                nRotationX += 90;  // X rotation (map Chart2 [-179,180] to OOXML [0..90])
    3677             :             }
    3678             :             else
    3679           0 :                 nRotationX += 360; // X rotation (map Chart2 [-179,180] to OOXML [-90..90])
    3680             :         }
    3681             :         pFS->singleElement( FSNS( XML_c, XML_rotX ),
    3682             :             XML_val, I32S( nRotationX ),
    3683          13 :             FSEND );
    3684             :     }
    3685             :     // rotY
    3686          13 :     if( GetProperty( xPropSet, "RotationVertical" ) )
    3687             :     {
    3688             :         // Y rotation (map Chart2 [-179,180] to OOXML [0..359])
    3689          13 :         if( eChartType == chart::TYPEID_PIE && GetProperty( xPropSet, "StartingAngle" ) )
    3690             :         {
    3691             :          // Y rotation used as 'first pie slice angle' in 3D pie charts
    3692           2 :             sal_Int32 nStartingAngle=0;
    3693           2 :             mAny >>= nStartingAngle;
    3694             :             // convert to ooxml angle
    3695           2 :             nStartingAngle = (450 - nStartingAngle ) % 360;
    3696             :             pFS->singleElement( FSNS( XML_c, XML_rotY ),
    3697             :                            XML_val, I32S( nStartingAngle ),
    3698           2 :                            FSEND );
    3699             :         }
    3700             :         else
    3701             :         {
    3702          11 :             sal_Int32 nRotationY = 0;
    3703          11 :             mAny >>= nRotationY;
    3704             :             // Y rotation (map Chart2 [-179,180] to OOXML [0..359])
    3705          11 :             if( nRotationY < 0 )
    3706           0 :                 nRotationY += 360;
    3707             :             pFS->singleElement( FSNS( XML_c, XML_rotY ),
    3708             :                             XML_val, I32S( nRotationY ),
    3709          11 :                             FSEND );
    3710             :         }
    3711             :     }
    3712             :     // rAngAx
    3713          13 :     if( GetProperty( xPropSet, "RightAngledAxes" ) )
    3714             :     {
    3715          13 :         bool bRightAngled = false;
    3716          13 :         mAny >>= bRightAngled;
    3717          13 :         const char* sRightAngled = bRightAngled ? "1":"0";
    3718             :         pFS->singleElement( FSNS( XML_c, XML_rAngAx ),
    3719             :             XML_val, sRightAngled,
    3720          13 :             FSEND );
    3721             :     }
    3722             :     // perspective
    3723          13 :     if( GetProperty( xPropSet, "Perspective" ) )
    3724             :     {
    3725          13 :         sal_Int32 nPerspective = 0;
    3726          13 :         mAny >>= nPerspective;
    3727             :         // map Chart2 [0,100] to OOXML [0..200]
    3728          13 :         nPerspective *= 2;
    3729             :         pFS->singleElement( FSNS( XML_c, XML_perspective ),
    3730             :             XML_val, I32S( nPerspective ),
    3731          13 :             FSEND );
    3732             :     }
    3733          26 :     pFS->endElement( FSNS( XML_c, XML_view3D ) );
    3734             : }
    3735             : 
    3736          37 : bool ChartExport::isDeep3dChart()
    3737             : {
    3738          37 :     bool isDeep = false;
    3739          37 :     if( mbIs3DChart )
    3740             :     {
    3741          17 :         Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
    3742          17 :         if( GetProperty( xPropSet, "Deep" ) )
    3743          17 :             mAny >>= isDeep;
    3744             :     }
    3745          37 :     return isDeep;
    3746             : }
    3747             : 
    3748         116 : OUString ChartExport::getNumberFormatCode(sal_Int32 nKey) const
    3749             : {
    3750         116 :     uno::Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(mxChartModel, uno::UNO_QUERY_THROW);
    3751         232 :     uno::Reference<util::XNumberFormats> xNumberFormats = xNumberFormatsSupplier->getNumberFormats();
    3752         232 :     uno::Reference<beans::XPropertySet> xNumberFormat = xNumberFormats->getByKey(nKey);
    3753             : 
    3754         116 :     if (!xNumberFormat.is())
    3755           0 :         return OUString();
    3756             : 
    3757         232 :     uno::Any aAny = xNumberFormat->getPropertyValue("FormatString");
    3758         232 :     OUString aValue;
    3759         116 :     aAny >>= aValue;
    3760         232 :     return aValue;
    3761             : }
    3762             : 
    3763             : }// drawingml
    3764         246 : }// oox
    3765             : 
    3766             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11