xref: /AOO41X/main/svx/source/customshapes/EnhancedCustomShapeEngine.cxx (revision f6e50924346d0b8c0b07c91832a97665dd718b0c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 #include "EnhancedCustomShapeEngine.hxx"
27 #include "svx/EnhancedCustomShape2d.hxx"
28 #include "EnhancedCustomShape3d.hxx"
29 #include "EnhancedCustomShapeFontWork.hxx"
30 #include "EnhancedCustomShapeHandle.hxx"
31 #include "svx/EnhancedCustomShapeGeometry.hxx"
32 #include <svx/unoshape.hxx>
33 #ifndef _SVX_UNOPAGE_HXX
34 #include "svx/unopage.hxx"
35 #endif
36 #include "svx/unoapi.hxx"
37 #include <svx/svdobj.hxx>
38 #include <svx/svdoashp.hxx>
39 #include <svx/svdogrp.hxx>
40 #include <svx/svdorect.hxx>
41 #include <editeng/outlobj.hxx>
42 #include <editeng/outliner.hxx>
43 #include <svx/svdoutl.hxx>
44 #include <svl/itemset.hxx>
45 #include <svx/svdopath.hxx>
46 #include <svx/svdpage.hxx>
47 #include <svx/svdmodel.hxx>
48 #include "svx/svditer.hxx"
49 #include "unopolyhelper.hxx"
50 #include <uno/mapping.hxx>
51 #include <basegfx/polygon/b2dpolypolygontools.hxx>
52 #include <com/sun/star/document/XActionLockable.hpp>
53 
54 // ---------------------------
55 // - EnhancedCustomShapeEngine -
56 // ---------------------------
57 
EnhancedCustomShapeEngine_getImplementationName()58 rtl::OUString EnhancedCustomShapeEngine_getImplementationName()
59     throw( NMSP_UNO::RuntimeException )
60 {
61     return B2UCONST( "com.sun.star.drawing.EnhancedCustomShapeEngine" );
62 }
EnhancedCustomShapeEngine_supportsService(const rtl::OUString & ServiceName)63 sal_Bool SAL_CALL EnhancedCustomShapeEngine_supportsService( const rtl::OUString& ServiceName )
64     throw( NMSP_UNO::RuntimeException )
65 {
66     return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.CustomShapeEngine" ) );
67 }
SEQ(rtl::OUString)68 SEQ( rtl::OUString ) SAL_CALL EnhancedCustomShapeEngine_getSupportedServiceNames()
69     throw( NMSP_UNO::RuntimeException )
70 {
71     SEQ( rtl::OUString ) aRet(1);
72     rtl::OUString* pArray = aRet.getArray();
73     pArray[0] = B2UCONST( "com.sun.star.drawing.CustomShapeEngine" );
74     return aRet;
75 }
76 
77 // -----------------------------------------------------------------------------
78 
EnhancedCustomShapeEngine(const REF (NMSP_LANG::XMultiServiceFactory)& rxMgr)79 EnhancedCustomShapeEngine::EnhancedCustomShapeEngine( const REF( NMSP_LANG::XMultiServiceFactory )& rxMgr ) :
80     mxFact                  ( rxMgr ),
81     mbForceGroupWithText    ( sal_False )
82 {
83 }
~EnhancedCustomShapeEngine()84 EnhancedCustomShapeEngine::~EnhancedCustomShapeEngine()
85 {
86 }
87 
88 // XInterface -----------------------------------------------------------------
89 
acquire()90 void SAL_CALL EnhancedCustomShapeEngine::acquire() throw()
91 {
92     OWeakObject::acquire();
93 }
release()94 void SAL_CALL EnhancedCustomShapeEngine::release() throw()
95 {
96     OWeakObject::release();
97 }
98 
99 // XInitialization ------------------------------------------------------------
100 
initialize(const SEQ (NMSP_UNO::Any)& aArguments)101 void SAL_CALL EnhancedCustomShapeEngine::initialize( const SEQ( NMSP_UNO::Any )& aArguments )
102     throw ( NMSP_UNO::Exception, NMSP_UNO::RuntimeException )
103 {
104     sal_Int32 i;
105     SEQ( NMSP_BEANS::PropertyValue ) aParameter;
106     for ( i = 0; i < aArguments.getLength(); i++ )
107     {
108         if ( aArguments[ i ] >>= aParameter )
109             break;
110     }
111     for ( i = 0; i < aParameter.getLength(); i++ )
112     {
113         const NMSP_BEANS::PropertyValue& rProp = aParameter[ i ];
114         if ( rProp.Name.equalsAscii( "CustomShape" ) )
115             rProp.Value >>= mxShape;
116         else if ( rProp.Name.equalsAscii( "ForceGroupWithText" ) )
117             rProp.Value >>= mbForceGroupWithText;
118     }
119 }
120 
121 // XServiceInfo ---------------------------------------------------------------
122 
getImplementationName()123 rtl::OUString SAL_CALL EnhancedCustomShapeEngine::getImplementationName()
124     throw( NMSP_UNO::RuntimeException )
125 {
126     return EnhancedCustomShapeEngine_getImplementationName();
127 }
supportsService(const rtl::OUString & rServiceName)128 sal_Bool SAL_CALL EnhancedCustomShapeEngine::supportsService( const rtl::OUString& rServiceName )
129     throw( NMSP_UNO::RuntimeException )
130 {
131     return EnhancedCustomShapeEngine_supportsService( rServiceName );
132 }
SEQ(rtl::OUString)133 SEQ( rtl::OUString ) SAL_CALL EnhancedCustomShapeEngine::getSupportedServiceNames()
134     throw ( NMSP_UNO::RuntimeException )
135 {
136     return EnhancedCustomShapeEngine_getSupportedServiceNames();
137 }
138 
139 // XCustomShapeEngine -----------------------------------------------------------
140 
ImplForceGroupWithText(const SdrObjCustomShape * pCustoObj,SdrObject * pRenderedShape)141 SdrObject* EnhancedCustomShapeEngine::ImplForceGroupWithText( const SdrObjCustomShape* pCustoObj, SdrObject* pRenderedShape )
142 {
143     bool bHasText = pCustoObj->HasText();
144     if ( pRenderedShape || bHasText )
145     {
146         // applying shadow
147         const SdrObject* pShadowGeometry = pCustoObj->GetSdrObjectShadowFromCustomShape();
148         if ( pShadowGeometry )
149         {
150             if ( pRenderedShape )
151             {
152                 if ( !pRenderedShape->ISA( SdrObjGroup ) )
153                 {
154                     SdrObject* pTmp = pRenderedShape;
155                     pRenderedShape = new SdrObjGroup();
156                     ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
157                 }
158                 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pShadowGeometry->Clone(), 0 );
159             }
160             else
161                 pRenderedShape = pShadowGeometry->Clone();
162         }
163 
164         // apply text
165         if ( bHasText )
166         {
167             // #i37011# also create a text object and add at rPos + 1
168             SdrTextObj* pTextObj = (SdrTextObj*)SdrObjFactory::MakeNewObject(
169                 pCustoObj->GetObjInventor(), OBJ_TEXT, 0L, pCustoObj->GetModel());
170 
171             // Copy text content
172             OutlinerParaObject* pParaObj = pCustoObj->GetOutlinerParaObject();
173             if( pParaObj )
174                 pTextObj->NbcSetOutlinerParaObject( new OutlinerParaObject(*pParaObj) );
175 
176             // copy all attributes
177             SfxItemSet aTargetItemSet( pCustoObj->GetMergedItemSet() );
178 
179             // clear fill and line style
180             aTargetItemSet.Put(XLineStyleItem(XLINE_NONE));
181             aTargetItemSet.Put(XFillStyleItem(XFILL_NONE));
182 
183             // get the text bounds and set at text object
184             Rectangle aTextBounds = pCustoObj->GetSnapRect();
185             SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
186             if ( pSdrObjCustomShape )
187             {
188                 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
189                 aTextBounds = aCustomShape2d.GetTextRect();
190             }
191             pTextObj->SetSnapRect( aTextBounds );
192 
193             // if rotated, copy GeoStat, too.
194             const GeoStat& rSourceGeo = pCustoObj->GetGeoStat();
195             if ( rSourceGeo.nDrehWink )
196             {
197                 pTextObj->NbcRotate(
198                     pCustoObj->GetSnapRect().Center(), rSourceGeo.nDrehWink,
199                     rSourceGeo.nSin, rSourceGeo.nCos);
200             }
201 
202             // set modified ItemSet at text object
203             pTextObj->SetMergedItemSet(aTargetItemSet);
204 
205             if ( pRenderedShape )
206             {
207                 if ( !pRenderedShape->ISA( SdrObjGroup ) )
208                 {
209                     SdrObject* pTmp = pRenderedShape;
210                     pRenderedShape = new SdrObjGroup();
211                     ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
212                 }
213                 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTextObj, LIST_APPEND );
214             }
215             else
216                 pRenderedShape = pTextObj;
217         }
218 
219         // force group
220         if ( pRenderedShape )
221         {
222             if ( !pRenderedShape->ISA( SdrObjGroup ) )
223             {
224                 SdrObject* pTmp = pRenderedShape;
225                 pRenderedShape = new SdrObjGroup();
226                 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
227             }
228             pRenderedShape->SetPage( pCustoObj->GetPage() );
229             pRenderedShape->SetModel( pCustoObj->GetModel() );
230         }
231     }
232     return pRenderedShape;
233 }
234 
SetTemporary(::com::sun::star::uno::Reference<::com::sun::star::drawing::XShape> & xShape)235 void SetTemporary( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape )
236 {
237     if ( xShape.is() )
238     {
239         SvxShape* pShape = SvxShape::getImplementation( xShape );
240         if ( pShape )
241             pShape->TakeSdrObjectOwnership();
242 /*
243         ::com::sun::star::uno::Reference<
244             ::com::sun::star::drawing::XShapes > xShapes( xShape, ::com::sun::star::uno::UNO_QUERY );
245         if ( xShapes.is() )
246         {
247             sal_Int32 i;
248             for ( i = 0; i < xShapes->getCount(); i++ )
249             {
250                 ::com::sun::star::uno::Any aAny( xShapes->getByIndex( i ) );
251                 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape;
252                 if ( aAny >>= xShape )
253                     SetTemporary( xShape );
254             }
255         }
256 */
257     }
258 }
259 
REF(com::sun::star::drawing::XShape)260 REF( com::sun::star::drawing::XShape ) SAL_CALL EnhancedCustomShapeEngine::render()
261     throw ( NMSP_UNO::RuntimeException )
262 {
263     REF( com::sun::star::drawing::XShape ) xShape;
264     SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
265     if ( pSdrObjCustomShape )
266     {
267         // retrieving the TextPath property to check if feature is enabled
268         SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)
269             pSdrObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
270         sal_Bool bTextPathOn = sal_False;
271         const rtl::OUString sTextPath( RTL_CONSTASCII_USTRINGPARAM ( "TextPath" ) );
272         com::sun::star::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath );
273         if ( pAny )
274             *pAny >>= bTextPathOn;
275 
276         EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
277         sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
278 
279         sal_Bool bFlipV = aCustomShape2d.IsFlipVert();
280         sal_Bool bFlipH = aCustomShape2d.IsFlipHorz();
281         sal_Bool bLineGeometryNeededOnly = bTextPathOn;
282 
283         SdrObject* pRenderedShape = aCustomShape2d.CreateObject( bLineGeometryNeededOnly );
284         if ( pRenderedShape )
285         {
286             if ( bTextPathOn )
287             {
288                 SdrObject* pRenderedFontWork = EnhancedCustomShapeFontWork::CreateFontWork( pRenderedShape, pSdrObjCustomShape );
289                 if ( pRenderedFontWork )
290                 {
291                     SdrObject::Free( pRenderedShape );
292                     pRenderedShape = pRenderedFontWork;
293                 }
294             }
295             SdrObject* pRenderedShape3d = EnhancedCustomShape3d::Create3DObject( pRenderedShape, pSdrObjCustomShape );
296             if ( pRenderedShape3d )
297             {
298                 bFlipV = bFlipH = sal_False;
299                 nRotateAngle = 0;
300                 SdrObject::Free( pRenderedShape );
301                 pRenderedShape = pRenderedShape3d;
302             }
303             Rectangle aRect( pSdrObjCustomShape->GetSnapRect() );
304 
305             const GeoStat& rGeoStat = ((SdrObjCustomShape*)pSdrObjCustomShape)->GetGeoStat();
306             if ( rGeoStat.nShearWink )
307             {
308                 long nShearWink = rGeoStat.nShearWink;
309                 double nTan = rGeoStat.nTan;
310                 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
311                 {
312                     nShearWink = -nShearWink;
313                     nTan = -nTan;
314                 }
315                 pRenderedShape->Shear( pSdrObjCustomShape->GetSnapRect().Center(), nShearWink, nTan, sal_False);
316             }
317             if( nRotateAngle )
318             {
319                 double a = nRotateAngle * F_PI18000;
320                 pRenderedShape->NbcRotate( pSdrObjCustomShape->GetSnapRect().Center(), nRotateAngle, sin( a ), cos( a ) );
321             }
322             if ( bFlipV )
323             {
324                 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
325                 Point aRight( aLeft.X() + 1000, aLeft.Y() );
326                 pRenderedShape->NbcMirror( aLeft, aRight );
327             }
328             if ( bFlipH )
329             {
330                 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
331                 Point aBottom( aTop.X(), aTop.Y() + 1000 );
332                 pRenderedShape->NbcMirror( aTop, aBottom );
333             }
334             pRenderedShape->NbcSetStyleSheet( pSdrObjCustomShape->GetStyleSheet(), sal_True );
335             pRenderedShape->RecalcSnapRect();
336         }
337 
338         if ( mbForceGroupWithText )
339             pRenderedShape = ImplForceGroupWithText( (SdrObjCustomShape*)pSdrObjCustomShape, pRenderedShape );
340 
341         if ( pRenderedShape )
342         {
343             aCustomShape2d.ApplyGluePoints( pRenderedShape );
344             xShape = SvxDrawPage::CreateShapeByTypeAndInventor( pRenderedShape->GetObjIdentifier(),
345                 pRenderedShape->GetObjInventor(), pRenderedShape, NULL );
346         }
347         SetTemporary( xShape );
348     }
349     return xShape;
350 }
351 
getTextBounds()352 com::sun::star::awt::Rectangle SAL_CALL EnhancedCustomShapeEngine::getTextBounds()
353     throw ( NMSP_UNO::RuntimeException )
354 {
355     com::sun::star::awt::Rectangle aTextRect;
356     SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
357     ::com::sun::star::uno::Reference< ::com::sun::star::document::XActionLockable > xLockable( mxShape, ::com::sun::star::uno::UNO_QUERY );
358     if ( pSdrObjCustomShape && pSdrObjCustomShape->GetModel() && xLockable.is() && !xLockable->isActionLocked() )
359     {
360         if ( pSdrObjCustomShape )
361         {
362             EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
363             Rectangle aRect( aCustomShape2d.GetTextRect() );
364             aTextRect.X = aRect.Left();
365             aTextRect.Y = aRect.Top();
366             aTextRect.Width = aRect.GetWidth();
367             aTextRect.Height = aRect.GetHeight();
368         }
369     }
370     return aTextRect;
371 }
372 
getLineGeometry()373 com::sun::star::drawing::PolyPolygonBezierCoords SAL_CALL EnhancedCustomShapeEngine::getLineGeometry()
374     throw ( NMSP_UNO::RuntimeException )
375 {
376     com::sun::star::drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords;
377     SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
378     if ( pSdrObjCustomShape )
379     {
380         EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
381         SdrObject* pObj = aCustomShape2d.CreateLineGeometry();
382         if ( pObj )
383         {
384             Rectangle aRect( pSdrObjCustomShape->GetSnapRect() );
385             sal_Bool bFlipV = aCustomShape2d.IsFlipVert();
386             sal_Bool bFlipH = aCustomShape2d.IsFlipHorz();
387 
388             const GeoStat& rGeoStat = ((SdrObjCustomShape*)pSdrObjCustomShape)->GetGeoStat();
389             if ( rGeoStat.nShearWink )
390             {
391                 long nShearWink = rGeoStat.nShearWink;
392                 double nTan = rGeoStat.nTan;
393                 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
394                 {
395                     nShearWink = -nShearWink;
396                     nTan = -nTan;
397                 }
398                 pObj->Shear( aRect.Center(), nShearWink, nTan, sal_False);
399             }
400             sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
401             if( nRotateAngle )
402             {
403                 double a = nRotateAngle * F_PI18000;
404                 pObj->NbcRotate( aRect.Center(), nRotateAngle, sin( a ), cos( a ) );
405             }
406             if ( bFlipH )
407             {
408                 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
409                 Point aBottom( aTop.X(), aTop.Y() + 1000 );
410                 pObj->NbcMirror( aTop, aBottom );
411             }
412             if ( bFlipV )
413             {
414                 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
415                 Point aRight( aLeft.X() + 1000, aLeft.Y() );
416                 pObj->NbcMirror( aLeft, aRight );
417             }
418 
419             basegfx::B2DPolyPolygon aPolyPolygon;
420             SdrObjListIter aIter( *pObj, IM_DEEPWITHGROUPS );
421 
422             while ( aIter.IsMore() )
423             {
424                 SdrObject* pNewObj = NULL;
425                 basegfx::B2DPolyPolygon aPP;
426                 const SdrObject* pNext = aIter.Next();
427 
428                 if ( pNext->ISA( SdrPathObj ) )
429                 {
430                     aPP = ((SdrPathObj*)pNext)->GetPathPoly();
431                 }
432                 else
433                 {
434                     pNewObj = pNext->ConvertToPolyObj( sal_False, sal_False );
435                     SdrPathObj* pPath = PTR_CAST( SdrPathObj, pNewObj );
436                     if ( pPath )
437                         aPP = pPath->GetPathPoly();
438                 }
439 
440                 if ( aPP.count() )
441                     aPolyPolygon.append(aPP);
442 
443                 SdrObject::Free( pNewObj );
444             }
445             SdrObject::Free( pObj );
446             SvxConvertB2DPolyPolygonToPolyPolygonBezier( aPolyPolygon, aPolyPolygonBezierCoords );
447         }
448     }
449 
450     return aPolyPolygonBezierCoords;
451 }
452 
SEQ(REF (com::sun::star::drawing::XCustomShapeHandle))453 SEQ( REF( com::sun::star::drawing::XCustomShapeHandle ) ) SAL_CALL EnhancedCustomShapeEngine::getInteraction()
454     throw ( NMSP_UNO::RuntimeException )
455 {
456     sal_uInt32 i, nHdlCount = 0;
457     SdrObject* pSdrObjCustomShape = GetSdrObjectFromXShape( mxShape );
458     if ( pSdrObjCustomShape )
459     {
460         EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
461         nHdlCount = aCustomShape2d.GetHdlCount();
462     }
463     SEQ( REF( com::sun::star::drawing::XCustomShapeHandle ) ) aSeq( nHdlCount );
464     for ( i = 0; i < nHdlCount; i++ )
465         aSeq[ i ] = new EnhancedCustomShapeHandle( mxShape, i );
466     return aSeq;
467 }
468