1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 #include <vos/macros.hxx> 31 #include <rtl/crc.h> 32 #include <tools/stream.hxx> 33 #include <tools/vcompat.hxx> 34 #include <vcl/metaact.hxx> 35 #include <vcl/salbtype.hxx> 36 #include <vcl/outdev.hxx> 37 #include <vcl/window.hxx> 38 #ifndef _SV_CVTSVM_HXX 39 #include <vcl/cvtsvm.hxx> 40 #endif 41 #include <vcl/virdev.hxx> 42 #include <vcl/gdimtf.hxx> 43 #include <vcl/graphictools.hxx> 44 45 // ----------- 46 // - Defines - 47 // ----------- 48 49 #define GAMMA( _def_cVal, _def_InvGamma ) ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L)) 50 51 // -------------------------- 52 // - Color exchange structs - 53 // -------------------------- 54 55 struct ImplColAdjustParam 56 { 57 sal_uInt8* pMapR; 58 sal_uInt8* pMapG; 59 sal_uInt8* pMapB; 60 }; 61 62 struct ImplBmpAdjustParam 63 { 64 short nLuminancePercent; 65 short nContrastPercent; 66 short nChannelRPercent; 67 short nChannelGPercent; 68 short nChannelBPercent; 69 double fGamma; 70 sal_Bool bInvert; 71 }; 72 73 // ----------------------------------------------------------------------------- 74 75 struct ImplColConvertParam 76 { 77 MtfConversion eConversion; 78 }; 79 80 struct ImplBmpConvertParam 81 { 82 BmpConversion eConversion; 83 }; 84 85 // ----------------------------------------------------------------------------- 86 87 struct ImplColMonoParam 88 { 89 Color aColor; 90 }; 91 92 struct ImplBmpMonoParam 93 { 94 Color aColor; 95 }; 96 97 // ----------------------------------------------------------------------------- 98 99 struct ImplColReplaceParam 100 { 101 sal_uLong* pMinR; 102 sal_uLong* pMaxR; 103 sal_uLong* pMinG; 104 sal_uLong* pMaxG; 105 sal_uLong* pMinB; 106 sal_uLong* pMaxB; 107 const Color* pDstCols; 108 sal_uLong nCount; 109 }; 110 111 struct ImplBmpReplaceParam 112 { 113 const Color* pSrcCols; 114 const Color* pDstCols; 115 sal_uLong nCount; 116 const sal_uLong* pTols; 117 }; 118 119 120 // --------- 121 // - Label - 122 // --------- 123 124 struct ImpLabel 125 { 126 String aLabelName; 127 sal_uLong nActionPos; 128 129 ImpLabel( const String& rLabelName, sal_uLong _nActionPos ) : 130 aLabelName( rLabelName ), 131 nActionPos( _nActionPos ) {} 132 }; 133 134 // ------------- 135 // - LabelList - 136 // ------------- 137 138 class ImpLabelList : private List 139 { 140 public: 141 142 ImpLabelList() : List( 8, 4, 4 ) {} 143 ImpLabelList( const ImpLabelList& rList ); 144 ~ImpLabelList(); 145 146 void ImplInsert( ImpLabel* p ) { Insert( p, LIST_APPEND ); } 147 ImpLabel* ImplRemove( sal_uLong nPos ) { return (ImpLabel*) Remove( nPos ); } 148 void ImplReplace( ImpLabel* p ) { Replace( (void*)p ); } 149 ImpLabel* ImplFirst() { return (ImpLabel*) First(); } 150 ImpLabel* ImplNext() { return (ImpLabel*) Next(); } 151 ImpLabel* ImplGetLabel( sal_uLong nPos ) const { return (ImpLabel*) GetObject( nPos ); } 152 sal_uLong ImplGetLabelPos( const String& rLabelName ); 153 sal_uLong ImplCount() const { return Count(); } 154 }; 155 156 // ------------------------------------------------------------------------ 157 158 ImpLabelList::ImpLabelList( const ImpLabelList& rList ) : 159 List( rList ) 160 { 161 for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() ) 162 ImplReplace( new ImpLabel( *pLabel ) ); 163 } 164 165 // ------------------------------------------------------------------------ 166 167 ImpLabelList::~ImpLabelList() 168 { 169 for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() ) 170 delete pLabel; 171 } 172 173 // ------------------------------------------------------------------------ 174 175 sal_uLong ImpLabelList::ImplGetLabelPos( const String& rLabelName ) 176 { 177 sal_uLong nLabelPos = METAFILE_LABEL_NOTFOUND; 178 179 for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() ) 180 { 181 if ( rLabelName == pLabel->aLabelName ) 182 { 183 nLabelPos = GetCurPos(); 184 break; 185 } 186 } 187 188 return nLabelPos; 189 } 190 191 // --------------- 192 // - GDIMetaFile - 193 // --------------- 194 195 GDIMetaFile::GDIMetaFile() : 196 List ( 0x3EFF, 64, 64 ), 197 aPrefSize ( 1, 1 ), 198 pPrev ( NULL ), 199 pNext ( NULL ), 200 pOutDev ( NULL ), 201 pLabelList ( NULL ), 202 bPause ( sal_False ), 203 bRecord ( sal_False ) 204 { 205 } 206 207 // ------------------------------------------------------------------------ 208 209 GDIMetaFile::GDIMetaFile( const GDIMetaFile& rMtf ) : 210 List ( rMtf ), 211 aPrefMapMode ( rMtf.aPrefMapMode ), 212 aPrefSize ( rMtf.aPrefSize ), 213 aHookHdlLink ( rMtf.aHookHdlLink ), 214 pPrev ( rMtf.pPrev ), 215 pNext ( rMtf.pNext ), 216 pOutDev ( NULL ), 217 bPause ( sal_False ), 218 bRecord ( sal_False ) 219 { 220 // RefCount der MetaActions erhoehen 221 for( void* pAct = First(); pAct; pAct = Next() ) 222 ( (MetaAction*) pAct )->Duplicate(); 223 224 if( rMtf.pLabelList ) 225 pLabelList = new ImpLabelList( *rMtf.pLabelList ); 226 else 227 pLabelList = NULL; 228 229 if( rMtf.bRecord ) 230 { 231 Record( rMtf.pOutDev ); 232 233 if ( rMtf.bPause ) 234 Pause( sal_True ); 235 } 236 } 237 238 // ------------------------------------------------------------------------ 239 240 GDIMetaFile::~GDIMetaFile() 241 { 242 Clear(); 243 } 244 245 // ------------------------------------------------------------------------ 246 247 GDIMetaFile& GDIMetaFile::operator=( const GDIMetaFile& rMtf ) 248 { 249 if( this != &rMtf ) 250 { 251 Clear(); 252 253 List::operator=( rMtf ); 254 255 // RefCount der MetaActions erhoehen 256 for( void* pAct = First(); pAct; pAct = Next() ) 257 ( (MetaAction*) pAct )->Duplicate(); 258 259 if( rMtf.pLabelList ) 260 pLabelList = new ImpLabelList( *rMtf.pLabelList ); 261 else 262 pLabelList = NULL; 263 264 aPrefMapMode = rMtf.aPrefMapMode; 265 aPrefSize = rMtf.aPrefSize; 266 aHookHdlLink = rMtf.aHookHdlLink; 267 pPrev = rMtf.pPrev; 268 pNext = rMtf.pNext; 269 pOutDev = NULL; 270 bPause = sal_False; 271 bRecord = sal_False; 272 273 if( rMtf.bRecord ) 274 { 275 Record( rMtf.pOutDev ); 276 277 if( rMtf.bPause ) 278 Pause( sal_True ); 279 } 280 } 281 282 return *this; 283 } 284 285 // ------------------------------------------------------------------------ 286 287 sal_Bool GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const 288 { 289 const sal_uLong nObjCount = Count(); 290 sal_Bool bRet = sal_False; 291 292 if( this == &rMtf ) 293 bRet = sal_True; 294 else if( rMtf.GetActionCount() == nObjCount && 295 rMtf.GetPrefSize() == aPrefSize && 296 rMtf.GetPrefMapMode() == aPrefMapMode ) 297 { 298 bRet = sal_True; 299 300 for( sal_uLong n = 0UL; n < nObjCount; n++ ) 301 { 302 if( GetObject( n ) != rMtf.GetObject( n ) ) 303 { 304 bRet = sal_False; 305 break; 306 } 307 } 308 } 309 310 return bRet; 311 } 312 313 // ------------------------------------------------------------------------ 314 315 sal_Bool GDIMetaFile::IsEqual( const GDIMetaFile& rMtf ) const 316 { 317 const sal_uLong nObjCount = Count(); 318 sal_Bool bRet = sal_False; 319 320 if( this == &rMtf ) 321 bRet = sal_True; 322 else if( rMtf.GetActionCount() == nObjCount && 323 rMtf.GetPrefSize() == aPrefSize && 324 rMtf.GetPrefMapMode() == aPrefMapMode ) 325 { 326 bRet = sal_True; 327 328 for( sal_uLong n = 0UL; n < nObjCount; n++ ) 329 { 330 if(!((MetaAction*)GetObject( n ))->IsEqual(*((MetaAction*)rMtf.GetObject( n )))) 331 { 332 bRet = sal_False; 333 break; 334 } 335 } 336 } 337 338 return bRet; 339 } 340 341 // ------------------------------------------------------------------------ 342 343 void GDIMetaFile::Clear() 344 { 345 if( bRecord ) 346 Stop(); 347 348 for( void* pAct = First(); pAct; pAct = Next() ) 349 ( (MetaAction*) pAct )->Delete(); 350 351 List::Clear(); 352 353 delete pLabelList; 354 pLabelList = NULL; 355 } 356 357 // ------------------------------------------------------------------------ 358 359 void GDIMetaFile::Linker( OutputDevice* pOut, sal_Bool bLink ) 360 { 361 if( bLink ) 362 { 363 pNext = NULL; 364 pPrev = pOut->GetConnectMetaFile(); 365 pOut->SetConnectMetaFile( this ); 366 367 if( pPrev ) 368 pPrev->pNext = this; 369 } 370 else 371 { 372 if( pNext ) 373 { 374 pNext->pPrev = pPrev; 375 376 if( pPrev ) 377 pPrev->pNext = pNext; 378 } 379 else 380 { 381 if( pPrev ) 382 pPrev->pNext = NULL; 383 384 pOut->SetConnectMetaFile( pPrev ); 385 } 386 387 pPrev = NULL; 388 pNext = NULL; 389 } 390 } 391 392 // ------------------------------------------------------------------------ 393 394 long GDIMetaFile::Hook() 395 { 396 return aHookHdlLink.Call( this ); 397 } 398 399 // ------------------------------------------------------------------------ 400 401 void GDIMetaFile::Record( OutputDevice* pOut ) 402 { 403 if( bRecord ) 404 Stop(); 405 406 Last(); 407 pOutDev = pOut; 408 bRecord = sal_True; 409 Linker( pOut, sal_True ); 410 } 411 412 // ------------------------------------------------------------------------ 413 414 void GDIMetaFile::Play( GDIMetaFile& rMtf, sal_uLong nPos ) 415 { 416 if ( !bRecord && !rMtf.bRecord ) 417 { 418 MetaAction* pAction = GetCurAction(); 419 const sal_uLong nObjCount = Count(); 420 421 if( nPos > nObjCount ) 422 nPos = nObjCount; 423 424 for( sal_uLong nCurPos = GetCurPos(); nCurPos < nPos; nCurPos++ ) 425 { 426 if( !Hook() ) 427 { 428 pAction->Duplicate(); 429 rMtf.AddAction( pAction ); 430 } 431 432 pAction = (MetaAction*) Next(); 433 } 434 } 435 } 436 437 // ------------------------------------------------------------------------ 438 439 void GDIMetaFile::Play( OutputDevice* pOut, sal_uLong nPos ) 440 { 441 if( !bRecord ) 442 { 443 MetaAction* pAction = GetCurAction(); 444 const sal_uLong nObjCount = Count(); 445 sal_uLong i = 0, nSyncCount = ( pOut->GetOutDevType() == OUTDEV_WINDOW ) ? 0x000000ff : 0xffffffff; 446 447 if( nPos > nObjCount ) 448 nPos = nObjCount; 449 450 // #i23407# Set backwards-compatible text language and layout mode 451 // This is necessary, since old metafiles don't even know of these 452 // recent add-ons. Newer metafiles must of course explicitely set 453 // those states. 454 pOut->Push( PUSH_TEXTLAYOUTMODE|PUSH_TEXTLANGUAGE ); 455 pOut->SetLayoutMode( 0 ); 456 pOut->SetDigitLanguage( 0 ); 457 458 for( sal_uLong nCurPos = GetCurPos(); nCurPos < nPos; nCurPos++ ) 459 { 460 if( !Hook() ) 461 { 462 pAction->Execute( pOut ); 463 464 // flush output from time to time 465 if( i++ > nSyncCount ) 466 ( (Window*) pOut )->Flush(), i = 0; 467 } 468 469 pAction = (MetaAction*) Next(); 470 } 471 472 pOut->Pop(); 473 } 474 } 475 476 // ------------------------------------------------------------------------ 477 478 void GDIMetaFile::Play( OutputDevice* pOut, const Point& rPos, 479 const Size& rSize, sal_uLong nPos ) 480 { 481 Region aDrawClipRegion; 482 MapMode aDrawMap( GetPrefMapMode() ); 483 Size aDestSize( pOut->LogicToPixel( rSize ) ); 484 485 if( aDestSize.Width() && aDestSize.Height() ) 486 { 487 Size aTmpPrefSize( pOut->LogicToPixel( GetPrefSize(), aDrawMap ) ); 488 GDIMetaFile* pMtf = pOut->GetConnectMetaFile(); 489 490 if( !aTmpPrefSize.Width() ) 491 aTmpPrefSize.Width() = aDestSize.Width(); 492 493 if( !aTmpPrefSize.Height() ) 494 aTmpPrefSize.Height() = aDestSize.Height(); 495 496 Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() ); 497 Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() ); 498 499 aScaleX *= aDrawMap.GetScaleX(); aDrawMap.SetScaleX( aScaleX ); 500 aScaleY *= aDrawMap.GetScaleY(); aDrawMap.SetScaleY( aScaleY ); 501 502 // #i47260# Convert logical output position to offset within 503 // the metafile's mapmode. Therefore, disable pixel offset on 504 // outdev, it's inverse mnOutOffLogicX/Y is calculated for a 505 // different mapmode (the one currently set on pOut, that is) 506 // - thus, aDrawMap's origin would generally be wrong. And 507 // even _if_ aDrawMap is similar to pOutDev's current mapmode, 508 // it's _still_ undesirable to have pixel offset unequal zero, 509 // because one would still get round-off errors (the 510 // round-trip error for LogicToPixel( PixelToLogic() ) was the 511 // reason for having pixel offset in the first place). 512 const Size& rOldOffset( pOut->GetPixelOffset() ); 513 const Size aEmptySize; 514 pOut->SetPixelOffset( aEmptySize ); 515 aDrawMap.SetOrigin( pOut->PixelToLogic( pOut->LogicToPixel( rPos ), aDrawMap ) ); 516 pOut->SetPixelOffset( rOldOffset ); 517 518 pOut->Push(); 519 520 if ( pMtf && pMtf->IsRecord() && ( pOut->GetOutDevType() != OUTDEV_PRINTER ) ) 521 pOut->SetRelativeMapMode( aDrawMap ); 522 else 523 pOut->SetMapMode( aDrawMap ); 524 525 // #i23407# Set backwards-compatible text language and layout mode 526 // This is necessary, since old metafiles don't even know of these 527 // recent add-ons. Newer metafiles must of course explicitely set 528 // those states. 529 pOut->SetLayoutMode( 0 ); 530 pOut->SetDigitLanguage( 0 ); 531 532 Play( pOut, nPos ); 533 534 pOut->Pop(); 535 } 536 } 537 538 // ------------------------------------------------------------------------ 539 540 void GDIMetaFile::Pause( sal_Bool _bPause ) 541 { 542 if( bRecord ) 543 { 544 if( _bPause ) 545 { 546 if( !bPause ) 547 Linker( pOutDev, sal_False ); 548 } 549 else 550 { 551 if( bPause ) 552 Linker( pOutDev, sal_True ); 553 } 554 555 bPause = _bPause; 556 } 557 } 558 559 // ------------------------------------------------------------------------ 560 561 void GDIMetaFile::Stop() 562 { 563 if( bRecord ) 564 { 565 bRecord = sal_False; 566 567 if( !bPause ) 568 Linker( pOutDev, sal_False ); 569 else 570 bPause = sal_False; 571 } 572 } 573 574 // ------------------------------------------------------------------------ 575 576 void GDIMetaFile::WindStart() 577 { 578 if( !bRecord ) 579 First(); 580 } 581 582 // ------------------------------------------------------------------------ 583 584 void GDIMetaFile::WindEnd() 585 { 586 if( !bRecord ) 587 Last(); 588 } 589 590 // ------------------------------------------------------------------------ 591 592 void GDIMetaFile::Wind( sal_uLong nActionPos ) 593 { 594 if( !bRecord ) 595 Seek( nActionPos ); 596 } 597 598 // ------------------------------------------------------------------------ 599 600 void GDIMetaFile::WindPrev() 601 { 602 if( !bRecord ) 603 Prev(); 604 } 605 606 // ------------------------------------------------------------------------ 607 608 void GDIMetaFile::WindNext() 609 { 610 if( !bRecord ) 611 Next(); 612 } 613 614 // ------------------------------------------------------------------------ 615 616 void GDIMetaFile::AddAction( MetaAction* pAction ) 617 { 618 Insert( pAction, LIST_APPEND ); 619 620 if( pPrev ) 621 { 622 pAction->Duplicate(); 623 pPrev->AddAction( pAction ); 624 } 625 } 626 627 // ------------------------------------------------------------------------ 628 629 void GDIMetaFile::AddAction( MetaAction* pAction, sal_uLong nPos ) 630 { 631 Insert( pAction, nPos ); 632 633 if( pPrev ) 634 { 635 pAction->Duplicate(); 636 pPrev->AddAction( pAction, nPos ); 637 } 638 } 639 640 // ------------------------------------------------------------------------ 641 642 // @since #110496# 643 void GDIMetaFile::RemoveAction( sal_uLong nPos ) 644 { 645 Remove( nPos ); 646 647 if( pPrev ) 648 pPrev->RemoveAction( nPos ); 649 } 650 651 // ------------------------------------------------------------------------ 652 653 MetaAction* GDIMetaFile::CopyAction( sal_uLong nPos ) const 654 { 655 return ( (MetaAction*) GetObject( nPos ) )->Clone(); 656 } 657 658 // ------------------------------------------------------------------------ 659 660 sal_uLong GDIMetaFile::GetActionPos( const String& rLabel ) 661 { 662 ImpLabel* pLabel = NULL; 663 664 if( pLabelList ) 665 pLabel = pLabelList->ImplGetLabel( pLabelList->ImplGetLabelPos( rLabel ) ); 666 else 667 pLabel = NULL; 668 669 return( pLabel ? pLabel->nActionPos : METAFILE_LABEL_NOTFOUND ); 670 } 671 672 // ------------------------------------------------------------------------ 673 674 sal_Bool GDIMetaFile::InsertLabel( const String& rLabel, sal_uLong nActionPos ) 675 { 676 sal_Bool bRet = sal_False; 677 678 if( !pLabelList ) 679 pLabelList = new ImpLabelList; 680 681 if( pLabelList->ImplGetLabelPos( rLabel ) == METAFILE_LABEL_NOTFOUND ) 682 { 683 pLabelList->ImplInsert( new ImpLabel( rLabel, nActionPos ) ); 684 bRet = sal_True; 685 } 686 687 return bRet; 688 } 689 690 // ------------------------------------------------------------------------ 691 692 void GDIMetaFile::RemoveLabel( const String& rLabel ) 693 { 694 if( pLabelList ) 695 { 696 const sal_uLong nLabelPos = pLabelList->ImplGetLabelPos( rLabel ); 697 698 if( nLabelPos != METAFILE_LABEL_NOTFOUND ) 699 delete pLabelList->ImplRemove( nLabelPos ); 700 } 701 } 702 703 // ------------------------------------------------------------------------ 704 705 void GDIMetaFile::RenameLabel( const String& rLabel, const String& rNewLabel ) 706 { 707 if( pLabelList ) 708 { 709 const sal_uLong nLabelPos = pLabelList->ImplGetLabelPos( rLabel ); 710 711 if ( nLabelPos != METAFILE_LABEL_NOTFOUND ) 712 pLabelList->ImplGetLabel( nLabelPos )->aLabelName = rNewLabel; 713 } 714 } 715 716 // ------------------------------------------------------------------------ 717 718 sal_uLong GDIMetaFile::GetLabelCount() const 719 { 720 return( pLabelList ? pLabelList->ImplCount() : 0UL ); 721 } 722 723 // ------------------------------------------------------------------------ 724 725 String GDIMetaFile::GetLabel( sal_uLong nLabel ) 726 { 727 String aString; 728 729 if( pLabelList ) 730 { 731 const ImpLabel* pLabel = pLabelList->ImplGetLabel( nLabel ); 732 733 if( pLabel ) 734 aString = pLabel->aLabelName; 735 } 736 737 return aString; 738 } 739 740 // ------------------------------------------------------------------------ 741 742 sal_Bool GDIMetaFile::SaveStatus() 743 { 744 if ( bRecord ) 745 { 746 if ( bPause ) 747 Linker( pOutDev, sal_True ); 748 749 AddAction( new MetaLineColorAction( pOutDev->GetLineColor(), 750 pOutDev->IsLineColor() ) ); 751 AddAction( new MetaFillColorAction( pOutDev->GetFillColor(), 752 pOutDev->IsFillColor() ) ); 753 AddAction( new MetaFontAction( pOutDev->GetFont() ) ); 754 AddAction( new MetaTextColorAction( pOutDev->GetTextColor() ) ); 755 AddAction( new MetaTextFillColorAction( pOutDev->GetTextFillColor(), 756 pOutDev->IsTextFillColor() ) ); 757 AddAction( new MetaTextLineColorAction( pOutDev->GetTextLineColor(), 758 pOutDev->IsTextLineColor() ) ); 759 AddAction( new MetaOverlineColorAction( pOutDev->GetOverlineColor(), 760 pOutDev->IsOverlineColor() ) ); 761 AddAction( new MetaTextAlignAction( pOutDev->GetTextAlign() ) ); 762 AddAction( new MetaRasterOpAction( pOutDev->GetRasterOp() ) ); 763 AddAction( new MetaMapModeAction( pOutDev->GetMapMode() ) ); 764 AddAction( new MetaClipRegionAction( pOutDev->GetClipRegion(), 765 pOutDev->IsClipRegion() ) ); 766 767 if ( bPause ) 768 Linker( pOutDev, sal_False ); 769 770 return sal_True; 771 } 772 else 773 return sal_False; 774 } 775 776 // ------------------------------------------------------------------------ 777 778 sal_Bool GDIMetaFile::Mirror( sal_uLong nMirrorFlags ) 779 { 780 const Size aOldPrefSize( GetPrefSize() ); 781 long nMoveX, nMoveY; 782 double fScaleX, fScaleY; 783 sal_Bool bRet; 784 785 if( nMirrorFlags & MTF_MIRROR_HORZ ) 786 nMoveX = VOS_ABS( aOldPrefSize.Width() ) - 1, fScaleX = -1.0; 787 else 788 nMoveX = 0, fScaleX = 1.0; 789 790 if( nMirrorFlags & MTF_MIRROR_VERT ) 791 nMoveY = VOS_ABS( aOldPrefSize.Height() ) - 1, fScaleY = -1.0; 792 else 793 nMoveY = 0, fScaleY = 1.0; 794 795 if( ( fScaleX != 1.0 ) || ( fScaleY != 1.0 ) ) 796 { 797 Scale( fScaleX, fScaleY ); 798 Move( nMoveX, nMoveY ); 799 SetPrefSize( aOldPrefSize ); 800 bRet = sal_True; 801 } 802 else 803 bRet = sal_False; 804 805 return bRet; 806 } 807 808 // ------------------------------------------------------------------------ 809 810 void GDIMetaFile::Move( long nX, long nY ) 811 { 812 const Size aBaseOffset( nX, nY ); 813 Size aOffset( aBaseOffset ); 814 VirtualDevice aMapVDev; 815 816 aMapVDev.EnableOutput( sal_False ); 817 aMapVDev.SetMapMode( GetPrefMapMode() ); 818 819 for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() ) 820 { 821 const long nType = pAct->GetType(); 822 MetaAction* pModAct; 823 824 if( pAct->GetRefCount() > 1 ) 825 { 826 Replace( pModAct = pAct->Clone(), GetCurPos() ); 827 pAct->Delete(); 828 } 829 else 830 pModAct = pAct; 831 832 if( ( META_MAPMODE_ACTION == nType ) || 833 ( META_PUSH_ACTION == nType ) || 834 ( META_POP_ACTION == nType ) ) 835 { 836 pModAct->Execute( &aMapVDev ); 837 aOffset = aMapVDev.LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev.GetMapMode() ); 838 } 839 840 pModAct->Move( aOffset.Width(), aOffset.Height() ); 841 } 842 } 843 844 void GDIMetaFile::Move( long nX, long nY, long nDPIX, long nDPIY ) 845 { 846 const Size aBaseOffset( nX, nY ); 847 Size aOffset( aBaseOffset ); 848 VirtualDevice aMapVDev; 849 850 aMapVDev.EnableOutput( sal_False ); 851 aMapVDev.SetReferenceDevice( nDPIX, nDPIY ); 852 aMapVDev.SetMapMode( GetPrefMapMode() ); 853 854 for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() ) 855 { 856 const long nType = pAct->GetType(); 857 MetaAction* pModAct; 858 859 if( pAct->GetRefCount() > 1 ) 860 { 861 Replace( pModAct = pAct->Clone(), GetCurPos() ); 862 pAct->Delete(); 863 } 864 else 865 pModAct = pAct; 866 867 if( ( META_MAPMODE_ACTION == nType ) || 868 ( META_PUSH_ACTION == nType ) || 869 ( META_POP_ACTION == nType ) ) 870 { 871 pModAct->Execute( &aMapVDev ); 872 if( aMapVDev.GetMapMode().GetMapUnit() == MAP_PIXEL ) 873 { 874 aOffset = aMapVDev.LogicToPixel( aBaseOffset, GetPrefMapMode() ); 875 MapMode aMap( aMapVDev.GetMapMode() ); 876 aOffset.Width() = static_cast<long>(aOffset.Width() * (double)aMap.GetScaleX()); 877 aOffset.Height() = static_cast<long>(aOffset.Height() * (double)aMap.GetScaleY()); 878 } 879 else 880 aOffset = aMapVDev.LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev.GetMapMode() ); 881 } 882 883 pModAct->Move( aOffset.Width(), aOffset.Height() ); 884 } 885 } 886 887 // ------------------------------------------------------------------------ 888 889 void GDIMetaFile::Scale( double fScaleX, double fScaleY ) 890 { 891 for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() ) 892 { 893 MetaAction* pModAct; 894 895 if( pAct->GetRefCount() > 1 ) 896 { 897 Replace( pModAct = pAct->Clone(), GetCurPos() ); 898 pAct->Delete(); 899 } 900 else 901 pModAct = pAct; 902 903 pModAct->Scale( fScaleX, fScaleY ); 904 } 905 906 aPrefSize.Width() = FRound( aPrefSize.Width() * fScaleX ); 907 aPrefSize.Height() = FRound( aPrefSize.Height() * fScaleY ); 908 } 909 910 // ------------------------------------------------------------------------ 911 912 void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY ) 913 { 914 Scale( (double) rScaleX, (double) rScaleY ); 915 } 916 917 // ------------------------------------------------------------------------ 918 919 void GDIMetaFile::Clip( const Rectangle& i_rClipRect ) 920 { 921 Rectangle aCurRect( i_rClipRect ); 922 VirtualDevice aMapVDev; 923 924 aMapVDev.EnableOutput( sal_False ); 925 aMapVDev.SetMapMode( GetPrefMapMode() ); 926 927 for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() ) 928 { 929 const long nType = pAct->GetType(); 930 931 if( ( META_MAPMODE_ACTION == nType ) || 932 ( META_PUSH_ACTION == nType ) || 933 ( META_POP_ACTION == nType ) ) 934 { 935 pAct->Execute( &aMapVDev ); 936 aCurRect = aMapVDev.LogicToLogic( i_rClipRect, GetPrefMapMode(), aMapVDev.GetMapMode() ); 937 } 938 else if( nType == META_CLIPREGION_ACTION ) 939 { 940 MetaClipRegionAction* pOldAct = (MetaClipRegionAction*)pAct; 941 Region aNewReg( aCurRect ); 942 if( pOldAct->IsClipping() ) 943 aNewReg.Intersect( pOldAct->GetRegion() ); 944 MetaClipRegionAction* pNewAct = new MetaClipRegionAction( aNewReg, sal_True ); 945 Replace( pNewAct, GetCurPos() ); 946 pOldAct->Delete(); 947 } 948 } 949 } 950 951 // ------------------------------------------------------------------------ 952 953 Point GDIMetaFile::ImplGetRotatedPoint( const Point& rPt, const Point& rRotatePt, 954 const Size& rOffset, double fSin, double fCos ) 955 { 956 const long nX = rPt.X() - rRotatePt.X(); 957 const long nY = rPt.Y() - rRotatePt.Y(); 958 959 return Point( FRound( fCos * nX + fSin * nY ) + rRotatePt.X() + rOffset.Width(), 960 -FRound( fSin * nX - fCos * nY ) + rRotatePt.Y() + rOffset.Height() ); 961 } 962 963 // ------------------------------------------------------------------------ 964 965 Polygon GDIMetaFile::ImplGetRotatedPolygon( const Polygon& rPoly, const Point& rRotatePt, 966 const Size& rOffset, double fSin, double fCos ) 967 { 968 Polygon aRet( rPoly ); 969 970 aRet.Rotate( rRotatePt, fSin, fCos ); 971 aRet.Move( rOffset.Width(), rOffset.Height() ); 972 973 return aRet; 974 } 975 976 // ------------------------------------------------------------------------ 977 978 PolyPolygon GDIMetaFile::ImplGetRotatedPolyPolygon( const PolyPolygon& rPolyPoly, const Point& rRotatePt, 979 const Size& rOffset, double fSin, double fCos ) 980 { 981 PolyPolygon aRet( rPolyPoly ); 982 983 aRet.Rotate( rRotatePt, fSin, fCos ); 984 aRet.Move( rOffset.Width(), rOffset.Height() ); 985 986 return aRet; 987 } 988 989 // ------------------------------------------------------------------------ 990 991 void GDIMetaFile::ImplAddGradientEx( GDIMetaFile& rMtf, 992 const OutputDevice& rMapDev, 993 const PolyPolygon& rPolyPoly, 994 const Gradient& rGrad ) 995 { 996 // #105055# Generate comment, GradientEx and Gradient actions 997 // (within DrawGradient) 998 VirtualDevice aVDev( rMapDev, 0 ); 999 aVDev.EnableOutput( sal_False ); 1000 GDIMetaFile aGradMtf; 1001 1002 aGradMtf.Record( &aVDev ); 1003 aVDev.DrawGradient( rPolyPoly, rGrad ); 1004 aGradMtf.Stop(); 1005 1006 int i, nAct( aGradMtf.GetActionCount() ); 1007 for( i=0; i<nAct; ++i ) 1008 { 1009 MetaAction* pMetaAct = aGradMtf.GetAction(i); 1010 pMetaAct->Duplicate(); 1011 rMtf.AddAction( pMetaAct ); 1012 } 1013 } 1014 1015 // ------------------------------------------------------------------------ 1016 1017 void GDIMetaFile::Rotate( long nAngle10 ) 1018 { 1019 nAngle10 %= 3600L; 1020 nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10; 1021 1022 if( nAngle10 ) 1023 { 1024 GDIMetaFile aMtf; 1025 VirtualDevice aMapVDev; 1026 const double fAngle = F_PI1800 * nAngle10; 1027 const double fSin = sin( fAngle ); 1028 const double fCos = cos( fAngle ); 1029 Rectangle aRect=Rectangle( Point(), GetPrefSize() ); 1030 Polygon aPoly( aRect ); 1031 1032 aPoly.Rotate( Point(), fSin, fCos ); 1033 1034 aMapVDev.EnableOutput( sal_False ); 1035 aMapVDev.SetMapMode( GetPrefMapMode() ); 1036 1037 const Rectangle aNewBound( aPoly.GetBoundRect() ); 1038 1039 const Point aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() ); 1040 const Size aOffset( -aNewBound.Left(), -aNewBound.Top() ); 1041 1042 Point aRotAnchor( aOrigin ); 1043 Size aRotOffset( aOffset ); 1044 1045 for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() ) 1046 { 1047 const sal_uInt16 nActionType = pAction->GetType(); 1048 1049 switch( nActionType ) 1050 { 1051 case( META_PIXEL_ACTION ): 1052 { 1053 MetaPixelAction* pAct = (MetaPixelAction*) pAction; 1054 aMtf.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ), 1055 pAct->GetColor() ) ); 1056 } 1057 break; 1058 1059 case( META_POINT_ACTION ): 1060 { 1061 MetaPointAction* pAct = (MetaPointAction*) pAction; 1062 aMtf.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ) ) ); 1063 } 1064 break; 1065 1066 case( META_LINE_ACTION ): 1067 { 1068 MetaLineAction* pAct = (MetaLineAction*) pAction; 1069 aMtf.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ), 1070 ImplGetRotatedPoint( pAct->GetEndPoint(), aRotAnchor, aRotOffset, fSin, fCos ), 1071 pAct->GetLineInfo() ) ); 1072 } 1073 break; 1074 1075 case( META_RECT_ACTION ): 1076 { 1077 MetaRectAction* pAct = (MetaRectAction*) pAction; 1078 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) ); 1079 } 1080 break; 1081 1082 case( META_ROUNDRECT_ACTION ): 1083 { 1084 MetaRoundRectAction* pAct = (MetaRoundRectAction*) pAction; 1085 const Polygon aRoundRectPoly( pAct->GetRect(), pAct->GetHorzRound(), pAct->GetVertRound() ); 1086 1087 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) ); 1088 } 1089 break; 1090 1091 case( META_ELLIPSE_ACTION ): 1092 { 1093 MetaEllipseAction* pAct = (MetaEllipseAction*) pAction; 1094 const Polygon aEllipsePoly( pAct->GetRect().Center(), pAct->GetRect().GetWidth() >> 1, pAct->GetRect().GetHeight() >> 1 ); 1095 1096 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) ); 1097 } 1098 break; 1099 1100 case( META_ARC_ACTION ): 1101 { 1102 MetaArcAction* pAct = (MetaArcAction*) pAction; 1103 const Polygon aArcPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_ARC ); 1104 1105 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) ); 1106 } 1107 break; 1108 1109 case( META_PIE_ACTION ): 1110 { 1111 MetaPieAction* pAct = (MetaPieAction*) pAction; 1112 const Polygon aPiePoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_PIE ); 1113 1114 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) ); 1115 } 1116 break; 1117 1118 case( META_CHORD_ACTION ): 1119 { 1120 MetaChordAction* pAct = (MetaChordAction*) pAction; 1121 const Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_CHORD ); 1122 1123 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) ); 1124 } 1125 break; 1126 1127 case( META_POLYLINE_ACTION ): 1128 { 1129 MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction; 1130 aMtf.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->GetLineInfo() ) ); 1131 } 1132 break; 1133 1134 case( META_POLYGON_ACTION ): 1135 { 1136 MetaPolygonAction* pAct = (MetaPolygonAction*) pAction; 1137 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ); 1138 } 1139 break; 1140 1141 case( META_POLYPOLYGON_ACTION ): 1142 { 1143 MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction; 1144 aMtf.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ); 1145 } 1146 break; 1147 1148 case( META_TEXT_ACTION ): 1149 { 1150 MetaTextAction* pAct = (MetaTextAction*) pAction; 1151 aMtf.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ), 1152 pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) ); 1153 } 1154 break; 1155 1156 case( META_TEXTARRAY_ACTION ): 1157 { 1158 MetaTextArrayAction* pAct = (MetaTextArrayAction*) pAction; 1159 aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ), 1160 pAct->GetText(), pAct->GetDXArray(), pAct->GetIndex(), pAct->GetLen() ) ); 1161 } 1162 break; 1163 1164 case( META_STRETCHTEXT_ACTION ): 1165 { 1166 MetaStretchTextAction* pAct = (MetaStretchTextAction*) pAction; 1167 aMtf.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ), 1168 pAct->GetWidth(), pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) ); 1169 } 1170 break; 1171 1172 case( META_TEXTLINE_ACTION ): 1173 { 1174 MetaTextLineAction* pAct = (MetaTextLineAction*) pAction; 1175 aMtf.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ), 1176 pAct->GetWidth(), pAct->GetStrikeout(), pAct->GetUnderline(), pAct->GetOverline() ) ); 1177 } 1178 break; 1179 1180 case( META_BMPSCALE_ACTION ): 1181 { 1182 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction; 1183 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) ); 1184 Rectangle aBmpRect( aBmpPoly.GetBoundRect() ); 1185 BitmapEx aBmpEx( pAct->GetBitmap() ); 1186 1187 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) ); 1188 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), 1189 aBmpEx ) ); 1190 } 1191 break; 1192 1193 case( META_BMPSCALEPART_ACTION ): 1194 { 1195 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction; 1196 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) ); 1197 Rectangle aBmpRect( aBmpPoly.GetBoundRect() ); 1198 BitmapEx aBmpEx( pAct->GetBitmap() ); 1199 1200 aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) ); 1201 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) ); 1202 1203 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) ); 1204 } 1205 break; 1206 1207 case( META_BMPEXSCALE_ACTION ): 1208 { 1209 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction; 1210 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) ); 1211 Rectangle aBmpRect( aBmpPoly.GetBoundRect() ); 1212 BitmapEx aBmpEx( pAct->GetBitmapEx() ); 1213 1214 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) ); 1215 1216 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) ); 1217 } 1218 break; 1219 1220 case( META_BMPEXSCALEPART_ACTION ): 1221 { 1222 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction; 1223 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) ); 1224 Rectangle aBmpRect( aBmpPoly.GetBoundRect() ); 1225 BitmapEx aBmpEx( pAct->GetBitmapEx() ); 1226 1227 aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) ); 1228 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) ); 1229 1230 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) ); 1231 } 1232 break; 1233 1234 case( META_GRADIENT_ACTION ): 1235 { 1236 MetaGradientAction* pAct = (MetaGradientAction*) pAction; 1237 1238 ImplAddGradientEx( aMtf, aMapVDev, 1239 ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ), 1240 pAct->GetGradient() ); 1241 } 1242 break; 1243 1244 case( META_GRADIENTEX_ACTION ): 1245 { 1246 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction; 1247 aMtf.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), 1248 pAct->GetGradient() ) ); 1249 } 1250 break; 1251 1252 // #105055# Handle gradientex comment block correctly 1253 case( META_COMMENT_ACTION ): 1254 { 1255 MetaCommentAction* pCommentAct = (MetaCommentAction*) pAction; 1256 if( pCommentAct->GetComment().Equals( "XGRAD_SEQ_BEGIN" ) ) 1257 { 1258 int nBeginComments( 1 ); 1259 pAction = (MetaAction*) Next(); 1260 1261 // skip everything, except gradientex action 1262 while( pAction ) 1263 { 1264 const sal_uInt16 nType = pAction->GetType(); 1265 1266 if( META_GRADIENTEX_ACTION == nType ) 1267 { 1268 // Add rotated gradientex 1269 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction; 1270 ImplAddGradientEx( aMtf, aMapVDev, 1271 ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), 1272 pAct->GetGradient() ); 1273 } 1274 else if( META_COMMENT_ACTION == nType) 1275 { 1276 MetaCommentAction* pAct = (MetaCommentAction*) pAction; 1277 if( pAct->GetComment().Equals( "XGRAD_SEQ_END" ) ) 1278 { 1279 // handle nested blocks 1280 --nBeginComments; 1281 1282 // gradientex comment block: end reached, done. 1283 if( !nBeginComments ) 1284 break; 1285 } 1286 else if( pAct->GetComment().Equals( "XGRAD_SEQ_BEGIN" ) ) 1287 { 1288 // handle nested blocks 1289 ++nBeginComments; 1290 } 1291 1292 } 1293 1294 pAction = (MetaAction*) Next(); 1295 } 1296 } 1297 else 1298 { 1299 sal_Bool bPathStroke = pCommentAct->GetComment().Equals( "XPATHSTROKE_SEQ_BEGIN" ); 1300 if ( bPathStroke || pCommentAct->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) ) 1301 { 1302 if ( pCommentAct->GetDataSize() ) 1303 { 1304 SvMemoryStream aMemStm( (void*)pCommentAct->GetData(), pCommentAct->GetDataSize(), STREAM_READ ); 1305 SvMemoryStream aDest; 1306 if ( bPathStroke ) 1307 { 1308 SvtGraphicStroke aStroke; 1309 aMemStm >> aStroke; 1310 Polygon aPath; 1311 aStroke.getPath( aPath ); 1312 aStroke.setPath( ImplGetRotatedPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) ); 1313 aDest << aStroke; 1314 aMtf.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0, 1315 static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) ); 1316 } 1317 else 1318 { 1319 SvtGraphicFill aFill; 1320 aMemStm >> aFill; 1321 PolyPolygon aPath; 1322 aFill.getPath( aPath ); 1323 aFill.setPath( ImplGetRotatedPolyPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) ); 1324 aDest << aFill; 1325 aMtf.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0, 1326 static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) ); 1327 } 1328 } 1329 } 1330 else if ( pCommentAct->GetComment().Equals( "XPATHSTROKE_SEQ_END" ) 1331 || pCommentAct->GetComment().Equals( "XPATHFILL_SEQ_END" ) ) 1332 { 1333 pAction->Execute( &aMapVDev ); 1334 pAction->Duplicate(); 1335 aMtf.AddAction( pAction ); 1336 } 1337 } 1338 } 1339 break; 1340 1341 case( META_HATCH_ACTION ): 1342 { 1343 MetaHatchAction* pAct = (MetaHatchAction*) pAction; 1344 Hatch aHatch( pAct->GetHatch() ); 1345 1346 aHatch.SetAngle( aHatch.GetAngle() + (sal_uInt16) nAngle10 ); 1347 aMtf.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), 1348 aHatch ) ); 1349 } 1350 break; 1351 1352 case( META_TRANSPARENT_ACTION ): 1353 { 1354 MetaTransparentAction* pAct = (MetaTransparentAction*) pAction; 1355 aMtf.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), 1356 pAct->GetTransparence() ) ); 1357 } 1358 break; 1359 1360 case( META_FLOATTRANSPARENT_ACTION ): 1361 { 1362 MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction; 1363 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() ); 1364 Polygon aMtfPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) ); 1365 Rectangle aMtfRect( aMtfPoly.GetBoundRect() ); 1366 1367 aTransMtf.Rotate( nAngle10 ); 1368 aMtf.AddAction( new MetaFloatTransparentAction( aTransMtf, aMtfRect.TopLeft(), aMtfRect.GetSize(), 1369 pAct->GetGradient() ) ); 1370 } 1371 break; 1372 1373 case( META_EPS_ACTION ): 1374 { 1375 MetaEPSAction* pAct = (MetaEPSAction*) pAction; 1376 GDIMetaFile aEPSMtf( pAct->GetSubstitute() ); 1377 Polygon aEPSPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) ); 1378 Rectangle aEPSRect( aEPSPoly.GetBoundRect() ); 1379 1380 aEPSMtf.Rotate( nAngle10 ); 1381 aMtf.AddAction( new MetaEPSAction( aEPSRect.TopLeft(), aEPSRect.GetSize(), 1382 pAct->GetLink(), aEPSMtf ) ); 1383 } 1384 break; 1385 1386 case( META_CLIPREGION_ACTION ): 1387 { 1388 MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction; 1389 1390 if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygon() ) 1391 aMtf.AddAction( new MetaClipRegionAction( Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), sal_True ) ); 1392 else 1393 { 1394 pAction->Duplicate(); 1395 aMtf.AddAction( pAction ); 1396 } 1397 } 1398 break; 1399 1400 case( META_ISECTRECTCLIPREGION_ACTION ): 1401 { 1402 MetaISectRectClipRegionAction* pAct = (MetaISectRectClipRegionAction*) pAction; 1403 aMtf.AddAction( new MetaISectRegionClipRegionAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) ); 1404 } 1405 break; 1406 1407 case( META_ISECTREGIONCLIPREGION_ACTION ): 1408 { 1409 MetaISectRegionClipRegionAction* pAct = (MetaISectRegionClipRegionAction*) pAction; 1410 const Region& rRegion = pAct->GetRegion(); 1411 1412 if( rRegion.HasPolyPolygon() ) 1413 aMtf.AddAction( new MetaISectRegionClipRegionAction( Region( ImplGetRotatedPolyPolygon( rRegion.GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) ); 1414 else 1415 { 1416 pAction->Duplicate(); 1417 aMtf.AddAction( pAction ); 1418 } 1419 } 1420 break; 1421 1422 case( META_REFPOINT_ACTION ): 1423 { 1424 MetaRefPointAction* pAct = (MetaRefPointAction*) pAction; 1425 aMtf.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct->GetRefPoint(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->IsSetting() ) ); 1426 } 1427 break; 1428 1429 case( META_FONT_ACTION ): 1430 { 1431 MetaFontAction* pAct = (MetaFontAction*) pAction; 1432 Font aFont( pAct->GetFont() ); 1433 1434 aFont.SetOrientation( aFont.GetOrientation() + (sal_uInt16) nAngle10 ); 1435 aMtf.AddAction( new MetaFontAction( aFont ) ); 1436 } 1437 break; 1438 1439 case( META_BMP_ACTION ): 1440 case( META_BMPEX_ACTION ): 1441 case( META_MASK_ACTION ): 1442 case( META_MASKSCALE_ACTION ): 1443 case( META_MASKSCALEPART_ACTION ): 1444 case( META_WALLPAPER_ACTION ): 1445 case( META_TEXTRECT_ACTION ): 1446 case( META_MOVECLIPREGION_ACTION ): 1447 { 1448 DBG_ERROR( "GDIMetaFile::Rotate(): unsupported action" ); 1449 } 1450 break; 1451 1452 case( META_RENDERGRAPHIC_ACTION ): 1453 { 1454 OSL_TRACE( "Rotate not supported for RenderGraphic MetaActions yet" ); 1455 1456 pAction->Duplicate(); 1457 aMtf.AddAction( pAction ); 1458 } 1459 break; 1460 1461 default: 1462 { 1463 pAction->Execute( &aMapVDev ); 1464 pAction->Duplicate(); 1465 aMtf.AddAction( pAction ); 1466 1467 // update rotation point and offset, if necessary 1468 if( ( META_MAPMODE_ACTION == nActionType ) || 1469 ( META_PUSH_ACTION == nActionType ) || 1470 ( META_POP_ACTION == nActionType ) ) 1471 { 1472 aRotAnchor = aMapVDev.LogicToLogic( aOrigin, aPrefMapMode, aMapVDev.GetMapMode() ); 1473 aRotOffset = aMapVDev.LogicToLogic( aOffset, aPrefMapMode, aMapVDev.GetMapMode() ); 1474 } 1475 } 1476 break; 1477 } 1478 } 1479 1480 aMtf.aPrefMapMode = aPrefMapMode; 1481 aMtf.aPrefSize = aNewBound.GetSize(); 1482 1483 *this = aMtf; 1484 } 1485 } 1486 1487 // ------------------------------------------------------------------------ 1488 1489 static void ImplActionBounds( Rectangle& o_rOutBounds, 1490 const Rectangle& i_rInBounds, 1491 const std::vector<Rectangle>& i_rClipStack ) 1492 { 1493 Rectangle aBounds( i_rInBounds ); 1494 if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() ) 1495 aBounds.Intersection( i_rClipStack.back() ); 1496 if( ! aBounds.IsEmpty() ) 1497 { 1498 if( ! o_rOutBounds.IsEmpty() ) 1499 o_rOutBounds.Union( aBounds ); 1500 else 1501 o_rOutBounds = aBounds; 1502 } 1503 } 1504 1505 Rectangle GDIMetaFile::GetBoundRect( OutputDevice& i_rReference ) 1506 { 1507 GDIMetaFile aMtf; 1508 VirtualDevice aMapVDev( i_rReference ); 1509 1510 aMapVDev.EnableOutput( sal_False ); 1511 aMapVDev.SetMapMode( GetPrefMapMode() ); 1512 1513 std::vector<Rectangle> aClipStack( 1, Rectangle() ); 1514 std::vector<sal_uInt16> aPushFlagStack; 1515 1516 Rectangle aBound; 1517 1518 for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() ) 1519 { 1520 const sal_uInt16 nActionType = pAction->GetType(); 1521 1522 switch( nActionType ) 1523 { 1524 case( META_PIXEL_ACTION ): 1525 { 1526 MetaPixelAction* pAct = (MetaPixelAction*) pAction; 1527 ImplActionBounds( aBound, 1528 Rectangle( aMapVDev.LogicToLogic( pAct->GetPoint(), aMapVDev.GetMapMode(), GetPrefMapMode() ), 1529 aMapVDev.PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ), 1530 aClipStack ); 1531 } 1532 break; 1533 1534 case( META_POINT_ACTION ): 1535 { 1536 MetaPointAction* pAct = (MetaPointAction*) pAction; 1537 ImplActionBounds( aBound, 1538 Rectangle( aMapVDev.LogicToLogic( pAct->GetPoint(), aMapVDev.GetMapMode(), GetPrefMapMode() ), 1539 aMapVDev.PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ), 1540 aClipStack ); 1541 } 1542 break; 1543 1544 case( META_LINE_ACTION ): 1545 { 1546 MetaLineAction* pAct = (MetaLineAction*) pAction; 1547 Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() ); 1548 Rectangle aRect( aP1, aP2 ); 1549 aRect.Justify(); 1550 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1551 } 1552 break; 1553 1554 case( META_RECT_ACTION ): 1555 { 1556 MetaRectAction* pAct = (MetaRectAction*) pAction; 1557 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1558 } 1559 break; 1560 1561 case( META_ROUNDRECT_ACTION ): 1562 { 1563 MetaRoundRectAction* pAct = (MetaRoundRectAction*) pAction; 1564 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1565 } 1566 break; 1567 1568 case( META_ELLIPSE_ACTION ): 1569 { 1570 MetaEllipseAction* pAct = (MetaEllipseAction*) pAction; 1571 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1572 } 1573 break; 1574 1575 case( META_ARC_ACTION ): 1576 { 1577 MetaArcAction* pAct = (MetaArcAction*) pAction; 1578 // FIXME: this is imprecise 1579 // e.g. for small arcs the whole rectangle is WAY too large 1580 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1581 } 1582 break; 1583 1584 case( META_PIE_ACTION ): 1585 { 1586 MetaPieAction* pAct = (MetaPieAction*) pAction; 1587 // FIXME: this is imprecise 1588 // e.g. for small arcs the whole rectangle is WAY too large 1589 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1590 } 1591 break; 1592 1593 case( META_CHORD_ACTION ): 1594 { 1595 MetaChordAction* pAct = (MetaChordAction*) pAction; 1596 // FIXME: this is imprecise 1597 // e.g. for small arcs the whole rectangle is WAY too large 1598 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1599 } 1600 break; 1601 1602 case( META_POLYLINE_ACTION ): 1603 { 1604 MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction; 1605 Rectangle aRect( pAct->GetPolygon().GetBoundRect() ); 1606 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1607 } 1608 break; 1609 1610 case( META_POLYGON_ACTION ): 1611 { 1612 MetaPolygonAction* pAct = (MetaPolygonAction*) pAction; 1613 Rectangle aRect( pAct->GetPolygon().GetBoundRect() ); 1614 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1615 } 1616 break; 1617 1618 case( META_POLYPOLYGON_ACTION ): 1619 { 1620 MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction; 1621 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() ); 1622 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1623 } 1624 break; 1625 1626 case( META_TEXT_ACTION ): 1627 { 1628 MetaTextAction* pAct = (MetaTextAction*) pAction; 1629 Rectangle aRect; 1630 // hdu said base = index 1631 aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() ); 1632 Point aPt( pAct->GetPoint() ); 1633 aRect.Move( aPt.X(), aPt.Y() ); 1634 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1635 } 1636 break; 1637 1638 case( META_TEXTARRAY_ACTION ): 1639 { 1640 MetaTextArrayAction* pAct = (MetaTextArrayAction*) pAction; 1641 Rectangle aRect; 1642 // hdu said base = index 1643 aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(), 1644 0, pAct->GetDXArray() ); 1645 Point aPt( pAct->GetPoint() ); 1646 aRect.Move( aPt.X(), aPt.Y() ); 1647 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1648 } 1649 break; 1650 1651 case( META_STRETCHTEXT_ACTION ): 1652 { 1653 MetaStretchTextAction* pAct = (MetaStretchTextAction*) pAction; 1654 Rectangle aRect; 1655 // hdu said base = index 1656 aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(), 1657 pAct->GetWidth(), NULL ); 1658 Point aPt( pAct->GetPoint() ); 1659 aRect.Move( aPt.X(), aPt.Y() ); 1660 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1661 } 1662 break; 1663 1664 case( META_TEXTLINE_ACTION ): 1665 { 1666 MetaTextLineAction* pAct = (MetaTextLineAction*) pAction; 1667 // measure a test string to get ascend and descent right 1668 static const sal_Unicode pStr[] = { 0xc4, 0x67, 0 }; 1669 String aStr( pStr ); 1670 1671 Rectangle aRect; 1672 aMapVDev.GetTextBoundRect( aRect, aStr, 0, 0, aStr.Len(), 0, NULL ); 1673 Point aPt( pAct->GetStartPoint() ); 1674 aRect.Move( aPt.X(), aPt.Y() ); 1675 aRect.Right() = aRect.Left() + pAct->GetWidth(); 1676 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1677 } 1678 break; 1679 1680 case( META_BMPSCALE_ACTION ): 1681 { 1682 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction; 1683 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() ); 1684 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1685 } 1686 break; 1687 1688 case( META_BMPSCALEPART_ACTION ): 1689 { 1690 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction; 1691 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() ); 1692 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1693 } 1694 break; 1695 1696 case( META_BMPEXSCALE_ACTION ): 1697 { 1698 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction; 1699 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() ); 1700 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1701 } 1702 break; 1703 1704 case( META_BMPEXSCALEPART_ACTION ): 1705 { 1706 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction; 1707 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() ); 1708 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1709 } 1710 break; 1711 1712 case( META_GRADIENT_ACTION ): 1713 { 1714 MetaGradientAction* pAct = (MetaGradientAction*) pAction; 1715 Rectangle aRect( pAct->GetRect() ); 1716 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1717 } 1718 break; 1719 1720 case( META_GRADIENTEX_ACTION ): 1721 { 1722 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction; 1723 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() ); 1724 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1725 } 1726 break; 1727 1728 case( META_COMMENT_ACTION ): 1729 { 1730 // nothing to do 1731 }; 1732 break; 1733 1734 case( META_HATCH_ACTION ): 1735 { 1736 MetaHatchAction* pAct = (MetaHatchAction*) pAction; 1737 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() ); 1738 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1739 } 1740 break; 1741 1742 case( META_TRANSPARENT_ACTION ): 1743 { 1744 MetaTransparentAction* pAct = (MetaTransparentAction*) pAction; 1745 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() ); 1746 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1747 } 1748 break; 1749 1750 case( META_FLOATTRANSPARENT_ACTION ): 1751 { 1752 MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction; 1753 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() ); 1754 // get the bound rect of the contained metafile 1755 Rectangle aRect( aTransMtf.GetBoundRect( i_rReference ) ); 1756 // scale the rect now on the assumption that the correct top left of the metafile 1757 // (not its bounds !) is (0,0) 1758 Size aPSize( aTransMtf.GetPrefSize() ); 1759 aPSize = aMapVDev.LogicToLogic( aPSize, aTransMtf.GetPrefMapMode(), aMapVDev.GetMapMode() ); 1760 Size aActSize( pAct->GetSize() ); 1761 double fX = double(aActSize.Width())/double(aPSize.Width()); 1762 double fY = double(aActSize.Height())/double(aPSize.Height()); 1763 aRect.Left() = long(double(aRect.Left())*fX); 1764 aRect.Right() = long(double(aRect.Right())*fX); 1765 aRect.Top() = long(double(aRect.Top())*fY); 1766 aRect.Bottom() = long(double(aRect.Bottom())*fY); 1767 1768 // transform the rect to current VDev state 1769 aRect = aMapVDev.LogicToLogic( aRect, aTransMtf.GetPrefMapMode(), aMapVDev.GetMapMode() ); 1770 1771 ImplActionBounds( aBound, aRect, aClipStack ); 1772 } 1773 break; 1774 1775 case( META_EPS_ACTION ): 1776 { 1777 MetaEPSAction* pAct = (MetaEPSAction*) pAction; 1778 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() ); 1779 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1780 } 1781 break; 1782 1783 case( META_CLIPREGION_ACTION ): 1784 { 1785 MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction; 1786 if( pAct->IsClipping() ) 1787 aClipStack.back() = aMapVDev.LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ); 1788 else 1789 aClipStack.back() = Rectangle(); 1790 } 1791 break; 1792 1793 case( META_ISECTRECTCLIPREGION_ACTION ): 1794 { 1795 MetaISectRectClipRegionAction* pAct = (MetaISectRectClipRegionAction*) pAction; 1796 Rectangle aRect( aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ) ); 1797 if( aClipStack.back().IsEmpty() ) 1798 aClipStack.back() = aRect; 1799 else 1800 aClipStack.back().Intersection( aRect ); 1801 } 1802 break; 1803 1804 case( META_ISECTREGIONCLIPREGION_ACTION ): 1805 { 1806 MetaISectRegionClipRegionAction* pAct = (MetaISectRegionClipRegionAction*) pAction; 1807 Rectangle aRect( aMapVDev.LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ) ); 1808 if( aClipStack.back().IsEmpty() ) 1809 aClipStack.back() = aRect; 1810 else 1811 aClipStack.back().Intersection( aRect ); 1812 } 1813 break; 1814 1815 case( META_BMP_ACTION ): 1816 { 1817 MetaBmpAction* pAct = (MetaBmpAction*) pAction; 1818 Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmap().GetSizePixel() ) ); 1819 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1820 } 1821 break; 1822 1823 case( META_BMPEX_ACTION ): 1824 { 1825 MetaBmpExAction* pAct = (MetaBmpExAction*) pAction; 1826 Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) ); 1827 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1828 } 1829 break; 1830 1831 case( META_MASK_ACTION ): 1832 { 1833 MetaMaskAction* pAct = (MetaMaskAction*) pAction; 1834 Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmap().GetSizePixel() ) ); 1835 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1836 } 1837 break; 1838 1839 case( META_MASKSCALE_ACTION ): 1840 { 1841 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction; 1842 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() ); 1843 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1844 } 1845 break; 1846 1847 case( META_MASKSCALEPART_ACTION ): 1848 { 1849 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction; 1850 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() ); 1851 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1852 } 1853 break; 1854 1855 case( META_WALLPAPER_ACTION ): 1856 { 1857 MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction; 1858 Rectangle aRect( pAct->GetRect() ); 1859 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1860 } 1861 break; 1862 1863 case( META_TEXTRECT_ACTION ): 1864 { 1865 MetaTextRectAction* pAct = (MetaTextRectAction*) pAction; 1866 Rectangle aRect( pAct->GetRect() ); 1867 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1868 } 1869 break; 1870 1871 case( META_MOVECLIPREGION_ACTION ): 1872 { 1873 MetaMoveClipRegionAction* pAct = (MetaMoveClipRegionAction*) pAction; 1874 if( ! aClipStack.back().IsEmpty() ) 1875 { 1876 Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() ); 1877 aDelta = aMapVDev.LogicToLogic( aDelta, aMapVDev.GetMapMode(), GetPrefMapMode() ); 1878 aClipStack.back().Move( aDelta.Width(), aDelta.Width() ); 1879 } 1880 } 1881 break; 1882 1883 case( META_RENDERGRAPHIC_ACTION ): 1884 { 1885 MetaRenderGraphicAction* pAct = (MetaRenderGraphicAction*) pAction; 1886 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() ); 1887 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); 1888 } 1889 break; 1890 1891 default: 1892 { 1893 pAction->Execute( &aMapVDev ); 1894 1895 if( nActionType == META_PUSH_ACTION ) 1896 { 1897 MetaPushAction* pAct = (MetaPushAction*) pAction; 1898 aPushFlagStack.push_back( pAct->GetFlags() ); 1899 if( (aPushFlagStack.back() & PUSH_CLIPREGION) != 0 ) 1900 { 1901 Rectangle aRect( aClipStack.back() ); 1902 aClipStack.push_back( aRect ); 1903 } 1904 } 1905 else if( nActionType == META_POP_ACTION ) 1906 { 1907 // sanity check 1908 if( ! aPushFlagStack.empty() ) 1909 { 1910 if( (aPushFlagStack.back() & PUSH_CLIPREGION) != 0 ) 1911 { 1912 if( aClipStack.size() > 1 ) 1913 aClipStack.pop_back(); 1914 } 1915 aPushFlagStack.pop_back(); 1916 } 1917 } 1918 } 1919 break; 1920 } 1921 } 1922 return aBound; 1923 } 1924 1925 // ------------------------------------------------------------------------ 1926 1927 Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam ) 1928 { 1929 return Color( rColor.GetTransparency(), 1930 ( (const ImplColAdjustParam*) pColParam )->pMapR[ rColor.GetRed() ], 1931 ( (const ImplColAdjustParam*) pColParam )->pMapG[ rColor.GetGreen() ], 1932 ( (const ImplColAdjustParam*) pColParam )->pMapB[ rColor.GetBlue() ] ); 1933 1934 } 1935 1936 // ------------------------------------------------------------------------ 1937 1938 BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam ) 1939 { 1940 const ImplBmpAdjustParam* p = (const ImplBmpAdjustParam*) pBmpParam; 1941 BitmapEx aRet( rBmpEx ); 1942 1943 aRet.Adjust( p->nLuminancePercent, p->nContrastPercent, 1944 p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent, 1945 p->fGamma, p->bInvert ); 1946 1947 return aRet; 1948 } 1949 1950 // ------------------------------------------------------------------------ 1951 1952 Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam ) 1953 { 1954 sal_uInt8 cLum = rColor.GetLuminance(); 1955 1956 if( MTF_CONVERSION_1BIT_THRESHOLD == ( (const ImplColConvertParam*) pColParam )->eConversion ) 1957 cLum = ( cLum < 128 ) ? 0 : 255; 1958 1959 return Color( rColor.GetTransparency(), cLum, cLum, cLum ); 1960 } 1961 1962 // ------------------------------------------------------------------------ 1963 1964 BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam ) 1965 { 1966 BitmapEx aRet( rBmpEx ); 1967 1968 aRet.Convert( ( (const ImplBmpConvertParam*) pBmpParam )->eConversion ); 1969 1970 return aRet; 1971 } 1972 1973 // ------------------------------------------------------------------------ 1974 1975 Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam ) 1976 { 1977 return( ( (const ImplColMonoParam*) pColParam )->aColor ); 1978 } 1979 1980 // ------------------------------------------------------------------------ 1981 1982 BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam ) 1983 { 1984 BitmapPalette aPal( 3 ); 1985 1986 aPal[ 0 ] = Color( COL_BLACK ); 1987 aPal[ 1 ] = Color( COL_WHITE ); 1988 aPal[ 2 ] = ( (const ImplBmpMonoParam*) pBmpParam )->aColor; 1989 1990 Bitmap aBmp( rBmpEx.GetSizePixel(), 4, &aPal ); 1991 aBmp.Erase( ( (const ImplBmpMonoParam*) pBmpParam )->aColor ); 1992 1993 if( rBmpEx.IsAlpha() ) 1994 return BitmapEx( aBmp, rBmpEx.GetAlpha() ); 1995 else if( rBmpEx.IsTransparent() ) 1996 return BitmapEx( aBmp, rBmpEx.GetMask() ); 1997 else 1998 return aBmp; 1999 } 2000 2001 // ------------------------------------------------------------------------ 2002 2003 Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam ) 2004 { 2005 const sal_uLong nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue(); 2006 2007 for( sal_uLong i = 0; i < ( (const ImplColReplaceParam*) pColParam )->nCount; i++ ) 2008 { 2009 if( ( ( (const ImplColReplaceParam*) pColParam )->pMinR[ i ] <= nR ) && 2010 ( ( (const ImplColReplaceParam*) pColParam )->pMaxR[ i ] >= nR ) && 2011 ( ( (const ImplColReplaceParam*) pColParam )->pMinG[ i ] <= nG ) && 2012 ( ( (const ImplColReplaceParam*) pColParam )->pMaxG[ i ] >= nG ) && 2013 ( ( (const ImplColReplaceParam*) pColParam )->pMinB[ i ] <= nB ) && 2014 ( ( (const ImplColReplaceParam*) pColParam )->pMaxB[ i ] >= nB ) ) 2015 { 2016 return( ( (const ImplColReplaceParam*) pColParam )->pDstCols[ i ] ); 2017 } 2018 } 2019 2020 return rColor; 2021 } 2022 2023 // ------------------------------------------------------------------------ 2024 2025 BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam ) 2026 { 2027 const ImplBmpReplaceParam* p = (const ImplBmpReplaceParam*) pBmpParam; 2028 BitmapEx aRet( rBmpEx ); 2029 2030 aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount, p->pTols ); 2031 2032 return aRet; 2033 } 2034 2035 // ------------------------------------------------------------------------ 2036 2037 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam, 2038 BmpExchangeFnc pFncBmp, const void* pBmpParam ) 2039 { 2040 GDIMetaFile aMtf; 2041 2042 aMtf.aPrefSize = aPrefSize; 2043 aMtf.aPrefMapMode = aPrefMapMode; 2044 2045 for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() ) 2046 { 2047 const sal_uInt16 nType = pAction->GetType(); 2048 2049 switch( nType ) 2050 { 2051 case( META_PIXEL_ACTION ): 2052 { 2053 MetaPixelAction* pAct = (MetaPixelAction*) pAction; 2054 aMtf.Insert( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND ); 2055 } 2056 break; 2057 2058 case( META_LINECOLOR_ACTION ): 2059 { 2060 MetaLineColorAction* pAct = (MetaLineColorAction*) pAction; 2061 2062 if( !pAct->IsSetting() ) 2063 pAct->Duplicate(); 2064 else 2065 pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True ); 2066 2067 aMtf.Insert( pAct, LIST_APPEND ); 2068 } 2069 break; 2070 2071 case( META_FILLCOLOR_ACTION ): 2072 { 2073 MetaFillColorAction* pAct = (MetaFillColorAction*) pAction; 2074 2075 if( !pAct->IsSetting() ) 2076 pAct->Duplicate(); 2077 else 2078 pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True ); 2079 2080 aMtf.Insert( pAct, LIST_APPEND ); 2081 } 2082 break; 2083 2084 case( META_TEXTCOLOR_ACTION ): 2085 { 2086 MetaTextColorAction* pAct = (MetaTextColorAction*) pAction; 2087 aMtf.Insert( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND ); 2088 } 2089 break; 2090 2091 case( META_TEXTFILLCOLOR_ACTION ): 2092 { 2093 MetaTextFillColorAction* pAct = (MetaTextFillColorAction*) pAction; 2094 2095 if( !pAct->IsSetting() ) 2096 pAct->Duplicate(); 2097 else 2098 pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True ); 2099 2100 aMtf.Insert( pAct, LIST_APPEND ); 2101 } 2102 break; 2103 2104 case( META_TEXTLINECOLOR_ACTION ): 2105 { 2106 MetaTextLineColorAction* pAct = (MetaTextLineColorAction*) pAction; 2107 2108 if( !pAct->IsSetting() ) 2109 pAct->Duplicate(); 2110 else 2111 pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True ); 2112 2113 aMtf.Insert( pAct, LIST_APPEND ); 2114 } 2115 break; 2116 2117 case( META_OVERLINECOLOR_ACTION ): 2118 { 2119 MetaOverlineColorAction* pAct = (MetaOverlineColorAction*) pAction; 2120 2121 if( !pAct->IsSetting() ) 2122 pAct->Duplicate(); 2123 else 2124 pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True ); 2125 2126 aMtf.Insert( pAct, LIST_APPEND ); 2127 } 2128 break; 2129 2130 case( META_FONT_ACTION ): 2131 { 2132 MetaFontAction* pAct = (MetaFontAction*) pAction; 2133 Font aFont( pAct->GetFont() ); 2134 2135 aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) ); 2136 aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) ); 2137 aMtf.Insert( new MetaFontAction( aFont ), LIST_APPEND ); 2138 } 2139 break; 2140 2141 case( META_WALLPAPER_ACTION ): 2142 { 2143 MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction; 2144 Wallpaper aWall( pAct->GetWallpaper() ); 2145 const Rectangle& rRect = pAct->GetRect(); 2146 2147 aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) ); 2148 2149 if( aWall.IsBitmap() ) 2150 aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) ); 2151 2152 if( aWall.IsGradient() ) 2153 { 2154 Gradient aGradient( aWall.GetGradient() ); 2155 2156 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) ); 2157 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) ); 2158 aWall.SetGradient( aGradient ); 2159 } 2160 2161 aMtf.Insert( new MetaWallpaperAction( rRect, aWall ), LIST_APPEND ); 2162 } 2163 break; 2164 2165 case( META_BMP_ACTION ): 2166 case( META_BMPEX_ACTION ): 2167 case( META_MASK_ACTION ): 2168 { 2169 DBG_ERROR( "Don't use bitmap actions of this type in metafiles!" ); 2170 } 2171 break; 2172 2173 case( META_BMPSCALE_ACTION ): 2174 { 2175 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction; 2176 aMtf.Insert( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(), 2177 pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ), 2178 LIST_APPEND ); 2179 } 2180 break; 2181 2182 case( META_BMPSCALEPART_ACTION ): 2183 { 2184 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction; 2185 aMtf.Insert( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(), 2186 pAct->GetSrcPoint(), pAct->GetSrcSize(), 2187 pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ), 2188 LIST_APPEND ); 2189 } 2190 break; 2191 2192 case( META_BMPEXSCALE_ACTION ): 2193 { 2194 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction; 2195 aMtf.Insert( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(), 2196 pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ), 2197 LIST_APPEND ); 2198 } 2199 break; 2200 2201 case( META_BMPEXSCALEPART_ACTION ): 2202 { 2203 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction; 2204 aMtf.Insert( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(), 2205 pAct->GetSrcPoint(), pAct->GetSrcSize(), 2206 pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ), 2207 LIST_APPEND ); 2208 } 2209 break; 2210 2211 case( META_MASKSCALE_ACTION ): 2212 { 2213 MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction; 2214 aMtf.Insert( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(), 2215 pAct->GetBitmap(), 2216 pFncCol( pAct->GetColor(), pColParam ) ), 2217 LIST_APPEND ); 2218 } 2219 break; 2220 2221 case( META_MASKSCALEPART_ACTION ): 2222 { 2223 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction; 2224 aMtf.Insert( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(), 2225 pAct->GetSrcPoint(), pAct->GetSrcSize(), 2226 pAct->GetBitmap(), 2227 pFncCol( pAct->GetColor(), pColParam ) ), 2228 LIST_APPEND ); 2229 } 2230 break; 2231 2232 case( META_GRADIENT_ACTION ): 2233 { 2234 MetaGradientAction* pAct = (MetaGradientAction*) pAction; 2235 Gradient aGradient( pAct->GetGradient() ); 2236 2237 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) ); 2238 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) ); 2239 aMtf.Insert( new MetaGradientAction( pAct->GetRect(), aGradient ), LIST_APPEND ); 2240 } 2241 break; 2242 2243 case( META_GRADIENTEX_ACTION ): 2244 { 2245 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction; 2246 Gradient aGradient( pAct->GetGradient() ); 2247 2248 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) ); 2249 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) ); 2250 aMtf.Insert( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ), LIST_APPEND ); 2251 } 2252 break; 2253 2254 case( META_HATCH_ACTION ): 2255 { 2256 MetaHatchAction* pAct = (MetaHatchAction*) pAction; 2257 Hatch aHatch( pAct->GetHatch() ); 2258 2259 aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) ); 2260 aMtf.Insert( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ), LIST_APPEND ); 2261 } 2262 break; 2263 2264 case( META_FLOATTRANSPARENT_ACTION ): 2265 { 2266 MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction; 2267 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() ); 2268 2269 aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam ); 2270 aMtf.Insert( new MetaFloatTransparentAction( aTransMtf, 2271 pAct->GetPoint(), pAct->GetSize(), 2272 pAct->GetGradient() ), 2273 LIST_APPEND ); 2274 } 2275 break; 2276 2277 case( META_EPS_ACTION ): 2278 { 2279 MetaEPSAction* pAct = (MetaEPSAction*) pAction; 2280 GDIMetaFile aSubst( pAct->GetSubstitute() ); 2281 2282 aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam ); 2283 aMtf.Insert( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(), 2284 pAct->GetLink(), aSubst ), 2285 LIST_APPEND ); 2286 } 2287 break; 2288 2289 case( META_RENDERGRAPHIC_ACTION ): 2290 { 2291 OSL_TRACE( "ExchangeColors not supported for RenderGraphic MetaActions yet" ); 2292 2293 pAction->Duplicate(); 2294 aMtf.Insert( pAction, LIST_APPEND ); 2295 } 2296 break; 2297 2298 default: 2299 { 2300 pAction->Duplicate(); 2301 aMtf.Insert( pAction, LIST_APPEND ); 2302 } 2303 break; 2304 } 2305 } 2306 2307 *this = aMtf; 2308 } 2309 2310 // ------------------------------------------------------------------------ 2311 2312 void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent, 2313 short nChannelRPercent, short nChannelGPercent, 2314 short nChannelBPercent, double fGamma, sal_Bool bInvert ) 2315 { 2316 // nothing to do? => return quickly 2317 if( nLuminancePercent || nContrastPercent || 2318 nChannelRPercent || nChannelGPercent || nChannelBPercent || 2319 ( fGamma != 1.0 ) || bInvert ) 2320 { 2321 double fM, fROff, fGOff, fBOff, fOff; 2322 ImplColAdjustParam aColParam; 2323 ImplBmpAdjustParam aBmpParam; 2324 2325 aColParam.pMapR = new sal_uInt8[ 256 ]; 2326 aColParam.pMapG = new sal_uInt8[ 256 ]; 2327 aColParam.pMapB = new sal_uInt8[ 256 ]; 2328 2329 // calculate slope 2330 if( nContrastPercent >= 0 ) 2331 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) ); 2332 else 2333 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0; 2334 2335 // total offset = luminance offset + contrast offset 2336 fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0; 2337 2338 // channel offset = channel offset + total offset 2339 fROff = nChannelRPercent * 2.55 + fOff; 2340 fGOff = nChannelGPercent * 2.55 + fOff; 2341 fBOff = nChannelBPercent * 2.55 + fOff; 2342 2343 // calculate gamma value 2344 fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma ); 2345 const sal_Bool bGamma = ( fGamma != 1.0 ); 2346 2347 // create mapping table 2348 for( long nX = 0L; nX < 256L; nX++ ) 2349 { 2350 aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L ); 2351 aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L ); 2352 aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L ); 2353 2354 if( bGamma ) 2355 { 2356 aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma ); 2357 aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma ); 2358 aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma ); 2359 } 2360 2361 if( bInvert ) 2362 { 2363 aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ]; 2364 aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ]; 2365 aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ]; 2366 } 2367 } 2368 2369 aBmpParam.nLuminancePercent = nLuminancePercent; 2370 aBmpParam.nContrastPercent = nContrastPercent; 2371 aBmpParam.nChannelRPercent = nChannelRPercent; 2372 aBmpParam.nChannelGPercent = nChannelGPercent; 2373 aBmpParam.nChannelBPercent = nChannelBPercent; 2374 aBmpParam.fGamma = fGamma; 2375 aBmpParam.bInvert = bInvert; 2376 2377 // do color adjustment 2378 ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam ); 2379 2380 delete[] aColParam.pMapR; 2381 delete[] aColParam.pMapG; 2382 delete[] aColParam.pMapB; 2383 } 2384 } 2385 2386 // ------------------------------------------------------------------------ 2387 2388 void GDIMetaFile::Convert( MtfConversion eConversion ) 2389 { 2390 // nothing to do? => return quickly 2391 if( eConversion != MTF_CONVERSION_NONE ) 2392 { 2393 ImplColConvertParam aColParam; 2394 ImplBmpConvertParam aBmpParam; 2395 2396 aColParam.eConversion = eConversion; 2397 aBmpParam.eConversion = ( MTF_CONVERSION_1BIT_THRESHOLD == eConversion ) ? BMP_CONVERSION_1BIT_THRESHOLD : BMP_CONVERSION_8BIT_GREYS; 2398 2399 ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam ); 2400 } 2401 } 2402 2403 // ------------------------------------------------------------------------ 2404 2405 void GDIMetaFile::ReplaceColors( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ) 2406 { 2407 ReplaceColors( &rSearchColor, &rReplaceColor, 1, &nTol ); 2408 } 2409 2410 // ------------------------------------------------------------------------ 2411 2412 void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, sal_uLong* pTols ) 2413 { 2414 ImplColReplaceParam aColParam; 2415 ImplBmpReplaceParam aBmpParam; 2416 2417 aColParam.pMinR = new sal_uLong[ nColorCount ]; 2418 aColParam.pMaxR = new sal_uLong[ nColorCount ]; 2419 aColParam.pMinG = new sal_uLong[ nColorCount ]; 2420 aColParam.pMaxG = new sal_uLong[ nColorCount ]; 2421 aColParam.pMinB = new sal_uLong[ nColorCount ]; 2422 aColParam.pMaxB = new sal_uLong[ nColorCount ]; 2423 2424 for( sal_uLong i = 0; i < nColorCount; i++ ) 2425 { 2426 const long nTol = pTols ? ( pTols[ i ] * 255 ) / 100 : 0; 2427 long nVal; 2428 2429 nVal = pSearchColors[ i ].GetRed(); 2430 aColParam.pMinR[ i ] = (sal_uLong) Max( nVal - nTol, 0L ); 2431 aColParam.pMaxR[ i ] = (sal_uLong) Min( nVal + nTol, 255L ); 2432 2433 nVal = pSearchColors[ i ].GetGreen(); 2434 aColParam.pMinG[ i ] = (sal_uLong) Max( nVal - nTol, 0L ); 2435 aColParam.pMaxG[ i ] = (sal_uLong) Min( nVal + nTol, 255L ); 2436 2437 nVal = pSearchColors[ i ].GetBlue(); 2438 aColParam.pMinB[ i ] = (sal_uLong) Max( nVal - nTol, 0L ); 2439 aColParam.pMaxB[ i ] = (sal_uLong) Min( nVal + nTol, 255L ); 2440 } 2441 2442 aColParam.pDstCols = pReplaceColors; 2443 aColParam.nCount = nColorCount; 2444 2445 aBmpParam.pSrcCols = pSearchColors; 2446 aBmpParam.pDstCols = pReplaceColors; 2447 aBmpParam.nCount = nColorCount; 2448 aBmpParam.pTols = pTols; 2449 2450 ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam ); 2451 2452 delete[] aColParam.pMinR; 2453 delete[] aColParam.pMaxR; 2454 delete[] aColParam.pMinG; 2455 delete[] aColParam.pMaxG; 2456 delete[] aColParam.pMinB; 2457 delete[] aColParam.pMaxB; 2458 }; 2459 2460 // ------------------------------------------------------------------------ 2461 2462 GDIMetaFile GDIMetaFile::GetMonochromeMtf( const Color& rColor ) const 2463 { 2464 GDIMetaFile aRet( *this ); 2465 2466 ImplColMonoParam aColParam; 2467 ImplBmpMonoParam aBmpParam; 2468 2469 aColParam.aColor = rColor; 2470 aBmpParam.aColor = rColor; 2471 2472 aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam ); 2473 2474 return aRet; 2475 } 2476 2477 // ------------------------------------------------------------------------ 2478 2479 sal_uLong GDIMetaFile::GetChecksum() const 2480 { 2481 GDIMetaFile aMtf; 2482 SvMemoryStream aMemStm( 65535, 65535 ); 2483 ImplMetaWriteData aWriteData; 2484 SVBT16 aBT16; 2485 SVBT32 aBT32; 2486 sal_uLong nCrc = 0; 2487 2488 aWriteData.meActualCharSet = aMemStm.GetStreamCharSet(); 2489 2490 for( sal_uLong i = 0, nObjCount = GetActionCount(); i < nObjCount; i++ ) 2491 { 2492 MetaAction* pAction = GetAction( i ); 2493 2494 switch( pAction->GetType() ) 2495 { 2496 case( META_BMP_ACTION ): 2497 { 2498 MetaBmpAction* pAct = (MetaBmpAction*) pAction; 2499 2500 ShortToSVBT16( pAct->GetType(), aBT16 ); 2501 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2502 2503 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2504 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2505 2506 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2507 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2508 2509 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2510 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2511 } 2512 break; 2513 2514 case( META_BMPSCALE_ACTION ): 2515 { 2516 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction; 2517 2518 ShortToSVBT16( pAct->GetType(), aBT16 ); 2519 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2520 2521 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2522 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2523 2524 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2525 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2526 2527 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2528 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2529 2530 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 ); 2531 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2532 2533 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 ); 2534 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2535 } 2536 break; 2537 2538 case( META_BMPSCALEPART_ACTION ): 2539 { 2540 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction; 2541 2542 ShortToSVBT16( pAct->GetType(), aBT16 ); 2543 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2544 2545 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2546 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2547 2548 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 ); 2549 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2550 2551 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 ); 2552 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2553 2554 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 ); 2555 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2556 2557 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 ); 2558 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2559 2560 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 ); 2561 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2562 2563 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 ); 2564 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2565 2566 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 ); 2567 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2568 2569 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 ); 2570 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2571 } 2572 break; 2573 2574 case( META_BMPEX_ACTION ): 2575 { 2576 MetaBmpExAction* pAct = (MetaBmpExAction*) pAction; 2577 2578 ShortToSVBT16( pAct->GetType(), aBT16 ); 2579 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2580 2581 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 ); 2582 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2583 2584 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2585 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2586 2587 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2588 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2589 } 2590 break; 2591 2592 case( META_BMPEXSCALE_ACTION ): 2593 { 2594 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction; 2595 2596 ShortToSVBT16( pAct->GetType(), aBT16 ); 2597 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2598 2599 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 ); 2600 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2601 2602 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2603 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2604 2605 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2606 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2607 2608 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 ); 2609 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2610 2611 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 ); 2612 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2613 } 2614 break; 2615 2616 case( META_BMPEXSCALEPART_ACTION ): 2617 { 2618 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction; 2619 2620 ShortToSVBT16( pAct->GetType(), aBT16 ); 2621 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2622 2623 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 ); 2624 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2625 2626 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 ); 2627 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2628 2629 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 ); 2630 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2631 2632 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 ); 2633 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2634 2635 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 ); 2636 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2637 2638 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 ); 2639 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2640 2641 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 ); 2642 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2643 2644 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 ); 2645 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2646 2647 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 ); 2648 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2649 } 2650 break; 2651 2652 case( META_MASK_ACTION ): 2653 { 2654 MetaMaskAction* pAct = (MetaMaskAction*) pAction; 2655 2656 ShortToSVBT16( pAct->GetType(), aBT16 ); 2657 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2658 2659 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2660 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2661 2662 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 ); 2663 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2664 2665 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2666 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2667 2668 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2669 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2670 } 2671 break; 2672 2673 case( META_MASKSCALE_ACTION ): 2674 { 2675 MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction; 2676 2677 ShortToSVBT16( pAct->GetType(), aBT16 ); 2678 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2679 2680 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2681 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2682 2683 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 ); 2684 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2685 2686 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2687 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2688 2689 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2690 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2691 2692 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 ); 2693 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2694 2695 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 ); 2696 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2697 } 2698 break; 2699 2700 case( META_MASKSCALEPART_ACTION ): 2701 { 2702 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction; 2703 2704 ShortToSVBT16( pAct->GetType(), aBT16 ); 2705 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2706 2707 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2708 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2709 2710 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 ); 2711 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2712 2713 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 ); 2714 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2715 2716 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 ); 2717 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2718 2719 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 ); 2720 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2721 2722 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 ); 2723 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2724 2725 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 ); 2726 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2727 2728 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 ); 2729 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2730 2731 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 ); 2732 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2733 2734 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 ); 2735 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2736 } 2737 break; 2738 2739 case META_EPS_ACTION : 2740 { 2741 MetaEPSAction* pAct = (MetaEPSAction*) pAction; 2742 nCrc = rtl_crc32( nCrc, pAct->GetLink().GetData(), pAct->GetLink().GetDataSize() ); 2743 } 2744 break; 2745 2746 case( META_RENDERGRAPHIC_ACTION ): 2747 { 2748 MetaRenderGraphicAction* pAct = (MetaRenderGraphicAction*) pAction; 2749 const ::vcl::RenderGraphic& rRenderGraphic = pAct->GetRenderGraphic(); 2750 2751 ShortToSVBT16( pAct->GetType(), aBT16 ); 2752 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2753 2754 nCrc = rtl_crc32( nCrc, rRenderGraphic.GetGraphicData().get(), rRenderGraphic.GetGraphicDataLength() ); 2755 2756 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2757 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2758 2759 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2760 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2761 2762 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 ); 2763 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2764 2765 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 ); 2766 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2767 } 2768 break; 2769 2770 default: 2771 { 2772 pAction->Write( aMemStm, &aWriteData ); 2773 nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() ); 2774 aMemStm.Seek( 0 ); 2775 } 2776 break; 2777 } 2778 } 2779 2780 return nCrc; 2781 } 2782 2783 // ------------------------------------------------------------------------ 2784 2785 sal_uLong GDIMetaFile::GetSizeBytes() const 2786 { 2787 sal_uLong nSizeBytes = 0; 2788 2789 for( sal_uLong i = 0, nObjCount = GetActionCount(); i < nObjCount; ++i ) 2790 { 2791 MetaAction* pAction = GetAction( i ); 2792 2793 // default action size is set to 32 (=> not the exact value) 2794 nSizeBytes += 32; 2795 2796 // add sizes for large action content 2797 switch( pAction->GetType() ) 2798 { 2799 case( META_BMP_ACTION ): nSizeBytes += ( (MetaBmpAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2800 case( META_BMPSCALE_ACTION ): nSizeBytes += ( (MetaBmpScaleAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2801 case( META_BMPSCALEPART_ACTION ): nSizeBytes += ( (MetaBmpScalePartAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2802 2803 case( META_BMPEX_ACTION ): nSizeBytes += ( (MetaBmpExAction*) pAction )->GetBitmapEx().GetSizeBytes(); break; 2804 case( META_BMPEXSCALE_ACTION ): nSizeBytes += ( (MetaBmpExScaleAction*) pAction )->GetBitmapEx().GetSizeBytes(); break; 2805 case( META_BMPEXSCALEPART_ACTION ): nSizeBytes += ( (MetaBmpExScalePartAction*) pAction )->GetBitmapEx().GetSizeBytes(); break; 2806 2807 case( META_MASK_ACTION ): nSizeBytes += ( (MetaMaskAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2808 case( META_MASKSCALE_ACTION ): nSizeBytes += ( (MetaMaskScaleAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2809 case( META_MASKSCALEPART_ACTION ): nSizeBytes += ( (MetaMaskScalePartAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2810 2811 case( META_POLYLINE_ACTION ): nSizeBytes += ( ( (MetaPolyLineAction*) pAction )->GetPolygon().GetSize() * sizeof( Point ) ); break; 2812 case( META_POLYGON_ACTION ): nSizeBytes += ( ( (MetaPolygonAction*) pAction )->GetPolygon().GetSize() * sizeof( Point ) ); break; 2813 case( META_POLYPOLYGON_ACTION ): 2814 { 2815 const PolyPolygon& rPolyPoly = ( (MetaPolyPolygonAction*) pAction )->GetPolyPolygon(); 2816 2817 for( sal_uInt16 n = 0; n < rPolyPoly.Count(); ++n ) 2818 nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) ); 2819 } 2820 break; 2821 2822 case( META_TEXT_ACTION ): nSizeBytes += ( ( (MetaTextAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break; 2823 case( META_STRETCHTEXT_ACTION ): nSizeBytes += ( ( (MetaStretchTextAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break; 2824 case( META_TEXTRECT_ACTION ): nSizeBytes += ( ( (MetaTextRectAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break; 2825 case( META_TEXTARRAY_ACTION ): 2826 { 2827 MetaTextArrayAction* pTextArrayAction = (MetaTextArrayAction*) pAction; 2828 2829 nSizeBytes += ( pTextArrayAction->GetText().Len() * sizeof( sal_Unicode ) ); 2830 2831 if( pTextArrayAction->GetDXArray() ) 2832 nSizeBytes += ( pTextArrayAction->GetLen() << 2 ); 2833 } 2834 break; 2835 2836 case( META_RENDERGRAPHIC_ACTION ): nSizeBytes += ( ( (MetaRenderGraphicAction*) pAction )->GetRenderGraphic() ).GetGraphicDataLength(); break; 2837 } 2838 } 2839 2840 return( nSizeBytes ); 2841 } 2842 2843 // ------------------------------------------------------------------------ 2844 2845 SvStream& operator>>( SvStream& rIStm, GDIMetaFile& rGDIMetaFile ) 2846 { 2847 if( !rIStm.GetError() ) 2848 { 2849 char aId[ 7 ]; 2850 sal_uLong nStmPos = rIStm.Tell(); 2851 sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt(); 2852 2853 rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 2854 2855 aId[ 0 ] = 0; 2856 aId[ 6 ] = 0; 2857 rIStm.Read( aId, 6 ); 2858 2859 if ( !strcmp( aId, "VCLMTF" ) ) 2860 { 2861 // new format 2862 VersionCompat* pCompat; 2863 MetaAction* pAction; 2864 sal_uInt32 nStmCompressMode = 0; 2865 sal_uInt32 nCount = 0; 2866 sal_uInt8 bRenderGraphicReplacements = 0; 2867 2868 pCompat = new VersionCompat( rIStm, STREAM_READ ); 2869 { 2870 // version 1 2871 rIStm >> nStmCompressMode; 2872 rIStm >> rGDIMetaFile.aPrefMapMode; 2873 rIStm >> rGDIMetaFile.aPrefSize; 2874 rIStm >> nCount; 2875 2876 if( pCompat->GetVersion() >= 2 ) 2877 { 2878 // version 2 2879 // ========= 2880 // contains an additional flag to indicate that RenderGraphic 2881 // actions are immediately followed by a replacement image, that 2882 // needs to be skipped in case the flag is set (KA 01/2011) 2883 2884 rIStm >> bRenderGraphicReplacements; 2885 } 2886 } 2887 delete pCompat; 2888 2889 ImplMetaReadData aReadData; 2890 aReadData.meActualCharSet = rIStm.GetStreamCharSet(); 2891 2892 for( sal_uInt32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); ++nAction ) 2893 { 2894 pAction = MetaAction::ReadMetaAction( rIStm, &aReadData ); 2895 2896 if( pAction ) 2897 { 2898 rGDIMetaFile.AddAction( pAction ); 2899 2900 // if the MetaFile was written in RenderGraphics replacement mode 2901 // and we just read a RenderGraphic action, skip the following 2902 // META_BMPEXSCALE_ACTION, since this is the replacement image, 2903 // just needed for old implementations; don't forget to increment 2904 // the action read counter! (KA 01/2011) 2905 if( bRenderGraphicReplacements && 2906 ( META_RENDERGRAPHIC_ACTION == pAction->GetType() ) && 2907 ( ++nAction < nCount ) && !rIStm.IsEof() ) 2908 { 2909 sal_uInt16 nFollowingType; 2910 2911 // dummy read of the next following META_BMPEXSCALE_ACTION 2912 // RenderGraphic replacement action (KA 01/2011) 2913 rIStm >> nFollowingType; 2914 delete ( new VersionCompat( rIStm, STREAM_READ ) ); 2915 2916 OSL_ENSURE( META_BMPEXSCALE_ACTION == nFollowingType, \ 2917 "META_RENDERGRAPHIC_ACTION read in RenderGraphic replacement mode \ 2918 without following META_BMPEXSCALE_ACTION replacement" ); 2919 } 2920 } 2921 } 2922 } 2923 else 2924 { 2925 // to avoid possible compiler optimizations => new/delete 2926 rIStm.Seek( nStmPos ); 2927 delete( new SVMConverter( rIStm, rGDIMetaFile, CONVERT_FROM_SVM1 ) ); 2928 } 2929 2930 // check for errors 2931 if( rIStm.GetError() ) 2932 { 2933 rGDIMetaFile.Clear(); 2934 rIStm.Seek( nStmPos ); 2935 } 2936 2937 rIStm.SetNumberFormatInt( nOldFormat ); 2938 } 2939 2940 return rIStm; 2941 } 2942 2943 // ------------------------------------------------------------------------ 2944 2945 SvStream& operator<<( SvStream& rOStm, const GDIMetaFile& rGDIMetaFile ) 2946 { 2947 if( !rOStm.GetError() ) 2948 { 2949 static const char* pEnableSVM1 = getenv( "SAL_ENABLE_SVM1" ); 2950 static const bool bNoSVM1 = (NULL == pEnableSVM1 ) || ( '0' == *pEnableSVM1 ); 2951 2952 if( bNoSVM1 || rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) 2953 { 2954 const_cast< GDIMetaFile& >( rGDIMetaFile ).Write( rOStm ); 2955 } 2956 else 2957 { 2958 delete( new SVMConverter( rOStm, const_cast< GDIMetaFile& >( rGDIMetaFile ), CONVERT_TO_SVM1 ) ); 2959 } 2960 2961 #ifdef DEBUG 2962 if( !bNoSVM1 && rOStm.GetVersion() < SOFFICE_FILEFORMAT_50 ) 2963 { 2964 OSL_TRACE( \ 2965 "GDIMetaFile would normally be written in old SVM1 format by this call. \ 2966 The current implementation always writes in VCLMTF format. \ 2967 Please set environment variable SAL_ENABLE_SVM1 to '1' to reenable old behavior" ); 2968 } 2969 #endif // DEBUG 2970 } 2971 2972 return rOStm; 2973 } 2974 2975 // ------------------------------------------------------------------------ 2976 2977 SvStream& GDIMetaFile::Read( SvStream& rIStm ) 2978 { 2979 Clear(); 2980 rIStm >> *this; 2981 2982 return rIStm; 2983 } 2984 2985 // ------------------------------------------------------------------------ 2986 2987 SvStream& GDIMetaFile::Write( SvStream& rOStm, GDIMetaFileWriteFlags nWriteFlags ) 2988 { 2989 VersionCompat* pCompat; 2990 const sal_uInt32 nStmCompressMode = rOStm.GetCompressMode(); 2991 sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt(); 2992 const sal_uInt8 bRenderGraphicReplacements = 2993 ( ( ( GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC & nWriteFlags ) != 0 ) ? 1 : 0 ); 2994 2995 // With the introduction of the META_RENDERGRAPHIC_ACTION, it is neccessary 2996 // to provide some kind of document backward compatibility: 2997 // 2998 // If the flag GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC is set in 2999 // parameter nWriteFlags, each META_RENDERGRAPHIC_ACTION is followed by 3000 // an additional META_BMPEXSCALE_ACTION, that contains a replacement 3001 // image for the new RenderGraphic action. 3002 // 3003 // Old implementations, not knowing anything about META_RENDERGRAPHIC_ACTION, 3004 // will skip this new action and read the META_BMPEXSCALE_ACTION instead 3005 // 3006 // Since the current implementation is able to handle the new action, the 3007 // then following image replacement action needs to be skipped by this 3008 // implementation, if the metafile was written in the RenderGraphic 3009 // replacement mode. 3010 // 3011 // To be able to detect this compatibility mode, the header needs to 3012 // be extended by a corresponding flag, resulting in version 2 of 3013 // the header. The surrounding VersionCompat of the header 3014 // allows to add such new data without any problems (KA 01/2011) 3015 3016 rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 3017 rOStm.Write( "VCLMTF", 6 ); 3018 3019 pCompat = new VersionCompat( rOStm, STREAM_WRITE, 2 ); 3020 3021 { 3022 // version 1 3023 sal_uInt32 nActionCount = 0; 3024 3025 // calculate correct action count and watch for 3026 // additional RenderGraphic replacement actions, if the 3027 // GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC is set 3028 // and META_RENDERGRAPHIC_ACTION are encountered (KA 01/2011) 3029 for( MetaAction* pAct = static_cast< MetaAction* >( First() ); pAct; pAct = static_cast< MetaAction* >( Next() ) ) 3030 { 3031 nActionCount += ( bRenderGraphicReplacements && ( META_RENDERGRAPHIC_ACTION == pAct->GetType() ) ? 2 : 1 ); 3032 } 3033 3034 rOStm << nStmCompressMode << aPrefMapMode << aPrefSize << nActionCount; 3035 3036 { 3037 // version 2 3038 // ========= 3039 // since version 2, a GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC flag 3040 // is written, to indicate that each META_BMPEXSCALE_ACTION following 3041 // a META_RENDERGRAPHIC_ACTION needs to be skipped, in case the flag is 3042 // set (KA 01/2011) 3043 rOStm << bRenderGraphicReplacements; 3044 } 3045 } 3046 3047 delete pCompat; 3048 3049 ImplMetaWriteData aWriteData; 3050 3051 aWriteData.meActualCharSet = rOStm.GetStreamCharSet(); 3052 aWriteData.mnWriteFlags = nWriteFlags; 3053 3054 for( MetaAction* pAct = static_cast< MetaAction* >( First() ); pAct; pAct = static_cast< MetaAction* >( Next() ) ) 3055 { 3056 pAct->Write( rOStm, &aWriteData ); 3057 3058 // write the RenderGraphic replacement image, if the 3059 // GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC flag is set 3060 // and if a META_RENDERGRAPHIC_ACTION is encountered (KA 01/2011) 3061 if( bRenderGraphicReplacements && ( META_RENDERGRAPHIC_ACTION == pAct->GetType() ) ) 3062 { 3063 MetaRenderGraphicAction* pRenderAction = static_cast< MetaRenderGraphicAction* >( pAct ); 3064 MetaBmpExScaleAction* pBmpExScaleAction = new MetaBmpExScaleAction( 3065 pRenderAction->GetPoint(), pRenderAction->GetSize(), 3066 pRenderAction->GetRenderGraphic().GetReplacement() ); 3067 3068 pBmpExScaleAction->Write( rOStm, &aWriteData ); 3069 pBmpExScaleAction->Delete(); 3070 } 3071 } 3072 3073 rOStm.SetNumberFormatInt( nOldFormat ); 3074 3075 return rOStm; 3076 } 3077 3078 // ------------------------------------------------------------------------ 3079 3080 sal_Bool GDIMetaFile::CreateThumbnail( sal_uInt32 nMaximumExtent, 3081 BitmapEx& rBmpEx, 3082 const BitmapEx* pOverlay, 3083 const Rectangle* pOverlayRect ) const 3084 { 3085 // the implementation is provided by KA 3086 3087 // initialization seems to be complicated but is used to avoid rounding errors 3088 VirtualDevice aVDev; 3089 const Point aNullPt; 3090 const Point aTLPix( aVDev.LogicToPixel( aNullPt, GetPrefMapMode() ) ); 3091 const Point aBRPix( aVDev.LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) ); 3092 Size aDrawSize( aVDev.LogicToPixel( GetPrefSize(), GetPrefMapMode() ) ); 3093 Size aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 ); 3094 Point aPosPix; 3095 3096 if ( !rBmpEx.IsEmpty() ) 3097 rBmpEx.SetEmpty(); 3098 3099 // determine size that has the same aspect ratio as image size and 3100 // fits into the rectangle determined by nMaximumExtent 3101 if ( aSizePix.Width() && aSizePix.Height() 3102 && ( sal::static_int_cast< unsigned long >(aSizePix.Width()) > 3103 nMaximumExtent || 3104 sal::static_int_cast< unsigned long >(aSizePix.Height()) > 3105 nMaximumExtent ) ) 3106 { 3107 const Size aOldSizePix( aSizePix ); 3108 double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height(); 3109 3110 if ( fWH <= 1.0 ) 3111 { 3112 aSizePix.Width() = FRound( nMaximumExtent * fWH ); 3113 aSizePix.Height() = nMaximumExtent; 3114 } 3115 else 3116 { 3117 aSizePix.Width() = nMaximumExtent; 3118 aSizePix.Height() = FRound( nMaximumExtent / fWH ); 3119 } 3120 3121 aDrawSize.Width() = FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() ); 3122 aDrawSize.Height() = FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() ); 3123 } 3124 3125 Size aFullSize; 3126 Point aBackPosPix; 3127 Rectangle aOverlayRect; 3128 3129 // calculate addigtional positions and sizes if an overlay image is used 3130 if ( pOverlay ) 3131 { 3132 aFullSize = Size( nMaximumExtent, nMaximumExtent ); 3133 aOverlayRect = Rectangle( aNullPt, aFullSize ); 3134 3135 aOverlayRect.Intersection( pOverlayRect ? *pOverlayRect : Rectangle( aNullPt, pOverlay->GetSizePixel() ) ); 3136 3137 if ( !aOverlayRect.IsEmpty() ) 3138 aBackPosPix = Point( ( nMaximumExtent - aSizePix.Width() ) >> 1, ( nMaximumExtent - aSizePix.Height() ) >> 1 ); 3139 else 3140 pOverlay = NULL; 3141 } 3142 else 3143 { 3144 aFullSize = aSizePix; 3145 pOverlay = NULL; 3146 } 3147 3148 // draw image(s) into VDev and get resulting image 3149 if ( aVDev.SetOutputSizePixel( aFullSize ) ) 3150 { 3151 // draw metafile into VDev 3152 const_cast<GDIMetaFile *>(this)->WindStart(); 3153 const_cast<GDIMetaFile *>(this)->Play( &aVDev, aBackPosPix, aDrawSize ); 3154 3155 // draw overlay if neccessary 3156 if ( pOverlay ) 3157 aVDev.DrawBitmapEx( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), *pOverlay ); 3158 3159 // get paint bitmap 3160 Bitmap aBmp( aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) ); 3161 3162 // assure that we have a true color image 3163 if ( aBmp.GetBitCount() != 24 ) 3164 aBmp.Convert( BMP_CONVERSION_24BIT ); 3165 3166 // create resulting mask bitmap with metafile output set to black 3167 GDIMetaFile aMonchromeMtf( GetMonochromeMtf( COL_BLACK ) ); 3168 aVDev.DrawWallpaper( Rectangle( aNullPt, aSizePix ), Wallpaper( Color( COL_WHITE ) ) ); 3169 aMonchromeMtf.WindStart(); 3170 aMonchromeMtf.Play( &aVDev, aBackPosPix, aDrawSize ); 3171 3172 // watch for overlay mask 3173 if ( pOverlay ) 3174 { 3175 Bitmap aOverlayMergeBmp( aVDev.GetBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize() ) ); 3176 3177 // create ANDed resulting mask at overlay area 3178 if ( pOverlay->IsTransparent() ) 3179 aVDev.DrawBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), pOverlay->GetMask() ); 3180 else 3181 { 3182 aVDev.SetLineColor( COL_BLACK ); 3183 aVDev.SetFillColor( COL_BLACK ); 3184 aVDev.DrawRect( aOverlayRect); 3185 } 3186 3187 aOverlayMergeBmp.CombineSimple( aVDev.GetBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize() ), BMP_COMBINE_AND ); 3188 aVDev.DrawBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), aOverlayMergeBmp ); 3189 } 3190 3191 rBmpEx = BitmapEx( aBmp, aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) ); 3192 } 3193 3194 return !rBmpEx.IsEmpty(); 3195 } 3196