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