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