LibreOffice Module vcl (master)  1
gdimtf.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <cstdlib>
21 #include <memory>
22 #include <sal/log.hxx>
23 #include <osl/diagnose.h>
24 #include <tools/diagnose_ex.h>
25 #include <tools/helpers.hxx>
26 #include <tools/stream.hxx>
27 #include <tools/vcompat.hxx>
28 #include <tools/fract.hxx>
29 #include <vcl/BitmapPalette.hxx>
30 #include <vcl/metaact.hxx>
31 #include <vcl/outdev.hxx>
32 #include <vcl/window.hxx>
33 #include <vcl/virdev.hxx>
34 #include <vcl/svapp.hxx>
35 #include <vcl/gdimtf.hxx>
36 #include <vcl/graphictools.hxx>
38 #include <vcl/canvastools.hxx>
39 #include <vcl/mtfxmldump.hxx>
40 
41 #include <svmconverter.hxx>
42 #include <TypeSerializer.hxx>
43 
44 #include <com/sun/star/beans/XFastPropertySet.hpp>
45 #include <com/sun/star/rendering/MtfRenderer.hpp>
46 #include <com/sun/star/rendering/XBitmapCanvas.hpp>
47 #include <com/sun/star/rendering/XCanvas.hpp>
49 
50 using namespace com::sun::star;
51 
52 #define GAMMA( _def_cVal, _def_InvGamma ) (static_cast<sal_uInt8>(MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0,255)))
53 
54 namespace {
55 
56 struct ImplColAdjustParam
57 {
58  std::unique_ptr<sal_uInt8[]> pMapR;
59  std::unique_ptr<sal_uInt8[]> pMapG;
60  std::unique_ptr<sal_uInt8[]> pMapB;
61 };
62 
63 struct ImplBmpAdjustParam
64 {
65  short nLuminancePercent;
66  short nContrastPercent;
67  short nChannelRPercent;
68  short nChannelGPercent;
69  short nChannelBPercent;
70  double fGamma;
71  bool bInvert;
72 };
73 
74 struct ImplColConvertParam
75 {
76  MtfConversion eConversion;
77 };
78 
79 struct ImplBmpConvertParam
80 {
81  BmpConversion eConversion;
82 };
83 
84 struct ImplColMonoParam
85 {
86  Color aColor;
87 };
88 
89 struct ImplBmpMonoParam
90 {
91  Color aColor;
92 };
93 
94 struct ImplColReplaceParam
95 {
96  std::unique_ptr<sal_uLong[]> pMinR;
97  std::unique_ptr<sal_uLong[]> pMaxR;
98  std::unique_ptr<sal_uLong[]> pMinG;
99  std::unique_ptr<sal_uLong[]> pMaxG;
100  std::unique_ptr<sal_uLong[]> pMinB;
101  std::unique_ptr<sal_uLong[]> pMaxB;
102  const Color * pDstCols;
104 };
105 
106 struct ImplBmpReplaceParam
107 {
108  const Color* pSrcCols;
109  const Color* pDstCols;
111 };
112 
113 }
114 
116  m_nCurrentActionElement( 0 ),
117  m_aPrefSize ( 1, 1 ),
118  m_pPrev ( nullptr ),
119  m_pNext ( nullptr ),
120  m_pOutDev ( nullptr ),
121  m_bPause ( false ),
122  m_bRecord ( false ),
123  m_bUseCanvas ( false )
124 {
125 }
126 
128  m_nCurrentActionElement( rMtf.m_nCurrentActionElement ),
129  m_aPrefMapMode ( rMtf.m_aPrefMapMode ),
130  m_aPrefSize ( rMtf.m_aPrefSize ),
131  m_pPrev ( rMtf.m_pPrev ),
132  m_pNext ( rMtf.m_pNext ),
133  m_pOutDev ( nullptr ),
134  m_bPause ( false ),
135  m_bRecord ( false ),
136  m_bUseCanvas ( rMtf.m_bUseCanvas )
137 {
138  for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
139  {
140  m_aList.push_back( rMtf.GetAction( i ) );
141  }
142 
143  if( rMtf.m_bRecord )
144  {
145  Record( rMtf.m_pOutDev );
146 
147  if ( rMtf.m_bPause )
148  Pause( true );
149  }
150 }
151 
153 {
154  Clear();
155 }
156 
158 {
159  return m_aList.size();
160 }
161 
162 MetaAction* GDIMetaFile::GetAction( size_t nAction ) const
163 {
164  return (nAction < m_aList.size()) ? m_aList[ nAction ].get() : nullptr;
165 }
166 
168 {
170  return m_aList.empty() ? nullptr : m_aList[ 0 ].get();
171 }
172 
174 {
175  return ( m_nCurrentActionElement + 1 < m_aList.size() ) ? m_aList[ ++m_nCurrentActionElement ].get() : nullptr;
176 }
177 
179 {
180  if ( nAction >= m_aList.size() )
181  {
182  return;
183  }
184  //fdo#39995 This doesn't increment the incoming action ref-count nor does it
185  //decrement the outgoing action ref-count
186  std::swap(pAction, m_aList[nAction]);
187 }
188 
190 {
191  if( this != &rMtf )
192  {
193  Clear();
194 
195  // Increment RefCount of MetaActions
196  for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
197  {
198  m_aList.push_back( rMtf.GetAction( i ) );
199  }
200 
202  m_aPrefSize = rMtf.m_aPrefSize;
203  m_pPrev = rMtf.m_pPrev;
204  m_pNext = rMtf.m_pNext;
205  m_pOutDev = nullptr;
206  m_bPause = false;
207  m_bRecord = false;
208  m_bUseCanvas = rMtf.m_bUseCanvas;
209 
210  if( rMtf.m_bRecord )
211  {
212  Record( rMtf.m_pOutDev );
213 
214  if( rMtf.m_bPause )
215  Pause( true );
216  }
217  }
218 
219  return *this;
220 }
221 
222 bool GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const
223 {
224  const size_t nObjCount = m_aList.size();
225  bool bRet = false;
226 
227  if( this == &rMtf )
228  bRet = true;
229  else if( rMtf.GetActionSize() == nObjCount &&
230  rMtf.GetPrefSize() == m_aPrefSize &&
231  rMtf.GetPrefMapMode() == m_aPrefMapMode )
232  {
233  bRet = true;
234 
235  for( size_t n = 0; n < nObjCount; n++ )
236  {
237  if( m_aList[ n ] != rMtf.GetAction( n ) )
238  {
239  bRet = false;
240  break;
241  }
242  }
243  }
244 
245  return bRet;
246 }
247 
249 {
250  if( m_bRecord )
251  Stop();
252 
253  m_aList.clear();
254 }
255 
256 void GDIMetaFile::Linker( OutputDevice* pOut, bool bLink )
257 {
258  if( bLink )
259  {
260  m_pNext = nullptr;
261  m_pPrev = pOut->GetConnectMetaFile();
262  pOut->SetConnectMetaFile( this );
263 
264  if( m_pPrev )
265  m_pPrev->m_pNext = this;
266  }
267  else
268  {
269  if( m_pNext )
270  {
272 
273  if( m_pPrev )
275  }
276  else
277  {
278  if( m_pPrev )
279  m_pPrev->m_pNext = nullptr;
280 
281  pOut->SetConnectMetaFile( m_pPrev );
282  }
283 
284  m_pPrev = nullptr;
285  m_pNext = nullptr;
286  }
287 }
288 
290 {
291  if( m_bRecord )
292  Stop();
293 
294  m_nCurrentActionElement = m_aList.empty() ? 0 : (m_aList.size() - 1);
295  m_pOutDev = pOut;
296  m_bRecord = true;
297  Linker( pOut, true );
298 }
299 
301 {
302  if ( !m_bRecord && !rMtf.m_bRecord )
303  {
304  MetaAction* pAction = GetCurAction();
305  const size_t nObjCount = m_aList.size();
306 
307  rMtf.UseCanvas( rMtf.GetUseCanvas() || m_bUseCanvas );
308 
309  for( size_t nCurPos = m_nCurrentActionElement; nCurPos < nObjCount; nCurPos++ )
310  {
311  if( pAction )
312  {
313  rMtf.AddAction( pAction );
314  }
315 
316  pAction = NextAction();
317  }
318  }
319 }
320 
321 void GDIMetaFile::Play( OutputDevice* pOut, size_t nPos )
322 {
323  if( !m_bRecord )
324  {
325  MetaAction* pAction = GetCurAction();
326  const size_t nObjCount = m_aList.size();
327  size_t nSyncCount = ( pOut->GetOutDevType() == OUTDEV_WINDOW ) ? 0x000000ff : 0xffffffff;
328 
329  if( nPos > nObjCount )
330  nPos = nObjCount;
331 
332  // #i23407# Set backwards-compatible text language and layout mode
333  // This is necessary, since old metafiles don't even know of these
334  // recent add-ons. Newer metafiles must of course explicitly set
335  // those states.
339 
340  SAL_INFO( "vcl.gdi", "GDIMetaFile::Play on device of size: " << pOut->GetOutputSizePixel().Width() << " " << pOut->GetOutputSizePixel().Height());
341 
342  if( !ImplPlayWithRenderer( pOut, Point(0,0), pOut->GetOutputSize() ) ) {
343  size_t i = 0;
344  for( size_t nCurPos = m_nCurrentActionElement; nCurPos < nPos; nCurPos++ )
345  {
346  if( pAction )
347  {
348  pAction->Execute( pOut );
349 
350  // flush output from time to time
351  if( i++ > nSyncCount )
352  {
353  static_cast<vcl::Window*>( pOut )->Flush();
354  i = 0;
355  }
356  }
357 
358  pAction = NextAction();
359  }
360  }
361  pOut->Pop();
362  }
363 }
364 
365 bool GDIMetaFile::ImplPlayWithRenderer( OutputDevice* pOut, const Point& rPos, Size rLogicDestSize )
366 {
367  if (!m_bUseCanvas)
368  return false;
369 
370  Size rDestSize( pOut->LogicToPixel( rLogicDestSize ) );
371 
372  const vcl::Window* win = dynamic_cast <vcl::Window*> ( pOut );
373 
374  if (!win)
376  if (!win)
378 
379  if (!win)
380  return false;
381 
382  try
383  {
384  uno::Reference<rendering::XCanvas> xCanvas = win->GetCanvas ();
385 
386  if (!xCanvas.is())
387  return false;
388 
389  Size aSize (rDestSize.Width () + 1, rDestSize.Height () + 1);
390  uno::Reference<rendering::XBitmap> xBitmap = xCanvas->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize));
391  if( xBitmap.is () )
392  {
393  uno::Reference< rendering::XBitmapCanvas > xBitmapCanvas( xBitmap, uno::UNO_QUERY );
394  if( xBitmapCanvas.is() )
395  {
396  uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
397  uno::Reference< rendering::XMtfRenderer > xMtfRenderer = rendering::MtfRenderer::createWithBitmapCanvas( xContext, xBitmapCanvas );
398 
399  xBitmapCanvas->clear();
400  uno::Reference< beans::XFastPropertySet > xMtfFastPropertySet( xMtfRenderer, uno::UNO_QUERY );
401  if( xMtfFastPropertySet.is() )
402  // set this metafile to the renderer to
403  // speedup things (instead of copying data to
404  // sequence of bytes passed to renderer)
405  xMtfFastPropertySet->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64>( this ) ) );
406 
407  xMtfRenderer->draw( rDestSize.Width(), rDestSize.Height() );
408 
409  BitmapEx aBitmapEx;
410  if( aBitmapEx.Create( xBitmapCanvas, aSize ) )
411  {
412  if (pOut->GetMapMode().GetMapUnit() == MapUnit::MapPixel)
413  pOut->DrawBitmapEx( rPos, aBitmapEx );
414  else
415  pOut->DrawBitmapEx( rPos, rLogicDestSize, aBitmapEx );
416  return true;
417  }
418  }
419  }
420  }
421  catch (const uno::RuntimeException& )
422  {
423  throw; // runtime errors are fatal
424  }
425  catch (const uno::Exception&)
426  {
427  // ignore errors, no way of reporting them here
428  TOOLS_WARN_EXCEPTION("vcl.gdi", "GDIMetaFile::ImplPlayWithRenderer");
429  }
430 
431  return false;
432 }
433 
434 void GDIMetaFile::Play( OutputDevice* pOut, const Point& rPos,
435  const Size& rSize )
436 {
437  MapMode aDrawMap( GetPrefMapMode() );
438  Size aDestSize( pOut->LogicToPixel( rSize ) );
439 
440  if( !aDestSize.Width() || !aDestSize.Height() )
441  return;
442 
443  GDIMetaFile* pMtf = pOut->GetConnectMetaFile();
444 
445  if( ImplPlayWithRenderer( pOut, rPos, rSize ) )
446  return;
447 
448  Size aTmpPrefSize( pOut->LogicToPixel( GetPrefSize(), aDrawMap ) );
449 
450  if( !aTmpPrefSize.Width() )
451  aTmpPrefSize.setWidth( aDestSize.Width() );
452 
453  if( !aTmpPrefSize.Height() )
454  aTmpPrefSize.setHeight( aDestSize.Height() );
455 
456  Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
457  Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
458 
459  aScaleX *= aDrawMap.GetScaleX(); aDrawMap.SetScaleX( aScaleX );
460  aScaleY *= aDrawMap.GetScaleY(); aDrawMap.SetScaleY( aScaleY );
461 
462  // #i47260# Convert logical output position to offset within
463  // the metafile's mapmode. Therefore, disable pixel offset on
464  // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
465  // different mapmode (the one currently set on pOut, that is)
466  // - thus, aDrawMap's origin would generally be wrong. And
467  // even _if_ aDrawMap is similar to pOutDev's current mapmode,
468  // it's _still_ undesirable to have pixel offset unequal zero,
469  // because one would still get round-off errors (the
470  // round-trip error for LogicToPixel( PixelToLogic() ) was the
471  // reason for having pixel offset in the first place).
472  const Size& rOldOffset( pOut->GetPixelOffset() );
473  const Size aEmptySize;
474  pOut->SetPixelOffset( aEmptySize );
475  aDrawMap.SetOrigin( pOut->PixelToLogic( pOut->LogicToPixel( rPos ), aDrawMap ) );
476  pOut->SetPixelOffset( rOldOffset );
477 
478  pOut->Push();
479 
480  if ( pMtf && pMtf->IsRecord() && ( pOut->GetOutDevType() != OUTDEV_PRINTER ) )
481  pOut->SetRelativeMapMode( aDrawMap );
482  else
483  pOut->SetMapMode( aDrawMap );
484 
485  // #i23407# Set backwards-compatible text language and layout mode
486  // This is necessary, since old metafiles don't even know of these
487  // recent add-ons. Newer metafiles must of course explicitly set
488  // those states.
491 
492  Play( pOut );
493 
494  pOut->Pop();
495 
496 }
497 
498 void GDIMetaFile::Pause( bool _bPause )
499 {
500  if( m_bRecord )
501  {
502  if( _bPause )
503  {
504  if( !m_bPause )
505  Linker( m_pOutDev, false );
506  }
507  else
508  {
509  if( m_bPause )
510  Linker( m_pOutDev, true );
511  }
512 
513  m_bPause = _bPause;
514  }
515 }
516 
518 {
519  if( m_bRecord )
520  {
521  m_bRecord = false;
522 
523  if( !m_bPause )
524  Linker( m_pOutDev, false );
525  else
526  m_bPause = false;
527  }
528 }
529 
531 {
532  if( !m_bRecord )
534 }
535 
537 {
538  if( !m_bRecord )
539  if ( m_nCurrentActionElement > 0 )
541 }
542 
544 {
545  m_aList.push_back( pAction );
546 
547  if( m_pPrev )
548  {
549  m_pPrev->AddAction( pAction );
550  }
551 }
552 
553 void GDIMetaFile::AddAction(const rtl::Reference<MetaAction>& pAction, size_t nPos)
554 {
555  if ( nPos < m_aList.size() )
556  {
557  m_aList.insert( m_aList.begin() + nPos, pAction );
558  }
559  else
560  {
561  m_aList.push_back( pAction );
562  }
563 
564  if( m_pPrev )
565  {
566  m_pPrev->AddAction( pAction, nPos );
567  }
568 }
569 
571 {
572  m_aList.push_back( pAction );
573 }
574 
576 {
577  const Size aOldPrefSize( GetPrefSize() );
578  long nMoveX, nMoveY;
579  double fScaleX, fScaleY;
580 
581  if( nMirrorFlags & BmpMirrorFlags::Horizontal )
582  {
583  nMoveX = std::abs( aOldPrefSize.Width() ) - 1;
584  fScaleX = -1.0;
585  }
586  else
587  {
588  nMoveX = 0;
589  fScaleX = 1.0;
590  }
591 
592  if( nMirrorFlags & BmpMirrorFlags::Vertical )
593  {
594  nMoveY = std::abs( aOldPrefSize.Height() ) - 1;
595  fScaleY = -1.0;
596  }
597  else
598  {
599  nMoveY = 0;
600  fScaleY = 1.0;
601  }
602 
603  if( ( fScaleX != 1.0 ) || ( fScaleY != 1.0 ) )
604  {
605  Scale( fScaleX, fScaleY );
606  Move( nMoveX, nMoveY );
607  SetPrefSize( aOldPrefSize );
608  }
609 }
610 
611 void GDIMetaFile::Move( long nX, long nY )
612 {
613  const Size aBaseOffset( nX, nY );
614  Size aOffset( aBaseOffset );
616 
617  aMapVDev->EnableOutput( false );
618  aMapVDev->SetMapMode( GetPrefMapMode() );
619 
620  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
621  {
622  const MetaActionType nType = pAct->GetType();
623  MetaAction* pModAct;
624 
625  if( pAct->GetRefCount() > 1 )
626  {
627  m_aList[ m_nCurrentActionElement ] = pAct->Clone();
628  pModAct = m_aList[ m_nCurrentActionElement ].get();
629  }
630  else
631  pModAct = pAct;
632 
633  if( ( MetaActionType::MAPMODE == nType ) ||
634  ( MetaActionType::PUSH == nType ) ||
635  ( MetaActionType::POP == nType ) )
636  {
637  pModAct->Execute( aMapVDev.get() );
638  aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
639  }
640 
641  pModAct->Move( aOffset.Width(), aOffset.Height() );
642  }
643 }
644 
645 void GDIMetaFile::Move( long nX, long nY, long nDPIX, long nDPIY )
646 {
647  const Size aBaseOffset( nX, nY );
648  Size aOffset( aBaseOffset );
650 
651  aMapVDev->EnableOutput( false );
652  aMapVDev->SetReferenceDevice( nDPIX, nDPIY );
653  aMapVDev->SetMapMode( GetPrefMapMode() );
654 
655  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
656  {
657  const MetaActionType nType = pAct->GetType();
658  MetaAction* pModAct;
659 
660  if( pAct->GetRefCount() > 1 )
661  {
662  m_aList[ m_nCurrentActionElement ] = pAct->Clone();
663  pModAct = m_aList[ m_nCurrentActionElement ].get();
664  }
665  else
666  pModAct = pAct;
667 
668  if( ( MetaActionType::MAPMODE == nType ) ||
669  ( MetaActionType::PUSH == nType ) ||
670  ( MetaActionType::POP == nType ) )
671  {
672  pModAct->Execute( aMapVDev.get() );
673  if( aMapVDev->GetMapMode().GetMapUnit() == MapUnit::MapPixel )
674  {
675  aOffset = aMapVDev->LogicToPixel( aBaseOffset, GetPrefMapMode() );
676  MapMode aMap( aMapVDev->GetMapMode() );
677  aOffset.setWidth( static_cast<long>(aOffset.Width() * static_cast<double>(aMap.GetScaleX())) );
678  aOffset.setHeight( static_cast<long>(aOffset.Height() * static_cast<double>(aMap.GetScaleY())) );
679  }
680  else
681  aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
682  }
683 
684  pModAct->Move( aOffset.Width(), aOffset.Height() );
685  }
686 }
687 
688 void GDIMetaFile::Scale( double fScaleX, double fScaleY )
689 {
690  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
691  {
692  MetaAction* pModAct;
693 
694  if( pAct->GetRefCount() > 1 )
695  {
696  m_aList[ m_nCurrentActionElement ] = pAct->Clone();
697  pModAct = m_aList[ m_nCurrentActionElement ].get();
698  }
699  else
700  pModAct = pAct;
701 
702  pModAct->Scale( fScaleX, fScaleY );
703  }
704 
705  m_aPrefSize.setWidth( FRound( m_aPrefSize.Width() * fScaleX ) );
706  m_aPrefSize.setHeight( FRound( m_aPrefSize.Height() * fScaleY ) );
707 }
708 
709 void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
710 {
711  Scale( static_cast<double>(rScaleX), static_cast<double>(rScaleY) );
712 }
713 
714 void GDIMetaFile::Clip( const tools::Rectangle& i_rClipRect )
715 {
716  tools::Rectangle aCurRect( i_rClipRect );
718 
719  aMapVDev->EnableOutput( false );
720  aMapVDev->SetMapMode( GetPrefMapMode() );
721 
722  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
723  {
724  const MetaActionType nType = pAct->GetType();
725 
726  if( ( MetaActionType::MAPMODE == nType ) ||
727  ( MetaActionType::PUSH == nType ) ||
728  ( MetaActionType::POP == nType ) )
729  {
730  pAct->Execute( aMapVDev.get() );
731  aCurRect = OutputDevice::LogicToLogic( i_rClipRect, GetPrefMapMode(), aMapVDev->GetMapMode() );
732  }
733  else if( nType == MetaActionType::CLIPREGION )
734  {
735  MetaClipRegionAction* pOldAct = static_cast<MetaClipRegionAction*>(pAct);
736  vcl::Region aNewReg( aCurRect );
737  if( pOldAct->IsClipping() )
738  aNewReg.Intersect( pOldAct->GetRegion() );
739  MetaClipRegionAction* pNewAct = new MetaClipRegionAction( aNewReg, true );
740  m_aList[ m_nCurrentActionElement ] = pNewAct;
741  }
742  }
743 }
744 
745 Point GDIMetaFile::ImplGetRotatedPoint( const Point& rPt, const Point& rRotatePt,
746  const Size& rOffset, double fSin, double fCos )
747 {
748  const long nX = rPt.X() - rRotatePt.X();
749  const long nY = rPt.Y() - rRotatePt.Y();
750 
751  return Point( FRound( fCos * nX + fSin * nY ) + rRotatePt.X() + rOffset.Width(),
752  -FRound( fSin * nX - fCos * nY ) + rRotatePt.Y() + rOffset.Height() );
753 }
754 
756  const Size& rOffset, double fSin, double fCos )
757 {
758  tools::Polygon aRet( rPoly );
759 
760  aRet.Rotate( rRotatePt, fSin, fCos );
761  aRet.Move( rOffset.Width(), rOffset.Height() );
762 
763  return aRet;
764 }
765 
767  const Size& rOffset, double fSin, double fCos )
768 {
769  tools::PolyPolygon aRet( rPolyPoly );
770 
771  aRet.Rotate( rRotatePt, fSin, fCos );
772  aRet.Move( rOffset.Width(), rOffset.Height() );
773 
774  return aRet;
775 }
776 
778  const OutputDevice& rMapDev,
779  const tools::PolyPolygon& rPolyPoly,
780  const Gradient& rGrad )
781 {
782  // Generate comment, GradientEx and Gradient actions (within DrawGradient)
784  aVDev->EnableOutput( false );
785  GDIMetaFile aGradMtf;
786 
787  aGradMtf.Record( aVDev.get() );
788  aVDev->DrawGradient( rPolyPoly, rGrad );
789  aGradMtf.Stop();
790 
791  size_t i, nAct( aGradMtf.GetActionSize() );
792  for( i=0; i < nAct; ++i )
793  {
794  MetaAction* pMetaAct = aGradMtf.GetAction( i );
795  rMtf.AddAction( pMetaAct );
796  }
797 }
798 
799 void GDIMetaFile::Rotate( long nAngle10 )
800 {
801  nAngle10 %= 3600;
802  nAngle10 = ( nAngle10 < 0 ) ? ( 3599 + nAngle10 ) : nAngle10;
803 
804  if( !nAngle10 )
805  return;
806 
807  GDIMetaFile aMtf;
809  const double fAngle = F_PI1800 * nAngle10;
810  const double fSin = sin( fAngle );
811  const double fCos = cos( fAngle );
812  tools::Rectangle aRect( Point(), GetPrefSize() );
813  tools::Polygon aPoly( aRect );
814 
815  aPoly.Rotate( Point(), fSin, fCos );
816 
817  aMapVDev->EnableOutput( false );
818  aMapVDev->SetMapMode( GetPrefMapMode() );
819 
820  const tools::Rectangle aNewBound( aPoly.GetBoundRect() );
821 
822  const Point aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
823  const Size aOffset( -aNewBound.Left(), -aNewBound.Top() );
824 
825  Point aRotAnchor( aOrigin );
826  Size aRotOffset( aOffset );
827 
828  for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
829  {
830  const MetaActionType nActionType = pAction->GetType();
831 
832  switch( nActionType )
833  {
835  {
836  MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
837  aMtf.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
838  pAct->GetColor() ) );
839  }
840  break;
841 
843  {
844  MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
845  aMtf.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
846  }
847  break;
848 
850  {
851  MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
852  aMtf.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
853  ImplGetRotatedPoint( pAct->GetEndPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
854  pAct->GetLineInfo() ) );
855  }
856  break;
857 
859  {
860  MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
861  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
862  }
863  break;
864 
866  {
867  MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
868  const tools::Polygon aRoundRectPoly( pAct->GetRect(), pAct->GetHorzRound(), pAct->GetVertRound() );
869 
870  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
871  }
872  break;
873 
875  {
876  MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
877  const tools::Polygon aEllipsePoly( pAct->GetRect().Center(), pAct->GetRect().GetWidth() >> 1, pAct->GetRect().GetHeight() >> 1 );
878 
879  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
880  }
881  break;
882 
883  case MetaActionType::ARC:
884  {
885  MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
886  const tools::Polygon aArcPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Arc );
887 
888  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
889  }
890  break;
891 
892  case MetaActionType::PIE:
893  {
894  MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
895  const tools::Polygon aPiePoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Pie );
896 
897  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
898  }
899  break;
900 
902  {
903  MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
904  const tools::Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Chord );
905 
906  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
907  }
908  break;
909 
911  {
912  MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
913  aMtf.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->GetLineInfo() ) );
914  }
915  break;
916 
918  {
919  MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
920  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
921  }
922  break;
923 
925  {
926  MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
927  aMtf.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
928  }
929  break;
930 
932  {
933  MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
934  aMtf.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
935  pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
936  }
937  break;
938 
940  {
941  MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
942  aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
943  pAct->GetText(), pAct->GetDXArray(), pAct->GetIndex(), pAct->GetLen() ) );
944  }
945  break;
946 
948  {
949  MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
950  aMtf.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
951  pAct->GetWidth(), pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
952  }
953  break;
954 
956  {
957  MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
958  aMtf.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
959  pAct->GetWidth(), pAct->GetStrikeout(), pAct->GetUnderline(), pAct->GetOverline() ) );
960  }
961  break;
962 
964  {
965  MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
966  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
967  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
968  BitmapEx aBmpEx( pAct->GetBitmap() );
969 
970  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
971  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(),
972  aBmpEx ) );
973  }
974  break;
975 
977  {
978  MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
979  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
980  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
981  BitmapEx aBmpEx( pAct->GetBitmap() );
982 
983  aBmpEx.Crop( tools::Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
984  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
985 
986  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
987  }
988  break;
989 
991  {
992  MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
993  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
994  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
995  BitmapEx aBmpEx( pAct->GetBitmapEx() );
996 
997  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
998 
999  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1000  }
1001  break;
1002 
1004  {
1005  MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1006  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1007  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1008  BitmapEx aBmpEx( pAct->GetBitmapEx() );
1009 
1010  aBmpEx.Crop( tools::Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1011  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1012 
1013  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1014  }
1015  break;
1016 
1018  {
1019  MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1020 
1021  ImplAddGradientEx( aMtf, *aMapVDev,
1022  ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ),
1023  pAct->GetGradient() );
1024  }
1025  break;
1026 
1028  {
1029  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1030  aMtf.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1031  pAct->GetGradient() ) );
1032  }
1033  break;
1034 
1035  // Handle gradientex comment block correctly
1037  {
1038  MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
1039  if( pCommentAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1040  {
1041  int nBeginComments( 1 );
1042  pAction = NextAction();
1043 
1044  // skip everything, except gradientex action
1045  while( pAction )
1046  {
1047  const MetaActionType nType = pAction->GetType();
1048 
1049  if( MetaActionType::GRADIENTEX == nType )
1050  {
1051  // Add rotated gradientex
1052  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1053  ImplAddGradientEx( aMtf, *aMapVDev,
1054  ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1055  pAct->GetGradient() );
1056  }
1057  else if( MetaActionType::COMMENT == nType)
1058  {
1059  MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pAction);
1060  if( pAct->GetComment() == "XGRAD_SEQ_END" )
1061  {
1062  // handle nested blocks
1063  --nBeginComments;
1064 
1065  // gradientex comment block: end reached, done.
1066  if( !nBeginComments )
1067  break;
1068  }
1069  else if( pAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1070  {
1071  // handle nested blocks
1072  ++nBeginComments;
1073  }
1074 
1075  }
1076 
1077  pAction =NextAction();
1078  }
1079  }
1080  else
1081  {
1082  bool bPathStroke = (pCommentAct->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1083  if ( bPathStroke || pCommentAct->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1084  {
1085  if ( pCommentAct->GetDataSize() )
1086  {
1087  SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pCommentAct->GetData()), pCommentAct->GetDataSize(), StreamMode::READ );
1088  SvMemoryStream aDest;
1089  if ( bPathStroke )
1090  {
1091  SvtGraphicStroke aStroke;
1092  ReadSvtGraphicStroke( aMemStm, aStroke );
1093  tools::Polygon aPath;
1094  aStroke.getPath( aPath );
1095  aStroke.setPath( ImplGetRotatedPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1096  WriteSvtGraphicStroke( aDest, aStroke );
1097  aMtf.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1098  static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1099  }
1100  else
1101  {
1102  SvtGraphicFill aFill;
1103  ReadSvtGraphicFill( aMemStm, aFill );
1104  tools::PolyPolygon aPath;
1105  aFill.getPath( aPath );
1106  aFill.setPath( ImplGetRotatedPolyPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1107  WriteSvtGraphicFill( aDest, aFill );
1108  aMtf.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1109  static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1110  }
1111  }
1112  }
1113  else if ( pCommentAct->GetComment() == "XPATHSTROKE_SEQ_END"
1114  || pCommentAct->GetComment() == "XPATHFILL_SEQ_END" )
1115  {
1116  pAction->Execute( aMapVDev.get() );
1117  aMtf.AddAction( pAction );
1118  }
1119  }
1120  }
1121  break;
1122 
1123  case MetaActionType::HATCH:
1124  {
1125  MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1126  Hatch aHatch( pAct->GetHatch() );
1127 
1128  aHatch.SetAngle( aHatch.GetAngle() + static_cast<sal_uInt16>(nAngle10) );
1129  aMtf.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1130  aHatch ) );
1131  }
1132  break;
1133 
1135  {
1136  MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1137  aMtf.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1138  pAct->GetTransparence() ) );
1139  }
1140  break;
1141 
1143  {
1144  MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1145  GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
1146  tools::Polygon aMtfPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1147  tools::Rectangle aMtfRect( aMtfPoly.GetBoundRect() );
1148 
1149  aTransMtf.Rotate( nAngle10 );
1150  aMtf.AddAction( new MetaFloatTransparentAction( aTransMtf, aMtfRect.TopLeft(), aMtfRect.GetSize(),
1151  pAct->GetGradient() ) );
1152  }
1153  break;
1154 
1155  case MetaActionType::EPS:
1156  {
1157  MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1158  GDIMetaFile aEPSMtf( pAct->GetSubstitute() );
1159  tools::Polygon aEPSPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1160  tools::Rectangle aEPSRect( aEPSPoly.GetBoundRect() );
1161 
1162  aEPSMtf.Rotate( nAngle10 );
1163  aMtf.AddAction( new MetaEPSAction( aEPSRect.TopLeft(), aEPSRect.GetSize(),
1164  pAct->GetLink(), aEPSMtf ) );
1165  }
1166  break;
1167 
1169  {
1170  MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1171 
1172  if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1173  aMtf.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), true ) );
1174  else
1175  {
1176  aMtf.AddAction( pAction );
1177  }
1178  }
1179  break;
1180 
1182  {
1183  MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1184  aMtf.AddAction( new MetaISectRegionClipRegionAction(vcl::Region(
1185  ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor,
1186  aRotOffset, fSin, fCos )) ) );
1187  }
1188  break;
1189 
1191  {
1192  MetaISectRegionClipRegionAction* pAct = static_cast<MetaISectRegionClipRegionAction*>(pAction);
1193  const vcl::Region& rRegion = pAct->GetRegion();
1194 
1195  if( rRegion.HasPolyPolygonOrB2DPolyPolygon() )
1196  aMtf.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion.GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
1197  else
1198  {
1199  aMtf.AddAction( pAction );
1200  }
1201  }
1202  break;
1203 
1205  {
1206  MetaRefPointAction* pAct = static_cast<MetaRefPointAction*>(pAction);
1207  aMtf.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct->GetRefPoint(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->IsSetting() ) );
1208  }
1209  break;
1210 
1211  case MetaActionType::FONT:
1212  {
1213  MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
1214  vcl::Font aFont( pAct->GetFont() );
1215 
1216  aFont.SetOrientation( aFont.GetOrientation() + static_cast<sal_uInt16>(nAngle10) );
1217  aMtf.AddAction( new MetaFontAction( aFont ) );
1218  }
1219  break;
1220 
1221  case MetaActionType::BMP:
1222  case MetaActionType::BMPEX:
1223  case MetaActionType::MASK:
1229  {
1230  OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1231  }
1232  break;
1233 
1234  default:
1235  {
1236  pAction->Execute( aMapVDev.get() );
1237  aMtf.AddAction( pAction );
1238 
1239  // update rotation point and offset, if necessary
1240  if( ( MetaActionType::MAPMODE == nActionType ) ||
1241  ( MetaActionType::PUSH == nActionType ) ||
1242  ( MetaActionType::POP == nActionType ) )
1243  {
1244  aRotAnchor = OutputDevice::LogicToLogic( aOrigin, m_aPrefMapMode, aMapVDev->GetMapMode() );
1245  aRotOffset = OutputDevice::LogicToLogic( aOffset, m_aPrefMapMode, aMapVDev->GetMapMode() );
1246  }
1247  }
1248  break;
1249  }
1250  }
1251 
1253  aMtf.m_aPrefSize = aNewBound.GetSize();
1254 
1255  *this = aMtf;
1256 
1257 }
1258 
1259 static void ImplActionBounds( tools::Rectangle& o_rOutBounds,
1260  const tools::Rectangle& i_rInBounds,
1261  const std::vector<tools::Rectangle>& i_rClipStack,
1262  tools::Rectangle* o_pHairline )
1263 {
1264  tools::Rectangle aBounds( i_rInBounds );
1265  if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() )
1266  aBounds.Intersection( i_rClipStack.back() );
1267  if( ! aBounds.IsEmpty() )
1268  {
1269  if( ! o_rOutBounds.IsEmpty() )
1270  o_rOutBounds.Union( aBounds );
1271  else
1272  o_rOutBounds = aBounds;
1273 
1274  if(o_pHairline)
1275  {
1276  if( ! o_pHairline->IsEmpty() )
1277  o_pHairline->Union( aBounds );
1278  else
1279  *o_pHairline = aBounds;
1280  }
1281  }
1282 }
1283 
1285 {
1286  ScopedVclPtrInstance< VirtualDevice > aMapVDev( i_rReference );
1287 
1288  aMapVDev->EnableOutput( false );
1289  aMapVDev->SetMapMode( GetPrefMapMode() );
1290 
1291  std::vector<tools::Rectangle> aClipStack( 1, tools::Rectangle() );
1292  std::vector<PushFlags> aPushFlagStack;
1293 
1294  tools::Rectangle aBound;
1295 
1296  if(pHairline)
1297  *pHairline = tools::Rectangle();
1298 
1299  const sal_uLong nCount(GetActionSize());
1300 
1301  for(sal_uLong a(0); a < nCount; a++)
1302  {
1303  MetaAction* pAction = GetAction(a);
1304  const MetaActionType nActionType = pAction->GetType();
1305  tools::Rectangle* pUseHairline = (pHairline && aMapVDev->IsLineColor()) ? pHairline : nullptr;
1306 
1307  switch( nActionType )
1308  {
1309  case MetaActionType::PIXEL:
1310  {
1311  MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1312  ImplActionBounds( aBound,
1313  tools::Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1314  aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1315  aClipStack, pUseHairline );
1316  }
1317  break;
1318 
1319  case MetaActionType::POINT:
1320  {
1321  MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
1322  ImplActionBounds( aBound,
1323  tools::Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1324  aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1325  aClipStack, pUseHairline );
1326  }
1327  break;
1328 
1329  case MetaActionType::LINE:
1330  {
1331  MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
1332  Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() );
1333  tools::Rectangle aRect( aP1, aP2 );
1334  aRect.Justify();
1335 
1336  if(pUseHairline)
1337  {
1338  const LineInfo& rLineInfo = pAct->GetLineInfo();
1339 
1340  if(0 != rLineInfo.GetWidth())
1341  pUseHairline = nullptr;
1342  }
1343 
1344  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1345  }
1346  break;
1347 
1348  case MetaActionType::RECT:
1349  {
1350  MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
1351  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1352  }
1353  break;
1354 
1356  {
1357  MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
1358  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1359  }
1360  break;
1361 
1363  {
1364  MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
1365  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1366  }
1367  break;
1368 
1369  case MetaActionType::ARC:
1370  {
1371  MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
1372  // FIXME: this is imprecise
1373  // e.g. for small arcs the whole rectangle is WAY too large
1374  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1375  }
1376  break;
1377 
1378  case MetaActionType::PIE:
1379  {
1380  MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
1381  // FIXME: this is imprecise
1382  // e.g. for small arcs the whole rectangle is WAY too large
1383  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1384  }
1385  break;
1386 
1387  case MetaActionType::CHORD:
1388  {
1389  MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
1390  // FIXME: this is imprecise
1391  // e.g. for small arcs the whole rectangle is WAY too large
1392  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1393  }
1394  break;
1395 
1397  {
1398  MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
1399  tools::Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1400 
1401  if(pUseHairline)
1402  {
1403  const LineInfo& rLineInfo = pAct->GetLineInfo();
1404 
1405  if(0 != rLineInfo.GetWidth())
1406  pUseHairline = nullptr;
1407  }
1408 
1409  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1410  }
1411  break;
1412 
1414  {
1415  MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
1416  tools::Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1417  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1418  }
1419  break;
1420 
1422  {
1423  MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
1424  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1425  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1426  }
1427  break;
1428 
1429  case MetaActionType::TEXT:
1430  {
1431  MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
1432  tools::Rectangle aRect;
1433  // hdu said base = index
1434  aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() );
1435  Point aPt( pAct->GetPoint() );
1436  aRect.Move( aPt.X(), aPt.Y() );
1437  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1438  }
1439  break;
1440 
1442  {
1443  MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
1444  tools::Rectangle aRect;
1445  // hdu said base = index
1446  aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1447  0, pAct->GetDXArray() );
1448  Point aPt( pAct->GetPoint() );
1449  aRect.Move( aPt.X(), aPt.Y() );
1450  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1451  }
1452  break;
1453 
1455  {
1456  MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
1457  tools::Rectangle aRect;
1458  // hdu said base = index
1459  aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1460  pAct->GetWidth() );
1461  Point aPt( pAct->GetPoint() );
1462  aRect.Move( aPt.X(), aPt.Y() );
1463  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1464  }
1465  break;
1466 
1468  {
1469  MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
1470  // measure a test string to get ascend and descent right
1471  static const sal_Unicode pStr[] = { 0xc4, 0x67, 0 };
1472  OUString aStr( pStr );
1473 
1474  tools::Rectangle aRect;
1475  aMapVDev->GetTextBoundRect( aRect, aStr, 0, 0, aStr.getLength() );
1476  Point aPt( pAct->GetStartPoint() );
1477  aRect.Move( aPt.X(), aPt.Y() );
1478  aRect.SetRight( aRect.Left() + pAct->GetWidth() );
1479  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1480  }
1481  break;
1482 
1484  {
1485  MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1486  tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1487  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1488  }
1489  break;
1490 
1492  {
1493  MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1494  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1495  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1496  }
1497  break;
1498 
1500  {
1501  MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1502  tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1503  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1504  }
1505  break;
1506 
1508  {
1509  MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1510  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1511  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1512  }
1513  break;
1514 
1516  {
1517  MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1518  tools::Rectangle aRect( pAct->GetRect() );
1519  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1520  }
1521  break;
1522 
1524  {
1525  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1526  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1527  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1528  }
1529  break;
1530 
1532  {
1533  // nothing to do
1534  };
1535  break;
1536 
1537  case MetaActionType::HATCH:
1538  {
1539  MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1540  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1541  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1542  }
1543  break;
1544 
1546  {
1547  MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1548  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1549  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1550  }
1551  break;
1552 
1554  {
1555  MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1556  // MetaFloatTransparentAction is defined limiting its content Metafile
1557  // to its geometry definition(Point, Size), so use these directly
1558  const tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1559  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1560  }
1561  break;
1562 
1563  case MetaActionType::EPS:
1564  {
1565  MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1566  tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1567  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1568  }
1569  break;
1570 
1572  {
1573  MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1574  if( pAct->IsClipping() )
1575  aClipStack.back() = OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() );
1576  else
1577  aClipStack.back() = tools::Rectangle();
1578  }
1579  break;
1580 
1582  {
1583  MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1584  tools::Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1585  if( aClipStack.back().IsEmpty() )
1586  aClipStack.back() = aRect;
1587  else
1588  aClipStack.back().Intersection( aRect );
1589  }
1590  break;
1591 
1593  {
1594  MetaISectRegionClipRegionAction* pAct = static_cast<MetaISectRegionClipRegionAction*>(pAction);
1595  tools::Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1596  if( aClipStack.back().IsEmpty() )
1597  aClipStack.back() = aRect;
1598  else
1599  aClipStack.back().Intersection( aRect );
1600  }
1601  break;
1602 
1603  case MetaActionType::BMP:
1604  {
1605  MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
1606  tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1607  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1608  }
1609  break;
1610 
1611  case MetaActionType::BMPEX:
1612  {
1613  MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
1614  tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) );
1615  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1616  }
1617  break;
1618 
1619  case MetaActionType::MASK:
1620  {
1621  MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
1622  tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1623  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1624  }
1625  break;
1626 
1628  {
1629  MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1630  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1631  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1632  }
1633  break;
1634 
1636  {
1637  MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1638  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1639  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1640  }
1641  break;
1642 
1644  {
1645  MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
1646  tools::Rectangle aRect( pAct->GetRect() );
1647  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1648  }
1649  break;
1650 
1652  {
1653  MetaTextRectAction* pAct = static_cast<MetaTextRectAction*>(pAction);
1654  tools::Rectangle aRect( pAct->GetRect() );
1655  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1656  }
1657  break;
1658 
1660  {
1661  MetaMoveClipRegionAction* pAct = static_cast<MetaMoveClipRegionAction*>(pAction);
1662  if( ! aClipStack.back().IsEmpty() )
1663  {
1664  Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() );
1665  aDelta = OutputDevice::LogicToLogic( aDelta, aMapVDev->GetMapMode(), GetPrefMapMode() );
1666  aClipStack.back().Move( aDelta.Width(), aDelta.Width() );
1667  }
1668  }
1669  break;
1670 
1671  default:
1672  {
1673  pAction->Execute( aMapVDev.get() );
1674 
1675  if( nActionType == MetaActionType::PUSH )
1676  {
1677  MetaPushAction* pAct = static_cast<MetaPushAction*>(pAction);
1678  aPushFlagStack.push_back( pAct->GetFlags() );
1679  if( aPushFlagStack.back() & PushFlags::CLIPREGION )
1680  {
1681  tools::Rectangle aRect( aClipStack.back() );
1682  aClipStack.push_back( aRect );
1683  }
1684  }
1685  else if( nActionType == MetaActionType::POP )
1686  {
1687  // sanity check
1688  if( ! aPushFlagStack.empty() )
1689  {
1690  if( aPushFlagStack.back() & PushFlags::CLIPREGION )
1691  {
1692  if( aClipStack.size() > 1 )
1693  aClipStack.pop_back();
1694  }
1695  aPushFlagStack.pop_back();
1696  }
1697  }
1698  }
1699  break;
1700  }
1701  }
1702  return aBound;
1703 }
1704 
1705 Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
1706 {
1707  return Color( rColor.GetTransparency(),
1708  static_cast<const ImplColAdjustParam*>(pColParam)->pMapR[ rColor.GetRed() ],
1709  static_cast<const ImplColAdjustParam*>(pColParam)->pMapG[ rColor.GetGreen() ],
1710  static_cast<const ImplColAdjustParam*>(pColParam)->pMapB[ rColor.GetBlue() ] );
1711 
1712 }
1713 
1714 BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1715 {
1716  const ImplBmpAdjustParam* p = static_cast<const ImplBmpAdjustParam*>(pBmpParam);
1717  BitmapEx aRet( rBmpEx );
1718 
1719  aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
1720  p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
1721  p->fGamma, p->bInvert );
1722 
1723  return aRet;
1724 }
1725 
1726 Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
1727 {
1728  sal_uInt8 cLum = rColor.GetLuminance();
1729 
1730  if( MtfConversion::N1BitThreshold == static_cast<const ImplColConvertParam*>(pColParam)->eConversion )
1731  cLum = ( cLum < 128 ) ? 0 : 255;
1732 
1733  return Color( rColor.GetTransparency(), cLum, cLum, cLum );
1734 }
1735 
1736 BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1737 {
1738  BitmapEx aRet( rBmpEx );
1739 
1740  aRet.Convert( static_cast<const ImplBmpConvertParam*>(pBmpParam)->eConversion );
1741 
1742  return aRet;
1743 }
1744 
1745 Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam )
1746 {
1747  return static_cast<const ImplColMonoParam*>(pColParam)->aColor;
1748 }
1749 
1750 BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1751 {
1752  BitmapPalette aPal( 3 );
1753 
1754  aPal[ 0 ] = COL_BLACK;
1755  aPal[ 1 ] = COL_WHITE;
1756  aPal[ 2 ] = static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor;
1757 
1758  Bitmap aBmp( rBmpEx.GetSizePixel(), 4, &aPal );
1759  aBmp.Erase( static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor );
1760 
1761  if( rBmpEx.IsAlpha() )
1762  return BitmapEx( aBmp, rBmpEx.GetAlpha() );
1763  else if( rBmpEx.IsTransparent() )
1764  return BitmapEx( aBmp, rBmpEx.GetMask() );
1765  else
1766  return BitmapEx( aBmp );
1767 }
1768 
1769 Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
1770 {
1771  const sal_uLong nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
1772 
1773  for( sal_uLong i = 0; i < static_cast<const ImplColReplaceParam*>(pColParam)->nCount; i++ )
1774  {
1775  if( ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinR[ i ] <= nR ) &&
1776  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxR[ i ] >= nR ) &&
1777  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinG[ i ] <= nG ) &&
1778  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxG[ i ] >= nG ) &&
1779  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinB[ i ] <= nB ) &&
1780  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxB[ i ] >= nB ) )
1781  {
1782  return static_cast<const ImplColReplaceParam*>(pColParam)->pDstCols[ i ];
1783  }
1784  }
1785 
1786  return rColor;
1787 }
1788 
1789 BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1790 {
1791  const ImplBmpReplaceParam* p = static_cast<const ImplBmpReplaceParam*>(pBmpParam);
1792  BitmapEx aRet( rBmpEx );
1793 
1794  aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount );
1795 
1796  return aRet;
1797 }
1798 
1799 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
1800  BmpExchangeFnc pFncBmp, const void* pBmpParam )
1801 {
1802  GDIMetaFile aMtf;
1803 
1804  aMtf.m_aPrefSize = m_aPrefSize;
1806  aMtf.m_bUseCanvas = m_bUseCanvas;
1807 
1808  for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
1809  {
1810  const MetaActionType nType = pAction->GetType();
1811 
1812  switch( nType )
1813  {
1814  case MetaActionType::PIXEL:
1815  {
1816  MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1817  aMtf.push_back( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ) );
1818  }
1819  break;
1820 
1822  {
1823  MetaLineColorAction* pAct = static_cast<MetaLineColorAction*>(pAction);
1824 
1825  if( pAct->IsSetting() )
1826  pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1827 
1828  aMtf.push_back( pAct );
1829  }
1830  break;
1831 
1833  {
1834  MetaFillColorAction* pAct = static_cast<MetaFillColorAction*>(pAction);
1835 
1836  if( pAct->IsSetting() )
1837  pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1838 
1839  aMtf.push_back( pAct );
1840  }
1841  break;
1842 
1844  {
1845  MetaTextColorAction* pAct = static_cast<MetaTextColorAction*>(pAction);
1846  aMtf.push_back( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ) );
1847  }
1848  break;
1849 
1851  {
1852  MetaTextFillColorAction* pAct = static_cast<MetaTextFillColorAction*>(pAction);
1853 
1854  if( pAct->IsSetting() )
1855  pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1856 
1857  aMtf.push_back( pAct );
1858  }
1859  break;
1860 
1862  {
1863  MetaTextLineColorAction* pAct = static_cast<MetaTextLineColorAction*>(pAction);
1864 
1865  if( pAct->IsSetting() )
1866  pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1867 
1868  aMtf.push_back( pAct );
1869  }
1870  break;
1871 
1873  {
1874  MetaOverlineColorAction* pAct = static_cast<MetaOverlineColorAction*>(pAction);
1875 
1876  if( pAct->IsSetting() )
1877  pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1878 
1879  aMtf.push_back( pAct );
1880  }
1881  break;
1882 
1883  case MetaActionType::FONT:
1884  {
1885  MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
1886  vcl::Font aFont( pAct->GetFont() );
1887 
1888  aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
1889  aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
1890  aMtf.push_back( new MetaFontAction( aFont ) );
1891  }
1892  break;
1893 
1895  {
1896  MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
1897  Wallpaper aWall( pAct->GetWallpaper() );
1898  const tools::Rectangle& rRect = pAct->GetRect();
1899 
1900  aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
1901 
1902  if( aWall.IsBitmap() )
1903  aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
1904 
1905  if( aWall.IsGradient() )
1906  {
1907  Gradient aGradient( aWall.GetGradient() );
1908 
1909  aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
1910  aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
1911  aWall.SetGradient( aGradient );
1912  }
1913 
1914  aMtf.push_back( new MetaWallpaperAction( rRect, aWall ) );
1915  }
1916  break;
1917 
1918  case MetaActionType::BMP:
1919  case MetaActionType::BMPEX:
1920  case MetaActionType::MASK:
1921  {
1922  OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
1923  }
1924  break;
1925 
1927  {
1928  MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1929  aMtf.push_back( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
1930  pFncBmp( BitmapEx(pAct->GetBitmap()), pBmpParam ).GetBitmap() ) );
1931  }
1932  break;
1933 
1935  {
1936  MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1937  aMtf.push_back( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1938  pAct->GetSrcPoint(), pAct->GetSrcSize(),
1939  pFncBmp( BitmapEx(pAct->GetBitmap()), pBmpParam ).GetBitmap() )
1940  );
1941  }
1942  break;
1943 
1945  {
1946  MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1947  aMtf.push_back( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
1948  pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
1949  );
1950  }
1951  break;
1952 
1954  {
1955  MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1956  aMtf.push_back( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1957  pAct->GetSrcPoint(), pAct->GetSrcSize(),
1958  pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
1959  );
1960  }
1961  break;
1962 
1964  {
1965  MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
1966  aMtf.push_back( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
1967  pAct->GetBitmap(),
1968  pFncCol( pAct->GetColor(), pColParam ) )
1969  );
1970  }
1971  break;
1972 
1974  {
1975  MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1976  aMtf.push_back( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1977  pAct->GetSrcPoint(), pAct->GetSrcSize(),
1978  pAct->GetBitmap(),
1979  pFncCol( pAct->GetColor(), pColParam ) )
1980  );
1981  }
1982  break;
1983 
1985  {
1986  MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1987  Gradient aGradient( pAct->GetGradient() );
1988 
1989  aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
1990  aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
1991  aMtf.push_back( new MetaGradientAction( pAct->GetRect(), aGradient ) );
1992  }
1993  break;
1994 
1996  {
1997  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1998  Gradient aGradient( pAct->GetGradient() );
1999 
2000  aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2001  aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2002  aMtf.push_back( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ) );
2003  }
2004  break;
2005 
2006  case MetaActionType::HATCH:
2007  {
2008  MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
2009  Hatch aHatch( pAct->GetHatch() );
2010 
2011  aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
2012  aMtf.push_back( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ) );
2013  }
2014  break;
2015 
2017  {
2018  MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
2019  GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
2020 
2021  aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2022  aMtf.push_back( new MetaFloatTransparentAction( aTransMtf,
2023  pAct->GetPoint(), pAct->GetSize(),
2024  pAct->GetGradient() )
2025  );
2026  }
2027  break;
2028 
2029  case MetaActionType::EPS:
2030  {
2031  MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
2032  GDIMetaFile aSubst( pAct->GetSubstitute() );
2033 
2034  aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2035  aMtf.push_back( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
2036  pAct->GetLink(), aSubst )
2037  );
2038  }
2039  break;
2040 
2041  default:
2042  {
2043  aMtf.push_back( pAction );
2044  }
2045  break;
2046  }
2047  }
2048 
2049  *this = aMtf;
2050 }
2051 
2052 void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
2053  short nChannelRPercent, short nChannelGPercent,
2054  short nChannelBPercent, double fGamma, bool bInvert, bool msoBrightness )
2055 {
2056  // nothing to do? => return quickly
2057  if( !(nLuminancePercent || nContrastPercent ||
2058  nChannelRPercent || nChannelGPercent || nChannelBPercent ||
2059  ( fGamma != 1.0 ) || bInvert) )
2060  return;
2061 
2062  double fM, fROff, fGOff, fBOff, fOff;
2063  ImplColAdjustParam aColParam;
2064  ImplBmpAdjustParam aBmpParam;
2065 
2066  aColParam.pMapR.reset(new sal_uInt8[ 256 ]);
2067  aColParam.pMapG.reset(new sal_uInt8[ 256 ]);
2068  aColParam.pMapB.reset(new sal_uInt8[ 256 ]);
2069 
2070  // calculate slope
2071  if( nContrastPercent >= 0 )
2072  fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0, 100 ) );
2073  else
2074  fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100, 0 ) ) / 128.0;
2075 
2076  if(!msoBrightness)
2077  // total offset = luminance offset + contrast offset
2078  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55 + 128.0 - fM * 128.0;
2079  else
2080  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55;
2081 
2082  // channel offset = channel offset + total offset
2083  fROff = nChannelRPercent * 2.55 + fOff;
2084  fGOff = nChannelGPercent * 2.55 + fOff;
2085  fBOff = nChannelBPercent * 2.55 + fOff;
2086 
2087  // calculate gamma value
2088  fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
2089  const bool bGamma = ( fGamma != 1.0 );
2090 
2091  // create mapping table
2092  for( long nX = 0; nX < 256; nX++ )
2093  {
2094  if(!msoBrightness)
2095  {
2096  aColParam.pMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fROff ), 0, 255 ));
2097  aColParam.pMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fGOff ), 0, 255 ));
2098  aColParam.pMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fBOff ), 0, 255 ));
2099  }
2100  else
2101  {
2102  aColParam.pMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0, 255 ));
2103  aColParam.pMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0, 255 ));
2104  aColParam.pMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0, 255 ));
2105  }
2106  if( bGamma )
2107  {
2108  aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
2109  aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
2110  aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
2111  }
2112 
2113  if( bInvert )
2114  {
2115  aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
2116  aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
2117  aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
2118  }
2119  }
2120 
2121  aBmpParam.nLuminancePercent = nLuminancePercent;
2122  aBmpParam.nContrastPercent = nContrastPercent;
2123  aBmpParam.nChannelRPercent = nChannelRPercent;
2124  aBmpParam.nChannelGPercent = nChannelGPercent;
2125  aBmpParam.nChannelBPercent = nChannelBPercent;
2126  aBmpParam.fGamma = fGamma;
2127  aBmpParam.bInvert = bInvert;
2128 
2129  // do color adjustment
2130  ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
2131 }
2132 
2134 {
2135  ImplColConvertParam aColParam;
2136  ImplBmpConvertParam aBmpParam;
2137 
2138  aColParam.eConversion = eConversion;
2139  aBmpParam.eConversion = ( MtfConversion::N1BitThreshold == eConversion ) ? BmpConversion::N1BitThreshold : BmpConversion::N8BitGreys;
2140 
2141  ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
2142 }
2143 
2144 void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount )
2145 {
2146  ImplColReplaceParam aColParam;
2147  ImplBmpReplaceParam aBmpParam;
2148 
2149  aColParam.pMinR.reset(new sal_uLong[ nColorCount ]);
2150  aColParam.pMaxR.reset(new sal_uLong[ nColorCount ]);
2151  aColParam.pMinG.reset(new sal_uLong[ nColorCount ]);
2152  aColParam.pMaxG.reset(new sal_uLong[ nColorCount ]);
2153  aColParam.pMinB.reset(new sal_uLong[ nColorCount ]);
2154  aColParam.pMaxB.reset(new sal_uLong[ nColorCount ]);
2155 
2156  for( sal_uLong i = 0; i < nColorCount; i++ )
2157  {
2158  long nVal;
2159 
2160  nVal = pSearchColors[ i ].GetRed();
2161  aColParam.pMinR[ i ] = static_cast<sal_uLong>(std::max( nVal, 0L ));
2162  aColParam.pMaxR[ i ] = static_cast<sal_uLong>(std::min( nVal, 255L ));
2163 
2164  nVal = pSearchColors[ i ].GetGreen();
2165  aColParam.pMinG[ i ] = static_cast<sal_uLong>(std::max( nVal, 0L ));
2166  aColParam.pMaxG[ i ] = static_cast<sal_uLong>(std::min( nVal, 255L ));
2167 
2168  nVal = pSearchColors[ i ].GetBlue();
2169  aColParam.pMinB[ i ] = static_cast<sal_uLong>(std::max( nVal, 0L ));
2170  aColParam.pMaxB[ i ] = static_cast<sal_uLong>(std::min( nVal, 255L ));
2171  }
2172 
2173  aColParam.pDstCols = pReplaceColors;
2174  aColParam.nCount = nColorCount;
2175 
2176  aBmpParam.pSrcCols = pSearchColors;
2177  aBmpParam.pDstCols = pReplaceColors;
2178  aBmpParam.nCount = nColorCount;
2179 
2180  ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
2181 };
2182 
2184 {
2185  GDIMetaFile aRet( *this );
2186 
2187  ImplColMonoParam aColParam;
2188  ImplBmpMonoParam aBmpParam;
2189 
2190  aColParam.aColor = rColor;
2191  aBmpParam.aColor = rColor;
2192 
2193  aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
2194 
2195  return aRet;
2196 }
2197 
2199 {
2200  SvMemoryStream aMemStm( 65535, 65535 );
2201  ImplMetaWriteData aWriteData;
2202  SVBT16 aBT16;
2203  SVBT32 aBT32;
2205  BitmapChecksum nCrc = 0;
2206 
2207  aWriteData.meActualCharSet = aMemStm.GetStreamCharSet();
2208  for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; i++ )
2209  {
2210  MetaAction* pAction = GetAction( i );
2211 
2212  switch( pAction->GetType() )
2213  {
2214  case MetaActionType::BMP:
2215  {
2216  MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
2217 
2218  ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2219  nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2220 
2221  BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2222  nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2223 
2224  Int32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2225  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2226 
2227  Int32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2228  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2229  }
2230  break;
2231 
2233  {
2234  MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
2235 
2236  ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2237  nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2238 
2239  BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2240  nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2241 
2242  Int32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2243  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2244 
2245  Int32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2246  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2247 
2248  Int32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2249  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2250 
2251  Int32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2252  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2253  }
2254  break;
2255 
2257  {
2258  MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
2259 
2260  ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2261  nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2262 
2263  BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2264  nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2265 
2266  Int32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2267  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2268 
2269  Int32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2270  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2271 
2272  Int32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2273  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2274 
2275  Int32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2276  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2277 
2278  Int32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2279  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2280 
2281  Int32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2282  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2283 
2284  Int32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2285  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2286 
2287  Int32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2288  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2289  }
2290  break;
2291 
2292  case MetaActionType::BMPEX:
2293  {
2294  MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
2295 
2296  ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2297  nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2298 
2299  BCToBCOA( pAct->GetBitmapEx().GetChecksum(), aBCOA );
2300  nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2301 
2302  Int32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2303  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2304 
2305  Int32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2306  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2307  }
2308  break;
2309 
2311  {
2312  MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
2313 
2314  ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2315  nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2316 
2317  BCToBCOA( pAct->GetBitmapEx().GetChecksum(), aBCOA );
2318  nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2319 
2320  Int32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2321  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2322 
2323  Int32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2324  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2325 
2326  Int32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2327  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2328 
2329  Int32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2330  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2331  }
2332  break;
2333 
2335  {
2336  MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
2337 
2338  ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2339  nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2340 
2341  BCToBCOA( pAct->GetBitmapEx().GetChecksum(), aBCOA );
2342  nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2343 
2344  Int32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2345  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2346 
2347  Int32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2348  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2349 
2350  Int32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2351  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2352 
2353  Int32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2354  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2355 
2356  Int32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2357  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2358 
2359  Int32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2360  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2361 
2362  Int32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2363  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2364 
2365  Int32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2366  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2367  }
2368  break;
2369 
2370  case MetaActionType::MASK:
2371  {
2372  MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
2373 
2374  ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2375  nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2376 
2377  BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2378  nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2379 
2380  UInt32ToSVBT32( sal_uInt32(pAct->GetColor()), aBT32 );
2381  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2382 
2383  Int32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2384  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2385 
2386  Int32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2387  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2388  }
2389  break;
2390 
2392  {
2393  MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
2394 
2395  ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2396  nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2397 
2398  BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2399  nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2400 
2401  UInt32ToSVBT32( sal_uInt32(pAct->GetColor()), aBT32 );
2402  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2403 
2404  Int32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2405  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2406 
2407  Int32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2408  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2409 
2410  Int32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2411  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2412 
2413  Int32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2414  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2415  }
2416  break;
2417 
2419  {
2420  MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
2421 
2422  ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2423  nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2424 
2425  BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2426  nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2427 
2428  UInt32ToSVBT32( sal_uInt32(pAct->GetColor()), aBT32 );
2429  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2430 
2431  Int32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2432  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2433 
2434  Int32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2435  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2436 
2437  Int32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2438  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2439 
2440  Int32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2441  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2442 
2443  Int32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2444  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2445 
2446  Int32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2447  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2448 
2449  Int32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2450  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2451 
2452  Int32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2453  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2454  }
2455  break;
2456 
2457  case MetaActionType::EPS :
2458  {
2459  MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
2460  nCrc = vcl_get_checksum( nCrc, pAct->GetLink().GetData(), pAct->GetLink().GetDataSize() );
2461  }
2462  break;
2463 
2465  {
2466  MetaClipRegionAction& rAct = static_cast<MetaClipRegionAction&>(*pAction);
2467  const vcl::Region& rRegion = rAct.GetRegion();
2468 
2469  if(rRegion.HasPolyPolygonOrB2DPolyPolygon())
2470  {
2471  // It has shown that this is a possible bottleneck for checksum calculation.
2472  // In worst case a very expensive RegionHandle representation gets created.
2473  // In this case it's cheaper to use the PolyPolygon
2474  const basegfx::B2DPolyPolygon aPolyPolygon(rRegion.GetAsB2DPolyPolygon());
2475  SVBT64 aSVBT64;
2476 
2477  for(auto const& rPolygon : aPolyPolygon)
2478  {
2479  const sal_uInt32 nPointCount(rPolygon.count());
2480  const bool bControl(rPolygon.areControlPointsUsed());
2481 
2482  for(sal_uInt32 b(0); b < nPointCount; b++)
2483  {
2484  const basegfx::B2DPoint aPoint(rPolygon.getB2DPoint(b));
2485 
2486  DoubleToSVBT64(aPoint.getX(), aSVBT64);
2487  nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2488  DoubleToSVBT64(aPoint.getY(), aSVBT64);
2489  nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2490 
2491  if(bControl)
2492  {
2493  if(rPolygon.isPrevControlPointUsed(b))
2494  {
2495  const basegfx::B2DPoint aCtrl(rPolygon.getPrevControlPoint(b));
2496 
2497  DoubleToSVBT64(aCtrl.getX(), aSVBT64);
2498  nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2499  DoubleToSVBT64(aCtrl.getY(), aSVBT64);
2500  nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2501  }
2502 
2503  if(rPolygon.isNextControlPointUsed(b))
2504  {
2505  const basegfx::B2DPoint aCtrl(rPolygon.getNextControlPoint(b));
2506 
2507  DoubleToSVBT64(aCtrl.getX(), aSVBT64);
2508  nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2509  DoubleToSVBT64(aCtrl.getY(), aSVBT64);
2510  nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2511  }
2512  }
2513  }
2514  }
2515 
2516  sal_uInt8 tmp = static_cast<sal_uInt8>(rAct.IsClipping());
2517  nCrc = vcl_get_checksum(nCrc, &tmp, 1);
2518  }
2519  else
2520  {
2521  pAction->Write( aMemStm, &aWriteData );
2522  nCrc = vcl_get_checksum( nCrc, aMemStm.GetData(), aMemStm.Tell() );
2523  aMemStm.Seek( 0 );
2524  }
2525  }
2526  break;
2527 
2528  default:
2529  {
2530  pAction->Write( aMemStm, &aWriteData );
2531  nCrc = vcl_get_checksum( nCrc, aMemStm.GetData(), aMemStm.Tell() );
2532  aMemStm.Seek( 0 );
2533  }
2534  break;
2535  }
2536  }
2537 
2538  return nCrc;
2539 }
2540 
2542 {
2543  sal_uLong nSizeBytes = 0;
2544 
2545  for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; ++i )
2546  {
2547  MetaAction* pAction = GetAction( i );
2548 
2549  // default action size is set to 32 (=> not the exact value)
2550  nSizeBytes += 32;
2551 
2552  // add sizes for large action content
2553  switch( pAction->GetType() )
2554  {
2555  case MetaActionType::BMP: nSizeBytes += static_cast<MetaBmpAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2556  case MetaActionType::BMPSCALE: nSizeBytes += static_cast<MetaBmpScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2557  case MetaActionType::BMPSCALEPART: nSizeBytes += static_cast<MetaBmpScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2558 
2559  case MetaActionType::BMPEX: nSizeBytes += static_cast<MetaBmpExAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2560  case MetaActionType::BMPEXSCALE: nSizeBytes += static_cast<MetaBmpExScaleAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2561  case MetaActionType::BMPEXSCALEPART: nSizeBytes += static_cast<MetaBmpExScalePartAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2562 
2563  case MetaActionType::MASK: nSizeBytes += static_cast<MetaMaskAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2564  case MetaActionType::MASKSCALE: nSizeBytes += static_cast<MetaMaskScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2565  case MetaActionType::MASKSCALEPART: nSizeBytes += static_cast<MetaMaskScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2566 
2567  case MetaActionType::POLYLINE: nSizeBytes += static_cast<MetaPolyLineAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2568  case MetaActionType::POLYGON: nSizeBytes += static_cast<MetaPolygonAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2570  {
2571  const tools::PolyPolygon& rPolyPoly = static_cast<MetaPolyPolygonAction*>( pAction )->GetPolyPolygon();
2572 
2573  for( sal_uInt16 n = 0; n < rPolyPoly.Count(); ++n )
2574  nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) );
2575  }
2576  break;
2577 
2578  case MetaActionType::TEXT: nSizeBytes += static_cast<MetaTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2579  case MetaActionType::STRETCHTEXT: nSizeBytes += static_cast<MetaStretchTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2580  case MetaActionType::TEXTRECT: nSizeBytes += static_cast<MetaTextRectAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2582  {
2583  MetaTextArrayAction* pTextArrayAction = static_cast<MetaTextArrayAction*>(pAction);
2584 
2585  nSizeBytes += ( pTextArrayAction->GetText().getLength() * sizeof( sal_Unicode ) );
2586 
2587  if( pTextArrayAction->GetDXArray() )
2588  nSizeBytes += ( pTextArrayAction->GetLen() << 2 );
2589  }
2590  break;
2591  default: break;
2592  }
2593  }
2594 
2595  return nSizeBytes;
2596 }
2597 
2598 namespace
2599 {
2600  class DepthGuard
2601  {
2602  private:
2604  rtl_TextEncoding m_eOrigCharSet;
2605  public:
2606  DepthGuard(ImplMetaReadData& rData, SvStream const & rIStm)
2607  : m_rData(rData)
2608  , m_eOrigCharSet(m_rData.meActualCharSet)
2609  {
2610  ++m_rData.mnParseDepth;
2611  m_rData.meActualCharSet = rIStm.GetStreamCharSet();
2612  }
2613  bool TooDeep() const { return m_rData.mnParseDepth > 1024; }
2614  ~DepthGuard()
2615  {
2616  --m_rData.mnParseDepth;
2617  m_rData.meActualCharSet = m_eOrigCharSet;
2618  }
2619  };
2620 }
2621 
2623 {
2624  if (rIStm.GetError())
2625  {
2626  SAL_WARN("vcl.gdi", "Stream error: " << rIStm.GetError());
2627  return rIStm;
2628  }
2629 
2630  sal_uLong nStmPos = rIStm.Tell();
2631  SvStreamEndian nOldFormat = rIStm.GetEndian();
2632 
2633  rIStm.SetEndian( SvStreamEndian::LITTLE );
2634 
2635  try
2636  {
2637  char aId[7];
2638  aId[0] = 0;
2639  aId[6] = 0;
2640  rIStm.ReadBytes( aId, 6 );
2641 
2642  if ( !strcmp( aId, "VCLMTF" ) )
2643  {
2644  // new format
2645  sal_uInt32 nStmCompressMode = 0;
2646  sal_uInt32 nCount = 0;
2647  std::unique_ptr<VersionCompat> pCompat(new VersionCompat( rIStm, StreamMode::READ ));
2648 
2649  rIStm.ReadUInt32( nStmCompressMode );
2650  ReadMapMode( rIStm, rGDIMetaFile.m_aPrefMapMode );
2651  TypeSerializer aSerializer(rIStm);
2652  aSerializer.readSize(rGDIMetaFile.m_aPrefSize);
2653  rIStm.ReadUInt32( nCount );
2654 
2655  pCompat.reset(); // destructor writes stuff into the header
2656 
2657  std::unique_ptr<ImplMetaReadData> xReadData;
2658  if (!pData)
2659  {
2660  xReadData.reset(new ImplMetaReadData);
2661  pData = xReadData.get();
2662  }
2663  DepthGuard aDepthGuard(*pData, rIStm);
2664 
2665  if (aDepthGuard.TooDeep())
2666  throw std::runtime_error("too much recursion");
2667 
2668  for( sal_uInt32 nAction = 0; ( nAction < nCount ) && !rIStm.eof(); nAction++ )
2669  {
2670  MetaAction* pAction = MetaAction::ReadMetaAction(rIStm, pData);
2671  if( pAction )
2672  {
2673  if (pAction->GetType() == MetaActionType::COMMENT)
2674  {
2675  MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
2676  if ( pCommentAct->GetComment() == "EMF_PLUS" )
2677  rGDIMetaFile.UseCanvas( true );
2678  }
2679  rGDIMetaFile.AddAction( pAction );
2680  }
2681  }
2682  }
2683  else
2684  {
2685  rIStm.Seek( nStmPos );
2686  SVMConverter( rIStm, rGDIMetaFile );
2687  }
2688  }
2689  catch (...)
2690  {
2691  SAL_WARN("vcl", "GDIMetaFile exception during load");
2693  };
2694 
2695  // check for errors
2696  if( rIStm.GetError() )
2697  {
2698  rGDIMetaFile.Clear();
2699  rIStm.Seek( nStmPos );
2700  }
2701 
2702  rIStm.SetEndian( nOldFormat );
2703  return rIStm;
2704 }
2705 
2706 SvStream& WriteGDIMetaFile( SvStream& rOStm, const GDIMetaFile& rGDIMetaFile )
2707 {
2708  if( !rOStm.GetError() )
2709  {
2710  const_cast< GDIMetaFile& >( rGDIMetaFile ).Write( rOStm );
2711  }
2712  return rOStm;
2713 }
2714 
2716 {
2717  Clear();
2718  ReadGDIMetaFile( rIStm, *this );
2719 
2720  return rIStm;
2721 }
2722 
2724 {
2725  VersionCompat* pCompat;
2726  const SvStreamCompressFlags nStmCompressMode = rOStm.GetCompressMode();
2727  SvStreamEndian nOldFormat = rOStm.GetEndian();
2728 
2729  rOStm.SetEndian( SvStreamEndian::LITTLE );
2730  rOStm.WriteBytes( "VCLMTF", 6 );
2731 
2732  pCompat = new VersionCompat( rOStm, StreamMode::WRITE, 1 );
2733 
2734  rOStm.WriteUInt32( static_cast<sal_uInt32>(nStmCompressMode) );
2735  WriteMapMode( rOStm, m_aPrefMapMode );
2736  TypeSerializer aSerializer(rOStm);
2737  aSerializer.writeSize(m_aPrefSize);
2738  rOStm.WriteUInt32( GetActionSize() );
2739 
2740  delete pCompat;
2741 
2742  ImplMetaWriteData aWriteData;
2743 
2744  aWriteData.meActualCharSet = rOStm.GetStreamCharSet();
2745 
2746  MetaAction* pAct = FirstAction();
2747  while ( pAct )
2748  {
2749  pAct->Write( rOStm, &aWriteData );
2750  pAct = NextAction();
2751  }
2752 
2753  rOStm.SetEndian( nOldFormat );
2754 
2755  return rOStm;
2756 }
2757 
2758 bool GDIMetaFile::CreateThumbnail(BitmapEx& rBitmapEx, BmpConversion eColorConversion, BmpScaleFlag nScaleFlag) const
2759 {
2760  // initialization seems to be complicated but is used to avoid rounding errors
2762  const Point aNullPt;
2763  const Point aTLPix( aVDev->LogicToPixel( aNullPt, GetPrefMapMode() ) );
2764  const Point aBRPix( aVDev->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2765  Size aDrawSize( aVDev->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2766  Size aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
2767  sal_uInt32 nMaximumExtent = 256;
2768 
2769  if (!rBitmapEx.IsEmpty())
2770  rBitmapEx.SetEmpty();
2771 
2772  // determine size that has the same aspect ratio as image size and
2773  // fits into the rectangle determined by nMaximumExtent
2774  if ( aSizePix.Width() && aSizePix.Height()
2775  && ( sal::static_int_cast< unsigned long >(aSizePix.Width()) >
2776  nMaximumExtent ||
2777  sal::static_int_cast< unsigned long >(aSizePix.Height()) >
2778  nMaximumExtent ) )
2779  {
2780  const Size aOldSizePix( aSizePix );
2781  double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
2782 
2783  if ( fWH <= 1.0 )
2784  {
2785  aSizePix.setWidth( FRound( nMaximumExtent * fWH ) );
2786  aSizePix.setHeight( nMaximumExtent );
2787  }
2788  else
2789  {
2790  aSizePix.setWidth( nMaximumExtent );
2791  aSizePix.setHeight( FRound( nMaximumExtent / fWH ) );
2792  }
2793 
2794  aDrawSize.setWidth( FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() ) );
2795  aDrawSize.setHeight( FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() ) );
2796  }
2797 
2798  // draw image(s) into VDev and get resulting image
2799  // do it 4x larger to be able to scale it down & get beautiful antialias
2800  Size aAntialiasSize(aSizePix.Width() * 4, aSizePix.Height() * 4);
2801  if (aVDev->SetOutputSizePixel(aAntialiasSize))
2802  {
2803  // antialias: provide 4x larger size, and then scale down the result
2804  Size aAntialias(aDrawSize.Width() * 4, aDrawSize.Height() * 4);
2805 
2806  // draw metafile into VDev
2807  const_cast<GDIMetaFile *>(this)->WindStart();
2808  const_cast<GDIMetaFile *>(this)->Play(aVDev.get(), Point(), aAntialias);
2809 
2810  // get paint bitmap
2811  BitmapEx aBitmap( aVDev->GetBitmapEx( aNullPt, aVDev->GetOutputSizePixel() ) );
2812 
2813  // scale down the image to the desired size - use the input scaler for the scaling operation
2814  aBitmap.Scale(aDrawSize, nScaleFlag);
2815 
2816  // convert to desired bitmap color format
2817  Size aSize(aBitmap.GetSizePixel());
2818  if (aSize.Width() && aSize.Height())
2819  aBitmap.Convert(eColorConversion);
2820 
2821  rBitmapEx = aBitmap;
2822  }
2823 
2824  return !rBitmapEx.IsEmpty();
2825 }
2826 
2827 void GDIMetaFile::UseCanvas( bool _bUseCanvas )
2828 {
2829  m_bUseCanvas = _bUseCanvas;
2830 }
2831 
2832 void GDIMetaFile::dumpAsXml(const char* pFileName) const
2833 {
2834  SvFileStream aStream(pFileName ? OUString::fromUtf8(pFileName) : OUString("file:///tmp/metafile.xml"),
2835  StreamMode::STD_READWRITE | StreamMode::TRUNC);
2836  assert(aStream.good());
2837  MetafileXmlDump aDumper;
2838  aDumper.dump(*this, aStream);
2839 }
2840 
2841 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt16 Count() const
static SAL_DLLPRIVATE BitmapEx ImplBmpAdjustFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1714
const Fraction & GetScaleX() const
Definition: mapmod.cxx:172
long Width() const
const Gradient & GetGradient() const
Definition: metaact.hxx:1560
void Mirror(BmpMirrorFlags nMirrorFlags)
Definition: gdimtf.cxx:575
OutDevType GetOutDevType() const
Definition: outdev.hxx:522
virtual void Execute(OutputDevice *pOut)
Definition: metaact.cxx:168
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:183
void dump(const GDIMetaFile &rMetaFile, SvStream &rStream)
The actual result that will be used for testing.
Definition: mtfxmldump.cxx:516
void SetDigitLanguage(LanguageType)
void SetPixelOffset(const Size &rOffset)
Set an offset in pixel.
Definition: map.cxx:1904
GDIMetaFile * m_pPrev
Definition: gdimtf.hxx:65
Bitmap GetMask() const
Definition: bitmapex.cxx:258
sal_uInt64 BitmapChecksum
Definition: checksum.hxx:30
const Size & GetDestSize() const
Definition: metaact.hxx:950
Definition: hatch.hxx:44
VclPtr< OutputDevice > m_pOutDev
Definition: gdimtf.hxx:67
void SetRelativeMapMode(const MapMode &rNewMapMode)
Definition: map.cxx:775
const Bitmap & GetBitmap() const
Definition: metaact.hxx:908
sal_Int32 GetLen() const
Definition: metaact.hxx:493
MetaAction * GetCurAction() const
Definition: gdimtf.hxx:171
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
const Point & GetPoint() const
Definition: metaact.hxx:701
sal_uInt8 GetRed() const
rtl_TextEncoding meActualCharSet
Definition: metaact.hxx:47
static MetaAction * ReadMetaAction(SvStream &rIStm, ImplMetaReadData *pData)
Definition: metaact.cxx:195
void ReplaceColors(const Color *pSearchColors, const Color *rReplaceColors, sal_uLong nColorCount)
Definition: gdimtf.cxx:2144
sal_uInt8 SVBT16[2]
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
long FRound(double fVal)
SAL_DLLPRIVATE bool ImplPlayWithRenderer(OutputDevice *pOut, const Point &rPos, Size rLogicDestSize)
Definition: gdimtf.cxx:365
const GDIMetaFile & GetGDIMetaFile() const
Definition: metaact.hxx:1557
void Replace(const Color &rSearchColor, const Color &rReplaceColor)
Replace all pixel having the search color with the specified color.
Definition: bitmapex.cxx:596
bool Adjust(short nLuminancePercent, short nContrastPercent, short nChannelRPercent, short nChannelGPercent, short nChannelBPercent, double fGamma=1.0, bool bInvert=false, bool msoBrightness=false)
Change various global color characteristics.
Definition: bitmapex.cxx:608
SvStream & WriteMapMode(SvStream &rOStm, const MapMode &rMapMode)
Definition: mapmod.cxx:152
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1668
GDIMetaFile & operator=(const GDIMetaFile &rMtf)
Definition: gdimtf.cxx:189
long Height() const
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
This is an overloaded member function, provided for convenience. It differs from the above function o...
SvStream & WriteSvtGraphicStroke(SvStream &rOStm, const SvtGraphicStroke &rClass)
SvStream & Read(SvStream &rIStm)
Definition: gdimtf.cxx:2715
const MapMode & GetPrefMapMode() const
Definition: gdimtf.hxx:176
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: bitmapex.cxx:370
sal_uInt8 GetTransparency() const
sal_uIntPtr sal_uLong
MtfConversion
Definition: gdimtf.hxx:44
void writeSize(const Size &rSize)
void dumpAsXml(const char *pFileName=nullptr) const
Dumps the meta actions as XML in metafile.xml.
Definition: gdimtf.cxx:2832
MetaAction * NextAction()
Definition: gdimtf.cxx:173
#define F_PI1800
sal_uInt8 GetLuminance() const
const Point & GetPoint() const
Definition: metaact.hxx:1594
sal_Int64 n
Encapsulates geometry and associated attributes of a graphical 'pen stroke'.
void SetPrefSize(const Size &rSize)
Definition: gdimtf.hxx:174
const Point & GetPoint() const
Definition: metaact.hxx:1558
void Clear()
Definition: gdimtf.cxx:248
static SAL_DLLPRIVATE Color ImplColMonoFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1745
sal_uInt64 Seek(sal_uInt64 nPos)
const Size & GetSize() const
Definition: metaact.hxx:702
const MapMode & GetMapMode() const
Definition: outdev.hxx:1681
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1524
OUString aId
void SetLayoutMode(ComplexTextLayoutFlags nTextLayoutMode)
BitmapChecksum vcl_get_checksum(BitmapChecksum Checksum, const void *Data, sal_uInt32 DatLen)
Definition: checksum.hxx:72
const Point & GetEndPoint() const
Definition: metaact.hxx:182
GDIMetaFile * GetConnectMetaFile() const
Definition: outdev.hxx:417
const OUString & GetText() const
Definition: metaact.hxx:565
bool IsRecord() const
Definition: gdimtf.hxx:142
Size GetSizePixel() const
SvStream & ReadSvtGraphicStroke(SvStream &rIStm, SvtGraphicStroke &rClass)
static SAL_DLLPRIVATE void ImplAddGradientEx(GDIMetaFile &rMtf, const OutputDevice &rMapDev, const tools::PolyPolygon &rPolyPoly, const Gradient &rGrad)
Definition: gdimtf.cxx:777
void SetOrientation(short nLineOrientation)
Definition: font/font.cxx:192
SvStreamCompressFlags GetCompressMode() const
static SAL_DLLPRIVATE BitmapEx ImplBmpReplaceFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1789
void Clip(const tools::Rectangle &)
Definition: gdimtf.cxx:714
void SetMapMode()
Definition: map.cxx:655
const Point & GetPoint() const
Definition: metaact.hxx:910
bool Convert(BmpConversion eConversion)
Convert bitmap format.
Definition: bitmapex.cxx:454
BitmapChecksum GetChecksum() const
Definition: bitmapex.cxx:292
SvStream & ReadSvtGraphicFill(SvStream &rIStm, SvtGraphicFill &rClass)
sal_uInt8 SVBT32[4]
void Move(long nHorzMoveDelta, long nVertMoveDelta)
const sal_uInt8 * GetData() const
Definition: metaact.hxx:1656
bool IsEmpty() const
HashMap_OWString_Interface aMap
sal_uInt16 sal_Unicode
constexpr::Color COL_TRANSPARENT(0xFF, 0xFF, 0xFF, 0xFF)
void Rotate(long nAngle10)
Definition: gdimtf.cxx:799
bool IsAlpha() const
Definition: bitmapex.cxx:226
static SAL_DLLPRIVATE tools::Polygon ImplGetRotatedPolygon(const tools::Polygon &rPoly, const Point &rRotatePt, const Size &rOffset, double fSin, double fCos)
Definition: gdimtf.cxx:755
ErrCode GetError() const
const Point & GetPoint() const
Definition: metaact.hxx:802
void Record(OutputDevice *pOutDev)
Definition: gdimtf.cxx:289
const Sequence< Sequence< double > > & m_rData
void push_back(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:570
bool eof() const
const OUString & GetText() const
Definition: metaact.hxx:491
const Fraction & GetScaleY() const
Definition: mapmod.cxx:174
const Color & GetColor() const
Definition: metaact.hxx:874
SvStream & WriteGDIMetaFile(SvStream &rOStm, const GDIMetaFile &rGDIMetaFile)
Definition: gdimtf.cxx:2706
geometry::IntegerSize2D integerSize2DFromSize(const Size &rSize)
#define X
Definition: field.cxx:1063
const Bitmap & GetBitmap() const
Definition: metaact.hxx:668
void Rotate(const Point &rCenter, double fSin, double fCos)
void Adjust(short nLuminancePercent, short nContrastPercent, short nChannelRPercent=0, short nChannelGPercent=0, short nChannelBPercent=0, double fGamma=1.0, bool bInvert=false, bool msoBrightness=false)
Definition: gdimtf.cxx:2052
int nCount
long GetWidth() const
Definition: metaact.hxx:636
bool CreateThumbnail(BitmapEx &rBitmapEx, BmpConversion nColorConversion=BmpConversion::N24Bit, BmpScaleFlag nScaleFlag=BmpScaleFlag::BestQuality) const
Creates an antialiased thumbnail.
Definition: gdimtf.cxx:2758
void SetStartColor(const Color &rColor)
const Gradient & GetGradient() const
Definition: metaact.hxx:982
SvStream & WriteUInt32(sal_uInt32 nUInt32)
const Color & GetColor() const
Definition: metaact.hxx:1214
MetaActionType
void Play(GDIMetaFile &rMtf)
Definition: gdimtf.cxx:300
BitmapEx(* BmpExchangeFnc)(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.hxx:52
const Size & GetSize() const
Definition: metaact.hxx:803
GDIMetaFile GetMonochromeMtf(const Color &rCol) const
Definition: gdimtf.cxx:2183
void readSize(Size &rSize)
sal_uInt8 GetBlue() const
FontLineStyle GetUnderline() const
Definition: metaact.hxx:638
Size m_aPrefSize
Definition: gdimtf.hxx:64
tools::PolyPolygon GetAsPolyPolygon() const
Definition: region.cxx:1261
void Move(long nHorzMove, long nVertMove)
void Rotate(const Point &rCenter, double fSin, double fCos)
void setPath(const tools::PolyPolygon &rPath)
Set path to fill.
static SAL_DLLPRIVATE tools::PolyPolygon ImplGetRotatedPolyPolygon(const tools::PolyPolygon &rPoly, const Point &rRotatePt, const Size &rOffset, double fSin, double fCos)
Definition: gdimtf.cxx:766
const Size & GetSrcSize() const
Definition: metaact.hxx:952
bool m_bPause
Definition: gdimtf.hxx:68
static SAL_DLLPRIVATE Point ImplGetRotatedPoint(const Point &rPt, const Point &rRotatePt, const Size &rOffset, double fSin, double fCos)
Definition: gdimtf.cxx:745
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
void SetEmpty()
Definition: bitmapex.cxx:208
static vcl::Window * GetFirstTopLevelWindow()
Get the first top-level window of the application.
Definition: svapp.cxx:1064
bool IsEmpty() const
Definition: bitmapex.cxx:203
void Move(long nHorzMove, long nVertMove)
bool GetUseCanvas() const
Definition: gdimtf.hxx:199
bool Create(const css::uno::Reference< css::rendering::XBitmapCanvas > &xBitmapCanvas, const Size &rSize)
populate from a canvas implementation
Definition: bitmapex.cxx:774
#define BITMAP_CHECKSUM_SIZE
Definition: checksum.hxx:28
void SetConnectMetaFile(GDIMetaFile *pMtf)
Definition: outdev.cxx:208
void SetScaleX(const Fraction &rScaleX)
Definition: mapmod.cxx:108
#define TOOLS_WARN_EXCEPTION(area, stream)
friend VCL_DLLPUBLIC SvStream & ReadGDIMetaFile(SvStream &rIStm, GDIMetaFile &rGDIMetaFile, ImplMetaReadData *pReadData)
Definition: gdimtf.cxx:2622
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:211
static SAL_DLLPRIVATE BitmapEx ImplBmpConvertFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1736
const Size & GetPrefSize() const
Definition: gdimtf.hxx:173
~GDIMetaFile()
Definition: gdimtf.cxx:152
GDIMetaFile * m_pNext
Definition: gdimtf.hxx:66
int i
::std::vector< rtl::Reference< MetaAction > > m_aList
Definition: gdimtf.hxx:60
uno_Any a
sal_uInt16 GetTransparence() const
Definition: metaact.hxx:1525
virtual void Scale(double fScaleX, double fScaleY)
Definition: metaact.cxx:181
const Size & GetSize() const
Definition: metaact.hxx:911
const Point & GetPoint() const
Definition: metaact.hxx:490
SAL_DLLPRIVATE void ImplExchangeColors(ColorExchangeFnc pFncCol, const void *pColParam, BmpExchangeFnc pFncBmp, const void *pBmpParam)
Definition: gdimtf.cxx:1799
void Convert(MtfConversion eConversion)
Definition: gdimtf.cxx:2133
bool IsSetting() const
Definition: metaact.hxx:1215
#define LANGUAGE_SYSTEM
BitmapChecksum GetChecksum() const
Color(* ColorExchangeFnc)(const Color &rColor, const void *pColParam)
Definition: gdimtf.hxx:51
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:769
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:981
Size GetOutputSize() const
Definition: outdev.hxx:450
const Size & GetSize() const
Definition: metaact.hxx:1559
void SetOrigin(const Point &rOrigin)
Definition: mapmod.cxx:102
sal_uInt32 GetWidth() const
Definition: metaact.hxx:566
void SetRight(long v)
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:304
std::size_t WriteBytes(const void *pData, std::size_t nSize)
rtl_TextEncoding meActualCharSet
Definition: metaact.hxx:58
SvStreamCompressFlags
BmpMirrorFlags
Definition: bitmap.hxx:36
void SetScaleY(const Fraction &rScaleY)
Definition: mapmod.cxx:115
void UseCanvas(bool _bUseCanvas)
Definition: gdimtf.cxx:2827
void SetError(ErrCode nErrorCode)
BmpScaleFlag
Definition: bitmap.hxx:48
void Intersect(const tools::Rectangle &rRegion)
Definition: region.cxx:584
void getPath(tools::Polygon &) const
Query path to stroke.
sal_Int32 GetLen() const
Definition: metaact.hxx:568
const Point & GetPoint() const
Definition: metaact.hxx:770
bool m_bRecord
Definition: gdimtf.hxx:69
const Bitmap & GetBitmap() const
Definition: metaact.hxx:873
Size GetOutputSizePixel() const
Definition: outdev.hxx:441
MapUnit GetMapUnit() const
Definition: mapmod.cxx:168
sal_uInt8 SVBT64[8]
BmpConversion
Definition: bitmap.hxx:65
void WindStart()
Definition: gdimtf.cxx:530
bool IsTransparent() const
Definition: bitmapex.cxx:221
const Bitmap & GetBitmap() const
Definition: metaact.hxx:947
const Point & GetPoint() const
Definition: metaact.hxx:875
static vcl::Window * GetActiveTopWindow()
Get the "active" top window.
Definition: svapp.cxx:1108
static SAL_DLLPRIVATE Color ImplColAdjustFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1705
FontStrikeout GetStrikeout() const
Definition: metaact.hxx:637
tools::Rectangle GetBoundRect(OutputDevice &i_rReference, tools::Rectangle *pHairline=nullptr) const
Definition: gdimtf.cxx:1284
#define Y
const Size & GetSize() const
Definition: metaact.hxx:1595
const Bitmap & GetBitmap() const
Definition: metaact.hxx:700
void SetColor(const Color &)
Definition: font/font.cxx:80
std::size_t ReadBytes(void *pData, std::size_t nSize)
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1179
Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:934
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1041
SvStream & WriteSvtGraphicFill(SvStream &rOStm, const SvtGraphicFill &rClass)
const GfxLink & GetLink() const
Definition: metaact.hxx:1592
const Point & GetPoint() const
Definition: metaact.hxx:564
void SetAngle(sal_uInt16 nAngle10)
Definition: gdi/hatch.cxx:74
bool IsSetting() const
Definition: metaact.hxx:1242
sal_uInt8 GetGreen() const
SvStreamEndian GetEndian() const
void Stop()
Definition: gdimtf.cxx:517
const Color & GetColor() const
Definition: metaact.hxx:909
MapMode m_aPrefMapMode
Definition: gdimtf.hxx:63
const Point & GetStartPoint() const
Definition: metaact.hxx:181
sal_uInt32 GetDataSize() const
Definition: metaact.hxx:1655
bool operator==(const GDIMetaFile &rMtf) const
Definition: gdimtf.cxx:222
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:801
void Pause(bool bPause)
Definition: gdimtf.cxx:498
AlphaMask GetAlpha() const
Definition: bitmapex.cxx:268
BitmapChecksum GetChecksum() const
Definition: gdimtf.cxx:2198
const Color & GetColor() const
Definition: metaact.hxx:948
tools::Rectangle & Union(const tools::Rectangle &rRect)
unsigned char sal_uInt8
void ReplaceAction(rtl::Reference< MetaAction > pAction, size_t nAction)
Definition: gdimtf.cxx:178
void BCToBCOA(BitmapChecksum n, BitmapChecksumOctetArray p)
Definition: checksum.hxx:34
const Point & GetStartPoint() const
Definition: metaact.hxx:635
static SAL_DLLPRIVATE Color ImplColReplaceFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1769
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:543
MetaAction * GetAction(size_t nAction) const
Definition: gdimtf.cxx:162
void Move(long nX, long nY)
Definition: gdimtf.cxx:611
SvStream & ReadGDIMetaFile(SvStream &rIStm, GDIMetaFile &rGDIMetaFile, ImplMetaReadData *pData)
Definition: gdimtf.cxx:2622
void SetEndian(SvStreamEndian SvStreamEndian)
#define SAL_INFO(area, stream)
const Point & GetPoint() const
Definition: metaact.hxx:149
const Point & GetPoint() const
Definition: metaact.hxx:669
bool m_bUseCanvas
Definition: gdimtf.hxx:70
void Linker(OutputDevice *pOut, bool bLink)
Definition: gdimtf.cxx:256
const Point & GetDestPoint() const
Definition: metaact.hxx:949
#define SVSTREAM_FILEFORMAT_ERROR
Definition: errcode.hxx:262
rtl_TextEncoding GetStreamCharSet() const
void Scale(double fScaleX, double fScaleY)
Definition: gdimtf.cxx:688
static SAL_DLLPRIVATE BitmapEx ImplBmpMonoFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1750
bool HasPolyPolygonOrB2DPolyPolygon() const
Definition: region.hxx:110
sal_uInt64 Tell() const
void * p
Reference< XComponentContext > getProcessComponentContext()
size_t GetActionSize() const
Definition: gdimtf.cxx:157
QPRO_FUNC_TYPE nType
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
MetaActionType GetType() const
Definition: metaact.hxx:90
long Left() const
void setPath(const tools::Polygon &)
Set path to stroke.
const Hatch & GetHatch() const
Definition: metaact.hxx:1042
const Point & GetSrcPoint() const
Definition: metaact.hxx:951
FontLineStyle GetOverline() const
Definition: metaact.hxx:639
bool good() const
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
Definition: bitmappaint.cxx:34
basegfx::B2DPolyPolygon GetAsB2DPolyPolygon() const
Definition: region.cxx:1289
MetaAction * FirstAction()
Definition: gdimtf.cxx:167
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
Size GetPixelOffset() const
Get the offset in pixel.
Definition: outdev.hxx:1725
tools::Rectangle GetBoundRect() const
#define SAL_WARN(area, stream)
DepthGuard(HWPFile &rFile)
sal_uInt8 BitmapChecksumOctetArray[BITMAP_CHECKSUM_SIZE]
Definition: checksum.hxx:31
SvStreamEndian
SvStream & ReadMapMode(SvStream &rIStm, MapMode &rMapMode)
Definition: mapmod.cxx:136
const OString & GetComment() const
Definition: metaact.hxx:1653
Encapsulates geometry and associated attributes of a filled area.
tools::Rectangle GetBoundRect() const
static void ImplActionBounds(tools::Rectangle &o_rOutBounds, const tools::Rectangle &i_rInBounds, const std::vector< tools::Rectangle > &i_rClipStack, tools::Rectangle *o_pHairline)
Definition: gdimtf.cxx:1259
virtual void Move(long nHorzMove, long nVertMove)
Definition: metaact.cxx:177
size_t m_nCurrentActionElement
Definition: gdimtf.hxx:61
void getPath(tools::PolyPolygon &) const
Query path to fill.
Converts old SVGDI aka SVM1 format data to current VCLMTF aka SVM2 format metafile data...
std::enable_if< std::is_signed< T >::value||std::is_floating_point< T >::value, long >::type MinMax(T nVal, long nMin, long nMax)
const Size & GetSizePixel() const
Definition: bitmapex.hxx:83
const Color & GetColor() const
Definition: metaact.hxx:1241
virtual void Write(SvStream &rOStm, ImplMetaWriteData *pData)
Definition: metaact.cxx:185
const GDIMetaFile & GetSubstitute() const
Definition: metaact.hxx:1593
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: outdevstate.cxx:60
void SetColor(const Color &rColor)
Definition: gdi/hatch.cxx:64
void setWidth(long nWidth)
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: bitmapex.cxx:434
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:599
#define GAMMA(_def_cVal, _def_InvGamma)
Definition: gdimtf.cxx:52
aStr
sal_Int32 GetIndex() const
Definition: metaact.hxx:567
sal_Int32 GetIndex() const
Definition: metaact.hxx:492
SvStream & Write(SvStream &rOStm)
Definition: gdimtf.cxx:2723
static SAL_DLLPRIVATE Color ImplColConvertFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1726
void WindPrev()
Definition: gdimtf.cxx:536
const void * GetData()
void setHeight(long nHeight)
bool Rotate(long nAngle10, const Color &rFillColor)
Rotate bitmap by the specified angle.
Definition: bitmapex.cxx:390
sal_uLong GetSizeBytes() const
Definition: gdimtf.cxx:2541