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