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