LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xichart.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1840 2330 79.0 %
Date: 2015-06-13 12:38:46 Functions: 236 269 87.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11