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 <vcl/TypeSerializer.hxx>
42 
43 #include <com/sun/star/beans/XFastPropertySet.hpp>
44 #include <com/sun/star/rendering/MtfRenderer.hpp>
45 #include <com/sun/star/rendering/XBitmapCanvas.hpp>
46 #include <com/sun/star/rendering/XCanvas.hpp>
48 
49 using namespace com::sun::star;
50 
51 namespace {
52 
53 struct ImplColAdjustParam
54 {
55  std::unique_ptr<sal_uInt8[]> pMapR;
56  std::unique_ptr<sal_uInt8[]> pMapG;
57  std::unique_ptr<sal_uInt8[]> pMapB;
58 };
59 
60 struct ImplBmpAdjustParam
61 {
62  short nLuminancePercent;
63  short nContrastPercent;
64  short nChannelRPercent;
65  short nChannelGPercent;
66  short nChannelBPercent;
67  double fGamma;
68  bool bInvert;
69 };
70 
71 struct ImplColConvertParam
72 {
73  MtfConversion eConversion;
74 };
75 
76 struct ImplBmpConvertParam
77 {
78  BmpConversion eConversion;
79 };
80 
81 struct ImplColMonoParam
82 {
83  Color aColor;
84 };
85 
86 struct ImplBmpMonoParam
87 {
88  Color aColor;
89 };
90 
91 struct ImplColReplaceParam
92 {
93  std::unique_ptr<sal_uLong[]> pMinR;
94  std::unique_ptr<sal_uLong[]> pMaxR;
95  std::unique_ptr<sal_uLong[]> pMinG;
96  std::unique_ptr<sal_uLong[]> pMaxG;
97  std::unique_ptr<sal_uLong[]> pMinB;
98  std::unique_ptr<sal_uLong[]> pMaxB;
99  const Color * pDstCols;
101 };
102 
103 struct ImplBmpReplaceParam
104 {
105  const Color* pSrcCols;
106  const Color* pDstCols;
108 };
109 
110 }
111 
113  m_nCurrentActionElement( 0 ),
114  m_aPrefSize ( 1, 1 ),
115  m_pPrev ( nullptr ),
116  m_pNext ( nullptr ),
117  m_pOutDev ( nullptr ),
118  m_bPause ( false ),
119  m_bRecord ( false ),
120  m_bUseCanvas ( false )
121 {
122 }
123 
125  m_nCurrentActionElement( rMtf.m_nCurrentActionElement ),
126  m_aPrefMapMode ( rMtf.m_aPrefMapMode ),
127  m_aPrefSize ( rMtf.m_aPrefSize ),
128  m_pPrev ( rMtf.m_pPrev ),
129  m_pNext ( rMtf.m_pNext ),
130  m_pOutDev ( nullptr ),
131  m_bPause ( false ),
132  m_bRecord ( false ),
133  m_bUseCanvas ( rMtf.m_bUseCanvas )
134 {
135  for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
136  {
137  m_aList.push_back( rMtf.GetAction( i ) );
138  }
139 
140  if( rMtf.m_bRecord )
141  {
142  Record( rMtf.m_pOutDev );
143 
144  if ( rMtf.m_bPause )
145  Pause( true );
146  }
147 }
148 
150 {
151  Clear();
152 }
153 
155 {
156  MetaAction* pCurrAct;
157 
158  // watch for transparent drawing actions
159  for(pCurrAct = const_cast<GDIMetaFile*>(this)->FirstAction();
160  pCurrAct;
161  pCurrAct = const_cast<GDIMetaFile*>(this)->NextAction())
162  {
163  // #i10613# determine if the action is transparency capable
164 
165  // #107169# Also examine metafiles with masked bitmaps in
166  // detail. Further down, this is optimized in such a way
167  // that there's no unnecessary painting of masked bitmaps
168  // (which are _always_ subdivided into rectangular regions
169  // of uniform opacity): if a masked bitmap is printed over
170  // empty background, we convert to a plain bitmap with
171  // white background.
172  if (pCurrAct->IsTransparent())
173  return true;
174  }
175 
176  return false;
177 }
178 
180 {
181  return m_aList.size();
182 }
183 
184 MetaAction* GDIMetaFile::GetAction( size_t nAction ) const
185 {
186  return (nAction < m_aList.size()) ? m_aList[ nAction ].get() : nullptr;
187 }
188 
190 {
192  return m_aList.empty() ? nullptr : m_aList[ 0 ].get();
193 }
194 
196 {
197  return ( m_nCurrentActionElement + 1 < m_aList.size() ) ? m_aList[ ++m_nCurrentActionElement ].get() : nullptr;
198 }
199 
201 {
202  if ( nAction >= m_aList.size() )
203  {
204  return;
205  }
206  //fdo#39995 This doesn't increment the incoming action ref-count nor does it
207  //decrement the outgoing action ref-count
208  std::swap(pAction, m_aList[nAction]);
209 }
210 
212 {
213  if( this != &rMtf )
214  {
215  Clear();
216 
217  // Increment RefCount of MetaActions
218  for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
219  {
220  m_aList.push_back( rMtf.GetAction( i ) );
221  }
222 
224  m_aPrefSize = rMtf.m_aPrefSize;
225  m_pPrev = rMtf.m_pPrev;
226  m_pNext = rMtf.m_pNext;
227  m_pOutDev = nullptr;
228  m_bPause = false;
229  m_bRecord = false;
230  m_bUseCanvas = rMtf.m_bUseCanvas;
231 
232  if( rMtf.m_bRecord )
233  {
234  Record( rMtf.m_pOutDev );
235 
236  if( rMtf.m_bPause )
237  Pause( true );
238  }
239  }
240 
241  return *this;
242 }
243 
244 bool GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const
245 {
246  const size_t nObjCount = m_aList.size();
247  bool bRet = false;
248 
249  if( this == &rMtf )
250  bRet = true;
251  else if( rMtf.GetActionSize() == nObjCount &&
252  rMtf.GetPrefSize() == m_aPrefSize &&
253  rMtf.GetPrefMapMode() == m_aPrefMapMode )
254  {
255  bRet = true;
256 
257  for( size_t n = 0; n < nObjCount; n++ )
258  {
259  if( m_aList[ n ] != rMtf.GetAction( n ) )
260  {
261  bRet = false;
262  break;
263  }
264  }
265  }
266 
267  return bRet;
268 }
269 
271 {
272  if( m_bRecord )
273  Stop();
274 
275  m_aList.clear();
276 }
277 
278 void GDIMetaFile::Linker( OutputDevice* pOut, bool bLink )
279 {
280  if( bLink )
281  {
282  m_pNext = nullptr;
283  m_pPrev = pOut->GetConnectMetaFile();
284  pOut->SetConnectMetaFile( this );
285 
286  if( m_pPrev )
287  m_pPrev->m_pNext = this;
288  }
289  else
290  {
291  if( m_pNext )
292  {
294 
295  if( m_pPrev )
297  }
298  else
299  {
300  if( m_pPrev )
301  m_pPrev->m_pNext = nullptr;
302 
303  pOut->SetConnectMetaFile( m_pPrev );
304  }
305 
306  m_pPrev = nullptr;
307  m_pNext = nullptr;
308  }
309 }
310 
312 {
313  if( m_bRecord )
314  Stop();
315 
316  m_nCurrentActionElement = m_aList.empty() ? 0 : (m_aList.size() - 1);
317  m_pOutDev = pOut;
318  m_bRecord = true;
319  Linker( pOut, true );
320 }
321 
323 {
324  if (m_bRecord || rMtf.m_bRecord)
325  return;
326 
327  MetaAction* pAction = GetCurAction();
328  const size_t nObjCount = m_aList.size();
329 
330  rMtf.UseCanvas( rMtf.GetUseCanvas() || m_bUseCanvas );
331 
332  for( size_t nCurPos = m_nCurrentActionElement; nCurPos < nObjCount; nCurPos++ )
333  {
334  if( pAction )
335  {
336  rMtf.AddAction( pAction );
337  }
338 
339  pAction = NextAction();
340  }
341 }
342 
343 void GDIMetaFile::Play(OutputDevice& rOut, size_t nPos)
344 {
345  if( m_bRecord )
346  return;
347 
348  MetaAction* pAction = GetCurAction();
349  const size_t nObjCount = m_aList.size();
350  size_t nSyncCount = rOut.GetSyncCount();
351 
352  if( nPos > nObjCount )
353  nPos = nObjCount;
354 
355  // #i23407# Set backwards-compatible text language and layout mode
356  // This is necessary, since old metafiles don't even know of these
357  // recent add-ons. Newer metafiles must of course explicitly set
358  // those states.
362 
363  SAL_INFO( "vcl.gdi", "GDIMetaFile::Play on device of size: " << rOut.GetOutputSizePixel().Width() << " " << rOut.GetOutputSizePixel().Height());
364 
365  if (!ImplPlayWithRenderer(rOut, Point(0,0), rOut.GetOutputSize())) {
366  size_t i = 0;
367  for( size_t nCurPos = m_nCurrentActionElement; nCurPos < nPos; nCurPos++ )
368  {
369  if( pAction )
370  {
371  pAction->Execute(&rOut);
372 
373  // flush output from time to time
374  if( i++ > nSyncCount )
375  {
376  rOut.Flush();
377  i = 0;
378  }
379  }
380 
381  pAction = NextAction();
382  }
383  }
384  rOut.Pop();
385 }
386 
387 bool GDIMetaFile::ImplPlayWithRenderer(OutputDevice& rOut, const Point& rPos, Size rLogicDestSize)
388 {
389  if (!m_bUseCanvas)
390  return false;
391 
392  Size rDestSize(rOut.LogicToPixel(rLogicDestSize));
393 
394  const vcl::Window* win = rOut.GetOwnerWindow();
395 
396  if (!win)
398  if (!win)
400 
401  if (!win)
402  return false;
403 
404  try
405  {
406  uno::Reference<rendering::XCanvas> xCanvas = win->GetOutDev()->GetCanvas ();
407 
408  if (!xCanvas.is())
409  return false;
410 
411  Size aSize (rDestSize.Width () + 1, rDestSize.Height () + 1);
412  uno::Reference<rendering::XBitmap> xBitmap = xCanvas->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize));
413  if( xBitmap.is () )
414  {
415  uno::Reference< rendering::XBitmapCanvas > xBitmapCanvas( xBitmap, uno::UNO_QUERY );
416  if( xBitmapCanvas.is() )
417  {
418  uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
419  uno::Reference< rendering::XMtfRenderer > xMtfRenderer = rendering::MtfRenderer::createWithBitmapCanvas( xContext, xBitmapCanvas );
420 
421  xBitmapCanvas->clear();
422  uno::Reference< beans::XFastPropertySet > xMtfFastPropertySet( xMtfRenderer, uno::UNO_QUERY );
423  if( xMtfFastPropertySet.is() )
424  // set this metafile to the renderer to
425  // speedup things (instead of copying data to
426  // sequence of bytes passed to renderer)
427  xMtfFastPropertySet->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64>( this ) ) );
428 
429  xMtfRenderer->draw( rDestSize.Width(), rDestSize.Height() );
430 
431  BitmapEx aBitmapEx;
432  if( aBitmapEx.Create( xBitmapCanvas, aSize ) )
433  {
434  if (rOut.GetMapMode().GetMapUnit() == MapUnit::MapPixel)
435  rOut.DrawBitmapEx( rPos, aBitmapEx );
436  else
437  rOut.DrawBitmapEx( rPos, rLogicDestSize, aBitmapEx );
438  return true;
439  }
440  }
441  }
442  }
443  catch (const uno::RuntimeException& )
444  {
445  throw; // runtime errors are fatal
446  }
447  catch (const uno::Exception&)
448  {
449  // ignore errors, no way of reporting them here
450  TOOLS_WARN_EXCEPTION("vcl.gdi", "GDIMetaFile::ImplPlayWithRenderer");
451  }
452 
453  return false;
454 }
455 
456 void GDIMetaFile::Play(OutputDevice& rOut, const Point& rPos,
457  const Size& rSize)
458 {
459  MapMode aDrawMap( GetPrefMapMode() );
460  Size aDestSize(rOut.LogicToPixel(rSize));
461 
462  if( !aDestSize.Width() || !aDestSize.Height() )
463  return;
464 
465  GDIMetaFile* pMtf = rOut.GetConnectMetaFile();
466 
467  if (ImplPlayWithRenderer(rOut, rPos, rSize))
468  return;
469 
470  Size aTmpPrefSize(rOut.LogicToPixel(GetPrefSize(), aDrawMap));
471 
472  if( !aTmpPrefSize.Width() )
473  aTmpPrefSize.setWidth( aDestSize.Width() );
474 
475  if( !aTmpPrefSize.Height() )
476  aTmpPrefSize.setHeight( aDestSize.Height() );
477 
478  Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
479  Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
480 
481  aScaleX *= aDrawMap.GetScaleX(); aDrawMap.SetScaleX( aScaleX );
482  aScaleY *= aDrawMap.GetScaleY(); aDrawMap.SetScaleY( aScaleY );
483 
484  // #i47260# Convert logical output position to offset within
485  // the metafile's mapmode. Therefore, disable pixel offset on
486  // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
487  // different mapmode (the one currently set on rOut, that is)
488  // - thus, aDrawMap's origin would generally be wrong. And
489  // even _if_ aDrawMap is similar to pOutDev's current mapmode,
490  // it's _still_ undesirable to have pixel offset unequal zero,
491  // because one would still get round-off errors (the
492  // round-trip error for LogicToPixel( PixelToLogic() ) was the
493  // reason for having pixel offset in the first place).
494  const Size& rOldOffset(rOut.GetPixelOffset());
495  const Size aEmptySize;
496  rOut.SetPixelOffset(aEmptySize);
497  aDrawMap.SetOrigin(rOut.PixelToLogic(rOut.LogicToPixel(rPos), aDrawMap));
498  rOut.SetPixelOffset(rOldOffset);
499 
500  rOut.Push();
501 
502  bool bIsRecord = (pMtf && pMtf->IsRecord());
503  rOut.SetMetafileMapMode(aDrawMap, bIsRecord);
504 
505  // #i23407# Set backwards-compatible text language and layout mode
506  // This is necessary, since old metafiles don't even know of these
507  // recent add-ons. Newer metafiles must of course explicitly set
508  // those states.
511 
512  Play(rOut);
513 
514  rOut.Pop();
515 }
516 
517 void GDIMetaFile::Pause( bool _bPause )
518 {
519  if( !m_bRecord )
520  return;
521 
522  if( _bPause )
523  {
524  if( !m_bPause )
525  Linker( m_pOutDev, false );
526  }
527  else
528  {
529  if( m_bPause )
530  Linker( m_pOutDev, true );
531  }
532 
533  m_bPause = _bPause;
534 }
535 
537 {
538  if( m_bRecord )
539  {
540  m_bRecord = false;
541 
542  if( !m_bPause )
543  Linker( m_pOutDev, false );
544  else
545  m_bPause = false;
546  }
547 }
548 
550 {
551  if( !m_bRecord )
553 }
554 
556 {
557  if( !m_bRecord )
558  if ( m_nCurrentActionElement > 0 )
560 }
561 
563 {
564  m_aList.push_back( pAction );
565 
566  if( m_pPrev )
567  {
568  m_pPrev->AddAction( pAction );
569  }
570 }
571 
572 void GDIMetaFile::AddAction(const rtl::Reference<MetaAction>& pAction, size_t nPos)
573 {
574  if ( nPos < m_aList.size() )
575  {
576  m_aList.insert( m_aList.begin() + nPos, pAction );
577  }
578  else
579  {
580  m_aList.push_back( pAction );
581  }
582 
583  if( m_pPrev )
584  {
585  m_pPrev->AddAction( pAction, nPos );
586  }
587 }
588 
590 {
591  m_aList.push_back( pAction );
592 }
593 
595 {
596  const Size aOldPrefSize( GetPrefSize() );
597  tools::Long nMoveX, nMoveY;
598  double fScaleX, fScaleY;
599 
600  if( nMirrorFlags & BmpMirrorFlags::Horizontal )
601  {
602  nMoveX = std::abs( aOldPrefSize.Width() ) - 1;
603  fScaleX = -1.0;
604  }
605  else
606  {
607  nMoveX = 0;
608  fScaleX = 1.0;
609  }
610 
611  if( nMirrorFlags & BmpMirrorFlags::Vertical )
612  {
613  nMoveY = std::abs( aOldPrefSize.Height() ) - 1;
614  fScaleY = -1.0;
615  }
616  else
617  {
618  nMoveY = 0;
619  fScaleY = 1.0;
620  }
621 
622  if( ( fScaleX != 1.0 ) || ( fScaleY != 1.0 ) )
623  {
624  Scale( fScaleX, fScaleY );
625  Move( nMoveX, nMoveY );
626  SetPrefSize( aOldPrefSize );
627  }
628 }
629 
631 {
632  const Size aBaseOffset( nX, nY );
633  Size aOffset( aBaseOffset );
635 
636  aMapVDev->EnableOutput( false );
637  aMapVDev->SetMapMode( GetPrefMapMode() );
638 
639  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
640  {
641  const MetaActionType nType = pAct->GetType();
642  MetaAction* pModAct;
643 
644  if( pAct->GetRefCount() > 1 )
645  {
646  m_aList[ m_nCurrentActionElement ] = pAct->Clone();
647  pModAct = m_aList[ m_nCurrentActionElement ].get();
648  }
649  else
650  pModAct = pAct;
651 
652  if( ( MetaActionType::MAPMODE == nType ) ||
653  ( MetaActionType::PUSH == nType ) ||
654  ( MetaActionType::POP == nType ) )
655  {
656  pModAct->Execute( aMapVDev.get() );
657  aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
658  }
659 
660  pModAct->Move( aOffset.Width(), aOffset.Height() );
661  }
662 }
663 
665 {
666  const Size aBaseOffset( nX, nY );
667  Size aOffset( aBaseOffset );
669 
670  aMapVDev->EnableOutput( false );
671  aMapVDev->SetReferenceDevice( nDPIX, nDPIY );
672  aMapVDev->SetMapMode( GetPrefMapMode() );
673 
674  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
675  {
676  const MetaActionType nType = pAct->GetType();
677  MetaAction* pModAct;
678 
679  if( pAct->GetRefCount() > 1 )
680  {
681  m_aList[ m_nCurrentActionElement ] = pAct->Clone();
682  pModAct = m_aList[ m_nCurrentActionElement ].get();
683  }
684  else
685  pModAct = pAct;
686 
687  if( ( MetaActionType::MAPMODE == nType ) ||
688  ( MetaActionType::PUSH == nType ) ||
689  ( MetaActionType::POP == nType ) )
690  {
691  pModAct->Execute( aMapVDev.get() );
692  if( aMapVDev->GetMapMode().GetMapUnit() == MapUnit::MapPixel )
693  {
694  aOffset = aMapVDev->LogicToPixel( aBaseOffset, GetPrefMapMode() );
695  MapMode aMap( aMapVDev->GetMapMode() );
696  aOffset.setWidth( static_cast<tools::Long>(aOffset.Width() * static_cast<double>(aMap.GetScaleX())) );
697  aOffset.setHeight( static_cast<tools::Long>(aOffset.Height() * static_cast<double>(aMap.GetScaleY())) );
698  }
699  else
700  aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
701  }
702 
703  pModAct->Move( aOffset.Width(), aOffset.Height() );
704  }
705 }
706 
707 void GDIMetaFile::Scale( double fScaleX, double fScaleY )
708 {
709  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
710  {
711  MetaAction* pModAct;
712 
713  if( pAct->GetRefCount() > 1 )
714  {
715  m_aList[ m_nCurrentActionElement ] = pAct->Clone();
716  pModAct = m_aList[ m_nCurrentActionElement ].get();
717  }
718  else
719  pModAct = pAct;
720 
721  pModAct->Scale( fScaleX, fScaleY );
722  }
723 
724  m_aPrefSize.setWidth( FRound( m_aPrefSize.Width() * fScaleX ) );
725  m_aPrefSize.setHeight( FRound( m_aPrefSize.Height() * fScaleY ) );
726 }
727 
728 void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
729 {
730  Scale( static_cast<double>(rScaleX), static_cast<double>(rScaleY) );
731 }
732 
733 void GDIMetaFile::Clip( const tools::Rectangle& i_rClipRect )
734 {
735  tools::Rectangle aCurRect( i_rClipRect );
737 
738  aMapVDev->EnableOutput( false );
739  aMapVDev->SetMapMode( GetPrefMapMode() );
740 
741  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
742  {
743  const MetaActionType nType = pAct->GetType();
744 
745  if( ( MetaActionType::MAPMODE == nType ) ||
746  ( MetaActionType::PUSH == nType ) ||
747  ( MetaActionType::POP == nType ) )
748  {
749  pAct->Execute( aMapVDev.get() );
750  aCurRect = OutputDevice::LogicToLogic( i_rClipRect, GetPrefMapMode(), aMapVDev->GetMapMode() );
751  }
752  else if( nType == MetaActionType::CLIPREGION )
753  {
754  MetaClipRegionAction* pOldAct = static_cast<MetaClipRegionAction*>(pAct);
755  vcl::Region aNewReg( aCurRect );
756  if( pOldAct->IsClipping() )
757  aNewReg.Intersect( pOldAct->GetRegion() );
758  MetaClipRegionAction* pNewAct = new MetaClipRegionAction( aNewReg, true );
759  m_aList[ m_nCurrentActionElement ] = pNewAct;
760  }
761  }
762 }
763 
764 Point GDIMetaFile::ImplGetRotatedPoint( const Point& rPt, const Point& rRotatePt,
765  const Size& rOffset, double fSin, double fCos )
766 {
767  const tools::Long nX = rPt.X() - rRotatePt.X();
768  const tools::Long nY = rPt.Y() - rRotatePt.Y();
769 
770  return Point( FRound( fCos * nX + fSin * nY ) + rRotatePt.X() + rOffset.Width(),
771  -FRound( fSin * nX - fCos * nY ) + rRotatePt.Y() + rOffset.Height() );
772 }
773 
775  const Size& rOffset, double fSin, double fCos )
776 {
777  tools::Polygon aRet( rPoly );
778 
779  aRet.Rotate( rRotatePt, fSin, fCos );
780  aRet.Move( rOffset.Width(), rOffset.Height() );
781 
782  return aRet;
783 }
784 
786  const Size& rOffset, double fSin, double fCos )
787 {
788  tools::PolyPolygon aRet( rPolyPoly );
789 
790  aRet.Rotate( rRotatePt, fSin, fCos );
791  aRet.Move( rOffset.Width(), rOffset.Height() );
792 
793  return aRet;
794 }
795 
797  const OutputDevice& rMapDev,
798  const tools::PolyPolygon& rPolyPoly,
799  const Gradient& rGrad )
800 {
801  // Generate comment, GradientEx and Gradient actions (within DrawGradient)
803  aVDev->EnableOutput( false );
804  GDIMetaFile aGradMtf;
805 
806  aGradMtf.Record( aVDev.get() );
807  aVDev->DrawGradient( rPolyPoly, rGrad );
808  aGradMtf.Stop();
809 
810  size_t i, nAct( aGradMtf.GetActionSize() );
811  for( i=0; i < nAct; ++i )
812  {
813  MetaAction* pMetaAct = aGradMtf.GetAction( i );
814  rMtf.AddAction( pMetaAct );
815  }
816 }
817 
819 {
820  nAngle10 %= 3600_deg10;
821  nAngle10 = ( nAngle10 < 0_deg10 ) ? ( Degree10(3599) + nAngle10 ) : nAngle10;
822 
823  if( !nAngle10 )
824  return;
825 
826  GDIMetaFile aMtf;
828  const double fAngle = F_PI1800 * nAngle10.get();
829  const double fSin = sin( fAngle );
830  const double fCos = cos( fAngle );
831  tools::Rectangle aRect( Point(), GetPrefSize() );
832  tools::Polygon aPoly( aRect );
833 
834  aPoly.Rotate( Point(), fSin, fCos );
835 
836  aMapVDev->EnableOutput( false );
837  aMapVDev->SetMapMode( GetPrefMapMode() );
838 
839  const tools::Rectangle aNewBound( aPoly.GetBoundRect() );
840 
841  const Point aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
842  const Size aOffset( -aNewBound.Left(), -aNewBound.Top() );
843 
844  Point aRotAnchor( aOrigin );
845  Size aRotOffset( aOffset );
846 
847  for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
848  {
849  const MetaActionType nActionType = pAction->GetType();
850 
851  switch( nActionType )
852  {
854  {
855  MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
856  aMtf.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
857  pAct->GetColor() ) );
858  }
859  break;
860 
862  {
863  MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
864  aMtf.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
865  }
866  break;
867 
869  {
870  MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
871  aMtf.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
872  ImplGetRotatedPoint( pAct->GetEndPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
873  pAct->GetLineInfo() ) );
874  }
875  break;
876 
878  {
879  MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
880  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
881  }
882  break;
883 
885  {
886  MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
887  const tools::Polygon aRoundRectPoly( pAct->GetRect(), pAct->GetHorzRound(), pAct->GetVertRound() );
888 
889  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
890  }
891  break;
892 
894  {
895  MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
896  const tools::Polygon aEllipsePoly( pAct->GetRect().Center(), pAct->GetRect().GetWidth() >> 1, pAct->GetRect().GetHeight() >> 1 );
897 
898  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
899  }
900  break;
901 
902  case MetaActionType::ARC:
903  {
904  MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
905  const tools::Polygon aArcPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Arc );
906 
907  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
908  }
909  break;
910 
911  case MetaActionType::PIE:
912  {
913  MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
914  const tools::Polygon aPiePoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Pie );
915 
916  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
917  }
918  break;
919 
921  {
922  MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
923  const tools::Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Chord );
924 
925  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
926  }
927  break;
928 
930  {
931  MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
932  aMtf.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->GetLineInfo() ) );
933  }
934  break;
935 
937  {
938  MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
939  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
940  }
941  break;
942 
944  {
945  MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
946  aMtf.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
947  }
948  break;
949 
951  {
952  MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
953  aMtf.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
954  pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
955  }
956  break;
957 
959  {
960  MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
961  aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
962  pAct->GetText(), pAct->GetDXArray(), pAct->GetIndex(), pAct->GetLen() ) );
963  }
964  break;
965 
967  {
968  MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
969  aMtf.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
970  pAct->GetWidth(), pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
971  }
972  break;
973 
975  {
976  MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
977  aMtf.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
978  pAct->GetWidth(), pAct->GetStrikeout(), pAct->GetUnderline(), pAct->GetOverline() ) );
979  }
980  break;
981 
983  {
984  MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
985  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
986  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
987  BitmapEx aBmpEx( pAct->GetBitmap() );
988 
989  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
990  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(),
991  aBmpEx ) );
992  }
993  break;
994 
996  {
997  MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
998  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
999  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1000  BitmapEx aBmpEx( pAct->GetBitmap() );
1001 
1002  aBmpEx.Crop( tools::Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1003  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1004 
1005  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1006  }
1007  break;
1008 
1010  {
1011  MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1012  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1013  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1014  BitmapEx aBmpEx( pAct->GetBitmapEx() );
1015 
1016  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1017 
1018  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1019  }
1020  break;
1021 
1023  {
1024  MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1025  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1026  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1027  BitmapEx aBmpEx( pAct->GetBitmapEx() );
1028 
1029  aBmpEx.Crop( tools::Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1030  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1031 
1032  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1033  }
1034  break;
1035 
1037  {
1038  MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1039 
1040  ImplAddGradientEx( aMtf, *aMapVDev,
1041  ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ),
1042  pAct->GetGradient() );
1043  }
1044  break;
1045 
1047  {
1048  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1049  aMtf.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1050  pAct->GetGradient() ) );
1051  }
1052  break;
1053 
1054  // Handle gradientex comment block correctly
1056  {
1057  MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
1058  if( pCommentAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1059  {
1060  int nBeginComments( 1 );
1061  pAction = NextAction();
1062 
1063  // skip everything, except gradientex action
1064  while( pAction )
1065  {
1066  const MetaActionType nType = pAction->GetType();
1067 
1068  if( MetaActionType::GRADIENTEX == nType )
1069  {
1070  // Add rotated gradientex
1071  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1072  ImplAddGradientEx( aMtf, *aMapVDev,
1073  ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1074  pAct->GetGradient() );
1075  }
1076  else if( MetaActionType::COMMENT == nType)
1077  {
1078  MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pAction);
1079  if( pAct->GetComment() == "XGRAD_SEQ_END" )
1080  {
1081  // handle nested blocks
1082  --nBeginComments;
1083 
1084  // gradientex comment block: end reached, done.
1085  if( !nBeginComments )
1086  break;
1087  }
1088  else if( pAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1089  {
1090  // handle nested blocks
1091  ++nBeginComments;
1092  }
1093 
1094  }
1095 
1096  pAction =NextAction();
1097  }
1098  }
1099  else
1100  {
1101  bool bPathStroke = (pCommentAct->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1102  if ( bPathStroke || pCommentAct->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1103  {
1104  if ( pCommentAct->GetDataSize() )
1105  {
1106  SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pCommentAct->GetData()), pCommentAct->GetDataSize(), StreamMode::READ );
1107  SvMemoryStream aDest;
1108  if ( bPathStroke )
1109  {
1110  SvtGraphicStroke aStroke;
1111  ReadSvtGraphicStroke( aMemStm, aStroke );
1112  tools::Polygon aPath;
1113  aStroke.getPath( aPath );
1114  aStroke.setPath( ImplGetRotatedPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1115  WriteSvtGraphicStroke( aDest, aStroke );
1116  aMtf.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1117  static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1118  }
1119  else
1120  {
1121  SvtGraphicFill aFill;
1122  ReadSvtGraphicFill( aMemStm, aFill );
1123  tools::PolyPolygon aPath;
1124  aFill.getPath( aPath );
1125  aFill.setPath( ImplGetRotatedPolyPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1126  WriteSvtGraphicFill( aDest, aFill );
1127  aMtf.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1128  static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1129  }
1130  }
1131  }
1132  else if ( pCommentAct->GetComment() == "XPATHSTROKE_SEQ_END"
1133  || pCommentAct->GetComment() == "XPATHFILL_SEQ_END" )
1134  {
1135  pAction->Execute( aMapVDev.get() );
1136  aMtf.AddAction( pAction );
1137  }
1138  }
1139  }
1140  break;
1141 
1142  case MetaActionType::HATCH:
1143  {
1144  MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1145  Hatch aHatch( pAct->GetHatch() );
1146 
1147  aHatch.SetAngle( aHatch.GetAngle() + nAngle10 );
1148  aMtf.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1149  aHatch ) );
1150  }
1151  break;
1152 
1154  {
1155  MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1156  aMtf.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1157  pAct->GetTransparence() ) );
1158  }
1159  break;
1160 
1162  {
1163  MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1164  GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
1165  tools::Polygon aMtfPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1166  tools::Rectangle aMtfRect( aMtfPoly.GetBoundRect() );
1167 
1168  aTransMtf.Rotate( nAngle10 );
1169  aMtf.AddAction( new MetaFloatTransparentAction( aTransMtf, aMtfRect.TopLeft(), aMtfRect.GetSize(),
1170  pAct->GetGradient() ) );
1171  }
1172  break;
1173 
1174  case MetaActionType::EPS:
1175  {
1176  MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1177  GDIMetaFile aEPSMtf( pAct->GetSubstitute() );
1178  tools::Polygon aEPSPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1179  tools::Rectangle aEPSRect( aEPSPoly.GetBoundRect() );
1180 
1181  aEPSMtf.Rotate( nAngle10 );
1182  aMtf.AddAction( new MetaEPSAction( aEPSRect.TopLeft(), aEPSRect.GetSize(),
1183  pAct->GetLink(), aEPSMtf ) );
1184  }
1185  break;
1186 
1188  {
1189  MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1190 
1191  if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1192  aMtf.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), true ) );
1193  else
1194  {
1195  aMtf.AddAction( pAction );
1196  }
1197  }
1198  break;
1199 
1201  {
1202  MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1204  ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor,
1205  aRotOffset, fSin, fCos )) ) );
1206  }
1207  break;
1208 
1210  {
1212  const vcl::Region& rRegion = pAct->GetRegion();
1213 
1214  if( rRegion.HasPolyPolygonOrB2DPolyPolygon() )
1215  aMtf.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion.GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
1216  else
1217  {
1218  aMtf.AddAction( pAction );
1219  }
1220  }
1221  break;
1222 
1224  {
1225  MetaRefPointAction* pAct = static_cast<MetaRefPointAction*>(pAction);
1226  aMtf.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct->GetRefPoint(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->IsSetting() ) );
1227  }
1228  break;
1229 
1230  case MetaActionType::FONT:
1231  {
1232  MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
1233  vcl::Font aFont( pAct->GetFont() );
1234 
1235  aFont.SetOrientation( aFont.GetOrientation() + nAngle10 );
1236  aMtf.AddAction( new MetaFontAction( aFont ) );
1237  }
1238  break;
1239 
1240  case MetaActionType::BMP:
1241  case MetaActionType::BMPEX:
1242  case MetaActionType::MASK:
1248  {
1249  OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1250  }
1251  break;
1252 
1253  default:
1254  {
1255  pAction->Execute( aMapVDev.get() );
1256  aMtf.AddAction( pAction );
1257 
1258  // update rotation point and offset, if necessary
1259  if( ( MetaActionType::MAPMODE == nActionType ) ||
1260  ( MetaActionType::PUSH == nActionType ) ||
1261  ( MetaActionType::POP == nActionType ) )
1262  {
1263  aRotAnchor = OutputDevice::LogicToLogic( aOrigin, m_aPrefMapMode, aMapVDev->GetMapMode() );
1264  aRotOffset = OutputDevice::LogicToLogic( aOffset, m_aPrefMapMode, aMapVDev->GetMapMode() );
1265  }
1266  }
1267  break;
1268  }
1269  }
1270 
1272  aMtf.m_aPrefSize = aNewBound.GetSize();
1273 
1274  *this = aMtf;
1275 
1276 }
1277 
1278 static void ImplActionBounds( tools::Rectangle& o_rOutBounds,
1279  const tools::Rectangle& i_rInBounds,
1280  const std::vector<tools::Rectangle>& i_rClipStack,
1281  tools::Rectangle* o_pHairline )
1282 {
1283  tools::Rectangle aBounds( i_rInBounds );
1284  if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() )
1285  aBounds.Intersection( i_rClipStack.back() );
1286  if( aBounds.IsEmpty() )
1287  return;
1288 
1289  if( ! o_rOutBounds.IsEmpty() )
1290  o_rOutBounds.Union( aBounds );
1291  else
1292  o_rOutBounds = aBounds;
1293 
1294  if(o_pHairline)
1295  {
1296  if( ! o_pHairline->IsEmpty() )
1297  o_pHairline->Union( aBounds );
1298  else
1299  *o_pHairline = aBounds;
1300  }
1301 }
1302 
1304 {
1305  ScopedVclPtrInstance< VirtualDevice > aMapVDev( i_rReference );
1306 
1307  aMapVDev->EnableOutput( false );
1308  aMapVDev->SetMapMode( GetPrefMapMode() );
1309 
1310  std::vector<tools::Rectangle> aClipStack( 1, tools::Rectangle() );
1311  std::vector<vcl::PushFlags> aPushFlagStack;
1312 
1313  tools::Rectangle aBound;
1314 
1315  if(pHairline)
1316  *pHairline = tools::Rectangle();
1317 
1318  const sal_uLong nCount(GetActionSize());
1319 
1320  for(sal_uLong a(0); a < nCount; a++)
1321  {
1322  MetaAction* pAction = GetAction(a);
1323  const MetaActionType nActionType = pAction->GetType();
1324  tools::Rectangle* pUseHairline = (pHairline && aMapVDev->IsLineColor()) ? pHairline : nullptr;
1325 
1326  switch( nActionType )
1327  {
1328  case MetaActionType::PIXEL:
1329  {
1330  MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1331  ImplActionBounds( aBound,
1332  tools::Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1333  aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1334  aClipStack, pUseHairline );
1335  }
1336  break;
1337 
1338  case MetaActionType::POINT:
1339  {
1340  MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
1341  ImplActionBounds( aBound,
1342  tools::Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1343  aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1344  aClipStack, pUseHairline );
1345  }
1346  break;
1347 
1348  case MetaActionType::LINE:
1349  {
1350  MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
1351  Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() );
1352  tools::Rectangle aRect( aP1, aP2 );
1353  aRect.Justify();
1354 
1355  if(pUseHairline)
1356  {
1357  const LineInfo& rLineInfo = pAct->GetLineInfo();
1358 
1359  if(0 != rLineInfo.GetWidth())
1360  pUseHairline = nullptr;
1361  }
1362 
1363  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1364  }
1365  break;
1366 
1367  case MetaActionType::RECT:
1368  {
1369  MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
1370  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1371  }
1372  break;
1373 
1375  {
1376  MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
1377  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1378  }
1379  break;
1380 
1382  {
1383  MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
1384  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1385  }
1386  break;
1387 
1388  case MetaActionType::ARC:
1389  {
1390  MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
1391  // FIXME: this is imprecise
1392  // e.g. for small arcs the whole rectangle is WAY too large
1393  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1394  }
1395  break;
1396 
1397  case MetaActionType::PIE:
1398  {
1399  MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
1400  // FIXME: this is imprecise
1401  // e.g. for small arcs the whole rectangle is WAY too large
1402  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1403  }
1404  break;
1405 
1406  case MetaActionType::CHORD:
1407  {
1408  MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
1409  // FIXME: this is imprecise
1410  // e.g. for small arcs the whole rectangle is WAY too large
1411  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1412  }
1413  break;
1414 
1416  {
1417  MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
1418  tools::Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1419 
1420  if(pUseHairline)
1421  {
1422  const LineInfo& rLineInfo = pAct->GetLineInfo();
1423 
1424  if(0 != rLineInfo.GetWidth())
1425  pUseHairline = nullptr;
1426  }
1427 
1428  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1429  }
1430  break;
1431 
1433  {
1434  MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
1435  tools::Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1436  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1437  }
1438  break;
1439 
1441  {
1442  MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
1443  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1444  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1445  }
1446  break;
1447 
1448  case MetaActionType::TEXT:
1449  {
1450  MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
1451  tools::Rectangle aRect;
1452  // hdu said base = index
1453  aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() );
1454  Point aPt( pAct->GetPoint() );
1455  aRect.Move( aPt.X(), aPt.Y() );
1456  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1457  }
1458  break;
1459 
1461  {
1462  MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
1463  tools::Rectangle aRect;
1464  // hdu said base = index
1465  aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1466  0, pAct->GetDXArray() );
1467  Point aPt( pAct->GetPoint() );
1468  aRect.Move( aPt.X(), aPt.Y() );
1469  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1470  }
1471  break;
1472 
1474  {
1475  MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
1476  tools::Rectangle aRect;
1477  // hdu said base = index
1478  aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1479  pAct->GetWidth() );
1480  Point aPt( pAct->GetPoint() );
1481  aRect.Move( aPt.X(), aPt.Y() );
1482  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1483  }
1484  break;
1485 
1487  {
1488  MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
1489  // measure a test string to get ascend and descent right
1490  static constexpr OUStringLiteral pStr = u"\u00c4g";
1491  OUString aStr( pStr );
1492 
1493  tools::Rectangle aRect;
1494  aMapVDev->GetTextBoundRect( aRect, aStr, 0, 0, aStr.getLength() );
1495  Point aPt( pAct->GetStartPoint() );
1496  aRect.Move( aPt.X(), aPt.Y() );
1497  aRect.SetRight( aRect.Left() + pAct->GetWidth() );
1498  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1499  }
1500  break;
1501 
1503  {
1504  MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1505  tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1506  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1507  }
1508  break;
1509 
1511  {
1512  MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1513  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1514  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1515  }
1516  break;
1517 
1519  {
1520  MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1521  tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1522  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1523  }
1524  break;
1525 
1527  {
1528  MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1529  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1530  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1531  }
1532  break;
1533 
1535  {
1536  MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1537  tools::Rectangle aRect( pAct->GetRect() );
1538  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1539  }
1540  break;
1541 
1543  {
1544  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1545  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1546  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1547  }
1548  break;
1549 
1551  {
1552  // nothing to do
1553  };
1554  break;
1555 
1556  case MetaActionType::HATCH:
1557  {
1558  MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1559  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1560  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1561  }
1562  break;
1563 
1565  {
1566  MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1567  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1568  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1569  }
1570  break;
1571 
1573  {
1574  MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1575  // MetaFloatTransparentAction is defined limiting its content Metafile
1576  // to its geometry definition(Point, Size), so use these directly
1577  const tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1578  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1579  }
1580  break;
1581 
1582  case MetaActionType::EPS:
1583  {
1584  MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1585  tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1586  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1587  }
1588  break;
1589 
1591  {
1592  MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1593  if( pAct->IsClipping() )
1594  aClipStack.back() = OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() );
1595  else
1596  aClipStack.back() = tools::Rectangle();
1597  }
1598  break;
1599 
1601  {
1602  MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1603  tools::Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1604  if( aClipStack.back().IsEmpty() )
1605  aClipStack.back() = aRect;
1606  else
1607  aClipStack.back().Intersection( aRect );
1608  }
1609  break;
1610 
1612  {
1614  tools::Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1615  if( aClipStack.back().IsEmpty() )
1616  aClipStack.back() = aRect;
1617  else
1618  aClipStack.back().Intersection( aRect );
1619  }
1620  break;
1621 
1622  case MetaActionType::BMP:
1623  {
1624  MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
1625  tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1626  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1627  }
1628  break;
1629 
1630  case MetaActionType::BMPEX:
1631  {
1632  MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
1633  tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) );
1634  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1635  }
1636  break;
1637 
1638  case MetaActionType::MASK:
1639  {
1640  MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
1641  tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1642  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1643  }
1644  break;
1645 
1647  {
1648  MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1649  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1650  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1651  }
1652  break;
1653 
1655  {
1656  MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1657  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1658  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1659  }
1660  break;
1661 
1663  {
1664  MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
1665  tools::Rectangle aRect( pAct->GetRect() );
1666  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1667  }
1668  break;
1669 
1671  {
1672  MetaTextRectAction* pAct = static_cast<MetaTextRectAction*>(pAction);
1673  tools::Rectangle aRect( pAct->GetRect() );
1674  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, nullptr );
1675  }
1676  break;
1677 
1679  {
1680  MetaMoveClipRegionAction* pAct = static_cast<MetaMoveClipRegionAction*>(pAction);
1681  if( ! aClipStack.back().IsEmpty() )
1682  {
1683  Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() );
1684  aDelta = OutputDevice::LogicToLogic( aDelta, aMapVDev->GetMapMode(), GetPrefMapMode() );
1685  aClipStack.back().Move( aDelta.Width(), aDelta.Width() );
1686  }
1687  }
1688  break;
1689 
1690  default:
1691  {
1692  pAction->Execute( aMapVDev.get() );
1693 
1694  if( nActionType == MetaActionType::PUSH )
1695  {
1696  MetaPushAction* pAct = static_cast<MetaPushAction*>(pAction);
1697  aPushFlagStack.push_back( pAct->GetFlags() );
1698  if( aPushFlagStack.back() & vcl::PushFlags::CLIPREGION )
1699  {
1700  tools::Rectangle aRect( aClipStack.back() );
1701  aClipStack.push_back( aRect );
1702  }
1703  }
1704  else if( nActionType == MetaActionType::POP )
1705  {
1706  // sanity check
1707  if( ! aPushFlagStack.empty() )
1708  {
1709  if( aPushFlagStack.back() & vcl::PushFlags::CLIPREGION )
1710  {
1711  if( aClipStack.size() > 1 )
1712  aClipStack.pop_back();
1713  }
1714  aPushFlagStack.pop_back();
1715  }
1716  }
1717  }
1718  break;
1719  }
1720  }
1721  return aBound;
1722 }
1723 
1724 Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
1725 {
1726  return Color( ColorAlpha, rColor.GetAlpha(),
1727  static_cast<const ImplColAdjustParam*>(pColParam)->pMapR[ rColor.GetRed() ],
1728  static_cast<const ImplColAdjustParam*>(pColParam)->pMapG[ rColor.GetGreen() ],
1729  static_cast<const ImplColAdjustParam*>(pColParam)->pMapB[ rColor.GetBlue() ] );
1730 
1731 }
1732 
1733 BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1734 {
1735  const ImplBmpAdjustParam* p = static_cast<const ImplBmpAdjustParam*>(pBmpParam);
1736  BitmapEx aRet( rBmpEx );
1737 
1738  aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
1739  p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
1740  p->fGamma, p->bInvert );
1741 
1742  return aRet;
1743 }
1744 
1745 Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
1746 {
1747  sal_uInt8 cLum = rColor.GetLuminance();
1748 
1749  if( MtfConversion::N1BitThreshold == static_cast<const ImplColConvertParam*>(pColParam)->eConversion )
1750  cLum = ( cLum < 128 ) ? 0 : 255;
1751 
1752  return Color( ColorTransparency, 255 - rColor.GetAlpha(), cLum, cLum, cLum );
1753 }
1754 
1755 BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1756 {
1757  BitmapEx aRet( rBmpEx );
1758 
1759  aRet.Convert( static_cast<const ImplBmpConvertParam*>(pBmpParam)->eConversion );
1760 
1761  return aRet;
1762 }
1763 
1764 Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam )
1765 {
1766  return static_cast<const ImplColMonoParam*>(pColParam)->aColor;
1767 }
1768 
1769 BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1770 {
1771  BitmapPalette aPal( 3 );
1772  aPal[ 0 ] = COL_BLACK;
1773  aPal[ 1 ] = COL_WHITE;
1774  aPal[ 2 ] = static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor;
1775 
1776  Bitmap aBmp(rBmpEx.GetSizePixel(), vcl::PixelFormat::N8_BPP, &aPal);
1777  aBmp.Erase( static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor );
1778 
1779  if( rBmpEx.IsAlpha() )
1780  return BitmapEx( aBmp, rBmpEx.GetAlpha() );
1781  else
1782  return BitmapEx( aBmp );
1783 }
1784 
1785 Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
1786 {
1787  const sal_uLong nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
1788 
1789  for( sal_uLong i = 0; i < static_cast<const ImplColReplaceParam*>(pColParam)->nCount; i++ )
1790  {
1791  if( ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinR[ i ] <= nR ) &&
1792  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxR[ i ] >= nR ) &&
1793  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinG[ i ] <= nG ) &&
1794  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxG[ i ] >= nG ) &&
1795  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinB[ i ] <= nB ) &&
1796  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxB[ i ] >= nB ) )
1797  {
1798  return static_cast<const ImplColReplaceParam*>(pColParam)->pDstCols[ i ];
1799  }
1800  }
1801 
1802  return rColor;
1803 }
1804 
1805 BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1806 {
1807  const ImplBmpReplaceParam* p = static_cast<const ImplBmpReplaceParam*>(pBmpParam);
1808  BitmapEx aRet( rBmpEx );
1809 
1810  aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount );
1811 
1812  return aRet;
1813 }
1814 
1815 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
1816  BmpExchangeFnc pFncBmp, const void* pBmpParam )
1817 {
1818  GDIMetaFile aMtf;
1819 
1820  aMtf.m_aPrefSize = m_aPrefSize;
1822  aMtf.m_bUseCanvas = m_bUseCanvas;
1823 
1824  for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
1825  {
1826  const MetaActionType nType = pAction->GetType();
1827 
1828  switch( nType )
1829  {
1830  case MetaActionType::PIXEL:
1831  {
1832  MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1833  aMtf.push_back( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ) );
1834  }
1835  break;
1836 
1838  {
1839  MetaLineColorAction* pAct = static_cast<MetaLineColorAction*>(pAction);
1840 
1841  if( pAct->IsSetting() )
1842  pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1843 
1844  aMtf.push_back( pAct );
1845  }
1846  break;
1847 
1849  {
1850  MetaFillColorAction* pAct = static_cast<MetaFillColorAction*>(pAction);
1851 
1852  if( pAct->IsSetting() )
1853  pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1854 
1855  aMtf.push_back( pAct );
1856  }
1857  break;
1858 
1860  {
1861  MetaTextColorAction* pAct = static_cast<MetaTextColorAction*>(pAction);
1862  aMtf.push_back( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ) );
1863  }
1864  break;
1865 
1867  {
1868  MetaTextFillColorAction* pAct = static_cast<MetaTextFillColorAction*>(pAction);
1869 
1870  if( pAct->IsSetting() )
1871  pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1872 
1873  aMtf.push_back( pAct );
1874  }
1875  break;
1876 
1878  {
1879  MetaTextLineColorAction* pAct = static_cast<MetaTextLineColorAction*>(pAction);
1880 
1881  if( pAct->IsSetting() )
1882  pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1883 
1884  aMtf.push_back( pAct );
1885  }
1886  break;
1887 
1889  {
1890  MetaOverlineColorAction* pAct = static_cast<MetaOverlineColorAction*>(pAction);
1891 
1892  if( pAct->IsSetting() )
1893  pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1894 
1895  aMtf.push_back( pAct );
1896  }
1897  break;
1898 
1899  case MetaActionType::FONT:
1900  {
1901  MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
1902  vcl::Font aFont( pAct->GetFont() );
1903 
1904  aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
1905  aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
1906  aMtf.push_back( new MetaFontAction( aFont ) );
1907  }
1908  break;
1909 
1911  {
1912  MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
1913  Wallpaper aWall( pAct->GetWallpaper() );
1914  const tools::Rectangle& rRect = pAct->GetRect();
1915 
1916  aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
1917 
1918  if( aWall.IsBitmap() )
1919  aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
1920 
1921  if( aWall.IsGradient() )
1922  {
1923  Gradient aGradient( aWall.GetGradient() );
1924 
1925  aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
1926  aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
1927  aWall.SetGradient( aGradient );
1928  }
1929 
1930  aMtf.push_back( new MetaWallpaperAction( rRect, aWall ) );
1931  }
1932  break;
1933 
1934  case MetaActionType::BMP:
1935  case MetaActionType::BMPEX:
1936  case MetaActionType::MASK:
1937  {
1938  OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
1939  }
1940  break;
1941 
1943  {
1944  MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1945  aMtf.push_back( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
1946  pFncBmp( BitmapEx(pAct->GetBitmap()), pBmpParam ).GetBitmap() ) );
1947  }
1948  break;
1949 
1951  {
1952  MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1953  aMtf.push_back( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1954  pAct->GetSrcPoint(), pAct->GetSrcSize(),
1955  pFncBmp( BitmapEx(pAct->GetBitmap()), pBmpParam ).GetBitmap() )
1956  );
1957  }
1958  break;
1959 
1961  {
1962  MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1963  aMtf.push_back( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
1964  pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
1965  );
1966  }
1967  break;
1968 
1970  {
1971  MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1972  aMtf.push_back( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1973  pAct->GetSrcPoint(), pAct->GetSrcSize(),
1974  pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
1975  );
1976  }
1977  break;
1978 
1980  {
1981  MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
1982  aMtf.push_back( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
1983  pAct->GetBitmap(),
1984  pFncCol( pAct->GetColor(), pColParam ) )
1985  );
1986  }
1987  break;
1988 
1990  {
1991  MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1992  aMtf.push_back( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1993  pAct->GetSrcPoint(), pAct->GetSrcSize(),
1994  pAct->GetBitmap(),
1995  pFncCol( pAct->GetColor(), pColParam ) )
1996  );
1997  }
1998  break;
1999 
2001  {
2002  MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
2003  Gradient aGradient( pAct->GetGradient() );
2004 
2005  aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2006  aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2007  aMtf.push_back( new MetaGradientAction( pAct->GetRect(), aGradient ) );
2008  }
2009  break;
2010 
2012  {
2013  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
2014  Gradient aGradient( pAct->GetGradient() );
2015 
2016  aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2017  aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2018  aMtf.push_back( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ) );
2019  }
2020  break;
2021 
2022  case MetaActionType::HATCH:
2023  {
2024  MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
2025  Hatch aHatch( pAct->GetHatch() );
2026 
2027  aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
2028  aMtf.push_back( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ) );
2029  }
2030  break;
2031 
2033  {
2034  MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
2035  GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
2036 
2037  aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2038  aMtf.push_back( new MetaFloatTransparentAction( aTransMtf,
2039  pAct->GetPoint(), pAct->GetSize(),
2040  pAct->GetGradient() )
2041  );
2042  }
2043  break;
2044 
2045  case MetaActionType::EPS:
2046  {
2047  MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
2048  GDIMetaFile aSubst( pAct->GetSubstitute() );
2049 
2050  aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2051  aMtf.push_back( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
2052  pAct->GetLink(), aSubst )
2053  );
2054  }
2055  break;
2056 
2057  default:
2058  {
2059  aMtf.push_back( pAction );
2060  }
2061  break;
2062  }
2063  }
2064 
2065  *this = aMtf;
2066 }
2067 
2068 void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
2069  short nChannelRPercent, short nChannelGPercent,
2070  short nChannelBPercent, double fGamma, bool bInvert, bool msoBrightness )
2071 {
2072  // nothing to do? => return quickly
2073  if( !(nLuminancePercent || nContrastPercent ||
2074  nChannelRPercent || nChannelGPercent || nChannelBPercent ||
2075  ( fGamma != 1.0 ) || bInvert) )
2076  return;
2077 
2078  double fM, fROff, fGOff, fBOff, fOff;
2079  ImplColAdjustParam aColParam;
2080  ImplBmpAdjustParam aBmpParam;
2081 
2082  aColParam.pMapR.reset(new sal_uInt8[ 256 ]);
2083  aColParam.pMapG.reset(new sal_uInt8[ 256 ]);
2084  aColParam.pMapB.reset(new sal_uInt8[ 256 ]);
2085 
2086  // calculate slope
2087  if( nContrastPercent >= 0 )
2088  fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0, 100 ) );
2089  else
2090  fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100, 0 ) ) / 128.0;
2091 
2092  if(!msoBrightness)
2093  // total offset = luminance offset + contrast offset
2094  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55 + 128.0 - fM * 128.0;
2095  else
2096  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55;
2097 
2098  // channel offset = channel offset + total offset
2099  fROff = nChannelRPercent * 2.55 + fOff;
2100  fGOff = nChannelGPercent * 2.55 + fOff;
2101  fBOff = nChannelBPercent * 2.55 + fOff;
2102 
2103  // calculate gamma value
2104  fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
2105  const bool bGamma = ( fGamma != 1.0 );
2106 
2107  // create mapping table
2108  for( tools::Long nX = 0; nX < 256; nX++ )
2109  {
2110  if(!msoBrightness)
2111  {
2112  aColParam.pMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fROff ), 0, 255 ));
2113  aColParam.pMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fGOff ), 0, 255 ));
2114  aColParam.pMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fBOff ), 0, 255 ));
2115  }
2116  else
2117  {
2118  aColParam.pMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0, 255 ));
2119  aColParam.pMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0, 255 ));
2120  aColParam.pMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0, 255 ));
2121  }
2122  if( bGamma )
2123  {
2124  aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
2125  aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
2126  aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
2127  }
2128 
2129  if( bInvert )
2130  {
2131  aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
2132  aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
2133  aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
2134  }
2135  }
2136 
2137  aBmpParam.nLuminancePercent = nLuminancePercent;
2138  aBmpParam.nContrastPercent = nContrastPercent;
2139  aBmpParam.nChannelRPercent = nChannelRPercent;
2140  aBmpParam.nChannelGPercent = nChannelGPercent;
2141  aBmpParam.nChannelBPercent = nChannelBPercent;
2142  aBmpParam.fGamma = fGamma;
2143  aBmpParam.bInvert = bInvert;
2144 
2145  // do color adjustment
2146  ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
2147 }
2148 
2150 {
2151  ImplColConvertParam aColParam;
2152  ImplBmpConvertParam aBmpParam;
2153 
2154  aColParam.eConversion = eConversion;
2155  aBmpParam.eConversion = ( MtfConversion::N1BitThreshold == eConversion ) ? BmpConversion::N1BitThreshold : BmpConversion::N8BitGreys;
2156 
2157  ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
2158 }
2159 
2160 void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount )
2161 {
2162  ImplColReplaceParam aColParam;
2163  ImplBmpReplaceParam aBmpParam;
2164 
2165  aColParam.pMinR.reset(new sal_uLong[ nColorCount ]);
2166  aColParam.pMaxR.reset(new sal_uLong[ nColorCount ]);
2167  aColParam.pMinG.reset(new sal_uLong[ nColorCount ]);
2168  aColParam.pMaxG.reset(new sal_uLong[ nColorCount ]);
2169  aColParam.pMinB.reset(new sal_uLong[ nColorCount ]);
2170  aColParam.pMaxB.reset(new sal_uLong[ nColorCount ]);
2171 
2172  for( sal_uLong i = 0; i < nColorCount; i++ )
2173  {
2174  tools::Long nVal;
2175 
2176  nVal = pSearchColors[ i ].GetRed();
2177  aColParam.pMinR[ i ] = static_cast<sal_uLong>(std::max( nVal, tools::Long(0) ));
2178  aColParam.pMaxR[ i ] = static_cast<sal_uLong>(std::min( nVal, tools::Long(255) ));
2179 
2180  nVal = pSearchColors[ i ].GetGreen();
2181  aColParam.pMinG[ i ] = static_cast<sal_uLong>(std::max( nVal, tools::Long(0) ));
2182  aColParam.pMaxG[ i ] = static_cast<sal_uLong>(std::min( nVal, tools::Long(255) ));
2183 
2184  nVal = pSearchColors[ i ].GetBlue();
2185  aColParam.pMinB[ i ] = static_cast<sal_uLong>(std::max( nVal, tools::Long(0) ));
2186  aColParam.pMaxB[ i ] = static_cast<sal_uLong>(std::min( nVal, tools::Long(255) ));
2187  }
2188 
2189  aColParam.pDstCols = pReplaceColors;
2190  aColParam.nCount = nColorCount;
2191 
2192  aBmpParam.pSrcCols = pSearchColors;
2193  aBmpParam.pDstCols = pReplaceColors;
2194  aBmpParam.nCount = nColorCount;
2195 
2196  ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
2197 };
2198 
2200 {
2201  GDIMetaFile aRet( *this );
2202 
2203  ImplColMonoParam aColParam;
2204  ImplBmpMonoParam aBmpParam;
2205 
2206  aColParam.aColor = rColor;
2207  aBmpParam.aColor = rColor;
2208 
2209  aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
2210 
2211  return aRet;
2212 }
2213 
2215 {
2216  sal_uLong nSizeBytes = 0;
2217 
2218  for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; ++i )
2219  {
2220  MetaAction* pAction = GetAction( i );
2221 
2222  // default action size is set to 32 (=> not the exact value)
2223  nSizeBytes += 32;
2224 
2225  // add sizes for large action content
2226  switch( pAction->GetType() )
2227  {
2228  case MetaActionType::BMP: nSizeBytes += static_cast<MetaBmpAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2229  case MetaActionType::BMPSCALE: nSizeBytes += static_cast<MetaBmpScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2230  case MetaActionType::BMPSCALEPART: nSizeBytes += static_cast<MetaBmpScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2231 
2232  case MetaActionType::BMPEX: nSizeBytes += static_cast<MetaBmpExAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2233  case MetaActionType::BMPEXSCALE: nSizeBytes += static_cast<MetaBmpExScaleAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2234  case MetaActionType::BMPEXSCALEPART: nSizeBytes += static_cast<MetaBmpExScalePartAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2235 
2236  case MetaActionType::MASK: nSizeBytes += static_cast<MetaMaskAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2237  case MetaActionType::MASKSCALE: nSizeBytes += static_cast<MetaMaskScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2238  case MetaActionType::MASKSCALEPART: nSizeBytes += static_cast<MetaMaskScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2239 
2240  case MetaActionType::POLYLINE: nSizeBytes += static_cast<MetaPolyLineAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2241  case MetaActionType::POLYGON: nSizeBytes += static_cast<MetaPolygonAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2243  {
2244  const tools::PolyPolygon& rPolyPoly = static_cast<MetaPolyPolygonAction*>( pAction )->GetPolyPolygon();
2245 
2246  for( sal_uInt16 n = 0; n < rPolyPoly.Count(); ++n )
2247  nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) );
2248  }
2249  break;
2250 
2251  case MetaActionType::TEXT: nSizeBytes += static_cast<MetaTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2252  case MetaActionType::STRETCHTEXT: nSizeBytes += static_cast<MetaStretchTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2253  case MetaActionType::TEXTRECT: nSizeBytes += static_cast<MetaTextRectAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2255  {
2256  MetaTextArrayAction* pTextArrayAction = static_cast<MetaTextArrayAction*>(pAction);
2257 
2258  nSizeBytes += ( pTextArrayAction->GetText().getLength() * sizeof( sal_Unicode ) );
2259 
2260  if( pTextArrayAction->GetDXArray() )
2261  nSizeBytes += ( pTextArrayAction->GetLen() << 2 );
2262  }
2263  break;
2264  default: break;
2265  }
2266  }
2267 
2268  return nSizeBytes;
2269 }
2270 
2271 bool GDIMetaFile::CreateThumbnail(BitmapEx& rBitmapEx, BmpConversion eColorConversion, BmpScaleFlag nScaleFlag) const
2272 {
2273  // initialization seems to be complicated but is used to avoid rounding errors
2275  // set Enable to tease the rendering down the code paths which use B2DPolygon and
2276  // avoid integer overflows on scaling tools::Polygon, e.g. moz1545040-1.svg
2277  // note: this is similar to DocumentToGraphicRenderer::renderToGraphic
2278  aVDev->SetAntialiasing(AntialiasingFlags::Enable | aVDev->GetAntialiasing());
2279  const Point aNullPt;
2280  const Point aTLPix( aVDev->LogicToPixel( aNullPt, GetPrefMapMode() ) );
2281  const Point aBRPix( aVDev->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2282  Size aDrawSize( aVDev->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2283  Size aSizePix( std::abs( aBRPix.X() - aTLPix.X() ) + 1, std::abs( aBRPix.Y() - aTLPix.Y() ) + 1 );
2284  sal_uInt32 nMaximumExtent = 256;
2285 
2286  if (!rBitmapEx.IsEmpty())
2287  rBitmapEx.SetEmpty();
2288 
2289  // determine size that has the same aspect ratio as image size and
2290  // fits into the rectangle determined by nMaximumExtent
2291  if ( aSizePix.Width() && aSizePix.Height()
2292  && ( sal::static_int_cast< tools::ULong >(aSizePix.Width()) >
2293  nMaximumExtent ||
2294  sal::static_int_cast< tools::ULong >(aSizePix.Height()) >
2295  nMaximumExtent ) )
2296  {
2297  const Size aOldSizePix( aSizePix );
2298  double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
2299 
2300  if ( fWH <= 1.0 )
2301  {
2302  aSizePix.setWidth( FRound( nMaximumExtent * fWH ) );
2303  aSizePix.setHeight( nMaximumExtent );
2304  }
2305  else
2306  {
2307  aSizePix.setWidth( nMaximumExtent );
2308  aSizePix.setHeight( FRound( nMaximumExtent / fWH ) );
2309  }
2310 
2311  aDrawSize.setWidth( FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() ) );
2312  aDrawSize.setHeight( FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() ) );
2313  }
2314 
2315  // draw image(s) into VDev and get resulting image
2316  // do it 4x larger to be able to scale it down & get beautiful antialias
2317  Size aAntialiasSize(aSizePix.Width() * 4, aSizePix.Height() * 4);
2318  if (aVDev->SetOutputSizePixel(aAntialiasSize))
2319  {
2320  // antialias: provide 4x larger size, and then scale down the result
2321  Size aAntialias(aDrawSize.Width() * 4, aDrawSize.Height() * 4);
2322 
2323  // draw metafile into VDev
2324  const_cast<GDIMetaFile *>(this)->WindStart();
2325  const_cast<GDIMetaFile *>(this)->Play(*aVDev, Point(), aAntialias);
2326 
2327  // get paint bitmap
2328  BitmapEx aBitmap( aVDev->GetBitmapEx( aNullPt, aVDev->GetOutputSizePixel() ) );
2329 
2330  // scale down the image to the desired size - use the input scaler for the scaling operation
2331  aBitmap.Scale(aDrawSize, nScaleFlag);
2332 
2333  // convert to desired bitmap color format
2334  Size aSize(aBitmap.GetSizePixel());
2335  if (aSize.Width() && aSize.Height())
2336  aBitmap.Convert(eColorConversion);
2337 
2338  rBitmapEx = aBitmap;
2339  }
2340 
2341  return !rBitmapEx.IsEmpty();
2342 }
2343 
2344 void GDIMetaFile::UseCanvas( bool _bUseCanvas )
2345 {
2346  m_bUseCanvas = _bUseCanvas;
2347 }
2348 
2349 void GDIMetaFile::dumpAsXml(const char* pFileName) const
2350 {
2351  SvFileStream aStream(pFileName ? OUString::fromUtf8(pFileName) : OUString("file:///tmp/metafile.xml"),
2352  StreamMode::STD_READWRITE | StreamMode::TRUNC);
2353  assert(aStream.good());
2354  MetafileXmlDump aDumper;
2355  aDumper.dump(*this, aStream);
2356 }
2357 
2358 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt16 Count() const
BitmapEx GetBitmapEx(BitmapEx const &rBitmapEx, DrawModeFlags nDrawMode)
Definition: drawmode.cxx:224
static SAL_DLLPRIVATE BitmapEx ImplBmpAdjustFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1733
const Fraction & GetScaleX() const
Definition: mapmod.cxx:142
SAL_DLLPRIVATE bool ImplPlayWithRenderer(OutputDevice &rOut, const Point &rPos, Size rLogicDestSize)
Definition: gdimtf.cxx:387
const Gradient & GetGradient() const
Definition: metaact.hxx:1591
void Mirror(BmpMirrorFlags nMirrorFlags)
Definition: gdimtf.cxx:594
virtual void Execute(OutputDevice *pOut)
Definition: metaact.cxx:97
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:184
void dump(const GDIMetaFile &rMetaFile, SvStream &rStream)
The actual result that will be used for testing.
Definition: mtfxmldump.cxx:585
virtual void Flush()
Definition: outdev.hxx:425
void SetDigitLanguage(LanguageType)
Definition: text.cxx:68
void SetPixelOffset(const Size &rOffset)
Set an offset in pixel.
Definition: map.cxx:1806
GDIMetaFile * m_pPrev
Definition: gdimtf.hxx:63
const Size & GetDestSize() const
Definition: metaact.hxx:975
Definition: hatch.hxx:46
VclPtr< OutputDevice > m_pOutDev
Definition: gdimtf.hxx:65
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:406
bool IsClipping() const
Definition: metaact.hxx:1131
const Color & GetColor() const
Definition: metaact.hxx:1374
const Bitmap & GetBitmap() const
Definition: metaact.hxx:932
sal_Int32 GetLen() const
Definition: metaact.hxx:495
MetaAction * GetCurAction() const
Definition: gdimtf.hxx:170
sal_uInt8 GetAlpha() const
const Point & GetPoint() const
Definition: metaact.hxx:714
sal_uInt8 GetRed() const
void ReplaceColors(const Color *pSearchColors, const Color *rReplaceColors, sal_uLong nColorCount)
Definition: gdimtf.cxx:2160
const Point & GetEndPoint() const
Definition: metaact.hxx:340
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
const GDIMetaFile & GetGDIMetaFile() const
Definition: metaact.hxx:1588
void setWidth(tools::Long nWidth)
tools::Long GetVertMove() const
Definition: metaact.hxx:1214
void Replace(const Color &rSearchColor, const Color &rReplaceColor)
Replace all pixel having the search color with the specified color.
Definition: BitmapEx.cxx:479
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:491
sal_uInt32 GetVertRound() const
Definition: metaact.hxx:245
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1040
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1564
GDIMetaFile & operator=(const GDIMetaFile &rMtf)
Definition: gdimtf.cxx:211
constexpr tools::Long Left() const
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
Definition: bitmapex.cxx:33
SvStream & WriteSvtGraphicStroke(SvStream &rOStm, const SvtGraphicStroke &rClass)
bool IsSetting() const
Definition: metaact.hxx:1322
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:243
const MapMode & GetPrefMapMode() const
Definition: gdimtf.hxx:175
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: BitmapEx.cxx:296
sal_uIntPtr sal_uLong
MtfConversion
Definition: gdimtf.hxx:45
long Long
constexpr::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
void dumpAsXml(const char *pFileName=nullptr) const
Dumps the meta actions as XML in metafile.xml.
Definition: gdimtf.cxx:2349
MetaAction * NextAction()
Definition: gdimtf.cxx:195
#define F_PI1800
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
Definition: stack.cxx:33
std::enable_if< std::is_signed< T >::value||std::is_floating_point< T >::value, long >::type MinMax(T nVal, tools::Long nMin, tools::Long nMax)
sal_uInt8 GetLuminance() const
const Point & GetPoint() const
Definition: metaact.hxx:1628
virtual bool IsTransparent() const
#i10613# Extracted from Printer::GetPreparedMetaFile.
Definition: metaact.hxx:97
sal_Int64 n
Encapsulates geometry and associated attributes of a graphical 'pen stroke'.
void SetPrefSize(const Size &rSize)
Definition: gdimtf.hxx:173
const Point & GetPoint() const
Definition: metaact.hxx:1589
void Clear()
Definition: gdimtf.cxx:270
static SAL_DLLPRIVATE Color ImplColMonoFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1764
const Size & GetSize() const
Definition: metaact.hxx:715
const MapMode & GetMapMode() const
Definition: outdev.hxx:1532
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1553
void Move(tools::Long nHorzMove, tools::Long nVertMove)
void Rotate(Degree10 nAngle10)
Definition: gdimtf.cxx:818
const Point & GetEndPoint() const
Definition: metaact.hxx:183
GDIMetaFile * GetConnectMetaFile() const
Definition: outdev.hxx:284
const OUString & GetText() const
Definition: metaact.hxx:571
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:796
tools::Rectangle GetBoundRect() const
Definition: region.cxx:1217
static SAL_DLLPRIVATE BitmapEx ImplBmpReplaceFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1805
void Clip(const tools::Rectangle &)
Definition: gdimtf.cxx:733
const Point & GetPoint() const
Definition: metaact.hxx:934
bool Convert(BmpConversion eConversion)
Convert bitmap format.
Definition: BitmapEx.cxx:374
SvStream & ReadSvtGraphicFill(SvStream &rIStm, SvtGraphicFill &rClass)
const sal_uInt8 * GetData() const
Definition: metaact.hxx:1692
constexpr tools::Long Width() const
HashMap_OWString_Interface aMap
sal_uInt16 sal_Unicode
bool IsAlpha() const
Definition: BitmapEx.cxx:193
static SAL_DLLPRIVATE tools::Polygon ImplGetRotatedPolygon(const tools::Polygon &rPoly, const Point &rRotatePt, const Size &rOffset, double fSin, double fCos)
Definition: gdimtf.cxx:774
const Point & GetPoint() const
Definition: metaact.hxx:820
void Record(OutputDevice *pOutDev)
Definition: gdimtf.cxx:311
void push_back(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:589
const OUString & GetText() const
Definition: metaact.hxx:493
const Fraction & GetScaleY() const
Definition: mapmod.cxx:144
unsigned long ULong
vcl::PushFlags GetFlags() const
Definition: metaact.hxx:1485
geometry::IntegerSize2D integerSize2DFromSize(const Size &rSize)
const Bitmap & GetBitmap() const
Definition: metaact.hxx:681
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:2068
int nCount
void SetLayoutMode(vcl::text::ComplexTextLayoutFlags nTextLayoutMode)
Definition: text.cxx:57
const vcl::Region & GetRegion() const
Definition: metaact.hxx:1130
bool CreateThumbnail(BitmapEx &rBitmapEx, BmpConversion nColorConversion=BmpConversion::N24Bit, BmpScaleFlag nScaleFlag=BmpScaleFlag::BestQuality) const
Creates an antialiased thumbnail.
Definition: gdimtf.cxx:2271
void SetStartColor(const Color &rColor)
#define GAMMA(_def_cVal, _def_InvGamma)
const Gradient & GetGradient() const
Definition: metaact.hxx:1011
constexpr tools::Long GetWidth() const
void Pop()
Definition: stack.cxx:92
const Point & GetStartPoint() const
Definition: metaact.hxx:305
const Color & GetColor() const
Definition: metaact.hxx:1240
MetaActionType
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:1159
void Play(GDIMetaFile &rMtf)
Definition: gdimtf.cxx:322
BitmapEx(* BmpExchangeFnc)(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.hxx:53
const Size & GetSize() const
Definition: metaact.hxx:821
GDIMetaFile GetMonochromeMtf(const Color &rCol) const
Definition: gdimtf.cxx:2199
sal_uInt8 GetBlue() const
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:274
FontLineStyle GetUnderline() const
Definition: metaact.hxx:648
Size m_aPrefSize
Definition: gdimtf.hxx:62
const tools::Polygon & GetPolygon() const
Definition: metaact.hxx:434
tools::PolyPolygon GetAsPolyPolygon() const
Definition: region.cxx:1264
sal_uInt32 GetHorzRound() const
Definition: metaact.hxx:244
constexpr bool IsEmpty() const
void Rotate(const Point &rCenter, double fSin, double fCos)
void setPath(const tools::PolyPolygon &rPath)
Set path to fill.
const vcl::Region & GetRegion() const
Definition: metaact.hxx:1186
static SAL_DLLPRIVATE tools::PolyPolygon ImplGetRotatedPolyPolygon(const tools::PolyPolygon &rPoly, const Point &rRotatePt, const Size &rOffset, double fSin, double fCos)
Definition: gdimtf.cxx:785
const Size & GetSrcSize() const
Definition: metaact.hxx:977
bool m_bPause
Definition: gdimtf.hxx:66
static SAL_DLLPRIVATE Point ImplGetRotatedPoint(const Point &rPt, const Point &rRotatePt, const Size &rOffset, double fSin, double fCos)
Definition: gdimtf.cxx:764
void SetEmpty()
Definition: BitmapEx.cxx:182
static vcl::Window * GetFirstTopLevelWindow()
Get the first top-level window of the application.
Definition: svapp.cxx:1074
bool IsEmpty() const
Definition: BitmapEx.cxx:177
bool GetUseCanvas() const
Definition: gdimtf.hxx:187
bool Create(const css::uno::Reference< css::rendering::XBitmapCanvas > &xBitmapCanvas, const Size &rSize)
populate from a canvas implementation
Definition: BitmapEx.cxx:619
UNDERLYING_TYPE get() const
void SetConnectMetaFile(GDIMetaFile *pMtf)
Definition: outdev.cxx:211
void SetScaleX(const Fraction &rScaleX)
Definition: mapmod.cxx:110
#define TOOLS_WARN_EXCEPTION(area, stream)
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:213
static SAL_DLLPRIVATE BitmapEx ImplBmpConvertFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1755
const Size & GetPrefSize() const
Definition: gdimtf.hxx:172
~GDIMetaFile()
Definition: gdimtf.cxx:149
tools::Long GetWidth() const
Definition: metaact.hxx:646
const tools::Polygon & GetPolygon() const
Definition: metaact.hxx:405
GDIMetaFile * m_pNext
Definition: gdimtf.hxx:64
int i
::std::vector< rtl::Reference< MetaAction > > m_aList
Definition: gdimtf.hxx:58
uno_Any a
sal_uInt16 GetTransparence() const
Definition: metaact.hxx:1554
virtual void Scale(double fScaleX, double fScaleY)
Definition: metaact.cxx:110
const Size & GetSize() const
Definition: metaact.hxx:935
void SetAngle(Degree10 nAngle10)
Definition: gdi/hatch.cxx:74
const Point & GetPoint() const
Definition: metaact.hxx:492
SAL_DLLPRIVATE void ImplExchangeColors(ColorExchangeFnc pFncCol, const void *pColParam, BmpExchangeFnc pFncBmp, const void *pBmpParam)
Definition: gdimtf.cxx:1815
void Convert(MtfConversion eConversion)
Definition: gdimtf.cxx:2149
bool IsSetting() const
Definition: metaact.hxx:1241
tools::Long FRound(double fVal)
#define LANGUAGE_SYSTEM
void SetOrientation(Degree10 nLineOrientation)
Definition: font/font.cxx:202
Color(* ColorExchangeFnc)(const Color &rColor, const void *pColParam)
Definition: gdimtf.hxx:52
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:786
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:1010
const Color & GetColor() const
Definition: metaact.hxx:1319
Size GetOutputSize() const
Definition: outdev.hxx:323
const Size & GetSize() const
Definition: metaact.hxx:1590
void SetOrigin(const Point &rOrigin)
Definition: mapmod.cxx:104
sal_uInt32 GetWidth() const
Definition: metaact.hxx:572
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:168
float u
void Move(tools::Long nHorzMove, tools::Long nVertMove)
const Point & GetEndPoint() const
Definition: metaact.hxx:306
void SetScaleY(const Fraction &rScaleY)
Definition: mapmod.cxx:117
void UseCanvas(bool _bUseCanvas)
Definition: gdimtf.cxx:2344
void Intersect(const tools::Rectangle &rRegion)
Definition: region.cxx:581
void getPath(tools::Polygon &) const
Query path to stroke.
const Point & GetStartPoint() const
Definition: metaact.hxx:373
sal_Int32 GetLen() const
Definition: metaact.hxx:574
void Move(tools::Long nX, tools::Long nY)
Definition: gdimtf.cxx:630
constexpr void SetRight(tools::Long v)
const Point & GetPoint() const
Definition: metaact.hxx:787
bool m_bRecord
Definition: gdimtf.hxx:67
const Bitmap & GetBitmap() const
Definition: metaact.hxx:897
Size GetOutputSizePixel() const
Definition: outdev.hxx:310
ColorTransparency
MapUnit GetMapUnit() const
Definition: mapmod.cxx:138
virtual void SetMetafileMapMode(const MapMode &rNewMapMode, bool bIsRecord)
Definition: map.cxx:710
void WindStart()
Definition: gdimtf.cxx:549
bool HasTransparentActions() const
Definition: gdimtf.cxx:154
virtual void Move(tools::Long nHorzMove, tools::Long nVertMove)
Definition: metaact.cxx:106
bool Rotate(Degree10 nAngle10, const Color &rFillColor)
Rotate bitmap by the specified angle.
Definition: BitmapEx.cxx:316
const Bitmap & GetBitmap() const
Definition: metaact.hxx:972
const Point & GetPoint() const
Definition: metaact.hxx:899
static vcl::Window * GetActiveTopWindow()
Get the "active" top window.
Definition: svapp.cxx:1118
static SAL_DLLPRIVATE Color ImplColAdjustFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1724
FontStrikeout GetStrikeout() const
Definition: metaact.hxx:647
tools::Rectangle GetBoundRect(OutputDevice &i_rReference, tools::Rectangle *pHairline=nullptr) const
Definition: gdimtf.cxx:1303
#define Y
const Size & GetSize() const
Definition: metaact.hxx:1629
const Bitmap & GetBitmap() const
Definition: metaact.hxx:713
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:304
constexpr Point Center() const
void SetColor(const Color &)
Definition: font/font.cxx:90
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:372
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1109
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:878
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1070
SvStream & WriteSvtGraphicFill(SvStream &rOStm, const SvtGraphicFill &rClass)
const GfxLink & GetLink() const
Definition: metaact.hxx:1626
const Point & GetPoint() const
Definition: metaact.hxx:570
bool IsSetting() const
Definition: metaact.hxx:1377
bool IsSetting() const
Definition: metaact.hxx:1268
sal_uInt8 GetGreen() const
bool IsSetting() const
Definition: metaact.hxx:1350
const Color & GetColor() const
Definition: metaact.hxx:1294
void Stop()
Definition: gdimtf.cxx:536
const Color & GetColor() const
Definition: metaact.hxx:933
MapMode m_aPrefMapMode
Definition: gdimtf.hxx:61
const Point & GetStartPoint() const
Definition: metaact.hxx:182
sal_uInt32 GetDataSize() const
Definition: metaact.hxx:1691
bool operator==(const GDIMetaFile &rMtf) const
Definition: gdimtf.cxx:244
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:819
void Pause(bool bPause)
Definition: gdimtf.cxx:517
bool IsSetting() const
Definition: metaact.hxx:1660
const Point & GetStartPoint() const
Definition: metaact.hxx:339
AlphaMask GetAlpha() const
Definition: BitmapEx.cxx:215
SAL_WARN_UNUSED_RESULT Size GetPixelOffset() const
Get the offset in pixel.
Definition: outdev.hxx:1576
const Point & GetPoint() const
Definition: metaact.hxx:123
const Color & GetColor() const
Definition: metaact.hxx:973
tools::Rectangle & Union(const tools::Rectangle &rRect)
constexpr tools::Long Height() const
unsigned char sal_uInt8
void ReplaceAction(rtl::Reference< MetaAction > pAction, size_t nAction)
Definition: gdimtf.cxx:200
const Point & GetStartPoint() const
Definition: metaact.hxx:645
static SAL_DLLPRIVATE Color ImplColReplaceFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1785
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:562
MetaAction * GetAction(size_t nAction) const
Definition: gdimtf.cxx:184
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_WHITE
#define SAL_INFO(area, stream)
const Gradient & GetGradient() const
Definition: metaact.hxx:1041
const Point & GetPoint() const
Definition: metaact.hxx:151
const Point & GetPoint() const
Definition: metaact.hxx:682
bool m_bUseCanvas
Definition: gdimtf.hxx:68
void Linker(OutputDevice *pOut, bool bLink)
Definition: gdimtf.cxx:278
const Point & GetDestPoint() const
Definition: metaact.hxx:974
sal_Int64 GetSizeBytes() const
Definition: BitmapEx.cxx:220
void Scale(double fScaleX, double fScaleY)
Definition: gdimtf.cxx:707
static SAL_DLLPRIVATE BitmapEx ImplBmpMonoFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1769
bool HasPolyPolygonOrB2DPolyPolygon() const
Definition: region.hxx:107
void * p
Reference< XComponentContext > getProcessComponentContext()
size_t GetActionSize() const
Definition: gdimtf.cxx:179
QPRO_FUNC_TYPE nType
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
MetaActionType GetType() const
Definition: metaact.hxx:93
const Color & GetColor() const
Definition: metaact.hxx:1347
void setPath(const tools::Polygon &)
Set path to stroke.
const Point & GetEndPoint() const
Definition: metaact.hxx:374
const Hatch & GetHatch() const
Definition: metaact.hxx:1071
const Point & GetSrcPoint() const
Definition: metaact.hxx:976
FontLineStyle GetOverline() const
Definition: metaact.hxx:649
bool good() const
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
Definition: bitmappaint.cxx:34
void setHeight(tools::Long nHeight)
const Color & GetColor() const
Definition: metaact.hxx:124
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:338
MetaAction * FirstAction()
Definition: gdimtf.cxx:189
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
tools::Rectangle GetBoundRect() const
const Point & GetRefPoint() const
Definition: metaact.hxx:1657
const OString & GetComment() const
Definition: metaact.hxx:1689
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:1278
size_t m_nCurrentActionElement
Definition: gdimtf.hxx:59
virtual size_t GetSyncCount() const
Definition: outdev.hxx:331
void getPath(tools::PolyPolygon &) const
Query path to fill.
const Size & GetSizePixel() const
Definition: bitmapex.hxx:73
const Color & GetColor() const
Definition: metaact.hxx:1267
const GDIMetaFile & GetSubstitute() const
Definition: metaact.hxx:1627
void SetColor(const Color &rColor)
Definition: gdi/hatch.cxx:64
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: BitmapEx.cxx:354
virtual vcl::Window * GetOwnerWindow() const
Get the vcl::Window that this OutputDevice belongs to, if any.
Definition: outdev.hxx:1881
const vcl::Font & GetFont() const
Definition: metaact.hxx:1460
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:608
aStr
sal_Int32 GetIndex() const
Definition: metaact.hxx:573
sal_Int32 GetIndex() const
Definition: metaact.hxx:494
static SAL_DLLPRIVATE Color ImplColConvertFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1745
tools::Long GetHorzMove() const
Definition: metaact.hxx:1213
void WindPrev()
Definition: gdimtf.cxx:555
constexpr tools::Long GetHeight() const
ColorAlpha
BmpMirrorFlags
sal_uLong GetSizeBytes() const
Definition: gdimtf.cxx:2214