1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include <sal/log.hxx>
23 #include <osl/diagnose.h>
24 #include <comphelper/diagnose_ex.hxx>
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>
37 #include <basegfx/polygon/b2dpolygon.hxx>
38 #include <vcl/canvastools.hxx>
39 #include <vcl/mtfxmldump.hxx>
41 #include <vcl/TypeSerializer.hxx>
43 #include <com/sun/star/beans/XFastPropertySet.hpp>
44 #include <com/sun/star/rendering/MtfRenderer.hpp>
45 #include <com/sun/star/rendering/XBitmapCanvas.hpp>
46 #include <com/sun/star/rendering/XCanvas.hpp>
47 #include <comphelper/processfactory.hxx>
49 using namespace com::sun::star
;
53 struct ImplColAdjustParam
55 std::unique_ptr
<sal_uInt8
[]> pMapR
;
56 std::unique_ptr
<sal_uInt8
[]> pMapG
;
57 std::unique_ptr
<sal_uInt8
[]> pMapB
;
60 struct ImplBmpAdjustParam
62 short nLuminancePercent
;
63 short nContrastPercent
;
64 short nChannelRPercent
;
65 short nChannelGPercent
;
66 short nChannelBPercent
;
71 struct ImplColConvertParam
73 MtfConversion eConversion
;
76 struct ImplBmpConvertParam
78 BmpConversion eConversion
;
81 struct ImplColMonoParam
86 struct ImplBmpMonoParam
91 struct ImplColReplaceParam
93 std::unique_ptr
<sal_uLong
[]> pMinR
;
94 std::unique_ptr
<sal_uLong
[]> pMaxR
;
95 std::unique_ptr
<sal_uLong
[]> pMinG
;
96 std::unique_ptr
<sal_uLong
[]> pMaxG
;
97 std::unique_ptr
<sal_uLong
[]> pMinB
;
98 std::unique_ptr
<sal_uLong
[]> pMaxB
;
99 const Color
* pDstCols
;
103 struct ImplBmpReplaceParam
105 const Color
* pSrcCols
;
106 const Color
* pDstCols
;
112 GDIMetaFile::GDIMetaFile() :
113 m_nCurrentActionElement( 0 ),
114 m_aPrefSize ( 1, 1 ),
117 m_pOutDev ( nullptr ),
120 m_bUseCanvas ( false ),
125 GDIMetaFile::GDIMetaFile( const GDIMetaFile
& rMtf
) :
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 ),
134 m_bUseCanvas ( rMtf
.m_bUseCanvas
),
135 m_bSVG ( rMtf
.m_bSVG
)
137 for( size_t i
= 0, n
= rMtf
.GetActionSize(); i
< n
; ++i
)
139 m_aList
.push_back( rMtf
.GetAction( i
) );
144 Record( rMtf
.m_pOutDev
);
151 GDIMetaFile::~GDIMetaFile()
156 bool GDIMetaFile::HasTransparentActions() const
158 MetaAction
* pCurrAct
;
160 // watch for transparent drawing actions
161 for(pCurrAct
= const_cast<GDIMetaFile
*>(this)->FirstAction();
163 pCurrAct
= const_cast<GDIMetaFile
*>(this)->NextAction())
165 // #i10613# determine if the action is transparency capable
167 // #107169# Also examine metafiles with masked bitmaps in
168 // detail. Further down, this is optimized in such a way
169 // that there's no unnecessary painting of masked bitmaps
170 // (which are _always_ subdivided into rectangular regions
171 // of uniform opacity): if a masked bitmap is printed over
172 // empty background, we convert to a plain bitmap with
174 if (pCurrAct
->IsTransparent())
181 size_t GDIMetaFile::GetActionSize() const
183 return m_aList
.size();
186 MetaAction
* GDIMetaFile::GetAction( size_t nAction
) const
188 return (nAction
< m_aList
.size()) ? m_aList
[ nAction
].get() : nullptr;
191 MetaAction
* GDIMetaFile::FirstAction()
193 m_nCurrentActionElement
= 0;
194 return m_aList
.empty() ? nullptr : m_aList
[ 0 ].get();
197 MetaAction
* GDIMetaFile::NextAction()
199 return ( m_nCurrentActionElement
+ 1 < m_aList
.size() ) ? m_aList
[ ++m_nCurrentActionElement
].get() : nullptr;
202 void GDIMetaFile::ReplaceAction( rtl::Reference
<MetaAction
> pAction
, size_t nAction
)
204 if ( nAction
>= m_aList
.size() )
208 m_aList
[nAction
] = std::move(pAction
);
211 GDIMetaFile
& GDIMetaFile::operator=( const GDIMetaFile
& rMtf
)
217 // Increment RefCount of MetaActions
218 for( size_t i
= 0, n
= rMtf
.GetActionSize(); i
< n
; ++i
)
220 m_aList
.push_back( rMtf
.GetAction( i
) );
223 m_aPrefMapMode
= rMtf
.m_aPrefMapMode
;
224 m_aPrefSize
= rMtf
.m_aPrefSize
;
225 m_pPrev
= rMtf
.m_pPrev
;
226 m_pNext
= rMtf
.m_pNext
;
230 m_bUseCanvas
= rMtf
.m_bUseCanvas
;
231 m_bSVG
= rMtf
.m_bSVG
;
235 Record( rMtf
.m_pOutDev
);
245 bool GDIMetaFile::operator==( const GDIMetaFile
& rMtf
) const
247 const size_t nObjCount
= m_aList
.size();
252 else if( rMtf
.GetActionSize() == nObjCount
&&
253 rMtf
.GetPrefSize() == m_aPrefSize
&&
254 rMtf
.GetPrefMapMode() == m_aPrefMapMode
)
258 for( size_t n
= 0; n
< nObjCount
; n
++ )
260 if( m_aList
[ n
] != rMtf
.GetAction( n
) )
271 void GDIMetaFile::Clear()
279 void GDIMetaFile::Linker( OutputDevice
* pOut
, bool bLink
)
284 m_pPrev
= pOut
->GetConnectMetaFile();
285 pOut
->SetConnectMetaFile( this );
288 m_pPrev
->m_pNext
= this;
294 m_pNext
->m_pPrev
= m_pPrev
;
297 m_pPrev
->m_pNext
= m_pNext
;
302 m_pPrev
->m_pNext
= nullptr;
304 pOut
->SetConnectMetaFile( m_pPrev
);
312 void GDIMetaFile::Record( OutputDevice
* pOut
)
317 m_nCurrentActionElement
= m_aList
.empty() ? 0 : (m_aList
.size() - 1);
320 Linker( pOut
, true );
323 void GDIMetaFile::Play( GDIMetaFile
& rMtf
)
325 if (m_bRecord
|| rMtf
.m_bRecord
)
328 MetaAction
* pAction
= GetCurAction();
329 const size_t nObjCount
= m_aList
.size();
331 rMtf
.UseCanvas( rMtf
.GetUseCanvas() || m_bUseCanvas
);
332 rMtf
.setSVG( rMtf
.getSVG() || m_bSVG
);
334 for( size_t nCurPos
= m_nCurrentActionElement
; nCurPos
< nObjCount
; nCurPos
++ )
338 rMtf
.AddAction( pAction
);
341 pAction
= NextAction();
345 void GDIMetaFile::Play(OutputDevice
& rOut
, size_t nPos
)
350 MetaAction
* pAction
= GetCurAction();
351 const size_t nObjCount
= m_aList
.size();
352 size_t nSyncCount
= rOut
.GetSyncCount();
354 if( nPos
> nObjCount
)
357 // #i23407# Set backwards-compatible text language and layout mode
358 // This is necessary, since old metafiles don't even know of these
359 // recent add-ons. Newer metafiles must of course explicitly set
361 rOut
.Push(vcl::PushFlags::TEXTLAYOUTMODE
|vcl::PushFlags::TEXTLANGUAGE
);
362 rOut
.SetLayoutMode(vcl::text::ComplexTextLayoutFlags::Default
);
363 rOut
.SetDigitLanguage(LANGUAGE_SYSTEM
);
365 SAL_INFO( "vcl.gdi", "GDIMetaFile::Play on device of size: " << rOut
.GetOutputSizePixel().Width() << " " << rOut
.GetOutputSizePixel().Height());
367 if (!ImplPlayWithRenderer(rOut
, Point(0,0), rOut
.GetOutputSize())) {
369 for( size_t nCurPos
= m_nCurrentActionElement
; nCurPos
< nPos
; nCurPos
++ )
373 pAction
->Execute(&rOut
);
375 // flush output from time to time
376 if( i
++ > nSyncCount
)
383 pAction
= NextAction();
389 bool GDIMetaFile::ImplPlayWithRenderer(OutputDevice
& rOut
, const Point
& rPos
, Size rLogicDestSize
)
394 Size
rDestSize(rOut
.LogicToPixel(rLogicDestSize
));
396 const vcl::Window
* win
= rOut
.GetOwnerWindow();
399 win
= Application::GetActiveTopWindow();
401 win
= Application::GetFirstTopLevelWindow();
408 uno::Reference
<rendering::XCanvas
> xCanvas
= win
->GetOutDev()->GetCanvas ();
413 Size
aSize (rDestSize
.Width () + 1, rDestSize
.Height () + 1);
414 uno::Reference
<rendering::XBitmap
> xBitmap
= xCanvas
->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize
));
417 uno::Reference
< rendering::XBitmapCanvas
> xBitmapCanvas( xBitmap
, uno::UNO_QUERY
);
418 if( xBitmapCanvas
.is() )
420 const uno::Reference
< uno::XComponentContext
>& xContext
= comphelper::getProcessComponentContext();
421 uno::Reference
< rendering::XMtfRenderer
> xMtfRenderer
= rendering::MtfRenderer::createWithBitmapCanvas( xContext
, xBitmapCanvas
);
423 xBitmapCanvas
->clear();
424 uno::Reference
< beans::XFastPropertySet
> xMtfFastPropertySet( xMtfRenderer
, uno::UNO_QUERY
);
425 if( xMtfFastPropertySet
.is() )
426 // set this metafile to the renderer to
427 // speedup things (instead of copying data to
428 // sequence of bytes passed to renderer)
429 xMtfFastPropertySet
->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64
>( this ) ) );
431 xMtfRenderer
->draw( rDestSize
.Width(), rDestSize
.Height() );
434 if( aBitmapEx
.Create( xBitmapCanvas
, aSize
) )
436 if (rOut
.GetMapMode().GetMapUnit() == MapUnit::MapPixel
)
437 rOut
.DrawBitmapEx( rPos
, aBitmapEx
);
439 rOut
.DrawBitmapEx( rPos
, rLogicDestSize
, aBitmapEx
);
445 catch (const uno::RuntimeException
& )
447 throw; // runtime errors are fatal
449 catch (const uno::Exception
&)
451 // ignore errors, no way of reporting them here
452 TOOLS_WARN_EXCEPTION("vcl.gdi", "GDIMetaFile::ImplPlayWithRenderer");
458 void GDIMetaFile::Play(OutputDevice
& rOut
, const Point
& rPos
,
461 MapMode
aDrawMap( GetPrefMapMode() );
462 Size
aDestSize(rOut
.LogicToPixel(rSize
));
464 if (aDestSize
.Width() <= 0 || aDestSize
.Height() <= 0)
467 if (aDestSize
.Width() > std::numeric_limits
<sal_Int32
>::max() ||
468 aDestSize
.Height() > std::numeric_limits
<sal_Int32
>::max())
471 GDIMetaFile
* pMtf
= rOut
.GetConnectMetaFile();
473 if (ImplPlayWithRenderer(rOut
, rPos
, rSize
))
476 Size
aTmpPrefSize(rOut
.LogicToPixel(GetPrefSize(), aDrawMap
));
478 if( !aTmpPrefSize
.Width() )
479 aTmpPrefSize
.setWidth( aDestSize
.Width() );
481 if( !aTmpPrefSize
.Height() )
482 aTmpPrefSize
.setHeight( aDestSize
.Height() );
484 Fraction
aScaleX( aDestSize
.Width(), aTmpPrefSize
.Width() );
485 Fraction
aScaleY( aDestSize
.Height(), aTmpPrefSize
.Height() );
487 aScaleX
*= aDrawMap
.GetScaleX();
488 aScaleY
*= aDrawMap
.GetScaleY();
489 // try reducing inaccurary first and abandon if the scaling
490 // still cannot be achieved
491 if (TooLargeScaleForMapMode(aScaleX
, rOut
.GetDPIX()))
492 aScaleX
.ReduceInaccurate(10);
493 if (TooLargeScaleForMapMode(aScaleY
, rOut
.GetDPIY()))
494 aScaleY
.ReduceInaccurate(10);
495 if (TooLargeScaleForMapMode(aScaleX
, rOut
.GetDPIX()) ||
496 TooLargeScaleForMapMode(aScaleY
, rOut
.GetDPIY()))
498 SAL_WARN("vcl", "GDIMetaFile Scaling is too high");
502 aDrawMap
.SetScaleX(aScaleX
);
503 aDrawMap
.SetScaleY(aScaleY
);
505 // #i47260# Convert logical output position to offset within
506 // the metafile's mapmode. Therefore, disable pixel offset on
507 // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
508 // different mapmode (the one currently set on rOut, that is)
509 // - thus, aDrawMap's origin would generally be wrong. And
510 // even _if_ aDrawMap is similar to pOutDev's current mapmode,
511 // it's _still_ undesirable to have pixel offset unequal zero,
512 // because one would still get round-off errors (the
513 // round-trip error for LogicToPixel( PixelToLogic() ) was the
514 // reason for having pixel offset in the first place).
515 const Size
aOldOffset(rOut
.GetPixelOffset());
516 const Size aEmptySize
;
517 rOut
.SetPixelOffset(aEmptySize
);
518 aDrawMap
.SetOrigin(rOut
.PixelToLogic(rOut
.LogicToPixel(rPos
), aDrawMap
));
519 rOut
.SetPixelOffset(aOldOffset
);
523 bool bIsRecord
= (pMtf
&& pMtf
->IsRecord());
524 rOut
.SetMetafileMapMode(aDrawMap
, bIsRecord
);
526 // #i23407# Set backwards-compatible text language and layout mode
527 // This is necessary, since old metafiles don't even know of these
528 // recent add-ons. Newer metafiles must of course explicitly set
530 rOut
.SetLayoutMode(vcl::text::ComplexTextLayoutFlags::Default
);
531 rOut
.SetDigitLanguage(LANGUAGE_SYSTEM
);
538 void GDIMetaFile::Pause( bool _bPause
)
546 Linker( m_pOutDev
, false );
551 Linker( m_pOutDev
, true );
557 void GDIMetaFile::Stop()
564 Linker( m_pOutDev
, false );
570 void GDIMetaFile::WindStart()
573 m_nCurrentActionElement
= 0;
576 void GDIMetaFile::WindPrev()
579 if ( m_nCurrentActionElement
> 0 )
580 --m_nCurrentActionElement
;
583 void GDIMetaFile::AddAction(const rtl::Reference
<MetaAction
>& pAction
)
585 m_aList
.push_back( pAction
);
589 m_pPrev
->AddAction( pAction
);
593 void GDIMetaFile::AddAction(const rtl::Reference
<MetaAction
>& pAction
, size_t nPos
)
595 if ( nPos
< m_aList
.size() )
597 m_aList
.insert( m_aList
.begin() + nPos
, pAction
);
601 m_aList
.push_back( pAction
);
606 m_pPrev
->AddAction( pAction
, nPos
);
610 void GDIMetaFile::push_back(const rtl::Reference
<MetaAction
>& pAction
)
612 m_aList
.push_back( pAction
);
615 void GDIMetaFile::Mirror( BmpMirrorFlags nMirrorFlags
)
617 const Size
aOldPrefSize( GetPrefSize() );
618 tools::Long nMoveX
, nMoveY
;
619 double fScaleX
, fScaleY
;
621 if( nMirrorFlags
& BmpMirrorFlags::Horizontal
)
623 nMoveX
= std::abs( aOldPrefSize
.Width() ) - 1;
632 if( nMirrorFlags
& BmpMirrorFlags::Vertical
)
634 nMoveY
= std::abs( aOldPrefSize
.Height() ) - 1;
643 if( ( fScaleX
!= 1.0 ) || ( fScaleY
!= 1.0 ) )
645 Scale( fScaleX
, fScaleY
);
646 Move( nMoveX
, nMoveY
);
647 SetPrefSize( aOldPrefSize
);
651 void GDIMetaFile::Move( tools::Long nX
, tools::Long nY
)
653 const Size
aBaseOffset( nX
, nY
);
654 Size
aOffset( aBaseOffset
);
655 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
657 aMapVDev
->EnableOutput( false );
658 aMapVDev
->SetMapMode( GetPrefMapMode() );
660 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
662 const MetaActionType nType
= pAct
->GetType();
665 if( pAct
->GetRefCount() > 1 )
667 m_aList
[ m_nCurrentActionElement
] = pAct
->Clone();
668 pModAct
= m_aList
[ m_nCurrentActionElement
].get();
673 if( ( MetaActionType::MAPMODE
== nType
) ||
674 ( MetaActionType::PUSH
== nType
) ||
675 ( MetaActionType::POP
== nType
) )
677 pModAct
->Execute( aMapVDev
.get() );
678 aOffset
= OutputDevice::LogicToLogic( aBaseOffset
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
681 pModAct
->Move( aOffset
.Width(), aOffset
.Height() );
685 void GDIMetaFile::Move( tools::Long nX
, tools::Long nY
, tools::Long nDPIX
, tools::Long nDPIY
)
687 const Size
aBaseOffset( nX
, nY
);
688 Size
aOffset( aBaseOffset
);
689 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
691 aMapVDev
->EnableOutput( false );
692 aMapVDev
->SetReferenceDevice( nDPIX
, nDPIY
);
693 aMapVDev
->SetMapMode( GetPrefMapMode() );
695 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
697 const MetaActionType nType
= pAct
->GetType();
700 if( pAct
->GetRefCount() > 1 )
702 m_aList
[ m_nCurrentActionElement
] = pAct
->Clone();
703 pModAct
= m_aList
[ m_nCurrentActionElement
].get();
708 if( ( MetaActionType::MAPMODE
== nType
) ||
709 ( MetaActionType::PUSH
== nType
) ||
710 ( MetaActionType::POP
== nType
) )
712 pModAct
->Execute( aMapVDev
.get() );
713 if( aMapVDev
->GetMapMode().GetMapUnit() == MapUnit::MapPixel
)
715 aOffset
= aMapVDev
->LogicToPixel( aBaseOffset
, GetPrefMapMode() );
716 MapMode
aMap( aMapVDev
->GetMapMode() );
717 aOffset
.setWidth( static_cast<tools::Long
>(aOffset
.Width() * static_cast<double>(aMap
.GetScaleX())) );
718 aOffset
.setHeight( static_cast<tools::Long
>(aOffset
.Height() * static_cast<double>(aMap
.GetScaleY())) );
721 aOffset
= OutputDevice::LogicToLogic( aBaseOffset
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
724 pModAct
->Move( aOffset
.Width(), aOffset
.Height() );
728 void GDIMetaFile::ScaleActions(double const fScaleX
, double const fScaleY
)
730 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
734 if( pAct
->GetRefCount() > 1 )
736 m_aList
[ m_nCurrentActionElement
] = pAct
->Clone();
737 pModAct
= m_aList
[ m_nCurrentActionElement
].get();
742 pModAct
->Scale( fScaleX
, fScaleY
);
746 void GDIMetaFile::Scale( double fScaleX
, double fScaleY
)
748 ScaleActions(fScaleX
, fScaleY
);
750 m_aPrefSize
.setWidth(basegfx::fround
<tools::Long
>(m_aPrefSize
.Width() * fScaleX
));
751 m_aPrefSize
.setHeight(basegfx::fround
<tools::Long
>(m_aPrefSize
.Height() * fScaleY
));
754 void GDIMetaFile::Scale( const Fraction
& rScaleX
, const Fraction
& rScaleY
)
756 Scale( static_cast<double>(rScaleX
), static_cast<double>(rScaleY
) );
759 void GDIMetaFile::Clip( const tools::Rectangle
& i_rClipRect
)
761 tools::Rectangle
aCurRect( i_rClipRect
);
762 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
764 aMapVDev
->EnableOutput( false );
765 aMapVDev
->SetMapMode( GetPrefMapMode() );
767 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
769 const MetaActionType nType
= pAct
->GetType();
771 if( ( MetaActionType::MAPMODE
== nType
) ||
772 ( MetaActionType::PUSH
== nType
) ||
773 ( MetaActionType::POP
== nType
) )
775 pAct
->Execute( aMapVDev
.get() );
776 aCurRect
= OutputDevice::LogicToLogic( i_rClipRect
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
778 else if( nType
== MetaActionType::CLIPREGION
)
780 MetaClipRegionAction
* pOldAct
= static_cast<MetaClipRegionAction
*>(pAct
);
781 vcl::Region
aNewReg( aCurRect
);
782 if( pOldAct
->IsClipping() )
783 aNewReg
.Intersect( pOldAct
->GetRegion() );
784 MetaClipRegionAction
* pNewAct
= new MetaClipRegionAction( std::move(aNewReg
), true );
785 m_aList
[ m_nCurrentActionElement
] = pNewAct
;
790 Point
GDIMetaFile::ImplGetRotatedPoint( const Point
& rPt
, const Point
& rRotatePt
,
791 const Size
& rOffset
, double fSin
, double fCos
)
793 const tools::Long nX
= rPt
.X() - rRotatePt
.X();
794 const tools::Long nY
= rPt
.Y() - rRotatePt
.Y();
796 return { basegfx::fround
<tools::Long
>(fCos
* nX
+ fSin
* nY
) + rRotatePt
.X() + rOffset
.Width(),
797 basegfx::fround
<tools::Long
>(fCos
* nY
- fSin
* nX
) + rRotatePt
.Y() + rOffset
.Height() };
800 tools::Polygon
GDIMetaFile::ImplGetRotatedPolygon( const tools::Polygon
& rPoly
, const Point
& rRotatePt
,
801 const Size
& rOffset
, double fSin
, double fCos
)
803 tools::Polygon
aRet( rPoly
);
805 aRet
.Rotate( rRotatePt
, fSin
, fCos
);
806 aRet
.Move( rOffset
.Width(), rOffset
.Height() );
811 tools::PolyPolygon
GDIMetaFile::ImplGetRotatedPolyPolygon( const tools::PolyPolygon
& rPolyPoly
, const Point
& rRotatePt
,
812 const Size
& rOffset
, double fSin
, double fCos
)
814 tools::PolyPolygon
aRet( rPolyPoly
);
816 aRet
.Rotate( rRotatePt
, fSin
, fCos
);
817 aRet
.Move( rOffset
.Width(), rOffset
.Height() );
822 void GDIMetaFile::ImplAddGradientEx( GDIMetaFile
& rMtf
,
823 const OutputDevice
& rMapDev
,
824 const tools::PolyPolygon
& rPolyPoly
,
825 const Gradient
& rGrad
)
827 // Generate comment, GradientEx and Gradient actions (within DrawGradient)
828 ScopedVclPtrInstance
< VirtualDevice
> aVDev(rMapDev
, DeviceFormat::WITHOUT_ALPHA
);
829 aVDev
->EnableOutput( false );
830 GDIMetaFile aGradMtf
;
832 aGradMtf
.Record( aVDev
.get() );
833 aVDev
->DrawGradient( rPolyPoly
, rGrad
);
836 size_t i
, nAct( aGradMtf
.GetActionSize() );
837 for( i
=0; i
< nAct
; ++i
)
839 MetaAction
* pMetaAct
= aGradMtf
.GetAction( i
);
840 rMtf
.AddAction( pMetaAct
);
844 void GDIMetaFile::Rotate( Degree10 nAngle10
)
846 nAngle10
%= 3600_deg10
;
847 nAngle10
= ( nAngle10
< 0_deg10
) ? ( Degree10(3599) + nAngle10
) : nAngle10
;
853 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
854 const double fAngle
= toRadians(nAngle10
);
855 const double fSin
= sin( fAngle
);
856 const double fCos
= cos( fAngle
);
857 tools::Rectangle
aRect( Point(), GetPrefSize() );
858 tools::Polygon
aPoly( aRect
);
860 aPoly
.Rotate( Point(), fSin
, fCos
);
862 aMapVDev
->EnableOutput( false );
863 aMapVDev
->SetMapMode( GetPrefMapMode() );
865 const tools::Rectangle
aNewBound( aPoly
.GetBoundRect() );
867 const Point
aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
868 const Size
aOffset( -aNewBound
.Left(), -aNewBound
.Top() );
870 Point
aRotAnchor( aOrigin
);
871 Size
aRotOffset( aOffset
);
873 for( MetaAction
* pAction
= FirstAction(); pAction
; pAction
= NextAction() )
875 const MetaActionType nActionType
= pAction
->GetType();
877 switch( nActionType
)
879 case MetaActionType::PIXEL
:
881 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
882 aMtf
.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
883 pAct
->GetColor() ) );
887 case MetaActionType::POINT
:
889 MetaPointAction
* pAct
= static_cast<MetaPointAction
*>(pAction
);
890 aMtf
.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
894 case MetaActionType::LINE
:
896 MetaLineAction
* pAct
= static_cast<MetaLineAction
*>(pAction
);
897 aMtf
.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct
->GetStartPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
898 ImplGetRotatedPoint( pAct
->GetEndPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
899 pAct
->GetLineInfo() ) );
903 case MetaActionType::RECT
:
905 MetaRectAction
* pAct
= static_cast<MetaRectAction
*>(pAction
);
906 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( tools::Polygon(pAct
->GetRect()), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
910 case MetaActionType::ROUNDRECT
:
912 MetaRoundRectAction
* pAct
= static_cast<MetaRoundRectAction
*>(pAction
);
913 const tools::Polygon
aRoundRectPoly( pAct
->GetRect(), pAct
->GetHorzRound(), pAct
->GetVertRound() );
915 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
919 case MetaActionType::ELLIPSE
:
921 MetaEllipseAction
* pAct
= static_cast<MetaEllipseAction
*>(pAction
);
922 const tools::Polygon
aEllipsePoly( pAct
->GetRect().Center(), pAct
->GetRect().GetWidth() >> 1, pAct
->GetRect().GetHeight() >> 1 );
924 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
928 case MetaActionType::ARC
:
930 MetaArcAction
* pAct
= static_cast<MetaArcAction
*>(pAction
);
931 const tools::Polygon
aArcPoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Arc
);
933 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
937 case MetaActionType::PIE
:
939 MetaPieAction
* pAct
= static_cast<MetaPieAction
*>(pAction
);
940 const tools::Polygon
aPiePoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Pie
);
942 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
946 case MetaActionType::CHORD
:
948 MetaChordAction
* pAct
= static_cast<MetaChordAction
*>(pAction
);
949 const tools::Polygon
aChordPoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Chord
);
951 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
955 case MetaActionType::POLYLINE
:
957 MetaPolyLineAction
* pAct
= static_cast<MetaPolyLineAction
*>(pAction
);
958 aMtf
.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct
->GetPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
), pAct
->GetLineInfo() ) );
962 case MetaActionType::POLYGON
:
964 MetaPolygonAction
* pAct
= static_cast<MetaPolygonAction
*>(pAction
);
965 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct
->GetPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
969 case MetaActionType::POLYPOLYGON
:
971 MetaPolyPolygonAction
* pAct
= static_cast<MetaPolyPolygonAction
*>(pAction
);
972 aMtf
.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
976 case MetaActionType::TEXT
:
978 MetaTextAction
* pAct
= static_cast<MetaTextAction
*>(pAction
);
979 aMtf
.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
980 pAct
->GetText(), pAct
->GetIndex(), pAct
->GetLen() ) );
984 case MetaActionType::TEXTARRAY
:
986 MetaTextArrayAction
* pAct
= static_cast<MetaTextArrayAction
*>(pAction
);
987 aMtf
.AddAction(new MetaTextArrayAction(
988 ImplGetRotatedPoint(pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
989 pAct
->GetText(), pAct
->GetDXArray(), pAct
->GetKashidaArray(), pAct
->GetIndex(),
990 pAct
->GetLen(), pAct
->GetLayoutContextIndex(), pAct
->GetLayoutContextLen()));
994 case MetaActionType::STRETCHTEXT
:
996 MetaStretchTextAction
* pAct
= static_cast<MetaStretchTextAction
*>(pAction
);
997 aMtf
.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
998 pAct
->GetWidth(), pAct
->GetText(), pAct
->GetIndex(), pAct
->GetLen() ) );
1002 case MetaActionType::TEXTLINE
:
1004 MetaTextLineAction
* pAct
= static_cast<MetaTextLineAction
*>(pAction
);
1005 aMtf
.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct
->GetStartPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1006 pAct
->GetWidth(), pAct
->GetStrikeout(), pAct
->GetUnderline(), pAct
->GetOverline() ) );
1010 case MetaActionType::BMPSCALE
:
1012 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1013 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Polygon(tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() )), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1014 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1015 BitmapEx
aBmpEx( pAct
->GetBitmap() );
1017 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
1018 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(),
1023 case MetaActionType::BMPSCALEPART
:
1025 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1026 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Polygon(tools::Rectangle( pAct
->GetDestPoint(), pAct
->GetDestSize() )), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1027 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1028 BitmapEx
aBmpEx( pAct
->GetBitmap() );
1030 aBmpEx
.Crop( tools::Rectangle( pAct
->GetSrcPoint(), pAct
->GetSrcSize() ) );
1031 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
1033 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1037 case MetaActionType::BMPEXSCALE
:
1039 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1040 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Polygon(tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() )), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1041 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1042 BitmapEx
aBmpEx( pAct
->GetBitmapEx() );
1044 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
1046 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1050 case MetaActionType::BMPEXSCALEPART
:
1052 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1053 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Polygon(tools::Rectangle( pAct
->GetDestPoint(), pAct
->GetDestSize() )), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1054 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1055 BitmapEx
aBmpEx( pAct
->GetBitmapEx() );
1057 aBmpEx
.Crop( tools::Rectangle( pAct
->GetSrcPoint(), pAct
->GetSrcSize() ) );
1058 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
1060 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1064 case MetaActionType::GRADIENT
:
1066 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1068 ImplAddGradientEx( aMtf
, *aMapVDev
,
1069 tools::PolyPolygon(ImplGetRotatedPolygon( tools::Polygon(pAct
->GetRect()), aRotAnchor
, aRotOffset
, fSin
, fCos
)),
1070 pAct
->GetGradient() );
1074 case MetaActionType::GRADIENTEX
:
1076 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1077 aMtf
.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1078 pAct
->GetGradient() ) );
1082 // Handle gradientex comment block correctly
1083 case MetaActionType::COMMENT
:
1085 MetaCommentAction
* pCommentAct
= static_cast<MetaCommentAction
*>(pAction
);
1086 if( pCommentAct
->GetComment() == "XGRAD_SEQ_BEGIN" )
1088 int nBeginComments( 1 );
1089 pAction
= NextAction();
1091 // skip everything, except gradientex action
1094 const MetaActionType nType
= pAction
->GetType();
1096 if( MetaActionType::GRADIENTEX
== nType
)
1098 // Add rotated gradientex
1099 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1100 ImplAddGradientEx( aMtf
, *aMapVDev
,
1101 ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1102 pAct
->GetGradient() );
1104 else if( MetaActionType::COMMENT
== nType
)
1106 MetaCommentAction
* pAct
= static_cast<MetaCommentAction
*>(pAction
);
1107 if( pAct
->GetComment() == "XGRAD_SEQ_END" )
1109 // handle nested blocks
1112 // gradientex comment block: end reached, done.
1113 if( !nBeginComments
)
1116 else if( pAct
->GetComment() == "XGRAD_SEQ_BEGIN" )
1118 // handle nested blocks
1124 pAction
=NextAction();
1129 bool bPathStroke
= (pCommentAct
->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1130 if ( bPathStroke
|| pCommentAct
->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1132 if ( pCommentAct
->GetDataSize() )
1134 SvMemoryStream
aMemStm( const_cast<sal_uInt8
*>(pCommentAct
->GetData()), pCommentAct
->GetDataSize(), StreamMode::READ
);
1135 SvMemoryStream aDest
;
1138 SvtGraphicStroke aStroke
;
1139 ReadSvtGraphicStroke( aMemStm
, aStroke
);
1140 tools::Polygon aPath
;
1141 aStroke
.getPath( aPath
);
1142 aStroke
.setPath( ImplGetRotatedPolygon( aPath
, aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1143 WriteSvtGraphicStroke( aDest
, aStroke
);
1144 aMtf
.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN"_ostr
, 0,
1145 static_cast<const sal_uInt8
*>( aDest
.GetData()), aDest
.Tell() ) );
1149 SvtGraphicFill aFill
;
1150 ReadSvtGraphicFill( aMemStm
, aFill
);
1151 tools::PolyPolygon aPath
;
1152 aFill
.getPath( aPath
);
1153 aFill
.setPath( ImplGetRotatedPolyPolygon( aPath
, aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1154 WriteSvtGraphicFill( aDest
, aFill
);
1155 aMtf
.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN"_ostr
, 0,
1156 static_cast<const sal_uInt8
*>( aDest
.GetData()), aDest
.Tell() ) );
1160 else if ( pCommentAct
->GetComment() == "XPATHSTROKE_SEQ_END"
1161 || pCommentAct
->GetComment() == "XPATHFILL_SEQ_END" )
1163 pAction
->Execute( aMapVDev
.get() );
1164 aMtf
.AddAction( pAction
);
1170 case MetaActionType::HATCH
:
1172 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
1173 Hatch
aHatch( pAct
->GetHatch() );
1175 aHatch
.SetAngle( aHatch
.GetAngle() + nAngle10
);
1176 aMtf
.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1181 case MetaActionType::Transparent
:
1183 MetaTransparentAction
* pAct
= static_cast<MetaTransparentAction
*>(pAction
);
1184 aMtf
.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1185 pAct
->GetTransparence() ) );
1189 case MetaActionType::FLOATTRANSPARENT
:
1191 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
1192 GDIMetaFile
aTransMtf( pAct
->GetGDIMetaFile() );
1193 tools::Polygon
aMtfPoly( ImplGetRotatedPolygon( tools::Polygon(tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() )), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1194 tools::Rectangle
aMtfRect( aMtfPoly
.GetBoundRect() );
1196 aTransMtf
.Rotate( nAngle10
);
1197 aMtf
.AddAction( new MetaFloatTransparentAction( aTransMtf
, aMtfRect
.TopLeft(), aMtfRect
.GetSize(),
1198 pAct
->GetGradient() ) );
1202 case MetaActionType::EPS
:
1204 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
1205 GDIMetaFile
aEPSMtf( pAct
->GetSubstitute() );
1206 tools::Polygon
aEPSPoly( ImplGetRotatedPolygon( tools::Polygon(tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() )), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1207 tools::Rectangle
aEPSRect( aEPSPoly
.GetBoundRect() );
1209 aEPSMtf
.Rotate( nAngle10
);
1210 aMtf
.AddAction( new MetaEPSAction( aEPSRect
.TopLeft(), aEPSRect
.GetSize(),
1211 pAct
->GetLink(), aEPSMtf
) );
1215 case MetaActionType::CLIPREGION
:
1217 MetaClipRegionAction
* pAct
= static_cast<MetaClipRegionAction
*>(pAction
);
1219 if( pAct
->IsClipping() && pAct
->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1220 aMtf
.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct
->GetRegion().GetAsPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ), true ) );
1223 aMtf
.AddAction( pAction
);
1228 case MetaActionType::ISECTRECTCLIPREGION
:
1230 MetaISectRectClipRegionAction
* pAct
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
1231 aMtf
.AddAction( new MetaISectRegionClipRegionAction(vcl::Region(
1232 ImplGetRotatedPolygon( tools::Polygon(pAct
->GetRect()), aRotAnchor
,
1233 aRotOffset
, fSin
, fCos
)) ) );
1237 case MetaActionType::ISECTREGIONCLIPREGION
:
1239 MetaISectRegionClipRegionAction
* pAct
= static_cast<MetaISectRegionClipRegionAction
*>(pAction
);
1240 const vcl::Region
& rRegion
= pAct
->GetRegion();
1242 if( rRegion
.HasPolyPolygonOrB2DPolyPolygon() )
1243 aMtf
.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion
.GetAsPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) ) );
1246 aMtf
.AddAction( pAction
);
1251 case MetaActionType::REFPOINT
:
1253 MetaRefPointAction
* pAct
= static_cast<MetaRefPointAction
*>(pAction
);
1254 aMtf
.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct
->GetRefPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
), pAct
->IsSetting() ) );
1258 case MetaActionType::FONT
:
1260 MetaFontAction
* pAct
= static_cast<MetaFontAction
*>(pAction
);
1261 vcl::Font
aFont( pAct
->GetFont() );
1263 aFont
.SetOrientation( aFont
.GetOrientation() + nAngle10
);
1264 aMtf
.AddAction( new MetaFontAction( std::move(aFont
) ) );
1268 case MetaActionType::BMP
:
1269 case MetaActionType::BMPEX
:
1270 case MetaActionType::MASK
:
1271 case MetaActionType::MASKSCALE
:
1272 case MetaActionType::MASKSCALEPART
:
1273 case MetaActionType::WALLPAPER
:
1274 case MetaActionType::TEXTRECT
:
1275 case MetaActionType::MOVECLIPREGION
:
1277 OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1283 pAction
->Execute( aMapVDev
.get() );
1284 aMtf
.AddAction( pAction
);
1286 // update rotation point and offset, if necessary
1287 if( ( MetaActionType::MAPMODE
== nActionType
) ||
1288 ( MetaActionType::PUSH
== nActionType
) ||
1289 ( MetaActionType::POP
== nActionType
) )
1291 aRotAnchor
= OutputDevice::LogicToLogic( aOrigin
, m_aPrefMapMode
, aMapVDev
->GetMapMode() );
1292 aRotOffset
= OutputDevice::LogicToLogic( aOffset
, m_aPrefMapMode
, aMapVDev
->GetMapMode() );
1299 aMtf
.m_aPrefMapMode
= m_aPrefMapMode
;
1300 aMtf
.m_aPrefSize
= aNewBound
.GetSize();
1306 static void ImplActionBounds( tools::Rectangle
& o_rOutBounds
,
1307 const tools::Rectangle
& i_rInBounds
,
1308 const std::vector
<tools::Rectangle
>& i_rClipStack
)
1310 tools::Rectangle
aBounds( i_rInBounds
);
1311 if( ! i_rInBounds
.IsEmpty() && ! i_rClipStack
.empty() && ! i_rClipStack
.back().IsEmpty() )
1312 aBounds
.Intersection( i_rClipStack
.back() );
1313 if( aBounds
.IsEmpty() )
1316 if( ! o_rOutBounds
.IsEmpty() )
1317 o_rOutBounds
.Union( aBounds
);
1319 o_rOutBounds
= aBounds
;
1322 tools::Rectangle
GDIMetaFile::GetBoundRect( OutputDevice
& i_rReference
) const
1324 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev( i_rReference
);
1326 aMapVDev
->EnableOutput( false );
1327 aMapVDev
->SetMapMode( GetPrefMapMode() );
1329 std::vector
<tools::Rectangle
> aClipStack( 1, tools::Rectangle() );
1330 std::vector
<vcl::PushFlags
> aPushFlagStack
;
1332 tools::Rectangle aBound
;
1333 const sal_uLong
nCount(GetActionSize());
1335 for(sal_uLong
a(0); a
< nCount
; a
++)
1337 MetaAction
* pAction
= GetAction(a
);
1338 const MetaActionType nActionType
= pAction
->GetType();
1340 switch( nActionType
)
1342 case MetaActionType::PIXEL
:
1344 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
1345 ImplActionBounds( aBound
,
1346 tools::Rectangle( OutputDevice::LogicToLogic( pAct
->GetPoint(), aMapVDev
->GetMapMode(), GetPrefMapMode() ),
1347 aMapVDev
->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1352 case MetaActionType::POINT
:
1354 MetaPointAction
* pAct
= static_cast<MetaPointAction
*>(pAction
);
1355 ImplActionBounds( aBound
,
1356 tools::Rectangle( OutputDevice::LogicToLogic( pAct
->GetPoint(), aMapVDev
->GetMapMode(), GetPrefMapMode() ),
1357 aMapVDev
->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1362 case MetaActionType::LINE
:
1364 MetaLineAction
* pAct
= static_cast<MetaLineAction
*>(pAction
);
1365 Point
aP1( pAct
->GetStartPoint() ), aP2( pAct
->GetEndPoint() );
1366 tools::Rectangle
aRect( aP1
, aP2
);
1369 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1373 case MetaActionType::RECT
:
1375 MetaRectAction
* pAct
= static_cast<MetaRectAction
*>(pAction
);
1376 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1380 case MetaActionType::ROUNDRECT
:
1382 MetaRoundRectAction
* pAct
= static_cast<MetaRoundRectAction
*>(pAction
);
1383 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1387 case MetaActionType::ELLIPSE
:
1389 MetaEllipseAction
* pAct
= static_cast<MetaEllipseAction
*>(pAction
);
1390 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1394 case MetaActionType::ARC
:
1396 MetaArcAction
* pAct
= static_cast<MetaArcAction
*>(pAction
);
1397 // FIXME: this is imprecise
1398 // e.g. for small arcs the whole rectangle is WAY too large
1399 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1403 case MetaActionType::PIE
:
1405 MetaPieAction
* pAct
= static_cast<MetaPieAction
*>(pAction
);
1406 // FIXME: this is imprecise
1407 // e.g. for small arcs the whole rectangle is WAY too large
1408 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1412 case MetaActionType::CHORD
:
1414 MetaChordAction
* pAct
= static_cast<MetaChordAction
*>(pAction
);
1415 // FIXME: this is imprecise
1416 // e.g. for small arcs the whole rectangle is WAY too large
1417 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1421 case MetaActionType::POLYLINE
:
1423 MetaPolyLineAction
* pAct
= static_cast<MetaPolyLineAction
*>(pAction
);
1424 tools::Rectangle
aRect( pAct
->GetPolygon().GetBoundRect() );
1426 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1430 case MetaActionType::POLYGON
:
1432 MetaPolygonAction
* pAct
= static_cast<MetaPolygonAction
*>(pAction
);
1433 tools::Rectangle
aRect( pAct
->GetPolygon().GetBoundRect() );
1434 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1438 case MetaActionType::POLYPOLYGON
:
1440 MetaPolyPolygonAction
* pAct
= static_cast<MetaPolyPolygonAction
*>(pAction
);
1441 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1442 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1446 case MetaActionType::TEXT
:
1448 MetaTextAction
* pAct
= static_cast<MetaTextAction
*>(pAction
);
1449 tools::Rectangle aRect
;
1450 // hdu said base = index
1451 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen() );
1452 Point
aPt( pAct
->GetPoint() );
1453 aRect
.Move( aPt
.X(), aPt
.Y() );
1454 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1458 case MetaActionType::TEXTARRAY
:
1460 MetaTextArrayAction
* pAct
= static_cast<MetaTextArrayAction
*>(pAction
);
1461 tools::Rectangle aRect
;
1462 // hdu said base = index
1463 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen(),
1464 0, pAct
->GetDXArray(), pAct
->GetKashidaArray() );
1465 Point
aPt( pAct
->GetPoint() );
1466 aRect
.Move( aPt
.X(), aPt
.Y() );
1467 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1471 case MetaActionType::STRETCHTEXT
:
1473 MetaStretchTextAction
* pAct
= static_cast<MetaStretchTextAction
*>(pAction
);
1474 tools::Rectangle aRect
;
1475 // hdu said base = index
1476 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen(),
1478 Point
aPt( pAct
->GetPoint() );
1479 aRect
.Move( aPt
.X(), aPt
.Y() );
1480 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1484 case MetaActionType::TEXTLINE
:
1486 MetaTextLineAction
* pAct
= static_cast<MetaTextLineAction
*>(pAction
);
1487 // measure a test string to get ascend and descent right
1488 static constexpr OUStringLiteral pStr
= u
"\u00c4g";
1489 OUString
aStr( pStr
);
1491 tools::Rectangle aRect
;
1492 aMapVDev
->GetTextBoundRect( aRect
, aStr
, 0, 0, aStr
.getLength() );
1493 Point
aPt( pAct
->GetStartPoint() );
1494 aRect
.Move( aPt
.X(), aPt
.Y() );
1495 aRect
.SetRight( aRect
.Left() + pAct
->GetWidth() );
1496 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1500 case MetaActionType::BMPSCALE
:
1502 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1503 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1504 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1508 case MetaActionType::BMPSCALEPART
:
1510 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1511 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1512 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1516 case MetaActionType::BMPEXSCALE
:
1518 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1519 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1520 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1524 case MetaActionType::BMPEXSCALEPART
:
1526 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1527 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1528 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1532 case MetaActionType::GRADIENT
:
1534 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1535 tools::Rectangle
aRect( pAct
->GetRect() );
1536 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1540 case MetaActionType::GRADIENTEX
:
1542 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1543 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1544 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1548 case MetaActionType::COMMENT
:
1554 case MetaActionType::HATCH
:
1556 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
1557 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1558 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1562 case MetaActionType::Transparent
:
1564 MetaTransparentAction
* pAct
= static_cast<MetaTransparentAction
*>(pAction
);
1565 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1566 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1570 case MetaActionType::FLOATTRANSPARENT
:
1572 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
1573 // MetaFloatTransparentAction is defined limiting its content Metafile
1574 // to its geometry definition(Point, Size), so use these directly
1575 const tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1576 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1580 case MetaActionType::EPS
:
1582 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
1583 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1584 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1588 case MetaActionType::CLIPREGION
:
1590 MetaClipRegionAction
* pAct
= static_cast<MetaClipRegionAction
*>(pAction
);
1591 if( pAct
->IsClipping() )
1592 aClipStack
.back() = OutputDevice::LogicToLogic( pAct
->GetRegion().GetBoundRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() );
1594 aClipStack
.back() = tools::Rectangle();
1598 case MetaActionType::ISECTRECTCLIPREGION
:
1600 MetaISectRectClipRegionAction
* pAct
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
1601 tools::Rectangle
aRect( OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ) );
1602 if( aClipStack
.back().IsEmpty() )
1603 aClipStack
.back() = aRect
;
1605 aClipStack
.back().Intersection( aRect
);
1609 case MetaActionType::ISECTREGIONCLIPREGION
:
1611 MetaISectRegionClipRegionAction
* pAct
= static_cast<MetaISectRegionClipRegionAction
*>(pAction
);
1612 tools::Rectangle
aRect( OutputDevice::LogicToLogic( pAct
->GetRegion().GetBoundRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ) );
1613 if( aClipStack
.back().IsEmpty() )
1614 aClipStack
.back() = aRect
;
1616 aClipStack
.back().Intersection( aRect
);
1620 case MetaActionType::BMP
:
1622 MetaBmpAction
* pAct
= static_cast<MetaBmpAction
*>(pAction
);
1623 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmap().GetSizePixel() ) );
1624 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1628 case MetaActionType::BMPEX
:
1630 MetaBmpExAction
* pAct
= static_cast<MetaBmpExAction
*>(pAction
);
1631 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmapEx().GetSizePixel() ) );
1632 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1636 case MetaActionType::MASK
:
1638 MetaMaskAction
* pAct
= static_cast<MetaMaskAction
*>(pAction
);
1639 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmap().GetSizePixel() ) );
1640 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1644 case MetaActionType::MASKSCALE
:
1646 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1647 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1648 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1652 case MetaActionType::MASKSCALEPART
:
1654 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1655 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1656 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1660 case MetaActionType::WALLPAPER
:
1662 MetaWallpaperAction
* pAct
= static_cast<MetaWallpaperAction
*>(pAction
);
1663 tools::Rectangle
aRect( pAct
->GetRect() );
1664 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1668 case MetaActionType::TEXTRECT
:
1670 MetaTextRectAction
* pAct
= static_cast<MetaTextRectAction
*>(pAction
);
1671 tools::Rectangle
aRect( pAct
->GetRect() );
1672 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
);
1676 case MetaActionType::MOVECLIPREGION
:
1678 MetaMoveClipRegionAction
* pAct
= static_cast<MetaMoveClipRegionAction
*>(pAction
);
1679 if( ! aClipStack
.back().IsEmpty() )
1681 Size
aDelta( pAct
->GetHorzMove(), pAct
->GetVertMove() );
1682 aDelta
= OutputDevice::LogicToLogic( aDelta
, aMapVDev
->GetMapMode(), GetPrefMapMode() );
1683 aClipStack
.back().Move( aDelta
.Width(), aDelta
.Width() );
1690 pAction
->Execute( aMapVDev
.get() );
1692 if( nActionType
== MetaActionType::PUSH
)
1694 MetaPushAction
* pAct
= static_cast<MetaPushAction
*>(pAction
);
1695 aPushFlagStack
.push_back( pAct
->GetFlags() );
1696 if( aPushFlagStack
.back() & vcl::PushFlags::CLIPREGION
)
1698 tools::Rectangle
aRect( aClipStack
.back() );
1699 aClipStack
.push_back( aRect
);
1702 else if( nActionType
== MetaActionType::POP
)
1705 if( ! aPushFlagStack
.empty() )
1707 if( aPushFlagStack
.back() & vcl::PushFlags::CLIPREGION
)
1709 if( aClipStack
.size() > 1 )
1710 aClipStack
.pop_back();
1712 aPushFlagStack
.pop_back();
1722 Color
GDIMetaFile::ImplColAdjustFnc( const Color
& rColor
, const void* pColParam
)
1724 return Color( ColorAlpha
, rColor
.GetAlpha(),
1725 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapR
[ rColor
.GetRed() ],
1726 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapG
[ rColor
.GetGreen() ],
1727 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapB
[ rColor
.GetBlue() ] );
1731 BitmapEx
GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1733 const ImplBmpAdjustParam
* p
= static_cast<const ImplBmpAdjustParam
*>(pBmpParam
);
1734 BitmapEx
aRet( rBmpEx
);
1736 aRet
.Adjust( p
->nLuminancePercent
, p
->nContrastPercent
,
1737 p
->nChannelRPercent
, p
->nChannelGPercent
, p
->nChannelBPercent
,
1738 p
->fGamma
, p
->bInvert
);
1743 Color
GDIMetaFile::ImplColConvertFnc( const Color
& rColor
, const void* pColParam
)
1745 sal_uInt8 cLum
= rColor
.GetLuminance();
1747 if( MtfConversion::N1BitThreshold
== static_cast<const ImplColConvertParam
*>(pColParam
)->eConversion
)
1748 cLum
= ( cLum
< 128 ) ? 0 : 255;
1750 return Color( ColorAlpha
, rColor
.GetAlpha(), cLum
, cLum
, cLum
);
1753 BitmapEx
GDIMetaFile::ImplBmpConvertFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1755 BitmapEx
aRet( rBmpEx
);
1757 aRet
.Convert( static_cast<const ImplBmpConvertParam
*>(pBmpParam
)->eConversion
);
1762 Color
GDIMetaFile::ImplColMonoFnc( const Color
&, const void* pColParam
)
1764 return static_cast<const ImplColMonoParam
*>(pColParam
)->aColor
;
1767 BitmapEx
GDIMetaFile::ImplBmpMonoFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1769 BitmapPalette
aPal( 3 );
1770 aPal
[ 0 ] = COL_BLACK
;
1771 aPal
[ 1 ] = COL_WHITE
;
1772 aPal
[ 2 ] = static_cast<const ImplBmpMonoParam
*>(pBmpParam
)->aColor
;
1774 Bitmap
aBmp(rBmpEx
.GetSizePixel(), vcl::PixelFormat::N8_BPP
, &aPal
);
1775 aBmp
.Erase( static_cast<const ImplBmpMonoParam
*>(pBmpParam
)->aColor
);
1777 if( rBmpEx
.IsAlpha() )
1778 return BitmapEx( aBmp
, rBmpEx
.GetAlphaMask() );
1780 return BitmapEx( aBmp
);
1783 Color
GDIMetaFile::ImplColReplaceFnc( const Color
& rColor
, const void* pColParam
)
1785 const sal_uLong nR
= rColor
.GetRed(), nG
= rColor
.GetGreen(), nB
= rColor
.GetBlue();
1787 for( sal_uLong i
= 0; i
< static_cast<const ImplColReplaceParam
*>(pColParam
)->nCount
; i
++ )
1789 if( ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinR
[ i
] <= nR
) &&
1790 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxR
[ i
] >= nR
) &&
1791 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinG
[ i
] <= nG
) &&
1792 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxG
[ i
] >= nG
) &&
1793 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinB
[ i
] <= nB
) &&
1794 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxB
[ i
] >= nB
) )
1796 return static_cast<const ImplColReplaceParam
*>(pColParam
)->pDstCols
[ i
];
1803 BitmapEx
GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1805 const ImplBmpReplaceParam
* p
= static_cast<const ImplBmpReplaceParam
*>(pBmpParam
);
1806 BitmapEx
aRet( rBmpEx
);
1808 aRet
.Replace( p
->pSrcCols
, p
->pDstCols
, p
->nCount
);
1813 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol
, const void* pColParam
,
1814 BmpExchangeFnc pFncBmp
, const void* pBmpParam
)
1818 aMtf
.m_aPrefSize
= m_aPrefSize
;
1819 aMtf
.m_aPrefMapMode
= m_aPrefMapMode
;
1820 aMtf
.m_bUseCanvas
= m_bUseCanvas
;
1821 aMtf
.m_bSVG
= m_bSVG
;
1823 for( MetaAction
* pAction
= FirstAction(); pAction
; pAction
= NextAction() )
1825 const MetaActionType nType
= pAction
->GetType();
1829 case MetaActionType::PIXEL
:
1831 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
1832 aMtf
.push_back( new MetaPixelAction( pAct
->GetPoint(), pFncCol( pAct
->GetColor(), pColParam
) ) );
1836 case MetaActionType::LINECOLOR
:
1838 MetaLineColorAction
* pAct
= static_cast<MetaLineColorAction
*>(pAction
);
1840 if( pAct
->IsSetting() )
1841 pAct
= new MetaLineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1843 aMtf
.push_back( pAct
);
1847 case MetaActionType::FILLCOLOR
:
1849 MetaFillColorAction
* pAct
= static_cast<MetaFillColorAction
*>(pAction
);
1851 if( pAct
->IsSetting() )
1852 pAct
= new MetaFillColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1854 aMtf
.push_back( pAct
);
1858 case MetaActionType::TEXTCOLOR
:
1860 MetaTextColorAction
* pAct
= static_cast<MetaTextColorAction
*>(pAction
);
1861 aMtf
.push_back( new MetaTextColorAction( pFncCol( pAct
->GetColor(), pColParam
) ) );
1865 case MetaActionType::TEXTFILLCOLOR
:
1867 MetaTextFillColorAction
* pAct
= static_cast<MetaTextFillColorAction
*>(pAction
);
1869 if( pAct
->IsSetting() )
1870 pAct
= new MetaTextFillColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1872 aMtf
.push_back( pAct
);
1876 case MetaActionType::TEXTLINECOLOR
:
1878 MetaTextLineColorAction
* pAct
= static_cast<MetaTextLineColorAction
*>(pAction
);
1880 if( pAct
->IsSetting() )
1881 pAct
= new MetaTextLineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1883 aMtf
.push_back( pAct
);
1887 case MetaActionType::OVERLINECOLOR
:
1889 MetaOverlineColorAction
* pAct
= static_cast<MetaOverlineColorAction
*>(pAction
);
1891 if( pAct
->IsSetting() )
1892 pAct
= new MetaOverlineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1894 aMtf
.push_back( pAct
);
1898 case MetaActionType::FONT
:
1900 MetaFontAction
* pAct
= static_cast<MetaFontAction
*>(pAction
);
1901 vcl::Font
aFont( pAct
->GetFont() );
1903 aFont
.SetColor( pFncCol( aFont
.GetColor(), pColParam
) );
1904 aFont
.SetFillColor( pFncCol( aFont
.GetFillColor(), pColParam
) );
1905 aMtf
.push_back( new MetaFontAction( std::move(aFont
) ) );
1909 case MetaActionType::WALLPAPER
:
1911 MetaWallpaperAction
* pAct
= static_cast<MetaWallpaperAction
*>(pAction
);
1912 Wallpaper
aWall( pAct
->GetWallpaper() );
1913 const tools::Rectangle
& rRect
= pAct
->GetRect();
1915 aWall
.SetColor( pFncCol( aWall
.GetColor(), pColParam
) );
1917 if( aWall
.IsBitmap() )
1918 aWall
.SetBitmap( pFncBmp( aWall
.GetBitmap(), pBmpParam
) );
1920 if( aWall
.IsGradient() )
1922 Gradient
aGradient( aWall
.GetGradient() );
1924 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
1925 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
1926 aWall
.SetGradient( aGradient
);
1929 aMtf
.push_back( new MetaWallpaperAction( rRect
, std::move(aWall
) ) );
1933 case MetaActionType::BMP
:
1934 case MetaActionType::BMPEX
:
1935 case MetaActionType::MASK
:
1937 OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
1941 case MetaActionType::BMPSCALE
:
1943 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1944 aMtf
.push_back( new MetaBmpScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
1945 pFncBmp( BitmapEx(pAct
->GetBitmap()), pBmpParam
).GetBitmap() ) );
1949 case MetaActionType::BMPSCALEPART
:
1951 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1952 aMtf
.push_back( new MetaBmpScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
1953 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
1954 pFncBmp( BitmapEx(pAct
->GetBitmap()), pBmpParam
).GetBitmap() )
1959 case MetaActionType::BMPEXSCALE
:
1961 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1962 aMtf
.push_back( new MetaBmpExScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
1963 pFncBmp( pAct
->GetBitmapEx(), pBmpParam
) )
1968 case MetaActionType::BMPEXSCALEPART
:
1970 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1971 aMtf
.push_back( new MetaBmpExScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
1972 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
1973 pFncBmp( pAct
->GetBitmapEx(), pBmpParam
) )
1978 case MetaActionType::MASKSCALE
:
1980 MetaMaskScaleAction
* pAct
= static_cast<MetaMaskScaleAction
*>(pAction
);
1981 aMtf
.push_back( new MetaMaskScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
1983 pFncCol( pAct
->GetColor(), pColParam
) )
1988 case MetaActionType::MASKSCALEPART
:
1990 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1991 aMtf
.push_back( new MetaMaskScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
1992 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
1994 pFncCol( pAct
->GetColor(), pColParam
) )
1999 case MetaActionType::GRADIENT
:
2001 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
2002 Gradient
aGradient( pAct
->GetGradient() );
2004 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
2005 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
2006 aMtf
.push_back( new MetaGradientAction( pAct
->GetRect(), std::move(aGradient
) ) );
2010 case MetaActionType::GRADIENTEX
:
2012 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
2013 Gradient
aGradient( pAct
->GetGradient() );
2015 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
2016 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
2017 aMtf
.push_back( new MetaGradientExAction( pAct
->GetPolyPolygon(), std::move(aGradient
) ) );
2021 case MetaActionType::HATCH
:
2023 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
2024 Hatch
aHatch( pAct
->GetHatch() );
2026 aHatch
.SetColor( pFncCol( aHatch
.GetColor(), pColParam
) );
2027 aMtf
.push_back( new MetaHatchAction( pAct
->GetPolyPolygon(), aHatch
) );
2031 case MetaActionType::FLOATTRANSPARENT
:
2033 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
2034 GDIMetaFile
aTransMtf( pAct
->GetGDIMetaFile() );
2036 aTransMtf
.ImplExchangeColors( pFncCol
, pColParam
, pFncBmp
, pBmpParam
);
2037 aMtf
.push_back( new MetaFloatTransparentAction( aTransMtf
,
2038 pAct
->GetPoint(), pAct
->GetSize(),
2039 pAct
->GetGradient() )
2044 case MetaActionType::EPS
:
2046 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
2047 GDIMetaFile
aSubst( pAct
->GetSubstitute() );
2049 aSubst
.ImplExchangeColors( pFncCol
, pColParam
, pFncBmp
, pBmpParam
);
2050 aMtf
.push_back( new MetaEPSAction( pAct
->GetPoint(), pAct
->GetSize(),
2051 pAct
->GetLink(), aSubst
)
2058 aMtf
.push_back( pAction
);
2067 void GDIMetaFile::Adjust( short nLuminancePercent
, short nContrastPercent
,
2068 short nChannelRPercent
, short nChannelGPercent
,
2069 short nChannelBPercent
, double fGamma
, bool bInvert
, bool msoBrightness
)
2071 // nothing to do? => return quickly
2072 if( !(nLuminancePercent
|| nContrastPercent
||
2073 nChannelRPercent
|| nChannelGPercent
|| nChannelBPercent
||
2074 ( fGamma
!= 1.0 ) || bInvert
) )
2077 double fM
, fROff
, fGOff
, fBOff
, fOff
;
2078 ImplColAdjustParam aColParam
;
2079 ImplBmpAdjustParam aBmpParam
;
2081 aColParam
.pMapR
.reset(new sal_uInt8
[ 256 ]);
2082 aColParam
.pMapG
.reset(new sal_uInt8
[ 256 ]);
2083 aColParam
.pMapB
.reset(new sal_uInt8
[ 256 ]);
2086 if( nContrastPercent
>= 0 )
2087 fM
= 128.0 / ( 128.0 - 1.27 * std::clamp( nContrastPercent
, short(0), short(100) ) );
2089 fM
= ( 128.0 + 1.27 * std::clamp( nContrastPercent
, short(-100), short(0) ) ) / 128.0;
2092 // total offset = luminance offset + contrast offset
2093 fOff
= std::clamp( nLuminancePercent
, short(-100), short(100) ) * 2.55 + 128.0 - fM
* 128.0;
2095 fOff
= std::clamp( nLuminancePercent
, short(-100), short(100) ) * 2.55;
2097 // channel offset = channel offset + total offset
2098 fROff
= nChannelRPercent
* 2.55 + fOff
;
2099 fGOff
= nChannelGPercent
* 2.55 + fOff
;
2100 fBOff
= nChannelBPercent
* 2.55 + fOff
;
2102 // calculate gamma value
2103 fGamma
= ( fGamma
<= 0.0 || fGamma
> 10.0 ) ? 1.0 : ( 1.0 / fGamma
);
2104 const bool bGamma
= ( fGamma
!= 1.0 );
2106 // create mapping table
2107 for( tools::Long nX
= 0; nX
< 256; nX
++ )
2111 aColParam
.pMapR
[nX
] = basegfx::fround
<sal_uInt8
>(nX
* fM
+ fROff
);
2112 aColParam
.pMapG
[nX
] = basegfx::fround
<sal_uInt8
>(nX
* fM
+ fGOff
);
2113 aColParam
.pMapB
[nX
] = basegfx::fround
<sal_uInt8
>(nX
* fM
+ fBOff
);
2117 aColParam
.pMapR
[nX
] = basegfx::fround
<sal_uInt8
>((nX
+fROff
/2-128) * fM
+ 128 + fROff
/2);
2118 aColParam
.pMapG
[nX
] = basegfx::fround
<sal_uInt8
>((nX
+fGOff
/2-128) * fM
+ 128 + fGOff
/2);
2119 aColParam
.pMapB
[nX
] = basegfx::fround
<sal_uInt8
>((nX
+fBOff
/2-128) * fM
+ 128 + fBOff
/2);
2123 aColParam
.pMapR
[ nX
] = GAMMA( aColParam
.pMapR
[ nX
], fGamma
);
2124 aColParam
.pMapG
[ nX
] = GAMMA( aColParam
.pMapG
[ nX
], fGamma
);
2125 aColParam
.pMapB
[ nX
] = GAMMA( aColParam
.pMapB
[ nX
], fGamma
);
2130 aColParam
.pMapR
[ nX
] = ~aColParam
.pMapR
[ nX
];
2131 aColParam
.pMapG
[ nX
] = ~aColParam
.pMapG
[ nX
];
2132 aColParam
.pMapB
[ nX
] = ~aColParam
.pMapB
[ nX
];
2136 aBmpParam
.nLuminancePercent
= nLuminancePercent
;
2137 aBmpParam
.nContrastPercent
= nContrastPercent
;
2138 aBmpParam
.nChannelRPercent
= nChannelRPercent
;
2139 aBmpParam
.nChannelGPercent
= nChannelGPercent
;
2140 aBmpParam
.nChannelBPercent
= nChannelBPercent
;
2141 aBmpParam
.fGamma
= fGamma
;
2142 aBmpParam
.bInvert
= bInvert
;
2144 // do color adjustment
2145 ImplExchangeColors( ImplColAdjustFnc
, &aColParam
, ImplBmpAdjustFnc
, &aBmpParam
);
2148 void GDIMetaFile::Convert( MtfConversion eConversion
)
2150 ImplColConvertParam aColParam
;
2151 ImplBmpConvertParam aBmpParam
;
2153 aColParam
.eConversion
= eConversion
;
2154 aBmpParam
.eConversion
= ( MtfConversion::N1BitThreshold
== eConversion
) ? BmpConversion::N1BitThreshold
: BmpConversion::N8BitGreys
;
2156 ImplExchangeColors( ImplColConvertFnc
, &aColParam
, ImplBmpConvertFnc
, &aBmpParam
);
2159 void GDIMetaFile::ReplaceColors( const Color
* pSearchColors
, const Color
* pReplaceColors
, sal_uLong nColorCount
)
2161 ImplColReplaceParam aColParam
;
2162 ImplBmpReplaceParam aBmpParam
;
2164 aColParam
.pMinR
.reset(new sal_uLong
[ nColorCount
]);
2165 aColParam
.pMaxR
.reset(new sal_uLong
[ nColorCount
]);
2166 aColParam
.pMinG
.reset(new sal_uLong
[ nColorCount
]);
2167 aColParam
.pMaxG
.reset(new sal_uLong
[ nColorCount
]);
2168 aColParam
.pMinB
.reset(new sal_uLong
[ nColorCount
]);
2169 aColParam
.pMaxB
.reset(new sal_uLong
[ nColorCount
]);
2171 for( sal_uLong i
= 0; i
< nColorCount
; i
++ )
2175 nVal
= pSearchColors
[ i
].GetRed();
2176 aColParam
.pMinR
[ i
] = static_cast<sal_uLong
>(std::max( nVal
, tools::Long(0) ));
2177 aColParam
.pMaxR
[ i
] = static_cast<sal_uLong
>(std::min( nVal
, tools::Long(255) ));
2179 nVal
= pSearchColors
[ i
].GetGreen();
2180 aColParam
.pMinG
[ i
] = static_cast<sal_uLong
>(std::max( nVal
, tools::Long(0) ));
2181 aColParam
.pMaxG
[ i
] = static_cast<sal_uLong
>(std::min( nVal
, tools::Long(255) ));
2183 nVal
= pSearchColors
[ i
].GetBlue();
2184 aColParam
.pMinB
[ i
] = static_cast<sal_uLong
>(std::max( nVal
, tools::Long(0) ));
2185 aColParam
.pMaxB
[ i
] = static_cast<sal_uLong
>(std::min( nVal
, tools::Long(255) ));
2188 aColParam
.pDstCols
= pReplaceColors
;
2189 aColParam
.nCount
= nColorCount
;
2191 aBmpParam
.pSrcCols
= pSearchColors
;
2192 aBmpParam
.pDstCols
= pReplaceColors
;
2193 aBmpParam
.nCount
= nColorCount
;
2195 ImplExchangeColors( ImplColReplaceFnc
, &aColParam
, ImplBmpReplaceFnc
, &aBmpParam
);
2198 GDIMetaFile
GDIMetaFile::GetMonochromeMtf( const Color
& rColor
) const
2200 GDIMetaFile
aRet( *this );
2202 ImplColMonoParam aColParam
;
2203 ImplBmpMonoParam aBmpParam
;
2205 aColParam
.aColor
= rColor
;
2206 aBmpParam
.aColor
= rColor
;
2208 aRet
.ImplExchangeColors( ImplColMonoFnc
, &aColParam
, ImplBmpMonoFnc
, &aBmpParam
);
2213 sal_uLong
GDIMetaFile::GetSizeBytes() const
2215 sal_uLong nSizeBytes
= 0;
2217 for( size_t i
= 0, nObjCount
= GetActionSize(); i
< nObjCount
; ++i
)
2219 MetaAction
* pAction
= GetAction( i
);
2221 // default action size is set to 32 (=> not the exact value)
2224 // add sizes for large action content
2225 switch( pAction
->GetType() )
2227 case MetaActionType::BMP
: nSizeBytes
+= static_cast<MetaBmpAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2228 case MetaActionType::BMPSCALE
: nSizeBytes
+= static_cast<MetaBmpScaleAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2229 case MetaActionType::BMPSCALEPART
: nSizeBytes
+= static_cast<MetaBmpScalePartAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2231 case MetaActionType::BMPEX
: nSizeBytes
+= static_cast<MetaBmpExAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2232 case MetaActionType::BMPEXSCALE
: nSizeBytes
+= static_cast<MetaBmpExScaleAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2233 case MetaActionType::BMPEXSCALEPART
: nSizeBytes
+= static_cast<MetaBmpExScalePartAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2235 case MetaActionType::MASK
: nSizeBytes
+= static_cast<MetaMaskAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2236 case MetaActionType::MASKSCALE
: nSizeBytes
+= static_cast<MetaMaskScaleAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2237 case MetaActionType::MASKSCALEPART
: nSizeBytes
+= static_cast<MetaMaskScalePartAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2239 case MetaActionType::POLYLINE
: nSizeBytes
+= static_cast<MetaPolyLineAction
*>( pAction
)->GetPolygon().GetSize() * sizeof( Point
); break;
2240 case MetaActionType::POLYGON
: nSizeBytes
+= static_cast<MetaPolygonAction
*>( pAction
)->GetPolygon().GetSize() * sizeof( Point
); break;
2241 case MetaActionType::POLYPOLYGON
:
2243 const tools::PolyPolygon
& rPolyPoly
= static_cast<MetaPolyPolygonAction
*>( pAction
)->GetPolyPolygon();
2245 for( sal_uInt16 n
= 0; n
< rPolyPoly
.Count(); ++n
)
2246 nSizeBytes
+= ( rPolyPoly
[ n
].GetSize() * sizeof( Point
) );
2250 case MetaActionType::TEXT
: nSizeBytes
+= static_cast<MetaTextAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2251 case MetaActionType::STRETCHTEXT
: nSizeBytes
+= static_cast<MetaStretchTextAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2252 case MetaActionType::TEXTRECT
: nSizeBytes
+= static_cast<MetaTextRectAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2253 case MetaActionType::TEXTARRAY
:
2255 MetaTextArrayAction
* pTextArrayAction
= static_cast<MetaTextArrayAction
*>(pAction
);
2257 nSizeBytes
+= ( pTextArrayAction
->GetText().getLength() * sizeof( sal_Unicode
) );
2259 if( !pTextArrayAction
->GetDXArray().empty() )
2260 nSizeBytes
+= ( pTextArrayAction
->GetLen() << 2 );
2270 bool GDIMetaFile::CreateThumbnail(BitmapEx
& rBitmapEx
, BmpConversion eColorConversion
, BmpScaleFlag nScaleFlag
) const
2272 // initialization seems to be complicated but is used to avoid rounding errors
2273 ScopedVclPtrInstance
< VirtualDevice
> aVDev
;
2274 // set Enable to tease the rendering down the code paths which use B2DPolygon and
2275 // avoid integer overflows on scaling tools::Polygon, e.g. moz1545040-1.svg
2276 // note: this is similar to DocumentToGraphicRenderer::renderToGraphic
2277 aVDev
->SetAntialiasing(AntialiasingFlags::Enable
| aVDev
->GetAntialiasing());
2278 const Point aNullPt
;
2279 const Point
aTLPix( aVDev
->LogicToPixel( aNullPt
, GetPrefMapMode() ) );
2280 const Point
aBRPix( aVDev
->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2281 Size
aDrawSize( aVDev
->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2282 Size
aSizePix( std::abs( aBRPix
.X() - aTLPix
.X() ) + 1, std::abs( aBRPix
.Y() - aTLPix
.Y() ) + 1 );
2283 sal_uInt32 nMaximumExtent
= 512;
2285 if (!rBitmapEx
.IsEmpty())
2286 rBitmapEx
.SetEmpty();
2288 // determine size that has the same aspect ratio as image size and
2289 // fits into the rectangle determined by nMaximumExtent
2290 if ( aSizePix
.Width() && aSizePix
.Height()
2291 && ( sal::static_int_cast
< tools::ULong
>(aSizePix
.Width()) >
2293 sal::static_int_cast
< tools::ULong
>(aSizePix
.Height()) >
2296 const Size
aOldSizePix( aSizePix
);
2297 double fWH
= static_cast< double >( aSizePix
.Width() ) / aSizePix
.Height();
2301 aSizePix
.setWidth(basegfx::fround
<tools::Long
>(nMaximumExtent
* fWH
));
2302 aSizePix
.setHeight( nMaximumExtent
);
2306 aSizePix
.setWidth( nMaximumExtent
);
2307 aSizePix
.setHeight(basegfx::fround
<tools::Long
>(nMaximumExtent
/ fWH
));
2310 aDrawSize
.setWidth( basegfx::fround
<tools::Long
>( ( static_cast< double >( aDrawSize
.Width() ) * aSizePix
.Width() ) / aOldSizePix
.Width() ) );
2311 aDrawSize
.setHeight( basegfx::fround
<tools::Long
>( ( static_cast< double >( aDrawSize
.Height() ) * aSizePix
.Height() ) / aOldSizePix
.Height() ) );
2314 // draw image(s) into VDev and get resulting image
2315 // do it 4x larger to be able to scale it down & get beautiful antialias
2316 Size
aAntialiasSize(aSizePix
.Width() * 4, aSizePix
.Height() * 4);
2317 if (aVDev
->SetOutputSizePixel(aAntialiasSize
))
2319 // antialias: provide 4x larger size, and then scale down the result
2320 Size
aAntialias(aDrawSize
.Width() * 4, aDrawSize
.Height() * 4);
2322 // draw metafile into VDev
2323 const_cast<GDIMetaFile
*>(this)->WindStart();
2324 const_cast<GDIMetaFile
*>(this)->Play(*aVDev
, Point(), aAntialias
);
2327 BitmapEx
aBitmap( aVDev
->GetBitmapEx( aNullPt
, aVDev
->GetOutputSizePixel() ) );
2329 // scale down the image to the desired size - use the input scaler for the scaling operation
2330 aBitmap
.Scale(aDrawSize
, nScaleFlag
);
2332 // convert to desired bitmap color format
2333 Size
aSize(aBitmap
.GetSizePixel());
2334 if (aSize
.Width() && aSize
.Height())
2335 aBitmap
.Convert(eColorConversion
);
2337 rBitmapEx
= aBitmap
;
2340 return !rBitmapEx
.IsEmpty();
2343 void GDIMetaFile::UseCanvas( bool _bUseCanvas
)
2345 m_bUseCanvas
= _bUseCanvas
;
2348 void GDIMetaFile::dumpAsXml(const char* pFileName
) const
2350 SvFileStream
aStream(pFileName
? OUString::fromUtf8(pFileName
) : u
"file:///tmp/metafile.xml"_ustr
,
2351 StreamMode::STD_READWRITE
| StreamMode::TRUNC
);
2352 assert(aStream
.good());
2353 MetafileXmlDump aDumper
;
2354 aDumper
.dump(*this, aStream
);
2357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */