fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / oox / source / drawingml / chart / converterbase.cxx
blob022d8675499d095dcf9cc1fc66b949bce9e098ee
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include "drawingml/chart/converterbase.hxx"
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/drawing/FillStyle.hpp>
31 #include <com/sun/star/drawing/LineStyle.hpp>
32 #include <com/sun/star/frame/XModel.hpp>
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <osl/diagnose.h>
35 #include "basegfx/numeric/ftools.hxx"
36 #include "oox/core/xmlfilterbase.hxx"
37 #include "oox/drawingml/theme.hxx"
38 #include <comphelper/processfactory.hxx>
40 namespace oox {
41 namespace drawingml {
42 namespace chart {
44 namespace cssc = ::com::sun::star::chart;
46 using namespace ::com::sun::star;
47 using namespace ::com::sun::star::chart2;
48 using namespace ::com::sun::star::drawing;
49 using namespace ::com::sun::star::frame;
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star::uno;
53 using ::oox::core::XmlFilterBase;
55 namespace {
57 struct TitleKey : public ::std::pair< ObjectType, ::std::pair< sal_Int32, sal_Int32 > >
59 inline explicit TitleKey( ObjectType eObjType, sal_Int32 nMainIdx = -1, sal_Int32 nSubIdx = -1 )
60 { first = eObjType; second.first = nMainIdx; second.second = nSubIdx; }
63 /** A helper structure to store all data related to title objects. Needed for
64 the conversion of manual title positions that needs the old Chart1 API.
66 struct TitleLayoutInfo
68 typedef Reference< XShape > (*GetShapeFunc)( const Reference< cssc::XChartDocument >& );
70 Reference< XTitle > mxTitle; /// The API title object.
71 ModelRef< LayoutModel > mxLayout; /// The layout model, if existing.
72 GetShapeFunc mpGetShape; /// Helper function to receive the title shape.
74 inline explicit TitleLayoutInfo() : mpGetShape( 0 ) {}
76 void convertTitlePos(
77 ConverterRoot& rRoot,
78 const Reference< cssc::XChartDocument >& rxChart1Doc );
81 void TitleLayoutInfo::convertTitlePos( ConverterRoot& rRoot, const Reference< cssc::XChartDocument >& rxChart1Doc )
83 if( mxTitle.is() && mpGetShape ) try
85 // try to get the title shape
86 Reference< XShape > xTitleShape = mpGetShape( rxChart1Doc );
87 // get title rotation angle, needed for correction of position of top-left edge
88 double fAngle = 0.0;
89 PropertySet aTitleProp( mxTitle );
90 aTitleProp.getProperty( fAngle, PROP_TextRotation );
91 // convert the position
92 LayoutModel& rLayout = mxLayout.getOrCreate();
93 LayoutConverter aLayoutConv( rRoot, rLayout );
94 aLayoutConv.convertFromModel( xTitleShape, fAngle );
96 catch( Exception& )
101 /* The following local functions implement getting the XShape interface of all
102 supported title objects (chart and axes). This needs some effort due to the
103 design of the old Chart1 API used to access these objects. */
105 /** A code fragment that returns a shape object from the passed shape supplier
106 using the specified interface function. Checks a boolean property first. */
107 #define OOX_FRAGMENT_GETTITLESHAPE( shape_supplier, supplier_func, property_name ) \
108 PropertySet aPropSet( shape_supplier ); \
109 if( shape_supplier.is() && aPropSet.getBoolProperty( PROP_##property_name ) ) \
110 return shape_supplier->supplier_func(); \
111 return Reference< XShape >(); \
113 /** Implements a function returning the drawing shape of an axis title, if
114 existing, using the specified API interface and its function. */
115 #define OOX_DEFINEFUNC_GETAXISTITLESHAPE( func_name, interface_type, supplier_func, property_name ) \
116 Reference< XShape > func_name( const Reference< cssc::XChartDocument >& rxChart1Doc ) \
118 Reference< cssc::interface_type > xAxisSupp( rxChart1Doc->getDiagram(), UNO_QUERY ); \
119 OOX_FRAGMENT_GETTITLESHAPE( xAxisSupp, supplier_func, property_name ) \
122 /** Returns the drawing shape of the main title, if existing. */
123 Reference< XShape > lclGetMainTitleShape( const Reference< cssc::XChartDocument >& rxChart1Doc )
125 OOX_FRAGMENT_GETTITLESHAPE( rxChart1Doc, getTitle, HasMainTitle )
128 OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetXAxisTitleShape, XAxisXSupplier, getXAxisTitle, HasXAxisTitle )
129 OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetYAxisTitleShape, XAxisYSupplier, getYAxisTitle, HasYAxisTitle )
130 OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetZAxisTitleShape, XAxisZSupplier, getZAxisTitle, HasZAxisTitle )
131 OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecXAxisTitleShape, XSecondAxisTitleSupplier, getSecondXAxisTitle, HasSecondaryXAxisTitle )
132 OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecYAxisTitleShape, XSecondAxisTitleSupplier, getSecondYAxisTitle, HasSecondaryYAxisTitle )
134 #undef OOX_DEFINEFUNC_GETAXISTITLESHAPE
135 #undef OOX_IMPLEMENT_GETTITLESHAPE
137 } // namespace
139 struct ConverterData
141 typedef ::std::map< TitleKey, TitleLayoutInfo > TitleMap;
143 ObjectFormatter maFormatter;
144 TitleMap maTitles;
145 XmlFilterBase& mrFilter;
146 ChartConverter& mrConverter;
147 Reference< XChartDocument > mxDoc;
148 awt::Size maSize;
150 explicit ConverterData(
151 XmlFilterBase& rFilter,
152 ChartConverter& rChartConverter,
153 const ChartSpaceModel& rChartModel,
154 const Reference< XChartDocument >& rxChartDoc,
155 const awt::Size& rChartSize );
156 ~ConverterData();
159 ConverterData::ConverterData(
160 XmlFilterBase& rFilter,
161 ChartConverter& rChartConverter,
162 const ChartSpaceModel& rChartModel,
163 const Reference< XChartDocument >& rxChartDoc,
164 const awt::Size& rChartSize ) :
165 maFormatter( rFilter, rxChartDoc, rChartModel ),
166 mrFilter( rFilter ),
167 mrConverter( rChartConverter ),
168 mxDoc( rxChartDoc ),
169 maSize( rChartSize )
171 OSL_ENSURE( mxDoc.is(), "ConverterData::ConverterData - missing chart document" );
172 // lock the model to suppress internal updates during conversion
175 mxDoc->lockControllers();
177 catch( Exception& )
181 // prepare conversion of title positions
182 maTitles[ TitleKey( OBJECTTYPE_CHARTTITLE ) ].mpGetShape = lclGetMainTitleShape;
183 maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_X_AXIS ) ].mpGetShape = lclGetXAxisTitleShape;
184 maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_Y_AXIS ) ].mpGetShape = lclGetYAxisTitleShape;
185 maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_Z_AXIS ) ].mpGetShape = lclGetZAxisTitleShape;
186 maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_SECN_AXESSET, API_X_AXIS ) ].mpGetShape = lclGetSecXAxisTitleShape;
187 maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_SECN_AXESSET, API_Y_AXIS ) ].mpGetShape = lclGetSecYAxisTitleShape;
190 ConverterData::~ConverterData()
192 // unlock the model
195 mxDoc->unlockControllers();
197 catch( Exception& )
202 ConverterRoot::ConverterRoot(
203 XmlFilterBase& rFilter,
204 ChartConverter& rChartConverter,
205 const ChartSpaceModel& rChartModel,
206 const Reference< XChartDocument >& rxChartDoc,
207 const awt::Size& rChartSize ) :
208 mxData( new ConverterData( rFilter, rChartConverter, rChartModel, rxChartDoc, rChartSize ) )
212 ConverterRoot::~ConverterRoot()
216 Reference< XInterface > ConverterRoot::createInstance( const OUString& rServiceName ) const
218 Reference< XInterface > xInt;
221 Reference<XMultiServiceFactory> xMSF = Reference<XMultiServiceFactory>(getComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW);
223 xInt = xMSF->createInstance( rServiceName );
225 catch( Exception& )
228 OSL_ENSURE( xInt.is(), "ConverterRoot::createInstance - cannot create instance" );
229 return xInt;
232 Reference< XComponentContext > ConverterRoot::getComponentContext() const
234 return mxData->mrFilter.getComponentContext();
237 XmlFilterBase& ConverterRoot::getFilter() const
239 return mxData->mrFilter;
242 ChartConverter* ConverterRoot::getChartConverter() const
244 return &mxData->mrConverter;
247 Reference< XChartDocument > ConverterRoot::getChartDocument() const
249 return mxData->mxDoc;
252 const awt::Size& ConverterRoot::getChartSize() const
254 return mxData->maSize;
257 ObjectFormatter& ConverterRoot::getFormatter() const
259 return mxData->maFormatter;
262 void ConverterRoot::registerTitleLayout( const Reference< XTitle >& rxTitle,
263 const ModelRef< LayoutModel >& rxLayout, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx )
265 OSL_ENSURE( rxTitle.is(), "ConverterRoot::registerTitleLayout - missing title object" );
266 TitleLayoutInfo& rTitleInfo = mxData->maTitles[ TitleKey( eObjType, nMainIdx, nSubIdx ) ];
267 OSL_ENSURE( rTitleInfo.mpGetShape, "ConverterRoot::registerTitleLayout - invalid title key" );
268 rTitleInfo.mxTitle = rxTitle;
269 rTitleInfo.mxLayout = rxLayout;
272 void ConverterRoot::convertTitlePositions()
276 Reference< cssc::XChartDocument > xChart1Doc( mxData->mxDoc, UNO_QUERY_THROW );
277 for( ConverterData::TitleMap::iterator aIt = mxData->maTitles.begin(), aEnd = mxData->maTitles.end(); aIt != aEnd; ++aIt )
278 aIt->second.convertTitlePos( *this, xChart1Doc );
280 catch( Exception& )
285 namespace {
287 /** Returns a position value in the chart area in 1/100 mm. */
288 sal_Int32 lclCalcPosition( sal_Int32 nChartSize, double fPos, sal_Int32 nPosMode )
290 switch( nPosMode )
292 case XML_edge: // absolute start position as factor of chart size
293 return getLimitedValue< sal_Int32, double >( nChartSize * fPos + 0.5, 0, nChartSize );
294 case XML_factor: // position relative to object default position
295 OSL_FAIL( "lclCalcPosition - relative positioning not supported" );
296 return -1;
299 OSL_FAIL( "lclCalcPosition - unknown positioning mode" );
300 return -1;
303 /** Returns a size value in the chart area in 1/100 mm. */
304 sal_Int32 lclCalcSize( sal_Int32 nPos, sal_Int32 nChartSize, double fSize, sal_Int32 nSizeMode )
306 sal_Int32 nValue = getLimitedValue< sal_Int32, double >( nChartSize * fSize + 0.5, 0, nChartSize );
307 switch( nSizeMode )
309 case XML_factor: // passed value is width/height
310 return nValue;
311 case XML_edge: // passed value is right/bottom position
312 return nValue - nPos + 1;
315 OSL_FAIL( "lclCalcSize - unknown size mode" );
316 return -1;
319 /** Returns a relative size value in the chart area. */
320 double lclCalcRelSize( double fPos, double fSize, sal_Int32 nSizeMode )
322 switch( nSizeMode )
324 case XML_factor: // passed value is width/height
325 break;
326 case XML_edge: // passed value is right/bottom position
327 fSize -= fPos;
328 break;
329 default:
330 OSL_ENSURE( false, "lclCalcRelSize - unknown size mode" );
331 fSize = 0.0;
333 return getLimitedValue< double, double >( fSize, 0.0, 1.0 - fPos );
336 } // namespace
338 LayoutConverter::LayoutConverter( const ConverterRoot& rParent, LayoutModel& rModel ) :
339 ConverterBase< LayoutModel >( rParent, rModel )
343 LayoutConverter::~LayoutConverter()
347 bool LayoutConverter::calcAbsRectangle( awt::Rectangle& orRect ) const
349 if( !mrModel.mbAutoLayout )
351 const awt::Size& rChartSize = getChartSize();
352 orRect.X = lclCalcPosition( rChartSize.Width, mrModel.mfX, mrModel.mnXMode );
353 orRect.Y = lclCalcPosition( rChartSize.Height, mrModel.mfY, mrModel.mnYMode );
354 if( (orRect.X >= 0) && (orRect.Y >= 0) )
356 orRect.Width = lclCalcSize( orRect.X, rChartSize.Width, mrModel.mfW, mrModel.mnWMode );
357 orRect.Height = lclCalcSize( orRect.Y, rChartSize.Height, mrModel.mfH, mrModel.mnHMode );
358 return (orRect.Width > 0) && (orRect.Height > 0);
361 return false;
364 bool LayoutConverter::convertFromModel( PropertySet& rPropSet )
366 if( !mrModel.mbAutoLayout &&
367 (mrModel.mnXMode == XML_edge) && (mrModel.mfX >= 0.0) &&
368 (mrModel.mnYMode == XML_edge) && (mrModel.mfY >= 0.0) )
370 RelativePosition aPos(
371 getLimitedValue< double, double >( mrModel.mfX, 0.0, 1.0 ),
372 getLimitedValue< double, double >( mrModel.mfY, 0.0, 1.0 ),
373 Alignment_TOP_LEFT );
374 rPropSet.setProperty( PROP_RelativePosition, aPos );
376 RelativeSize aSize(
377 lclCalcRelSize( aPos.Primary, mrModel.mfW, mrModel.mnWMode ),
378 lclCalcRelSize( aPos.Secondary, mrModel.mfH, mrModel.mnHMode ) );
379 if( (aSize.Primary > 0.0) && (aSize.Secondary > 0.0) )
381 rPropSet.setProperty( PROP_RelativeSize, aSize );
382 return true;
385 return false;
388 bool LayoutConverter::convertFromModel( const Reference< XShape >& rxShape, double fRotationAngle )
390 if( !mrModel.mbAutoLayout )
392 const awt::Size& rChartSize = getChartSize();
393 awt::Point aShapePos(
394 lclCalcPosition( rChartSize.Width, mrModel.mfX, mrModel.mnXMode ),
395 lclCalcPosition( rChartSize.Height, mrModel.mfY, mrModel.mnYMode ) );
396 if( (aShapePos.X >= 0) && (aShapePos.Y >= 0) )
398 // the call to XShape.getSize() may recalc the chart view
399 awt::Size aShapeSize = rxShape->getSize();
400 // rotated shapes need special handling...
401 double fSin = fabs( sin( fRotationAngle * F_PI180 ) );
402 // add part of height to X direction, if title is rotated down
403 if( fRotationAngle > 180.0 )
404 aShapePos.X += static_cast< sal_Int32 >( fSin * aShapeSize.Height + 0.5 );
405 // add part of width to Y direction, if title is rotated up
406 else if( fRotationAngle > 0.0 )
407 aShapePos.Y += static_cast< sal_Int32 >( fSin * aShapeSize.Width + 0.5 );
408 // set the resulting position at the shape
409 rxShape->setPosition( aShapePos );
410 return true;
413 return false;
416 } // namespace chart
417 } // namespace drawingml
418 } // namespace oox
420 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */