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