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