LibreOffice Module oox (master) 1
plotareaconverter.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
21
22#include <com/sun/star/chart/XChartDocument.hpp>
23#include <com/sun/star/chart/XDiagramPositioning.hpp>
24#include <com/sun/star/chart2/XChartDocument.hpp>
25#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
26#include <com/sun/star/chart2/XDiagram.hpp>
27#include <com/sun/star/drawing/Direction3D.hpp>
28#include <com/sun/star/drawing/ProjectionMode.hpp>
29#include <com/sun/star/drawing/ShadeMode.hpp>
30#include <osl/diagnose.h>
36#include <oox/token/namespaces.hxx>
37#include <oox/token/properties.hxx>
38#include <oox/token/tokens.hxx>
39#include <tools/helpers.hxx>
40
41namespace oox::drawingml::chart {
42
43using namespace ::com::sun::star;
44using namespace ::com::sun::star::chart2;
45using namespace ::com::sun::star::uno;
46
47namespace {
48
51struct AxesSetModel
52{
53 typedef ModelVector< TypeGroupModel > TypeGroupVector;
54 typedef ModelMap< sal_Int32, AxisModel > AxisMap;
55
56 TypeGroupVector maTypeGroups;
57 AxisMap maAxes;
58
59 explicit AxesSetModel() {}
60};
61
63class AxesSetConverter : public ConverterBase< AxesSetModel >
64{
65public:
66 explicit AxesSetConverter( const ConverterRoot& rParent, AxesSetModel& rModel );
67
70 void convertFromModel(
71 const Reference< XDiagram >& rxDiagram,
72 View3DModel& rView3DModel,
73 sal_Int32 nAxesSetIdx,
74 bool bSupportsVaryColorsByPoint,
75 bool bUseFixedInnerSize );
76
78 const OUString& getAutomaticTitle() const { return maAutoTitle; }
80 bool is3dChart() const { return mb3dChart; }
82 bool isWall3dChart() const { return mbWall3dChart; }
84 bool isPieChart() const { return mbPieChart; }
85
86private:
87 OUString maAutoTitle;
91};
92
93AxesSetConverter::AxesSetConverter( const ConverterRoot& rParent, AxesSetModel& rModel ) :
94 ConverterBase< AxesSetModel >( rParent, rModel ),
95 mb3dChart( false ),
96 mbWall3dChart( false ),
97 mbPieChart( false )
98{
99}
100
101ModelRef< AxisModel > lclGetOrCreateAxis( const AxesSetModel::AxisMap& rFromAxes, sal_Int32 nAxisIdx, sal_Int32 nDefTypeId, bool bMSO2007Doc )
102{
103 ModelRef< AxisModel > xAxis = rFromAxes.get( nAxisIdx );
104 if( !xAxis )
105 xAxis.create( nDefTypeId, bMSO2007Doc ).mbDeleted = true; // missing axis is invisible
106 return xAxis;
107}
108
109void AxesSetConverter::convertFromModel( const Reference< XDiagram >& rxDiagram,
110 View3DModel& rView3DModel, sal_Int32 nAxesSetIdx,
111 bool bSupportsVaryColorsByPoint, bool bUseFixedInnerSize)
112{
113 // create type group converter objects for all type groups
114 typedef RefVector< TypeGroupConverter > TypeGroupConvVector;
115 TypeGroupConvVector aTypeGroups;
116 for (auto const& typeGroup : mrModel.maTypeGroups)
117 aTypeGroups.push_back( std::make_shared<TypeGroupConverter>( *this, *typeGroup ) );
118
119 OSL_ENSURE( !aTypeGroups.empty(), "AxesSetConverter::convertFromModel - no type groups in axes set" );
120 if( aTypeGroups.empty() )
121 return;
122
123 try
124 {
125 // first type group needed for coordinate system and axis conversion
126 TypeGroupConverter& rFirstTypeGroup = *aTypeGroups.front();
127
128 // get automatic chart title, if there is only one type group
129 if( aTypeGroups.size() == 1 )
130 maAutoTitle = rFirstTypeGroup.getSingleSeriesTitle();
131
132 /* Create a coordinate system. For now, all type groups from all axes sets
133 have to be inserted into one coordinate system. Later, chart2 should
134 support using one coordinate system for each axes set. */
135 Reference< XCoordinateSystem > xCoordSystem;
136 Reference< XCoordinateSystemContainer > xCoordSystemCont( rxDiagram, UNO_QUERY_THROW );
137 Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems();
138 if( aCoordSystems.hasElements() )
139 {
140 OSL_ENSURE( aCoordSystems.getLength() == 1, "AxesSetConverter::convertFromModel - too many coordinate systems" );
141 xCoordSystem = aCoordSystems[ 0 ];
142 OSL_ENSURE( xCoordSystem.is(), "AxesSetConverter::convertFromModel - invalid coordinate system" );
143 }
144 else
145 {
146 xCoordSystem = rFirstTypeGroup.createCoordinateSystem();
147 if( xCoordSystem.is() )
148 xCoordSystemCont->addCoordinateSystem( xCoordSystem );
149 }
150
151 // 3D view settings
152 mb3dChart = rFirstTypeGroup.is3dChart();
153 mbWall3dChart = rFirstTypeGroup.isWall3dChart();
154 mbPieChart = rFirstTypeGroup.getTypeInfo().meTypeCategory == TYPECATEGORY_PIE;
155 if( mb3dChart )
156 {
157 View3DConverter aView3DConv( *this, rView3DModel );
158 aView3DConv.convertFromModel( rxDiagram, rFirstTypeGroup );
159 }
160
161 /* Convert all chart type groups. Each type group will add its series
162 to the data provider attached to the chart document. */
163 if( xCoordSystem.is() )
164 {
165 bool bMSO2007Doc = getFilter().isMSO2007Document();
166 // convert all axes (create missing axis models)
167 ModelRef< AxisModel > xXAxis = lclGetOrCreateAxis( mrModel.maAxes, API_X_AXIS, rFirstTypeGroup.getTypeInfo().mbCategoryAxis ? C_TOKEN( catAx ) : C_TOKEN( valAx ), bMSO2007Doc );
168 ModelRef< AxisModel > xYAxis = lclGetOrCreateAxis( mrModel.maAxes, API_Y_AXIS, C_TOKEN( valAx ), bMSO2007Doc );
169
170 AxisConverter aXAxisConv( *this, *xXAxis );
171 aXAxisConv.convertFromModel(xCoordSystem, aTypeGroups, xYAxis.get(), nAxesSetIdx,
172 API_X_AXIS, bUseFixedInnerSize);
173 AxisConverter aYAxisConv( *this, *xYAxis );
174 aYAxisConv.convertFromModel(xCoordSystem, aTypeGroups, xXAxis.get(), nAxesSetIdx,
175 API_Y_AXIS, bUseFixedInnerSize);
176
177 if( rFirstTypeGroup.isDeep3dChart() )
178 {
179 ModelRef< AxisModel > xZAxis = lclGetOrCreateAxis( mrModel.maAxes, API_Z_AXIS, C_TOKEN( serAx ), bMSO2007Doc );
180 AxisConverter aZAxisConv( *this, *xZAxis );
181 aZAxisConv.convertFromModel(xCoordSystem, aTypeGroups, nullptr, nAxesSetIdx,
182 API_Z_AXIS, bUseFixedInnerSize);
183 }
184
185 // convert all chart type groups, this converts all series data and formatting
186 for (auto const& typeGroup : aTypeGroups)
187 typeGroup->convertFromModel( rxDiagram, xCoordSystem, nAxesSetIdx, bSupportsVaryColorsByPoint );
188 }
189 }
190 catch( Exception& )
191 {
192 }
193}
194
195} // namespace
196
197View3DConverter::View3DConverter( const ConverterRoot& rParent, View3DModel& rModel ) :
198 ConverterBase< View3DModel >( rParent, rModel )
199{
200}
201
203{
204}
205
207{
208 namespace cssd = ::com::sun::star::drawing;
209 PropertySet aPropSet( rxDiagram );
210
211 sal_Int32 nRotationY = 0;
212 sal_Int32 nRotationX = 0;
213 bool bRightAngled = false;
214 sal_Int32 nAmbientColor = 0;
215 sal_Int32 nLightColor = 0;
216
217 if( rTypeGroup.getTypeInfo().meTypeCategory == TYPECATEGORY_PIE )
218 {
219 // Y rotation used as 'first pie slice angle' in 3D pie charts
220 rTypeGroup.convertPieRotation( aPropSet, mrModel.monRotationY.value_or( 0 ) );
221 // X rotation a.k.a. elevation (map OOXML [0..90] to Chart2 [-90,0])
222 nRotationX = getLimitedValue< sal_Int32, sal_Int32 >( mrModel.monRotationX.value_or( 15 ), 0, 90 ) - 90;
223 // no right-angled axes in pie charts
224 bRightAngled = false;
225 // ambient color (Gray 30%)
226 nAmbientColor = 0xB3B3B3;
227 // light color (Gray 70%)
228 nLightColor = 0x4C4C4C;
229 }
230 else // 3D bar/area/line charts
231 {
232 // Y rotation (OOXML [0..359], Chart2 [-179,180])
233 nRotationY = mrModel.monRotationY.value_or( 20 );
234 // X rotation a.k.a. elevation (OOXML [-90..90], Chart2 [-179,180])
235 nRotationX = getLimitedValue< sal_Int32, sal_Int32 >( mrModel.monRotationX.value_or( 15 ), -90, 90 );
236 // right-angled axes
237 bRightAngled = mrModel.mbRightAngled;
238 // ambient color (Gray 20%)
239 nAmbientColor = 0xCCCCCC;
240 // light color (Gray 60%)
241 nLightColor = 0x666666;
242 }
243
244 // Y rotation (map OOXML [0..359] to Chart2 [-179,180])
245 nRotationY = NormAngle180(nRotationY);
246 /* Perspective (map OOXML [0..200] to Chart2 [0,100]). Seems that MSO 2007 is
247 buggy here, the XML plugin of MSO 2003 writes the correct perspective in
248 the range from 0 to 100. We will emulate the wrong behaviour of MSO 2007. */
249 sal_Int32 nPerspective = getLimitedValue< sal_Int32, sal_Int32 >( mrModel.mnPerspective / 2, 0, 100 );
250 // projection mode (parallel axes, if right-angled, #i90360# or if perspective is at 0%)
251 bool bParallel = bRightAngled || (nPerspective == 0);
252 cssd::ProjectionMode eProjMode = bParallel ? cssd::ProjectionMode_PARALLEL : cssd::ProjectionMode_PERSPECTIVE;
253
254 // set rotation properties
255 aPropSet.setProperty( PROP_RightAngledAxes, bRightAngled );
256 aPropSet.setProperty( PROP_RotationVertical, nRotationY );
257 aPropSet.setProperty( PROP_RotationHorizontal, nRotationX );
258 aPropSet.setProperty( PROP_Perspective, nPerspective );
259 aPropSet.setProperty( PROP_D3DScenePerspective, eProjMode );
260
261 // set light settings
262 aPropSet.setProperty( PROP_D3DSceneShadeMode, cssd::ShadeMode_FLAT );
263 aPropSet.setProperty( PROP_D3DSceneAmbientColor, nAmbientColor );
264 aPropSet.setProperty( PROP_D3DSceneLightOn1, false );
265 aPropSet.setProperty( PROP_D3DSceneLightOn2, true );
266 aPropSet.setProperty( PROP_D3DSceneLightColor2, nLightColor );
267 aPropSet.setProperty( PROP_D3DSceneLightDirection2, cssd::Direction3D( 0.2, 0.4, 1.0 ) );
268}
269
271 ConverterBase< WallFloorModel >( rParent, rModel )
272{
273}
274
276{
277}
278
280{
281 bool bMSO2007Doc = getFilter().isMSO2007Document();
282 if( rxDiagram.is() )
283 {
284 PropertySet aPropSet;
285 switch( eObjType )
286 {
287 case OBJECTTYPE_FLOOR: aPropSet.set( rxDiagram->getFloor() ); break;
288 case OBJECTTYPE_WALL: aPropSet.set( rxDiagram->getWall() ); break;
289 default: OSL_FAIL( "WallFloorConverter::convertFromModel - invalid object type" );
290 }
291 if( aPropSet.is() )
293 }
294}
295
297 ConverterBase< PlotAreaModel >( rParent, rModel ),
298 mb3dChart( false ),
299 mbWall3dChart( false ),
300 mbPieChart( false )
301{
302}
303
305{
306}
307
309{
310 /* Create the diagram object and attach it to the chart document. One
311 diagram is used to carry all coordinate systems and data series. */
312 Reference< XDiagram > xDiagram;
313 try
314 {
315 xDiagram.set( createInstance( "com.sun.star.chart2.Diagram" ), UNO_QUERY_THROW );
316 getChartDocument()->setFirstDiagram( xDiagram );
317 }
318 catch( Exception& )
319 {
320 }
321
322 // store all axis models in a map, keyed by axis identifier
323 typedef ModelMap< sal_Int32, AxisModel > AxisMap;
324 AxisMap aAxisMap;
325 std::vector<sal_Int32>rValAxisIds;
326 std::vector<sal_Int32>rRealValAxisIds;
327
328 for (auto const& atypeGroup : mrModel.maTypeGroups)
329 {
330 if (atypeGroup->maAxisIds.size() > 1)
331 {
332 // let's collect which axId belongs to the Y Axis according to maTypeGroups
333 rRealValAxisIds.push_back(atypeGroup->maAxisIds[1]);
334 }
335 }
336
337 for (auto const& axis : mrModel.maAxes)
338 {
339 OSL_ENSURE( axis->mnAxisId >= 0, "PlotAreaConverter::convertFromModel - invalid axis identifier" );
340 OSL_ENSURE( !aAxisMap.has( axis->mnAxisId ), "PlotAreaConverter::convertFromModel - axis identifiers not unique" );
341 if( axis->mnAxisId != -1 )
342 aAxisMap[ axis->mnAxisId ] = axis;
343
344 if ( axis->mnAxisId != -1 && axis->mnTypeId == C_TOKEN(valAx) )
345 {
346 for (size_t i = 0; i < rRealValAxisIds.size(); i++)
347 {
348 if (axis->mnAxisId == rRealValAxisIds[i])
349 {
350 // let's collect which axId belongs to the Y Axis according to maAxes
351 rValAxisIds.push_back(axis->mnAxisId);
352 }
353 }
354 }
355 }
356
357 // group the type group models into different axes sets
358 typedef ModelVector< AxesSetModel > AxesSetVector;
359 AxesSetVector aAxesSets;
360 sal_Int32 nMaxSeriesIdx = -1;
361 for (auto const& typeGroup : mrModel.maTypeGroups)
362 {
363 if( !typeGroup->maSeries.empty() )
364 {
365 // try to find a compatible axes set for the type group
366 AxesSetModel* pAxesSet = nullptr;
367 for (auto const& axesSet : aAxesSets)
368 {
369 if( axesSet->maTypeGroups.front()->maAxisIds == typeGroup->maAxisIds )
370 {
371 pAxesSet = axesSet.get();
372 if (pAxesSet)
373 break;
374 }
375 }
376
377 // not possible to insert into an existing axes set -> start a new axes set
378 if( !pAxesSet )
379 {
380 pAxesSet = &aAxesSets.create();
381 // find axis models used by the type group
382 const std::vector<sal_Int32>& rAxisIds = typeGroup->maAxisIds;
383 if( !rAxisIds.empty() )
384 pAxesSet->maAxes[ API_X_AXIS ] = aAxisMap.get( rAxisIds[ 0 ] );
385 if( rAxisIds.size() >= 2 )
386 pAxesSet->maAxes[ API_Y_AXIS ] = aAxisMap.get( rAxisIds[ 1 ] );
387 if( rAxisIds.size() >= 3 )
388 pAxesSet->maAxes[ API_Z_AXIS ] = aAxisMap.get( rAxisIds[ 2 ] );
389 }
390
391 // insert the type group model
392 pAxesSet->maTypeGroups.push_back( typeGroup );
393
394 // collect the maximum series index for automatic series formatting
395 for (auto const& elemSeries : typeGroup->maSeries)
396 nMaxSeriesIdx = ::std::max( nMaxSeriesIdx, elemSeries->mnIndex );
397 }
398 }
399 getFormatter().setMaxSeriesIndex( nMaxSeriesIdx );
400
401 // varying point colors only for single series in single chart type
402 bool bSupportsVaryColorsByPoint = mrModel.maTypeGroups.size() == 1;
403
404 bool bIsCombinedChart = mrModel.maTypeGroups.size() == 2 &&
405 mrModel.maTypeGroups[0]->mnTypeId != mrModel.maTypeGroups[1]->mnTypeId;
406
407 // convert all axes sets, and check which axis is attached to the first maTypeGroups
408 sal_Int32 nStartAxesSetIdx = bIsCombinedChart ? ((rValAxisIds.size() > 1 && aAxesSets.size() > 0 && aAxesSets[0]->maAxes.count( API_Y_AXIS )
409 && aAxesSets[0]->maAxes[ API_Y_AXIS ]->mnAxisId != rValAxisIds[0] ) ? 1 : 0)
410 : 0;
411 sal_Int32 nAxesSetIdx = nStartAxesSetIdx;
412
413 bool bUseFixedInnerSize = false;
414 if (mrModel.mxLayout && !mrModel.mxLayout->mbAutoLayout)
415 bUseFixedInnerSize = mrModel.mxLayout->mnTarget == XML_inner;
416
417 for (auto const& axesSet : aAxesSets)
418 {
419 AxesSetConverter aAxesSetConv(*this, *axesSet);
420 aAxesSetConv.convertFromModel(xDiagram, rView3DModel, nAxesSetIdx,
421 bSupportsVaryColorsByPoint, bUseFixedInnerSize);
422 if(nAxesSetIdx == nStartAxesSetIdx)
423 {
424 maAutoTitle = aAxesSetConv.getAutomaticTitle();
425 mb3dChart = aAxesSetConv.is3dChart();
426 mbWall3dChart = aAxesSetConv.isWall3dChart();
427 mbPieChart = aAxesSetConv.isPieChart();
428 }
429 else
430 {
431 maAutoTitle.clear();
432 }
433 nAxesSetIdx = 1 - nAxesSetIdx;
434 }
435
437 {
438 DataTableConverter dataTableConverter(*this, *mrModel.mxDataTable);
439 dataTableConverter.convertFromModel(xDiagram);
440 }
441
442 // plot area formatting
443 if( xDiagram.is() && !mb3dChart )
444 {
445 PropertySet aPropSet( xDiagram->getWall() );
447 }
448}
449
451{
453 LayoutConverter aLayoutConv( *this, rLayout );
454 awt::Rectangle aDiagramRect;
455 if( !aLayoutConv.calcAbsRectangle( aDiagramRect ) )
456 return;
457
458 try
459 {
460 namespace cssc = ::com::sun::star::chart;
461 Reference< cssc::XChartDocument > xChart1Doc( getChartDocument(), UNO_QUERY_THROW );
462 Reference< cssc::XDiagramPositioning > xPositioning( xChart1Doc->getDiagram(), UNO_QUERY_THROW );
463 // for pie charts, always set inner plot area size to exclude the data labels as Excel does
464 sal_Int32 nTarget = (mbPieChart && (rLayout.mnTarget == XML_outer)) ? XML_inner : rLayout.mnTarget;
465 switch( nTarget )
466 {
467 case XML_inner:
468 xPositioning->setDiagramPositionExcludingAxes( aDiagramRect );
469 break;
470 case XML_outer:
471 xPositioning->setDiagramPositionIncludingAxes( aDiagramRect );
472 break;
473 default:
474 OSL_FAIL( "PlotAreaConverter::convertPositionFromModel - unknown positioning target" );
475 }
476 }
477 catch( Exception& )
478 {
479 }
480}
481
482} // namespace oox
483
484/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ChartModel & mrModel
A wrapper for a UNO property set.
Definition: propertyset.hxx:58
void set(const css::uno::Reference< css::beans::XPropertySet > &rxPropSet)
Sets the passed UNO property set and releases the old UNO property set.
bool is() const
Returns true, if the contained XPropertySet interface is valid.
Definition: propertyset.hxx:80
bool setProperty(sal_Int32 nPropId, const Type &rValue)
Puts the passed value into the property set.
value_type get(sal_Int32 nIndex) const
Returns a reference to the object with the passed index, or 0 on error.
Definition: refvector.hxx:52
Base class of all converter classes.
::oox::core::XmlFilterBase & getFilter() const
Returns the filter object of the imported/exported document.
css::uno::Reference< css::chart2::XChartDocument > const & getChartDocument() const
Returns the API chart document model.
ObjectFormatter & getFormatter() const
Returns the object formatter.
css::uno::Reference< css::uno::XInterface > createInstance(const OUString &rServiceName) const
Creates an instance for the passed service name, using the process service factory.
Converts the data table element and properties from OOXML model to the internal chart implementation.
void convertFromModel(css::uno::Reference< css::chart2::XDiagram > const &rxDiagram)
Converts the OOXML data table model to a chart2 diagram.
A layout converter calculates positions and sizes for various chart objects.
bool calcAbsRectangle(css::awt::Rectangle &orRect) const
Tries to calculate the absolute position and size from the contained OOXML layout model.
void convertFrameFormatting(PropertySet &rPropSet, const ModelRef< Shape > &rxShapeProp, ObjectType eObjType, sal_Int32 nSeriesIdx=-1)
Sets frame formatting properties to the passed property set.
void setMaxSeriesIndex(sal_Int32 nMaxSeriesIdx)
Sets the maximum series index used for color cycling/fading.
void convertFromModel(View3DModel &rView3DModel)
Converts the OOXML plot area model to a chart2 diagram.
PlotAreaConverter(const ConverterRoot &rParent, PlotAreaModel &rModel)
void convertPositionFromModel()
Converts the manual plot area position and size, if set.
void convertPieRotation(PropertySet &rPropSet, sal_Int32 nOoxAngle) const
Sets the passed OOXML pie rotation at the passed property set.
const TypeGroupInfo & getTypeInfo() const
Returns the type info struct that describes this chart type group.
void convertFromModel(const css::uno::Reference< css::chart2::XDiagram > &rxDiagram, TypeGroupConverter const &rTypeGroup)
Converts the OOXML plot area model to a chart2 diagram.
void convertFromModel(const css::uno::Reference< css::chart2::XDiagram > &rxDiagram, ObjectType eObjType)
Converts the OOXML wall/floor model to a chart2 diagram.
WallFloorConverter(const ConverterRoot &rParent, WallFloorModel &rModel)
std::enable_if< std::is_signed< T >::value, T >::type NormAngle180(T angle)
@ Exception
const sal_Int32 API_Y_AXIS
@ TYPECATEGORY_PIE
Radar charts (linear or filled).
const sal_Int32 API_X_AXIS
ObjectType
Enumerates different object types for specific automatic formatting behaviour.
@ OBJECTTYPE_FLOOR
Background and side wall in 3D charts.
@ OBJECTTYPE_WALL
Plot area containing axes and data series in 3D charts.
const sal_Int32 API_Z_AXIS
bool mbWall3dChart
bool mb3dChart
AxisMap maAxes
All type groups containing data series.
bool mbPieChart
OUString maAutoTitle
TypeGroupVector maTypeGroups
sal_Int32 mnTarget
Mode for height.
Definition: modelbase.hxx:111
DataTableRef mxDataTable
Layout/position of the plot area.
ShapeRef mxShapeProp
All axes contained in the chart.
LayoutRef mxLayout
Plot area frame formatting.
AxisVector maAxes
All chart type groups contained in the chart.
TypeCategory meTypeCategory
Unique chart type identifier.
std::optional< sal_Int32 > monRotationY
Horizontal rotation in degrees.
bool mbRightAngled
Eye distance to the 3D objects.
sal_Int32 mnPerspective
Depth of the 3D view, relative to chart width.
std::optional< sal_Int32 > monRotationX
Height of the 3D view, relative to chart width.
PictureOptionsRef mxPicOptions
Wall/floor frame formatting.
constexpr OUStringLiteral PROP_RightAngledAxes