bump product version to 5.0.4.1
[LibreOffice.git] / oox / source / ppt / pptshape.cxx
blobcf61562ae6ad61acef08de3813bf65305a2ab0c2
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 "oox/ppt/pptshape.hxx"
21 #include "oox/core/xmlfilterbase.hxx"
22 #include "drawingml/textbody.hxx"
24 #include <com/sun/star/container/XNamed.hpp>
25 #include <com/sun/star/beans/XMultiPropertySet.hpp>
26 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
28 #include <com/sun/star/text/XText.hpp>
29 #include <basegfx/matrix/b2dhommatrix.hxx>
30 #include "oox/ppt/slidepersist.hxx"
32 using namespace ::oox::core;
33 using namespace ::oox::drawingml;
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::awt;
36 using namespace ::com::sun::star::uno;
37 using namespace ::com::sun::star::beans;
38 using namespace ::com::sun::star::frame;
39 using namespace ::com::sun::star::text;
40 using namespace ::com::sun::star::drawing;
42 namespace oox { namespace ppt {
44 PPTShape::PPTShape( const oox::ppt::ShapeLocation eShapeLocation, const sal_Char* pServiceName )
45 : Shape( pServiceName )
46 , meShapeLocation( eShapeLocation )
47 , mbReferenced( false )
51 PPTShape::~PPTShape()
55 static const char* lclDebugSubType( sal_Int32 nType )
57 switch (nType) {
58 case XML_ctrTitle :
59 return "ctrTitle";
60 case XML_title :
61 return "title";
62 case XML_subTitle :
63 return "subTitle";
64 case XML_obj :
65 return "obj";
66 case XML_body :
67 return "body";
68 case XML_dt :
69 return "dt";
70 case XML_hdr :
71 return "hdr";
72 case XML_ftr :
73 return "frt";
74 case XML_sldNum :
75 return "sldNum";
76 case XML_sldImg :
77 return "sldImg";
80 return "unknown - please extend lclDebugSubType";
83 oox::drawingml::TextListStylePtr PPTShape::getSubTypeTextListStyle( const SlidePersist& rSlidePersist, sal_Int32 nSubType )
85 oox::drawingml::TextListStylePtr pTextListStyle;
87 SAL_INFO("oox.ppt", "subtype style: " << lclDebugSubType( nSubType ) );
89 switch( nSubType )
91 case XML_ctrTitle :
92 case XML_title :
93 pTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle();
94 break;
95 case XML_subTitle :
96 case XML_obj :
97 case XML_body :
98 if ( rSlidePersist.isNotesPage() )
99 pTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle();
100 else
101 pTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
102 break;
105 return pTextListStyle;
108 void PPTShape::addShape(
109 oox::core::XmlFilterBase& rFilterBase,
110 SlidePersist& rSlidePersist,
111 const oox::drawingml::Theme* pTheme,
112 const Reference< XShapes >& rxShapes,
113 basegfx::B2DHomMatrix& aTransformation,
114 const awt::Rectangle* pShapeRect,
115 ::oox::drawingml::ShapeIdMap* pShapeMap )
117 SAL_INFO("oox.ppt","add shape id: " << msId << " location: " << ((meShapeLocation == Master) ? "master" : ((meShapeLocation == Slide) ? "slide" : ((meShapeLocation == Layout) ? "layout" : "other"))) << " subtype: " << mnSubType << " service: " << msServiceName);
118 // only placeholder from layout are being inserted
119 if ( mnSubType && ( meShapeLocation == Master ) )
120 return;
123 OUString sServiceName( msServiceName );
124 if( !sServiceName.isEmpty() )
126 oox::drawingml::TextListStylePtr aMasterTextListStyle;
127 Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW );
128 bool bClearText = false;
130 if ( sServiceName != "com.sun.star.drawing.GraphicObjectShape" &&
131 sServiceName != "com.sun.star.drawing.OLE2Shape" )
133 const OUString sOutlinerShapeService( "com.sun.star.presentation.OutlinerShape" );
134 SAL_INFO("oox.ppt","has master: " << std::hex << rSlidePersist.getMasterPersist().get());
135 switch( mnSubType )
137 case XML_ctrTitle :
138 case XML_title :
140 sServiceName = "com.sun.star.presentation.TitleTextShape";
141 aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle();
142 bClearText = true;
144 break;
145 case XML_subTitle :
147 sServiceName = "com.sun.star.presentation.SubtitleShape";
148 aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
149 bClearText = true;
151 break;
152 case XML_obj :
154 sServiceName = sOutlinerShapeService;
155 aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
157 break;
158 case XML_body :
160 if ( rSlidePersist.isNotesPage() )
162 sServiceName = "com.sun.star.presentation.NotesShape";
163 aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle();
165 else
167 sServiceName = sOutlinerShapeService;
168 aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
171 break;
172 case XML_dt :
173 sServiceName = "com.sun.star.presentation.DateTimeShape";
174 bClearText = true;
175 break;
176 case XML_hdr :
177 sServiceName = "com.sun.star.presentation.HeaderShape";
178 bClearText = true;
179 break;
180 case XML_ftr :
181 sServiceName = "com.sun.star.presentation.FooterShape";
182 bClearText = true;
183 break;
184 case XML_sldNum :
185 sServiceName = "com.sun.star.presentation.SlideNumberShape";
186 bClearText = true;
187 break;
188 case XML_sldImg :
189 sServiceName = "com.sun.star.presentation.PageShape";
190 break;
191 case XML_chart :
192 if ( meShapeLocation == Layout )
193 sServiceName = sOutlinerShapeService;
194 else
195 sServiceName = "com.sun.star.presentation.ChartShape";
196 break;
197 case XML_tbl :
198 if ( meShapeLocation == Layout )
199 sServiceName = sOutlinerShapeService;
200 else
201 sServiceName = "com.sun.star.presentation.TableShape";
202 break;
203 case XML_pic :
204 if ( meShapeLocation == Layout )
205 sServiceName = sOutlinerShapeService;
206 else
207 sServiceName = "com.sun.star.presentation.GraphicObjectShape";
208 break;
209 case XML_media :
210 if ( meShapeLocation == Layout )
211 sServiceName = sOutlinerShapeService;
212 else
213 sServiceName = "com.sun.star.presentation.MediaShape";
214 break;
215 default:
216 if ( mnSubType && meShapeLocation == Layout )
217 sServiceName = sOutlinerShapeService;
218 break;
222 SAL_INFO("oox.ppt","shape service: " << sServiceName);
224 if( mnSubType && getSubTypeIndex().has() && meShapeLocation == Layout ) {
225 oox::drawingml::ShapePtr pPlaceholder = PPTShape::findPlaceholderByIndex( getSubTypeIndex().get(), rSlidePersist.getShapes()->getChildren(), true );
226 if (!pPlaceholder.get())
227 pPlaceholder = PPTShape::findPlaceholder( mnSubType, 0, getSubTypeIndex(), rSlidePersist.getShapes()->getChildren(), true );
229 if (pPlaceholder.get()) {
230 if( maSize.Width == 0 || maSize.Height == 0 ) {
231 awt::Size aSize = maSize;
232 if( maSize.Width == 0 )
233 aSize.Width = pPlaceholder->getSize().Width;
234 if( maSize.Height == 0 )
235 aSize.Height = pPlaceholder->getSize().Height;
236 setSize( aSize );
237 if ( maPosition.X == 0 || maPosition.Y == 0 ) {
238 awt::Point aPosition = maPosition;
239 if( maPosition.X == 0 )
240 aPosition.X = pPlaceholder->getPosition().X;
241 if( maPosition.Y == 0 )
242 aPosition.Y = pPlaceholder->getPosition().Y;
243 setPosition( aPosition );
249 // use placeholder index if possible
250 if( mnSubType && getSubTypeIndex().has() && rSlidePersist.getMasterPersist().get() ) {
251 oox::drawingml::ShapePtr pPlaceholder = PPTShape::findPlaceholderByIndex( getSubTypeIndex().get(), rSlidePersist.getMasterPersist()->getShapes()->getChildren() );
252 // TODO: Check if this is required for non-notes slides as well...
253 if( rSlidePersist.isNotesPage() && pPlaceholder.get() && pPlaceholder->getSubType() != getSubType() )
254 pPlaceholder.reset();
256 if( pPlaceholder.get()) {
257 SAL_INFO("oox.ppt","found placeholder with index: " << getSubTypeIndex().get() << " and type: " << lclDebugSubType( mnSubType ));
259 if( pPlaceholder.get() ) {
260 PPTShape* pPPTPlaceholder = dynamic_cast< PPTShape* >( pPlaceholder.get() );
261 TextListStylePtr pNewTextListStyle ( new TextListStyle() );
263 if( pPlaceholder->getTextBody() ) {
265 pNewTextListStyle->apply( pPlaceholder->getTextBody()->getTextListStyle() );
266 if( pPlaceholder->getMasterTextListStyle().get() )
267 pNewTextListStyle->apply( *pPlaceholder->getMasterTextListStyle() );
269 // SAL_INFO("oox.ppt","placeholder body style");
270 // pPlaceholder->getTextBody()->getTextListStyle().dump();
271 // SAL_INFO("oox.ppt","master text list style");
272 // pPlaceholder->getMasterTextListStyle()->dump();
274 aMasterTextListStyle = pNewTextListStyle;
275 // SAL_INFO("oox.ppt","combined master text list style");
276 // aMasterTextListStyle->dump();
278 if( pPPTPlaceholder && pPPTPlaceholder->mpPlaceholder.get() ) {
279 SAL_INFO("oox.ppt","placeholder has parent placeholder: " << pPPTPlaceholder->mpPlaceholder->getId() << " type: " << lclDebugSubType( pPPTPlaceholder->mpPlaceholder->getSubType() ) << " index: " << pPPTPlaceholder->mpPlaceholder->getSubTypeIndex().get() );
280 SAL_INFO("oox.ppt","has textbody " << (pPPTPlaceholder->mpPlaceholder->getTextBody() != 0) );
281 TextListStylePtr pPlaceholderStyle = getSubTypeTextListStyle( rSlidePersist, pPPTPlaceholder->mpPlaceholder->getSubType() );
282 if( pPPTPlaceholder->mpPlaceholder->getTextBody() )
283 pNewTextListStyle->apply( pPPTPlaceholder->mpPlaceholder->getTextBody()->getTextListStyle() );
284 if( pPlaceholderStyle.get() ) {
285 pNewTextListStyle->apply( *pPlaceholderStyle );
286 //pPlaceholderStyle->dump();
289 } else if( !mpPlaceholder.get() ) {
290 aMasterTextListStyle.reset();
292 SAL_INFO("oox.ppt","placeholder id: " << (pPlaceholder.get() ? pPlaceholder->getId() : "not found"));
295 if ( !sServiceName.isEmpty() )
297 if ( !aMasterTextListStyle.get() )
299 bool isOther = !getTextBody().get() && sServiceName != "com.sun.star.drawing.GroupShape";
300 TextListStylePtr aSlideStyle = isOther ? rSlidePersist.getOtherTextStyle() : rSlidePersist.getDefaultTextStyle();
301 // Combine from MasterSlide details as well.
302 if( rSlidePersist.getMasterPersist().get() )
304 aMasterTextListStyle = isOther ? rSlidePersist.getMasterPersist()->getOtherTextStyle() : rSlidePersist.getMasterPersist()->getDefaultTextStyle();
305 if( aSlideStyle.get() )
306 aMasterTextListStyle->apply( *aSlideStyle.get() );
308 else
310 aMasterTextListStyle = aSlideStyle;
314 if( aMasterTextListStyle.get() && getTextBody().get() ) {
315 TextListStylePtr aCombinedTextListStyle (new TextListStyle());
317 aCombinedTextListStyle->apply( *aMasterTextListStyle.get() );
319 if( mpPlaceholder.get() && mpPlaceholder->getTextBody().get() )
320 aCombinedTextListStyle->apply( mpPlaceholder->getTextBody()->getTextListStyle() );
321 aCombinedTextListStyle->apply( getTextBody()->getTextListStyle() );
323 setMasterTextListStyle( aCombinedTextListStyle );
324 } else
325 setMasterTextListStyle( aMasterTextListStyle );
327 Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, pShapeRect, bClearText, mpPlaceholder.get() != NULL, aTransformation, getFillProperties() ) );
328 if ( !rSlidePersist.isMasterPage() && rSlidePersist.getPage().is() && ( (sal_Int32)mnSubType == XML_title ) )
332 OUString aTitleText;
333 Reference< XTextRange > xText( xShape, UNO_QUERY_THROW );
334 aTitleText = xText->getString();
335 if ( !aTitleText.isEmpty() && ( aTitleText.getLength() < 64 ) ) // just a magic value, but we don't want to set slide names which are too long
337 Reference< container::XNamed > xName( rSlidePersist.getPage(), UNO_QUERY_THROW );
338 xName->setName( aTitleText );
341 catch( uno::Exception& )
346 if( pShapeMap )
348 // bnc#705982 - if optional model id reference is
349 // there, use that to obtain target shape
350 if( !msModelId.isEmpty() )
352 (*pShapeMap)[ msModelId ] = shared_from_this();
354 else if( !msId.isEmpty() )
356 (*pShapeMap)[ msId ] = shared_from_this();
360 // if this is a group shape, we have to add also each child shape
361 Reference< XShapes > xShapes( xShape, UNO_QUERY );
362 if ( xShapes.is() )
363 addChildren( rFilterBase, *this, pTheme, xShapes, pShapeRect ? *pShapeRect : awt::Rectangle( maPosition.X, maPosition.Y, maSize.Width, maSize.Height ), pShapeMap, aTransformation );
367 catch( const Exception& )
372 void PPTShape::applyShapeReference( const oox::drawingml::Shape& rReferencedShape, bool bUseText )
374 Shape::applyShapeReference( rReferencedShape, bUseText );
377 namespace
379 bool ShapeLocationIsMaster(oox::drawingml::Shape *pInShape)
381 PPTShape* pShape = dynamic_cast<PPTShape*>(pInShape);
382 return pShape && pShape->getShapeLocation() == Master;
386 // Function to find placeholder (ph) for a shape. No idea how MSO implements this, but
387 // this order seems to work quite well (probably it's unnecessary complicated / wrong):
388 // 1. ph with nFirstSubType and the same oSubTypeIndex
389 // 2. ph with nFirstSubType
390 // 3. ph with nSecondSubType and the same oSubTypeIndex
391 // 4. ph with nSecondSubType
392 // 5. ph with the same oSubTypeIndex
393 oox::drawingml::ShapePtr PPTShape::findPlaceholder( sal_Int32 nFirstSubType, sal_Int32 nSecondSubType,
394 const OptValue< sal_Int32 >& oSubTypeIndex, std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly )
396 oox::drawingml::ShapePtr aShapePtr;
397 oox::drawingml::ShapePtr aChoiceShapePtr1;
398 oox::drawingml::ShapePtr aChoiceShapePtr2;
399 oox::drawingml::ShapePtr aChoiceShapePtr3;
400 oox::drawingml::ShapePtr aChoiceShapePtr4;
401 std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() );
402 while (aRevIter != rShapes.rend())
404 if (!bMasterOnly || ShapeLocationIsMaster((*aRevIter).get()))
406 if ((*aRevIter)->getSubTypeIndex() == oSubTypeIndex)
408 if ((*aRevIter)->getSubType() == nFirstSubType)
410 aShapePtr = *aRevIter;
411 break;
413 else if ((*aRevIter)->getSubType() == nSecondSubType && !aChoiceShapePtr2.get())
414 aChoiceShapePtr2 = *aRevIter;
415 else if (!aChoiceShapePtr4.get())
416 aChoiceShapePtr4 = *aRevIter;
418 else if ((*aRevIter)->getSubType() == nFirstSubType && !aChoiceShapePtr1.get())
419 aChoiceShapePtr1 = *aRevIter;
420 else if ((*aRevIter)->getSubType() == nSecondSubType && !aChoiceShapePtr3.get())
421 aChoiceShapePtr3 = *aRevIter;
423 std::vector< oox::drawingml::ShapePtr >& rChildren = (*aRevIter)->getChildren();
424 aChoiceShapePtr4 = findPlaceholder( nFirstSubType, nSecondSubType, oSubTypeIndex, rChildren, bMasterOnly );
425 if (aChoiceShapePtr4.get())
427 if (aChoiceShapePtr4->getSubType() == nFirstSubType)
429 if (aChoiceShapePtr4->getSubTypeIndex() == oSubTypeIndex)
430 aShapePtr = aChoiceShapePtr4;
431 else
432 aChoiceShapePtr1 = aChoiceShapePtr4;
434 else if (aChoiceShapePtr4->getSubType() == nSecondSubType)
436 if (aChoiceShapePtr4->getSubTypeIndex() == oSubTypeIndex)
437 aChoiceShapePtr2 = aChoiceShapePtr4;
438 else
439 aChoiceShapePtr3 = aChoiceShapePtr4;
442 if (aShapePtr.get())
443 break;
444 ++aRevIter;
446 if (aShapePtr.get())
447 return aShapePtr;
448 if (aChoiceShapePtr1.get())
449 return aChoiceShapePtr1;
450 if (aChoiceShapePtr2.get())
451 return aChoiceShapePtr2;
452 if (aChoiceShapePtr3.get())
453 return aChoiceShapePtr3;
454 return aChoiceShapePtr4;
457 oox::drawingml::ShapePtr PPTShape::findPlaceholderByIndex( const sal_Int32 nIdx, std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly )
459 oox::drawingml::ShapePtr aShapePtr;
461 std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() );
462 while( aRevIter != rShapes.rend() )
464 if ( (*aRevIter)->getSubTypeIndex().has() && (*aRevIter)->getSubTypeIndex().get() == nIdx &&
465 ( !bMasterOnly || ShapeLocationIsMaster((*aRevIter).get()) ) )
467 aShapePtr = *aRevIter;
468 break;
470 std::vector< oox::drawingml::ShapePtr >& rChildren = (*aRevIter)->getChildren();
471 aShapePtr = findPlaceholderByIndex( nIdx, rChildren, bMasterOnly );
472 if ( aShapePtr.get() )
473 break;
474 ++aRevIter;
476 return aShapePtr;
481 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */