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_svtools.hxx" 26 27 #define ENABLE_BYTESTRING_STREAM_OPERATORS 28 29 #include <algorithm> 30 31 #include <com/sun/star/uno/Reference.hxx> 32 #include <com/sun/star/document/XLinkAuthorizer.hpp> 33 #include <com/sun/star/frame/XDesktop.hpp> 34 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 35 #include <tools/vcompat.hxx> 36 #include <ucbhelper/contentbroker.hxx> 37 #include <unotools/ucbstreamhelper.hxx> 38 #include <unotools/localfilehelper.hxx> 39 #include <unotools/tempfile.hxx> 40 #include <vcl/svapp.hxx> 41 #include <vcl/cvtgrf.hxx> 42 #include <vcl/metaact.hxx> 43 #include <vcl/virdev.hxx> 44 #include <vcl/salbtype.hxx> 45 #include <unotools/cacheoptions.hxx> 46 #include <svtools/grfmgr.hxx> 47 #include <svtools/linkpolicy.hxx> 48 49 // --> OD 2010-01-04 #i105243# 50 #include <vcl/pdfextoutdevdata.hxx> 51 // <-- 52 53 using namespace ::com::sun::star; 54 55 // ----------- 56 // - Defines - 57 // ----------- 58 59 #define WATERMARK_LUM_OFFSET 50 60 #define WATERMARK_CON_OFFSET -70 61 62 // ----------- 63 // - statics - 64 // ----------- 65 66 GraphicManager* GraphicObject::mpGlobalMgr = NULL; 67 68 // --------------------- 69 // - GrfDirectCacheObj - 70 // --------------------- 71 72 struct GrfSimpleCacheObj 73 { 74 Graphic maGraphic; 75 GraphicAttr maAttr; 76 77 GrfSimpleCacheObj( const Graphic& rGraphic, const GraphicAttr& rAttr ) : 78 maGraphic( rGraphic ), maAttr( rAttr ) {} 79 }; 80 81 // ----------------- 82 // - GraphicObject - 83 // ----------------- 84 85 TYPEINIT1_AUTOFACTORY( GraphicObject, SvDataCopyStream ); 86 87 // unique increasing ID for being able to detect the GraphicObject with the 88 // oldest last data changes 89 static sal_uLong aIncrementingTimeOfLastDataChange = 1; 90 91 void GraphicObject::ImplAfterDataChange() 92 { 93 // set unique timestamp ID of last data change 94 mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++; 95 96 // check memory footprint of all GraphicObjects managed and evtl. take action 97 GetGraphicManager().ImplCheckSizeOfSwappedInGraphics(); 98 } 99 100 // ----------------------------------------------------------------------------- 101 102 GraphicObject::GraphicObject( const GraphicManager* pMgr ) : 103 mpLink ( NULL ), 104 mpUserData ( NULL ) 105 { 106 ImplConstruct(); 107 ImplAssignGraphicData(); 108 ImplSetGraphicManager( pMgr ); 109 } 110 111 // ----------------------------------------------------------------------------- 112 113 GraphicObject::GraphicObject( const Graphic& rGraphic, const GraphicManager* pMgr ) : 114 maGraphic ( rGraphic ), 115 mpLink ( NULL ), 116 mpUserData ( NULL ) 117 { 118 ImplConstruct(); 119 ImplAssignGraphicData(); 120 ImplSetGraphicManager( pMgr ); 121 } 122 123 // ----------------------------------------------------------------------------- 124 125 GraphicObject::GraphicObject( const Graphic& rGraphic, const String& rLink, const GraphicManager* pMgr ) : 126 maGraphic ( rGraphic ), 127 mpLink ( rLink.Len() ? ( new String( rLink ) ) : NULL ), 128 mpUserData ( NULL ) 129 { 130 ImplConstruct(); 131 ImplAssignGraphicData(); 132 ImplSetGraphicManager( pMgr ); 133 } 134 135 // ----------------------------------------------------------------------------- 136 137 GraphicObject::GraphicObject( const GraphicObject& rGraphicObj, const GraphicManager* pMgr ) : 138 SvDataCopyStream(), 139 maGraphic ( rGraphicObj.GetGraphic() ), 140 maAttr ( rGraphicObj.maAttr ), 141 mpLink ( rGraphicObj.mpLink ? ( new String( *rGraphicObj.mpLink ) ) : NULL ), 142 mpUserData ( rGraphicObj.mpUserData ? ( new String( *rGraphicObj.mpUserData ) ) : NULL ) 143 { 144 ImplConstruct(); 145 ImplAssignGraphicData(); 146 ImplSetGraphicManager( pMgr, NULL, &rGraphicObj ); 147 } 148 149 // ----------------------------------------------------------------------------- 150 151 GraphicObject::GraphicObject( const ByteString& rUniqueID, const GraphicManager* pMgr ) : 152 mpLink ( NULL ), 153 mpUserData ( NULL ) 154 { 155 ImplConstruct(); 156 157 // assign default properties 158 ImplAssignGraphicData(); 159 160 ImplSetGraphicManager( pMgr, &rUniqueID ); 161 162 // update properties 163 ImplAssignGraphicData(); 164 } 165 166 // ----------------------------------------------------------------------------- 167 168 GraphicObject::~GraphicObject() 169 { 170 if( mpMgr ) 171 { 172 mpMgr->ImplUnregisterObj( *this ); 173 174 if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() ) 175 delete mpGlobalMgr, mpGlobalMgr = NULL; 176 } 177 178 delete mpSwapOutTimer; 179 delete mpSwapStreamHdl; 180 delete mpLink; 181 delete mpUserData; 182 delete mpSimpleCache; 183 } 184 185 // ----------------------------------------------------------------------------- 186 187 void GraphicObject::ImplConstruct() 188 { 189 mpMgr = NULL; 190 mpSwapStreamHdl = NULL; 191 mpSwapOutTimer = NULL; 192 mpSimpleCache = NULL; 193 mnAnimationLoopCount = 0; 194 mbAutoSwapped = sal_False; 195 mbIsInSwapIn = sal_False; 196 mbIsInSwapOut = sal_False; 197 198 // Init with a unique, increasing ID 199 mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++; 200 } 201 202 // ----------------------------------------------------------------------------- 203 204 void GraphicObject::ImplAssignGraphicData() 205 { 206 maPrefSize = maGraphic.GetPrefSize(); 207 maPrefMapMode = maGraphic.GetPrefMapMode(); 208 mnSizeBytes = maGraphic.GetSizeBytes(); 209 meType = maGraphic.GetType(); 210 mbTransparent = maGraphic.IsTransparent(); 211 mbAlpha = maGraphic.IsAlpha(); 212 mbAnimated = maGraphic.IsAnimated(); 213 mbEPS = maGraphic.IsEPS(); 214 mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 ); 215 } 216 217 // ----------------------------------------------------------------------------- 218 219 void GraphicObject::ImplSetGraphicManager( const GraphicManager* pMgr, const ByteString* pID, const GraphicObject* pCopyObj ) 220 { 221 if( !mpMgr || ( pMgr != mpMgr ) ) 222 { 223 if( !pMgr && mpMgr && ( mpMgr == mpGlobalMgr ) ) 224 return; 225 else 226 { 227 if( mpMgr ) 228 { 229 mpMgr->ImplUnregisterObj( *this ); 230 231 if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() ) 232 delete mpGlobalMgr, mpGlobalMgr = NULL; 233 } 234 235 if( !pMgr ) 236 { 237 if( !mpGlobalMgr ) 238 { 239 SvtCacheOptions aCacheOptions; 240 241 mpGlobalMgr = new GraphicManager( aCacheOptions.GetGraphicManagerTotalCacheSize(), 242 aCacheOptions.GetGraphicManagerObjectCacheSize() ); 243 mpGlobalMgr->SetCacheTimeout( aCacheOptions.GetGraphicManagerObjectReleaseTime() ); 244 } 245 246 mpMgr = mpGlobalMgr; 247 } 248 else 249 mpMgr = (GraphicManager*) pMgr; 250 251 mpMgr->ImplRegisterObj( *this, maGraphic, pID, pCopyObj ); 252 } 253 } 254 } 255 256 // ----------------------------------------------------------------------------- 257 258 void GraphicObject::ImplAutoSwapIn() 259 { 260 if( IsSwappedOut() ) 261 { 262 if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) ) 263 mbAutoSwapped = sal_False; 264 else 265 { 266 mbIsInSwapIn = sal_True; 267 268 if( maGraphic.SwapIn() ) 269 mbAutoSwapped = sal_False; 270 else 271 { 272 SvStream* pStream = GetSwapStream(); 273 274 if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream ) 275 { 276 if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream ) 277 { 278 if( HasLink() ) 279 { 280 String aURLStr; 281 282 if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( GetLink(), aURLStr ) ) 283 { 284 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aURLStr, STREAM_READ ); 285 286 if( pIStm ) 287 { 288 (*pIStm) >> maGraphic; 289 mbAutoSwapped = ( maGraphic.GetType() != GRAPHIC_NONE ); 290 delete pIStm; 291 } 292 } 293 } 294 } 295 else if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream ) 296 mbAutoSwapped = !maGraphic.SwapIn(); 297 else if( GRFMGR_AUTOSWAPSTREAM_LOADED == pStream ) 298 mbAutoSwapped = maGraphic.IsSwapOut(); 299 else 300 { 301 mbAutoSwapped = !maGraphic.SwapIn( pStream ); 302 delete pStream; 303 } 304 } 305 else 306 { 307 DBG_ASSERT( ( GRAPHIC_NONE == meType ) || ( GRAPHIC_DEFAULT == meType ), 308 "GraphicObject::ImplAutoSwapIn: could not get stream to swap in graphic! (=>KA)" ); 309 } 310 } 311 312 mbIsInSwapIn = sal_False; 313 314 if( !mbAutoSwapped && mpMgr ) 315 mpMgr->ImplGraphicObjectWasSwappedIn( *this ); 316 } 317 318 // Handle evtl. needed AfterDataChanges 319 ImplAfterDataChange(); 320 } 321 } 322 323 // ----------------------------------------------------------------------------- 324 sal_Bool GraphicObject::ImplGetCropParams( OutputDevice* pOut, Point& rPt, Size& rSz, const GraphicAttr* pAttr, 325 PolyPolygon& rClipPolyPoly, sal_Bool& bRectClipRegion ) const 326 { 327 sal_Bool bRet = sal_False; 328 329 if( GetType() != GRAPHIC_NONE ) 330 { 331 Polygon aClipPoly( Rectangle( rPt, rSz ) ); 332 const sal_uInt16 nRot10 = pAttr->GetRotation() % 3600; 333 const Point aOldOrigin( rPt ); 334 // --> OD 2005-09-30 #i54875# - It's not needed to get the graphic again. 335 // const Graphic& rGraphic = GetGraphic(); 336 // <-- 337 const MapMode aMap100( MAP_100TH_MM ); 338 Size aSize100; 339 long nTotalWidth, nTotalHeight; 340 long nNewLeft, nNewTop, nNewRight, nNewBottom; 341 double fScale; 342 343 if( nRot10 ) 344 { 345 aClipPoly.Rotate( rPt, nRot10 ); 346 bRectClipRegion = sal_False; 347 } 348 else 349 bRectClipRegion = sal_True; 350 351 rClipPolyPoly = aClipPoly; 352 353 // --> OD 2005-09-30 #i54875# - directly access member <maGraphic> to 354 // get <PrefSize> and <PrefMapMode>. 355 // if( rGraphic.GetPrefMapMode() == MAP_PIXEL ) 356 // aSize100 = Application::GetDefaultDevice()->PixelToLogic( rGraphic.GetPrefSize(), aMap100 ); 357 // else 358 // aSize100 = pOut->LogicToLogic( rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), aMap100 ); 359 if( maGraphic.GetPrefMapMode() == MAP_PIXEL ) 360 aSize100 = Application::GetDefaultDevice()->PixelToLogic( maGraphic.GetPrefSize(), aMap100 ); 361 else 362 { 363 MapMode m(maGraphic.GetPrefMapMode()); 364 aSize100 = pOut->LogicToLogic( maGraphic.GetPrefSize(), &m, &aMap100 ); 365 } 366 // <-- 367 368 nTotalWidth = aSize100.Width() - pAttr->GetLeftCrop() - pAttr->GetRightCrop(); 369 nTotalHeight = aSize100.Height() - pAttr->GetTopCrop() - pAttr->GetBottomCrop(); 370 371 if( aSize100.Width() > 0 && aSize100.Height() > 0 && nTotalWidth > 0 && nTotalHeight > 0 ) 372 { 373 fScale = (double) aSize100.Width() / nTotalWidth; 374 nNewLeft = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_HORZ ) ? pAttr->GetRightCrop() : pAttr->GetLeftCrop() ) * fScale ); 375 nNewRight = nNewLeft + FRound( aSize100.Width() * fScale ) - 1; 376 377 fScale = (double) rSz.Width() / aSize100.Width(); 378 rPt.X() += FRound( nNewLeft * fScale ); 379 rSz.Width() = FRound( ( nNewRight - nNewLeft + 1 ) * fScale ); 380 381 fScale = (double) aSize100.Height() / nTotalHeight; 382 nNewTop = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_VERT ) ? pAttr->GetBottomCrop() : pAttr->GetTopCrop() ) * fScale ); 383 nNewBottom = nNewTop + FRound( aSize100.Height() * fScale ) - 1; 384 385 fScale = (double) rSz.Height() / aSize100.Height(); 386 rPt.Y() += FRound( nNewTop * fScale ); 387 rSz.Height() = FRound( ( nNewBottom - nNewTop + 1 ) * fScale ); 388 389 if( nRot10 ) 390 { 391 Polygon aOriginPoly( 1 ); 392 393 aOriginPoly[ 0 ] = rPt; 394 aOriginPoly.Rotate( aOldOrigin, nRot10 ); 395 rPt = aOriginPoly[ 0 ]; 396 } 397 398 bRet = sal_True; 399 } 400 } 401 402 return bRet; 403 } 404 405 // ----------------------------------------------------------------------------- 406 407 GraphicObject& GraphicObject::operator=( const GraphicObject& rGraphicObj ) 408 { 409 if( &rGraphicObj != this ) 410 { 411 mpMgr->ImplUnregisterObj( *this ); 412 413 delete mpSwapStreamHdl, mpSwapStreamHdl = NULL; 414 delete mpSimpleCache, mpSimpleCache = NULL; 415 delete mpLink; 416 delete mpUserData; 417 418 maGraphic = rGraphicObj.GetGraphic(); 419 maAttr = rGraphicObj.maAttr; 420 mpLink = rGraphicObj.mpLink ? new String( *rGraphicObj.mpLink ) : NULL; 421 mpUserData = rGraphicObj.mpUserData ? new String( *rGraphicObj.mpUserData ) : NULL; 422 ImplAssignGraphicData(); 423 mbAutoSwapped = sal_False; 424 mpMgr = rGraphicObj.mpMgr; 425 426 mpMgr->ImplRegisterObj( *this, maGraphic, NULL, &rGraphicObj ); 427 } 428 429 return *this; 430 } 431 432 // ----------------------------------------------------------------------------- 433 434 sal_Bool GraphicObject::operator==( const GraphicObject& rGraphicObj ) const 435 { 436 return( ( rGraphicObj.maGraphic == maGraphic ) && 437 ( rGraphicObj.maAttr == maAttr ) && 438 ( rGraphicObj.GetLink() == GetLink() ) ); 439 } 440 441 // ------------------------------------------------------------------------ 442 443 void GraphicObject::Load( SvStream& rIStm ) 444 { 445 rIStm >> *this; 446 } 447 448 // ------------------------------------------------------------------------ 449 450 void GraphicObject::Save( SvStream& rOStm ) 451 { 452 rOStm << *this; 453 } 454 455 // ------------------------------------------------------------------------ 456 457 void GraphicObject::Assign( const SvDataCopyStream& rCopyStream ) 458 { 459 *this = (const GraphicObject& ) rCopyStream; 460 } 461 462 // ----------------------------------------------------------------------------- 463 464 ByteString GraphicObject::GetUniqueID() const 465 { 466 if ( !IsInSwapIn() && IsEPS() ) 467 const_cast<GraphicObject*>(this)->FireSwapInRequest(); 468 469 ByteString aRet; 470 471 if( mpMgr ) 472 aRet = mpMgr->ImplGetUniqueID( *this ); 473 474 return aRet; 475 } 476 477 // ----------------------------------------------------------------------------- 478 479 sal_uLong GraphicObject::GetChecksum() const 480 { 481 return( ( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() ) ? maGraphic.GetChecksum() : 0 ); 482 } 483 484 // ----------------------------------------------------------------------------- 485 486 SvStream* GraphicObject::GetSwapStream() const 487 { 488 return( HasSwapStreamHdl() ? (SvStream*) mpSwapStreamHdl->Call( (void*) this ) : GRFMGR_AUTOSWAPSTREAM_NONE ); 489 } 490 491 // ----------------------------------------------------------------------------- 492 493 // !!! to be removed 494 sal_uLong GraphicObject::GetReleaseFromCache() const 495 { 496 return 0; 497 } 498 499 // ----------------------------------------------------------------------------- 500 501 void GraphicObject::SetAttr( const GraphicAttr& rAttr ) 502 { 503 maAttr = rAttr; 504 505 if( mpSimpleCache && ( mpSimpleCache->maAttr != rAttr ) ) 506 delete mpSimpleCache, mpSimpleCache = NULL; 507 } 508 509 // ----------------------------------------------------------------------------- 510 511 void GraphicObject::SetLink() 512 { 513 if( mpLink ) 514 delete mpLink, mpLink = NULL; 515 } 516 517 // ----------------------------------------------------------------------------- 518 519 void GraphicObject::SetLink( const String& rLink ) 520 { 521 delete mpLink, mpLink = new String( rLink ); 522 } 523 524 // ----------------------------------------------------------------------------- 525 526 String GraphicObject::GetLink() const 527 { 528 if( mpLink ) 529 return *mpLink; 530 else 531 return String(); 532 } 533 534 // ----------------------------------------------------------------------------- 535 536 void GraphicObject::SetUserData() 537 { 538 if( mpUserData ) 539 delete mpUserData, mpUserData = NULL; 540 } 541 542 // ----------------------------------------------------------------------------- 543 544 void GraphicObject::SetUserData( const String& rUserData ) 545 { 546 delete mpUserData, mpUserData = new String( rUserData ); 547 } 548 549 // ----------------------------------------------------------------------------- 550 551 String GraphicObject::GetUserData() const 552 { 553 if( mpUserData ) 554 return *mpUserData; 555 else 556 return String(); 557 } 558 559 // ----------------------------------------------------------------------------- 560 561 void GraphicObject::SetSwapStreamHdl() 562 { 563 if( mpSwapStreamHdl ) 564 { 565 delete mpSwapOutTimer, mpSwapOutTimer = NULL; 566 delete mpSwapStreamHdl, mpSwapStreamHdl = NULL; 567 } 568 } 569 570 // ----------------------------------------------------------------------------- 571 572 void GraphicObject::SetSwapStreamHdl( const Link& rHdl, const sal_uLong nSwapOutTimeout ) 573 { 574 delete mpSwapStreamHdl, mpSwapStreamHdl = new Link( rHdl ); 575 576 if( nSwapOutTimeout ) 577 { 578 if( !mpSwapOutTimer ) 579 { 580 mpSwapOutTimer = new Timer; 581 mpSwapOutTimer->SetTimeoutHdl( LINK( this, GraphicObject, ImplAutoSwapOutHdl ) ); 582 } 583 584 mpSwapOutTimer->SetTimeout( nSwapOutTimeout ); 585 mpSwapOutTimer->Start(); 586 } 587 else 588 delete mpSwapOutTimer, mpSwapOutTimer = NULL; 589 } 590 591 // ----------------------------------------------------------------------------- 592 593 Link GraphicObject::GetSwapStreamHdl() const 594 { 595 if( mpSwapStreamHdl ) 596 return *mpSwapStreamHdl; 597 else 598 return Link(); 599 } 600 601 // ----------------------------------------------------------------------------- 602 603 void GraphicObject::FireSwapInRequest() 604 { 605 ImplAutoSwapIn(); 606 } 607 608 // ----------------------------------------------------------------------------- 609 610 void GraphicObject::FireSwapOutRequest() 611 { 612 ImplAutoSwapOutHdl( NULL ); 613 } 614 615 // ----------------------------------------------------------------------------- 616 617 void GraphicObject::GraphicManagerDestroyed() 618 { 619 // we're alive, but our manager doesn't live anymore ==> connect to default manager 620 mpMgr = NULL; 621 ImplSetGraphicManager( NULL ); 622 } 623 624 // ----------------------------------------------------------------------------- 625 626 void GraphicObject::SetGraphicManager( const GraphicManager& rMgr ) 627 { 628 ImplSetGraphicManager( &rMgr ); 629 } 630 631 // ----------------------------------------------------------------------------- 632 633 sal_Bool GraphicObject::IsCached( OutputDevice* pOut, const Point& rPt, const Size& rSz, 634 const GraphicAttr* pAttr, sal_uLong nFlags ) const 635 { 636 sal_Bool bRet; 637 638 if( nFlags & GRFMGR_DRAW_CACHED ) 639 { 640 // --> OD 2005-10-11 #i54875# - Consider cropped graphics. 641 // Note: The graphic manager caches a cropped graphic with its 642 // uncropped position and size. 643 // bRet = mpMgr->IsInCache( pOut, rPt, rSz, *this, ( pAttr ? *pAttr : GetAttr() ) ); 644 Point aPt( rPt ); 645 Size aSz( rSz ); 646 if ( pAttr->IsCropped() ) 647 { 648 PolyPolygon aClipPolyPoly; 649 sal_Bool bRectClip; 650 ImplGetCropParams( pOut, aPt, aSz, pAttr, aClipPolyPoly, bRectClip ); 651 } 652 bRet = mpMgr->IsInCache( pOut, aPt, aSz, *this, ( pAttr ? *pAttr : GetAttr() ) ); 653 } 654 else 655 bRet = sal_False; 656 657 return bRet; 658 } 659 660 // ----------------------------------------------------------------------------- 661 662 void GraphicObject::ReleaseFromCache() 663 { 664 665 mpMgr->ReleaseFromCache( *this ); 666 } 667 668 // ----------------------------------------------------------------------------- 669 670 void GraphicObject::SetAnimationNotifyHdl( const Link& rLink ) 671 { 672 maGraphic.SetAnimationNotifyHdl( rLink ); 673 } 674 675 // ----------------------------------------------------------------------------- 676 677 List* GraphicObject::GetAnimationInfoList() const 678 { 679 return maGraphic.GetAnimationInfoList(); 680 } 681 682 // ----------------------------------------------------------------------------- 683 684 sal_Bool GraphicObject::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz, 685 const GraphicAttr* pAttr, sal_uLong nFlags ) 686 { 687 GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() ); 688 Point aPt( rPt ); 689 Size aSz( rSz ); 690 const sal_uInt32 nOldDrawMode = pOut->GetDrawMode(); 691 sal_Bool bCropped = aAttr.IsCropped(); 692 sal_Bool bCached = sal_False; 693 sal_Bool bRet; 694 695 // #i29534# Provide output rects for PDF writer 696 Rectangle aCropRect; 697 698 if( !( GRFMGR_DRAW_USE_DRAWMODE_SETTINGS & nFlags ) ) 699 pOut->SetDrawMode( nOldDrawMode & ( ~( DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT ) ) ); 700 701 // mirrored horizontically 702 if( aSz.Width() < 0L ) 703 { 704 aPt.X() += aSz.Width() + 1; 705 aSz.Width() = -aSz.Width(); 706 aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_HORZ ); 707 } 708 709 // mirrored vertically 710 if( aSz.Height() < 0L ) 711 { 712 aPt.Y() += aSz.Height() + 1; 713 aSz.Height() = -aSz.Height(); 714 aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_VERT ); 715 } 716 717 if( bCropped ) 718 { 719 PolyPolygon aClipPolyPoly; 720 sal_Bool bRectClip; 721 const sal_Bool bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip ); 722 723 pOut->Push( PUSH_CLIPREGION ); 724 725 if( bCrop ) 726 { 727 if( bRectClip ) 728 { 729 // #i29534# Store crop rect for later forwarding to 730 // PDF writer 731 aCropRect = aClipPolyPoly.GetBoundRect(); 732 pOut->IntersectClipRegion( aCropRect ); 733 } 734 else 735 { 736 pOut->IntersectClipRegion( aClipPolyPoly ); 737 } 738 } 739 } 740 741 bRet = mpMgr->DrawObj( pOut, aPt, aSz, *this, aAttr, nFlags, bCached ); 742 743 if( bCropped ) 744 pOut->Pop(); 745 746 pOut->SetDrawMode( nOldDrawMode ); 747 748 // #i29534# Moved below OutDev restoration, to avoid multiple swap-ins 749 // (code above needs to call GetGraphic twice) 750 if( bCached ) 751 { 752 if( mpSwapOutTimer ) 753 mpSwapOutTimer->Start(); 754 else 755 FireSwapOutRequest(); 756 } 757 758 return bRet; 759 } 760 761 // --> OD 2010-01-04 #i105243# 762 sal_Bool GraphicObject::DrawWithPDFHandling( OutputDevice& rOutDev, 763 const Point& rPt, const Size& rSz, 764 const GraphicAttr* pGrfAttr, 765 const sal_uLong nFlags ) 766 { 767 const GraphicAttr aGrfAttr( pGrfAttr ? *pGrfAttr : GetAttr() ); 768 769 // Notify PDF writer about linked graphic (if any) 770 sal_Bool bWritingPdfLinkedGraphic( sal_False ); 771 Point aPt( rPt ); 772 Size aSz( rSz ); 773 Rectangle aCropRect; 774 vcl::PDFExtOutDevData* pPDFExtOutDevData = 775 dynamic_cast<vcl::PDFExtOutDevData*>(rOutDev.GetExtOutDevData()); 776 if( pPDFExtOutDevData ) 777 { 778 // only delegate image handling to PDF, if no special treatment is necessary 779 if( GetGraphic().IsLink() && 780 rSz.Width() > 0L && 781 rSz.Height() > 0L && 782 !aGrfAttr.IsSpecialDrawMode() && 783 !aGrfAttr.IsMirrored() && 784 !aGrfAttr.IsRotated() && 785 !aGrfAttr.IsAdjusted() ) 786 { 787 bWritingPdfLinkedGraphic = true; 788 789 if( aGrfAttr.IsCropped() ) 790 { 791 PolyPolygon aClipPolyPoly; 792 sal_Bool bRectClip; 793 const sal_Bool bCrop = ImplGetCropParams( &rOutDev, 794 aPt, aSz, 795 &aGrfAttr, 796 aClipPolyPoly, 797 bRectClip ); 798 if ( bCrop && bRectClip ) 799 { 800 aCropRect = aClipPolyPoly.GetBoundRect(); 801 } 802 } 803 804 pPDFExtOutDevData->BeginGroup(); 805 } 806 } 807 808 sal_Bool bRet = Draw( &rOutDev, rPt, rSz, &aGrfAttr, nFlags ); 809 810 // Notify PDF writer about linked graphic (if any) 811 if( bWritingPdfLinkedGraphic ) 812 { 813 pPDFExtOutDevData->EndGroup( const_cast< Graphic& >(GetGraphic()), 814 aGrfAttr.GetTransparency(), 815 Rectangle( aPt, aSz ), 816 aCropRect ); 817 } 818 819 return bRet; 820 } 821 // <-- 822 823 // ----------------------------------------------------------------------------- 824 825 sal_Bool GraphicObject::DrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSize, 826 const Size& rOffset, const GraphicAttr* pAttr, sal_uLong nFlags, int nTileCacheSize1D ) 827 { 828 if( pOut == NULL || rSize.Width() == 0 || rSize.Height() == 0 ) 829 return sal_False; 830 831 const MapMode aOutMapMode( pOut->GetMapMode() ); 832 const MapMode aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() ); 833 // #106258# Clamp size to 1 for zero values. This is okay, since 834 // logical size of zero is handled above already 835 const Size aOutTileSize( ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Width() ), 836 ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Height() ) ); 837 838 //#i69780 clip final tile size to a sane max size 839 while (((sal_Int64)rSize.Width() * nTileCacheSize1D) > SAL_MAX_UINT16) 840 nTileCacheSize1D /= 2; 841 while (((sal_Int64)rSize.Height() * nTileCacheSize1D) > SAL_MAX_UINT16) 842 nTileCacheSize1D /= 2; 843 844 return ImplDrawTiled( pOut, rArea, aOutTileSize, rOffset, pAttr, nFlags, nTileCacheSize1D ); 845 } 846 847 // ----------------------------------------------------------------------------- 848 849 sal_Bool GraphicObject::StartAnimation( OutputDevice* pOut, const Point& rPt, const Size& rSz, 850 long nExtraData, const GraphicAttr* pAttr, sal_uLong /*nFlags*/, 851 OutputDevice* pFirstFrameOutDev ) 852 { 853 sal_Bool bRet = sal_False; 854 855 GetGraphic(); 856 857 if( !IsSwappedOut() ) 858 { 859 const GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() ); 860 861 if( mbAnimated ) 862 { 863 Point aPt( rPt ); 864 Size aSz( rSz ); 865 sal_Bool bCropped = aAttr.IsCropped(); 866 867 if( bCropped ) 868 { 869 PolyPolygon aClipPolyPoly; 870 sal_Bool bRectClip; 871 const sal_Bool bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip ); 872 873 pOut->Push( PUSH_CLIPREGION ); 874 875 if( bCrop ) 876 { 877 if( bRectClip ) 878 pOut->IntersectClipRegion( aClipPolyPoly.GetBoundRect() ); 879 else 880 pOut->IntersectClipRegion( aClipPolyPoly ); 881 } 882 } 883 884 if( !mpSimpleCache || ( mpSimpleCache->maAttr != aAttr ) || pFirstFrameOutDev ) 885 { 886 if( mpSimpleCache ) 887 delete mpSimpleCache; 888 889 mpSimpleCache = new GrfSimpleCacheObj( GetTransformedGraphic( &aAttr ), aAttr ); 890 mpSimpleCache->maGraphic.SetAnimationNotifyHdl( GetAnimationNotifyHdl() ); 891 } 892 893 mpSimpleCache->maGraphic.StartAnimation( pOut, aPt, aSz, nExtraData, pFirstFrameOutDev ); 894 895 if( bCropped ) 896 pOut->Pop(); 897 898 bRet = sal_True; 899 } 900 else 901 bRet = Draw( pOut, rPt, rSz, &aAttr, GRFMGR_DRAW_STANDARD ); 902 } 903 904 return bRet; 905 } 906 907 // ----------------------------------------------------------------------------- 908 909 void GraphicObject::StopAnimation( OutputDevice* pOut, long nExtraData ) 910 { 911 if( mpSimpleCache ) 912 mpSimpleCache->maGraphic.StopAnimation( pOut, nExtraData ); 913 } 914 915 // ----------------------------------------------------------------------------- 916 917 const Graphic& GraphicObject::GetGraphic() const 918 { 919 if( mbAutoSwapped ) 920 ( (GraphicObject*) this )->ImplAutoSwapIn(); 921 922 return maGraphic; 923 } 924 925 // ----------------------------------------------------------------------------- 926 927 void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pCopyObj ) 928 { 929 mpMgr->ImplUnregisterObj( *this ); 930 931 if( mpSwapOutTimer ) 932 mpSwapOutTimer->Stop(); 933 934 maGraphic = rGraphic; 935 mbAutoSwapped = sal_False; 936 ImplAssignGraphicData(); 937 delete mpLink, mpLink = NULL; 938 delete mpSimpleCache, mpSimpleCache = NULL; 939 940 mpMgr->ImplRegisterObj( *this, maGraphic, 0, pCopyObj); 941 942 if( mpSwapOutTimer ) 943 mpSwapOutTimer->Start(); 944 945 // Handle evtl. needed AfterDataChanges 946 ImplAfterDataChange(); 947 } 948 949 // ----------------------------------------------------------------------------- 950 951 void GraphicObject::SetGraphic( const Graphic& rGraphic, const String& rLink ) 952 { 953 SetGraphic( rGraphic ); 954 mpLink = new String( rLink ); 955 } 956 957 // ----------------------------------------------------------------------------- 958 959 Graphic GraphicObject::GetTransformedGraphic( const Size& rDestSize, const MapMode& rDestMap, const GraphicAttr& rAttr ) const 960 { 961 // #104550# Extracted from svx/source/svdraw/svdograf.cxx 962 Graphic aTransGraphic( maGraphic ); 963 const GraphicType eType = GetType(); 964 const Size aSrcSize( aTransGraphic.GetPrefSize() ); 965 966 // #104115# Convert the crop margins to graphic object mapmode 967 const MapMode aMapGraph( aTransGraphic.GetPrefMapMode() ); 968 const MapMode aMap100( MAP_100TH_MM ); 969 970 Size aCropLeftTop; 971 Size aCropRightBottom; 972 973 if( GRAPHIC_GDIMETAFILE == eType ) 974 { 975 GDIMetaFile aMtf( aTransGraphic.GetGDIMetaFile() ); 976 977 if( aMapGraph == MAP_PIXEL ) 978 { 979 // crops are in 1/100th mm -> to aMapGraph -> to MAP_PIXEL 980 aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( 981 Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()), 982 aMap100); 983 aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( 984 Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()), 985 aMap100); 986 } 987 else 988 { 989 // crops are in GraphicObject units -> to aMapGraph 990 aCropLeftTop = OutputDevice::LogicToLogic( 991 Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()), 992 aMap100, 993 aMapGraph); 994 aCropRightBottom = OutputDevice::LogicToLogic( 995 Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()), 996 aMap100, 997 aMapGraph); 998 } 999 1000 // #104115# If the metafile is cropped, give it a special 1001 // treatment: clip against the remaining area, scale up such 1002 // that this area later fills the desired size, and move the 1003 // origin to the upper left edge of that area. 1004 if( rAttr.IsCropped() ) 1005 { 1006 const MapMode aMtfMapMode( aMtf.GetPrefMapMode() ); 1007 1008 Rectangle aClipRect( aMtfMapMode.GetOrigin().X() + aCropLeftTop.Width(), 1009 aMtfMapMode.GetOrigin().Y() + aCropLeftTop.Height(), 1010 aMtfMapMode.GetOrigin().X() + aSrcSize.Width() - aCropRightBottom.Width(), 1011 aMtfMapMode.GetOrigin().Y() + aSrcSize.Height() - aCropRightBottom.Height() ); 1012 1013 // #104115# To correctly crop rotated metafiles, clip by view rectangle 1014 aMtf.AddAction( new MetaISectRectClipRegionAction( aClipRect ), 0 ); 1015 1016 // #104115# To crop the metafile, scale larger than the output rectangle 1017 aMtf.Scale( (double)rDestSize.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()), 1018 (double)rDestSize.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) ); 1019 1020 // #104115# Adapt the pref size by hand (scale changes it 1021 // proportionally, but we want it to be smaller than the 1022 // former size, to crop the excess out) 1023 aMtf.SetPrefSize( Size( (long)((double)rDestSize.Width() * (1.0 + (aCropLeftTop.Width() + aCropRightBottom.Width()) / aSrcSize.Width()) + .5), 1024 (long)((double)rDestSize.Height() * (1.0 + (aCropLeftTop.Height() + aCropRightBottom.Height()) / aSrcSize.Height()) + .5) ) ); 1025 1026 // #104115# Adapt the origin of the new mapmode, such that it 1027 // is shifted to the place where the cropped output starts 1028 Point aNewOrigin( (long)((double)aMtfMapMode.GetOrigin().X() + rDestSize.Width() * aCropLeftTop.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()) + .5), 1029 (long)((double)aMtfMapMode.GetOrigin().Y() + rDestSize.Height() * aCropLeftTop.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) + .5) ); 1030 MapMode aNewMap( rDestMap ); 1031 aNewMap.SetOrigin( OutputDevice::LogicToLogic(aNewOrigin, aMtfMapMode, rDestMap) ); 1032 aMtf.SetPrefMapMode( aNewMap ); 1033 } 1034 else 1035 { 1036 aMtf.Scale( Fraction( rDestSize.Width(), aSrcSize.Width() ), Fraction( rDestSize.Height(), aSrcSize.Height() ) ); 1037 aMtf.SetPrefMapMode( rDestMap ); 1038 } 1039 1040 aTransGraphic = aMtf; 1041 } 1042 else if( GRAPHIC_BITMAP == eType ) 1043 { 1044 BitmapEx aBitmapEx( aTransGraphic.GetBitmapEx() ); 1045 Rectangle aCropRect; 1046 1047 // convert crops to pixel 1048 if(rAttr.IsCropped()) 1049 { 1050 if( aMapGraph == MAP_PIXEL ) 1051 { 1052 // crops are in 1/100th mm -> to MAP_PIXEL 1053 aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( 1054 Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()), 1055 aMap100); 1056 aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( 1057 Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()), 1058 aMap100); 1059 } 1060 else 1061 { 1062 // crops are in GraphicObject units -> to MAP_PIXEL 1063 aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( 1064 Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()), 1065 aMapGraph); 1066 aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( 1067 Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()), 1068 aMapGraph); 1069 } 1070 1071 // convert from prefmapmode to pixel 1072 Size aSrcSizePixel( 1073 Application::GetDefaultDevice()->LogicToPixel( 1074 aSrcSize, 1075 aMapGraph)); 1076 1077 if(rAttr.IsCropped() 1078 && (aSrcSizePixel.Width() != aBitmapEx.GetSizePixel().Width() || aSrcSizePixel.Height() != aBitmapEx.GetSizePixel().Height()) 1079 && aSrcSizePixel.Width()) 1080 { 1081 // the size in pixels calculated from Graphic's internal MapMode (aTransGraphic.GetPrefMapMode()) 1082 // and it's internal size (aTransGraphic.GetPrefSize()) is different from it's real pixel size. 1083 // This can be interpreted as this values to be set wrong, but needs to be corrected since e.g. 1084 // existing cropping is calculated based on this logic values already. 1085 // aBitmapEx.Scale(aSrcSizePixel); 1086 1087 // another possibility is to adapt the values created so far with a factor; this 1088 // will keep the original Bitmap untouched and thus quality will not change 1089 // caution: convert to double first, else pretty big errors may occurr 1090 const double fFactorX((double)aBitmapEx.GetSizePixel().Width() / aSrcSizePixel.Width()); 1091 const double fFactorY((double)aBitmapEx.GetSizePixel().Height() / aSrcSizePixel.Height()); 1092 1093 aCropLeftTop.Width() = basegfx::fround(aCropLeftTop.Width() * fFactorX); 1094 aCropLeftTop.Height() = basegfx::fround(aCropLeftTop.Height() * fFactorY); 1095 aCropRightBottom.Width() = basegfx::fround(aCropRightBottom.Width() * fFactorX); 1096 aCropRightBottom.Height() = basegfx::fround(aCropRightBottom.Height() * fFactorY); 1097 1098 aSrcSizePixel = aBitmapEx.GetSizePixel(); 1099 } 1100 1101 // setup crop rectangle in pixel 1102 aCropRect = Rectangle( aCropLeftTop.Width(), aCropLeftTop.Height(), 1103 aSrcSizePixel.Width() - aCropRightBottom.Width(), 1104 aSrcSizePixel.Height() - aCropRightBottom.Height() ); 1105 } 1106 1107 // #105641# Also crop animations 1108 if( aTransGraphic.IsAnimated() ) 1109 { 1110 sal_uInt16 nFrame; 1111 Animation aAnim( aTransGraphic.GetAnimation() ); 1112 1113 for( nFrame=0; nFrame<aAnim.Count(); ++nFrame ) 1114 { 1115 AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) ); 1116 1117 if( !aCropRect.IsInside( Rectangle(aAnimBmp.aPosPix, aAnimBmp.aSizePix) ) ) 1118 { 1119 // setup actual cropping (relative to frame position) 1120 Rectangle aCropRectRel( aCropRect ); 1121 aCropRectRel.Move( -aAnimBmp.aPosPix.X(), 1122 -aAnimBmp.aPosPix.Y() ); 1123 1124 // cropping affects this frame, apply it then 1125 // do _not_ apply enlargement, this is done below 1126 ImplTransformBitmap( aAnimBmp.aBmpEx, rAttr, Size(), Size(), 1127 aCropRectRel, rDestSize, sal_False ); 1128 1129 aAnim.Replace( aAnimBmp, nFrame ); 1130 } 1131 // else: bitmap completely within crop area, 1132 // i.e. nothing is cropped away 1133 } 1134 1135 // now, apply enlargement (if any) through global animation size 1136 if( aCropLeftTop.Width() < 0 || 1137 aCropLeftTop.Height() < 0 || 1138 aCropRightBottom.Width() < 0 || 1139 aCropRightBottom.Height() < 0 ) 1140 { 1141 Size aNewSize( aAnim.GetDisplaySizePixel() ); 1142 aNewSize.Width() += aCropRightBottom.Width() < 0 ? -aCropRightBottom.Width() : 0; 1143 aNewSize.Width() += aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0; 1144 aNewSize.Height() += aCropRightBottom.Height() < 0 ? -aCropRightBottom.Height() : 0; 1145 aNewSize.Height() += aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0; 1146 aAnim.SetDisplaySizePixel( aNewSize ); 1147 } 1148 1149 // if topleft has changed, we must move all frames to the 1150 // right and bottom, resp. 1151 if( aCropLeftTop.Width() < 0 || 1152 aCropLeftTop.Height() < 0 ) 1153 { 1154 Point aPosOffset( aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0, 1155 aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0 ); 1156 1157 for( nFrame=0; nFrame<aAnim.Count(); ++nFrame ) 1158 { 1159 AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) ); 1160 1161 aAnimBmp.aPosPix += aPosOffset; 1162 1163 aAnim.Replace( aAnimBmp, nFrame ); 1164 } 1165 } 1166 1167 aTransGraphic = aAnim; 1168 } 1169 else 1170 { 1171 ImplTransformBitmap( aBitmapEx, rAttr, aCropLeftTop, aCropRightBottom, 1172 aCropRect, rDestSize, sal_True ); 1173 1174 aTransGraphic = aBitmapEx; 1175 } 1176 1177 aTransGraphic.SetPrefSize( rDestSize ); 1178 aTransGraphic.SetPrefMapMode( rDestMap ); 1179 } 1180 1181 GraphicObject aGrfObj( aTransGraphic ); 1182 aTransGraphic = aGrfObj.GetTransformedGraphic( &rAttr ); 1183 1184 return aTransGraphic; 1185 } 1186 1187 // ----------------------------------------------------------------------------- 1188 1189 Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const // TODO: Change to Impl 1190 { 1191 GetGraphic(); 1192 1193 Graphic aGraphic; 1194 GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() ); 1195 1196 if( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() ) 1197 { 1198 if( aAttr.IsSpecialDrawMode() || aAttr.IsAdjusted() || aAttr.IsMirrored() || aAttr.IsRotated() || aAttr.IsTransparent() ) 1199 { 1200 if( GetType() == GRAPHIC_BITMAP ) 1201 { 1202 if( IsAnimated() ) 1203 { 1204 Animation aAnimation( maGraphic.GetAnimation() ); 1205 GraphicManager::ImplAdjust( aAnimation, aAttr, ADJUSTMENT_ALL ); 1206 aAnimation.SetLoopCount( mnAnimationLoopCount ); 1207 aGraphic = aAnimation; 1208 } 1209 else 1210 { 1211 BitmapEx aBmpEx( maGraphic.GetBitmapEx() ); 1212 GraphicManager::ImplAdjust( aBmpEx, aAttr, ADJUSTMENT_ALL ); 1213 aGraphic = aBmpEx; 1214 } 1215 } 1216 else 1217 { 1218 GDIMetaFile aMtf( maGraphic.GetGDIMetaFile() ); 1219 GraphicManager::ImplAdjust( aMtf, aAttr, ADJUSTMENT_ALL ); 1220 aGraphic = aMtf; 1221 } 1222 } 1223 else 1224 { 1225 if( ( GetType() == GRAPHIC_BITMAP ) && IsAnimated() ) 1226 { 1227 Animation aAnimation( maGraphic.GetAnimation() ); 1228 aAnimation.SetLoopCount( mnAnimationLoopCount ); 1229 aGraphic = aAnimation; 1230 } 1231 else 1232 aGraphic = maGraphic; 1233 } 1234 } 1235 1236 return aGraphic; 1237 } 1238 1239 // ----------------------------------------------------------------------------- 1240 1241 void GraphicObject::ResetAnimationLoopCount() 1242 { 1243 if( IsAnimated() && !IsSwappedOut() ) 1244 { 1245 maGraphic.ResetAnimationLoopCount(); 1246 1247 if( mpSimpleCache ) 1248 mpSimpleCache->maGraphic.ResetAnimationLoopCount(); 1249 } 1250 } 1251 1252 // ----------------------------------------------------------------------------- 1253 1254 sal_Bool GraphicObject::SwapOut() 1255 { 1256 sal_Bool bRet = ( !mbAutoSwapped ? maGraphic.SwapOut() : sal_False ); 1257 1258 if( bRet && mpMgr ) 1259 mpMgr->ImplGraphicObjectWasSwappedOut( *this ); 1260 1261 return bRet; 1262 } 1263 1264 // ----------------------------------------------------------------------------- 1265 1266 sal_Bool GraphicObject::SwapOut( SvStream* pOStm ) 1267 { 1268 sal_Bool bRet = ( !mbAutoSwapped ? maGraphic.SwapOut( pOStm ) : sal_False ); 1269 1270 if( bRet && mpMgr ) 1271 mpMgr->ImplGraphicObjectWasSwappedOut( *this ); 1272 1273 return bRet; 1274 } 1275 1276 // ----------------------------------------------------------------------------- 1277 1278 sal_Bool GraphicObject::SwapIn() 1279 { 1280 sal_Bool bRet; 1281 1282 if( mbAutoSwapped ) 1283 { 1284 ImplAutoSwapIn(); 1285 bRet = sal_True; 1286 } 1287 else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) ) 1288 { 1289 bRet = sal_True; 1290 } 1291 else 1292 { 1293 bRet = maGraphic.SwapIn(); 1294 1295 if( bRet && mpMgr ) 1296 mpMgr->ImplGraphicObjectWasSwappedIn( *this ); 1297 } 1298 1299 if( bRet ) 1300 { 1301 ImplAssignGraphicData(); 1302 1303 // Handle evtl. needed AfterDataChanges 1304 ImplAfterDataChange(); 1305 } 1306 1307 return bRet; 1308 } 1309 1310 // ----------------------------------------------------------------------------- 1311 1312 sal_Bool GraphicObject::SwapIn( SvStream* pIStm ) 1313 { 1314 sal_Bool bRet; 1315 1316 if( mbAutoSwapped ) 1317 { 1318 ImplAutoSwapIn(); 1319 bRet = sal_True; 1320 } 1321 else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) ) 1322 { 1323 bRet = sal_True; 1324 } 1325 else 1326 { 1327 bRet = maGraphic.SwapIn( pIStm ); 1328 1329 if( bRet && mpMgr ) 1330 mpMgr->ImplGraphicObjectWasSwappedIn( *this ); 1331 } 1332 1333 if( bRet ) 1334 { 1335 ImplAssignGraphicData(); 1336 1337 // 1338 ImplAfterDataChange(); 1339 } 1340 1341 return bRet; 1342 } 1343 1344 // ----------------------------------------------------------------------------- 1345 1346 void GraphicObject::SetSwapState() 1347 { 1348 if( !IsSwappedOut() ) 1349 { 1350 mbAutoSwapped = sal_True; 1351 1352 if( mpMgr ) 1353 mpMgr->ImplGraphicObjectWasSwappedOut( *this ); 1354 } 1355 } 1356 1357 // ----------------------------------------------------------------------------- 1358 1359 IMPL_LINK( GraphicObject, ImplAutoSwapOutHdl, void*, EMPTYARG ) 1360 { 1361 if( !IsSwappedOut() ) 1362 { 1363 mbIsInSwapOut = sal_True; 1364 1365 SvStream* pStream = GetSwapStream(); 1366 1367 if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream ) 1368 { 1369 if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream ) 1370 mbAutoSwapped = SwapOut( NULL ); 1371 else 1372 { 1373 if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream ) 1374 mbAutoSwapped = SwapOut(); 1375 else 1376 { 1377 mbAutoSwapped = SwapOut( pStream ); 1378 delete pStream; 1379 } 1380 } 1381 } 1382 1383 mbIsInSwapOut = sal_False; 1384 } 1385 1386 if( mpSwapOutTimer ) 1387 mpSwapOutTimer->Start(); 1388 1389 return 0L; 1390 } 1391 1392 // ------------------------------------------------------------------------ 1393 1394 SvStream& operator>>( SvStream& rIStm, GraphicObject& rGraphicObj ) 1395 { 1396 VersionCompat aCompat( rIStm, STREAM_READ ); 1397 Graphic aGraphic; 1398 GraphicAttr aAttr; 1399 ByteString aLink; 1400 sal_Bool bLink; 1401 1402 rIStm >> aGraphic >> aAttr >> bLink; 1403 1404 rGraphicObj.SetGraphic( aGraphic ); 1405 rGraphicObj.SetAttr( aAttr ); 1406 1407 if( bLink ) 1408 { 1409 rIStm >> aLink; 1410 rGraphicObj.SetLink( UniString( aLink, RTL_TEXTENCODING_UTF8 ) ); 1411 } 1412 else 1413 rGraphicObj.SetLink(); 1414 1415 rGraphicObj.SetSwapStreamHdl(); 1416 1417 return rIStm; 1418 } 1419 1420 // ------------------------------------------------------------------------ 1421 1422 SvStream& operator<<( SvStream& rOStm, const GraphicObject& rGraphicObj ) 1423 { 1424 VersionCompat aCompat( rOStm, STREAM_WRITE, 1 ); 1425 const sal_Bool bLink = rGraphicObj.HasLink(); 1426 1427 rOStm << rGraphicObj.GetGraphic() << rGraphicObj.GetAttr() << bLink; 1428 1429 if( bLink ) 1430 rOStm << ByteString( rGraphicObj.GetLink(), RTL_TEXTENCODING_UTF8 ); 1431 1432 return rOStm; 1433 } 1434 1435 #define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:" 1436 1437 GraphicObject GraphicObject::CreateGraphicObjectFromURL( const ::rtl::OUString &rURL ) 1438 { 1439 const String aURL( rURL ), aPrefix( RTL_CONSTASCII_STRINGPARAM(UNO_NAME_GRAPHOBJ_URLPREFIX) ); 1440 if( aURL.Search( aPrefix ) == 0 ) 1441 { 1442 // graphic manager url 1443 ByteString aUniqueID( String(rURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 )), RTL_TEXTENCODING_UTF8 ); 1444 return GraphicObject( aUniqueID ); 1445 } 1446 else 1447 { 1448 Graphic aGraphic; 1449 if ( aURL.Len() ) 1450 { 1451 // The URL comes out of document content, so it is followed only if 1452 // the shared policy permits it (see svtools/linkpolicy.hxx). 1453 if ( !::svt::linkpolicy::mayFollowDocumentLink( rURL ) ) 1454 return GraphicObject( aGraphic ); 1455 1456 SvStream* pStream = utl::UcbStreamHelper::CreateStream( aURL, STREAM_READ ); 1457 if( pStream ) 1458 GraphicConverter::Import( *pStream, aGraphic ); 1459 } 1460 1461 return GraphicObject( aGraphic ); 1462 } 1463 } 1464 1465 // calculate scalings between real image size and logic object size. This 1466 // is necessary since the crop values are relative to original bitmap size 1467 basegfx::B2DVector GraphicObject::calculateCropScaling( 1468 double fWidth, 1469 double fHeight, 1470 double fLeftCrop, 1471 double fTopCrop, 1472 double fRightCrop, 1473 double fBottomCrop) const 1474 { 1475 const MapMode aMapMode100thmm(MAP_100TH_MM); 1476 Size aBitmapSize(GetPrefSize()); 1477 double fFactorX(1.0); 1478 double fFactorY(1.0); 1479 1480 if(MAP_PIXEL == GetPrefMapMode().GetMapUnit()) 1481 { 1482 aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, aMapMode100thmm); 1483 } 1484 else 1485 { 1486 aBitmapSize = Application::GetDefaultDevice()->LogicToLogic(aBitmapSize, GetPrefMapMode(), aMapMode100thmm); 1487 } 1488 1489 const double fDivX(aBitmapSize.Width() - fLeftCrop - fRightCrop); 1490 const double fDivY(aBitmapSize.Height() - fTopCrop - fBottomCrop); 1491 1492 if(!basegfx::fTools::equalZero(fDivX)) 1493 { 1494 fFactorX = fabs(fWidth) / fDivX; 1495 } 1496 1497 if(!basegfx::fTools::equalZero(fDivY)) 1498 { 1499 fFactorY = fabs(fHeight) / fDivY; 1500 } 1501 1502 return basegfx::B2DVector(fFactorX,fFactorY); 1503 } 1504 1505 // ------------------------------------------------------------------------ 1506 // restart SwapOut timer 1507 1508 void GraphicObject::restartSwapOutTimer() const 1509 { 1510 if( mpSwapOutTimer && mpSwapOutTimer->IsActive() ) 1511 { 1512 mpSwapOutTimer->Start(); 1513 } 1514 } 1515 1516 // eof 1517