bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / customshapes / EnhancedCustomShapeEngine.cxx
blobc78641fcb78e9cd86b82ce3351f03b93ba00d8c8
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 <com/sun/star/uno/Reference.h>
21 #include <com/sun/star/uno/RuntimeException.hpp>
22 #include <com/sun/star/uno/XComponentContext.hpp>
23 #include <com/sun/star/awt/Rectangle.hpp>
24 #include <com/sun/star/beans/PropertyValue.hpp>
25 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
26 #include <com/sun/star/lang/XInitialization.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <com/sun/star/drawing/XCustomShapeEngine.hpp>
29 #include <rtl/ref.hxx>
30 #include "svx/EnhancedCustomShape2d.hxx"
31 #include "EnhancedCustomShape3d.hxx"
32 #include "EnhancedCustomShapeFontWork.hxx"
33 #include "EnhancedCustomShapeHandle.hxx"
34 #include "svx/EnhancedCustomShapeGeometry.hxx"
35 #include <svx/unoshape.hxx>
36 #include "svx/unopage.hxx"
37 #include "svx/unoapi.hxx"
38 #include <svx/svdobj.hxx>
39 #include <svx/svdoashp.hxx>
40 #include <svx/svdogrp.hxx>
41 #include <svx/svdorect.hxx>
42 #include <editeng/outlobj.hxx>
43 #include <editeng/outliner.hxx>
44 #include <svx/svdoutl.hxx>
45 #include <svl/itemset.hxx>
46 #include <svx/svdopath.hxx>
47 #include <svx/svdpage.hxx>
48 #include <svx/svdmodel.hxx>
49 #include "svx/svditer.hxx"
50 #include <uno/mapping.hxx>
51 #include <basegfx/polygon/b2dpolypolygontools.hxx>
52 #include <basegfx/tools/unotools.hxx>
53 #include <com/sun/star/document/XActionLockable.hpp>
54 #include <cppuhelper/implbase3.hxx>
55 #include <cppuhelper/supportsservice.hxx>
57 using namespace css;
58 using namespace css::uno;
60 class SdrObject;
61 class SdrObjCustomShape;
63 namespace {
65 class EnhancedCustomShapeEngine : public cppu::WeakImplHelper3
67 css::lang::XInitialization,
68 css::lang::XServiceInfo,
69 css::drawing::XCustomShapeEngine
72 css::uno::Reference< css::drawing::XShape > mxShape;
73 bool mbForceGroupWithText;
75 SdrObject* ImplForceGroupWithText( const SdrObjCustomShape* pCustoObj, SdrObject* pRenderedShape );
77 public:
78 EnhancedCustomShapeEngine();
79 virtual ~EnhancedCustomShapeEngine();
81 // XInterface
82 virtual void SAL_CALL acquire() throw() SAL_OVERRIDE;
83 virtual void SAL_CALL release() throw() SAL_OVERRIDE;
85 // XInitialization
86 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
87 throw ( css::uno::Exception, css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
89 // XServiceInfo
90 virtual OUString SAL_CALL getImplementationName()
91 throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
92 virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName )
93 throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
94 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames()
95 throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
97 // XCustomShapeEngine
98 virtual css::uno::Reference< css::drawing::XShape > SAL_CALL render()
99 throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
100 virtual css::awt::Rectangle SAL_CALL getTextBounds()
101 throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
102 virtual css::drawing::PolyPolygonBezierCoords SAL_CALL getLineGeometry()
103 throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
104 virtual css::uno::Sequence< css::uno::Reference< css::drawing::XCustomShapeHandle > > SAL_CALL getInteraction()
105 throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
108 EnhancedCustomShapeEngine::EnhancedCustomShapeEngine() :
109 mbForceGroupWithText ( false )
112 EnhancedCustomShapeEngine::~EnhancedCustomShapeEngine()
116 // XInterface
117 void SAL_CALL EnhancedCustomShapeEngine::acquire() throw()
119 OWeakObject::acquire();
121 void SAL_CALL EnhancedCustomShapeEngine::release() throw()
123 OWeakObject::release();
126 // XInitialization
127 void SAL_CALL EnhancedCustomShapeEngine::initialize( const Sequence< Any >& aArguments )
128 throw ( Exception, RuntimeException, std::exception )
130 sal_Int32 i;
131 Sequence< beans::PropertyValue > aParameter;
132 for ( i = 0; i < aArguments.getLength(); i++ )
134 if ( aArguments[ i ] >>= aParameter )
135 break;
137 for ( i = 0; i < aParameter.getLength(); i++ )
139 const beans::PropertyValue& rProp = aParameter[ i ];
140 if ( rProp.Name == "CustomShape" )
141 rProp.Value >>= mxShape;
142 else if ( rProp.Name == "ForceGroupWithText" )
143 rProp.Value >>= mbForceGroupWithText;
147 // XServiceInfo
148 OUString SAL_CALL EnhancedCustomShapeEngine::getImplementationName()
149 throw( RuntimeException, std::exception )
151 return OUString( "com.sun.star.drawing.EnhancedCustomShapeEngine" );
153 sal_Bool SAL_CALL EnhancedCustomShapeEngine::supportsService( const OUString& rServiceName )
154 throw( RuntimeException, std::exception )
156 return cppu::supportsService(this, rServiceName);
158 Sequence< OUString > SAL_CALL EnhancedCustomShapeEngine::getSupportedServiceNames()
159 throw ( RuntimeException, std::exception )
161 Sequence< OUString > aRet(1);
162 OUString* pArray = aRet.getArray();
163 pArray[0] = "com.sun.star.drawing.CustomShapeEngine";
164 return aRet;
167 // XCustomShapeEngine
168 SdrObject* EnhancedCustomShapeEngine::ImplForceGroupWithText( const SdrObjCustomShape* pCustoObj, SdrObject* pRenderedShape )
170 bool bHasText = pCustoObj->HasText();
171 if ( pRenderedShape || bHasText )
173 // applying shadow
174 const SdrObject* pShadowGeometry = pCustoObj->GetSdrObjectShadowFromCustomShape();
175 if ( pShadowGeometry )
177 if ( pRenderedShape )
179 if ( !pRenderedShape->ISA( SdrObjGroup ) )
181 SdrObject* pTmp = pRenderedShape;
182 pRenderedShape = new SdrObjGroup();
183 static_cast<SdrObjGroup*>(pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
185 static_cast<SdrObjGroup*>(pRenderedShape)->GetSubList()->NbcInsertObject( pShadowGeometry->Clone(), 0 );
187 else
188 pRenderedShape = pShadowGeometry->Clone();
191 // apply text
192 if ( bHasText )
194 // #i37011# also create a text object and add at rPos + 1
195 SdrObject* pTextObj = SdrObjFactory::MakeNewObject(
196 pCustoObj->GetObjInventor(), OBJ_TEXT, 0L, pCustoObj->GetModel());
198 // Copy text content
199 OutlinerParaObject* pParaObj = pCustoObj->GetOutlinerParaObject();
200 if( pParaObj )
201 pTextObj->NbcSetOutlinerParaObject( new OutlinerParaObject(*pParaObj) );
203 // copy all attributes
204 SfxItemSet aTargetItemSet( pCustoObj->GetMergedItemSet() );
206 // clear fill and line style
207 aTargetItemSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
208 aTargetItemSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
210 // get the text bounds and set at text object
211 Rectangle aTextBounds = pCustoObj->GetSnapRect();
212 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
213 if ( pSdrObjCustomShape )
215 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
216 aTextBounds = aCustomShape2d.GetTextRect();
218 pTextObj->SetSnapRect( aTextBounds );
220 // if rotated, copy GeoStat, too.
221 const GeoStat& rSourceGeo = pCustoObj->GetGeoStat();
222 if ( rSourceGeo.nRotationAngle )
224 pTextObj->NbcRotate(
225 pCustoObj->GetSnapRect().Center(), rSourceGeo.nRotationAngle,
226 rSourceGeo.nSin, rSourceGeo.nCos);
229 // set modified ItemSet at text object
230 pTextObj->SetMergedItemSet(aTargetItemSet);
232 if ( pRenderedShape )
234 if ( !pRenderedShape->ISA( SdrObjGroup ) )
236 SdrObject* pTmp = pRenderedShape;
237 pRenderedShape = new SdrObjGroup();
238 static_cast<SdrObjGroup*>(pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
240 static_cast<SdrObjGroup*>(pRenderedShape)->GetSubList()->NbcInsertObject( pTextObj );
242 else
243 pRenderedShape = pTextObj;
246 // force group
247 if ( pRenderedShape )
249 if ( !pRenderedShape->ISA( SdrObjGroup ) )
251 SdrObject* pTmp = pRenderedShape;
252 pRenderedShape = new SdrObjGroup();
253 static_cast<SdrObjGroup*>(pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
255 pRenderedShape->SetPage( pCustoObj->GetPage() );
256 pRenderedShape->SetModel( pCustoObj->GetModel() );
259 return pRenderedShape;
262 void SetTemporary( uno::Reference< drawing::XShape >& xShape )
264 if ( xShape.is() )
266 SvxShape* pShape = SvxShape::getImplementation( xShape );
267 if ( pShape )
268 pShape->TakeSdrObjectOwnership();
272 Reference< drawing::XShape > SAL_CALL EnhancedCustomShapeEngine::render()
273 throw ( RuntimeException, std::exception )
275 Reference< drawing::XShape > xShape;
276 SdrObject* pSdrObjCustomShape( PTR_CAST( SdrObjCustomShape, GetSdrObjectFromXShape( mxShape ) ) );
277 if ( pSdrObjCustomShape )
279 // retrieving the TextPath property to check if feature is enabled
280 const SdrCustomShapeGeometryItem& rGeometryItem = static_cast<const SdrCustomShapeGeometryItem&>(
281 pSdrObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
282 bool bTextPathOn = false;
283 const uno::Any* pAny = rGeometryItem.GetPropertyValueByName( "TextPath", "TextPath" );
284 if ( pAny )
285 *pAny >>= bTextPathOn;
287 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
288 sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
289 bool bPostRotateAngle = aCustomShape2d.IsPostRotate();
291 bool bFlipV = aCustomShape2d.IsFlipVert();
292 bool bFlipH = aCustomShape2d.IsFlipHorz();
293 bool bLineGeometryNeededOnly = bTextPathOn;
295 SdrObject* pRenderedShape = aCustomShape2d.CreateObject( bLineGeometryNeededOnly );
296 if ( pRenderedShape )
298 if ( bTextPathOn )
300 SdrObject* pRenderedFontWork = EnhancedCustomShapeFontWork::CreateFontWork( pRenderedShape, pSdrObjCustomShape );
301 if ( pRenderedFontWork )
303 SdrObject::Free( pRenderedShape );
304 pRenderedShape = pRenderedFontWork;
307 SdrObject* pRenderedShape3d = EnhancedCustomShape3d::Create3DObject( pRenderedShape, pSdrObjCustomShape );
308 if ( pRenderedShape3d )
310 bFlipV = bFlipH = false;
311 nRotateAngle = 0;
312 SdrObject::Free( pRenderedShape );
313 pRenderedShape = pRenderedShape3d;
315 Rectangle aRect( pSdrObjCustomShape->GetSnapRect() );
317 const GeoStat& rGeoStat = static_cast<SdrObjCustomShape*>(pSdrObjCustomShape)->GetGeoStat();
318 if ( rGeoStat.nShearAngle )
320 long nShearAngle = rGeoStat.nShearAngle;
321 double nTan = rGeoStat.nTan;
322 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
324 nShearAngle = -nShearAngle;
325 nTan = -nTan;
327 pRenderedShape->Shear( pSdrObjCustomShape->GetSnapRect().Center(), nShearAngle, nTan, false);
329 if( !bPostRotateAngle && nRotateAngle )
331 double a = nRotateAngle * F_PI18000;
332 pRenderedShape->NbcRotate( pSdrObjCustomShape->GetSnapRect().Center(), nRotateAngle, sin( a ), cos( a ) );
334 if ( bFlipV )
336 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
337 Point aRight( aLeft.X() + 1000, aLeft.Y() );
338 pRenderedShape->NbcMirror( aLeft, aRight );
340 if ( bFlipH )
342 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
343 Point aBottom( aTop.X(), aTop.Y() + 1000 );
344 pRenderedShape->NbcMirror( aTop, aBottom );
346 // Specifically for pptx imports
347 if( bPostRotateAngle && nRotateAngle )
349 double a = nRotateAngle * F_PI18000;
350 pRenderedShape->NbcRotate( pSdrObjCustomShape->GetSnapRect().Center(), nRotateAngle, sin( a ), cos( a ) );
352 pRenderedShape->NbcSetStyleSheet( pSdrObjCustomShape->GetStyleSheet(), true );
353 pRenderedShape->RecalcSnapRect();
356 if ( mbForceGroupWithText )
357 pRenderedShape = ImplForceGroupWithText( static_cast<SdrObjCustomShape*>(pSdrObjCustomShape), pRenderedShape );
359 if ( pRenderedShape )
361 aCustomShape2d.ApplyGluePoints( pRenderedShape );
362 xShape = SvxDrawPage::CreateShapeByTypeAndInventor( pRenderedShape->GetObjIdentifier(),
363 pRenderedShape->GetObjInventor(), pRenderedShape, NULL );
365 SetTemporary( xShape );
367 return xShape;
370 awt::Rectangle SAL_CALL EnhancedCustomShapeEngine::getTextBounds()
371 throw ( RuntimeException, std::exception )
373 awt::Rectangle aTextRect;
374 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
375 uno::Reference< document::XActionLockable > xLockable( mxShape, uno::UNO_QUERY );
376 if ( pSdrObjCustomShape && pSdrObjCustomShape->GetModel() && xLockable.is() && !xLockable->isActionLocked() )
378 if ( pSdrObjCustomShape )
380 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
381 Rectangle aRect( aCustomShape2d.GetTextRect() );
382 aTextRect.X = aRect.Left();
383 aTextRect.Y = aRect.Top();
384 aTextRect.Width = aRect.GetWidth();
385 aTextRect.Height = aRect.GetHeight();
388 return aTextRect;
391 drawing::PolyPolygonBezierCoords SAL_CALL EnhancedCustomShapeEngine::getLineGeometry()
392 throw ( RuntimeException, std::exception )
394 drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords;
395 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
396 if ( pSdrObjCustomShape )
398 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
399 SdrObject* pObj = aCustomShape2d.CreateLineGeometry();
400 if ( pObj )
402 Rectangle aRect( pSdrObjCustomShape->GetSnapRect() );
403 bool bFlipV = aCustomShape2d.IsFlipVert();
404 bool bFlipH = aCustomShape2d.IsFlipHorz();
406 const GeoStat& rGeoStat = static_cast<SdrObjCustomShape*>(pSdrObjCustomShape)->GetGeoStat();
407 if ( rGeoStat.nShearAngle )
409 long nShearAngle = rGeoStat.nShearAngle;
410 double nTan = rGeoStat.nTan;
411 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
413 nShearAngle = -nShearAngle;
414 nTan = -nTan;
416 pObj->Shear( aRect.Center(), nShearAngle, nTan, false);
418 sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
419 if( nRotateAngle )
421 double a = nRotateAngle * F_PI18000;
422 pObj->NbcRotate( aRect.Center(), nRotateAngle, sin( a ), cos( a ) );
424 if ( bFlipH )
426 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
427 Point aBottom( aTop.X(), aTop.Y() + 1000 );
428 pObj->NbcMirror( aTop, aBottom );
430 if ( bFlipV )
432 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
433 Point aRight( aLeft.X() + 1000, aLeft.Y() );
434 pObj->NbcMirror( aLeft, aRight );
437 basegfx::B2DPolyPolygon aPolyPolygon;
438 SdrObjListIter aIter( *pObj, IM_DEEPWITHGROUPS );
440 while ( aIter.IsMore() )
442 SdrObject* pNewObj = NULL;
443 basegfx::B2DPolyPolygon aPP;
444 const SdrObject* pNext = aIter.Next();
446 if ( pNext->ISA( SdrPathObj ) )
448 aPP = static_cast<const SdrPathObj*>(pNext)->GetPathPoly();
450 else
452 pNewObj = pNext->ConvertToPolyObj( false, false );
453 SdrPathObj* pPath = PTR_CAST( SdrPathObj, pNewObj );
454 if ( pPath )
455 aPP = pPath->GetPathPoly();
458 if ( aPP.count() )
459 aPolyPolygon.append(aPP);
461 SdrObject::Free( pNewObj );
463 SdrObject::Free( pObj );
464 basegfx::unotools::b2DPolyPolygonToPolyPolygonBezier( aPolyPolygon,
465 aPolyPolygonBezierCoords );
469 return aPolyPolygonBezierCoords;
472 Sequence< Reference< drawing::XCustomShapeHandle > > SAL_CALL EnhancedCustomShapeEngine::getInteraction()
473 throw ( RuntimeException, std::exception )
475 sal_uInt32 i, nHdlCount = 0;
476 SdrObject* pSdrObjCustomShape = GetSdrObjectFromXShape( mxShape );
477 if ( pSdrObjCustomShape )
479 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
480 nHdlCount = aCustomShape2d.GetHdlCount();
482 Sequence< Reference< drawing::XCustomShapeHandle > > aSeq( nHdlCount );
483 for ( i = 0; i < nHdlCount; i++ )
484 aSeq[ i ] = new EnhancedCustomShapeHandle( mxShape, i );
485 return aSeq;
490 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
491 com_sun_star_drawing_EnhancedCustomShapeEngine_get_implementation(
492 css::uno::XComponentContext *,
493 css::uno::Sequence<css::uno::Any> const &)
495 return cppu::acquire(new EnhancedCustomShapeEngine);
498 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */