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