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