LibreOffice Module oox (master) 1
converterbase.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/XAxisXSupplier.hpp>
23#include <com/sun/star/chart/XAxisYSupplier.hpp>
24#include <com/sun/star/chart/XAxisZSupplier.hpp>
25#include <com/sun/star/chart/XChartDocument.hpp>
26#include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
27#include <com/sun/star/chart2/XChartDocument.hpp>
28#include <com/sun/star/chart2/RelativePosition.hpp>
29#include <com/sun/star/chart2/RelativeSize.hpp>
30#include <com/sun/star/chart2/XTitle.hpp>
31#include <com/sun/star/lang/XMultiServiceFactory.hpp>
32#include <com/sun/star/uno/XComponentContext.hpp>
33#include <osl/diagnose.h>
34#include <sal/log.hxx>
37#include <oox/helper/helper.hxx>
38#include <oox/token/properties.hxx>
39#include <oox/token/tokens.hxx>
40
41
42namespace oox::drawingml::chart {
43
44namespace cssc = ::com::sun::star::chart;
45
46using namespace ::com::sun::star;
47using namespace ::com::sun::star::chart2;
48using namespace ::com::sun::star::drawing;
49using namespace ::com::sun::star::lang;
50using namespace ::com::sun::star::uno;
51
52using ::oox::core::XmlFilterBase;
53
54namespace {
55
56struct TitleKey : public ::std::pair< ObjectType, ::std::pair< sal_Int32, sal_Int32 > >
57{
58 explicit TitleKey( ObjectType eObjType, sal_Int32 nMainIdx = -1, sal_Int32 nSubIdx = -1 )
59 { first = eObjType; second.first = nMainIdx; second.second = nSubIdx; }
60};
61
65struct TitleLayoutInfo
66{
67 typedef Reference< XShape > (*GetShapeFunc)( const Reference< cssc::XChartDocument >& );
68
69 Reference< XTitle > mxTitle;
71 GetShapeFunc mpGetShape;
72
73 explicit TitleLayoutInfo() : mpGetShape( nullptr ) {}
74
75 void convertTitlePos(
76 ConverterRoot const & rRoot,
77 const Reference< cssc::XChartDocument >& rxChart1Doc );
78};
79
80void TitleLayoutInfo::convertTitlePos( ConverterRoot const & rRoot, const Reference< cssc::XChartDocument >& rxChart1Doc )
81{
82 if( !(mxTitle.is() && mpGetShape) )
83 return;
84
85 try
86 {
87 // try to get the title shape
88 Reference< XShape > xTitleShape = mpGetShape( rxChart1Doc );
89 if (!xTitleShape)
90 {
91 SAL_WARN("oox", "failed to get a TitleShape");
92 return;
93 }
94 // get title rotation angle, needed for correction of position of top-left edge
95 double fAngle = 0.0;
96 PropertySet aTitleProp( mxTitle );
97 aTitleProp.getProperty( fAngle, PROP_TextRotation );
98 // convert the position
99 LayoutModel& rLayout = mxLayout.getOrCreate();
100 LayoutConverter aLayoutConv( rRoot, rLayout );
101 aLayoutConv.convertFromModel( xTitleShape, fAngle );
102 }
103 catch( Exception& )
104 {
105 }
106}
107
108/* The following local functions implement getting the XShape interface of all
109 supported title objects (chart and axes). This needs some effort due to the
110 design of the old Chart1 API used to access these objects. */
111
114#define OOX_FRAGMENT_GETTITLESHAPE( shape_supplier, supplier_func, property_name ) \
115 PropertySet aPropSet( shape_supplier ); \
116 if( shape_supplier.is() && aPropSet.getBoolProperty( PROP_##property_name ) ) \
117 return shape_supplier->supplier_func(); \
118 return Reference< XShape >(); \
119
122#define OOX_DEFINEFUNC_GETAXISTITLESHAPE( func_name, interface_type, supplier_func, property_name ) \
123Reference< XShape > func_name( const Reference< cssc::XChartDocument >& rxChart1Doc ) \
124{ \
125 Reference< cssc::interface_type > xAxisSupp( rxChart1Doc->getDiagram(), UNO_QUERY ); \
126 OOX_FRAGMENT_GETTITLESHAPE( xAxisSupp, supplier_func, property_name ) \
127}
128
130Reference< XShape > lclGetMainTitleShape( const Reference< cssc::XChartDocument >& rxChart1Doc )
131{
132 OOX_FRAGMENT_GETTITLESHAPE( rxChart1Doc, getTitle, HasMainTitle )
133}
134
135OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetXAxisTitleShape, XAxisXSupplier, getXAxisTitle, HasXAxisTitle )
136OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetYAxisTitleShape, XAxisYSupplier, getYAxisTitle, HasYAxisTitle )
137OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetZAxisTitleShape, XAxisZSupplier, getZAxisTitle, HasZAxisTitle )
138OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecXAxisTitleShape, XSecondAxisTitleSupplier, getSecondXAxisTitle, HasSecondaryXAxisTitle )
139OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecYAxisTitleShape, XSecondAxisTitleSupplier, getSecondYAxisTitle, HasSecondaryYAxisTitle )
140
141#undef OOX_DEFINEFUNC_GETAXISTITLESHAPE
142#undef OOX_IMPLEMENT_GETTITLESHAPE
143
144} // namespace
145
147{
149 std::map< TitleKey, TitleLayoutInfo >
154 awt::Size maSize;
155
156 explicit ConverterData(
157 XmlFilterBase& rFilter,
158 ChartConverter& rChartConverter,
159 const ChartSpaceModel& rChartModel,
160 const Reference< XChartDocument >& rxChartDoc,
161 const awt::Size& rChartSize );
163};
164
166 XmlFilterBase& rFilter,
167 ChartConverter& rChartConverter,
168 const ChartSpaceModel& rChartModel,
169 const Reference< XChartDocument >& rxChartDoc,
170 const awt::Size& rChartSize ) :
171 maFormatter( rFilter, rxChartDoc, rChartModel ),
172 mrFilter( rFilter ),
173 mrConverter( rChartConverter ),
174 mxDoc( rxChartDoc ),
175 maSize( rChartSize )
176{
177 OSL_ENSURE( mxDoc.is(), "ConverterData::ConverterData - missing chart document" );
178 // lock the model to suppress internal updates during conversion
179 try
180 {
181 mxDoc->lockControllers();
182 }
183 catch( Exception& )
184 {
185 }
186
187 // prepare conversion of title positions
188 maTitles[ TitleKey( OBJECTTYPE_CHARTTITLE ) ].mpGetShape = lclGetMainTitleShape;
189 maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_X_AXIS ) ].mpGetShape = lclGetXAxisTitleShape;
190 maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_Y_AXIS ) ].mpGetShape = lclGetYAxisTitleShape;
191 maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_Z_AXIS ) ].mpGetShape = lclGetZAxisTitleShape;
192 maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_SECN_AXESSET, API_X_AXIS ) ].mpGetShape = lclGetSecXAxisTitleShape;
193 maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_SECN_AXESSET, API_Y_AXIS ) ].mpGetShape = lclGetSecYAxisTitleShape;
194}
195
197{
198 // unlock the model
199 try
200 {
201 mxDoc->unlockControllers();
202 }
203 catch( Exception& )
204 {
205 }
206}
207
209 XmlFilterBase& rFilter,
210 ChartConverter& rChartConverter,
211 const ChartSpaceModel& rChartModel,
212 const Reference< XChartDocument >& rxChartDoc,
213 const awt::Size& rChartSize ) :
214 mxData( std::make_shared<ConverterData>( rFilter, rChartConverter, rChartModel, rxChartDoc, rChartSize ) )
215{
216}
217
219{
220}
221
222Reference< XInterface > ConverterRoot::createInstance( const OUString& rServiceName ) const
223{
225 try
226 {
227 Reference<XMultiServiceFactory> xMSF(getComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW);
228
229 xInt = xMSF->createInstance( rServiceName );
230 }
231 catch( Exception& )
232 {
233 }
234 OSL_ENSURE( xInt.is(), "ConverterRoot::createInstance - cannot create instance" );
235 return xInt;
236}
237
239{
240 return mxData->mrFilter.getComponentContext();
241}
242
244{
245 return mxData->mrFilter;
246}
247
249{
250 return mxData->mrConverter;
251}
252
254{
255 return mxData->mxDoc;
256}
257
258const awt::Size& ConverterRoot::getChartSize() const
259{
260 return mxData->maSize;
261}
262
264{
265 return mxData->maFormatter;
266}
267
269 const ModelRef< LayoutModel >& rxLayout, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx )
270{
271 OSL_ENSURE( rxTitle.is(), "ConverterRoot::registerTitleLayout - missing title object" );
272 TitleLayoutInfo& rTitleInfo = mxData->maTitles[ TitleKey( eObjType, nMainIdx, nSubIdx ) ];
273 OSL_ENSURE( rTitleInfo.mpGetShape, "ConverterRoot::registerTitleLayout - invalid title key" );
274 rTitleInfo.mxTitle = rxTitle;
275 rTitleInfo.mxLayout = rxLayout;
276}
277
279{
280 try
281 {
282 Reference< cssc::XChartDocument > xChart1Doc( mxData->mxDoc, UNO_QUERY_THROW );
283 for (auto & title : mxData->maTitles)
284 title.second.convertTitlePos( *this, xChart1Doc );
285 }
286 catch( Exception& )
287 {
288 }
289}
290
291namespace {
292
294sal_Int32 lclCalcPosition( sal_Int32 nChartSize, double fPos, sal_Int32 nPosMode )
295{
296 switch( nPosMode )
297 {
298 case XML_edge: // absolute start position as factor of chart size
299 return getLimitedValue< sal_Int32, double >( nChartSize * fPos + 0.5, 0, nChartSize );
300 case XML_factor: // position relative to object default position
301 OSL_FAIL( "lclCalcPosition - relative positioning not supported" );
302 return -1;
303 };
304
305 OSL_FAIL( "lclCalcPosition - unknown positioning mode" );
306 return -1;
307}
308
310sal_Int32 lclCalcSize( sal_Int32 nPos, sal_Int32 nChartSize, double fSize, sal_Int32 nSizeMode )
311{
312 sal_Int32 nValue = getLimitedValue< sal_Int32, double >( nChartSize * fSize + 0.5, 0, nChartSize );
313 switch( nSizeMode )
314 {
315 case XML_factor: // passed value is width/height
316 return nValue;
317 case XML_edge: // passed value is right/bottom position
318 return nValue - nPos + 1;
319 };
320
321 OSL_FAIL( "lclCalcSize - unknown size mode" );
322 return -1;
323}
324
326double lclCalcRelSize( double fPos, double fSize, sal_Int32 nSizeMode )
327{
328 switch( nSizeMode )
329 {
330 case XML_factor: // passed value is width/height
331 break;
332 case XML_edge: // passed value is right/bottom position
333 fSize -= fPos;
334 break;
335 default:
336 OSL_ENSURE( false, "lclCalcRelSize - unknown size mode" );
337 fSize = 0.0;
338 };
339 return getLimitedValue< double, double >( fSize, 0.0, 1.0 - fPos );
340}
341
342} // namespace
343
345 ConverterBase< LayoutModel >( rParent, rModel )
346{
347}
348
350{
351}
352
353bool LayoutConverter::calcAbsRectangle( awt::Rectangle& orRect ) const
354{
355 if( !mrModel.mbAutoLayout )
356 {
357 awt::Size aChartSize = getChartSize();
358 if( aChartSize.Width <= 0 || aChartSize.Height <= 0 )
359 {
360 aChartSize = getDefaultPageSize();
361 }
362 orRect.X = lclCalcPosition( aChartSize.Width, mrModel.mfX, mrModel.mnXMode );
363 orRect.Y = lclCalcPosition( aChartSize.Height, mrModel.mfY, mrModel.mnYMode );
364 if( (orRect.X >= 0) && (orRect.Y >= 0) )
365 {
366 orRect.Width = lclCalcSize( orRect.X, aChartSize.Width, mrModel.mfW, mrModel.mnWMode );
367 orRect.Height = lclCalcSize( orRect.Y, aChartSize.Height, mrModel.mfH, mrModel.mnHMode );
368 return (orRect.Width > 0) && (orRect.Height > 0);
369 }
370 }
371 return false;
372}
373
375{
376 if( !mrModel.mbAutoLayout &&
377 (mrModel.mnXMode == XML_edge) && (mrModel.mfX >= 0.0) &&
378 (mrModel.mnYMode == XML_edge) && (mrModel.mfY >= 0.0) )
379 {
380 RelativePosition aPos(
381 getLimitedValue< double, double >( mrModel.mfX, 0.0, 1.0 ),
382 getLimitedValue< double, double >( mrModel.mfY, 0.0, 1.0 ),
383 Alignment_TOP_LEFT );
384 rPropSet.setProperty( PROP_RelativePosition, aPos );
385
386 RelativeSize aSize(
387 lclCalcRelSize( aPos.Primary, mrModel.mfW, mrModel.mnWMode ),
388 lclCalcRelSize( aPos.Secondary, mrModel.mfH, mrModel.mnHMode ) );
389 if( (aSize.Primary > 0.0) && (aSize.Secondary > 0.0) )
390 {
391 rPropSet.setProperty( PROP_RelativeSize, aSize );
392 return true;
393 }
394 }
395 return false;
396}
397
398void LayoutConverter::convertFromModel( const Reference< XShape >& rxShape, double fRotationAngle )
399{
401 return;
402
403 awt::Size aChartSize = getChartSize();
404 if( aChartSize.Width <= 0 || aChartSize.Height <= 0 )
405 {
406 aChartSize = getDefaultPageSize();
407 }
408 awt::Point aShapePos(
409 lclCalcPosition( aChartSize.Width, mrModel.mfX, mrModel.mnXMode ),
410 lclCalcPosition( aChartSize.Height, mrModel.mfY, mrModel.mnYMode ) );
411 if( (aShapePos.X < 0) || (aShapePos.Y < 0) )
412 return;
413
414 bool bPropSet = false;
415 // the call to XShape.getSize() may recalc the chart view
416 awt::Size aShapeSize = rxShape->getSize();
417 // rotated shapes need special handling...
418 if( aShapeSize.Height > 0 || aShapeSize.Width > 0 )
419 {
420 double fSin = fabs(sin(basegfx::deg2rad(fRotationAngle)));
421 // add part of height to X direction, if title is rotated down
422 if( fRotationAngle > 180.0 )
423 aShapePos.X += static_cast<sal_Int32>(fSin * aShapeSize.Height + 0.5);
424 // add part of width to Y direction, if title is rotated up
425 else if( fRotationAngle > 0.0 )
426 aShapePos.Y += static_cast<sal_Int32>(fSin * aShapeSize.Width + 0.5);
427 }
428 else if( fRotationAngle == 90.0 || fRotationAngle == 270.0 )
429 {
430 PropertySet aShapeProp( rxShape );
431 RelativePosition aPos(
432 getLimitedValue< double, double >(mrModel.mfX, 0.0, 1.0),
433 getLimitedValue< double, double >(mrModel.mfY, 0.0, 1.0),
434 fRotationAngle == 90.0 ? Alignment_TOP_RIGHT : Alignment_BOTTOM_LEFT );
435 // set the resulting position at the shape
436 if( aShapeProp.setProperty(PROP_RelativePosition, aPos) )
437 bPropSet = true;
438 }
439 // set the resulting position at the shape
440 if( !bPropSet )
441 rxShape->setPosition( aShapePos );
442}
443
444} // namespace oox
445
446/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
geometry::RealSize2D maSize
A wrapper for a UNO property set.
Definition: propertyset.hxx:58
bool setProperty(sal_Int32 nPropId, const Type &rValue)
Puts the passed value into the property set.
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.
ChartConverter & getChartConverter() const
Returns the chart converter.
const css::awt::Size & getChartSize() const
Returns the position and size of the chart shape in 1/100 mm.
void convertTitlePositions()
Converts the positions of the main title and all axis titles.
void registerTitleLayout(const css::uno::Reference< css::chart2::XTitle > &rxTitle, const ModelRef< LayoutModel > &rxLayout, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx)
Registers a title object and its layout data, needed for conversion of the title position using the o...
ObjectFormatter & getFormatter() const
Returns the object formatter.
static css::awt::Size getDefaultPageSize()
Returns the default position and size of the chart shape in 1/100 mm.
std::shared_ptr< ConverterData > mxData
css::uno::Reference< css::uno::XInterface > createInstance(const OUString &rServiceName) const
Creates an instance for the passed service name, using the process service factory.
ConverterRoot(::oox::core::XmlFilterBase &rFilter, ChartConverter &rChartConverter, const ChartSpaceModel &rChartModel, const css::uno::Reference< css::chart2::XChartDocument > &rxChartDoc, const css::awt::Size &rChartSize)
css::uno::Reference< css::uno::XComponentContext > const & getComponentContext() const
LayoutConverter(const ConverterRoot &rParent, LayoutModel &rModel)
bool calcAbsRectangle(css::awt::Rectangle &orRect) const
Tries to calculate the absolute position and size from the contained OOXML layout model.
bool convertFromModel(PropertySet &rPropSet)
Tries to set the position and size from the contained OOXML layout model.
GetShapeFunc mpGetShape
The layout model, if existing.
Reference< XTitle > mxTitle
#define OOX_DEFINEFUNC_GETAXISTITLESHAPE(func_name, interface_type, supplier_func, property_name)
Implements a function returning the drawing shape of an axis title, if existing, using the specified ...
#define OOX_FRAGMENT_GETTITLESHAPE(shape_supplier, supplier_func, property_name)
A code fragment that returns a shape object from the passed shape supplier using the specified interf...
ModelRef< LayoutModel > mxLayout
The API title object.
sal_Int16 nValue
sal_uInt16 nPos
#define SAL_WARN(area, stream)
constexpr double deg2rad(double v)
@ Exception
std::u16string_view getTitle(std::u16string_view aPath)
constexpr OUStringLiteral first
std::shared_ptr< T > make_shared(Args &&... args)
const sal_Int32 API_Y_AXIS
const sal_Int32 API_PRIM_AXESSET
const sal_Int32 API_X_AXIS
ObjectType
Enumerates different object types for specific automatic formatting behaviour.
@ OBJECTTYPE_AXISTITLE
Axis line, labels, tick marks.
@ OBJECTTYPE_CHARTTITLE
Chart background.
const sal_Int32 API_SECN_AXESSET
const sal_Int32 API_Z_AXIS
ObjectType
const PowerPointImport & mrFilter
Definition: pptimport.cxx:264
ConverterData(XmlFilterBase &rFilter, ChartConverter &rChartConverter, const ChartSpaceModel &rChartModel, const Reference< XChartDocument > &rxChartDoc, const awt::Size &rChartSize)
std::map< TitleKey, TitleLayoutInfo > maTitles
Reference< XChartDocument > mxDoc
sal_Int32 mnXMode
Height of this object.
Definition: modelbase.hxx:107
double mfW
Top position of this object.
Definition: modelbase.hxx:105
sal_Int32 mnYMode
Mode for left position.
Definition: modelbase.hxx:108
double mfY
Left position of this object.
Definition: modelbase.hxx:104
sal_Int32 mnHMode
Mode for width.
Definition: modelbase.hxx:110
sal_Int32 mnWMode
Mode for top position.
Definition: modelbase.hxx:109
bool mbAutoLayout
Layout target for plot area.
Definition: modelbase.hxx:112
double mfH
Width of this object.
Definition: modelbase.hxx:106