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 Rectangle* o_pHairline ) 1481 { 1482 Rectangle aBounds( i_rInBounds ); 1483 if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() ) 1484 aBounds.Intersection( i_rClipStack.back() ); 1485 if( ! aBounds.IsEmpty() ) 1486 { 1487 if( ! o_rOutBounds.IsEmpty() ) 1488 o_rOutBounds.Union( aBounds ); 1489 else 1490 o_rOutBounds = aBounds; 1491 1492 if(o_pHairline) 1493 { 1494 if( ! o_pHairline->IsEmpty() ) 1495 o_pHairline->Union( aBounds ); 1496 else 1497 *o_pHairline = aBounds; 1498 } 1499 } 1500 } 1501 1502 Rectangle GDIMetaFile::GetBoundRect( OutputDevice& i_rReference, Rectangle* pHairline ) const 1503 { 1504 GDIMetaFile aMtf; 1505 VirtualDevice aMapVDev( i_rReference ); 1506 1507 aMapVDev.EnableOutput( sal_False ); 1508 aMapVDev.SetMapMode( GetPrefMapMode() ); 1509 1510 std::vector<Rectangle> aClipStack( 1, Rectangle() ); 1511 std::vector<sal_uInt16> aPushFlagStack; 1512 1513 Rectangle aBound; 1514 1515 if(pHairline) 1516 { 1517 *pHairline = Rectangle(); 1518 } 1519 1520 const sal_uLong nCount(GetActionCount()); 1521 1522 for(sal_uLong a(0); a < nCount; a++) 1523 { 1524 MetaAction* pAction = GetAction(a); 1525 const sal_uInt16 nActionType = pAction->GetType(); 1526 Rectangle* pUseHairline = (pHairline && aMapVDev.IsLineColor()) ? pHairline : 0; 1527 1528 switch( nActionType ) 1529 { 1530 case( META_PIXEL_ACTION ): 1531 { 1532 MetaPixelAction* pAct = (MetaPixelAction*) pAction; 1533 ImplActionBounds( aBound, 1534 Rectangle( aMapVDev.LogicToLogic( pAct->GetPoint(), aMapVDev.GetMapMode(), GetPrefMapMode() ), 1535 aMapVDev.PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ), 1536 aClipStack, pUseHairline ); 1537 } 1538 break; 1539 1540 case( META_POINT_ACTION ): 1541 { 1542 MetaPointAction* pAct = (MetaPointAction*) pAction; 1543 ImplActionBounds( aBound, 1544 Rectangle( aMapVDev.LogicToLogic( pAct->GetPoint(), aMapVDev.GetMapMode(), GetPrefMapMode() ), 1545 aMapVDev.PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ), 1546 aClipStack, pUseHairline ); 1547 } 1548 break; 1549 1550 case( META_LINE_ACTION ): 1551 { 1552 MetaLineAction* pAct = (MetaLineAction*) pAction; 1553 Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() ); 1554 Rectangle aRect( aP1, aP2 ); 1555 aRect.Justify(); 1556 1557 if(pUseHairline) 1558 { 1559 const LineInfo& rLineInfo = pAct->GetLineInfo(); 1560 1561 if(0 != rLineInfo.GetWidth()) 1562 { 1563 pUseHairline = 0; 1564 } 1565 } 1566 1567 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline ); 1568 } 1569 break; 1570 1571 case( META_RECT_ACTION ): 1572 { 1573 MetaRectAction* pAct = (MetaRectAction*) pAction; 1574 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline ); 1575 } 1576 break; 1577 1578 case( META_ROUNDRECT_ACTION ): 1579 { 1580 MetaRoundRectAction* pAct = (MetaRoundRectAction*) pAction; 1581 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline ); 1582 } 1583 break; 1584 1585 case( META_ELLIPSE_ACTION ): 1586 { 1587 MetaEllipseAction* pAct = (MetaEllipseAction*) pAction; 1588 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline ); 1589 } 1590 break; 1591 1592 case( META_ARC_ACTION ): 1593 { 1594 MetaArcAction* pAct = (MetaArcAction*) pAction; 1595 // FIXME: this is imprecise 1596 // e.g. for small arcs the whole rectangle is WAY too large 1597 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline ); 1598 } 1599 break; 1600 1601 case( META_PIE_ACTION ): 1602 { 1603 MetaPieAction* pAct = (MetaPieAction*) pAction; 1604 // FIXME: this is imprecise 1605 // e.g. for small arcs the whole rectangle is WAY too large 1606 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline ); 1607 } 1608 break; 1609 1610 case( META_CHORD_ACTION ): 1611 { 1612 MetaChordAction* pAct = (MetaChordAction*) pAction; 1613 // FIXME: this is imprecise 1614 // e.g. for small arcs the whole rectangle is WAY too large 1615 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline ); 1616 } 1617 break; 1618 1619 case( META_POLYLINE_ACTION ): 1620 { 1621 MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction; 1622 Rectangle aRect( pAct->GetPolygon().GetBoundRect() ); 1623 1624 if(pUseHairline) 1625 { 1626 const LineInfo& rLineInfo = pAct->GetLineInfo(); 1627 1628 if(0 != rLineInfo.GetWidth()) 1629 { 1630 pUseHairline = 0; 1631 } 1632 } 1633 1634 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline ); 1635 } 1636 break; 1637 1638 case( META_POLYGON_ACTION ): 1639 { 1640 MetaPolygonAction* pAct = (MetaPolygonAction*) pAction; 1641 Rectangle aRect( pAct->GetPolygon().GetBoundRect() ); 1642 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline ); 1643 } 1644 break; 1645 1646 case( META_POLYPOLYGON_ACTION ): 1647 { 1648 MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction; 1649 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() ); 1650 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline ); 1651 } 1652 break; 1653 1654 case( META_TEXT_ACTION ): 1655 { 1656 MetaTextAction* pAct = (MetaTextAction*) pAction; 1657 Rectangle aRect; 1658 // hdu said base = index 1659 aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() ); 1660 Point aPt( pAct->GetPoint() ); 1661 aRect.Move( aPt.X(), aPt.Y() ); 1662 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1663 } 1664 break; 1665 1666 case( META_TEXTARRAY_ACTION ): 1667 { 1668 MetaTextArrayAction* pAct = (MetaTextArrayAction*) pAction; 1669 Rectangle aRect; 1670 // hdu said base = index 1671 aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(), 1672 0, pAct->GetDXArray() ); 1673 Point aPt( pAct->GetPoint() ); 1674 aRect.Move( aPt.X(), aPt.Y() ); 1675 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1676 } 1677 break; 1678 1679 case( META_STRETCHTEXT_ACTION ): 1680 { 1681 MetaStretchTextAction* pAct = (MetaStretchTextAction*) pAction; 1682 Rectangle aRect; 1683 // hdu said base = index 1684 aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(), 1685 pAct->GetWidth(), NULL ); 1686 Point aPt( pAct->GetPoint() ); 1687 aRect.Move( aPt.X(), aPt.Y() ); 1688 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1689 } 1690 break; 1691 1692 case( META_TEXTLINE_ACTION ): 1693 { 1694 MetaTextLineAction* pAct = (MetaTextLineAction*) pAction; 1695 // measure a test string to get ascend and descent right 1696 static const sal_Unicode pStr[] = { 0xc4, 0x67, 0 }; 1697 String aStr( pStr ); 1698 1699 Rectangle aRect; 1700 aMapVDev.GetTextBoundRect( aRect, aStr, 0, 0, aStr.Len(), 0, NULL ); 1701 Point aPt( pAct->GetStartPoint() ); 1702 aRect.Move( aPt.X(), aPt.Y() ); 1703 aRect.Right() = aRect.Left() + pAct->GetWidth(); 1704 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1705 } 1706 break; 1707 1708 case( META_BMPSCALE_ACTION ): 1709 { 1710 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction; 1711 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() ); 1712 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1713 } 1714 break; 1715 1716 case( META_BMPSCALEPART_ACTION ): 1717 { 1718 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction; 1719 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() ); 1720 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1721 } 1722 break; 1723 1724 case( META_BMPEXSCALE_ACTION ): 1725 { 1726 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction; 1727 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() ); 1728 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1729 } 1730 break; 1731 1732 case( META_BMPEXSCALEPART_ACTION ): 1733 { 1734 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction; 1735 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() ); 1736 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1737 } 1738 break; 1739 1740 case( META_GRADIENT_ACTION ): 1741 { 1742 MetaGradientAction* pAct = (MetaGradientAction*) pAction; 1743 Rectangle aRect( pAct->GetRect() ); 1744 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1745 } 1746 break; 1747 1748 case( META_GRADIENTEX_ACTION ): 1749 { 1750 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction; 1751 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() ); 1752 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1753 } 1754 break; 1755 1756 case( META_COMMENT_ACTION ): 1757 { 1758 // nothing to do 1759 }; 1760 break; 1761 1762 case( META_HATCH_ACTION ): 1763 { 1764 MetaHatchAction* pAct = (MetaHatchAction*) pAction; 1765 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() ); 1766 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1767 } 1768 break; 1769 1770 case( META_TRANSPARENT_ACTION ): 1771 { 1772 MetaTransparentAction* pAct = (MetaTransparentAction*) pAction; 1773 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() ); 1774 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1775 } 1776 break; 1777 1778 case( META_FLOATTRANSPARENT_ACTION ): 1779 { 1780 MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction; 1781 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() ); 1782 // get the bound rect of the contained metafile 1783 Rectangle aRect( aTransMtf.GetBoundRect( i_rReference ) ); 1784 // scale the rect now on the assumption that the correct top left of the metafile 1785 // (not its bounds !) is (0,0) 1786 Size aPSize( aTransMtf.GetPrefSize() ); 1787 aPSize = aMapVDev.LogicToLogic( aPSize, aTransMtf.GetPrefMapMode(), aMapVDev.GetMapMode() ); 1788 Size aActSize( pAct->GetSize() ); 1789 double fX = double(aActSize.Width())/double(aPSize.Width()); 1790 double fY = double(aActSize.Height())/double(aPSize.Height()); 1791 aRect.Left() = long(double(aRect.Left())*fX); 1792 aRect.Right() = long(double(aRect.Right())*fX); 1793 aRect.Top() = long(double(aRect.Top())*fY); 1794 aRect.Bottom() = long(double(aRect.Bottom())*fY); 1795 1796 // transform the rect to current VDev state 1797 aRect = aMapVDev.LogicToLogic( aRect, aTransMtf.GetPrefMapMode(), aMapVDev.GetMapMode() ); 1798 1799 ImplActionBounds( aBound, aRect, aClipStack, 0 ); 1800 } 1801 break; 1802 1803 case( META_EPS_ACTION ): 1804 { 1805 MetaEPSAction* pAct = (MetaEPSAction*) pAction; 1806 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() ); 1807 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1808 } 1809 break; 1810 1811 case( META_CLIPREGION_ACTION ): 1812 { 1813 MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction; 1814 if( pAct->IsClipping() ) 1815 aClipStack.back() = aMapVDev.LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ); 1816 else 1817 aClipStack.back() = Rectangle(); 1818 } 1819 break; 1820 1821 case( META_ISECTRECTCLIPREGION_ACTION ): 1822 { 1823 MetaISectRectClipRegionAction* pAct = (MetaISectRectClipRegionAction*) pAction; 1824 Rectangle aRect( aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ) ); 1825 if( aClipStack.back().IsEmpty() ) 1826 aClipStack.back() = aRect; 1827 else 1828 aClipStack.back().Intersection( aRect ); 1829 } 1830 break; 1831 1832 case( META_ISECTREGIONCLIPREGION_ACTION ): 1833 { 1834 MetaISectRegionClipRegionAction* pAct = (MetaISectRegionClipRegionAction*) pAction; 1835 Rectangle aRect( aMapVDev.LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ) ); 1836 if( aClipStack.back().IsEmpty() ) 1837 aClipStack.back() = aRect; 1838 else 1839 aClipStack.back().Intersection( aRect ); 1840 } 1841 break; 1842 1843 case( META_BMP_ACTION ): 1844 { 1845 MetaBmpAction* pAct = (MetaBmpAction*) pAction; 1846 Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmap().GetSizePixel() ) ); 1847 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1848 } 1849 break; 1850 1851 case( META_BMPEX_ACTION ): 1852 { 1853 MetaBmpExAction* pAct = (MetaBmpExAction*) pAction; 1854 Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) ); 1855 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1856 } 1857 break; 1858 1859 case( META_MASK_ACTION ): 1860 { 1861 MetaMaskAction* pAct = (MetaMaskAction*) pAction; 1862 Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmap().GetSizePixel() ) ); 1863 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1864 } 1865 break; 1866 1867 case( META_MASKSCALE_ACTION ): 1868 { 1869 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction; 1870 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() ); 1871 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1872 } 1873 break; 1874 1875 case( META_MASKSCALEPART_ACTION ): 1876 { 1877 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction; 1878 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() ); 1879 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1880 } 1881 break; 1882 1883 case( META_WALLPAPER_ACTION ): 1884 { 1885 MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction; 1886 Rectangle aRect( pAct->GetRect() ); 1887 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1888 } 1889 break; 1890 1891 case( META_TEXTRECT_ACTION ): 1892 { 1893 MetaTextRectAction* pAct = (MetaTextRectAction*) pAction; 1894 Rectangle aRect( pAct->GetRect() ); 1895 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack, 0 ); 1896 } 1897 break; 1898 1899 case( META_MOVECLIPREGION_ACTION ): 1900 { 1901 MetaMoveClipRegionAction* pAct = (MetaMoveClipRegionAction*) pAction; 1902 if( ! aClipStack.back().IsEmpty() ) 1903 { 1904 Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() ); 1905 aDelta = aMapVDev.LogicToLogic( aDelta, aMapVDev.GetMapMode(), GetPrefMapMode() ); 1906 aClipStack.back().Move( aDelta.Width(), aDelta.Width() ); 1907 } 1908 } 1909 break; 1910 1911 default: 1912 { 1913 pAction->Execute( &aMapVDev ); 1914 1915 if( nActionType == META_PUSH_ACTION ) 1916 { 1917 MetaPushAction* pAct = (MetaPushAction*) pAction; 1918 aPushFlagStack.push_back( pAct->GetFlags() ); 1919 if( (aPushFlagStack.back() & PUSH_CLIPREGION) != 0 ) 1920 { 1921 Rectangle aRect( aClipStack.back() ); 1922 aClipStack.push_back( aRect ); 1923 } 1924 } 1925 else if( nActionType == META_POP_ACTION ) 1926 { 1927 // sanity check 1928 if( ! aPushFlagStack.empty() ) 1929 { 1930 if( (aPushFlagStack.back() & PUSH_CLIPREGION) != 0 ) 1931 { 1932 if( aClipStack.size() > 1 ) 1933 aClipStack.pop_back(); 1934 } 1935 aPushFlagStack.pop_back(); 1936 } 1937 } 1938 } 1939 break; 1940 } 1941 } 1942 return aBound; 1943 } 1944 1945 // ------------------------------------------------------------------------ 1946 1947 Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam ) 1948 { 1949 return Color( rColor.GetTransparency(), 1950 ( (const ImplColAdjustParam*) pColParam )->pMapR[ rColor.GetRed() ], 1951 ( (const ImplColAdjustParam*) pColParam )->pMapG[ rColor.GetGreen() ], 1952 ( (const ImplColAdjustParam*) pColParam )->pMapB[ rColor.GetBlue() ] ); 1953 1954 } 1955 1956 // ------------------------------------------------------------------------ 1957 1958 BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam ) 1959 { 1960 const ImplBmpAdjustParam* p = (const ImplBmpAdjustParam*) pBmpParam; 1961 BitmapEx aRet( rBmpEx ); 1962 1963 aRet.Adjust( p->nLuminancePercent, p->nContrastPercent, 1964 p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent, 1965 p->fGamma, p->bInvert ); 1966 1967 return aRet; 1968 } 1969 1970 // ------------------------------------------------------------------------ 1971 1972 Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam ) 1973 { 1974 sal_uInt8 cLum = rColor.GetLuminance(); 1975 1976 if( MTF_CONVERSION_1BIT_THRESHOLD == ( (const ImplColConvertParam*) pColParam )->eConversion ) 1977 cLum = ( cLum < 128 ) ? 0 : 255; 1978 1979 return Color( rColor.GetTransparency(), cLum, cLum, cLum ); 1980 } 1981 1982 // ------------------------------------------------------------------------ 1983 1984 BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam ) 1985 { 1986 BitmapEx aRet( rBmpEx ); 1987 1988 aRet.Convert( ( (const ImplBmpConvertParam*) pBmpParam )->eConversion ); 1989 1990 return aRet; 1991 } 1992 1993 // ------------------------------------------------------------------------ 1994 1995 Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam ) 1996 { 1997 return( ( (const ImplColMonoParam*) pColParam )->aColor ); 1998 } 1999 2000 // ------------------------------------------------------------------------ 2001 2002 BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam ) 2003 { 2004 BitmapPalette aPal( 3 ); 2005 2006 aPal[ 0 ] = Color( COL_BLACK ); 2007 aPal[ 1 ] = Color( COL_WHITE ); 2008 aPal[ 2 ] = ( (const ImplBmpMonoParam*) pBmpParam )->aColor; 2009 2010 Bitmap aBmp( rBmpEx.GetSizePixel(), 4, &aPal ); 2011 aBmp.Erase( ( (const ImplBmpMonoParam*) pBmpParam )->aColor ); 2012 2013 if( rBmpEx.IsAlpha() ) 2014 return BitmapEx( aBmp, rBmpEx.GetAlpha() ); 2015 else if( rBmpEx.IsTransparent() ) 2016 return BitmapEx( aBmp, rBmpEx.GetMask() ); 2017 else 2018 return aBmp; 2019 } 2020 2021 // ------------------------------------------------------------------------ 2022 2023 Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam ) 2024 { 2025 const sal_uLong nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue(); 2026 2027 for( sal_uLong i = 0; i < ( (const ImplColReplaceParam*) pColParam )->nCount; i++ ) 2028 { 2029 if( ( ( (const ImplColReplaceParam*) pColParam )->pMinR[ i ] <= nR ) && 2030 ( ( (const ImplColReplaceParam*) pColParam )->pMaxR[ i ] >= nR ) && 2031 ( ( (const ImplColReplaceParam*) pColParam )->pMinG[ i ] <= nG ) && 2032 ( ( (const ImplColReplaceParam*) pColParam )->pMaxG[ i ] >= nG ) && 2033 ( ( (const ImplColReplaceParam*) pColParam )->pMinB[ i ] <= nB ) && 2034 ( ( (const ImplColReplaceParam*) pColParam )->pMaxB[ i ] >= nB ) ) 2035 { 2036 return( ( (const ImplColReplaceParam*) pColParam )->pDstCols[ i ] ); 2037 } 2038 } 2039 2040 return rColor; 2041 } 2042 2043 // ------------------------------------------------------------------------ 2044 2045 BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam ) 2046 { 2047 const ImplBmpReplaceParam* p = (const ImplBmpReplaceParam*) pBmpParam; 2048 BitmapEx aRet( rBmpEx ); 2049 2050 aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount, p->pTols ); 2051 2052 return aRet; 2053 } 2054 2055 // ------------------------------------------------------------------------ 2056 2057 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam, 2058 BmpExchangeFnc pFncBmp, const void* pBmpParam ) 2059 { 2060 GDIMetaFile aMtf; 2061 2062 aMtf.aPrefSize = aPrefSize; 2063 aMtf.aPrefMapMode = aPrefMapMode; 2064 2065 for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() ) 2066 { 2067 const sal_uInt16 nType = pAction->GetType(); 2068 2069 switch( nType ) 2070 { 2071 case( META_PIXEL_ACTION ): 2072 { 2073 MetaPixelAction* pAct = (MetaPixelAction*) pAction; 2074 aMtf.Insert( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND ); 2075 } 2076 break; 2077 2078 case( META_LINECOLOR_ACTION ): 2079 { 2080 MetaLineColorAction* pAct = (MetaLineColorAction*) pAction; 2081 2082 if( !pAct->IsSetting() ) 2083 pAct->Duplicate(); 2084 else 2085 pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True ); 2086 2087 aMtf.Insert( pAct, LIST_APPEND ); 2088 } 2089 break; 2090 2091 case( META_FILLCOLOR_ACTION ): 2092 { 2093 MetaFillColorAction* pAct = (MetaFillColorAction*) pAction; 2094 2095 if( !pAct->IsSetting() ) 2096 pAct->Duplicate(); 2097 else 2098 pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True ); 2099 2100 aMtf.Insert( pAct, LIST_APPEND ); 2101 } 2102 break; 2103 2104 case( META_TEXTCOLOR_ACTION ): 2105 { 2106 MetaTextColorAction* pAct = (MetaTextColorAction*) pAction; 2107 aMtf.Insert( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND ); 2108 } 2109 break; 2110 2111 case( META_TEXTFILLCOLOR_ACTION ): 2112 { 2113 MetaTextFillColorAction* pAct = (MetaTextFillColorAction*) pAction; 2114 2115 if( !pAct->IsSetting() ) 2116 pAct->Duplicate(); 2117 else 2118 pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True ); 2119 2120 aMtf.Insert( pAct, LIST_APPEND ); 2121 } 2122 break; 2123 2124 case( META_TEXTLINECOLOR_ACTION ): 2125 { 2126 MetaTextLineColorAction* pAct = (MetaTextLineColorAction*) pAction; 2127 2128 if( !pAct->IsSetting() ) 2129 pAct->Duplicate(); 2130 else 2131 pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True ); 2132 2133 aMtf.Insert( pAct, LIST_APPEND ); 2134 } 2135 break; 2136 2137 case( META_OVERLINECOLOR_ACTION ): 2138 { 2139 MetaOverlineColorAction* pAct = (MetaOverlineColorAction*) pAction; 2140 2141 if( !pAct->IsSetting() ) 2142 pAct->Duplicate(); 2143 else 2144 pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True ); 2145 2146 aMtf.Insert( pAct, LIST_APPEND ); 2147 } 2148 break; 2149 2150 case( META_FONT_ACTION ): 2151 { 2152 MetaFontAction* pAct = (MetaFontAction*) pAction; 2153 Font aFont( pAct->GetFont() ); 2154 2155 aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) ); 2156 aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) ); 2157 aMtf.Insert( new MetaFontAction( aFont ), LIST_APPEND ); 2158 } 2159 break; 2160 2161 case( META_WALLPAPER_ACTION ): 2162 { 2163 MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction; 2164 Wallpaper aWall( pAct->GetWallpaper() ); 2165 const Rectangle& rRect = pAct->GetRect(); 2166 2167 aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) ); 2168 2169 if( aWall.IsBitmap() ) 2170 aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) ); 2171 2172 if( aWall.IsGradient() ) 2173 { 2174 Gradient aGradient( aWall.GetGradient() ); 2175 2176 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) ); 2177 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) ); 2178 aWall.SetGradient( aGradient ); 2179 } 2180 2181 aMtf.Insert( new MetaWallpaperAction( rRect, aWall ), LIST_APPEND ); 2182 } 2183 break; 2184 2185 case( META_BMP_ACTION ): 2186 case( META_BMPEX_ACTION ): 2187 case( META_MASK_ACTION ): 2188 { 2189 DBG_ERROR( "Don't use bitmap actions of this type in metafiles!" ); 2190 } 2191 break; 2192 2193 case( META_BMPSCALE_ACTION ): 2194 { 2195 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction; 2196 aMtf.Insert( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(), 2197 pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ), 2198 LIST_APPEND ); 2199 } 2200 break; 2201 2202 case( META_BMPSCALEPART_ACTION ): 2203 { 2204 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction; 2205 aMtf.Insert( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(), 2206 pAct->GetSrcPoint(), pAct->GetSrcSize(), 2207 pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ), 2208 LIST_APPEND ); 2209 } 2210 break; 2211 2212 case( META_BMPEXSCALE_ACTION ): 2213 { 2214 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction; 2215 aMtf.Insert( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(), 2216 pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ), 2217 LIST_APPEND ); 2218 } 2219 break; 2220 2221 case( META_BMPEXSCALEPART_ACTION ): 2222 { 2223 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction; 2224 aMtf.Insert( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(), 2225 pAct->GetSrcPoint(), pAct->GetSrcSize(), 2226 pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ), 2227 LIST_APPEND ); 2228 } 2229 break; 2230 2231 case( META_MASKSCALE_ACTION ): 2232 { 2233 MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction; 2234 aMtf.Insert( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(), 2235 pAct->GetBitmap(), 2236 pFncCol( pAct->GetColor(), pColParam ) ), 2237 LIST_APPEND ); 2238 } 2239 break; 2240 2241 case( META_MASKSCALEPART_ACTION ): 2242 { 2243 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction; 2244 aMtf.Insert( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(), 2245 pAct->GetSrcPoint(), pAct->GetSrcSize(), 2246 pAct->GetBitmap(), 2247 pFncCol( pAct->GetColor(), pColParam ) ), 2248 LIST_APPEND ); 2249 } 2250 break; 2251 2252 case( META_GRADIENT_ACTION ): 2253 { 2254 MetaGradientAction* pAct = (MetaGradientAction*) pAction; 2255 Gradient aGradient( pAct->GetGradient() ); 2256 2257 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) ); 2258 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) ); 2259 aMtf.Insert( new MetaGradientAction( pAct->GetRect(), aGradient ), LIST_APPEND ); 2260 } 2261 break; 2262 2263 case( META_GRADIENTEX_ACTION ): 2264 { 2265 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction; 2266 Gradient aGradient( pAct->GetGradient() ); 2267 2268 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) ); 2269 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) ); 2270 aMtf.Insert( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ), LIST_APPEND ); 2271 } 2272 break; 2273 2274 case( META_HATCH_ACTION ): 2275 { 2276 MetaHatchAction* pAct = (MetaHatchAction*) pAction; 2277 Hatch aHatch( pAct->GetHatch() ); 2278 2279 aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) ); 2280 aMtf.Insert( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ), LIST_APPEND ); 2281 } 2282 break; 2283 2284 case( META_FLOATTRANSPARENT_ACTION ): 2285 { 2286 MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction; 2287 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() ); 2288 2289 aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam ); 2290 aMtf.Insert( new MetaFloatTransparentAction( aTransMtf, 2291 pAct->GetPoint(), pAct->GetSize(), 2292 pAct->GetGradient() ), 2293 LIST_APPEND ); 2294 } 2295 break; 2296 2297 case( META_EPS_ACTION ): 2298 { 2299 MetaEPSAction* pAct = (MetaEPSAction*) pAction; 2300 GDIMetaFile aSubst( pAct->GetSubstitute() ); 2301 2302 aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam ); 2303 aMtf.Insert( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(), 2304 pAct->GetLink(), aSubst ), 2305 LIST_APPEND ); 2306 } 2307 break; 2308 2309 default: 2310 { 2311 pAction->Duplicate(); 2312 aMtf.Insert( pAction, LIST_APPEND ); 2313 } 2314 break; 2315 } 2316 } 2317 2318 *this = aMtf; 2319 } 2320 2321 // ------------------------------------------------------------------------ 2322 2323 void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent, 2324 short nChannelRPercent, short nChannelGPercent, 2325 short nChannelBPercent, double fGamma, sal_Bool bInvert ) 2326 { 2327 // nothing to do? => return quickly 2328 if( nLuminancePercent || nContrastPercent || 2329 nChannelRPercent || nChannelGPercent || nChannelBPercent || 2330 ( fGamma != 1.0 ) || bInvert ) 2331 { 2332 double fM, fROff, fGOff, fBOff, fOff; 2333 ImplColAdjustParam aColParam; 2334 ImplBmpAdjustParam aBmpParam; 2335 2336 aColParam.pMapR = new sal_uInt8[ 256 ]; 2337 aColParam.pMapG = new sal_uInt8[ 256 ]; 2338 aColParam.pMapB = new sal_uInt8[ 256 ]; 2339 2340 // calculate slope 2341 if( nContrastPercent >= 0 ) 2342 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) ); 2343 else 2344 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0; 2345 2346 // total offset = luminance offset + contrast offset 2347 fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0; 2348 2349 // channel offset = channel offset + total offset 2350 fROff = nChannelRPercent * 2.55 + fOff; 2351 fGOff = nChannelGPercent * 2.55 + fOff; 2352 fBOff = nChannelBPercent * 2.55 + fOff; 2353 2354 // calculate gamma value 2355 fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma ); 2356 const sal_Bool bGamma = ( fGamma != 1.0 ); 2357 2358 // create mapping table 2359 for( long nX = 0L; nX < 256L; nX++ ) 2360 { 2361 aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L ); 2362 aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L ); 2363 aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L ); 2364 2365 if( bGamma ) 2366 { 2367 aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma ); 2368 aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma ); 2369 aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma ); 2370 } 2371 2372 if( bInvert ) 2373 { 2374 aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ]; 2375 aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ]; 2376 aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ]; 2377 } 2378 } 2379 2380 aBmpParam.nLuminancePercent = nLuminancePercent; 2381 aBmpParam.nContrastPercent = nContrastPercent; 2382 aBmpParam.nChannelRPercent = nChannelRPercent; 2383 aBmpParam.nChannelGPercent = nChannelGPercent; 2384 aBmpParam.nChannelBPercent = nChannelBPercent; 2385 aBmpParam.fGamma = fGamma; 2386 aBmpParam.bInvert = bInvert; 2387 2388 // do color adjustment 2389 ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam ); 2390 2391 delete[] aColParam.pMapR; 2392 delete[] aColParam.pMapG; 2393 delete[] aColParam.pMapB; 2394 } 2395 } 2396 2397 // ------------------------------------------------------------------------ 2398 2399 void GDIMetaFile::Convert( MtfConversion eConversion ) 2400 { 2401 // nothing to do? => return quickly 2402 if( eConversion != MTF_CONVERSION_NONE ) 2403 { 2404 ImplColConvertParam aColParam; 2405 ImplBmpConvertParam aBmpParam; 2406 2407 aColParam.eConversion = eConversion; 2408 aBmpParam.eConversion = ( MTF_CONVERSION_1BIT_THRESHOLD == eConversion ) ? BMP_CONVERSION_1BIT_THRESHOLD : BMP_CONVERSION_8BIT_GREYS; 2409 2410 ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam ); 2411 } 2412 } 2413 2414 // ------------------------------------------------------------------------ 2415 2416 void GDIMetaFile::ReplaceColors( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ) 2417 { 2418 ReplaceColors( &rSearchColor, &rReplaceColor, 1, &nTol ); 2419 } 2420 2421 // ------------------------------------------------------------------------ 2422 2423 void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, sal_uLong* pTols ) 2424 { 2425 ImplColReplaceParam aColParam; 2426 ImplBmpReplaceParam aBmpParam; 2427 2428 aColParam.pMinR = new sal_uLong[ nColorCount ]; 2429 aColParam.pMaxR = new sal_uLong[ nColorCount ]; 2430 aColParam.pMinG = new sal_uLong[ nColorCount ]; 2431 aColParam.pMaxG = new sal_uLong[ nColorCount ]; 2432 aColParam.pMinB = new sal_uLong[ nColorCount ]; 2433 aColParam.pMaxB = new sal_uLong[ nColorCount ]; 2434 2435 for( sal_uLong i = 0; i < nColorCount; i++ ) 2436 { 2437 const long nTol = pTols ? ( pTols[ i ] * 255 ) / 100 : 0; 2438 long nVal; 2439 2440 nVal = pSearchColors[ i ].GetRed(); 2441 aColParam.pMinR[ i ] = (sal_uLong) Max( nVal - nTol, 0L ); 2442 aColParam.pMaxR[ i ] = (sal_uLong) Min( nVal + nTol, 255L ); 2443 2444 nVal = pSearchColors[ i ].GetGreen(); 2445 aColParam.pMinG[ i ] = (sal_uLong) Max( nVal - nTol, 0L ); 2446 aColParam.pMaxG[ i ] = (sal_uLong) Min( nVal + nTol, 255L ); 2447 2448 nVal = pSearchColors[ i ].GetBlue(); 2449 aColParam.pMinB[ i ] = (sal_uLong) Max( nVal - nTol, 0L ); 2450 aColParam.pMaxB[ i ] = (sal_uLong) Min( nVal + nTol, 255L ); 2451 } 2452 2453 aColParam.pDstCols = pReplaceColors; 2454 aColParam.nCount = nColorCount; 2455 2456 aBmpParam.pSrcCols = pSearchColors; 2457 aBmpParam.pDstCols = pReplaceColors; 2458 aBmpParam.nCount = nColorCount; 2459 aBmpParam.pTols = pTols; 2460 2461 ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam ); 2462 2463 delete[] aColParam.pMinR; 2464 delete[] aColParam.pMaxR; 2465 delete[] aColParam.pMinG; 2466 delete[] aColParam.pMaxG; 2467 delete[] aColParam.pMinB; 2468 delete[] aColParam.pMaxB; 2469 }; 2470 2471 // ------------------------------------------------------------------------ 2472 2473 GDIMetaFile GDIMetaFile::GetMonochromeMtf( const Color& rColor ) const 2474 { 2475 GDIMetaFile aRet( *this ); 2476 2477 ImplColMonoParam aColParam; 2478 ImplBmpMonoParam aBmpParam; 2479 2480 aColParam.aColor = rColor; 2481 aBmpParam.aColor = rColor; 2482 2483 aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam ); 2484 2485 return aRet; 2486 } 2487 2488 // ------------------------------------------------------------------------ 2489 2490 sal_uLong GDIMetaFile::GetChecksum() const 2491 { 2492 GDIMetaFile aMtf; 2493 SvMemoryStream aMemStm( 65535, 65535 ); 2494 ImplMetaWriteData aWriteData; 2495 SVBT16 aBT16; 2496 SVBT32 aBT32; 2497 sal_uLong nCrc = 0; 2498 2499 aWriteData.meActualCharSet = aMemStm.GetStreamCharSet(); 2500 2501 for( sal_uLong i = 0, nObjCount = GetActionCount(); i < nObjCount; i++ ) 2502 { 2503 MetaAction* pAction = GetAction( i ); 2504 2505 switch( pAction->GetType() ) 2506 { 2507 case( META_BMP_ACTION ): 2508 { 2509 MetaBmpAction* pAct = (MetaBmpAction*) pAction; 2510 2511 ShortToSVBT16( pAct->GetType(), aBT16 ); 2512 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2513 2514 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2515 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2516 2517 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2518 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2519 2520 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2521 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2522 } 2523 break; 2524 2525 case( META_BMPSCALE_ACTION ): 2526 { 2527 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction; 2528 2529 ShortToSVBT16( pAct->GetType(), aBT16 ); 2530 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2531 2532 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2533 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2534 2535 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2536 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2537 2538 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2539 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2540 2541 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 ); 2542 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2543 2544 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 ); 2545 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2546 } 2547 break; 2548 2549 case( META_BMPSCALEPART_ACTION ): 2550 { 2551 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction; 2552 2553 ShortToSVBT16( pAct->GetType(), aBT16 ); 2554 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2555 2556 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2557 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2558 2559 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 ); 2560 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2561 2562 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 ); 2563 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2564 2565 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 ); 2566 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2567 2568 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 ); 2569 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2570 2571 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 ); 2572 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2573 2574 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 ); 2575 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2576 2577 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 ); 2578 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2579 2580 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 ); 2581 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2582 } 2583 break; 2584 2585 case( META_BMPEX_ACTION ): 2586 { 2587 MetaBmpExAction* pAct = (MetaBmpExAction*) pAction; 2588 2589 ShortToSVBT16( pAct->GetType(), aBT16 ); 2590 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2591 2592 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 ); 2593 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2594 2595 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2596 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2597 2598 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2599 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2600 } 2601 break; 2602 2603 case( META_BMPEXSCALE_ACTION ): 2604 { 2605 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction; 2606 2607 ShortToSVBT16( pAct->GetType(), aBT16 ); 2608 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2609 2610 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 ); 2611 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2612 2613 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2614 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2615 2616 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2617 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2618 2619 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 ); 2620 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2621 2622 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 ); 2623 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2624 } 2625 break; 2626 2627 case( META_BMPEXSCALEPART_ACTION ): 2628 { 2629 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction; 2630 2631 ShortToSVBT16( pAct->GetType(), aBT16 ); 2632 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2633 2634 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 ); 2635 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2636 2637 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 ); 2638 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2639 2640 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 ); 2641 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2642 2643 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 ); 2644 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2645 2646 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 ); 2647 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2648 2649 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 ); 2650 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2651 2652 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 ); 2653 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2654 2655 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 ); 2656 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2657 2658 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 ); 2659 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2660 } 2661 break; 2662 2663 case( META_MASK_ACTION ): 2664 { 2665 MetaMaskAction* pAct = (MetaMaskAction*) pAction; 2666 2667 ShortToSVBT16( pAct->GetType(), aBT16 ); 2668 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2669 2670 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2671 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2672 2673 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 ); 2674 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2675 2676 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2677 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2678 2679 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2680 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2681 } 2682 break; 2683 2684 case( META_MASKSCALE_ACTION ): 2685 { 2686 MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction; 2687 2688 ShortToSVBT16( pAct->GetType(), aBT16 ); 2689 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2690 2691 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2692 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2693 2694 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 ); 2695 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2696 2697 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); 2698 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2699 2700 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); 2701 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2702 2703 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 ); 2704 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2705 2706 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 ); 2707 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2708 } 2709 break; 2710 2711 case( META_MASKSCALEPART_ACTION ): 2712 { 2713 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction; 2714 2715 ShortToSVBT16( pAct->GetType(), aBT16 ); 2716 nCrc = rtl_crc32( nCrc, aBT16, 2 ); 2717 2718 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 ); 2719 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2720 2721 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 ); 2722 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2723 2724 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 ); 2725 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2726 2727 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 ); 2728 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2729 2730 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 ); 2731 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2732 2733 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 ); 2734 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2735 2736 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 ); 2737 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2738 2739 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 ); 2740 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2741 2742 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 ); 2743 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2744 2745 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 ); 2746 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 2747 } 2748 break; 2749 2750 case META_EPS_ACTION : 2751 { 2752 MetaEPSAction* pAct = (MetaEPSAction*) pAction; 2753 nCrc = rtl_crc32( nCrc, pAct->GetLink().GetData(), pAct->GetLink().GetDataSize() ); 2754 } 2755 break; 2756 2757 case META_CLIPREGION_ACTION : 2758 { 2759 MetaClipRegionAction* pAct = dynamic_cast< MetaClipRegionAction* >(pAction); 2760 const Region& rRegion = pAct->GetRegion(); 2761 2762 if(rRegion.HasPolyPolygon()) 2763 { 2764 // It has shown that this is a possible bottleneck for checksum calculation. 2765 // In worst case a very expensive RegionHandle representation gets created. 2766 // In this case it's cheaper to use the PolyPolygon 2767 const basegfx::B2DPolyPolygon aPolyPolygon(rRegion.GetB2DPolyPolygon()); 2768 const sal_uInt32 nPolyCount(aPolyPolygon.count()); 2769 SVBT64 aSVBT64; 2770 2771 for(sal_uInt32 a(0); a < nPolyCount; a++) 2772 { 2773 const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(a)); 2774 const sal_uInt32 nPointCount(aPolygon.count()); 2775 const bool bControl(aPolygon.areControlPointsUsed()); 2776 2777 for(sal_uInt32 b(0); b < nPointCount; b++) 2778 { 2779 const basegfx::B2DPoint aPoint(aPolygon.getB2DPoint(b)); 2780 2781 DoubleToSVBT64(aPoint.getX(), aSVBT64); 2782 nCrc = rtl_crc32(nCrc, aSVBT64, 8); 2783 DoubleToSVBT64(aPoint.getY(), aSVBT64); 2784 nCrc = rtl_crc32(nCrc, aSVBT64, 8); 2785 2786 if(bControl) 2787 { 2788 if(aPolygon.isPrevControlPointUsed(b)) 2789 { 2790 const basegfx::B2DPoint aCtrl(aPolygon.getPrevControlPoint(b)); 2791 2792 DoubleToSVBT64(aCtrl.getX(), aSVBT64); 2793 nCrc = rtl_crc32(nCrc, aSVBT64, 8); 2794 DoubleToSVBT64(aCtrl.getY(), aSVBT64); 2795 nCrc = rtl_crc32(nCrc, aSVBT64, 8); 2796 } 2797 2798 if(aPolygon.isNextControlPointUsed(b)) 2799 { 2800 const basegfx::B2DPoint aCtrl(aPolygon.getNextControlPoint(b)); 2801 2802 DoubleToSVBT64(aCtrl.getX(), aSVBT64); 2803 nCrc = rtl_crc32(nCrc, aSVBT64, 8); 2804 DoubleToSVBT64(aCtrl.getY(), aSVBT64); 2805 nCrc = rtl_crc32(nCrc, aSVBT64, 8); 2806 } 2807 } 2808 } 2809 } 2810 2811 SVBT8 aSVBT8; 2812 ByteToSVBT8((sal_uInt8)pAct->IsClipping(), aSVBT8); 2813 nCrc = rtl_crc32(nCrc, aSVBT8, 1); 2814 } 2815 else 2816 { 2817 pAction->Write( aMemStm, &aWriteData ); 2818 nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() ); 2819 aMemStm.Seek( 0 ); 2820 } 2821 } 2822 break; 2823 2824 default: 2825 { 2826 pAction->Write( aMemStm, &aWriteData ); 2827 nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() ); 2828 aMemStm.Seek( 0 ); 2829 } 2830 break; 2831 } 2832 } 2833 2834 return nCrc; 2835 } 2836 2837 // ------------------------------------------------------------------------ 2838 2839 sal_uLong GDIMetaFile::GetSizeBytes() const 2840 { 2841 sal_uLong nSizeBytes = 0; 2842 2843 for( sal_uLong i = 0, nObjCount = GetActionCount(); i < nObjCount; ++i ) 2844 { 2845 MetaAction* pAction = GetAction( i ); 2846 2847 // default action size is set to 32 (=> not the exact value) 2848 nSizeBytes += 32; 2849 2850 // add sizes for large action content 2851 switch( pAction->GetType() ) 2852 { 2853 case( META_BMP_ACTION ): nSizeBytes += ( (MetaBmpAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2854 case( META_BMPSCALE_ACTION ): nSizeBytes += ( (MetaBmpScaleAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2855 case( META_BMPSCALEPART_ACTION ): nSizeBytes += ( (MetaBmpScalePartAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2856 2857 case( META_BMPEX_ACTION ): nSizeBytes += ( (MetaBmpExAction*) pAction )->GetBitmapEx().GetSizeBytes(); break; 2858 case( META_BMPEXSCALE_ACTION ): nSizeBytes += ( (MetaBmpExScaleAction*) pAction )->GetBitmapEx().GetSizeBytes(); break; 2859 case( META_BMPEXSCALEPART_ACTION ): nSizeBytes += ( (MetaBmpExScalePartAction*) pAction )->GetBitmapEx().GetSizeBytes(); break; 2860 2861 case( META_MASK_ACTION ): nSizeBytes += ( (MetaMaskAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2862 case( META_MASKSCALE_ACTION ): nSizeBytes += ( (MetaMaskScaleAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2863 case( META_MASKSCALEPART_ACTION ): nSizeBytes += ( (MetaMaskScalePartAction*) pAction )->GetBitmap().GetSizeBytes(); break; 2864 2865 case( META_POLYLINE_ACTION ): nSizeBytes += ( ( (MetaPolyLineAction*) pAction )->GetPolygon().GetSize() * sizeof( Point ) ); break; 2866 case( META_POLYGON_ACTION ): nSizeBytes += ( ( (MetaPolygonAction*) pAction )->GetPolygon().GetSize() * sizeof( Point ) ); break; 2867 case( META_POLYPOLYGON_ACTION ): 2868 { 2869 const PolyPolygon& rPolyPoly = ( (MetaPolyPolygonAction*) pAction )->GetPolyPolygon(); 2870 2871 for( sal_uInt16 n = 0; n < rPolyPoly.Count(); ++n ) 2872 nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) ); 2873 } 2874 break; 2875 2876 case( META_TEXT_ACTION ): nSizeBytes += ( ( (MetaTextAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break; 2877 case( META_STRETCHTEXT_ACTION ): nSizeBytes += ( ( (MetaStretchTextAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break; 2878 case( META_TEXTRECT_ACTION ): nSizeBytes += ( ( (MetaTextRectAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break; 2879 case( META_TEXTARRAY_ACTION ): 2880 { 2881 MetaTextArrayAction* pTextArrayAction = (MetaTextArrayAction*) pAction; 2882 2883 nSizeBytes += ( pTextArrayAction->GetText().Len() * sizeof( sal_Unicode ) ); 2884 2885 if( pTextArrayAction->GetDXArray() ) 2886 nSizeBytes += ( pTextArrayAction->GetLen() << 2 ); 2887 } 2888 break; 2889 } 2890 } 2891 2892 return( nSizeBytes ); 2893 } 2894 2895 // ------------------------------------------------------------------------ 2896 2897 SvStream& operator>>( SvStream& rIStm, GDIMetaFile& rGDIMetaFile ) 2898 { 2899 if( !rIStm.GetError() ) 2900 { 2901 char aId[ 7 ]; 2902 sal_uLong nStmPos = rIStm.Tell(); 2903 sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt(); 2904 2905 rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 2906 2907 aId[ 0 ] = 0; 2908 aId[ 6 ] = 0; 2909 rIStm.Read( aId, 6 ); 2910 2911 if ( !strcmp( aId, "VCLMTF" ) ) 2912 { 2913 // new format 2914 VersionCompat* pCompat; 2915 MetaAction* pAction; 2916 sal_uInt32 nStmCompressMode = 0; 2917 sal_uInt32 nCount = 0; 2918 2919 pCompat = new VersionCompat( rIStm, STREAM_READ ); 2920 2921 rIStm >> nStmCompressMode; 2922 rIStm >> rGDIMetaFile.aPrefMapMode; 2923 rIStm >> rGDIMetaFile.aPrefSize; 2924 rIStm >> nCount; 2925 2926 delete pCompat; 2927 2928 ImplMetaReadData aReadData; 2929 aReadData.meActualCharSet = rIStm.GetStreamCharSet(); 2930 2931 for( sal_uInt32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); nAction++ ) 2932 { 2933 pAction = MetaAction::ReadMetaAction( rIStm, &aReadData ); 2934 2935 if( pAction ) 2936 rGDIMetaFile.AddAction( pAction ); 2937 } 2938 } 2939 else 2940 { 2941 // to avoid possible compiler optimizations => new/delete 2942 rIStm.Seek( nStmPos ); 2943 delete( new SVMConverter( rIStm, rGDIMetaFile, CONVERT_FROM_SVM1 ) ); 2944 } 2945 2946 // check for errors 2947 if( rIStm.GetError() ) 2948 { 2949 rGDIMetaFile.Clear(); 2950 rIStm.Seek( nStmPos ); 2951 } 2952 2953 rIStm.SetNumberFormatInt( nOldFormat ); 2954 } 2955 2956 return rIStm; 2957 } 2958 2959 // ------------------------------------------------------------------------ 2960 2961 SvStream& operator<<( SvStream& rOStm, const GDIMetaFile& rGDIMetaFile ) 2962 { 2963 if( !rOStm.GetError() ) 2964 { 2965 static const char* pEnableSVM1 = getenv( "SAL_ENABLE_SVM1" ); 2966 static const bool bNoSVM1 = (NULL == pEnableSVM1 ) || ( '0' == *pEnableSVM1 ); 2967 2968 if( bNoSVM1 || rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) 2969 { 2970 const_cast< GDIMetaFile& >( rGDIMetaFile ).Write( rOStm ); 2971 } 2972 else 2973 { 2974 delete( new SVMConverter( rOStm, const_cast< GDIMetaFile& >( rGDIMetaFile ), CONVERT_TO_SVM1 ) ); 2975 } 2976 2977 #ifdef DEBUG 2978 if( !bNoSVM1 && rOStm.GetVersion() < SOFFICE_FILEFORMAT_50 ) 2979 { 2980 OSL_TRACE( \ 2981 "GDIMetaFile would normally be written in old SVM1 format by this call. \ 2982 The current implementation always writes in VCLMTF format. \ 2983 Please set environment variable SAL_ENABLE_SVM1 to '1' to reenable old behavior" ); 2984 } 2985 #endif // DEBUG 2986 } 2987 2988 return rOStm; 2989 } 2990 2991 // ------------------------------------------------------------------------ 2992 2993 SvStream& GDIMetaFile::Read( SvStream& rIStm ) 2994 { 2995 Clear(); 2996 rIStm >> *this; 2997 2998 return rIStm; 2999 } 3000 3001 // ------------------------------------------------------------------------ 3002 3003 SvStream& GDIMetaFile::Write( SvStream& rOStm ) 3004 { 3005 VersionCompat* pCompat; 3006 const sal_uInt32 nStmCompressMode = rOStm.GetCompressMode(); 3007 sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt(); 3008 3009 rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 3010 rOStm.Write( "VCLMTF", 6 ); 3011 3012 pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 ); 3013 3014 rOStm << nStmCompressMode; 3015 rOStm << aPrefMapMode; 3016 rOStm << aPrefSize; 3017 rOStm << (sal_uInt32) GetActionCount(); 3018 3019 delete pCompat; 3020 3021 ImplMetaWriteData aWriteData; 3022 aWriteData.meActualCharSet = rOStm.GetStreamCharSet(); 3023 3024 MetaAction* pAct = (MetaAction*)First(); 3025 while ( pAct ) 3026 { 3027 pAct->Write( rOStm, &aWriteData ); 3028 pAct = (MetaAction*)Next(); 3029 } 3030 3031 rOStm.SetNumberFormatInt( nOldFormat ); 3032 3033 return rOStm; 3034 } 3035 3036 // ------------------------------------------------------------------------ 3037 3038 sal_Bool GDIMetaFile::CreateThumbnail( sal_uInt32 nMaximumExtent, 3039 BitmapEx& rBmpEx, 3040 const BitmapEx* pOverlay, 3041 const Rectangle* pOverlayRect ) const 3042 { 3043 // the implementation is provided by KA 3044 3045 // initialization seems to be complicated but is used to avoid rounding errors 3046 VirtualDevice aVDev; 3047 const Point aNullPt; 3048 const Point aTLPix( aVDev.LogicToPixel( aNullPt, GetPrefMapMode() ) ); 3049 const Point aBRPix( aVDev.LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) ); 3050 Size aDrawSize( aVDev.LogicToPixel( GetPrefSize(), GetPrefMapMode() ) ); 3051 Size aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 ); 3052 Point aPosPix; 3053 3054 if ( !rBmpEx.IsEmpty() ) 3055 rBmpEx.SetEmpty(); 3056 3057 // determine size that has the same aspect ratio as image size and 3058 // fits into the rectangle determined by nMaximumExtent 3059 if ( aSizePix.Width() && aSizePix.Height() 3060 && ( sal::static_int_cast< unsigned long >(aSizePix.Width()) > 3061 nMaximumExtent || 3062 sal::static_int_cast< unsigned long >(aSizePix.Height()) > 3063 nMaximumExtent ) ) 3064 { 3065 const Size aOldSizePix( aSizePix ); 3066 double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height(); 3067 3068 if ( fWH <= 1.0 ) 3069 { 3070 aSizePix.Width() = FRound( nMaximumExtent * fWH ); 3071 aSizePix.Height() = nMaximumExtent; 3072 } 3073 else 3074 { 3075 aSizePix.Width() = nMaximumExtent; 3076 aSizePix.Height() = FRound( nMaximumExtent / fWH ); 3077 } 3078 3079 aDrawSize.Width() = FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() ); 3080 aDrawSize.Height() = FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() ); 3081 } 3082 3083 Size aFullSize; 3084 Point aBackPosPix; 3085 Rectangle aOverlayRect; 3086 3087 // calculate addigtional positions and sizes if an overlay image is used 3088 if ( pOverlay ) 3089 { 3090 aFullSize = Size( nMaximumExtent, nMaximumExtent ); 3091 aOverlayRect = Rectangle( aNullPt, aFullSize ); 3092 3093 aOverlayRect.Intersection( pOverlayRect ? *pOverlayRect : Rectangle( aNullPt, pOverlay->GetSizePixel() ) ); 3094 3095 if ( !aOverlayRect.IsEmpty() ) 3096 aBackPosPix = Point( ( nMaximumExtent - aSizePix.Width() ) >> 1, ( nMaximumExtent - aSizePix.Height() ) >> 1 ); 3097 else 3098 pOverlay = NULL; 3099 } 3100 else 3101 { 3102 aFullSize = aSizePix; 3103 pOverlay = NULL; 3104 } 3105 3106 // draw image(s) into VDev and get resulting image 3107 if ( aVDev.SetOutputSizePixel( aFullSize ) ) 3108 { 3109 // draw metafile into VDev 3110 const_cast<GDIMetaFile *>(this)->WindStart(); 3111 const_cast<GDIMetaFile *>(this)->Play( &aVDev, aBackPosPix, aDrawSize ); 3112 3113 // draw overlay if neccessary 3114 if ( pOverlay ) 3115 aVDev.DrawBitmapEx( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), *pOverlay ); 3116 3117 // get paint bitmap 3118 Bitmap aBmp( aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) ); 3119 3120 // assure that we have a true color image 3121 if ( aBmp.GetBitCount() != 24 ) 3122 aBmp.Convert( BMP_CONVERSION_24BIT ); 3123 3124 // create resulting mask bitmap with metafile output set to black 3125 GDIMetaFile aMonchromeMtf( GetMonochromeMtf( COL_BLACK ) ); 3126 aVDev.DrawWallpaper( Rectangle( aNullPt, aSizePix ), Wallpaper( Color( COL_WHITE ) ) ); 3127 aMonchromeMtf.WindStart(); 3128 aMonchromeMtf.Play( &aVDev, aBackPosPix, aDrawSize ); 3129 3130 // watch for overlay mask 3131 if ( pOverlay ) 3132 { 3133 Bitmap aOverlayMergeBmp( aVDev.GetBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize() ) ); 3134 3135 // create ANDed resulting mask at overlay area 3136 if ( pOverlay->IsTransparent() ) 3137 aVDev.DrawBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), pOverlay->GetMask() ); 3138 else 3139 { 3140 aVDev.SetLineColor( COL_BLACK ); 3141 aVDev.SetFillColor( COL_BLACK ); 3142 aVDev.DrawRect( aOverlayRect); 3143 } 3144 3145 aOverlayMergeBmp.CombineSimple( aVDev.GetBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize() ), BMP_COMBINE_AND ); 3146 aVDev.DrawBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), aOverlayMergeBmp ); 3147 } 3148 3149 rBmpEx = BitmapEx( aBmp, aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) ); 3150 } 3151 3152 return !rBmpEx.IsEmpty(); 3153 } 3154