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 .
23 #include <tools/stream.hxx>
24 #include <tools/vcompat.hxx>
25 #include <tools/fract.hxx>
26 #include <vcl/metaact.hxx>
27 #include <vcl/salbtype.hxx>
28 #include <vcl/outdev.hxx>
29 #include <vcl/window.hxx>
30 #include <vcl/virdev.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/gdimtf.hxx>
33 #include <vcl/graphictools.hxx>
34 #include <basegfx/polygon/b2dpolygon.hxx>
35 #include <vcl/canvastools.hxx>
37 #include "svmconverter.hxx"
40 #include <salinst.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>
48 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
49 #include <com/sun/star/lang/XInitialization.hpp>
50 #include <com/sun/star/awt/XGraphics.hpp>
51 #include <com/sun/star/graphic/XGraphic.hpp>
52 #include <com/sun/star/graphic/XGraphicRenderer.hpp>
54 using namespace com::sun::star
;
56 #define GAMMA( _def_cVal, _def_InvGamma ) ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0,255))
58 struct ImplColAdjustParam
65 struct ImplBmpAdjustParam
67 short nLuminancePercent
;
68 short nContrastPercent
;
69 short nChannelRPercent
;
70 short nChannelGPercent
;
71 short nChannelBPercent
;
76 struct ImplColConvertParam
78 MtfConversion eConversion
;
81 struct ImplBmpConvertParam
83 BmpConversion eConversion
;
86 struct ImplColMonoParam
91 struct ImplBmpMonoParam
96 struct ImplColReplaceParam
104 const Color
* pDstCols
;
108 struct ImplBmpReplaceParam
110 const Color
* pSrcCols
;
111 const Color
* pDstCols
;
113 const sal_uLong
* pTols
;
116 GDIMetaFile::GDIMetaFile() :
117 m_nCurrentActionElement( 0 ),
118 m_aPrefSize ( 1, 1 ),
121 m_pOutDev ( nullptr ),
124 m_bUseCanvas ( false )
128 GDIMetaFile::GDIMetaFile( const GDIMetaFile
& rMtf
) :
129 m_nCurrentActionElement( rMtf
.m_nCurrentActionElement
),
130 m_aPrefMapMode ( rMtf
.m_aPrefMapMode
),
131 m_aPrefSize ( rMtf
.m_aPrefSize
),
132 m_pPrev ( rMtf
.m_pPrev
),
133 m_pNext ( rMtf
.m_pNext
),
134 m_pOutDev ( nullptr ),
137 m_bUseCanvas ( rMtf
.m_bUseCanvas
)
139 // Increment RefCount of MetaActions
140 for( size_t i
= 0, n
= rMtf
.GetActionSize(); i
< n
; ++i
)
142 rMtf
.GetAction( i
)->Duplicate();
143 m_aList
.push_back( rMtf
.GetAction( i
) );
148 Record( rMtf
.m_pOutDev
);
155 GDIMetaFile::~GDIMetaFile()
160 size_t GDIMetaFile::GetActionSize() const
162 return m_aList
.size();
165 MetaAction
* GDIMetaFile::GetAction( size_t nAction
) const
167 return (nAction
< m_aList
.size()) ? m_aList
[ nAction
] : nullptr;
170 MetaAction
* GDIMetaFile::FirstAction()
172 m_nCurrentActionElement
= 0;
173 return m_aList
.empty() ? nullptr : m_aList
[ 0 ];
176 MetaAction
* GDIMetaFile::NextAction()
178 return ( m_nCurrentActionElement
+ 1 < m_aList
.size() ) ? m_aList
[ ++m_nCurrentActionElement
] : nullptr;
181 MetaAction
* GDIMetaFile::ReplaceAction( MetaAction
* pAction
, size_t nAction
)
183 if ( nAction
>= m_aList
.size() )
185 // this method takes ownership of pAction and is
186 // therefore responsible for deleting it
190 //fdo#39995 This does't increment the incoming action ref-count nor does it
191 //decrement the outgoing action ref-count
192 std::swap(pAction
, m_aList
[nAction
]);
196 GDIMetaFile
& GDIMetaFile::operator=( const GDIMetaFile
& rMtf
)
202 // Increment RefCount of MetaActions
203 for( size_t i
= 0, n
= rMtf
.GetActionSize(); i
< n
; ++i
)
205 rMtf
.GetAction( i
)->Duplicate();
206 m_aList
.push_back( rMtf
.GetAction( i
) );
209 m_aPrefMapMode
= rMtf
.m_aPrefMapMode
;
210 m_aPrefSize
= rMtf
.m_aPrefSize
;
211 m_pPrev
= rMtf
.m_pPrev
;
212 m_pNext
= rMtf
.m_pNext
;
216 m_bUseCanvas
= rMtf
.m_bUseCanvas
;
220 Record( rMtf
.m_pOutDev
);
230 bool GDIMetaFile::operator==( const GDIMetaFile
& rMtf
) const
232 const size_t nObjCount
= m_aList
.size();
237 else if( rMtf
.GetActionSize() == nObjCount
&&
238 rMtf
.GetPrefSize() == m_aPrefSize
&&
239 rMtf
.GetPrefMapMode() == m_aPrefMapMode
)
243 for( size_t n
= 0; n
< nObjCount
; n
++ )
245 if( m_aList
[ n
] != rMtf
.GetAction( n
) )
256 void GDIMetaFile::Clear()
261 for(MetaAction
* i
: m_aList
)
266 void GDIMetaFile::Linker( OutputDevice
* pOut
, bool bLink
)
271 m_pPrev
= pOut
->GetConnectMetaFile();
272 pOut
->SetConnectMetaFile( this );
275 m_pPrev
->m_pNext
= this;
281 m_pNext
->m_pPrev
= m_pPrev
;
284 m_pPrev
->m_pNext
= m_pNext
;
289 m_pPrev
->m_pNext
= nullptr;
291 pOut
->SetConnectMetaFile( m_pPrev
);
299 void GDIMetaFile::Record( OutputDevice
* pOut
)
304 m_nCurrentActionElement
= m_aList
.empty() ? 0 : (m_aList
.size() - 1);
307 Linker( pOut
, true );
310 void GDIMetaFile::Play( GDIMetaFile
& rMtf
)
312 if ( !m_bRecord
&& !rMtf
.m_bRecord
)
314 MetaAction
* pAction
= GetCurAction();
315 const size_t nObjCount
= m_aList
.size();
317 rMtf
.UseCanvas( rMtf
.GetUseCanvas() || m_bUseCanvas
);
319 for( size_t nCurPos
= m_nCurrentActionElement
; nCurPos
< nObjCount
; nCurPos
++ )
323 pAction
->Duplicate();
324 rMtf
.AddAction( pAction
);
327 pAction
= NextAction();
332 void GDIMetaFile::Play( OutputDevice
* pOut
, size_t nPos
)
336 MetaAction
* pAction
= GetCurAction();
337 const size_t nObjCount
= m_aList
.size();
338 size_t nSyncCount
= ( pOut
->GetOutDevType() == OUTDEV_WINDOW
) ? 0x000000ff : 0xffffffff;
340 if( nPos
> nObjCount
)
343 // #i23407# Set backwards-compatible text language and layout mode
344 // This is necessary, since old metafiles don't even know of these
345 // recent add-ons. Newer metafiles must of course explicitly set
347 pOut
->Push( PushFlags::TEXTLAYOUTMODE
|PushFlags::TEXTLANGUAGE
);
348 pOut
->SetLayoutMode( ComplexTextLayoutFlags::Default
);
349 pOut
->SetDigitLanguage( LANGUAGE_SYSTEM
);
351 SAL_INFO( "vcl.gdi", "GDIMetaFile::Play on device of size: " << pOut
->GetOutputSizePixel().Width() << " " << pOut
->GetOutputSizePixel().Height());
353 if( !ImplPlayWithRenderer( pOut
, Point(0,0), pOut
->GetOutputSize() ) ) {
355 for( size_t nCurPos
= m_nCurrentActionElement
; nCurPos
< nPos
; nCurPos
++ )
359 pAction
->Execute( pOut
);
361 // flush output from time to time
362 if( i
++ > nSyncCount
)
364 static_cast<vcl::Window
*>( pOut
)->Flush();
369 pAction
= NextAction();
376 bool GDIMetaFile::ImplPlayWithRenderer( OutputDevice
* pOut
, const Point
& rPos
, Size rLogicDestSize
)
381 Size
rDestSize( pOut
->LogicToPixel( rLogicDestSize
) );
383 const vcl::Window
* win
= dynamic_cast <vcl::Window
*> ( pOut
);
386 win
= Application::GetActiveTopWindow();
388 win
= Application::GetFirstTopLevelWindow();
395 uno::Reference
<rendering::XCanvas
> xCanvas
= win
->GetCanvas ();
400 Size
aSize (rDestSize
.Width () + 1, rDestSize
.Height () + 1);
401 uno::Reference
<rendering::XBitmap
> xBitmap
= xCanvas
->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize
));
404 uno::Reference
< rendering::XBitmapCanvas
> xBitmapCanvas( xBitmap
, uno::UNO_QUERY
);
405 if( xBitmapCanvas
.is() )
407 uno::Reference
< uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
408 uno::Reference
< rendering::XMtfRenderer
> xMtfRenderer
= rendering::MtfRenderer::createWithBitmapCanvas( xContext
, xBitmapCanvas
);
410 xBitmapCanvas
->clear();
411 uno::Reference
< beans::XFastPropertySet
> xMtfFastPropertySet( xMtfRenderer
, uno::UNO_QUERY
);
412 if( xMtfFastPropertySet
.is() )
413 // set this metafile to the renderer to
414 // speedup things (instead of copying data to
415 // sequence of bytes passed to renderer)
416 xMtfFastPropertySet
->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64
>( this ) ) );
418 xMtfRenderer
->draw( rDestSize
.Width(), rDestSize
.Height() );
421 if( aBitmapEx
.Create( xBitmapCanvas
, aSize
) )
423 if ( pOut
->GetMapMode() == MapUnit::MapPixel
)
424 pOut
->DrawBitmapEx( rPos
, aBitmapEx
);
426 pOut
->DrawBitmapEx( rPos
, rLogicDestSize
, aBitmapEx
);
432 catch (const uno::RuntimeException
& )
434 throw; // runtime errors are fatal
436 catch (const uno::Exception
& e
)
438 // ignore errors, no way of reporting them here
440 "GDIMetaFile::ImplPlayWithRenderer: exception: " << e
.Message
);
446 void GDIMetaFile::Play( OutputDevice
* pOut
, const Point
& rPos
,
449 vcl::Region aDrawClipRegion
;
450 MapMode
aDrawMap( GetPrefMapMode() );
451 Size
aDestSize( pOut
->LogicToPixel( rSize
) );
453 if( aDestSize
.Width() && aDestSize
.Height() )
455 GDIMetaFile
* pMtf
= pOut
->GetConnectMetaFile();
457 if( ImplPlayWithRenderer( pOut
, rPos
, rSize
) )
460 Size
aTmpPrefSize( pOut
->LogicToPixel( GetPrefSize(), aDrawMap
) );
462 if( !aTmpPrefSize
.Width() )
463 aTmpPrefSize
.Width() = aDestSize
.Width();
465 if( !aTmpPrefSize
.Height() )
466 aTmpPrefSize
.Height() = aDestSize
.Height();
468 Fraction
aScaleX( aDestSize
.Width(), aTmpPrefSize
.Width() );
469 Fraction
aScaleY( aDestSize
.Height(), aTmpPrefSize
.Height() );
471 aScaleX
*= aDrawMap
.GetScaleX(); aDrawMap
.SetScaleX( aScaleX
);
472 aScaleY
*= aDrawMap
.GetScaleY(); aDrawMap
.SetScaleY( aScaleY
);
474 // #i47260# Convert logical output position to offset within
475 // the metafile's mapmode. Therefore, disable pixel offset on
476 // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
477 // different mapmode (the one currently set on pOut, that is)
478 // - thus, aDrawMap's origin would generally be wrong. And
479 // even _if_ aDrawMap is similar to pOutDev's current mapmode,
480 // it's _still_ undesirable to have pixel offset unequal zero,
481 // because one would still get round-off errors (the
482 // round-trip error for LogicToPixel( PixelToLogic() ) was the
483 // reason for having pixel offset in the first place).
484 const Size
& rOldOffset( pOut
->GetPixelOffset() );
485 const Size aEmptySize
;
486 pOut
->SetPixelOffset( aEmptySize
);
487 aDrawMap
.SetOrigin( pOut
->PixelToLogic( pOut
->LogicToPixel( rPos
), aDrawMap
) );
488 pOut
->SetPixelOffset( rOldOffset
);
492 if ( pMtf
&& pMtf
->IsRecord() && ( pOut
->GetOutDevType() != OUTDEV_PRINTER
) )
493 pOut
->SetRelativeMapMode( aDrawMap
);
495 pOut
->SetMapMode( aDrawMap
);
497 // #i23407# Set backwards-compatible text language and layout mode
498 // This is necessary, since old metafiles don't even know of these
499 // recent add-ons. Newer metafiles must of course explicitly set
501 pOut
->SetLayoutMode( ComplexTextLayoutFlags::Default
);
502 pOut
->SetDigitLanguage( LANGUAGE_SYSTEM
);
510 void GDIMetaFile::Pause( bool _bPause
)
517 Linker( m_pOutDev
, false );
522 Linker( m_pOutDev
, true );
529 void GDIMetaFile::Stop()
536 Linker( m_pOutDev
, false );
542 void GDIMetaFile::WindStart()
545 m_nCurrentActionElement
= 0;
548 void GDIMetaFile::WindPrev()
551 if ( m_nCurrentActionElement
> 0 )
552 --m_nCurrentActionElement
;
555 void GDIMetaFile::AddAction( MetaAction
* pAction
)
557 m_aList
.push_back( pAction
);
561 pAction
->Duplicate();
562 m_pPrev
->AddAction( pAction
);
566 void GDIMetaFile::AddAction( MetaAction
* pAction
, size_t nPos
)
568 if ( nPos
< m_aList
.size() )
570 ::std::vector
< MetaAction
* >::iterator it
= m_aList
.begin();
571 ::std::advance( it
, nPos
);
572 m_aList
.insert( it
, pAction
);
576 m_aList
.push_back( pAction
);
581 pAction
->Duplicate();
582 m_pPrev
->AddAction( pAction
, nPos
);
586 void GDIMetaFile::push_back( MetaAction
* pAction
)
588 m_aList
.push_back( pAction
);
591 void GDIMetaFile::RemoveAction( size_t nPos
)
593 if ( nPos
< m_aList
.size() )
595 ::std::vector
< MetaAction
* >::iterator it
= m_aList
.begin();
596 ::std::advance( it
, nPos
);
603 m_pPrev
->RemoveAction( nPos
);
606 bool GDIMetaFile::Mirror( BmpMirrorFlags nMirrorFlags
)
608 const Size
aOldPrefSize( GetPrefSize() );
610 double fScaleX
, fScaleY
;
613 if( nMirrorFlags
& BmpMirrorFlags::Horizontal
)
615 nMoveX
= std::abs( aOldPrefSize
.Width() ) - 1;
624 if( nMirrorFlags
& BmpMirrorFlags::Vertical
)
626 nMoveY
= std::abs( aOldPrefSize
.Height() ) - 1;
635 if( ( fScaleX
!= 1.0 ) || ( fScaleY
!= 1.0 ) )
637 Scale( fScaleX
, fScaleY
);
638 Move( nMoveX
, nMoveY
);
639 SetPrefSize( aOldPrefSize
);
648 void GDIMetaFile::Move( long nX
, long nY
)
650 const Size
aBaseOffset( nX
, nY
);
651 Size
aOffset( aBaseOffset
);
652 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
654 aMapVDev
->EnableOutput( false );
655 aMapVDev
->SetMapMode( GetPrefMapMode() );
657 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
659 const MetaActionType nType
= pAct
->GetType();
662 if( pAct
->GetRefCount() > 1 )
664 m_aList
[ m_nCurrentActionElement
] = pModAct
= pAct
->Clone();
670 if( ( MetaActionType::MAPMODE
== nType
) ||
671 ( MetaActionType::PUSH
== nType
) ||
672 ( MetaActionType::POP
== nType
) )
674 pModAct
->Execute( aMapVDev
.get() );
675 aOffset
= OutputDevice::LogicToLogic( aBaseOffset
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
678 pModAct
->Move( aOffset
.Width(), aOffset
.Height() );
682 void GDIMetaFile::Move( long nX
, long nY
, long nDPIX
, long nDPIY
)
684 const Size
aBaseOffset( nX
, nY
);
685 Size
aOffset( aBaseOffset
);
686 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
688 aMapVDev
->EnableOutput( false );
689 aMapVDev
->SetReferenceDevice( nDPIX
, nDPIY
);
690 aMapVDev
->SetMapMode( GetPrefMapMode() );
692 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
694 const MetaActionType nType
= pAct
->GetType();
697 if( pAct
->GetRefCount() > 1 )
699 m_aList
[ m_nCurrentActionElement
] = pModAct
= pAct
->Clone();
705 if( ( MetaActionType::MAPMODE
== nType
) ||
706 ( MetaActionType::PUSH
== nType
) ||
707 ( MetaActionType::POP
== nType
) )
709 pModAct
->Execute( aMapVDev
.get() );
710 if( aMapVDev
->GetMapMode().GetMapUnit() == MapUnit::MapPixel
)
712 aOffset
= aMapVDev
->LogicToPixel( aBaseOffset
, GetPrefMapMode() );
713 MapMode
aMap( aMapVDev
->GetMapMode() );
714 aOffset
.Width() = static_cast<long>(aOffset
.Width() * (double)aMap
.GetScaleX());
715 aOffset
.Height() = static_cast<long>(aOffset
.Height() * (double)aMap
.GetScaleY());
718 aOffset
= OutputDevice::LogicToLogic( aBaseOffset
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
721 pModAct
->Move( aOffset
.Width(), aOffset
.Height() );
725 void GDIMetaFile::Scale( double fScaleX
, double fScaleY
)
727 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
731 if( pAct
->GetRefCount() > 1 )
733 m_aList
[ m_nCurrentActionElement
] = pModAct
= pAct
->Clone();
739 pModAct
->Scale( fScaleX
, fScaleY
);
742 m_aPrefSize
.Width() = FRound( m_aPrefSize
.Width() * fScaleX
);
743 m_aPrefSize
.Height() = FRound( m_aPrefSize
.Height() * fScaleY
);
746 void GDIMetaFile::Scale( const Fraction
& rScaleX
, const Fraction
& rScaleY
)
748 Scale( (double) rScaleX
, (double) rScaleY
);
751 void GDIMetaFile::Clip( const tools::Rectangle
& i_rClipRect
)
753 tools::Rectangle
aCurRect( i_rClipRect
);
754 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
756 aMapVDev
->EnableOutput( false );
757 aMapVDev
->SetMapMode( GetPrefMapMode() );
759 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
761 const MetaActionType nType
= pAct
->GetType();
763 if( ( MetaActionType::MAPMODE
== nType
) ||
764 ( MetaActionType::PUSH
== nType
) ||
765 ( MetaActionType::POP
== nType
) )
767 pAct
->Execute( aMapVDev
.get() );
768 aCurRect
= OutputDevice::LogicToLogic( i_rClipRect
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
770 else if( nType
== MetaActionType::CLIPREGION
)
772 MetaClipRegionAction
* pOldAct
= static_cast<MetaClipRegionAction
*>(pAct
);
773 vcl::Region
aNewReg( aCurRect
);
774 if( pOldAct
->IsClipping() )
775 aNewReg
.Intersect( pOldAct
->GetRegion() );
776 MetaClipRegionAction
* pNewAct
= new MetaClipRegionAction( aNewReg
, true );
777 m_aList
[ m_nCurrentActionElement
] = pNewAct
;
783 Point
GDIMetaFile::ImplGetRotatedPoint( const Point
& rPt
, const Point
& rRotatePt
,
784 const Size
& rOffset
, double fSin
, double fCos
)
786 const long nX
= rPt
.X() - rRotatePt
.X();
787 const long nY
= rPt
.Y() - rRotatePt
.Y();
789 return Point( FRound( fCos
* nX
+ fSin
* nY
) + rRotatePt
.X() + rOffset
.Width(),
790 -FRound( fSin
* nX
- fCos
* nY
) + rRotatePt
.Y() + rOffset
.Height() );
793 tools::Polygon
GDIMetaFile::ImplGetRotatedPolygon( const tools::Polygon
& rPoly
, const Point
& rRotatePt
,
794 const Size
& rOffset
, double fSin
, double fCos
)
796 tools::Polygon
aRet( rPoly
);
798 aRet
.Rotate( rRotatePt
, fSin
, fCos
);
799 aRet
.Move( rOffset
.Width(), rOffset
.Height() );
804 tools::PolyPolygon
GDIMetaFile::ImplGetRotatedPolyPolygon( const tools::PolyPolygon
& rPolyPoly
, const Point
& rRotatePt
,
805 const Size
& rOffset
, double fSin
, double fCos
)
807 tools::PolyPolygon
aRet( rPolyPoly
);
809 aRet
.Rotate( rRotatePt
, fSin
, fCos
);
810 aRet
.Move( rOffset
.Width(), rOffset
.Height() );
815 void GDIMetaFile::ImplAddGradientEx( GDIMetaFile
& rMtf
,
816 const OutputDevice
& rMapDev
,
817 const tools::PolyPolygon
& rPolyPoly
,
818 const Gradient
& rGrad
)
820 // Generate comment, GradientEx and Gradient actions (within DrawGradient)
821 ScopedVclPtrInstance
< VirtualDevice
> aVDev(rMapDev
, DeviceFormat::DEFAULT
);
822 aVDev
->EnableOutput( false );
823 GDIMetaFile aGradMtf
;
825 aGradMtf
.Record( aVDev
.get() );
826 aVDev
->DrawGradient( rPolyPoly
, rGrad
);
829 size_t i
, nAct( aGradMtf
.GetActionSize() );
830 for( i
=0; i
< nAct
; ++i
)
832 MetaAction
* pMetaAct
= aGradMtf
.GetAction( i
);
833 pMetaAct
->Duplicate();
834 rMtf
.AddAction( pMetaAct
);
838 void GDIMetaFile::Rotate( long nAngle10
)
841 nAngle10
= ( nAngle10
< 0 ) ? ( 3599 + nAngle10
) : nAngle10
;
846 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
847 const double fAngle
= F_PI1800
* nAngle10
;
848 const double fSin
= sin( fAngle
);
849 const double fCos
= cos( fAngle
);
850 tools::Rectangle aRect
=tools::Rectangle( Point(), GetPrefSize() );
851 tools::Polygon
aPoly( aRect
);
853 aPoly
.Rotate( Point(), fSin
, fCos
);
855 aMapVDev
->EnableOutput( false );
856 aMapVDev
->SetMapMode( GetPrefMapMode() );
858 const tools::Rectangle
aNewBound( aPoly
.GetBoundRect() );
860 const Point
aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
861 const Size
aOffset( -aNewBound
.Left(), -aNewBound
.Top() );
863 Point
aRotAnchor( aOrigin
);
864 Size
aRotOffset( aOffset
);
866 for( MetaAction
* pAction
= FirstAction(); pAction
; pAction
= NextAction() )
868 const MetaActionType nActionType
= pAction
->GetType();
870 switch( nActionType
)
872 case( MetaActionType::PIXEL
):
874 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
875 aMtf
.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
876 pAct
->GetColor() ) );
880 case( MetaActionType::POINT
):
882 MetaPointAction
* pAct
= static_cast<MetaPointAction
*>(pAction
);
883 aMtf
.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
887 case( MetaActionType::LINE
):
889 MetaLineAction
* pAct
= static_cast<MetaLineAction
*>(pAction
);
890 aMtf
.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct
->GetStartPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
891 ImplGetRotatedPoint( pAct
->GetEndPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
892 pAct
->GetLineInfo() ) );
896 case( MetaActionType::RECT
):
898 MetaRectAction
* pAct
= static_cast<MetaRectAction
*>(pAction
);
899 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
903 case( MetaActionType::ROUNDRECT
):
905 MetaRoundRectAction
* pAct
= static_cast<MetaRoundRectAction
*>(pAction
);
906 const tools::Polygon
aRoundRectPoly( pAct
->GetRect(), pAct
->GetHorzRound(), pAct
->GetVertRound() );
908 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
912 case( MetaActionType::ELLIPSE
):
914 MetaEllipseAction
* pAct
= static_cast<MetaEllipseAction
*>(pAction
);
915 const tools::Polygon
aEllipsePoly( pAct
->GetRect().Center(), pAct
->GetRect().GetWidth() >> 1, pAct
->GetRect().GetHeight() >> 1 );
917 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
921 case( MetaActionType::ARC
):
923 MetaArcAction
* pAct
= static_cast<MetaArcAction
*>(pAction
);
924 const tools::Polygon
aArcPoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Arc
);
926 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
930 case( MetaActionType::PIE
):
932 MetaPieAction
* pAct
= static_cast<MetaPieAction
*>(pAction
);
933 const tools::Polygon
aPiePoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Pie
);
935 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
939 case( MetaActionType::CHORD
):
941 MetaChordAction
* pAct
= static_cast<MetaChordAction
*>(pAction
);
942 const tools::Polygon
aChordPoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Chord
);
944 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
948 case( MetaActionType::POLYLINE
):
950 MetaPolyLineAction
* pAct
= static_cast<MetaPolyLineAction
*>(pAction
);
951 aMtf
.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct
->GetPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
), pAct
->GetLineInfo() ) );
955 case( MetaActionType::POLYGON
):
957 MetaPolygonAction
* pAct
= static_cast<MetaPolygonAction
*>(pAction
);
958 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct
->GetPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
962 case( MetaActionType::POLYPOLYGON
):
964 MetaPolyPolygonAction
* pAct
= static_cast<MetaPolyPolygonAction
*>(pAction
);
965 aMtf
.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
969 case( MetaActionType::TEXT
):
971 MetaTextAction
* pAct
= static_cast<MetaTextAction
*>(pAction
);
972 aMtf
.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
973 pAct
->GetText(), pAct
->GetIndex(), pAct
->GetLen() ) );
977 case( MetaActionType::TEXTARRAY
):
979 MetaTextArrayAction
* pAct
= static_cast<MetaTextArrayAction
*>(pAction
);
980 aMtf
.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
981 pAct
->GetText(), pAct
->GetDXArray(), pAct
->GetIndex(), pAct
->GetLen() ) );
985 case( MetaActionType::STRETCHTEXT
):
987 MetaStretchTextAction
* pAct
= static_cast<MetaStretchTextAction
*>(pAction
);
988 aMtf
.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
989 pAct
->GetWidth(), pAct
->GetText(), pAct
->GetIndex(), pAct
->GetLen() ) );
993 case( MetaActionType::TEXTLINE
):
995 MetaTextLineAction
* pAct
= static_cast<MetaTextLineAction
*>(pAction
);
996 aMtf
.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct
->GetStartPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
997 pAct
->GetWidth(), pAct
->GetStrikeout(), pAct
->GetUnderline(), pAct
->GetOverline() ) );
1001 case( MetaActionType::BMPSCALE
):
1003 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1004 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1005 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1006 BitmapEx
aBmpEx( pAct
->GetBitmap() );
1008 aBmpEx
.Rotate( nAngle10
, Color( COL_TRANSPARENT
) );
1009 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(),
1014 case( MetaActionType::BMPSCALEPART
):
1016 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1017 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetDestPoint(), pAct
->GetDestSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1018 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1019 BitmapEx
aBmpEx( pAct
->GetBitmap() );
1021 aBmpEx
.Crop( tools::Rectangle( pAct
->GetSrcPoint(), pAct
->GetSrcSize() ) );
1022 aBmpEx
.Rotate( nAngle10
, Color( COL_TRANSPARENT
) );
1024 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1028 case( MetaActionType::BMPEXSCALE
):
1030 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1031 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1032 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1033 BitmapEx
aBmpEx( pAct
->GetBitmapEx() );
1035 aBmpEx
.Rotate( nAngle10
, Color( COL_TRANSPARENT
) );
1037 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1041 case( MetaActionType::BMPEXSCALEPART
):
1043 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1044 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetDestPoint(), pAct
->GetDestSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1045 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1046 BitmapEx
aBmpEx( pAct
->GetBitmapEx() );
1048 aBmpEx
.Crop( tools::Rectangle( pAct
->GetSrcPoint(), pAct
->GetSrcSize() ) );
1049 aBmpEx
.Rotate( nAngle10
, Color( COL_TRANSPARENT
) );
1051 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1055 case( MetaActionType::GRADIENT
):
1057 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1059 ImplAddGradientEx( aMtf
, *aMapVDev
.get(),
1060 ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1061 pAct
->GetGradient() );
1065 case( MetaActionType::GRADIENTEX
):
1067 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1068 aMtf
.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1069 pAct
->GetGradient() ) );
1073 // Handle gradientex comment block correctly
1074 case( MetaActionType::COMMENT
):
1076 MetaCommentAction
* pCommentAct
= static_cast<MetaCommentAction
*>(pAction
);
1077 if( pCommentAct
->GetComment() == "XGRAD_SEQ_BEGIN" )
1079 int nBeginComments( 1 );
1080 pAction
= NextAction();
1082 // skip everything, except gradientex action
1085 const MetaActionType nType
= pAction
->GetType();
1087 if( MetaActionType::GRADIENTEX
== nType
)
1089 // Add rotated gradientex
1090 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1091 ImplAddGradientEx( aMtf
, *aMapVDev
.get(),
1092 ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1093 pAct
->GetGradient() );
1095 else if( MetaActionType::COMMENT
== nType
)
1097 MetaCommentAction
* pAct
= static_cast<MetaCommentAction
*>(pAction
);
1098 if( pAct
->GetComment() == "XGRAD_SEQ_END" )
1100 // handle nested blocks
1103 // gradientex comment block: end reached, done.
1104 if( !nBeginComments
)
1107 else if( pAct
->GetComment() == "XGRAD_SEQ_BEGIN" )
1109 // handle nested blocks
1115 pAction
=NextAction();
1120 bool bPathStroke
= (pCommentAct
->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1121 if ( bPathStroke
|| pCommentAct
->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1123 if ( pCommentAct
->GetDataSize() )
1125 SvMemoryStream
aMemStm( const_cast<sal_uInt8
*>(pCommentAct
->GetData()), pCommentAct
->GetDataSize(), StreamMode::READ
);
1126 SvMemoryStream aDest
;
1129 SvtGraphicStroke aStroke
;
1130 ReadSvtGraphicStroke( aMemStm
, aStroke
);
1131 tools::Polygon aPath
;
1132 aStroke
.getPath( aPath
);
1133 aStroke
.setPath( ImplGetRotatedPolygon( aPath
, aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1134 WriteSvtGraphicStroke( aDest
, aStroke
);
1135 aMtf
.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1136 static_cast<const sal_uInt8
*>( aDest
.GetData()), aDest
.Tell() ) );
1140 SvtGraphicFill aFill
;
1141 ReadSvtGraphicFill( aMemStm
, aFill
);
1142 tools::PolyPolygon aPath
;
1143 aFill
.getPath( aPath
);
1144 aFill
.setPath( ImplGetRotatedPolyPolygon( aPath
, aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1145 WriteSvtGraphicFill( aDest
, aFill
);
1146 aMtf
.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1147 static_cast<const sal_uInt8
*>( aDest
.GetData()), aDest
.Tell() ) );
1151 else if ( pCommentAct
->GetComment() == "XPATHSTROKE_SEQ_END"
1152 || pCommentAct
->GetComment() == "XPATHFILL_SEQ_END" )
1154 pAction
->Execute( aMapVDev
.get() );
1155 pAction
->Duplicate();
1156 aMtf
.AddAction( pAction
);
1162 case( MetaActionType::HATCH
):
1164 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
1165 Hatch
aHatch( pAct
->GetHatch() );
1167 aHatch
.SetAngle( aHatch
.GetAngle() + (sal_uInt16
) nAngle10
);
1168 aMtf
.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1173 case( MetaActionType::Transparent
):
1175 MetaTransparentAction
* pAct
= static_cast<MetaTransparentAction
*>(pAction
);
1176 aMtf
.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1177 pAct
->GetTransparence() ) );
1181 case( MetaActionType::FLOATTRANSPARENT
):
1183 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
1184 GDIMetaFile
aTransMtf( pAct
->GetGDIMetaFile() );
1185 tools::Polygon
aMtfPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1186 tools::Rectangle
aMtfRect( aMtfPoly
.GetBoundRect() );
1188 aTransMtf
.Rotate( nAngle10
);
1189 aMtf
.AddAction( new MetaFloatTransparentAction( aTransMtf
, aMtfRect
.TopLeft(), aMtfRect
.GetSize(),
1190 pAct
->GetGradient() ) );
1194 case( MetaActionType::EPS
):
1196 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
1197 GDIMetaFile
aEPSMtf( pAct
->GetSubstitute() );
1198 tools::Polygon
aEPSPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1199 tools::Rectangle
aEPSRect( aEPSPoly
.GetBoundRect() );
1201 aEPSMtf
.Rotate( nAngle10
);
1202 aMtf
.AddAction( new MetaEPSAction( aEPSRect
.TopLeft(), aEPSRect
.GetSize(),
1203 pAct
->GetLink(), aEPSMtf
) );
1207 case( MetaActionType::CLIPREGION
):
1209 MetaClipRegionAction
* pAct
= static_cast<MetaClipRegionAction
*>(pAction
);
1211 if( pAct
->IsClipping() && pAct
->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1212 aMtf
.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct
->GetRegion().GetAsPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ), true ) );
1215 pAction
->Duplicate();
1216 aMtf
.AddAction( pAction
);
1221 case( MetaActionType::ISECTRECTCLIPREGION
):
1223 MetaISectRectClipRegionAction
* pAct
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
1224 aMtf
.AddAction( new MetaISectRegionClipRegionAction(vcl::Region(
1225 ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
,
1226 aRotOffset
, fSin
, fCos
)) ) );
1230 case( MetaActionType::ISECTREGIONCLIPREGION
):
1232 MetaISectRegionClipRegionAction
* pAct
= static_cast<MetaISectRegionClipRegionAction
*>(pAction
);
1233 const vcl::Region
& rRegion
= pAct
->GetRegion();
1235 if( rRegion
.HasPolyPolygonOrB2DPolyPolygon() )
1236 aMtf
.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion
.GetAsPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) ) );
1239 pAction
->Duplicate();
1240 aMtf
.AddAction( pAction
);
1245 case( MetaActionType::REFPOINT
):
1247 MetaRefPointAction
* pAct
= static_cast<MetaRefPointAction
*>(pAction
);
1248 aMtf
.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct
->GetRefPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
), pAct
->IsSetting() ) );
1252 case( MetaActionType::FONT
):
1254 MetaFontAction
* pAct
= static_cast<MetaFontAction
*>(pAction
);
1255 vcl::Font
aFont( pAct
->GetFont() );
1257 aFont
.SetOrientation( aFont
.GetOrientation() + (sal_uInt16
) nAngle10
);
1258 aMtf
.AddAction( new MetaFontAction( aFont
) );
1262 case( MetaActionType::BMP
):
1263 case( MetaActionType::BMPEX
):
1264 case( MetaActionType::MASK
):
1265 case( MetaActionType::MASKSCALE
):
1266 case( MetaActionType::MASKSCALEPART
):
1267 case( MetaActionType::WALLPAPER
):
1268 case( MetaActionType::TEXTRECT
):
1269 case( MetaActionType::MOVECLIPREGION
):
1271 OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1277 pAction
->Execute( aMapVDev
.get() );
1278 pAction
->Duplicate();
1279 aMtf
.AddAction( pAction
);
1281 // update rotation point and offset, if necessary
1282 if( ( MetaActionType::MAPMODE
== nActionType
) ||
1283 ( MetaActionType::PUSH
== nActionType
) ||
1284 ( MetaActionType::POP
== nActionType
) )
1286 aRotAnchor
= OutputDevice::LogicToLogic( aOrigin
, m_aPrefMapMode
, aMapVDev
->GetMapMode() );
1287 aRotOffset
= OutputDevice::LogicToLogic( aOffset
, m_aPrefMapMode
, aMapVDev
->GetMapMode() );
1294 aMtf
.m_aPrefMapMode
= m_aPrefMapMode
;
1295 aMtf
.m_aPrefSize
= aNewBound
.GetSize();
1301 static void ImplActionBounds( tools::Rectangle
& o_rOutBounds
,
1302 const tools::Rectangle
& i_rInBounds
,
1303 const std::vector
<tools::Rectangle
>& i_rClipStack
,
1304 tools::Rectangle
* o_pHairline
)
1306 tools::Rectangle
aBounds( i_rInBounds
);
1307 if( ! i_rInBounds
.IsEmpty() && ! i_rClipStack
.empty() && ! i_rClipStack
.back().IsEmpty() )
1308 aBounds
.Intersection( i_rClipStack
.back() );
1309 if( ! aBounds
.IsEmpty() )
1311 if( ! o_rOutBounds
.IsEmpty() )
1312 o_rOutBounds
.Union( aBounds
);
1314 o_rOutBounds
= aBounds
;
1318 if( ! o_pHairline
->IsEmpty() )
1319 o_pHairline
->Union( aBounds
);
1321 *o_pHairline
= aBounds
;
1326 tools::Rectangle
GDIMetaFile::GetBoundRect( OutputDevice
& i_rReference
, tools::Rectangle
* pHairline
) const
1329 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev( i_rReference
);
1331 aMapVDev
->EnableOutput( false );
1332 aMapVDev
->SetMapMode( GetPrefMapMode() );
1334 std::vector
<tools::Rectangle
> aClipStack( 1, tools::Rectangle() );
1335 std::vector
<PushFlags
> aPushFlagStack
;
1337 tools::Rectangle aBound
;
1340 *pHairline
= tools::Rectangle();
1342 const sal_uLong
nCount(GetActionSize());
1344 for(sal_uLong
a(0); a
< nCount
; a
++)
1346 MetaAction
* pAction
= GetAction(a
);
1347 const MetaActionType nActionType
= pAction
->GetType();
1348 tools::Rectangle
* pUseHairline
= (pHairline
&& aMapVDev
->IsLineColor()) ? pHairline
: nullptr;
1350 switch( nActionType
)
1352 case( MetaActionType::PIXEL
):
1354 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
1355 ImplActionBounds( aBound
,
1356 tools::Rectangle( OutputDevice::LogicToLogic( pAct
->GetPoint(), aMapVDev
->GetMapMode(), GetPrefMapMode() ),
1357 aMapVDev
->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1358 aClipStack
, pUseHairline
);
1362 case( MetaActionType::POINT
):
1364 MetaPointAction
* pAct
= static_cast<MetaPointAction
*>(pAction
);
1365 ImplActionBounds( aBound
,
1366 tools::Rectangle( OutputDevice::LogicToLogic( pAct
->GetPoint(), aMapVDev
->GetMapMode(), GetPrefMapMode() ),
1367 aMapVDev
->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1368 aClipStack
, pUseHairline
);
1372 case( MetaActionType::LINE
):
1374 MetaLineAction
* pAct
= static_cast<MetaLineAction
*>(pAction
);
1375 Point
aP1( pAct
->GetStartPoint() ), aP2( pAct
->GetEndPoint() );
1376 tools::Rectangle
aRect( aP1
, aP2
);
1381 const LineInfo
& rLineInfo
= pAct
->GetLineInfo();
1383 if(0 != rLineInfo
.GetWidth())
1384 pUseHairline
= nullptr;
1387 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1391 case( MetaActionType::RECT
):
1393 MetaRectAction
* pAct
= static_cast<MetaRectAction
*>(pAction
);
1394 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1398 case( MetaActionType::ROUNDRECT
):
1400 MetaRoundRectAction
* pAct
= static_cast<MetaRoundRectAction
*>(pAction
);
1401 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1405 case( MetaActionType::ELLIPSE
):
1407 MetaEllipseAction
* pAct
= static_cast<MetaEllipseAction
*>(pAction
);
1408 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1412 case( MetaActionType::ARC
):
1414 MetaArcAction
* pAct
= static_cast<MetaArcAction
*>(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
, pUseHairline
);
1421 case( MetaActionType::PIE
):
1423 MetaPieAction
* pAct
= static_cast<MetaPieAction
*>(pAction
);
1424 // FIXME: this is imprecise
1425 // e.g. for small arcs the whole rectangle is WAY too large
1426 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1430 case( MetaActionType::CHORD
):
1432 MetaChordAction
* pAct
= static_cast<MetaChordAction
*>(pAction
);
1433 // FIXME: this is imprecise
1434 // e.g. for small arcs the whole rectangle is WAY too large
1435 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1439 case( MetaActionType::POLYLINE
):
1441 MetaPolyLineAction
* pAct
= static_cast<MetaPolyLineAction
*>(pAction
);
1442 tools::Rectangle
aRect( pAct
->GetPolygon().GetBoundRect() );
1446 const LineInfo
& rLineInfo
= pAct
->GetLineInfo();
1448 if(0 != rLineInfo
.GetWidth())
1449 pUseHairline
= nullptr;
1452 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1456 case( MetaActionType::POLYGON
):
1458 MetaPolygonAction
* pAct
= static_cast<MetaPolygonAction
*>(pAction
);
1459 tools::Rectangle
aRect( pAct
->GetPolygon().GetBoundRect() );
1460 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1464 case( MetaActionType::POLYPOLYGON
):
1466 MetaPolyPolygonAction
* pAct
= static_cast<MetaPolyPolygonAction
*>(pAction
);
1467 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1468 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1472 case( MetaActionType::TEXT
):
1474 MetaTextAction
* pAct
= static_cast<MetaTextAction
*>(pAction
);
1475 tools::Rectangle aRect
;
1476 // hdu said base = index
1477 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
, nullptr );
1484 case( MetaActionType::TEXTARRAY
):
1486 MetaTextArrayAction
* pAct
= static_cast<MetaTextArrayAction
*>(pAction
);
1487 tools::Rectangle aRect
;
1488 // hdu said base = index
1489 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen(),
1490 0, pAct
->GetDXArray() );
1491 Point
aPt( pAct
->GetPoint() );
1492 aRect
.Move( aPt
.X(), aPt
.Y() );
1493 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1497 case( MetaActionType::STRETCHTEXT
):
1499 MetaStretchTextAction
* pAct
= static_cast<MetaStretchTextAction
*>(pAction
);
1500 tools::Rectangle aRect
;
1501 // hdu said base = index
1502 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen(),
1504 Point
aPt( pAct
->GetPoint() );
1505 aRect
.Move( aPt
.X(), aPt
.Y() );
1506 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1510 case( MetaActionType::TEXTLINE
):
1512 MetaTextLineAction
* pAct
= static_cast<MetaTextLineAction
*>(pAction
);
1513 // measure a test string to get ascend and descent right
1514 static const sal_Unicode pStr
[] = { 0xc4, 0x67, 0 };
1515 OUString
aStr( pStr
);
1517 tools::Rectangle aRect
;
1518 aMapVDev
->GetTextBoundRect( aRect
, aStr
, 0, 0, aStr
.getLength() );
1519 Point
aPt( pAct
->GetStartPoint() );
1520 aRect
.Move( aPt
.X(), aPt
.Y() );
1521 aRect
.Right() = aRect
.Left() + pAct
->GetWidth();
1522 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1526 case( MetaActionType::BMPSCALE
):
1528 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1529 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1530 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1534 case( MetaActionType::BMPSCALEPART
):
1536 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1537 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1538 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1542 case( MetaActionType::BMPEXSCALE
):
1544 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1545 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1546 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1550 case( MetaActionType::BMPEXSCALEPART
):
1552 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1553 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1554 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1558 case( MetaActionType::GRADIENT
):
1560 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1561 tools::Rectangle
aRect( pAct
->GetRect() );
1562 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1566 case( MetaActionType::GRADIENTEX
):
1568 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1569 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1570 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1574 case( MetaActionType::COMMENT
):
1580 case( MetaActionType::HATCH
):
1582 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
1583 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1584 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1588 case( MetaActionType::Transparent
):
1590 MetaTransparentAction
* pAct
= static_cast<MetaTransparentAction
*>(pAction
);
1591 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1592 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1596 case( MetaActionType::FLOATTRANSPARENT
):
1598 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
1599 // MetaFloatTransparentAction is defined limiting its content Metafile
1600 // to its geometry definition(Point, Size), so use these directly
1601 const tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1602 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1606 case( MetaActionType::EPS
):
1608 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
1609 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1610 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1614 case( MetaActionType::CLIPREGION
):
1616 MetaClipRegionAction
* pAct
= static_cast<MetaClipRegionAction
*>(pAction
);
1617 if( pAct
->IsClipping() )
1618 aClipStack
.back() = OutputDevice::LogicToLogic( pAct
->GetRegion().GetBoundRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() );
1620 aClipStack
.back() = tools::Rectangle();
1624 case( MetaActionType::ISECTRECTCLIPREGION
):
1626 MetaISectRectClipRegionAction
* pAct
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
1627 tools::Rectangle
aRect( OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ) );
1628 if( aClipStack
.back().IsEmpty() )
1629 aClipStack
.back() = aRect
;
1631 aClipStack
.back().Intersection( aRect
);
1635 case( MetaActionType::ISECTREGIONCLIPREGION
):
1637 MetaISectRegionClipRegionAction
* pAct
= static_cast<MetaISectRegionClipRegionAction
*>(pAction
);
1638 tools::Rectangle
aRect( OutputDevice::LogicToLogic( pAct
->GetRegion().GetBoundRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ) );
1639 if( aClipStack
.back().IsEmpty() )
1640 aClipStack
.back() = aRect
;
1642 aClipStack
.back().Intersection( aRect
);
1646 case( MetaActionType::BMP
):
1648 MetaBmpAction
* pAct
= static_cast<MetaBmpAction
*>(pAction
);
1649 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmap().GetSizePixel() ) );
1650 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1654 case( MetaActionType::BMPEX
):
1656 MetaBmpExAction
* pAct
= static_cast<MetaBmpExAction
*>(pAction
);
1657 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmapEx().GetSizePixel() ) );
1658 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1662 case( MetaActionType::MASK
):
1664 MetaMaskAction
* pAct
= static_cast<MetaMaskAction
*>(pAction
);
1665 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmap().GetSizePixel() ) );
1666 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1670 case( MetaActionType::MASKSCALE
):
1672 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1673 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1674 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1678 case( MetaActionType::MASKSCALEPART
):
1680 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1681 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1682 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1686 case( MetaActionType::WALLPAPER
):
1688 MetaWallpaperAction
* pAct
= static_cast<MetaWallpaperAction
*>(pAction
);
1689 tools::Rectangle
aRect( pAct
->GetRect() );
1690 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1694 case( MetaActionType::TEXTRECT
):
1696 MetaTextRectAction
* pAct
= static_cast<MetaTextRectAction
*>(pAction
);
1697 tools::Rectangle
aRect( pAct
->GetRect() );
1698 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1702 case( MetaActionType::MOVECLIPREGION
):
1704 MetaMoveClipRegionAction
* pAct
= static_cast<MetaMoveClipRegionAction
*>(pAction
);
1705 if( ! aClipStack
.back().IsEmpty() )
1707 Size
aDelta( pAct
->GetHorzMove(), pAct
->GetVertMove() );
1708 aDelta
= OutputDevice::LogicToLogic( aDelta
, aMapVDev
->GetMapMode(), GetPrefMapMode() );
1709 aClipStack
.back().Move( aDelta
.Width(), aDelta
.Width() );
1716 pAction
->Execute( aMapVDev
.get() );
1718 if( nActionType
== MetaActionType::PUSH
)
1720 MetaPushAction
* pAct
= static_cast<MetaPushAction
*>(pAction
);
1721 aPushFlagStack
.push_back( pAct
->GetFlags() );
1722 if( aPushFlagStack
.back() & PushFlags::CLIPREGION
)
1724 tools::Rectangle
aRect( aClipStack
.back() );
1725 aClipStack
.push_back( aRect
);
1728 else if( nActionType
== MetaActionType::POP
)
1731 if( ! aPushFlagStack
.empty() )
1733 if( aPushFlagStack
.back() & PushFlags::CLIPREGION
)
1735 if( aClipStack
.size() > 1 )
1736 aClipStack
.pop_back();
1738 aPushFlagStack
.pop_back();
1748 Color
GDIMetaFile::ImplColAdjustFnc( const Color
& rColor
, const void* pColParam
)
1750 return Color( rColor
.GetTransparency(),
1751 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapR
[ rColor
.GetRed() ],
1752 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapG
[ rColor
.GetGreen() ],
1753 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapB
[ rColor
.GetBlue() ] );
1757 BitmapEx
GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1759 const ImplBmpAdjustParam
* p
= static_cast<const ImplBmpAdjustParam
*>(pBmpParam
);
1760 BitmapEx
aRet( rBmpEx
);
1762 aRet
.Adjust( p
->nLuminancePercent
, p
->nContrastPercent
,
1763 p
->nChannelRPercent
, p
->nChannelGPercent
, p
->nChannelBPercent
,
1764 p
->fGamma
, p
->bInvert
);
1769 Color
GDIMetaFile::ImplColConvertFnc( const Color
& rColor
, const void* pColParam
)
1771 sal_uInt8 cLum
= rColor
.GetLuminance();
1773 if( MtfConversion::N1BitThreshold
== static_cast<const ImplColConvertParam
*>(pColParam
)->eConversion
)
1774 cLum
= ( cLum
< 128 ) ? 0 : 255;
1776 return Color( rColor
.GetTransparency(), cLum
, cLum
, cLum
);
1779 BitmapEx
GDIMetaFile::ImplBmpConvertFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1781 BitmapEx
aRet( rBmpEx
);
1783 aRet
.Convert( static_cast<const ImplBmpConvertParam
*>(pBmpParam
)->eConversion
);
1788 Color
GDIMetaFile::ImplColMonoFnc( const Color
&, const void* pColParam
)
1790 return static_cast<const ImplColMonoParam
*>(pColParam
)->aColor
;
1793 BitmapEx
GDIMetaFile::ImplBmpMonoFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1795 BitmapPalette
aPal( 3 );
1797 aPal
[ 0 ] = Color( COL_BLACK
);
1798 aPal
[ 1 ] = Color( COL_WHITE
);
1799 aPal
[ 2 ] = static_cast<const ImplBmpMonoParam
*>(pBmpParam
)->aColor
;
1801 Bitmap
aBmp( rBmpEx
.GetSizePixel(), 4, &aPal
);
1802 aBmp
.Erase( static_cast<const ImplBmpMonoParam
*>(pBmpParam
)->aColor
);
1804 if( rBmpEx
.IsAlpha() )
1805 return BitmapEx( aBmp
, rBmpEx
.GetAlpha() );
1806 else if( rBmpEx
.IsTransparent() )
1807 return BitmapEx( aBmp
, rBmpEx
.GetMask() );
1812 Color
GDIMetaFile::ImplColReplaceFnc( const Color
& rColor
, const void* pColParam
)
1814 const sal_uLong nR
= rColor
.GetRed(), nG
= rColor
.GetGreen(), nB
= rColor
.GetBlue();
1816 for( sal_uLong i
= 0; i
< static_cast<const ImplColReplaceParam
*>(pColParam
)->nCount
; i
++ )
1818 if( ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinR
[ i
] <= nR
) &&
1819 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxR
[ i
] >= nR
) &&
1820 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinG
[ i
] <= nG
) &&
1821 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxG
[ i
] >= nG
) &&
1822 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinB
[ i
] <= nB
) &&
1823 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxB
[ i
] >= nB
) )
1825 return static_cast<const ImplColReplaceParam
*>(pColParam
)->pDstCols
[ i
];
1832 BitmapEx
GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1834 const ImplBmpReplaceParam
* p
= static_cast<const ImplBmpReplaceParam
*>(pBmpParam
);
1835 BitmapEx
aRet( rBmpEx
);
1837 aRet
.Replace( p
->pSrcCols
, p
->pDstCols
, p
->nCount
, p
->pTols
);
1842 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol
, const void* pColParam
,
1843 BmpExchangeFnc pFncBmp
, const void* pBmpParam
)
1847 aMtf
.m_aPrefSize
= m_aPrefSize
;
1848 aMtf
.m_aPrefMapMode
= m_aPrefMapMode
;
1849 aMtf
.m_bUseCanvas
= m_bUseCanvas
;
1851 for( MetaAction
* pAction
= FirstAction(); pAction
; pAction
= NextAction() )
1853 const MetaActionType nType
= pAction
->GetType();
1857 case( MetaActionType::PIXEL
):
1859 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
1860 aMtf
.push_back( new MetaPixelAction( pAct
->GetPoint(), pFncCol( pAct
->GetColor(), pColParam
) ) );
1864 case( MetaActionType::LINECOLOR
):
1866 MetaLineColorAction
* pAct
= static_cast<MetaLineColorAction
*>(pAction
);
1868 if( !pAct
->IsSetting() )
1871 pAct
= new MetaLineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1873 aMtf
.push_back( pAct
);
1877 case( MetaActionType::FILLCOLOR
):
1879 MetaFillColorAction
* pAct
= static_cast<MetaFillColorAction
*>(pAction
);
1881 if( !pAct
->IsSetting() )
1884 pAct
= new MetaFillColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1886 aMtf
.push_back( pAct
);
1890 case( MetaActionType::TEXTCOLOR
):
1892 MetaTextColorAction
* pAct
= static_cast<MetaTextColorAction
*>(pAction
);
1893 aMtf
.push_back( new MetaTextColorAction( pFncCol( pAct
->GetColor(), pColParam
) ) );
1897 case( MetaActionType::TEXTFILLCOLOR
):
1899 MetaTextFillColorAction
* pAct
= static_cast<MetaTextFillColorAction
*>(pAction
);
1901 if( !pAct
->IsSetting() )
1904 pAct
= new MetaTextFillColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1906 aMtf
.push_back( pAct
);
1910 case( MetaActionType::TEXTLINECOLOR
):
1912 MetaTextLineColorAction
* pAct
= static_cast<MetaTextLineColorAction
*>(pAction
);
1914 if( !pAct
->IsSetting() )
1917 pAct
= new MetaTextLineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1919 aMtf
.push_back( pAct
);
1923 case( MetaActionType::OVERLINECOLOR
):
1925 MetaOverlineColorAction
* pAct
= static_cast<MetaOverlineColorAction
*>(pAction
);
1927 if( !pAct
->IsSetting() )
1930 pAct
= new MetaOverlineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1932 aMtf
.push_back( pAct
);
1936 case( MetaActionType::FONT
):
1938 MetaFontAction
* pAct
= static_cast<MetaFontAction
*>(pAction
);
1939 vcl::Font
aFont( pAct
->GetFont() );
1941 aFont
.SetColor( pFncCol( aFont
.GetColor(), pColParam
) );
1942 aFont
.SetFillColor( pFncCol( aFont
.GetFillColor(), pColParam
) );
1943 aMtf
.push_back( new MetaFontAction( aFont
) );
1947 case( MetaActionType::WALLPAPER
):
1949 MetaWallpaperAction
* pAct
= static_cast<MetaWallpaperAction
*>(pAction
);
1950 Wallpaper
aWall( pAct
->GetWallpaper() );
1951 const tools::Rectangle
& rRect
= pAct
->GetRect();
1953 aWall
.SetColor( pFncCol( aWall
.GetColor(), pColParam
) );
1955 if( aWall
.IsBitmap() )
1956 aWall
.SetBitmap( pFncBmp( aWall
.GetBitmap(), pBmpParam
) );
1958 if( aWall
.IsGradient() )
1960 Gradient
aGradient( aWall
.GetGradient() );
1962 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
1963 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
1964 aWall
.SetGradient( aGradient
);
1967 aMtf
.push_back( new MetaWallpaperAction( rRect
, aWall
) );
1971 case( MetaActionType::BMP
):
1972 case( MetaActionType::BMPEX
):
1973 case( MetaActionType::MASK
):
1975 OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
1979 case( MetaActionType::BMPSCALE
):
1981 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1982 aMtf
.push_back( new MetaBmpScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
1983 pFncBmp( pAct
->GetBitmap(), pBmpParam
).GetBitmap() ) );
1987 case( MetaActionType::BMPSCALEPART
):
1989 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1990 aMtf
.push_back( new MetaBmpScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
1991 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
1992 pFncBmp( pAct
->GetBitmap(), pBmpParam
).GetBitmap() )
1997 case( MetaActionType::BMPEXSCALE
):
1999 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
2000 aMtf
.push_back( new MetaBmpExScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
2001 pFncBmp( pAct
->GetBitmapEx(), pBmpParam
) )
2006 case( MetaActionType::BMPEXSCALEPART
):
2008 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
2009 aMtf
.push_back( new MetaBmpExScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
2010 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
2011 pFncBmp( pAct
->GetBitmapEx(), pBmpParam
) )
2016 case( MetaActionType::MASKSCALE
):
2018 MetaMaskScaleAction
* pAct
= static_cast<MetaMaskScaleAction
*>(pAction
);
2019 aMtf
.push_back( new MetaMaskScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
2021 pFncCol( pAct
->GetColor(), pColParam
) )
2026 case( MetaActionType::MASKSCALEPART
):
2028 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
2029 aMtf
.push_back( new MetaMaskScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
2030 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
2032 pFncCol( pAct
->GetColor(), pColParam
) )
2037 case( MetaActionType::GRADIENT
):
2039 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
2040 Gradient
aGradient( pAct
->GetGradient() );
2042 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
2043 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
2044 aMtf
.push_back( new MetaGradientAction( pAct
->GetRect(), aGradient
) );
2048 case( MetaActionType::GRADIENTEX
):
2050 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
2051 Gradient
aGradient( pAct
->GetGradient() );
2053 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
2054 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
2055 aMtf
.push_back( new MetaGradientExAction( pAct
->GetPolyPolygon(), aGradient
) );
2059 case( MetaActionType::HATCH
):
2061 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
2062 Hatch
aHatch( pAct
->GetHatch() );
2064 aHatch
.SetColor( pFncCol( aHatch
.GetColor(), pColParam
) );
2065 aMtf
.push_back( new MetaHatchAction( pAct
->GetPolyPolygon(), aHatch
) );
2069 case( MetaActionType::FLOATTRANSPARENT
):
2071 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
2072 GDIMetaFile
aTransMtf( pAct
->GetGDIMetaFile() );
2074 aTransMtf
.ImplExchangeColors( pFncCol
, pColParam
, pFncBmp
, pBmpParam
);
2075 aMtf
.push_back( new MetaFloatTransparentAction( aTransMtf
,
2076 pAct
->GetPoint(), pAct
->GetSize(),
2077 pAct
->GetGradient() )
2082 case( MetaActionType::EPS
):
2084 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
2085 GDIMetaFile
aSubst( pAct
->GetSubstitute() );
2087 aSubst
.ImplExchangeColors( pFncCol
, pColParam
, pFncBmp
, pBmpParam
);
2088 aMtf
.push_back( new MetaEPSAction( pAct
->GetPoint(), pAct
->GetSize(),
2089 pAct
->GetLink(), aSubst
)
2096 pAction
->Duplicate();
2097 aMtf
.push_back( pAction
);
2106 void GDIMetaFile::Adjust( short nLuminancePercent
, short nContrastPercent
,
2107 short nChannelRPercent
, short nChannelGPercent
,
2108 short nChannelBPercent
, double fGamma
, bool bInvert
, bool msoBrightness
)
2110 // nothing to do? => return quickly
2111 if( nLuminancePercent
|| nContrastPercent
||
2112 nChannelRPercent
|| nChannelGPercent
|| nChannelBPercent
||
2113 ( fGamma
!= 1.0 ) || bInvert
)
2115 double fM
, fROff
, fGOff
, fBOff
, fOff
;
2116 ImplColAdjustParam aColParam
;
2117 ImplBmpAdjustParam aBmpParam
;
2119 aColParam
.pMapR
= new sal_uInt8
[ 256 ];
2120 aColParam
.pMapG
= new sal_uInt8
[ 256 ];
2121 aColParam
.pMapB
= new sal_uInt8
[ 256 ];
2124 if( nContrastPercent
>= 0 )
2125 fM
= 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent
, 0, 100 ) );
2127 fM
= ( 128.0 + 1.27 * MinMax( nContrastPercent
, -100, 0 ) ) / 128.0;
2130 // total offset = luminance offset + contrast offset
2131 fOff
= MinMax( nLuminancePercent
, -100, 100 ) * 2.55 + 128.0 - fM
* 128.0;
2133 fOff
= MinMax( nLuminancePercent
, -100, 100 ) * 2.55;
2135 // channel offset = channel offset + total offset
2136 fROff
= nChannelRPercent
* 2.55 + fOff
;
2137 fGOff
= nChannelGPercent
* 2.55 + fOff
;
2138 fBOff
= nChannelBPercent
* 2.55 + fOff
;
2140 // calculate gamma value
2141 fGamma
= ( fGamma
<= 0.0 || fGamma
> 10.0 ) ? 1.0 : ( 1.0 / fGamma
);
2142 const bool bGamma
= ( fGamma
!= 1.0 );
2144 // create mapping table
2145 for( long nX
= 0; nX
< 256; nX
++ )
2149 aColParam
.pMapR
[ nX
] = (sal_uInt8
) MinMax( FRound( nX
* fM
+ fROff
), 0, 255 );
2150 aColParam
.pMapG
[ nX
] = (sal_uInt8
) MinMax( FRound( nX
* fM
+ fGOff
), 0, 255 );
2151 aColParam
.pMapB
[ nX
] = (sal_uInt8
) MinMax( FRound( nX
* fM
+ fBOff
), 0, 255 );
2155 aColParam
.pMapR
[ nX
] = (sal_uInt8
) MinMax( FRound( (nX
+fROff
/2-128) * fM
+ 128 + fROff
/2 ), 0, 255 );
2156 aColParam
.pMapG
[ nX
] = (sal_uInt8
) MinMax( FRound( (nX
+fGOff
/2-128) * fM
+ 128 + fGOff
/2 ), 0, 255 );
2157 aColParam
.pMapB
[ nX
] = (sal_uInt8
) MinMax( FRound( (nX
+fBOff
/2-128) * fM
+ 128 + fBOff
/2 ), 0, 255 );
2161 aColParam
.pMapR
[ nX
] = GAMMA( aColParam
.pMapR
[ nX
], fGamma
);
2162 aColParam
.pMapG
[ nX
] = GAMMA( aColParam
.pMapG
[ nX
], fGamma
);
2163 aColParam
.pMapB
[ nX
] = GAMMA( aColParam
.pMapB
[ nX
], fGamma
);
2168 aColParam
.pMapR
[ nX
] = ~aColParam
.pMapR
[ nX
];
2169 aColParam
.pMapG
[ nX
] = ~aColParam
.pMapG
[ nX
];
2170 aColParam
.pMapB
[ nX
] = ~aColParam
.pMapB
[ nX
];
2174 aBmpParam
.nLuminancePercent
= nLuminancePercent
;
2175 aBmpParam
.nContrastPercent
= nContrastPercent
;
2176 aBmpParam
.nChannelRPercent
= nChannelRPercent
;
2177 aBmpParam
.nChannelGPercent
= nChannelGPercent
;
2178 aBmpParam
.nChannelBPercent
= nChannelBPercent
;
2179 aBmpParam
.fGamma
= fGamma
;
2180 aBmpParam
.bInvert
= bInvert
;
2182 // do color adjustment
2183 ImplExchangeColors( ImplColAdjustFnc
, &aColParam
, ImplBmpAdjustFnc
, &aBmpParam
);
2185 delete[] aColParam
.pMapR
;
2186 delete[] aColParam
.pMapG
;
2187 delete[] aColParam
.pMapB
;
2191 void GDIMetaFile::Convert( MtfConversion eConversion
)
2193 ImplColConvertParam aColParam
;
2194 ImplBmpConvertParam aBmpParam
;
2196 aColParam
.eConversion
= eConversion
;
2197 aBmpParam
.eConversion
= ( MtfConversion::N1BitThreshold
== eConversion
) ? BmpConversion::N1BitThreshold
: BmpConversion::N8BitGreys
;
2199 ImplExchangeColors( ImplColConvertFnc
, &aColParam
, ImplBmpConvertFnc
, &aBmpParam
);
2202 void GDIMetaFile::ReplaceColors( const Color
* pSearchColors
, const Color
* pReplaceColors
, sal_uLong nColorCount
)
2204 ImplColReplaceParam aColParam
;
2205 ImplBmpReplaceParam aBmpParam
;
2207 aColParam
.pMinR
= new sal_uLong
[ nColorCount
];
2208 aColParam
.pMaxR
= new sal_uLong
[ nColorCount
];
2209 aColParam
.pMinG
= new sal_uLong
[ nColorCount
];
2210 aColParam
.pMaxG
= new sal_uLong
[ nColorCount
];
2211 aColParam
.pMinB
= new sal_uLong
[ nColorCount
];
2212 aColParam
.pMaxB
= new sal_uLong
[ nColorCount
];
2214 for( sal_uLong i
= 0; i
< nColorCount
; i
++ )
2218 nVal
= pSearchColors
[ i
].GetRed();
2219 aColParam
.pMinR
[ i
] = (sal_uLong
) std::max( nVal
, 0L );
2220 aColParam
.pMaxR
[ i
] = (sal_uLong
) std::min( nVal
, 255L );
2222 nVal
= pSearchColors
[ i
].GetGreen();
2223 aColParam
.pMinG
[ i
] = (sal_uLong
) std::max( nVal
, 0L );
2224 aColParam
.pMaxG
[ i
] = (sal_uLong
) std::min( nVal
, 255L );
2226 nVal
= pSearchColors
[ i
].GetBlue();
2227 aColParam
.pMinB
[ i
] = (sal_uLong
) std::max( nVal
, 0L );
2228 aColParam
.pMaxB
[ i
] = (sal_uLong
) std::min( nVal
, 255L );
2231 aColParam
.pDstCols
= pReplaceColors
;
2232 aColParam
.nCount
= nColorCount
;
2234 aBmpParam
.pSrcCols
= pSearchColors
;
2235 aBmpParam
.pDstCols
= pReplaceColors
;
2236 aBmpParam
.nCount
= nColorCount
;
2237 aBmpParam
.pTols
= nullptr;
2239 ImplExchangeColors( ImplColReplaceFnc
, &aColParam
, ImplBmpReplaceFnc
, &aBmpParam
);
2241 delete[] aColParam
.pMinR
;
2242 delete[] aColParam
.pMaxR
;
2243 delete[] aColParam
.pMinG
;
2244 delete[] aColParam
.pMaxG
;
2245 delete[] aColParam
.pMinB
;
2246 delete[] aColParam
.pMaxB
;
2249 GDIMetaFile
GDIMetaFile::GetMonochromeMtf( const Color
& rColor
) const
2251 GDIMetaFile
aRet( *this );
2253 ImplColMonoParam aColParam
;
2254 ImplBmpMonoParam aBmpParam
;
2256 aColParam
.aColor
= rColor
;
2257 aBmpParam
.aColor
= rColor
;
2259 aRet
.ImplExchangeColors( ImplColMonoFnc
, &aColParam
, ImplBmpMonoFnc
, &aBmpParam
);
2264 BitmapChecksum
GDIMetaFile::GetChecksum() const
2267 SvMemoryStream
aMemStm( 65535, 65535 );
2268 ImplMetaWriteData aWriteData
;
2271 BitmapChecksumOctetArray aBCOA
;
2272 BitmapChecksum nCrc
= 0;
2274 aWriteData
.meActualCharSet
= aMemStm
.GetStreamCharSet();
2275 for( size_t i
= 0, nObjCount
= GetActionSize(); i
< nObjCount
; i
++ )
2277 MetaAction
* pAction
= GetAction( i
);
2279 switch( pAction
->GetType() )
2281 case( MetaActionType::BMP
):
2283 MetaBmpAction
* pAct
= static_cast<MetaBmpAction
*>(pAction
);
2285 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2286 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2288 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2289 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2291 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2292 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2294 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2295 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2299 case( MetaActionType::BMPSCALE
):
2301 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
2303 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2304 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2306 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2307 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2309 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2310 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2312 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2313 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2315 UInt32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2316 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2318 UInt32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2319 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2323 case( MetaActionType::BMPSCALEPART
):
2325 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
2327 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2328 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2330 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2331 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2333 UInt32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2334 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2336 UInt32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2337 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2339 UInt32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2340 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2342 UInt32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2343 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2345 UInt32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2346 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2348 UInt32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2349 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2351 UInt32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2352 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2354 UInt32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2355 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2359 case( MetaActionType::BMPEX
):
2361 MetaBmpExAction
* pAct
= static_cast<MetaBmpExAction
*>(pAction
);
2363 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2364 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2366 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2367 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2369 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2370 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2372 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2373 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2377 case( MetaActionType::BMPEXSCALE
):
2379 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
2381 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2382 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2384 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2385 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2387 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2388 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2390 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2391 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2393 UInt32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2394 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2396 UInt32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2397 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2401 case( MetaActionType::BMPEXSCALEPART
):
2403 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
2405 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2406 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2408 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2409 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2411 UInt32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2412 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2414 UInt32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2415 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2417 UInt32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2418 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2420 UInt32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2421 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2423 UInt32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2424 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2426 UInt32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2427 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2429 UInt32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2430 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2432 UInt32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2433 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2437 case( MetaActionType::MASK
):
2439 MetaMaskAction
* pAct
= static_cast<MetaMaskAction
*>(pAction
);
2441 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2442 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2444 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2445 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2447 UInt32ToSVBT32( pAct
->GetColor().GetColor(), aBT32
);
2448 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2450 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2451 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2453 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2454 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2458 case( MetaActionType::MASKSCALE
):
2460 MetaMaskScaleAction
* pAct
= static_cast<MetaMaskScaleAction
*>(pAction
);
2462 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2463 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2465 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2466 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2468 UInt32ToSVBT32( pAct
->GetColor().GetColor(), aBT32
);
2469 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2471 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2472 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2474 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2475 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2477 UInt32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2478 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2480 UInt32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2481 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2485 case( MetaActionType::MASKSCALEPART
):
2487 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
2489 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2490 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2492 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2493 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2495 UInt32ToSVBT32( pAct
->GetColor().GetColor(), aBT32
);
2496 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2498 UInt32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2499 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2501 UInt32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2502 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2504 UInt32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2505 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2507 UInt32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2508 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2510 UInt32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2511 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2513 UInt32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2514 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2516 UInt32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2517 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2519 UInt32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2520 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2524 case MetaActionType::EPS
:
2526 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
2527 nCrc
= vcl_get_checksum( nCrc
, pAct
->GetLink().GetData(), pAct
->GetLink().GetDataSize() );
2531 case MetaActionType::CLIPREGION
:
2533 MetaClipRegionAction
& rAct
= static_cast<MetaClipRegionAction
&>(*pAction
);
2534 const vcl::Region
& rRegion
= rAct
.GetRegion();
2536 if(rRegion
.HasPolyPolygonOrB2DPolyPolygon())
2538 // It has shown that this is a possible bottleneck for checksum calculation.
2539 // In worst case a very expensive RegionHandle representation gets created.
2540 // In this case it's cheaper to use the PolyPolygon
2541 const basegfx::B2DPolyPolygon
aPolyPolygon(rRegion
.GetAsB2DPolyPolygon());
2542 const sal_uInt32
nPolyCount(aPolyPolygon
.count());
2545 for(sal_uInt32
a(0); a
< nPolyCount
; a
++)
2547 const basegfx::B2DPolygon
aPolygon(aPolyPolygon
.getB2DPolygon(a
));
2548 const sal_uInt32
nPointCount(aPolygon
.count());
2549 const bool bControl(aPolygon
.areControlPointsUsed());
2551 for(sal_uInt32
b(0); b
< nPointCount
; b
++)
2553 const basegfx::B2DPoint
aPoint(aPolygon
.getB2DPoint(b
));
2555 DoubleToSVBT64(aPoint
.getX(), aSVBT64
);
2556 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2557 DoubleToSVBT64(aPoint
.getY(), aSVBT64
);
2558 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2562 if(aPolygon
.isPrevControlPointUsed(b
))
2564 const basegfx::B2DPoint
aCtrl(aPolygon
.getPrevControlPoint(b
));
2566 DoubleToSVBT64(aCtrl
.getX(), aSVBT64
);
2567 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2568 DoubleToSVBT64(aCtrl
.getY(), aSVBT64
);
2569 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2572 if(aPolygon
.isNextControlPointUsed(b
))
2574 const basegfx::B2DPoint
aCtrl(aPolygon
.getNextControlPoint(b
));
2576 DoubleToSVBT64(aCtrl
.getX(), aSVBT64
);
2577 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2578 DoubleToSVBT64(aCtrl
.getY(), aSVBT64
);
2579 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2585 sal_uInt8 tmp
= (sal_uInt8
)rAct
.IsClipping();
2586 nCrc
= vcl_get_checksum(nCrc
, &tmp
, 1);
2590 pAction
->Write( aMemStm
, &aWriteData
);
2591 nCrc
= vcl_get_checksum( nCrc
, aMemStm
.GetData(), aMemStm
.Tell() );
2599 pAction
->Write( aMemStm
, &aWriteData
);
2600 nCrc
= vcl_get_checksum( nCrc
, aMemStm
.GetData(), aMemStm
.Tell() );
2610 sal_uLong
GDIMetaFile::GetSizeBytes() const
2612 sal_uLong nSizeBytes
= 0;
2614 for( size_t i
= 0, nObjCount
= GetActionSize(); i
< nObjCount
; ++i
)
2616 MetaAction
* pAction
= GetAction( i
);
2618 // default action size is set to 32 (=> not the exact value)
2621 // add sizes for large action content
2622 switch( pAction
->GetType() )
2624 case( MetaActionType::BMP
): nSizeBytes
+= static_cast<MetaBmpAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2625 case( MetaActionType::BMPSCALE
): nSizeBytes
+= static_cast<MetaBmpScaleAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2626 case( MetaActionType::BMPSCALEPART
): nSizeBytes
+= static_cast<MetaBmpScalePartAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2628 case( MetaActionType::BMPEX
): nSizeBytes
+= static_cast<MetaBmpExAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2629 case( MetaActionType::BMPEXSCALE
): nSizeBytes
+= static_cast<MetaBmpExScaleAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2630 case( MetaActionType::BMPEXSCALEPART
): nSizeBytes
+= static_cast<MetaBmpExScalePartAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2632 case( MetaActionType::MASK
): nSizeBytes
+= static_cast<MetaMaskAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2633 case( MetaActionType::MASKSCALE
): nSizeBytes
+= static_cast<MetaMaskScaleAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2634 case( MetaActionType::MASKSCALEPART
): nSizeBytes
+= static_cast<MetaMaskScalePartAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2636 case( MetaActionType::POLYLINE
): nSizeBytes
+= static_cast<MetaPolyLineAction
*>( pAction
)->GetPolygon().GetSize() * sizeof( Point
); break;
2637 case( MetaActionType::POLYGON
): nSizeBytes
+= static_cast<MetaPolygonAction
*>( pAction
)->GetPolygon().GetSize() * sizeof( Point
); break;
2638 case( MetaActionType::POLYPOLYGON
):
2640 const tools::PolyPolygon
& rPolyPoly
= static_cast<MetaPolyPolygonAction
*>( pAction
)->GetPolyPolygon();
2642 for( sal_uInt16 n
= 0; n
< rPolyPoly
.Count(); ++n
)
2643 nSizeBytes
+= ( rPolyPoly
[ n
].GetSize() * sizeof( Point
) );
2647 case( MetaActionType::TEXT
): nSizeBytes
+= static_cast<MetaTextAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2648 case( MetaActionType::STRETCHTEXT
): nSizeBytes
+= static_cast<MetaStretchTextAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2649 case( MetaActionType::TEXTRECT
): nSizeBytes
+= static_cast<MetaTextRectAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2650 case( MetaActionType::TEXTARRAY
):
2652 MetaTextArrayAction
* pTextArrayAction
= static_cast<MetaTextArrayAction
*>(pAction
);
2654 nSizeBytes
+= ( pTextArrayAction
->GetText().getLength() * sizeof( sal_Unicode
) );
2656 if( pTextArrayAction
->GetDXArray() )
2657 nSizeBytes
+= ( pTextArrayAction
->GetLen() << 2 );
2667 SvStream
& ReadGDIMetaFile( SvStream
& rIStm
, GDIMetaFile
& rGDIMetaFile
)
2669 if (rIStm
.GetError())
2671 SAL_WARN("vcl.gdi", "Stream error: " << rIStm
.GetError());
2675 sal_uLong nStmPos
= rIStm
.Tell();
2676 SvStreamEndian nOldFormat
= rIStm
.GetEndian();
2678 rIStm
.SetEndian( SvStreamEndian::LITTLE
);
2685 rIStm
.ReadBytes( aId
, 6 );
2687 if ( !strcmp( aId
, "VCLMTF" ) )
2690 sal_uInt32 nStmCompressMode
= 0;
2691 sal_uInt32 nCount
= 0;
2692 std::unique_ptr
<VersionCompat
> pCompat(new VersionCompat( rIStm
, StreamMode::READ
));
2694 rIStm
.ReadUInt32( nStmCompressMode
);
2695 ReadMapMode( rIStm
, rGDIMetaFile
.m_aPrefMapMode
);
2696 ReadPair( rIStm
, rGDIMetaFile
.m_aPrefSize
);
2697 rIStm
.ReadUInt32( nCount
);
2699 pCompat
.reset(); // destructor writes stuff into the header
2701 ImplMetaReadData aReadData
;
2702 aReadData
.meActualCharSet
= rIStm
.GetStreamCharSet();
2704 for( sal_uInt32 nAction
= 0UL; ( nAction
< nCount
) && !rIStm
.IsEof(); nAction
++ )
2706 MetaAction
* pAction
= MetaAction::ReadMetaAction( rIStm
, &aReadData
);
2709 if (pAction
->GetType() == MetaActionType::COMMENT
)
2711 MetaCommentAction
* pCommentAct
= static_cast<MetaCommentAction
*>(pAction
);
2712 if ( pCommentAct
->GetComment() == "EMF_PLUS" )
2713 rGDIMetaFile
.UseCanvas( true );
2715 rGDIMetaFile
.AddAction( pAction
);
2721 // to avoid possible compiler optimizations => new/delete
2722 rIStm
.Seek( nStmPos
);
2723 delete( new SVMConverter( rIStm
, rGDIMetaFile
, CONVERT_FROM_SVM1
) );
2728 SAL_WARN("vcl", "GDIMetaFile exception during load");
2729 rIStm
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
2733 if( rIStm
.GetError() )
2735 rGDIMetaFile
.Clear();
2736 rIStm
.Seek( nStmPos
);
2739 rIStm
.SetEndian( nOldFormat
);
2743 SvStream
& WriteGDIMetaFile( SvStream
& rOStm
, const GDIMetaFile
& rGDIMetaFile
)
2745 if( !rOStm
.GetError() )
2747 static const char* pEnableSVM1
= getenv( "SAL_ENABLE_SVM1" );
2748 static const bool bNoSVM1
= (nullptr == pEnableSVM1
) || ( '0' == *pEnableSVM1
);
2750 if( bNoSVM1
|| rOStm
.GetVersion() >= SOFFICE_FILEFORMAT_50
)
2752 const_cast< GDIMetaFile
& >( rGDIMetaFile
).Write( rOStm
);
2756 delete( new SVMConverter( rOStm
, const_cast< GDIMetaFile
& >( rGDIMetaFile
), CONVERT_TO_SVM1
) );
2760 if( !bNoSVM1
&& rOStm
.GetVersion() < SOFFICE_FILEFORMAT_50
)
2762 SAL_WARN( "vcl", "GDIMetaFile would normally be written in old SVM1 format by this call. "
2763 "The current implementation always writes in VCLMTF format. "
2764 "Please set environment variable SAL_ENABLE_SVM1 to '1' to reenable old behavior" );
2772 SvStream
& GDIMetaFile::Read( SvStream
& rIStm
)
2775 ReadGDIMetaFile( rIStm
, *this );
2780 SvStream
& GDIMetaFile::Write( SvStream
& rOStm
)
2782 VersionCompat
* pCompat
;
2783 const SvStreamCompressFlags nStmCompressMode
= rOStm
.GetCompressMode();
2784 SvStreamEndian nOldFormat
= rOStm
.GetEndian();
2786 rOStm
.SetEndian( SvStreamEndian::LITTLE
);
2787 rOStm
.WriteBytes( "VCLMTF", 6 );
2789 pCompat
= new VersionCompat( rOStm
, StreamMode::WRITE
, 1 );
2791 rOStm
.WriteUInt32( static_cast<sal_uInt32
>(nStmCompressMode
) );
2792 WriteMapMode( rOStm
, m_aPrefMapMode
);
2793 WritePair( rOStm
, m_aPrefSize
);
2794 rOStm
.WriteUInt32( GetActionSize() );
2798 ImplMetaWriteData aWriteData
;
2800 aWriteData
.meActualCharSet
= rOStm
.GetStreamCharSet();
2802 MetaAction
* pAct
= FirstAction();
2805 pAct
->Write( rOStm
, &aWriteData
);
2806 pAct
= NextAction();
2809 rOStm
.SetEndian( nOldFormat
);
2814 bool GDIMetaFile::CreateThumbnail(BitmapEx
& rBitmapEx
, BmpConversion eColorConversion
, BmpScaleFlag nScaleFlag
) const
2816 // initialization seems to be complicated but is used to avoid rounding errors
2817 ScopedVclPtrInstance
< VirtualDevice
> aVDev
;
2818 const Point aNullPt
;
2819 const Point
aTLPix( aVDev
->LogicToPixel( aNullPt
, GetPrefMapMode() ) );
2820 const Point
aBRPix( aVDev
->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2821 Size
aDrawSize( aVDev
->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2822 Size
aSizePix( labs( aBRPix
.X() - aTLPix
.X() ) + 1, labs( aBRPix
.Y() - aTLPix
.Y() ) + 1 );
2823 sal_uInt32 nMaximumExtent
= 256;
2825 if (!rBitmapEx
.IsEmpty())
2826 rBitmapEx
.SetEmpty();
2828 // determine size that has the same aspect ratio as image size and
2829 // fits into the rectangle determined by nMaximumExtent
2830 if ( aSizePix
.Width() && aSizePix
.Height()
2831 && ( sal::static_int_cast
< unsigned long >(aSizePix
.Width()) >
2833 sal::static_int_cast
< unsigned long >(aSizePix
.Height()) >
2836 const Size
aOldSizePix( aSizePix
);
2837 double fWH
= static_cast< double >( aSizePix
.Width() ) / aSizePix
.Height();
2841 aSizePix
.Width() = FRound( nMaximumExtent
* fWH
);
2842 aSizePix
.Height() = nMaximumExtent
;
2846 aSizePix
.Width() = nMaximumExtent
;
2847 aSizePix
.Height() = FRound( nMaximumExtent
/ fWH
);
2850 aDrawSize
.Width() = FRound( ( static_cast< double >( aDrawSize
.Width() ) * aSizePix
.Width() ) / aOldSizePix
.Width() );
2851 aDrawSize
.Height() = FRound( ( static_cast< double >( aDrawSize
.Height() ) * aSizePix
.Height() ) / aOldSizePix
.Height() );
2854 // draw image(s) into VDev and get resulting image
2855 // do it 4x larger to be able to scale it down & get beautiful antialias
2856 Size
aAntialiasSize(aSizePix
.Width() * 4, aSizePix
.Height() * 4);
2857 if (aVDev
->SetOutputSizePixel(aAntialiasSize
))
2859 // antialias: provide 4x larger size, and then scale down the result
2860 Size
aAntialias(aDrawSize
.Width() * 4, aDrawSize
.Height() * 4);
2862 // draw metafile into VDev
2864 const_cast<GDIMetaFile
*>(this)->WindStart();
2865 const_cast<GDIMetaFile
*>(this)->Play(aVDev
.get(), aBackPosPix
, aAntialias
);
2868 Bitmap
aBitmap( aVDev
->GetBitmap( aNullPt
, aVDev
->GetOutputSizePixel() ) );
2870 // scale down the image to the desired size - use the input scaler for the scaling operation
2871 aBitmap
.Scale(aDrawSize
, nScaleFlag
);
2873 // convert to desired bitmap color format
2874 aBitmap
.Convert(eColorConversion
);
2876 rBitmapEx
= BitmapEx(aBitmap
);
2879 return !rBitmapEx
.IsEmpty();
2882 void GDIMetaFile::UseCanvas( bool _bUseCanvas
)
2884 m_bUseCanvas
= _bUseCanvas
;
2887 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */