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()
117 void SAL_CALL
EnhancedCustomShapeEngine::acquire() throw()
119 OWeakObject::acquire();
121 void SAL_CALL
EnhancedCustomShapeEngine::release() throw()
123 OWeakObject::release();
127 void SAL_CALL
EnhancedCustomShapeEngine::initialize( const Sequence
< Any
>& aArguments
)
128 throw ( Exception
, RuntimeException
, std::exception
)
131 Sequence
< beans::PropertyValue
> aParameter
;
132 for ( i
= 0; i
< aArguments
.getLength(); i
++ )
134 if ( aArguments
[ i
] >>= aParameter
)
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
;
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";
167 // XCustomShapeEngine
168 SdrObject
* EnhancedCustomShapeEngine::ImplForceGroupWithText( const SdrObjCustomShape
* pCustoObj
, SdrObject
* pRenderedShape
)
170 bool bHasText
= pCustoObj
->HasText();
171 if ( pRenderedShape
|| bHasText
)
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 );
188 pRenderedShape
= pShadowGeometry
->Clone();
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());
199 OutlinerParaObject
* pParaObj
= pCustoObj
->GetOutlinerParaObject();
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
)
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
);
243 pRenderedShape
= pTextObj
;
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
)
266 SvxShape
* pShape
= SvxShape::getImplementation( xShape
);
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" );
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
)
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;
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
;
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
) );
336 Point
aLeft( aRect
.Left(), ( aRect
.Top() + aRect
.Bottom() ) >> 1 );
337 Point
aRight( aLeft
.X() + 1000, aLeft
.Y() );
338 pRenderedShape
->NbcMirror( aLeft
, aRight
);
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
);
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();
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();
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
;
416 pObj
->Shear( aRect
.Center(), nShearAngle
, nTan
, false);
418 sal_Int32 nRotateAngle
= aCustomShape2d
.GetRotateAngle();
421 double a
= nRotateAngle
* F_PI18000
;
422 pObj
->NbcRotate( aRect
.Center(), nRotateAngle
, sin( a
), cos( a
) );
426 Point
aTop( ( aRect
.Left() + aRect
.Right() ) >> 1, aRect
.Top() );
427 Point
aBottom( aTop
.X(), aTop
.Y() + 1000 );
428 pObj
->NbcMirror( aTop
, aBottom
);
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();
452 pNewObj
= pNext
->ConvertToPolyObj( false, false );
453 SdrPathObj
* pPath
= PTR_CAST( SdrPathObj
, pNewObj
);
455 aPP
= pPath
->GetPathPoly();
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
);
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: */