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 {
60 return B2UCONST( "com.sun.star.drawing.EnhancedCustomShapeEngine" );
61 }
EnhancedCustomShapeEngine_supportsService(const rtl::OUString & ServiceName)62 sal_Bool SAL_CALL EnhancedCustomShapeEngine_supportsService( const rtl::OUString& ServiceName )
63 {
64 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.CustomShapeEngine" ) );
65 }
SEQ(rtl::OUString)66 SEQ( rtl::OUString ) SAL_CALL EnhancedCustomShapeEngine_getSupportedServiceNames()
67 {
68 SEQ( rtl::OUString ) aRet(1);
69 rtl::OUString* pArray = aRet.getArray();
70 pArray[0] = B2UCONST( "com.sun.star.drawing.CustomShapeEngine" );
71 return aRet;
72 }
73
74 // -----------------------------------------------------------------------------
75
EnhancedCustomShapeEngine(const REF (NMSP_LANG::XMultiServiceFactory)& rxMgr)76 EnhancedCustomShapeEngine::EnhancedCustomShapeEngine( const REF( NMSP_LANG::XMultiServiceFactory )& rxMgr ) :
77 mxFact ( rxMgr ),
78 mbForceGroupWithText ( sal_False )
79 {
80 }
~EnhancedCustomShapeEngine()81 EnhancedCustomShapeEngine::~EnhancedCustomShapeEngine()
82 {
83 }
84
85 // XInterface -----------------------------------------------------------------
86
acquire()87 void SAL_CALL EnhancedCustomShapeEngine::acquire() throw()
88 {
89 OWeakObject::acquire();
90 }
release()91 void SAL_CALL EnhancedCustomShapeEngine::release() throw()
92 {
93 OWeakObject::release();
94 }
95
96 // XInitialization ------------------------------------------------------------
97
initialize(const SEQ (NMSP_UNO::Any)& aArguments)98 void SAL_CALL EnhancedCustomShapeEngine::initialize( const SEQ( NMSP_UNO::Any )& aArguments )
99 {
100 sal_Int32 i;
101 SEQ( NMSP_BEANS::PropertyValue ) aParameter;
102 for ( i = 0; i < aArguments.getLength(); i++ )
103 {
104 if ( aArguments[ i ] >>= aParameter )
105 break;
106 }
107 for ( i = 0; i < aParameter.getLength(); i++ )
108 {
109 const NMSP_BEANS::PropertyValue& rProp = aParameter[ i ];
110 if ( rProp.Name.equalsAscii( "CustomShape" ) )
111 rProp.Value >>= mxShape;
112 else if ( rProp.Name.equalsAscii( "ForceGroupWithText" ) )
113 rProp.Value >>= mbForceGroupWithText;
114 }
115 }
116
117 // XServiceInfo ---------------------------------------------------------------
118
getImplementationName()119 rtl::OUString SAL_CALL EnhancedCustomShapeEngine::getImplementationName()
120 {
121 return EnhancedCustomShapeEngine_getImplementationName();
122 }
supportsService(const rtl::OUString & rServiceName)123 sal_Bool SAL_CALL EnhancedCustomShapeEngine::supportsService( const rtl::OUString& rServiceName )
124 {
125 return EnhancedCustomShapeEngine_supportsService( rServiceName );
126 }
SEQ(rtl::OUString)127 SEQ( rtl::OUString ) SAL_CALL EnhancedCustomShapeEngine::getSupportedServiceNames()
128 {
129 return EnhancedCustomShapeEngine_getSupportedServiceNames();
130 }
131
132 // XCustomShapeEngine -----------------------------------------------------------
133
ImplForceGroupWithText(const SdrObjCustomShape * pCustoObj,SdrObject * pRenderedShape)134 SdrObject* EnhancedCustomShapeEngine::ImplForceGroupWithText( const SdrObjCustomShape* pCustoObj, SdrObject* pRenderedShape )
135 {
136 bool bHasText = pCustoObj->HasText();
137 if ( pRenderedShape || bHasText )
138 {
139 // applying shadow
140 const SdrObject* pShadowGeometry = pCustoObj->GetSdrObjectShadowFromCustomShape();
141 if ( pShadowGeometry )
142 {
143 if ( pRenderedShape )
144 {
145 if ( !pRenderedShape->ISA( SdrObjGroup ) )
146 {
147 SdrObject* pTmp = pRenderedShape;
148 pRenderedShape = new SdrObjGroup();
149 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
150 }
151 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pShadowGeometry->Clone(), 0 );
152 }
153 else
154 pRenderedShape = pShadowGeometry->Clone();
155 }
156
157 // apply text
158 if ( bHasText )
159 {
160 // #i37011# also create a text object and add at rPos + 1
161 SdrTextObj* pTextObj = (SdrTextObj*)SdrObjFactory::MakeNewObject(
162 pCustoObj->GetObjInventor(), OBJ_TEXT, 0L, pCustoObj->GetModel());
163
164 // Copy text content
165 OutlinerParaObject* pParaObj = pCustoObj->GetOutlinerParaObject();
166 if( pParaObj )
167 pTextObj->NbcSetOutlinerParaObject( new OutlinerParaObject(*pParaObj) );
168
169 // copy all attributes
170 SfxItemSet aTargetItemSet( pCustoObj->GetMergedItemSet() );
171
172 // clear fill and line style
173 aTargetItemSet.Put(XLineStyleItem(XLINE_NONE));
174 aTargetItemSet.Put(XFillStyleItem(XFILL_NONE));
175
176 // get the text bounds and set at text object
177 Rectangle aTextBounds = pCustoObj->GetSnapRect();
178 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
179 if ( pSdrObjCustomShape )
180 {
181 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
182 aTextBounds = aCustomShape2d.GetTextRect();
183 }
184 pTextObj->SetSnapRect( aTextBounds );
185
186 // if rotated, copy GeoStat, too.
187 const GeoStat& rSourceGeo = pCustoObj->GetGeoStat();
188 if ( rSourceGeo.nDrehWink )
189 {
190 pTextObj->NbcRotate(
191 pCustoObj->GetSnapRect().Center(), rSourceGeo.nDrehWink,
192 rSourceGeo.nSin, rSourceGeo.nCos);
193 }
194
195 // set modified ItemSet at text object
196 pTextObj->SetMergedItemSet(aTargetItemSet);
197
198 if ( pRenderedShape )
199 {
200 if ( !pRenderedShape->ISA( SdrObjGroup ) )
201 {
202 SdrObject* pTmp = pRenderedShape;
203 pRenderedShape = new SdrObjGroup();
204 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
205 }
206 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTextObj, LIST_APPEND );
207 }
208 else
209 pRenderedShape = pTextObj;
210 }
211
212 // force group
213 if ( pRenderedShape )
214 {
215 if ( !pRenderedShape->ISA( SdrObjGroup ) )
216 {
217 SdrObject* pTmp = pRenderedShape;
218 pRenderedShape = new SdrObjGroup();
219 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp );
220 }
221 pRenderedShape->SetPage( pCustoObj->GetPage() );
222 pRenderedShape->SetModel( pCustoObj->GetModel() );
223 }
224 }
225 return pRenderedShape;
226 }
227
SetTemporary(::com::sun::star::uno::Reference<::com::sun::star::drawing::XShape> & xShape)228 void SetTemporary( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape )
229 {
230 if ( xShape.is() )
231 {
232 SvxShape* pShape = SvxShape::getImplementation( xShape );
233 if ( pShape )
234 pShape->TakeSdrObjectOwnership();
235 /*
236 ::com::sun::star::uno::Reference<
237 ::com::sun::star::drawing::XShapes > xShapes( xShape, ::com::sun::star::uno::UNO_QUERY );
238 if ( xShapes.is() )
239 {
240 sal_Int32 i;
241 for ( i = 0; i < xShapes->getCount(); i++ )
242 {
243 ::com::sun::star::uno::Any aAny( xShapes->getByIndex( i ) );
244 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape;
245 if ( aAny >>= xShape )
246 SetTemporary( xShape );
247 }
248 }
249 */
250 }
251 }
252
REF(com::sun::star::drawing::XShape)253 REF( com::sun::star::drawing::XShape ) SAL_CALL EnhancedCustomShapeEngine::render()
254 {
255 REF( com::sun::star::drawing::XShape ) xShape;
256 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
257 if ( pSdrObjCustomShape )
258 {
259 // retrieving the TextPath property to check if feature is enabled
260 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)
261 pSdrObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
262 sal_Bool bTextPathOn = sal_False;
263 const rtl::OUString sTextPath( RTL_CONSTASCII_USTRINGPARAM ( "TextPath" ) );
264 com::sun::star::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath );
265 if ( pAny )
266 *pAny >>= bTextPathOn;
267
268 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
269 sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
270
271 sal_Bool bFlipV = aCustomShape2d.IsFlipVert();
272 sal_Bool bFlipH = aCustomShape2d.IsFlipHorz();
273 sal_Bool bLineGeometryNeededOnly = bTextPathOn;
274
275 SdrObject* pRenderedShape = aCustomShape2d.CreateObject( bLineGeometryNeededOnly );
276 if ( pRenderedShape )
277 {
278 if ( bTextPathOn )
279 {
280 SdrObject* pRenderedFontWork = EnhancedCustomShapeFontWork::CreateFontWork( pRenderedShape, pSdrObjCustomShape );
281 if ( pRenderedFontWork )
282 {
283 SdrObject::Free( pRenderedShape );
284 pRenderedShape = pRenderedFontWork;
285 }
286 }
287 SdrObject* pRenderedShape3d = EnhancedCustomShape3d::Create3DObject( pRenderedShape, pSdrObjCustomShape );
288 if ( pRenderedShape3d )
289 {
290 bFlipV = bFlipH = sal_False;
291 nRotateAngle = 0;
292 SdrObject::Free( pRenderedShape );
293 pRenderedShape = pRenderedShape3d;
294 }
295 Rectangle aRect( pSdrObjCustomShape->GetSnapRect() );
296
297 const GeoStat& rGeoStat = ((SdrObjCustomShape*)pSdrObjCustomShape)->GetGeoStat();
298 if ( rGeoStat.nShearWink )
299 {
300 long nShearWink = rGeoStat.nShearWink;
301 double nTan = rGeoStat.nTan;
302 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
303 {
304 nShearWink = -nShearWink;
305 nTan = -nTan;
306 }
307 pRenderedShape->Shear( pSdrObjCustomShape->GetSnapRect().Center(), nShearWink, nTan, sal_False);
308 }
309 if( nRotateAngle )
310 {
311 double a = nRotateAngle * F_PI18000;
312 pRenderedShape->NbcRotate( pSdrObjCustomShape->GetSnapRect().Center(), nRotateAngle, sin( a ), cos( a ) );
313 }
314 if ( bFlipV )
315 {
316 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
317 Point aRight( aLeft.X() + 1000, aLeft.Y() );
318 pRenderedShape->NbcMirror( aLeft, aRight );
319 }
320 if ( bFlipH )
321 {
322 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
323 Point aBottom( aTop.X(), aTop.Y() + 1000 );
324 pRenderedShape->NbcMirror( aTop, aBottom );
325 }
326 pRenderedShape->NbcSetStyleSheet( pSdrObjCustomShape->GetStyleSheet(), sal_True );
327 pRenderedShape->RecalcSnapRect();
328 }
329
330 if ( mbForceGroupWithText )
331 pRenderedShape = ImplForceGroupWithText( (SdrObjCustomShape*)pSdrObjCustomShape, pRenderedShape );
332
333 if ( pRenderedShape )
334 {
335 aCustomShape2d.ApplyGluePoints( pRenderedShape );
336 xShape = SvxDrawPage::CreateShapeByTypeAndInventor( pRenderedShape->GetObjIdentifier(),
337 pRenderedShape->GetObjInventor(), pRenderedShape, NULL );
338 }
339 SetTemporary( xShape );
340 }
341 return xShape;
342 }
343
getTextBounds()344 com::sun::star::awt::Rectangle SAL_CALL EnhancedCustomShapeEngine::getTextBounds()
345 {
346 com::sun::star::awt::Rectangle aTextRect;
347 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
348 ::com::sun::star::uno::Reference< ::com::sun::star::document::XActionLockable > xLockable( mxShape, ::com::sun::star::uno::UNO_QUERY );
349 if ( pSdrObjCustomShape && pSdrObjCustomShape->GetModel() && xLockable.is() && !xLockable->isActionLocked() )
350 {
351 if ( pSdrObjCustomShape )
352 {
353 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
354 Rectangle aRect( aCustomShape2d.GetTextRect() );
355 aTextRect.X = aRect.Left();
356 aTextRect.Y = aRect.Top();
357 aTextRect.Width = aRect.GetWidth();
358 aTextRect.Height = aRect.GetHeight();
359 }
360 }
361 return aTextRect;
362 }
363
getLineGeometry()364 com::sun::star::drawing::PolyPolygonBezierCoords SAL_CALL EnhancedCustomShapeEngine::getLineGeometry()
365 {
366 com::sun::star::drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords;
367 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) );
368 if ( pSdrObjCustomShape )
369 {
370 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
371 SdrObject* pObj = aCustomShape2d.CreateLineGeometry();
372 if ( pObj )
373 {
374 Rectangle aRect( pSdrObjCustomShape->GetSnapRect() );
375 sal_Bool bFlipV = aCustomShape2d.IsFlipVert();
376 sal_Bool bFlipH = aCustomShape2d.IsFlipHorz();
377
378 const GeoStat& rGeoStat = ((SdrObjCustomShape*)pSdrObjCustomShape)->GetGeoStat();
379 if ( rGeoStat.nShearWink )
380 {
381 long nShearWink = rGeoStat.nShearWink;
382 double nTan = rGeoStat.nTan;
383 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
384 {
385 nShearWink = -nShearWink;
386 nTan = -nTan;
387 }
388 pObj->Shear( aRect.Center(), nShearWink, nTan, sal_False);
389 }
390 sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle();
391 if( nRotateAngle )
392 {
393 double a = nRotateAngle * F_PI18000;
394 pObj->NbcRotate( aRect.Center(), nRotateAngle, sin( a ), cos( a ) );
395 }
396 if ( bFlipH )
397 {
398 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() );
399 Point aBottom( aTop.X(), aTop.Y() + 1000 );
400 pObj->NbcMirror( aTop, aBottom );
401 }
402 if ( bFlipV )
403 {
404 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 );
405 Point aRight( aLeft.X() + 1000, aLeft.Y() );
406 pObj->NbcMirror( aLeft, aRight );
407 }
408
409 basegfx::B2DPolyPolygon aPolyPolygon;
410 SdrObjListIter aIter( *pObj, IM_DEEPWITHGROUPS );
411
412 while ( aIter.IsMore() )
413 {
414 SdrObject* pNewObj = NULL;
415 basegfx::B2DPolyPolygon aPP;
416 const SdrObject* pNext = aIter.Next();
417
418 if ( pNext->ISA( SdrPathObj ) )
419 {
420 aPP = ((SdrPathObj*)pNext)->GetPathPoly();
421 }
422 else
423 {
424 pNewObj = pNext->ConvertToPolyObj( sal_False, sal_False );
425 SdrPathObj* pPath = PTR_CAST( SdrPathObj, pNewObj );
426 if ( pPath )
427 aPP = pPath->GetPathPoly();
428 }
429
430 if ( aPP.count() )
431 aPolyPolygon.append(aPP);
432
433 SdrObject::Free( pNewObj );
434 }
435 SdrObject::Free( pObj );
436 SvxConvertB2DPolyPolygonToPolyPolygonBezier( aPolyPolygon, aPolyPolygonBezierCoords );
437 }
438 }
439
440 return aPolyPolygonBezierCoords;
441 }
442
SEQ(REF (com::sun::star::drawing::XCustomShapeHandle))443 SEQ( REF( com::sun::star::drawing::XCustomShapeHandle ) ) SAL_CALL EnhancedCustomShapeEngine::getInteraction()
444 {
445 sal_uInt32 i, nHdlCount = 0;
446 SdrObject* pSdrObjCustomShape = GetSdrObjectFromXShape( mxShape );
447 if ( pSdrObjCustomShape )
448 {
449 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape );
450 nHdlCount = aCustomShape2d.GetHdlCount();
451 }
452 SEQ( REF( com::sun::star::drawing::XCustomShapeHandle ) ) aSeq( nHdlCount );
453 for ( i = 0; i < nHdlCount; i++ )
454 aSeq[ i ] = new EnhancedCustomShapeHandle( mxShape, i );
455 return aSeq;
456 }
457