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 "EnhancedCustomShapeEngine.hxx" 31 #include "svx/EnhancedCustomShape2d.hxx" 32 #include "EnhancedCustomShape3d.hxx" 33 #include "EnhancedCustomShapeFontWork.hxx" 34 #include "EnhancedCustomShapeHandle.hxx" 35 #include "svx/EnhancedCustomShapeGeometry.hxx" 36 #include <svx/unoshape.hxx> 37 #ifndef _SVX_UNOPAGE_HXX 38 #include "svx/unopage.hxx" 39 #endif 40 #include "svx/unoapi.hxx" 41 #include <svx/svdobj.hxx> 42 #include <svx/svdoashp.hxx> 43 #include <svx/svdogrp.hxx> 44 #include <svx/svdorect.hxx> 45 #include <editeng/outlobj.hxx> 46 #include <editeng/outliner.hxx> 47 #include <svx/svdoutl.hxx> 48 #include <svl/itemset.hxx> 49 #include <svx/svdopath.hxx> 50 #include <svx/svdpage.hxx> 51 #include <svx/svdmodel.hxx> 52 #include "svx/svditer.hxx" 53 #include "unopolyhelper.hxx" 54 #include <uno/mapping.hxx> 55 #include <basegfx/polygon/b2dpolypolygontools.hxx> 56 #include <com/sun/star/document/XActionLockable.hpp> 57 58 // --------------------------- 59 // - EnhancedCustomShapeEngine - 60 // --------------------------- 61 62 rtl::OUString EnhancedCustomShapeEngine_getImplementationName() 63 throw( NMSP_UNO::RuntimeException ) 64 { 65 return B2UCONST( "com.sun.star.drawing.EnhancedCustomShapeEngine" ); 66 } 67 sal_Bool SAL_CALL EnhancedCustomShapeEngine_supportsService( const rtl::OUString& ServiceName ) 68 throw( NMSP_UNO::RuntimeException ) 69 { 70 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.CustomShapeEngine" ) ); 71 } 72 SEQ( rtl::OUString ) SAL_CALL EnhancedCustomShapeEngine_getSupportedServiceNames() 73 throw( NMSP_UNO::RuntimeException ) 74 { 75 SEQ( rtl::OUString ) aRet(1); 76 rtl::OUString* pArray = aRet.getArray(); 77 pArray[0] = B2UCONST( "com.sun.star.drawing.CustomShapeEngine" ); 78 return aRet; 79 } 80 81 // ----------------------------------------------------------------------------- 82 83 EnhancedCustomShapeEngine::EnhancedCustomShapeEngine( const REF( NMSP_LANG::XMultiServiceFactory )& rxMgr ) : 84 mxFact ( rxMgr ), 85 mbForceGroupWithText ( sal_False ) 86 { 87 } 88 EnhancedCustomShapeEngine::~EnhancedCustomShapeEngine() 89 { 90 } 91 92 // XInterface ----------------------------------------------------------------- 93 94 void SAL_CALL EnhancedCustomShapeEngine::acquire() throw() 95 { 96 OWeakObject::acquire(); 97 } 98 void SAL_CALL EnhancedCustomShapeEngine::release() throw() 99 { 100 OWeakObject::release(); 101 } 102 103 // XInitialization ------------------------------------------------------------ 104 105 void SAL_CALL EnhancedCustomShapeEngine::initialize( const SEQ( NMSP_UNO::Any )& aArguments ) 106 throw ( NMSP_UNO::Exception, NMSP_UNO::RuntimeException ) 107 { 108 sal_Int32 i; 109 SEQ( NMSP_BEANS::PropertyValue ) aParameter; 110 for ( i = 0; i < aArguments.getLength(); i++ ) 111 { 112 if ( aArguments[ i ] >>= aParameter ) 113 break; 114 } 115 for ( i = 0; i < aParameter.getLength(); i++ ) 116 { 117 const NMSP_BEANS::PropertyValue& rProp = aParameter[ i ]; 118 if ( rProp.Name.equalsAscii( "CustomShape" ) ) 119 rProp.Value >>= mxShape; 120 else if ( rProp.Name.equalsAscii( "ForceGroupWithText" ) ) 121 rProp.Value >>= mbForceGroupWithText; 122 } 123 } 124 125 // XServiceInfo --------------------------------------------------------------- 126 127 rtl::OUString SAL_CALL EnhancedCustomShapeEngine::getImplementationName() 128 throw( NMSP_UNO::RuntimeException ) 129 { 130 return EnhancedCustomShapeEngine_getImplementationName(); 131 } 132 sal_Bool SAL_CALL EnhancedCustomShapeEngine::supportsService( const rtl::OUString& rServiceName ) 133 throw( NMSP_UNO::RuntimeException ) 134 { 135 return EnhancedCustomShapeEngine_supportsService( rServiceName ); 136 } 137 SEQ( rtl::OUString ) SAL_CALL EnhancedCustomShapeEngine::getSupportedServiceNames() 138 throw ( NMSP_UNO::RuntimeException ) 139 { 140 return EnhancedCustomShapeEngine_getSupportedServiceNames(); 141 } 142 143 // XCustomShapeEngine ----------------------------------------------------------- 144 145 SdrObject* EnhancedCustomShapeEngine::ImplForceGroupWithText( const SdrObjCustomShape* pCustoObj, SdrObject* pRenderedShape ) 146 { 147 bool bHasText = pCustoObj->HasText(); 148 if ( pRenderedShape || bHasText ) 149 { 150 // applying shadow 151 const SdrObject* pShadowGeometry = pCustoObj->GetSdrObjectShadowFromCustomShape(); 152 if ( pShadowGeometry ) 153 { 154 if ( pRenderedShape ) 155 { 156 if ( !pRenderedShape->ISA( SdrObjGroup ) ) 157 { 158 SdrObject* pTmp = pRenderedShape; 159 pRenderedShape = new SdrObjGroup(); 160 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp ); 161 } 162 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pShadowGeometry->Clone(), 0 ); 163 } 164 else 165 pRenderedShape = pShadowGeometry->Clone(); 166 } 167 168 // apply text 169 if ( bHasText ) 170 { 171 // #i37011# also create a text object and add at rPos + 1 172 SdrTextObj* pTextObj = (SdrTextObj*)SdrObjFactory::MakeNewObject( 173 pCustoObj->GetObjInventor(), OBJ_TEXT, 0L, pCustoObj->GetModel()); 174 175 // Copy text content 176 OutlinerParaObject* pParaObj = pCustoObj->GetOutlinerParaObject(); 177 if( pParaObj ) 178 pTextObj->NbcSetOutlinerParaObject( new OutlinerParaObject(*pParaObj) ); 179 180 // copy all attributes 181 SfxItemSet aTargetItemSet( pCustoObj->GetMergedItemSet() ); 182 183 // clear fill and line style 184 aTargetItemSet.Put(XLineStyleItem(XLINE_NONE)); 185 aTargetItemSet.Put(XFillStyleItem(XFILL_NONE)); 186 187 // get the text bounds and set at text object 188 Rectangle aTextBounds = pCustoObj->GetSnapRect(); 189 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) ); 190 if ( pSdrObjCustomShape ) 191 { 192 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape ); 193 aTextBounds = aCustomShape2d.GetTextRect(); 194 } 195 pTextObj->SetSnapRect( aTextBounds ); 196 197 // if rotated, copy GeoStat, too. 198 const GeoStat& rSourceGeo = pCustoObj->GetGeoStat(); 199 if ( rSourceGeo.nDrehWink ) 200 { 201 pTextObj->NbcRotate( 202 pCustoObj->GetSnapRect().Center(), rSourceGeo.nDrehWink, 203 rSourceGeo.nSin, rSourceGeo.nCos); 204 } 205 206 // set modified ItemSet at text object 207 pTextObj->SetMergedItemSet(aTargetItemSet); 208 209 if ( pRenderedShape ) 210 { 211 if ( !pRenderedShape->ISA( SdrObjGroup ) ) 212 { 213 SdrObject* pTmp = pRenderedShape; 214 pRenderedShape = new SdrObjGroup(); 215 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp ); 216 } 217 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTextObj, LIST_APPEND ); 218 } 219 else 220 pRenderedShape = pTextObj; 221 } 222 223 // force group 224 if ( pRenderedShape ) 225 { 226 if ( !pRenderedShape->ISA( SdrObjGroup ) ) 227 { 228 SdrObject* pTmp = pRenderedShape; 229 pRenderedShape = new SdrObjGroup(); 230 ((SdrObjGroup*)pRenderedShape)->GetSubList()->NbcInsertObject( pTmp ); 231 } 232 pRenderedShape->SetPage( pCustoObj->GetPage() ); 233 pRenderedShape->SetModel( pCustoObj->GetModel() ); 234 } 235 } 236 return pRenderedShape; 237 } 238 239 void SetTemporary( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape ) 240 { 241 if ( xShape.is() ) 242 { 243 SvxShape* pShape = SvxShape::getImplementation( xShape ); 244 if ( pShape ) 245 pShape->TakeSdrObjectOwnership(); 246 /* 247 ::com::sun::star::uno::Reference< 248 ::com::sun::star::drawing::XShapes > xShapes( xShape, ::com::sun::star::uno::UNO_QUERY ); 249 if ( xShapes.is() ) 250 { 251 sal_Int32 i; 252 for ( i = 0; i < xShapes->getCount(); i++ ) 253 { 254 ::com::sun::star::uno::Any aAny( xShapes->getByIndex( i ) ); 255 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape; 256 if ( aAny >>= xShape ) 257 SetTemporary( xShape ); 258 } 259 } 260 */ 261 } 262 } 263 264 REF( com::sun::star::drawing::XShape ) SAL_CALL EnhancedCustomShapeEngine::render() 265 throw ( NMSP_UNO::RuntimeException ) 266 { 267 REF( com::sun::star::drawing::XShape ) xShape; 268 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) ); 269 if ( pSdrObjCustomShape ) 270 { 271 // retrieving the TextPath property to check if feature is enabled 272 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&) 273 pSdrObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); 274 sal_Bool bTextPathOn = sal_False; 275 const rtl::OUString sTextPath( RTL_CONSTASCII_USTRINGPARAM ( "TextPath" ) ); 276 com::sun::star::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath ); 277 if ( pAny ) 278 *pAny >>= bTextPathOn; 279 280 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape ); 281 sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle(); 282 283 sal_Bool bFlipV = aCustomShape2d.IsFlipVert(); 284 sal_Bool bFlipH = aCustomShape2d.IsFlipHorz(); 285 sal_Bool bLineGeometryNeededOnly = bTextPathOn; 286 287 SdrObject* pRenderedShape = aCustomShape2d.CreateObject( bLineGeometryNeededOnly ); 288 if ( pRenderedShape ) 289 { 290 if ( bTextPathOn ) 291 { 292 SdrObject* pRenderedFontWork = EnhancedCustomShapeFontWork::CreateFontWork( pRenderedShape, pSdrObjCustomShape ); 293 if ( pRenderedFontWork ) 294 { 295 SdrObject::Free( pRenderedShape ); 296 pRenderedShape = pRenderedFontWork; 297 } 298 } 299 SdrObject* pRenderedShape3d = EnhancedCustomShape3d::Create3DObject( pRenderedShape, pSdrObjCustomShape ); 300 if ( pRenderedShape3d ) 301 { 302 bFlipV = bFlipH = sal_False; 303 nRotateAngle = 0; 304 SdrObject::Free( pRenderedShape ); 305 pRenderedShape = pRenderedShape3d; 306 } 307 Rectangle aRect( pSdrObjCustomShape->GetSnapRect() ); 308 309 const GeoStat& rGeoStat = ((SdrObjCustomShape*)pSdrObjCustomShape)->GetGeoStat(); 310 if ( rGeoStat.nShearWink ) 311 { 312 long nShearWink = rGeoStat.nShearWink; 313 double nTan = rGeoStat.nTan; 314 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV)) 315 { 316 nShearWink = -nShearWink; 317 nTan = -nTan; 318 } 319 pRenderedShape->Shear( pSdrObjCustomShape->GetSnapRect().Center(), nShearWink, nTan, sal_False); 320 } 321 if( nRotateAngle ) 322 { 323 double a = nRotateAngle * F_PI18000; 324 pRenderedShape->NbcRotate( pSdrObjCustomShape->GetSnapRect().Center(), nRotateAngle, sin( a ), cos( a ) ); 325 } 326 if ( bFlipV ) 327 { 328 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 ); 329 Point aRight( aLeft.X() + 1000, aLeft.Y() ); 330 pRenderedShape->NbcMirror( aLeft, aRight ); 331 } 332 if ( bFlipH ) 333 { 334 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() ); 335 Point aBottom( aTop.X(), aTop.Y() + 1000 ); 336 pRenderedShape->NbcMirror( aTop, aBottom ); 337 } 338 pRenderedShape->NbcSetStyleSheet( pSdrObjCustomShape->GetStyleSheet(), sal_True ); 339 pRenderedShape->RecalcSnapRect(); 340 } 341 342 if ( mbForceGroupWithText ) 343 pRenderedShape = ImplForceGroupWithText( (SdrObjCustomShape*)pSdrObjCustomShape, pRenderedShape ); 344 345 if ( pRenderedShape ) 346 { 347 aCustomShape2d.ApplyGluePoints( pRenderedShape ); 348 xShape = SvxDrawPage::CreateShapeByTypeAndInventor( pRenderedShape->GetObjIdentifier(), 349 pRenderedShape->GetObjInventor(), pRenderedShape, NULL ); 350 } 351 SetTemporary( xShape ); 352 } 353 return xShape; 354 } 355 356 com::sun::star::awt::Rectangle SAL_CALL EnhancedCustomShapeEngine::getTextBounds() 357 throw ( NMSP_UNO::RuntimeException ) 358 { 359 com::sun::star::awt::Rectangle aTextRect; 360 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) ); 361 ::com::sun::star::uno::Reference< ::com::sun::star::document::XActionLockable > xLockable( mxShape, ::com::sun::star::uno::UNO_QUERY ); 362 if ( pSdrObjCustomShape && pSdrObjCustomShape->GetModel() && xLockable.is() && !xLockable->isActionLocked() ) 363 { 364 if ( pSdrObjCustomShape ) 365 { 366 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape ); 367 Rectangle aRect( aCustomShape2d.GetTextRect() ); 368 aTextRect.X = aRect.Left(); 369 aTextRect.Y = aRect.Top(); 370 aTextRect.Width = aRect.GetWidth(); 371 aTextRect.Height = aRect.GetHeight(); 372 } 373 } 374 return aTextRect; 375 } 376 377 com::sun::star::drawing::PolyPolygonBezierCoords SAL_CALL EnhancedCustomShapeEngine::getLineGeometry() 378 throw ( NMSP_UNO::RuntimeException ) 379 { 380 com::sun::star::drawing::PolyPolygonBezierCoords aPolyPolygonBezierCoords; 381 SdrObject* pSdrObjCustomShape( GetSdrObjectFromXShape( mxShape ) ); 382 if ( pSdrObjCustomShape ) 383 { 384 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape ); 385 SdrObject* pObj = aCustomShape2d.CreateLineGeometry(); 386 if ( pObj ) 387 { 388 Rectangle aRect( pSdrObjCustomShape->GetSnapRect() ); 389 sal_Bool bFlipV = aCustomShape2d.IsFlipVert(); 390 sal_Bool bFlipH = aCustomShape2d.IsFlipHorz(); 391 392 const GeoStat& rGeoStat = ((SdrObjCustomShape*)pSdrObjCustomShape)->GetGeoStat(); 393 if ( rGeoStat.nShearWink ) 394 { 395 long nShearWink = rGeoStat.nShearWink; 396 double nTan = rGeoStat.nTan; 397 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV)) 398 { 399 nShearWink = -nShearWink; 400 nTan = -nTan; 401 } 402 pObj->Shear( aRect.Center(), nShearWink, nTan, sal_False); 403 } 404 sal_Int32 nRotateAngle = aCustomShape2d.GetRotateAngle(); 405 if( nRotateAngle ) 406 { 407 double a = nRotateAngle * F_PI18000; 408 pObj->NbcRotate( aRect.Center(), nRotateAngle, sin( a ), cos( a ) ); 409 } 410 if ( bFlipH ) 411 { 412 Point aTop( ( aRect.Left() + aRect.Right() ) >> 1, aRect.Top() ); 413 Point aBottom( aTop.X(), aTop.Y() + 1000 ); 414 pObj->NbcMirror( aTop, aBottom ); 415 } 416 if ( bFlipV ) 417 { 418 Point aLeft( aRect.Left(), ( aRect.Top() + aRect.Bottom() ) >> 1 ); 419 Point aRight( aLeft.X() + 1000, aLeft.Y() ); 420 pObj->NbcMirror( aLeft, aRight ); 421 } 422 423 basegfx::B2DPolyPolygon aPolyPolygon; 424 SdrObjListIter aIter( *pObj, IM_DEEPWITHGROUPS ); 425 426 while ( aIter.IsMore() ) 427 { 428 SdrObject* pNewObj = NULL; 429 basegfx::B2DPolyPolygon aPP; 430 const SdrObject* pNext = aIter.Next(); 431 432 if ( pNext->ISA( SdrPathObj ) ) 433 { 434 aPP = ((SdrPathObj*)pNext)->GetPathPoly(); 435 } 436 else 437 { 438 pNewObj = pNext->ConvertToPolyObj( sal_False, sal_False ); 439 SdrPathObj* pPath = PTR_CAST( SdrPathObj, pNewObj ); 440 if ( pPath ) 441 aPP = pPath->GetPathPoly(); 442 } 443 444 if ( aPP.count() ) 445 aPolyPolygon.append(aPP); 446 447 SdrObject::Free( pNewObj ); 448 } 449 SdrObject::Free( pObj ); 450 SvxConvertB2DPolyPolygonToPolyPolygonBezier( aPolyPolygon, aPolyPolygonBezierCoords ); 451 } 452 } 453 454 return aPolyPolygonBezierCoords; 455 } 456 457 SEQ( REF( com::sun::star::drawing::XCustomShapeHandle ) ) SAL_CALL EnhancedCustomShapeEngine::getInteraction() 458 throw ( NMSP_UNO::RuntimeException ) 459 { 460 sal_uInt32 i, nHdlCount = 0; 461 SdrObject* pSdrObjCustomShape = GetSdrObjectFromXShape( mxShape ); 462 if ( pSdrObjCustomShape ) 463 { 464 EnhancedCustomShape2d aCustomShape2d( pSdrObjCustomShape ); 465 nHdlCount = aCustomShape2d.GetHdlCount(); 466 } 467 SEQ( REF( com::sun::star::drawing::XCustomShapeHandle ) ) aSeq( nHdlCount ); 468 for ( i = 0; i < nHdlCount; i++ ) 469 aSeq[ i ] = new EnhancedCustomShapeHandle( mxShape, i ); 470 return aSeq; 471 } 472