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() <= 0 || aDestSize.Height() <= 0)
463  return;
464 
465  if (aDestSize.Width() > std::numeric_limits<sal_Int32>::max() ||
466  aDestSize.Height() > std::numeric_limits<sal_Int32>::max())
467  return;
468 
469  GDIMetaFile* pMtf = rOut.GetConnectMetaFile();
470 
471  if (ImplPlayWithRenderer(rOut, rPos, rSize))
472  return;
473 
474  Size aTmpPrefSize(rOut.LogicToPixel(GetPrefSize(), aDrawMap));
475 
476  if( !aTmpPrefSize.Width() )
477  aTmpPrefSize.setWidth( aDestSize.Width() );
478 
479  if( !aTmpPrefSize.Height() )
480  aTmpPrefSize.setHeight( aDestSize.Height() );
481 
482  Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
483  Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
484 
485  aScaleX *= aDrawMap.GetScaleX();
486  aScaleY *= aDrawMap.GetScaleY();
487  // try reducing inaccurary first and abandon if the scaling
488  // still cannot be achieved
489  if (TooLargeScaleForMapMode(aScaleX, rOut.GetDPIX()))
490  aScaleX.ReduceInaccurate(10);
491  if (TooLargeScaleForMapMode(aScaleY, rOut.GetDPIY()))
492  aScaleY.ReduceInaccurate(10);
493  if (TooLargeScaleForMapMode(aScaleX, rOut.GetDPIX()) ||
494  TooLargeScaleForMapMode(aScaleY, rOut.GetDPIY()))
495  {
496  SAL_WARN("vcl", "GDIMetaFile Scaling is too high");
497  return;
498  }
499 
500  aDrawMap.SetScaleX(aScaleX);
501  aDrawMap.SetScaleY(aScaleY);
502 
503  // #i47260# Convert logical output position to offset within
504  // the metafile's mapmode. Therefore, disable pixel offset on
505  // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
506  // different mapmode (the one currently set on rOut, that is)
507  // - thus, aDrawMap's origin would generally be wrong. And
508  // even _if_ aDrawMap is similar to pOutDev's current mapmode,
509  // it's _still_ undesirable to have pixel offset unequal zero,
510  // because one would still get round-off errors (the
511  // round-trip error for LogicToPixel( PixelToLogic() ) was the
512  // reason for having pixel offset in the first place).
513  const Size& rOldOffset(rOut.GetPixelOffset());
514  const Size aEmptySize;
515  rOut.SetPixelOffset(aEmptySize);
516  aDrawMap.SetOrigin(rOut.PixelToLogic(rOut.LogicToPixel(rPos), aDrawMap));
517  rOut.SetPixelOffset(rOldOffset);
518 
519  rOut.Push();
520 
521  bool bIsRecord = (pMtf && pMtf->IsRecord());
522  rOut.SetMetafileMapMode(aDrawMap, bIsRecord);
523 
524  // #i23407# Set backwards-compatible text language and layout mode
525  // This is necessary, since old metafiles don't even know of these
526  // recent add-ons. Newer metafiles must of course explicitly set
527  // those states.
530 
531  Play(rOut);
532 
533  rOut.Pop();
534 }
535 
536 void GDIMetaFile::Pause( bool _bPause )
537 {
538  if( !m_bRecord )
539  return;
540 
541  if( _bPause )
542  {
543  if( !m_bPause )
544  Linker( m_pOutDev, false );
545  }
546  else
547  {
548  if( m_bPause )
549  Linker( m_pOutDev, true );
550  }
551 
552  m_bPause = _bPause;
553 }
554 
556 {
557  if( m_bRecord )
558  {
559  m_bRecord = false;
560 
561  if( !m_bPause )
562  Linker( m_pOutDev, false );
563  else
564  m_bPause = false;
565  }
566 }
567 
569 {
570  if( !m_bRecord )
572 }
573 
575 {
576  if( !m_bRecord )
577  if ( m_nCurrentActionElement > 0 )
579 }
580 
582 {
583  m_aList.push_back( pAction );
584 
585  if( m_pPrev )
586  {
587  m_pPrev->AddAction( pAction );
588  }
589 }
590 
591 void GDIMetaFile::AddAction(const rtl::Reference<MetaAction>& pAction, size_t nPos)
592 {
593  if ( nPos < m_aList.size() )
594  {
595  m_aList.insert( m_aList.begin() + nPos, pAction );
596  }
597  else
598  {
599  m_aList.push_back( pAction );
600  }
601 
602  if( m_pPrev )
603  {
604  m_pPrev->AddAction( pAction, nPos );
605  }
606 }
607 
609 {
610  m_aList.push_back( pAction );
611 }
612 
614 {
615  const Size aOldPrefSize( GetPrefSize() );
616  tools::Long nMoveX, nMoveY;
617  double fScaleX, fScaleY;
618 
619  if( nMirrorFlags & BmpMirrorFlags::Horizontal )
620  {
621  nMoveX = std::abs( aOldPrefSize.Width() ) - 1;
622  fScaleX = -1.0;
623  }
624  else
625  {
626  nMoveX = 0;
627  fScaleX = 1.0;
628  }
629 
630  if( nMirrorFlags & BmpMirrorFlags::Vertical )
631  {
632  nMoveY = std::abs( aOldPrefSize.Height() ) - 1;
633  fScaleY = -1.0;
634  }
635  else
636  {
637  nMoveY = 0;
638  fScaleY = 1.0;
639  }
640 
641  if( ( fScaleX != 1.0 ) || ( fScaleY != 1.0 ) )
642  {
643  Scale( fScaleX, fScaleY );
644  Move( nMoveX, nMoveY );
645  SetPrefSize( aOldPrefSize );
646  }
647 }
648 
650 {
651  const Size aBaseOffset( nX, nY );
652  Size aOffset( aBaseOffset );
654 
655  aMapVDev->EnableOutput( false );
656  aMapVDev->SetMapMode( GetPrefMapMode() );
657 
658  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
659  {
660  const MetaActionType nType = pAct->GetType();
661  MetaAction* pModAct;
662 
663  if( pAct->GetRefCount() > 1 )
664  {
665  m_aList[ m_nCurrentActionElement ] = pAct->Clone();
666  pModAct = m_aList[ m_nCurrentActionElement ].get();
667  }
668  else
669  pModAct = pAct;
670 
671  if( ( MetaActionType::MAPMODE == nType ) ||
672  ( MetaActionType::PUSH == nType ) ||
673  ( MetaActionType::POP == nType ) )
674  {
675  pModAct->Execute( aMapVDev.get() );
676  aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
677  }
678 
679  pModAct->Move( aOffset.Width(), aOffset.Height() );
680  }
681 }
682 
684 {
685  const Size aBaseOffset( nX, nY );
686  Size aOffset( aBaseOffset );
688 
689  aMapVDev->EnableOutput( false );
690  aMapVDev->SetReferenceDevice( nDPIX, nDPIY );
691  aMapVDev->SetMapMode( GetPrefMapMode() );
692 
693  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
694  {
695  const MetaActionType nType = pAct->GetType();
696  MetaAction* pModAct;
697 
698  if( pAct->GetRefCount() > 1 )
699  {
700  m_aList[ m_nCurrentActionElement ] = pAct->Clone();
701  pModAct = m_aList[ m_nCurrentActionElement ].get();
702  }
703  else
704  pModAct = pAct;
705 
706  if( ( MetaActionType::MAPMODE == nType ) ||
707  ( MetaActionType::PUSH == nType ) ||
708  ( MetaActionType::POP == nType ) )
709  {
710  pModAct->Execute( aMapVDev.get() );
711  if( aMapVDev->GetMapMode().GetMapUnit() == MapUnit::MapPixel )
712  {
713  aOffset = aMapVDev->LogicToPixel( aBaseOffset, GetPrefMapMode() );
714  MapMode aMap( aMapVDev->GetMapMode() );
715  aOffset.setWidth( static_cast<tools::Long>(aOffset.Width() * static_cast<double>(aMap.GetScaleX())) );
716  aOffset.setHeight( static_cast<tools::Long>(aOffset.Height() * static_cast<double>(aMap.GetScaleY())) );
717  }
718  else
719  aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
720  }
721 
722  pModAct->Move( aOffset.Width(), aOffset.Height() );
723  }
724 }
725 
726 void GDIMetaFile::Scale( double fScaleX, double fScaleY )
727 {
728  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
729  {
730  MetaAction* pModAct;
731 
732  if( pAct->GetRefCount() > 1 )
733  {
734  m_aList[ m_nCurrentActionElement ] = pAct->Clone();
735  pModAct = m_aList[ m_nCurrentActionElement ].get();
736  }
737  else
738  pModAct = pAct;
739 
740  pModAct->Scale( fScaleX, fScaleY );
741  }
742 
743  m_aPrefSize.setWidth( FRound( m_aPrefSize.Width() * fScaleX ) );
744  m_aPrefSize.setHeight( FRound( m_aPrefSize.Height() * fScaleY ) );
745 }
746 
747 void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
748 {
749  Scale( static_cast<double>(rScaleX), static_cast<double>(rScaleY) );
750 }
751 
752 void GDIMetaFile::Clip( const tools::Rectangle& i_rClipRect )
753 {
754  tools::Rectangle aCurRect( i_rClipRect );
756 
757  aMapVDev->EnableOutput( false );
758  aMapVDev->SetMapMode( GetPrefMapMode() );
759 
760  for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
761  {
762  const MetaActionType nType = pAct->GetType();
763 
764  if( ( MetaActionType::MAPMODE == nType ) ||
765  ( MetaActionType::PUSH == nType ) ||
766  ( MetaActionType::POP == nType ) )
767  {
768  pAct->Execute( aMapVDev.get() );
769  aCurRect = OutputDevice::LogicToLogic( i_rClipRect, GetPrefMapMode(), aMapVDev->GetMapMode() );
770  }
771  else if( nType == MetaActionType::CLIPREGION )
772  {
773  MetaClipRegionAction* pOldAct = static_cast<MetaClipRegionAction*>(pAct);
774  vcl::Region aNewReg( aCurRect );
775  if( pOldAct->IsClipping() )
776  aNewReg.Intersect( pOldAct->GetRegion() );
777  MetaClipRegionAction* pNewAct = new MetaClipRegionAction( aNewReg, true );
778  m_aList[ m_nCurrentActionElement ] = pNewAct;
779  }
780  }
781 }
782 
783 Point GDIMetaFile::ImplGetRotatedPoint( const Point& rPt, const Point& rRotatePt,
784  const Size& rOffset, double fSin, double fCos )
785 {
786  const tools::Long nX = rPt.X() - rRotatePt.X();
787  const tools::Long nY = rPt.Y() - rRotatePt.Y();
788 
789  return Point( FRound( fCos * nX + fSin * nY ) + rRotatePt.X() + rOffset.Width(),
790  -FRound( fSin * nX - fCos * nY ) + rRotatePt.Y() + rOffset.Height() );
791 }
792 
794  const Size& rOffset, double fSin, double fCos )
795 {
796  tools::Polygon aRet( rPoly );
797 
798  aRet.Rotate( rRotatePt, fSin, fCos );
799  aRet.Move( rOffset.Width(), rOffset.Height() );
800 
801  return aRet;
802 }
803 
805  const Size& rOffset, double fSin, double fCos )
806 {
807  tools::PolyPolygon aRet( rPolyPoly );
808 
809  aRet.Rotate( rRotatePt, fSin, fCos );
810  aRet.Move( rOffset.Width(), rOffset.Height() );
811 
812  return aRet;
813 }
814 
816  const OutputDevice& rMapDev,
817  const tools::PolyPolygon& rPolyPoly,
818  const Gradient& rGrad )
819 {
820  // Generate comment, GradientEx and Gradient actions (within DrawGradient)
822  aVDev->EnableOutput( false );
823  GDIMetaFile aGradMtf;
824 
825  aGradMtf.Record( aVDev.get() );
826  aVDev->DrawGradient( rPolyPoly, rGrad );
827  aGradMtf.Stop();
828 
829  size_t i, nAct( aGradMtf.GetActionSize() );
830  for( i=0; i < nAct; ++i )
831  {
832  MetaAction* pMetaAct = aGradMtf.GetAction( i );
833  rMtf.AddAction( pMetaAct );
834  }
835 }
836 
838 {
839  nAngle10 %= 3600_deg10;
840  nAngle10 = ( nAngle10 < 0_deg10 ) ? ( Degree10(3599) + nAngle10 ) : nAngle10;
841 
842  if( !nAngle10 )
843  return;
844 
845  GDIMetaFile aMtf;
847  const double fAngle = toRadians(nAngle10);
848  const double fSin = sin( fAngle );
849  const double fCos = cos( fAngle );
850  tools::Rectangle aRect( Point(), GetPrefSize() );
851  tools::Polygon aPoly( aRect );
852 
853  aPoly.Rotate( Point(), fSin, fCos );
854 
855  aMapVDev->EnableOutput( false );
856  aMapVDev->SetMapMode( GetPrefMapMode() );
857 
858  const tools::Rectangle aNewBound( aPoly.GetBoundRect() );
859 
860  const Point aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
861  const Size aOffset( -aNewBound.Left(), -aNewBound.Top() );
862 
863  Point aRotAnchor( aOrigin );
864  Size aRotOffset( aOffset );
865 
866  for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
867  {
868  const MetaActionType nActionType = pAction->GetType();
869 
870  switch( nActionType )
871  {
873  {
874  MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
875  aMtf.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
876  pAct->GetColor() ) );
877  }
878  break;
879 
881  {
882  MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
883  aMtf.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
884  }
885  break;
886 
888  {
889  MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
890  aMtf.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
891  ImplGetRotatedPoint( pAct->GetEndPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
892  pAct->GetLineInfo() ) );
893  }
894  break;
895 
897  {
898  MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
899  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
900  }
901  break;
902 
904  {
905  MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
906  const tools::Polygon aRoundRectPoly( pAct->GetRect(), pAct->GetHorzRound(), pAct->GetVertRound() );
907 
908  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
909  }
910  break;
911 
913  {
914  MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
915  const tools::Polygon aEllipsePoly( pAct->GetRect().Center(), pAct->GetRect().GetWidth() >> 1, pAct->GetRect().GetHeight() >> 1 );
916 
917  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
918  }
919  break;
920 
921  case MetaActionType::ARC:
922  {
923  MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
924  const tools::Polygon aArcPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Arc );
925 
926  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
927  }
928  break;
929 
930  case MetaActionType::PIE:
931  {
932  MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
933  const tools::Polygon aPiePoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Pie );
934 
935  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
936  }
937  break;
938 
940  {
941  MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
942  const tools::Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Chord );
943 
944  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
945  }
946  break;
947 
949  {
950  MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
951  aMtf.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->GetLineInfo() ) );
952  }
953  break;
954 
956  {
957  MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
958  aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
959  }
960  break;
961 
963  {
964  MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
965  aMtf.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
966  }
967  break;
968 
970  {
971  MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
972  aMtf.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
973  pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
974  }
975  break;
976 
978  {
979  MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
980  aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
981  pAct->GetText(), pAct->GetDXArray(), pAct->GetIndex(), pAct->GetLen() ) );
982  }
983  break;
984 
986  {
987  MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
988  aMtf.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
989  pAct->GetWidth(), pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
990  }
991  break;
992 
994  {
995  MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
996  aMtf.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
997  pAct->GetWidth(), pAct->GetStrikeout(), pAct->GetUnderline(), pAct->GetOverline() ) );
998  }
999  break;
1000 
1002  {
1003  MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1004  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1005  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1006  BitmapEx aBmpEx( pAct->GetBitmap() );
1007 
1008  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1009  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(),
1010  aBmpEx ) );
1011  }
1012  break;
1013 
1015  {
1016  MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1017  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1018  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1019  BitmapEx aBmpEx( pAct->GetBitmap() );
1020 
1021  aBmpEx.Crop( tools::Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1022  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1023 
1024  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1025  }
1026  break;
1027 
1029  {
1030  MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1031  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1032  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1033  BitmapEx aBmpEx( pAct->GetBitmapEx() );
1034 
1035  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1036 
1037  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1038  }
1039  break;
1040 
1042  {
1043  MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1044  tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1045  tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1046  BitmapEx aBmpEx( pAct->GetBitmapEx() );
1047 
1048  aBmpEx.Crop( tools::Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1049  aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1050 
1051  aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1052  }
1053  break;
1054 
1056  {
1057  MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1058 
1059  ImplAddGradientEx( aMtf, *aMapVDev,
1060  ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ),
1061  pAct->GetGradient() );
1062  }
1063  break;
1064 
1066  {
1067  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1068  aMtf.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1069  pAct->GetGradient() ) );
1070  }
1071  break;
1072 
1073  // Handle gradientex comment block correctly
1075  {
1076  MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
1077  if( pCommentAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1078  {
1079  int nBeginComments( 1 );
1080  pAction = NextAction();
1081 
1082  // skip everything, except gradientex action
1083  while( pAction )
1084  {
1085  const MetaActionType nType = pAction->GetType();
1086 
1087  if( MetaActionType::GRADIENTEX == nType )
1088  {
1089  // Add rotated gradientex
1090  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1091  ImplAddGradientEx( aMtf, *aMapVDev,
1092  ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1093  pAct->GetGradient() );
1094  }
1095  else if( MetaActionType::COMMENT == nType)
1096  {
1097  MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pAction);
1098  if( pAct->GetComment() == "XGRAD_SEQ_END" )
1099  {
1100  // handle nested blocks
1101  --nBeginComments;
1102 
1103  // gradientex comment block: end reached, done.
1104  if( !nBeginComments )
1105  break;
1106  }
1107  else if( pAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1108  {
1109  // handle nested blocks
1110  ++nBeginComments;
1111  }
1112 
1113  }
1114 
1115  pAction =NextAction();
1116  }
1117  }
1118  else
1119  {
1120  bool bPathStroke = (pCommentAct->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1121  if ( bPathStroke || pCommentAct->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1122  {
1123  if ( pCommentAct->GetDataSize() )
1124  {
1125  SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pCommentAct->GetData()), pCommentAct->GetDataSize(), StreamMode::READ );
1126  SvMemoryStream aDest;
1127  if ( bPathStroke )
1128  {
1129  SvtGraphicStroke aStroke;
1130  ReadSvtGraphicStroke( aMemStm, aStroke );
1131  tools::Polygon aPath;
1132  aStroke.getPath( aPath );
1133  aStroke.setPath( ImplGetRotatedPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1134  WriteSvtGraphicStroke( aDest, aStroke );
1135  aMtf.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1136  static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1137  }
1138  else
1139  {
1140  SvtGraphicFill aFill;
1141  ReadSvtGraphicFill( aMemStm, aFill );
1142  tools::PolyPolygon aPath;
1143  aFill.getPath( aPath );
1144  aFill.setPath( ImplGetRotatedPolyPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1145  WriteSvtGraphicFill( aDest, aFill );
1146  aMtf.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1147  static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1148  }
1149  }
1150  }
1151  else if ( pCommentAct->GetComment() == "XPATHSTROKE_SEQ_END"
1152  || pCommentAct->GetComment() == "XPATHFILL_SEQ_END" )
1153  {
1154  pAction->Execute( aMapVDev.get() );
1155  aMtf.AddAction( pAction );
1156  }
1157  }
1158  }
1159  break;
1160 
1161  case MetaActionType::HATCH:
1162  {
1163  MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1164  Hatch aHatch( pAct->GetHatch() );
1165 
1166  aHatch.SetAngle( aHatch.GetAngle() + nAngle10 );
1167  aMtf.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1168  aHatch ) );
1169  }
1170  break;
1171 
1173  {
1174  MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1175  aMtf.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1176  pAct->GetTransparence() ) );
1177  }
1178  break;
1179 
1181  {
1182  MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1183  GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
1184  tools::Polygon aMtfPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1185  tools::Rectangle aMtfRect( aMtfPoly.GetBoundRect() );
1186 
1187  aTransMtf.Rotate( nAngle10 );
1188  aMtf.AddAction( new MetaFloatTransparentAction( aTransMtf, aMtfRect.TopLeft(), aMtfRect.GetSize(),
1189  pAct->GetGradient() ) );
1190  }
1191  break;
1192 
1193  case MetaActionType::EPS:
1194  {
1195  MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1196  GDIMetaFile aEPSMtf( pAct->GetSubstitute() );
1197  tools::Polygon aEPSPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1198  tools::Rectangle aEPSRect( aEPSPoly.GetBoundRect() );
1199 
1200  aEPSMtf.Rotate( nAngle10 );
1201  aMtf.AddAction( new MetaEPSAction( aEPSRect.TopLeft(), aEPSRect.GetSize(),
1202  pAct->GetLink(), aEPSMtf ) );
1203  }
1204  break;
1205 
1207  {
1208  MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1209 
1210  if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1211  aMtf.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), true ) );
1212  else
1213  {
1214  aMtf.AddAction( pAction );
1215  }
1216  }
1217  break;
1218 
1220  {
1221  MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1223  ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor,
1224  aRotOffset, fSin, fCos )) ) );
1225  }
1226  break;
1227 
1229  {
1231  const vcl::Region& rRegion = pAct->GetRegion();
1232 
1233  if( rRegion.HasPolyPolygonOrB2DPolyPolygon() )
1234  aMtf.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion.GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
1235  else
1236  {
1237  aMtf.AddAction( pAction );
1238  }
1239  }
1240  break;
1241 
1243  {
1244  MetaRefPointAction* pAct = static_cast<MetaRefPointAction*>(pAction);
1245  aMtf.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct->GetRefPoint(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->IsSetting() ) );
1246  }
1247  break;
1248 
1249  case MetaActionType::FONT:
1250  {
1251  MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
1252  vcl::Font aFont( pAct->GetFont() );
1253 
1254  aFont.SetOrientation( aFont.GetOrientation() + nAngle10 );
1255  aMtf.AddAction( new MetaFontAction( aFont ) );
1256  }
1257  break;
1258 
1259  case MetaActionType::BMP:
1260  case MetaActionType::BMPEX:
1261  case MetaActionType::MASK:
1267  {
1268  OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1269  }
1270  break;
1271 
1272  default:
1273  {
1274  pAction->Execute( aMapVDev.get() );
1275  aMtf.AddAction( pAction );
1276 
1277  // update rotation point and offset, if necessary
1278  if( ( MetaActionType::MAPMODE == nActionType ) ||
1279  ( MetaActionType::PUSH == nActionType ) ||
1280  ( MetaActionType::POP == nActionType ) )
1281  {
1282  aRotAnchor = OutputDevice::LogicToLogic( aOrigin, m_aPrefMapMode, aMapVDev->GetMapMode() );
1283  aRotOffset = OutputDevice::LogicToLogic( aOffset, m_aPrefMapMode, aMapVDev->GetMapMode() );
1284  }
1285  }
1286  break;
1287  }
1288  }
1289 
1291  aMtf.m_aPrefSize = aNewBound.GetSize();
1292 
1293  *this = aMtf;
1294 
1295 }
1296 
1297 static void ImplActionBounds( tools::Rectangle& o_rOutBounds,
1298  const tools::Rectangle& i_rInBounds,
1299  const std::vector<tools::Rectangle>& i_rClipStack )
1300 {
1301  tools::Rectangle aBounds( i_rInBounds );
1302  if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() )
1303  aBounds.Intersection( i_rClipStack.back() );
1304  if( aBounds.IsEmpty() )
1305  return;
1306 
1307  if( ! o_rOutBounds.IsEmpty() )
1308  o_rOutBounds.Union( aBounds );
1309  else
1310  o_rOutBounds = aBounds;
1311 }
1312 
1314 {
1315  ScopedVclPtrInstance< VirtualDevice > aMapVDev( i_rReference );
1316 
1317  aMapVDev->EnableOutput( false );
1318  aMapVDev->SetMapMode( GetPrefMapMode() );
1319 
1320  std::vector<tools::Rectangle> aClipStack( 1, tools::Rectangle() );
1321  std::vector<vcl::PushFlags> aPushFlagStack;
1322 
1323  tools::Rectangle aBound;
1324  const sal_uLong nCount(GetActionSize());
1325 
1326  for(sal_uLong a(0); a < nCount; a++)
1327  {
1328  MetaAction* pAction = GetAction(a);
1329  const MetaActionType nActionType = pAction->GetType();
1330 
1331  switch( nActionType )
1332  {
1333  case MetaActionType::PIXEL:
1334  {
1335  MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1336  ImplActionBounds( aBound,
1337  tools::Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1338  aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1339  aClipStack );
1340  }
1341  break;
1342 
1343  case MetaActionType::POINT:
1344  {
1345  MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
1346  ImplActionBounds( aBound,
1347  tools::Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1348  aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1349  aClipStack );
1350  }
1351  break;
1352 
1353  case MetaActionType::LINE:
1354  {
1355  MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
1356  Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() );
1357  tools::Rectangle aRect( aP1, aP2 );
1358  aRect.Justify();
1359 
1360  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1361  }
1362  break;
1363 
1364  case MetaActionType::RECT:
1365  {
1366  MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
1367  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1368  }
1369  break;
1370 
1372  {
1373  MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
1374  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1375  }
1376  break;
1377 
1379  {
1380  MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
1381  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1382  }
1383  break;
1384 
1385  case MetaActionType::ARC:
1386  {
1387  MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
1388  // FIXME: this is imprecise
1389  // e.g. for small arcs the whole rectangle is WAY too large
1390  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1391  }
1392  break;
1393 
1394  case MetaActionType::PIE:
1395  {
1396  MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
1397  // FIXME: this is imprecise
1398  // e.g. for small arcs the whole rectangle is WAY too large
1399  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1400  }
1401  break;
1402 
1403  case MetaActionType::CHORD:
1404  {
1405  MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
1406  // FIXME: this is imprecise
1407  // e.g. for small arcs the whole rectangle is WAY too large
1408  ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1409  }
1410  break;
1411 
1413  {
1414  MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
1415  tools::Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1416 
1417  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1418  }
1419  break;
1420 
1422  {
1423  MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
1424  tools::Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1425  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1426  }
1427  break;
1428 
1430  {
1431  MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
1432  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1433  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1434  }
1435  break;
1436 
1437  case MetaActionType::TEXT:
1438  {
1439  MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
1440  tools::Rectangle aRect;
1441  // hdu said base = index
1442  aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() );
1443  Point aPt( pAct->GetPoint() );
1444  aRect.Move( aPt.X(), aPt.Y() );
1445  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1446  }
1447  break;
1448 
1450  {
1451  MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
1452  tools::Rectangle aRect;
1453  // hdu said base = index
1454  aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1455  0, pAct->GetDXArray() );
1456  Point aPt( pAct->GetPoint() );
1457  aRect.Move( aPt.X(), aPt.Y() );
1458  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1459  }
1460  break;
1461 
1463  {
1464  MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
1465  tools::Rectangle aRect;
1466  // hdu said base = index
1467  aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1468  pAct->GetWidth() );
1469  Point aPt( pAct->GetPoint() );
1470  aRect.Move( aPt.X(), aPt.Y() );
1471  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1472  }
1473  break;
1474 
1476  {
1477  MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
1478  // measure a test string to get ascend and descent right
1479  static constexpr OUStringLiteral pStr = u"\u00c4g";
1480  OUString aStr( pStr );
1481 
1482  tools::Rectangle aRect;
1483  aMapVDev->GetTextBoundRect( aRect, aStr, 0, 0, aStr.getLength() );
1484  Point aPt( pAct->GetStartPoint() );
1485  aRect.Move( aPt.X(), aPt.Y() );
1486  aRect.SetRight( aRect.Left() + pAct->GetWidth() );
1487  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1488  }
1489  break;
1490 
1492  {
1493  MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1494  tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1495  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1496  }
1497  break;
1498 
1500  {
1501  MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1502  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1503  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1504  }
1505  break;
1506 
1508  {
1509  MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1510  tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1511  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1512  }
1513  break;
1514 
1516  {
1517  MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1518  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1519  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1520  }
1521  break;
1522 
1524  {
1525  MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1526  tools::Rectangle aRect( pAct->GetRect() );
1527  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1528  }
1529  break;
1530 
1532  {
1533  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1534  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1535  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1536  }
1537  break;
1538 
1540  {
1541  // nothing to do
1542  };
1543  break;
1544 
1545  case MetaActionType::HATCH:
1546  {
1547  MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1548  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1549  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1550  }
1551  break;
1552 
1554  {
1555  MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1556  tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1557  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1558  }
1559  break;
1560 
1562  {
1563  MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1564  // MetaFloatTransparentAction is defined limiting its content Metafile
1565  // to its geometry definition(Point, Size), so use these directly
1566  const tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1567  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1568  }
1569  break;
1570 
1571  case MetaActionType::EPS:
1572  {
1573  MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1574  tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1575  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1576  }
1577  break;
1578 
1580  {
1581  MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1582  if( pAct->IsClipping() )
1583  aClipStack.back() = OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() );
1584  else
1585  aClipStack.back() = tools::Rectangle();
1586  }
1587  break;
1588 
1590  {
1591  MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1592  tools::Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1593  if( aClipStack.back().IsEmpty() )
1594  aClipStack.back() = aRect;
1595  else
1596  aClipStack.back().Intersection( aRect );
1597  }
1598  break;
1599 
1601  {
1603  tools::Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1604  if( aClipStack.back().IsEmpty() )
1605  aClipStack.back() = aRect;
1606  else
1607  aClipStack.back().Intersection( aRect );
1608  }
1609  break;
1610 
1611  case MetaActionType::BMP:
1612  {
1613  MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
1614  tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1615  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1616  }
1617  break;
1618 
1619  case MetaActionType::BMPEX:
1620  {
1621  MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
1622  tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) );
1623  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1624  }
1625  break;
1626 
1627  case MetaActionType::MASK:
1628  {
1629  MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
1630  tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1631  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1632  }
1633  break;
1634 
1636  {
1637  MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1638  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1639  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1640  }
1641  break;
1642 
1644  {
1645  MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1646  tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1647  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1648  }
1649  break;
1650 
1652  {
1653  MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
1654  tools::Rectangle aRect( pAct->GetRect() );
1655  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1656  }
1657  break;
1658 
1660  {
1661  MetaTextRectAction* pAct = static_cast<MetaTextRectAction*>(pAction);
1662  tools::Rectangle aRect( pAct->GetRect() );
1663  ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1664  }
1665  break;
1666 
1668  {
1669  MetaMoveClipRegionAction* pAct = static_cast<MetaMoveClipRegionAction*>(pAction);
1670  if( ! aClipStack.back().IsEmpty() )
1671  {
1672  Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() );
1673  aDelta = OutputDevice::LogicToLogic( aDelta, aMapVDev->GetMapMode(), GetPrefMapMode() );
1674  aClipStack.back().Move( aDelta.Width(), aDelta.Width() );
1675  }
1676  }
1677  break;
1678 
1679  default:
1680  {
1681  pAction->Execute( aMapVDev.get() );
1682 
1683  if( nActionType == MetaActionType::PUSH )
1684  {
1685  MetaPushAction* pAct = static_cast<MetaPushAction*>(pAction);
1686  aPushFlagStack.push_back( pAct->GetFlags() );
1687  if( aPushFlagStack.back() & vcl::PushFlags::CLIPREGION )
1688  {
1689  tools::Rectangle aRect( aClipStack.back() );
1690  aClipStack.push_back( aRect );
1691  }
1692  }
1693  else if( nActionType == MetaActionType::POP )
1694  {
1695  // sanity check
1696  if( ! aPushFlagStack.empty() )
1697  {
1698  if( aPushFlagStack.back() & vcl::PushFlags::CLIPREGION )
1699  {
1700  if( aClipStack.size() > 1 )
1701  aClipStack.pop_back();
1702  }
1703  aPushFlagStack.pop_back();
1704  }
1705  }
1706  }
1707  break;
1708  }
1709  }
1710  return aBound;
1711 }
1712 
1713 Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
1714 {
1715  return Color( ColorAlpha, rColor.GetAlpha(),
1716  static_cast<const ImplColAdjustParam*>(pColParam)->pMapR[ rColor.GetRed() ],
1717  static_cast<const ImplColAdjustParam*>(pColParam)->pMapG[ rColor.GetGreen() ],
1718  static_cast<const ImplColAdjustParam*>(pColParam)->pMapB[ rColor.GetBlue() ] );
1719 
1720 }
1721 
1722 BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1723 {
1724  const ImplBmpAdjustParam* p = static_cast<const ImplBmpAdjustParam*>(pBmpParam);
1725  BitmapEx aRet( rBmpEx );
1726 
1727  aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
1728  p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
1729  p->fGamma, p->bInvert );
1730 
1731  return aRet;
1732 }
1733 
1734 Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
1735 {
1736  sal_uInt8 cLum = rColor.GetLuminance();
1737 
1738  if( MtfConversion::N1BitThreshold == static_cast<const ImplColConvertParam*>(pColParam)->eConversion )
1739  cLum = ( cLum < 128 ) ? 0 : 255;
1740 
1741  return Color( ColorTransparency, 255 - rColor.GetAlpha(), cLum, cLum, cLum );
1742 }
1743 
1744 BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1745 {
1746  BitmapEx aRet( rBmpEx );
1747 
1748  aRet.Convert( static_cast<const ImplBmpConvertParam*>(pBmpParam)->eConversion );
1749 
1750  return aRet;
1751 }
1752 
1753 Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam )
1754 {
1755  return static_cast<const ImplColMonoParam*>(pColParam)->aColor;
1756 }
1757 
1758 BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1759 {
1760  BitmapPalette aPal( 3 );
1761  aPal[ 0 ] = COL_BLACK;
1762  aPal[ 1 ] = COL_WHITE;
1763  aPal[ 2 ] = static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor;
1764 
1765  Bitmap aBmp(rBmpEx.GetSizePixel(), vcl::PixelFormat::N8_BPP, &aPal);
1766  aBmp.Erase( static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor );
1767 
1768  if( rBmpEx.IsAlpha() )
1769  return BitmapEx( aBmp, rBmpEx.GetAlpha() );
1770  else
1771  return BitmapEx( aBmp );
1772 }
1773 
1774 Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
1775 {
1776  const sal_uLong nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
1777 
1778  for( sal_uLong i = 0; i < static_cast<const ImplColReplaceParam*>(pColParam)->nCount; i++ )
1779  {
1780  if( ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinR[ i ] <= nR ) &&
1781  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxR[ i ] >= nR ) &&
1782  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinG[ i ] <= nG ) &&
1783  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxG[ i ] >= nG ) &&
1784  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinB[ i ] <= nB ) &&
1785  ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxB[ i ] >= nB ) )
1786  {
1787  return static_cast<const ImplColReplaceParam*>(pColParam)->pDstCols[ i ];
1788  }
1789  }
1790 
1791  return rColor;
1792 }
1793 
1794 BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1795 {
1796  const ImplBmpReplaceParam* p = static_cast<const ImplBmpReplaceParam*>(pBmpParam);
1797  BitmapEx aRet( rBmpEx );
1798 
1799  aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount );
1800 
1801  return aRet;
1802 }
1803 
1804 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
1805  BmpExchangeFnc pFncBmp, const void* pBmpParam )
1806 {
1807  GDIMetaFile aMtf;
1808 
1809  aMtf.m_aPrefSize = m_aPrefSize;
1811  aMtf.m_bUseCanvas = m_bUseCanvas;
1812 
1813  for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
1814  {
1815  const MetaActionType nType = pAction->GetType();
1816 
1817  switch( nType )
1818  {
1819  case MetaActionType::PIXEL:
1820  {
1821  MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1822  aMtf.push_back( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ) );
1823  }
1824  break;
1825 
1827  {
1828  MetaLineColorAction* pAct = static_cast<MetaLineColorAction*>(pAction);
1829 
1830  if( pAct->IsSetting() )
1831  pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1832 
1833  aMtf.push_back( pAct );
1834  }
1835  break;
1836 
1838  {
1839  MetaFillColorAction* pAct = static_cast<MetaFillColorAction*>(pAction);
1840 
1841  if( pAct->IsSetting() )
1842  pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1843 
1844  aMtf.push_back( pAct );
1845  }
1846  break;
1847 
1849  {
1850  MetaTextColorAction* pAct = static_cast<MetaTextColorAction*>(pAction);
1851  aMtf.push_back( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ) );
1852  }
1853  break;
1854 
1856  {
1857  MetaTextFillColorAction* pAct = static_cast<MetaTextFillColorAction*>(pAction);
1858 
1859  if( pAct->IsSetting() )
1860  pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1861 
1862  aMtf.push_back( pAct );
1863  }
1864  break;
1865 
1867  {
1868  MetaTextLineColorAction* pAct = static_cast<MetaTextLineColorAction*>(pAction);
1869 
1870  if( pAct->IsSetting() )
1871  pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1872 
1873  aMtf.push_back( pAct );
1874  }
1875  break;
1876 
1878  {
1879  MetaOverlineColorAction* pAct = static_cast<MetaOverlineColorAction*>(pAction);
1880 
1881  if( pAct->IsSetting() )
1882  pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1883 
1884  aMtf.push_back( pAct );
1885  }
1886  break;
1887 
1888  case MetaActionType::FONT:
1889  {
1890  MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
1891  vcl::Font aFont( pAct->GetFont() );
1892 
1893  aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
1894  aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
1895  aMtf.push_back( new MetaFontAction( aFont ) );
1896  }
1897  break;
1898 
1900  {
1901  MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
1902  Wallpaper aWall( pAct->GetWallpaper() );
1903  const tools::Rectangle& rRect = pAct->GetRect();
1904 
1905  aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
1906 
1907  if( aWall.IsBitmap() )
1908  aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
1909 
1910  if( aWall.IsGradient() )
1911  {
1912  Gradient aGradient( aWall.GetGradient() );
1913 
1914  aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
1915  aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
1916  aWall.SetGradient( aGradient );
1917  }
1918 
1919  aMtf.push_back( new MetaWallpaperAction( rRect, aWall ) );
1920  }
1921  break;
1922 
1923  case MetaActionType::BMP:
1924  case MetaActionType::BMPEX:
1925  case MetaActionType::MASK:
1926  {
1927  OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
1928  }
1929  break;
1930 
1932  {
1933  MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1934  aMtf.push_back( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
1935  pFncBmp( BitmapEx(pAct->GetBitmap()), pBmpParam ).GetBitmap() ) );
1936  }
1937  break;
1938 
1940  {
1941  MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1942  aMtf.push_back( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1943  pAct->GetSrcPoint(), pAct->GetSrcSize(),
1944  pFncBmp( BitmapEx(pAct->GetBitmap()), pBmpParam ).GetBitmap() )
1945  );
1946  }
1947  break;
1948 
1950  {
1951  MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1952  aMtf.push_back( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
1953  pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
1954  );
1955  }
1956  break;
1957 
1959  {
1960  MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1961  aMtf.push_back( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1962  pAct->GetSrcPoint(), pAct->GetSrcSize(),
1963  pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
1964  );
1965  }
1966  break;
1967 
1969  {
1970  MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
1971  aMtf.push_back( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
1972  pAct->GetBitmap(),
1973  pFncCol( pAct->GetColor(), pColParam ) )
1974  );
1975  }
1976  break;
1977 
1979  {
1980  MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1981  aMtf.push_back( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1982  pAct->GetSrcPoint(), pAct->GetSrcSize(),
1983  pAct->GetBitmap(),
1984  pFncCol( pAct->GetColor(), pColParam ) )
1985  );
1986  }
1987  break;
1988 
1990  {
1991  MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1992  Gradient aGradient( pAct->GetGradient() );
1993 
1994  aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
1995  aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
1996  aMtf.push_back( new MetaGradientAction( pAct->GetRect(), aGradient ) );
1997  }
1998  break;
1999 
2001  {
2002  MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(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 MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ) );
2008  }
2009  break;
2010 
2011  case MetaActionType::HATCH:
2012  {
2013  MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
2014  Hatch aHatch( pAct->GetHatch() );
2015 
2016  aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
2017  aMtf.push_back( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ) );
2018  }
2019  break;
2020 
2022  {
2023  MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
2024  GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
2025 
2026  aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2027  aMtf.push_back( new MetaFloatTransparentAction( aTransMtf,
2028  pAct->GetPoint(), pAct->GetSize(),
2029  pAct->GetGradient() )
2030  );
2031  }
2032  break;
2033 
2034  case MetaActionType::EPS:
2035  {
2036  MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
2037  GDIMetaFile aSubst( pAct->GetSubstitute() );
2038 
2039  aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2040  aMtf.push_back( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
2041  pAct->GetLink(), aSubst )
2042  );
2043  }
2044  break;
2045 
2046  default:
2047  {
2048  aMtf.push_back( pAction );
2049  }
2050  break;
2051  }
2052  }
2053 
2054  *this = aMtf;
2055 }
2056 
2057 void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
2058  short nChannelRPercent, short nChannelGPercent,
2059  short nChannelBPercent, double fGamma, bool bInvert, bool msoBrightness )
2060 {
2061  // nothing to do? => return quickly
2062  if( !(nLuminancePercent || nContrastPercent ||
2063  nChannelRPercent || nChannelGPercent || nChannelBPercent ||
2064  ( fGamma != 1.0 ) || bInvert) )
2065  return;
2066 
2067  double fM, fROff, fGOff, fBOff, fOff;
2068  ImplColAdjustParam aColParam;
2069  ImplBmpAdjustParam aBmpParam;
2070 
2071  aColParam.pMapR.reset(new sal_uInt8[ 256 ]);
2072  aColParam.pMapG.reset(new sal_uInt8[ 256 ]);
2073  aColParam.pMapB.reset(new sal_uInt8[ 256 ]);
2074 
2075  // calculate slope
2076  if( nContrastPercent >= 0 )
2077  fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0, 100 ) );
2078  else
2079  fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100, 0 ) ) / 128.0;
2080 
2081  if(!msoBrightness)
2082  // total offset = luminance offset + contrast offset
2083  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55 + 128.0 - fM * 128.0;
2084  else
2085  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55;
2086 
2087  // channel offset = channel offset + total offset
2088  fROff = nChannelRPercent * 2.55 + fOff;
2089  fGOff = nChannelGPercent * 2.55 + fOff;
2090  fBOff = nChannelBPercent * 2.55 + fOff;
2091 
2092  // calculate gamma value
2093  fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
2094  const bool bGamma = ( fGamma != 1.0 );
2095 
2096  // create mapping table
2097  for( tools::Long nX = 0; nX < 256; nX++ )
2098  {
2099  if(!msoBrightness)
2100  {
2101  aColParam.pMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fROff ), 0, 255 ));
2102  aColParam.pMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fGOff ), 0, 255 ));
2103  aColParam.pMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fBOff ), 0, 255 ));
2104  }
2105  else
2106  {
2107  aColParam.pMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0, 255 ));
2108  aColParam.pMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0, 255 ));
2109  aColParam.pMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0, 255 ));
2110  }
2111  if( bGamma )
2112  {
2113  aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
2114  aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
2115  aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
2116  }
2117 
2118  if( bInvert )
2119  {
2120  aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
2121  aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
2122  aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
2123  }
2124  }
2125 
2126  aBmpParam.nLuminancePercent = nLuminancePercent;
2127  aBmpParam.nContrastPercent = nContrastPercent;
2128  aBmpParam.nChannelRPercent = nChannelRPercent;
2129  aBmpParam.nChannelGPercent = nChannelGPercent;
2130  aBmpParam.nChannelBPercent = nChannelBPercent;
2131  aBmpParam.fGamma = fGamma;
2132  aBmpParam.bInvert = bInvert;
2133 
2134  // do color adjustment
2135  ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
2136 }
2137 
2139 {
2140  ImplColConvertParam aColParam;
2141  ImplBmpConvertParam aBmpParam;
2142 
2143  aColParam.eConversion = eConversion;
2144  aBmpParam.eConversion = ( MtfConversion::N1BitThreshold == eConversion ) ? BmpConversion::N1BitThreshold : BmpConversion::N8BitGreys;
2145 
2146  ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
2147 }
2148 
2149 void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount )
2150 {
2151  ImplColReplaceParam aColParam;
2152  ImplBmpReplaceParam aBmpParam;
2153 
2154  aColParam.pMinR.reset(new sal_uLong[ nColorCount ]);
2155  aColParam.pMaxR.reset(new sal_uLong[ nColorCount ]);
2156  aColParam.pMinG.reset(new sal_uLong[ nColorCount ]);
2157  aColParam.pMaxG.reset(new sal_uLong[ nColorCount ]);
2158  aColParam.pMinB.reset(new sal_uLong[ nColorCount ]);
2159  aColParam.pMaxB.reset(new sal_uLong[ nColorCount ]);
2160 
2161  for( sal_uLong i = 0; i < nColorCount; i++ )
2162  {
2163  tools::Long nVal;
2164 
2165  nVal = pSearchColors[ i ].GetRed();
2166  aColParam.pMinR[ i ] = static_cast<sal_uLong>(std::max( nVal, tools::Long(0) ));
2167  aColParam.pMaxR[ i ] = static_cast<sal_uLong>(std::min( nVal, tools::Long(255) ));
2168 
2169  nVal = pSearchColors[ i ].GetGreen();
2170  aColParam.pMinG[ i ] = static_cast<sal_uLong>(std::max( nVal, tools::Long(0) ));
2171  aColParam.pMaxG[ i ] = static_cast<sal_uLong>(std::min( nVal, tools::Long(255) ));
2172 
2173  nVal = pSearchColors[ i ].GetBlue();
2174  aColParam.pMinB[ i ] = static_cast<sal_uLong>(std::max( nVal, tools::Long(0) ));
2175  aColParam.pMaxB[ i ] = static_cast<sal_uLong>(std::min( nVal, tools::Long(255) ));
2176  }
2177 
2178  aColParam.pDstCols = pReplaceColors;
2179  aColParam.nCount = nColorCount;
2180 
2181  aBmpParam.pSrcCols = pSearchColors;
2182  aBmpParam.pDstCols = pReplaceColors;
2183  aBmpParam.nCount = nColorCount;
2184 
2185  ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
2186 };
2187 
2189 {
2190  GDIMetaFile aRet( *this );
2191 
2192  ImplColMonoParam aColParam;
2193  ImplBmpMonoParam aBmpParam;
2194 
2195  aColParam.aColor = rColor;
2196  aBmpParam.aColor = rColor;
2197 
2198  aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
2199 
2200  return aRet;
2201 }
2202 
2204 {
2205  sal_uLong nSizeBytes = 0;
2206 
2207  for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; ++i )
2208  {
2209  MetaAction* pAction = GetAction( i );
2210 
2211  // default action size is set to 32 (=> not the exact value)
2212  nSizeBytes += 32;
2213 
2214  // add sizes for large action content
2215  switch( pAction->GetType() )
2216  {
2217  case MetaActionType::BMP: nSizeBytes += static_cast<MetaBmpAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2218  case MetaActionType::BMPSCALE: nSizeBytes += static_cast<MetaBmpScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2219  case MetaActionType::BMPSCALEPART: nSizeBytes += static_cast<MetaBmpScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2220 
2221  case MetaActionType::BMPEX: nSizeBytes += static_cast<MetaBmpExAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2222  case MetaActionType::BMPEXSCALE: nSizeBytes += static_cast<MetaBmpExScaleAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2223  case MetaActionType::BMPEXSCALEPART: nSizeBytes += static_cast<MetaBmpExScalePartAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2224 
2225  case MetaActionType::MASK: nSizeBytes += static_cast<MetaMaskAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2226  case MetaActionType::MASKSCALE: nSizeBytes += static_cast<MetaMaskScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2227  case MetaActionType::MASKSCALEPART: nSizeBytes += static_cast<MetaMaskScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2228 
2229  case MetaActionType::POLYLINE: nSizeBytes += static_cast<MetaPolyLineAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2230  case MetaActionType::POLYGON: nSizeBytes += static_cast<MetaPolygonAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2232  {
2233  const tools::PolyPolygon& rPolyPoly = static_cast<MetaPolyPolygonAction*>( pAction )->GetPolyPolygon();
2234 
2235  for( sal_uInt16 n = 0; n < rPolyPoly.Count(); ++n )
2236  nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) );
2237  }
2238  break;
2239 
2240  case MetaActionType::TEXT: nSizeBytes += static_cast<MetaTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2241  case MetaActionType::STRETCHTEXT: nSizeBytes += static_cast<MetaStretchTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2242  case MetaActionType::TEXTRECT: nSizeBytes += static_cast<MetaTextRectAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2244  {
2245  MetaTextArrayAction* pTextArrayAction = static_cast<MetaTextArrayAction*>(pAction);
2246 
2247  nSizeBytes += ( pTextArrayAction->GetText().getLength() * sizeof( sal_Unicode ) );
2248 
2249  if( !pTextArrayAction->GetDXArray().empty() )
2250  nSizeBytes += ( pTextArrayAction->GetLen() << 2 );
2251  }
2252  break;
2253  default: break;
2254  }
2255  }
2256 
2257  return nSizeBytes;
2258 }
2259 
2260 bool GDIMetaFile::CreateThumbnail(BitmapEx& rBitmapEx, BmpConversion eColorConversion, BmpScaleFlag nScaleFlag) const
2261 {
2262  // initialization seems to be complicated but is used to avoid rounding errors
2264  // set Enable to tease the rendering down the code paths which use B2DPolygon and
2265  // avoid integer overflows on scaling tools::Polygon, e.g. moz1545040-1.svg
2266  // note: this is similar to DocumentToGraphicRenderer::renderToGraphic
2267  aVDev->SetAntialiasing(AntialiasingFlags::Enable | aVDev->GetAntialiasing());
2268  const Point aNullPt;
2269  const Point aTLPix( aVDev->LogicToPixel( aNullPt, GetPrefMapMode() ) );
2270  const Point aBRPix( aVDev->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2271  Size aDrawSize( aVDev->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2272  Size aSizePix( std::abs( aBRPix.X() - aTLPix.X() ) + 1, std::abs( aBRPix.Y() - aTLPix.Y() ) + 1 );
2273  sal_uInt32 nMaximumExtent = 512;
2274 
2275  if (!rBitmapEx.IsEmpty())
2276  rBitmapEx.SetEmpty();
2277 
2278  // determine size that has the same aspect ratio as image size and
2279  // fits into the rectangle determined by nMaximumExtent
2280  if ( aSizePix.Width() && aSizePix.Height()
2281  && ( sal::static_int_cast< tools::ULong >(aSizePix.Width()) >
2282  nMaximumExtent ||
2283  sal::static_int_cast< tools::ULong >(aSizePix.Height()) >
2284  nMaximumExtent ) )
2285  {
2286  const Size aOldSizePix( aSizePix );
2287  double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
2288 
2289  if ( fWH <= 1.0 )
2290  {
2291  aSizePix.setWidth( FRound( nMaximumExtent * fWH ) );
2292  aSizePix.setHeight( nMaximumExtent );
2293  }
2294  else
2295  {
2296  aSizePix.setWidth( nMaximumExtent );
2297  aSizePix.setHeight( FRound( nMaximumExtent / fWH ) );
2298  }
2299 
2300  aDrawSize.setWidth( FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() ) );
2301  aDrawSize.setHeight( FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() ) );
2302  }
2303 
2304  // draw image(s) into VDev and get resulting image
2305  // do it 4x larger to be able to scale it down & get beautiful antialias
2306  Size aAntialiasSize(aSizePix.Width() * 4, aSizePix.Height() * 4);
2307  if (aVDev->SetOutputSizePixel(aAntialiasSize))
2308  {
2309  // antialias: provide 4x larger size, and then scale down the result
2310  Size aAntialias(aDrawSize.Width() * 4, aDrawSize.Height() * 4);
2311 
2312  // draw metafile into VDev
2313  const_cast<GDIMetaFile *>(this)->WindStart();
2314  const_cast<GDIMetaFile *>(this)->Play(*aVDev, Point(), aAntialias);
2315 
2316  // get paint bitmap
2317  BitmapEx aBitmap( aVDev->GetBitmapEx( aNullPt, aVDev->GetOutputSizePixel() ) );
2318 
2319  // scale down the image to the desired size - use the input scaler for the scaling operation
2320  aBitmap.Scale(aDrawSize, nScaleFlag);
2321 
2322  // convert to desired bitmap color format
2323  Size aSize(aBitmap.GetSizePixel());
2324  if (aSize.Width() && aSize.Height())
2325  aBitmap.Convert(eColorConversion);
2326 
2327  rBitmapEx = aBitmap;
2328  }
2329 
2330  return !rBitmapEx.IsEmpty();
2331 }
2332 
2333 void GDIMetaFile::UseCanvas( bool _bUseCanvas )
2334 {
2335  m_bUseCanvas = _bUseCanvas;
2336 }
2337 
2338 void GDIMetaFile::dumpAsXml(const char* pFileName) const
2339 {
2340  SvFileStream aStream(pFileName ? OUString::fromUtf8(pFileName) : OUString("file:///tmp/metafile.xml"),
2341  StreamMode::STD_READWRITE | StreamMode::TRUNC);
2342  assert(aStream.good());
2343  MetafileXmlDump aDumper;
2344  aDumper.dump(*this, aStream);
2345 }
2346 
2347 /* 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:1722
const Fraction & GetScaleX() const
Definition: mapmod.cxx:154
SAL_DLLPRIVATE bool ImplPlayWithRenderer(OutputDevice &rOut, const Point &rPos, Size rLogicDestSize)
Definition: gdimtf.cxx:387
const Gradient & GetGradient() const
Definition: metaact.hxx:1594
void Mirror(BmpMirrorFlags nMirrorFlags)
Definition: gdimtf.cxx:613
virtual void Execute(OutputDevice *pOut)
Definition: metaact.cxx:98
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:185
void dump(const GDIMetaFile &rMetaFile, SvStream &rStream)
The actual result that will be used for testing.
Definition: mtfxmldump.cxx:583
virtual void Flush()
Definition: outdev.hxx:436
void SetDigitLanguage(LanguageType)
Definition: text.cxx:70
void SetPixelOffset(const Size &rOffset)
Set an offset in pixel.
Definition: map.cxx:1861
GDIMetaFile * m_pPrev
Definition: gdimtf.hxx:63
const Size & GetDestSize() const
Definition: metaact.hxx:978
Definition: hatch.hxx:46
VclPtr< OutputDevice > m_pOutDev
Definition: gdimtf.hxx:65
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:407
bool IsClipping() const
Definition: metaact.hxx:1134
const Color & GetColor() const
Definition: metaact.hxx:1377
const Bitmap & GetBitmap() const
Definition: metaact.hxx:935
sal_Int32 GetLen() const
Definition: metaact.hxx:496
MetaAction * GetCurAction() const
Definition: gdimtf.hxx:170
sal_uInt8 GetAlpha() const
const Point & GetPoint() const
Definition: metaact.hxx:717
sal_uInt8 GetRed() const
void ReplaceColors(const Color *pSearchColors, const Color *rReplaceColors, sal_uLong nColorCount)
Definition: gdimtf.cxx:2149
const Point & GetEndPoint() const
Definition: metaact.hxx:341
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
const GDIMetaFile & GetGDIMetaFile() const
Definition: metaact.hxx:1591
void setWidth(tools::Long nWidth)
tools::Long GetVertMove() const
Definition: metaact.hxx:1217
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:246
Class that is used for testing of the decomposition into shapes.
Definition: mtfxmldump.hxx:44
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1043
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1619
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:1325
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:244
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:2338
MetaAction * NextAction()
Definition: gdimtf.cxx:195
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
static void ImplActionBounds(tools::Rectangle &o_rOutBounds, const tools::Rectangle &i_rInBounds, const std::vector< tools::Rectangle > &i_rClipStack)
Definition: gdimtf.cxx:1297
const Point & GetPoint() const
Definition: metaact.hxx:1631
virtual bool IsTransparent() const
#i10613# Extracted from Printer::GetPreparedMetaFile.
Definition: metaact.hxx:98
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:1592
void Clear()
Definition: gdimtf.cxx:270
static SAL_DLLPRIVATE Color ImplColMonoFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1753
const Size & GetSize() const
Definition: metaact.hxx:718
const MapMode & GetMapMode() const
Definition: outdev.hxx:1572
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1556
void Move(tools::Long nHorzMove, tools::Long nVertMove)
void Rotate(Degree10 nAngle10)
Definition: gdimtf.cxx:837
const Point & GetEndPoint() const
Definition: metaact.hxx:184
GDIMetaFile * GetConnectMetaFile() const
Definition: outdev.hxx:292
const OUString & GetText() const
Definition: metaact.hxx:574
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:815
tools::Rectangle GetBoundRect() const
Definition: region.cxx:1221
static SAL_DLLPRIVATE BitmapEx ImplBmpReplaceFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1794
void Clip(const tools::Rectangle &)
Definition: gdimtf.cxx:752
const Point & GetPoint() const
Definition: metaact.hxx:937
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:1695
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:793
const Point & GetPoint() const
Definition: metaact.hxx:823
void Record(OutputDevice *pOutDev)
Definition: gdimtf.cxx:311
void push_back(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:608
const OUString & GetText() const
Definition: metaact.hxx:494
const Fraction & GetScaleY() const
Definition: mapmod.cxx:156
unsigned long ULong
vcl::PushFlags GetFlags() const
Definition: metaact.hxx:1488
geometry::IntegerSize2D integerSize2DFromSize(const Size &rSize)
const Bitmap & GetBitmap() const
Definition: metaact.hxx:684
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:2057
int nCount
void SetLayoutMode(vcl::text::ComplexTextLayoutFlags nTextLayoutMode)
Definition: text.cxx:59
const vcl::Region & GetRegion() const
Definition: metaact.hxx:1133
bool CreateThumbnail(BitmapEx &rBitmapEx, BmpConversion nColorConversion=BmpConversion::N24Bit, BmpScaleFlag nScaleFlag=BmpScaleFlag::BestQuality) const
Creates an antialiased thumbnail.
Definition: gdimtf.cxx:2260
void SetStartColor(const Color &rColor)
#define GAMMA(_def_cVal, _def_InvGamma)
const Gradient & GetGradient() const
Definition: metaact.hxx:1014
constexpr tools::Long GetWidth() const
void Pop()
Definition: stack.cxx:92
const Point & GetStartPoint() const
Definition: metaact.hxx:306
const Color & GetColor() const
Definition: metaact.hxx:1243
MetaActionType
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:1162
void Play(GDIMetaFile &rMtf)
Definition: gdimtf.cxx:322
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:462
BitmapEx(* BmpExchangeFnc)(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.hxx:53
const Size & GetSize() const
Definition: metaact.hxx:824
GDIMetaFile GetMonochromeMtf(const Color &rCol) const
Definition: gdimtf.cxx:2188
sal_uInt8 GetBlue() const
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:275
FontLineStyle GetUnderline() const
Definition: metaact.hxx:651
Size m_aPrefSize
Definition: gdimtf.hxx:62
const tools::Polygon & GetPolygon() const
Definition: metaact.hxx:435
tools::PolyPolygon GetAsPolyPolygon() const
Definition: region.cxx:1268
sal_uInt32 GetHorzRound() const
Definition: metaact.hxx:245
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:1189
static SAL_DLLPRIVATE tools::PolyPolygon ImplGetRotatedPolyPolygon(const tools::PolyPolygon &rPoly, const Point &rRotatePt, const Size &rOffset, double fSin, double fCos)
Definition: gdimtf.cxx:804
const Size & GetSrcSize() const
Definition: metaact.hxx:980
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:783
void SetEmpty()
Definition: BitmapEx.cxx:182
static vcl::Window * GetFirstTopLevelWindow()
Get the first top-level window of the application.
Definition: svapp.cxx:1169
bool IsEmpty() const
Definition: BitmapEx.cxx:177
void ReduceInaccurate(unsigned nSignificantBits)
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
void SetConnectMetaFile(GDIMetaFile *pMtf)
Definition: outdev.cxx:212
void SetScaleX(const Fraction &rScaleX)
Definition: mapmod.cxx:111
#define TOOLS_WARN_EXCEPTION(area, stream)
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:214
static SAL_DLLPRIVATE BitmapEx ImplBmpConvertFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1744
const Size & GetPrefSize() const
Definition: gdimtf.hxx:172
~GDIMetaFile()
Definition: gdimtf.cxx:149
tools::Long GetWidth() const
Definition: metaact.hxx:649
const tools::Polygon & GetPolygon() const
Definition: metaact.hxx:406
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:1557
virtual void Scale(double fScaleX, double fScaleY)
Definition: metaact.cxx:111
const Size & GetSize() const
Definition: metaact.hxx:938
void SetAngle(Degree10 nAngle10)
Definition: gdi/hatch.cxx:74
const Point & GetPoint() const
Definition: metaact.hxx:493
SAL_DLLPRIVATE void ImplExchangeColors(ColorExchangeFnc pFncCol, const void *pColParam, BmpExchangeFnc pFncBmp, const void *pBmpParam)
Definition: gdimtf.cxx:1804
void Convert(MtfConversion eConversion)
Definition: gdimtf.cxx:2138
bool IsSetting() const
Definition: metaact.hxx:1244
tools::Long FRound(double fVal)
#define LANGUAGE_SYSTEM
void SetOrientation(Degree10 nLineOrientation)
Definition: font/font.cxx:226
Color(* ColorExchangeFnc)(const Color &rColor, const void *pColParam)
Definition: gdimtf.hxx:52
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:789
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:1013
const Color & GetColor() const
Definition: metaact.hxx:1322
Size GetOutputSize() const
Definition: outdev.hxx:334
const Size & GetSize() const
Definition: metaact.hxx:1593
void SetOrigin(const Point &rOrigin)
Definition: mapmod.cxx:105
sal_uInt32 GetWidth() const
Definition: metaact.hxx:575
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:175
float u
void Move(tools::Long nHorzMove, tools::Long nVertMove)
const Point & GetEndPoint() const
Definition: metaact.hxx:307
void SetScaleY(const Fraction &rScaleY)
Definition: mapmod.cxx:118
void UseCanvas(bool _bUseCanvas)
Definition: gdimtf.cxx:2333
void Intersect(const tools::Rectangle &rRegion)
Definition: region.cxx:582
void getPath(tools::Polygon &) const
Query path to stroke.
const Point & GetStartPoint() const
Definition: metaact.hxx:374
double toRadians(D x)
sal_Int32 GetLen() const
Definition: metaact.hxx:577
void Move(tools::Long nX, tools::Long nY)
Definition: gdimtf.cxx:649
constexpr void SetRight(tools::Long v)
const Point & GetPoint() const
Definition: metaact.hxx:790
bool m_bRecord
Definition: gdimtf.hxx:67
const Bitmap & GetBitmap() const
Definition: metaact.hxx:900
Size GetOutputSizePixel() const
Definition: outdev.hxx:321
ColorTransparency
MapUnit GetMapUnit() const
Definition: mapmod.cxx:150
virtual void SetMetafileMapMode(const MapMode &rNewMapMode, bool bIsRecord)
Definition: map.cxx:765
void WindStart()
Definition: gdimtf.cxx:568
bool HasTransparentActions() const
Definition: gdimtf.cxx:154
tools::Rectangle GetBoundRect(OutputDevice &i_rReference) const
Definition: gdimtf.cxx:1313
bool TooLargeScaleForMapMode(const Fraction &rScale, int nDPI)
virtual void Move(tools::Long nHorzMove, tools::Long nVertMove)
Definition: metaact.cxx:107
bool Rotate(Degree10 nAngle10, const Color &rFillColor)
Rotate bitmap by the specified angle.
Definition: BitmapEx.cxx:316
const Bitmap & GetBitmap() const
Definition: metaact.hxx:975
const Point & GetPoint() const
Definition: metaact.hxx:902
static vcl::Window * GetActiveTopWindow()
Get the "active" top window.
Definition: svapp.cxx:1213
static SAL_DLLPRIVATE Color ImplColAdjustFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1713
FontStrikeout GetStrikeout() const
Definition: metaact.hxx:650
#define Y
const Size & GetSize() const
Definition: metaact.hxx:1632
const Bitmap & GetBitmap() const
Definition: metaact.hxx:716
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:305
constexpr Point Center() const
void SetColor(const Color &)
Definition: font/font.cxx:106
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:373
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1164
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:933
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1073
SvStream & WriteSvtGraphicFill(SvStream &rOStm, const SvtGraphicFill &rClass)
const GfxLink & GetLink() const
Definition: metaact.hxx:1629
const Point & GetPoint() const
Definition: metaact.hxx:573
bool IsSetting() const
Definition: metaact.hxx:1380
bool IsSetting() const
Definition: metaact.hxx:1271
sal_uInt8 GetGreen() const
bool IsSetting() const
Definition: metaact.hxx:1353
const Color & GetColor() const
Definition: metaact.hxx:1297
void Stop()
Definition: gdimtf.cxx:555
const Color & GetColor() const
Definition: metaact.hxx:936
MapMode m_aPrefMapMode
Definition: gdimtf.hxx:61
const Point & GetStartPoint() const
Definition: metaact.hxx:183
sal_uInt32 GetDataSize() const
Definition: metaact.hxx:1694
bool operator==(const GDIMetaFile &rMtf) const
Definition: gdimtf.cxx:244
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:822
void Pause(bool bPause)
Definition: gdimtf.cxx:536
bool IsSetting() const
Definition: metaact.hxx:1663
const Point & GetStartPoint() const
Definition: metaact.hxx:340
AlphaMask GetAlpha() const
Definition: BitmapEx.cxx:215
SAL_WARN_UNUSED_RESULT Size GetPixelOffset() const
Get the offset in pixel.
Definition: outdev.hxx:1616
const Point & GetPoint() const
Definition: metaact.hxx:124
const Color & GetColor() const
Definition: metaact.hxx:976
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:648
static SAL_DLLPRIVATE Color ImplColReplaceFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1774
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:581
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:1044
const Point & GetPoint() const
Definition: metaact.hxx:152
const Point & GetPoint() const
Definition: metaact.hxx:685
bool m_bUseCanvas
Definition: gdimtf.hxx:68
void Linker(OutputDevice *pOut, bool bLink)
Definition: gdimtf.cxx:278
const Point & GetDestPoint() const
Definition: metaact.hxx:977
sal_Int64 GetSizeBytes() const
Definition: BitmapEx.cxx:220
void Scale(double fScaleX, double fScaleY)
Definition: gdimtf.cxx:726
static SAL_DLLPRIVATE BitmapEx ImplBmpMonoFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1758
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:94
const Color & GetColor() const
Definition: metaact.hxx:1350
void setPath(const tools::Polygon &)
Set path to stroke.
const Point & GetEndPoint() const
Definition: metaact.hxx:375
const Hatch & GetHatch() const
Definition: metaact.hxx:1074
const Point & GetSrcPoint() const
Definition: metaact.hxx:979
FontLineStyle GetOverline() const
Definition: metaact.hxx:652
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:125
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:339
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
#define SAL_WARN(area, stream)
const Point & GetRefPoint() const
Definition: metaact.hxx:1660
const OString & GetComment() const
Definition: metaact.hxx:1692
Encapsulates geometry and associated attributes of a filled area.
tools::Rectangle GetBoundRect() const
size_t m_nCurrentActionElement
Definition: gdimtf.hxx:59
virtual size_t GetSyncCount() const
Definition: outdev.hxx:342
void getPath(tools::PolyPolygon &) const
Query path to fill.
const Size & GetSizePixel() const
Definition: bitmapex.hxx:72
const Color & GetColor() const
Definition: metaact.hxx:1270
const GDIMetaFile & GetSubstitute() const
Definition: metaact.hxx:1630
void SetColor(const Color &rColor)
Definition: gdi/hatch.cxx:64
SAL_DLLPRIVATE sal_Int32 GetDPIY() const
Get the output device's DPI y-axis value.
Definition: outdev.hxx:398
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:1923
const vcl::Font & GetFont() const
Definition: metaact.hxx:1463
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:611
aStr
sal_Int32 GetIndex() const
Definition: metaact.hxx:576
sal_Int32 GetIndex() const
Definition: metaact.hxx:495
SAL_DLLPRIVATE sal_Int32 GetDPIX() const
Get the output device's DPI x-axis value.
Definition: outdev.hxx:392
static SAL_DLLPRIVATE Color ImplColConvertFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1734
tools::Long GetHorzMove() const
Definition: metaact.hxx:1216
void WindPrev()
Definition: gdimtf.cxx:574
bool m_bDetectedRangeSegmentation false
constexpr tools::Long GetHeight() const
ColorAlpha
BmpMirrorFlags
sal_uLong GetSizeBytes() const
Definition: gdimtf.cxx:2203