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