LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xichart.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1768 2289 77.2 %
Date: 2014-11-03 Functions: 233 269 86.6 %
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 "xichart.hxx"
      21             : 
      22             : #include <algorithm>
      23             : #include <memory>
      24             : #include <utility>
      25             : 
      26             : #include <com/sun/star/frame/XModel.hpp>
      27             : #include <com/sun/star/drawing/Direction3D.hpp>
      28             : #include <com/sun/star/drawing/ProjectionMode.hpp>
      29             : #include <com/sun/star/drawing/ShadeMode.hpp>
      30             : #include <com/sun/star/drawing/XShape.hpp>
      31             : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
      32             : #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
      33             : #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
      34             : #include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
      35             : #include <com/sun/star/chart/ChartAxisPosition.hpp>
      36             : #include <com/sun/star/chart/ChartLegendExpansion.hpp>
      37             : #include <com/sun/star/chart/TimeInterval.hpp>
      38             : #include <com/sun/star/chart/TimeUnit.hpp>
      39             : #include <com/sun/star/chart/XChartDocument.hpp>
      40             : #include <com/sun/star/chart/XDiagramPositioning.hpp>
      41             : #include <com/sun/star/chart/DataLabelPlacement.hpp>
      42             : #include <com/sun/star/chart/ErrorBarStyle.hpp>
      43             : #include <com/sun/star/chart/MissingValueTreatment.hpp>
      44             : #include <com/sun/star/chart2/LinearRegressionCurve.hpp>
      45             : #include <com/sun/star/chart2/ExponentialRegressionCurve.hpp>
      46             : #include <com/sun/star/chart2/LogarithmicRegressionCurve.hpp>
      47             : #include <com/sun/star/chart2/PotentialRegressionCurve.hpp>
      48             : #include <com/sun/star/chart2/PolynomialRegressionCurve.hpp>
      49             : #include <com/sun/star/chart2/MovingAverageRegressionCurve.hpp>
      50             : #include <com/sun/star/chart2/CartesianCoordinateSystem2d.hpp>
      51             : #include <com/sun/star/chart2/CartesianCoordinateSystem3d.hpp>
      52             : #include <com/sun/star/chart2/FormattedString.hpp>
      53             : #include <com/sun/star/chart2/LogarithmicScaling.hpp>
      54             : #include <com/sun/star/chart2/LinearScaling.hpp>
      55             : #include <com/sun/star/chart2/PolarCoordinateSystem2d.hpp>
      56             : #include <com/sun/star/chart2/PolarCoordinateSystem3d.hpp>
      57             : #include <com/sun/star/chart2/XChartDocument.hpp>
      58             : #include <com/sun/star/chart2/XDiagram.hpp>
      59             : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
      60             : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
      61             : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
      62             : #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
      63             : #include <com/sun/star/chart2/XTitled.hpp>
      64             : #include <com/sun/star/chart2/AxisType.hpp>
      65             : #include <com/sun/star/chart2/CurveStyle.hpp>
      66             : #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
      67             : #include <com/sun/star/chart2/DataPointLabel.hpp>
      68             : #include <com/sun/star/chart2/LegendPosition.hpp>
      69             : #include <com/sun/star/chart2/StackingDirection.hpp>
      70             : #include <com/sun/star/chart2/TickmarkStyle.hpp>
      71             : #include <com/sun/star/chart2/RelativePosition.hpp>
      72             : #include <com/sun/star/chart2/RelativeSize.hpp>
      73             : #include <com/sun/star/chart2/data/XDataProvider.hpp>
      74             : #include <com/sun/star/chart2/data/XDataReceiver.hpp>
      75             : #include <com/sun/star/chart2/data/XDataSink.hpp>
      76             : #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
      77             : #include <o3tl/numeric.hxx>
      78             : #include <o3tl/ptr_container.hxx>
      79             : #include <sfx2/objsh.hxx>
      80             : #include <svx/svdpage.hxx>
      81             : #include <svx/unoapi.hxx>
      82             : 
      83             : #include "document.hxx"
      84             : #include "drwlayer.hxx"
      85             : #include "rangeutl.hxx"
      86             : #include "tokenarray.hxx"
      87             : #include "token.hxx"
      88             : #include "compiler.hxx"
      89             : #include "reftokenhelper.hxx"
      90             : #include "chartlis.hxx"
      91             : #include "fprogressbar.hxx"
      92             : #include "xltracer.hxx"
      93             : #include "xistream.hxx"
      94             : #include "xiformula.hxx"
      95             : #include "xistyle.hxx"
      96             : #include "xipage.hxx"
      97             : #include "xiview.hxx"
      98             : 
      99             : using ::com::sun::star::uno::Any;
     100             : using ::com::sun::star::uno::Reference;
     101             : using ::com::sun::star::uno::Sequence;
     102             : using ::com::sun::star::uno::UNO_QUERY;
     103             : using ::com::sun::star::uno::UNO_QUERY_THROW;
     104             : using ::com::sun::star::uno::UNO_SET_THROW;
     105             : using ::com::sun::star::uno::Exception;
     106             : using ::com::sun::star::beans::XPropertySet;
     107             : using ::com::sun::star::lang::XMultiServiceFactory;
     108             : using ::com::sun::star::frame::XModel;
     109             : using ::com::sun::star::util::XNumberFormatsSupplier;
     110             : using ::com::sun::star::drawing::XDrawPage;
     111             : using ::com::sun::star::drawing::XDrawPageSupplier;
     112             : using ::com::sun::star::drawing::XShape;
     113             : 
     114             : using namespace ::com::sun::star::chart2;
     115             : 
     116             : using ::com::sun::star::chart2::data::XDataProvider;
     117             : using ::com::sun::star::chart2::data::XDataReceiver;
     118             : using ::com::sun::star::chart2::data::XDataSequence;
     119             : using ::com::sun::star::chart2::data::XDataSink;
     120             : using ::com::sun::star::chart2::data::XLabeledDataSequence;
     121             : using ::com::sun::star::chart2::data::LabeledDataSequence;
     122             : 
     123             : using ::formula::FormulaToken;
     124             : using ::formula::StackVar;
     125             : using ::boost::shared_ptr;
     126             : using ::std::pair;
     127             : using ::std::unique_ptr;
     128             : 
     129             : namespace cssc = ::com::sun::star::chart;
     130             : namespace cssc2 = ::com::sun::star::chart2;
     131             : 
     132             : // Helpers ====================================================================
     133             : 
     134             : namespace {
     135             : 
     136         616 : XclImpStream& operator>>( XclImpStream& rStrm, XclChRectangle& rRect )
     137             : {
     138         616 :     return rStrm >> rRect.mnX >> rRect.mnY >> rRect.mnWidth >> rRect.mnHeight;
     139             : }
     140             : 
     141         270 : inline void lclSetValueOrClearAny( Any& rAny, double fValue, bool bClear )
     142             : {
     143         270 :     if( bClear )
     144         270 :         rAny.clear();
     145             :     else
     146           0 :         rAny <<= fValue;
     147         270 : }
     148             : 
     149         180 : void lclSetExpValueOrClearAny( Any& rAny, double fValue, bool bLogScale, bool bClear )
     150             : {
     151         180 :     if( !bClear && bLogScale )
     152           0 :         fValue = pow( 10.0, fValue );
     153         180 :     lclSetValueOrClearAny( rAny, fValue, bClear );
     154         180 : }
     155             : 
     156           2 : double lclGetSerialDay( const XclImpRoot& rRoot, sal_uInt16 nValue, sal_uInt16 nTimeUnit )
     157             : {
     158           2 :     switch( nTimeUnit )
     159             :     {
     160             :         case EXC_CHDATERANGE_DAYS:
     161           2 :             return nValue;
     162             :         case EXC_CHDATERANGE_MONTHS:
     163           0 :             return rRoot.GetDoubleFromDateTime( Date( 1, static_cast< sal_uInt16 >( 1 + nValue % 12 ), static_cast< sal_uInt16 >( rRoot.GetBaseYear() + nValue / 12 ) ) );
     164             :         case EXC_CHDATERANGE_YEARS:
     165           0 :             return rRoot.GetDoubleFromDateTime( Date( 1, 1, static_cast< sal_uInt16 >( rRoot.GetBaseYear() + nValue ) ) );
     166             :         default:
     167             :             OSL_ENSURE( false, "lclGetSerialDay - unexpected time unit" );
     168             :     }
     169           0 :     return nValue;
     170             : }
     171             : 
     172           8 : void lclConvertTimeValue( const XclImpRoot& rRoot, Any& rAny, sal_uInt16 nValue, bool bAuto, sal_uInt16 nTimeUnit )
     173             : {
     174           8 :     if( bAuto )
     175           8 :         rAny.clear();
     176             :     else
     177           0 :         rAny <<= lclGetSerialDay( rRoot, nValue, nTimeUnit );
     178           8 : }
     179             : 
     180           0 : sal_Int32 lclGetApiTimeUnit( sal_uInt16 nTimeUnit )
     181             : {
     182           0 :     switch( nTimeUnit )
     183             :     {
     184           0 :         case EXC_CHDATERANGE_DAYS:      return cssc::TimeUnit::DAY;
     185           0 :         case EXC_CHDATERANGE_MONTHS:    return cssc::TimeUnit::MONTH;
     186           0 :         case EXC_CHDATERANGE_YEARS:     return cssc::TimeUnit::YEAR;
     187             :         default:                        OSL_ENSURE( false, "lclGetApiTimeUnit - unexpected time unit" );
     188             :     }
     189           0 :     return cssc::TimeUnit::DAY;
     190             : }
     191             : 
     192           8 : void lclConvertTimeInterval( Any& rInterval, sal_uInt16 nValue, bool bAuto, sal_uInt16 nTimeUnit )
     193             : {
     194           8 :     if( bAuto || (nValue == 0) )
     195           8 :         rInterval.clear();
     196             :     else
     197           0 :         rInterval <<= cssc::TimeInterval( nValue, lclGetApiTimeUnit( nTimeUnit ) );
     198           8 : }
     199             : 
     200             : } // namespace
     201             : 
     202             : // Common =====================================================================
     203             : 
     204             : /** Stores global data needed in various classes of the Chart import filter. */
     205         176 : struct XclImpChRootData : public XclChRootData
     206             : {
     207             :     XclImpChChart&      mrChartData;            /// The chart data object.
     208             : 
     209          88 :     inline explicit     XclImpChRootData( XclImpChChart& rChartData ) : mrChartData( rChartData ) {}
     210             : };
     211             : 
     212          88 : XclImpChRoot::XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart& rChartData ) :
     213             :     XclImpRoot( rRoot ),
     214          88 :     mxChData( new XclImpChRootData( rChartData ) )
     215             : {
     216          88 : }
     217             : 
     218        3426 : XclImpChRoot::~XclImpChRoot()
     219             : {
     220        3426 : }
     221             : 
     222         926 : XclImpChChart& XclImpChRoot::GetChartData() const
     223             : {
     224         926 :     return mxChData->mrChartData;
     225             : }
     226             : 
     227         174 : const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( XclChTypeId eType ) const
     228             : {
     229         174 :     return mxChData->mxTypeInfoProv->GetTypeInfo( eType );
     230             : }
     231             : 
     232           2 : const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( sal_uInt16 nRecId ) const
     233             : {
     234           2 :     return mxChData->mxTypeInfoProv->GetTypeInfoFromRecId( nRecId );
     235             : }
     236             : 
     237        2362 : const XclChFormatInfo& XclImpChRoot::GetFormatInfo( XclChObjectType eObjType ) const
     238             : {
     239        2362 :     return mxChData->mxFmtInfoProv->GetFormatInfo( eObjType );
     240             : }
     241             : 
     242         188 : Color XclImpChRoot::GetFontAutoColor() const
     243             : {
     244         188 :     return GetPalette().GetColor( EXC_COLOR_CHWINDOWTEXT );
     245             : }
     246             : 
     247           4 : Color XclImpChRoot::GetSeriesLineAutoColor( sal_uInt16 nFormatIdx ) const
     248             : {
     249           4 :     return GetPalette().GetColor( XclChartHelper::GetSeriesLineAutoColorIdx( nFormatIdx ) );
     250             : }
     251             : 
     252           4 : Color XclImpChRoot::GetSeriesFillAutoColor( sal_uInt16 nFormatIdx ) const
     253             : {
     254           4 :     const XclImpPalette& rPal = GetPalette();
     255           4 :     Color aColor = rPal.GetColor( XclChartHelper::GetSeriesFillAutoColorIdx( nFormatIdx ) );
     256           4 :     sal_uInt8 nTrans = XclChartHelper::GetSeriesFillAutoTransp( nFormatIdx );
     257           4 :     return ScfTools::GetMixedColor( aColor, rPal.GetColor( EXC_COLOR_CHWINDOWBACK ), nTrans );
     258             : }
     259             : 
     260          88 : void XclImpChRoot::InitConversion( const Reference<XChartDocument>& xChartDoc, const Rectangle& rChartRect ) const
     261             : {
     262             :     // create formatting object tables
     263          88 :     mxChData->InitConversion( GetRoot(), xChartDoc, rChartRect );
     264             : 
     265             :     // lock the model to suppress any internal updates
     266          88 :     if( xChartDoc.is() )
     267          88 :         xChartDoc->lockControllers();
     268             : 
     269          88 :     SfxObjectShell* pDocShell = GetDocShell();
     270          88 :     Reference< XDataReceiver > xDataRec( xChartDoc, UNO_QUERY );
     271          88 :     if( pDocShell && xDataRec.is() )
     272             :     {
     273             :         // create and register a data provider
     274             :         Reference< XDataProvider > xDataProv(
     275          88 :             ScfApiHelper::CreateInstance( pDocShell, SERVICE_CHART2_DATAPROVIDER ), UNO_QUERY );
     276          88 :         if( xDataProv.is() )
     277          88 :             xDataRec->attachDataProvider( xDataProv );
     278             :         // attach the number formatter
     279         176 :         Reference< XNumberFormatsSupplier > xNumFmtSupp( pDocShell->GetModel(), UNO_QUERY );
     280          88 :         if( xNumFmtSupp.is() )
     281         176 :             xDataRec->attachNumberFormatsSupplier( xNumFmtSupp );
     282          88 :     }
     283          88 : }
     284             : 
     285          88 : void XclImpChRoot::FinishConversion( XclImpDffConverter& rDffConv ) const
     286             : {
     287          88 :     rDffConv.Progress( EXC_CHART_PROGRESS_SIZE );
     288             :     // unlock the model
     289          88 :     Reference< XModel > xModel( mxChData->mxChartDoc, UNO_QUERY );
     290          88 :     if( xModel.is() )
     291          88 :         xModel->unlockControllers();
     292          88 :     rDffConv.Progress( EXC_CHART_PROGRESS_SIZE );
     293             : 
     294          88 :     mxChData->FinishConversion();
     295          88 : }
     296             : 
     297         272 : Reference< XDataProvider > XclImpChRoot::GetDataProvider() const
     298             : {
     299         272 :     return mxChData->mxChartDoc->getDataProvider();
     300             : }
     301             : 
     302          40 : Reference< XShape > XclImpChRoot::GetTitleShape( const XclChTextKey& rTitleKey ) const
     303             : {
     304          40 :     return mxChData->GetTitleShape( rTitleKey );
     305             : }
     306             : 
     307         236 : sal_Int32 XclImpChRoot::CalcHmmFromChartX( sal_Int32 nPosX ) const
     308             : {
     309         236 :     return static_cast< sal_Int32 >( mxChData->mfUnitSizeX * nPosX + mxChData->mnBorderGapX + 0.5 );
     310             : }
     311             : 
     312         236 : sal_Int32 XclImpChRoot::CalcHmmFromChartY( sal_Int32 nPosY ) const
     313             : {
     314         236 :     return static_cast< sal_Int32 >( mxChData->mfUnitSizeY * nPosY + mxChData->mnBorderGapY + 0.5 );
     315             : }
     316             : 
     317          78 : ::com::sun::star::awt::Rectangle XclImpChRoot::CalcHmmFromChartRect( const XclChRectangle& rRect ) const
     318             : {
     319             :     return ::com::sun::star::awt::Rectangle(
     320          78 :         CalcHmmFromChartX( rRect.mnX ),
     321          78 :         CalcHmmFromChartY( rRect.mnY ),
     322          78 :         CalcHmmFromChartX( rRect.mnWidth ),
     323         312 :         CalcHmmFromChartY( rRect.mnHeight ) );
     324             : }
     325             : 
     326          78 : double XclImpChRoot::CalcRelativeFromHmmX( sal_Int32 nPosX ) const
     327             : {
     328          78 :     const long nWidth = mxChData->maChartRect.GetWidth();
     329          78 :     if (!nWidth)
     330           0 :         throw o3tl::divide_by_zero();
     331          78 :     return static_cast<double>(nPosX) / nWidth;
     332             : }
     333             : 
     334          78 : double XclImpChRoot::CalcRelativeFromHmmY( sal_Int32 nPosY ) const
     335             : {
     336          78 :     const long nHeight = mxChData->maChartRect.GetHeight();
     337          78 :     if (!nHeight)
     338           0 :         throw o3tl::divide_by_zero();
     339          78 :     return static_cast<double >(nPosY) / nHeight;
     340             : }
     341             : 
     342          40 : double XclImpChRoot::CalcRelativeFromChartX( sal_Int32 nPosX ) const
     343             : {
     344          40 :     return CalcRelativeFromHmmX( CalcHmmFromChartX( nPosX ) );
     345             : }
     346             : 
     347          40 : double XclImpChRoot::CalcRelativeFromChartY( sal_Int32 nPosY ) const
     348             : {
     349          40 :     return CalcRelativeFromHmmY( CalcHmmFromChartY( nPosY ) );
     350             : }
     351             : 
     352         660 : void XclImpChRoot::ConvertLineFormat( ScfPropertySet& rPropSet,
     353             :         const XclChLineFormat& rLineFmt, XclChPropertyMode ePropMode ) const
     354             : {
     355         660 :     GetChartPropSetHelper().WriteLineProperties(
     356        1320 :         rPropSet, *mxChData->mxLineDashTable, rLineFmt, ePropMode );
     357         660 : }
     358             : 
     359         272 : void XclImpChRoot::ConvertAreaFormat( ScfPropertySet& rPropSet,
     360             :         const XclChAreaFormat& rAreaFmt, XclChPropertyMode ePropMode ) const
     361             : {
     362         272 :     GetChartPropSetHelper().WriteAreaProperties( rPropSet, rAreaFmt, ePropMode );
     363         272 : }
     364             : 
     365         300 : void XclImpChRoot::ConvertEscherFormat( ScfPropertySet& rPropSet,
     366             :         const XclChEscherFormat& rEscherFmt, const XclChPicFormat* pPicFmt,
     367             :         sal_uInt32 nDffFillType, XclChPropertyMode ePropMode ) const
     368             : {
     369         300 :     GetChartPropSetHelper().WriteEscherProperties( rPropSet,
     370         300 :         *mxChData->mxGradientTable, *mxChData->mxHatchTable, *mxChData->mxBitmapTable,
     371         300 :         rEscherFmt, pPicFmt, nDffFillType, ePropMode );
     372         300 : }
     373             : 
     374         386 : void XclImpChRoot::ConvertFont( ScfPropertySet& rPropSet,
     375             :         sal_uInt16 nFontIdx, const Color* pFontColor ) const
     376             : {
     377         386 :     GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CHART, nFontIdx, pFontColor );
     378         386 : }
     379             : 
     380          74 : void XclImpChRoot::ConvertPieRotation( ScfPropertySet& rPropSet, sal_uInt16 nAngle )
     381             : {
     382          74 :     sal_Int32 nApiRot = (450 - (nAngle % 360)) % 360;
     383          74 :     rPropSet.SetProperty( EXC_CHPROP_STARTINGANGLE, nApiRot );
     384          74 : }
     385             : 
     386        2148 : XclImpChGroupBase::~XclImpChGroupBase()
     387             : {
     388        2148 : }
     389             : 
     390        1564 : void XclImpChGroupBase::ReadRecordGroup( XclImpStream& rStrm )
     391             : {
     392             :     // read contents of the header record
     393        1564 :     ReadHeaderRecord( rStrm );
     394             : 
     395             :     // only read sub records, if the next record is a CHBEGIN
     396        1564 :     if( rStrm.GetNextRecId() == EXC_ID_CHBEGIN )
     397             :     {
     398             :         // read the CHBEGIN record, may be used for special initial processing
     399        1374 :         rStrm.StartNextRecord();
     400        1374 :         ReadSubRecord( rStrm );
     401             : 
     402             :         // read the nested records
     403        1374 :         bool bLoop = true;
     404       13170 :         while( bLoop && rStrm.StartNextRecord() )
     405             :         {
     406       10422 :             sal_uInt16 nRecId = rStrm.GetRecId();
     407       10422 :             bLoop = nRecId != EXC_ID_CHEND;
     408             :             // skip unsupported nested blocks
     409       10422 :             if( nRecId == EXC_ID_CHBEGIN )
     410          60 :                 SkipBlock( rStrm );
     411             :             else
     412       10362 :                 ReadSubRecord( rStrm );
     413             :         }
     414             :     }
     415             :     /*  Returns with current CHEND record or unchanged stream, if no record
     416             :         group present. In every case another call to StartNextRecord() will go
     417             :         to next record of interest. */
     418        1564 : }
     419             : 
     420         120 : void XclImpChGroupBase::SkipBlock( XclImpStream& rStrm )
     421             : {
     422             :     OSL_ENSURE( rStrm.GetRecId() == EXC_ID_CHBEGIN, "XclImpChGroupBase::SkipBlock - no CHBEGIN record" );
     423             :     // do nothing if current record is not CHBEGIN
     424         120 :     bool bLoop = rStrm.GetRecId() == EXC_ID_CHBEGIN;
     425         840 :     while( bLoop && rStrm.StartNextRecord() )
     426             :     {
     427         600 :         sal_uInt16 nRecId = rStrm.GetRecId();
     428         600 :         bLoop = nRecId != EXC_ID_CHEND;
     429             :         // skip nested record groups
     430         600 :         if( nRecId == EXC_ID_CHBEGIN )
     431          60 :             SkipBlock( rStrm );
     432             :     }
     433         120 : }
     434             : 
     435             : // Frame formatting ===========================================================
     436             : 
     437         510 : void XclImpChFramePos::ReadChFramePos( XclImpStream& rStrm )
     438             : {
     439         510 :     rStrm >> maData.mnTLMode >> maData.mnBRMode;
     440             :     /*  According to the spec, the upper 16 bits of all members in the
     441             :         rectangle are unused and may contain garbage. */
     442         510 :     maData.maRect.mnX = rStrm.ReadInt16(); rStrm.Ignore( 2 );
     443         510 :     maData.maRect.mnY = rStrm.ReadInt16(); rStrm.Ignore( 2 );
     444         510 :     maData.maRect.mnWidth = rStrm.ReadInt16(); rStrm.Ignore( 2 );
     445         510 :     maData.maRect.mnHeight = rStrm.ReadInt16(); rStrm.Ignore( 2 );
     446         510 : }
     447             : 
     448         566 : void XclImpChLineFormat::ReadChLineFormat( XclImpStream& rStrm )
     449             : {
     450         566 :     rStrm >> maData.maColor >> maData.mnPattern >> maData.mnWeight >> maData.mnFlags;
     451             : 
     452         566 :     const XclImpRoot& rRoot = rStrm.GetRoot();
     453         566 :     if( rRoot.GetBiff() == EXC_BIFF8 )
     454             :         // BIFF8: index into palette used instead of RGB data
     455         566 :         maData.maColor = rRoot.GetPalette().GetColor( rStrm.ReaduInt16() );
     456         566 : }
     457             : 
     458         660 : void XclImpChLineFormat::Convert( const XclImpChRoot& rRoot,
     459             :         ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
     460             : {
     461         660 :     const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
     462         660 :     if( IsAuto() )
     463             :     {
     464         196 :         XclChLineFormat aLineFmt;
     465             :         aLineFmt.maColor = (eObjType == EXC_CHOBJTYPE_LINEARSERIES) ?
     466           2 :             rRoot.GetSeriesLineAutoColor( nFormatIdx ) :
     467         198 :             rRoot.GetPalette().GetColor( rFmtInfo.mnAutoLineColorIdx );
     468         196 :         aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;
     469         196 :         aLineFmt.mnWeight = rFmtInfo.mnAutoLineWeight;
     470         196 :         rRoot.ConvertLineFormat( rPropSet, aLineFmt, rFmtInfo.mePropMode );
     471             :     }
     472             :     else
     473             :     {
     474         464 :         rRoot.ConvertLineFormat( rPropSet, maData, rFmtInfo.mePropMode );
     475             :     }
     476         660 : }
     477             : 
     478         534 : void XclImpChAreaFormat::ReadChAreaFormat( XclImpStream& rStrm )
     479             : {
     480         534 :     rStrm >> maData.maPattColor >> maData.maBackColor >> maData.mnPattern >> maData.mnFlags;
     481             : 
     482         534 :     const XclImpRoot& rRoot = rStrm.GetRoot();
     483         534 :     if( rRoot.GetBiff() == EXC_BIFF8 )
     484             :     {
     485             :         // BIFF8: index into palette used instead of RGB data
     486         534 :         const XclImpPalette& rPal = rRoot.GetPalette();
     487         534 :         maData.maPattColor = rPal.GetColor( rStrm.ReaduInt16() );
     488         534 :         maData.maBackColor = rPal.GetColor( rStrm.ReaduInt16());
     489             :     }
     490         534 : }
     491             : 
     492         272 : void XclImpChAreaFormat::Convert( const XclImpChRoot& rRoot,
     493             :         ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
     494             : {
     495         272 :     const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
     496         272 :     if( IsAuto() )
     497             :     {
     498          20 :         XclChAreaFormat aAreaFmt;
     499             :         aAreaFmt.maPattColor = (eObjType == EXC_CHOBJTYPE_FILLEDSERIES) ?
     500           4 :             rRoot.GetSeriesFillAutoColor( nFormatIdx ) :
     501          24 :             rRoot.GetPalette().GetColor( rFmtInfo.mnAutoPattColorIdx );
     502          20 :         aAreaFmt.mnPattern = EXC_PATT_SOLID;
     503          20 :         rRoot.ConvertAreaFormat( rPropSet, aAreaFmt, rFmtInfo.mePropMode );
     504             :     }
     505             :     else
     506             :     {
     507         252 :         rRoot.ConvertAreaFormat( rPropSet, maData, rFmtInfo.mePropMode );
     508             :     }
     509         272 : }
     510             : 
     511         190 : XclImpChEscherFormat::XclImpChEscherFormat( const XclImpRoot& rRoot ) :
     512         190 :     mnDffFillType( mso_fillSolid )
     513             : {
     514             :     maData.mxItemSet.reset(
     515         190 :         new SfxItemSet( rRoot.GetDoc().GetDrawLayer()->GetItemPool() ) );
     516         190 : }
     517             : 
     518         190 : void XclImpChEscherFormat::ReadHeaderRecord( XclImpStream& rStrm )
     519             : {
     520             :     // read from stream - CHESCHERFORMAT uses own ID for record continuation
     521         190 :     XclImpDffPropSet aPropSet( rStrm.GetRoot() );
     522         190 :     rStrm.ResetRecord( true, rStrm.GetRecId() );
     523         190 :     rStrm >> aPropSet;
     524             :     // get the data
     525         190 :     aPropSet.FillToItemSet( *maData.mxItemSet );
     526             :     // get fill type from DFF property set
     527         190 :     mnDffFillType = aPropSet.GetPropertyValue( DFF_Prop_fillType, mso_fillSolid );
     528         190 : }
     529             : 
     530           0 : void XclImpChEscherFormat::ReadSubRecord( XclImpStream& rStrm )
     531             : {
     532           0 :     switch( rStrm.GetRecId() )
     533             :     {
     534             :         case EXC_ID_CHPICFORMAT:
     535           0 :             rStrm >> maPicFmt.mnBmpMode;
     536           0 :             rStrm.Ignore( 2 );
     537           0 :             rStrm >> maPicFmt.mnFlags >> maPicFmt.mfScale;
     538           0 :         break;
     539             :     }
     540           0 : }
     541             : 
     542         300 : void XclImpChEscherFormat::Convert( const XclImpChRoot& rRoot,
     543             :         ScfPropertySet& rPropSet, XclChObjectType eObjType, bool bUsePicFmt ) const
     544             : {
     545         300 :     const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
     546         300 :     rRoot.ConvertEscherFormat( rPropSet, maData, bUsePicFmt ? &maPicFmt : 0, mnDffFillType, rFmtInfo.mePropMode );
     547         300 : }
     548             : 
     549         554 : XclImpChFrameBase::XclImpChFrameBase( const XclChFormatInfo& rFmtInfo )
     550             : {
     551         554 :     if( rFmtInfo.mbCreateDefFrame ) switch( rFmtInfo.meDefFrameType )
     552             :     {
     553             :         case EXC_CHFRAMETYPE_AUTO:
     554         222 :             mxLineFmt.reset( new XclImpChLineFormat );
     555         222 :             if( rFmtInfo.mbIsFrame )
     556         222 :                 mxAreaFmt.reset( new XclImpChAreaFormat );
     557         222 :         break;
     558             :         case EXC_CHFRAMETYPE_INVISIBLE:
     559             :         {
     560         176 :             XclChLineFormat aLineFmt;
     561         176 :             ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_AUTO, false );
     562         176 :             aLineFmt.mnPattern = EXC_CHLINEFORMAT_NONE;
     563         176 :             mxLineFmt.reset( new XclImpChLineFormat( aLineFmt ) );
     564         176 :             if( rFmtInfo.mbIsFrame )
     565             :             {
     566         176 :                 XclChAreaFormat aAreaFmt;
     567         176 :                 ::set_flag( aAreaFmt.mnFlags, EXC_CHAREAFORMAT_AUTO, false );
     568         176 :                 aAreaFmt.mnPattern = EXC_PATT_NONE;
     569         176 :                 mxAreaFmt.reset( new XclImpChAreaFormat( aAreaFmt ) );
     570             :             }
     571             :         }
     572         176 :         break;
     573             :         default:
     574             :             OSL_FAIL( "XclImpChFrameBase::XclImpChFrameBase - unknown frame type" );
     575             :     }
     576         554 : }
     577             : 
     578        4164 : void XclImpChFrameBase::ReadSubRecord( XclImpStream& rStrm )
     579             : {
     580        4164 :     switch( rStrm.GetRecId() )
     581             :     {
     582             :         case EXC_ID_CHLINEFORMAT:
     583         542 :             mxLineFmt.reset( new XclImpChLineFormat );
     584         542 :             mxLineFmt->ReadChLineFormat( rStrm );
     585         542 :         break;
     586             :         case EXC_ID_CHAREAFORMAT:
     587         534 :             mxAreaFmt.reset( new XclImpChAreaFormat );
     588         534 :             mxAreaFmt->ReadChAreaFormat( rStrm );
     589         534 :         break;
     590             :         case EXC_ID_CHESCHERFORMAT:
     591         190 :             mxEscherFmt.reset( new XclImpChEscherFormat( rStrm.GetRoot() ) );
     592         190 :             mxEscherFmt->ReadRecordGroup( rStrm );
     593         190 :         break;
     594             :     }
     595        4164 : }
     596             : 
     597         472 : void XclImpChFrameBase::ConvertLineBase( const XclImpChRoot& rRoot,
     598             :         ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
     599             : {
     600         472 :     if( mxLineFmt )
     601         472 :         mxLineFmt->Convert( rRoot, rPropSet, eObjType, nFormatIdx );
     602         472 : }
     603             : 
     604         576 : void XclImpChFrameBase::ConvertAreaBase( const XclImpChRoot& rRoot,
     605             :         ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx, bool bUsePicFmt ) const
     606             : {
     607         576 :     if( rRoot.GetFormatInfo( eObjType ).mbIsFrame )
     608             :     {
     609             :         // CHESCHERFORMAT overrides CHAREAFORMAT (even if it is auto)
     610         572 :         if( mxEscherFmt )
     611         300 :             mxEscherFmt->Convert( rRoot, rPropSet, eObjType, bUsePicFmt );
     612         272 :         else if( mxAreaFmt )
     613         272 :             mxAreaFmt->Convert( rRoot, rPropSet, eObjType, nFormatIdx );
     614             :     }
     615         576 : }
     616             : 
     617         466 : void XclImpChFrameBase::ConvertFrameBase( const XclImpChRoot& rRoot,
     618             :         ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx, bool bUsePicFmt ) const
     619             : {
     620         466 :     ConvertLineBase( rRoot, rPropSet, eObjType, nFormatIdx );
     621         466 :     ConvertAreaBase( rRoot, rPropSet, eObjType, nFormatIdx, bUsePicFmt );
     622         466 : }
     623             : 
     624         554 : XclImpChFrame::XclImpChFrame( const XclImpChRoot& rRoot, XclChObjectType eObjType ) :
     625         554 :     XclImpChFrameBase( rRoot.GetFormatInfo( eObjType ) ),
     626             :     XclImpChRoot( rRoot ),
     627         554 :     meObjType( eObjType )
     628             : {
     629         554 : }
     630             : 
     631         298 : void XclImpChFrame::ReadHeaderRecord( XclImpStream& rStrm )
     632             : {
     633         298 :     rStrm >> maData.mnFormat >> maData.mnFlags;
     634         298 : }
     635             : 
     636           0 : void XclImpChFrame::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
     637             : {
     638           0 :     const XclImpPalette& rPal = GetPalette();
     639             : 
     640           0 :     if( rLineData.IsVisible() && (!mxLineFmt || !mxLineFmt->HasLine()) )
     641             :     {
     642             :         // line formatting
     643           0 :         XclChLineFormat aLineFmt;
     644           0 :         aLineFmt.maColor = rPal.GetColor( rLineData.mnColorIdx );
     645           0 :         switch( rLineData.mnStyle )
     646             :         {
     647           0 :             case EXC_OBJ_LINE_SOLID:        aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;        break;
     648           0 :             case EXC_OBJ_LINE_DASH:         aLineFmt.mnPattern = EXC_CHLINEFORMAT_DASH;         break;
     649           0 :             case EXC_OBJ_LINE_DOT:          aLineFmt.mnPattern = EXC_CHLINEFORMAT_DOT;          break;
     650           0 :             case EXC_OBJ_LINE_DASHDOT:      aLineFmt.mnPattern = EXC_CHLINEFORMAT_DASHDOT;      break;
     651           0 :             case EXC_OBJ_LINE_DASHDOTDOT:   aLineFmt.mnPattern = EXC_CHLINEFORMAT_DASHDOTDOT;   break;
     652           0 :             case EXC_OBJ_LINE_MEDTRANS:     aLineFmt.mnPattern = EXC_CHLINEFORMAT_MEDTRANS;     break;
     653           0 :             case EXC_OBJ_LINE_DARKTRANS:    aLineFmt.mnPattern = EXC_CHLINEFORMAT_DARKTRANS;    break;
     654           0 :             case EXC_OBJ_LINE_LIGHTTRANS:   aLineFmt.mnPattern = EXC_CHLINEFORMAT_LIGHTTRANS;   break;
     655           0 :             case EXC_OBJ_LINE_NONE:         aLineFmt.mnPattern = EXC_CHLINEFORMAT_NONE;         break;
     656           0 :             default:                        aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;
     657             :         }
     658           0 :         switch( rLineData.mnWidth )
     659             :         {
     660           0 :             case EXC_OBJ_LINE_HAIR:     aLineFmt.mnWeight = EXC_CHLINEFORMAT_HAIR;      break;
     661           0 :             case EXC_OBJ_LINE_THIN:     aLineFmt.mnWeight = EXC_CHLINEFORMAT_SINGLE;    break;
     662           0 :             case EXC_OBJ_LINE_MEDIUM:   aLineFmt.mnWeight = EXC_CHLINEFORMAT_DOUBLE;    break;
     663           0 :             case EXC_OBJ_LINE_THICK:    aLineFmt.mnWeight = EXC_CHLINEFORMAT_TRIPLE;    break;
     664           0 :             default:                    aLineFmt.mnWeight = EXC_CHLINEFORMAT_HAIR;
     665             :         }
     666           0 :         ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_AUTO, rLineData.IsAuto() );
     667           0 :         mxLineFmt.reset( new XclImpChLineFormat( aLineFmt ) );
     668             :     }
     669             : 
     670           0 :     if( rFillData.IsFilled() && (!mxAreaFmt || !mxAreaFmt->HasArea()) && !mxEscherFmt )
     671             :     {
     672             :         // area formatting
     673           0 :         XclChAreaFormat aAreaFmt;
     674           0 :         aAreaFmt.maPattColor = rPal.GetColor( rFillData.mnPattColorIdx );
     675           0 :         aAreaFmt.maBackColor = rPal.GetColor( rFillData.mnBackColorIdx );
     676           0 :         aAreaFmt.mnPattern = rFillData.mnPattern;
     677           0 :         ::set_flag( aAreaFmt.mnFlags, EXC_CHAREAFORMAT_AUTO, rFillData.IsAuto() );
     678           0 :         mxAreaFmt.reset( new XclImpChAreaFormat( aAreaFmt ) );
     679             :     }
     680           0 : }
     681             : 
     682         260 : void XclImpChFrame::Convert( ScfPropertySet& rPropSet, bool bUsePicFmt ) const
     683             : {
     684         260 :     ConvertFrameBase( GetChRoot(), rPropSet, meObjType, EXC_CHDATAFORMAT_UNKNOWN, bUsePicFmt );
     685         260 : }
     686             : 
     687             : // Source links ===============================================================
     688             : 
     689             : namespace {
     690             : 
     691             : /** Creates a labeled data sequence object, adds link for series title if present. */
     692         180 : Reference< XLabeledDataSequence > lclCreateLabeledDataSequence(
     693             :         const XclImpChSourceLinkRef& xValueLink, const OUString& rValueRole,
     694             :         const XclImpChSourceLink* pTitleLink = 0 )
     695             : {
     696             :     // create data sequence for values and title
     697         180 :     Reference< XDataSequence > xValueSeq;
     698         180 :     if( xValueLink )
     699         180 :         xValueSeq = xValueLink->CreateDataSequence( rValueRole );
     700         360 :     Reference< XDataSequence > xTitleSeq;
     701         180 :     if( pTitleLink )
     702          92 :         xTitleSeq = pTitleLink->CreateDataSequence( EXC_CHPROP_ROLE_LABEL );
     703             : 
     704             :     // create the labeled data sequence, if values or title are present
     705         180 :     Reference< XLabeledDataSequence > xLabeledSeq;
     706         180 :     if( xValueSeq.is() || xTitleSeq.is() )
     707         140 :         xLabeledSeq.set( LabeledDataSequence::create(comphelper::getProcessComponentContext()), UNO_QUERY );
     708         180 :     if( xLabeledSeq.is() )
     709             :     {
     710         140 :         if( xValueSeq.is() )
     711         140 :             xLabeledSeq->setValues( xValueSeq );
     712         140 :         if( xTitleSeq.is() )
     713          54 :             xLabeledSeq->setLabel( xTitleSeq );
     714             :     }
     715         360 :     return xLabeledSeq;
     716             : }
     717             : 
     718             : } // namespace
     719             : 
     720         782 : XclImpChSourceLink::XclImpChSourceLink( const XclImpChRoot& rRoot ) :
     721         782 :     XclImpChRoot( rRoot )
     722             : {
     723         782 : }
     724             : 
     725        1564 : XclImpChSourceLink::~XclImpChSourceLink()
     726             : {
     727        1564 : }
     728             : 
     729         776 : void XclImpChSourceLink::ReadChSourceLink( XclImpStream& rStrm )
     730             : {
     731         776 :     rStrm   >> maData.mnDestType
     732        1552 :             >> maData.mnLinkType
     733        1552 :             >> maData.mnFlags
     734        1552 :             >> maData.mnNumFmtIdx;
     735             : 
     736         776 :     mxTokenArray.reset();
     737         776 :     if( GetLinkType() == EXC_CHSRCLINK_WORKSHEET )
     738             :     {
     739             :         // read token array
     740         194 :         XclTokenArray aXclTokArr;
     741         194 :         rStrm >> aXclTokArr;
     742             : 
     743             :         // convert BIFF formula tokens to Calc token array
     744         194 :         if( const ScTokenArray* pTokens = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CHART, aXclTokArr ) )
     745         194 :             mxTokenArray.reset( pTokens->Clone() );
     746             :     }
     747             : 
     748             :     // try to read a following CHSTRING record
     749         776 :     if( (rStrm.GetNextRecId() == EXC_ID_CHSTRING) && rStrm.StartNextRecord() )
     750             :     {
     751          80 :         mxString.reset( new XclImpString );
     752          80 :         rStrm.Ignore( 2 );
     753          80 :         mxString->Read( rStrm, EXC_STR_8BITLENGTH | EXC_STR_SEPARATEFORMATS );
     754             :     }
     755         776 : }
     756             : 
     757          46 : void XclImpChSourceLink::SetString( const OUString& rString )
     758             : {
     759          46 :     if( !mxString )
     760          46 :         mxString.reset( new XclImpString );
     761          46 :     mxString->SetText( rString );
     762          46 : }
     763             : 
     764           0 : void XclImpChSourceLink::SetTextFormats( const XclFormatRunVec& rFormats )
     765             : {
     766           0 :     if( mxString )
     767           0 :         mxString->SetFormats( rFormats );
     768           0 : }
     769             : 
     770          74 : sal_uInt16 XclImpChSourceLink::GetCellCount() const
     771             : {
     772          74 :     sal_uInt32 nCellCount = 0;
     773          74 :     if( mxTokenArray )
     774             :     {
     775          74 :         mxTokenArray->Reset();
     776         148 :         for( const FormulaToken* pToken = mxTokenArray->First(); pToken; pToken = mxTokenArray->Next() )
     777             :         {
     778          74 :             switch( pToken->GetType() )
     779             :             {
     780             :                 case ::formula::svSingleRef:
     781             :                 case ::formula::svExternalSingleRef:
     782             :                     // single cell
     783          38 :                     ++nCellCount;
     784          38 :                 break;
     785             :                 case ::formula::svDoubleRef:
     786             :                 case ::formula::svExternalDoubleRef:
     787             :                 {
     788             :                     // cell range
     789          36 :                     const ScComplexRefData& rComplexRef = *pToken->GetDoubleRef();
     790          36 :                     ScAddress aAbs1 = rComplexRef.Ref1.toAbs(ScAddress());
     791          36 :                     ScAddress aAbs2 = rComplexRef.Ref2.toAbs(ScAddress());
     792          36 :                     sal_uInt32 nTabs = static_cast<sal_uInt32>(aAbs2.Tab() - aAbs1.Tab() + 1);
     793          36 :                     sal_uInt32 nCols = static_cast<sal_uInt32>(aAbs2.Col() - aAbs1.Col() + 1);
     794          36 :                     sal_uInt32 nRows = static_cast<sal_uInt32>(aAbs2.Row() - aAbs1.Row() + 1);
     795          36 :                     nCellCount += nCols * nRows * nTabs;
     796             :                 }
     797          36 :                 break;
     798             :                 default: ;
     799             :             }
     800             :         }
     801             :     }
     802          74 :     return limit_cast< sal_uInt16 >( nCellCount );
     803             : }
     804             : 
     805          96 : void XclImpChSourceLink::ConvertNumFmt( ScfPropertySet& rPropSet, bool bPercent ) const
     806             : {
     807          96 :     bool bLinkToSource = ::get_flag( maData.mnFlags, EXC_CHSRCLINK_NUMFMT );
     808          96 :     sal_uInt32 nScNumFmt = bLinkToSource ? GetNumFmtBuffer().GetScFormat( maData.mnNumFmtIdx ) : NUMBERFORMAT_ENTRY_NOT_FOUND;
     809          96 :     OUString aPropName = bPercent ? OUString( EXC_CHPROP_PERCENTAGENUMFMT ) : OUString( EXC_CHPROP_NUMBERFORMAT );
     810          96 :     if( nScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND )
     811           2 :         rPropSet.SetProperty( aPropName, static_cast< sal_Int32 >( nScNumFmt ) );
     812             :     else
     813             :         // restore 'link to source' at data point (series may contain manual number format)
     814          94 :         rPropSet.SetAnyProperty( aPropName, Any() );
     815          96 : }
     816             : 
     817         272 : Reference< XDataSequence > XclImpChSourceLink::CreateDataSequence( const OUString& rRole ) const
     818             : {
     819         272 :     Reference< XDataSequence > xDataSeq;
     820         544 :     Reference< XDataProvider > xDataProv = GetDataProvider();
     821         272 :     if( xDataProv.is() && mxTokenArray )
     822             :     {
     823         194 :         ScCompiler aComp( GetDocPtr(), ScAddress(), *mxTokenArray );
     824         194 :         aComp.SetGrammar(GetDoc().GetGrammar());
     825         388 :         OUStringBuffer aRangeRep;
     826         194 :         aComp.CreateStringFromTokenArray( aRangeRep );
     827             :         try
     828             :         {
     829         194 :             xDataSeq = xDataProv->createDataSequenceByRangeRepresentation( aRangeRep.makeStringAndClear() );
     830             :             // set sequence role
     831         194 :             ScfPropertySet aSeqProp( xDataSeq );
     832         194 :             aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole );
     833             :         }
     834           0 :         catch( Exception& )
     835             :         {
     836             : //            OSL_FAIL( "XclImpChSourceLink::CreateDataSequence - cannot create data sequence" );
     837         194 :         }
     838             :     }
     839          78 :     else if( rRole == EXC_CHPROP_ROLE_LABEL && mxString && !mxString->GetText().isEmpty() )
     840             :     {
     841             :         try
     842             :         {
     843           0 :             OUString aString("\"");
     844           0 :             xDataSeq = xDataProv->createDataSequenceByRangeRepresentation( aString + mxString->GetText() + aString );
     845             :             // set sequence role
     846           0 :             ScfPropertySet aSeqProp( xDataSeq );
     847           0 :             aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole );
     848             :         }
     849           0 :         catch( Exception& ) { }
     850             :     }
     851         544 :     return xDataSeq;
     852             : }
     853             : 
     854          42 : Sequence< Reference< XFormattedString > > XclImpChSourceLink::CreateStringSequence(
     855             :         const XclImpChRoot& rRoot, sal_uInt16 nLeadFontIdx, const Color& rLeadFontColor ) const
     856             : {
     857          42 :     ::std::vector< Reference< XFormattedString > > aStringVec;
     858          42 :     if( mxString )
     859             :     {
     860          84 :         for( XclImpStringIterator aIt( *mxString ); aIt.Is(); ++aIt )
     861             :         {
     862          42 :             Reference< css::chart2::XFormattedString2 > xFmtStr = css::chart2::FormattedString::create( comphelper::getProcessComponentContext() );
     863             :             // set text data
     864          42 :             xFmtStr->setString( aIt.GetPortionText() );
     865             : 
     866             :             // set font formatting and font color
     867          84 :             ScfPropertySet aStringProp( xFmtStr );
     868          42 :             sal_uInt16 nFontIdx = aIt.GetPortionFont();
     869          42 :             if( (nFontIdx == EXC_FONT_NOTFOUND) && (aIt.GetPortionIndex() == 0) )
     870             :                 // leading unformatted portion - use passed font settings
     871          42 :                 rRoot.ConvertFont( aStringProp, nLeadFontIdx, &rLeadFontColor );
     872             :             else
     873           0 :                 rRoot.ConvertFont( aStringProp, nFontIdx );
     874             : 
     875             :             // add string to vector of strings
     876          42 :             aStringVec.push_back( xFmtStr );
     877          42 :         }
     878             :     }
     879          42 :     return ScfApiHelper::VectorToSequence( aStringVec );
     880             : }
     881             : 
     882         392 : void XclImpChSourceLink::FillSourceLink( ::std::vector< ScTokenRef >& rTokens ) const
     883             : {
     884         392 :     if( !mxTokenArray )
     885             :         // no links to fill.
     886         590 :         return;
     887             : 
     888         194 :     mxTokenArray->Reset();
     889         388 :     for (FormulaToken* p = mxTokenArray->First(); p; p = mxTokenArray->Next())
     890             :     {
     891         194 :         ScTokenRef pToken(p->Clone());
     892         194 :         if (ScRefTokenHelper::isRef(pToken))
     893             :             // This is a reference token.  Store it.
     894         194 :             ScRefTokenHelper::join(rTokens, pToken, ScAddress());
     895         194 :     }
     896             : }
     897             : 
     898             : // Text =======================================================================
     899             : 
     900         570 : XclImpChFontBase::~XclImpChFontBase()
     901             : {
     902         570 : }
     903             : 
     904         344 : void XclImpChFontBase::ConvertFontBase( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet ) const
     905             : {
     906         344 :     Color aFontColor = GetFontColor();
     907         344 :     rRoot.ConvertFont( rPropSet, GetFontIndex(), &aFontColor );
     908         344 : }
     909             : 
     910         336 : void XclImpChFontBase::ConvertRotationBase( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet, bool bSupportsStacked ) const
     911             : {
     912         336 :     rRoot.GetChartPropSetHelper().WriteRotationProperties( rPropSet, GetRotation(), bSupportsStacked );
     913         336 : }
     914             : 
     915         386 : XclImpChFont::XclImpChFont() :
     916         386 :     mnFontIdx( EXC_FONT_NOTFOUND )
     917             : {
     918         386 : }
     919             : 
     920         386 : void XclImpChFont::ReadChFont( XclImpStream& rStrm )
     921             : {
     922         386 :     rStrm >> mnFontIdx;
     923         386 : }
     924             : 
     925         394 : XclImpChText::XclImpChText( const XclImpChRoot& rRoot ) :
     926         394 :     XclImpChRoot( rRoot )
     927             : {
     928         394 : }
     929             : 
     930         394 : void XclImpChText::ReadHeaderRecord( XclImpStream& rStrm )
     931             : {
     932         394 :     rStrm   >> maData.mnHAlign
     933         788 :             >> maData.mnVAlign
     934         788 :             >> maData.mnBackMode
     935         788 :             >> maData.maTextColor
     936         788 :             >> maData.maRect
     937         788 :             >> maData.mnFlags;
     938             : 
     939         394 :     if( GetBiff() == EXC_BIFF8 )
     940             :     {
     941             :         // BIFF8: index into palette used instead of RGB data
     942         394 :         maData.maTextColor = GetPalette().GetColor( rStrm.ReaduInt16() );
     943             :         // placement and rotation
     944         394 :         rStrm >> maData.mnFlags2 >> maData.mnRotation;
     945             :     }
     946             :     else
     947             :     {
     948             :         // BIFF2-BIFF7: get rotation from text orientation
     949           0 :         sal_uInt8 nOrient = ::extract_value< sal_uInt8 >( maData.mnFlags, 8, 3 );
     950           0 :         maData.mnRotation = XclTools::GetXclRotFromOrient( nOrient );
     951             :     }
     952         394 : }
     953             : 
     954        2916 : void XclImpChText::ReadSubRecord( XclImpStream& rStrm )
     955             : {
     956        2916 :     switch( rStrm.GetRecId() )
     957             :     {
     958             :         case EXC_ID_CHFRAMEPOS:
     959         380 :             mxFramePos.reset( new XclImpChFramePos );
     960         380 :             mxFramePos->ReadChFramePos( rStrm );
     961         380 :         break;
     962             :         case EXC_ID_CHFONT:
     963         370 :             mxFont.reset( new XclImpChFont );
     964         370 :             mxFont->ReadChFont( rStrm );
     965         370 :         break;
     966             :         case EXC_ID_CHFORMATRUNS:
     967           0 :             if( GetBiff() == EXC_BIFF8 )
     968           0 :                 XclImpString::ReadFormats( rStrm, maFormats );
     969           0 :         break;
     970             :         case EXC_ID_CHSOURCELINK:
     971         384 :             mxSrcLink.reset( new XclImpChSourceLink( GetChRoot() ) );
     972         384 :             mxSrcLink->ReadChSourceLink( rStrm );
     973         384 :         break;
     974             :         case EXC_ID_CHFRAME:
     975         156 :             mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_TEXT ) );
     976         156 :             mxFrame->ReadRecordGroup( rStrm );
     977         156 :         break;
     978             :         case EXC_ID_CHOBJECTLINK:
     979         184 :             rStrm >> maObjLink.mnTarget >> maObjLink.maPointPos.mnSeriesIdx >> maObjLink.maPointPos.mnPointIdx;
     980         184 :         break;
     981             :         case EXC_ID_CHFRLABELPROPS:
     982           0 :             ReadChFrLabelProps( rStrm );
     983           0 :         break;
     984             :         case EXC_ID_CHEND:
     985         394 :             if( mxSrcLink && !maFormats.empty() )
     986           0 :                 mxSrcLink->SetTextFormats( maFormats );
     987         394 :         break;
     988             :     }
     989        2916 : }
     990             : 
     991         370 : sal_uInt16 XclImpChText::GetFontIndex() const
     992             : {
     993         370 :     return mxFont ? mxFont->GetFontIndex() : EXC_FONT_NOTFOUND;
     994             : }
     995             : 
     996         370 : Color XclImpChText::GetFontColor() const
     997             : {
     998         370 :     return ::get_flag( maData.mnFlags, EXC_CHTEXT_AUTOCOLOR ) ? GetFontAutoColor() : maData.maTextColor;
     999             : }
    1000             : 
    1001         200 : sal_uInt16 XclImpChText::GetRotation() const
    1002             : {
    1003         200 :     return maData.mnRotation;
    1004             : }
    1005             : 
    1006          46 : void XclImpChText::SetString( const OUString& rString )
    1007             : {
    1008          46 :     if( !mxSrcLink )
    1009           6 :         mxSrcLink.reset( new XclImpChSourceLink( GetChRoot() ) );
    1010          46 :     mxSrcLink->SetString( rString );
    1011          46 : }
    1012             : 
    1013         222 : void XclImpChText::UpdateText( const XclImpChText* pParentText )
    1014             : {
    1015         222 :     if( pParentText )
    1016             :     {
    1017             :         // update missing members
    1018         214 :         if( !mxFrame )
    1019          58 :             mxFrame = pParentText->mxFrame;
    1020         214 :         if( !mxFont )
    1021             :         {
    1022          16 :             mxFont = pParentText->mxFont;
    1023             :             // text color is taken from CHTEXT record, not from font in CHFONT
    1024          16 :             ::set_flag( maData.mnFlags, EXC_CHTEXT_AUTOCOLOR, ::get_flag( pParentText->maData.mnFlags, EXC_CHTEXT_AUTOCOLOR ) );
    1025          16 :             maData.maTextColor = pParentText->maData.maTextColor;
    1026             :         }
    1027             :     }
    1028         222 : }
    1029             : 
    1030           0 : void XclImpChText::UpdateDataLabel( bool bCateg, bool bValue, bool bPercent )
    1031             : {
    1032           0 :     ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEG,     bCateg );
    1033           0 :     ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWVALUE,     bValue );
    1034           0 :     ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWPERCENT,   bPercent );
    1035           0 :     ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEGPERC, bCateg && bPercent );
    1036           0 :     ::set_flag( maData.mnFlags, EXC_CHTEXT_DELETED,       !bCateg && !bValue && !bPercent );
    1037           0 : }
    1038             : 
    1039         328 : void XclImpChText::ConvertFont( ScfPropertySet& rPropSet ) const
    1040             : {
    1041         328 :     ConvertFontBase( GetChRoot(), rPropSet );
    1042         328 : }
    1043             : 
    1044         160 : void XclImpChText::ConvertRotation( ScfPropertySet& rPropSet, bool bSupportsStacked ) const
    1045             : {
    1046         160 :     ConvertRotationBase( GetChRoot(), rPropSet, bSupportsStacked );
    1047         160 : }
    1048             : 
    1049          46 : void XclImpChText::ConvertFrame( ScfPropertySet& rPropSet ) const
    1050             : {
    1051          46 :     if( mxFrame )
    1052          38 :         mxFrame->Convert( rPropSet );
    1053          46 : }
    1054             : 
    1055          96 : void XclImpChText::ConvertNumFmt( ScfPropertySet& rPropSet, bool bPercent ) const
    1056             : {
    1057          96 :     if( mxSrcLink )
    1058          96 :         mxSrcLink->ConvertNumFmt( rPropSet, bPercent );
    1059          96 : }
    1060             : 
    1061         130 : void XclImpChText::ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeInfo& rTypeInfo ) const
    1062             : {
    1063             :     // existing CHFRLABELPROPS record wins over flags from CHTEXT
    1064         130 :     sal_uInt16 nShowFlags = mxLabelProps ? mxLabelProps->mnFlags : maData.mnFlags;
    1065         130 :     sal_uInt16 SHOWANYCATEG   = mxLabelProps ? EXC_CHFRLABELPROPS_SHOWCATEG : (EXC_CHTEXT_SHOWCATEGPERC | EXC_CHTEXT_SHOWCATEG);
    1066         130 :     sal_uInt16 SHOWANYVALUE   = mxLabelProps ? EXC_CHFRLABELPROPS_SHOWVALUE : EXC_CHTEXT_SHOWVALUE;
    1067         130 :     sal_uInt16 SHOWANYPERCENT = mxLabelProps ? EXC_CHFRLABELPROPS_SHOWPERCENT : (EXC_CHTEXT_SHOWPERCENT | EXC_CHTEXT_SHOWCATEGPERC);
    1068         130 :     sal_uInt16 SHOWANYBUBBLE  = mxLabelProps ? EXC_CHFRLABELPROPS_SHOWBUBBLE : EXC_CHTEXT_SHOWBUBBLE;
    1069             : 
    1070             :     // get raw flags for label values
    1071         130 :     bool bShowNone    = IsDeleted();
    1072         130 :     bool bShowCateg   = !bShowNone && ::get_flag( nShowFlags, SHOWANYCATEG );
    1073         130 :     bool bShowPercent = !bShowNone && ::get_flag( nShowFlags, SHOWANYPERCENT );
    1074         130 :     bool bShowValue   = !bShowNone && ::get_flag( nShowFlags, SHOWANYVALUE );
    1075         130 :     bool bShowBubble  = !bShowNone && ::get_flag( nShowFlags, SHOWANYBUBBLE );
    1076             : 
    1077             :     // adjust to Chart2 behaviour
    1078         130 :     if( rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES )
    1079           0 :          bShowValue = bShowBubble;  // Chart2 bubble charts show bubble size if 'ShowValue' is set
    1080             : 
    1081             :     // other flags
    1082         130 :     bool bShowAny = bShowValue || bShowPercent || bShowCateg;
    1083         130 :     bool bShowSymbol = bShowAny && ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWSYMBOL );
    1084             : 
    1085             :     // create API struct for label values, set API label separator
    1086         130 :     cssc2::DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol );
    1087         130 :     rPropSet.SetProperty( EXC_CHPROP_LABEL, aPointLabel );
    1088         130 :     OUString aSep = mxLabelProps ? mxLabelProps->maSeparator : OUString('\n');
    1089         130 :     if( aSep.isEmpty() )
    1090           0 :         aSep = "; ";
    1091         130 :     rPropSet.SetStringProperty( EXC_CHPROP_LABELSEPARATOR, aSep );
    1092             : 
    1093             :     // text properties of attached label
    1094         130 :     if( bShowAny )
    1095             :     {
    1096         118 :         ConvertFont( rPropSet );
    1097         118 :         ConvertRotation( rPropSet, false );
    1098             :         // label placement
    1099             :         using namespace cssc::DataLabelPlacement;
    1100         118 :         sal_Int32 nPlacement = rTypeInfo.mnDefaultLabelPos;
    1101         118 :         switch( ::extract_value< sal_uInt16 >( maData.mnFlags2, 0, 4 ) )
    1102             :         {
    1103          76 :             case EXC_CHTEXT_POS_DEFAULT:    nPlacement = rTypeInfo.mnDefaultLabelPos;   break;
    1104           0 :             case EXC_CHTEXT_POS_OUTSIDE:    nPlacement = OUTSIDE;                       break;
    1105           0 :             case EXC_CHTEXT_POS_INSIDE:     nPlacement = INSIDE;                        break;
    1106           4 :             case EXC_CHTEXT_POS_CENTER:     nPlacement = CENTER;                        break;
    1107           0 :             case EXC_CHTEXT_POS_AXIS:       nPlacement = NEAR_ORIGIN;                   break;
    1108           0 :             case EXC_CHTEXT_POS_ABOVE:      nPlacement = TOP;                           break;
    1109           0 :             case EXC_CHTEXT_POS_BELOW:      nPlacement = BOTTOM;                        break;
    1110           0 :             case EXC_CHTEXT_POS_LEFT:       nPlacement = LEFT;                          break;
    1111           0 :             case EXC_CHTEXT_POS_RIGHT:      nPlacement = RIGHT;                         break;
    1112           0 :             case EXC_CHTEXT_POS_AUTO:       nPlacement = AVOID_OVERLAP;                 break;
    1113             :         }
    1114         118 :         rPropSet.SetProperty( EXC_CHPROP_LABELPLACEMENT, nPlacement );
    1115             :         // label number format (percentage format wins over value format)
    1116         118 :         if( bShowPercent || bShowValue )
    1117          92 :             ConvertNumFmt( rPropSet, bShowPercent );
    1118         130 :     }
    1119         130 : }
    1120             : 
    1121          42 : Reference< XTitle > XclImpChText::CreateTitle() const
    1122             : {
    1123          42 :     Reference< XTitle > xTitle;
    1124          42 :     if( mxSrcLink && mxSrcLink->HasString() )
    1125             :     {
    1126             :         // create the formatted strings
    1127             :         Sequence< Reference< XFormattedString > > aStringSeq(
    1128          42 :             mxSrcLink->CreateStringSequence( GetChRoot(), GetFontIndex(), GetFontColor() ) );
    1129          42 :         if( aStringSeq.hasElements() )
    1130             :         {
    1131             :             // create the title object
    1132          42 :             xTitle.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_TITLE ), UNO_QUERY );
    1133          42 :             if( xTitle.is() )
    1134             :             {
    1135             :                 // set the formatted strings
    1136          42 :                 xTitle->setText( aStringSeq );
    1137             :                 // more title formatting properties
    1138          42 :                 ScfPropertySet aTitleProp( xTitle );
    1139          42 :                 ConvertFrame( aTitleProp );
    1140          42 :                 ConvertRotation( aTitleProp, true );
    1141             :             }
    1142          42 :         }
    1143             :     }
    1144          42 :     return xTitle;
    1145             : }
    1146             : 
    1147          42 : void XclImpChText::ConvertTitlePosition( const XclChTextKey& rTitleKey ) const
    1148             : {
    1149          84 :     if( !mxFramePos ) return;
    1150             : 
    1151          42 :     const XclChFramePos& rPosData = mxFramePos->GetFramePosData();
    1152             :     OSL_ENSURE( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rPosData.mnBRMode == EXC_CHFRAMEPOS_PARENT),
    1153             :         "XclImpChText::ConvertTitlePosition - unexpected frame position mode" );
    1154             : 
    1155             :     /*  Check if title is moved manually. To get the actual position of the
    1156             :         title, we do some kind of hack and use the values from the CHTEXT
    1157             :         record, effectively ignoring the contents of the CHFRAMEPOS record
    1158             :         which contains the position relative to the default title position
    1159             :         (according to the spec, the CHFRAMEPOS supersedes the CHTEXT record).
    1160             :         Especially when it comes to axis titles, things would become very
    1161             :         complicated here, because the relative title position is stored in a
    1162             :         measurement unit that is dependent on the size of the inner plot area,
    1163             :         the interpretation of the X and Y coordinate is dependent on the
    1164             :         direction of the axis, and in 3D charts, and the title default
    1165             :         positions are dependent on the 3D view settings (rotation, elevation,
    1166             :         and perspective). Thus, it is easier to assume that the creator has
    1167             :         written out the correct absolute position and size of the title in the
    1168             :         CHTEXT record. This is assured by checking that the shape size stored
    1169             :         in the CHTEXT record is non-zero. */
    1170          84 :     if( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) &&
    1171          84 :         ((rPosData.maRect.mnX != 0) || (rPosData.maRect.mnY != 0)) &&
    1172          80 :         (maData.maRect.mnWidth > 0) && (maData.maRect.mnHeight > 0) ) try
    1173             :     {
    1174          40 :         Reference< XShape > xTitleShape( GetTitleShape( rTitleKey ), UNO_SET_THROW );
    1175             :         // the call to XShape.getSize() may recalc the chart view
    1176          40 :         ::com::sun::star::awt::Size aTitleSize = xTitleShape->getSize();
    1177             :         // rotated titles need special handling...
    1178          40 :         sal_Int32 nScRot = XclTools::GetScRotation( GetRotation(), 0 );
    1179          40 :         double fRad = nScRot * F_PI18000;
    1180          40 :         double fSin = fabs( sin( fRad ) );
    1181          40 :         double fCos = fabs( cos( fRad ) );
    1182             :         ::com::sun::star::awt::Size aBoundSize(
    1183          40 :             static_cast< sal_Int32 >( fCos * aTitleSize.Width + fSin * aTitleSize.Height + 0.5 ),
    1184          80 :             static_cast< sal_Int32 >( fSin * aTitleSize.Width + fCos * aTitleSize.Height + 0.5 ) );
    1185             :         // calculate the title position from the values in the CHTEXT record
    1186             :         ::com::sun::star::awt::Point aTitlePos(
    1187          40 :             CalcHmmFromChartX( maData.maRect.mnX ),
    1188          80 :             CalcHmmFromChartY( maData.maRect.mnY ) );
    1189             :         // add part of height to X direction, if title is rotated down (clockwise)
    1190          40 :         if( nScRot > 18000 )
    1191           0 :             aTitlePos.X += static_cast< sal_Int32 >( fSin * aTitleSize.Height + 0.5 );
    1192             :         // add part of width to Y direction, if title is rotated up (counterclockwise)
    1193          40 :         else if( nScRot > 0 )
    1194           0 :             aTitlePos.Y += static_cast< sal_Int32 >( fSin * aTitleSize.Width + 0.5 );
    1195             :         // set the resulting position at the title shape
    1196          40 :         xTitleShape->setPosition( aTitlePos );
    1197             :     }
    1198           0 :     catch( Exception& )
    1199             :     {
    1200             :     }
    1201             : }
    1202             : 
    1203           0 : void XclImpChText::ReadChFrLabelProps( XclImpStream& rStrm )
    1204             : {
    1205           0 :     if( GetBiff() == EXC_BIFF8 )
    1206             :     {
    1207           0 :         mxLabelProps.reset( new XclChFrLabelProps );
    1208             :         sal_uInt16 nSepLen;
    1209           0 :         rStrm.Ignore( 12 );
    1210           0 :         rStrm >> mxLabelProps->mnFlags >> nSepLen;
    1211           0 :         if( nSepLen > 0 )
    1212           0 :             mxLabelProps->maSeparator = rStrm.ReadUniString( nSepLen );
    1213             :     }
    1214           0 : }
    1215             : 
    1216             : namespace {
    1217             : 
    1218          46 : void lclUpdateText( XclImpChTextRef& rxText, const XclImpChText* xDefText )
    1219             : {
    1220          46 :     if( rxText )
    1221          46 :         rxText->UpdateText( xDefText );
    1222             :     else
    1223             :     {
    1224           0 :         XclImpChTextRef xNew(new XclImpChText(*xDefText));
    1225           0 :         rxText = xNew;
    1226             :     }
    1227          46 : }
    1228             : 
    1229         352 : void lclFinalizeTitle( XclImpChTextRef& rxTitle, const XclImpChText* pDefText, const OUString& rAutoTitle )
    1230             : {
    1231             :     /*  Do not update a title, if it is not visible (if rxTitle is null).
    1232             :         Existing reference indicates enabled title. */
    1233         352 :     if( rxTitle )
    1234             :     {
    1235          50 :         if( !rxTitle->HasString() )
    1236          46 :             rxTitle->SetString( rAutoTitle );
    1237          50 :         if( rxTitle->HasString() )
    1238          42 :             rxTitle->UpdateText(pDefText);
    1239             :         else
    1240           8 :             rxTitle.reset();
    1241             :     }
    1242         352 : }
    1243             : 
    1244             : } // namespace
    1245             : 
    1246             : // Data series ================================================================
    1247             : 
    1248         230 : void XclImpChMarkerFormat::ReadChMarkerFormat( XclImpStream& rStrm )
    1249             : {
    1250         230 :     rStrm >> maData.maLineColor >> maData.maFillColor >> maData.mnMarkerType >> maData.mnFlags;
    1251             : 
    1252         230 :     const XclImpRoot& rRoot = rStrm.GetRoot();
    1253         230 :     if( rRoot.GetBiff() == EXC_BIFF8 )
    1254             :     {
    1255             :         // BIFF8: index into palette used instead of RGB data
    1256         230 :         const XclImpPalette& rPal = rRoot.GetPalette();
    1257         230 :         maData.maLineColor = rPal.GetColor( rStrm.ReaduInt16() );
    1258         230 :         maData.maFillColor = rPal.GetColor( rStrm.ReaduInt16() );
    1259             :         // marker size
    1260         230 :         rStrm >> maData.mnMarkerSize;
    1261             :     }
    1262         230 : }
    1263             : 
    1264           4 : void XclImpChMarkerFormat::Convert( const XclImpChRoot& rRoot,
    1265             :         ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx, sal_Int16 nLineWeight ) const
    1266             : {
    1267           4 :     if( IsAuto() )
    1268             :     {
    1269           2 :         XclChMarkerFormat aMarkerFmt;
    1270             :         // line and fill color of the symbol are equal to series line color
    1271             :         //! TODO: Excel sets no fill color for specific symbols (e.g. cross)
    1272           2 :         aMarkerFmt.maLineColor = aMarkerFmt.maFillColor = rRoot.GetSeriesLineAutoColor( nFormatIdx );
    1273           2 :         switch( nLineWeight )
    1274             :         {
    1275           0 :             case EXC_CHLINEFORMAT_HAIR:     aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_HAIRSIZE;      break;
    1276           2 :             case EXC_CHLINEFORMAT_SINGLE:   aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_SINGLESIZE;    break;
    1277           0 :             case EXC_CHLINEFORMAT_DOUBLE:   aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_DOUBLESIZE;    break;
    1278           0 :             case EXC_CHLINEFORMAT_TRIPLE:   aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_TRIPLESIZE;    break;
    1279           0 :             default:                        aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_SINGLESIZE;
    1280             :         }
    1281           2 :         aMarkerFmt.mnMarkerType = XclChartHelper::GetAutoMarkerType( nFormatIdx );
    1282           2 :         rRoot.GetChartPropSetHelper().WriteMarkerProperties( rPropSet, aMarkerFmt );
    1283             :     }
    1284             :     else
    1285             :     {
    1286           2 :         rRoot.GetChartPropSetHelper().WriteMarkerProperties( rPropSet, maData );
    1287             :     }
    1288           4 : }
    1289             : 
    1290           2 : void XclImpChMarkerFormat::ConvertColor( const XclImpChRoot& rRoot,
    1291             :         ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx ) const
    1292             : {
    1293           2 :     Color aLineColor = IsAuto() ? rRoot.GetSeriesLineAutoColor( nFormatIdx ) : maData.maFillColor;
    1294           2 :     rPropSet.SetColorProperty( EXC_CHPROP_COLOR, aLineColor );
    1295           2 : }
    1296             : 
    1297         228 : XclImpChPieFormat::XclImpChPieFormat() :
    1298         228 :     mnPieDist( 0 )
    1299             : {
    1300         228 : }
    1301             : 
    1302         228 : void XclImpChPieFormat::ReadChPieFormat( XclImpStream& rStrm )
    1303             : {
    1304         228 :     rStrm >> mnPieDist;
    1305         228 : }
    1306             : 
    1307         184 : void XclImpChPieFormat::Convert( ScfPropertySet& rPropSet ) const
    1308             : {
    1309         184 :     double fApiDist = ::std::min< double >( mnPieDist / 100.0, 1.0 );
    1310         184 :     rPropSet.SetProperty( EXC_CHPROP_OFFSET, fApiDist );
    1311         184 : }
    1312             : 
    1313           0 : XclImpChSeriesFormat::XclImpChSeriesFormat() :
    1314           0 :     mnFlags( 0 )
    1315             : {
    1316           0 : }
    1317             : 
    1318           0 : void XclImpChSeriesFormat::ReadChSeriesFormat( XclImpStream& rStrm )
    1319             : {
    1320           0 :     rStrm >> mnFlags;
    1321           0 : }
    1322             : 
    1323         234 : void XclImpCh3dDataFormat::ReadCh3dDataFormat( XclImpStream& rStrm )
    1324             : {
    1325         234 :     rStrm >> maData.mnBase >> maData.mnTop;
    1326         234 : }
    1327             : 
    1328           0 : void XclImpCh3dDataFormat::Convert( ScfPropertySet& rPropSet ) const
    1329             : {
    1330             :     using namespace ::com::sun::star::chart2::DataPointGeometry3D;
    1331           0 :     sal_Int32 nApiType = (maData.mnBase == EXC_CH3DDATAFORMAT_RECT) ?
    1332           0 :         ((maData.mnTop == EXC_CH3DDATAFORMAT_STRAIGHT) ? CUBOID : PYRAMID) :
    1333           0 :         ((maData.mnTop == EXC_CH3DDATAFORMAT_STRAIGHT) ? CYLINDER : CONE);
    1334           0 :     rPropSet.SetProperty( EXC_CHPROP_GEOMETRY3D, nApiType );
    1335           0 : }
    1336             : 
    1337          64 : XclImpChAttachedLabel::XclImpChAttachedLabel( const XclImpChRoot& rRoot ) :
    1338             :     XclImpChRoot( rRoot ),
    1339          64 :     mnFlags( 0 )
    1340             : {
    1341          64 : }
    1342             : 
    1343          64 : void XclImpChAttachedLabel::ReadChAttachedLabel( XclImpStream& rStrm )
    1344             : {
    1345          64 :     rStrm >> mnFlags;
    1346          64 : }
    1347             : 
    1348           0 : XclImpChTextRef XclImpChAttachedLabel::CreateDataLabel( const XclImpChText* pParent ) const
    1349             : {
    1350           0 :     const sal_uInt16 EXC_CHATTLABEL_SHOWANYVALUE = EXC_CHATTLABEL_SHOWVALUE;
    1351           0 :     const sal_uInt16 EXC_CHATTLABEL_SHOWANYPERCENT = EXC_CHATTLABEL_SHOWPERCENT | EXC_CHATTLABEL_SHOWCATEGPERC;
    1352           0 :     const sal_uInt16 EXC_CHATTLABEL_SHOWANYCATEG = EXC_CHATTLABEL_SHOWCATEG | EXC_CHATTLABEL_SHOWCATEGPERC;
    1353             : 
    1354           0 :     XclImpChTextRef xLabel( pParent ? new XclImpChText( *pParent ) : new XclImpChText( GetChRoot() ) );
    1355             :     xLabel->UpdateDataLabel(
    1356           0 :         ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYCATEG ),
    1357           0 :         ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYVALUE ),
    1358           0 :         ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYPERCENT ) );
    1359           0 :     return xLabel;
    1360             : }
    1361             : 
    1362         250 : XclImpChDataFormat::XclImpChDataFormat( const XclImpChRoot& rRoot ) :
    1363         250 :     XclImpChRoot( rRoot )
    1364             : {
    1365         250 : }
    1366             : 
    1367         250 : void XclImpChDataFormat::ReadHeaderRecord( XclImpStream& rStrm )
    1368             : {
    1369         250 :     rStrm   >> maData.maPointPos.mnPointIdx
    1370         500 :             >> maData.maPointPos.mnSeriesIdx
    1371         500 :             >> maData.mnFormatIdx
    1372         500 :             >> maData.mnFlags;
    1373         250 : }
    1374             : 
    1375        2572 : void XclImpChDataFormat::ReadSubRecord( XclImpStream& rStrm )
    1376             : {
    1377        2572 :     switch( rStrm.GetRecId() )
    1378             :     {
    1379             :         case EXC_ID_CHMARKERFORMAT:
    1380         230 :             mxMarkerFmt.reset( new XclImpChMarkerFormat );
    1381         230 :             mxMarkerFmt->ReadChMarkerFormat( rStrm );
    1382         230 :         break;
    1383             :         case EXC_ID_CHPIEFORMAT:
    1384         228 :             mxPieFmt.reset( new XclImpChPieFormat );
    1385         228 :             mxPieFmt->ReadChPieFormat( rStrm );
    1386         228 :         break;
    1387             :         case EXC_ID_CHSERIESFORMAT:
    1388           0 :             mxSeriesFmt.reset( new XclImpChSeriesFormat );
    1389           0 :             mxSeriesFmt->ReadChSeriesFormat( rStrm );
    1390           0 :         break;
    1391             :         case EXC_ID_CH3DDATAFORMAT:
    1392         234 :             mx3dDataFmt.reset( new XclImpCh3dDataFormat );
    1393         234 :             mx3dDataFmt->ReadCh3dDataFormat( rStrm );
    1394         234 :         break;
    1395             :         case EXC_ID_CHATTACHEDLABEL:
    1396          64 :             mxAttLabel.reset( new XclImpChAttachedLabel( GetChRoot() ) );
    1397          64 :             mxAttLabel->ReadChAttachedLabel( rStrm );
    1398          64 :         break;
    1399             :         default:
    1400        1816 :             XclImpChFrameBase::ReadSubRecord( rStrm );
    1401             :     }
    1402        2572 : }
    1403             : 
    1404           0 : void XclImpChDataFormat::SetPointPos( const XclChDataPointPos& rPointPos, sal_uInt16 nFormatIdx )
    1405             : {
    1406           0 :     maData.maPointPos = rPointPos;
    1407           0 :     maData.mnFormatIdx = nFormatIdx;
    1408           0 : }
    1409             : 
    1410          38 : void XclImpChDataFormat::UpdateGroupFormat( const XclChExtTypeInfo& rTypeInfo )
    1411             : {
    1412             :     // remove formats not used for the current chart type
    1413          38 :     RemoveUnusedFormats( rTypeInfo );
    1414          38 : }
    1415             : 
    1416          92 : void XclImpChDataFormat::UpdateSeriesFormat( const XclChExtTypeInfo& rTypeInfo, const XclImpChDataFormat* pGroupFmt )
    1417             : {
    1418             :     // update missing formats from passed chart type group format
    1419          92 :     if( pGroupFmt )
    1420             :     {
    1421          38 :         if( !mxLineFmt )
    1422           0 :             mxLineFmt = pGroupFmt->mxLineFmt;
    1423          38 :         if( !mxAreaFmt && !mxEscherFmt )
    1424             :         {
    1425           0 :             mxAreaFmt = pGroupFmt->mxAreaFmt;
    1426           0 :             mxEscherFmt = pGroupFmt->mxEscherFmt;
    1427             :         }
    1428          38 :         if( !mxMarkerFmt )
    1429           0 :             mxMarkerFmt = pGroupFmt->mxMarkerFmt;
    1430          38 :         if( !mxPieFmt )
    1431           0 :             mxPieFmt = pGroupFmt->mxPieFmt;
    1432          38 :         if( !mxSeriesFmt )
    1433          38 :             mxSeriesFmt = pGroupFmt->mxSeriesFmt;
    1434          38 :         if( !mx3dDataFmt )
    1435           0 :             mx3dDataFmt = pGroupFmt->mx3dDataFmt;
    1436          38 :         if( !mxAttLabel )
    1437           8 :             mxAttLabel = pGroupFmt->mxAttLabel;
    1438             :     }
    1439             : 
    1440             :     /*  Create missing but required formats. Existing line, area, and marker
    1441             :         format objects are needed to create automatic series formatting. */
    1442          92 :     if( !mxLineFmt )
    1443           6 :         mxLineFmt.reset( new XclImpChLineFormat );
    1444          92 :     if( !mxAreaFmt && !mxEscherFmt )
    1445           8 :         mxAreaFmt.reset( new XclImpChAreaFormat );
    1446          92 :     if( !mxMarkerFmt )
    1447          14 :         mxMarkerFmt.reset( new XclImpChMarkerFormat );
    1448             : 
    1449             :     // remove formats not used for the current chart type
    1450          92 :     RemoveUnusedFormats( rTypeInfo );
    1451             :     // update data label
    1452          92 :     UpdateDataLabel( pGroupFmt );
    1453          92 : }
    1454             : 
    1455         114 : void XclImpChDataFormat::UpdatePointFormat( const XclChExtTypeInfo& rTypeInfo, const XclImpChDataFormat* pSeriesFmt )
    1456             : {
    1457             :     // remove formats if they are automatic in this and in the passed series format
    1458         114 :     if( pSeriesFmt )
    1459             :     {
    1460         114 :         if( IsAutoLine() && pSeriesFmt->IsAutoLine() )
    1461           0 :             mxLineFmt.reset();
    1462         114 :         if( IsAutoArea() && pSeriesFmt->IsAutoArea() )
    1463           0 :             mxAreaFmt.reset();
    1464         114 :         if( IsAutoMarker() && pSeriesFmt->IsAutoMarker() )
    1465         114 :             mxMarkerFmt.reset();
    1466         114 :         mxSeriesFmt.reset();
    1467             :     }
    1468             : 
    1469             :     // Excel ignores 3D bar format for single data points
    1470         114 :     mx3dDataFmt.reset();
    1471             :     // remove point line formats for linear chart types, TODO: implement in OOChart
    1472         114 :     if( !rTypeInfo.IsSeriesFrameFormat() )
    1473           0 :         mxLineFmt.reset();
    1474             : 
    1475             :     // remove formats not used for the current chart type
    1476         114 :     RemoveUnusedFormats( rTypeInfo );
    1477             :     // update data label
    1478         114 :     UpdateDataLabel( pSeriesFmt );
    1479         114 : }
    1480             : 
    1481           6 : void XclImpChDataFormat::UpdateTrendLineFormat()
    1482             : {
    1483           6 :     if( !mxLineFmt )
    1484           0 :         mxLineFmt.reset( new XclImpChLineFormat );
    1485           6 :     mxAreaFmt.reset();
    1486           6 :     mxEscherFmt.reset();
    1487           6 :     mxMarkerFmt.reset();
    1488           6 :     mxPieFmt.reset();
    1489           6 :     mxSeriesFmt.reset();
    1490           6 :     mx3dDataFmt.reset();
    1491           6 :     mxAttLabel.reset();
    1492             :     // update data label
    1493           6 :     UpdateDataLabel( 0 );
    1494           6 : }
    1495             : 
    1496         206 : void XclImpChDataFormat::Convert( ScfPropertySet& rPropSet, const XclChExtTypeInfo& rTypeInfo ) const
    1497             : {
    1498             :     /*  Line and area format.
    1499             :         #i71810# If the data points are filled with bitmaps, textures, or
    1500             :         patterns, then only bar charts will use the CHPICFORMAT record to
    1501             :         determine stacking/streching mode. All other chart types ignore this
    1502             :         record and always use the property 'fill-type' from the DFF property
    1503             :         set (streched for bitmaps, and stacked for textures and patterns). */
    1504         206 :     bool bUsePicFmt = rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_BAR;
    1505         206 :     ConvertFrameBase( GetChRoot(), rPropSet, rTypeInfo.GetSeriesObjectType(), maData.mnFormatIdx, bUsePicFmt );
    1506             : 
    1507             : #if EXC_CHART2_3DBAR_HAIRLINES_ONLY
    1508             :     // #i83151# only hair lines in 3D charts with filled data points
    1509         206 :     if( rTypeInfo.mb3dChart && rTypeInfo.IsSeriesFrameFormat() && mxLineFmt && mxLineFmt->HasLine() )
    1510           0 :         rPropSet.SetProperty< sal_Int32 >( "BorderWidth", 0 );
    1511             : #endif
    1512             : 
    1513             :     // other formatting
    1514         206 :     if( mxMarkerFmt )
    1515           4 :         mxMarkerFmt->Convert( GetChRoot(), rPropSet, maData.mnFormatIdx, GetLineWeight() );
    1516         206 :     if( mxPieFmt )
    1517         184 :         mxPieFmt->Convert( rPropSet );
    1518         206 :     if( mx3dDataFmt )
    1519           0 :         mx3dDataFmt->Convert( rPropSet );
    1520         206 :     if( mxLabel )
    1521         130 :         mxLabel->ConvertDataLabel( rPropSet, rTypeInfo );
    1522             : 
    1523             :     // 3D settings
    1524         206 :     rPropSet.SetProperty< sal_Int16 >( EXC_CHPROP_PERCENTDIAGONAL, 0 );
    1525             : 
    1526             :     /*  Special case: set marker color as line color, if series line is not
    1527             :         visible. This makes the color visible in the marker area.
    1528             :         TODO: remove this if OOChart supports own colors in markers. */
    1529         206 :     if( !rTypeInfo.IsSeriesFrameFormat() && !HasLine() && mxMarkerFmt )
    1530           2 :         mxMarkerFmt->ConvertColor( GetChRoot(), rPropSet, maData.mnFormatIdx );
    1531         206 : }
    1532             : 
    1533           6 : void XclImpChDataFormat::ConvertLine( ScfPropertySet& rPropSet, XclChObjectType eObjType ) const
    1534             : {
    1535           6 :     ConvertLineBase( GetChRoot(), rPropSet, eObjType );
    1536           6 : }
    1537             : 
    1538         110 : void XclImpChDataFormat::ConvertArea( ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx, bool bUsePicFmt ) const
    1539             : {
    1540         110 :     ConvertAreaBase( GetChRoot(), rPropSet, EXC_CHOBJTYPE_FILLEDSERIES, nFormatIdx, bUsePicFmt );
    1541         110 : }
    1542             : 
    1543         244 : void XclImpChDataFormat::RemoveUnusedFormats( const XclChExtTypeInfo& rTypeInfo )
    1544             : {
    1545             :     // data point marker only in linear 2D charts
    1546         244 :     if( rTypeInfo.IsSeriesFrameFormat() )
    1547         240 :         mxMarkerFmt.reset();
    1548             :     // pie format only in pie/donut charts
    1549         244 :     if( rTypeInfo.meTypeCateg != EXC_CHTYPECATEG_PIE )
    1550          24 :         mxPieFmt.reset();
    1551             :     // 3D format only in 3D bar charts
    1552         244 :     if( !rTypeInfo.mb3dChart || (rTypeInfo.meTypeCateg != EXC_CHTYPECATEG_BAR) )
    1553         244 :         mx3dDataFmt.reset();
    1554         244 : }
    1555             : 
    1556         212 : void XclImpChDataFormat::UpdateDataLabel( const XclImpChDataFormat* pParentFmt )
    1557             : {
    1558             :     /*  CHTEXT groups linked to data labels override existing CHATTACHEDLABEL
    1559             :         records. Only if there is a CHATTACHEDLABEL record without a CHTEXT
    1560             :         group, the contents of the CHATTACHEDLABEL record are used. In this
    1561             :         case a new CHTEXT group is created and filled with the settings from
    1562             :         the CHATTACHEDLABEL record. */
    1563         212 :     const XclImpChText* pDefText = NULL;
    1564         212 :     if (pParentFmt)
    1565         152 :         pDefText = pParentFmt->GetDataLabel();
    1566         212 :     if (!pDefText)
    1567          98 :         pDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_DATALABEL );
    1568         212 :     if (mxLabel)
    1569         134 :         mxLabel->UpdateText(pDefText);
    1570          78 :     else if (mxAttLabel)
    1571           0 :         mxLabel = mxAttLabel->CreateDataLabel( pDefText );
    1572         212 : }
    1573             : 
    1574           6 : XclImpChSerTrendLine::XclImpChSerTrendLine( const XclImpChRoot& rRoot ) :
    1575           6 :     XclImpChRoot( rRoot )
    1576             : {
    1577           6 : }
    1578             : 
    1579           6 : void XclImpChSerTrendLine::ReadChSerTrendLine( XclImpStream& rStrm )
    1580             : {
    1581           6 :     rStrm   >> maData.mnLineType
    1582          12 :             >> maData.mnOrder
    1583          12 :             >> maData.mfIntercept
    1584          12 :             >> maData.mnShowEquation
    1585          12 :             >> maData.mnShowRSquared
    1586          12 :             >> maData.mfForecastFor
    1587          12 :             >> maData.mfForecastBack;
    1588           6 : }
    1589             : 
    1590           6 : Reference< XRegressionCurve > XclImpChSerTrendLine::CreateRegressionCurve() const
    1591             : {
    1592             :     // trend line type
    1593           6 :     Reference< XRegressionCurve > xRegCurve;
    1594           6 :     switch( maData.mnLineType )
    1595             :     {
    1596             :         case EXC_CHSERTREND_POLYNOMIAL:
    1597           4 :             if( maData.mnOrder == 1 )
    1598             :             {
    1599           2 :                 xRegCurve = LinearRegressionCurve::create( comphelper::getProcessComponentContext() );
    1600             :             } else {
    1601           2 :                 xRegCurve = PolynomialRegressionCurve::create( comphelper::getProcessComponentContext() );
    1602             :             }
    1603           4 :         break;
    1604             :         case EXC_CHSERTREND_EXPONENTIAL:
    1605           0 :             xRegCurve = ExponentialRegressionCurve::create( comphelper::getProcessComponentContext() );
    1606           0 :         break;
    1607             :         case EXC_CHSERTREND_LOGARITHMIC:
    1608           0 :             xRegCurve = LogarithmicRegressionCurve::create( comphelper::getProcessComponentContext() );
    1609           0 :         break;
    1610             :         case EXC_CHSERTREND_POWER:
    1611           0 :             xRegCurve = PotentialRegressionCurve::create( comphelper::getProcessComponentContext() );
    1612           0 :         break;
    1613             :         case EXC_CHSERTREND_MOVING_AVG:
    1614           2 :             xRegCurve = MovingAverageRegressionCurve::create( comphelper::getProcessComponentContext() );
    1615           2 :         break;
    1616             :     }
    1617             : 
    1618             :     // trend line formatting
    1619           6 :     if( xRegCurve.is() && mxDataFmt )
    1620             :     {
    1621           6 :         ScfPropertySet aPropSet( xRegCurve );
    1622           6 :         mxDataFmt->ConvertLine( aPropSet, EXC_CHOBJTYPE_TRENDLINE );
    1623             : 
    1624           6 :         aPropSet.SetProperty(EXC_CHPROP_CURVENAME, maTrendLineName);
    1625           6 :         aPropSet.SetProperty(EXC_CHPROP_POLYNOMIAL_DEGREE, static_cast<sal_Int32> (maData.mnOrder) );
    1626           6 :         aPropSet.SetProperty(EXC_CHPROP_MOVING_AVERAGE_PERIOD, static_cast<sal_Int32> (maData.mnOrder) );
    1627           6 :         aPropSet.SetProperty(EXC_CHPROP_EXTRAPOLATE_FORWARD, maData.mfForecastFor);
    1628           6 :         aPropSet.SetProperty(EXC_CHPROP_EXTRAPOLATE_BACKWARD, maData.mfForecastBack);
    1629             : 
    1630           6 :         bool bForceIntercept = !rtl::math::isNan(maData.mfIntercept);
    1631           6 :         aPropSet.SetProperty(EXC_CHPROP_FORCE_INTERCEPT, bForceIntercept);
    1632           6 :         if (bForceIntercept)
    1633             :         {
    1634           2 :             aPropSet.SetProperty(EXC_CHPROP_INTERCEPT_VALUE, maData.mfIntercept);
    1635             :         }
    1636             : 
    1637             :         // #i83100# show equation and correlation coefficient
    1638          12 :         ScfPropertySet aLabelProp( xRegCurve->getEquationProperties() );
    1639           6 :         aLabelProp.SetBoolProperty( EXC_CHPROP_SHOWEQUATION, maData.mnShowEquation != 0 );
    1640           6 :         aLabelProp.SetBoolProperty( EXC_CHPROP_SHOWCORRELATION, maData.mnShowRSquared != 0 );
    1641             : 
    1642             :         // #i83100# formatting of the equation text box
    1643           6 :         if (const XclImpChText* pLabel = mxDataFmt->GetDataLabel())
    1644             :         {
    1645           4 :             pLabel->ConvertFont( aLabelProp );
    1646           4 :             pLabel->ConvertFrame( aLabelProp );
    1647           4 :             pLabel->ConvertNumFmt( aLabelProp, false );
    1648           6 :         }
    1649             :     }
    1650             : 
    1651             :     // missing features
    1652             :     // #i20819# polynomial trend lines
    1653             :     // #i66819# moving average trend lines
    1654             :     // #i5085# manual trend line size
    1655             :     // #i34093# manual crossing point
    1656             : 
    1657           6 :     return xRegCurve;
    1658             : }
    1659             : 
    1660           0 : XclImpChSerErrorBar::XclImpChSerErrorBar( const XclImpChRoot& rRoot ) :
    1661           0 :     XclImpChRoot( rRoot )
    1662             : {
    1663           0 : }
    1664             : 
    1665           0 : void XclImpChSerErrorBar::ReadChSerErrorBar( XclImpStream& rStrm )
    1666             : {
    1667           0 :     rStrm >> maData.mnBarType >> maData.mnSourceType >> maData.mnLineEnd;
    1668           0 :     rStrm.Ignore( 1 );
    1669           0 :     rStrm >> maData.mfValue >> maData.mnValueCount;
    1670           0 : }
    1671             : 
    1672           0 : void XclImpChSerErrorBar::SetSeriesData( XclImpChSourceLinkRef xValueLink, XclImpChDataFormatRef xDataFmt )
    1673             : {
    1674           0 :     mxValueLink = xValueLink;
    1675           0 :     mxDataFmt = xDataFmt;
    1676           0 : }
    1677             : 
    1678           0 : Reference< XLabeledDataSequence > XclImpChSerErrorBar::CreateValueSequence() const
    1679             : {
    1680           0 :     return lclCreateLabeledDataSequence( mxValueLink, XclChartHelper::GetErrorBarValuesRole( maData.mnBarType ) );
    1681             : }
    1682             : 
    1683           0 : Reference< XPropertySet > XclImpChSerErrorBar::CreateErrorBar( const XclImpChSerErrorBar* pPosBar, const XclImpChSerErrorBar* pNegBar )
    1684             : {
    1685           0 :     Reference< XPropertySet > xErrorBar;
    1686             : 
    1687           0 :     if( const XclImpChSerErrorBar* pPrimaryBar = pPosBar ? pPosBar : pNegBar )
    1688             :     {
    1689           0 :         xErrorBar.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_ERRORBAR ), UNO_QUERY );
    1690           0 :         ScfPropertySet aBarProp( xErrorBar );
    1691             : 
    1692             :         // plus/minus bars visible?
    1693           0 :         aBarProp.SetBoolProperty( EXC_CHPROP_SHOWPOSITIVEERROR, pPosBar != 0 );
    1694           0 :         aBarProp.SetBoolProperty( EXC_CHPROP_SHOWNEGATIVEERROR, pNegBar != 0 );
    1695             : 
    1696             :         // type of displayed error
    1697           0 :         switch( pPrimaryBar->maData.mnSourceType )
    1698             :         {
    1699             :             case EXC_CHSERERR_PERCENT:
    1700           0 :                 aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::RELATIVE );
    1701           0 :                 aBarProp.SetProperty( EXC_CHPROP_POSITIVEERROR, pPrimaryBar->maData.mfValue );
    1702           0 :                 aBarProp.SetProperty( EXC_CHPROP_NEGATIVEERROR, pPrimaryBar->maData.mfValue );
    1703           0 :             break;
    1704             :             case EXC_CHSERERR_FIXED:
    1705           0 :                 aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::ABSOLUTE );
    1706           0 :                 aBarProp.SetProperty( EXC_CHPROP_POSITIVEERROR, pPrimaryBar->maData.mfValue );
    1707           0 :                 aBarProp.SetProperty( EXC_CHPROP_NEGATIVEERROR, pPrimaryBar->maData.mfValue );
    1708           0 :             break;
    1709             :             case EXC_CHSERERR_STDDEV:
    1710           0 :                 aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::STANDARD_DEVIATION );
    1711           0 :                 aBarProp.SetProperty( EXC_CHPROP_WEIGHT, pPrimaryBar->maData.mfValue );
    1712           0 :             break;
    1713             :             case EXC_CHSERERR_STDERR:
    1714           0 :                 aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::STANDARD_ERROR );
    1715           0 :             break;
    1716             :             case EXC_CHSERERR_CUSTOM:
    1717             :             {
    1718           0 :                 aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::FROM_DATA );
    1719             :                 // attach data sequences to erorr bar
    1720           0 :                 Reference< XDataSink > xDataSink( xErrorBar, UNO_QUERY );
    1721           0 :                 if( xDataSink.is() )
    1722             :                 {
    1723             :                     // create vector of all value sequences
    1724           0 :                     ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
    1725             :                     // add positive values
    1726           0 :                     if( pPosBar )
    1727             :                     {
    1728           0 :                         Reference< XLabeledDataSequence > xValueSeq = pPosBar->CreateValueSequence();
    1729           0 :                         if( xValueSeq.is() )
    1730           0 :                             aLabeledSeqVec.push_back( xValueSeq );
    1731             :                     }
    1732             :                     // add negative values
    1733           0 :                     if( pNegBar )
    1734             :                     {
    1735           0 :                         Reference< XLabeledDataSequence > xValueSeq = pNegBar->CreateValueSequence();
    1736           0 :                         if( xValueSeq.is() )
    1737           0 :                             aLabeledSeqVec.push_back( xValueSeq );
    1738             :                     }
    1739             :                     // attach labeled data sequences to series
    1740           0 :                     if( aLabeledSeqVec.empty() )
    1741           0 :                         xErrorBar.clear();
    1742             :                     else
    1743           0 :                         xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
    1744           0 :                 }
    1745             :             }
    1746           0 :             break;
    1747             :             default:
    1748           0 :                 xErrorBar.clear();
    1749             :         }
    1750             : 
    1751             :         // error bar formatting
    1752           0 :         if( pPrimaryBar->mxDataFmt && xErrorBar.is() )
    1753           0 :             pPrimaryBar->mxDataFmt->ConvertLine( aBarProp, EXC_CHOBJTYPE_ERRORBAR );
    1754             :     }
    1755             : 
    1756           0 :     return xErrorBar;
    1757             : }
    1758             : 
    1759          98 : XclImpChSeries::XclImpChSeries( const XclImpChRoot& rRoot, sal_uInt16 nSeriesIdx ) :
    1760             :     XclImpChRoot( rRoot ),
    1761             :     mnGroupIdx( EXC_CHSERGROUP_NONE ),
    1762             :     mnSeriesIdx( nSeriesIdx ),
    1763          98 :     mnParentIdx( EXC_CHSERIES_INVALID )
    1764             : {
    1765          98 : }
    1766             : 
    1767          98 : void XclImpChSeries::ReadHeaderRecord( XclImpStream& rStrm )
    1768             : {
    1769          98 :     rStrm >> maData.mnCategType >> maData.mnValueType >> maData.mnCategCount >> maData.mnValueCount;
    1770          98 :     if( GetBiff() == EXC_BIFF8 )
    1771          98 :         rStrm >> maData.mnBubbleType >> maData.mnBubbleCount;
    1772          98 : }
    1773             : 
    1774        1040 : void XclImpChSeries::ReadSubRecord( XclImpStream& rStrm )
    1775             : {
    1776        1040 :     switch( rStrm.GetRecId() )
    1777             :     {
    1778             :         case EXC_ID_CHSOURCELINK:
    1779         392 :             ReadChSourceLink( rStrm );
    1780         392 :         break;
    1781             :         case EXC_ID_CHDATAFORMAT:
    1782         212 :             ReadChDataFormat( rStrm );
    1783         212 :         break;
    1784             :         case EXC_ID_CHSERGROUP:
    1785          92 :             rStrm >> mnGroupIdx;
    1786          92 :         break;
    1787             :         case EXC_ID_CHSERPARENT:
    1788           6 :             ReadChSerParent( rStrm );
    1789           6 :         break;
    1790             :         case EXC_ID_CHSERTRENDLINE:
    1791           6 :             ReadChSerTrendLine( rStrm );
    1792           6 :         break;
    1793             :         case EXC_ID_CHSERERRORBAR:
    1794           0 :             ReadChSerErrorBar( rStrm );
    1795           0 :         break;
    1796             :     }
    1797        1040 : }
    1798             : 
    1799         212 : void XclImpChSeries::SetDataFormat( const XclImpChDataFormatRef& xDataFmt )
    1800             : {
    1801         212 :     if (!xDataFmt)
    1802          98 :         return;
    1803             : 
    1804         212 :     sal_uInt16 nPointIdx = xDataFmt->GetPointPos().mnPointIdx;
    1805         212 :     if (nPointIdx == EXC_CHDATAFORMAT_ALLPOINTS)
    1806             :     {
    1807          98 :         if (mxSeriesFmt)
    1808             :             // Don't overwrite the existing format.
    1809           0 :             return;
    1810             : 
    1811          98 :         mxSeriesFmt = xDataFmt;
    1812          98 :         if (HasParentSeries())
    1813           6 :             return;
    1814             : 
    1815          92 :         XclImpChTypeGroupRef pTypeGroup = GetChartData().GetTypeGroup(mnGroupIdx);
    1816          92 :         if (pTypeGroup)
    1817          92 :             pTypeGroup->SetUsedFormatIndex(xDataFmt->GetFormatIdx());
    1818             : 
    1819          92 :         return;
    1820             :     }
    1821             : 
    1822         114 :     if (nPointIdx >= EXC_CHDATAFORMAT_MAXPOINTCOUNT)
    1823             :         // Above the max point count.  Bail out.
    1824           0 :         return;
    1825             : 
    1826         114 :     XclImpChDataFormatMap::iterator itr = maPointFmts.lower_bound(nPointIdx);
    1827         114 :     if (itr == maPointFmts.end() || maPointFmts.key_comp()(nPointIdx, itr->first))
    1828             :     {
    1829             :         // No object exists at this point index position.  Insert it.
    1830         114 :         itr = maPointFmts.insert(itr, XclImpChDataFormatMap::value_type(nPointIdx, xDataFmt));
    1831             :     }
    1832             : }
    1833             : 
    1834         134 : void XclImpChSeries::SetDataLabel( const XclImpChTextRef& xLabel )
    1835             : {
    1836         134 :     if (!xLabel)
    1837           0 :         return;
    1838             : 
    1839         134 :     sal_uInt16 nPointIdx = xLabel->GetPointPos().mnPointIdx;
    1840         134 :     if ((nPointIdx != EXC_CHDATAFORMAT_ALLPOINTS) && (nPointIdx >= EXC_CHDATAFORMAT_MAXPOINTCOUNT))
    1841             :         // Above the maximum allowed data points. Bail out.
    1842           0 :         return;
    1843             : 
    1844         134 :     XclImpChTextMap::iterator itr = maLabels.lower_bound(nPointIdx);
    1845         134 :     if (itr == maLabels.end() || maLabels.key_comp()(nPointIdx, itr->first))
    1846             :     {
    1847             :         // No object exists at this point index position.  Insert it.
    1848         134 :         itr = maLabels.insert(itr, XclImpChTextMap::value_type(nPointIdx, xLabel));
    1849             :     }
    1850             : }
    1851             : 
    1852           6 : void XclImpChSeries::AddChildSeries( const XclImpChSeries& rSeries )
    1853             : {
    1854             :     OSL_ENSURE( !HasParentSeries(), "XclImpChSeries::AddChildSeries - not allowed for child series" );
    1855             : 
    1856             :     /*  In Excel, trend lines and error bars are stored as own series. In Calc,
    1857             :         these are properties of the parent series. This function adds the
    1858             :         settings of the passed series to this series. */
    1859           6 :     maTrendLines.insert( maTrendLines.end(), rSeries.maTrendLines.begin(), rSeries.maTrendLines.end() );
    1860           6 :     maErrorBars.insert( rSeries.maErrorBars.begin(), rSeries.maErrorBars.end() );
    1861           6 : }
    1862             : 
    1863          98 : void XclImpChSeries::FinalizeDataFormats()
    1864             : {
    1865          98 :     if( HasParentSeries() )
    1866             :     {
    1867             :         // *** series is a child series, e.g. trend line or error bar ***
    1868             : 
    1869             :         // create missing series format
    1870           6 :         if( !mxSeriesFmt )
    1871           0 :             mxSeriesFmt = CreateDataFormat( EXC_CHDATAFORMAT_ALLPOINTS, 0 );
    1872             : 
    1873           6 :         if( mxSeriesFmt )
    1874             :         {
    1875             :             // #i83100# set text label format, e.g. for trend line equations
    1876           6 :             XclImpChTextRef xLabel;
    1877           6 :             XclImpChTextMap::iterator itr = maLabels.find(EXC_CHDATAFORMAT_ALLPOINTS);
    1878           6 :             if (itr != maLabels.end())
    1879           4 :                 xLabel = itr->second;
    1880           6 :             mxSeriesFmt->SetDataLabel(xLabel);
    1881             :             // create missing automatic formats
    1882           6 :             mxSeriesFmt->UpdateTrendLineFormat();
    1883             :         }
    1884             : 
    1885             :         // copy series formatting to child objects
    1886          12 :         for( XclImpChSerTrendLineList::iterator aLIt = maTrendLines.begin(), aLEnd = maTrendLines.end(); aLIt != aLEnd; ++aLIt )
    1887             :         {
    1888           6 :             (*aLIt)->SetDataFormat(mxSeriesFmt);
    1889           6 :             if (mxTitleLink->HasString())
    1890             :             {
    1891           6 :                 (*aLIt)->SetTrendlineName(mxTitleLink->GetString());
    1892             :             }
    1893             :         }
    1894           6 :         for( XclImpChSerErrorBarMap::iterator aMIt = maErrorBars.begin(), aMEnd = maErrorBars.end(); aMIt != aMEnd; ++aMIt )
    1895             :         {
    1896           0 :             aMIt->second->SetSeriesData( mxValueLink, mxSeriesFmt );
    1897             :         }
    1898             :     }
    1899          92 :     else if( XclImpChTypeGroup* pTypeGroup = GetChartData().GetTypeGroup( mnGroupIdx ).get() )
    1900             :     {
    1901             :         // *** series is a regular data series ***
    1902             : 
    1903             :         // create missing series format
    1904          92 :         if( !mxSeriesFmt )
    1905             :         {
    1906             :             // #i51639# use a new unused format index to create series default format
    1907           0 :             sal_uInt16 nFormatIdx = pTypeGroup->PopUnusedFormatIndex();
    1908           0 :             mxSeriesFmt = CreateDataFormat( EXC_CHDATAFORMAT_ALLPOINTS, nFormatIdx );
    1909             :         }
    1910             : 
    1911             :         // set text labels to data formats
    1912         222 :         for( XclImpChTextMap::iterator aTIt = maLabels.begin(), aTEnd = maLabels.end(); aTIt != aTEnd; ++aTIt )
    1913             :         {
    1914         130 :             sal_uInt16 nPointIdx = aTIt->first;
    1915         130 :             if (nPointIdx == EXC_CHDATAFORMAT_ALLPOINTS)
    1916             :             {
    1917          76 :                 if (!mxSeriesFmt)
    1918           0 :                     mxSeriesFmt = CreateDataFormat(nPointIdx, EXC_CHDATAFORMAT_DEFAULT);
    1919          76 :                 mxSeriesFmt->SetDataLabel(aTIt->second);
    1920             :             }
    1921          54 :             else if (nPointIdx < EXC_CHDATAFORMAT_MAXPOINTCOUNT)
    1922             :             {
    1923          54 :                 XclImpChDataFormatRef p;
    1924          54 :                 XclImpChDataFormatMap::iterator itr = maPointFmts.lower_bound(nPointIdx);
    1925          54 :                 if (itr == maPointFmts.end() || maPointFmts.key_comp()(nPointIdx, itr->first))
    1926             :                 {
    1927             :                     // No object exists at this point index position.  Insert
    1928             :                     // a new one.
    1929           0 :                     p = CreateDataFormat(nPointIdx, EXC_CHDATAFORMAT_DEFAULT);
    1930             :                     itr = maPointFmts.insert(
    1931           0 :                         itr, XclImpChDataFormatMap::value_type(nPointIdx, p));
    1932             :                 }
    1933             :                 else
    1934          54 :                     p = itr->second;
    1935          54 :                 p->SetDataLabel(aTIt->second);
    1936             :             }
    1937             :         }
    1938             : 
    1939             :         // update series format (copy missing formatting from group default format)
    1940          92 :         if( mxSeriesFmt )
    1941          92 :             mxSeriesFmt->UpdateSeriesFormat( pTypeGroup->GetTypeInfo(), pTypeGroup->GetGroupFormat().get() );
    1942             : 
    1943             :         // update data point formats (removes unchanged automatic formatting)
    1944         206 :         for( XclImpChDataFormatMap::iterator aFIt = maPointFmts.begin(), aFEnd = maPointFmts.end(); aFIt != aFEnd; ++aFIt )
    1945         114 :             aFIt->second->UpdatePointFormat( pTypeGroup->GetTypeInfo(), mxSeriesFmt.get() );
    1946             :     }
    1947          98 : }
    1948             : 
    1949             : namespace {
    1950             : 
    1951             : /** Returns the property set of the specified data point. */
    1952         224 : ScfPropertySet lclGetPointPropSet( Reference< XDataSeries > xDataSeries, sal_uInt16 nPointIdx )
    1953             : {
    1954         224 :     ScfPropertySet aPropSet;
    1955             :     try
    1956             :     {
    1957         224 :         aPropSet.Set( xDataSeries->getDataPointByIndex( static_cast< sal_Int32 >( nPointIdx ) ) );
    1958             :     }
    1959           0 :     catch( Exception& )
    1960             :     {
    1961             :         OSL_FAIL( "lclGetPointPropSet - no data point property set" );
    1962             :     }
    1963         224 :     return aPropSet;
    1964             : }
    1965             : 
    1966             : } // namespace
    1967             : 
    1968          92 : Reference< XLabeledDataSequence > XclImpChSeries::CreateValueSequence( const OUString& rValueRole ) const
    1969             : {
    1970          92 :     return lclCreateLabeledDataSequence( mxValueLink, rValueRole, mxTitleLink.get() );
    1971             : }
    1972             : 
    1973          88 : Reference< XLabeledDataSequence > XclImpChSeries::CreateCategSequence( const OUString& rCategRole ) const
    1974             : {
    1975          88 :     return lclCreateLabeledDataSequence( mxCategLink, rCategRole );
    1976             : }
    1977             : 
    1978          92 : Reference< XDataSeries > XclImpChSeries::CreateDataSeries() const
    1979             : {
    1980          92 :     Reference< XDataSeries > xDataSeries;
    1981          92 :     if( const XclImpChTypeGroup* pTypeGroup = GetChartData().GetTypeGroup( mnGroupIdx ).get() )
    1982             :     {
    1983          92 :         const XclChExtTypeInfo& rTypeInfo = pTypeGroup->GetTypeInfo();
    1984             : 
    1985             :         // create the data series object
    1986          92 :         xDataSeries.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES ), UNO_QUERY );
    1987             : 
    1988             :         // attach data and title sequences to series
    1989          92 :         Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
    1990          92 :         if( xDataSink.is() )
    1991             :         {
    1992             :             // create vector of all value sequences
    1993          92 :             ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
    1994             :             // add Y values
    1995             :             Reference< XLabeledDataSequence > xYValueSeq =
    1996         184 :                 CreateValueSequence( EXC_CHPROP_ROLE_YVALUES );
    1997          92 :             if( xYValueSeq.is() )
    1998          92 :                 aLabeledSeqVec.push_back( xYValueSeq );
    1999             :             // add X values
    2000          92 :             if( !rTypeInfo.mbCategoryAxis )
    2001             :             {
    2002             :                 Reference< XLabeledDataSequence > xXValueSeq =
    2003           2 :                     CreateCategSequence( EXC_CHPROP_ROLE_XVALUES );
    2004           2 :                 if( xXValueSeq.is() )
    2005           2 :                     aLabeledSeqVec.push_back( xXValueSeq );
    2006             :                 // add size values of bubble charts
    2007           2 :                 if( rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES )
    2008             :                 {
    2009             :                     Reference< XLabeledDataSequence > xSizeValueSeq =
    2010           0 :                         lclCreateLabeledDataSequence( mxBubbleLink, EXC_CHPROP_ROLE_SIZEVALUES, mxTitleLink.get() );
    2011           0 :                     if( xSizeValueSeq.is() )
    2012           0 :                         aLabeledSeqVec.push_back( xSizeValueSeq );
    2013           2 :                 }
    2014             :             }
    2015             :             // attach labeled data sequences to series
    2016          92 :             if( !aLabeledSeqVec.empty() )
    2017         184 :                 xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
    2018             :         }
    2019             : 
    2020             :         // series formatting
    2021         184 :         ScfPropertySet aSeriesProp( xDataSeries );
    2022          92 :         if( mxSeriesFmt )
    2023          92 :             mxSeriesFmt->Convert( aSeriesProp, rTypeInfo );
    2024             : 
    2025             :         // trend lines
    2026          92 :         ConvertTrendLines( xDataSeries );
    2027             : 
    2028             :         // error bars
    2029         184 :         Reference< XPropertySet > xErrorBarX = CreateErrorBar( EXC_CHSERERR_XPLUS, EXC_CHSERERR_XMINUS );
    2030          92 :         if( xErrorBarX.is() )
    2031           0 :             aSeriesProp.SetProperty( EXC_CHPROP_ERRORBARX, xErrorBarX );
    2032         184 :         Reference< XPropertySet > xErrorBarY = CreateErrorBar( EXC_CHSERERR_YPLUS, EXC_CHSERERR_YMINUS );
    2033          92 :         if( xErrorBarY.is() )
    2034           0 :             aSeriesProp.SetProperty( EXC_CHPROP_ERRORBARY, xErrorBarY );
    2035             : 
    2036             :         // own area formatting for every data point (TODO: varying line color not supported)
    2037          92 :         bool bVarPointFmt = pTypeGroup->HasVarPointFormat() && rTypeInfo.IsSeriesFrameFormat();
    2038             : #if EXC_CHART2_VARYCOLORSBY_PROP
    2039             :         aSeriesProp.SetBoolProperty( EXC_CHPROP_VARYCOLORSBY, bVarPointFmt );
    2040             : #else
    2041          92 :         aSeriesProp.SetBoolProperty( EXC_CHPROP_VARYCOLORSBY, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE );
    2042             : #endif
    2043             :         // #i91271# always set area formatting for every point in pie/doughnut charts
    2044          92 :         if (mxSeriesFmt && mxValueLink && ((bVarPointFmt && mxSeriesFmt->IsAutoArea()) || (rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE)))
    2045             :         {
    2046         184 :             for( sal_uInt16 nPointIdx = 0, nPointCount = mxValueLink->GetCellCount(); nPointIdx < nPointCount; ++nPointIdx )
    2047             :             {
    2048         110 :                 ScfPropertySet aPointProp = lclGetPointPropSet( xDataSeries, nPointIdx );
    2049         110 :                 mxSeriesFmt->ConvertArea( aPointProp, bVarPointFmt ? nPointIdx : mnSeriesIdx, false );
    2050         110 :             }
    2051             :         }
    2052             : 
    2053             :         // data point formatting
    2054         206 :         for( XclImpChDataFormatMap::const_iterator aIt = maPointFmts.begin(), aEnd = maPointFmts.end(); aIt != aEnd; ++aIt )
    2055             :         {
    2056         114 :             ScfPropertySet aPointProp = lclGetPointPropSet( xDataSeries, aIt->first );
    2057         114 :             aIt->second->Convert( aPointProp, rTypeInfo );
    2058         206 :         }
    2059             :     }
    2060          92 :     return xDataSeries;
    2061             : }
    2062             : 
    2063          98 : void XclImpChSeries::FillAllSourceLinks( ::std::vector< ScTokenRef >& rTokens ) const
    2064             : {
    2065          98 :     if( mxValueLink )
    2066          98 :         mxValueLink->FillSourceLink( rTokens );
    2067          98 :     if( mxCategLink )
    2068          98 :         mxCategLink->FillSourceLink( rTokens );
    2069          98 :     if( mxTitleLink )
    2070          98 :         mxTitleLink->FillSourceLink( rTokens );
    2071          98 :     if( mxBubbleLink )
    2072          98 :         mxBubbleLink->FillSourceLink( rTokens );
    2073          98 : }
    2074             : 
    2075         392 : void XclImpChSeries::ReadChSourceLink( XclImpStream& rStrm )
    2076             : {
    2077         392 :     XclImpChSourceLinkRef xSrcLink( new XclImpChSourceLink( GetChRoot() ) );
    2078         392 :     xSrcLink->ReadChSourceLink( rStrm );
    2079         392 :     switch( xSrcLink->GetDestType() )
    2080             :     {
    2081          98 :         case EXC_CHSRCLINK_TITLE:       mxTitleLink = xSrcLink;     break;
    2082          98 :         case EXC_CHSRCLINK_VALUES:      mxValueLink = xSrcLink;     break;
    2083          98 :         case EXC_CHSRCLINK_CATEGORY:    mxCategLink = xSrcLink;     break;
    2084          98 :         case EXC_CHSRCLINK_BUBBLES:     mxBubbleLink = xSrcLink;    break;
    2085         392 :     }
    2086         392 : }
    2087             : 
    2088         212 : void XclImpChSeries::ReadChDataFormat( XclImpStream& rStrm )
    2089             : {
    2090             :     // #i51639# chart stores all data formats and assigns them later to the series
    2091         212 :     GetChartData().ReadChDataFormat( rStrm );
    2092         212 : }
    2093             : 
    2094           6 : void XclImpChSeries::ReadChSerParent( XclImpStream& rStrm )
    2095             : {
    2096           6 :     rStrm >> mnParentIdx;
    2097             :     // index to parent series is 1-based, convert it to 0-based
    2098           6 :     if( mnParentIdx > 0 )
    2099           6 :         --mnParentIdx;
    2100             :     else
    2101           0 :         mnParentIdx = EXC_CHSERIES_INVALID;
    2102           6 : }
    2103             : 
    2104           6 : void XclImpChSeries::ReadChSerTrendLine( XclImpStream& rStrm )
    2105             : {
    2106           6 :     XclImpChSerTrendLineRef xTrendLine( new XclImpChSerTrendLine( GetChRoot() ) );
    2107           6 :     xTrendLine->ReadChSerTrendLine( rStrm );
    2108           6 :     maTrendLines.push_back( xTrendLine );
    2109           6 : }
    2110             : 
    2111           0 : void XclImpChSeries::ReadChSerErrorBar( XclImpStream& rStrm )
    2112             : {
    2113           0 :     unique_ptr<XclImpChSerErrorBar> pErrorBar(new XclImpChSerErrorBar(GetChRoot()));
    2114           0 :     pErrorBar->ReadChSerErrorBar(rStrm);
    2115           0 :     sal_uInt8 nBarType = pErrorBar->GetBarType();
    2116           0 :     o3tl::ptr_container::insert(maErrorBars, nBarType, std::move(pErrorBar));
    2117           0 : }
    2118             : 
    2119           0 : XclImpChDataFormatRef XclImpChSeries::CreateDataFormat( sal_uInt16 nPointIdx, sal_uInt16 nFormatIdx )
    2120             : {
    2121           0 :     XclImpChDataFormatRef xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
    2122           0 :     xDataFmt->SetPointPos( XclChDataPointPos( mnSeriesIdx, nPointIdx ), nFormatIdx );
    2123           0 :     return xDataFmt;
    2124             : }
    2125             : 
    2126          92 : void XclImpChSeries::ConvertTrendLines( Reference< XDataSeries > xDataSeries ) const
    2127             : {
    2128          92 :     Reference< XRegressionCurveContainer > xRegCurveCont( xDataSeries, UNO_QUERY );
    2129          92 :     if( xRegCurveCont.is() )
    2130             :     {
    2131          98 :         for( XclImpChSerTrendLineList::const_iterator aIt = maTrendLines.begin(), aEnd = maTrendLines.end(); aIt != aEnd; ++aIt )
    2132             :         {
    2133             :             try
    2134             :             {
    2135           6 :                 Reference< XRegressionCurve > xRegCurve = (*aIt)->CreateRegressionCurve();
    2136           6 :                 if( xRegCurve.is() )
    2137             :                 {
    2138           6 :                     xRegCurveCont->addRegressionCurve( xRegCurve );
    2139           6 :                 }
    2140             :             }
    2141           0 :             catch( Exception& )
    2142             :             {
    2143             :                 OSL_FAIL( "XclImpChSeries::ConvertTrendLines - cannot add regression curve" );
    2144             :             }
    2145             :         }
    2146          92 :     }
    2147          92 : }
    2148             : 
    2149         184 : Reference< XPropertySet > XclImpChSeries::CreateErrorBar( sal_uInt8 nPosBarId, sal_uInt8 nNegBarId ) const
    2150             : {
    2151         184 :     XclImpChSerErrorBarMap::const_iterator itrPosBar = maErrorBars.find(nPosBarId);
    2152         184 :     XclImpChSerErrorBarMap::const_iterator itrNegBar = maErrorBars.find(nNegBarId);
    2153         184 :     XclImpChSerErrorBarMap::const_iterator itrEnd = maErrorBars.end();
    2154         184 :     if (itrPosBar == itrEnd || itrNegBar == itrEnd)
    2155         184 :         return Reference<XPropertySet>();
    2156             : 
    2157           0 :     return XclImpChSerErrorBar::CreateErrorBar(itrPosBar->second, itrNegBar->second);
    2158             : }
    2159             : 
    2160             : // Chart type groups ==========================================================
    2161             : 
    2162          88 : XclImpChType::XclImpChType( const XclImpChRoot& rRoot ) :
    2163             :     XclImpChRoot( rRoot ),
    2164             :     mnRecId( EXC_ID_CHUNKNOWN ),
    2165          88 :     maTypeInfo( rRoot.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN ) )
    2166             : {
    2167          88 : }
    2168             : 
    2169         384 : void XclImpChType::ReadChType( XclImpStream& rStrm )
    2170             : {
    2171         384 :     sal_uInt16 nRecId = rStrm.GetRecId();
    2172         384 :     bool bKnownType = true;
    2173             : 
    2174         384 :     switch( nRecId )
    2175             :     {
    2176             :         case EXC_ID_CHBAR:
    2177           8 :             rStrm >> maData.mnOverlap >> maData.mnGap >> maData.mnFlags;
    2178           8 :         break;
    2179             : 
    2180             :         case EXC_ID_CHLINE:
    2181             :         case EXC_ID_CHAREA:
    2182             :         case EXC_ID_CHRADARLINE:
    2183             :         case EXC_ID_CHRADARAREA:
    2184           2 :             rStrm >> maData.mnFlags;
    2185           2 :         break;
    2186             : 
    2187             :         case EXC_ID_CHPIE:
    2188          74 :             rStrm >> maData.mnRotation >> maData.mnPieHole;
    2189          74 :             if( GetBiff() == EXC_BIFF8 )
    2190          74 :                 rStrm >> maData.mnFlags;
    2191             :             else
    2192           0 :                 maData.mnFlags = 0;
    2193          74 :         break;
    2194             : 
    2195             :         case EXC_ID_CHPIEEXT:
    2196           0 :             maData.mnRotation = 0;
    2197           0 :             maData.mnPieHole = 0;
    2198           0 :             maData.mnFlags = 0;
    2199           0 :         break;
    2200             : 
    2201             :         case EXC_ID_CHSCATTER:
    2202           2 :             if( GetBiff() == EXC_BIFF8 )
    2203           2 :                 rStrm >> maData.mnBubbleSize >> maData.mnBubbleType >> maData.mnFlags;
    2204             :             else
    2205           0 :                 maData.mnFlags = 0;
    2206           2 :         break;
    2207             : 
    2208             :         case EXC_ID_CHSURFACE:
    2209           0 :             rStrm >> maData.mnFlags;
    2210           0 :         break;
    2211             : 
    2212             :         default:
    2213         298 :             bKnownType = false;
    2214             :     }
    2215             : 
    2216         384 :     if( bKnownType )
    2217          86 :         mnRecId = nRecId;
    2218         384 : }
    2219             : 
    2220          88 : void XclImpChType::Finalize( bool bStockChart )
    2221             : {
    2222          88 :     switch( mnRecId )
    2223             :     {
    2224             :         case EXC_ID_CHLINE:
    2225             :             maTypeInfo = GetChartTypeInfo( bStockChart ?
    2226           2 :                 EXC_CHTYPEID_STOCK : EXC_CHTYPEID_LINE );
    2227           2 :         break;
    2228             :         case EXC_ID_CHBAR:
    2229             :             maTypeInfo = GetChartTypeInfo( ::get_flagvalue(
    2230             :                 maData.mnFlags, EXC_CHBAR_HORIZONTAL,
    2231           8 :                 EXC_CHTYPEID_HORBAR, EXC_CHTYPEID_BAR ) );
    2232           8 :         break;
    2233             :         case EXC_ID_CHPIE:
    2234          74 :             maTypeInfo = GetChartTypeInfo( (maData.mnPieHole > 0) ?
    2235          74 :                 EXC_CHTYPEID_DONUT : EXC_CHTYPEID_PIE );
    2236          74 :         break;
    2237             :         case EXC_ID_CHSCATTER:
    2238             :             maTypeInfo = GetChartTypeInfo( ::get_flagvalue(
    2239             :                 maData.mnFlags, EXC_CHSCATTER_BUBBLES,
    2240           2 :                 EXC_CHTYPEID_BUBBLES, EXC_CHTYPEID_SCATTER ) );
    2241           2 :         break;
    2242             :         default:
    2243           2 :             maTypeInfo = GetChartTypeInfo( mnRecId );
    2244             :     }
    2245             : 
    2246          88 :     switch( maTypeInfo.meTypeId )
    2247             :     {
    2248             :         case EXC_CHTYPEID_PIEEXT:
    2249             :         case EXC_CHTYPEID_BUBBLES:
    2250             :         case EXC_CHTYPEID_SURFACE:
    2251             :         case EXC_CHTYPEID_UNKNOWN:
    2252           2 :             GetTracer().TraceChartUnKnownType();
    2253           2 :         break;
    2254             :         default:;
    2255             :     }
    2256          88 : }
    2257             : 
    2258         180 : bool XclImpChType::IsStacked() const
    2259             : {
    2260         180 :     bool bStacked = false;
    2261         180 :     if( maTypeInfo.mbSupportsStacking ) switch( maTypeInfo.meTypeCateg )
    2262             :     {
    2263             :         case EXC_CHTYPECATEG_LINE:
    2264             :             bStacked =
    2265           8 :                 ::get_flag( maData.mnFlags, EXC_CHLINE_STACKED ) &&
    2266           8 :                 !::get_flag( maData.mnFlags, EXC_CHLINE_PERCENT );
    2267           4 :         break;
    2268             :         case EXC_CHTYPECATEG_BAR:
    2269             :             bStacked =
    2270          24 :                 ::get_flag( maData.mnFlags, EXC_CHBAR_STACKED ) &&
    2271          24 :                 !::get_flag( maData.mnFlags, EXC_CHBAR_PERCENT );
    2272          24 :         break;
    2273             :         default:;
    2274             :     }
    2275         180 :     return bStacked;
    2276             : }
    2277             : 
    2278         264 : bool XclImpChType::IsPercent() const
    2279             : {
    2280         264 :     bool bPercent = false;
    2281         264 :     if( maTypeInfo.mbSupportsStacking ) switch( maTypeInfo.meTypeCateg )
    2282             :     {
    2283             :         case EXC_CHTYPECATEG_LINE:
    2284             :             bPercent =
    2285           4 :                 ::get_flag( maData.mnFlags, EXC_CHLINE_STACKED ) &&
    2286           4 :                 ::get_flag( maData.mnFlags, EXC_CHLINE_PERCENT );
    2287           2 :         break;
    2288             :         case EXC_CHTYPECATEG_BAR:
    2289             :             bPercent =
    2290          34 :                 ::get_flag( maData.mnFlags, EXC_CHBAR_STACKED ) &&
    2291          34 :                 ::get_flag( maData.mnFlags, EXC_CHBAR_PERCENT );
    2292          34 :         break;
    2293             :         default:;
    2294             :     }
    2295         264 :     return bPercent;
    2296             : }
    2297             : 
    2298          88 : bool XclImpChType::HasCategoryLabels() const
    2299             : {
    2300             :     // radar charts disable category labels in chart type, not in CHTICK of X axis
    2301          88 :     return (maTypeInfo.meTypeCateg != EXC_CHTYPECATEG_RADAR) || ::get_flag( maData.mnFlags, EXC_CHRADAR_AXISLABELS );
    2302             : }
    2303             : 
    2304          88 : Reference< XCoordinateSystem > XclImpChType::CreateCoordSystem( bool b3dChart ) const
    2305             : {
    2306             :     // create the coordinate system object
    2307          88 :     Reference< css::uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
    2308          88 :     Reference< XCoordinateSystem > xCoordSystem;
    2309          88 :     if( maTypeInfo.mbPolarCoordSystem )
    2310             :     {
    2311          74 :         if( b3dChart )
    2312           0 :             xCoordSystem = css::chart2::PolarCoordinateSystem3d::create(xContext);
    2313             :         else
    2314          74 :             xCoordSystem = css::chart2::PolarCoordinateSystem2d::create(xContext);
    2315             :     }
    2316             :     else
    2317             :     {
    2318          14 :         if( b3dChart )
    2319           0 :             xCoordSystem = css::chart2::CartesianCoordinateSystem3d::create(xContext);
    2320             :         else
    2321          14 :             xCoordSystem = css::chart2::CartesianCoordinateSystem2d::create(xContext);
    2322             :     }
    2323             : 
    2324             :     // swap X and Y axis
    2325          88 :     if( maTypeInfo.mbSwappedAxesSet )
    2326             :     {
    2327           0 :         ScfPropertySet aCoordSysProp( xCoordSystem );
    2328           0 :         aCoordSysProp.SetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS, true );
    2329             :     }
    2330             : 
    2331          88 :     return xCoordSystem;
    2332             : }
    2333             : 
    2334          88 : Reference< XChartType > XclImpChType::CreateChartType( Reference< XDiagram > xDiagram, bool b3dChart ) const
    2335             : {
    2336          88 :     OUString aService = OUString::createFromAscii( maTypeInfo.mpcServiceName );
    2337          88 :     Reference< XChartType > xChartType( ScfApiHelper::CreateInstance( aService ), UNO_QUERY );
    2338             : 
    2339             :     // additional properties
    2340          88 :     switch( maTypeInfo.meTypeCateg )
    2341             :     {
    2342             :         case EXC_CHTYPECATEG_BAR:
    2343             :         {
    2344          10 :             ScfPropertySet aTypeProp( xChartType );
    2345          20 :             Sequence< sal_Int32 > aInt32Seq( 2 );
    2346          10 :             aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = -maData.mnOverlap;
    2347          10 :             aTypeProp.SetProperty( EXC_CHPROP_OVERLAPSEQ, aInt32Seq );
    2348          10 :             aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = maData.mnGap;
    2349          20 :             aTypeProp.SetProperty( EXC_CHPROP_GAPWIDTHSEQ, aInt32Seq );
    2350             :         }
    2351          10 :         break;
    2352             :         case EXC_CHTYPECATEG_PIE:
    2353             :         {
    2354          74 :             ScfPropertySet aTypeProp( xChartType );
    2355          74 :             aTypeProp.SetBoolProperty( EXC_CHPROP_USERINGS, maTypeInfo.meTypeId == EXC_CHTYPEID_DONUT );
    2356             :             /*  #i85166# starting angle of first pie slice. 3D pie charts use Y
    2357             :                 rotation setting in view3D element. Of-pie charts do not
    2358             :                 support pie rotation. */
    2359          74 :             if( !b3dChart && (maTypeInfo.meTypeId != EXC_CHTYPEID_PIEEXT) )
    2360             :             {
    2361          74 :                 ScfPropertySet aDiaProp( xDiagram );
    2362          74 :                 XclImpChRoot::ConvertPieRotation( aDiaProp, maData.mnRotation );
    2363          74 :             }
    2364             :         }
    2365          74 :         break;
    2366             :         default:;
    2367             :     }
    2368             : 
    2369          88 :     return xChartType;
    2370             : }
    2371             : 
    2372           0 : void XclImpChChart3d::ReadChChart3d( XclImpStream& rStrm )
    2373             : {
    2374           0 :     rStrm   >> maData.mnRotation
    2375           0 :             >> maData.mnElevation
    2376           0 :             >> maData.mnEyeDist
    2377           0 :             >> maData.mnRelHeight
    2378           0 :             >> maData.mnRelDepth
    2379           0 :             >> maData.mnDepthGap
    2380           0 :             >> maData.mnFlags;
    2381           0 : }
    2382             : 
    2383           0 : void XclImpChChart3d::Convert( ScfPropertySet& rPropSet, bool b3dWallChart ) const
    2384             : {
    2385             :     namespace cssd = ::com::sun::star::drawing;
    2386             : 
    2387             : //    #i104057# do not assert this, written by broken external generators
    2388             : //    OSL_ENSURE( ::get_flag( maData.mnFlags, EXC_CHCHART3D_HASWALLS ) == b3dWallChart, "XclImpChChart3d::Convert - wrong wall flag" );
    2389             : 
    2390           0 :     sal_Int32 nRotationY = 0;
    2391           0 :     sal_Int32 nRotationX = 0;
    2392           0 :     sal_Int32 nPerspective = 15;
    2393           0 :     bool bRightAngled = false;
    2394           0 :     cssd::ProjectionMode eProjMode = cssd::ProjectionMode_PERSPECTIVE;
    2395           0 :     Color aAmbientColor, aLightColor;
    2396             : 
    2397           0 :     if( b3dWallChart )
    2398             :     {
    2399             :         // Y rotation (Excel [0..359], Chart2 [-179,180])
    2400           0 :         nRotationY = maData.mnRotation % 360;
    2401           0 :         if( nRotationY > 180 ) nRotationY -= 360;
    2402             :         // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
    2403           0 :         nRotationX = limit_cast< sal_Int32, sal_Int32 >( maData.mnElevation, -90, 90 );
    2404             :         // perspective (Excel and Chart2 [0,100])
    2405           0 :         nPerspective = limit_cast< sal_Int32, sal_Int32 >( maData.mnEyeDist, 0, 100 );
    2406             :         // right-angled axes
    2407           0 :         bRightAngled = !::get_flag( maData.mnFlags, EXC_CHCHART3D_REAL3D );
    2408             :         // projection mode (parallel axes, if right-angled, #i90360# or if perspective is at 0%)
    2409           0 :         bool bParallel = bRightAngled || (nPerspective == 0);
    2410           0 :         eProjMode = bParallel ? cssd::ProjectionMode_PARALLEL : cssd::ProjectionMode_PERSPECTIVE;
    2411             :         // ambient color (Gray 20%)
    2412           0 :         aAmbientColor.SetColor( RGB_COLORDATA( 204, 204, 204 ) );
    2413             :         // light color (Gray 60%)
    2414           0 :         aLightColor.SetColor( RGB_COLORDATA( 102, 102, 102 ) );
    2415             :     }
    2416             :     else
    2417             :     {
    2418             :         // Y rotation not used in pie charts, but 'first pie slice angle'
    2419           0 :         nRotationY = 0;
    2420           0 :         XclImpChRoot::ConvertPieRotation( rPropSet, maData.mnRotation );
    2421             :         // X rotation a.k.a. elevation (map Excel [10..80] to Chart2 [-80,-10])
    2422           0 :         nRotationX = limit_cast< sal_Int32, sal_Int32 >( maData.mnElevation, 10, 80 ) - 90;
    2423             :         // perspective (Excel and Chart2 [0,100])
    2424           0 :         nPerspective = limit_cast< sal_Int32, sal_Int32 >( maData.mnEyeDist, 0, 100 );
    2425             :         // no right-angled axes in pie charts, but parallel projection
    2426           0 :         bRightAngled = false;
    2427           0 :         eProjMode = cssd::ProjectionMode_PARALLEL;
    2428             :         // ambient color (Gray 30%)
    2429           0 :         aAmbientColor.SetColor( RGB_COLORDATA( 179, 179, 179 ) );
    2430             :         // light color (Gray 70%)
    2431           0 :         aLightColor.SetColor( RGB_COLORDATA( 76, 76, 76 ) );
    2432             :     }
    2433             : 
    2434             :     // properties
    2435           0 :     rPropSet.SetProperty( EXC_CHPROP_3DRELATIVEHEIGHT, (sal_Int32)(maData.mnRelHeight / 2)); // seems to be 200%, cange to 100%
    2436           0 :     rPropSet.SetProperty( EXC_CHPROP_ROTATIONVERTICAL, nRotationY );
    2437           0 :     rPropSet.SetProperty( EXC_CHPROP_ROTATIONHORIZONTAL, nRotationX );
    2438           0 :     rPropSet.SetProperty( EXC_CHPROP_PERSPECTIVE, nPerspective );
    2439           0 :     rPropSet.SetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES, bRightAngled );
    2440           0 :     rPropSet.SetProperty( EXC_CHPROP_D3DSCENEPERSPECTIVE, eProjMode );
    2441             : 
    2442             :     // light settings
    2443           0 :     rPropSet.SetProperty( EXC_CHPROP_D3DSCENESHADEMODE, cssd::ShadeMode_FLAT );
    2444           0 :     rPropSet.SetColorProperty( EXC_CHPROP_D3DSCENEAMBIENTCOLOR, aAmbientColor );
    2445           0 :     rPropSet.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON1, false );
    2446           0 :     rPropSet.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON2, true );
    2447           0 :     rPropSet.SetColorProperty( EXC_CHPROP_D3DSCENELIGHTCOLOR2, aLightColor );
    2448           0 :     rPropSet.SetProperty( EXC_CHPROP_D3DSCENELIGHTDIR2, cssd::Direction3D( 0.2, 0.4, 1.0 ) );
    2449           0 : }
    2450             : 
    2451          46 : XclImpChLegend::XclImpChLegend( const XclImpChRoot& rRoot ) :
    2452          46 :     XclImpChRoot( rRoot )
    2453             : {
    2454          46 : }
    2455             : 
    2456          46 : void XclImpChLegend::ReadHeaderRecord( XclImpStream& rStrm )
    2457             : {
    2458          46 :     rStrm >> maData.maRect >> maData.mnDockMode >> maData.mnSpacing >> maData.mnFlags;
    2459             : 
    2460             :     // trace unsupported features
    2461          46 :     if( GetTracer().IsEnabled() )
    2462             :     {
    2463           0 :         if( maData.mnDockMode == EXC_CHLEGEND_NOTDOCKED )
    2464           0 :             GetTracer().TraceChartLegendPosition();
    2465           0 :         if( ::get_flag( maData.mnFlags, EXC_CHLEGEND_DATATABLE ) )
    2466           0 :             GetTracer().TraceChartDataTable();
    2467             :     }
    2468          46 : }
    2469             : 
    2470         374 : void XclImpChLegend::ReadSubRecord( XclImpStream& rStrm )
    2471             : {
    2472         374 :     switch( rStrm.GetRecId() )
    2473             :     {
    2474             :         case EXC_ID_CHFRAMEPOS:
    2475          42 :             mxFramePos.reset( new XclImpChFramePos );
    2476          42 :             mxFramePos->ReadChFramePos( rStrm );
    2477          42 :         break;
    2478             :         case EXC_ID_CHTEXT:
    2479          46 :             mxText.reset( new XclImpChText( GetChRoot() ) );
    2480          46 :             mxText->ReadRecordGroup( rStrm );
    2481          46 :         break;
    2482             :         case EXC_ID_CHFRAME:
    2483          42 :             mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND ) );
    2484          42 :             mxFrame->ReadRecordGroup( rStrm );
    2485          42 :         break;
    2486             :     }
    2487         374 : }
    2488             : 
    2489          46 : void XclImpChLegend::Finalize()
    2490             : {
    2491             :     // legend default formatting differs in OOChart and Excel, missing frame means automatic
    2492          46 :     if( !mxFrame )
    2493           4 :         mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND ) );
    2494             :     // Update text formatting. If mxText is empty, the passed default text is used.
    2495          46 :     lclUpdateText( mxText, GetChartData().GetDefaultText( EXC_CHTEXTTYPE_LEGEND ) );
    2496          46 : }
    2497             : 
    2498          46 : Reference< XLegend > XclImpChLegend::CreateLegend() const
    2499             : {
    2500          46 :     Reference< XLegend > xLegend( ScfApiHelper::CreateInstance( SERVICE_CHART2_LEGEND ), UNO_QUERY );
    2501          46 :     if( xLegend.is() )
    2502             :     {
    2503          46 :         ScfPropertySet aLegendProp( xLegend );
    2504          46 :         aLegendProp.SetBoolProperty( EXC_CHPROP_SHOW, true );
    2505             : 
    2506             :         // frame properties
    2507          46 :         if( mxFrame )
    2508          46 :             mxFrame->Convert( aLegendProp );
    2509             :         // text properties
    2510          46 :         if( mxText )
    2511          46 :             mxText->ConvertFont( aLegendProp );
    2512             : 
    2513             :         /*  Legend position and size. Default positions are used only if the
    2514             :             plot area is positioned automatically (Excel sets the plot area to
    2515             :             manual mode, if the legend is moved or resized). With manual plot
    2516             :             areas, Excel ignores the value in maData.mnDockMode completely. */
    2517          46 :         cssc2::LegendPosition eApiPos = cssc2::LegendPosition_CUSTOM;
    2518          46 :         cssc::ChartLegendExpansion eApiExpand = cssc::ChartLegendExpansion_CUSTOM;
    2519          46 :         if( !GetChartData().IsManualPlotArea() ) switch( maData.mnDockMode )
    2520             :         {
    2521             :             case EXC_CHLEGEND_LEFT:
    2522           0 :                 eApiPos = cssc2::LegendPosition_LINE_START;
    2523           0 :                 eApiExpand = cssc::ChartLegendExpansion_HIGH;
    2524           0 :             break;
    2525             :             case EXC_CHLEGEND_RIGHT:
    2526             :             // top-right not supported
    2527             :             case EXC_CHLEGEND_CORNER:
    2528           6 :                 eApiPos = cssc2::LegendPosition_LINE_END;
    2529           6 :                 eApiExpand = cssc::ChartLegendExpansion_HIGH;
    2530           6 :             break;
    2531             :             case EXC_CHLEGEND_TOP:
    2532           0 :                 eApiPos = cssc2::LegendPosition_PAGE_START;
    2533           0 :                 eApiExpand = cssc::ChartLegendExpansion_WIDE;
    2534           0 :             break;
    2535             :             case EXC_CHLEGEND_BOTTOM:
    2536           0 :                 eApiPos = cssc2::LegendPosition_PAGE_END;
    2537           0 :                 eApiExpand = cssc::ChartLegendExpansion_WIDE;
    2538           0 :             break;
    2539             :         }
    2540             : 
    2541             :         // no automatic position/size: try to find the correct position and size
    2542          46 :         if( eApiPos == cssc2::LegendPosition_CUSTOM )
    2543             :         {
    2544          40 :             const XclChFramePos* pFramePos = mxFramePos ? &mxFramePos->GetFramePosData() : 0;
    2545             : 
    2546             :             /*  Legend position. Only the settings from the CHFRAMEPOS record
    2547             :                 are used by Excel, the position in the CHLEGEND record will be
    2548             :                 ignored. */
    2549          40 :             if( pFramePos )
    2550             :             {
    2551             :                 RelativePosition aRelPos(
    2552          40 :                     CalcRelativeFromChartX( pFramePos->maRect.mnX ),
    2553          40 :                     CalcRelativeFromChartY( pFramePos->maRect.mnY ),
    2554         120 :                     ::com::sun::star::drawing::Alignment_TOP_LEFT );
    2555          40 :                 aLegendProp.SetProperty( EXC_CHPROP_RELATIVEPOSITION, aRelPos );
    2556             :             }
    2557             :             else
    2558             :             {
    2559             :                 // no manual position/size found, just go for the default
    2560           0 :                 eApiPos = cssc2::LegendPosition_LINE_END;
    2561             :             }
    2562             : 
    2563             :             /*  Legend size. The member mnBRMode specifies whether size is
    2564             :                 automatic or changes manually. Manual size is given in points,
    2565             :                 not in chart units. */
    2566          78 :             if( pFramePos && (pFramePos->mnBRMode == EXC_CHFRAMEPOS_ABSSIZE_POINTS) &&
    2567          76 :                 (pFramePos->maRect.mnWidth > 0) && (pFramePos->maRect.mnHeight > 0) )
    2568             :             {
    2569          38 :                 eApiExpand = cssc::ChartLegendExpansion_CUSTOM;
    2570          38 :                 sal_Int32 nWidthHmm = static_cast< sal_Int32 >( pFramePos->maRect.mnWidth / EXC_POINTS_PER_HMM );
    2571          38 :                 sal_Int32 nHeightHmm = static_cast< sal_Int32 >( pFramePos->maRect.mnHeight / EXC_POINTS_PER_HMM );
    2572          38 :                 RelativeSize aRelSize( CalcRelativeFromHmmX( nWidthHmm ), CalcRelativeFromHmmY( nHeightHmm ) );
    2573          38 :                 aLegendProp.SetProperty( EXC_CHPROP_RELATIVESIZE, aRelSize );
    2574             :             }
    2575             :             else
    2576             :             {
    2577             :                 // automatic size: determine entry direction from flags
    2578             :                 eApiExpand = ::get_flagvalue( maData.mnFlags, EXC_CHLEGEND_STACKED,
    2579           2 :                     cssc::ChartLegendExpansion_HIGH, cssc::ChartLegendExpansion_WIDE );
    2580             :             }
    2581             :         }
    2582          46 :         aLegendProp.SetProperty( EXC_CHPROP_ANCHORPOSITION, eApiPos );
    2583          46 :         aLegendProp.SetProperty( EXC_CHPROP_EXPANSION, eApiExpand );
    2584             :     }
    2585          46 :     return xLegend;
    2586             : }
    2587             : 
    2588           0 : XclImpChDropBar::XclImpChDropBar( sal_uInt16 nDropBar ) :
    2589             :     mnDropBar( nDropBar ),
    2590           0 :     mnBarDist( 0 )
    2591             : {
    2592           0 : }
    2593             : 
    2594           0 : void XclImpChDropBar::ReadHeaderRecord( XclImpStream& rStrm )
    2595             : {
    2596           0 :     rStrm >> mnBarDist;
    2597           0 : }
    2598             : 
    2599           0 : void XclImpChDropBar::Convert( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet ) const
    2600             : {
    2601           0 :     XclChObjectType eObjType = EXC_CHOBJTYPE_BACKGROUND;
    2602           0 :     switch( mnDropBar )
    2603             :     {
    2604           0 :         case EXC_CHDROPBAR_UP:      eObjType = EXC_CHOBJTYPE_WHITEDROPBAR;  break;
    2605           0 :         case EXC_CHDROPBAR_DOWN:    eObjType = EXC_CHOBJTYPE_BLACKDROPBAR;  break;
    2606             :     }
    2607           0 :     ConvertFrameBase( rRoot, rPropSet, eObjType );
    2608           0 : }
    2609             : 
    2610          88 : XclImpChTypeGroup::XclImpChTypeGroup( const XclImpChRoot& rRoot ) :
    2611             :     XclImpChRoot( rRoot ),
    2612             :     maType( rRoot ),
    2613          88 :     maTypeInfo( maType.GetTypeInfo() )
    2614             : {
    2615             :     // Initialize unused format indexes set. At this time, all formats are unused.
    2616       22616 :     for( sal_uInt16 nFormatIdx = 0; nFormatIdx <= EXC_CHSERIES_MAXSERIES; ++nFormatIdx )
    2617       22528 :         maUnusedFormats.insert( maUnusedFormats.end(), nFormatIdx );
    2618          88 : }
    2619             : 
    2620          88 : void XclImpChTypeGroup::ReadHeaderRecord( XclImpStream& rStrm )
    2621             : {
    2622          88 :     rStrm.Ignore( 16 );
    2623          88 :     rStrm >> maData.mnFlags >> maData.mnGroupIdx;
    2624          88 : }
    2625             : 
    2626         468 : void XclImpChTypeGroup::ReadSubRecord( XclImpStream& rStrm )
    2627             : {
    2628         468 :     switch( rStrm.GetRecId() )
    2629             :     {
    2630             :         case EXC_ID_CHCHART3D:
    2631           0 :             mxChart3d.reset( new XclImpChChart3d );
    2632           0 :             mxChart3d->ReadChChart3d( rStrm );
    2633           0 :         break;
    2634             :         case EXC_ID_CHLEGEND:
    2635          46 :             mxLegend.reset( new XclImpChLegend( GetChRoot() ) );
    2636          46 :             mxLegend->ReadRecordGroup( rStrm );
    2637          46 :         break;
    2638             :         case EXC_ID_CHDEFAULTTEXT:
    2639           0 :             GetChartData().ReadChDefaultText( rStrm );
    2640           0 :         break;
    2641             :         case EXC_ID_CHDROPBAR:
    2642           0 :             ReadChDropBar( rStrm );
    2643           0 :         break;
    2644             :         case EXC_ID_CHCHARTLINE:
    2645           0 :             ReadChChartLine( rStrm );
    2646           0 :         break;
    2647             :         case EXC_ID_CHDATAFORMAT:
    2648          38 :             ReadChDataFormat( rStrm );
    2649          38 :         break;
    2650             :         default:
    2651         384 :             maType.ReadChType( rStrm );
    2652             :     }
    2653         468 : }
    2654             : 
    2655          88 : void XclImpChTypeGroup::Finalize()
    2656             : {
    2657             :     // check and set valid chart type
    2658             :     bool bStockChart =
    2659          90 :         (maType.GetRecId() == EXC_ID_CHLINE) &&         // must be a line chart
    2660           4 :         !mxChart3d &&                                   // must be a 2d chart
    2661          90 :         HasHiLoLine() &&                                // must contain hi-lo lines
    2662          88 :         (maSeries.size() == static_cast<XclImpChSeriesVec::size_type>(HasDropBars() ? 4 : 3));   // correct series count
    2663          88 :     maType.Finalize( bStockChart );
    2664             : 
    2665             :     // extended type info
    2666          88 :     maTypeInfo.Set( maType.GetTypeInfo(), static_cast< bool >(mxChart3d), false );
    2667             : 
    2668             :     // reverse series order for some unstacked 2D chart types
    2669          88 :     if( maTypeInfo.mbReverseSeries && !Is3dChart() && !maType.IsStacked() && !maType.IsPercent() )
    2670           0 :         ::std::reverse( maSeries.begin(), maSeries.end() );
    2671             : 
    2672             :     // update chart type group format, may depend on chart type finalized above
    2673          88 :     if( mxGroupFmt )
    2674          38 :         mxGroupFmt->UpdateGroupFormat( maTypeInfo );
    2675          88 : }
    2676             : 
    2677          92 : void XclImpChTypeGroup::AddSeries( XclImpChSeriesRef xSeries )
    2678             : {
    2679          92 :     if( xSeries )
    2680          92 :         maSeries.push_back( xSeries );
    2681             :     // store first inserted series separately, series order may be reversed later
    2682          92 :     if( !mxFirstSeries )
    2683          88 :         mxFirstSeries = xSeries;
    2684          92 : }
    2685             : 
    2686          92 : void XclImpChTypeGroup::SetUsedFormatIndex( sal_uInt16 nFormatIdx )
    2687             : {
    2688          92 :     maUnusedFormats.erase( nFormatIdx );
    2689          92 : }
    2690             : 
    2691           0 : sal_uInt16 XclImpChTypeGroup::PopUnusedFormatIndex()
    2692             : {
    2693             :     OSL_ENSURE( !maUnusedFormats.empty(), "XclImpChTypeGroup::PopUnusedFormatIndex - no more format indexes available" );
    2694           0 :     sal_uInt16 nFormatIdx = maUnusedFormats.empty() ? 0 : *maUnusedFormats.begin();
    2695           0 :     SetUsedFormatIndex( nFormatIdx );
    2696           0 :     return nFormatIdx;
    2697             : }
    2698             : 
    2699          92 : bool XclImpChTypeGroup::HasVarPointFormat() const
    2700             : {
    2701         244 :     return ::get_flag( maData.mnFlags, EXC_CHTYPEGROUP_VARIEDCOLORS ) &&
    2702          78 :         ((maTypeInfo.meVarPointMode == EXC_CHVARPOINT_MULTI) ||         // multiple series allowed
    2703           4 :             ((maTypeInfo.meVarPointMode == EXC_CHVARPOINT_SINGLE) &&    // or exactly 1 series?
    2704          94 :                 (maSeries.size() == 1)));
    2705             : }
    2706             : 
    2707          88 : bool XclImpChTypeGroup::HasConnectorLines() const
    2708             : {
    2709             :     // existence of connector lines (only in stacked bar charts)
    2710          88 :     if ( !(maType.IsStacked() || maType.IsPercent()) || (maTypeInfo.meTypeCateg != EXC_CHTYPECATEG_BAR) )
    2711          88 :         return false;
    2712           0 :     XclImpChLineFormatMap::const_iterator xConLine = maChartLines.find( EXC_CHCHARTLINE_CONNECT );
    2713           0 :     return ( xConLine != maChartLines.end() && xConLine->second->HasLine() );
    2714             : }
    2715             : 
    2716          76 : OUString XclImpChTypeGroup::GetSingleSeriesTitle() const
    2717             : {
    2718             :     // no automatic title for series with trendlines or error bars
    2719             :     // pie charts always show an automatic title, even if more series exist
    2720         152 :     return (mxFirstSeries && !mxFirstSeries->HasChildSeries() && (maTypeInfo.mbSingleSeriesVis || (maSeries.size() == 1))) ?
    2721         152 :         mxFirstSeries->GetTitle() : OUString();
    2722             : }
    2723             : 
    2724          88 : void XclImpChTypeGroup::ConvertChart3d( ScfPropertySet& rPropSet ) const
    2725             : {
    2726          88 :     if( mxChart3d )
    2727           0 :         mxChart3d->Convert( rPropSet, Is3dWallChart() );
    2728          88 : }
    2729             : 
    2730          88 : Reference< XCoordinateSystem > XclImpChTypeGroup::CreateCoordSystem() const
    2731             : {
    2732          88 :     return maType.CreateCoordSystem( Is3dChart() );
    2733             : }
    2734             : 
    2735          88 : Reference< XChartType > XclImpChTypeGroup::CreateChartType( Reference< XDiagram > xDiagram, sal_Int32 nApiAxesSetIdx ) const
    2736             : {
    2737             :     OSL_ENSURE( IsValidGroup(), "XclImpChTypeGroup::CreateChartType - type group without series" );
    2738             : 
    2739             :     // create the chart type object
    2740          88 :     Reference< XChartType > xChartType = maType.CreateChartType( xDiagram, Is3dChart() );
    2741             : 
    2742             :     // bar chart connector lines
    2743          88 :     if( HasConnectorLines() )
    2744             :     {
    2745           0 :         ScfPropertySet aDiaProp( xDiagram );
    2746           0 :         aDiaProp.SetBoolProperty( EXC_CHPROP_CONNECTBARS, true );
    2747             :     }
    2748             : 
    2749             :     /*  Stock chart needs special processing. Create one 'big' series with
    2750             :         data sequences of different roles. */
    2751          88 :     if( maTypeInfo.meTypeId == EXC_CHTYPEID_STOCK )
    2752           0 :         CreateStockSeries( xChartType, nApiAxesSetIdx );
    2753             :     else
    2754          88 :         CreateDataSeries( xChartType, nApiAxesSetIdx );
    2755             : 
    2756          88 :     return xChartType;
    2757             : }
    2758             : 
    2759          86 : Reference< XLabeledDataSequence > XclImpChTypeGroup::CreateCategSequence() const
    2760             : {
    2761          86 :     Reference< XLabeledDataSequence > xLabeledSeq;
    2762             :     // create category sequence from first visible series
    2763          86 :     if( mxFirstSeries )
    2764          86 :         xLabeledSeq = mxFirstSeries->CreateCategSequence( EXC_CHPROP_ROLE_CATEG );
    2765          86 :     return xLabeledSeq;
    2766             : }
    2767             : 
    2768           0 : void XclImpChTypeGroup::ReadChDropBar( XclImpStream& rStrm )
    2769             : {
    2770           0 :     if (maDropBars.find(EXC_CHDROPBAR_UP) == maDropBars.end())
    2771             :     {
    2772           0 :         unique_ptr<XclImpChDropBar> p(new XclImpChDropBar(EXC_CHDROPBAR_UP));
    2773           0 :         p->ReadRecordGroup(rStrm);
    2774           0 :         o3tl::ptr_container::insert(maDropBars, EXC_CHDROPBAR_UP, std::move(p));
    2775             :     }
    2776           0 :     else if(maDropBars.find(EXC_CHDROPBAR_DOWN) == maDropBars.end())
    2777             :     {
    2778           0 :         unique_ptr<XclImpChDropBar> p(new XclImpChDropBar(EXC_CHDROPBAR_DOWN));
    2779           0 :         p->ReadRecordGroup(rStrm);
    2780           0 :         o3tl::ptr_container::insert(maDropBars, EXC_CHDROPBAR_DOWN, std::move(p));
    2781             :     }
    2782           0 : }
    2783             : 
    2784           0 : void XclImpChTypeGroup::ReadChChartLine( XclImpStream& rStrm )
    2785             : {
    2786           0 :     sal_uInt16 nLineId = rStrm.ReaduInt16();
    2787           0 :     if( (rStrm.GetNextRecId() == EXC_ID_CHLINEFORMAT) && rStrm.StartNextRecord() )
    2788             :     {
    2789           0 :         XclImpChLineFormat xLineFmt;
    2790           0 :         xLineFmt.ReadChLineFormat( rStrm );
    2791           0 :         maChartLines[ nLineId ] = xLineFmt;
    2792             :     }
    2793           0 : }
    2794             : 
    2795          38 : void XclImpChTypeGroup::ReadChDataFormat( XclImpStream& rStrm )
    2796             : {
    2797             :     // global series and data point format
    2798          38 :     XclImpChDataFormatRef xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
    2799          38 :     xDataFmt->ReadRecordGroup( rStrm );
    2800          38 :     const XclChDataPointPos& rPos = xDataFmt->GetPointPos();
    2801          76 :     if( (rPos.mnSeriesIdx == 0) && (rPos.mnPointIdx == 0) &&
    2802          38 :             (xDataFmt->GetFormatIdx() == EXC_CHDATAFORMAT_DEFAULT) )
    2803          38 :         mxGroupFmt = xDataFmt;
    2804          38 : }
    2805             : 
    2806          92 : void XclImpChTypeGroup::InsertDataSeries( Reference< XChartType > xChartType,
    2807             :         Reference< XDataSeries > xSeries, sal_Int32 nApiAxesSetIdx ) const
    2808             : {
    2809          92 :     Reference< XDataSeriesContainer > xSeriesCont( xChartType, UNO_QUERY );
    2810          92 :     if( xSeriesCont.is() && xSeries.is() )
    2811             :     {
    2812             :         // series stacking mode
    2813          92 :         cssc2::StackingDirection eStacking = cssc2::StackingDirection_NO_STACKING;
    2814             :         // stacked overrides deep-3d
    2815          92 :         if( maType.IsStacked() || maType.IsPercent() )
    2816           2 :             eStacking = cssc2::StackingDirection_Y_STACKING;
    2817          90 :         else if( Is3dDeepChart() )
    2818           0 :             eStacking = cssc2::StackingDirection_Z_STACKING;
    2819             : 
    2820             :         // additional series properties
    2821          92 :         ScfPropertySet aSeriesProp( xSeries );
    2822          92 :         aSeriesProp.SetProperty( EXC_CHPROP_STACKINGDIR, eStacking );
    2823          92 :         aSeriesProp.SetProperty( EXC_CHPROP_ATTAXISINDEX, nApiAxesSetIdx );
    2824             : 
    2825             :         // insert series into container
    2826             :         try
    2827             :         {
    2828          92 :             xSeriesCont->addDataSeries( xSeries );
    2829             :         }
    2830           0 :         catch( Exception& )
    2831             :         {
    2832             :             OSL_FAIL( "XclImpChTypeGroup::InsertDataSeries - cannot add data series" );
    2833          92 :         }
    2834          92 :     }
    2835          92 : }
    2836             : 
    2837          88 : void XclImpChTypeGroup::CreateDataSeries( Reference< XChartType > xChartType, sal_Int32 nApiAxesSetIdx ) const
    2838             : {
    2839          88 :     bool bSpline = false;
    2840         180 :     for( XclImpChSeriesVec::const_iterator aIt = maSeries.begin(), aEnd = maSeries.end(); aIt != aEnd; ++aIt )
    2841             :     {
    2842          92 :         Reference< XDataSeries > xDataSeries = (*aIt)->CreateDataSeries();
    2843          92 :         InsertDataSeries( xChartType, xDataSeries, nApiAxesSetIdx );
    2844          92 :         bSpline |= (*aIt)->HasSpline();
    2845          92 :     }
    2846             :     // spline - TODO: set at single series (#i66858#)
    2847          88 :     if( bSpline && !maTypeInfo.IsSeriesFrameFormat() && (maTypeInfo.meTypeCateg != EXC_CHTYPECATEG_RADAR) )
    2848             :     {
    2849           0 :         ScfPropertySet aTypeProp( xChartType );
    2850           0 :         aTypeProp.SetProperty( EXC_CHPROP_CURVESTYLE, ::com::sun::star::chart2::CurveStyle_CUBIC_SPLINES );
    2851             :     }
    2852          88 : }
    2853             : 
    2854           0 : void XclImpChTypeGroup::CreateStockSeries( Reference< XChartType > xChartType, sal_Int32 nApiAxesSetIdx ) const
    2855             : {
    2856             :     // create the data series object
    2857           0 :     Reference< XDataSeries > xDataSeries( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES ), UNO_QUERY );
    2858           0 :     Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
    2859           0 :     if( xDataSink.is() )
    2860             :     {
    2861             :         // create a list of data sequences from all series
    2862           0 :         ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
    2863             :         OSL_ENSURE( maSeries.size() >= 3, "XclImpChTypeGroup::CreateChartType - missing stock series" );
    2864           0 :         int nRoleIdx = (maSeries.size() == 3) ? 1 : 0;
    2865           0 :         for( XclImpChSeriesVec::const_iterator aIt = maSeries.begin(), aEnd = maSeries.end();
    2866           0 :                 (nRoleIdx < 4) && (aIt != aEnd); ++nRoleIdx, ++aIt )
    2867             :         {
    2868             :             // create a data sequence with a specific role
    2869           0 :             OUString aRole;
    2870           0 :             switch( nRoleIdx )
    2871             :             {
    2872           0 :                 case 0: aRole = EXC_CHPROP_ROLE_OPENVALUES;     break;
    2873           0 :                 case 1: aRole = EXC_CHPROP_ROLE_HIGHVALUES;     break;
    2874           0 :                 case 2: aRole = EXC_CHPROP_ROLE_LOWVALUES;      break;
    2875           0 :                 case 3: aRole = EXC_CHPROP_ROLE_CLOSEVALUES;    break;
    2876             :             }
    2877           0 :             Reference< XLabeledDataSequence > xDataSeq = (*aIt)->CreateValueSequence( aRole );
    2878           0 :             if( xDataSeq.is() )
    2879           0 :                 aLabeledSeqVec.push_back( xDataSeq );
    2880           0 :         }
    2881             : 
    2882             :         // attach labeled data sequences to series and insert series into chart type
    2883           0 :         xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
    2884             : 
    2885             :         // formatting of special stock chart elements
    2886           0 :         ScfPropertySet aTypeProp( xChartType );
    2887           0 :         aTypeProp.SetBoolProperty( EXC_CHPROP_JAPANESE, HasDropBars() );
    2888           0 :         aTypeProp.SetBoolProperty( EXC_CHPROP_SHOWFIRST, HasDropBars() );
    2889           0 :         aTypeProp.SetBoolProperty( EXC_CHPROP_SHOWHIGHLOW, true );
    2890             :         // hi-lo line format
    2891           0 :         XclImpChLineFormatMap::const_iterator xHiLoLine = maChartLines.find( EXC_CHCHARTLINE_HILO );
    2892           0 :         if ( xHiLoLine != maChartLines.end() )
    2893             :         {
    2894           0 :             ScfPropertySet aSeriesProp( xDataSeries );
    2895           0 :             xHiLoLine->second->Convert( GetChRoot(), aSeriesProp, EXC_CHOBJTYPE_HILOLINE );
    2896             :         }
    2897             :         // white dropbar format
    2898           0 :         XclImpChDropBarMap::const_iterator itr = maDropBars.find(EXC_CHDROPBAR_UP);
    2899           0 :         Reference<XPropertySet> xWhitePropSet;
    2900           0 :         if (itr != maDropBars.end() && aTypeProp.GetProperty(xWhitePropSet, EXC_CHPROP_WHITEDAY))
    2901             :         {
    2902           0 :             ScfPropertySet aBarProp( xWhitePropSet );
    2903           0 :             itr->second->Convert(GetChRoot(), aBarProp);
    2904             :         }
    2905             :         // black dropbar format
    2906           0 :         itr = maDropBars.find(EXC_CHDROPBAR_DOWN);
    2907           0 :         Reference<XPropertySet> xBlackPropSet;
    2908           0 :         if (itr != maDropBars.end() && aTypeProp.GetProperty(xBlackPropSet, EXC_CHPROP_BLACKDAY))
    2909             :         {
    2910           0 :             ScfPropertySet aBarProp( xBlackPropSet );
    2911           0 :             itr->second->Convert(GetChRoot(), aBarProp);
    2912             :         }
    2913             : 
    2914             :         // insert the series into the chart type object
    2915           0 :         InsertDataSeries( xChartType, xDataSeries, nApiAxesSetIdx );
    2916           0 :     }
    2917           0 : }
    2918             : 
    2919             : // Axes =======================================================================
    2920             : 
    2921         176 : XclImpChLabelRange::XclImpChLabelRange( const XclImpChRoot& rRoot ) :
    2922         176 :     XclImpChRoot( rRoot )
    2923             : {
    2924         176 : }
    2925             : 
    2926          10 : void XclImpChLabelRange::ReadChLabelRange( XclImpStream& rStrm )
    2927             : {
    2928          10 :     rStrm >> maLabelData.mnCross >> maLabelData.mnLabelFreq >> maLabelData.mnTickFreq >> maLabelData.mnFlags;
    2929          10 : }
    2930             : 
    2931          10 : void XclImpChLabelRange::ReadChDateRange( XclImpStream& rStrm )
    2932             : {
    2933          10 :     rStrm   >> maDateData.mnMinDate
    2934          20 :             >> maDateData.mnMaxDate
    2935          20 :             >> maDateData.mnMajorStep
    2936          20 :             >> maDateData.mnMajorUnit
    2937          20 :             >> maDateData.mnMinorStep
    2938          20 :             >> maDateData.mnMinorUnit
    2939          20 :             >> maDateData.mnBaseUnit
    2940          20 :             >> maDateData.mnCross
    2941          20 :             >> maDateData.mnFlags;
    2942          10 : }
    2943             : 
    2944          86 : void XclImpChLabelRange::Convert( ScfPropertySet& rPropSet, ScaleData& rScaleData, bool bMirrorOrient ) const
    2945             : {
    2946             :     // automatic axis type detection
    2947          86 :     rScaleData.AutoDateAxis = ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTODATE );
    2948             : 
    2949             :     // the flag EXC_CHDATERANGE_DATEAXIS specifies whether this is a date axis
    2950          86 :     if( ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_DATEAXIS ) )
    2951             :     {
    2952             :         /*  Chart2 requires axis type CATEGORY for automatic category/date axis
    2953             :             (even if it is a date axis currently). */
    2954           4 :         rScaleData.AxisType = rScaleData.AutoDateAxis ? cssc2::AxisType::CATEGORY : cssc2::AxisType::DATE;
    2955           4 :         rScaleData.Scaling = css::chart2::LinearScaling::create( comphelper::getProcessComponentContext() );
    2956             :         /*  Min/max values depend on base time unit, they specify the number of
    2957             :             days, months, or years starting from null date. */
    2958           4 :         lclConvertTimeValue( GetRoot(), rScaleData.Minimum, maDateData.mnMinDate, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMIN ), maDateData.mnBaseUnit );
    2959           4 :         lclConvertTimeValue( GetRoot(), rScaleData.Maximum, maDateData.mnMaxDate, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMAX ), maDateData.mnBaseUnit );
    2960             :         // increment
    2961           4 :         cssc::TimeIncrement& rTimeIncrement = rScaleData.TimeIncrement;
    2962           4 :         lclConvertTimeInterval( rTimeIncrement.MajorTimeInterval, maDateData.mnMajorStep, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMAJOR ), maDateData.mnMajorUnit );
    2963           4 :         lclConvertTimeInterval( rTimeIncrement.MinorTimeInterval, maDateData.mnMinorStep, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMINOR ), maDateData.mnMinorUnit );
    2964             :         // base unit
    2965           4 :         if( ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOBASE ) )
    2966           4 :             rTimeIncrement.TimeResolution.clear();
    2967             :         else
    2968           0 :             rTimeIncrement.TimeResolution <<= lclGetApiTimeUnit( maDateData.mnBaseUnit );
    2969             :     }
    2970             :     else
    2971             :     {
    2972             :         // do not overlap text unless all labels are visible
    2973          82 :         rPropSet.SetBoolProperty( EXC_CHPROP_TEXTOVERLAP, maLabelData.mnLabelFreq == 1 );
    2974             :         // do not break text into several lines unless all labels are visible
    2975          82 :         rPropSet.SetBoolProperty( EXC_CHPROP_TEXTBREAK, maLabelData.mnLabelFreq == 1 );
    2976             :         // do not stagger labels in two lines
    2977          82 :         rPropSet.SetProperty( EXC_CHPROP_ARRANGEORDER, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE );
    2978             :     }
    2979             : 
    2980             :     // reverse order
    2981          86 :     bool bReverse = ::get_flag( maLabelData.mnFlags, EXC_CHLABELRANGE_REVERSE ) != bMirrorOrient;
    2982          86 :     rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
    2983             : 
    2984             :     //! TODO #i58731# show n-th category
    2985          86 : }
    2986             : 
    2987          86 : void XclImpChLabelRange::ConvertAxisPosition( ScfPropertySet& rPropSet, bool b3dChart ) const
    2988             : {
    2989             :     /*  Crossing mode (max-cross flag overrides other crossing settings). Excel
    2990             :         does not move the Y axis in 3D charts, regardless of actual settings.
    2991             :         But: the Y axis has to be moved to "end", if the X axis is mirrored,
    2992             :         to keep it at the left end of the chart. */
    2993          86 :     bool bMaxCross = ::get_flag( maLabelData.mnFlags, b3dChart ? EXC_CHLABELRANGE_REVERSE : EXC_CHLABELRANGE_MAXCROSS );
    2994          86 :     cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE;
    2995          86 :     rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos );
    2996             : 
    2997             :     // crossing position (depending on axis type text/date)
    2998          86 :     if( ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_DATEAXIS ) )
    2999             :     {
    3000           4 :         bool bAutoCross = ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOCROSS );
    3001             :         /*  Crossing position value depends on base time unit, it specifies the
    3002             :             number of days, months, or years from null date. Note that Excel
    3003             :             2007/2010 write broken BIFF8 files, they always stores the number
    3004             :             of days cregardless of the base time unit (and they are reading it
    3005             :             the same way, thus wrongly displaying files written by Excel
    3006             :             97-2003). This filter sticks to the correct behaviour of Excel
    3007             :             97-2003. */
    3008           4 :         double fCrossingPos = bAutoCross ? 1.0 : lclGetSerialDay( GetRoot(), maDateData.mnCross, maDateData.mnBaseUnit );
    3009           4 :         rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
    3010             :     }
    3011             :     else
    3012             :     {
    3013          82 :         double fCrossingPos = b3dChart ? 1.0 : maLabelData.mnCross;
    3014          82 :         rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
    3015             :     }
    3016          86 : }
    3017             : 
    3018         176 : XclImpChValueRange::XclImpChValueRange( const XclImpChRoot& rRoot ) :
    3019         176 :     XclImpChRoot( rRoot )
    3020             : {
    3021         176 : }
    3022             : 
    3023          14 : void XclImpChValueRange::ReadChValueRange( XclImpStream& rStrm )
    3024             : {
    3025          14 :     rStrm   >> maData.mfMin
    3026          28 :             >> maData.mfMax
    3027          28 :             >> maData.mfMajorStep
    3028          28 :             >> maData.mfMinorStep
    3029          28 :             >> maData.mfCross
    3030          28 :             >> maData.mnFlags;
    3031          14 : }
    3032             : 
    3033          90 : void XclImpChValueRange::Convert( ScaleData& rScaleData, bool bMirrorOrient ) const
    3034             : {
    3035             :     // scaling algorithm
    3036          90 :     bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE );
    3037          90 :     if( bLogScale )
    3038           0 :         rScaleData.Scaling = css::chart2::LogarithmicScaling::create( comphelper::getProcessComponentContext() );
    3039             :     else
    3040          90 :         rScaleData.Scaling = css::chart2::LinearScaling::create( comphelper::getProcessComponentContext() );
    3041             : 
    3042             :     // min/max
    3043          90 :     lclSetExpValueOrClearAny( rScaleData.Minimum, maData.mfMin, bLogScale, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMIN ) );
    3044          90 :     lclSetExpValueOrClearAny( rScaleData.Maximum, maData.mfMax, bLogScale, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAX ) );
    3045             : 
    3046             :     // increment
    3047          90 :     bool bAutoMajor = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAJOR );
    3048          90 :     bool bAutoMinor = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMINOR );
    3049             :     // major increment
    3050          90 :     IncrementData& rIncrementData = rScaleData.IncrementData;
    3051          90 :     lclSetValueOrClearAny( rIncrementData.Distance, maData.mfMajorStep, bAutoMajor );
    3052             :     // minor increment
    3053          90 :     Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements;
    3054          90 :     rSubIncrementSeq.realloc( 1 );
    3055          90 :     Any& rIntervalCount = rSubIncrementSeq[ 0 ].IntervalCount;
    3056          90 :     rIntervalCount.clear();
    3057          90 :     if( bLogScale )
    3058             :     {
    3059           0 :         if( !bAutoMinor )
    3060           0 :             rIntervalCount <<= sal_Int32( 9 );
    3061             :     }
    3062             :     else
    3063             :     {
    3064          90 :         if( !bAutoMajor && !bAutoMinor && (0.0 < maData.mfMinorStep) && (maData.mfMinorStep <= maData.mfMajorStep) )
    3065             :         {
    3066           0 :             double fCount = maData.mfMajorStep / maData.mfMinorStep + 0.5;
    3067           0 :             if( (1.0 <= fCount) && (fCount < 1001.0) )
    3068           0 :                 rIntervalCount <<= static_cast< sal_Int32 >( fCount );
    3069             :         }
    3070             :     }
    3071             : 
    3072             :     // reverse order
    3073          90 :     bool bReverse = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE ) != bMirrorOrient;
    3074          90 :     rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
    3075          90 : }
    3076             : 
    3077          90 : void XclImpChValueRange::ConvertAxisPosition( ScfPropertySet& rPropSet ) const
    3078             : {
    3079          90 :     bool bMaxCross = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_MAXCROSS );
    3080          90 :     bool bAutoCross = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOCROSS );
    3081          90 :     bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE );
    3082             : 
    3083             :     // crossing mode (max-cross flag overrides other crossing settings)
    3084          90 :     cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE;
    3085          90 :     rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos );
    3086             : 
    3087             :     // crossing position
    3088          90 :     double fCrossingPos = bAutoCross ? 0.0 : maData.mfCross;
    3089          90 :     if( bLogScale ) fCrossingPos = pow( 10.0, fCrossingPos );
    3090          90 :     rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
    3091          90 : }
    3092             : 
    3093             : namespace {
    3094             : 
    3095         352 : sal_Int32 lclGetApiTickmarks( sal_uInt8 nXclTickPos )
    3096             : {
    3097             :     using namespace ::com::sun::star::chart2::TickmarkStyle;
    3098         352 :     sal_Int32 nApiTickmarks = css::chart2::TickmarkStyle::NONE;
    3099         352 :     ::set_flag( nApiTickmarks, INNER, ::get_flag( nXclTickPos, EXC_CHTICK_INSIDE ) );
    3100         352 :     ::set_flag( nApiTickmarks, OUTER, ::get_flag( nXclTickPos, EXC_CHTICK_OUTSIDE ) );
    3101         352 :     return nApiTickmarks;
    3102             : }
    3103             : 
    3104         176 : cssc::ChartAxisLabelPosition lclGetApiLabelPosition( sal_Int8 nXclLabelPos )
    3105             : {
    3106             :     using namespace ::com::sun::star::chart;
    3107         176 :     switch( nXclLabelPos )
    3108             :     {
    3109           0 :         case EXC_CHTICK_LOW:    return ChartAxisLabelPosition_OUTSIDE_START;
    3110           0 :         case EXC_CHTICK_HIGH:   return ChartAxisLabelPosition_OUTSIDE_END;
    3111         176 :         case EXC_CHTICK_NEXT:   return ChartAxisLabelPosition_NEAR_AXIS;
    3112             :     }
    3113           0 :     return ChartAxisLabelPosition_NEAR_AXIS;
    3114             : }
    3115             : 
    3116             : } // namespace
    3117             : 
    3118         176 : XclImpChTick::XclImpChTick( const XclImpChRoot& rRoot ) :
    3119         176 :     XclImpChRoot( rRoot )
    3120             : {
    3121         176 : }
    3122             : 
    3123          24 : void XclImpChTick::ReadChTick( XclImpStream& rStrm )
    3124             : {
    3125          24 :     rStrm   >> maData.mnMajor
    3126          48 :             >> maData.mnMinor
    3127          48 :             >> maData.mnLabelPos
    3128          48 :             >> maData.mnBackMode;
    3129          24 :     rStrm.Ignore( 16 );
    3130          24 :     rStrm   >> maData.maTextColor
    3131          48 :             >> maData.mnFlags;
    3132             : 
    3133          24 :     if( GetBiff() == EXC_BIFF8 )
    3134             :     {
    3135             :         // BIFF8: index into palette used instead of RGB data
    3136          24 :         maData.maTextColor = GetPalette().GetColor( rStrm.ReaduInt16() );
    3137             :         // rotation
    3138          24 :         rStrm >> maData.mnRotation;
    3139             :     }
    3140             :     else
    3141             :     {
    3142             :         // BIFF2-BIFF7: get rotation from text orientation
    3143           0 :         sal_uInt8 nOrient = ::extract_value< sal_uInt8 >( maData.mnFlags, 2, 3 );
    3144           0 :         maData.mnRotation = XclTools::GetXclRotFromOrient( nOrient );
    3145             :     }
    3146          24 : }
    3147             : 
    3148          16 : Color XclImpChTick::GetFontColor() const
    3149             : {
    3150          16 :     return ::get_flag( maData.mnFlags, EXC_CHTICK_AUTOCOLOR ) ? GetFontAutoColor() : maData.maTextColor;
    3151             : }
    3152             : 
    3153         176 : sal_uInt16 XclImpChTick::GetRotation() const
    3154             : {
    3155             :     /* n#720443: Ignore auto-rotation if there is a suggested rotation.
    3156             :      * Better fix would be to improve our axis auto rotation algorithm.
    3157             :      */
    3158         176 :     if( maData.mnRotation != EXC_ROT_NONE )
    3159           4 :         return maData.mnRotation;
    3160         172 :     return ::get_flag( maData.mnFlags, EXC_CHTICK_AUTOROT ) ? EXC_CHART_AUTOROTATION : maData.mnRotation;
    3161             : }
    3162             : 
    3163         176 : void XclImpChTick::Convert( ScfPropertySet& rPropSet ) const
    3164             : {
    3165         176 :     rPropSet.SetProperty( EXC_CHPROP_MAJORTICKS, lclGetApiTickmarks( maData.mnMajor ) );
    3166         176 :     rPropSet.SetProperty( EXC_CHPROP_MINORTICKS, lclGetApiTickmarks( maData.mnMinor ) );
    3167         176 :     rPropSet.SetProperty( EXC_CHPROP_LABELPOSITION, lclGetApiLabelPosition( maData.mnLabelPos ) );
    3168         176 :     rPropSet.SetProperty( EXC_CHPROP_MARKPOSITION, cssc::ChartAxisMarkPosition_AT_AXIS );
    3169         176 : }
    3170             : 
    3171         176 : XclImpChAxis::XclImpChAxis( const XclImpChRoot& rRoot, sal_uInt16 nAxisType ) :
    3172             :     XclImpChRoot( rRoot ),
    3173         176 :     mnNumFmtIdx( EXC_FORMAT_NOTFOUND )
    3174             : {
    3175         176 :     maData.mnType = nAxisType;
    3176         176 : }
    3177             : 
    3178          24 : void XclImpChAxis::ReadHeaderRecord( XclImpStream& rStrm )
    3179             : {
    3180          24 :     rStrm >> maData.mnType;
    3181          24 : }
    3182             : 
    3183         150 : void XclImpChAxis::ReadSubRecord( XclImpStream& rStrm )
    3184             : {
    3185         150 :     switch( rStrm.GetRecId() )
    3186             :     {
    3187             :         case EXC_ID_CHLABELRANGE:
    3188          10 :             mxLabelRange.reset( new XclImpChLabelRange( GetChRoot() ) );
    3189          10 :             mxLabelRange->ReadChLabelRange( rStrm );
    3190          10 :         break;
    3191             :         case EXC_ID_CHDATERANGE:
    3192          10 :             if( !mxLabelRange )
    3193           0 :                 mxLabelRange.reset( new XclImpChLabelRange( GetChRoot() ) );
    3194          10 :             mxLabelRange->ReadChDateRange( rStrm );
    3195          10 :         break;
    3196             :         case EXC_ID_CHVALUERANGE:
    3197          14 :             mxValueRange.reset( new XclImpChValueRange( GetChRoot() ) );
    3198          14 :             mxValueRange->ReadChValueRange( rStrm );
    3199          14 :         break;
    3200             :         case EXC_ID_CHFORMAT:
    3201           4 :             rStrm >> mnNumFmtIdx;
    3202           4 :         break;
    3203             :         case EXC_ID_CHTICK:
    3204          24 :             mxTick.reset( new XclImpChTick( GetChRoot() ) );
    3205          24 :             mxTick->ReadChTick( rStrm );
    3206          24 :         break;
    3207             :         case EXC_ID_CHFONT:
    3208          16 :             mxFont.reset( new XclImpChFont );
    3209          16 :             mxFont->ReadChFont( rStrm );
    3210          16 :         break;
    3211             :         case EXC_ID_CHAXISLINE:
    3212          24 :             ReadChAxisLine( rStrm );
    3213          24 :         break;
    3214             :     }
    3215         150 : }
    3216             : 
    3217         176 : void XclImpChAxis::Finalize()
    3218             : {
    3219             :     // add default scaling, needed e.g. to adjust rotation direction of pie and radar charts
    3220         176 :     if( !mxLabelRange )
    3221         166 :         mxLabelRange.reset( new XclImpChLabelRange( GetChRoot() ) );
    3222         176 :     if( !mxValueRange )
    3223         162 :         mxValueRange.reset( new XclImpChValueRange( GetChRoot() ) );
    3224             :     // remove invisible grid lines completely
    3225         176 :     if( mxMajorGrid && !mxMajorGrid->HasLine() )
    3226           0 :         mxMajorGrid.reset();
    3227         176 :     if( mxMinorGrid && !mxMinorGrid->HasLine() )
    3228           0 :         mxMinorGrid.reset();
    3229             :     // default tick settings different in OOChart and Excel
    3230         176 :     if( !mxTick )
    3231         152 :         mxTick.reset( new XclImpChTick( GetChRoot() ) );
    3232             :     // #i4140# different default axis line color
    3233         176 :     if( !mxAxisLine )
    3234             :     {
    3235         164 :         XclChLineFormat aLineFmt;
    3236             :         // set "show axis" flag, default if line format record is missing
    3237         164 :         ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_SHOWAXIS );
    3238         164 :         mxAxisLine.reset( new XclImpChLineFormat( aLineFmt ) );
    3239             :     }
    3240             :     // add wall/floor frame for 3d charts
    3241         176 :     if( !mxWallFrame )
    3242         176 :         CreateWallFrame();
    3243         176 : }
    3244             : 
    3245          16 : sal_uInt16 XclImpChAxis::GetFontIndex() const
    3246             : {
    3247          16 :     return mxFont ? mxFont->GetFontIndex() : EXC_FONT_NOTFOUND;
    3248             : }
    3249             : 
    3250          16 : Color XclImpChAxis::GetFontColor() const
    3251             : {
    3252          16 :     return mxTick ? mxTick->GetFontColor() : GetFontAutoColor();
    3253             : }
    3254             : 
    3255         176 : sal_uInt16 XclImpChAxis::GetRotation() const
    3256             : {
    3257         176 :     return mxTick ? mxTick->GetRotation() : EXC_CHART_AUTOROTATION;
    3258             : }
    3259             : 
    3260         176 : Reference< XAxis > XclImpChAxis::CreateAxis( const XclImpChTypeGroup& rTypeGroup, const XclImpChAxis* pCrossingAxis ) const
    3261             : {
    3262             :     // create the axis object (always)
    3263         176 :     Reference< XAxis > xAxis( ScfApiHelper::CreateInstance( SERVICE_CHART2_AXIS ), UNO_QUERY );
    3264         176 :     if( xAxis.is() )
    3265             :     {
    3266         176 :         ScfPropertySet aAxisProp( xAxis );
    3267             :         // #i58688# axis enabled
    3268         176 :         aAxisProp.SetBoolProperty( EXC_CHPROP_SHOW, IsActivated() );
    3269             : 
    3270             :         // axis line properties
    3271         176 :         if( mxAxisLine )
    3272         176 :             mxAxisLine->Convert( GetChRoot(), aAxisProp, EXC_CHOBJTYPE_AXISLINE );
    3273             :         // axis ticks properties
    3274         176 :         if( mxTick )
    3275         176 :             mxTick->Convert( aAxisProp );
    3276             : 
    3277             :         // axis caption text --------------------------------------------------
    3278             : 
    3279             :         // radar charts disable their category labels via chart type, not via axis
    3280         528 :         bool bHasLabels = HasLabels() &&
    3281         440 :             ((GetAxisType() != EXC_CHAXIS_X) || rTypeGroup.HasCategoryLabels());
    3282         176 :         aAxisProp.SetBoolProperty( EXC_CHPROP_DISPLAYLABELS, bHasLabels );
    3283         176 :         if( bHasLabels )
    3284             :         {
    3285             :             // font settings from CHFONT record or from default text
    3286         176 :             if( mxFont )
    3287          16 :                 ConvertFontBase( GetChRoot(), aAxisProp );
    3288         160 :             else if( const XclImpChText* pDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISLABEL ) )
    3289         160 :                 pDefText->ConvertFont( aAxisProp );
    3290             :             // label text rotation
    3291         176 :             ConvertRotationBase( GetChRoot(), aAxisProp, true );
    3292             :             // number format
    3293         176 :             sal_uInt32 nScNumFmt = GetNumFmtBuffer().GetScFormat( mnNumFmtIdx );
    3294         176 :             if( nScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND )
    3295           4 :                 aAxisProp.SetProperty( EXC_CHPROP_NUMBERFORMAT, static_cast< sal_Int32 >( nScNumFmt ) );
    3296             :         }
    3297             : 
    3298             :         // axis scaling and increment -----------------------------------------
    3299             : 
    3300         176 :         const XclChExtTypeInfo& rTypeInfo = rTypeGroup.GetTypeInfo();
    3301         352 :         ScaleData aScaleData = xAxis->getScaleData();
    3302             :         // set axis type
    3303         176 :         switch( GetAxisType() )
    3304             :         {
    3305             :             case EXC_CHAXIS_X:
    3306          88 :                 if( rTypeInfo.mbCategoryAxis )
    3307             :                 {
    3308          86 :                     aScaleData.AxisType = cssc2::AxisType::CATEGORY;
    3309          86 :                     aScaleData.Categories = rTypeGroup.CreateCategSequence();
    3310             :                 }
    3311             :                 else
    3312           2 :                     aScaleData.AxisType = cssc2::AxisType::REALNUMBER;
    3313          88 :             break;
    3314             :             case EXC_CHAXIS_Y:
    3315          88 :                 aScaleData.AxisType = rTypeGroup.IsPercent() ?
    3316          88 :                     cssc2::AxisType::PERCENT : cssc2::AxisType::REALNUMBER;
    3317          88 :             break;
    3318             :             case EXC_CHAXIS_Z:
    3319           0 :                 aScaleData.AxisType = cssc2::AxisType::SERIES;
    3320           0 :             break;
    3321             :         }
    3322             :         // axis scaling settings, dependent on axis type
    3323         176 :         switch( aScaleData.AxisType )
    3324             :         {
    3325             :             case cssc2::AxisType::CATEGORY:
    3326             :             case cssc2::AxisType::SERIES:
    3327             :                 OSL_ENSURE( mxLabelRange, "Missing Label Range" );
    3328             :                 // #i71684# radar charts have reversed rotation direction
    3329          86 :                 if (mxLabelRange)
    3330          86 :                     mxLabelRange->Convert( aAxisProp, aScaleData, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_RADAR );
    3331          86 :             break;
    3332             :             case cssc2::AxisType::REALNUMBER:
    3333             :             case cssc2::AxisType::PERCENT:
    3334             :                 // #i85167# pie/donut charts have reversed rotation direction (at Y axis!)
    3335          90 :                 mxValueRange->Convert( aScaleData, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE );
    3336          90 :             break;
    3337             :             default:
    3338             :                 OSL_FAIL( "XclImpChAxis::CreateAxis - unknown axis type" );
    3339             :         }
    3340             : 
    3341             :         /*  Do not set a value to the Origin member anymore (will be done via
    3342             :             new axis properties 'CrossoverPosition' and 'CrossoverValue'). */
    3343         176 :         aScaleData.Origin.clear();
    3344             : 
    3345             :         // write back
    3346         176 :         xAxis->setScaleData( aScaleData );
    3347             : 
    3348             :         // grid ---------------------------------------------------------------
    3349             : 
    3350             :         // main grid
    3351         176 :         ScfPropertySet aGridProp( xAxis->getGridProperties() );
    3352         176 :         aGridProp.SetBoolProperty( EXC_CHPROP_SHOW, HasMajorGrid() );
    3353         176 :         if( mxMajorGrid )
    3354          12 :             mxMajorGrid->Convert( GetChRoot(), aGridProp, EXC_CHOBJTYPE_GRIDLINE );
    3355             :         // sub grid
    3356         352 :         Sequence< Reference< XPropertySet > > aSubGridPropSeq = xAxis->getSubGridProperties();
    3357         176 :         if( aSubGridPropSeq.hasElements() )
    3358             :         {
    3359         176 :             ScfPropertySet aSubGridProp( aSubGridPropSeq[ 0 ] );
    3360         176 :             aSubGridProp.SetBoolProperty( EXC_CHPROP_SHOW, HasMinorGrid() );
    3361         176 :             if( mxMinorGrid )
    3362           0 :                 mxMinorGrid->Convert( GetChRoot(), aSubGridProp, EXC_CHOBJTYPE_GRIDLINE );
    3363             :         }
    3364             : 
    3365             :         // position of crossing axis ------------------------------------------
    3366             : 
    3367         176 :         if( pCrossingAxis )
    3368         528 :             pCrossingAxis->ConvertAxisPosition( aAxisProp, rTypeGroup );
    3369             :     }
    3370         176 :     return xAxis;
    3371             : }
    3372             : 
    3373           0 : void XclImpChAxis::ConvertWall( ScfPropertySet& rPropSet ) const
    3374             : {
    3375             :     // #i71810# walls and floor in 3D charts use the CHPICFORMAT record for bitmap mode
    3376           0 :     if( mxWallFrame )
    3377           0 :         mxWallFrame->Convert( rPropSet, true );
    3378           0 : }
    3379             : 
    3380         176 : void XclImpChAxis::ConvertAxisPosition( ScfPropertySet& rPropSet, const XclImpChTypeGroup& rTypeGroup ) const
    3381             : {
    3382         176 :     if( ((GetAxisType() == EXC_CHAXIS_X) && rTypeGroup.GetTypeInfo().mbCategoryAxis) || (GetAxisType() == EXC_CHAXIS_Z) )
    3383             :     {
    3384             :         OSL_ENSURE( mxLabelRange, "Missing Label Range" );
    3385          86 :         if (mxLabelRange)
    3386          86 :             mxLabelRange->ConvertAxisPosition( rPropSet, rTypeGroup.Is3dChart() );
    3387             :     }
    3388             :     else
    3389          90 :         mxValueRange->ConvertAxisPosition( rPropSet );
    3390         176 : }
    3391             : 
    3392          24 : void XclImpChAxis::ReadChAxisLine( XclImpStream& rStrm )
    3393             : {
    3394          24 :     XclImpChLineFormatRef* pxLineFmt = 0;
    3395          24 :     bool bWallFrame = false;
    3396          24 :     switch( rStrm.ReaduInt16() )
    3397             :     {
    3398          12 :         case EXC_CHAXISLINE_AXISLINE:   pxLineFmt = &mxAxisLine;    break;
    3399          12 :         case EXC_CHAXISLINE_MAJORGRID:  pxLineFmt = &mxMajorGrid;   break;
    3400           0 :         case EXC_CHAXISLINE_MINORGRID:  pxLineFmt = &mxMinorGrid;   break;
    3401           0 :         case EXC_CHAXISLINE_WALLS:      bWallFrame = true;          break;
    3402             :     }
    3403          24 :     if( bWallFrame )
    3404           0 :         CreateWallFrame();
    3405             : 
    3406          24 :     bool bLoop = pxLineFmt || bWallFrame;
    3407          96 :     while( bLoop )
    3408             :     {
    3409          48 :         sal_uInt16 nRecId = rStrm.GetNextRecId();
    3410          24 :         bLoop = ((nRecId == EXC_ID_CHLINEFORMAT) ||
    3411          24 :                  (nRecId == EXC_ID_CHAREAFORMAT) ||
    3412             :                  (nRecId == EXC_ID_CHESCHERFORMAT))
    3413          72 :                  && rStrm.StartNextRecord();
    3414          48 :         if( bLoop )
    3415             :         {
    3416          24 :             if( pxLineFmt && (nRecId == EXC_ID_CHLINEFORMAT) )
    3417             :             {
    3418          24 :                 pxLineFmt->reset( new XclImpChLineFormat );
    3419          24 :                 (*pxLineFmt)->ReadChLineFormat( rStrm );
    3420             :             }
    3421           0 :             else if( bWallFrame && mxWallFrame )
    3422             :             {
    3423           0 :                 mxWallFrame->ReadSubRecord( rStrm );
    3424             :             }
    3425             :         }
    3426             :     }
    3427          24 : }
    3428             : 
    3429         176 : void XclImpChAxis::CreateWallFrame()
    3430             : {
    3431         176 :     switch( GetAxisType() )
    3432             :     {
    3433             :         case EXC_CHAXIS_X:
    3434          88 :             mxWallFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_WALL3D ) );
    3435          88 :         break;
    3436             :         case EXC_CHAXIS_Y:
    3437          88 :             mxWallFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_FLOOR3D ) );
    3438          88 :         break;
    3439             :         default:
    3440           0 :             mxWallFrame.reset();
    3441             :     }
    3442         176 : }
    3443             : 
    3444         264 : XclImpChAxesSet::XclImpChAxesSet( const XclImpChRoot& rRoot, sal_uInt16 nAxesSetId ) :
    3445         264 :     XclImpChRoot( rRoot )
    3446             : {
    3447         264 :     maData.mnAxesSetId = nAxesSetId;
    3448         264 : }
    3449             : 
    3450          88 : void XclImpChAxesSet::ReadHeaderRecord( XclImpStream& rStrm )
    3451             : {
    3452          88 :     rStrm >> maData.mnAxesSetId >> maData.maRect;
    3453          88 : }
    3454             : 
    3455         426 : void XclImpChAxesSet::ReadSubRecord( XclImpStream& rStrm )
    3456             : {
    3457         426 :     switch( rStrm.GetRecId() )
    3458             :     {
    3459             :         case EXC_ID_CHFRAMEPOS:
    3460          88 :             mxFramePos.reset( new XclImpChFramePos );
    3461          88 :             mxFramePos->ReadChFramePos( rStrm );
    3462          88 :         break;
    3463             :         case EXC_ID_CHAXIS:
    3464          24 :             ReadChAxis( rStrm );
    3465          24 :         break;
    3466             :         case EXC_ID_CHTEXT:
    3467           0 :             ReadChText( rStrm );
    3468           0 :         break;
    3469             :         case EXC_ID_CHPLOTFRAME:
    3470          12 :             ReadChPlotFrame( rStrm );
    3471          12 :         break;
    3472             :         case EXC_ID_CHTYPEGROUP:
    3473          88 :             ReadChTypeGroup( rStrm );
    3474          88 :         break;
    3475             :     }
    3476         426 : }
    3477             : 
    3478         176 : void XclImpChAxesSet::Finalize()
    3479             : {
    3480         176 :     if( IsValidAxesSet() )
    3481             :     {
    3482             :         // finalize chart type groups, erase empty groups without series
    3483          88 :         XclImpChTypeGroupMap aValidGroups;
    3484         176 :         for( XclImpChTypeGroupMap::const_iterator aIt = maTypeGroups.begin(), aEnd = maTypeGroups.end(); aIt != aEnd; ++aIt )
    3485             :         {
    3486          88 :             XclImpChTypeGroupRef xTypeGroup = aIt->second;
    3487          88 :             xTypeGroup->Finalize();
    3488          88 :             if( xTypeGroup->IsValidGroup() )
    3489             :                 aValidGroups.insert(
    3490          88 :                     XclImpChTypeGroupMap::value_type(aIt->first, xTypeGroup));
    3491          88 :         }
    3492          88 :         maTypeGroups.swap( aValidGroups );
    3493             :     }
    3494             : 
    3495             :     // invalid chart type groups are deleted now, check again with IsValidAxesSet()
    3496         176 :     if( IsValidAxesSet() )
    3497             :     {
    3498             :         // always create missing axis objects
    3499          88 :         if( !mxXAxis )
    3500          76 :             mxXAxis.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_X ) );
    3501          88 :         if( !mxYAxis )
    3502          76 :             mxYAxis.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_Y ) );
    3503          88 :         if( !mxZAxis && GetFirstTypeGroup()->Is3dDeepChart() )
    3504           0 :             mxZAxis.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_Z ) );
    3505             : 
    3506             :         // finalize axes
    3507          88 :         if( mxXAxis ) mxXAxis->Finalize();
    3508          88 :         if( mxYAxis ) mxYAxis->Finalize();
    3509          88 :         if( mxZAxis ) mxZAxis->Finalize();
    3510             : 
    3511             :         // finalize axis titles
    3512          88 :         const XclImpChText* pDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISTITLE );
    3513          88 :         OUString aAutoTitle("Axis Title");
    3514          88 :         lclFinalizeTitle( mxXAxisTitle, pDefText, aAutoTitle );
    3515          88 :         lclFinalizeTitle( mxYAxisTitle, pDefText, aAutoTitle );
    3516          88 :         lclFinalizeTitle( mxZAxisTitle, pDefText, aAutoTitle );
    3517             : 
    3518             :         // #i47745# missing plot frame -> invisible border and area
    3519          88 :         if( !mxPlotFrame )
    3520          76 :             mxPlotFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME ) );
    3521             :     }
    3522         176 : }
    3523             : 
    3524         368 : XclImpChTypeGroupRef XclImpChAxesSet::GetTypeGroup( sal_uInt16 nGroupIdx ) const
    3525             : {
    3526         368 :     XclImpChTypeGroupMap::const_iterator itr = maTypeGroups.find(nGroupIdx);
    3527         368 :     return itr == maTypeGroups.end() ? XclImpChTypeGroupRef() : itr->second;
    3528             : }
    3529             : 
    3530         518 : XclImpChTypeGroupRef XclImpChAxesSet::GetFirstTypeGroup() const
    3531             : {
    3532         518 :     XclImpChTypeGroupRef xTypeGroup;
    3533         518 :     if( !maTypeGroups.empty() )
    3534         518 :         xTypeGroup = maTypeGroups.begin()->second;
    3535         518 :     return xTypeGroup;
    3536             : }
    3537             : 
    3538         130 : XclImpChLegendRef XclImpChAxesSet::GetLegend() const
    3539             : {
    3540         130 :     XclImpChLegendRef xLegend;
    3541         218 :     for( XclImpChTypeGroupMap::const_iterator aIt = maTypeGroups.begin(), aEnd = maTypeGroups.end(); !xLegend && (aIt != aEnd); ++aIt )
    3542          88 :         xLegend = aIt->second->GetLegend();
    3543         130 :     return xLegend;
    3544             : }
    3545             : 
    3546          76 : OUString XclImpChAxesSet::GetSingleSeriesTitle() const
    3547             : {
    3548          76 :     return (maTypeGroups.size() == 1) ? maTypeGroups.begin()->second->GetSingleSeriesTitle() : OUString();
    3549             : }
    3550             : 
    3551         176 : void XclImpChAxesSet::Convert( Reference< XDiagram > xDiagram ) const
    3552             : {
    3553         176 :     if( IsValidAxesSet() && xDiagram.is() )
    3554             :     {
    3555             :         // diagram background formatting
    3556          88 :         if( GetAxesSetId() == EXC_CHAXESSET_PRIMARY )
    3557          88 :             ConvertBackground( xDiagram );
    3558             : 
    3559             :         // create the coordinate system, this inserts all chart types and series
    3560          88 :         Reference< XCoordinateSystem > xCoordSystem = CreateCoordSystem( xDiagram );
    3561          88 :         if( xCoordSystem.is() )
    3562             :         {
    3563             :             // insert coordinate system, if not already done
    3564             :             try
    3565             :             {
    3566          88 :                 Reference< XCoordinateSystemContainer > xCoordSystemCont( xDiagram, UNO_QUERY_THROW );
    3567         176 :                 Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems();
    3568          88 :                 if( aCoordSystems.getLength() == 0 )
    3569         176 :                     xCoordSystemCont->addCoordinateSystem( xCoordSystem );
    3570             :             }
    3571           0 :             catch( Exception& )
    3572             :             {
    3573             :                 OSL_FAIL( "XclImpChAxesSet::Convert - cannot insert coordinate system" );
    3574             :             }
    3575             : 
    3576             :             // create the axes with grids and axis titles and insert them into the diagram
    3577          88 :             ConvertAxis( mxXAxis, mxXAxisTitle, xCoordSystem, mxYAxis.get() );
    3578          88 :             ConvertAxis( mxYAxis, mxYAxisTitle, xCoordSystem, mxXAxis.get() );
    3579          88 :             ConvertAxis( mxZAxis, mxZAxisTitle, xCoordSystem, 0 );
    3580          88 :         }
    3581             :     }
    3582         176 : }
    3583             : 
    3584         176 : void XclImpChAxesSet::ConvertTitlePositions() const
    3585             : {
    3586         176 :     if( mxXAxisTitle )
    3587           0 :         mxXAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_X ) );
    3588         176 :     if( mxYAxisTitle )
    3589           0 :         mxYAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_Y ) );
    3590         176 :     if( mxZAxisTitle )
    3591           0 :         mxZAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_Z ) );
    3592         176 : }
    3593             : 
    3594          24 : void XclImpChAxesSet::ReadChAxis( XclImpStream& rStrm )
    3595             : {
    3596          24 :     XclImpChAxisRef xAxis( new XclImpChAxis( GetChRoot() ) );
    3597          24 :     xAxis->ReadRecordGroup( rStrm );
    3598             : 
    3599          24 :     switch( xAxis->GetAxisType() )
    3600             :     {
    3601          12 :         case EXC_CHAXIS_X:  mxXAxis = xAxis;    break;
    3602          12 :         case EXC_CHAXIS_Y:  mxYAxis = xAxis;    break;
    3603           0 :         case EXC_CHAXIS_Z:  mxZAxis = xAxis;    break;
    3604          24 :     }
    3605          24 : }
    3606             : 
    3607           0 : void XclImpChAxesSet::ReadChText( XclImpStream& rStrm )
    3608             : {
    3609           0 :     XclImpChTextRef xText( new XclImpChText( GetChRoot() ) );
    3610           0 :     xText->ReadRecordGroup( rStrm );
    3611             : 
    3612           0 :     switch( xText->GetLinkTarget() )
    3613             :     {
    3614           0 :         case EXC_CHOBJLINK_XAXIS:   mxXAxisTitle = xText;   break;
    3615           0 :         case EXC_CHOBJLINK_YAXIS:   mxYAxisTitle = xText;   break;
    3616           0 :         case EXC_CHOBJLINK_ZAXIS:   mxZAxisTitle = xText;   break;
    3617           0 :     }
    3618           0 : }
    3619             : 
    3620          12 : void XclImpChAxesSet::ReadChPlotFrame( XclImpStream& rStrm )
    3621             : {
    3622          12 :     if( (rStrm.GetNextRecId() == EXC_ID_CHFRAME) && rStrm.StartNextRecord() )
    3623             :     {
    3624          12 :         mxPlotFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME ) );
    3625          12 :         mxPlotFrame->ReadRecordGroup( rStrm );
    3626             :     }
    3627          12 : }
    3628             : 
    3629          88 : void XclImpChAxesSet::ReadChTypeGroup( XclImpStream& rStrm )
    3630             : {
    3631          88 :     XclImpChTypeGroupRef xTypeGroup( new XclImpChTypeGroup( GetChRoot() ) );
    3632          88 :     xTypeGroup->ReadRecordGroup( rStrm );
    3633          88 :     sal_uInt16 nGroupIdx = xTypeGroup->GetGroupIdx();
    3634          88 :     XclImpChTypeGroupMap::iterator itr = maTypeGroups.lower_bound(nGroupIdx);
    3635          88 :     if (itr != maTypeGroups.end() && !maTypeGroups.key_comp()(nGroupIdx, itr->first))
    3636             :         // Overwrite the existing element.
    3637           0 :         itr->second = xTypeGroup;
    3638             :     else
    3639             :         maTypeGroups.insert(
    3640          88 :             itr, XclImpChTypeGroupMap::value_type(nGroupIdx, xTypeGroup));
    3641          88 : }
    3642             : 
    3643          88 : Reference< XCoordinateSystem > XclImpChAxesSet::CreateCoordSystem( Reference< XDiagram > xDiagram ) const
    3644             : {
    3645          88 :     Reference< XCoordinateSystem > xCoordSystem;
    3646             : 
    3647             :     /*  Try to get existing coordinate system. For now, all series from primary
    3648             :         and secondary axes sets are inserted into one coordinate system. Later,
    3649             :         this should be changed to use one coordinate system for each axes set. */
    3650         176 :     Reference< XCoordinateSystemContainer > xCoordSystemCont( xDiagram, UNO_QUERY );
    3651          88 :     if( xCoordSystemCont.is() )
    3652             :     {
    3653          88 :         Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems();
    3654             :         OSL_ENSURE( aCoordSystems.getLength() <= 1, "XclImpChAxesSet::CreateCoordSystem - too many existing coordinate systems" );
    3655          88 :         if( aCoordSystems.getLength() > 0 )
    3656           0 :             xCoordSystem = aCoordSystems[ 0 ];
    3657             :     }
    3658             : 
    3659             :     // create the coordinate system according to the first chart type
    3660          88 :     if( !xCoordSystem.is() )
    3661             :     {
    3662          88 :         XclImpChTypeGroupRef xTypeGroup = GetFirstTypeGroup();
    3663          88 :         if( xTypeGroup )
    3664             :         {
    3665          88 :             xCoordSystem = xTypeGroup->CreateCoordSystem();
    3666             :             // convert 3d chart settings
    3667          88 :             ScfPropertySet aDiaProp( xDiagram );
    3668          88 :             xTypeGroup->ConvertChart3d( aDiaProp );
    3669          88 :         }
    3670             :     }
    3671             : 
    3672             :     /*  Create XChartType objects for all chart type groups. Each group will
    3673             :         add its series to the data provider attached to the chart document. */
    3674         176 :     Reference< XChartTypeContainer > xChartTypeCont( xCoordSystem, UNO_QUERY );
    3675          88 :     if( xChartTypeCont.is() )
    3676             :     {
    3677          88 :         sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex();
    3678         176 :         for( XclImpChTypeGroupMap::const_iterator aIt = maTypeGroups.begin(), aEnd = maTypeGroups.end(); aIt != aEnd; ++aIt )
    3679             :         {
    3680             :             try
    3681             :             {
    3682          88 :                 Reference< XChartType > xChartType = aIt->second->CreateChartType( xDiagram, nApiAxesSetIdx );
    3683          88 :                 if( xChartType.is() )
    3684          88 :                     xChartTypeCont->addChartType( xChartType );
    3685             :             }
    3686           0 :             catch( Exception& )
    3687             :             {
    3688             :                 OSL_FAIL( "XclImpChAxesSet::CreateCoordSystem - cannot add chart type" );
    3689             :             }
    3690             :         }
    3691             :     }
    3692             : 
    3693         176 :     return xCoordSystem;
    3694             : }
    3695             : 
    3696         264 : void XclImpChAxesSet::ConvertAxis(
    3697             :         XclImpChAxisRef xChAxis, XclImpChTextRef xChAxisTitle,
    3698             :         Reference< XCoordinateSystem > xCoordSystem, const XclImpChAxis* pCrossingAxis ) const
    3699             : {
    3700         264 :     if( xChAxis )
    3701             :     {
    3702             :         // create and attach the axis object
    3703         176 :         Reference< XAxis > xAxis = CreateAxis( *xChAxis, pCrossingAxis );
    3704         176 :         if( xAxis.is() )
    3705             :         {
    3706             :             // create and attach the axis title
    3707         176 :             if( xChAxisTitle ) try
    3708             :             {
    3709           0 :                 Reference< XTitled > xTitled( xAxis, UNO_QUERY_THROW );
    3710           0 :                 Reference< XTitle > xTitle( xChAxisTitle->CreateTitle(), UNO_SET_THROW );
    3711           0 :                 xTitled->setTitleObject( xTitle );
    3712             :             }
    3713           0 :             catch( Exception& )
    3714             :             {
    3715             :                 OSL_FAIL( "XclImpChAxesSet::ConvertAxis - cannot set axis title" );
    3716             :             }
    3717             : 
    3718             :             // insert axis into coordinate system
    3719             :             try
    3720             :             {
    3721         176 :                 sal_Int32 nApiAxisDim = xChAxis->GetApiAxisDimension();
    3722         176 :                 sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex();
    3723         176 :                 xCoordSystem->setAxisByDimension( nApiAxisDim, xAxis, nApiAxesSetIdx );
    3724             :             }
    3725           0 :             catch( Exception& )
    3726             :             {
    3727             :                 OSL_FAIL( "XclImpChAxesSet::ConvertAxis - cannot set axis" );
    3728             :             }
    3729         176 :         }
    3730             :     }
    3731         264 : }
    3732             : 
    3733         176 : Reference< XAxis > XclImpChAxesSet::CreateAxis( const XclImpChAxis& rChAxis, const XclImpChAxis* pCrossingAxis ) const
    3734             : {
    3735         176 :     Reference< XAxis > xAxis;
    3736         176 :     if( const XclImpChTypeGroup* pTypeGroup = GetFirstTypeGroup().get() )
    3737         176 :         xAxis = rChAxis.CreateAxis( *pTypeGroup, pCrossingAxis );
    3738         176 :     return xAxis;
    3739             : }
    3740             : 
    3741          88 : void XclImpChAxesSet::ConvertBackground( Reference< XDiagram > xDiagram ) const
    3742             : {
    3743          88 :     XclImpChTypeGroupRef xTypeGroup = GetFirstTypeGroup();
    3744          88 :     if( xTypeGroup && xTypeGroup->Is3dWallChart() )
    3745             :     {
    3746             :         // wall/floor formatting (3D charts)
    3747           0 :         if( mxXAxis )
    3748             :         {
    3749           0 :             ScfPropertySet aWallProp( xDiagram->getWall() );
    3750           0 :             mxXAxis->ConvertWall( aWallProp );
    3751             :         }
    3752           0 :         if( mxYAxis )
    3753             :         {
    3754           0 :             ScfPropertySet aFloorProp( xDiagram->getFloor() );
    3755           0 :             mxYAxis->ConvertWall( aFloorProp );
    3756             :         }
    3757             :     }
    3758          88 :     else if( mxPlotFrame )
    3759             :     {
    3760             :         // diagram background formatting
    3761          88 :         ScfPropertySet aWallProp( xDiagram->getWall() );
    3762          88 :         mxPlotFrame->Convert( aWallProp );
    3763          88 :     }
    3764          88 : }
    3765             : 
    3766             : // The chart object ===========================================================
    3767             : 
    3768          88 : XclImpChChart::XclImpChChart( const XclImpRoot& rRoot ) :
    3769          88 :     XclImpChRoot( rRoot, *this )
    3770             : {
    3771          88 :     mxPrimAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY ) );
    3772          88 :     mxSecnAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY ) );
    3773          88 : }
    3774             : 
    3775         176 : XclImpChChart::~XclImpChChart()
    3776             : {
    3777         176 : }
    3778             : 
    3779          88 : void XclImpChChart::ReadHeaderRecord( XclImpStream& rStrm )
    3780             : {
    3781             :     // coordinates are stored as 16.16 fixed point
    3782          88 :     rStrm >> maRect;
    3783          88 : }
    3784             : 
    3785        1442 : void XclImpChChart::ReadSubRecord( XclImpStream& rStrm )
    3786             : {
    3787        1442 :     switch( rStrm.GetRecId() )
    3788             :     {
    3789             :         case EXC_ID_CHFRAME:
    3790          88 :             mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND ) );
    3791          88 :             mxFrame->ReadRecordGroup( rStrm );
    3792          88 :         break;
    3793             :         case EXC_ID_CHSERIES:
    3794          98 :             ReadChSeries( rStrm );
    3795          98 :         break;
    3796             :         case EXC_ID_CHPROPERTIES:
    3797          88 :             ReadChProperties( rStrm );
    3798          88 :         break;
    3799             :         case EXC_ID_CHDEFAULTTEXT:
    3800         164 :             ReadChDefaultText( rStrm );
    3801         164 :         break;
    3802             :         case EXC_ID_CHAXESSET:
    3803          88 :             ReadChAxesSet( rStrm );
    3804          88 :         break;
    3805             :         case EXC_ID_CHTEXT:
    3806         184 :             ReadChText( rStrm );
    3807         184 :         break;
    3808             :         case EXC_ID_CHEND:
    3809          88 :             Finalize();     // finalize the entire chart object
    3810          88 :         break;
    3811             :     }
    3812        1442 : }
    3813             : 
    3814         164 : void XclImpChChart::ReadChDefaultText( XclImpStream& rStrm )
    3815             : {
    3816         164 :     sal_uInt16 nTextId = rStrm.ReaduInt16();
    3817         164 :     if( (rStrm.GetNextRecId() == EXC_ID_CHTEXT) && rStrm.StartNextRecord() )
    3818             :     {
    3819         164 :         unique_ptr<XclImpChText> pText(new XclImpChText(GetChRoot()));
    3820         164 :         pText->ReadRecordGroup(rStrm);
    3821         164 :         o3tl::ptr_container::insert(maDefTexts, nTextId, std::move(pText));
    3822             :     }
    3823         164 : }
    3824             : 
    3825         212 : void XclImpChChart::ReadChDataFormat( XclImpStream& rStrm )
    3826             : {
    3827         212 :     XclImpChDataFormatRef xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
    3828         212 :     xDataFmt->ReadRecordGroup( rStrm );
    3829         212 :     if( xDataFmt->GetPointPos().mnSeriesIdx <= EXC_CHSERIES_MAXSERIES )
    3830             :     {
    3831         212 :         const XclChDataPointPos& rPos = xDataFmt->GetPointPos();
    3832         212 :         XclImpChDataFormatMap::iterator itr = maDataFmts.lower_bound(rPos);
    3833         212 :         if (itr == maDataFmts.end() || maDataFmts.key_comp()(rPos, itr->first))
    3834             :             // No element exists for this data point.  Insert it.
    3835             :             maDataFmts.insert(
    3836         212 :                 itr, XclImpChDataFormatMap::value_type(rPos, xDataFmt));
    3837             : 
    3838             :         /*  Do not overwrite existing data format group, Excel always uses the
    3839             :             first data format group occurring in any CHSERIES group. */
    3840         212 :     }
    3841         212 : }
    3842             : 
    3843           0 : void XclImpChChart::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
    3844             : {
    3845           0 :     if( !mxFrame )
    3846           0 :         mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND ) );
    3847           0 :     mxFrame->UpdateObjFrame( rLineData, rFillData );
    3848           0 : }
    3849             : 
    3850         368 : XclImpChTypeGroupRef XclImpChChart::GetTypeGroup( sal_uInt16 nGroupIdx ) const
    3851             : {
    3852         368 :     XclImpChTypeGroupRef xTypeGroup = mxPrimAxesSet->GetTypeGroup( nGroupIdx );
    3853         368 :     if( !xTypeGroup ) xTypeGroup = mxSecnAxesSet->GetTypeGroup( nGroupIdx );
    3854         368 :     if( !xTypeGroup ) xTypeGroup = mxPrimAxesSet->GetFirstTypeGroup();
    3855         368 :     return xTypeGroup;
    3856             : }
    3857             : 
    3858         480 : const XclImpChText* XclImpChChart::GetDefaultText( XclChTextType eTextType ) const
    3859             : {
    3860         480 :     sal_uInt16 nDefTextId = EXC_CHDEFTEXT_GLOBAL;
    3861         480 :     bool bBiff8 = GetBiff() == EXC_BIFF8;
    3862         480 :     switch( eTextType )
    3863             :     {
    3864          88 :         case EXC_CHTEXTTYPE_TITLE:      nDefTextId = EXC_CHDEFTEXT_GLOBAL;                                  break;
    3865          46 :         case EXC_CHTEXTTYPE_LEGEND:     nDefTextId = EXC_CHDEFTEXT_GLOBAL;                                  break;
    3866          88 :         case EXC_CHTEXTTYPE_AXISTITLE:  nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
    3867         160 :         case EXC_CHTEXTTYPE_AXISLABEL:  nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
    3868          98 :         case EXC_CHTEXTTYPE_DATALABEL:  nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
    3869             :     }
    3870             : 
    3871         480 :     XclImpChTextMap::const_iterator itr = maDefTexts.find(nDefTextId);
    3872         480 :     return itr == maDefTexts.end() ? NULL : itr->second;
    3873             : }
    3874             : 
    3875         134 : bool XclImpChChart::IsManualPlotArea() const
    3876             : {
    3877             :     // there is no real automatic mode in BIFF5 charts
    3878         134 :     return (GetBiff() <= EXC_BIFF5) || ::get_flag( maProps.mnFlags, EXC_CHPROPS_USEMANPLOTAREA );
    3879             : }
    3880             : 
    3881          88 : void XclImpChChart::Convert( const Reference<XChartDocument>& xChartDoc,
    3882             :         XclImpDffConverter& rDffConv, const OUString& rObjName, const Rectangle& rChartRect ) const
    3883             : {
    3884             :     // initialize conversion (locks the model to suppress any internal updates)
    3885          88 :     InitConversion( xChartDoc, rChartRect );
    3886             : 
    3887             :     // chart frame formatting
    3888          88 :     if( mxFrame )
    3889             :     {
    3890          88 :         ScfPropertySet aFrameProp( xChartDoc->getPageBackground() );
    3891          88 :         mxFrame->Convert( aFrameProp );
    3892             :     }
    3893             : 
    3894             :     // chart title
    3895          88 :     if( mxTitle ) try
    3896             :     {
    3897          42 :         Reference< XTitled > xTitled( xChartDoc, UNO_QUERY_THROW );
    3898          84 :         Reference< XTitle > xTitle( mxTitle->CreateTitle(), UNO_SET_THROW );
    3899          84 :         xTitled->setTitleObject( xTitle );
    3900             :     }
    3901           0 :     catch( Exception& )
    3902             :     {
    3903             :     }
    3904             : 
    3905             :     /*  Create the diagram object and attach it to the chart document. Currently,
    3906             :         one diagram is used to carry all coordinate systems and data series. */
    3907          88 :     Reference< XDiagram > xDiagram = CreateDiagram();
    3908          88 :     xChartDoc->setFirstDiagram( xDiagram );
    3909             : 
    3910             :     // coordinate systems and chart types, convert axis settings
    3911          88 :     mxPrimAxesSet->Convert( xDiagram );
    3912          88 :     mxSecnAxesSet->Convert( xDiagram );
    3913             : 
    3914             :     // legend
    3915          88 :     if( xDiagram.is() && mxLegend )
    3916          46 :         xDiagram->setLegend( mxLegend->CreateLegend() );
    3917             : 
    3918             :     /*  Following all conversions needing the old Chart1 API that involves full
    3919             :         initialization of the chart view. */
    3920         176 :     Reference< cssc::XChartDocument > xChart1Doc( xChartDoc, UNO_QUERY );
    3921          88 :     if( xChart1Doc.is() )
    3922             :     {
    3923          88 :         Reference< cssc::XDiagram > xDiagram1 = xChart1Doc->getDiagram();
    3924             : 
    3925             :         /*  Set the 'IncludeHiddenCells' property via the old API as only this
    3926             :             ensures that the data provider and all created sequences get this
    3927             :             flag correctly. */
    3928         176 :         ScfPropertySet aDiaProp( xDiagram1 );
    3929          88 :         bool bShowVisCells = ::get_flag( maProps.mnFlags, EXC_CHPROPS_SHOWVISIBLEONLY );
    3930          88 :         aDiaProp.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS, !bShowVisCells );
    3931             : 
    3932             :         // plot area position and size (there is no real automatic mode in BIFF5 charts)
    3933         176 :         XclImpChFramePosRef xPlotAreaPos = mxPrimAxesSet->GetPlotAreaFramePos();
    3934          88 :         if( IsManualPlotArea() && xPlotAreaPos ) try
    3935             :         {
    3936          78 :             const XclChFramePos& rFramePos = xPlotAreaPos->GetFramePosData();
    3937          78 :             if( (rFramePos.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rFramePos.mnBRMode == EXC_CHFRAMEPOS_PARENT) )
    3938             :             {
    3939          78 :                 Reference< cssc::XDiagramPositioning > xPositioning( xDiagram1, UNO_QUERY_THROW );
    3940          78 :                 ::com::sun::star::awt::Rectangle aDiagramRect = CalcHmmFromChartRect( rFramePos.maRect );
    3941             :                 // for pie charts, always set inner plot area size to exclude the data labels as Excel does
    3942          78 :                 const XclImpChTypeGroup* pFirstTypeGroup = mxPrimAxesSet->GetFirstTypeGroup().get();
    3943          78 :                 if( pFirstTypeGroup && (pFirstTypeGroup->GetTypeInfo().meTypeCateg == EXC_CHTYPECATEG_PIE) )
    3944          74 :                     xPositioning->setDiagramPositionExcludingAxes( aDiagramRect );
    3945           4 :                 else if( pFirstTypeGroup && pFirstTypeGroup->Is3dChart() )
    3946           0 :                     xPositioning->setDiagramPositionIncludingAxesAndAxisTitles( aDiagramRect );
    3947             :                 else
    3948           4 :                     xPositioning->setDiagramPositionIncludingAxes( aDiagramRect );
    3949             :             }
    3950             :         }
    3951           0 :         catch( Exception& )
    3952             :         {
    3953             :         }
    3954             : 
    3955             :         // positions of all title objects
    3956          88 :         if( mxTitle )
    3957          42 :             mxTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_TITLE ) );
    3958          88 :         mxPrimAxesSet->ConvertTitlePositions();
    3959         176 :         mxSecnAxesSet->ConvertTitlePositions();
    3960             :     }
    3961             : 
    3962             :     // unlock the model
    3963          88 :     FinishConversion( rDffConv );
    3964             : 
    3965             :     // start listening to this chart
    3966          88 :     ScDocument& rDoc = GetRoot().GetDoc();
    3967          88 :     if( ScChartListenerCollection* pChartCollection = rDoc.GetChartListenerCollection() )
    3968             :     {
    3969          88 :         ::std::unique_ptr< ::std::vector< ScTokenRef > > xRefTokens( new ::std::vector< ScTokenRef > );
    3970         186 :         for( XclImpChSeriesVec::const_iterator aIt = maSeries.begin(), aEnd = maSeries.end(); aIt != aEnd; ++aIt )
    3971          98 :             (*aIt)->FillAllSourceLinks( *xRefTokens );
    3972          88 :         if( !xRefTokens->empty() )
    3973             :         {
    3974          88 :             ::std::unique_ptr< ScChartListener > xListener( new ScChartListener( rObjName, &rDoc, xRefTokens.release() ) );
    3975          88 :             xListener->SetUsed( true );
    3976          88 :             xListener->StartListeningTo();
    3977          88 :             pChartCollection->insert( xListener.release() );
    3978          88 :         }
    3979          88 :     }
    3980          88 : }
    3981             : 
    3982          98 : void XclImpChChart::ReadChSeries( XclImpStream& rStrm )
    3983             : {
    3984          98 :     sal_uInt16 nNewSeriesIdx = static_cast< sal_uInt16 >( maSeries.size() );
    3985          98 :     XclImpChSeriesRef xSeries( new XclImpChSeries( GetChRoot(), nNewSeriesIdx ) );
    3986          98 :     xSeries->ReadRecordGroup( rStrm );
    3987          98 :     maSeries.push_back( xSeries );
    3988          98 : }
    3989             : 
    3990          88 : void XclImpChChart::ReadChProperties( XclImpStream& rStrm )
    3991             : {
    3992          88 :     rStrm >> maProps.mnFlags >> maProps.mnEmptyMode;
    3993          88 : }
    3994             : 
    3995          88 : void XclImpChChart::ReadChAxesSet( XclImpStream& rStrm )
    3996             : {
    3997          88 :     XclImpChAxesSetRef xAxesSet( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_NONE ) );
    3998          88 :     xAxesSet->ReadRecordGroup( rStrm );
    3999          88 :     switch( xAxesSet->GetAxesSetId() )
    4000             :     {
    4001          88 :         case EXC_CHAXESSET_PRIMARY:     mxPrimAxesSet = xAxesSet;   break;
    4002           0 :         case EXC_CHAXESSET_SECONDARY:   mxSecnAxesSet = xAxesSet;   break;
    4003          88 :     }
    4004          88 : }
    4005             : 
    4006         184 : void XclImpChChart::ReadChText( XclImpStream& rStrm )
    4007             : {
    4008         184 :     XclImpChTextRef xText( new XclImpChText( GetChRoot() ) );
    4009         184 :     xText->ReadRecordGroup( rStrm );
    4010         184 :     switch( xText->GetLinkTarget() )
    4011             :     {
    4012             :         case EXC_CHOBJLINK_TITLE:
    4013          50 :             mxTitle = xText;
    4014          50 :         break;
    4015             :         case EXC_CHOBJLINK_DATA:
    4016             :         {
    4017         134 :             sal_uInt16 nSeriesIdx = xText->GetPointPos().mnSeriesIdx;
    4018         134 :             if( nSeriesIdx < maSeries.size() )
    4019         134 :                 maSeries[ nSeriesIdx ]->SetDataLabel( xText );
    4020             :         }
    4021         134 :         break;
    4022         184 :     }
    4023         184 : }
    4024             : 
    4025          88 : void XclImpChChart::Finalize()
    4026             : {
    4027             :     // finalize series (must be done first)
    4028          88 :     FinalizeSeries();
    4029             :     // #i49218# legend may be attached to primary or secondary axes set
    4030          88 :     mxLegend = mxPrimAxesSet->GetLegend();
    4031          88 :     if( !mxLegend )
    4032          42 :         mxLegend = mxSecnAxesSet->GetLegend();
    4033          88 :     if( mxLegend )
    4034          46 :         mxLegend->Finalize();
    4035             :     // axes sets, updates chart type group default formats -> must be called before FinalizeDataFormats()
    4036          88 :     mxPrimAxesSet->Finalize();
    4037          88 :     mxSecnAxesSet->Finalize();
    4038             :     // formatting of all series
    4039          88 :     FinalizeDataFormats();
    4040             :     // #i47745# missing frame -> invisible border and area
    4041          88 :     if( !mxFrame )
    4042           0 :         mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND ) );
    4043             :     // chart title
    4044          88 :     FinalizeTitle();
    4045          88 : }
    4046             : 
    4047          88 : void XclImpChChart::FinalizeSeries()
    4048             : {
    4049         186 :     for( XclImpChSeriesVec::iterator aSIt = maSeries.begin(), aSEnd = maSeries.end(); aSIt != aSEnd; ++aSIt )
    4050             :     {
    4051          98 :         XclImpChSeriesRef xSeries = *aSIt;
    4052          98 :         if( xSeries->HasParentSeries() )
    4053             :         {
    4054             :             /*  Process child series (trend lines and error bars). Data of
    4055             :                 child series will be set at the connected parent series. */
    4056           6 :             if( xSeries->GetParentIdx() < maSeries.size() )
    4057           6 :                 maSeries[ xSeries->GetParentIdx() ]->AddChildSeries( *xSeries );
    4058             :         }
    4059             :         else
    4060             :         {
    4061             :             // insert the series into the related chart type group
    4062          92 :             if( XclImpChTypeGroup* pTypeGroup = GetTypeGroup( xSeries->GetGroupIdx() ).get() )
    4063          92 :                 pTypeGroup->AddSeries( xSeries );
    4064             :         }
    4065          98 :     }
    4066          88 : }
    4067             : 
    4068          88 : void XclImpChChart::FinalizeDataFormats()
    4069             : {
    4070             :     /*  #i51639# (part 1): CHDATAFORMAT groups are part of CHSERIES groups.
    4071             :         Each CHDATAFORMAT group specifies the series and data point it is
    4072             :         assigned to. This makes it possible to have a data format that is
    4073             :         related to another series, e.g. a CHDATAFORMAT group for series 2 is
    4074             :         part of a CHSERIES group that describes series 1. Therefore the chart
    4075             :         itself has collected all CHDATAFORMAT groups to be able to store data
    4076             :         format groups for series that have not been imported at that time. This
    4077             :         loop finally assigns these groups to the related series. */
    4078         300 :     for( XclImpChDataFormatMap::const_iterator aMIt = maDataFmts.begin(), aMEnd = maDataFmts.end(); aMIt != aMEnd; ++aMIt )
    4079             :     {
    4080         212 :         sal_uInt16 nSeriesIdx = aMIt->first.mnSeriesIdx;
    4081         212 :         if( nSeriesIdx < maSeries.size() )
    4082         212 :             maSeries[ nSeriesIdx ]->SetDataFormat( aMIt->second );
    4083             :     }
    4084             : 
    4085             :     /*  #i51639# (part 2): Finalize data formats of all series. This adds for
    4086             :         example missing CHDATAFORMAT groups for entire series that are needed
    4087             :         for automatic colors of lines and areas. */
    4088         186 :     for( XclImpChSeriesVec::iterator aVIt = maSeries.begin(), aVEnd = maSeries.end(); aVIt != aVEnd; ++aVIt )
    4089          98 :         (*aVIt)->FinalizeDataFormats();
    4090          88 : }
    4091             : 
    4092          88 : void XclImpChChart::FinalizeTitle()
    4093             : {
    4094             :     // special handling for auto-generated title
    4095          88 :     OUString aAutoTitle;
    4096          88 :     if( !mxTitle || (!mxTitle->IsDeleted() && !mxTitle->HasString()) )
    4097             :     {
    4098             :         // automatic title from first series name (if there are no series on secondary axes set)
    4099          76 :         if( !mxSecnAxesSet->IsValidAxesSet() )
    4100          76 :             aAutoTitle = mxPrimAxesSet->GetSingleSeriesTitle();
    4101          76 :         if( mxTitle || (!aAutoTitle.isEmpty()) )
    4102             :         {
    4103          38 :             if( !mxTitle )
    4104           0 :                 mxTitle.reset( new XclImpChText( GetChRoot() ) );
    4105          38 :             if( aAutoTitle.isEmpty() )
    4106           0 :                 aAutoTitle = "Chart Title";
    4107             :         }
    4108             :     }
    4109             : 
    4110             :     // will reset mxTitle, if it does not contain a string and no auto title exists
    4111          88 :     lclFinalizeTitle( mxTitle, GetDefaultText( EXC_CHTEXTTYPE_TITLE ), aAutoTitle );
    4112          88 : }
    4113             : 
    4114          88 : Reference< XDiagram > XclImpChChart::CreateDiagram() const
    4115             : {
    4116             :     // create a diagram object
    4117          88 :     Reference< XDiagram > xDiagram( ScfApiHelper::CreateInstance( SERVICE_CHART2_DIAGRAM ), UNO_QUERY );
    4118             : 
    4119             :     // convert global chart settings
    4120         176 :     ScfPropertySet aDiaProp( xDiagram );
    4121             : 
    4122             :     // treatment of missing values
    4123             :     using namespace cssc::MissingValueTreatment;
    4124          88 :     sal_Int32 nMissingValues = LEAVE_GAP;
    4125          88 :     switch( maProps.mnEmptyMode )
    4126             :     {
    4127          10 :         case EXC_CHPROPS_EMPTY_SKIP:        nMissingValues = LEAVE_GAP; break;
    4128          76 :         case EXC_CHPROPS_EMPTY_ZERO:        nMissingValues = USE_ZERO;  break;
    4129           2 :         case EXC_CHPROPS_EMPTY_INTERPOLATE: nMissingValues = CONTINUE;  break;
    4130             :     }
    4131          88 :     aDiaProp.SetProperty( EXC_CHPROP_MISSINGVALUETREATMENT, nMissingValues );
    4132             : 
    4133         176 :     return xDiagram;
    4134             : }
    4135             : 
    4136          76 : XclImpChartDrawing::XclImpChartDrawing( const XclImpRoot& rRoot, bool bOwnTab ) :
    4137             :     XclImpDrawing( rRoot, bOwnTab ), // sheet charts may contain OLE objects
    4138          76 :     mnScTab( rRoot.GetCurrScTab() ),
    4139         152 :     mbOwnTab( bOwnTab )
    4140             : {
    4141          76 : }
    4142             : 
    4143          76 : void XclImpChartDrawing::ConvertObjects( XclImpDffConverter& rDffConv,
    4144             :         const Reference< XModel >& rxModel, const Rectangle& rChartRect )
    4145             : {
    4146          76 :     maChartRect = rChartRect;   // needed in CalcAnchorRect() callback
    4147             : 
    4148          76 :     SdrModel* pSdrModel = 0;
    4149          76 :     SdrPage* pSdrPage = 0;
    4150          76 :     if( mbOwnTab )
    4151             :     {
    4152             :         // chart sheet: insert all shapes into the sheet, not into the chart object
    4153           0 :         pSdrModel = GetDoc().GetDrawLayer();
    4154           0 :         pSdrPage = GetSdrPage( mnScTab );
    4155             :     }
    4156             :     else
    4157             :     {
    4158             :         // embedded chart object: insert all shapes into the chart
    4159             :         try
    4160             :         {
    4161          76 :             Reference< XDrawPageSupplier > xDrawPageSupp( rxModel, UNO_QUERY_THROW );
    4162         152 :             Reference< XDrawPage > xDrawPage( xDrawPageSupp->getDrawPage(), UNO_SET_THROW );
    4163          76 :             pSdrPage = ::GetSdrPageFromXDrawPage( xDrawPage );
    4164         152 :             pSdrModel = pSdrPage ? pSdrPage->GetModel() : 0;
    4165             :         }
    4166           0 :         catch( Exception& )
    4167             :         {
    4168             :         }
    4169             :     }
    4170             : 
    4171          76 :     if( pSdrModel && pSdrPage )
    4172          76 :         ImplConvertObjects( rDffConv, *pSdrModel, *pSdrPage );
    4173          76 : }
    4174             : 
    4175           0 : Rectangle XclImpChartDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool bDffAnchor ) const
    4176             : {
    4177             :     /*  In objects with DFF client anchor, the position of the shape is stored
    4178             :         in the cell address components of the client anchor. In old BIFF3-BIFF5
    4179             :         objects, the position is stored in the offset components of the anchor. */
    4180             :     Rectangle aRect(
    4181           0 :         static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnCol : rAnchor.mnLX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth()  + 0.5 ),
    4182           0 :         static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnRow : rAnchor.mnTY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ),
    4183           0 :         static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnCol  : rAnchor.mnRX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth()  + 0.5 ),
    4184           0 :         static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnRow  : rAnchor.mnBY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ) );
    4185           0 :     aRect.Justify();
    4186             :     // move shapes into chart area for sheet charts
    4187           0 :     if( mbOwnTab )
    4188           0 :         aRect.Move( maChartRect.Left(), maChartRect.Top() );
    4189           0 :     return aRect;
    4190             : }
    4191             : 
    4192           0 : void XclImpChartDrawing::OnObjectInserted( const XclImpDrawObjBase& )
    4193             : {
    4194           0 : }
    4195             : 
    4196          90 : XclImpChart::XclImpChart( const XclImpRoot& rRoot, bool bOwnTab ) :
    4197             :     XclImpRoot( rRoot ),
    4198             :     mbOwnTab( bOwnTab ),
    4199          90 :     mbIsPivotChart( false )
    4200             : {
    4201          90 : }
    4202             : 
    4203         180 : XclImpChart::~XclImpChart()
    4204             : {
    4205         180 : }
    4206             : 
    4207          90 : void XclImpChart::ReadChartSubStream( XclImpStream& rStrm )
    4208             : {
    4209          90 :     XclImpPageSettings& rPageSett = GetPageSettings();
    4210          90 :     XclImpTabViewSettings& rTabViewSett = GetTabViewSettings();
    4211             : 
    4212          90 :     bool bLoop = true;
    4213        2138 :     while( bLoop && rStrm.StartNextRecord() )
    4214             :     {
    4215             :         // page settings - only for charts in entire sheet
    4216        1958 :         if( mbOwnTab ) switch( rStrm.GetRecId() )
    4217             :         {
    4218             :             case EXC_ID_HORPAGEBREAKS:
    4219           0 :             case EXC_ID_VERPAGEBREAKS:  rPageSett.ReadPageBreaks( rStrm );      break;
    4220             :             case EXC_ID_HEADER:
    4221           0 :             case EXC_ID_FOOTER:         rPageSett.ReadHeaderFooter( rStrm );    break;
    4222             :             case EXC_ID_LEFTMARGIN:
    4223             :             case EXC_ID_RIGHTMARGIN:
    4224             :             case EXC_ID_TOPMARGIN:
    4225           0 :             case EXC_ID_BOTTOMMARGIN:   rPageSett.ReadMargin( rStrm );          break;
    4226           0 :             case EXC_ID_PRINTHEADERS:   rPageSett.ReadPrintHeaders( rStrm );    break;
    4227           0 :             case EXC_ID_PRINTGRIDLINES: rPageSett.ReadPrintGridLines( rStrm );  break;
    4228             :             case EXC_ID_HCENTER:
    4229           0 :             case EXC_ID_VCENTER:        rPageSett.ReadCenter( rStrm );          break;
    4230           0 :             case EXC_ID_SETUP:          rPageSett.ReadSetup( rStrm );           break;
    4231           0 :             case EXC_ID8_IMGDATA:       rPageSett.ReadImgData( rStrm );         break;
    4232             : 
    4233           0 :             case EXC_ID_WINDOW2:        rTabViewSett.ReadWindow2( rStrm, true );break;
    4234           0 :             case EXC_ID_SCL:            rTabViewSett.ReadScl( rStrm );          break;
    4235             : 
    4236             :             case EXC_ID_SHEETEXT: //0x0862
    4237             :             {
    4238             :                 // FIXME: do not need to pass palette, XclImpTabVieSettings is derived from root
    4239           0 :                 XclImpPalette& rPal = GetPalette();
    4240           0 :                 rTabViewSett.ReadTabBgColor( rStrm,  rPal);
    4241             :             }
    4242           0 :             break;
    4243             : 
    4244           0 :             case EXC_ID_CODENAME:       ReadCodeName( rStrm, false );           break;
    4245             :         }
    4246             : 
    4247             :         // common records
    4248        1958 :         switch( rStrm.GetRecId() )
    4249             :         {
    4250          90 :             case EXC_ID_EOF:            bLoop = false;                          break;
    4251             : 
    4252             :             // #i31882# ignore embedded chart objects
    4253             :             case EXC_ID2_BOF:
    4254             :             case EXC_ID3_BOF:
    4255             :             case EXC_ID4_BOF:
    4256           0 :             case EXC_ID5_BOF:           XclTools::SkipSubStream( rStrm );       break;
    4257             : 
    4258          88 :             case EXC_ID_CHCHART:        ReadChChart( rStrm );                   break;
    4259             : 
    4260             :             case EXC_ID8_CHPIVOTREF:
    4261           0 :                 GetTracer().TracePivotChartExists();
    4262           0 :                 mbIsPivotChart = true;
    4263           0 :             break;
    4264             : 
    4265             :             // BIFF specific records
    4266        1780 :             default: switch( GetBiff() )
    4267             :             {
    4268           0 :                 case EXC_BIFF5: switch( rStrm.GetRecId() )
    4269             :                 {
    4270           0 :                     case EXC_ID_OBJ:        GetChartDrawing().ReadObj( rStrm );         break;
    4271             :                 }
    4272           0 :                 break;
    4273        1780 :                 case EXC_BIFF8: switch( rStrm.GetRecId() )
    4274             :                 {
    4275          76 :                     case EXC_ID_MSODRAWING: GetChartDrawing().ReadMsoDrawing( rStrm );  break;
    4276             :                     // #i61786# weird documents: OBJ without MSODRAWING -> read in BIFF5 format
    4277           0 :                     case EXC_ID_OBJ:        GetChartDrawing().ReadObj( rStrm );         break;
    4278             :                 }
    4279        1780 :                 break;
    4280             :                 default:;
    4281             :             }
    4282             :         }
    4283             :     }
    4284          90 : }
    4285             : 
    4286           0 : void XclImpChart::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
    4287             : {
    4288           0 :     if( !mxChartData )
    4289           0 :         mxChartData.reset( new XclImpChChart( GetRoot() ) );
    4290           0 :     mxChartData->UpdateObjFrame( rLineData, rFillData );
    4291           0 : }
    4292             : 
    4293          90 : sal_Size XclImpChart::GetProgressSize() const
    4294             : {
    4295             :     return
    4296         256 :         (mxChartData ? mxChartData->GetProgressSize() : 0) +
    4297         256 :         (mxChartDrawing ? mxChartDrawing->GetProgressSize() : 0);
    4298             : }
    4299             : 
    4300          90 : void XclImpChart::Convert( Reference< XModel > xModel, XclImpDffConverter& rDffConv, const OUString& rObjName, const Rectangle& rChartRect ) const
    4301             : {
    4302          90 :     Reference< XChartDocument > xChartDoc( xModel, UNO_QUERY );
    4303          90 :     if( xChartDoc.is() )
    4304             :     {
    4305          90 :         if( mxChartData )
    4306          88 :             mxChartData->Convert( xChartDoc, rDffConv, rObjName, rChartRect );
    4307          90 :         if( mxChartDrawing )
    4308          76 :             mxChartDrawing->ConvertObjects( rDffConv, xModel, rChartRect );
    4309          90 :     }
    4310          90 : }
    4311             : 
    4312          76 : XclImpChartDrawing& XclImpChart::GetChartDrawing()
    4313             : {
    4314          76 :     if( !mxChartDrawing )
    4315          76 :         mxChartDrawing.reset( new XclImpChartDrawing( GetRoot(), mbOwnTab ) );
    4316          76 :     return *mxChartDrawing;
    4317             : }
    4318             : 
    4319          88 : void XclImpChart::ReadChChart( XclImpStream& rStrm )
    4320             : {
    4321          88 :     mxChartData.reset( new XclImpChChart( GetRoot() ) );
    4322          88 :     mxChartData->ReadRecordGroup( rStrm );
    4323         136 : }
    4324             : 
    4325             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10