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_vcl.hxx" 26 27 #include <tools/vcompat.hxx> 28 #include <tools/urlobj.hxx> 29 #include <tools/debug.hxx> 30 #include <tools/stream.hxx> 31 #include <ucbhelper/content.hxx> 32 #include <unotools/ucbstreamhelper.hxx> 33 #include <unotools/tempfile.hxx> 34 #include <vcl/outdev.hxx> 35 #include <vcl/virdev.hxx> 36 #include <vcl/gfxlink.hxx> 37 #include <vcl/cvtgrf.hxx> 38 #include <vcl/salbtype.hxx> 39 #include <vcl/graph.hxx> 40 #include <vcl/metaact.hxx> 41 #include <impgraph.hxx> 42 #include <com/sun/star/ucb/CommandAbortedException.hpp> 43 44 // ----------- 45 // - Defines - 46 // ----------- 47 48 #define GRAPHIC_MAXPARTLEN 256000L 49 #define GRAPHIC_MTFTOBMP_MAXEXT 2048 50 #define GRAPHIC_STREAMBUFSIZE 8192UL 51 52 #define SYS_WINMETAFILE 0x00000003L 53 #define SYS_WNTMETAFILE 0x00000004L 54 #define SYS_OS2METAFILE 0x00000005L 55 #define SYS_MACMETAFILE 0x00000006L 56 57 #define GRAPHIC_FORMAT_50 static_cast<sal_uInt32>(COMPAT_FORMAT( 'G', 'R', 'F', '5' )) 58 #define NATIVE_FORMAT_50 static_cast<sal_uInt32>(COMPAT_FORMAT( 'N', 'A', 'T', '5' )) 59 60 // --------------- 61 // - ImpSwapFile - 62 // --------------- 63 64 struct ImpSwapFile 65 { 66 INetURLObject aSwapURL; 67 sal_uLong nRefCount; 68 }; 69 70 // ----------------- 71 // - Graphicreader - 72 // ----------------- 73 74 class ReaderData 75 { 76 public: 77 Size maPreviewSize; 78 }; 79 80 GraphicReader::~GraphicReader() 81 { 82 delete mpReaderData; 83 } 84 85 // ------------------------------------------------------------------------ 86 87 sal_Bool GraphicReader::IsPreviewModeEnabled() const 88 { 89 if( !mpReaderData ) 90 return sal_False; 91 if( mpReaderData->maPreviewSize.Width() ) 92 return sal_True; 93 if( mpReaderData->maPreviewSize.Height() ) 94 return sal_True; 95 return sal_False; 96 } 97 98 // ------------------------------------------------------------------------ 99 100 void GraphicReader::DisablePreviewMode() 101 { 102 if( mpReaderData ) 103 mpReaderData->maPreviewSize = Size( 0, 0 ); 104 } 105 106 // ------------------------------------------------------------------------ 107 108 void GraphicReader::SetPreviewSize( const Size& rSize ) 109 { 110 if( !mpReaderData ) 111 mpReaderData = new ReaderData; 112 mpReaderData->maPreviewSize = rSize; 113 } 114 115 // ------------------------------------------------------------------------ 116 117 Size GraphicReader::GetPreviewSize() const 118 { 119 Size aSize( 0, 0 ); 120 if( mpReaderData ) 121 aSize = mpReaderData->maPreviewSize; 122 return aSize; 123 } 124 125 // -------------- 126 // - ImpGraphic - 127 // -------------- 128 129 ImpGraphic::ImpGraphic() : 130 mpAnimation ( NULL ), 131 mpContext ( NULL ), 132 mpSwapFile ( NULL ), 133 mpGfxLink ( NULL ), 134 meType ( GRAPHIC_NONE ), 135 mnDocFilePos ( 0UL ), 136 mnSizeBytes ( 0UL ), 137 mnRefCount ( 1UL ), 138 mbSwapOut ( sal_False ), 139 mbSwapUnderway ( sal_False ) 140 { 141 } 142 143 // ------------------------------------------------------------------------ 144 145 ImpGraphic::ImpGraphic( const ImpGraphic& rImpGraphic ) : 146 maMetaFile ( rImpGraphic.maMetaFile ), 147 maEx ( rImpGraphic.maEx ), 148 mpContext ( NULL ), 149 mpSwapFile ( rImpGraphic.mpSwapFile ), 150 meType ( rImpGraphic.meType ), 151 maDocFileURLStr ( rImpGraphic.maDocFileURLStr ), 152 mnDocFilePos ( rImpGraphic.mnDocFilePos ), 153 mnSizeBytes ( rImpGraphic.mnSizeBytes ), 154 mnRefCount ( 1UL ), 155 mbSwapOut ( rImpGraphic.mbSwapOut ), 156 mbSwapUnderway ( sal_False ) 157 { 158 if( mpSwapFile ) 159 mpSwapFile->nRefCount++; 160 161 if( rImpGraphic.mpGfxLink ) 162 mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink ); 163 else 164 mpGfxLink = NULL; 165 166 if( rImpGraphic.mpAnimation ) 167 { 168 mpAnimation = new Animation( *rImpGraphic.mpAnimation ); 169 maEx = mpAnimation->GetBitmapEx(); 170 } 171 else 172 mpAnimation = NULL; 173 174 maSvgData = rImpGraphic.maSvgData; 175 } 176 177 // ------------------------------------------------------------------------ 178 179 ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) : 180 maEx ( rBitmap ), 181 mpAnimation ( NULL ), 182 mpContext ( NULL ), 183 mpSwapFile ( NULL ), 184 mpGfxLink ( NULL ), 185 meType ( !rBitmap ? GRAPHIC_NONE : GRAPHIC_BITMAP ), 186 mnDocFilePos ( 0UL ), 187 mnSizeBytes ( 0UL ), 188 mnRefCount ( 1UL ), 189 mbSwapOut ( sal_False ), 190 mbSwapUnderway ( sal_False ) 191 { 192 } 193 194 // ------------------------------------------------------------------------ 195 196 ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) : 197 maEx ( rBitmapEx ), 198 mpAnimation ( NULL ), 199 mpContext ( NULL ), 200 mpSwapFile ( NULL ), 201 mpGfxLink ( NULL ), 202 meType ( !rBitmapEx ? GRAPHIC_NONE : GRAPHIC_BITMAP ), 203 mnDocFilePos ( 0UL ), 204 mnSizeBytes ( 0UL ), 205 mnRefCount ( 1UL ), 206 mbSwapOut ( sal_False ), 207 mbSwapUnderway ( sal_False ) 208 { 209 } 210 211 // ------------------------------------------------------------------------ 212 213 ImpGraphic::ImpGraphic(const SvgDataPtr& rSvgDataPtr) 214 : mpAnimation( NULL ), 215 mpContext( NULL ), 216 mpSwapFile( NULL ), 217 mpGfxLink( NULL ), 218 meType( rSvgDataPtr.get() ? GRAPHIC_BITMAP : GRAPHIC_NONE ), 219 mnDocFilePos( 0UL ), 220 mnSizeBytes( 0UL ), 221 mnRefCount( 1UL ), 222 mbSwapOut( sal_False ), 223 mbSwapUnderway( sal_False ), 224 maSvgData(rSvgDataPtr) 225 { 226 } 227 228 // ------------------------------------------------------------------------ 229 230 ImpGraphic::ImpGraphic( const Animation& rAnimation ) : 231 maEx ( rAnimation.GetBitmapEx() ), 232 mpAnimation ( new Animation( rAnimation ) ), 233 mpContext ( NULL ), 234 mpSwapFile ( NULL ), 235 mpGfxLink ( NULL ), 236 meType ( GRAPHIC_BITMAP ), 237 mnDocFilePos ( 0UL ), 238 mnSizeBytes ( 0UL ), 239 mnRefCount ( 1UL ), 240 mbSwapOut ( sal_False ), 241 mbSwapUnderway ( sal_False ) 242 { 243 } 244 245 // ------------------------------------------------------------------------ 246 247 ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) : 248 maMetaFile ( rMtf ), 249 mpAnimation ( NULL ), 250 mpContext ( NULL ), 251 mpSwapFile ( NULL ), 252 mpGfxLink ( NULL ), 253 meType ( GRAPHIC_GDIMETAFILE ), 254 mnDocFilePos ( 0UL ), 255 mnSizeBytes ( 0UL ), 256 mnRefCount ( 1UL ), 257 mbSwapOut ( sal_False ), 258 mbSwapUnderway ( sal_False ) 259 { 260 } 261 262 // ------------------------------------------------------------------------ 263 264 ImpGraphic::~ImpGraphic() 265 { 266 ImplClear(); 267 268 if( (sal_uLong) mpContext > 1UL ) 269 delete mpContext; 270 } 271 272 // ------------------------------------------------------------------------ 273 274 ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic ) 275 { 276 if( &rImpGraphic != this ) 277 { 278 if( !mbSwapUnderway ) 279 ImplClear(); 280 281 maMetaFile = rImpGraphic.maMetaFile; 282 meType = rImpGraphic.meType; 283 mnSizeBytes = rImpGraphic.mnSizeBytes; 284 285 delete mpAnimation; 286 287 if ( rImpGraphic.mpAnimation ) 288 { 289 mpAnimation = new Animation( *rImpGraphic.mpAnimation ); 290 maEx = mpAnimation->GetBitmapEx(); 291 } 292 else 293 { 294 mpAnimation = NULL; 295 maEx = rImpGraphic.maEx; 296 } 297 298 if( !mbSwapUnderway ) 299 { 300 maDocFileURLStr = rImpGraphic.maDocFileURLStr; 301 mnDocFilePos = rImpGraphic.mnDocFilePos; 302 mbSwapOut = rImpGraphic.mbSwapOut; 303 mpSwapFile = rImpGraphic.mpSwapFile; 304 305 if( mpSwapFile ) 306 mpSwapFile->nRefCount++; 307 } 308 309 delete mpGfxLink; 310 311 if( rImpGraphic.mpGfxLink ) 312 mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink ); 313 else 314 mpGfxLink = NULL; 315 316 maSvgData = rImpGraphic.maSvgData; 317 } 318 319 return *this; 320 } 321 322 // ------------------------------------------------------------------------ 323 324 sal_Bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const 325 { 326 sal_Bool bRet = sal_False; 327 328 if( this == &rImpGraphic ) 329 bRet = sal_True; 330 else if( !ImplIsSwapOut() && ( rImpGraphic.meType == meType ) ) 331 { 332 switch( meType ) 333 { 334 case( GRAPHIC_NONE ): 335 bRet = sal_True; 336 break; 337 338 case( GRAPHIC_GDIMETAFILE ): 339 { 340 if( rImpGraphic.maMetaFile == maMetaFile ) 341 bRet = sal_True; 342 } 343 break; 344 345 case( GRAPHIC_BITMAP ): 346 { 347 if(maSvgData.get()) 348 { 349 if(maSvgData == rImpGraphic.maSvgData) 350 { 351 bRet = sal_True; 352 } 353 else if(rImpGraphic.maSvgData) 354 { 355 if(maSvgData->getSvgDataArrayLength() == rImpGraphic.maSvgData->getSvgDataArrayLength()) 356 { 357 if(0 == memcmp( 358 maSvgData->getSvgDataArray().get(), 359 rImpGraphic.maSvgData->getSvgDataArray().get(), 360 maSvgData->getSvgDataArrayLength())) 361 { 362 bRet = sal_True; 363 } 364 } 365 } 366 } 367 else if( mpAnimation ) 368 { 369 if( rImpGraphic.mpAnimation && ( *rImpGraphic.mpAnimation == *mpAnimation ) ) 370 bRet = sal_True; 371 } 372 else if( !rImpGraphic.mpAnimation && ( rImpGraphic.maEx == maEx ) ) 373 { 374 bRet = sal_True; 375 } 376 } 377 break; 378 379 default: 380 break; 381 } 382 } 383 384 return bRet; 385 } 386 387 // ------------------------------------------------------------------------ 388 389 void ImpGraphic::ImplClearGraphics( sal_Bool bCreateSwapInfo ) 390 { 391 if( bCreateSwapInfo && !ImplIsSwapOut() ) 392 { 393 maSwapInfo.maPrefMapMode = ImplGetPrefMapMode(); 394 maSwapInfo.maPrefSize = ImplGetPrefSize(); 395 } 396 397 maEx.Clear(); 398 maMetaFile.Clear(); 399 400 if( mpAnimation ) 401 { 402 mpAnimation->Clear(); 403 delete mpAnimation; 404 mpAnimation = NULL; 405 } 406 407 if( mpGfxLink ) 408 { 409 delete mpGfxLink; 410 mpGfxLink = NULL; 411 } 412 413 maSvgData.reset(); 414 } 415 416 // ------------------------------------------------------------------------ 417 418 void ImpGraphic::ImplClear() 419 { 420 if( mpSwapFile ) 421 { 422 if( mpSwapFile->nRefCount > 1 ) 423 mpSwapFile->nRefCount--; 424 else 425 { 426 try 427 { 428 ::ucbhelper::Content aCnt( mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE ), 429 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); 430 431 aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), 432 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); 433 } 434 catch( const ::com::sun::star::ucb::ContentCreationException& ) 435 { 436 } 437 catch( const ::com::sun::star::uno::RuntimeException& ) 438 { 439 } 440 catch( const ::com::sun::star::ucb::CommandAbortedException& ) 441 { 442 } 443 catch( const ::com::sun::star::uno::Exception& ) 444 { 445 } 446 447 delete mpSwapFile; 448 } 449 450 mpSwapFile = NULL; 451 } 452 453 mbSwapOut = sal_False; 454 mnDocFilePos = 0UL; 455 maDocFileURLStr.Erase(); 456 457 // cleanup 458 ImplClearGraphics( sal_False ); 459 meType = GRAPHIC_NONE; 460 mnSizeBytes = 0; 461 } 462 463 // ------------------------------------------------------------------------ 464 465 GraphicType ImpGraphic::ImplGetType() const 466 { 467 return meType; 468 } 469 470 // ------------------------------------------------------------------------ 471 472 void ImpGraphic::ImplSetDefaultType() 473 { 474 ImplClear(); 475 meType = GRAPHIC_DEFAULT; 476 } 477 478 // ------------------------------------------------------------------------ 479 480 sal_Bool ImpGraphic::ImplIsSupportedGraphic() const 481 { 482 return( meType != GRAPHIC_NONE ); 483 } 484 485 // ------------------------------------------------------------------------ 486 487 sal_Bool ImpGraphic::ImplIsTransparent() const 488 { 489 sal_Bool bRet(sal_True); 490 491 if( meType == GRAPHIC_BITMAP && !maSvgData.get()) 492 { 493 bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() ); 494 } 495 496 return bRet; 497 } 498 499 // ------------------------------------------------------------------------ 500 501 sal_Bool ImpGraphic::ImplIsAlpha() const 502 { 503 sal_Bool bRet(sal_False); 504 505 if(maSvgData.get()) 506 { 507 bRet = sal_True; 508 } 509 else if( meType == GRAPHIC_BITMAP ) 510 { 511 bRet = ( NULL == mpAnimation ) && maEx.IsAlpha(); 512 } 513 514 return bRet; 515 } 516 517 // ------------------------------------------------------------------------ 518 519 sal_Bool ImpGraphic::ImplIsAnimated() const 520 { 521 return( mpAnimation != NULL ); 522 } 523 524 // ------------------------------------------------------------------------ 525 526 sal_Bool ImpGraphic::ImplIsEPS() const 527 { 528 return( ( meType == GRAPHIC_GDIMETAFILE ) && 529 ( maMetaFile.GetActionCount() > 0 ) && 530 ( maMetaFile.GetAction( 0 )->GetType() == META_EPS_ACTION ) ); 531 } 532 533 // ------------------------------------------------------------------------ 534 535 Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) const 536 { 537 Bitmap aRetBmp; 538 539 if( meType == GRAPHIC_BITMAP ) 540 { 541 if(maSvgData.get() && maEx.IsEmpty()) 542 { 543 // use maEx as local buffer for rendered svg 544 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); 545 } 546 547 const BitmapEx& rRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx ); 548 const Color aReplaceColor( COL_WHITE ); 549 550 aRetBmp = rRetBmpEx.GetBitmap( &aReplaceColor ); 551 552 if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height()) 553 aRetBmp.Scale(rParameters.getSizePixel()); 554 } 555 else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() ) 556 { 557 if(maEx.IsEmpty()) 558 { 559 // calculate size 560 VirtualDevice aVDev; 561 Size aDrawSize(aVDev.LogicToPixel(maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode())); 562 563 if(rParameters.getSizePixel().Width() && rParameters.getSizePixel().Height()) 564 { 565 // apply given size if exists 566 aDrawSize = rParameters.getSizePixel(); 567 } 568 569 if(aDrawSize.Width() && aDrawSize.Height() && !rParameters.getUnlimitedSize() 570 && (aDrawSize.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aDrawSize.Height() > GRAPHIC_MTFTOBMP_MAXEXT)) 571 { 572 // limit bitmap size to a maximum of GRAPHIC_MTFTOBMP_MAXEXT x GRAPHIC_MTFTOBMP_MAXEXT 573 double fWH((double)aDrawSize.Width() / (double)aDrawSize.Height()); 574 575 if(fWH <= 1.0) 576 { 577 aDrawSize.setWidth(basegfx::fround(GRAPHIC_MTFTOBMP_MAXEXT * fWH)); 578 aDrawSize.setHeight(GRAPHIC_MTFTOBMP_MAXEXT); 579 } 580 else 581 { 582 aDrawSize.setWidth(GRAPHIC_MTFTOBMP_MAXEXT); 583 aDrawSize.setHeight(basegfx::fround(GRAPHIC_MTFTOBMP_MAXEXT / fWH)); 584 } 585 } 586 587 // calculate pixel size. Normally, it's the same as aDrawSize, but may 588 // need to be extended when hairlines are on the right or bottom edge 589 Size aPixelSize(aDrawSize); 590 591 if(GRAPHIC_GDIMETAFILE == ImplGetType()) 592 { 593 // get hairline and full bound rect 594 Rectangle aHairlineRect; 595 const Rectangle aRect(maMetaFile.GetBoundRect(aVDev, &aHairlineRect)); 596 597 if(!aRect.IsEmpty() && !aHairlineRect.IsEmpty()) 598 { 599 // expand if needed to allow bottom and right hairlines to be added 600 if(aRect.Right() == aHairlineRect.Right()) 601 { 602 aPixelSize.setWidth(aPixelSize.getWidth() + 1); 603 } 604 605 if(aRect.Bottom() == aHairlineRect.Bottom()) 606 { 607 aPixelSize.setHeight(aPixelSize.getHeight() + 1); 608 } 609 } 610 } 611 612 if(aVDev.SetOutputSizePixel(aPixelSize)) 613 { 614 if(rParameters.getAntiAliase()) 615 { 616 aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW); 617 } 618 619 if(rParameters.getSnapHorVerLines()) 620 { 621 aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_PIXELSNAPHAIRLINE); 622 } 623 624 ImplDraw( &aVDev, Point(), aDrawSize ); 625 626 // use maEx as local buffer for rendered metafile 627 const_cast< ImpGraphic* >(this)->maEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() ); 628 } 629 } 630 631 aRetBmp = maEx.GetBitmap(); 632 } 633 634 if( !!aRetBmp ) 635 { 636 aRetBmp.SetPrefMapMode( ImplGetPrefMapMode() ); 637 aRetBmp.SetPrefSize( ImplGetPrefSize() ); 638 } 639 640 return aRetBmp; 641 } 642 643 // ------------------------------------------------------------------------ 644 645 BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const 646 { 647 BitmapEx aRetBmpEx; 648 649 if( meType == GRAPHIC_BITMAP ) 650 { 651 if(maSvgData.get() && maEx.IsEmpty()) 652 { 653 // use maEx as local buffer for rendered svg 654 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); 655 } 656 657 aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx ); 658 659 if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height()) 660 aRetBmpEx.Scale(rParameters.getSizePixel()); 661 } 662 else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() ) 663 { 664 if(maEx.IsEmpty()) 665 { 666 const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) ); 667 668 // use maEx as local buffer for rendered metafile 669 const_cast< ImpGraphic* >(this)->maEx = BitmapEx(ImplGetBitmap(rParameters), aMonoMask.ImplGetBitmap(rParameters)); 670 } 671 672 aRetBmpEx = maEx; 673 } 674 675 return aRetBmpEx; 676 } 677 678 // ------------------------------------------------------------------------ 679 680 Animation ImpGraphic::ImplGetAnimation() const 681 { 682 Animation aAnimation; 683 684 if( mpAnimation ) 685 aAnimation = *mpAnimation; 686 687 return aAnimation; 688 } 689 690 // ------------------------------------------------------------------------ 691 692 const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const 693 { 694 if(GRAPHIC_BITMAP == meType && !maMetaFile.GetActionCount()) 695 { 696 // #119735# 697 // Use the local maMetaFile as container for a metafile-representation 698 // of the bitmap graphic. This will be done only once, thus be buffered. 699 // I checked all usages of maMetaFile, it is only used when type is not 700 // GRAPHIC_BITMAP. In operator= it will get copied, thus buffering will 701 // survive copying (change this if not wanted) 702 ImpGraphic* pThat = const_cast< ImpGraphic* >(this); 703 704 if(maSvgData.get() && !maEx) 705 { 706 // use maEx as local buffer for rendered svg 707 pThat->maEx = maSvgData->getReplacement(); 708 } 709 710 VirtualDevice aVirDev; 711 const Size aSizePixel(maEx.GetSizePixel()); 712 713 pThat->maMetaFile.Record(&aVirDev); 714 715 if(maEx.IsTransparent()) 716 { 717 aVirDev.DrawBitmapEx(Point(), maEx); 718 } 719 else 720 { 721 aVirDev.DrawBitmap(Point(), maEx.GetBitmap()); 722 } 723 724 pThat->maMetaFile.Stop(); 725 pThat->maMetaFile.SetPrefSize(aSizePixel); 726 } 727 728 return maMetaFile; 729 } 730 731 // ------------------------------------------------------------------------ 732 733 Size ImpGraphic::ImplGetPrefSize() const 734 { 735 Size aSize; 736 737 if( ImplIsSwapOut() ) 738 aSize = maSwapInfo.maPrefSize; 739 else 740 { 741 switch( meType ) 742 { 743 case( GRAPHIC_NONE ): 744 case( GRAPHIC_DEFAULT ): 745 break; 746 747 case( GRAPHIC_BITMAP ): 748 { 749 if(maSvgData.get() && maEx.IsEmpty()) 750 { 751 // svg not yet buffered in maEx, return size derived from range 752 const basegfx::B2DRange& rRange = maSvgData->getRange(); 753 754 aSize = Size(basegfx::fround(rRange.getWidth()), basegfx::fround(rRange.getHeight())); 755 } 756 else 757 { 758 aSize = maEx.GetPrefSize(); 759 760 if( !aSize.Width() || !aSize.Height() ) 761 { 762 aSize = maEx.GetSizePixel(); 763 } 764 } 765 } 766 break; 767 768 default: 769 { 770 if( ImplIsSupportedGraphic() ) 771 aSize = maMetaFile.GetPrefSize(); 772 } 773 break; 774 } 775 } 776 777 return aSize; 778 } 779 780 // ------------------------------------------------------------------------ 781 782 void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize ) 783 { 784 switch( meType ) 785 { 786 case( GRAPHIC_NONE ): 787 case( GRAPHIC_DEFAULT ): 788 break; 789 790 case( GRAPHIC_BITMAP ): 791 { 792 // #108077# Push through pref size to animation object, 793 // will be lost on copy otherwise 794 if(maSvgData.get()) 795 { 796 // ignore for Svg. If this is really used (except the grfcache) 797 // it can be extended by using maEx as buffer for maSvgData->getReplacement() 798 } 799 else 800 { 801 if( ImplIsAnimated() ) 802 { 803 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefSize( rPrefSize ); 804 } 805 806 maEx.SetPrefSize( rPrefSize ); 807 } 808 } 809 break; 810 811 default: 812 { 813 if( ImplIsSupportedGraphic() ) 814 maMetaFile.SetPrefSize( rPrefSize ); 815 } 816 break; 817 } 818 } 819 820 // ------------------------------------------------------------------------ 821 822 MapMode ImpGraphic::ImplGetPrefMapMode() const 823 { 824 MapMode aMapMode; 825 826 if( ImplIsSwapOut() ) 827 aMapMode = maSwapInfo.maPrefMapMode; 828 else 829 { 830 switch( meType ) 831 { 832 case( GRAPHIC_NONE ): 833 case( GRAPHIC_DEFAULT ): 834 break; 835 836 case( GRAPHIC_BITMAP ): 837 { 838 if(maSvgData.get() && maEx.IsEmpty()) 839 { 840 // svg not yet buffered in maEx, return default PrefMapMode 841 aMapMode = MapMode(MAP_100TH_MM); 842 } 843 else 844 { 845 const Size aSize( maEx.GetPrefSize() ); 846 847 if ( aSize.Width() && aSize.Height() ) 848 aMapMode = maEx.GetPrefMapMode(); 849 } 850 } 851 break; 852 853 default: 854 { 855 if( ImplIsSupportedGraphic() ) 856 return maMetaFile.GetPrefMapMode(); 857 } 858 break; 859 } 860 } 861 862 return aMapMode; 863 } 864 865 // ------------------------------------------------------------------------ 866 867 void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode ) 868 { 869 switch( meType ) 870 { 871 case( GRAPHIC_NONE ): 872 case( GRAPHIC_DEFAULT ): 873 break; 874 875 case( GRAPHIC_BITMAP ): 876 { 877 if(maSvgData.get()) 878 { 879 // ignore for Svg. If this is really used (except the grfcache) 880 // it can be extended by using maEx as buffer for maSvgData->getReplacement() 881 } 882 else 883 { 884 // #108077# Push through pref mapmode to animation object, 885 // will be lost on copy otherwise 886 if( ImplIsAnimated() ) 887 { 888 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefMapMode( rPrefMapMode ); 889 } 890 891 maEx.SetPrefMapMode( rPrefMapMode ); 892 } 893 } 894 break; 895 896 default: 897 { 898 if( ImplIsSupportedGraphic() ) 899 maMetaFile.SetPrefMapMode( rPrefMapMode ); 900 } 901 break; 902 } 903 } 904 905 // ------------------------------------------------------------------------ 906 907 sal_uLong ImpGraphic::ImplGetSizeBytes() const 908 { 909 if( 0 == mnSizeBytes ) 910 { 911 if( meType == GRAPHIC_BITMAP ) 912 { 913 if(maSvgData.get()) 914 { 915 mnSizeBytes = maSvgData->getSvgDataArrayLength(); 916 } 917 else 918 { 919 mnSizeBytes = mpAnimation ? mpAnimation->GetSizeBytes() : maEx.GetSizeBytes(); 920 } 921 } 922 else if( meType == GRAPHIC_GDIMETAFILE ) 923 { 924 mnSizeBytes = maMetaFile.GetSizeBytes(); 925 } 926 } 927 928 return( mnSizeBytes ); 929 } 930 931 // ------------------------------------------------------------------------ 932 933 void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const 934 { 935 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) 936 { 937 switch( meType ) 938 { 939 case( GRAPHIC_DEFAULT ): 940 break; 941 942 case( GRAPHIC_BITMAP ): 943 { 944 if(maSvgData.get() && !maEx) 945 { 946 // use maEx as local buffer for rendered svg 947 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); 948 } 949 950 if ( mpAnimation ) 951 { 952 mpAnimation->Draw( pOutDev, rDestPt ); 953 } 954 else 955 { 956 maEx.Draw( pOutDev, rDestPt ); 957 } 958 } 959 break; 960 961 default: 962 ImplDraw( pOutDev, rDestPt, maMetaFile.GetPrefSize() ); 963 break; 964 } 965 } 966 } 967 968 // ------------------------------------------------------------------------ 969 970 void ImpGraphic::ImplDraw( OutputDevice* pOutDev, 971 const Point& rDestPt, const Size& rDestSize ) const 972 { 973 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) 974 { 975 switch( meType ) 976 { 977 case( GRAPHIC_DEFAULT ): 978 break; 979 980 case( GRAPHIC_BITMAP ): 981 { 982 if(maSvgData.get() && maEx.IsEmpty()) 983 { 984 // use maEx as local buffer for rendered svg 985 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); 986 } 987 988 if( mpAnimation ) 989 { 990 mpAnimation->Draw( pOutDev, rDestPt, rDestSize ); 991 } 992 else 993 { 994 maEx.Draw( pOutDev, rDestPt, rDestSize ); 995 } 996 } 997 break; 998 999 default: 1000 { 1001 ( (ImpGraphic*) this )->maMetaFile.WindStart(); 1002 ( (ImpGraphic*) this )->maMetaFile.Play( pOutDev, rDestPt, rDestSize ); 1003 ( (ImpGraphic*) this )->maMetaFile.WindStart(); 1004 } 1005 break; 1006 } 1007 } 1008 } 1009 1010 // ------------------------------------------------------------------------ 1011 1012 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, 1013 const Point& rDestPt, 1014 long nExtraData, 1015 OutputDevice* pFirstFrameOutDev ) 1016 { 1017 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation ) 1018 mpAnimation->Start( pOutDev, rDestPt, nExtraData, pFirstFrameOutDev ); 1019 } 1020 1021 // ------------------------------------------------------------------------ 1022 1023 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt, 1024 const Size& rDestSize, long nExtraData, 1025 OutputDevice* pFirstFrameOutDev ) 1026 { 1027 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation ) 1028 mpAnimation->Start( pOutDev, rDestPt, rDestSize, nExtraData, pFirstFrameOutDev ); 1029 } 1030 1031 // ------------------------------------------------------------------------ 1032 1033 void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData ) 1034 { 1035 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation ) 1036 mpAnimation->Stop( pOutDev, nExtraData ); 1037 } 1038 1039 // ------------------------------------------------------------------------ 1040 1041 void ImpGraphic::ImplSetAnimationNotifyHdl( const Link& rLink ) 1042 { 1043 if( mpAnimation ) 1044 mpAnimation->SetNotifyHdl( rLink ); 1045 } 1046 1047 // ------------------------------------------------------------------------ 1048 1049 Link ImpGraphic::ImplGetAnimationNotifyHdl() const 1050 { 1051 Link aLink; 1052 1053 if( mpAnimation ) 1054 aLink = mpAnimation->GetNotifyHdl(); 1055 1056 return aLink; 1057 } 1058 1059 // ------------------------------------------------------------------------ 1060 1061 sal_uLong ImpGraphic::ImplGetAnimationLoopCount() const 1062 { 1063 return( mpAnimation ? mpAnimation->GetLoopCount() : 0UL ); 1064 } 1065 1066 // ------------------------------------------------------------------------ 1067 1068 void ImpGraphic::ImplResetAnimationLoopCount() 1069 { 1070 if( mpAnimation ) 1071 mpAnimation->ResetLoopCount(); 1072 } 1073 1074 // ------------------------------------------------------------------------ 1075 1076 List* ImpGraphic::ImplGetAnimationInfoList() const 1077 { 1078 return( mpAnimation ? mpAnimation->GetAInfoList() : NULL ); 1079 } 1080 1081 // ------------------------------------------------------------------------ 1082 1083 GraphicReader* ImpGraphic::ImplGetContext() 1084 { 1085 return mpContext; 1086 } 1087 1088 // ------------------------------------------------------------------------ 1089 1090 void ImpGraphic::ImplSetContext( GraphicReader* pReader ) 1091 { 1092 mpContext = pReader; 1093 } 1094 1095 // ------------------------------------------------------------------------ 1096 1097 void ImpGraphic::ImplSetDocFileName( const String& rName, sal_uLong nFilePos ) 1098 { 1099 const INetURLObject aURL( rName ); 1100 1101 DBG_ASSERT( !rName.Len() || ( aURL.GetProtocol() != INET_PROT_NOT_VALID ), "Graphic::SetDocFileName(...): invalid URL" ); 1102 1103 maDocFileURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE ); 1104 mnDocFilePos = nFilePos; 1105 } 1106 1107 // ------------------------------------------------------------------------ 1108 1109 const String& ImpGraphic::ImplGetDocFileName() const 1110 { 1111 return maDocFileURLStr; 1112 } 1113 1114 // ------------------------------------------------------------------------ 1115 1116 sal_uLong ImpGraphic::ImplGetDocFilePos() const 1117 { 1118 return mnDocFilePos; 1119 } 1120 1121 // ------------------------------------------------------------------------ 1122 1123 sal_Bool ImpGraphic::ImplReadEmbedded( SvStream& rIStm, sal_Bool bSwap ) 1124 { 1125 MapMode aMapMode; 1126 Size aSize; 1127 const sal_uLong nStartPos = rIStm.Tell(); 1128 sal_uInt32 nId; 1129 sal_uLong nHeaderLen; 1130 long nType; 1131 long nLen; 1132 const sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt(); 1133 sal_Bool bRet = sal_False; 1134 1135 if( !mbSwapUnderway ) 1136 { 1137 const String aTempURLStr( maDocFileURLStr ); 1138 const sal_uLong nTempPos = mnDocFilePos; 1139 1140 ImplClear(); 1141 1142 maDocFileURLStr = aTempURLStr; 1143 mnDocFilePos = nTempPos; 1144 } 1145 1146 rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 1147 rIStm >> nId; 1148 1149 // check version 1150 if( GRAPHIC_FORMAT_50 == nId ) 1151 { 1152 // read new style header 1153 VersionCompat* pCompat = new VersionCompat( rIStm, STREAM_READ ); 1154 1155 rIStm >> nType; 1156 rIStm >> nLen; 1157 rIStm >> aSize; 1158 rIStm >> aMapMode; 1159 1160 delete pCompat; 1161 } 1162 else 1163 { 1164 // read old style header 1165 long nWidth, nHeight; 1166 long nMapMode, nScaleNumX, nScaleDenomX; 1167 long nScaleNumY, nScaleDenomY, nOffsX, nOffsY; 1168 1169 rIStm.SeekRel( -4L ); 1170 1171 rIStm >> nType >> nLen >> nWidth >> nHeight; 1172 rIStm >> nMapMode >> nScaleNumX >> nScaleDenomX >> nScaleNumY; 1173 rIStm >> nScaleDenomY >> nOffsX >> nOffsY; 1174 1175 // swapped 1176 if( nType > 100L ) 1177 { 1178 nType = SWAPLONG( nType ); 1179 nLen = SWAPLONG( nLen ); 1180 nWidth = SWAPLONG( nWidth ); 1181 nHeight = SWAPLONG( nHeight ); 1182 nMapMode = SWAPLONG( nMapMode ); 1183 nScaleNumX = SWAPLONG( nScaleNumX ); 1184 nScaleDenomX = SWAPLONG( nScaleDenomX ); 1185 nScaleNumY = SWAPLONG( nScaleNumY ); 1186 nScaleDenomY = SWAPLONG( nScaleDenomY ); 1187 nOffsX = SWAPLONG( nOffsX ); 1188 nOffsY = SWAPLONG( nOffsY ); 1189 } 1190 1191 aSize = Size( nWidth, nHeight ); 1192 aMapMode = MapMode( (MapUnit) nMapMode, Point( nOffsX, nOffsY ), 1193 Fraction( nScaleNumX, nScaleDenomX ), 1194 Fraction( nScaleNumY, nScaleDenomY ) ); 1195 } 1196 1197 nHeaderLen = rIStm.Tell() - nStartPos; 1198 meType = (GraphicType) nType; 1199 1200 if( meType ) 1201 { 1202 if( meType == GRAPHIC_BITMAP ) 1203 { 1204 if(maSvgData.get() && maEx.IsEmpty()) 1205 { 1206 // use maEx as local buffer for rendered svg 1207 maEx = maSvgData->getReplacement(); 1208 } 1209 1210 maEx.aBitmapSize = aSize; 1211 1212 if( aMapMode != MapMode() ) 1213 { 1214 maEx.SetPrefMapMode( aMapMode ); 1215 maEx.SetPrefSize( aSize ); 1216 } 1217 } 1218 else 1219 { 1220 maMetaFile.SetPrefMapMode( aMapMode ); 1221 maMetaFile.SetPrefSize( aSize ); 1222 } 1223 1224 if( bSwap ) 1225 { 1226 if( maDocFileURLStr.Len() ) 1227 { 1228 rIStm.Seek( nStartPos + nHeaderLen + nLen ); 1229 bRet = mbSwapOut = sal_True; 1230 } 1231 else 1232 { 1233 ::utl::TempFile aTempFile; 1234 const INetURLObject aTmpURL( aTempFile.GetURL() ); 1235 1236 if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) 1237 { 1238 SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); 1239 1240 if( pOStm ) 1241 { 1242 sal_uLong nFullLen = nHeaderLen + nLen; 1243 sal_uLong nPartLen = Min( nFullLen, (sal_uLong) GRAPHIC_MAXPARTLEN ); 1244 sal_uInt8* pBuffer = (sal_uInt8*) rtl_allocateMemory( nPartLen ); 1245 1246 pOStm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 1247 1248 if( pBuffer ) 1249 { 1250 rIStm.Seek( nStartPos ); 1251 1252 while( nFullLen ) 1253 { 1254 rIStm.Read( (char*) pBuffer, nPartLen ); 1255 pOStm->Write( (char*) pBuffer, nPartLen ); 1256 1257 nFullLen -= nPartLen; 1258 1259 if( nFullLen < GRAPHIC_MAXPARTLEN ) 1260 nPartLen = nFullLen; 1261 } 1262 1263 rtl_freeMemory( pBuffer ); 1264 sal_uLong nReadErr = rIStm.GetError(), nWriteErr = pOStm->GetError(); 1265 delete pOStm, pOStm = NULL; 1266 1267 if( !nReadErr && !nWriteErr ) 1268 { 1269 bRet = mbSwapOut = sal_True; 1270 mpSwapFile = new ImpSwapFile; 1271 mpSwapFile->nRefCount = 1; 1272 mpSwapFile->aSwapURL = aTmpURL; 1273 } 1274 else 1275 { 1276 try 1277 { 1278 ::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), 1279 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); 1280 1281 aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), 1282 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); 1283 } 1284 catch( const ::com::sun::star::ucb::ContentCreationException& ) 1285 { 1286 } 1287 catch( const ::com::sun::star::uno::RuntimeException& ) 1288 { 1289 } 1290 catch( const ::com::sun::star::ucb::CommandAbortedException& ) 1291 { 1292 } 1293 catch( const ::com::sun::star::uno::Exception& ) 1294 { 1295 } 1296 } 1297 } 1298 1299 delete pOStm; 1300 } 1301 } 1302 } 1303 } 1304 else if( meType == GRAPHIC_BITMAP || meType == GRAPHIC_GDIMETAFILE ) 1305 { 1306 rIStm >> *this; 1307 bRet = ( rIStm.GetError() == 0UL ); 1308 } 1309 else if( meType >= SYS_WINMETAFILE && meType <= SYS_MACMETAFILE ) 1310 { 1311 Graphic aSysGraphic; 1312 sal_uLong nCvtType; 1313 1314 switch( sal::static_int_cast<sal_uLong>(meType) ) 1315 { 1316 case( SYS_WINMETAFILE ): 1317 case( SYS_WNTMETAFILE ): nCvtType = CVT_WMF; break; 1318 case( SYS_OS2METAFILE ): nCvtType = CVT_MET; break; 1319 case( SYS_MACMETAFILE ): nCvtType = CVT_PCT; break; 1320 1321 default: 1322 nCvtType = CVT_UNKNOWN; 1323 break; 1324 } 1325 1326 if( nType && GraphicConverter::Import( rIStm, aSysGraphic, nCvtType ) == ERRCODE_NONE ) 1327 { 1328 *this = ImpGraphic( aSysGraphic.GetGDIMetaFile() ); 1329 bRet = ( rIStm.GetError() == 0UL ); 1330 } 1331 else 1332 meType = GRAPHIC_DEFAULT; 1333 } 1334 1335 if( bRet ) 1336 { 1337 ImplSetPrefMapMode( aMapMode ); 1338 ImplSetPrefSize( aSize ); 1339 } 1340 } 1341 else 1342 bRet = sal_True; 1343 1344 rIStm.SetNumberFormatInt( nOldFormat ); 1345 1346 return bRet; 1347 } 1348 1349 // ------------------------------------------------------------------------ 1350 1351 sal_Bool ImpGraphic::ImplWriteEmbedded( SvStream& rOStm ) 1352 { 1353 sal_Bool bRet = sal_False; 1354 1355 if( ( meType != GRAPHIC_NONE ) && ( meType != GRAPHIC_DEFAULT ) && !ImplIsSwapOut() ) 1356 { 1357 const MapMode aMapMode( ImplGetPrefMapMode() ); 1358 const Size aSize( ImplGetPrefSize() ); 1359 const sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt(); 1360 sal_uLong nDataFieldPos; 1361 1362 rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 1363 1364 // write correct version ( old style/new style header ) 1365 if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) 1366 { 1367 // write ID for new format (5.0) 1368 rOStm << GRAPHIC_FORMAT_50; 1369 1370 // write new style header 1371 VersionCompat* pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 ); 1372 1373 rOStm << (long) meType; 1374 1375 // data size is updated later 1376 nDataFieldPos = rOStm.Tell(); 1377 rOStm << (long) 0; 1378 1379 rOStm << aSize; 1380 rOStm << aMapMode; 1381 1382 delete pCompat; 1383 } 1384 else 1385 { 1386 // write old style (<=4.0) header 1387 rOStm << (long) meType; 1388 1389 // data size is updated later 1390 nDataFieldPos = rOStm.Tell(); 1391 rOStm << (long) 0; 1392 1393 rOStm << (long) aSize.Width(); 1394 rOStm << (long) aSize.Height(); 1395 rOStm << (long) aMapMode.GetMapUnit(); 1396 rOStm << (long) aMapMode.GetScaleX().GetNumerator(); 1397 rOStm << (long) aMapMode.GetScaleX().GetDenominator(); 1398 rOStm << (long) aMapMode.GetScaleY().GetNumerator(); 1399 rOStm << (long) aMapMode.GetScaleY().GetDenominator(); 1400 rOStm << (long) aMapMode.GetOrigin().X(); 1401 rOStm << (long) aMapMode.GetOrigin().Y(); 1402 } 1403 1404 // write data block 1405 if( !rOStm.GetError() ) 1406 { 1407 const sal_uLong nDataStart = rOStm.Tell(); 1408 1409 if( ImplIsSupportedGraphic() ) 1410 rOStm << *this; 1411 1412 if( !rOStm.GetError() ) 1413 { 1414 const sal_uLong nStmPos2 = rOStm.Tell(); 1415 rOStm.Seek( nDataFieldPos ); 1416 rOStm << (long) ( nStmPos2 - nDataStart ); 1417 rOStm.Seek( nStmPos2 ); 1418 bRet = sal_True; 1419 } 1420 } 1421 1422 rOStm.SetNumberFormatInt( nOldFormat ); 1423 } 1424 1425 return bRet; 1426 } 1427 1428 // ------------------------------------------------------------------------ 1429 1430 sal_Bool ImpGraphic::ImplSwapOut() 1431 { 1432 sal_Bool bRet = sal_False; 1433 1434 if( !ImplIsSwapOut() ) 1435 { 1436 if( !maDocFileURLStr.Len() ) 1437 { 1438 ::utl::TempFile aTempFile; 1439 const INetURLObject aTmpURL( aTempFile.GetURL() ); 1440 1441 if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) 1442 { 1443 SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); 1444 1445 if( pOStm ) 1446 { 1447 pOStm->SetVersion( SOFFICE_FILEFORMAT_50 ); 1448 pOStm->SetCompressMode( COMPRESSMODE_NATIVE ); 1449 1450 if( ( bRet = ImplSwapOut( pOStm ) ) == sal_True ) 1451 { 1452 mpSwapFile = new ImpSwapFile; 1453 mpSwapFile->nRefCount = 1; 1454 mpSwapFile->aSwapURL = aTmpURL; 1455 } 1456 else 1457 { 1458 delete pOStm, pOStm = NULL; 1459 1460 try 1461 { 1462 ::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), 1463 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); 1464 1465 aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), 1466 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); 1467 } 1468 catch( const ::com::sun::star::ucb::ContentCreationException& ) 1469 { 1470 } 1471 catch( const ::com::sun::star::uno::RuntimeException& ) 1472 { 1473 } 1474 catch( const ::com::sun::star::ucb::CommandAbortedException& ) 1475 { 1476 } 1477 catch( const ::com::sun::star::uno::Exception& ) 1478 { 1479 } 1480 } 1481 1482 delete pOStm; 1483 } 1484 } 1485 } 1486 else 1487 { 1488 ImplClearGraphics( sal_True ); 1489 bRet = mbSwapOut = sal_True; 1490 } 1491 } 1492 1493 return bRet; 1494 } 1495 1496 // ------------------------------------------------------------------------ 1497 1498 sal_Bool ImpGraphic::ImplSwapOut( SvStream* pOStm ) 1499 { 1500 sal_Bool bRet = sal_False; 1501 1502 if( pOStm ) 1503 { 1504 pOStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE ); 1505 1506 if( !pOStm->GetError() && ImplWriteEmbedded( *pOStm ) ) 1507 { 1508 pOStm->Flush(); 1509 1510 if( !pOStm->GetError() ) 1511 { 1512 ImplClearGraphics( sal_True ); 1513 bRet = mbSwapOut = sal_True; 1514 } 1515 } 1516 } 1517 else 1518 { 1519 ImplClearGraphics( sal_True ); 1520 bRet = mbSwapOut = sal_True; 1521 } 1522 1523 return bRet; 1524 } 1525 1526 // ------------------------------------------------------------------------ 1527 1528 sal_Bool ImpGraphic::ImplSwapIn() 1529 { 1530 sal_Bool bRet = sal_False; 1531 1532 if( ImplIsSwapOut() ) 1533 { 1534 String aSwapURL; 1535 1536 if( mpSwapFile ) 1537 aSwapURL = mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE ); 1538 else 1539 aSwapURL = maDocFileURLStr; 1540 1541 if( aSwapURL.Len() ) 1542 { 1543 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aSwapURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); 1544 1545 if( pIStm ) 1546 { 1547 pIStm->SetVersion( SOFFICE_FILEFORMAT_50 ); 1548 pIStm->SetCompressMode( COMPRESSMODE_NATIVE ); 1549 1550 if( !mpSwapFile ) 1551 pIStm->Seek( mnDocFilePos ); 1552 1553 bRet = ImplSwapIn( pIStm ); 1554 delete pIStm; 1555 1556 if( mpSwapFile ) 1557 { 1558 if( mpSwapFile->nRefCount > 1 ) 1559 mpSwapFile->nRefCount--; 1560 else 1561 { 1562 try 1563 { 1564 ::ucbhelper::Content aCnt( aSwapURL, 1565 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); 1566 1567 aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), 1568 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); 1569 } 1570 catch( const ::com::sun::star::ucb::ContentCreationException& ) 1571 { 1572 } 1573 catch( const ::com::sun::star::uno::RuntimeException& ) 1574 { 1575 } 1576 catch( const ::com::sun::star::ucb::CommandAbortedException& ) 1577 { 1578 } 1579 catch( const ::com::sun::star::uno::Exception& ) 1580 { 1581 } 1582 1583 delete mpSwapFile; 1584 } 1585 1586 mpSwapFile = NULL; 1587 } 1588 } 1589 } 1590 } 1591 1592 return bRet; 1593 } 1594 1595 // ------------------------------------------------------------------------ 1596 1597 sal_Bool ImpGraphic::ImplSwapIn( SvStream* pIStm ) 1598 { 1599 sal_Bool bRet = sal_False; 1600 1601 if( pIStm ) 1602 { 1603 pIStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE ); 1604 1605 if( !pIStm->GetError() ) 1606 { 1607 mbSwapUnderway = sal_True; 1608 bRet = ImplReadEmbedded( *pIStm ); 1609 mbSwapUnderway = sal_False; 1610 1611 if( !bRet ) 1612 ImplClear(); 1613 else 1614 mbSwapOut = sal_False; 1615 } 1616 } 1617 1618 return bRet; 1619 } 1620 1621 // ------------------------------------------------------------------------ 1622 1623 sal_Bool ImpGraphic::ImplIsSwapOut() const 1624 { 1625 return mbSwapOut; 1626 } 1627 1628 // ------------------------------------------------------------------------ 1629 1630 void ImpGraphic::ImplSetLink( const GfxLink& rGfxLink ) 1631 { 1632 delete mpGfxLink; 1633 mpGfxLink = new GfxLink( rGfxLink ); 1634 1635 if( mpGfxLink->IsNative() ) 1636 mpGfxLink->SwapOut(); 1637 } 1638 1639 // ------------------------------------------------------------------------ 1640 1641 GfxLink ImpGraphic::ImplGetLink() 1642 { 1643 return( mpGfxLink ? *mpGfxLink : GfxLink() ); 1644 } 1645 1646 // ------------------------------------------------------------------------ 1647 1648 sal_Bool ImpGraphic::ImplIsLink() const 1649 { 1650 return ( mpGfxLink != NULL ) ? sal_True : sal_False; 1651 } 1652 1653 // ------------------------------------------------------------------------ 1654 1655 sal_uLong ImpGraphic::ImplGetChecksum() const 1656 { 1657 sal_uLong nRet = 0; 1658 1659 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) 1660 { 1661 switch( meType ) 1662 { 1663 case( GRAPHIC_DEFAULT ): 1664 break; 1665 1666 case( GRAPHIC_BITMAP ): 1667 { 1668 if(maSvgData.get() && maEx.IsEmpty()) 1669 { 1670 // use maEx as local buffer for rendered svg 1671 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); 1672 } 1673 1674 if( mpAnimation ) 1675 { 1676 nRet = mpAnimation->GetChecksum(); 1677 } 1678 else 1679 { 1680 nRet = maEx.GetChecksum(); 1681 } 1682 } 1683 break; 1684 1685 default: 1686 nRet = maMetaFile.GetChecksum(); 1687 break; 1688 } 1689 } 1690 1691 return nRet; 1692 } 1693 1694 // ------------------------------------------------------------------------ 1695 1696 sal_Bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const 1697 { 1698 sal_Bool bResult = sal_False; 1699 1700 if( !rOStm.GetError() ) 1701 { 1702 if( !ImplIsSwapOut() ) 1703 { 1704 if( mpGfxLink && mpGfxLink->IsNative() ) 1705 bResult = mpGfxLink->ExportNative( rOStm ); 1706 else 1707 { 1708 rOStm << *this; 1709 bResult = ( rOStm.GetError() == ERRCODE_NONE ); 1710 } 1711 } 1712 else 1713 rOStm.SetError( SVSTREAM_GENERALERROR ); 1714 } 1715 1716 return bResult; 1717 } 1718 1719 // ------------------------------------------------------------------------ 1720 1721 const SvgDataPtr& ImpGraphic::getSvgData() const 1722 { 1723 return maSvgData; 1724 } 1725 1726 // ------------------------------------------------------------------------ 1727 1728 SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic ) 1729 { 1730 if( !rIStm.GetError() ) 1731 { 1732 const sal_uLong nStmPos1 = rIStm.Tell(); 1733 sal_uInt32 nTmp; 1734 1735 if ( !rImpGraphic.mbSwapUnderway ) 1736 rImpGraphic.ImplClear(); 1737 1738 // read Id 1739 rIStm >> nTmp; 1740 1741 // if there is no more data, avoid further expensive 1742 // reading which will create VDevs and other stuff, just to 1743 // read nothing. CAUTION: Eof is only true AFTER reading another 1744 // byte, a speciality of SvMemoryStream (!) 1745 if(!rIStm.GetError() && !rIStm.IsEof()) 1746 { 1747 if( NATIVE_FORMAT_50 == nTmp ) 1748 { 1749 Graphic aGraphic; 1750 GfxLink aLink; 1751 VersionCompat* pCompat; 1752 1753 // read compat info 1754 pCompat = new VersionCompat( rIStm, STREAM_READ ); 1755 delete pCompat; 1756 1757 rIStm >> aLink; 1758 1759 // set dummy link to avoid creation of additional link after filtering; 1760 // we set a default link to avoid unnecessary swapping of native data 1761 aGraphic.SetLink( GfxLink() ); 1762 1763 if( !rIStm.GetError() && aLink.LoadNative( aGraphic ) ) 1764 { 1765 // set link only, if no other link was set 1766 const sal_Bool bSetLink = ( rImpGraphic.mpGfxLink == NULL ); 1767 1768 // assign graphic 1769 rImpGraphic = *aGraphic.ImplGetImpGraphic(); 1770 1771 if( aLink.IsPrefMapModeValid() ) 1772 rImpGraphic.ImplSetPrefMapMode( aLink.GetPrefMapMode() ); 1773 1774 if( aLink.IsPrefSizeValid() ) 1775 rImpGraphic.ImplSetPrefSize( aLink.GetPrefSize() ); 1776 1777 if( bSetLink ) 1778 rImpGraphic.ImplSetLink( aLink ); 1779 } 1780 else 1781 { 1782 rIStm.Seek( nStmPos1 ); 1783 rIStm.SetError( ERRCODE_IO_WRONGFORMAT ); 1784 } 1785 } 1786 else 1787 { 1788 BitmapEx aBmpEx; 1789 const sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt(); 1790 1791 rIStm.SeekRel( -4 ); 1792 rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 1793 rIStm >> aBmpEx; 1794 1795 if( !rIStm.GetError() ) 1796 { 1797 sal_uInt32 nMagic1(0), nMagic2(0); 1798 sal_uLong nActPos = rIStm.Tell(); 1799 1800 rIStm >> nMagic1 >> nMagic2; 1801 rIStm.Seek( nActPos ); 1802 1803 rImpGraphic = ImpGraphic( aBmpEx ); 1804 1805 if( !rIStm.GetError() && ( 0x5344414e == nMagic1 ) && ( 0x494d4931 == nMagic2 ) ) 1806 { 1807 delete rImpGraphic.mpAnimation; 1808 rImpGraphic.mpAnimation = new Animation; 1809 rIStm >> *rImpGraphic.mpAnimation; 1810 1811 // #108077# manually set loaded BmpEx to Animation 1812 // (which skips loading its BmpEx if already done) 1813 rImpGraphic.mpAnimation->SetBitmapEx(aBmpEx); 1814 } 1815 else 1816 rIStm.ResetError(); 1817 } 1818 else 1819 { 1820 GDIMetaFile aMtf; 1821 1822 rIStm.Seek( nStmPos1 ); 1823 rIStm.ResetError(); 1824 rIStm >> aMtf; 1825 1826 if( !rIStm.GetError() ) 1827 { 1828 rImpGraphic = aMtf; 1829 } 1830 else 1831 { 1832 // try to stream in Svg defining data (length, byte array and evtl. path) 1833 // See below (operator<<) for more information 1834 const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0')); 1835 sal_uInt32 nMagic; 1836 rIStm.Seek(nStmPos1); 1837 rIStm.ResetError(); 1838 rIStm >> nMagic; 1839 1840 if(nSvgMagic == nMagic) 1841 { 1842 sal_uInt32 mnSvgDataArrayLength(0); 1843 rIStm >> mnSvgDataArrayLength; 1844 1845 if(mnSvgDataArrayLength) 1846 { 1847 SvgDataArray aNewData(new sal_uInt8[mnSvgDataArrayLength]); 1848 UniString aPath; 1849 1850 rIStm.Read(aNewData.get(), mnSvgDataArrayLength); 1851 rIStm.ReadByteString(aPath); 1852 1853 if(!rIStm.GetError()) 1854 { 1855 SvgDataPtr aSvgDataPtr( 1856 new SvgData( 1857 aNewData, 1858 mnSvgDataArrayLength, 1859 rtl::OUString(aPath))); 1860 1861 rImpGraphic = aSvgDataPtr; 1862 } 1863 } 1864 } 1865 1866 rIStm.Seek(nStmPos1); 1867 } 1868 } 1869 1870 rIStm.SetNumberFormatInt( nOldFormat ); 1871 } 1872 } 1873 } 1874 1875 return rIStm; 1876 } 1877 1878 // ------------------------------------------------------------------------ 1879 1880 SvStream& operator<<( SvStream& rOStm, const ImpGraphic& rImpGraphic ) 1881 { 1882 if( !rOStm.GetError() ) 1883 { 1884 if( !rImpGraphic.ImplIsSwapOut() ) 1885 { 1886 if( ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) && 1887 ( rOStm.GetCompressMode() & COMPRESSMODE_NATIVE ) && 1888 rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative() ) 1889 { 1890 VersionCompat* pCompat; 1891 1892 // native format 1893 rOStm << NATIVE_FORMAT_50; 1894 1895 // write compat info 1896 pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 ); 1897 delete pCompat; 1898 1899 rImpGraphic.mpGfxLink->SetPrefMapMode( rImpGraphic.ImplGetPrefMapMode() ); 1900 rImpGraphic.mpGfxLink->SetPrefSize( rImpGraphic.ImplGetPrefSize() ); 1901 rOStm << *rImpGraphic.mpGfxLink; 1902 } 1903 else 1904 { 1905 // own format 1906 const sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt(); 1907 rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 1908 1909 switch( rImpGraphic.ImplGetType() ) 1910 { 1911 case( GRAPHIC_NONE ): 1912 case( GRAPHIC_DEFAULT ): 1913 break; 1914 1915 case GRAPHIC_BITMAP: 1916 { 1917 if(rImpGraphic.getSvgData().get()) 1918 { 1919 // stream out Svg defining data (length, byte array and evtl. path) 1920 // this is used e.g. in swapping out graphic data and in transporting it over UNO API 1921 // as sequence of bytes, but AFAIK not written anywhere to any kind of file, so it should be 1922 // no problem to extend it; only used at runtime 1923 const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0')); 1924 1925 rOStm << nSvgMagic; 1926 rOStm << rImpGraphic.getSvgData()->getSvgDataArrayLength(); 1927 rOStm.Write(rImpGraphic.getSvgData()->getSvgDataArray().get(), rImpGraphic.getSvgData()->getSvgDataArrayLength()); 1928 rOStm.WriteByteString(rImpGraphic.getSvgData()->getPath()); 1929 } 1930 else if( rImpGraphic.ImplIsAnimated()) 1931 { 1932 rOStm << *rImpGraphic.mpAnimation; 1933 } 1934 else 1935 { 1936 rOStm << rImpGraphic.maEx; 1937 } 1938 } 1939 break; 1940 1941 default: 1942 { 1943 if( rImpGraphic.ImplIsSupportedGraphic() ) 1944 rOStm << rImpGraphic.maMetaFile; 1945 } 1946 break; 1947 } 1948 1949 rOStm.SetNumberFormatInt( nOldFormat ); 1950 } 1951 } 1952 else 1953 rOStm.SetError( SVSTREAM_GENERALERROR ); 1954 } 1955 1956 return rOStm; 1957 } 1958