1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include "EnhancedCustomShape3d.hxx"
31 #include <svx/svdetc.hxx>
32 #include <svx/svdmodel.hxx>
33 #include <tools/poly.hxx>
34 #include <svx/svditer.hxx>
35 #include <svx/svdobj.hxx>
36 #include <svx/svdoashp.hxx>
37 #include <svl/poolitem.hxx>
38 #include <svl/itemset.hxx>
39 #include <svx/xfillit0.hxx>
40 #include <svx/xsflclit.hxx>
41 #include <svx/xit.hxx>
42 #include <svx/xbtmpit.hxx>
43 #include <svx/xflclit.hxx>
44 #include <svx/svdopath.hxx>
45 #include <svx/svdogrp.hxx>
46 #include <svx/svdpage.hxx>
47 #include <svx/polysc3d.hxx>
48 #include <svx/svddef.hxx>
49 #include <svx/svx3ditems.hxx>
50 #include <svx/extrud3d.hxx>
51 #include <svx/xflbmtit.hxx>
52 #include <vcl/svapp.hxx>
53 #include <svx/xlnclit.hxx>
54 #include <svx/sdasitm.hxx>
55 #include <com/sun/star/awt/Point.hpp>
56 #include <com/sun/star/drawing/Position3D.hpp>
57 #include <com/sun/star/drawing/Direction3D.hpp>
58 #include <com/sun/star/drawing/ShadeMode.hpp>
59 #include <svx/sdr/properties/properties.hxx>
60 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
61 #include <basegfx/polygon/b2dpolypolygontools.hxx>
62 #include <basegfx/range/b2drange.hxx>
63 
64 #define ITEMVALUE(ItemSet,Id,Cast)  ((const Cast&)(ItemSet).Get(Id)).GetValue()
65 using namespace com::sun::star;
66 using namespace com::sun::star::uno;
67 
68 const rtl::OUString	sExtrusion( RTL_CONSTASCII_USTRINGPARAM ( "Extrusion" ) );
69 
70 void GetOrigin( SdrCustomShapeGeometryItem& rItem, double& rOriginX, double& rOriginY )
71 {
72 	::com::sun::star::drawing::EnhancedCustomShapeParameterPair aOriginParaPair;
73  	const rtl::OUString	sOrigin( RTL_CONSTASCII_USTRINGPARAM ( "Origin" ) );
74 	Any* pAny = rItem.GetPropertyValueByName( sExtrusion, sOrigin );
75 	if ( ! ( pAny && ( *pAny >>= aOriginParaPair ) && ( aOriginParaPair.First.Value >>= rOriginX ) && ( aOriginParaPair.Second.Value >>= rOriginY ) ) )
76 	{
77 		rOriginX = 0.50;
78 		rOriginY =-0.50;
79 	}
80 }
81 
82 void GetRotateAngle( SdrCustomShapeGeometryItem& rItem, double& rAngleX, double& rAngleY )
83 {
84 	::com::sun::star::drawing::EnhancedCustomShapeParameterPair aRotateAngleParaPair;
85  	const rtl::OUString	sRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "RotateAngle" ) );
86 	Any* pAny = rItem.GetPropertyValueByName( sExtrusion, sRotateAngle );
87 	if ( ! ( pAny && ( *pAny >>= aRotateAngleParaPair ) && ( aRotateAngleParaPair.First.Value >>= rAngleX ) && ( aRotateAngleParaPair.Second.Value >>= rAngleY ) ) )
88 	{
89 		rAngleX = 0.0;
90 		rAngleY = 0.0;
91 	}
92 	rAngleX *= F_PI180;
93 	rAngleY *= F_PI180;
94 }
95 
96 void GetSkew( SdrCustomShapeGeometryItem& rItem, double& rSkewAmount, double& rSkewAngle )
97 {
98 	::com::sun::star::drawing::EnhancedCustomShapeParameterPair aSkewParaPair;
99  	const rtl::OUString	sSkew( RTL_CONSTASCII_USTRINGPARAM ( "Skew" ) );
100 	Any* pAny = rItem.GetPropertyValueByName( sExtrusion, sSkew );
101 	if ( ! ( pAny && ( *pAny >>= aSkewParaPair ) && ( aSkewParaPair.First.Value >>= rSkewAmount ) && ( aSkewParaPair.Second.Value >>= rSkewAngle ) ) )
102 	{
103 		rSkewAmount = 50;
104 		rSkewAngle = -135;
105 	}
106 	rSkewAngle *= F_PI180;
107 }
108 
109 void GetExtrusionDepth( SdrCustomShapeGeometryItem& rItem, const double* pMap, double& rBackwardDepth, double& rForwardDepth )
110 {
111 	::com::sun::star::drawing::EnhancedCustomShapeParameterPair aDepthParaPair;
112 	double fDepth = 0, fFraction = 0;
113 	const rtl::OUString	sDepth( RTL_CONSTASCII_USTRINGPARAM ( "Depth" ) );
114 	Any* pAny = rItem.GetPropertyValueByName( sExtrusion, sDepth );
115 	if ( pAny && ( *pAny >>= aDepthParaPair ) && ( aDepthParaPair.First.Value >>= fDepth ) && ( aDepthParaPair.Second.Value >>= fFraction ) )
116 	{
117 		rForwardDepth = fDepth * fFraction;
118 		rBackwardDepth = fDepth - rForwardDepth;
119 	}
120 	else
121 	{
122 		rBackwardDepth = 1270;
123 		rForwardDepth = 0;
124 	}
125 	if ( pMap )
126 	{
127 		double fMap = *pMap;
128 		rBackwardDepth *= fMap;
129 		rForwardDepth *= fMap;
130 	}
131 }
132 
133 double GetDouble( SdrCustomShapeGeometryItem& rItem, const rtl::OUString& rPropertyName, double fDefault, const double* pMap )
134 {
135 	double fRetValue = fDefault;
136 	Any* pAny = rItem.GetPropertyValueByName( sExtrusion, rPropertyName );
137 	if ( pAny )
138 		*pAny >>= fRetValue;
139 	if ( pMap )
140 		fRetValue *= *pMap;
141 	return fRetValue;
142 }
143 
144 drawing::ShadeMode GetShadeMode( SdrCustomShapeGeometryItem& rItem, const drawing::ShadeMode eDefault )
145 {
146 	drawing::ShadeMode eRet( eDefault );
147 	const rtl::OUString	sShadeMode( RTL_CONSTASCII_USTRINGPARAM ( "ShadeMode" ) );
148 	Any* pAny = rItem.GetPropertyValueByName( sExtrusion, sShadeMode );
149 	if ( pAny )
150 		*pAny >>= eRet;
151 	return eRet;
152 }
153 
154 sal_Int32 GetInt32( SdrCustomShapeGeometryItem& rItem, const rtl::OUString& rPropertyName, const sal_Int32 nDefault )
155 {
156 	sal_Int32 nRetValue = nDefault;
157 	Any* pAny = rItem.GetPropertyValueByName( sExtrusion, rPropertyName );
158 	if ( pAny )
159 		*pAny >>= nRetValue;
160 	return nRetValue;
161 }
162 
163 sal_Bool GetBool( SdrCustomShapeGeometryItem& rItem, const rtl::OUString& rPropertyName, const sal_Bool bDefault )
164 {
165 	sal_Bool bRetValue = bDefault;
166 	const Any* pAny = rItem.GetPropertyValueByName( sExtrusion, rPropertyName );
167 	if ( pAny )
168 		*pAny >>= bRetValue;
169 	return bRetValue;
170 }
171 
172 awt::Point GetPoint( SdrCustomShapeGeometryItem& rItem, const rtl::OUString& rPropertyName, const awt::Point& rDefault )
173 {
174 	awt::Point aRetValue( rDefault );
175 	const Any* pAny = rItem.GetPropertyValueByName( sExtrusion, rPropertyName );
176 	if ( pAny )
177 		*pAny >>= aRetValue;
178 	return aRetValue;
179 }
180 
181 drawing::Position3D GetPosition3D( SdrCustomShapeGeometryItem& rItem, const rtl::OUString& rPropertyName,
182 									const drawing::Position3D& rDefault, const double* pMap )
183 {
184 	drawing::Position3D aRetValue( rDefault );
185 	const Any* pAny = rItem.GetPropertyValueByName( sExtrusion, rPropertyName );
186 	if ( pAny )
187 		*pAny >>= aRetValue;
188 	if ( pMap )
189 	{
190 		aRetValue.PositionX *= *pMap;
191 		aRetValue.PositionY *= *pMap;
192 		aRetValue.PositionZ *= *pMap;
193 	}
194 	return aRetValue;
195 }
196 
197 drawing::Direction3D GetDirection3D( SdrCustomShapeGeometryItem& rItem, const rtl::OUString& rPropertyName, const drawing::Direction3D& rDefault )
198 {
199 	drawing::Direction3D aRetValue( rDefault );
200 	const Any* pAny = rItem.GetPropertyValueByName( sExtrusion, rPropertyName );
201 	if ( pAny )
202 		*pAny >>= aRetValue;
203 	return aRetValue;
204 }
205 
206 EnhancedCustomShape3d::Transformation2D::Transformation2D( const SdrObject* pCustomShape, const Rectangle& /*rBoundRect*/, const double *pM )
207 :	aCenter( pCustomShape->GetSnapRect().Center() )
208 ,	eProjectionMode( drawing::ProjectionMode_PARALLEL )
209 ,	pMap( pM )
210 {
211 	SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
212 	const rtl::OUString	sProjectionMode( RTL_CONSTASCII_USTRINGPARAM ( "ProjectionMode" ) );
213 	Any* pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, sProjectionMode );
214 	if ( pAny )
215 		*pAny >>= eProjectionMode;
216 
217 	if ( eProjectionMode == drawing::ProjectionMode_PARALLEL )
218 		GetSkew( rGeometryItem, fSkew, fSkewAngle );
219 	else
220 	{
221 		fZScreen = 0.0;
222 		GetOrigin( rGeometryItem, fOriginX, fOriginY );
223 		fOriginX = fOriginX * pCustomShape->GetLogicRect().GetWidth();
224 		fOriginY = fOriginY * pCustomShape->GetLogicRect().GetHeight();
225 
226 		const rtl::OUString	sViewPoint( RTL_CONSTASCII_USTRINGPARAM ( "ViewPoint" ) );
227 		drawing::Position3D aViewPointDefault( 3472, -3472, 25000 );
228 		drawing::Position3D aViewPoint( GetPosition3D( rGeometryItem, sViewPoint, aViewPointDefault, pMap ) );
229 		fViewPoint.setX(aViewPoint.PositionX);
230 		fViewPoint.setY(aViewPoint.PositionY);
231 		fViewPoint.setZ(-aViewPoint.PositionZ);
232 	}
233 }
234 
235 basegfx::B3DPolygon EnhancedCustomShape3d::Transformation2D::ApplySkewSettings( const basegfx::B3DPolygon& rPoly3D ) const
236 {
237 	basegfx::B3DPolygon aRetval;
238 
239 	sal_uInt32 j;
240 	for ( j = 0L; j < rPoly3D.count(); j++ )
241 	{
242 		const basegfx::B3DPoint aPoint(rPoly3D.getB3DPoint(j));
243 		double fDepth(-( aPoint.getZ() * fSkew ) / 100.0);
244 		aRetval.append(basegfx::B3DPoint(
245 			aPoint.getX() + (fDepth * cos( fSkewAngle )),
246 			aPoint.getY() - (fDepth * sin( fSkewAngle )),
247 			aPoint.getZ()));
248 	}
249 
250 	return aRetval;
251 }
252 
253 Point EnhancedCustomShape3d::Transformation2D::Transform2D( const basegfx::B3DPoint& rPoint3D ) const
254 {
255 	Point aPoint2D;
256 	if ( eProjectionMode == drawing::ProjectionMode_PARALLEL )
257 	{
258 		aPoint2D.X() = (sal_Int32)rPoint3D.getX();
259 		aPoint2D.Y() = (sal_Int32)rPoint3D.getY();
260 	}
261 	else
262 	{
263 		double fX = rPoint3D.getX() - fOriginX;
264 		double fY = rPoint3D.getY() - fOriginY;
265 		double f = ( fZScreen - fViewPoint.getZ() ) / ( rPoint3D.getZ() - fViewPoint.getZ() );
266 		aPoint2D.X() = (sal_Int32)(( fX - fViewPoint.getX() ) * f + fViewPoint.getX() + fOriginX );
267 		aPoint2D.Y() = (sal_Int32)(( fY - fViewPoint.getY() ) * f + fViewPoint.getY() + fOriginY );
268 	}
269 	aPoint2D.Move( aCenter.X(), aCenter.Y() );
270 	return aPoint2D;
271 }
272 
273 sal_Bool EnhancedCustomShape3d::Transformation2D::IsParallel() const
274 {
275 	return eProjectionMode == com::sun::star::drawing::ProjectionMode_PARALLEL;
276 }
277 
278 SdrObject* EnhancedCustomShape3d::Create3DObject( const SdrObject* pShape2d, const SdrObject* pCustomShape )
279 {
280 	SdrObject*	pRet = NULL;
281 	SdrModel*	pModel = pCustomShape->GetModel();
282 	SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
283 
284 	double		fMap, *pMap = NULL;
285 	if ( pModel )
286 	{
287 		fMap = 1.0;
288 		Fraction aFraction( pModel->GetScaleFraction() );
289 		if ( ( aFraction.GetNumerator() ) != 1 || ( aFraction.GetDenominator() != 1 ) )
290 		{
291 			fMap *= aFraction.GetNumerator();
292 			fMap /= aFraction.GetDenominator();
293 			pMap = &fMap;
294 		}
295 		if ( pModel->GetScaleUnit() != MAP_100TH_MM )
296 		{
297 			DBG_ASSERT( pModel->GetScaleUnit() == MAP_TWIP, "EnhancedCustomShape3d::Current MapMode is Unsupported" );
298 			fMap *= 1440.0 / 2540.0;
299 			pMap = &fMap;
300 		}
301 	}
302 	if ( GetBool( rGeometryItem, sExtrusion, sal_False ) )
303 	{
304 		sal_Bool bIsMirroredX = ((SdrObjCustomShape*)pCustomShape)->IsMirroredX();
305 		sal_Bool bIsMirroredY = ((SdrObjCustomShape*)pCustomShape)->IsMirroredY();
306 		Rectangle aSnapRect( pCustomShape->GetLogicRect() );
307 		long nObjectRotation = pCustomShape->GetRotateAngle();
308 		if ( nObjectRotation )
309 		{
310 			double a = ( 36000 - nObjectRotation ) * nPi180;
311 			long dx = aSnapRect.Right() - aSnapRect.Left();
312 			long dy = aSnapRect.Bottom()- aSnapRect.Top();
313 			Point aP( aSnapRect.TopLeft() );
314 			RotatePoint( aP, pCustomShape->GetSnapRect().Center(), sin( a ), cos( a ) );
315 			aSnapRect.Left() = aP.X();
316 			aSnapRect.Top() = aP.Y();
317 			aSnapRect.Right() = aSnapRect.Left() + dx;
318 			aSnapRect.Bottom() = aSnapRect.Top() + dy;
319 		}
320 		Point aCenter( aSnapRect.Center() );
321 
322 		SfxItemSet aSet( pCustomShape->GetMergedItemSet() );
323 
324         //SJ: vertical writing is not required, by removing this item no outliner is created
325         aSet.ClearItem( SDRATTR_TEXTDIRECTION );
326 
327         // #i105323# For 3D AutoShapes, the shadow attribute has to be applied to each
328 		// created visualisation helper model shape individually. The shadow itself
329 		// will then be rendered from the 3D renderer correctly for the whole 3D scene
330 		// (and thus behind all objects of which the visualisation may be built). So,
331 		// dio NOT remove it from the ItemSet here.
332 	    // aSet.ClearItem(SDRATTR_SHADOW);
333 
334         std::vector< E3dCompoundObject* > aPlaceholderObjectList;
335 
336 		double fExtrusionBackward, fExtrusionForward;
337 		GetExtrusionDepth( rGeometryItem, pMap, fExtrusionBackward, fExtrusionForward );
338 		double fDepth = fExtrusionBackward - fExtrusionForward;
339 		if ( fDepth < 1.0 )
340 			fDepth = 1.0;
341 
342 		drawing::ProjectionMode eProjectionMode( drawing::ProjectionMode_PARALLEL );
343 		const rtl::OUString	sProjectionMode( RTL_CONSTASCII_USTRINGPARAM ( "ProjectionMode" ) );
344 		Any* pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, sProjectionMode );
345 		if ( pAny )
346 			*pAny >>= eProjectionMode;
347 		ProjectionType eProjectionType( eProjectionMode == drawing::ProjectionMode_PARALLEL ? PR_PARALLEL : PR_PERSPECTIVE );
348 
349 		// pShape2d Umwandeln in Szene mit 3D Objekt
350 		E3dDefaultAttributes a3DDefaultAttr;
351 		a3DDefaultAttr.SetDefaultLatheCharacterMode( sal_True );
352 		a3DDefaultAttr.SetDefaultExtrudeCharacterMode( sal_True );
353 
354 		E3dScene* pScene = new E3dPolyScene( a3DDefaultAttr );
355 
356 		sal_Bool bSceneHasObjects ( sal_False );
357 		sal_Bool bUseTwoFillStyles( sal_False );
358 
359 		drawing::ShadeMode eShadeMode( GetShadeMode( rGeometryItem, drawing::ShadeMode_FLAT ) );
360 		const rtl::OUString	sExtrusionColor( RTL_CONSTASCII_USTRINGPARAM ( "Color" ) );
361 		sal_Bool bUseExtrusionColor = GetBool( rGeometryItem, sExtrusionColor, sal_False );
362 
363 		XFillStyle eFillStyle( ITEMVALUE( aSet, XATTR_FILLSTYLE, XFillStyleItem ) );
364 		pScene->GetProperties().SetObjectItem( Svx3DShadeModeItem( 0 ) );
365 		aSet.Put( Svx3DPercentDiagonalItem( 0 ) );
366 		aSet.Put( Svx3DTextureModeItem( 1 ) );
367 		aSet.Put( Svx3DNormalsKindItem( 1 ) );
368 
369 		if ( eShadeMode == drawing::ShadeMode_DRAFT )
370 		{
371 			aSet.Put( XLineStyleItem( XLINE_SOLID ) );
372 			aSet.Put( XFillStyleItem ( XFILL_NONE ) );
373 			aSet.Put( Svx3DDoubleSidedItem( sal_True ) );
374 		}
375 		else
376 		{
377 			aSet.Put( XLineStyleItem( XLINE_NONE ) );
378 			if ( eFillStyle == XFILL_NONE )
379 				aSet.Put( XFillStyleItem( XFILL_SOLID ) );
380 			else if ( ( eFillStyle == XFILL_BITMAP ) || ( eFillStyle == XFILL_GRADIENT ) || bUseExtrusionColor )
381 				bUseTwoFillStyles = sal_True;
382 
383 			// #116336#
384 			// If shapes are mirrored once (mirroring two times correct geometry again)
385 			// double-sided at the object and two-sided-lighting at the scene need to be set.
386 			if((bIsMirroredX && !bIsMirroredY) || (!bIsMirroredX && bIsMirroredY))
387 			{
388 				aSet.Put( Svx3DDoubleSidedItem( sal_True ) );
389 				pScene->GetProperties().SetObjectItem( Svx3DTwoSidedLightingItem( sal_True ) );
390 			}
391 		}
392 
393 		Rectangle aBoundRect2d;
394 		SdrObjListIter aIter( *pShape2d, IM_DEEPWITHGROUPS );
395 		while( aIter.IsMore() )
396 		{
397 			const SdrObject* pNext = aIter.Next();
398 			sal_Bool bIsPlaceholderObject = (((XFillStyleItem&)pNext->GetMergedItem( XATTR_FILLSTYLE )).GetValue() == XFILL_NONE )
399 										&& (((XLineStyleItem&)pNext->GetMergedItem( XATTR_LINESTYLE )).GetValue() == XLINE_NONE );
400 			basegfx::B2DPolyPolygon aPolyPoly;
401 
402 			if ( pNext->ISA( SdrPathObj ) )
403 			{
404 				aPolyPoly = ((SdrPathObj*)pNext)->GetPathPoly();
405 
406 				if(aPolyPoly.areControlPointsUsed())
407 				{
408 					aPolyPoly = basegfx::tools::adaptiveSubdivideByAngle(aPolyPoly);
409 				}
410 			}
411 			else
412 			{
413 				SdrObject* pNewObj = pNext->ConvertToPolyObj( sal_False, sal_False );
414 				SdrPathObj* pPath = PTR_CAST( SdrPathObj, pNewObj );
415 				if ( pPath )
416 					aPolyPoly = pPath->GetPathPoly();
417                 SdrObject::Free( pNewObj );
418 			}
419 
420 			if( aPolyPoly.count() )
421 			{
422 				const basegfx::B2DRange aTempRange(basegfx::tools::getRange(aPolyPoly));
423                 const Rectangle aBoundRect(basegfx::fround(aTempRange.getMinX()), basegfx::fround(aTempRange.getMinY()), basegfx::fround(aTempRange.getMaxX()), basegfx::fround(aTempRange.getMaxY()));
424 				aBoundRect2d.Union( aBoundRect );
425 
426 				E3dCompoundObject* p3DObj = new E3dExtrudeObj( a3DDefaultAttr, aPolyPoly, bUseTwoFillStyles ? 10 : fDepth );
427 				p3DObj->NbcSetLayer( pShape2d->GetLayer() );
428 				p3DObj->SetMergedItemSet( aSet );
429 				if ( bIsPlaceholderObject )
430 					aPlaceholderObjectList.push_back( p3DObj );
431 				else if ( bUseTwoFillStyles )
432 				{
433 					Bitmap aFillBmp;
434 					sal_Bool bFillBmpTile = ((XFillBmpTileItem&)p3DObj->GetMergedItem( XATTR_FILLBMP_TILE )).GetValue();
435 					if ( bFillBmpTile )
436 					{
437 						const XFillBitmapItem& rBmpItm = (XFillBitmapItem&)p3DObj->GetMergedItem( XATTR_FILLBITMAP );
438 						const XOBitmap& rXOBmp = rBmpItm.GetBitmapValue();
439 						aFillBmp = rXOBmp.GetBitmap();
440 						Size aLogicalSize = aFillBmp.GetPrefSize();
441 						if ( aFillBmp.GetPrefMapMode() == MAP_PIXEL )
442 							aLogicalSize = Application::GetDefaultDevice()->PixelToLogic( aLogicalSize, MAP_100TH_MM );
443 						else
444 							aLogicalSize = OutputDevice::LogicToLogic( aLogicalSize, aFillBmp.GetPrefMapMode(), MAP_100TH_MM );
445 						aLogicalSize.Width()  *= 5;			;//				:-(		nice scaling, look at engine3d/obj3d.cxx
446 						aLogicalSize.Height() *= 5;
447 						aFillBmp.SetPrefSize( aLogicalSize );
448 						aFillBmp.SetPrefMapMode( MAP_100TH_MM );
449 						p3DObj->SetMergedItem( XFillBitmapItem( String(), aFillBmp ) );
450 					}
451 					else
452 					{
453 						if ( aSnapRect != aBoundRect )
454 						{
455 							const XFillBitmapItem& rBmpItm = (XFillBitmapItem&)p3DObj->GetMergedItem( XATTR_FILLBITMAP );
456 							const XOBitmap& rXOBmp = rBmpItm.GetBitmapValue();
457 							aFillBmp = rXOBmp.GetBitmap();
458 							Size aBmpSize( aFillBmp.GetSizePixel() );
459 							double fXScale = (double)aBoundRect.GetWidth() / (double)aSnapRect.GetWidth();
460 							double fYScale = (double)aBoundRect.GetHeight() / (double)aSnapRect.GetHeight();
461 
462 							Point aPt( (sal_Int32)( (double)( aBoundRect.Left() - aSnapRect.Left() )* (double)aBmpSize.Width() / (double)aSnapRect.GetWidth() ),
463 												(sal_Int32)( (double)( aBoundRect.Top() - aSnapRect.Top() ) * (double)aBmpSize.Height() / (double)aSnapRect.GetHeight() ) );
464 							Size aSize( (sal_Int32)( aBmpSize.Width() * fXScale ),
465 													(sal_Int32)( aBmpSize.Height() * fYScale ) );
466 							Rectangle aCropRect( aPt, aSize );
467  							aFillBmp.Crop( aCropRect );
468 							p3DObj->SetMergedItem( XFillBitmapItem( String(), aFillBmp ) );
469 						}
470 					}
471 					pScene->Insert3DObj( p3DObj );
472 					p3DObj = new E3dExtrudeObj( a3DDefaultAttr, aPolyPoly, fDepth );
473 					p3DObj->NbcSetLayer( pShape2d->GetLayer() );
474 					p3DObj->SetMergedItemSet( aSet );
475 					if ( bUseExtrusionColor )
476 						p3DObj->SetMergedItem( XFillColorItem( String(), ((XSecondaryFillColorItem&)pCustomShape->GetMergedItem( XATTR_SECONDARYFILLCOLOR )).GetColorValue() ) );
477 					p3DObj->SetMergedItem( XFillStyleItem( XFILL_SOLID ) );
478 					p3DObj->SetMergedItem( Svx3DCloseFrontItem( sal_False ) );
479 					p3DObj->SetMergedItem( Svx3DCloseBackItem( sal_False ) );
480 					pScene->Insert3DObj( p3DObj );
481 					p3DObj = new E3dExtrudeObj( a3DDefaultAttr, aPolyPoly, 10 );
482 					p3DObj->NbcSetLayer( pShape2d->GetLayer() );
483 					p3DObj->SetMergedItemSet( aSet );
484 
485 					basegfx::B3DHomMatrix aFrontTransform( p3DObj->GetTransform() );
486 					aFrontTransform.translate( 0.0, 0.0, fDepth );
487 					p3DObj->NbcSetTransform( aFrontTransform );
488 
489 					if ( ( eFillStyle == XFILL_BITMAP ) && !aFillBmp.IsEmpty() )
490 						p3DObj->SetMergedItem( XFillBitmapItem( String(), aFillBmp ) );
491 				}
492 				else if ( eFillStyle == XFILL_NONE )
493 				{
494 					XLineColorItem& rLineColor = (XLineColorItem&)p3DObj->GetMergedItem( XATTR_LINECOLOR );
495 					p3DObj->SetMergedItem( XFillColorItem( String(), rLineColor.GetColorValue() ) );
496 					p3DObj->SetMergedItem( Svx3DDoubleSidedItem( sal_True ) );
497 					p3DObj->SetMergedItem( Svx3DCloseFrontItem( sal_False ) );
498 					p3DObj->SetMergedItem( Svx3DCloseBackItem( sal_False ) );
499 				}
500 				pScene->Insert3DObj( p3DObj );
501 				bSceneHasObjects = sal_True;
502 			}
503 		}
504 
505 		if ( bSceneHasObjects )	// is the SdrObject properly converted
506 		{
507 			// then we can change the return value
508 			pRet = pScene;
509 
510 			// Kameraeinstellungen, Perspektive ...
511 			Camera3D& rCamera = (Camera3D&)pScene->GetCamera();
512 			const basegfx::B3DRange& rVolume = pScene->GetBoundVolume();
513 			pScene->NbcSetSnapRect( aSnapRect );
514 
515 			// InitScene replacement
516 			double fW = rVolume.getWidth();
517 			double fH = rVolume.getHeight();
518 
519 			rCamera.SetAutoAdjustProjection( sal_False );
520 			rCamera.SetViewWindow( -fW / 2, - fH / 2, fW, fH);
521 			basegfx::B3DPoint aLookAt( 0.0, 0.0, 0.0 );
522 			basegfx::B3DPoint aCamPos( 0.0, 0.0, 100.0 );
523 			rCamera.SetDefaults( basegfx::B3DPoint( 0.0, 0.0, 100.0 ), aLookAt, 100.0 );
524 			rCamera.SetPosAndLookAt( aCamPos, aLookAt );
525 			rCamera.SetFocalLength( 1.0 );
526 			rCamera.SetProjection( eProjectionType );
527 			pScene->SetCamera( rCamera );
528 			pScene->SetRectsDirty();
529 
530 			double fOriginX, fOriginY;
531 			GetOrigin( rGeometryItem, fOriginX, fOriginY );
532 			fOriginX = fOriginX * aSnapRect.GetWidth();
533 			fOriginY = fOriginY * aSnapRect.GetHeight();
534 
535 			basegfx::B3DHomMatrix aNewTransform( pScene->GetTransform() );
536 			aNewTransform.translate( -aCenter.X(), aCenter.Y(), -pScene->GetBoundVolume().getDepth() );
537 
538 			double fXRotate, fYRotate;
539 			GetRotateAngle( rGeometryItem, fXRotate, fYRotate );
540 			double fZRotate = ((SdrObjCustomShape*)pCustomShape)->GetObjectRotation() * F_PI180;
541 			if ( fZRotate != 0.0 )
542 				aNewTransform.rotate( 0.0, 0.0, fZRotate );
543 			if ( bIsMirroredX )
544 				aNewTransform.scale( -1.0, 1, 1 );
545 			if ( bIsMirroredY )
546 				aNewTransform.scale( 1, -1.0, 1 );
547 			if( fYRotate != 0.0 )
548 				aNewTransform.rotate( 0.0, -fYRotate, 0.0 );
549 			if( fXRotate != 0.0 )
550 				aNewTransform.rotate( -fXRotate, 0.0, 0.0 );
551 			if ( eProjectionType == PR_PARALLEL )
552 			{
553 				double fSkew, fAlpha;
554 				GetSkew( rGeometryItem, fSkew, fAlpha );
555 				if ( fSkew != 0.0 )
556 				{
557 					double fInvTanBeta( fSkew / 100.0 );
558 					if(fInvTanBeta)
559 					{
560 						aNewTransform.shearXY(
561 							fInvTanBeta * cos(fAlpha),
562 							fInvTanBeta * sin(fAlpha));
563 					}
564 				}
565 				basegfx::B3DPoint _aLookAt( 0.0, 0.0, 0.0 );
566 				basegfx::B3DPoint _aNewCamPos( 0.0, 0.0, 25000.0 );
567 				rCamera.SetPosAndLookAt( _aNewCamPos, _aLookAt );
568 				pScene->SetCamera( rCamera );
569 			}
570 			else
571 			{
572 				aNewTransform.translate( -fOriginX, fOriginY, 0.0 );
573 				// now set correct camera position
574 				const rtl::OUString	sViewPoint( RTL_CONSTASCII_USTRINGPARAM ( "ViewPoint" ) );
575 				drawing::Position3D aViewPointDefault( 3472, -3472, 25000 );
576 				drawing::Position3D aViewPoint( GetPosition3D( rGeometryItem, sViewPoint, aViewPointDefault, pMap ) );
577 				double fViewPointX = aViewPoint.PositionX;
578 				double fViewPointY = aViewPoint.PositionY;
579 				double fViewPointZ = aViewPoint.PositionZ;
580 				basegfx::B3DPoint _aLookAt( fViewPointX, -fViewPointY, 0.0 );
581 				basegfx::B3DPoint aNewCamPos( fViewPointX, -fViewPointY, fViewPointZ );
582 				rCamera.SetPosAndLookAt( aNewCamPos, _aLookAt );
583 				pScene->SetCamera( rCamera );
584 			}
585 
586 			pScene->NbcSetTransform( aNewTransform );
587 
588 			///////////
589 			// light //
590 			///////////
591 
592 			const rtl::OUString	sBrightness( RTL_CONSTASCII_USTRINGPARAM ( "Brightness" ) );
593 			double fAmbientIntensity = GetDouble( rGeometryItem, sBrightness, 22178.0 / 655.36, NULL ) / 100.0;
594 
595 
596 			const rtl::OUString	sFirstLightDirection( RTL_CONSTASCII_USTRINGPARAM ( "FirstLightDirection" ) );
597 			drawing::Direction3D aFirstLightDirectionDefault( 50000, 0, 10000 );
598 			drawing::Direction3D aFirstLightDirection( GetDirection3D( rGeometryItem, sFirstLightDirection, aFirstLightDirectionDefault ) );
599 			if ( aFirstLightDirection.DirectionZ == 0.0 )
600 				aFirstLightDirection.DirectionZ = 1.0;
601 
602 			const rtl::OUString	sFirstLightLevel( RTL_CONSTASCII_USTRINGPARAM ( "FirstLightLevel" ) );
603 			double fLightIntensity = GetDouble( rGeometryItem, sFirstLightLevel, 43712.0 / 655.36, NULL ) / 100.0;
604 
605 			const rtl::OUString	sFirstLightHarsh( RTL_CONSTASCII_USTRINGPARAM ( "FirstLightHarsh" ) );
606 			/* sal_Bool bFirstLightHarsh = */ GetBool( rGeometryItem, sFirstLightHarsh, sal_False );
607 
608 			const rtl::OUString	sSecondLightDirection( RTL_CONSTASCII_USTRINGPARAM ( "SecondLightDirection" ) );
609 			drawing::Direction3D aSecondLightDirectionDefault( -50000, 0, 10000 );
610 			drawing::Direction3D aSecondLightDirection( GetDirection3D( rGeometryItem, sSecondLightDirection, aSecondLightDirectionDefault ) );
611 			if ( aSecondLightDirection.DirectionZ == 0.0 )
612 				aSecondLightDirection.DirectionZ = -1;
613 
614 			const rtl::OUString	sSecondLightLevel( RTL_CONSTASCII_USTRINGPARAM ( "SecondLightLevel" ) );
615 			double fLight2Intensity = GetDouble( rGeometryItem, sSecondLightLevel, 43712.0 / 655.36, NULL ) / 100.0;
616 
617 			const rtl::OUString	sSecondLightHarsh( RTL_CONSTASCII_USTRINGPARAM ( "SecondLightHarsh" ) );
618 			const rtl::OUString	sLightFace( RTL_CONSTASCII_USTRINGPARAM ( "LightFace" ) );
619 			/* sal_Bool bLight2Harsh = */ GetBool( rGeometryItem, sSecondLightHarsh, sal_False );
620 			/* sal_Bool bLightFace = */ GetBool( rGeometryItem, sLightFace, sal_False );
621 
622 			sal_uInt16 nAmbientColor = (sal_uInt16)( fAmbientIntensity * 255.0 );
623 			if ( nAmbientColor > 255 )
624 				nAmbientColor = 255;
625 			Color aGlobalAmbientColor( (sal_uInt8)nAmbientColor, (sal_uInt8)nAmbientColor, (sal_uInt8)nAmbientColor );
626 			pScene->GetProperties().SetObjectItem( Svx3DAmbientcolorItem( aGlobalAmbientColor ) );
627 
628 			sal_uInt8 nSpotLight1 = (sal_uInt8)( fLightIntensity * 255.0 );
629 			basegfx::B3DVector aSpotLight1( aFirstLightDirection.DirectionX, - ( aFirstLightDirection.DirectionY ), -( aFirstLightDirection.DirectionZ ) );
630 			aSpotLight1.normalize();
631 			pScene->GetProperties().SetObjectItem( Svx3DLightOnOff1Item( sal_True ) );
632 			Color aAmbientSpot1Color( nSpotLight1, nSpotLight1, nSpotLight1 );
633 			pScene->GetProperties().SetObjectItem( Svx3DLightcolor1Item( aAmbientSpot1Color ) );
634 			pScene->GetProperties().SetObjectItem( Svx3DLightDirection1Item( aSpotLight1 ) );
635 
636 			sal_uInt8 nSpotLight2 = (sal_uInt8)( fLight2Intensity * 255.0 );
637 			basegfx::B3DVector aSpotLight2( aSecondLightDirection.DirectionX, -aSecondLightDirection.DirectionY, -aSecondLightDirection.DirectionZ );
638 			aSpotLight2.normalize();
639 			pScene->GetProperties().SetObjectItem( Svx3DLightOnOff2Item( sal_True ) );
640 			Color aAmbientSpot2Color( nSpotLight2, nSpotLight2, nSpotLight2 );
641 			pScene->GetProperties().SetObjectItem( Svx3DLightcolor2Item( aAmbientSpot2Color ) );
642 			pScene->GetProperties().SetObjectItem( Svx3DLightDirection2Item( aSpotLight2 ) );
643 
644 				sal_uInt8 nSpotLight3 = 70;
645 				basegfx::B3DVector aSpotLight3( 0.0, 0.0, 1.0 );
646 				pScene->GetProperties().SetObjectItem( Svx3DLightOnOff3Item( sal_True ) );
647 				Color aAmbientSpot3Color( nSpotLight3, nSpotLight3, nSpotLight3 );
648 				pScene->GetProperties().SetObjectItem( Svx3DLightcolor3Item( aAmbientSpot3Color ) );
649 				pScene->GetProperties().SetObjectItem( Svx3DLightDirection3Item( aSpotLight3 ) );
650 
651 			const rtl::OUString	sSpecularity( RTL_CONSTASCII_USTRINGPARAM ( "Specularity" ) );
652 			const rtl::OUString	sDiffusion( RTL_CONSTASCII_USTRINGPARAM ( "Diffusion" ) );
653 			const rtl::OUString	sShininess( RTL_CONSTASCII_USTRINGPARAM ( "Shininess" ) );
654 			const rtl::OUString	sMetal( RTL_CONSTASCII_USTRINGPARAM ( "Metal" ) );
655 			double fSpecular = GetDouble( rGeometryItem, sSpecularity, 0, NULL ) / 100;
656 			sal_Bool bMetal = GetBool( rGeometryItem, sMetal, sal_False );
657 
658 			Color aSpecularCol( 225,225,225 );
659 			if ( bMetal )
660 			{
661 				aSpecularCol = Color( 200, 200, 200 );
662 				fSpecular += 0.15;
663 			}
664 			sal_Int32 nIntensity = (sal_Int32)fSpecular * 100;
665 			if ( nIntensity > 100 )
666 				nIntensity = 100;
667 			else if ( nIntensity < 0 )
668 				nIntensity = 0;
669 			nIntensity = 100 - nIntensity;
670 			pScene->GetProperties().SetObjectItem( Svx3DMaterialSpecularItem( aSpecularCol ) );
671 			pScene->GetProperties().SetObjectItem( Svx3DMaterialSpecularIntensityItem( (sal_uInt16)nIntensity ) );
672 
673 			pScene->SetLogicRect( CalculateNewSnapRect( pCustomShape, aSnapRect, aBoundRect2d, pMap ) );
674 
675 			// removing placeholder objects
676 			std::vector< E3dCompoundObject* >::iterator aObjectListIter( aPlaceholderObjectList.begin() );
677 			while ( aObjectListIter != aPlaceholderObjectList.end() )
678 			{
679 				pScene->Remove3DObj( *aObjectListIter );
680 				delete *aObjectListIter++;
681 			}
682 		}
683 		else
684 			delete pScene;
685 	}
686 	return pRet;
687 }
688 
689 Rectangle EnhancedCustomShape3d::CalculateNewSnapRect( const SdrObject* pCustomShape, const Rectangle& rSnapRect, const Rectangle& rBoundRect, const double* pMap )
690 {
691 	SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
692 	const Point aCenter( rSnapRect.Center() );
693 	double fExtrusionBackward, fExtrusionForward;
694 	GetExtrusionDepth( rGeometryItem, pMap, fExtrusionBackward, fExtrusionForward );
695 	sal_uInt32 i;
696 
697 	// creating initial bound volume ( without rotation. skewing.and camera )
698 	basegfx::B3DPolygon aBoundVolume;
699 	const Polygon aPolygon( rBoundRect );
700 
701 	for ( i = 0L; i < 4L; i++ )
702 	{
703 		aBoundVolume.append(basegfx::B3DPoint(aPolygon[ (sal_uInt16)i ].X() - aCenter.X(), aPolygon[ (sal_uInt16)i ].Y() - aCenter.Y(), fExtrusionForward));
704 	}
705 
706 	for ( i = 0L; i < 4L; i++ )
707 	{
708 		aBoundVolume.append(basegfx::B3DPoint(aPolygon[ (sal_uInt16)i ].X() - aCenter.X(), aPolygon[ (sal_uInt16)i ].Y() - aCenter.Y(), fExtrusionBackward));
709 	}
710 
711 	const rtl::OUString	sRotationCenter( RTL_CONSTASCII_USTRINGPARAM ( "RotationCenter" ) );
712 	drawing::Direction3D aRotationCenterDefault( 0, 0, 0 );	// default seems to be wrong, a fractional size of shape has to be used!!
713 	drawing::Direction3D aRotationCenter( GetDirection3D( rGeometryItem, sRotationCenter, aRotationCenterDefault ) );
714 
715 	// double XCenterInGUnits = rPropSet.GetPropertyValue( DFF_Prop_c3DRotationCenterX, 0 );
716 	// double YCenterInGUnits = rPropSet.GetPropertyValue( DFF_Prop_c3DRotationCenterY, 0 );
717 
718 	// sal_Int32 nRotationXAxisInProz = rPropSet.GetPropertyValue( DFF_Prop_c3DRotationAxisX, 100 );
719 	// sal_Int32 nRotationYAxisInProz = rPropSet.GetPropertyValue( DFF_Prop_c3DRotationAxisY, 0 );
720 	// sal_Int32 nRotationZAxisInProz = rPropSet.GetPropertyValue( DFF_Prop_c3DRotationAxisZ, 0 );
721 
722 
723 	double fXRotate, fYRotate;
724 	GetRotateAngle( rGeometryItem, fXRotate, fYRotate );
725 	double fZRotate = - ((SdrObjCustomShape*)pCustomShape)->GetObjectRotation() * F_PI180;
726 
727 	// rotating bound volume
728 	basegfx::B3DHomMatrix aMatrix;
729 	aMatrix.translate(-aRotationCenter.DirectionX, -aRotationCenter.DirectionY, -aRotationCenter.DirectionZ);
730 	if ( fZRotate != 0.0 )
731 		aMatrix.rotate( 0.0, 0.0, fZRotate );
732 	if ( ((SdrObjCustomShape*)pCustomShape)->IsMirroredX() )
733 		aMatrix.scale( -1.0, 1, 1 );
734 	if ( ((SdrObjCustomShape*)pCustomShape)->IsMirroredY() )
735 		aMatrix.scale( 1, -1.0, 1 );
736 	if( fYRotate != 0.0 )
737 		aMatrix.rotate( 0.0, fYRotate, 0.0 );
738 	if( fXRotate != 0.0 )
739 		aMatrix.rotate( -fXRotate, 0.0, 0.0 );
740 	aMatrix.translate(aRotationCenter.DirectionX, aRotationCenter.DirectionY, aRotationCenter.DirectionZ);
741 	aBoundVolume.transform(aMatrix);
742 
743 	Transformation2D aTransformation2D( pCustomShape, rSnapRect, pMap );
744 	if ( aTransformation2D.IsParallel() )
745 		aBoundVolume = aTransformation2D.ApplySkewSettings( aBoundVolume );
746 
747 	Polygon aTransformed( 8 );
748 	for ( i = 0L; i < 8L; i++ )
749 		aTransformed[ (sal_uInt16)i ] = aTransformation2D.Transform2D( aBoundVolume.getB3DPoint( i ) );
750 
751 	return aTransformed.GetBoundRect();
752 }
753