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 <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>
37 #include <basegfx/polygon/b2dpolygon.hxx>
38 #include <vcl/canvastools.hxx>
39 #include <vcl/mtfxmldump.hxx>
41 #include <svmconverter.hxx>
42 #include <vcl/TypeSerializer.hxx>
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>
48 #include <comphelper/processfactory.hxx>
50 using namespace com::sun::star
;
54 struct ImplColAdjustParam
56 std::unique_ptr
<sal_uInt8
[]> pMapR
;
57 std::unique_ptr
<sal_uInt8
[]> pMapG
;
58 std::unique_ptr
<sal_uInt8
[]> pMapB
;
61 struct ImplBmpAdjustParam
63 short nLuminancePercent
;
64 short nContrastPercent
;
65 short nChannelRPercent
;
66 short nChannelGPercent
;
67 short nChannelBPercent
;
72 struct ImplColConvertParam
74 MtfConversion eConversion
;
77 struct ImplBmpConvertParam
79 BmpConversion eConversion
;
82 struct ImplColMonoParam
87 struct ImplBmpMonoParam
92 struct ImplColReplaceParam
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
;
104 struct ImplBmpReplaceParam
106 const Color
* pSrcCols
;
107 const Color
* pDstCols
;
113 GDIMetaFile::GDIMetaFile() :
114 m_nCurrentActionElement( 0 ),
115 m_aPrefSize ( 1, 1 ),
118 m_pOutDev ( nullptr ),
121 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
)
136 for( size_t i
= 0, n
= rMtf
.GetActionSize(); i
< n
; ++i
)
138 m_aList
.push_back( rMtf
.GetAction( i
) );
143 Record( rMtf
.m_pOutDev
);
150 GDIMetaFile::~GDIMetaFile()
155 bool GDIMetaFile::HasTransparentActions() const
157 MetaAction
* pCurrAct
;
159 // watch for transparent drawing actions
160 for(pCurrAct
= const_cast<GDIMetaFile
*>(this)->FirstAction();
162 pCurrAct
= const_cast<GDIMetaFile
*>(this)->NextAction())
164 // #i10613# determine if the action is transparency capable
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
173 if (pCurrAct
->IsTransparent())
180 size_t GDIMetaFile::GetActionSize() const
182 return m_aList
.size();
185 MetaAction
* GDIMetaFile::GetAction( size_t nAction
) const
187 return (nAction
< m_aList
.size()) ? m_aList
[ nAction
].get() : nullptr;
190 MetaAction
* GDIMetaFile::FirstAction()
192 m_nCurrentActionElement
= 0;
193 return m_aList
.empty() ? nullptr : m_aList
[ 0 ].get();
196 MetaAction
* GDIMetaFile::NextAction()
198 return ( m_nCurrentActionElement
+ 1 < m_aList
.size() ) ? m_aList
[ ++m_nCurrentActionElement
].get() : nullptr;
201 void GDIMetaFile::ReplaceAction( rtl::Reference
<MetaAction
> pAction
, size_t nAction
)
203 if ( nAction
>= m_aList
.size() )
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
]);
212 GDIMetaFile
& GDIMetaFile::operator=( const GDIMetaFile
& rMtf
)
218 // Increment RefCount of MetaActions
219 for( size_t i
= 0, n
= rMtf
.GetActionSize(); i
< n
; ++i
)
221 m_aList
.push_back( rMtf
.GetAction( i
) );
224 m_aPrefMapMode
= rMtf
.m_aPrefMapMode
;
225 m_aPrefSize
= rMtf
.m_aPrefSize
;
226 m_pPrev
= rMtf
.m_pPrev
;
227 m_pNext
= rMtf
.m_pNext
;
231 m_bUseCanvas
= rMtf
.m_bUseCanvas
;
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
);
333 for( size_t nCurPos
= m_nCurrentActionElement
; nCurPos
< nObjCount
; nCurPos
++ )
337 rMtf
.AddAction( pAction
);
340 pAction
= NextAction();
344 void GDIMetaFile::Play(OutputDevice
& rOut
, size_t nPos
)
349 MetaAction
* pAction
= GetCurAction();
350 const size_t nObjCount
= m_aList
.size();
351 size_t nSyncCount
= rOut
.GetSyncCount();
353 if( nPos
> nObjCount
)
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
360 rOut
.Push(PushFlags::TEXTLAYOUTMODE
|PushFlags::TEXTLANGUAGE
);
361 rOut
.SetLayoutMode(ComplexTextLayoutFlags::Default
);
362 rOut
.SetDigitLanguage(LANGUAGE_SYSTEM
);
364 SAL_INFO( "vcl.gdi", "GDIMetaFile::Play on device of size: " << rOut
.GetOutputSizePixel().Width() << " " << rOut
.GetOutputSizePixel().Height());
366 if (!ImplPlayWithRenderer(rOut
, Point(0,0), rOut
.GetOutputSize())) {
368 for( size_t nCurPos
= m_nCurrentActionElement
; nCurPos
< nPos
; nCurPos
++ )
372 pAction
->Execute(&rOut
);
374 // flush output from time to time
375 if( i
++ > nSyncCount
)
382 pAction
= NextAction();
388 bool GDIMetaFile::ImplPlayWithRenderer(OutputDevice
& rOut
, const Point
& rPos
, Size rLogicDestSize
)
393 Size
rDestSize(rOut
.LogicToPixel(rLogicDestSize
));
395 const vcl::Window
* win
= rOut
.GetOwnerWindow();
398 win
= Application::GetActiveTopWindow();
400 win
= Application::GetFirstTopLevelWindow();
407 uno::Reference
<rendering::XCanvas
> xCanvas
= win
->GetOutDev()->GetCanvas ();
412 Size
aSize (rDestSize
.Width () + 1, rDestSize
.Height () + 1);
413 uno::Reference
<rendering::XBitmap
> xBitmap
= xCanvas
->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize
));
416 uno::Reference
< rendering::XBitmapCanvas
> xBitmapCanvas( xBitmap
, uno::UNO_QUERY
);
417 if( xBitmapCanvas
.is() )
419 uno::Reference
< uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
420 uno::Reference
< rendering::XMtfRenderer
> xMtfRenderer
= rendering::MtfRenderer::createWithBitmapCanvas( xContext
, xBitmapCanvas
);
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 ) ) );
430 xMtfRenderer
->draw( rDestSize
.Width(), rDestSize
.Height() );
433 if( aBitmapEx
.Create( xBitmapCanvas
, aSize
) )
435 if (rOut
.GetMapMode().GetMapUnit() == MapUnit::MapPixel
)
436 rOut
.DrawBitmapEx( rPos
, aBitmapEx
);
438 rOut
.DrawBitmapEx( rPos
, rLogicDestSize
, aBitmapEx
);
444 catch (const uno::RuntimeException
& )
446 throw; // runtime errors are fatal
448 catch (const uno::Exception
&)
450 // ignore errors, no way of reporting them here
451 TOOLS_WARN_EXCEPTION("vcl.gdi", "GDIMetaFile::ImplPlayWithRenderer");
457 void GDIMetaFile::Play(OutputDevice
& rOut
, const Point
& rPos
,
460 MapMode
aDrawMap( GetPrefMapMode() );
461 Size
aDestSize(rOut
.LogicToPixel(rSize
));
463 if( !aDestSize
.Width() || !aDestSize
.Height() )
466 GDIMetaFile
* pMtf
= rOut
.GetConnectMetaFile();
468 if (ImplPlayWithRenderer(rOut
, rPos
, rSize
))
471 Size
aTmpPrefSize(rOut
.LogicToPixel(GetPrefSize(), aDrawMap
));
473 if( !aTmpPrefSize
.Width() )
474 aTmpPrefSize
.setWidth( aDestSize
.Width() );
476 if( !aTmpPrefSize
.Height() )
477 aTmpPrefSize
.setHeight( aDestSize
.Height() );
479 Fraction
aScaleX( aDestSize
.Width(), aTmpPrefSize
.Width() );
480 Fraction
aScaleY( aDestSize
.Height(), aTmpPrefSize
.Height() );
482 aScaleX
*= aDrawMap
.GetScaleX(); aDrawMap
.SetScaleX( aScaleX
);
483 aScaleY
*= aDrawMap
.GetScaleY(); aDrawMap
.SetScaleY( aScaleY
);
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 rOut, 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(rOut
.GetPixelOffset());
496 const Size aEmptySize
;
497 rOut
.SetPixelOffset(aEmptySize
);
498 aDrawMap
.SetOrigin(rOut
.PixelToLogic(rOut
.LogicToPixel(rPos
), aDrawMap
));
499 rOut
.SetPixelOffset(rOldOffset
);
503 bool bIsRecord
= (pMtf
&& pMtf
->IsRecord());
504 rOut
.SetMetafileMapMode(aDrawMap
, bIsRecord
);
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
510 rOut
.SetLayoutMode(ComplexTextLayoutFlags::Default
);
511 rOut
.SetDigitLanguage(LANGUAGE_SYSTEM
);
518 void GDIMetaFile::Pause( bool _bPause
)
526 Linker( m_pOutDev
, false );
531 Linker( m_pOutDev
, true );
537 void GDIMetaFile::Stop()
544 Linker( m_pOutDev
, false );
550 void GDIMetaFile::WindStart()
553 m_nCurrentActionElement
= 0;
556 void GDIMetaFile::WindPrev()
559 if ( m_nCurrentActionElement
> 0 )
560 --m_nCurrentActionElement
;
563 void GDIMetaFile::AddAction(const rtl::Reference
<MetaAction
>& pAction
)
565 m_aList
.push_back( pAction
);
569 m_pPrev
->AddAction( pAction
);
573 void GDIMetaFile::AddAction(const rtl::Reference
<MetaAction
>& pAction
, size_t nPos
)
575 if ( nPos
< m_aList
.size() )
577 m_aList
.insert( m_aList
.begin() + nPos
, pAction
);
581 m_aList
.push_back( pAction
);
586 m_pPrev
->AddAction( pAction
, nPos
);
590 void GDIMetaFile::push_back(const rtl::Reference
<MetaAction
>& pAction
)
592 m_aList
.push_back( pAction
);
595 void GDIMetaFile::Mirror( BmpMirrorFlags nMirrorFlags
)
597 const Size
aOldPrefSize( GetPrefSize() );
598 tools::Long nMoveX
, nMoveY
;
599 double fScaleX
, fScaleY
;
601 if( nMirrorFlags
& BmpMirrorFlags::Horizontal
)
603 nMoveX
= std::abs( aOldPrefSize
.Width() ) - 1;
612 if( nMirrorFlags
& BmpMirrorFlags::Vertical
)
614 nMoveY
= std::abs( aOldPrefSize
.Height() ) - 1;
623 if( ( fScaleX
!= 1.0 ) || ( fScaleY
!= 1.0 ) )
625 Scale( fScaleX
, fScaleY
);
626 Move( nMoveX
, nMoveY
);
627 SetPrefSize( aOldPrefSize
);
631 void GDIMetaFile::Move( tools::Long nX
, tools::Long nY
)
633 const Size
aBaseOffset( nX
, nY
);
634 Size
aOffset( aBaseOffset
);
635 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
637 aMapVDev
->EnableOutput( false );
638 aMapVDev
->SetMapMode( GetPrefMapMode() );
640 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
642 const MetaActionType nType
= pAct
->GetType();
645 if( pAct
->GetRefCount() > 1 )
647 m_aList
[ m_nCurrentActionElement
] = pAct
->Clone();
648 pModAct
= m_aList
[ m_nCurrentActionElement
].get();
653 if( ( MetaActionType::MAPMODE
== nType
) ||
654 ( MetaActionType::PUSH
== nType
) ||
655 ( MetaActionType::POP
== nType
) )
657 pModAct
->Execute( aMapVDev
.get() );
658 aOffset
= OutputDevice::LogicToLogic( aBaseOffset
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
661 pModAct
->Move( aOffset
.Width(), aOffset
.Height() );
665 void GDIMetaFile::Move( tools::Long nX
, tools::Long nY
, tools::Long nDPIX
, tools::Long nDPIY
)
667 const Size
aBaseOffset( nX
, nY
);
668 Size
aOffset( aBaseOffset
);
669 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
671 aMapVDev
->EnableOutput( false );
672 aMapVDev
->SetReferenceDevice( nDPIX
, nDPIY
);
673 aMapVDev
->SetMapMode( GetPrefMapMode() );
675 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
677 const MetaActionType nType
= pAct
->GetType();
680 if( pAct
->GetRefCount() > 1 )
682 m_aList
[ m_nCurrentActionElement
] = pAct
->Clone();
683 pModAct
= m_aList
[ m_nCurrentActionElement
].get();
688 if( ( MetaActionType::MAPMODE
== nType
) ||
689 ( MetaActionType::PUSH
== nType
) ||
690 ( MetaActionType::POP
== nType
) )
692 pModAct
->Execute( aMapVDev
.get() );
693 if( aMapVDev
->GetMapMode().GetMapUnit() == MapUnit::MapPixel
)
695 aOffset
= aMapVDev
->LogicToPixel( aBaseOffset
, GetPrefMapMode() );
696 MapMode
aMap( aMapVDev
->GetMapMode() );
697 aOffset
.setWidth( static_cast<tools::Long
>(aOffset
.Width() * static_cast<double>(aMap
.GetScaleX())) );
698 aOffset
.setHeight( static_cast<tools::Long
>(aOffset
.Height() * static_cast<double>(aMap
.GetScaleY())) );
701 aOffset
= OutputDevice::LogicToLogic( aBaseOffset
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
704 pModAct
->Move( aOffset
.Width(), aOffset
.Height() );
708 void GDIMetaFile::Scale( double fScaleX
, double fScaleY
)
710 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
714 if( pAct
->GetRefCount() > 1 )
716 m_aList
[ m_nCurrentActionElement
] = pAct
->Clone();
717 pModAct
= m_aList
[ m_nCurrentActionElement
].get();
722 pModAct
->Scale( fScaleX
, fScaleY
);
725 m_aPrefSize
.setWidth( FRound( m_aPrefSize
.Width() * fScaleX
) );
726 m_aPrefSize
.setHeight( FRound( m_aPrefSize
.Height() * fScaleY
) );
729 void GDIMetaFile::Scale( const Fraction
& rScaleX
, const Fraction
& rScaleY
)
731 Scale( static_cast<double>(rScaleX
), static_cast<double>(rScaleY
) );
734 void GDIMetaFile::Clip( const tools::Rectangle
& i_rClipRect
)
736 tools::Rectangle
aCurRect( i_rClipRect
);
737 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
739 aMapVDev
->EnableOutput( false );
740 aMapVDev
->SetMapMode( GetPrefMapMode() );
742 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
744 const MetaActionType nType
= pAct
->GetType();
746 if( ( MetaActionType::MAPMODE
== nType
) ||
747 ( MetaActionType::PUSH
== nType
) ||
748 ( MetaActionType::POP
== nType
) )
750 pAct
->Execute( aMapVDev
.get() );
751 aCurRect
= OutputDevice::LogicToLogic( i_rClipRect
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
753 else if( nType
== MetaActionType::CLIPREGION
)
755 MetaClipRegionAction
* pOldAct
= static_cast<MetaClipRegionAction
*>(pAct
);
756 vcl::Region
aNewReg( aCurRect
);
757 if( pOldAct
->IsClipping() )
758 aNewReg
.Intersect( pOldAct
->GetRegion() );
759 MetaClipRegionAction
* pNewAct
= new MetaClipRegionAction( aNewReg
, true );
760 m_aList
[ m_nCurrentActionElement
] = pNewAct
;
765 Point
GDIMetaFile::ImplGetRotatedPoint( const Point
& rPt
, const Point
& rRotatePt
,
766 const Size
& rOffset
, double fSin
, double fCos
)
768 const tools::Long nX
= rPt
.X() - rRotatePt
.X();
769 const tools::Long nY
= rPt
.Y() - rRotatePt
.Y();
771 return Point( FRound( fCos
* nX
+ fSin
* nY
) + rRotatePt
.X() + rOffset
.Width(),
772 -FRound( fSin
* nX
- fCos
* nY
) + rRotatePt
.Y() + rOffset
.Height() );
775 tools::Polygon
GDIMetaFile::ImplGetRotatedPolygon( const tools::Polygon
& rPoly
, const Point
& rRotatePt
,
776 const Size
& rOffset
, double fSin
, double fCos
)
778 tools::Polygon
aRet( rPoly
);
780 aRet
.Rotate( rRotatePt
, fSin
, fCos
);
781 aRet
.Move( rOffset
.Width(), rOffset
.Height() );
786 tools::PolyPolygon
GDIMetaFile::ImplGetRotatedPolyPolygon( const tools::PolyPolygon
& rPolyPoly
, const Point
& rRotatePt
,
787 const Size
& rOffset
, double fSin
, double fCos
)
789 tools::PolyPolygon
aRet( rPolyPoly
);
791 aRet
.Rotate( rRotatePt
, fSin
, fCos
);
792 aRet
.Move( rOffset
.Width(), rOffset
.Height() );
797 void GDIMetaFile::ImplAddGradientEx( GDIMetaFile
& rMtf
,
798 const OutputDevice
& rMapDev
,
799 const tools::PolyPolygon
& rPolyPoly
,
800 const Gradient
& rGrad
)
802 // Generate comment, GradientEx and Gradient actions (within DrawGradient)
803 ScopedVclPtrInstance
< VirtualDevice
> aVDev(rMapDev
, DeviceFormat::DEFAULT
);
804 aVDev
->EnableOutput( false );
805 GDIMetaFile aGradMtf
;
807 aGradMtf
.Record( aVDev
.get() );
808 aVDev
->DrawGradient( rPolyPoly
, rGrad
);
811 size_t i
, nAct( aGradMtf
.GetActionSize() );
812 for( i
=0; i
< nAct
; ++i
)
814 MetaAction
* pMetaAct
= aGradMtf
.GetAction( i
);
815 rMtf
.AddAction( pMetaAct
);
819 void GDIMetaFile::Rotate( Degree10 nAngle10
)
821 nAngle10
%= 3600_deg10
;
822 nAngle10
= ( nAngle10
< 0_deg10
) ? ( Degree10(3599) + nAngle10
) : nAngle10
;
828 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
829 const double fAngle
= F_PI1800
* nAngle10
.get();
830 const double fSin
= sin( fAngle
);
831 const double fCos
= cos( fAngle
);
832 tools::Rectangle
aRect( Point(), GetPrefSize() );
833 tools::Polygon
aPoly( aRect
);
835 aPoly
.Rotate( Point(), fSin
, fCos
);
837 aMapVDev
->EnableOutput( false );
838 aMapVDev
->SetMapMode( GetPrefMapMode() );
840 const tools::Rectangle
aNewBound( aPoly
.GetBoundRect() );
842 const Point
aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
843 const Size
aOffset( -aNewBound
.Left(), -aNewBound
.Top() );
845 Point
aRotAnchor( aOrigin
);
846 Size
aRotOffset( aOffset
);
848 for( MetaAction
* pAction
= FirstAction(); pAction
; pAction
= NextAction() )
850 const MetaActionType nActionType
= pAction
->GetType();
852 switch( nActionType
)
854 case MetaActionType::PIXEL
:
856 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
857 aMtf
.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
858 pAct
->GetColor() ) );
862 case MetaActionType::POINT
:
864 MetaPointAction
* pAct
= static_cast<MetaPointAction
*>(pAction
);
865 aMtf
.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
869 case MetaActionType::LINE
:
871 MetaLineAction
* pAct
= static_cast<MetaLineAction
*>(pAction
);
872 aMtf
.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct
->GetStartPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
873 ImplGetRotatedPoint( pAct
->GetEndPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
874 pAct
->GetLineInfo() ) );
878 case MetaActionType::RECT
:
880 MetaRectAction
* pAct
= static_cast<MetaRectAction
*>(pAction
);
881 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
885 case MetaActionType::ROUNDRECT
:
887 MetaRoundRectAction
* pAct
= static_cast<MetaRoundRectAction
*>(pAction
);
888 const tools::Polygon
aRoundRectPoly( pAct
->GetRect(), pAct
->GetHorzRound(), pAct
->GetVertRound() );
890 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
894 case MetaActionType::ELLIPSE
:
896 MetaEllipseAction
* pAct
= static_cast<MetaEllipseAction
*>(pAction
);
897 const tools::Polygon
aEllipsePoly( pAct
->GetRect().Center(), pAct
->GetRect().GetWidth() >> 1, pAct
->GetRect().GetHeight() >> 1 );
899 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
903 case MetaActionType::ARC
:
905 MetaArcAction
* pAct
= static_cast<MetaArcAction
*>(pAction
);
906 const tools::Polygon
aArcPoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Arc
);
908 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
912 case MetaActionType::PIE
:
914 MetaPieAction
* pAct
= static_cast<MetaPieAction
*>(pAction
);
915 const tools::Polygon
aPiePoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Pie
);
917 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
921 case MetaActionType::CHORD
:
923 MetaChordAction
* pAct
= static_cast<MetaChordAction
*>(pAction
);
924 const tools::Polygon
aChordPoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Chord
);
926 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
930 case MetaActionType::POLYLINE
:
932 MetaPolyLineAction
* pAct
= static_cast<MetaPolyLineAction
*>(pAction
);
933 aMtf
.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct
->GetPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
), pAct
->GetLineInfo() ) );
937 case MetaActionType::POLYGON
:
939 MetaPolygonAction
* pAct
= static_cast<MetaPolygonAction
*>(pAction
);
940 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct
->GetPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
944 case MetaActionType::POLYPOLYGON
:
946 MetaPolyPolygonAction
* pAct
= static_cast<MetaPolyPolygonAction
*>(pAction
);
947 aMtf
.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
951 case MetaActionType::TEXT
:
953 MetaTextAction
* pAct
= static_cast<MetaTextAction
*>(pAction
);
954 aMtf
.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
955 pAct
->GetText(), pAct
->GetIndex(), pAct
->GetLen() ) );
959 case MetaActionType::TEXTARRAY
:
961 MetaTextArrayAction
* pAct
= static_cast<MetaTextArrayAction
*>(pAction
);
962 aMtf
.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
963 pAct
->GetText(), pAct
->GetDXArray(), pAct
->GetIndex(), pAct
->GetLen() ) );
967 case MetaActionType::STRETCHTEXT
:
969 MetaStretchTextAction
* pAct
= static_cast<MetaStretchTextAction
*>(pAction
);
970 aMtf
.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
971 pAct
->GetWidth(), pAct
->GetText(), pAct
->GetIndex(), pAct
->GetLen() ) );
975 case MetaActionType::TEXTLINE
:
977 MetaTextLineAction
* pAct
= static_cast<MetaTextLineAction
*>(pAction
);
978 aMtf
.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct
->GetStartPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
979 pAct
->GetWidth(), pAct
->GetStrikeout(), pAct
->GetUnderline(), pAct
->GetOverline() ) );
983 case MetaActionType::BMPSCALE
:
985 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
986 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
987 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
988 BitmapEx
aBmpEx( pAct
->GetBitmap() );
990 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
991 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(),
996 case MetaActionType::BMPSCALEPART
:
998 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
999 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetDestPoint(), pAct
->GetDestSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1000 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1001 BitmapEx
aBmpEx( pAct
->GetBitmap() );
1003 aBmpEx
.Crop( tools::Rectangle( pAct
->GetSrcPoint(), pAct
->GetSrcSize() ) );
1004 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
1006 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1010 case MetaActionType::BMPEXSCALE
:
1012 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1013 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1014 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1015 BitmapEx
aBmpEx( pAct
->GetBitmapEx() );
1017 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
1019 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1023 case MetaActionType::BMPEXSCALEPART
:
1025 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1026 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetDestPoint(), pAct
->GetDestSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1027 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1028 BitmapEx
aBmpEx( pAct
->GetBitmapEx() );
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::GRADIENT
:
1039 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1041 ImplAddGradientEx( aMtf
, *aMapVDev
,
1042 ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1043 pAct
->GetGradient() );
1047 case MetaActionType::GRADIENTEX
:
1049 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1050 aMtf
.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1051 pAct
->GetGradient() ) );
1055 // Handle gradientex comment block correctly
1056 case MetaActionType::COMMENT
:
1058 MetaCommentAction
* pCommentAct
= static_cast<MetaCommentAction
*>(pAction
);
1059 if( pCommentAct
->GetComment() == "XGRAD_SEQ_BEGIN" )
1061 int nBeginComments( 1 );
1062 pAction
= NextAction();
1064 // skip everything, except gradientex action
1067 const MetaActionType nType
= pAction
->GetType();
1069 if( MetaActionType::GRADIENTEX
== nType
)
1071 // Add rotated gradientex
1072 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1073 ImplAddGradientEx( aMtf
, *aMapVDev
,
1074 ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1075 pAct
->GetGradient() );
1077 else if( MetaActionType::COMMENT
== nType
)
1079 MetaCommentAction
* pAct
= static_cast<MetaCommentAction
*>(pAction
);
1080 if( pAct
->GetComment() == "XGRAD_SEQ_END" )
1082 // handle nested blocks
1085 // gradientex comment block: end reached, done.
1086 if( !nBeginComments
)
1089 else if( pAct
->GetComment() == "XGRAD_SEQ_BEGIN" )
1091 // handle nested blocks
1097 pAction
=NextAction();
1102 bool bPathStroke
= (pCommentAct
->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1103 if ( bPathStroke
|| pCommentAct
->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1105 if ( pCommentAct
->GetDataSize() )
1107 SvMemoryStream
aMemStm( const_cast<sal_uInt8
*>(pCommentAct
->GetData()), pCommentAct
->GetDataSize(), StreamMode::READ
);
1108 SvMemoryStream aDest
;
1111 SvtGraphicStroke aStroke
;
1112 ReadSvtGraphicStroke( aMemStm
, aStroke
);
1113 tools::Polygon aPath
;
1114 aStroke
.getPath( aPath
);
1115 aStroke
.setPath( ImplGetRotatedPolygon( aPath
, aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1116 WriteSvtGraphicStroke( aDest
, aStroke
);
1117 aMtf
.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1118 static_cast<const sal_uInt8
*>( aDest
.GetData()), aDest
.Tell() ) );
1122 SvtGraphicFill aFill
;
1123 ReadSvtGraphicFill( aMemStm
, aFill
);
1124 tools::PolyPolygon aPath
;
1125 aFill
.getPath( aPath
);
1126 aFill
.setPath( ImplGetRotatedPolyPolygon( aPath
, aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1127 WriteSvtGraphicFill( aDest
, aFill
);
1128 aMtf
.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1129 static_cast<const sal_uInt8
*>( aDest
.GetData()), aDest
.Tell() ) );
1133 else if ( pCommentAct
->GetComment() == "XPATHSTROKE_SEQ_END"
1134 || pCommentAct
->GetComment() == "XPATHFILL_SEQ_END" )
1136 pAction
->Execute( aMapVDev
.get() );
1137 aMtf
.AddAction( pAction
);
1143 case MetaActionType::HATCH
:
1145 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
1146 Hatch
aHatch( pAct
->GetHatch() );
1148 aHatch
.SetAngle( aHatch
.GetAngle() + nAngle10
);
1149 aMtf
.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1154 case MetaActionType::Transparent
:
1156 MetaTransparentAction
* pAct
= static_cast<MetaTransparentAction
*>(pAction
);
1157 aMtf
.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1158 pAct
->GetTransparence() ) );
1162 case MetaActionType::FLOATTRANSPARENT
:
1164 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
1165 GDIMetaFile
aTransMtf( pAct
->GetGDIMetaFile() );
1166 tools::Polygon
aMtfPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1167 tools::Rectangle
aMtfRect( aMtfPoly
.GetBoundRect() );
1169 aTransMtf
.Rotate( nAngle10
);
1170 aMtf
.AddAction( new MetaFloatTransparentAction( aTransMtf
, aMtfRect
.TopLeft(), aMtfRect
.GetSize(),
1171 pAct
->GetGradient() ) );
1175 case MetaActionType::EPS
:
1177 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
1178 GDIMetaFile
aEPSMtf( pAct
->GetSubstitute() );
1179 tools::Polygon
aEPSPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1180 tools::Rectangle
aEPSRect( aEPSPoly
.GetBoundRect() );
1182 aEPSMtf
.Rotate( nAngle10
);
1183 aMtf
.AddAction( new MetaEPSAction( aEPSRect
.TopLeft(), aEPSRect
.GetSize(),
1184 pAct
->GetLink(), aEPSMtf
) );
1188 case MetaActionType::CLIPREGION
:
1190 MetaClipRegionAction
* pAct
= static_cast<MetaClipRegionAction
*>(pAction
);
1192 if( pAct
->IsClipping() && pAct
->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1193 aMtf
.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct
->GetRegion().GetAsPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ), true ) );
1196 aMtf
.AddAction( pAction
);
1201 case MetaActionType::ISECTRECTCLIPREGION
:
1203 MetaISectRectClipRegionAction
* pAct
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
1204 aMtf
.AddAction( new MetaISectRegionClipRegionAction(vcl::Region(
1205 ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
,
1206 aRotOffset
, fSin
, fCos
)) ) );
1210 case MetaActionType::ISECTREGIONCLIPREGION
:
1212 MetaISectRegionClipRegionAction
* pAct
= static_cast<MetaISectRegionClipRegionAction
*>(pAction
);
1213 const vcl::Region
& rRegion
= pAct
->GetRegion();
1215 if( rRegion
.HasPolyPolygonOrB2DPolyPolygon() )
1216 aMtf
.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion
.GetAsPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) ) );
1219 aMtf
.AddAction( pAction
);
1224 case MetaActionType::REFPOINT
:
1226 MetaRefPointAction
* pAct
= static_cast<MetaRefPointAction
*>(pAction
);
1227 aMtf
.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct
->GetRefPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
), pAct
->IsSetting() ) );
1231 case MetaActionType::FONT
:
1233 MetaFontAction
* pAct
= static_cast<MetaFontAction
*>(pAction
);
1234 vcl::Font
aFont( pAct
->GetFont() );
1236 aFont
.SetOrientation( aFont
.GetOrientation() + nAngle10
);
1237 aMtf
.AddAction( new MetaFontAction( aFont
) );
1241 case MetaActionType::BMP
:
1242 case MetaActionType::BMPEX
:
1243 case MetaActionType::MASK
:
1244 case MetaActionType::MASKSCALE
:
1245 case MetaActionType::MASKSCALEPART
:
1246 case MetaActionType::WALLPAPER
:
1247 case MetaActionType::TEXTRECT
:
1248 case MetaActionType::MOVECLIPREGION
:
1250 OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1256 pAction
->Execute( aMapVDev
.get() );
1257 aMtf
.AddAction( pAction
);
1259 // update rotation point and offset, if necessary
1260 if( ( MetaActionType::MAPMODE
== nActionType
) ||
1261 ( MetaActionType::PUSH
== nActionType
) ||
1262 ( MetaActionType::POP
== nActionType
) )
1264 aRotAnchor
= OutputDevice::LogicToLogic( aOrigin
, m_aPrefMapMode
, aMapVDev
->GetMapMode() );
1265 aRotOffset
= OutputDevice::LogicToLogic( aOffset
, m_aPrefMapMode
, aMapVDev
->GetMapMode() );
1272 aMtf
.m_aPrefMapMode
= m_aPrefMapMode
;
1273 aMtf
.m_aPrefSize
= aNewBound
.GetSize();
1279 static void ImplActionBounds( tools::Rectangle
& o_rOutBounds
,
1280 const tools::Rectangle
& i_rInBounds
,
1281 const std::vector
<tools::Rectangle
>& i_rClipStack
,
1282 tools::Rectangle
* o_pHairline
)
1284 tools::Rectangle
aBounds( i_rInBounds
);
1285 if( ! i_rInBounds
.IsEmpty() && ! i_rClipStack
.empty() && ! i_rClipStack
.back().IsEmpty() )
1286 aBounds
.Intersection( i_rClipStack
.back() );
1287 if( aBounds
.IsEmpty() )
1290 if( ! o_rOutBounds
.IsEmpty() )
1291 o_rOutBounds
.Union( aBounds
);
1293 o_rOutBounds
= aBounds
;
1297 if( ! o_pHairline
->IsEmpty() )
1298 o_pHairline
->Union( aBounds
);
1300 *o_pHairline
= aBounds
;
1304 tools::Rectangle
GDIMetaFile::GetBoundRect( OutputDevice
& i_rReference
, tools::Rectangle
* pHairline
) const
1306 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev( i_rReference
);
1308 aMapVDev
->EnableOutput( false );
1309 aMapVDev
->SetMapMode( GetPrefMapMode() );
1311 std::vector
<tools::Rectangle
> aClipStack( 1, tools::Rectangle() );
1312 std::vector
<PushFlags
> aPushFlagStack
;
1314 tools::Rectangle aBound
;
1317 *pHairline
= tools::Rectangle();
1319 const sal_uLong
nCount(GetActionSize());
1321 for(sal_uLong
a(0); a
< nCount
; a
++)
1323 MetaAction
* pAction
= GetAction(a
);
1324 const MetaActionType nActionType
= pAction
->GetType();
1325 tools::Rectangle
* pUseHairline
= (pHairline
&& aMapVDev
->IsLineColor()) ? pHairline
: nullptr;
1327 switch( nActionType
)
1329 case MetaActionType::PIXEL
:
1331 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
1332 ImplActionBounds( aBound
,
1333 tools::Rectangle( OutputDevice::LogicToLogic( pAct
->GetPoint(), aMapVDev
->GetMapMode(), GetPrefMapMode() ),
1334 aMapVDev
->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1335 aClipStack
, pUseHairline
);
1339 case MetaActionType::POINT
:
1341 MetaPointAction
* pAct
= static_cast<MetaPointAction
*>(pAction
);
1342 ImplActionBounds( aBound
,
1343 tools::Rectangle( OutputDevice::LogicToLogic( pAct
->GetPoint(), aMapVDev
->GetMapMode(), GetPrefMapMode() ),
1344 aMapVDev
->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1345 aClipStack
, pUseHairline
);
1349 case MetaActionType::LINE
:
1351 MetaLineAction
* pAct
= static_cast<MetaLineAction
*>(pAction
);
1352 Point
aP1( pAct
->GetStartPoint() ), aP2( pAct
->GetEndPoint() );
1353 tools::Rectangle
aRect( aP1
, aP2
);
1358 const LineInfo
& rLineInfo
= pAct
->GetLineInfo();
1360 if(0 != rLineInfo
.GetWidth())
1361 pUseHairline
= nullptr;
1364 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1368 case MetaActionType::RECT
:
1370 MetaRectAction
* pAct
= static_cast<MetaRectAction
*>(pAction
);
1371 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1375 case MetaActionType::ROUNDRECT
:
1377 MetaRoundRectAction
* pAct
= static_cast<MetaRoundRectAction
*>(pAction
);
1378 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1382 case MetaActionType::ELLIPSE
:
1384 MetaEllipseAction
* pAct
= static_cast<MetaEllipseAction
*>(pAction
);
1385 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1389 case MetaActionType::ARC
:
1391 MetaArcAction
* pAct
= static_cast<MetaArcAction
*>(pAction
);
1392 // FIXME: this is imprecise
1393 // e.g. for small arcs the whole rectangle is WAY too large
1394 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1398 case MetaActionType::PIE
:
1400 MetaPieAction
* pAct
= static_cast<MetaPieAction
*>(pAction
);
1401 // FIXME: this is imprecise
1402 // e.g. for small arcs the whole rectangle is WAY too large
1403 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1407 case MetaActionType::CHORD
:
1409 MetaChordAction
* pAct
= static_cast<MetaChordAction
*>(pAction
);
1410 // FIXME: this is imprecise
1411 // e.g. for small arcs the whole rectangle is WAY too large
1412 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1416 case MetaActionType::POLYLINE
:
1418 MetaPolyLineAction
* pAct
= static_cast<MetaPolyLineAction
*>(pAction
);
1419 tools::Rectangle
aRect( pAct
->GetPolygon().GetBoundRect() );
1423 const LineInfo
& rLineInfo
= pAct
->GetLineInfo();
1425 if(0 != rLineInfo
.GetWidth())
1426 pUseHairline
= nullptr;
1429 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1433 case MetaActionType::POLYGON
:
1435 MetaPolygonAction
* pAct
= static_cast<MetaPolygonAction
*>(pAction
);
1436 tools::Rectangle
aRect( pAct
->GetPolygon().GetBoundRect() );
1437 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1441 case MetaActionType::POLYPOLYGON
:
1443 MetaPolyPolygonAction
* pAct
= static_cast<MetaPolyPolygonAction
*>(pAction
);
1444 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1445 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1449 case MetaActionType::TEXT
:
1451 MetaTextAction
* pAct
= static_cast<MetaTextAction
*>(pAction
);
1452 tools::Rectangle aRect
;
1453 // hdu said base = index
1454 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen() );
1455 Point
aPt( pAct
->GetPoint() );
1456 aRect
.Move( aPt
.X(), aPt
.Y() );
1457 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1461 case MetaActionType::TEXTARRAY
:
1463 MetaTextArrayAction
* pAct
= static_cast<MetaTextArrayAction
*>(pAction
);
1464 tools::Rectangle aRect
;
1465 // hdu said base = index
1466 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen(),
1467 0, pAct
->GetDXArray() );
1468 Point
aPt( pAct
->GetPoint() );
1469 aRect
.Move( aPt
.X(), aPt
.Y() );
1470 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1474 case MetaActionType::STRETCHTEXT
:
1476 MetaStretchTextAction
* pAct
= static_cast<MetaStretchTextAction
*>(pAction
);
1477 tools::Rectangle aRect
;
1478 // hdu said base = index
1479 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen(),
1481 Point
aPt( pAct
->GetPoint() );
1482 aRect
.Move( aPt
.X(), aPt
.Y() );
1483 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1487 case MetaActionType::TEXTLINE
:
1489 MetaTextLineAction
* pAct
= static_cast<MetaTextLineAction
*>(pAction
);
1490 // measure a test string to get ascend and descent right
1491 static constexpr OUStringLiteral pStr
= u
"\u00c4g";
1492 OUString
aStr( pStr
);
1494 tools::Rectangle aRect
;
1495 aMapVDev
->GetTextBoundRect( aRect
, aStr
, 0, 0, aStr
.getLength() );
1496 Point
aPt( pAct
->GetStartPoint() );
1497 aRect
.Move( aPt
.X(), aPt
.Y() );
1498 aRect
.SetRight( aRect
.Left() + pAct
->GetWidth() );
1499 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1503 case MetaActionType::BMPSCALE
:
1505 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1506 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1507 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1511 case MetaActionType::BMPSCALEPART
:
1513 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1514 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1515 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1519 case MetaActionType::BMPEXSCALE
:
1521 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1522 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1523 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1527 case MetaActionType::BMPEXSCALEPART
:
1529 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1530 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1531 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1535 case MetaActionType::GRADIENT
:
1537 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1538 tools::Rectangle
aRect( pAct
->GetRect() );
1539 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1543 case MetaActionType::GRADIENTEX
:
1545 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1546 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1547 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1551 case MetaActionType::COMMENT
:
1557 case MetaActionType::HATCH
:
1559 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
1560 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1561 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1565 case MetaActionType::Transparent
:
1567 MetaTransparentAction
* pAct
= static_cast<MetaTransparentAction
*>(pAction
);
1568 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1569 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1573 case MetaActionType::FLOATTRANSPARENT
:
1575 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
1576 // MetaFloatTransparentAction is defined limiting its content Metafile
1577 // to its geometry definition(Point, Size), so use these directly
1578 const tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1579 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1583 case MetaActionType::EPS
:
1585 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
1586 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1587 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1591 case MetaActionType::CLIPREGION
:
1593 MetaClipRegionAction
* pAct
= static_cast<MetaClipRegionAction
*>(pAction
);
1594 if( pAct
->IsClipping() )
1595 aClipStack
.back() = OutputDevice::LogicToLogic( pAct
->GetRegion().GetBoundRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() );
1597 aClipStack
.back() = tools::Rectangle();
1601 case MetaActionType::ISECTRECTCLIPREGION
:
1603 MetaISectRectClipRegionAction
* pAct
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
1604 tools::Rectangle
aRect( OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ) );
1605 if( aClipStack
.back().IsEmpty() )
1606 aClipStack
.back() = aRect
;
1608 aClipStack
.back().Intersection( aRect
);
1612 case MetaActionType::ISECTREGIONCLIPREGION
:
1614 MetaISectRegionClipRegionAction
* pAct
= static_cast<MetaISectRegionClipRegionAction
*>(pAction
);
1615 tools::Rectangle
aRect( OutputDevice::LogicToLogic( pAct
->GetRegion().GetBoundRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ) );
1616 if( aClipStack
.back().IsEmpty() )
1617 aClipStack
.back() = aRect
;
1619 aClipStack
.back().Intersection( aRect
);
1623 case MetaActionType::BMP
:
1625 MetaBmpAction
* pAct
= static_cast<MetaBmpAction
*>(pAction
);
1626 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmap().GetSizePixel() ) );
1627 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1631 case MetaActionType::BMPEX
:
1633 MetaBmpExAction
* pAct
= static_cast<MetaBmpExAction
*>(pAction
);
1634 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmapEx().GetSizePixel() ) );
1635 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1639 case MetaActionType::MASK
:
1641 MetaMaskAction
* pAct
= static_cast<MetaMaskAction
*>(pAction
);
1642 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmap().GetSizePixel() ) );
1643 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1647 case MetaActionType::MASKSCALE
:
1649 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1650 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1651 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1655 case MetaActionType::MASKSCALEPART
:
1657 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1658 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1659 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1663 case MetaActionType::WALLPAPER
:
1665 MetaWallpaperAction
* pAct
= static_cast<MetaWallpaperAction
*>(pAction
);
1666 tools::Rectangle
aRect( pAct
->GetRect() );
1667 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1671 case MetaActionType::TEXTRECT
:
1673 MetaTextRectAction
* pAct
= static_cast<MetaTextRectAction
*>(pAction
);
1674 tools::Rectangle
aRect( pAct
->GetRect() );
1675 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1679 case MetaActionType::MOVECLIPREGION
:
1681 MetaMoveClipRegionAction
* pAct
= static_cast<MetaMoveClipRegionAction
*>(pAction
);
1682 if( ! aClipStack
.back().IsEmpty() )
1684 Size
aDelta( pAct
->GetHorzMove(), pAct
->GetVertMove() );
1685 aDelta
= OutputDevice::LogicToLogic( aDelta
, aMapVDev
->GetMapMode(), GetPrefMapMode() );
1686 aClipStack
.back().Move( aDelta
.Width(), aDelta
.Width() );
1693 pAction
->Execute( aMapVDev
.get() );
1695 if( nActionType
== MetaActionType::PUSH
)
1697 MetaPushAction
* pAct
= static_cast<MetaPushAction
*>(pAction
);
1698 aPushFlagStack
.push_back( pAct
->GetFlags() );
1699 if( aPushFlagStack
.back() & PushFlags::CLIPREGION
)
1701 tools::Rectangle
aRect( aClipStack
.back() );
1702 aClipStack
.push_back( aRect
);
1705 else if( nActionType
== MetaActionType::POP
)
1708 if( ! aPushFlagStack
.empty() )
1710 if( aPushFlagStack
.back() & PushFlags::CLIPREGION
)
1712 if( aClipStack
.size() > 1 )
1713 aClipStack
.pop_back();
1715 aPushFlagStack
.pop_back();
1725 Color
GDIMetaFile::ImplColAdjustFnc( const Color
& rColor
, const void* pColParam
)
1727 return Color( ColorAlpha
, rColor
.GetAlpha(),
1728 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapR
[ rColor
.GetRed() ],
1729 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapG
[ rColor
.GetGreen() ],
1730 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapB
[ rColor
.GetBlue() ] );
1734 BitmapEx
GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1736 const ImplBmpAdjustParam
* p
= static_cast<const ImplBmpAdjustParam
*>(pBmpParam
);
1737 BitmapEx
aRet( rBmpEx
);
1739 aRet
.Adjust( p
->nLuminancePercent
, p
->nContrastPercent
,
1740 p
->nChannelRPercent
, p
->nChannelGPercent
, p
->nChannelBPercent
,
1741 p
->fGamma
, p
->bInvert
);
1746 Color
GDIMetaFile::ImplColConvertFnc( const Color
& rColor
, const void* pColParam
)
1748 sal_uInt8 cLum
= rColor
.GetLuminance();
1750 if( MtfConversion::N1BitThreshold
== static_cast<const ImplColConvertParam
*>(pColParam
)->eConversion
)
1751 cLum
= ( cLum
< 128 ) ? 0 : 255;
1753 return Color( ColorTransparency
, 255 - rColor
.GetAlpha(), cLum
, cLum
, cLum
);
1756 BitmapEx
GDIMetaFile::ImplBmpConvertFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1758 BitmapEx
aRet( rBmpEx
);
1760 aRet
.Convert( static_cast<const ImplBmpConvertParam
*>(pBmpParam
)->eConversion
);
1765 Color
GDIMetaFile::ImplColMonoFnc( const Color
&, const void* pColParam
)
1767 return static_cast<const ImplColMonoParam
*>(pColParam
)->aColor
;
1770 BitmapEx
GDIMetaFile::ImplBmpMonoFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1772 BitmapPalette
aPal( 3 );
1773 aPal
[ 0 ] = COL_BLACK
;
1774 aPal
[ 1 ] = COL_WHITE
;
1775 aPal
[ 2 ] = static_cast<const ImplBmpMonoParam
*>(pBmpParam
)->aColor
;
1777 Bitmap
aBmp(rBmpEx
.GetSizePixel(), vcl::PixelFormat::N8_BPP
, &aPal
);
1778 aBmp
.Erase( static_cast<const ImplBmpMonoParam
*>(pBmpParam
)->aColor
);
1780 if( rBmpEx
.IsAlpha() )
1781 return BitmapEx( aBmp
, rBmpEx
.GetAlpha() );
1783 return BitmapEx( aBmp
);
1786 Color
GDIMetaFile::ImplColReplaceFnc( const Color
& rColor
, const void* pColParam
)
1788 const sal_uLong nR
= rColor
.GetRed(), nG
= rColor
.GetGreen(), nB
= rColor
.GetBlue();
1790 for( sal_uLong i
= 0; i
< static_cast<const ImplColReplaceParam
*>(pColParam
)->nCount
; i
++ )
1792 if( ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinR
[ i
] <= nR
) &&
1793 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxR
[ i
] >= nR
) &&
1794 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinG
[ i
] <= nG
) &&
1795 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxG
[ i
] >= nG
) &&
1796 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinB
[ i
] <= nB
) &&
1797 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxB
[ i
] >= nB
) )
1799 return static_cast<const ImplColReplaceParam
*>(pColParam
)->pDstCols
[ i
];
1806 BitmapEx
GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1808 const ImplBmpReplaceParam
* p
= static_cast<const ImplBmpReplaceParam
*>(pBmpParam
);
1809 BitmapEx
aRet( rBmpEx
);
1811 aRet
.Replace( p
->pSrcCols
, p
->pDstCols
, p
->nCount
);
1816 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol
, const void* pColParam
,
1817 BmpExchangeFnc pFncBmp
, const void* pBmpParam
)
1821 aMtf
.m_aPrefSize
= m_aPrefSize
;
1822 aMtf
.m_aPrefMapMode
= m_aPrefMapMode
;
1823 aMtf
.m_bUseCanvas
= m_bUseCanvas
;
1825 for( MetaAction
* pAction
= FirstAction(); pAction
; pAction
= NextAction() )
1827 const MetaActionType nType
= pAction
->GetType();
1831 case MetaActionType::PIXEL
:
1833 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
1834 aMtf
.push_back( new MetaPixelAction( pAct
->GetPoint(), pFncCol( pAct
->GetColor(), pColParam
) ) );
1838 case MetaActionType::LINECOLOR
:
1840 MetaLineColorAction
* pAct
= static_cast<MetaLineColorAction
*>(pAction
);
1842 if( pAct
->IsSetting() )
1843 pAct
= new MetaLineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1845 aMtf
.push_back( pAct
);
1849 case MetaActionType::FILLCOLOR
:
1851 MetaFillColorAction
* pAct
= static_cast<MetaFillColorAction
*>(pAction
);
1853 if( pAct
->IsSetting() )
1854 pAct
= new MetaFillColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1856 aMtf
.push_back( pAct
);
1860 case MetaActionType::TEXTCOLOR
:
1862 MetaTextColorAction
* pAct
= static_cast<MetaTextColorAction
*>(pAction
);
1863 aMtf
.push_back( new MetaTextColorAction( pFncCol( pAct
->GetColor(), pColParam
) ) );
1867 case MetaActionType::TEXTFILLCOLOR
:
1869 MetaTextFillColorAction
* pAct
= static_cast<MetaTextFillColorAction
*>(pAction
);
1871 if( pAct
->IsSetting() )
1872 pAct
= new MetaTextFillColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1874 aMtf
.push_back( pAct
);
1878 case MetaActionType::TEXTLINECOLOR
:
1880 MetaTextLineColorAction
* pAct
= static_cast<MetaTextLineColorAction
*>(pAction
);
1882 if( pAct
->IsSetting() )
1883 pAct
= new MetaTextLineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1885 aMtf
.push_back( pAct
);
1889 case MetaActionType::OVERLINECOLOR
:
1891 MetaOverlineColorAction
* pAct
= static_cast<MetaOverlineColorAction
*>(pAction
);
1893 if( pAct
->IsSetting() )
1894 pAct
= new MetaOverlineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1896 aMtf
.push_back( pAct
);
1900 case MetaActionType::FONT
:
1902 MetaFontAction
* pAct
= static_cast<MetaFontAction
*>(pAction
);
1903 vcl::Font
aFont( pAct
->GetFont() );
1905 aFont
.SetColor( pFncCol( aFont
.GetColor(), pColParam
) );
1906 aFont
.SetFillColor( pFncCol( aFont
.GetFillColor(), pColParam
) );
1907 aMtf
.push_back( new MetaFontAction( aFont
) );
1911 case MetaActionType::WALLPAPER
:
1913 MetaWallpaperAction
* pAct
= static_cast<MetaWallpaperAction
*>(pAction
);
1914 Wallpaper
aWall( pAct
->GetWallpaper() );
1915 const tools::Rectangle
& rRect
= pAct
->GetRect();
1917 aWall
.SetColor( pFncCol( aWall
.GetColor(), pColParam
) );
1919 if( aWall
.IsBitmap() )
1920 aWall
.SetBitmap( pFncBmp( aWall
.GetBitmap(), pBmpParam
) );
1922 if( aWall
.IsGradient() )
1924 Gradient
aGradient( aWall
.GetGradient() );
1926 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
1927 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
1928 aWall
.SetGradient( aGradient
);
1931 aMtf
.push_back( new MetaWallpaperAction( rRect
, aWall
) );
1935 case MetaActionType::BMP
:
1936 case MetaActionType::BMPEX
:
1937 case MetaActionType::MASK
:
1939 OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
1943 case MetaActionType::BMPSCALE
:
1945 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1946 aMtf
.push_back( new MetaBmpScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
1947 pFncBmp( BitmapEx(pAct
->GetBitmap()), pBmpParam
).GetBitmap() ) );
1951 case MetaActionType::BMPSCALEPART
:
1953 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1954 aMtf
.push_back( new MetaBmpScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
1955 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
1956 pFncBmp( BitmapEx(pAct
->GetBitmap()), pBmpParam
).GetBitmap() )
1961 case MetaActionType::BMPEXSCALE
:
1963 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1964 aMtf
.push_back( new MetaBmpExScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
1965 pFncBmp( pAct
->GetBitmapEx(), pBmpParam
) )
1970 case MetaActionType::BMPEXSCALEPART
:
1972 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1973 aMtf
.push_back( new MetaBmpExScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
1974 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
1975 pFncBmp( pAct
->GetBitmapEx(), pBmpParam
) )
1980 case MetaActionType::MASKSCALE
:
1982 MetaMaskScaleAction
* pAct
= static_cast<MetaMaskScaleAction
*>(pAction
);
1983 aMtf
.push_back( new MetaMaskScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
1985 pFncCol( pAct
->GetColor(), pColParam
) )
1990 case MetaActionType::MASKSCALEPART
:
1992 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1993 aMtf
.push_back( new MetaMaskScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
1994 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
1996 pFncCol( pAct
->GetColor(), pColParam
) )
2001 case MetaActionType::GRADIENT
:
2003 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
2004 Gradient
aGradient( pAct
->GetGradient() );
2006 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
2007 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
2008 aMtf
.push_back( new MetaGradientAction( pAct
->GetRect(), aGradient
) );
2012 case MetaActionType::GRADIENTEX
:
2014 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
2015 Gradient
aGradient( pAct
->GetGradient() );
2017 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
2018 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
2019 aMtf
.push_back( new MetaGradientExAction( pAct
->GetPolyPolygon(), aGradient
) );
2023 case MetaActionType::HATCH
:
2025 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
2026 Hatch
aHatch( pAct
->GetHatch() );
2028 aHatch
.SetColor( pFncCol( aHatch
.GetColor(), pColParam
) );
2029 aMtf
.push_back( new MetaHatchAction( pAct
->GetPolyPolygon(), aHatch
) );
2033 case MetaActionType::FLOATTRANSPARENT
:
2035 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
2036 GDIMetaFile
aTransMtf( pAct
->GetGDIMetaFile() );
2038 aTransMtf
.ImplExchangeColors( pFncCol
, pColParam
, pFncBmp
, pBmpParam
);
2039 aMtf
.push_back( new MetaFloatTransparentAction( aTransMtf
,
2040 pAct
->GetPoint(), pAct
->GetSize(),
2041 pAct
->GetGradient() )
2046 case MetaActionType::EPS
:
2048 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
2049 GDIMetaFile
aSubst( pAct
->GetSubstitute() );
2051 aSubst
.ImplExchangeColors( pFncCol
, pColParam
, pFncBmp
, pBmpParam
);
2052 aMtf
.push_back( new MetaEPSAction( pAct
->GetPoint(), pAct
->GetSize(),
2053 pAct
->GetLink(), aSubst
)
2060 aMtf
.push_back( pAction
);
2069 void GDIMetaFile::Adjust( short nLuminancePercent
, short nContrastPercent
,
2070 short nChannelRPercent
, short nChannelGPercent
,
2071 short nChannelBPercent
, double fGamma
, bool bInvert
, bool msoBrightness
)
2073 // nothing to do? => return quickly
2074 if( !(nLuminancePercent
|| nContrastPercent
||
2075 nChannelRPercent
|| nChannelGPercent
|| nChannelBPercent
||
2076 ( fGamma
!= 1.0 ) || bInvert
) )
2079 double fM
, fROff
, fGOff
, fBOff
, fOff
;
2080 ImplColAdjustParam aColParam
;
2081 ImplBmpAdjustParam aBmpParam
;
2083 aColParam
.pMapR
.reset(new sal_uInt8
[ 256 ]);
2084 aColParam
.pMapG
.reset(new sal_uInt8
[ 256 ]);
2085 aColParam
.pMapB
.reset(new sal_uInt8
[ 256 ]);
2088 if( nContrastPercent
>= 0 )
2089 fM
= 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent
, 0, 100 ) );
2091 fM
= ( 128.0 + 1.27 * MinMax( nContrastPercent
, -100, 0 ) ) / 128.0;
2094 // total offset = luminance offset + contrast offset
2095 fOff
= MinMax( nLuminancePercent
, -100, 100 ) * 2.55 + 128.0 - fM
* 128.0;
2097 fOff
= MinMax( nLuminancePercent
, -100, 100 ) * 2.55;
2099 // channel offset = channel offset + total offset
2100 fROff
= nChannelRPercent
* 2.55 + fOff
;
2101 fGOff
= nChannelGPercent
* 2.55 + fOff
;
2102 fBOff
= nChannelBPercent
* 2.55 + fOff
;
2104 // calculate gamma value
2105 fGamma
= ( fGamma
<= 0.0 || fGamma
> 10.0 ) ? 1.0 : ( 1.0 / fGamma
);
2106 const bool bGamma
= ( fGamma
!= 1.0 );
2108 // create mapping table
2109 for( tools::Long nX
= 0; nX
< 256; nX
++ )
2113 aColParam
.pMapR
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( nX
* fM
+ fROff
), 0, 255 ));
2114 aColParam
.pMapG
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( nX
* fM
+ fGOff
), 0, 255 ));
2115 aColParam
.pMapB
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( nX
* fM
+ fBOff
), 0, 255 ));
2119 aColParam
.pMapR
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( (nX
+fROff
/2-128) * fM
+ 128 + fROff
/2 ), 0, 255 ));
2120 aColParam
.pMapG
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( (nX
+fGOff
/2-128) * fM
+ 128 + fGOff
/2 ), 0, 255 ));
2121 aColParam
.pMapB
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( (nX
+fBOff
/2-128) * fM
+ 128 + fBOff
/2 ), 0, 255 ));
2125 aColParam
.pMapR
[ nX
] = GAMMA( aColParam
.pMapR
[ nX
], fGamma
);
2126 aColParam
.pMapG
[ nX
] = GAMMA( aColParam
.pMapG
[ nX
], fGamma
);
2127 aColParam
.pMapB
[ nX
] = GAMMA( aColParam
.pMapB
[ nX
], fGamma
);
2132 aColParam
.pMapR
[ nX
] = ~aColParam
.pMapR
[ nX
];
2133 aColParam
.pMapG
[ nX
] = ~aColParam
.pMapG
[ nX
];
2134 aColParam
.pMapB
[ nX
] = ~aColParam
.pMapB
[ nX
];
2138 aBmpParam
.nLuminancePercent
= nLuminancePercent
;
2139 aBmpParam
.nContrastPercent
= nContrastPercent
;
2140 aBmpParam
.nChannelRPercent
= nChannelRPercent
;
2141 aBmpParam
.nChannelGPercent
= nChannelGPercent
;
2142 aBmpParam
.nChannelBPercent
= nChannelBPercent
;
2143 aBmpParam
.fGamma
= fGamma
;
2144 aBmpParam
.bInvert
= bInvert
;
2146 // do color adjustment
2147 ImplExchangeColors( ImplColAdjustFnc
, &aColParam
, ImplBmpAdjustFnc
, &aBmpParam
);
2150 void GDIMetaFile::Convert( MtfConversion eConversion
)
2152 ImplColConvertParam aColParam
;
2153 ImplBmpConvertParam aBmpParam
;
2155 aColParam
.eConversion
= eConversion
;
2156 aBmpParam
.eConversion
= ( MtfConversion::N1BitThreshold
== eConversion
) ? BmpConversion::N1BitThreshold
: BmpConversion::N8BitGreys
;
2158 ImplExchangeColors( ImplColConvertFnc
, &aColParam
, ImplBmpConvertFnc
, &aBmpParam
);
2161 void GDIMetaFile::ReplaceColors( const Color
* pSearchColors
, const Color
* pReplaceColors
, sal_uLong nColorCount
)
2163 ImplColReplaceParam aColParam
;
2164 ImplBmpReplaceParam aBmpParam
;
2166 aColParam
.pMinR
.reset(new sal_uLong
[ nColorCount
]);
2167 aColParam
.pMaxR
.reset(new sal_uLong
[ nColorCount
]);
2168 aColParam
.pMinG
.reset(new sal_uLong
[ nColorCount
]);
2169 aColParam
.pMaxG
.reset(new sal_uLong
[ nColorCount
]);
2170 aColParam
.pMinB
.reset(new sal_uLong
[ nColorCount
]);
2171 aColParam
.pMaxB
.reset(new sal_uLong
[ nColorCount
]);
2173 for( sal_uLong i
= 0; i
< nColorCount
; i
++ )
2177 nVal
= pSearchColors
[ i
].GetRed();
2178 aColParam
.pMinR
[ i
] = static_cast<sal_uLong
>(std::max( nVal
, tools::Long(0) ));
2179 aColParam
.pMaxR
[ i
] = static_cast<sal_uLong
>(std::min( nVal
, tools::Long(255) ));
2181 nVal
= pSearchColors
[ i
].GetGreen();
2182 aColParam
.pMinG
[ i
] = static_cast<sal_uLong
>(std::max( nVal
, tools::Long(0) ));
2183 aColParam
.pMaxG
[ i
] = static_cast<sal_uLong
>(std::min( nVal
, tools::Long(255) ));
2185 nVal
= pSearchColors
[ i
].GetBlue();
2186 aColParam
.pMinB
[ i
] = static_cast<sal_uLong
>(std::max( nVal
, tools::Long(0) ));
2187 aColParam
.pMaxB
[ i
] = static_cast<sal_uLong
>(std::min( nVal
, tools::Long(255) ));
2190 aColParam
.pDstCols
= pReplaceColors
;
2191 aColParam
.nCount
= nColorCount
;
2193 aBmpParam
.pSrcCols
= pSearchColors
;
2194 aBmpParam
.pDstCols
= pReplaceColors
;
2195 aBmpParam
.nCount
= nColorCount
;
2197 ImplExchangeColors( ImplColReplaceFnc
, &aColParam
, ImplBmpReplaceFnc
, &aBmpParam
);
2200 GDIMetaFile
GDIMetaFile::GetMonochromeMtf( const Color
& rColor
) const
2202 GDIMetaFile
aRet( *this );
2204 ImplColMonoParam aColParam
;
2205 ImplBmpMonoParam aBmpParam
;
2207 aColParam
.aColor
= rColor
;
2208 aBmpParam
.aColor
= rColor
;
2210 aRet
.ImplExchangeColors( ImplColMonoFnc
, &aColParam
, ImplBmpMonoFnc
, &aBmpParam
);
2215 BitmapChecksum
GDIMetaFile::GetChecksum() const
2217 SvMemoryStream
aMemStm( 65535, 65535 );
2218 ImplMetaWriteData aWriteData
;
2221 BitmapChecksumOctetArray aBCOA
;
2222 BitmapChecksum nCrc
= 0;
2224 aWriteData
.meActualCharSet
= aMemStm
.GetStreamCharSet();
2225 for( size_t i
= 0, nObjCount
= GetActionSize(); i
< nObjCount
; i
++ )
2227 MetaAction
* pAction
= GetAction( i
);
2229 switch( pAction
->GetType() )
2231 case MetaActionType::BMP
:
2233 MetaBmpAction
* pAct
= static_cast<MetaBmpAction
*>(pAction
);
2235 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2236 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2238 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2239 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2241 Int32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2242 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2244 Int32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2245 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2249 case MetaActionType::BMPSCALE
:
2251 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
2253 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2254 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2256 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2257 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2259 Int32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2260 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2262 Int32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2263 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2265 Int32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2266 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2268 Int32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2269 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2273 case MetaActionType::BMPSCALEPART
:
2275 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
2277 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2278 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2280 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2281 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2283 Int32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2284 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2286 Int32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2287 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2289 Int32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2290 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2292 Int32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2293 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2295 Int32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2296 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2298 Int32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2299 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2301 Int32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2302 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2304 Int32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2305 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2309 case MetaActionType::BMPEX
:
2311 MetaBmpExAction
* pAct
= static_cast<MetaBmpExAction
*>(pAction
);
2313 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2314 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2316 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2317 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2319 Int32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2320 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2322 Int32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2323 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2327 case MetaActionType::BMPEXSCALE
:
2329 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
2331 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2332 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2334 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2335 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2337 Int32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2338 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2340 Int32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2341 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2343 Int32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2344 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2346 Int32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2347 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2351 case MetaActionType::BMPEXSCALEPART
:
2353 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
2355 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2356 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2358 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2359 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2361 Int32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2362 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2364 Int32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2365 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2367 Int32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2368 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2370 Int32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2371 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2373 Int32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2374 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2376 Int32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2377 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2379 Int32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2380 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2382 Int32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2383 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2387 case MetaActionType::MASK
:
2389 MetaMaskAction
* pAct
= static_cast<MetaMaskAction
*>(pAction
);
2391 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2392 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2394 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2395 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2397 UInt32ToSVBT32( sal_uInt32(pAct
->GetColor()), aBT32
);
2398 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2400 Int32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2401 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2403 Int32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2404 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2408 case MetaActionType::MASKSCALE
:
2410 MetaMaskScaleAction
* pAct
= static_cast<MetaMaskScaleAction
*>(pAction
);
2412 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2413 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2415 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2416 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2418 UInt32ToSVBT32( sal_uInt32(pAct
->GetColor()), aBT32
);
2419 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2421 Int32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2422 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2424 Int32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2425 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2427 Int32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2428 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2430 Int32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2431 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2435 case MetaActionType::MASKSCALEPART
:
2437 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
2439 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2440 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2442 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2443 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2445 UInt32ToSVBT32( sal_uInt32(pAct
->GetColor()), aBT32
);
2446 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2448 Int32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2449 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2451 Int32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2452 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2454 Int32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2455 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2457 Int32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2458 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2460 Int32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2461 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2463 Int32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2464 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2466 Int32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2467 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2469 Int32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2470 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2474 case MetaActionType::EPS
:
2476 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
2477 nCrc
= vcl_get_checksum( nCrc
, pAct
->GetLink().GetData(), pAct
->GetLink().GetDataSize() );
2481 case MetaActionType::CLIPREGION
:
2483 MetaClipRegionAction
& rAct
= static_cast<MetaClipRegionAction
&>(*pAction
);
2484 const vcl::Region
& rRegion
= rAct
.GetRegion();
2486 if(rRegion
.HasPolyPolygonOrB2DPolyPolygon())
2488 // It has shown that this is a possible bottleneck for checksum calculation.
2489 // In worst case a very expensive RegionHandle representation gets created.
2490 // In this case it's cheaper to use the PolyPolygon
2491 const basegfx::B2DPolyPolygon
aPolyPolygon(rRegion
.GetAsB2DPolyPolygon());
2494 for(auto const& rPolygon
: aPolyPolygon
)
2496 const sal_uInt32
nPointCount(rPolygon
.count());
2497 const bool bControl(rPolygon
.areControlPointsUsed());
2499 for(sal_uInt32
b(0); b
< nPointCount
; b
++)
2501 const basegfx::B2DPoint
aPoint(rPolygon
.getB2DPoint(b
));
2503 DoubleToSVBT64(aPoint
.getX(), aSVBT64
);
2504 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2505 DoubleToSVBT64(aPoint
.getY(), aSVBT64
);
2506 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2510 if(rPolygon
.isPrevControlPointUsed(b
))
2512 const basegfx::B2DPoint
aCtrl(rPolygon
.getPrevControlPoint(b
));
2514 DoubleToSVBT64(aCtrl
.getX(), aSVBT64
);
2515 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2516 DoubleToSVBT64(aCtrl
.getY(), aSVBT64
);
2517 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2520 if(rPolygon
.isNextControlPointUsed(b
))
2522 const basegfx::B2DPoint
aCtrl(rPolygon
.getNextControlPoint(b
));
2524 DoubleToSVBT64(aCtrl
.getX(), aSVBT64
);
2525 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2526 DoubleToSVBT64(aCtrl
.getY(), aSVBT64
);
2527 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2533 sal_uInt8 tmp
= static_cast<sal_uInt8
>(rAct
.IsClipping());
2534 nCrc
= vcl_get_checksum(nCrc
, &tmp
, 1);
2538 pAction
->Write( aMemStm
, &aWriteData
);
2539 nCrc
= vcl_get_checksum( nCrc
, aMemStm
.GetData(), aMemStm
.Tell() );
2547 pAction
->Write( aMemStm
, &aWriteData
);
2548 nCrc
= vcl_get_checksum( nCrc
, aMemStm
.GetData(), aMemStm
.Tell() );
2558 sal_uLong
GDIMetaFile::GetSizeBytes() const
2560 sal_uLong nSizeBytes
= 0;
2562 for( size_t i
= 0, nObjCount
= GetActionSize(); i
< nObjCount
; ++i
)
2564 MetaAction
* pAction
= GetAction( i
);
2566 // default action size is set to 32 (=> not the exact value)
2569 // add sizes for large action content
2570 switch( pAction
->GetType() )
2572 case MetaActionType::BMP
: nSizeBytes
+= static_cast<MetaBmpAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2573 case MetaActionType::BMPSCALE
: nSizeBytes
+= static_cast<MetaBmpScaleAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2574 case MetaActionType::BMPSCALEPART
: nSizeBytes
+= static_cast<MetaBmpScalePartAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2576 case MetaActionType::BMPEX
: nSizeBytes
+= static_cast<MetaBmpExAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2577 case MetaActionType::BMPEXSCALE
: nSizeBytes
+= static_cast<MetaBmpExScaleAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2578 case MetaActionType::BMPEXSCALEPART
: nSizeBytes
+= static_cast<MetaBmpExScalePartAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2580 case MetaActionType::MASK
: nSizeBytes
+= static_cast<MetaMaskAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2581 case MetaActionType::MASKSCALE
: nSizeBytes
+= static_cast<MetaMaskScaleAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2582 case MetaActionType::MASKSCALEPART
: nSizeBytes
+= static_cast<MetaMaskScalePartAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2584 case MetaActionType::POLYLINE
: nSizeBytes
+= static_cast<MetaPolyLineAction
*>( pAction
)->GetPolygon().GetSize() * sizeof( Point
); break;
2585 case MetaActionType::POLYGON
: nSizeBytes
+= static_cast<MetaPolygonAction
*>( pAction
)->GetPolygon().GetSize() * sizeof( Point
); break;
2586 case MetaActionType::POLYPOLYGON
:
2588 const tools::PolyPolygon
& rPolyPoly
= static_cast<MetaPolyPolygonAction
*>( pAction
)->GetPolyPolygon();
2590 for( sal_uInt16 n
= 0; n
< rPolyPoly
.Count(); ++n
)
2591 nSizeBytes
+= ( rPolyPoly
[ n
].GetSize() * sizeof( Point
) );
2595 case MetaActionType::TEXT
: nSizeBytes
+= static_cast<MetaTextAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2596 case MetaActionType::STRETCHTEXT
: nSizeBytes
+= static_cast<MetaStretchTextAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2597 case MetaActionType::TEXTRECT
: nSizeBytes
+= static_cast<MetaTextRectAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2598 case MetaActionType::TEXTARRAY
:
2600 MetaTextArrayAction
* pTextArrayAction
= static_cast<MetaTextArrayAction
*>(pAction
);
2602 nSizeBytes
+= ( pTextArrayAction
->GetText().getLength() * sizeof( sal_Unicode
) );
2604 if( pTextArrayAction
->GetDXArray() )
2605 nSizeBytes
+= ( pTextArrayAction
->GetLen() << 2 );
2620 ImplMetaReadData
& m_rData
;
2621 rtl_TextEncoding m_eOrigCharSet
;
2623 DepthGuard(ImplMetaReadData
& rData
, SvStream
const & rIStm
)
2625 , m_eOrigCharSet(m_rData
.meActualCharSet
)
2627 ++m_rData
.mnParseDepth
;
2628 m_rData
.meActualCharSet
= rIStm
.GetStreamCharSet();
2630 bool TooDeep() const { return m_rData
.mnParseDepth
> 1024; }
2633 --m_rData
.mnParseDepth
;
2634 m_rData
.meActualCharSet
= m_eOrigCharSet
;
2639 SvStream
& ReadGDIMetaFile(SvStream
& rIStm
, GDIMetaFile
& rGDIMetaFile
, ImplMetaReadData
* pData
)
2641 if (rIStm
.GetError())
2643 SAL_WARN("vcl.gdi", "Stream error: " << rIStm
.GetError());
2647 sal_uLong nStmPos
= rIStm
.Tell();
2648 SvStreamEndian nOldFormat
= rIStm
.GetEndian();
2650 rIStm
.SetEndian( SvStreamEndian::LITTLE
);
2657 rIStm
.ReadBytes( aId
, 6 );
2659 if ( !strcmp( aId
, "VCLMTF" ) )
2662 sal_uInt32 nStmCompressMode
= 0;
2663 sal_uInt32 nCount
= 0;
2664 std::unique_ptr
<VersionCompatRead
> pCompat(new VersionCompatRead(rIStm
));
2666 rIStm
.ReadUInt32( nStmCompressMode
);
2667 TypeSerializer
aSerializer(rIStm
);
2668 aSerializer
.readMapMode(rGDIMetaFile
.m_aPrefMapMode
);
2669 aSerializer
.readSize(rGDIMetaFile
.m_aPrefSize
);
2670 rIStm
.ReadUInt32( nCount
);
2672 pCompat
.reset(); // destructor writes stuff into the header
2674 std::unique_ptr
<ImplMetaReadData
> xReadData
;
2677 xReadData
.reset(new ImplMetaReadData
);
2678 pData
= xReadData
.get();
2680 DepthGuard
aDepthGuard(*pData
, rIStm
);
2682 if (aDepthGuard
.TooDeep())
2683 throw std::runtime_error("too much recursion");
2685 for( sal_uInt32 nAction
= 0; ( nAction
< nCount
) && !rIStm
.eof(); nAction
++ )
2687 rtl::Reference
<MetaAction
> pAction
= MetaAction::ReadMetaAction(rIStm
, pData
);
2690 if (pAction
->GetType() == MetaActionType::COMMENT
)
2692 MetaCommentAction
* pCommentAct
= static_cast<MetaCommentAction
*>(pAction
.get());
2693 if ( pCommentAct
->GetComment() == "EMF_PLUS" )
2694 rGDIMetaFile
.UseCanvas( true );
2696 rGDIMetaFile
.AddAction( pAction
);
2702 rIStm
.Seek( nStmPos
);
2703 SVMConverter( rIStm
, rGDIMetaFile
);
2708 SAL_WARN("vcl", "GDIMetaFile exception during load");
2709 rIStm
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
2713 if( rIStm
.GetError() )
2715 rGDIMetaFile
.Clear();
2716 rIStm
.Seek( nStmPos
);
2719 rIStm
.SetEndian( nOldFormat
);
2723 SvStream
& WriteGDIMetaFile( SvStream
& rOStm
, const GDIMetaFile
& rGDIMetaFile
)
2725 if( !rOStm
.GetError() )
2727 const_cast< GDIMetaFile
& >( rGDIMetaFile
).Write( rOStm
);
2732 SvStream
& GDIMetaFile::Read( SvStream
& rIStm
)
2735 ReadGDIMetaFile( rIStm
, *this );
2740 SvStream
& GDIMetaFile::Write( SvStream
& rOStm
)
2742 const SvStreamCompressFlags nStmCompressMode
= rOStm
.GetCompressMode();
2743 SvStreamEndian nOldFormat
= rOStm
.GetEndian();
2745 rOStm
.SetEndian( SvStreamEndian::LITTLE
);
2746 rOStm
.WriteBytes( "VCLMTF", 6 );
2749 VersionCompatWrite
aCompat(rOStm
, 1);
2751 rOStm
.WriteUInt32(static_cast<sal_uInt32
>(nStmCompressMode
));
2752 TypeSerializer
aSerializer(rOStm
);
2753 aSerializer
.writeMapMode(m_aPrefMapMode
);
2754 aSerializer
.writeSize(m_aPrefSize
);
2755 rOStm
.WriteUInt32(GetActionSize());
2756 } // VersionCompatWrite dtor writes stuff into the header
2758 ImplMetaWriteData aWriteData
;
2760 aWriteData
.meActualCharSet
= rOStm
.GetStreamCharSet();
2762 MetaAction
* pAct
= FirstAction();
2765 pAct
->Write( rOStm
, &aWriteData
);
2766 pAct
= NextAction();
2769 rOStm
.SetEndian( nOldFormat
);
2774 bool GDIMetaFile::CreateThumbnail(BitmapEx
& rBitmapEx
, BmpConversion eColorConversion
, BmpScaleFlag nScaleFlag
) const
2776 // initialization seems to be complicated but is used to avoid rounding errors
2777 ScopedVclPtrInstance
< VirtualDevice
> aVDev
;
2778 // set Enable to tease the rendering down the code paths which use B2DPolygon and
2779 // avoid integer overflows on scaling tools::Polygon, e.g. moz1545040-1.svg
2780 // note: this is similar to DocumentToGraphicRenderer::renderToGraphic
2781 aVDev
->SetAntialiasing(AntialiasingFlags::Enable
| aVDev
->GetAntialiasing());
2782 const Point aNullPt
;
2783 const Point
aTLPix( aVDev
->LogicToPixel( aNullPt
, GetPrefMapMode() ) );
2784 const Point
aBRPix( aVDev
->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2785 Size
aDrawSize( aVDev
->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2786 Size
aSizePix( std::abs( aBRPix
.X() - aTLPix
.X() ) + 1, std::abs( aBRPix
.Y() - aTLPix
.Y() ) + 1 );
2787 sal_uInt32 nMaximumExtent
= 256;
2789 if (!rBitmapEx
.IsEmpty())
2790 rBitmapEx
.SetEmpty();
2792 // determine size that has the same aspect ratio as image size and
2793 // fits into the rectangle determined by nMaximumExtent
2794 if ( aSizePix
.Width() && aSizePix
.Height()
2795 && ( sal::static_int_cast
< tools::ULong
>(aSizePix
.Width()) >
2797 sal::static_int_cast
< tools::ULong
>(aSizePix
.Height()) >
2800 const Size
aOldSizePix( aSizePix
);
2801 double fWH
= static_cast< double >( aSizePix
.Width() ) / aSizePix
.Height();
2805 aSizePix
.setWidth( FRound( nMaximumExtent
* fWH
) );
2806 aSizePix
.setHeight( nMaximumExtent
);
2810 aSizePix
.setWidth( nMaximumExtent
);
2811 aSizePix
.setHeight( FRound( nMaximumExtent
/ fWH
) );
2814 aDrawSize
.setWidth( FRound( ( static_cast< double >( aDrawSize
.Width() ) * aSizePix
.Width() ) / aOldSizePix
.Width() ) );
2815 aDrawSize
.setHeight( FRound( ( static_cast< double >( aDrawSize
.Height() ) * aSizePix
.Height() ) / aOldSizePix
.Height() ) );
2818 // draw image(s) into VDev and get resulting image
2819 // do it 4x larger to be able to scale it down & get beautiful antialias
2820 Size
aAntialiasSize(aSizePix
.Width() * 4, aSizePix
.Height() * 4);
2821 if (aVDev
->SetOutputSizePixel(aAntialiasSize
))
2823 // antialias: provide 4x larger size, and then scale down the result
2824 Size
aAntialias(aDrawSize
.Width() * 4, aDrawSize
.Height() * 4);
2826 // draw metafile into VDev
2827 const_cast<GDIMetaFile
*>(this)->WindStart();
2828 const_cast<GDIMetaFile
*>(this)->Play(*aVDev
, Point(), aAntialias
);
2831 BitmapEx
aBitmap( aVDev
->GetBitmapEx( aNullPt
, aVDev
->GetOutputSizePixel() ) );
2833 // scale down the image to the desired size - use the input scaler for the scaling operation
2834 aBitmap
.Scale(aDrawSize
, nScaleFlag
);
2836 // convert to desired bitmap color format
2837 Size
aSize(aBitmap
.GetSizePixel());
2838 if (aSize
.Width() && aSize
.Height())
2839 aBitmap
.Convert(eColorConversion
);
2841 rBitmapEx
= aBitmap
;
2844 return !rBitmapEx
.IsEmpty();
2847 void GDIMetaFile::UseCanvas( bool _bUseCanvas
)
2849 m_bUseCanvas
= _bUseCanvas
;
2852 void GDIMetaFile::dumpAsXml(const char* pFileName
) const
2854 SvFileStream
aStream(pFileName
? OUString::fromUtf8(pFileName
) : OUString("file:///tmp/metafile.xml"),
2855 StreamMode::STD_READWRITE
| StreamMode::TRUNC
);
2856 assert(aStream
.good());
2857 MetafileXmlDump aDumper
;
2858 aDumper
.dump(*this, aStream
);
2861 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */