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