1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <xlchart.hxx>
23 #include <com/sun/star/container/XNameContainer.hpp>
24 #include <com/sun/star/awt/Size.hpp>
25 #include <com/sun/star/awt/Gradient.hpp>
26 #include <com/sun/star/drawing/Hatch.hpp>
27 #include <com/sun/star/drawing/LineDash.hpp>
28 #include <com/sun/star/drawing/LineStyle.hpp>
29 #include <com/sun/star/drawing/FillStyle.hpp>
30 #include <com/sun/star/drawing/BitmapMode.hpp>
31 #include <com/sun/star/chart/DataLabelPlacement.hpp>
32 #include <com/sun/star/chart/XAxisXSupplier.hpp>
33 #include <com/sun/star/chart/XAxisYSupplier.hpp>
34 #include <com/sun/star/chart/XAxisZSupplier.hpp>
35 #include <com/sun/star/chart/XChartDocument.hpp>
36 #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
37 #include <com/sun/star/chart2/Symbol.hpp>
38 #include <com/sun/star/chart2/XChartDocument.hpp>
39 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <o3tl/string_view.hxx>
42 #include <sal/macros.h>
43 #include <sal/mathconf.h>
44 #include <svl/itemset.hxx>
45 #include <svx/xfillit0.hxx>
46 #include <svx/xflclit.hxx>
47 #include <svx/xfltrit.hxx>
48 #include <svx/xflgrit.hxx>
49 #include <svx/xbtmpit.hxx>
50 #include <svx/unomid.hxx>
51 #include <filter/msfilter/escherex.hxx>
53 #include <xlstyle.hxx>
54 #include <xltools.hxx>
58 // Common =====================================================================
60 XclChRectangle::XclChRectangle() :
68 XclChDataPointPos::XclChDataPointPos( sal_uInt16 nSeriesIdx
, sal_uInt16 nPointIdx
) :
69 mnSeriesIdx( nSeriesIdx
),
70 mnPointIdx( nPointIdx
)
74 bool operator<( const XclChDataPointPos
& rL
, const XclChDataPointPos
& rR
)
76 return (rL
.mnSeriesIdx
< rR
.mnSeriesIdx
) ||
77 ((rL
.mnSeriesIdx
== rR
.mnSeriesIdx
) && (rL
.mnPointIdx
< rR
.mnPointIdx
));
80 XclChFrBlock::XclChFrBlock( sal_uInt16 nType
) :
88 // Frame formatting ===========================================================
90 XclChFramePos::XclChFramePos() :
91 mnTLMode( EXC_CHFRAMEPOS_PARENT
),
92 mnBRMode( EXC_CHFRAMEPOS_PARENT
)
96 XclChLineFormat::XclChLineFormat() :
98 mnPattern( EXC_CHLINEFORMAT_SOLID
),
99 mnWeight( EXC_CHLINEFORMAT_SINGLE
),
100 mnFlags( EXC_CHLINEFORMAT_AUTO
)
104 XclChAreaFormat::XclChAreaFormat() :
105 maPattColor( COL_WHITE
),
106 maBackColor( COL_BLACK
),
107 mnPattern( EXC_PATT_SOLID
),
108 mnFlags( EXC_CHAREAFORMAT_AUTO
)
112 XclChEscherFormat::XclChEscherFormat()
116 XclChEscherFormat::~XclChEscherFormat()
120 XclChPicFormat::XclChPicFormat() :
121 mnBmpMode( EXC_CHPICFORMAT_NONE
),
122 mnFlags( EXC_CHPICFORMAT_TOPBOTTOM
| EXC_CHPICFORMAT_FRONTBACK
| EXC_CHPICFORMAT_LEFTRIGHT
),
127 XclChFrame::XclChFrame() :
128 mnFormat( EXC_CHFRAME_STANDARD
),
129 mnFlags( EXC_CHFRAME_AUTOSIZE
| EXC_CHFRAME_AUTOPOS
)
133 // Source links ===============================================================
135 XclChSourceLink::XclChSourceLink() :
136 mnDestType( EXC_CHSRCLINK_TITLE
),
137 mnLinkType( EXC_CHSRCLINK_DEFAULT
),
143 // Text =======================================================================
145 XclChObjectLink::XclChObjectLink() :
146 mnTarget( EXC_CHOBJLINK_NONE
)
150 XclChFrLabelProps::XclChFrLabelProps() :
155 XclChText::XclChText() :
156 mnHAlign( EXC_CHTEXT_ALIGN_CENTER
),
157 mnVAlign( EXC_CHTEXT_ALIGN_CENTER
),
158 mnBackMode( EXC_CHTEXT_TRANSPARENT
),
159 mnFlags( EXC_CHTEXT_AUTOCOLOR
| EXC_CHTEXT_AUTOFILL
),
160 mnFlags2( EXC_CHTEXT_POS_DEFAULT
),
161 mnRotation( EXC_ROT_NONE
)
163 maTextComplexColor
.setColor(COL_BLACK
);
166 // Data series ================================================================
168 XclChMarkerFormat::XclChMarkerFormat() :
169 maLineColor( COL_BLACK
),
170 maFillColor( COL_WHITE
),
171 mnMarkerSize( EXC_CHMARKERFORMAT_SINGLESIZE
),
172 mnMarkerType( EXC_CHMARKERFORMAT_NOSYMBOL
),
173 mnFlags( EXC_CHMARKERFORMAT_AUTO
)
177 XclCh3dDataFormat::XclCh3dDataFormat() :
178 mnBase( EXC_CH3DDATAFORMAT_RECT
),
179 mnTop( EXC_CH3DDATAFORMAT_STRAIGHT
)
183 XclChDataFormat::XclChDataFormat() :
184 mnFormatIdx( EXC_CHDATAFORMAT_DEFAULT
),
189 XclChSerTrendLine::XclChSerTrendLine() :
190 mfForecastFor( 0.0 ),
191 mfForecastBack( 0.0 ),
192 mnLineType( EXC_CHSERTREND_POLYNOMIAL
),
197 /* Set all bits in mfIntercept to 1 (that is -1.#NAN) to indicate that
198 there is no interception point. Cannot use ::rtl::math::setNan() here
199 cause it misses the sign bit. */
200 reinterpret_cast<sal_math_Double
*>(&mfIntercept
)->intrep
= 0xFFFFFFFFFFFFFFFF;
203 XclChSerErrorBar::XclChSerErrorBar() :
206 mnBarType( EXC_CHSERERR_NONE
),
207 mnSourceType( EXC_CHSERERR_FIXED
),
208 mnLineEnd( EXC_CHSERERR_END_TSHAPE
)
212 XclChSeries::XclChSeries() :
213 mnCategType( EXC_CHSERIES_NUMERIC
),
214 mnValueType( EXC_CHSERIES_NUMERIC
),
215 mnBubbleType( EXC_CHSERIES_NUMERIC
),
222 // Chart type groups ==========================================================
224 XclChType::XclChType() :
230 mnBubbleType( EXC_CHSCATTER_AREA
),
235 XclChChart3d::XclChChart3d() :
242 mnFlags( EXC_CHCHART3D_AUTOHEIGHT
)
246 XclChLegend::XclChLegend() :
247 mnDockMode( EXC_CHLEGEND_RIGHT
),
248 mnSpacing( EXC_CHLEGEND_MEDIUM
),
249 mnFlags( EXC_CHLEGEND_DOCKED
| EXC_CHLEGEND_AUTOSERIES
|
250 EXC_CHLEGEND_AUTOPOSX
| EXC_CHLEGEND_AUTOPOSY
| EXC_CHLEGEND_STACKED
)
254 XclChTypeGroup::XclChTypeGroup() :
256 mnGroupIdx( EXC_CHSERGROUP_NONE
)
260 XclChProperties::XclChProperties() :
262 mnEmptyMode( EXC_CHPROPS_EMPTY_SKIP
)
266 // Axes =======================================================================
268 XclChLabelRange::XclChLabelRange() :
276 XclChDateRange::XclChDateRange() :
280 mnMajorUnit( EXC_CHDATERANGE_DAYS
),
282 mnMinorUnit( EXC_CHDATERANGE_DAYS
),
283 mnBaseUnit( EXC_CHDATERANGE_DAYS
),
285 mnFlags( EXC_CHDATERANGE_AUTOMIN
| EXC_CHDATERANGE_AUTOMAX
|
286 EXC_CHDATERANGE_AUTOMAJOR
| EXC_CHDATERANGE_AUTOMINOR
|
287 EXC_CHDATERANGE_AUTOBASE
| EXC_CHDATERANGE_AUTOCROSS
|
288 EXC_CHDATERANGE_AUTODATE
)
292 XclChValueRange::XclChValueRange() :
298 mnFlags( EXC_CHVALUERANGE_AUTOMIN
| EXC_CHVALUERANGE_AUTOMAX
|
299 EXC_CHVALUERANGE_AUTOMAJOR
| EXC_CHVALUERANGE_AUTOMINOR
|
300 EXC_CHVALUERANGE_AUTOCROSS
| EXC_CHVALUERANGE_BIT8
)
304 XclChTick::XclChTick() :
305 mnMajor( EXC_CHTICK_INSIDE
| EXC_CHTICK_OUTSIDE
),
307 mnLabelPos( EXC_CHTICK_NEXT
),
308 mnBackMode( EXC_CHTICK_TRANSPARENT
),
309 mnFlags( EXC_CHTICK_AUTOCOLOR
| EXC_CHTICK_AUTOROT
),
310 mnRotation( EXC_ROT_NONE
)
312 maTextComplexColor
.setColor(COL_BLACK
);
315 XclChAxis::XclChAxis() :
316 mnType( EXC_CHAXIS_NONE
)
320 sal_Int32
XclChAxis::GetApiAxisDimension() const
322 sal_Int32 nApiAxisDim
= EXC_CHART_AXIS_NONE
;
325 case EXC_CHAXIS_X
: nApiAxisDim
= EXC_CHART_AXIS_X
; break;
326 case EXC_CHAXIS_Y
: nApiAxisDim
= EXC_CHART_AXIS_Y
; break;
327 case EXC_CHAXIS_Z
: nApiAxisDim
= EXC_CHART_AXIS_Z
; break;
332 XclChAxesSet::XclChAxesSet() :
333 mnAxesSetId( EXC_CHAXESSET_PRIMARY
)
337 sal_Int32
XclChAxesSet::GetApiAxesSetIndex() const
339 sal_Int32 nApiAxesSetIdx
= EXC_CHART_AXESSET_NONE
;
340 switch( mnAxesSetId
)
342 case EXC_CHAXESSET_PRIMARY
: nApiAxesSetIdx
= EXC_CHART_AXESSET_PRIMARY
; break;
343 case EXC_CHAXESSET_SECONDARY
: nApiAxesSetIdx
= EXC_CHART_AXESSET_SECONDARY
; break;
345 return nApiAxesSetIdx
;
348 // Static helper functions ====================================================
350 sal_uInt16
XclChartHelper::GetSeriesLineAutoColorIdx( sal_uInt16 nFormatIdx
)
352 static const sal_uInt16 spnLineColors
[] =
354 32, 33, 34, 35, 36, 37, 38, 39,
355 40, 41, 42, 43, 44, 45, 46, 47,
356 48, 49, 50, 51, 52, 53, 54, 55,
357 56, 57, 58, 59, 60, 61, 62, 8,
358 9, 10, 11, 12, 13, 14, 15, 16,
359 17, 18, 19, 20, 21, 22, 23, 24,
360 25, 26, 27, 28, 29, 30, 31, 63
362 return spnLineColors
[ nFormatIdx
% SAL_N_ELEMENTS( spnLineColors
) ];
365 sal_uInt16
XclChartHelper::GetSeriesFillAutoColorIdx( sal_uInt16 nFormatIdx
)
367 static const sal_uInt16 spnFillColors
[] =
369 24, 25, 26, 27, 28, 29, 30, 31,
370 32, 33, 34, 35, 36, 37, 38, 39,
371 40, 41, 42, 43, 44, 45, 46, 47,
372 48, 49, 50, 51, 52, 53, 54, 55,
373 56, 57, 58, 59, 60, 61, 62, 63,
374 8, 9, 10, 11, 12, 13, 14, 15,
375 16, 17, 18, 19, 20, 21, 22, 23
377 return spnFillColors
[ nFormatIdx
% SAL_N_ELEMENTS( spnFillColors
) ];
380 sal_uInt8
XclChartHelper::GetSeriesFillAutoTransp( sal_uInt16 nFormatIdx
)
382 static const sal_uInt8 spnTrans
[] = { 0x00, 0x40, 0x20, 0x60, 0x70 };
383 return spnTrans
[ (nFormatIdx
/ 56) % SAL_N_ELEMENTS( spnTrans
) ];
386 sal_uInt16
XclChartHelper::GetAutoMarkerType( sal_uInt16 nFormatIdx
)
388 static const sal_uInt16 spnSymbols
[] = {
389 EXC_CHMARKERFORMAT_DIAMOND
, EXC_CHMARKERFORMAT_SQUARE
, EXC_CHMARKERFORMAT_TRIANGLE
,
390 EXC_CHMARKERFORMAT_CROSS
, EXC_CHMARKERFORMAT_STAR
, EXC_CHMARKERFORMAT_CIRCLE
,
391 EXC_CHMARKERFORMAT_PLUS
, EXC_CHMARKERFORMAT_DOWJ
, EXC_CHMARKERFORMAT_STDDEV
};
392 return spnSymbols
[ nFormatIdx
% SAL_N_ELEMENTS( spnSymbols
) ];
395 bool XclChartHelper::HasMarkerFillColor( sal_uInt16 nMarkerType
)
397 static const bool spbFilled
[] = {
398 false, true, true, true, false, false, false, false, true, false };
399 return (nMarkerType
< SAL_N_ELEMENTS( spbFilled
)) && spbFilled
[ nMarkerType
];
402 const OUString
& XclChartHelper::GetErrorBarValuesRole( sal_uInt8 nBarType
)
406 case EXC_CHSERERR_XPLUS
: return EXC_CHPROP_ROLE_ERRORBARS_POSX
;
407 case EXC_CHSERERR_XMINUS
: return EXC_CHPROP_ROLE_ERRORBARS_NEGX
;
408 case EXC_CHSERERR_YPLUS
: return EXC_CHPROP_ROLE_ERRORBARS_POSY
;
409 case EXC_CHSERERR_YMINUS
: return EXC_CHPROP_ROLE_ERRORBARS_NEGY
;
410 default: OSL_FAIL( "XclChartHelper::GetErrorBarValuesRole - unknown bar type" );
412 return EMPTY_OUSTRING
;
415 // Chart formatting info provider =============================================
419 const XclChFormatInfo spFmtInfos
[] =
421 // object type property mode auto line color auto line weight auto pattern color missing frame type create delete isframe
422 { EXC_CHOBJTYPE_BACKGROUND
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_INVISIBLE
, true, true, true },
423 { EXC_CHOBJTYPE_PLOTFRAME
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_INVISIBLE
, true, true, true },
424 { EXC_CHOBJTYPE_WALL3D
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_AUTO
, true, false, true },
425 { EXC_CHOBJTYPE_FLOOR3D
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, 23, EXC_CHFRAMETYPE_AUTO
, true, false, true },
426 { EXC_CHOBJTYPE_TEXT
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_INVISIBLE
, false, true, true },
427 { EXC_CHOBJTYPE_LEGEND
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_AUTO
, true, true, true },
428 { EXC_CHOBJTYPE_LINEARSERIES
, EXC_CHPROPMODE_LINEARSERIES
, 0xFFFF, EXC_CHLINEFORMAT_SINGLE
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_AUTO
, false, false, false },
429 { EXC_CHOBJTYPE_FILLEDSERIES
, EXC_CHPROPMODE_FILLEDSERIES
, EXC_COLOR_CHBORDERAUTO
, EXC_CHLINEFORMAT_SINGLE
, 0xFFFF, EXC_CHFRAMETYPE_AUTO
, false, false, true },
430 { EXC_CHOBJTYPE_AXISLINE
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_AUTO
, false, false, false },
431 { EXC_CHOBJTYPE_GRIDLINE
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_INVISIBLE
, false, true, false },
432 { EXC_CHOBJTYPE_TRENDLINE
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_DOUBLE
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_INVISIBLE
, false, false, false },
433 { EXC_CHOBJTYPE_ERRORBAR
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_SINGLE
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_INVISIBLE
, false, false, false },
434 { EXC_CHOBJTYPE_CONNECTLINE
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_INVISIBLE
, false, false, false },
435 { EXC_CHOBJTYPE_HILOLINE
, EXC_CHPROPMODE_LINEARSERIES
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_INVISIBLE
, false, false, false },
436 { EXC_CHOBJTYPE_WHITEDROPBAR
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWBACK
, EXC_CHFRAMETYPE_INVISIBLE
, false, false, true },
437 { EXC_CHOBJTYPE_BLACKDROPBAR
, EXC_CHPROPMODE_COMMON
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHLINEFORMAT_HAIR
, EXC_COLOR_CHWINDOWTEXT
, EXC_CHFRAMETYPE_INVISIBLE
, false, false, true }
442 XclChFormatInfoProvider::XclChFormatInfoProvider()
444 for(auto const &rIt
: spFmtInfos
)
445 maInfoMap
[ rIt
.meObjType
] = &rIt
;
448 const XclChFormatInfo
& XclChFormatInfoProvider::GetFormatInfo( XclChObjectType eObjType
) const
450 XclFmtInfoMap::const_iterator aIt
= maInfoMap
.find( eObjType
);
451 OSL_ENSURE( aIt
!= maInfoMap
.end(), "XclChFormatInfoProvider::GetFormatInfo - unknown object type" );
452 return (aIt
== maInfoMap
.end()) ? *spFmtInfos
: *aIt
->second
;
455 // Chart type info provider ===================================================
459 // chart type service names
460 const char SERVICE_CHART2_AREA
[] = "com.sun.star.chart2.AreaChartType";
461 const char SERVICE_CHART2_CANDLE
[] = "com.sun.star.chart2.CandleStickChartType";
462 const char SERVICE_CHART2_COLUMN
[] = "com.sun.star.chart2.ColumnChartType";
463 const char SERVICE_CHART2_LINE
[] = "com.sun.star.chart2.LineChartType";
464 const char SERVICE_CHART2_NET
[] = "com.sun.star.chart2.NetChartType";
465 const char SERVICE_CHART2_FILLEDNET
[] = "com.sun.star.chart2.FilledNetChartType";
466 const char SERVICE_CHART2_PIE
[] = "com.sun.star.chart2.PieChartType";
467 const char SERVICE_CHART2_SCATTER
[] = "com.sun.star.chart2.ScatterChartType";
468 const char SERVICE_CHART2_BUBBLE
[] = "com.sun.star.chart2.BubbleChartType";
469 const char SERVICE_CHART2_SURFACE
[] = "com.sun.star.chart2.ColumnChartType"; // Todo
471 namespace csscd
= css::chart::DataLabelPlacement
;
473 const XclChTypeInfo spTypeInfos
[] =
475 // 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
476 { 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 },
477 { 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 },
478 { 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 },
479 { 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 },
480 { 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 },
481 { 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 },
482 { 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 },
483 { 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 },
484 { 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 },
485 { 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 },
486 { 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 },
487 { 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 },
488 { 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 },
489 { 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 }
494 XclChExtTypeInfo::XclChExtTypeInfo( const XclChTypeInfo
& rTypeInfo
) :
495 XclChTypeInfo( rTypeInfo
),
501 void XclChExtTypeInfo::Set( const XclChTypeInfo
& rTypeInfo
, bool b3dChart
, bool bSpline
)
503 static_cast< XclChTypeInfo
& >( *this ) = rTypeInfo
;
504 mb3dChart
= mbSupports3d
&& b3dChart
;
508 XclChTypeInfoProvider::XclChTypeInfoProvider()
510 for(const auto &rIt
: spTypeInfos
)
511 maInfoMap
[ rIt
.meTypeId
] = &rIt
;
514 const XclChTypeInfo
& XclChTypeInfoProvider::GetTypeInfo( XclChTypeId eTypeId
) const
516 XclChTypeInfoMap::const_iterator aIt
= maInfoMap
.find( eTypeId
);
517 OSL_ENSURE( aIt
!= maInfoMap
.end(), "XclChTypeInfoProvider::GetTypeInfo - unknown chart type" );
518 return (aIt
== maInfoMap
.end()) ? *maInfoMap
.rbegin()->second
: *aIt
->second
;
521 const XclChTypeInfo
& XclChTypeInfoProvider::GetTypeInfoFromRecId( sal_uInt16 nRecId
) const
523 for(const auto &rIt
: spTypeInfos
)
525 if(rIt
.mnRecId
== nRecId
)
528 OSL_FAIL( "XclChTypeInfoProvider::GetTypeInfoFromRecId - unknown record id" );
529 return GetTypeInfo( EXC_CHTYPEID_UNKNOWN
);
532 const XclChTypeInfo
& XclChTypeInfoProvider::GetTypeInfoFromService( std::u16string_view rServiceName
) const
534 for(auto const &rIt
: spTypeInfos
)
535 if( o3tl::equalsAscii( rServiceName
, rIt
.mpcServiceName
) )
537 OSL_FAIL( "XclChTypeInfoProvider::GetTypeInfoFromService - unknown service name" );
538 return GetTypeInfo( EXC_CHTYPEID_UNKNOWN
);
541 // Property helpers ===========================================================
543 XclChObjectTable::XclChObjectTable(uno::Reference
<lang::XMultiServiceFactory
> xFactory
,
544 OUString aServiceName
, OUString aObjNameBase
) :
545 mxFactory(std::move( xFactory
)),
546 maServiceName(std::move( aServiceName
)),
547 maObjNameBase(std::move( aObjNameBase
)),
552 uno::Any
XclChObjectTable::GetObject( const OUString
& rObjName
)
555 if( !mxContainer
.is() )
556 mxContainer
.set(ScfApiHelper::CreateInstance( mxFactory
, maServiceName
), uno::UNO_QUERY
);
557 OSL_ENSURE( mxContainer
.is(), "XclChObjectTable::GetObject - container not found" );
560 if( mxContainer
.is() )
562 // get object from container
565 aObj
= mxContainer
->getByName( rObjName
);
567 catch (uno::Exception
&)
569 OSL_FAIL( "XclChObjectTable::GetObject - object not found" );
575 OUString
XclChObjectTable::InsertObject(const uno::Any
& rObj
)
578 // create object table
579 if( !mxContainer
.is() )
580 mxContainer
.set(ScfApiHelper::CreateInstance( mxFactory
, maServiceName
), uno::UNO_QUERY
);
581 OSL_ENSURE( mxContainer
.is(), "XclChObjectTable::InsertObject - container not found" );
584 if( mxContainer
.is() )
586 // create new unused identifier
589 aObjName
= maObjNameBase
+ OUString::number( ++mnIndex
);
591 while( mxContainer
->hasByName( aObjName
) );
596 mxContainer
->insertByName( aObjName
, rObj
);
598 catch (uno::Exception
&)
600 OSL_FAIL( "XclChObjectTable::InsertObject - cannot insert object" );
607 // Property names -------------------------------------------------------------
611 /** Property names for line style in common objects. */
612 const char* const sppcLineNamesCommon
[] =
613 { "LineStyle", "LineWidth", "LineColor", "LineTransparence", "LineDashName", nullptr };
614 /** Property names for line style in linear series objects. */
615 const char* const sppcLineNamesLinear
[] =
616 { "LineStyle", "LineWidth", "Color", "Transparency", "LineDashName", nullptr };
617 /** Property names for line style in filled series objects. */
618 const char* const sppcLineNamesFilled
[] =
619 { "BorderStyle", "BorderWidth", "BorderColor", "BorderTransparency", "BorderDashName", nullptr };
621 /** Property names for solid area style in common objects. */
622 const char* const sppcAreaNamesCommon
[] = { "FillStyle", "FillColor", "FillTransparence", nullptr };
623 /** Property names for solid area style in filled series objects. */
624 const char* const sppcAreaNamesFilled
[] = { "FillStyle", "Color", "Transparency", nullptr };
625 /** Property names for gradient area style in common objects. */
626 const char* const sppcGradNamesCommon
[] = { "FillStyle", "FillGradientName", nullptr };
627 /** Property names for gradient area style in filled series objects. */
628 const char* const sppcGradNamesFilled
[] = { "FillStyle", "GradientName", nullptr };
629 /** Property names for hatch area style in common objects. */
630 const char* const sppcHatchNamesCommon
[] = { "FillStyle", "FillHatchName", "FillColor", "FillBackground", nullptr };
631 /** Property names for hatch area style in filled series objects. */
632 const char* const sppcHatchNamesFilled
[] = { "FillStyle", "HatchName", "Color", "FillBackground", nullptr };
633 /** Property names for bitmap area style. */
634 const char* const sppcBitmapNames
[] = { "FillStyle", "FillBitmapName", "FillBitmapMode", nullptr };
638 XclChPropSetHelper::XclChPropSetHelper() :
639 maLineHlpCommon( sppcLineNamesCommon
),
640 maLineHlpLinear( sppcLineNamesLinear
),
641 maLineHlpFilled( sppcLineNamesFilled
),
642 maAreaHlpCommon( sppcAreaNamesCommon
),
643 maAreaHlpFilled( sppcAreaNamesFilled
),
644 maGradHlpCommon( sppcGradNamesCommon
),
645 maGradHlpFilled( sppcGradNamesFilled
),
646 maHatchHlpCommon( sppcHatchNamesCommon
),
647 maHatchHlpFilled( sppcHatchNamesFilled
),
648 maBitmapHlp( sppcBitmapNames
)
652 // read properties ------------------------------------------------------------
654 void XclChPropSetHelper::ReadLineProperties(
655 XclChLineFormat
& rLineFmt
, XclChObjectTable
& rDashTable
,
656 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
)
658 // read properties from property set
659 drawing::LineStyle eApiStyle
= drawing::LineStyle_NONE
;
660 sal_Int32 nApiWidth
= 0;
661 sal_Int16 nApiTrans
= 0;
662 uno::Any aDashNameAny
;
664 ScfPropSetHelper
& rLineHlp
= GetLineHelper( ePropMode
);
665 rLineHlp
.ReadFromPropertySet( rPropSet
);
666 rLineHlp
>> eApiStyle
>> nApiWidth
>> rLineFmt
.maColor
>> nApiTrans
>> aDashNameAny
;
668 // clear automatic flag
669 ::set_flag( rLineFmt
.mnFlags
, EXC_CHLINEFORMAT_AUTO
, false );
672 if( nApiWidth
<= 0 ) rLineFmt
.mnWeight
= EXC_CHLINEFORMAT_HAIR
;
673 else if( nApiWidth
<= 35 ) rLineFmt
.mnWeight
= EXC_CHLINEFORMAT_SINGLE
;
674 else if( nApiWidth
<= 70 ) rLineFmt
.mnWeight
= EXC_CHLINEFORMAT_DOUBLE
;
675 else rLineFmt
.mnWeight
= EXC_CHLINEFORMAT_TRIPLE
;
680 case drawing::LineStyle_NONE
:
681 rLineFmt
.mnPattern
= EXC_CHLINEFORMAT_NONE
;
683 case drawing::LineStyle_SOLID
:
685 if( nApiTrans
< 13 ) rLineFmt
.mnPattern
= EXC_CHLINEFORMAT_SOLID
;
686 else if( nApiTrans
< 38 ) rLineFmt
.mnPattern
= EXC_CHLINEFORMAT_DARKTRANS
;
687 else if( nApiTrans
< 63 ) rLineFmt
.mnPattern
= EXC_CHLINEFORMAT_MEDTRANS
;
688 else if( nApiTrans
< 100 ) rLineFmt
.mnPattern
= EXC_CHLINEFORMAT_LIGHTTRANS
;
689 else rLineFmt
.mnPattern
= EXC_CHLINEFORMAT_NONE
;
692 case drawing::LineStyle_DASH
:
694 rLineFmt
.mnPattern
= EXC_CHLINEFORMAT_SOLID
;
696 drawing::LineDash aApiDash
;
697 if( (aDashNameAny
>>= aDashName
) && (rDashTable
.GetObject( aDashName
) >>= aApiDash
) )
699 // reorder dashes that are shorter than dots
700 if( (aApiDash
.Dashes
== 0) || (aApiDash
.DashLen
< aApiDash
.DotLen
) )
702 ::std::swap( aApiDash
.Dashes
, aApiDash
.Dots
);
703 ::std::swap( aApiDash
.DashLen
, aApiDash
.DotLen
);
705 // ignore dots that are nearly equal to dashes
706 if( aApiDash
.DotLen
* 3 > aApiDash
.DashLen
* 2 )
709 // convert line dash to predefined Excel dash types
710 if( (aApiDash
.Dashes
== 1) && (aApiDash
.Dots
>= 1) )
711 // one dash and one or more dots
712 rLineFmt
.mnPattern
= (aApiDash
.Dots
== 1) ?
713 EXC_CHLINEFORMAT_DASHDOT
: EXC_CHLINEFORMAT_DASHDOTDOT
;
714 else if( aApiDash
.Dashes
>= 1 )
715 // one or more dashes and no dots (also: dash-dash-dot)
716 rLineFmt
.mnPattern
= (aApiDash
.DashLen
< 250) ?
717 EXC_CHLINEFORMAT_DOT
: EXC_CHLINEFORMAT_DASH
;
722 OSL_FAIL( "XclChPropSetHelper::ReadLineProperties - unknown line style" );
723 rLineFmt
.mnPattern
= EXC_CHLINEFORMAT_SOLID
;
727 bool XclChPropSetHelper::ReadAreaProperties( XclChAreaFormat
& rAreaFmt
,
728 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
)
730 // read properties from property set
731 drawing::FillStyle eApiStyle
= drawing::FillStyle_NONE
;
732 sal_Int16 nTransparency
= 0;
734 ScfPropSetHelper
& rAreaHlp
= GetAreaHelper( ePropMode
);
735 rAreaHlp
.ReadFromPropertySet( rPropSet
);
736 rAreaHlp
>> eApiStyle
>> rAreaFmt
.maPattColor
>> nTransparency
;
738 // clear automatic flag
739 ::set_flag( rAreaFmt
.mnFlags
, EXC_CHAREAFORMAT_AUTO
, false );
741 // set fill style transparent or solid (set solid for anything but transparent)
742 rAreaFmt
.mnPattern
= (eApiStyle
== drawing::FillStyle_NONE
) ? EXC_PATT_NONE
: EXC_PATT_SOLID
;
744 // return true to indicate complex fill (gradient, bitmap, solid transparency)
745 return (eApiStyle
!= drawing::FillStyle_NONE
) && ((eApiStyle
!= drawing::FillStyle_SOLID
) || (nTransparency
> 0));
748 void XclChPropSetHelper::ReadEscherProperties(
749 XclChEscherFormat
& rEscherFmt
, XclChPicFormat
& rPicFmt
,
750 XclChObjectTable
& rGradientTable
, XclChObjectTable
& rHatchTable
, XclChObjectTable
& rBitmapTable
,
751 const ScfPropertySet
& rPropSet
, XclChPropertyMode ePropMode
)
753 // read style and transparency properties from property set
754 drawing::FillStyle eApiStyle
= drawing::FillStyle_NONE
;
756 sal_Int16 nTransparency
= 0;
758 ScfPropSetHelper
& rAreaHlp
= GetAreaHelper( ePropMode
);
759 rAreaHlp
.ReadFromPropertySet( rPropSet
);
760 rAreaHlp
>> eApiStyle
>> aColor
>> nTransparency
;
764 case drawing::FillStyle_SOLID
:
766 OSL_ENSURE( nTransparency
> 0, "XclChPropSetHelper::ReadEscherProperties - unexpected solid area without transparency" );
767 if( (0 < nTransparency
) && (nTransparency
<= 100) )
769 // convert to Escher properties
770 sal_uInt32 nEscherColor
= 0x02000000;
771 ::insert_value( nEscherColor
, aColor
.GetBlue(), 16, 8 );
772 ::insert_value( nEscherColor
, aColor
.GetGreen(), 8, 8 );
773 ::insert_value( nEscherColor
, aColor
.GetRed(), 0, 8 );
774 sal_uInt32 nEscherOpacity
= static_cast< sal_uInt32
>( (100 - nTransparency
) * 655.36 );
775 rEscherFmt
.mxEscherSet
= std::make_shared
<EscherPropertyContainer
>();
776 rEscherFmt
.mxEscherSet
->AddOpt( ESCHER_Prop_fillType
, ESCHER_FillSolid
);
777 rEscherFmt
.mxEscherSet
->AddOpt( ESCHER_Prop_fillColor
, nEscherColor
);
778 rEscherFmt
.mxEscherSet
->AddOpt( ESCHER_Prop_fillOpacity
, nEscherOpacity
);
779 rEscherFmt
.mxEscherSet
->AddOpt( ESCHER_Prop_fillBackColor
, 0x02FFFFFF );
780 rEscherFmt
.mxEscherSet
->AddOpt( ESCHER_Prop_fillBackOpacity
, 0x00010000 );
781 rEscherFmt
.mxEscherSet
->AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x001F001C );
785 case drawing::FillStyle_GRADIENT
:
787 // extract gradient from global gradient table
788 OUString aGradientName
;
789 ScfPropSetHelper
& rGradHlp
= GetGradientHelper( ePropMode
);
790 rGradHlp
.ReadFromPropertySet( rPropSet
);
791 rGradHlp
>> eApiStyle
>> aGradientName
;
792 awt::Gradient aGradient
;
793 if( rGradientTable
.GetObject( aGradientName
) >>= aGradient
)
795 // convert to Escher properties
796 rEscherFmt
.mxEscherSet
= std::make_shared
<EscherPropertyContainer
>();
797 rEscherFmt
.mxEscherSet
->CreateGradientProperties( aGradient
);
801 case drawing::FillStyle_HATCH
:
803 // extract hatch from global hatch table
805 bool bFillBackground
;
806 ScfPropSetHelper
& rHatchHlp
= GetHatchHelper( ePropMode
);
807 rHatchHlp
.ReadFromPropertySet( rPropSet
);
808 rHatchHlp
>> eApiStyle
>> aHatchName
>> aColor
>> bFillBackground
;
809 drawing::Hatch aHatch
;
810 if( rHatchTable
.GetObject( aHatchName
) >>= aHatch
)
812 // convert to Escher properties
813 rEscherFmt
.mxEscherSet
= std::make_shared
<EscherPropertyContainer
>();
814 rEscherFmt
.mxEscherSet
->CreateEmbeddedHatchProperties( aHatch
, aColor
, bFillBackground
);
815 rPicFmt
.mnBmpMode
= EXC_CHPICFORMAT_STACK
;
819 case drawing::FillStyle_BITMAP
:
821 // extract bitmap URL from global bitmap table
822 OUString aBitmapName
;
823 drawing::BitmapMode eApiBmpMode
;
824 maBitmapHlp
.ReadFromPropertySet( rPropSet
);
825 maBitmapHlp
>> eApiStyle
>> aBitmapName
>> eApiBmpMode
;
826 uno::Reference
<awt::XBitmap
> xBitmap
;
827 if (rBitmapTable
.GetObject( aBitmapName
) >>= xBitmap
)
829 // convert to Escher properties
830 rEscherFmt
.mxEscherSet
= std::make_shared
<EscherPropertyContainer
>();
831 rEscherFmt
.mxEscherSet
->CreateEmbeddedBitmapProperties( xBitmap
, eApiBmpMode
);
832 rPicFmt
.mnBmpMode
= (eApiBmpMode
== drawing::BitmapMode_REPEAT
) ?
833 EXC_CHPICFORMAT_STACK
: EXC_CHPICFORMAT_STRETCH
;
838 OSL_FAIL( "XclChPropSetHelper::ReadEscherProperties - unknown fill style" );
842 void XclChPropSetHelper::ReadMarkerProperties(
843 XclChMarkerFormat
& rMarkerFmt
, const ScfPropertySet
& rPropSet
, sal_uInt16 nFormatIdx
)
845 chart2::Symbol aApiSymbol
;
846 if( !rPropSet
.GetProperty( aApiSymbol
, EXC_CHPROP_SYMBOL
) )
849 // clear automatic flag
850 ::set_flag( rMarkerFmt
.mnFlags
, EXC_CHMARKERFORMAT_AUTO
, false );
853 switch( aApiSymbol
.Style
)
855 case chart2::SymbolStyle_NONE
:
856 rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_NOSYMBOL
;
858 case chart2::SymbolStyle_STANDARD
:
859 switch( aApiSymbol
.StandardSymbol
)
861 case 0: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_SQUARE
; break; // square
862 case 1: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_DIAMOND
; break; // diamond
863 case 2: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_STDDEV
; break; // arrow down
864 case 3: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_TRIANGLE
; break; // arrow up
865 case 4: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_DOWJ
; break; // arrow right, same as import
866 case 5: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_PLUS
; break; // arrow left
867 case 6: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_CROSS
; break; // bow tie
868 case 7: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_STAR
; break; // sand glass
869 case 8: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_CIRCLE
; break; // circle new in LibO3.5
870 case 9: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_DIAMOND
; break; // star new in LibO3.5
871 case 10: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_CROSS
; break; // X new in LibO3.5
872 case 11: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_PLUS
; break; // plus new in LibO3.5
873 case 12: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_STAR
; break; // asterisk new in LibO3.5
874 case 13: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_STDDEV
; break; // horizontal bar new in LibO3.5
875 case 14: rMarkerFmt
.mnMarkerType
= EXC_CHMARKERFORMAT_STAR
; break; // vertical bar new in LibO3.5
876 default: rMarkerFmt
.mnMarkerType
= XclChartHelper::GetAutoMarkerType( nFormatIdx
);
880 rMarkerFmt
.mnMarkerType
= XclChartHelper::GetAutoMarkerType( nFormatIdx
);
882 bool bHasFillColor
= XclChartHelper::HasMarkerFillColor( rMarkerFmt
.mnMarkerType
);
883 ::set_flag( rMarkerFmt
.mnFlags
, EXC_CHMARKERFORMAT_NOFILL
, !bHasFillColor
);
886 sal_Int32 nApiSize
= (aApiSymbol
.Size
.Width
+ aApiSymbol
.Size
.Height
+ 1) / 2;
887 rMarkerFmt
.mnMarkerSize
= XclTools::GetTwipsFromHmm( nApiSize
);
890 rMarkerFmt
.maLineColor
= Color( ColorTransparency
, aApiSymbol
.BorderColor
);
891 rMarkerFmt
.maFillColor
= Color( ColorTransparency
, aApiSymbol
.FillColor
);
894 sal_uInt16
XclChPropSetHelper::ReadRotationProperties( const ScfPropertySet
& rPropSet
, bool bSupportsStacked
)
896 // chart2 handles rotation as double in the range [0,360)
898 rPropSet
.GetProperty( fAngle
, EXC_CHPROP_TEXTROTATION
);
899 bool bStacked
= bSupportsStacked
&& rPropSet
.GetBoolProperty( EXC_CHPROP_STACKCHARACTERS
);
900 return bStacked
? EXC_ROT_STACKED
:
901 XclTools::GetXclRotation( Degree100(static_cast< sal_Int32
>( fAngle
* 100.0 + 0.5 )) );
904 // write properties -----------------------------------------------------------
906 void XclChPropSetHelper::WriteLineProperties(
907 ScfPropertySet
& rPropSet
, XclChObjectTable
& rDashTable
,
908 const XclChLineFormat
& rLineFmt
, XclChPropertyMode ePropMode
)
911 sal_Int32 nApiWidth
= 0; // 0 is the width of a hair line
912 switch( rLineFmt
.mnWeight
)
914 case EXC_CHLINEFORMAT_SINGLE
: nApiWidth
= 35; break;
915 case EXC_CHLINEFORMAT_DOUBLE
: nApiWidth
= 70; break;
916 case EXC_CHLINEFORMAT_TRIPLE
: nApiWidth
= 105; break;
920 drawing::LineStyle eApiStyle
= drawing::LineStyle_NONE
;
921 sal_Int16 nApiTrans
= 0;
922 sal_Int32 nDotLen
= ::std::min
< sal_Int32
>( rLineFmt
.mnWeight
+ 105, 210 );
923 drawing::LineDash
aApiDash( drawing::DashStyle_RECT
, 0, nDotLen
, 0, 4 * nDotLen
, nDotLen
);
925 switch( rLineFmt
.mnPattern
)
927 case EXC_CHLINEFORMAT_SOLID
:
928 eApiStyle
= drawing::LineStyle_SOLID
;
930 case EXC_CHLINEFORMAT_DARKTRANS
:
931 eApiStyle
= drawing::LineStyle_SOLID
; nApiTrans
= 25;
933 case EXC_CHLINEFORMAT_MEDTRANS
:
934 eApiStyle
= drawing::LineStyle_SOLID
; nApiTrans
= 50;
936 case EXC_CHLINEFORMAT_LIGHTTRANS
:
937 eApiStyle
= drawing::LineStyle_SOLID
; nApiTrans
= 75;
939 case EXC_CHLINEFORMAT_DASH
:
940 eApiStyle
= drawing::LineStyle_DASH
; aApiDash
.Dashes
= 1;
942 case EXC_CHLINEFORMAT_DOT
:
943 eApiStyle
= drawing::LineStyle_DASH
; aApiDash
.Dots
= 1;
945 case EXC_CHLINEFORMAT_DASHDOT
:
946 eApiStyle
= drawing::LineStyle_DASH
; aApiDash
.Dashes
= aApiDash
.Dots
= 1;
948 case EXC_CHLINEFORMAT_DASHDOTDOT
:
949 eApiStyle
= drawing::LineStyle_DASH
; aApiDash
.Dashes
= 1; aApiDash
.Dots
= 2;
954 sal_Int32 nApiColor
= sal_Int32( rLineFmt
.maColor
);
956 // try to insert the dash style and receive its name
957 uno::Any aDashNameAny
;
958 if( eApiStyle
== drawing::LineStyle_DASH
)
960 OUString aDashName
= rDashTable
.InsertObject( uno::Any( aApiDash
) );
961 if( !aDashName
.isEmpty() )
962 aDashNameAny
<<= aDashName
;
965 // write the properties
966 ScfPropSetHelper
& rLineHlp
= GetLineHelper( ePropMode
);
967 rLineHlp
.InitializeWrite();
968 rLineHlp
<< eApiStyle
<< nApiWidth
<< nApiColor
<< nApiTrans
<< aDashNameAny
;
969 rLineHlp
.WriteToPropertySet( rPropSet
);
972 void XclChPropSetHelper::WriteAreaProperties( ScfPropertySet
& rPropSet
,
973 const XclChAreaFormat
& rAreaFmt
, XclChPropertyMode ePropMode
)
975 drawing::FillStyle eFillStyle
= drawing::FillStyle_NONE
;
979 if( rAreaFmt
.mnPattern
!= EXC_PATT_NONE
)
981 eFillStyle
= drawing::FillStyle_SOLID
;
982 aColor
= XclTools::GetPatternColor( rAreaFmt
.maPattColor
, rAreaFmt
.maBackColor
, rAreaFmt
.mnPattern
);
985 // write the properties
986 ScfPropSetHelper
& rAreaHlp
= GetAreaHelper( ePropMode
);
987 rAreaHlp
.InitializeWrite();
988 rAreaHlp
<< eFillStyle
<< aColor
<< sal_Int16(0)/*nTransparency*/;
989 rAreaHlp
.WriteToPropertySet( rPropSet
);
992 void XclChPropSetHelper::WriteEscherProperties( ScfPropertySet
& rPropSet
,
993 XclChObjectTable
& rGradientTable
, XclChObjectTable
& rBitmapTable
,
994 const XclChEscherFormat
& rEscherFmt
, const XclChPicFormat
* pPicFmt
,
995 sal_uInt32 nDffFillType
, XclChPropertyMode ePropMode
)
997 if( !rEscherFmt
.mxItemSet
)
1000 const XFillStyleItem
* pStyleItem
= rEscherFmt
.mxItemSet
->GetItem
<XFillStyleItem
>( XATTR_FILLSTYLE
, false );
1004 switch( pStyleItem
->GetValue() )
1006 case drawing::FillStyle_SOLID
:
1007 // #i84812# Excel 2007 writes Escher properties for solid fill
1008 if( const XFillColorItem
* pColorItem
= rEscherFmt
.mxItemSet
->GetItem
<XFillColorItem
>( XATTR_FILLCOLOR
, false ) )
1010 // get solid transparence too
1011 const XFillTransparenceItem
* pTranspItem
= rEscherFmt
.mxItemSet
->GetItem
<XFillTransparenceItem
>( XATTR_FILLTRANSPARENCE
, false );
1012 sal_uInt16 nTransp
= pTranspItem
? pTranspItem
->GetValue() : 0;
1013 ScfPropSetHelper
& rAreaHlp
= GetAreaHelper( ePropMode
);
1014 rAreaHlp
.InitializeWrite();
1015 rAreaHlp
<< drawing::FillStyle_SOLID
<< pColorItem
->GetColorValue() << static_cast< sal_Int16
>( nTransp
);
1016 rAreaHlp
.WriteToPropertySet( rPropSet
);
1019 case drawing::FillStyle_GRADIENT
:
1020 if( const XFillGradientItem
* pGradItem
= rEscherFmt
.mxItemSet
->GetItem
<XFillGradientItem
>( XATTR_FILLGRADIENT
, false ) )
1022 uno::Any aGradientAny
;
1023 if( pGradItem
->QueryValue( aGradientAny
, MID_FILLGRADIENT
) )
1025 OUString aGradName
= rGradientTable
.InsertObject( aGradientAny
);
1026 if( !aGradName
.isEmpty() )
1028 ScfPropSetHelper
& rGradHlp
= GetGradientHelper( ePropMode
);
1029 rGradHlp
.InitializeWrite();
1030 rGradHlp
<< drawing::FillStyle_GRADIENT
<< aGradName
;
1031 rGradHlp
.WriteToPropertySet( rPropSet
);
1036 case drawing::FillStyle_BITMAP
:
1037 if( const XFillBitmapItem
* pBmpItem
= rEscherFmt
.mxItemSet
->GetItem
<XFillBitmapItem
>( XATTR_FILLBITMAP
, false ) )
1039 uno::Any aBitmapAny
;
1040 if (pBmpItem
->QueryValue(aBitmapAny
, MID_BITMAP
))
1042 OUString aBmpName
= rBitmapTable
.InsertObject( aBitmapAny
);
1043 if( !aBmpName
.isEmpty() )
1045 /* #i71810# Caller decides whether to use a CHPICFORMAT record for bitmap mode.
1046 If not passed, detect fill mode from the DFF property 'fill-type'. */
1047 bool bStretch
= pPicFmt
? (pPicFmt
->mnBmpMode
== EXC_CHPICFORMAT_STRETCH
) : (nDffFillType
== mso_fillPicture
);
1048 drawing::BitmapMode eApiBmpMode
= bStretch
? drawing::BitmapMode_STRETCH
: drawing::BitmapMode_REPEAT
;
1049 maBitmapHlp
.InitializeWrite();
1050 maBitmapHlp
<< drawing::FillStyle_BITMAP
<< aBmpName
<< eApiBmpMode
;
1051 maBitmapHlp
.WriteToPropertySet( rPropSet
);
1057 OSL_FAIL( "XclChPropSetHelper::WriteEscherProperties - unknown fill mode" );
1061 void XclChPropSetHelper::WriteMarkerProperties(
1062 ScfPropertySet
& rPropSet
, const XclChMarkerFormat
& rMarkerFmt
)
1065 chart2::Symbol aApiSymbol
;
1066 aApiSymbol
.Style
= chart2::SymbolStyle_STANDARD
;
1067 switch( rMarkerFmt
.mnMarkerType
)
1069 case EXC_CHMARKERFORMAT_NOSYMBOL
: aApiSymbol
.Style
= chart2::SymbolStyle_NONE
; break;
1070 case EXC_CHMARKERFORMAT_SQUARE
: aApiSymbol
.StandardSymbol
= 0; break; // square
1071 case EXC_CHMARKERFORMAT_DIAMOND
: aApiSymbol
.StandardSymbol
= 1; break; // diamond
1072 case EXC_CHMARKERFORMAT_TRIANGLE
: aApiSymbol
.StandardSymbol
= 3; break; // arrow up
1073 case EXC_CHMARKERFORMAT_CROSS
: aApiSymbol
.StandardSymbol
= 10; break; // X, legacy bow tie
1074 case EXC_CHMARKERFORMAT_STAR
: aApiSymbol
.StandardSymbol
= 12; break; // asterisk, legacy sand glass
1075 case EXC_CHMARKERFORMAT_DOWJ
: aApiSymbol
.StandardSymbol
= 4; break; // arrow right, same as export
1076 case EXC_CHMARKERFORMAT_STDDEV
: aApiSymbol
.StandardSymbol
= 13; break; // horizontal bar, legacy arrow down
1077 case EXC_CHMARKERFORMAT_CIRCLE
: aApiSymbol
.StandardSymbol
= 8; break; // circle, legacy arrow right
1078 case EXC_CHMARKERFORMAT_PLUS
: aApiSymbol
.StandardSymbol
= 11; break; // plus, legacy arrow left
1083 sal_Int32 nApiSize
= XclTools::GetHmmFromTwips( rMarkerFmt
.mnMarkerSize
);
1084 aApiSymbol
.Size
= awt::Size( nApiSize
, nApiSize
);
1087 aApiSymbol
.FillColor
= sal_Int32( rMarkerFmt
.maFillColor
);
1088 aApiSymbol
.BorderColor
= ::get_flag( rMarkerFmt
.mnFlags
, EXC_CHMARKERFORMAT_NOLINE
) ?
1089 aApiSymbol
.FillColor
: sal_Int32( rMarkerFmt
.maLineColor
);
1092 rPropSet
.SetProperty( EXC_CHPROP_SYMBOL
, aApiSymbol
);
1095 void XclChPropSetHelper::WriteRotationProperties(
1096 ScfPropertySet
& rPropSet
, sal_uInt16 nRotation
, bool bSupportsStacked
)
1098 if( nRotation
!= EXC_CHART_AUTOROTATION
)
1100 // chart2 handles rotation as double in the range [0,360)
1101 double fAngle
= XclTools::GetScRotation( nRotation
, 0_deg100
).get() / 100.0;
1102 rPropSet
.SetProperty( EXC_CHPROP_TEXTROTATION
, fAngle
);
1103 if( bSupportsStacked
)
1104 rPropSet
.SetProperty( EXC_CHPROP_STACKCHARACTERS
, nRotation
== EXC_ROT_STACKED
);
1108 // private --------------------------------------------------------------------
1110 ScfPropSetHelper
& XclChPropSetHelper::GetLineHelper( XclChPropertyMode ePropMode
)
1114 case EXC_CHPROPMODE_COMMON
: return maLineHlpCommon
;
1115 case EXC_CHPROPMODE_LINEARSERIES
: return maLineHlpLinear
;
1116 case EXC_CHPROPMODE_FILLEDSERIES
: return maLineHlpFilled
;
1117 default: OSL_FAIL( "XclChPropSetHelper::GetLineHelper - unknown property mode" );
1119 return maLineHlpCommon
;
1122 ScfPropSetHelper
& XclChPropSetHelper::GetAreaHelper( XclChPropertyMode ePropMode
)
1126 case EXC_CHPROPMODE_COMMON
: return maAreaHlpCommon
;
1127 case EXC_CHPROPMODE_FILLEDSERIES
: return maAreaHlpFilled
;
1128 default: OSL_FAIL( "XclChPropSetHelper::GetAreaHelper - unknown property mode" );
1130 return maAreaHlpCommon
;
1133 ScfPropSetHelper
& XclChPropSetHelper::GetGradientHelper( XclChPropertyMode ePropMode
)
1137 case EXC_CHPROPMODE_COMMON
: return maGradHlpCommon
;
1138 case EXC_CHPROPMODE_FILLEDSERIES
: return maGradHlpFilled
;
1139 default: OSL_FAIL( "XclChPropSetHelper::GetGradientHelper - unknown property mode" );
1141 return maGradHlpCommon
;
1144 ScfPropSetHelper
& XclChPropSetHelper::GetHatchHelper( XclChPropertyMode ePropMode
)
1148 case EXC_CHPROPMODE_COMMON
: return maHatchHlpCommon
;
1149 case EXC_CHPROPMODE_FILLEDSERIES
: return maHatchHlpFilled
;
1150 default: OSL_FAIL( "XclChPropSetHelper::GetHatchHelper - unknown property mode" );
1152 return maHatchHlpCommon
;
1157 /* The following local functions implement getting the XShape interface of all
1158 supported title objects (chart and axes). This needs some effort due to the
1159 design of the old Chart1 API used to access these objects. */
1161 /** Returns the drawing shape of the main title, if existing. */
1162 uno::Reference
<drawing::XShape
> lclGetMainTitleShape(const uno::Reference
<chart::XChartDocument
> & rxChart1Doc
)
1164 ScfPropertySet
aPropSet(rxChart1Doc
);
1165 if (rxChart1Doc
.is() && aPropSet
.GetBoolProperty(u
"HasMainTitle"_ustr
))
1166 return rxChart1Doc
->getTitle();
1167 return uno::Reference
<drawing::XShape
>();
1170 uno::Reference
<drawing::XShape
> lclGetXAxisTitleShape(const uno::Reference
<chart::XChartDocument
> & rxChart1Doc
)
1172 uno::Reference
<chart::XAxisXSupplier
> xAxisSupp(rxChart1Doc
->getDiagram(), uno::UNO_QUERY
);
1173 ScfPropertySet
aPropSet(xAxisSupp
);
1174 if (xAxisSupp
.is() && aPropSet
.GetBoolProperty(u
"HasXAxisTitle"_ustr
))
1175 return xAxisSupp
->getXAxisTitle();
1176 return uno::Reference
<drawing::XShape
>();
1179 uno::Reference
<drawing::XShape
> lclGetYAxisTitleShape(const uno::Reference
<chart::XChartDocument
> & rxChart1Doc
)
1181 uno::Reference
<chart::XAxisYSupplier
> xAxisSupp(rxChart1Doc
->getDiagram(), uno::UNO_QUERY
);
1182 ScfPropertySet
aPropSet(xAxisSupp
);
1183 if (xAxisSupp
.is() && aPropSet
.GetBoolProperty(u
"HasYAxisTitle"_ustr
))
1184 return xAxisSupp
->getYAxisTitle();
1185 return uno::Reference
<drawing::XShape
>();
1188 uno::Reference
<drawing::XShape
> lclGetZAxisTitleShape(const uno::Reference
<chart::XChartDocument
> & rxChart1Doc
)
1190 uno::Reference
<chart::XAxisZSupplier
> xAxisSupp(rxChart1Doc
->getDiagram(), uno::UNO_QUERY
);
1191 ScfPropertySet
aPropSet(xAxisSupp
);
1192 if (xAxisSupp
.is() && aPropSet
.GetBoolProperty(u
"HasZAxisTitle"_ustr
))
1193 return xAxisSupp
->getZAxisTitle();
1194 return uno::Reference
<drawing::XShape
>();
1197 uno::Reference
<drawing::XShape
> lclGetSecXAxisTitleShape(const uno::Reference
<chart::XChartDocument
> & rxChart1Doc
)
1199 uno::Reference
<chart::XSecondAxisTitleSupplier
> xAxisSupp(rxChart1Doc
->getDiagram(), uno::UNO_QUERY
);
1200 ScfPropertySet
aPropSet(xAxisSupp
);
1201 if (xAxisSupp
.is() && aPropSet
.GetBoolProperty(u
"HasSecondaryXAxisTitle"_ustr
))
1202 return xAxisSupp
->getSecondXAxisTitle();
1203 return uno::Reference
<drawing::XShape
>();
1206 uno::Reference
<drawing::XShape
> lclGetSecYAxisTitleShape(const uno::Reference
<chart::XChartDocument
> & rxChart1Doc
)
1208 uno::Reference
<chart::XSecondAxisTitleSupplier
> xAxisSupp(rxChart1Doc
->getDiagram(), uno::UNO_QUERY
);
1209 ScfPropertySet
aPropSet(xAxisSupp
);
1210 if (xAxisSupp
.is() && aPropSet
.GetBoolProperty(u
"HasSecondaryYAxisTitle"_ustr
))
1211 return xAxisSupp
->getSecondYAxisTitle();
1212 return uno::Reference
<drawing::XShape
>();
1217 XclChRootData::XclChRootData()
1218 : mxTypeInfoProv(std::make_shared
<XclChTypeInfoProvider
>())
1219 , mxFmtInfoProv(std::make_shared
<XclChFormatInfoProvider
>())
1225 // remember some title shape getter functions
1226 maGetShapeFuncs
[ XclChTextKey( EXC_CHTEXTTYPE_TITLE
) ] = lclGetMainTitleShape
;
1227 maGetShapeFuncs
[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE
, EXC_CHAXESSET_PRIMARY
, EXC_CHAXIS_X
) ] = lclGetXAxisTitleShape
;
1228 maGetShapeFuncs
[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE
, EXC_CHAXESSET_PRIMARY
, EXC_CHAXIS_Y
) ] = lclGetYAxisTitleShape
;
1229 maGetShapeFuncs
[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE
, EXC_CHAXESSET_PRIMARY
, EXC_CHAXIS_Z
) ] = lclGetZAxisTitleShape
;
1230 maGetShapeFuncs
[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE
, EXC_CHAXESSET_SECONDARY
, EXC_CHAXIS_X
) ] = lclGetSecXAxisTitleShape
;
1231 maGetShapeFuncs
[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE
, EXC_CHAXESSET_SECONDARY
, EXC_CHAXIS_Y
) ] = lclGetSecYAxisTitleShape
;
1234 XclChRootData::~XclChRootData()
1238 void XclChRootData::InitConversion(const XclRoot
& rRoot
, const uno::Reference
<chart2::XChartDocument
> & rxChartDoc
, const tools::Rectangle
& rChartRect
)
1240 // remember chart document reference and chart shape position/size
1241 OSL_ENSURE( rxChartDoc
.is(), "XclChRootData::InitConversion - missing chart document" );
1242 mxChartDoc
= rxChartDoc
;
1243 maChartRect
= rChartRect
;
1245 // Excel excludes a border of 5 pixels in each direction from chart area
1246 mnBorderGapX
= rRoot
.GetHmmFromPixelX( 5.0 );
1247 mnBorderGapY
= rRoot
.GetHmmFromPixelY( 5.0 );
1249 // size of a chart unit in 1/100 mm
1250 mfUnitSizeX
= std::max
<double>( maChartRect
.GetWidth() - 2 * mnBorderGapX
, mnBorderGapX
) / EXC_CHART_TOTALUNITS
;
1251 mfUnitSizeY
= std::max
<double>( maChartRect
.GetHeight() - 2 * mnBorderGapY
, mnBorderGapY
) / EXC_CHART_TOTALUNITS
;
1253 // create object tables
1254 uno::Reference
<lang::XMultiServiceFactory
> xFactory(mxChartDoc
, uno::UNO_QUERY
);
1255 mxLineDashTable
= std::make_shared
<XclChObjectTable
>(xFactory
, SERVICE_DRAWING_DASHTABLE
, "Excel line dash ");
1256 mxGradientTable
= std::make_shared
<XclChObjectTable
>(xFactory
, SERVICE_DRAWING_GRADIENTTABLE
, "Excel gradient ");
1257 mxHatchTable
= std::make_shared
<XclChObjectTable
>(xFactory
, SERVICE_DRAWING_HATCHTABLE
, "Excel hatch ");
1258 mxBitmapTable
= std::make_shared
<XclChObjectTable
>(xFactory
, SERVICE_DRAWING_BITMAPTABLE
, "Excel bitmap ");
1261 void XclChRootData::FinishConversion()
1263 // forget formatting object tables
1264 mxBitmapTable
.reset();
1265 mxHatchTable
.reset();
1266 mxGradientTable
.reset();
1267 mxLineDashTable
.reset();
1268 // forget chart document reference
1272 uno::Reference
<drawing::XShape
> XclChRootData::GetTitleShape(const XclChTextKey
& rTitleKey
) const
1274 XclChGetShapeFuncMap::const_iterator aIt
= maGetShapeFuncs
.find( rTitleKey
);
1275 OSL_ENSURE( aIt
!= maGetShapeFuncs
.end(), "XclChRootData::GetTitleShape - invalid title key" );
1276 uno::Reference
<chart::XChartDocument
> xChart1Doc( mxChartDoc
, uno::UNO_QUERY
);
1277 uno::Reference
<drawing::XShape
> xTitleShape
;
1278 if (xChart1Doc
.is() && (aIt
!= maGetShapeFuncs
.end()))
1279 xTitleShape
= (aIt
->second
)(xChart1Doc
);
1283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */