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