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 <xlchart.hxx>
21 
22 #include <com/sun/star/container/XNameContainer.hpp>
23 #include <com/sun/star/awt/Size.hpp>
24 #include <com/sun/star/awt/Gradient.hpp>
25 #include <com/sun/star/drawing/Hatch.hpp>
26 #include <com/sun/star/drawing/LineDash.hpp>
27 #include <com/sun/star/drawing/LineStyle.hpp>
28 #include <com/sun/star/drawing/FillStyle.hpp>
29 #include <com/sun/star/drawing/BitmapMode.hpp>
30 #include <com/sun/star/chart/DataLabelPlacement.hpp>
31 #include <com/sun/star/chart/XAxisXSupplier.hpp>
32 #include <com/sun/star/chart/XAxisYSupplier.hpp>
33 #include <com/sun/star/chart/XAxisZSupplier.hpp>
34 #include <com/sun/star/chart/XChartDocument.hpp>
35 #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
36 #include <com/sun/star/chart2/Symbol.hpp>
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 
39 #include <sal/macros.h>
40 #include <svl/itemset.hxx>
41 #include <svx/xfillit0.hxx>
42 #include <svx/xflclit.hxx>
43 #include <svx/xfltrit.hxx>
44 #include <svx/xflgrit.hxx>
45 #include <svx/xbtmpit.hxx>
46 #include <svx/unomid.hxx>
47 #include <filter/msfilter/escherex.hxx>
48 #include <xlroot.hxx>
49 #include <xlstyle.hxx>
50 #include <xltools.hxx>
51 
52 using namespace css;
53 
54 // Common =====================================================================
55 
XclChRectangle()56 XclChRectangle::XclChRectangle() :
57     mnX( 0 ),
58     mnY( 0 ),
59     mnWidth( 0 ),
60     mnHeight( 0 )
61 {
62 }
63 
XclChDataPointPos(sal_uInt16 nSeriesIdx,sal_uInt16 nPointIdx)64 XclChDataPointPos::XclChDataPointPos( sal_uInt16 nSeriesIdx, sal_uInt16 nPointIdx ) :
65     mnSeriesIdx( nSeriesIdx ),
66     mnPointIdx( nPointIdx )
67 {
68 }
69 
operator <(const XclChDataPointPos & rL,const XclChDataPointPos & rR)70 bool operator<( const XclChDataPointPos& rL, const XclChDataPointPos& rR )
71 {
72     return (rL.mnSeriesIdx < rR.mnSeriesIdx) ||
73         ((rL.mnSeriesIdx == rR.mnSeriesIdx) && (rL.mnPointIdx < rR.mnPointIdx));
74 }
75 
XclChFrBlock(sal_uInt16 nType)76 XclChFrBlock::XclChFrBlock( sal_uInt16 nType ) :
77     mnType( nType ),
78     mnContext( 0 ),
79     mnValue1( 0 ),
80     mnValue2( 0 )
81 {
82 }
83 
84 // Frame formatting ===========================================================
85 
XclChFramePos()86 XclChFramePos::XclChFramePos() :
87     mnTLMode( EXC_CHFRAMEPOS_PARENT ),
88     mnBRMode( EXC_CHFRAMEPOS_PARENT )
89 {
90 }
91 
XclChLineFormat()92 XclChLineFormat::XclChLineFormat() :
93     maColor( COL_BLACK ),
94     mnPattern( EXC_CHLINEFORMAT_SOLID ),
95     mnWeight( EXC_CHLINEFORMAT_SINGLE ),
96     mnFlags( EXC_CHLINEFORMAT_AUTO )
97 {
98 }
99 
XclChAreaFormat()100 XclChAreaFormat::XclChAreaFormat() :
101     maPattColor( COL_WHITE ),
102     maBackColor( COL_BLACK ),
103     mnPattern( EXC_PATT_SOLID ),
104     mnFlags( EXC_CHAREAFORMAT_AUTO )
105 {
106 }
107 
XclChEscherFormat()108 XclChEscherFormat::XclChEscherFormat()
109 {
110 }
111 
~XclChEscherFormat()112 XclChEscherFormat::~XclChEscherFormat()
113 {
114 }
115 
XclChPicFormat()116 XclChPicFormat::XclChPicFormat() :
117     mnBmpMode( EXC_CHPICFORMAT_NONE ),
118     mnFlags( EXC_CHPICFORMAT_TOPBOTTOM | EXC_CHPICFORMAT_FRONTBACK | EXC_CHPICFORMAT_LEFTRIGHT ),
119     mfScale( 0.5 )
120 {
121 }
122 
XclChFrame()123 XclChFrame::XclChFrame() :
124     mnFormat( EXC_CHFRAME_STANDARD ),
125     mnFlags( EXC_CHFRAME_AUTOSIZE | EXC_CHFRAME_AUTOPOS )
126 {
127 }
128 
129 // Source links ===============================================================
130 
XclChSourceLink()131 XclChSourceLink::XclChSourceLink() :
132     mnDestType( EXC_CHSRCLINK_TITLE ),
133     mnLinkType( EXC_CHSRCLINK_DEFAULT ),
134     mnFlags( 0 ),
135     mnNumFmtIdx( 0 )
136 {
137 }
138 
139 // Text =======================================================================
140 
XclChObjectLink()141 XclChObjectLink::XclChObjectLink() :
142     mnTarget( EXC_CHOBJLINK_NONE )
143 {
144 }
145 
XclChFrLabelProps()146 XclChFrLabelProps::XclChFrLabelProps() :
147     mnFlags( 0 )
148 {
149 }
150 
XclChText()151 XclChText::XclChText() :
152     maTextColor( COL_BLACK ),
153     mnHAlign( EXC_CHTEXT_ALIGN_CENTER ),
154     mnVAlign( EXC_CHTEXT_ALIGN_CENTER ),
155     mnBackMode( EXC_CHTEXT_TRANSPARENT ),
156     mnFlags( EXC_CHTEXT_AUTOCOLOR | EXC_CHTEXT_AUTOFILL ),
157     mnFlags2( EXC_CHTEXT_POS_DEFAULT ),
158     mnRotation( EXC_ROT_NONE )
159 {
160 }
161 
162 // Data series ================================================================
163 
XclChMarkerFormat()164 XclChMarkerFormat::XclChMarkerFormat() :
165     maLineColor( COL_BLACK ),
166     maFillColor( COL_WHITE ),
167     mnMarkerSize( EXC_CHMARKERFORMAT_SINGLESIZE ),
168     mnMarkerType( EXC_CHMARKERFORMAT_NOSYMBOL ),
169     mnFlags( EXC_CHMARKERFORMAT_AUTO )
170 {
171 };
172 
XclCh3dDataFormat()173 XclCh3dDataFormat::XclCh3dDataFormat() :
174     mnBase( EXC_CH3DDATAFORMAT_RECT ),
175     mnTop( EXC_CH3DDATAFORMAT_STRAIGHT )
176 {
177 }
178 
XclChDataFormat()179 XclChDataFormat::XclChDataFormat() :
180     mnFormatIdx( EXC_CHDATAFORMAT_DEFAULT ),
181     mnFlags( 0 )
182 {
183 }
184 
XclChSerTrendLine()185 XclChSerTrendLine::XclChSerTrendLine() :
186     mfForecastFor( 0.0 ),
187     mfForecastBack( 0.0 ),
188     mnLineType( EXC_CHSERTREND_POLYNOMIAL ),
189     mnOrder( 1 ),
190     mnShowEquation( 0 ),
191     mnShowRSquared( 0 )
192 {
193     /*  Set all bits in mfIntercept to 1 (that is -1.#NAN) to indicate that
194         there is no interception point. Cannot use ::rtl::math::setNan() here
195         cause it misses the sign bit. */
196     sal_math_Double* pDouble = reinterpret_cast< sal_math_Double* >( &mfIntercept );
197     pDouble->w32_parts.msw = pDouble->w32_parts.lsw = 0xFFFFFFFF;
198 }
199 
XclChSerErrorBar()200 XclChSerErrorBar::XclChSerErrorBar() :
201     mfValue( 0.0 ),
202     mnValueCount( 1 ),
203     mnBarType( EXC_CHSERERR_NONE ),
204     mnSourceType( EXC_CHSERERR_FIXED ),
205     mnLineEnd( EXC_CHSERERR_END_TSHAPE )
206 {
207 }
208 
XclChSeries()209 XclChSeries::XclChSeries() :
210     mnCategType( EXC_CHSERIES_NUMERIC ),
211     mnValueType( EXC_CHSERIES_NUMERIC ),
212     mnBubbleType( EXC_CHSERIES_NUMERIC ),
213     mnCategCount( 0 ),
214     mnValueCount( 0 ),
215     mnBubbleCount( 0 )
216 {
217 }
218 
219 // Chart type groups ==========================================================
220 
XclChType()221 XclChType::XclChType() :
222     mnOverlap( 0 ),
223     mnGap( 150 ),
224     mnRotation( 0 ),
225     mnPieHole( 0 ),
226     mnBubbleSize( 100 ),
227     mnBubbleType( EXC_CHSCATTER_AREA ),
228     mnFlags( 0 )
229 {
230 }
231 
XclChChart3d()232 XclChChart3d::XclChChart3d() :
233     mnRotation( 20 ),
234     mnElevation( 15 ),
235     mnEyeDist( 30 ),
236     mnRelHeight( 100 ),
237     mnRelDepth( 100 ),
238     mnDepthGap( 150 ),
239     mnFlags( EXC_CHCHART3D_AUTOHEIGHT )
240 {
241 }
242 
XclChLegend()243 XclChLegend::XclChLegend() :
244     mnDockMode( EXC_CHLEGEND_RIGHT ),
245     mnSpacing( EXC_CHLEGEND_MEDIUM ),
246     mnFlags( EXC_CHLEGEND_DOCKED | EXC_CHLEGEND_AUTOSERIES |
247         EXC_CHLEGEND_AUTOPOSX | EXC_CHLEGEND_AUTOPOSY | EXC_CHLEGEND_STACKED )
248 {
249 }
250 
XclChTypeGroup()251 XclChTypeGroup::XclChTypeGroup() :
252     mnFlags( 0 ),
253     mnGroupIdx( EXC_CHSERGROUP_NONE )
254 {
255 }
256 
XclChProperties()257 XclChProperties::XclChProperties() :
258     mnFlags( 0 ),
259     mnEmptyMode( EXC_CHPROPS_EMPTY_SKIP )
260 {
261 }
262 
263 // Axes =======================================================================
264 
XclChLabelRange()265 XclChLabelRange::XclChLabelRange() :
266     mnCross( 1 ),
267     mnLabelFreq( 1 ),
268     mnTickFreq( 1 ),
269     mnFlags( 0 )
270 {
271 }
272 
XclChDateRange()273 XclChDateRange::XclChDateRange() :
274     mnMinDate( 0 ),
275     mnMaxDate( 0 ),
276     mnMajorStep( 0 ),
277     mnMajorUnit( EXC_CHDATERANGE_DAYS ),
278     mnMinorStep( 0 ),
279     mnMinorUnit( EXC_CHDATERANGE_DAYS ),
280     mnBaseUnit( EXC_CHDATERANGE_DAYS ),
281     mnCross( 0 ),
282     mnFlags( EXC_CHDATERANGE_AUTOMIN | EXC_CHDATERANGE_AUTOMAX |
283         EXC_CHDATERANGE_AUTOMAJOR | EXC_CHDATERANGE_AUTOMINOR |
284         EXC_CHDATERANGE_AUTOBASE | EXC_CHDATERANGE_AUTOCROSS |
285         EXC_CHDATERANGE_AUTODATE )
286 {
287 }
288 
XclChValueRange()289 XclChValueRange::XclChValueRange() :
290     mfMin( 0.0 ),
291     mfMax( 0.0 ),
292     mfMajorStep( 0.0 ),
293     mfMinorStep( 0.0 ),
294     mfCross( 0.0 ),
295     mnFlags( EXC_CHVALUERANGE_AUTOMIN | EXC_CHVALUERANGE_AUTOMAX |
296         EXC_CHVALUERANGE_AUTOMAJOR | EXC_CHVALUERANGE_AUTOMINOR |
297         EXC_CHVALUERANGE_AUTOCROSS | EXC_CHVALUERANGE_BIT8 )
298 {
299 }
300 
XclChTick()301 XclChTick::XclChTick() :
302     maTextColor( COL_BLACK ),
303     mnMajor( EXC_CHTICK_INSIDE | EXC_CHTICK_OUTSIDE ),
304     mnMinor( 0 ),
305     mnLabelPos( EXC_CHTICK_NEXT ),
306     mnBackMode( EXC_CHTICK_TRANSPARENT ),
307     mnFlags( EXC_CHTICK_AUTOCOLOR | EXC_CHTICK_AUTOROT ),
308     mnRotation( EXC_ROT_NONE )
309 {
310 }
311 
XclChAxis()312 XclChAxis::XclChAxis() :
313     mnType( EXC_CHAXIS_NONE )
314 {
315 }
316 
GetApiAxisDimension() const317 sal_Int32 XclChAxis::GetApiAxisDimension() const
318 {
319     sal_Int32 nApiAxisDim = EXC_CHART_AXIS_NONE;
320     switch( mnType )
321     {
322         case EXC_CHAXIS_X:  nApiAxisDim = EXC_CHART_AXIS_X; break;
323         case EXC_CHAXIS_Y:  nApiAxisDim = EXC_CHART_AXIS_Y; break;
324         case EXC_CHAXIS_Z:  nApiAxisDim = EXC_CHART_AXIS_Z; break;
325     }
326     return nApiAxisDim;
327 }
328 
XclChAxesSet()329 XclChAxesSet::XclChAxesSet() :
330     mnAxesSetId( EXC_CHAXESSET_PRIMARY )
331 {
332 }
333 
GetApiAxesSetIndex() const334 sal_Int32 XclChAxesSet::GetApiAxesSetIndex() const
335 {
336     sal_Int32 nApiAxesSetIdx = EXC_CHART_AXESSET_NONE;
337     switch( mnAxesSetId )
338     {
339         case EXC_CHAXESSET_PRIMARY:     nApiAxesSetIdx = EXC_CHART_AXESSET_PRIMARY;     break;
340         case EXC_CHAXESSET_SECONDARY:   nApiAxesSetIdx = EXC_CHART_AXESSET_SECONDARY;   break;
341     }
342     return nApiAxesSetIdx;
343 }
344 
345 // Static helper functions ====================================================
346 
GetSeriesLineAutoColorIdx(sal_uInt16 nFormatIdx)347 sal_uInt16 XclChartHelper::GetSeriesLineAutoColorIdx( sal_uInt16 nFormatIdx )
348 {
349     static const sal_uInt16 spnLineColors[] =
350     {
351         32, 33, 34, 35, 36, 37, 38, 39,
352         40, 41, 42, 43, 44, 45, 46, 47,
353         48, 49, 50, 51, 52, 53, 54, 55,
354         56, 57, 58, 59, 60, 61, 62,  8,
355          9, 10, 11, 12, 13, 14, 15, 16,
356         17, 18, 19, 20, 21, 22, 23, 24,
357         25, 26, 27, 28, 29, 30, 31, 63
358     };
359     return spnLineColors[ nFormatIdx % SAL_N_ELEMENTS( spnLineColors ) ];
360 }
361 
GetSeriesFillAutoColorIdx(sal_uInt16 nFormatIdx)362 sal_uInt16 XclChartHelper::GetSeriesFillAutoColorIdx( sal_uInt16 nFormatIdx )
363 {
364     static const sal_uInt16 spnFillColors[] =
365     {
366         24, 25, 26, 27, 28, 29, 30, 31,
367         32, 33, 34, 35, 36, 37, 38, 39,
368         40, 41, 42, 43, 44, 45, 46, 47,
369         48, 49, 50, 51, 52, 53, 54, 55,
370         56, 57, 58, 59, 60, 61, 62, 63,
371          8,  9, 10, 11, 12, 13, 14, 15,
372         16, 17, 18, 19, 20, 21, 22, 23
373     };
374     return spnFillColors[ nFormatIdx % SAL_N_ELEMENTS( spnFillColors ) ];
375 }
376 
GetSeriesFillAutoTransp(sal_uInt16 nFormatIdx)377 sal_uInt8 XclChartHelper::GetSeriesFillAutoTransp( sal_uInt16 nFormatIdx )
378 {
379     static const sal_uInt8 spnTrans[] = { 0x00, 0x40, 0x20, 0x60, 0x70 };
380     return spnTrans[ (nFormatIdx / 56) % SAL_N_ELEMENTS( spnTrans ) ];
381 }
382 
GetAutoMarkerType(sal_uInt16 nFormatIdx)383 sal_uInt16 XclChartHelper::GetAutoMarkerType( sal_uInt16 nFormatIdx )
384 {
385     static const sal_uInt16 spnSymbols[] = {
386         EXC_CHMARKERFORMAT_DIAMOND, EXC_CHMARKERFORMAT_SQUARE, EXC_CHMARKERFORMAT_TRIANGLE,
387         EXC_CHMARKERFORMAT_CROSS, EXC_CHMARKERFORMAT_STAR, EXC_CHMARKERFORMAT_CIRCLE,
388         EXC_CHMARKERFORMAT_PLUS, EXC_CHMARKERFORMAT_DOWJ, EXC_CHMARKERFORMAT_STDDEV };
389     return spnSymbols[ nFormatIdx % SAL_N_ELEMENTS( spnSymbols ) ];
390 }
391 
HasMarkerFillColor(sal_uInt16 nMarkerType)392 bool XclChartHelper::HasMarkerFillColor( sal_uInt16 nMarkerType )
393 {
394     static const bool spbFilled[] = {
395         false, true, true, true, false, false, false, false, true, false };
396     return (nMarkerType < SAL_N_ELEMENTS( spbFilled )) && spbFilled[ nMarkerType ];
397 }
398 
GetErrorBarValuesRole(sal_uInt8 nBarType)399 OUString XclChartHelper::GetErrorBarValuesRole( sal_uInt8 nBarType )
400 {
401     switch( nBarType )
402     {
403         case EXC_CHSERERR_XPLUS:    return EXC_CHPROP_ROLE_ERRORBARS_POSX;
404         case EXC_CHSERERR_XMINUS:   return EXC_CHPROP_ROLE_ERRORBARS_NEGX;
405         case EXC_CHSERERR_YPLUS:    return EXC_CHPROP_ROLE_ERRORBARS_POSY;
406         case EXC_CHSERERR_YMINUS:   return EXC_CHPROP_ROLE_ERRORBARS_NEGY;
407         default:    OSL_FAIL( "XclChartHelper::GetErrorBarValuesRole - unknown bar type" );
408     }
409     return OUString();
410 }
411 
412 // Chart formatting info provider =============================================
413 
414 namespace {
415 
416 static const XclChFormatInfo spFmtInfos[] =
417 {
418     // object type                  property mode                auto line color         auto line weight         auto pattern color      missing frame type         create delete isframe
419     { EXC_CHOBJTYPE_BACKGROUND,     EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_INVISIBLE, true,  true,  true  },
420     { EXC_CHOBJTYPE_PLOTFRAME,      EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_INVISIBLE, true,  true,  true  },
421     { EXC_CHOBJTYPE_WALL3D,         EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_AUTO,      true,  false, true  },
422     { EXC_CHOBJTYPE_FLOOR3D,        EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   23,                     EXC_CHFRAMETYPE_AUTO,      true,  false, true  },
423     { EXC_CHOBJTYPE_TEXT,           EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_INVISIBLE, false, true,  true  },
424     { EXC_CHOBJTYPE_LEGEND,         EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_AUTO,      true,  true,  true  },
425     { EXC_CHOBJTYPE_LINEARSERIES,   EXC_CHPROPMODE_LINEARSERIES, 0xFFFF,                 EXC_CHLINEFORMAT_SINGLE, EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_AUTO,      false, false, false },
426     { EXC_CHOBJTYPE_FILLEDSERIES,   EXC_CHPROPMODE_FILLEDSERIES, EXC_COLOR_CHBORDERAUTO, EXC_CHLINEFORMAT_SINGLE, 0xFFFF,                 EXC_CHFRAMETYPE_AUTO,      false, false, true  },
427     { EXC_CHOBJTYPE_AXISLINE,       EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_AUTO,      false, false, false },
428     { EXC_CHOBJTYPE_GRIDLINE,       EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_INVISIBLE, false, true,  false  },
429     { EXC_CHOBJTYPE_TRENDLINE,      EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_DOUBLE, EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_INVISIBLE, false, false, false },
430     { EXC_CHOBJTYPE_ERRORBAR,       EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_SINGLE, EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_INVISIBLE, false, false, false },
431     { EXC_CHOBJTYPE_CONNECTLINE,    EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_INVISIBLE, false, false, false },
432     { EXC_CHOBJTYPE_HILOLINE,       EXC_CHPROPMODE_LINEARSERIES, EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_INVISIBLE, false, false, false },
433     { EXC_CHOBJTYPE_WHITEDROPBAR,   EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWBACK, EXC_CHFRAMETYPE_INVISIBLE, false, false, true  },
434     { EXC_CHOBJTYPE_BLACKDROPBAR,   EXC_CHPROPMODE_COMMON,       EXC_COLOR_CHWINDOWTEXT, EXC_CHLINEFORMAT_HAIR,   EXC_COLOR_CHWINDOWTEXT, EXC_CHFRAMETYPE_INVISIBLE, false, false, true  }
435 };
436 
437 }
438 
XclChFormatInfoProvider()439 XclChFormatInfoProvider::XclChFormatInfoProvider()
440 {
441     for(auto const &rIt : spFmtInfos)
442         maInfoMap[ rIt.meObjType ] = &rIt;
443 }
444 
GetFormatInfo(XclChObjectType eObjType) const445 const XclChFormatInfo& XclChFormatInfoProvider::GetFormatInfo( XclChObjectType eObjType ) const
446 {
447     XclFmtInfoMap::const_iterator aIt = maInfoMap.find( eObjType );
448     OSL_ENSURE( aIt != maInfoMap.end(), "XclChFormatInfoProvider::GetFormatInfo - unknown object type" );
449     return (aIt == maInfoMap.end()) ? *spFmtInfos : *aIt->second;
450 }
451 
452 // Chart type info provider ===================================================
453 
454 namespace {
455 
456 // chart type service names
457 const sal_Char SERVICE_CHART2_AREA[]      = "com.sun.star.chart2.AreaChartType";
458 const sal_Char SERVICE_CHART2_CANDLE[]    = "com.sun.star.chart2.CandleStickChartType";
459 const sal_Char SERVICE_CHART2_COLUMN[]    = "com.sun.star.chart2.ColumnChartType";
460 const sal_Char SERVICE_CHART2_LINE[]      = "com.sun.star.chart2.LineChartType";
461 const sal_Char SERVICE_CHART2_NET[]       = "com.sun.star.chart2.NetChartType";
462 const sal_Char SERVICE_CHART2_FILLEDNET[] = "com.sun.star.chart2.FilledNetChartType";
463 const sal_Char SERVICE_CHART2_PIE[]       = "com.sun.star.chart2.PieChartType";
464 const sal_Char SERVICE_CHART2_SCATTER[]   = "com.sun.star.chart2.ScatterChartType";
465 const sal_Char SERVICE_CHART2_BUBBLE[]    = "com.sun.star.chart2.BubbleChartType";
466 const sal_Char SERVICE_CHART2_SURFACE[]   = "com.sun.star.chart2.ColumnChartType";    // Todo
467 
468 namespace csscd = css::chart::DataLabelPlacement;
469 
470 static const XclChTypeInfo spTypeInfos[] =
471 {
472     // chart type             chart type category      record id           service                   varied point color     def label pos         comb2d 3d     polar  area2d area3d 1stvis xcateg swap   stack  revers betw
473     { EXC_CHTYPEID_BAR,       EXC_CHTYPECATEG_BAR,     EXC_ID_CHBAR,       SERVICE_CHART2_COLUMN,    EXC_CHVARPOINT_SINGLE, csscd::OUTSIDE,       true,  true,  false, true,  true,  false, true,  false, true,  false, true  },
474     { EXC_CHTYPEID_HORBAR,    EXC_CHTYPECATEG_BAR,     EXC_ID_CHBAR,       SERVICE_CHART2_COLUMN,    EXC_CHVARPOINT_SINGLE, csscd::OUTSIDE,       false, true,  false, true,  true,  false, true,  true,  true,  false, true  },
475     { EXC_CHTYPEID_LINE,      EXC_CHTYPECATEG_LINE,    EXC_ID_CHLINE,      SERVICE_CHART2_LINE,      EXC_CHVARPOINT_SINGLE, csscd::RIGHT,         true,  true,  false, false, true,  false, true,  false, true,  false, false },
476     { EXC_CHTYPEID_AREA,      EXC_CHTYPECATEG_LINE,    EXC_ID_CHAREA,      SERVICE_CHART2_AREA,      EXC_CHVARPOINT_NONE,   csscd::CENTER,        true,  true,  false, true,  true,  false, true,  false, true,  true,  false },
477     { EXC_CHTYPEID_STOCK,     EXC_CHTYPECATEG_LINE,    EXC_ID_CHLINE,      SERVICE_CHART2_CANDLE,    EXC_CHVARPOINT_NONE,   csscd::RIGHT,         true,  false, false, false, false, false, true,  false, true,  false, false },
478     { EXC_CHTYPEID_RADARLINE, EXC_CHTYPECATEG_RADAR,   EXC_ID_CHRADARLINE, SERVICE_CHART2_NET,       EXC_CHVARPOINT_SINGLE, csscd::TOP,           false, false, true,  false, true,  false, true,  false, false, false, false },
479     { EXC_CHTYPEID_RADARAREA, EXC_CHTYPECATEG_RADAR,   EXC_ID_CHRADARAREA, SERVICE_CHART2_FILLEDNET, EXC_CHVARPOINT_NONE,   csscd::TOP,           false, false, true,  true,  true,  false, true,  false, false, true,  false },
480     { EXC_CHTYPEID_PIE,       EXC_CHTYPECATEG_PIE,     EXC_ID_CHPIE,       SERVICE_CHART2_PIE,       EXC_CHVARPOINT_MULTI,  csscd::AVOID_OVERLAP, false, true,  true,  true,  true,  true,  true,  false, false, false, false },
481     { EXC_CHTYPEID_DONUT,     EXC_CHTYPECATEG_PIE,     EXC_ID_CHPIE,       SERVICE_CHART2_PIE,       EXC_CHVARPOINT_MULTI,  csscd::AVOID_OVERLAP, false, true,  true,  true,  true,  false, true,  false, false, false, false },
482     { EXC_CHTYPEID_PIEEXT,    EXC_CHTYPECATEG_PIE,     EXC_ID_CHPIEEXT,    SERVICE_CHART2_PIE,       EXC_CHVARPOINT_MULTI,  csscd::AVOID_OVERLAP, false, false, true,  true,  true,  true,  true,  false, false, false, false },
483     { EXC_CHTYPEID_SCATTER,   EXC_CHTYPECATEG_SCATTER, EXC_ID_CHSCATTER,   SERVICE_CHART2_SCATTER,   EXC_CHVARPOINT_SINGLE, csscd::RIGHT,         true,  false, false, false, true,  false, false, false, false, false, false },
484     { EXC_CHTYPEID_BUBBLES,   EXC_CHTYPECATEG_SCATTER, EXC_ID_CHSCATTER,   SERVICE_CHART2_BUBBLE,    EXC_CHVARPOINT_SINGLE, csscd::RIGHT,         false, false, false, true,  true,  false, false, false, false, false, false },
485     { EXC_CHTYPEID_SURFACE,   EXC_CHTYPECATEG_SURFACE, EXC_ID_CHSURFACE,   SERVICE_CHART2_SURFACE,   EXC_CHVARPOINT_NONE,   csscd::RIGHT,         false, true,  false, true,  true,  false, true,  false, false, false, false },
486     { EXC_CHTYPEID_UNKNOWN,   EXC_CHTYPECATEG_BAR,     EXC_ID_CHBAR,       SERVICE_CHART2_COLUMN,    EXC_CHVARPOINT_SINGLE, csscd::OUTSIDE,       true,  true,  false, true,  true,  false, true,  false, true,  false, true  }
487 };
488 
489 } // namespace
490 
XclChExtTypeInfo(const XclChTypeInfo & rTypeInfo)491 XclChExtTypeInfo::XclChExtTypeInfo( const XclChTypeInfo& rTypeInfo ) :
492     XclChTypeInfo( rTypeInfo ),
493     mb3dChart( false ),
494     mbSpline( false )
495 {
496 }
497 
Set(const XclChTypeInfo & rTypeInfo,bool b3dChart,bool bSpline)498 void XclChExtTypeInfo::Set( const XclChTypeInfo& rTypeInfo, bool b3dChart, bool bSpline )
499 {
500     static_cast< XclChTypeInfo& >( *this ) = rTypeInfo;
501     mb3dChart = mbSupports3d && b3dChart;
502     mbSpline = bSpline;
503 }
504 
XclChTypeInfoProvider()505 XclChTypeInfoProvider::XclChTypeInfoProvider()
506 {
507     for(const auto &rIt : spTypeInfos)
508         maInfoMap[ rIt.meTypeId ] = &rIt;
509 }
510 
GetTypeInfo(XclChTypeId eTypeId) const511 const XclChTypeInfo& XclChTypeInfoProvider::GetTypeInfo( XclChTypeId eTypeId ) const
512 {
513     XclChTypeInfoMap::const_iterator aIt = maInfoMap.find( eTypeId );
514     OSL_ENSURE( aIt != maInfoMap.end(), "XclChTypeInfoProvider::GetTypeInfo - unknown chart type" );
515     return (aIt == maInfoMap.end()) ? *maInfoMap.rbegin()->second : *aIt->second;
516 }
517 
GetTypeInfoFromRecId(sal_uInt16 nRecId) const518 const XclChTypeInfo& XclChTypeInfoProvider::GetTypeInfoFromRecId( sal_uInt16 nRecId ) const
519 {
520     for(const auto &rIt : spTypeInfos)
521     {
522         if(rIt.mnRecId == nRecId)
523             return rIt;
524     }
525     OSL_FAIL( "XclChTypeInfoProvider::GetTypeInfoFromRecId - unknown record id" );
526     return GetTypeInfo( EXC_CHTYPEID_UNKNOWN );
527 }
528 
GetTypeInfoFromService(const OUString & rServiceName) const529 const XclChTypeInfo& XclChTypeInfoProvider::GetTypeInfoFromService( const OUString& rServiceName ) const
530 {
531     for(auto const &rIt : spTypeInfos)
532         if( rServiceName.equalsAscii( rIt.mpcServiceName ) )
533             return rIt;
534     OSL_FAIL( "XclChTypeInfoProvider::GetTypeInfoFromService - unknown service name" );
535     return GetTypeInfo( EXC_CHTYPEID_UNKNOWN );
536 }
537 
538 // Property helpers ===========================================================
539 
XclChObjectTable(uno::Reference<lang::XMultiServiceFactory> const & xFactory,const OUString & rServiceName,const OUString & rObjNameBase)540 XclChObjectTable::XclChObjectTable(uno::Reference<lang::XMultiServiceFactory> const & xFactory,
541         const OUString& rServiceName, const OUString& rObjNameBase ) :
542     mxFactory( xFactory ),
543     maServiceName( rServiceName ),
544     maObjNameBase( rObjNameBase ),
545     mnIndex( 0 )
546 {
547 }
548 
GetObject(const OUString & rObjName)549 uno::Any XclChObjectTable::GetObject( const OUString& rObjName )
550 {
551     // get object table
552     if( !mxContainer.is() )
553         mxContainer.set(ScfApiHelper::CreateInstance( mxFactory, maServiceName ), uno::UNO_QUERY);
554     OSL_ENSURE( mxContainer.is(), "XclChObjectTable::GetObject - container not found" );
555 
556     uno::Any aObj;
557     if( mxContainer.is() )
558     {
559         // get object from container
560         try
561         {
562             aObj = mxContainer->getByName( rObjName );
563         }
564         catch (uno::Exception &)
565         {
566             OSL_FAIL( "XclChObjectTable::GetObject - object not found" );
567         }
568     }
569     return aObj;
570 }
571 
InsertObject(const uno::Any & rObj)572 OUString XclChObjectTable::InsertObject(const uno::Any& rObj)
573 {
574 
575     // create object table
576     if( !mxContainer.is() )
577         mxContainer.set(ScfApiHelper::CreateInstance( mxFactory, maServiceName ), uno::UNO_QUERY);
578     OSL_ENSURE( mxContainer.is(), "XclChObjectTable::InsertObject - container not found" );
579 
580     OUString aObjName;
581     if( mxContainer.is() )
582     {
583         // create new unused identifier
584         do
585         {
586             aObjName = maObjNameBase + OUString::number( ++mnIndex );
587         }
588         while( mxContainer->hasByName( aObjName ) );
589 
590         // insert object
591         try
592         {
593             mxContainer->insertByName( aObjName, rObj );
594         }
595         catch (uno::Exception &)
596         {
597             OSL_FAIL( "XclChObjectTable::InsertObject - cannot insert object" );
598             aObjName.clear();
599         }
600     }
601     return aObjName;
602 }
603 
604 // Property names -------------------------------------------------------------
605 
606 namespace {
607 
608 /** Property names for line style in common objects. */
609 const sal_Char* const sppcLineNamesCommon[] =
610     { "LineStyle", "LineWidth", "LineColor", "LineTransparence", "LineDashName", nullptr };
611 /** Property names for line style in linear series objects. */
612 const sal_Char* const sppcLineNamesLinear[] =
613     { "LineStyle", "LineWidth", "Color", "Transparency", "LineDashName", nullptr };
614 /** Property names for line style in filled series objects. */
615 const sal_Char* const sppcLineNamesFilled[] =
616     { "BorderStyle", "BorderWidth", "BorderColor", "BorderTransparency", "BorderDashName", nullptr };
617 
618 /** Property names for solid area style in common objects. */
619 const sal_Char* const sppcAreaNamesCommon[] = { "FillStyle", "FillColor", "FillTransparence", nullptr };
620 /** Property names for solid area style in filled series objects. */
621 const sal_Char* const sppcAreaNamesFilled[] = { "FillStyle", "Color", "Transparency", nullptr };
622 /** Property names for gradient area style in common objects. */
623 const sal_Char* const sppcGradNamesCommon[] = {  "FillStyle", "FillGradientName", nullptr };
624 /** Property names for gradient area style in filled series objects. */
625 const sal_Char* const sppcGradNamesFilled[] = {  "FillStyle", "GradientName", nullptr };
626 /** Property names for hatch area style in common objects. */
627 const sal_Char* const sppcHatchNamesCommon[] = { "FillStyle", "FillHatchName", "FillColor", "FillBackground", nullptr };
628 /** Property names for hatch area style in filled series objects. */
629 const sal_Char* const sppcHatchNamesFilled[] = { "FillStyle", "HatchName", "Color", "FillBackground", nullptr };
630 /** Property names for bitmap area style. */
631 const sal_Char* const sppcBitmapNames[] = { "FillStyle", "FillBitmapName", "FillBitmapMode", nullptr };
632 
633 } // namespace
634 
XclChPropSetHelper()635 XclChPropSetHelper::XclChPropSetHelper() :
636     maLineHlpCommon( sppcLineNamesCommon ),
637     maLineHlpLinear( sppcLineNamesLinear ),
638     maLineHlpFilled( sppcLineNamesFilled ),
639     maAreaHlpCommon( sppcAreaNamesCommon ),
640     maAreaHlpFilled( sppcAreaNamesFilled ),
641     maGradHlpCommon( sppcGradNamesCommon ),
642     maGradHlpFilled( sppcGradNamesFilled ),
643     maHatchHlpCommon( sppcHatchNamesCommon ),
644     maHatchHlpFilled( sppcHatchNamesFilled ),
645     maBitmapHlp( sppcBitmapNames )
646 {
647 }
648 
649 // read properties ------------------------------------------------------------
650 
ReadLineProperties(XclChLineFormat & rLineFmt,XclChObjectTable & rDashTable,const ScfPropertySet & rPropSet,XclChPropertyMode ePropMode)651 void XclChPropSetHelper::ReadLineProperties(
652         XclChLineFormat& rLineFmt, XclChObjectTable& rDashTable,
653         const ScfPropertySet& rPropSet, XclChPropertyMode ePropMode )
654 {
655     // read properties from property set
656     drawing::LineStyle eApiStyle = drawing::LineStyle_NONE;
657     sal_Int32 nApiWidth = 0;
658     sal_Int16 nApiTrans = 0;
659     uno::Any aDashNameAny;
660 
661     ScfPropSetHelper& rLineHlp = GetLineHelper( ePropMode );
662     rLineHlp.ReadFromPropertySet( rPropSet );
663     rLineHlp >> eApiStyle >> nApiWidth >> rLineFmt.maColor >> nApiTrans >> aDashNameAny;
664 
665     // clear automatic flag
666     ::set_flag( rLineFmt.mnFlags, EXC_CHLINEFORMAT_AUTO, false );
667 
668     // line width
669     if( nApiWidth <= 0 )        rLineFmt.mnWeight = EXC_CHLINEFORMAT_HAIR;
670     else if( nApiWidth <= 35 )  rLineFmt.mnWeight = EXC_CHLINEFORMAT_SINGLE;
671     else if( nApiWidth <= 70 )  rLineFmt.mnWeight = EXC_CHLINEFORMAT_DOUBLE;
672     else                        rLineFmt.mnWeight = EXC_CHLINEFORMAT_TRIPLE;
673 
674     // line style
675     switch( eApiStyle )
676     {
677         case drawing::LineStyle_NONE:
678             rLineFmt.mnPattern = EXC_CHLINEFORMAT_NONE;
679         break;
680         case drawing::LineStyle_SOLID:
681         {
682             if( nApiTrans < 13 )        rLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;
683             else if( nApiTrans < 38 )   rLineFmt.mnPattern = EXC_CHLINEFORMAT_DARKTRANS;
684             else if( nApiTrans < 63 )   rLineFmt.mnPattern = EXC_CHLINEFORMAT_MEDTRANS;
685             else if( nApiTrans < 100 )  rLineFmt.mnPattern = EXC_CHLINEFORMAT_LIGHTTRANS;
686             else                        rLineFmt.mnPattern = EXC_CHLINEFORMAT_NONE;
687         }
688         break;
689         case drawing::LineStyle_DASH:
690         {
691             rLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;
692             OUString aDashName;
693             drawing::LineDash aApiDash;
694             if( (aDashNameAny >>= aDashName) && (rDashTable.GetObject( aDashName ) >>= aApiDash) )
695             {
696                 // reorder dashes that are shorter than dots
697                 if( (aApiDash.Dashes == 0) || (aApiDash.DashLen < aApiDash.DotLen) )
698                 {
699                     ::std::swap( aApiDash.Dashes, aApiDash.Dots );
700                     ::std::swap( aApiDash.DashLen, aApiDash.DotLen );
701                 }
702                 // ignore dots that are nearly equal to dashes
703                 if( aApiDash.DotLen * 3 > aApiDash.DashLen * 2 )
704                     aApiDash.Dots = 0;
705 
706                 // convert line dash to predefined Excel dash types
707                 if( (aApiDash.Dashes == 1) && (aApiDash.Dots >= 1) )
708                     // one dash and one or more dots
709                     rLineFmt.mnPattern = (aApiDash.Dots == 1) ?
710                         EXC_CHLINEFORMAT_DASHDOT : EXC_CHLINEFORMAT_DASHDOTDOT;
711                 else if( aApiDash.Dashes >= 1 )
712                     // one or more dashes and no dots (also: dash-dash-dot)
713                     rLineFmt.mnPattern = (aApiDash.DashLen < 250) ?
714                         EXC_CHLINEFORMAT_DOT : EXC_CHLINEFORMAT_DASH;
715             }
716         }
717         break;
718         default:
719             OSL_FAIL( "XclChPropSetHelper::ReadLineProperties - unknown line style" );
720             rLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;
721     }
722 }
723 
ReadAreaProperties(XclChAreaFormat & rAreaFmt,const ScfPropertySet & rPropSet,XclChPropertyMode ePropMode)724 bool XclChPropSetHelper::ReadAreaProperties( XclChAreaFormat& rAreaFmt,
725         const ScfPropertySet& rPropSet, XclChPropertyMode ePropMode )
726 {
727     // read properties from property set
728     drawing::FillStyle eApiStyle = drawing::FillStyle_NONE;
729     sal_Int16 nTransparency = 0;
730 
731     ScfPropSetHelper& rAreaHlp = GetAreaHelper( ePropMode );
732     rAreaHlp.ReadFromPropertySet( rPropSet );
733     rAreaHlp >> eApiStyle >> rAreaFmt.maPattColor >> nTransparency;
734 
735     // clear automatic flag
736     ::set_flag( rAreaFmt.mnFlags, EXC_CHAREAFORMAT_AUTO, false );
737 
738     // set fill style transparent or solid (set solid for anything but transparent)
739     rAreaFmt.mnPattern = (eApiStyle == drawing::FillStyle_NONE) ? EXC_PATT_NONE : EXC_PATT_SOLID;
740 
741     // return true to indicate complex fill (gradient, bitmap, solid transparency)
742     return (eApiStyle != drawing::FillStyle_NONE) && ((eApiStyle != drawing::FillStyle_SOLID) || (nTransparency > 0));
743 }
744 
ReadEscherProperties(XclChEscherFormat & rEscherFmt,XclChPicFormat & rPicFmt,XclChObjectTable & rGradientTable,XclChObjectTable & rHatchTable,XclChObjectTable & rBitmapTable,const ScfPropertySet & rPropSet,XclChPropertyMode ePropMode)745 void XclChPropSetHelper::ReadEscherProperties(
746         XclChEscherFormat& rEscherFmt, XclChPicFormat& rPicFmt,
747         XclChObjectTable& rGradientTable, XclChObjectTable& rHatchTable, XclChObjectTable& rBitmapTable,
748         const ScfPropertySet& rPropSet, XclChPropertyMode ePropMode )
749 {
750     // read style and transparency properties from property set
751     drawing::FillStyle eApiStyle = drawing::FillStyle_NONE;
752     Color aColor;
753     sal_Int16 nTransparency = 0;
754 
755     ScfPropSetHelper& rAreaHlp = GetAreaHelper( ePropMode );
756     rAreaHlp.ReadFromPropertySet( rPropSet );
757     rAreaHlp >> eApiStyle >> aColor >> nTransparency;
758 
759     switch( eApiStyle )
760     {
761         case drawing::FillStyle_SOLID:
762         {
763             OSL_ENSURE( nTransparency > 0, "XclChPropSetHelper::ReadEscherProperties - unexpected solid area without transparency" );
764             if( (0 < nTransparency) && (nTransparency <= 100) )
765             {
766                 // convert to Escher properties
767                 sal_uInt32 nEscherColor = 0x02000000;
768                 ::insert_value( nEscherColor, aColor.GetBlue(), 16, 8 );
769                 ::insert_value( nEscherColor, aColor.GetGreen(), 8, 8 );
770                 ::insert_value( nEscherColor, aColor.GetRed(), 0, 8 );
771                 sal_uInt32 nEscherOpacity = static_cast< sal_uInt32 >( (100 - nTransparency) * 655.36 );
772                 rEscherFmt.mxEscherSet.reset( new EscherPropertyContainer );
773                 rEscherFmt.mxEscherSet->AddOpt( ESCHER_Prop_fillType, ESCHER_FillSolid );
774                 rEscherFmt.mxEscherSet->AddOpt( ESCHER_Prop_fillColor, nEscherColor );
775                 rEscherFmt.mxEscherSet->AddOpt( ESCHER_Prop_fillOpacity, nEscherOpacity );
776                 rEscherFmt.mxEscherSet->AddOpt( ESCHER_Prop_fillBackColor, 0x02FFFFFF );
777                 rEscherFmt.mxEscherSet->AddOpt( ESCHER_Prop_fillBackOpacity, 0x00010000 );
778                 rEscherFmt.mxEscherSet->AddOpt( ESCHER_Prop_fNoFillHitTest, 0x001F001C );
779             }
780         }
781         break;
782         case drawing::FillStyle_GRADIENT:
783         {
784             // extract gradient from global gradient table
785             OUString aGradientName;
786             ScfPropSetHelper& rGradHlp = GetGradientHelper( ePropMode );
787             rGradHlp.ReadFromPropertySet( rPropSet );
788             rGradHlp >> eApiStyle >> aGradientName;
789             awt::Gradient aGradient;
790             if( rGradientTable.GetObject( aGradientName ) >>= aGradient )
791             {
792                 // convert to Escher properties
793                 rEscherFmt.mxEscherSet.reset( new EscherPropertyContainer );
794                 rEscherFmt.mxEscherSet->CreateGradientProperties( aGradient );
795             }
796         }
797         break;
798         case drawing::FillStyle_HATCH:
799         {
800             // extract hatch from global hatch table
801             OUString aHatchName;
802             bool bFillBackground;
803             ScfPropSetHelper& rHatchHlp = GetHatchHelper( ePropMode );
804             rHatchHlp.ReadFromPropertySet( rPropSet );
805             rHatchHlp >> eApiStyle >> aHatchName >> aColor >> bFillBackground;
806             drawing::Hatch aHatch;
807             if( rHatchTable.GetObject( aHatchName ) >>= aHatch )
808             {
809                 // convert to Escher properties
810                 rEscherFmt.mxEscherSet.reset( new EscherPropertyContainer );
811                 rEscherFmt.mxEscherSet->CreateEmbeddedHatchProperties( aHatch, aColor, bFillBackground );
812                 rPicFmt.mnBmpMode = EXC_CHPICFORMAT_STACK;
813             }
814         }
815         break;
816         case drawing::FillStyle_BITMAP:
817         {
818             // extract bitmap URL from global bitmap table
819             OUString aBitmapName;
820             drawing::BitmapMode eApiBmpMode;
821             maBitmapHlp.ReadFromPropertySet( rPropSet );
822             maBitmapHlp >> eApiStyle >> aBitmapName >> eApiBmpMode;
823             uno::Reference<awt::XBitmap> xBitmap;
824             if (rBitmapTable.GetObject( aBitmapName ) >>= xBitmap)
825             {
826                 // convert to Escher properties
827                 rEscherFmt.mxEscherSet.reset( new EscherPropertyContainer );
828                 rEscherFmt.mxEscherSet->CreateEmbeddedBitmapProperties( xBitmap, eApiBmpMode );
829                 rPicFmt.mnBmpMode = (eApiBmpMode == drawing::BitmapMode_REPEAT) ?
830                     EXC_CHPICFORMAT_STACK : EXC_CHPICFORMAT_STRETCH;
831             }
832         }
833         break;
834         default:
835             OSL_FAIL( "XclChPropSetHelper::ReadEscherProperties - unknown fill style" );
836     }
837 }
838 
ReadMarkerProperties(XclChMarkerFormat & rMarkerFmt,const ScfPropertySet & rPropSet,sal_uInt16 nFormatIdx)839 void XclChPropSetHelper::ReadMarkerProperties(
840         XclChMarkerFormat& rMarkerFmt, const ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx )
841 {
842     chart2::Symbol aApiSymbol;
843     if( rPropSet.GetProperty( aApiSymbol, EXC_CHPROP_SYMBOL ) )
844     {
845         // clear automatic flag
846         ::set_flag( rMarkerFmt.mnFlags, EXC_CHMARKERFORMAT_AUTO, false );
847 
848         // symbol style
849         switch( aApiSymbol.Style )
850         {
851             case chart2::SymbolStyle_NONE:
852                 rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_NOSYMBOL;
853             break;
854             case chart2::SymbolStyle_STANDARD:
855                 switch( aApiSymbol.StandardSymbol )
856                 {
857                     case 0:     rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_SQUARE;    break;  // square
858                     case 1:     rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_DIAMOND;   break;  // diamond
859                     case 2:     rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_STDDEV;    break;  // arrow down
860                     case 3:     rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_TRIANGLE;  break;  // arrow up
861                     case 4:     rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_DOWJ;      break;  // arrow right, same as import
862                     case 5:     rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_PLUS;      break;  // arrow left
863                     case 6:     rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_CROSS;     break;  // bow tie
864                     case 7:     rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_STAR;      break;  // sand glass
865                     case 8:     rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_CIRCLE;    break;  // circle new in LibO3.5
866                     case 9:     rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_DIAMOND;   break;  // star new in LibO3.5
867                     case 10:    rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_CROSS;     break;  // X new in LibO3.5
868                     case 11:    rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_PLUS;      break;  // plus new in LibO3.5
869                     case 12:    rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_STAR;      break;  // asterisk new in LibO3.5
870                     case 13:    rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_STDDEV;    break;  // horizontal bar new in LibO3.5
871                     case 14:    rMarkerFmt.mnMarkerType = EXC_CHMARKERFORMAT_STAR;      break;  // vertical bar new in LibO3.5
872                     default:    rMarkerFmt.mnMarkerType = XclChartHelper::GetAutoMarkerType( nFormatIdx );
873                 }
874             break;
875             default:
876                 rMarkerFmt.mnMarkerType = XclChartHelper::GetAutoMarkerType( nFormatIdx );
877         }
878         bool bHasFillColor = XclChartHelper::HasMarkerFillColor( rMarkerFmt.mnMarkerType );
879         ::set_flag( rMarkerFmt.mnFlags, EXC_CHMARKERFORMAT_NOFILL, !bHasFillColor );
880 
881         // symbol size
882         sal_Int32 nApiSize = (aApiSymbol.Size.Width + aApiSymbol.Size.Height + 1) / 2;
883         rMarkerFmt.mnMarkerSize = XclTools::GetTwipsFromHmm( nApiSize );
884 
885         // symbol colors
886         rMarkerFmt.maLineColor = Color( aApiSymbol.BorderColor );
887         rMarkerFmt.maFillColor = Color( aApiSymbol.FillColor );
888     }
889 }
890 
ReadRotationProperties(const ScfPropertySet & rPropSet,bool bSupportsStacked)891 sal_uInt16 XclChPropSetHelper::ReadRotationProperties( const ScfPropertySet& rPropSet, bool bSupportsStacked )
892 {
893     // chart2 handles rotation as double in the range [0,360)
894     double fAngle = 0.0;
895     rPropSet.GetProperty( fAngle, EXC_CHPROP_TEXTROTATION );
896     bool bStacked = bSupportsStacked && rPropSet.GetBoolProperty( EXC_CHPROP_STACKCHARACTERS );
897     return bStacked ? EXC_ROT_STACKED :
898         XclTools::GetXclRotation( static_cast< sal_Int32 >( fAngle * 100.0 + 0.5 ) );
899 }
900 
901 // write properties -----------------------------------------------------------
902 
WriteLineProperties(ScfPropertySet & rPropSet,XclChObjectTable & rDashTable,const XclChLineFormat & rLineFmt,XclChPropertyMode ePropMode)903 void XclChPropSetHelper::WriteLineProperties(
904         ScfPropertySet& rPropSet, XclChObjectTable& rDashTable,
905         const XclChLineFormat& rLineFmt, XclChPropertyMode ePropMode )
906 {
907     // line width
908     sal_Int32 nApiWidth = 0;    // 0 is the width of a hair line
909     switch( rLineFmt.mnWeight )
910     {
911         case EXC_CHLINEFORMAT_SINGLE:   nApiWidth = 35;     break;
912         case EXC_CHLINEFORMAT_DOUBLE:   nApiWidth = 70;     break;
913         case EXC_CHLINEFORMAT_TRIPLE:   nApiWidth = 105;    break;
914     }
915 
916     // line style
917     drawing::LineStyle eApiStyle = drawing::LineStyle_NONE;
918     sal_Int16 nApiTrans = 0;
919     sal_Int32 nDotLen = ::std::min< sal_Int32 >( rLineFmt.mnWeight + 105, 210 );
920     drawing::LineDash aApiDash( drawing::DashStyle_RECT, 0, nDotLen, 0, 4 * nDotLen, nDotLen );
921 
922     switch( rLineFmt.mnPattern )
923     {
924         case EXC_CHLINEFORMAT_SOLID:
925             eApiStyle = drawing::LineStyle_SOLID;
926         break;
927         case EXC_CHLINEFORMAT_DARKTRANS:
928             eApiStyle = drawing::LineStyle_SOLID; nApiTrans = 25;
929         break;
930         case EXC_CHLINEFORMAT_MEDTRANS:
931             eApiStyle = drawing::LineStyle_SOLID; nApiTrans = 50;
932         break;
933         case EXC_CHLINEFORMAT_LIGHTTRANS:
934             eApiStyle = drawing::LineStyle_SOLID; nApiTrans = 75;
935         break;
936         case EXC_CHLINEFORMAT_DASH:
937             eApiStyle = drawing::LineStyle_DASH; aApiDash.Dashes = 1;
938         break;
939         case EXC_CHLINEFORMAT_DOT:
940             eApiStyle = drawing::LineStyle_DASH; aApiDash.Dots = 1;
941         break;
942         case EXC_CHLINEFORMAT_DASHDOT:
943             eApiStyle = drawing::LineStyle_DASH; aApiDash.Dashes = aApiDash.Dots = 1;
944         break;
945         case EXC_CHLINEFORMAT_DASHDOTDOT:
946             eApiStyle = drawing::LineStyle_DASH; aApiDash.Dashes = 1; aApiDash.Dots = 2;
947         break;
948     }
949 
950     // line color
951     sal_Int32 nApiColor = sal_Int32( rLineFmt.maColor );
952 
953     // try to insert the dash style and receive its name
954     uno::Any aDashNameAny;
955     if( eApiStyle == drawing::LineStyle_DASH )
956     {
957         OUString aDashName = rDashTable.InsertObject( uno::makeAny( aApiDash ) );
958         if( !aDashName.isEmpty() )
959             aDashNameAny <<= aDashName;
960     }
961 
962     // write the properties
963     ScfPropSetHelper& rLineHlp = GetLineHelper( ePropMode );
964     rLineHlp.InitializeWrite();
965     rLineHlp << eApiStyle << nApiWidth << nApiColor << nApiTrans << aDashNameAny;
966     rLineHlp.WriteToPropertySet( rPropSet );
967 }
968 
WriteAreaProperties(ScfPropertySet & rPropSet,const XclChAreaFormat & rAreaFmt,XclChPropertyMode ePropMode)969 void XclChPropSetHelper::WriteAreaProperties( ScfPropertySet& rPropSet,
970         const XclChAreaFormat& rAreaFmt, XclChPropertyMode ePropMode )
971 {
972     drawing::FillStyle eFillStyle = drawing::FillStyle_NONE;
973     Color aColor;
974 
975     // fill color
976     if( rAreaFmt.mnPattern != EXC_PATT_NONE )
977     {
978         eFillStyle = drawing::FillStyle_SOLID;
979         aColor = XclTools::GetPatternColor( rAreaFmt.maPattColor, rAreaFmt.maBackColor, rAreaFmt.mnPattern );
980     }
981 
982     // write the properties
983     ScfPropSetHelper& rAreaHlp = GetAreaHelper( ePropMode );
984     rAreaHlp.InitializeWrite();
985     rAreaHlp << eFillStyle << aColor << sal_Int16(0)/*nTransparency*/;
986     rAreaHlp.WriteToPropertySet( rPropSet );
987 }
988 
WriteEscherProperties(ScfPropertySet & rPropSet,XclChObjectTable & rGradientTable,XclChObjectTable & rBitmapTable,const XclChEscherFormat & rEscherFmt,const XclChPicFormat * pPicFmt,sal_uInt32 nDffFillType,XclChPropertyMode ePropMode)989 void XclChPropSetHelper::WriteEscherProperties( ScfPropertySet& rPropSet,
990         XclChObjectTable& rGradientTable, XclChObjectTable& rBitmapTable,
991         const XclChEscherFormat& rEscherFmt, const XclChPicFormat* pPicFmt,
992         sal_uInt32 nDffFillType, XclChPropertyMode ePropMode )
993 {
994     if( rEscherFmt.mxItemSet )
995     {
996         if( const XFillStyleItem* pStyleItem = rEscherFmt.mxItemSet->GetItem<XFillStyleItem>( XATTR_FILLSTYLE, false ) )
997         {
998             switch( pStyleItem->GetValue() )
999             {
1000                 case drawing::FillStyle_SOLID:
1001                     // #i84812# Excel 2007 writes Escher properties for solid fill
1002                     if( const XFillColorItem* pColorItem = rEscherFmt.mxItemSet->GetItem<XFillColorItem>( XATTR_FILLCOLOR, false ) )
1003                     {
1004                         // get solid transparence too
1005                         const XFillTransparenceItem* pTranspItem = rEscherFmt.mxItemSet->GetItem<XFillTransparenceItem>( XATTR_FILLTRANSPARENCE, false );
1006                         sal_uInt16 nTransp = pTranspItem ? pTranspItem->GetValue() : 0;
1007                         ScfPropSetHelper& rAreaHlp = GetAreaHelper( ePropMode );
1008                         rAreaHlp.InitializeWrite();
1009                         rAreaHlp << drawing::FillStyle_SOLID << pColorItem->GetColorValue() << static_cast< sal_Int16 >( nTransp );
1010                         rAreaHlp.WriteToPropertySet( rPropSet );
1011                     }
1012                 break;
1013                 case drawing::FillStyle_GRADIENT:
1014                     if( const XFillGradientItem* pGradItem = rEscherFmt.mxItemSet->GetItem<XFillGradientItem>( XATTR_FILLGRADIENT, false ) )
1015                     {
1016                         uno::Any aGradientAny;
1017                         if( pGradItem->QueryValue( aGradientAny, MID_FILLGRADIENT ) )
1018                         {
1019                             OUString aGradName = rGradientTable.InsertObject( aGradientAny );
1020                             if( !aGradName.isEmpty() )
1021                             {
1022                                 ScfPropSetHelper& rGradHlp = GetGradientHelper( ePropMode );
1023                                 rGradHlp.InitializeWrite();
1024                                 rGradHlp << drawing::FillStyle_GRADIENT << aGradName;
1025                                 rGradHlp.WriteToPropertySet( rPropSet );
1026                             }
1027                         }
1028                     }
1029                 break;
1030                 case drawing::FillStyle_BITMAP:
1031                     if( const XFillBitmapItem* pBmpItem = rEscherFmt.mxItemSet->GetItem<XFillBitmapItem>( XATTR_FILLBITMAP, false ) )
1032                     {
1033                         uno::Any aBitmapAny;
1034                         if (pBmpItem->QueryValue(aBitmapAny, MID_BITMAP))
1035                         {
1036                             OUString aBmpName = rBitmapTable.InsertObject( aBitmapAny );
1037                             if( !aBmpName.isEmpty() )
1038                             {
1039                                 /*  #i71810# Caller decides whether to use a CHPICFORMAT record for bitmap mode.
1040                                     If not passed, detect fill mode from the DFF property 'fill-type'. */
1041                                 bool bStretch = pPicFmt ? (pPicFmt->mnBmpMode == EXC_CHPICFORMAT_STRETCH) : (nDffFillType == mso_fillPicture);
1042                                 drawing::BitmapMode eApiBmpMode = bStretch ? drawing::BitmapMode_STRETCH : drawing::BitmapMode_REPEAT;
1043                                 maBitmapHlp.InitializeWrite();
1044                                 maBitmapHlp << drawing::FillStyle_BITMAP << aBmpName << eApiBmpMode;
1045                                 maBitmapHlp.WriteToPropertySet( rPropSet );
1046                             }
1047                         }
1048                     }
1049                 break;
1050                 default:
1051                     OSL_FAIL( "XclChPropSetHelper::WriteEscherProperties - unknown fill mode" );
1052             }
1053         }
1054     }
1055 }
1056 
WriteMarkerProperties(ScfPropertySet & rPropSet,const XclChMarkerFormat & rMarkerFmt)1057 void XclChPropSetHelper::WriteMarkerProperties(
1058         ScfPropertySet& rPropSet, const XclChMarkerFormat& rMarkerFmt )
1059 {
1060     // symbol style
1061     chart2::Symbol aApiSymbol;
1062     aApiSymbol.Style = chart2::SymbolStyle_STANDARD;
1063     switch( rMarkerFmt.mnMarkerType )
1064     {
1065         case EXC_CHMARKERFORMAT_NOSYMBOL:   aApiSymbol.Style = chart2::SymbolStyle_NONE;  break;
1066         case EXC_CHMARKERFORMAT_SQUARE:     aApiSymbol.StandardSymbol = 0;              break;  // square
1067         case EXC_CHMARKERFORMAT_DIAMOND:    aApiSymbol.StandardSymbol = 1;              break;  // diamond
1068         case EXC_CHMARKERFORMAT_TRIANGLE:   aApiSymbol.StandardSymbol = 3;              break;  // arrow up
1069         case EXC_CHMARKERFORMAT_CROSS:      aApiSymbol.StandardSymbol = 10;             break;  // X, legacy bow tie
1070         case EXC_CHMARKERFORMAT_STAR:       aApiSymbol.StandardSymbol = 12;             break;  // asterisk, legacy sand glass
1071         case EXC_CHMARKERFORMAT_DOWJ:       aApiSymbol.StandardSymbol = 4;              break;  // arrow right, same as export
1072         case EXC_CHMARKERFORMAT_STDDEV:     aApiSymbol.StandardSymbol = 13;             break;  // horizontal bar, legacy arrow down
1073         case EXC_CHMARKERFORMAT_CIRCLE:     aApiSymbol.StandardSymbol = 8;              break;  // circle, legacy arrow right
1074         case EXC_CHMARKERFORMAT_PLUS:       aApiSymbol.StandardSymbol = 11;             break;  // plus, legacy arrow left
1075         default: break;
1076     }
1077 
1078     // symbol size
1079     sal_Int32 nApiSize = XclTools::GetHmmFromTwips( rMarkerFmt.mnMarkerSize );
1080     aApiSymbol.Size = awt::Size( nApiSize, nApiSize );
1081 
1082     // symbol colors
1083     aApiSymbol.FillColor = sal_Int32( rMarkerFmt.maFillColor );
1084     aApiSymbol.BorderColor = ::get_flag( rMarkerFmt.mnFlags, EXC_CHMARKERFORMAT_NOLINE ) ?
1085         aApiSymbol.FillColor : sal_Int32( rMarkerFmt.maLineColor );
1086 
1087     // set the property
1088     rPropSet.SetProperty( EXC_CHPROP_SYMBOL, aApiSymbol );
1089 }
1090 
WriteRotationProperties(ScfPropertySet & rPropSet,sal_uInt16 nRotation,bool bSupportsStacked)1091 void XclChPropSetHelper::WriteRotationProperties(
1092         ScfPropertySet& rPropSet, sal_uInt16 nRotation, bool bSupportsStacked )
1093 {
1094     if( nRotation != EXC_CHART_AUTOROTATION )
1095     {
1096         // chart2 handles rotation as double in the range [0,360)
1097         double fAngle = XclTools::GetScRotation( nRotation, 0 ) / 100.0;
1098         rPropSet.SetProperty( EXC_CHPROP_TEXTROTATION, fAngle );
1099         if( bSupportsStacked )
1100             rPropSet.SetProperty( EXC_CHPROP_STACKCHARACTERS, nRotation == EXC_ROT_STACKED );
1101     }
1102 }
1103 
1104 // private --------------------------------------------------------------------
1105 
GetLineHelper(XclChPropertyMode ePropMode)1106 ScfPropSetHelper& XclChPropSetHelper::GetLineHelper( XclChPropertyMode ePropMode )
1107 {
1108     switch( ePropMode )
1109     {
1110         case EXC_CHPROPMODE_COMMON:         return maLineHlpCommon;
1111         case EXC_CHPROPMODE_LINEARSERIES:   return maLineHlpLinear;
1112         case EXC_CHPROPMODE_FILLEDSERIES:   return maLineHlpFilled;
1113         default: OSL_FAIL( "XclChPropSetHelper::GetLineHelper - unknown property mode" );
1114     }
1115     return maLineHlpCommon;
1116 }
1117 
GetAreaHelper(XclChPropertyMode ePropMode)1118 ScfPropSetHelper& XclChPropSetHelper::GetAreaHelper( XclChPropertyMode ePropMode )
1119 {
1120     switch( ePropMode )
1121     {
1122         case EXC_CHPROPMODE_COMMON:         return maAreaHlpCommon;
1123         case EXC_CHPROPMODE_FILLEDSERIES:   return maAreaHlpFilled;
1124         default:    OSL_FAIL( "XclChPropSetHelper::GetAreaHelper - unknown property mode" );
1125     }
1126     return maAreaHlpCommon;
1127 }
1128 
GetGradientHelper(XclChPropertyMode ePropMode)1129 ScfPropSetHelper& XclChPropSetHelper::GetGradientHelper( XclChPropertyMode ePropMode )
1130 {
1131     switch( ePropMode )
1132     {
1133         case EXC_CHPROPMODE_COMMON:         return maGradHlpCommon;
1134         case EXC_CHPROPMODE_FILLEDSERIES:   return maGradHlpFilled;
1135         default:    OSL_FAIL( "XclChPropSetHelper::GetGradientHelper - unknown property mode" );
1136     }
1137     return maGradHlpCommon;
1138 }
1139 
GetHatchHelper(XclChPropertyMode ePropMode)1140 ScfPropSetHelper& XclChPropSetHelper::GetHatchHelper( XclChPropertyMode ePropMode )
1141 {
1142     switch( ePropMode )
1143     {
1144         case EXC_CHPROPMODE_COMMON:         return maHatchHlpCommon;
1145         case EXC_CHPROPMODE_FILLEDSERIES:   return maHatchHlpFilled;
1146         default:    OSL_FAIL( "XclChPropSetHelper::GetHatchHelper - unknown property mode" );
1147     }
1148     return maHatchHlpCommon;
1149 }
1150 
1151 namespace {
1152 
1153 /*  The following local functions implement getting the XShape interface of all
1154     supported title objects (chart and axes). This needs some effort due to the
1155     design of the old Chart1 API used to access these objects. */
1156 
1157 /** Returns the drawing shape of the main title, if existing. */
lclGetMainTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc)1158 uno::Reference<drawing::XShape> lclGetMainTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc)
1159 {
1160     ScfPropertySet aPropSet(rxChart1Doc);
1161     if (rxChart1Doc.is() && aPropSet.GetBoolProperty("HasMainTitle"))
1162         return rxChart1Doc->getTitle();
1163     return uno::Reference<drawing::XShape>();
1164 }
1165 
lclGetXAxisTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc)1166 uno::Reference<drawing::XShape> lclGetXAxisTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc)
1167 {
1168     uno::Reference<chart::XAxisXSupplier> xAxisSupp(rxChart1Doc->getDiagram(), uno::UNO_QUERY);
1169     ScfPropertySet aPropSet(xAxisSupp);
1170     if (xAxisSupp.is() && aPropSet.GetBoolProperty("HasXAxisTitle"))
1171         return xAxisSupp->getXAxisTitle();
1172     return uno::Reference<drawing::XShape>();
1173 }
1174 
lclGetYAxisTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc)1175 uno::Reference<drawing::XShape> lclGetYAxisTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc )
1176 {
1177     uno::Reference<chart::XAxisYSupplier> xAxisSupp(rxChart1Doc->getDiagram(), uno::UNO_QUERY);
1178     ScfPropertySet aPropSet(xAxisSupp);
1179     if (xAxisSupp.is() && aPropSet.GetBoolProperty("HasYAxisTitle"))
1180         return xAxisSupp->getYAxisTitle();
1181     return uno::Reference<drawing::XShape>();
1182 }
1183 
lclGetZAxisTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc)1184 uno::Reference<drawing::XShape> lclGetZAxisTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc )
1185 {
1186     uno::Reference<chart::XAxisZSupplier> xAxisSupp(rxChart1Doc->getDiagram(), uno::UNO_QUERY);
1187     ScfPropertySet aPropSet(xAxisSupp);
1188     if (xAxisSupp.is() && aPropSet.GetBoolProperty("HasZAxisTitle"))
1189         return xAxisSupp->getZAxisTitle();
1190     return uno::Reference<drawing::XShape>();
1191 }
1192 
lclGetSecXAxisTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc)1193 uno::Reference<drawing::XShape> lclGetSecXAxisTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc)
1194 {
1195     uno::Reference<chart::XSecondAxisTitleSupplier> xAxisSupp(rxChart1Doc->getDiagram(), uno::UNO_QUERY);
1196     ScfPropertySet aPropSet(xAxisSupp);
1197     if (xAxisSupp.is() && aPropSet.GetBoolProperty("HasSecondaryXAxisTitle"))
1198         return xAxisSupp->getSecondXAxisTitle();
1199     return uno::Reference<drawing::XShape>();
1200 }
1201 
lclGetSecYAxisTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc)1202 uno::Reference<drawing::XShape> lclGetSecYAxisTitleShape(const uno::Reference<chart::XChartDocument> & rxChart1Doc)
1203 {
1204     uno::Reference<chart::XSecondAxisTitleSupplier> xAxisSupp(rxChart1Doc->getDiagram(), uno::UNO_QUERY);
1205     ScfPropertySet aPropSet(xAxisSupp);
1206     if (xAxisSupp.is() && aPropSet.GetBoolProperty("HasSecondaryYAxisTitle"))
1207         return xAxisSupp->getSecondYAxisTitle();
1208     return uno::Reference<drawing::XShape>();
1209 }
1210 
1211 } // namespace
1212 
XclChRootData()1213 XclChRootData::XclChRootData()
1214     : mxTypeInfoProv(new XclChTypeInfoProvider)
1215     , mxFmtInfoProv(new XclChFormatInfoProvider)
1216     , mnBorderGapX(0)
1217     , mnBorderGapY(0)
1218     , mfUnitSizeX(0.0)
1219     , mfUnitSizeY(0.0)
1220 {
1221     // remember some title shape getter functions
1222     maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_TITLE ) ] = lclGetMainTitleShape;
1223     maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_PRIMARY, EXC_CHAXIS_X ) ] = lclGetXAxisTitleShape;
1224     maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_PRIMARY, EXC_CHAXIS_Y ) ] = lclGetYAxisTitleShape;
1225     maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_PRIMARY, EXC_CHAXIS_Z ) ] = lclGetZAxisTitleShape;
1226     maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_SECONDARY, EXC_CHAXIS_X ) ] = lclGetSecXAxisTitleShape;
1227     maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_SECONDARY, EXC_CHAXIS_Y ) ] = lclGetSecYAxisTitleShape;
1228 }
1229 
~XclChRootData()1230 XclChRootData::~XclChRootData()
1231 {
1232 }
1233 
InitConversion(const XclRoot & rRoot,const uno::Reference<chart2::XChartDocument> & rxChartDoc,const tools::Rectangle & rChartRect)1234 void XclChRootData::InitConversion(const XclRoot& rRoot, const uno::Reference<chart2::XChartDocument> & rxChartDoc, const tools::Rectangle& rChartRect)
1235 {
1236     // remember chart document reference and chart shape position/size
1237     OSL_ENSURE( rxChartDoc.is(), "XclChRootData::InitConversion - missing chart document" );
1238     mxChartDoc = rxChartDoc;
1239     maChartRect = rChartRect;
1240 
1241     // Excel excludes a border of 5 pixels in each direction from chart area
1242     mnBorderGapX = rRoot.GetHmmFromPixelX( 5.0 );
1243     mnBorderGapY = rRoot.GetHmmFromPixelY( 5.0 );
1244 
1245     // size of a chart unit in 1/100 mm
1246     mfUnitSizeX = std::max<double>( maChartRect.GetWidth()  - 2 * mnBorderGapX, mnBorderGapX ) / EXC_CHART_TOTALUNITS;
1247     mfUnitSizeY = std::max<double>( maChartRect.GetHeight() - 2 * mnBorderGapY, mnBorderGapY ) / EXC_CHART_TOTALUNITS;
1248 
1249     // create object tables
1250     uno::Reference<lang::XMultiServiceFactory> xFactory(mxChartDoc, uno::UNO_QUERY);
1251     mxLineDashTable.reset(new XclChObjectTable(xFactory, SERVICE_DRAWING_DASHTABLE, "Excel line dash "));
1252     mxGradientTable.reset(new XclChObjectTable(xFactory, SERVICE_DRAWING_GRADIENTTABLE, "Excel gradient "));
1253     mxHatchTable.reset(new XclChObjectTable(xFactory, SERVICE_DRAWING_HATCHTABLE, "Excel hatch "));
1254     mxBitmapTable.reset(new XclChObjectTable(xFactory, SERVICE_DRAWING_BITMAPTABLE, "Excel bitmap "));
1255 }
1256 
FinishConversion()1257 void XclChRootData::FinishConversion()
1258 {
1259     // forget formatting object tables
1260     mxBitmapTable.reset();
1261     mxHatchTable.reset();
1262     mxGradientTable.reset();
1263     mxLineDashTable.reset();
1264     // forget chart document reference
1265     mxChartDoc.clear();
1266 }
1267 
GetTitleShape(const XclChTextKey & rTitleKey) const1268 uno::Reference<drawing::XShape> XclChRootData::GetTitleShape(const XclChTextKey& rTitleKey) const
1269 {
1270     XclChGetShapeFuncMap::const_iterator aIt = maGetShapeFuncs.find( rTitleKey );
1271     OSL_ENSURE( aIt != maGetShapeFuncs.end(), "XclChRootData::GetTitleShape - invalid title key" );
1272     uno::Reference<chart::XChartDocument> xChart1Doc( mxChartDoc, uno::UNO_QUERY );
1273     uno::Reference<drawing::XShape> xTitleShape;
1274     if (xChart1Doc.is() && (aIt != maGetShapeFuncs.end()))
1275         xTitleShape = (aIt->second)(xChart1Doc);
1276     return xTitleShape;
1277 }
1278 
1279 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1280