1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
58 using namespace css::uno
;
61 class SdrObjCustomShape
;
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
);
78 EnhancedCustomShapeEngine();
79 virtual ~EnhancedCustomShapeEngine();
82 virtual void SAL_CALL
acquire() throw() SAL_OVERRIDE
;
83 virtual void SAL_CALL
release() throw() SAL_OVERRIDE
;
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
;
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
;
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
)
133 Sequence
< beans::PropertyValue
> aParameter
;
134 for ( i
= 0; i
< aArguments
.getLength(); i
++ )
136 if ( aArguments
[ i
] >>= aParameter
)
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";
169 // XCustomShapeEngine -----------------------------------------------------------
170 SdrObject
* EnhancedCustomShapeEngine::ImplForceGroupWithText( const SdrObjCustomShape
* pCustoObj
, SdrObject
* pRenderedShape
)
172 bool bHasText
= pCustoObj
->HasText();
173 if ( pRenderedShape
|| bHasText
)
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 );
190 pRenderedShape
= pShadowGeometry
->Clone();
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());
201 OutlinerParaObject
* pParaObj
= pCustoObj
->GetOutlinerParaObject();
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
)
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
);
245 pRenderedShape
= pTextObj
;
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
)
268 SvxShape
* pShape
= SvxShape::getImplementation( xShape
);
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
);
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
)
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;
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
;
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
) );
339 Point
aLeft( aRect
.Left(), ( aRect
.Top() + aRect
.Bottom() ) >> 1 );
340 Point
aRight( aLeft
.X() + 1000, aLeft
.Y() );
341 pRenderedShape
->NbcMirror( aLeft
, aRight
);
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
);
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();
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();
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
;
419 pObj
->Shear( aRect
.Center(), nShearWink
, nTan
, false);
421 sal_Int32 nRotateAngle
= aCustomShape2d
.GetRotateAngle();
424 double a
= nRotateAngle
* F_PI18000
;
425 pObj
->NbcRotate( aRect
.Center(), nRotateAngle
, sin( a
), cos( a
) );
429 Point
aTop( ( aRect
.Left() + aRect
.Right() ) >> 1, aRect
.Top() );
430 Point
aBottom( aTop
.X(), aTop
.Y() + 1000 );
431 pObj
->NbcMirror( aTop
, aBottom
);
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();
455 pNewObj
= pNext
->ConvertToPolyObj( false, false );
456 SdrPathObj
* pPath
= PTR_CAST( SdrPathObj
, pNewObj
);
458 aPP
= pPath
->GetPathPoly();
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
);
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: */