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