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 // calculate size 558 VirtualDevice aVDev; 559 Size aDrawSize(aVDev.LogicToPixel(maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode())); 560 561 if(rParameters.getSizePixel().Width() && rParameters.getSizePixel().Height()) 562 { 563 // apply given size if exists 564 aDrawSize = rParameters.getSizePixel(); 565 } 566 567 if(aDrawSize.Width() && aDrawSize.Height() && !rParameters.getUnlimitedSize() 568 && (aDrawSize.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aDrawSize.Height() > GRAPHIC_MTFTOBMP_MAXEXT)) 569 { 570 // limit bitmap size to a maximum of GRAPHIC_MTFTOBMP_MAXEXT x GRAPHIC_MTFTOBMP_MAXEXT 571 double fWH((double)aDrawSize.Width() / (double)aDrawSize.Height()); 572 573 if(fWH <= 1.0) 574 { 575 aDrawSize.setWidth(basegfx::fround(GRAPHIC_MTFTOBMP_MAXEXT * fWH)); 576 aDrawSize.setHeight(GRAPHIC_MTFTOBMP_MAXEXT); 577 } 578 else 579 { 580 aDrawSize.setWidth(GRAPHIC_MTFTOBMP_MAXEXT); 581 aDrawSize.setHeight(basegfx::fround(GRAPHIC_MTFTOBMP_MAXEXT / fWH)); 582 } 583 } 584 585 // calculate pixel size. Normally, it's the same as aDrawSize, but may 586 // need to be extended when hairlines are on the right or bottom edge 587 Size aPixelSize(aDrawSize); 588 589 if(GRAPHIC_GDIMETAFILE == ImplGetType()) 590 { 591 // get hairline and full bound rect 592 Rectangle aHairlineRect; 593 const Rectangle aRect(maMetaFile.GetBoundRect(aVDev, &aHairlineRect)); 594 595 if(!aRect.IsEmpty() && !aHairlineRect.IsEmpty()) 596 { 597 // expand if needed to allow bottom and right hairlines to be added 598 if(aRect.Right() == aHairlineRect.Right()) 599 { 600 aPixelSize.setWidth(aPixelSize.getWidth() + 1); 601 } 602 603 if(aRect.Bottom() == aHairlineRect.Bottom()) 604 { 605 aPixelSize.setHeight(aPixelSize.getHeight() + 1); 606 } 607 } 608 } 609 610 if(aVDev.SetOutputSizePixel(aPixelSize)) 611 { 612 if(rParameters.getAntiAliase()) 613 { 614 aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW); 615 } 616 617 if(rParameters.getSnapHorVerLines()) 618 { 619 aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_PIXELSNAPHAIRLINE); 620 } 621 622 ImplDraw( &aVDev, Point(), aDrawSize ); 623 aRetBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() ); 624 } 625 } 626 627 if( !!aRetBmp ) 628 { 629 aRetBmp.SetPrefMapMode( ImplGetPrefMapMode() ); 630 aRetBmp.SetPrefSize( ImplGetPrefSize() ); 631 } 632 633 return aRetBmp; 634 } 635 636 // ------------------------------------------------------------------------ 637 638 BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const 639 { 640 BitmapEx aRetBmpEx; 641 642 if( meType == GRAPHIC_BITMAP ) 643 { 644 if(maSvgData.get() && maEx.IsEmpty()) 645 { 646 // use maEx as local buffer for rendered svg 647 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); 648 } 649 650 aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx ); 651 652 if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height()) 653 aRetBmpEx.Scale(rParameters.getSizePixel()); 654 } 655 else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() ) 656 { 657 const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) ); 658 aRetBmpEx = BitmapEx(ImplGetBitmap(rParameters), aMonoMask.ImplGetBitmap(rParameters)); 659 } 660 661 return aRetBmpEx; 662 } 663 664 // ------------------------------------------------------------------------ 665 666 Animation ImpGraphic::ImplGetAnimation() const 667 { 668 Animation aAnimation; 669 670 if( mpAnimation ) 671 aAnimation = *mpAnimation; 672 673 return aAnimation; 674 } 675 676 // ------------------------------------------------------------------------ 677 678 const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const 679 { 680 return maMetaFile; 681 } 682 683 // ------------------------------------------------------------------------ 684 685 Size ImpGraphic::ImplGetPrefSize() const 686 { 687 Size aSize; 688 689 if( ImplIsSwapOut() ) 690 aSize = maSwapInfo.maPrefSize; 691 else 692 { 693 switch( meType ) 694 { 695 case( GRAPHIC_NONE ): 696 case( GRAPHIC_DEFAULT ): 697 break; 698 699 case( GRAPHIC_BITMAP ): 700 { 701 if(maSvgData.get() && maEx.IsEmpty()) 702 { 703 // svg not yet buffered in maEx, return size derived from range 704 const basegfx::B2DRange& rRange = maSvgData->getRange(); 705 706 aSize = Size(basegfx::fround(rRange.getWidth()), basegfx::fround(rRange.getHeight())); 707 } 708 else 709 { 710 aSize = maEx.GetPrefSize(); 711 712 if( !aSize.Width() || !aSize.Height() ) 713 { 714 aSize = maEx.GetSizePixel(); 715 } 716 } 717 } 718 break; 719 720 default: 721 { 722 if( ImplIsSupportedGraphic() ) 723 aSize = maMetaFile.GetPrefSize(); 724 } 725 break; 726 } 727 } 728 729 return aSize; 730 } 731 732 // ------------------------------------------------------------------------ 733 734 void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize ) 735 { 736 switch( meType ) 737 { 738 case( GRAPHIC_NONE ): 739 case( GRAPHIC_DEFAULT ): 740 break; 741 742 case( GRAPHIC_BITMAP ): 743 { 744 // #108077# Push through pref size to animation object, 745 // will be lost on copy otherwise 746 if(maSvgData.get()) 747 { 748 // ignore for Svg. If this is really used (except the grfcache) 749 // it can be extended by using maEx as buffer for maSvgData->getReplacement() 750 } 751 else 752 { 753 if( ImplIsAnimated() ) 754 { 755 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefSize( rPrefSize ); 756 } 757 758 maEx.SetPrefSize( rPrefSize ); 759 } 760 } 761 break; 762 763 default: 764 { 765 if( ImplIsSupportedGraphic() ) 766 maMetaFile.SetPrefSize( rPrefSize ); 767 } 768 break; 769 } 770 } 771 772 // ------------------------------------------------------------------------ 773 774 MapMode ImpGraphic::ImplGetPrefMapMode() const 775 { 776 MapMode aMapMode; 777 778 if( ImplIsSwapOut() ) 779 aMapMode = maSwapInfo.maPrefMapMode; 780 else 781 { 782 switch( meType ) 783 { 784 case( GRAPHIC_NONE ): 785 case( GRAPHIC_DEFAULT ): 786 break; 787 788 case( GRAPHIC_BITMAP ): 789 { 790 if(maSvgData.get() && maEx.IsEmpty()) 791 { 792 // svg not yet buffered in maEx, return default PrefMapMode 793 aMapMode = MapMode(MAP_100TH_MM); 794 } 795 else 796 { 797 const Size aSize( maEx.GetPrefSize() ); 798 799 if ( aSize.Width() && aSize.Height() ) 800 aMapMode = maEx.GetPrefMapMode(); 801 } 802 } 803 break; 804 805 default: 806 { 807 if( ImplIsSupportedGraphic() ) 808 return maMetaFile.GetPrefMapMode(); 809 } 810 break; 811 } 812 } 813 814 return aMapMode; 815 } 816 817 // ------------------------------------------------------------------------ 818 819 void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode ) 820 { 821 switch( meType ) 822 { 823 case( GRAPHIC_NONE ): 824 case( GRAPHIC_DEFAULT ): 825 break; 826 827 case( GRAPHIC_BITMAP ): 828 { 829 if(maSvgData.get()) 830 { 831 // ignore for Svg. If this is really used (except the grfcache) 832 // it can be extended by using maEx as buffer for maSvgData->getReplacement() 833 } 834 else 835 { 836 // #108077# Push through pref mapmode to animation object, 837 // will be lost on copy otherwise 838 if( ImplIsAnimated() ) 839 { 840 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefMapMode( rPrefMapMode ); 841 } 842 843 maEx.SetPrefMapMode( rPrefMapMode ); 844 } 845 } 846 break; 847 848 default: 849 { 850 if( ImplIsSupportedGraphic() ) 851 maMetaFile.SetPrefMapMode( rPrefMapMode ); 852 } 853 break; 854 } 855 } 856 857 // ------------------------------------------------------------------------ 858 859 sal_uLong ImpGraphic::ImplGetSizeBytes() const 860 { 861 if( 0 == mnSizeBytes ) 862 { 863 if( meType == GRAPHIC_BITMAP ) 864 { 865 if(maSvgData.get()) 866 { 867 mnSizeBytes = maSvgData->getSvgDataArrayLength(); 868 } 869 else 870 { 871 mnSizeBytes = mpAnimation ? mpAnimation->GetSizeBytes() : maEx.GetSizeBytes(); 872 } 873 } 874 else if( meType == GRAPHIC_GDIMETAFILE ) 875 { 876 mnSizeBytes = maMetaFile.GetSizeBytes(); 877 } 878 } 879 880 return( mnSizeBytes ); 881 } 882 883 // ------------------------------------------------------------------------ 884 885 void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const 886 { 887 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) 888 { 889 switch( meType ) 890 { 891 case( GRAPHIC_DEFAULT ): 892 break; 893 894 case( GRAPHIC_BITMAP ): 895 { 896 if(maSvgData.get() && !maEx) 897 { 898 // use maEx as local buffer for rendered svg 899 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); 900 } 901 902 if ( mpAnimation ) 903 { 904 mpAnimation->Draw( pOutDev, rDestPt ); 905 } 906 else 907 { 908 maEx.Draw( pOutDev, rDestPt ); 909 } 910 } 911 break; 912 913 default: 914 ImplDraw( pOutDev, rDestPt, maMetaFile.GetPrefSize() ); 915 break; 916 } 917 } 918 } 919 920 // ------------------------------------------------------------------------ 921 922 void ImpGraphic::ImplDraw( OutputDevice* pOutDev, 923 const Point& rDestPt, const Size& rDestSize ) const 924 { 925 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) 926 { 927 switch( meType ) 928 { 929 case( GRAPHIC_DEFAULT ): 930 break; 931 932 case( GRAPHIC_BITMAP ): 933 { 934 if(maSvgData.get() && maEx.IsEmpty()) 935 { 936 // use maEx as local buffer for rendered svg 937 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); 938 } 939 940 if( mpAnimation ) 941 { 942 mpAnimation->Draw( pOutDev, rDestPt, rDestSize ); 943 } 944 else 945 { 946 maEx.Draw( pOutDev, rDestPt, rDestSize ); 947 } 948 } 949 break; 950 951 default: 952 { 953 ( (ImpGraphic*) this )->maMetaFile.WindStart(); 954 ( (ImpGraphic*) this )->maMetaFile.Play( pOutDev, rDestPt, rDestSize ); 955 ( (ImpGraphic*) this )->maMetaFile.WindStart(); 956 } 957 break; 958 } 959 } 960 } 961 962 // ------------------------------------------------------------------------ 963 964 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, 965 const Point& rDestPt, 966 long nExtraData, 967 OutputDevice* pFirstFrameOutDev ) 968 { 969 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation ) 970 mpAnimation->Start( pOutDev, rDestPt, nExtraData, pFirstFrameOutDev ); 971 } 972 973 // ------------------------------------------------------------------------ 974 975 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt, 976 const Size& rDestSize, long nExtraData, 977 OutputDevice* pFirstFrameOutDev ) 978 { 979 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation ) 980 mpAnimation->Start( pOutDev, rDestPt, rDestSize, nExtraData, pFirstFrameOutDev ); 981 } 982 983 // ------------------------------------------------------------------------ 984 985 void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData ) 986 { 987 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation ) 988 mpAnimation->Stop( pOutDev, nExtraData ); 989 } 990 991 // ------------------------------------------------------------------------ 992 993 void ImpGraphic::ImplSetAnimationNotifyHdl( const Link& rLink ) 994 { 995 if( mpAnimation ) 996 mpAnimation->SetNotifyHdl( rLink ); 997 } 998 999 // ------------------------------------------------------------------------ 1000 1001 Link ImpGraphic::ImplGetAnimationNotifyHdl() const 1002 { 1003 Link aLink; 1004 1005 if( mpAnimation ) 1006 aLink = mpAnimation->GetNotifyHdl(); 1007 1008 return aLink; 1009 } 1010 1011 // ------------------------------------------------------------------------ 1012 1013 sal_uLong ImpGraphic::ImplGetAnimationLoopCount() const 1014 { 1015 return( mpAnimation ? mpAnimation->GetLoopCount() : 0UL ); 1016 } 1017 1018 // ------------------------------------------------------------------------ 1019 1020 void ImpGraphic::ImplResetAnimationLoopCount() 1021 { 1022 if( mpAnimation ) 1023 mpAnimation->ResetLoopCount(); 1024 } 1025 1026 // ------------------------------------------------------------------------ 1027 1028 List* ImpGraphic::ImplGetAnimationInfoList() const 1029 { 1030 return( mpAnimation ? mpAnimation->GetAInfoList() : NULL ); 1031 } 1032 1033 // ------------------------------------------------------------------------ 1034 1035 GraphicReader* ImpGraphic::ImplGetContext() 1036 { 1037 return mpContext; 1038 } 1039 1040 // ------------------------------------------------------------------------ 1041 1042 void ImpGraphic::ImplSetContext( GraphicReader* pReader ) 1043 { 1044 mpContext = pReader; 1045 } 1046 1047 // ------------------------------------------------------------------------ 1048 1049 void ImpGraphic::ImplSetDocFileName( const String& rName, sal_uLong nFilePos ) 1050 { 1051 const INetURLObject aURL( rName ); 1052 1053 DBG_ASSERT( !rName.Len() || ( aURL.GetProtocol() != INET_PROT_NOT_VALID ), "Graphic::SetDocFileName(...): invalid URL" ); 1054 1055 maDocFileURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE ); 1056 mnDocFilePos = nFilePos; 1057 } 1058 1059 // ------------------------------------------------------------------------ 1060 1061 const String& ImpGraphic::ImplGetDocFileName() const 1062 { 1063 return maDocFileURLStr; 1064 } 1065 1066 // ------------------------------------------------------------------------ 1067 1068 sal_uLong ImpGraphic::ImplGetDocFilePos() const 1069 { 1070 return mnDocFilePos; 1071 } 1072 1073 // ------------------------------------------------------------------------ 1074 1075 sal_Bool ImpGraphic::ImplReadEmbedded( SvStream& rIStm, sal_Bool bSwap ) 1076 { 1077 MapMode aMapMode; 1078 Size aSize; 1079 const sal_uLong nStartPos = rIStm.Tell(); 1080 sal_uInt32 nId; 1081 sal_uLong nHeaderLen; 1082 long nType; 1083 long nLen; 1084 const sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt(); 1085 sal_Bool bRet = sal_False; 1086 1087 if( !mbSwapUnderway ) 1088 { 1089 const String aTempURLStr( maDocFileURLStr ); 1090 const sal_uLong nTempPos = mnDocFilePos; 1091 1092 ImplClear(); 1093 1094 maDocFileURLStr = aTempURLStr; 1095 mnDocFilePos = nTempPos; 1096 } 1097 1098 rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 1099 rIStm >> nId; 1100 1101 // check version 1102 if( GRAPHIC_FORMAT_50 == nId ) 1103 { 1104 // read new style header 1105 VersionCompat* pCompat = new VersionCompat( rIStm, STREAM_READ ); 1106 1107 rIStm >> nType; 1108 rIStm >> nLen; 1109 rIStm >> aSize; 1110 rIStm >> aMapMode; 1111 1112 delete pCompat; 1113 } 1114 else 1115 { 1116 // read old style header 1117 long nWidth, nHeight; 1118 long nMapMode, nScaleNumX, nScaleDenomX; 1119 long nScaleNumY, nScaleDenomY, nOffsX, nOffsY; 1120 1121 rIStm.SeekRel( -4L ); 1122 1123 rIStm >> nType >> nLen >> nWidth >> nHeight; 1124 rIStm >> nMapMode >> nScaleNumX >> nScaleDenomX >> nScaleNumY; 1125 rIStm >> nScaleDenomY >> nOffsX >> nOffsY; 1126 1127 // swapped 1128 if( nType > 100L ) 1129 { 1130 nType = SWAPLONG( nType ); 1131 nLen = SWAPLONG( nLen ); 1132 nWidth = SWAPLONG( nWidth ); 1133 nHeight = SWAPLONG( nHeight ); 1134 nMapMode = SWAPLONG( nMapMode ); 1135 nScaleNumX = SWAPLONG( nScaleNumX ); 1136 nScaleDenomX = SWAPLONG( nScaleDenomX ); 1137 nScaleNumY = SWAPLONG( nScaleNumY ); 1138 nScaleDenomY = SWAPLONG( nScaleDenomY ); 1139 nOffsX = SWAPLONG( nOffsX ); 1140 nOffsY = SWAPLONG( nOffsY ); 1141 } 1142 1143 aSize = Size( nWidth, nHeight ); 1144 aMapMode = MapMode( (MapUnit) nMapMode, Point( nOffsX, nOffsY ), 1145 Fraction( nScaleNumX, nScaleDenomX ), 1146 Fraction( nScaleNumY, nScaleDenomY ) ); 1147 } 1148 1149 nHeaderLen = rIStm.Tell() - nStartPos; 1150 meType = (GraphicType) nType; 1151 1152 if( meType ) 1153 { 1154 if( meType == GRAPHIC_BITMAP ) 1155 { 1156 if(maSvgData.get() && maEx.IsEmpty()) 1157 { 1158 // use maEx as local buffer for rendered svg 1159 maEx = maSvgData->getReplacement(); 1160 } 1161 1162 maEx.aBitmapSize = aSize; 1163 1164 if( aMapMode != MapMode() ) 1165 { 1166 maEx.SetPrefMapMode( aMapMode ); 1167 maEx.SetPrefSize( aSize ); 1168 } 1169 } 1170 else 1171 { 1172 maMetaFile.SetPrefMapMode( aMapMode ); 1173 maMetaFile.SetPrefSize( aSize ); 1174 } 1175 1176 if( bSwap ) 1177 { 1178 if( maDocFileURLStr.Len() ) 1179 { 1180 rIStm.Seek( nStartPos + nHeaderLen + nLen ); 1181 bRet = mbSwapOut = sal_True; 1182 } 1183 else 1184 { 1185 ::utl::TempFile aTempFile; 1186 const INetURLObject aTmpURL( aTempFile.GetURL() ); 1187 1188 if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) 1189 { 1190 SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); 1191 1192 if( pOStm ) 1193 { 1194 sal_uLong nFullLen = nHeaderLen + nLen; 1195 sal_uLong nPartLen = Min( nFullLen, (sal_uLong) GRAPHIC_MAXPARTLEN ); 1196 sal_uInt8* pBuffer = (sal_uInt8*) rtl_allocateMemory( nPartLen ); 1197 1198 pOStm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 1199 1200 if( pBuffer ) 1201 { 1202 rIStm.Seek( nStartPos ); 1203 1204 while( nFullLen ) 1205 { 1206 rIStm.Read( (char*) pBuffer, nPartLen ); 1207 pOStm->Write( (char*) pBuffer, nPartLen ); 1208 1209 nFullLen -= nPartLen; 1210 1211 if( nFullLen < GRAPHIC_MAXPARTLEN ) 1212 nPartLen = nFullLen; 1213 } 1214 1215 rtl_freeMemory( pBuffer ); 1216 sal_uLong nReadErr = rIStm.GetError(), nWriteErr = pOStm->GetError(); 1217 delete pOStm, pOStm = NULL; 1218 1219 if( !nReadErr && !nWriteErr ) 1220 { 1221 bRet = mbSwapOut = sal_True; 1222 mpSwapFile = new ImpSwapFile; 1223 mpSwapFile->nRefCount = 1; 1224 mpSwapFile->aSwapURL = aTmpURL; 1225 } 1226 else 1227 { 1228 try 1229 { 1230 ::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), 1231 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); 1232 1233 aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), 1234 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); 1235 } 1236 catch( const ::com::sun::star::ucb::ContentCreationException& ) 1237 { 1238 } 1239 catch( const ::com::sun::star::uno::RuntimeException& ) 1240 { 1241 } 1242 catch( const ::com::sun::star::ucb::CommandAbortedException& ) 1243 { 1244 } 1245 catch( const ::com::sun::star::uno::Exception& ) 1246 { 1247 } 1248 } 1249 } 1250 1251 delete pOStm; 1252 } 1253 } 1254 } 1255 } 1256 else if( meType == GRAPHIC_BITMAP || meType == GRAPHIC_GDIMETAFILE ) 1257 { 1258 rIStm >> *this; 1259 bRet = ( rIStm.GetError() == 0UL ); 1260 } 1261 else if( meType >= SYS_WINMETAFILE && meType <= SYS_MACMETAFILE ) 1262 { 1263 Graphic aSysGraphic; 1264 sal_uLong nCvtType; 1265 1266 switch( sal::static_int_cast<sal_uLong>(meType) ) 1267 { 1268 case( SYS_WINMETAFILE ): 1269 case( SYS_WNTMETAFILE ): nCvtType = CVT_WMF; break; 1270 case( SYS_OS2METAFILE ): nCvtType = CVT_MET; break; 1271 case( SYS_MACMETAFILE ): nCvtType = CVT_PCT; break; 1272 1273 default: 1274 nCvtType = CVT_UNKNOWN; 1275 break; 1276 } 1277 1278 if( nType && GraphicConverter::Import( rIStm, aSysGraphic, nCvtType ) == ERRCODE_NONE ) 1279 { 1280 *this = ImpGraphic( aSysGraphic.GetGDIMetaFile() ); 1281 bRet = ( rIStm.GetError() == 0UL ); 1282 } 1283 else 1284 meType = GRAPHIC_DEFAULT; 1285 } 1286 1287 if( bRet ) 1288 { 1289 ImplSetPrefMapMode( aMapMode ); 1290 ImplSetPrefSize( aSize ); 1291 } 1292 } 1293 else 1294 bRet = sal_True; 1295 1296 rIStm.SetNumberFormatInt( nOldFormat ); 1297 1298 return bRet; 1299 } 1300 1301 // ------------------------------------------------------------------------ 1302 1303 sal_Bool ImpGraphic::ImplWriteEmbedded( SvStream& rOStm ) 1304 { 1305 sal_Bool bRet = sal_False; 1306 1307 if( ( meType != GRAPHIC_NONE ) && ( meType != GRAPHIC_DEFAULT ) && !ImplIsSwapOut() ) 1308 { 1309 const MapMode aMapMode( ImplGetPrefMapMode() ); 1310 const Size aSize( ImplGetPrefSize() ); 1311 const sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt(); 1312 sal_uLong nDataFieldPos; 1313 1314 rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 1315 1316 // write correct version ( old style/new style header ) 1317 if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) 1318 { 1319 // write ID for new format (5.0) 1320 rOStm << GRAPHIC_FORMAT_50; 1321 1322 // write new style header 1323 VersionCompat* pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 ); 1324 1325 rOStm << (long) meType; 1326 1327 // data size is updated later 1328 nDataFieldPos = rOStm.Tell(); 1329 rOStm << (long) 0; 1330 1331 rOStm << aSize; 1332 rOStm << aMapMode; 1333 1334 delete pCompat; 1335 } 1336 else 1337 { 1338 // write old style (<=4.0) header 1339 rOStm << (long) meType; 1340 1341 // data size is updated later 1342 nDataFieldPos = rOStm.Tell(); 1343 rOStm << (long) 0; 1344 1345 rOStm << (long) aSize.Width(); 1346 rOStm << (long) aSize.Height(); 1347 rOStm << (long) aMapMode.GetMapUnit(); 1348 rOStm << (long) aMapMode.GetScaleX().GetNumerator(); 1349 rOStm << (long) aMapMode.GetScaleX().GetDenominator(); 1350 rOStm << (long) aMapMode.GetScaleY().GetNumerator(); 1351 rOStm << (long) aMapMode.GetScaleY().GetDenominator(); 1352 rOStm << (long) aMapMode.GetOrigin().X(); 1353 rOStm << (long) aMapMode.GetOrigin().Y(); 1354 } 1355 1356 // write data block 1357 if( !rOStm.GetError() ) 1358 { 1359 const sal_uLong nDataStart = rOStm.Tell(); 1360 1361 if( ImplIsSupportedGraphic() ) 1362 rOStm << *this; 1363 1364 if( !rOStm.GetError() ) 1365 { 1366 const sal_uLong nStmPos2 = rOStm.Tell(); 1367 rOStm.Seek( nDataFieldPos ); 1368 rOStm << (long) ( nStmPos2 - nDataStart ); 1369 rOStm.Seek( nStmPos2 ); 1370 bRet = sal_True; 1371 } 1372 } 1373 1374 rOStm.SetNumberFormatInt( nOldFormat ); 1375 } 1376 1377 return bRet; 1378 } 1379 1380 // ------------------------------------------------------------------------ 1381 1382 sal_Bool ImpGraphic::ImplSwapOut() 1383 { 1384 sal_Bool bRet = sal_False; 1385 1386 if( !ImplIsSwapOut() ) 1387 { 1388 if( !maDocFileURLStr.Len() ) 1389 { 1390 ::utl::TempFile aTempFile; 1391 const INetURLObject aTmpURL( aTempFile.GetURL() ); 1392 1393 if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) 1394 { 1395 SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); 1396 1397 if( pOStm ) 1398 { 1399 pOStm->SetVersion( SOFFICE_FILEFORMAT_50 ); 1400 pOStm->SetCompressMode( COMPRESSMODE_NATIVE ); 1401 1402 if( ( bRet = ImplSwapOut( pOStm ) ) == sal_True ) 1403 { 1404 mpSwapFile = new ImpSwapFile; 1405 mpSwapFile->nRefCount = 1; 1406 mpSwapFile->aSwapURL = aTmpURL; 1407 } 1408 else 1409 { 1410 delete pOStm, pOStm = NULL; 1411 1412 try 1413 { 1414 ::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), 1415 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); 1416 1417 aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), 1418 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); 1419 } 1420 catch( const ::com::sun::star::ucb::ContentCreationException& ) 1421 { 1422 } 1423 catch( const ::com::sun::star::uno::RuntimeException& ) 1424 { 1425 } 1426 catch( const ::com::sun::star::ucb::CommandAbortedException& ) 1427 { 1428 } 1429 catch( const ::com::sun::star::uno::Exception& ) 1430 { 1431 } 1432 } 1433 1434 delete pOStm; 1435 } 1436 } 1437 } 1438 else 1439 { 1440 ImplClearGraphics( sal_True ); 1441 bRet = mbSwapOut = sal_True; 1442 } 1443 } 1444 1445 return bRet; 1446 } 1447 1448 // ------------------------------------------------------------------------ 1449 1450 sal_Bool ImpGraphic::ImplSwapOut( SvStream* pOStm ) 1451 { 1452 sal_Bool bRet = sal_False; 1453 1454 if( pOStm ) 1455 { 1456 pOStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE ); 1457 1458 if( !pOStm->GetError() && ImplWriteEmbedded( *pOStm ) ) 1459 { 1460 pOStm->Flush(); 1461 1462 if( !pOStm->GetError() ) 1463 { 1464 ImplClearGraphics( sal_True ); 1465 bRet = mbSwapOut = sal_True; 1466 } 1467 } 1468 } 1469 else 1470 { 1471 ImplClearGraphics( sal_True ); 1472 bRet = mbSwapOut = sal_True; 1473 } 1474 1475 return bRet; 1476 } 1477 1478 // ------------------------------------------------------------------------ 1479 1480 sal_Bool ImpGraphic::ImplSwapIn() 1481 { 1482 sal_Bool bRet = sal_False; 1483 1484 if( ImplIsSwapOut() ) 1485 { 1486 String aSwapURL; 1487 1488 if( mpSwapFile ) 1489 aSwapURL = mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE ); 1490 else 1491 aSwapURL = maDocFileURLStr; 1492 1493 if( aSwapURL.Len() ) 1494 { 1495 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aSwapURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE ); 1496 1497 if( pIStm ) 1498 { 1499 pIStm->SetVersion( SOFFICE_FILEFORMAT_50 ); 1500 pIStm->SetCompressMode( COMPRESSMODE_NATIVE ); 1501 1502 if( !mpSwapFile ) 1503 pIStm->Seek( mnDocFilePos ); 1504 1505 bRet = ImplSwapIn( pIStm ); 1506 delete pIStm; 1507 1508 if( mpSwapFile ) 1509 { 1510 if( mpSwapFile->nRefCount > 1 ) 1511 mpSwapFile->nRefCount--; 1512 else 1513 { 1514 try 1515 { 1516 ::ucbhelper::Content aCnt( aSwapURL, 1517 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() ); 1518 1519 aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), 1520 ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) ); 1521 } 1522 catch( const ::com::sun::star::ucb::ContentCreationException& ) 1523 { 1524 } 1525 catch( const ::com::sun::star::uno::RuntimeException& ) 1526 { 1527 } 1528 catch( const ::com::sun::star::ucb::CommandAbortedException& ) 1529 { 1530 } 1531 catch( const ::com::sun::star::uno::Exception& ) 1532 { 1533 } 1534 1535 delete mpSwapFile; 1536 } 1537 1538 mpSwapFile = NULL; 1539 } 1540 } 1541 } 1542 } 1543 1544 return bRet; 1545 } 1546 1547 // ------------------------------------------------------------------------ 1548 1549 sal_Bool ImpGraphic::ImplSwapIn( SvStream* pIStm ) 1550 { 1551 sal_Bool bRet = sal_False; 1552 1553 if( pIStm ) 1554 { 1555 pIStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE ); 1556 1557 if( !pIStm->GetError() ) 1558 { 1559 mbSwapUnderway = sal_True; 1560 bRet = ImplReadEmbedded( *pIStm ); 1561 mbSwapUnderway = sal_False; 1562 1563 if( !bRet ) 1564 ImplClear(); 1565 else 1566 mbSwapOut = sal_False; 1567 } 1568 } 1569 1570 return bRet; 1571 } 1572 1573 // ------------------------------------------------------------------------ 1574 1575 sal_Bool ImpGraphic::ImplIsSwapOut() const 1576 { 1577 return mbSwapOut; 1578 } 1579 1580 // ------------------------------------------------------------------------ 1581 1582 void ImpGraphic::ImplSetLink( const GfxLink& rGfxLink ) 1583 { 1584 delete mpGfxLink; 1585 mpGfxLink = new GfxLink( rGfxLink ); 1586 1587 if( mpGfxLink->IsNative() ) 1588 mpGfxLink->SwapOut(); 1589 } 1590 1591 // ------------------------------------------------------------------------ 1592 1593 GfxLink ImpGraphic::ImplGetLink() 1594 { 1595 return( mpGfxLink ? *mpGfxLink : GfxLink() ); 1596 } 1597 1598 // ------------------------------------------------------------------------ 1599 1600 sal_Bool ImpGraphic::ImplIsLink() const 1601 { 1602 return ( mpGfxLink != NULL ) ? sal_True : sal_False; 1603 } 1604 1605 // ------------------------------------------------------------------------ 1606 1607 sal_uLong ImpGraphic::ImplGetChecksum() const 1608 { 1609 sal_uLong nRet = 0; 1610 1611 if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) 1612 { 1613 switch( meType ) 1614 { 1615 case( GRAPHIC_DEFAULT ): 1616 break; 1617 1618 case( GRAPHIC_BITMAP ): 1619 { 1620 if(maSvgData.get() && maEx.IsEmpty()) 1621 { 1622 // use maEx as local buffer for rendered svg 1623 const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); 1624 } 1625 1626 if( mpAnimation ) 1627 { 1628 nRet = mpAnimation->GetChecksum(); 1629 } 1630 else 1631 { 1632 nRet = maEx.GetChecksum(); 1633 } 1634 } 1635 break; 1636 1637 default: 1638 nRet = maMetaFile.GetChecksum(); 1639 break; 1640 } 1641 } 1642 1643 return nRet; 1644 } 1645 1646 // ------------------------------------------------------------------------ 1647 1648 sal_Bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const 1649 { 1650 sal_Bool bResult = sal_False; 1651 1652 if( !rOStm.GetError() ) 1653 { 1654 if( !ImplIsSwapOut() ) 1655 { 1656 if( mpGfxLink && mpGfxLink->IsNative() ) 1657 bResult = mpGfxLink->ExportNative( rOStm ); 1658 else 1659 { 1660 rOStm << *this; 1661 bResult = ( rOStm.GetError() == ERRCODE_NONE ); 1662 } 1663 } 1664 else 1665 rOStm.SetError( SVSTREAM_GENERALERROR ); 1666 } 1667 1668 return bResult; 1669 } 1670 1671 // ------------------------------------------------------------------------ 1672 1673 const SvgDataPtr& ImpGraphic::getSvgData() const 1674 { 1675 return maSvgData; 1676 } 1677 1678 // ------------------------------------------------------------------------ 1679 1680 SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic ) 1681 { 1682 if( !rIStm.GetError() ) 1683 { 1684 const sal_uLong nStmPos1 = rIStm.Tell(); 1685 sal_uInt32 nTmp; 1686 1687 if ( !rImpGraphic.mbSwapUnderway ) 1688 rImpGraphic.ImplClear(); 1689 1690 // read Id 1691 rIStm >> nTmp; 1692 1693 // if there is no more data, avoid further expensive 1694 // reading which will create VDevs and other stuff, just to 1695 // read nothing. CAUTION: Eof is only true AFTER reading another 1696 // byte, a speciality of SvMemoryStream (!) 1697 if(!rIStm.GetError() && !rIStm.IsEof()) 1698 { 1699 if( NATIVE_FORMAT_50 == nTmp ) 1700 { 1701 Graphic aGraphic; 1702 GfxLink aLink; 1703 VersionCompat* pCompat; 1704 1705 // read compat info 1706 pCompat = new VersionCompat( rIStm, STREAM_READ ); 1707 delete pCompat; 1708 1709 rIStm >> aLink; 1710 1711 // set dummy link to avoid creation of additional link after filtering; 1712 // we set a default link to avoid unnecessary swapping of native data 1713 aGraphic.SetLink( GfxLink() ); 1714 1715 if( !rIStm.GetError() && aLink.LoadNative( aGraphic ) ) 1716 { 1717 // set link only, if no other link was set 1718 const sal_Bool bSetLink = ( rImpGraphic.mpGfxLink == NULL ); 1719 1720 // assign graphic 1721 rImpGraphic = *aGraphic.ImplGetImpGraphic(); 1722 1723 if( aLink.IsPrefMapModeValid() ) 1724 rImpGraphic.ImplSetPrefMapMode( aLink.GetPrefMapMode() ); 1725 1726 if( aLink.IsPrefSizeValid() ) 1727 rImpGraphic.ImplSetPrefSize( aLink.GetPrefSize() ); 1728 1729 if( bSetLink ) 1730 rImpGraphic.ImplSetLink( aLink ); 1731 } 1732 else 1733 { 1734 rIStm.Seek( nStmPos1 ); 1735 rIStm.SetError( ERRCODE_IO_WRONGFORMAT ); 1736 } 1737 } 1738 else 1739 { 1740 BitmapEx aBmpEx; 1741 const sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt(); 1742 1743 rIStm.SeekRel( -4 ); 1744 rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 1745 rIStm >> aBmpEx; 1746 1747 if( !rIStm.GetError() ) 1748 { 1749 sal_uInt32 nMagic1(0), nMagic2(0); 1750 sal_uLong nActPos = rIStm.Tell(); 1751 1752 rIStm >> nMagic1 >> nMagic2; 1753 rIStm.Seek( nActPos ); 1754 1755 rImpGraphic = ImpGraphic( aBmpEx ); 1756 1757 if( !rIStm.GetError() && ( 0x5344414e == nMagic1 ) && ( 0x494d4931 == nMagic2 ) ) 1758 { 1759 delete rImpGraphic.mpAnimation; 1760 rImpGraphic.mpAnimation = new Animation; 1761 rIStm >> *rImpGraphic.mpAnimation; 1762 1763 // #108077# manually set loaded BmpEx to Animation 1764 // (which skips loading its BmpEx if already done) 1765 rImpGraphic.mpAnimation->SetBitmapEx(aBmpEx); 1766 } 1767 else 1768 rIStm.ResetError(); 1769 } 1770 else 1771 { 1772 GDIMetaFile aMtf; 1773 1774 rIStm.Seek( nStmPos1 ); 1775 rIStm.ResetError(); 1776 rIStm >> aMtf; 1777 1778 if( !rIStm.GetError() ) 1779 { 1780 rImpGraphic = aMtf; 1781 } 1782 else 1783 { 1784 // try to stream in Svg defining data (length, byte array and evtl. path) 1785 // See below (operator<<) for more information 1786 const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0')); 1787 sal_uInt32 nMagic; 1788 rIStm.Seek(nStmPos1); 1789 rIStm.ResetError(); 1790 rIStm >> nMagic; 1791 1792 if(nSvgMagic == nMagic) 1793 { 1794 sal_uInt32 mnSvgDataArrayLength(0); 1795 rIStm >> mnSvgDataArrayLength; 1796 1797 if(mnSvgDataArrayLength) 1798 { 1799 SvgDataArray aNewData(new sal_uInt8[mnSvgDataArrayLength]); 1800 UniString aPath; 1801 1802 rIStm.Read(aNewData.get(), mnSvgDataArrayLength); 1803 rIStm.ReadByteString(aPath); 1804 1805 if(!rIStm.GetError()) 1806 { 1807 SvgDataPtr aSvgDataPtr( 1808 new SvgData( 1809 aNewData, 1810 mnSvgDataArrayLength, 1811 rtl::OUString(aPath))); 1812 1813 rImpGraphic = aSvgDataPtr; 1814 } 1815 } 1816 } 1817 1818 rIStm.Seek(nStmPos1); 1819 } 1820 } 1821 1822 rIStm.SetNumberFormatInt( nOldFormat ); 1823 } 1824 } 1825 } 1826 1827 return rIStm; 1828 } 1829 1830 // ------------------------------------------------------------------------ 1831 1832 SvStream& operator<<( SvStream& rOStm, const ImpGraphic& rImpGraphic ) 1833 { 1834 if( !rOStm.GetError() ) 1835 { 1836 if( !rImpGraphic.ImplIsSwapOut() ) 1837 { 1838 if( ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) && 1839 ( rOStm.GetCompressMode() & COMPRESSMODE_NATIVE ) && 1840 rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative() ) 1841 { 1842 VersionCompat* pCompat; 1843 1844 // native format 1845 rOStm << NATIVE_FORMAT_50; 1846 1847 // write compat info 1848 pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 ); 1849 delete pCompat; 1850 1851 rImpGraphic.mpGfxLink->SetPrefMapMode( rImpGraphic.ImplGetPrefMapMode() ); 1852 rImpGraphic.mpGfxLink->SetPrefSize( rImpGraphic.ImplGetPrefSize() ); 1853 rOStm << *rImpGraphic.mpGfxLink; 1854 } 1855 else 1856 { 1857 // own format 1858 const sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt(); 1859 rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 1860 1861 switch( rImpGraphic.ImplGetType() ) 1862 { 1863 case( GRAPHIC_NONE ): 1864 case( GRAPHIC_DEFAULT ): 1865 break; 1866 1867 case GRAPHIC_BITMAP: 1868 { 1869 if(rImpGraphic.getSvgData().get()) 1870 { 1871 // stream out Svg defining data (length, byte array and evtl. path) 1872 // this is used e.g. in swapping out graphic data and in transporting it over UNO API 1873 // as sequence of bytes, but AFAIK not written anywhere to any kind of file, so it should be 1874 // no problem to extend it; only used at runtime 1875 const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0')); 1876 1877 rOStm << nSvgMagic; 1878 rOStm << rImpGraphic.getSvgData()->getSvgDataArrayLength(); 1879 rOStm.Write(rImpGraphic.getSvgData()->getSvgDataArray().get(), rImpGraphic.getSvgData()->getSvgDataArrayLength()); 1880 rOStm.WriteByteString(rImpGraphic.getSvgData()->getPath()); 1881 } 1882 else if( rImpGraphic.ImplIsAnimated()) 1883 { 1884 rOStm << *rImpGraphic.mpAnimation; 1885 } 1886 else 1887 { 1888 rOStm << rImpGraphic.maEx; 1889 } 1890 } 1891 break; 1892 1893 default: 1894 { 1895 if( rImpGraphic.ImplIsSupportedGraphic() ) 1896 rOStm << rImpGraphic.maMetaFile; 1897 } 1898 break; 1899 } 1900 1901 rOStm.SetNumberFormatInt( nOldFormat ); 1902 } 1903 } 1904 else 1905 rOStm.SetError( SVSTREAM_GENERALERROR ); 1906 } 1907 1908 return rOStm; 1909 } 1910