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