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

Generated by: LCOV version 1.10