Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / customshapes / EnhancedCustomShapeEngine.cxx
blob4835d60e18acfbefa6b99b68fe8d460ef8c26c14
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 -----------------------------------------------------------------
118 void SAL_CALL EnhancedCustomShapeEngine::acquire() throw()
120 OWeakObject::acquire();
122 void SAL_CALL EnhancedCustomShapeEngine::release() throw()
124 OWeakObject::release();
127 // XInitialization ------------------------------------------------------------
129 void SAL_CALL EnhancedCustomShapeEngine::initialize( const Sequence< Any >& aArguments )
130 throw ( Exception, RuntimeException, std::exception )
132 sal_Int32 i;
133 Sequence< beans::PropertyValue > aParameter;
134 for ( i = 0; i < aArguments.getLength(); i++ )
136 if ( aArguments[ i ] >>= aParameter )
137 break;
139 for ( i = 0; i < aParameter.getLength(); i++ )
141 const beans::PropertyValue& rProp = aParameter[ i ];
142 if ( rProp.Name == "CustomShape" )
143 rProp.Value >>= mxShape;
144 else if ( rProp.Name == "ForceGroupWithText" )
145 rProp.Value >>= mbForceGroupWithText;
149 // XServiceInfo ---------------------------------------------------------------
150 OUString SAL_CALL EnhancedCustomShapeEngine::getImplementationName()
151 throw( RuntimeException, std::exception )
153 return OUString( "com.sun.star.drawing.EnhancedCustomShapeEngine" );
155 sal_Bool SAL_CALL EnhancedCustomShapeEngine::supportsService( const OUString& rServiceName )
156 throw( RuntimeException, std::exception )
158 return cppu::supportsService(this, rServiceName);
160 Sequence< OUString > SAL_CALL EnhancedCustomShapeEngine::getSupportedServiceNames()
161 throw ( RuntimeException, std::exception )
163 Sequence< OUString > aRet(1);
164 OUString* pArray = aRet.getArray();
165 pArray[0] = "com.sun.star.drawing.CustomShapeEngine";
166 return aRet;
169 // XCustomShapeEngine -----------------------------------------------------------
170 SdrObject* EnhancedCustomShapeEngine::ImplForceGroupWithText( const SdrObjCustomShape* pCustoObj, SdrObject* pRenderedShape )
172 bool bHasText = pCustoObj->HasText();
173 if ( pRenderedShape || bHasText )
175 // applying shadow
176 const SdrObject* pShadowGeometry = pCustoObj->GetSdrObjectShadowFromCustomShape();
177 if ( pShadowGeometry )
179 if ( pRenderedShape )
181 if ( !pRenderedShape->ISA( SdrObjGroup ) )
183 SdrObject* pTmp = pRenderedShape;
184 pRenderedShape = new SdrObjGroup();
185 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
187 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pShadowGeometry->Clone(), 0 );
189 else
190 pRenderedShape = pShadowGeometry->Clone();
193 // apply text
194 if ( bHasText )
196 // #i37011# also create a text object and add at rPos + 1
197 SdrObject* pTextObj = SdrObjFactory::MakeNewObject(
198 pCustoObj->GetObjInventor(), OBJ_TEXT, 0L, pCustoObj->GetModel());
200 // Copy text content
201 OutlinerParaObject* pParaObj = pCustoObj->GetOutlinerParaObject();
202 if( pParaObj )
203 pTextObj->NbcSetOutlinerParaObject( new OutlinerParaObject(*pParaObj) );
205 // copy all attributes
206 SfxItemSet aTargetItemSet( pCustoObj->GetMergedItemSet() );
208 // clear fill and line style
209 aTargetItemSet.Put(XLineStyleItem(XLINE_NONE));
210 aTargetItemSet.Put(XFillStyleItem(XFILL_NONE));
212 // get the text bounds and set at text object
213 Rectangle aTextBounds = pCustoObj->GetSnapRect();
214 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
215 if ( pSdrObjCustomShape )
217 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
218 aTextBounds = aCustomShape2d.GetTextRect();
220 pTextObj->SetSnapRect( aTextBounds );
222 // if rotated, copy GeoStat, too.
223 const GeoStat& rSourceGeo = pCustoObj->GetGeoStat();
224 if ( rSourceGeo.nDrehWink )
226 pTextObj->NbcRotate(
227 pCustoObj->GetSnapRect().Center(), rSourceGeo.nDrehWink,
228 rSourceGeo.nSin, rSourceGeo.nCos);
231 // set modified ItemSet at text object
232 pTextObj->SetMergedItemSet(aTargetItemSet);
234 if ( pRenderedShape )
236 if ( !pRenderedShape->ISA( SdrObjGroup ) )
238 SdrObject* pTmp = pRenderedShape;
239 pRenderedShape = new SdrObjGroup();
240 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
242 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTextObj, CONTAINER_APPEND );
244 else
245 pRenderedShape = pTextObj;
248 // force group
249 if ( pRenderedShape )
251 if ( !pRenderedShape->ISA( SdrObjGroup ) )
253 SdrObject* pTmp = pRenderedShape;
254 pRenderedShape = new SdrObjGroup();
255 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
257 pRenderedShape->SetPage( pCustoObj->GetPage() );
258 pRenderedShape->SetModel( pCustoObj->GetModel() );
261 return pRenderedShape;
264 void SetTemporary( uno::Reference< drawing::XShape >& xShape )
266 if ( xShape.is() )
268 SvxShape* pShape = SvxShape::getImplementation( xShape );
269 if ( pShape )
270 pShape->TakeSdrObjectOwnership();
274 Reference< drawing::XShape > SAL_CALL EnhancedCustomShapeEngine::render()
275 throw ( RuntimeException, std::exception )
277 Reference< drawing::XShape > xShape;
278 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
279 if ( pSdrObjCustomShape )
281 // retrieving the TextPath property to check if feature is enabled
282 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)
283 pSdrObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
284 bool bTextPathOn = false;
285 const OUString sTextPath( "TextPath" );
286 uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath );
287 if ( pAny )
288 *pAny >>= bTextPathOn;
290 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
291 sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
292 bool bPostRotateAngle = aCustomShape2d.IsPostRotate();
294 bool bFlipV = aCustomShape2d.IsFlipVert();
295 bool bFlipH = aCustomShape2d.IsFlipHorz();
296 bool bLineGeometryNeededOnly = bTextPathOn;
298 SdrObject* pRenderedShape = aCustomShape2d.CreateObject( bLineGeometryNeededOnly );
299 if ( pRenderedShape )
301 if ( bTextPathOn )
303 SdrObject* pRenderedFontWork = EnhancedCustomShapeFontWork::CreateFontWork( pRenderedShape, pSdrObjCustomShape );
304 if ( pRenderedFontWork )
306 SdrObject::Free( pRenderedShape );
307 pRenderedShape = pRenderedFontWork;
310 SdrObject* pRenderedShape3d = EnhancedCustomShape3d::Create3DObject( pRenderedShape, pSdrObjCustomShape );
311 if ( pRenderedShape3d )
313 bFlipV = bFlipH = false;
314 nRotateAngle = 0;
315 SdrObject::Free( pRenderedShape );
316 pRenderedShape = pRenderedShape3d;
318 Rectangle aRect( pSdrObjCustomShape->GetSnapRect() );
320 const GeoStat& rGeoStat = ((SdrObjCustomShape*)pSdrObjCustomShape)->GetGeoStat();
321 if ( rGeoStat.nShearWink )
323 long nShearWink = rGeoStat.nShearWink;
324 double nTan = rGeoStat.nTan;
325 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
327 nShearWink = -nShearWink;
328 nTan = -nTan;
330 pRenderedShape->Shear( pSdrObjCustomShape->GetSnapRect().Center(), nShearWink, nTan, false);
332 if( !bPostRotateAngle && nRotateAngle )
334 double a = nRotateAngle * F_PI18000;
335 pRenderedShape->NbcRotate( pSdrObjCustomShape->GetSnapRect().Center(), nRotateAngle, sin( a ), cos( a ) );
337 if ( bFlipV )
339 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
340 Point aRight( aLeft.X() + 1000, aLeft.Y() );
341 pRenderedShape->NbcMirror( aLeft, aRight );
343 if ( bFlipH )
345 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
346 Point aBottom( aTop.X(), aTop.Y() + 1000 );
347 pRenderedShape->NbcMirror( aTop, aBottom );
349 // Specifically for pptx imports
350 if( bPostRotateAngle && nRotateAngle )
352 double a = nRotateAngle * F_PI18000;
353 pRenderedShape->NbcRotate( pSdrObjCustomShape->GetSnapRect().Center(), nRotateAngle, sin( a ), cos( a ) );
355 pRenderedShape->NbcSetStyleSheet( pSdrObjCustomShape->GetStyleSheet(), true );
356 pRenderedShape->RecalcSnapRect();
359 if ( mbForceGroupWithText )
360 pRenderedShape = ImplForceGroupWithText( (SdrObjCustomShape*)pSdrObjCustomShape, pRenderedShape );
362 if ( pRenderedShape )
364 aCustomShape2d.ApplyGluePoints( pRenderedShape );
365 xShape = SvxDrawPage::CreateShapeByTypeAndInventor( pRenderedShape->GetObjIdentifier(),
366 pRenderedShape->GetObjInventor(), pRenderedShape, NULL );
368 SetTemporary( xShape );
370 return xShape;
373 awt::Rectangle SAL_CALL EnhancedCustomShapeEngine::getTextBounds()
374 throw ( RuntimeException, std::exception )
376 awt::Rectangle aTextRect;
377 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
378 uno::Reference< document::XActionLockable > xLockable( mxShape, uno::UNO_QUERY );
379 if ( pSdrObjCustomShape && pSdrObjCustomShape->GetModel() && xLockable.is() && !xLockable->isActionLocked() )
381 if ( pSdrObjCustomShape )
383 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
384 Rectangle aRect( aCustomShape2d.GetTextRect() );
385 aTextRect.X = aRect.Left();
386 aTextRect.Y = aRect.Top();
387 aTextRect.Width = aRect.GetWidth();
388 aTextRect.Height = aRect.GetHeight();
391 return aTextRect;
394 drawing::PolyPolygonBezierCoords SAL_CALL EnhancedCustomShapeEngine::getLineGeometry()
395 throw ( RuntimeException, std::exception )
397 drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords;
398 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
399 if ( pSdrObjCustomShape )
401 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
402 SdrObject* pObj = aCustomShape2d.CreateLineGeometry();
403 if ( pObj )
405 Rectangle aRect( pSdrObjCustomShape->GetSnapRect() );
406 bool bFlipV = aCustomShape2d.IsFlipVert();
407 bool bFlipH = aCustomShape2d.IsFlipHorz();
409 const GeoStat& rGeoStat = ((SdrObjCustomShape*)pSdrObjCustomShape)->GetGeoStat();
410 if ( rGeoStat.nShearWink )
412 long nShearWink = rGeoStat.nShearWink;
413 double nTan = rGeoStat.nTan;
414 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
416 nShearWink = -nShearWink;
417 nTan = -nTan;
419 pObj->Shear( aRect.Center(), nShearWink, nTan, false);
421 sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
422 if( nRotateAngle )
424 double a = nRotateAngle * F_PI18000;
425 pObj->NbcRotate( aRect.Center(), nRotateAngle, sin( a ), cos( a ) );
427 if ( bFlipH )
429 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
430 Point aBottom( aTop.X(), aTop.Y() + 1000 );
431 pObj->NbcMirror( aTop, aBottom );
433 if ( bFlipV )
435 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
436 Point aRight( aLeft.X() + 1000, aLeft.Y() );
437 pObj->NbcMirror( aLeft, aRight );
440 basegfx::B2DPolyPolygon aPolyPolygon;
441 SdrObjListIter aIter( *pObj, IM_DEEPWITHGROUPS );
443 while ( aIter.IsMore() )
445 SdrObject* pNewObj = NULL;
446 basegfx::B2DPolyPolygon aPP;
447 const SdrObject* pNext = aIter.Next();
449 if ( pNext->ISA( SdrPathObj ) )
451 aPP = ((SdrPathObj*)pNext)->GetPathPoly();
453 else
455 pNewObj = pNext->ConvertToPolyObj( false, false );
456 SdrPathObj* pPath = PTR_CAST( SdrPathObj, pNewObj );
457 if ( pPath )
458 aPP = pPath->GetPathPoly();
461 if ( aPP.count() )
462 aPolyPolygon.append(aPP);
464 SdrObject::Free( pNewObj );
466 SdrObject::Free( pObj );
467 basegfx::unotools::b2DPolyPolygonToPolyPolygonBezier( aPolyPolygon,
468 aPolyPolygonBezierCoords );
472 return aPolyPolygonBezierCoords;
475 Sequence< Reference< drawing::XCustomShapeHandle > > SAL_CALL EnhancedCustomShapeEngine::getInteraction()
476 throw ( RuntimeException, std::exception )
478 sal_uInt32 i, nHdlCount = 0;
479 SdrObject* pSdrObjCustomShape = GetSdrObjectFromXShape( mxShape );
480 if ( pSdrObjCustomShape )
482 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
483 nHdlCount = aCustomShape2d.GetHdlCount();
485 Sequence< Reference< drawing::XCustomShapeHandle > > aSeq( nHdlCount );
486 for ( i = 0; i < nHdlCount; i++ )
487 aSeq[ i ] = new EnhancedCustomShapeHandle( mxShape, i );
488 return aSeq;
493 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
494 com_sun_star_drawing_EnhancedCustomShapeEngine_get_implementation(
495 css::uno::XComponentContext *,
496 css::uno::Sequence<css::uno::Any> const &)
498 return cppu::acquire(new EnhancedCustomShapeEngine);
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */