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 <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
;
52 #define GAMMA( _def_cVal, _def_InvGamma ) (static_cast<sal_uInt8>(MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0,255)))
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
;
111 GDIMetaFile::GDIMetaFile() :
112 m_nCurrentActionElement( 0 ),
113 m_aPrefSize ( 1, 1 ),
116 m_pOutDev ( nullptr ),
119 m_bUseCanvas ( false )
123 GDIMetaFile::GDIMetaFile( const GDIMetaFile
& rMtf
) :
124 m_nCurrentActionElement( rMtf
.m_nCurrentActionElement
),
125 m_aPrefMapMode ( rMtf
.m_aPrefMapMode
),
126 m_aPrefSize ( rMtf
.m_aPrefSize
),
127 m_pPrev ( rMtf
.m_pPrev
),
128 m_pNext ( rMtf
.m_pNext
),
129 m_pOutDev ( nullptr ),
132 m_bUseCanvas ( rMtf
.m_bUseCanvas
)
134 for( size_t i
= 0, n
= rMtf
.GetActionSize(); i
< n
; ++i
)
136 m_aList
.push_back( rMtf
.GetAction( i
) );
141 Record( rMtf
.m_pOutDev
);
148 GDIMetaFile::~GDIMetaFile()
153 size_t GDIMetaFile::GetActionSize() const
155 return m_aList
.size();
158 MetaAction
* GDIMetaFile::GetAction( size_t nAction
) const
160 return (nAction
< m_aList
.size()) ? m_aList
[ nAction
].get() : nullptr;
163 MetaAction
* GDIMetaFile::FirstAction()
165 m_nCurrentActionElement
= 0;
166 return m_aList
.empty() ? nullptr : m_aList
[ 0 ].get();
169 MetaAction
* GDIMetaFile::NextAction()
171 return ( m_nCurrentActionElement
+ 1 < m_aList
.size() ) ? m_aList
[ ++m_nCurrentActionElement
].get() : nullptr;
174 void GDIMetaFile::ReplaceAction( rtl::Reference
<MetaAction
> pAction
, size_t nAction
)
176 if ( nAction
>= m_aList
.size() )
180 //fdo#39995 This doesn't increment the incoming action ref-count nor does it
181 //decrement the outgoing action ref-count
182 std::swap(pAction
, m_aList
[nAction
]);
185 GDIMetaFile
& GDIMetaFile::operator=( const GDIMetaFile
& rMtf
)
191 // Increment RefCount of MetaActions
192 for( size_t i
= 0, n
= rMtf
.GetActionSize(); i
< n
; ++i
)
194 m_aList
.push_back( rMtf
.GetAction( i
) );
197 m_aPrefMapMode
= rMtf
.m_aPrefMapMode
;
198 m_aPrefSize
= rMtf
.m_aPrefSize
;
199 m_pPrev
= rMtf
.m_pPrev
;
200 m_pNext
= rMtf
.m_pNext
;
204 m_bUseCanvas
= rMtf
.m_bUseCanvas
;
208 Record( rMtf
.m_pOutDev
);
218 bool GDIMetaFile::operator==( const GDIMetaFile
& rMtf
) const
220 const size_t nObjCount
= m_aList
.size();
225 else if( rMtf
.GetActionSize() == nObjCount
&&
226 rMtf
.GetPrefSize() == m_aPrefSize
&&
227 rMtf
.GetPrefMapMode() == m_aPrefMapMode
)
231 for( size_t n
= 0; n
< nObjCount
; n
++ )
233 if( m_aList
[ n
] != rMtf
.GetAction( n
) )
244 void GDIMetaFile::Clear()
252 void GDIMetaFile::Linker( OutputDevice
* pOut
, bool bLink
)
257 m_pPrev
= pOut
->GetConnectMetaFile();
258 pOut
->SetConnectMetaFile( this );
261 m_pPrev
->m_pNext
= this;
267 m_pNext
->m_pPrev
= m_pPrev
;
270 m_pPrev
->m_pNext
= m_pNext
;
275 m_pPrev
->m_pNext
= nullptr;
277 pOut
->SetConnectMetaFile( m_pPrev
);
285 void GDIMetaFile::Record( OutputDevice
* pOut
)
290 m_nCurrentActionElement
= m_aList
.empty() ? 0 : (m_aList
.size() - 1);
293 Linker( pOut
, true );
296 void GDIMetaFile::Play( GDIMetaFile
& rMtf
)
298 if ( !m_bRecord
&& !rMtf
.m_bRecord
)
300 MetaAction
* pAction
= GetCurAction();
301 const size_t nObjCount
= m_aList
.size();
303 rMtf
.UseCanvas( rMtf
.GetUseCanvas() || m_bUseCanvas
);
305 for( size_t nCurPos
= m_nCurrentActionElement
; nCurPos
< nObjCount
; nCurPos
++ )
309 rMtf
.AddAction( pAction
);
312 pAction
= NextAction();
317 void GDIMetaFile::Play( OutputDevice
* pOut
, size_t nPos
)
321 MetaAction
* pAction
= GetCurAction();
322 const size_t nObjCount
= m_aList
.size();
323 size_t nSyncCount
= ( pOut
->GetOutDevType() == OUTDEV_WINDOW
) ? 0x000000ff : 0xffffffff;
325 if( nPos
> nObjCount
)
328 // #i23407# Set backwards-compatible text language and layout mode
329 // This is necessary, since old metafiles don't even know of these
330 // recent add-ons. Newer metafiles must of course explicitly set
332 pOut
->Push( PushFlags::TEXTLAYOUTMODE
|PushFlags::TEXTLANGUAGE
);
333 pOut
->SetLayoutMode( ComplexTextLayoutFlags::Default
);
334 pOut
->SetDigitLanguage( LANGUAGE_SYSTEM
);
336 SAL_INFO( "vcl.gdi", "GDIMetaFile::Play on device of size: " << pOut
->GetOutputSizePixel().Width() << " " << pOut
->GetOutputSizePixel().Height());
338 if( !ImplPlayWithRenderer( pOut
, Point(0,0), pOut
->GetOutputSize() ) ) {
340 for( size_t nCurPos
= m_nCurrentActionElement
; nCurPos
< nPos
; nCurPos
++ )
344 pAction
->Execute( pOut
);
346 // flush output from time to time
347 if( i
++ > nSyncCount
)
349 static_cast<vcl::Window
*>( pOut
)->Flush();
354 pAction
= NextAction();
361 bool GDIMetaFile::ImplPlayWithRenderer( OutputDevice
* pOut
, const Point
& rPos
, Size rLogicDestSize
)
366 Size
rDestSize( pOut
->LogicToPixel( rLogicDestSize
) );
368 const vcl::Window
* win
= dynamic_cast <vcl::Window
*> ( pOut
);
371 win
= Application::GetActiveTopWindow();
373 win
= Application::GetFirstTopLevelWindow();
380 uno::Reference
<rendering::XCanvas
> xCanvas
= win
->GetCanvas ();
385 Size
aSize (rDestSize
.Width () + 1, rDestSize
.Height () + 1);
386 uno::Reference
<rendering::XBitmap
> xBitmap
= xCanvas
->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize
));
389 uno::Reference
< rendering::XBitmapCanvas
> xBitmapCanvas( xBitmap
, uno::UNO_QUERY
);
390 if( xBitmapCanvas
.is() )
392 uno::Reference
< uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
393 uno::Reference
< rendering::XMtfRenderer
> xMtfRenderer
= rendering::MtfRenderer::createWithBitmapCanvas( xContext
, xBitmapCanvas
);
395 xBitmapCanvas
->clear();
396 uno::Reference
< beans::XFastPropertySet
> xMtfFastPropertySet( xMtfRenderer
, uno::UNO_QUERY
);
397 if( xMtfFastPropertySet
.is() )
398 // set this metafile to the renderer to
399 // speedup things (instead of copying data to
400 // sequence of bytes passed to renderer)
401 xMtfFastPropertySet
->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64
>( this ) ) );
403 xMtfRenderer
->draw( rDestSize
.Width(), rDestSize
.Height() );
406 if( aBitmapEx
.Create( xBitmapCanvas
, aSize
) )
408 if (pOut
->GetMapMode().GetMapUnit() == MapUnit::MapPixel
)
409 pOut
->DrawBitmapEx( rPos
, aBitmapEx
);
411 pOut
->DrawBitmapEx( rPos
, rLogicDestSize
, aBitmapEx
);
417 catch (const uno::RuntimeException
& )
419 throw; // runtime errors are fatal
421 catch (const uno::Exception
&)
423 // ignore errors, no way of reporting them here
424 TOOLS_WARN_EXCEPTION("vcl.gdi", "GDIMetaFile::ImplPlayWithRenderer");
430 void GDIMetaFile::Play( OutputDevice
* pOut
, const Point
& rPos
,
433 vcl::Region aDrawClipRegion
;
434 MapMode
aDrawMap( GetPrefMapMode() );
435 Size
aDestSize( pOut
->LogicToPixel( rSize
) );
437 if( !aDestSize
.Width() || !aDestSize
.Height() )
440 GDIMetaFile
* pMtf
= pOut
->GetConnectMetaFile();
442 if( ImplPlayWithRenderer( pOut
, rPos
, rSize
) )
445 Size
aTmpPrefSize( pOut
->LogicToPixel( GetPrefSize(), aDrawMap
) );
447 if( !aTmpPrefSize
.Width() )
448 aTmpPrefSize
.setWidth( aDestSize
.Width() );
450 if( !aTmpPrefSize
.Height() )
451 aTmpPrefSize
.setHeight( aDestSize
.Height() );
453 Fraction
aScaleX( aDestSize
.Width(), aTmpPrefSize
.Width() );
454 Fraction
aScaleY( aDestSize
.Height(), aTmpPrefSize
.Height() );
456 aScaleX
*= aDrawMap
.GetScaleX(); aDrawMap
.SetScaleX( aScaleX
);
457 aScaleY
*= aDrawMap
.GetScaleY(); aDrawMap
.SetScaleY( aScaleY
);
459 // #i47260# Convert logical output position to offset within
460 // the metafile's mapmode. Therefore, disable pixel offset on
461 // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
462 // different mapmode (the one currently set on pOut, that is)
463 // - thus, aDrawMap's origin would generally be wrong. And
464 // even _if_ aDrawMap is similar to pOutDev's current mapmode,
465 // it's _still_ undesirable to have pixel offset unequal zero,
466 // because one would still get round-off errors (the
467 // round-trip error for LogicToPixel( PixelToLogic() ) was the
468 // reason for having pixel offset in the first place).
469 const Size
& rOldOffset( pOut
->GetPixelOffset() );
470 const Size aEmptySize
;
471 pOut
->SetPixelOffset( aEmptySize
);
472 aDrawMap
.SetOrigin( pOut
->PixelToLogic( pOut
->LogicToPixel( rPos
), aDrawMap
) );
473 pOut
->SetPixelOffset( rOldOffset
);
477 if ( pMtf
&& pMtf
->IsRecord() && ( pOut
->GetOutDevType() != OUTDEV_PRINTER
) )
478 pOut
->SetRelativeMapMode( aDrawMap
);
480 pOut
->SetMapMode( aDrawMap
);
482 // #i23407# Set backwards-compatible text language and layout mode
483 // This is necessary, since old metafiles don't even know of these
484 // recent add-ons. Newer metafiles must of course explicitly set
486 pOut
->SetLayoutMode( ComplexTextLayoutFlags::Default
);
487 pOut
->SetDigitLanguage( LANGUAGE_SYSTEM
);
495 void GDIMetaFile::Pause( bool _bPause
)
502 Linker( m_pOutDev
, false );
507 Linker( m_pOutDev
, true );
514 void GDIMetaFile::Stop()
521 Linker( m_pOutDev
, false );
527 void GDIMetaFile::WindStart()
530 m_nCurrentActionElement
= 0;
533 void GDIMetaFile::WindPrev()
536 if ( m_nCurrentActionElement
> 0 )
537 --m_nCurrentActionElement
;
540 void GDIMetaFile::AddAction(const rtl::Reference
<MetaAction
>& pAction
)
542 m_aList
.push_back( pAction
);
546 m_pPrev
->AddAction( pAction
);
550 void GDIMetaFile::AddAction(const rtl::Reference
<MetaAction
>& pAction
, size_t nPos
)
552 if ( nPos
< m_aList
.size() )
554 m_aList
.insert( m_aList
.begin() + nPos
, pAction
);
558 m_aList
.push_back( pAction
);
563 m_pPrev
->AddAction( pAction
, nPos
);
567 void GDIMetaFile::push_back(const rtl::Reference
<MetaAction
>& pAction
)
569 m_aList
.push_back( pAction
);
572 void GDIMetaFile::Mirror( BmpMirrorFlags nMirrorFlags
)
574 const Size
aOldPrefSize( GetPrefSize() );
576 double fScaleX
, fScaleY
;
578 if( nMirrorFlags
& BmpMirrorFlags::Horizontal
)
580 nMoveX
= std::abs( aOldPrefSize
.Width() ) - 1;
589 if( nMirrorFlags
& BmpMirrorFlags::Vertical
)
591 nMoveY
= std::abs( aOldPrefSize
.Height() ) - 1;
600 if( ( fScaleX
!= 1.0 ) || ( fScaleY
!= 1.0 ) )
602 Scale( fScaleX
, fScaleY
);
603 Move( nMoveX
, nMoveY
);
604 SetPrefSize( aOldPrefSize
);
608 void GDIMetaFile::Move( long nX
, long nY
)
610 const Size
aBaseOffset( nX
, nY
);
611 Size
aOffset( aBaseOffset
);
612 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
614 aMapVDev
->EnableOutput( false );
615 aMapVDev
->SetMapMode( GetPrefMapMode() );
617 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
619 const MetaActionType nType
= pAct
->GetType();
622 if( pAct
->GetRefCount() > 1 )
624 m_aList
[ m_nCurrentActionElement
] = pAct
->Clone();
625 pModAct
= m_aList
[ m_nCurrentActionElement
].get();
630 if( ( MetaActionType::MAPMODE
== nType
) ||
631 ( MetaActionType::PUSH
== nType
) ||
632 ( MetaActionType::POP
== nType
) )
634 pModAct
->Execute( aMapVDev
.get() );
635 aOffset
= OutputDevice::LogicToLogic( aBaseOffset
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
638 pModAct
->Move( aOffset
.Width(), aOffset
.Height() );
642 void GDIMetaFile::Move( long nX
, long nY
, long nDPIX
, long nDPIY
)
644 const Size
aBaseOffset( nX
, nY
);
645 Size
aOffset( aBaseOffset
);
646 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
648 aMapVDev
->EnableOutput( false );
649 aMapVDev
->SetReferenceDevice( nDPIX
, nDPIY
);
650 aMapVDev
->SetMapMode( GetPrefMapMode() );
652 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
654 const MetaActionType nType
= pAct
->GetType();
657 if( pAct
->GetRefCount() > 1 )
659 m_aList
[ m_nCurrentActionElement
] = pAct
->Clone();
660 pModAct
= m_aList
[ m_nCurrentActionElement
].get();
665 if( ( MetaActionType::MAPMODE
== nType
) ||
666 ( MetaActionType::PUSH
== nType
) ||
667 ( MetaActionType::POP
== nType
) )
669 pModAct
->Execute( aMapVDev
.get() );
670 if( aMapVDev
->GetMapMode().GetMapUnit() == MapUnit::MapPixel
)
672 aOffset
= aMapVDev
->LogicToPixel( aBaseOffset
, GetPrefMapMode() );
673 MapMode
aMap( aMapVDev
->GetMapMode() );
674 aOffset
.setWidth( static_cast<long>(aOffset
.Width() * static_cast<double>(aMap
.GetScaleX())) );
675 aOffset
.setHeight( static_cast<long>(aOffset
.Height() * static_cast<double>(aMap
.GetScaleY())) );
678 aOffset
= OutputDevice::LogicToLogic( aBaseOffset
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
681 pModAct
->Move( aOffset
.Width(), aOffset
.Height() );
685 void GDIMetaFile::Scale( double fScaleX
, double fScaleY
)
687 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
691 if( pAct
->GetRefCount() > 1 )
693 m_aList
[ m_nCurrentActionElement
] = pAct
->Clone();
694 pModAct
= m_aList
[ m_nCurrentActionElement
].get();
699 pModAct
->Scale( fScaleX
, fScaleY
);
702 m_aPrefSize
.setWidth( FRound( m_aPrefSize
.Width() * fScaleX
) );
703 m_aPrefSize
.setHeight( FRound( m_aPrefSize
.Height() * fScaleY
) );
706 void GDIMetaFile::Scale( const Fraction
& rScaleX
, const Fraction
& rScaleY
)
708 Scale( static_cast<double>(rScaleX
), static_cast<double>(rScaleY
) );
711 void GDIMetaFile::Clip( const tools::Rectangle
& i_rClipRect
)
713 tools::Rectangle
aCurRect( i_rClipRect
);
714 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
716 aMapVDev
->EnableOutput( false );
717 aMapVDev
->SetMapMode( GetPrefMapMode() );
719 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
721 const MetaActionType nType
= pAct
->GetType();
723 if( ( MetaActionType::MAPMODE
== nType
) ||
724 ( MetaActionType::PUSH
== nType
) ||
725 ( MetaActionType::POP
== nType
) )
727 pAct
->Execute( aMapVDev
.get() );
728 aCurRect
= OutputDevice::LogicToLogic( i_rClipRect
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
730 else if( nType
== MetaActionType::CLIPREGION
)
732 MetaClipRegionAction
* pOldAct
= static_cast<MetaClipRegionAction
*>(pAct
);
733 vcl::Region
aNewReg( aCurRect
);
734 if( pOldAct
->IsClipping() )
735 aNewReg
.Intersect( pOldAct
->GetRegion() );
736 MetaClipRegionAction
* pNewAct
= new MetaClipRegionAction( aNewReg
, true );
737 m_aList
[ m_nCurrentActionElement
] = pNewAct
;
742 Point
GDIMetaFile::ImplGetRotatedPoint( const Point
& rPt
, const Point
& rRotatePt
,
743 const Size
& rOffset
, double fSin
, double fCos
)
745 const long nX
= rPt
.X() - rRotatePt
.X();
746 const long nY
= rPt
.Y() - rRotatePt
.Y();
748 return Point( FRound( fCos
* nX
+ fSin
* nY
) + rRotatePt
.X() + rOffset
.Width(),
749 -FRound( fSin
* nX
- fCos
* nY
) + rRotatePt
.Y() + rOffset
.Height() );
752 tools::Polygon
GDIMetaFile::ImplGetRotatedPolygon( const tools::Polygon
& rPoly
, const Point
& rRotatePt
,
753 const Size
& rOffset
, double fSin
, double fCos
)
755 tools::Polygon
aRet( rPoly
);
757 aRet
.Rotate( rRotatePt
, fSin
, fCos
);
758 aRet
.Move( rOffset
.Width(), rOffset
.Height() );
763 tools::PolyPolygon
GDIMetaFile::ImplGetRotatedPolyPolygon( const tools::PolyPolygon
& rPolyPoly
, const Point
& rRotatePt
,
764 const Size
& rOffset
, double fSin
, double fCos
)
766 tools::PolyPolygon
aRet( rPolyPoly
);
768 aRet
.Rotate( rRotatePt
, fSin
, fCos
);
769 aRet
.Move( rOffset
.Width(), rOffset
.Height() );
774 void GDIMetaFile::ImplAddGradientEx( GDIMetaFile
& rMtf
,
775 const OutputDevice
& rMapDev
,
776 const tools::PolyPolygon
& rPolyPoly
,
777 const Gradient
& rGrad
)
779 // Generate comment, GradientEx and Gradient actions (within DrawGradient)
780 ScopedVclPtrInstance
< VirtualDevice
> aVDev(rMapDev
, DeviceFormat::DEFAULT
);
781 aVDev
->EnableOutput( false );
782 GDIMetaFile aGradMtf
;
784 aGradMtf
.Record( aVDev
.get() );
785 aVDev
->DrawGradient( rPolyPoly
, rGrad
);
788 size_t i
, nAct( aGradMtf
.GetActionSize() );
789 for( i
=0; i
< nAct
; ++i
)
791 MetaAction
* pMetaAct
= aGradMtf
.GetAction( i
);
792 rMtf
.AddAction( pMetaAct
);
796 void GDIMetaFile::Rotate( long nAngle10
)
799 nAngle10
= ( nAngle10
< 0 ) ? ( 3599 + nAngle10
) : nAngle10
;
805 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
806 const double fAngle
= F_PI1800
* nAngle10
;
807 const double fSin
= sin( fAngle
);
808 const double fCos
= cos( fAngle
);
809 tools::Rectangle
aRect( Point(), GetPrefSize() );
810 tools::Polygon
aPoly( aRect
);
812 aPoly
.Rotate( Point(), fSin
, fCos
);
814 aMapVDev
->EnableOutput( false );
815 aMapVDev
->SetMapMode( GetPrefMapMode() );
817 const tools::Rectangle
aNewBound( aPoly
.GetBoundRect() );
819 const Point
aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
820 const Size
aOffset( -aNewBound
.Left(), -aNewBound
.Top() );
822 Point
aRotAnchor( aOrigin
);
823 Size
aRotOffset( aOffset
);
825 for( MetaAction
* pAction
= FirstAction(); pAction
; pAction
= NextAction() )
827 const MetaActionType nActionType
= pAction
->GetType();
829 switch( nActionType
)
831 case MetaActionType::PIXEL
:
833 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
834 aMtf
.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
835 pAct
->GetColor() ) );
839 case MetaActionType::POINT
:
841 MetaPointAction
* pAct
= static_cast<MetaPointAction
*>(pAction
);
842 aMtf
.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
846 case MetaActionType::LINE
:
848 MetaLineAction
* pAct
= static_cast<MetaLineAction
*>(pAction
);
849 aMtf
.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct
->GetStartPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
850 ImplGetRotatedPoint( pAct
->GetEndPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
851 pAct
->GetLineInfo() ) );
855 case MetaActionType::RECT
:
857 MetaRectAction
* pAct
= static_cast<MetaRectAction
*>(pAction
);
858 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
862 case MetaActionType::ROUNDRECT
:
864 MetaRoundRectAction
* pAct
= static_cast<MetaRoundRectAction
*>(pAction
);
865 const tools::Polygon
aRoundRectPoly( pAct
->GetRect(), pAct
->GetHorzRound(), pAct
->GetVertRound() );
867 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
871 case MetaActionType::ELLIPSE
:
873 MetaEllipseAction
* pAct
= static_cast<MetaEllipseAction
*>(pAction
);
874 const tools::Polygon
aEllipsePoly( pAct
->GetRect().Center(), pAct
->GetRect().GetWidth() >> 1, pAct
->GetRect().GetHeight() >> 1 );
876 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
880 case MetaActionType::ARC
:
882 MetaArcAction
* pAct
= static_cast<MetaArcAction
*>(pAction
);
883 const tools::Polygon
aArcPoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Arc
);
885 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
889 case MetaActionType::PIE
:
891 MetaPieAction
* pAct
= static_cast<MetaPieAction
*>(pAction
);
892 const tools::Polygon
aPiePoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Pie
);
894 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
898 case MetaActionType::CHORD
:
900 MetaChordAction
* pAct
= static_cast<MetaChordAction
*>(pAction
);
901 const tools::Polygon
aChordPoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), PolyStyle::Chord
);
903 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
907 case MetaActionType::POLYLINE
:
909 MetaPolyLineAction
* pAct
= static_cast<MetaPolyLineAction
*>(pAction
);
910 aMtf
.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct
->GetPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
), pAct
->GetLineInfo() ) );
914 case MetaActionType::POLYGON
:
916 MetaPolygonAction
* pAct
= static_cast<MetaPolygonAction
*>(pAction
);
917 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct
->GetPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
921 case MetaActionType::POLYPOLYGON
:
923 MetaPolyPolygonAction
* pAct
= static_cast<MetaPolyPolygonAction
*>(pAction
);
924 aMtf
.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
928 case MetaActionType::TEXT
:
930 MetaTextAction
* pAct
= static_cast<MetaTextAction
*>(pAction
);
931 aMtf
.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
932 pAct
->GetText(), pAct
->GetIndex(), pAct
->GetLen() ) );
936 case MetaActionType::TEXTARRAY
:
938 MetaTextArrayAction
* pAct
= static_cast<MetaTextArrayAction
*>(pAction
);
939 aMtf
.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
940 pAct
->GetText(), pAct
->GetDXArray(), pAct
->GetIndex(), pAct
->GetLen() ) );
944 case MetaActionType::STRETCHTEXT
:
946 MetaStretchTextAction
* pAct
= static_cast<MetaStretchTextAction
*>(pAction
);
947 aMtf
.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
948 pAct
->GetWidth(), pAct
->GetText(), pAct
->GetIndex(), pAct
->GetLen() ) );
952 case MetaActionType::TEXTLINE
:
954 MetaTextLineAction
* pAct
= static_cast<MetaTextLineAction
*>(pAction
);
955 aMtf
.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct
->GetStartPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
956 pAct
->GetWidth(), pAct
->GetStrikeout(), pAct
->GetUnderline(), pAct
->GetOverline() ) );
960 case MetaActionType::BMPSCALE
:
962 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
963 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
964 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
965 BitmapEx
aBmpEx( pAct
->GetBitmap() );
967 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
968 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(),
973 case MetaActionType::BMPSCALEPART
:
975 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
976 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetDestPoint(), pAct
->GetDestSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
977 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
978 BitmapEx
aBmpEx( pAct
->GetBitmap() );
980 aBmpEx
.Crop( tools::Rectangle( pAct
->GetSrcPoint(), pAct
->GetSrcSize() ) );
981 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
983 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
987 case MetaActionType::BMPEXSCALE
:
989 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
990 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
991 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
992 BitmapEx
aBmpEx( pAct
->GetBitmapEx() );
994 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
996 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1000 case MetaActionType::BMPEXSCALEPART
:
1002 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1003 tools::Polygon
aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetDestPoint(), pAct
->GetDestSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1004 tools::Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1005 BitmapEx
aBmpEx( pAct
->GetBitmapEx() );
1007 aBmpEx
.Crop( tools::Rectangle( pAct
->GetSrcPoint(), pAct
->GetSrcSize() ) );
1008 aBmpEx
.Rotate( nAngle10
, COL_TRANSPARENT
);
1010 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1014 case MetaActionType::GRADIENT
:
1016 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1018 ImplAddGradientEx( aMtf
, *aMapVDev
,
1019 ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1020 pAct
->GetGradient() );
1024 case MetaActionType::GRADIENTEX
:
1026 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1027 aMtf
.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1028 pAct
->GetGradient() ) );
1032 // Handle gradientex comment block correctly
1033 case MetaActionType::COMMENT
:
1035 MetaCommentAction
* pCommentAct
= static_cast<MetaCommentAction
*>(pAction
);
1036 if( pCommentAct
->GetComment() == "XGRAD_SEQ_BEGIN" )
1038 int nBeginComments( 1 );
1039 pAction
= NextAction();
1041 // skip everything, except gradientex action
1044 const MetaActionType nType
= pAction
->GetType();
1046 if( MetaActionType::GRADIENTEX
== nType
)
1048 // Add rotated gradientex
1049 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1050 ImplAddGradientEx( aMtf
, *aMapVDev
,
1051 ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1052 pAct
->GetGradient() );
1054 else if( MetaActionType::COMMENT
== nType
)
1056 MetaCommentAction
* pAct
= static_cast<MetaCommentAction
*>(pAction
);
1057 if( pAct
->GetComment() == "XGRAD_SEQ_END" )
1059 // handle nested blocks
1062 // gradientex comment block: end reached, done.
1063 if( !nBeginComments
)
1066 else if( pAct
->GetComment() == "XGRAD_SEQ_BEGIN" )
1068 // handle nested blocks
1074 pAction
=NextAction();
1079 bool bPathStroke
= (pCommentAct
->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1080 if ( bPathStroke
|| pCommentAct
->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1082 if ( pCommentAct
->GetDataSize() )
1084 SvMemoryStream
aMemStm( const_cast<sal_uInt8
*>(pCommentAct
->GetData()), pCommentAct
->GetDataSize(), StreamMode::READ
);
1085 SvMemoryStream aDest
;
1088 SvtGraphicStroke aStroke
;
1089 ReadSvtGraphicStroke( aMemStm
, aStroke
);
1090 tools::Polygon aPath
;
1091 aStroke
.getPath( aPath
);
1092 aStroke
.setPath( ImplGetRotatedPolygon( aPath
, aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1093 WriteSvtGraphicStroke( aDest
, aStroke
);
1094 aMtf
.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1095 static_cast<const sal_uInt8
*>( aDest
.GetData()), aDest
.Tell() ) );
1099 SvtGraphicFill aFill
;
1100 ReadSvtGraphicFill( aMemStm
, aFill
);
1101 tools::PolyPolygon aPath
;
1102 aFill
.getPath( aPath
);
1103 aFill
.setPath( ImplGetRotatedPolyPolygon( aPath
, aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1104 WriteSvtGraphicFill( aDest
, aFill
);
1105 aMtf
.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1106 static_cast<const sal_uInt8
*>( aDest
.GetData()), aDest
.Tell() ) );
1110 else if ( pCommentAct
->GetComment() == "XPATHSTROKE_SEQ_END"
1111 || pCommentAct
->GetComment() == "XPATHFILL_SEQ_END" )
1113 pAction
->Execute( aMapVDev
.get() );
1114 aMtf
.AddAction( pAction
);
1120 case MetaActionType::HATCH
:
1122 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
1123 Hatch
aHatch( pAct
->GetHatch() );
1125 aHatch
.SetAngle( aHatch
.GetAngle() + static_cast<sal_uInt16
>(nAngle10
) );
1126 aMtf
.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1131 case MetaActionType::Transparent
:
1133 MetaTransparentAction
* pAct
= static_cast<MetaTransparentAction
*>(pAction
);
1134 aMtf
.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1135 pAct
->GetTransparence() ) );
1139 case MetaActionType::FLOATTRANSPARENT
:
1141 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
1142 GDIMetaFile
aTransMtf( pAct
->GetGDIMetaFile() );
1143 tools::Polygon
aMtfPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1144 tools::Rectangle
aMtfRect( aMtfPoly
.GetBoundRect() );
1146 aTransMtf
.Rotate( nAngle10
);
1147 aMtf
.AddAction( new MetaFloatTransparentAction( aTransMtf
, aMtfRect
.TopLeft(), aMtfRect
.GetSize(),
1148 pAct
->GetGradient() ) );
1152 case MetaActionType::EPS
:
1154 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
1155 GDIMetaFile
aEPSMtf( pAct
->GetSubstitute() );
1156 tools::Polygon
aEPSPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1157 tools::Rectangle
aEPSRect( aEPSPoly
.GetBoundRect() );
1159 aEPSMtf
.Rotate( nAngle10
);
1160 aMtf
.AddAction( new MetaEPSAction( aEPSRect
.TopLeft(), aEPSRect
.GetSize(),
1161 pAct
->GetLink(), aEPSMtf
) );
1165 case MetaActionType::CLIPREGION
:
1167 MetaClipRegionAction
* pAct
= static_cast<MetaClipRegionAction
*>(pAction
);
1169 if( pAct
->IsClipping() && pAct
->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1170 aMtf
.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct
->GetRegion().GetAsPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ), true ) );
1173 aMtf
.AddAction( pAction
);
1178 case MetaActionType::ISECTRECTCLIPREGION
:
1180 MetaISectRectClipRegionAction
* pAct
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
1181 aMtf
.AddAction( new MetaISectRegionClipRegionAction(vcl::Region(
1182 ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
,
1183 aRotOffset
, fSin
, fCos
)) ) );
1187 case MetaActionType::ISECTREGIONCLIPREGION
:
1189 MetaISectRegionClipRegionAction
* pAct
= static_cast<MetaISectRegionClipRegionAction
*>(pAction
);
1190 const vcl::Region
& rRegion
= pAct
->GetRegion();
1192 if( rRegion
.HasPolyPolygonOrB2DPolyPolygon() )
1193 aMtf
.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion
.GetAsPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) ) );
1196 aMtf
.AddAction( pAction
);
1201 case MetaActionType::REFPOINT
:
1203 MetaRefPointAction
* pAct
= static_cast<MetaRefPointAction
*>(pAction
);
1204 aMtf
.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct
->GetRefPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
), pAct
->IsSetting() ) );
1208 case MetaActionType::FONT
:
1210 MetaFontAction
* pAct
= static_cast<MetaFontAction
*>(pAction
);
1211 vcl::Font
aFont( pAct
->GetFont() );
1213 aFont
.SetOrientation( aFont
.GetOrientation() + static_cast<sal_uInt16
>(nAngle10
) );
1214 aMtf
.AddAction( new MetaFontAction( aFont
) );
1218 case MetaActionType::BMP
:
1219 case MetaActionType::BMPEX
:
1220 case MetaActionType::MASK
:
1221 case MetaActionType::MASKSCALE
:
1222 case MetaActionType::MASKSCALEPART
:
1223 case MetaActionType::WALLPAPER
:
1224 case MetaActionType::TEXTRECT
:
1225 case MetaActionType::MOVECLIPREGION
:
1227 OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1233 pAction
->Execute( aMapVDev
.get() );
1234 aMtf
.AddAction( pAction
);
1236 // update rotation point and offset, if necessary
1237 if( ( MetaActionType::MAPMODE
== nActionType
) ||
1238 ( MetaActionType::PUSH
== nActionType
) ||
1239 ( MetaActionType::POP
== nActionType
) )
1241 aRotAnchor
= OutputDevice::LogicToLogic( aOrigin
, m_aPrefMapMode
, aMapVDev
->GetMapMode() );
1242 aRotOffset
= OutputDevice::LogicToLogic( aOffset
, m_aPrefMapMode
, aMapVDev
->GetMapMode() );
1249 aMtf
.m_aPrefMapMode
= m_aPrefMapMode
;
1250 aMtf
.m_aPrefSize
= aNewBound
.GetSize();
1256 static void ImplActionBounds( tools::Rectangle
& o_rOutBounds
,
1257 const tools::Rectangle
& i_rInBounds
,
1258 const std::vector
<tools::Rectangle
>& i_rClipStack
,
1259 tools::Rectangle
* o_pHairline
)
1261 tools::Rectangle
aBounds( i_rInBounds
);
1262 if( ! i_rInBounds
.IsEmpty() && ! i_rClipStack
.empty() && ! i_rClipStack
.back().IsEmpty() )
1263 aBounds
.Intersection( i_rClipStack
.back() );
1264 if( ! aBounds
.IsEmpty() )
1266 if( ! o_rOutBounds
.IsEmpty() )
1267 o_rOutBounds
.Union( aBounds
);
1269 o_rOutBounds
= aBounds
;
1273 if( ! o_pHairline
->IsEmpty() )
1274 o_pHairline
->Union( aBounds
);
1276 *o_pHairline
= aBounds
;
1281 tools::Rectangle
GDIMetaFile::GetBoundRect( OutputDevice
& i_rReference
, tools::Rectangle
* pHairline
) const
1284 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev( i_rReference
);
1286 aMapVDev
->EnableOutput( false );
1287 aMapVDev
->SetMapMode( GetPrefMapMode() );
1289 std::vector
<tools::Rectangle
> aClipStack( 1, tools::Rectangle() );
1290 std::vector
<PushFlags
> aPushFlagStack
;
1292 tools::Rectangle aBound
;
1295 *pHairline
= tools::Rectangle();
1297 const sal_uLong
nCount(GetActionSize());
1299 for(sal_uLong
a(0); a
< nCount
; a
++)
1301 MetaAction
* pAction
= GetAction(a
);
1302 const MetaActionType nActionType
= pAction
->GetType();
1303 tools::Rectangle
* pUseHairline
= (pHairline
&& aMapVDev
->IsLineColor()) ? pHairline
: nullptr;
1305 switch( nActionType
)
1307 case MetaActionType::PIXEL
:
1309 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
1310 ImplActionBounds( aBound
,
1311 tools::Rectangle( OutputDevice::LogicToLogic( pAct
->GetPoint(), aMapVDev
->GetMapMode(), GetPrefMapMode() ),
1312 aMapVDev
->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1313 aClipStack
, pUseHairline
);
1317 case MetaActionType::POINT
:
1319 MetaPointAction
* pAct
= static_cast<MetaPointAction
*>(pAction
);
1320 ImplActionBounds( aBound
,
1321 tools::Rectangle( OutputDevice::LogicToLogic( pAct
->GetPoint(), aMapVDev
->GetMapMode(), GetPrefMapMode() ),
1322 aMapVDev
->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1323 aClipStack
, pUseHairline
);
1327 case MetaActionType::LINE
:
1329 MetaLineAction
* pAct
= static_cast<MetaLineAction
*>(pAction
);
1330 Point
aP1( pAct
->GetStartPoint() ), aP2( pAct
->GetEndPoint() );
1331 tools::Rectangle
aRect( aP1
, aP2
);
1336 const LineInfo
& rLineInfo
= pAct
->GetLineInfo();
1338 if(0 != rLineInfo
.GetWidth())
1339 pUseHairline
= nullptr;
1342 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1346 case MetaActionType::RECT
:
1348 MetaRectAction
* pAct
= static_cast<MetaRectAction
*>(pAction
);
1349 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1353 case MetaActionType::ROUNDRECT
:
1355 MetaRoundRectAction
* pAct
= static_cast<MetaRoundRectAction
*>(pAction
);
1356 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1360 case MetaActionType::ELLIPSE
:
1362 MetaEllipseAction
* pAct
= static_cast<MetaEllipseAction
*>(pAction
);
1363 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1367 case MetaActionType::ARC
:
1369 MetaArcAction
* pAct
= static_cast<MetaArcAction
*>(pAction
);
1370 // FIXME: this is imprecise
1371 // e.g. for small arcs the whole rectangle is WAY too large
1372 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1376 case MetaActionType::PIE
:
1378 MetaPieAction
* pAct
= static_cast<MetaPieAction
*>(pAction
);
1379 // FIXME: this is imprecise
1380 // e.g. for small arcs the whole rectangle is WAY too large
1381 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1385 case MetaActionType::CHORD
:
1387 MetaChordAction
* pAct
= static_cast<MetaChordAction
*>(pAction
);
1388 // FIXME: this is imprecise
1389 // e.g. for small arcs the whole rectangle is WAY too large
1390 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1394 case MetaActionType::POLYLINE
:
1396 MetaPolyLineAction
* pAct
= static_cast<MetaPolyLineAction
*>(pAction
);
1397 tools::Rectangle
aRect( pAct
->GetPolygon().GetBoundRect() );
1401 const LineInfo
& rLineInfo
= pAct
->GetLineInfo();
1403 if(0 != rLineInfo
.GetWidth())
1404 pUseHairline
= nullptr;
1407 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1411 case MetaActionType::POLYGON
:
1413 MetaPolygonAction
* pAct
= static_cast<MetaPolygonAction
*>(pAction
);
1414 tools::Rectangle
aRect( pAct
->GetPolygon().GetBoundRect() );
1415 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1419 case MetaActionType::POLYPOLYGON
:
1421 MetaPolyPolygonAction
* pAct
= static_cast<MetaPolyPolygonAction
*>(pAction
);
1422 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1423 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1427 case MetaActionType::TEXT
:
1429 MetaTextAction
* pAct
= static_cast<MetaTextAction
*>(pAction
);
1430 tools::Rectangle aRect
;
1431 // hdu said base = index
1432 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen() );
1433 Point
aPt( pAct
->GetPoint() );
1434 aRect
.Move( aPt
.X(), aPt
.Y() );
1435 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1439 case MetaActionType::TEXTARRAY
:
1441 MetaTextArrayAction
* pAct
= static_cast<MetaTextArrayAction
*>(pAction
);
1442 tools::Rectangle aRect
;
1443 // hdu said base = index
1444 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen(),
1445 0, pAct
->GetDXArray() );
1446 Point
aPt( pAct
->GetPoint() );
1447 aRect
.Move( aPt
.X(), aPt
.Y() );
1448 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1452 case MetaActionType::STRETCHTEXT
:
1454 MetaStretchTextAction
* pAct
= static_cast<MetaStretchTextAction
*>(pAction
);
1455 tools::Rectangle aRect
;
1456 // hdu said base = index
1457 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen(),
1459 Point
aPt( pAct
->GetPoint() );
1460 aRect
.Move( aPt
.X(), aPt
.Y() );
1461 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1465 case MetaActionType::TEXTLINE
:
1467 MetaTextLineAction
* pAct
= static_cast<MetaTextLineAction
*>(pAction
);
1468 // measure a test string to get ascend and descent right
1469 static const sal_Unicode pStr
[] = { 0xc4, 0x67, 0 };
1470 OUString
aStr( pStr
);
1472 tools::Rectangle aRect
;
1473 aMapVDev
->GetTextBoundRect( aRect
, aStr
, 0, 0, aStr
.getLength() );
1474 Point
aPt( pAct
->GetStartPoint() );
1475 aRect
.Move( aPt
.X(), aPt
.Y() );
1476 aRect
.SetRight( aRect
.Left() + pAct
->GetWidth() );
1477 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1481 case MetaActionType::BMPSCALE
:
1483 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1484 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1485 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1489 case MetaActionType::BMPSCALEPART
:
1491 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1492 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1493 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1497 case MetaActionType::BMPEXSCALE
:
1499 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1500 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1501 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1505 case MetaActionType::BMPEXSCALEPART
:
1507 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1508 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1509 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1513 case MetaActionType::GRADIENT
:
1515 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1516 tools::Rectangle
aRect( pAct
->GetRect() );
1517 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1521 case MetaActionType::GRADIENTEX
:
1523 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1524 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1525 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1529 case MetaActionType::COMMENT
:
1535 case MetaActionType::HATCH
:
1537 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
1538 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1539 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1543 case MetaActionType::Transparent
:
1545 MetaTransparentAction
* pAct
= static_cast<MetaTransparentAction
*>(pAction
);
1546 tools::Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1547 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1551 case MetaActionType::FLOATTRANSPARENT
:
1553 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
1554 // MetaFloatTransparentAction is defined limiting its content Metafile
1555 // to its geometry definition(Point, Size), so use these directly
1556 const tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1557 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1561 case MetaActionType::EPS
:
1563 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
1564 tools::Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1565 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1569 case MetaActionType::CLIPREGION
:
1571 MetaClipRegionAction
* pAct
= static_cast<MetaClipRegionAction
*>(pAction
);
1572 if( pAct
->IsClipping() )
1573 aClipStack
.back() = OutputDevice::LogicToLogic( pAct
->GetRegion().GetBoundRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() );
1575 aClipStack
.back() = tools::Rectangle();
1579 case MetaActionType::ISECTRECTCLIPREGION
:
1581 MetaISectRectClipRegionAction
* pAct
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
1582 tools::Rectangle
aRect( OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ) );
1583 if( aClipStack
.back().IsEmpty() )
1584 aClipStack
.back() = aRect
;
1586 aClipStack
.back().Intersection( aRect
);
1590 case MetaActionType::ISECTREGIONCLIPREGION
:
1592 MetaISectRegionClipRegionAction
* pAct
= static_cast<MetaISectRegionClipRegionAction
*>(pAction
);
1593 tools::Rectangle
aRect( OutputDevice::LogicToLogic( pAct
->GetRegion().GetBoundRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ) );
1594 if( aClipStack
.back().IsEmpty() )
1595 aClipStack
.back() = aRect
;
1597 aClipStack
.back().Intersection( aRect
);
1601 case MetaActionType::BMP
:
1603 MetaBmpAction
* pAct
= static_cast<MetaBmpAction
*>(pAction
);
1604 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmap().GetSizePixel() ) );
1605 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1609 case MetaActionType::BMPEX
:
1611 MetaBmpExAction
* pAct
= static_cast<MetaBmpExAction
*>(pAction
);
1612 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmapEx().GetSizePixel() ) );
1613 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1617 case MetaActionType::MASK
:
1619 MetaMaskAction
* pAct
= static_cast<MetaMaskAction
*>(pAction
);
1620 tools::Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmap().GetSizePixel() ) );
1621 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1625 case MetaActionType::MASKSCALE
:
1627 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1628 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1629 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1633 case MetaActionType::MASKSCALEPART
:
1635 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1636 tools::Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1637 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1641 case MetaActionType::WALLPAPER
:
1643 MetaWallpaperAction
* pAct
= static_cast<MetaWallpaperAction
*>(pAction
);
1644 tools::Rectangle
aRect( pAct
->GetRect() );
1645 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1649 case MetaActionType::TEXTRECT
:
1651 MetaTextRectAction
* pAct
= static_cast<MetaTextRectAction
*>(pAction
);
1652 tools::Rectangle
aRect( pAct
->GetRect() );
1653 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, nullptr );
1657 case MetaActionType::MOVECLIPREGION
:
1659 MetaMoveClipRegionAction
* pAct
= static_cast<MetaMoveClipRegionAction
*>(pAction
);
1660 if( ! aClipStack
.back().IsEmpty() )
1662 Size
aDelta( pAct
->GetHorzMove(), pAct
->GetVertMove() );
1663 aDelta
= OutputDevice::LogicToLogic( aDelta
, aMapVDev
->GetMapMode(), GetPrefMapMode() );
1664 aClipStack
.back().Move( aDelta
.Width(), aDelta
.Width() );
1671 pAction
->Execute( aMapVDev
.get() );
1673 if( nActionType
== MetaActionType::PUSH
)
1675 MetaPushAction
* pAct
= static_cast<MetaPushAction
*>(pAction
);
1676 aPushFlagStack
.push_back( pAct
->GetFlags() );
1677 if( aPushFlagStack
.back() & PushFlags::CLIPREGION
)
1679 tools::Rectangle
aRect( aClipStack
.back() );
1680 aClipStack
.push_back( aRect
);
1683 else if( nActionType
== MetaActionType::POP
)
1686 if( ! aPushFlagStack
.empty() )
1688 if( aPushFlagStack
.back() & PushFlags::CLIPREGION
)
1690 if( aClipStack
.size() > 1 )
1691 aClipStack
.pop_back();
1693 aPushFlagStack
.pop_back();
1703 Color
GDIMetaFile::ImplColAdjustFnc( const Color
& rColor
, const void* pColParam
)
1705 return Color( rColor
.GetTransparency(),
1706 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapR
[ rColor
.GetRed() ],
1707 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapG
[ rColor
.GetGreen() ],
1708 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapB
[ rColor
.GetBlue() ] );
1712 BitmapEx
GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1714 const ImplBmpAdjustParam
* p
= static_cast<const ImplBmpAdjustParam
*>(pBmpParam
);
1715 BitmapEx
aRet( rBmpEx
);
1717 aRet
.Adjust( p
->nLuminancePercent
, p
->nContrastPercent
,
1718 p
->nChannelRPercent
, p
->nChannelGPercent
, p
->nChannelBPercent
,
1719 p
->fGamma
, p
->bInvert
);
1724 Color
GDIMetaFile::ImplColConvertFnc( const Color
& rColor
, const void* pColParam
)
1726 sal_uInt8 cLum
= rColor
.GetLuminance();
1728 if( MtfConversion::N1BitThreshold
== static_cast<const ImplColConvertParam
*>(pColParam
)->eConversion
)
1729 cLum
= ( cLum
< 128 ) ? 0 : 255;
1731 return Color( rColor
.GetTransparency(), cLum
, cLum
, cLum
);
1734 BitmapEx
GDIMetaFile::ImplBmpConvertFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1736 BitmapEx
aRet( rBmpEx
);
1738 aRet
.Convert( static_cast<const ImplBmpConvertParam
*>(pBmpParam
)->eConversion
);
1743 Color
GDIMetaFile::ImplColMonoFnc( const Color
&, const void* pColParam
)
1745 return static_cast<const ImplColMonoParam
*>(pColParam
)->aColor
;
1748 BitmapEx
GDIMetaFile::ImplBmpMonoFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1750 BitmapPalette
aPal( 3 );
1752 aPal
[ 0 ] = COL_BLACK
;
1753 aPal
[ 1 ] = COL_WHITE
;
1754 aPal
[ 2 ] = static_cast<const ImplBmpMonoParam
*>(pBmpParam
)->aColor
;
1756 Bitmap
aBmp( rBmpEx
.GetSizePixel(), 4, &aPal
);
1757 aBmp
.Erase( static_cast<const ImplBmpMonoParam
*>(pBmpParam
)->aColor
);
1759 if( rBmpEx
.IsAlpha() )
1760 return BitmapEx( aBmp
, rBmpEx
.GetAlpha() );
1761 else if( rBmpEx
.IsTransparent() )
1762 return BitmapEx( aBmp
, rBmpEx
.GetMask() );
1764 return BitmapEx( aBmp
);
1767 Color
GDIMetaFile::ImplColReplaceFnc( const Color
& rColor
, const void* pColParam
)
1769 const sal_uLong nR
= rColor
.GetRed(), nG
= rColor
.GetGreen(), nB
= rColor
.GetBlue();
1771 for( sal_uLong i
= 0; i
< static_cast<const ImplColReplaceParam
*>(pColParam
)->nCount
; i
++ )
1773 if( ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinR
[ i
] <= nR
) &&
1774 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxR
[ i
] >= nR
) &&
1775 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinG
[ i
] <= nG
) &&
1776 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxG
[ i
] >= nG
) &&
1777 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinB
[ i
] <= nB
) &&
1778 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxB
[ i
] >= nB
) )
1780 return static_cast<const ImplColReplaceParam
*>(pColParam
)->pDstCols
[ i
];
1787 BitmapEx
GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1789 const ImplBmpReplaceParam
* p
= static_cast<const ImplBmpReplaceParam
*>(pBmpParam
);
1790 BitmapEx
aRet( rBmpEx
);
1792 aRet
.Replace( p
->pSrcCols
, p
->pDstCols
, p
->nCount
);
1797 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol
, const void* pColParam
,
1798 BmpExchangeFnc pFncBmp
, const void* pBmpParam
)
1802 aMtf
.m_aPrefSize
= m_aPrefSize
;
1803 aMtf
.m_aPrefMapMode
= m_aPrefMapMode
;
1804 aMtf
.m_bUseCanvas
= m_bUseCanvas
;
1806 for( MetaAction
* pAction
= FirstAction(); pAction
; pAction
= NextAction() )
1808 const MetaActionType nType
= pAction
->GetType();
1812 case MetaActionType::PIXEL
:
1814 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
1815 aMtf
.push_back( new MetaPixelAction( pAct
->GetPoint(), pFncCol( pAct
->GetColor(), pColParam
) ) );
1819 case MetaActionType::LINECOLOR
:
1821 MetaLineColorAction
* pAct
= static_cast<MetaLineColorAction
*>(pAction
);
1823 if( pAct
->IsSetting() )
1824 pAct
= new MetaLineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1826 aMtf
.push_back( pAct
);
1830 case MetaActionType::FILLCOLOR
:
1832 MetaFillColorAction
* pAct
= static_cast<MetaFillColorAction
*>(pAction
);
1834 if( pAct
->IsSetting() )
1835 pAct
= new MetaFillColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1837 aMtf
.push_back( pAct
);
1841 case MetaActionType::TEXTCOLOR
:
1843 MetaTextColorAction
* pAct
= static_cast<MetaTextColorAction
*>(pAction
);
1844 aMtf
.push_back( new MetaTextColorAction( pFncCol( pAct
->GetColor(), pColParam
) ) );
1848 case MetaActionType::TEXTFILLCOLOR
:
1850 MetaTextFillColorAction
* pAct
= static_cast<MetaTextFillColorAction
*>(pAction
);
1852 if( pAct
->IsSetting() )
1853 pAct
= new MetaTextFillColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1855 aMtf
.push_back( pAct
);
1859 case MetaActionType::TEXTLINECOLOR
:
1861 MetaTextLineColorAction
* pAct
= static_cast<MetaTextLineColorAction
*>(pAction
);
1863 if( pAct
->IsSetting() )
1864 pAct
= new MetaTextLineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1866 aMtf
.push_back( pAct
);
1870 case MetaActionType::OVERLINECOLOR
:
1872 MetaOverlineColorAction
* pAct
= static_cast<MetaOverlineColorAction
*>(pAction
);
1874 if( pAct
->IsSetting() )
1875 pAct
= new MetaOverlineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1877 aMtf
.push_back( pAct
);
1881 case MetaActionType::FONT
:
1883 MetaFontAction
* pAct
= static_cast<MetaFontAction
*>(pAction
);
1884 vcl::Font
aFont( pAct
->GetFont() );
1886 aFont
.SetColor( pFncCol( aFont
.GetColor(), pColParam
) );
1887 aFont
.SetFillColor( pFncCol( aFont
.GetFillColor(), pColParam
) );
1888 aMtf
.push_back( new MetaFontAction( aFont
) );
1892 case MetaActionType::WALLPAPER
:
1894 MetaWallpaperAction
* pAct
= static_cast<MetaWallpaperAction
*>(pAction
);
1895 Wallpaper
aWall( pAct
->GetWallpaper() );
1896 const tools::Rectangle
& rRect
= pAct
->GetRect();
1898 aWall
.SetColor( pFncCol( aWall
.GetColor(), pColParam
) );
1900 if( aWall
.IsBitmap() )
1901 aWall
.SetBitmap( pFncBmp( aWall
.GetBitmap(), pBmpParam
) );
1903 if( aWall
.IsGradient() )
1905 Gradient
aGradient( aWall
.GetGradient() );
1907 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
1908 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
1909 aWall
.SetGradient( aGradient
);
1912 aMtf
.push_back( new MetaWallpaperAction( rRect
, aWall
) );
1916 case MetaActionType::BMP
:
1917 case MetaActionType::BMPEX
:
1918 case MetaActionType::MASK
:
1920 OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
1924 case MetaActionType::BMPSCALE
:
1926 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1927 aMtf
.push_back( new MetaBmpScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
1928 pFncBmp( BitmapEx(pAct
->GetBitmap()), pBmpParam
).GetBitmap() ) );
1932 case MetaActionType::BMPSCALEPART
:
1934 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1935 aMtf
.push_back( new MetaBmpScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
1936 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
1937 pFncBmp( BitmapEx(pAct
->GetBitmap()), pBmpParam
).GetBitmap() )
1942 case MetaActionType::BMPEXSCALE
:
1944 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1945 aMtf
.push_back( new MetaBmpExScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
1946 pFncBmp( pAct
->GetBitmapEx(), pBmpParam
) )
1951 case MetaActionType::BMPEXSCALEPART
:
1953 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1954 aMtf
.push_back( new MetaBmpExScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
1955 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
1956 pFncBmp( pAct
->GetBitmapEx(), pBmpParam
) )
1961 case MetaActionType::MASKSCALE
:
1963 MetaMaskScaleAction
* pAct
= static_cast<MetaMaskScaleAction
*>(pAction
);
1964 aMtf
.push_back( new MetaMaskScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
1966 pFncCol( pAct
->GetColor(), pColParam
) )
1971 case MetaActionType::MASKSCALEPART
:
1973 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1974 aMtf
.push_back( new MetaMaskScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
1975 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
1977 pFncCol( pAct
->GetColor(), pColParam
) )
1982 case MetaActionType::GRADIENT
:
1984 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1985 Gradient
aGradient( pAct
->GetGradient() );
1987 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
1988 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
1989 aMtf
.push_back( new MetaGradientAction( pAct
->GetRect(), aGradient
) );
1993 case MetaActionType::GRADIENTEX
:
1995 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1996 Gradient
aGradient( pAct
->GetGradient() );
1998 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
1999 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
2000 aMtf
.push_back( new MetaGradientExAction( pAct
->GetPolyPolygon(), aGradient
) );
2004 case MetaActionType::HATCH
:
2006 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
2007 Hatch
aHatch( pAct
->GetHatch() );
2009 aHatch
.SetColor( pFncCol( aHatch
.GetColor(), pColParam
) );
2010 aMtf
.push_back( new MetaHatchAction( pAct
->GetPolyPolygon(), aHatch
) );
2014 case MetaActionType::FLOATTRANSPARENT
:
2016 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
2017 GDIMetaFile
aTransMtf( pAct
->GetGDIMetaFile() );
2019 aTransMtf
.ImplExchangeColors( pFncCol
, pColParam
, pFncBmp
, pBmpParam
);
2020 aMtf
.push_back( new MetaFloatTransparentAction( aTransMtf
,
2021 pAct
->GetPoint(), pAct
->GetSize(),
2022 pAct
->GetGradient() )
2027 case MetaActionType::EPS
:
2029 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
2030 GDIMetaFile
aSubst( pAct
->GetSubstitute() );
2032 aSubst
.ImplExchangeColors( pFncCol
, pColParam
, pFncBmp
, pBmpParam
);
2033 aMtf
.push_back( new MetaEPSAction( pAct
->GetPoint(), pAct
->GetSize(),
2034 pAct
->GetLink(), aSubst
)
2041 aMtf
.push_back( pAction
);
2050 void GDIMetaFile::Adjust( short nLuminancePercent
, short nContrastPercent
,
2051 short nChannelRPercent
, short nChannelGPercent
,
2052 short nChannelBPercent
, double fGamma
, bool bInvert
, bool msoBrightness
)
2054 // nothing to do? => return quickly
2055 if( !(nLuminancePercent
|| nContrastPercent
||
2056 nChannelRPercent
|| nChannelGPercent
|| nChannelBPercent
||
2057 ( fGamma
!= 1.0 ) || bInvert
) )
2060 double fM
, fROff
, fGOff
, fBOff
, fOff
;
2061 ImplColAdjustParam aColParam
;
2062 ImplBmpAdjustParam aBmpParam
;
2064 aColParam
.pMapR
.reset(new sal_uInt8
[ 256 ]);
2065 aColParam
.pMapG
.reset(new sal_uInt8
[ 256 ]);
2066 aColParam
.pMapB
.reset(new sal_uInt8
[ 256 ]);
2069 if( nContrastPercent
>= 0 )
2070 fM
= 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent
, 0, 100 ) );
2072 fM
= ( 128.0 + 1.27 * MinMax( nContrastPercent
, -100, 0 ) ) / 128.0;
2075 // total offset = luminance offset + contrast offset
2076 fOff
= MinMax( nLuminancePercent
, -100, 100 ) * 2.55 + 128.0 - fM
* 128.0;
2078 fOff
= MinMax( nLuminancePercent
, -100, 100 ) * 2.55;
2080 // channel offset = channel offset + total offset
2081 fROff
= nChannelRPercent
* 2.55 + fOff
;
2082 fGOff
= nChannelGPercent
* 2.55 + fOff
;
2083 fBOff
= nChannelBPercent
* 2.55 + fOff
;
2085 // calculate gamma value
2086 fGamma
= ( fGamma
<= 0.0 || fGamma
> 10.0 ) ? 1.0 : ( 1.0 / fGamma
);
2087 const bool bGamma
= ( fGamma
!= 1.0 );
2089 // create mapping table
2090 for( long nX
= 0; nX
< 256; nX
++ )
2094 aColParam
.pMapR
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( nX
* fM
+ fROff
), 0, 255 ));
2095 aColParam
.pMapG
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( nX
* fM
+ fGOff
), 0, 255 ));
2096 aColParam
.pMapB
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( nX
* fM
+ fBOff
), 0, 255 ));
2100 aColParam
.pMapR
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( (nX
+fROff
/2-128) * fM
+ 128 + fROff
/2 ), 0, 255 ));
2101 aColParam
.pMapG
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( (nX
+fGOff
/2-128) * fM
+ 128 + fGOff
/2 ), 0, 255 ));
2102 aColParam
.pMapB
[ nX
] = static_cast<sal_uInt8
>(MinMax( FRound( (nX
+fBOff
/2-128) * fM
+ 128 + fBOff
/2 ), 0, 255 ));
2106 aColParam
.pMapR
[ nX
] = GAMMA( aColParam
.pMapR
[ nX
], fGamma
);
2107 aColParam
.pMapG
[ nX
] = GAMMA( aColParam
.pMapG
[ nX
], fGamma
);
2108 aColParam
.pMapB
[ nX
] = GAMMA( aColParam
.pMapB
[ nX
], fGamma
);
2113 aColParam
.pMapR
[ nX
] = ~aColParam
.pMapR
[ nX
];
2114 aColParam
.pMapG
[ nX
] = ~aColParam
.pMapG
[ nX
];
2115 aColParam
.pMapB
[ nX
] = ~aColParam
.pMapB
[ nX
];
2119 aBmpParam
.nLuminancePercent
= nLuminancePercent
;
2120 aBmpParam
.nContrastPercent
= nContrastPercent
;
2121 aBmpParam
.nChannelRPercent
= nChannelRPercent
;
2122 aBmpParam
.nChannelGPercent
= nChannelGPercent
;
2123 aBmpParam
.nChannelBPercent
= nChannelBPercent
;
2124 aBmpParam
.fGamma
= fGamma
;
2125 aBmpParam
.bInvert
= bInvert
;
2127 // do color adjustment
2128 ImplExchangeColors( ImplColAdjustFnc
, &aColParam
, ImplBmpAdjustFnc
, &aBmpParam
);
2131 void GDIMetaFile::Convert( MtfConversion eConversion
)
2133 ImplColConvertParam aColParam
;
2134 ImplBmpConvertParam aBmpParam
;
2136 aColParam
.eConversion
= eConversion
;
2137 aBmpParam
.eConversion
= ( MtfConversion::N1BitThreshold
== eConversion
) ? BmpConversion::N1BitThreshold
: BmpConversion::N8BitGreys
;
2139 ImplExchangeColors( ImplColConvertFnc
, &aColParam
, ImplBmpConvertFnc
, &aBmpParam
);
2142 void GDIMetaFile::ReplaceColors( const Color
* pSearchColors
, const Color
* pReplaceColors
, sal_uLong nColorCount
)
2144 ImplColReplaceParam aColParam
;
2145 ImplBmpReplaceParam aBmpParam
;
2147 aColParam
.pMinR
.reset(new sal_uLong
[ nColorCount
]);
2148 aColParam
.pMaxR
.reset(new sal_uLong
[ nColorCount
]);
2149 aColParam
.pMinG
.reset(new sal_uLong
[ nColorCount
]);
2150 aColParam
.pMaxG
.reset(new sal_uLong
[ nColorCount
]);
2151 aColParam
.pMinB
.reset(new sal_uLong
[ nColorCount
]);
2152 aColParam
.pMaxB
.reset(new sal_uLong
[ nColorCount
]);
2154 for( sal_uLong i
= 0; i
< nColorCount
; i
++ )
2158 nVal
= pSearchColors
[ i
].GetRed();
2159 aColParam
.pMinR
[ i
] = static_cast<sal_uLong
>(std::max( nVal
, 0L ));
2160 aColParam
.pMaxR
[ i
] = static_cast<sal_uLong
>(std::min( nVal
, 255L ));
2162 nVal
= pSearchColors
[ i
].GetGreen();
2163 aColParam
.pMinG
[ i
] = static_cast<sal_uLong
>(std::max( nVal
, 0L ));
2164 aColParam
.pMaxG
[ i
] = static_cast<sal_uLong
>(std::min( nVal
, 255L ));
2166 nVal
= pSearchColors
[ i
].GetBlue();
2167 aColParam
.pMinB
[ i
] = static_cast<sal_uLong
>(std::max( nVal
, 0L ));
2168 aColParam
.pMaxB
[ i
] = static_cast<sal_uLong
>(std::min( nVal
, 255L ));
2171 aColParam
.pDstCols
= pReplaceColors
;
2172 aColParam
.nCount
= nColorCount
;
2174 aBmpParam
.pSrcCols
= pSearchColors
;
2175 aBmpParam
.pDstCols
= pReplaceColors
;
2176 aBmpParam
.nCount
= nColorCount
;
2178 ImplExchangeColors( ImplColReplaceFnc
, &aColParam
, ImplBmpReplaceFnc
, &aBmpParam
);
2181 GDIMetaFile
GDIMetaFile::GetMonochromeMtf( const Color
& rColor
) const
2183 GDIMetaFile
aRet( *this );
2185 ImplColMonoParam aColParam
;
2186 ImplBmpMonoParam aBmpParam
;
2188 aColParam
.aColor
= rColor
;
2189 aBmpParam
.aColor
= rColor
;
2191 aRet
.ImplExchangeColors( ImplColMonoFnc
, &aColParam
, ImplBmpMonoFnc
, &aBmpParam
);
2196 BitmapChecksum
GDIMetaFile::GetChecksum() const
2199 SvMemoryStream
aMemStm( 65535, 65535 );
2200 ImplMetaWriteData aWriteData
;
2203 BitmapChecksumOctetArray aBCOA
;
2204 BitmapChecksum nCrc
= 0;
2206 aWriteData
.meActualCharSet
= aMemStm
.GetStreamCharSet();
2207 for( size_t i
= 0, nObjCount
= GetActionSize(); i
< nObjCount
; i
++ )
2209 MetaAction
* pAction
= GetAction( i
);
2211 switch( pAction
->GetType() )
2213 case MetaActionType::BMP
:
2215 MetaBmpAction
* pAct
= static_cast<MetaBmpAction
*>(pAction
);
2217 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2218 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2220 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2221 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2223 Int32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2224 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2226 Int32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2227 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2231 case MetaActionType::BMPSCALE
:
2233 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(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 );
2247 Int32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2248 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2250 Int32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2251 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2255 case MetaActionType::BMPSCALEPART
:
2257 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
2259 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2260 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2262 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2263 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2265 Int32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2266 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2268 Int32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2269 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2271 Int32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2272 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2274 Int32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2275 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2277 Int32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2278 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2280 Int32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2281 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2283 Int32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2284 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2286 Int32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2287 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2291 case MetaActionType::BMPEX
:
2293 MetaBmpExAction
* pAct
= static_cast<MetaBmpExAction
*>(pAction
);
2295 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2296 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2298 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2299 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2301 Int32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2302 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2304 Int32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2305 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2309 case MetaActionType::BMPEXSCALE
:
2311 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(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 );
2325 Int32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2326 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2328 Int32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2329 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2333 case MetaActionType::BMPEXSCALEPART
:
2335 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
2337 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2338 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2340 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2341 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2343 Int32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2344 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2346 Int32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2347 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2349 Int32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2350 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2352 Int32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2353 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2355 Int32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2356 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2358 Int32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2359 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2361 Int32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2362 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2364 Int32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2365 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2369 case MetaActionType::MASK
:
2371 MetaMaskAction
* pAct
= static_cast<MetaMaskAction
*>(pAction
);
2373 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2374 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2376 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2377 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2379 UInt32ToSVBT32( sal_uInt32(pAct
->GetColor()), aBT32
);
2380 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2382 Int32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2383 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2385 Int32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2386 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2390 case MetaActionType::MASKSCALE
:
2392 MetaMaskScaleAction
* pAct
= static_cast<MetaMaskScaleAction
*>(pAction
);
2394 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2395 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2397 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2398 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2400 UInt32ToSVBT32( sal_uInt32(pAct
->GetColor()), aBT32
);
2401 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2403 Int32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2404 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2406 Int32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2407 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2409 Int32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2410 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2412 Int32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2413 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2417 case MetaActionType::MASKSCALEPART
:
2419 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
2421 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2422 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2424 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2425 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2427 UInt32ToSVBT32( sal_uInt32(pAct
->GetColor()), aBT32
);
2428 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2430 Int32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2431 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2433 Int32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2434 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2436 Int32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2437 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2439 Int32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2440 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2442 Int32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2443 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2445 Int32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2446 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2448 Int32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2449 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2451 Int32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2452 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2456 case MetaActionType::EPS
:
2458 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
2459 nCrc
= vcl_get_checksum( nCrc
, pAct
->GetLink().GetData(), pAct
->GetLink().GetDataSize() );
2463 case MetaActionType::CLIPREGION
:
2465 MetaClipRegionAction
& rAct
= static_cast<MetaClipRegionAction
&>(*pAction
);
2466 const vcl::Region
& rRegion
= rAct
.GetRegion();
2468 if(rRegion
.HasPolyPolygonOrB2DPolyPolygon())
2470 // It has shown that this is a possible bottleneck for checksum calculation.
2471 // In worst case a very expensive RegionHandle representation gets created.
2472 // In this case it's cheaper to use the PolyPolygon
2473 const basegfx::B2DPolyPolygon
aPolyPolygon(rRegion
.GetAsB2DPolyPolygon());
2476 for(auto const& rPolygon
: aPolyPolygon
)
2478 const sal_uInt32
nPointCount(rPolygon
.count());
2479 const bool bControl(rPolygon
.areControlPointsUsed());
2481 for(sal_uInt32
b(0); b
< nPointCount
; b
++)
2483 const basegfx::B2DPoint
aPoint(rPolygon
.getB2DPoint(b
));
2485 DoubleToSVBT64(aPoint
.getX(), aSVBT64
);
2486 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2487 DoubleToSVBT64(aPoint
.getY(), aSVBT64
);
2488 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2492 if(rPolygon
.isPrevControlPointUsed(b
))
2494 const basegfx::B2DPoint
aCtrl(rPolygon
.getPrevControlPoint(b
));
2496 DoubleToSVBT64(aCtrl
.getX(), aSVBT64
);
2497 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2498 DoubleToSVBT64(aCtrl
.getY(), aSVBT64
);
2499 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2502 if(rPolygon
.isNextControlPointUsed(b
))
2504 const basegfx::B2DPoint
aCtrl(rPolygon
.getNextControlPoint(b
));
2506 DoubleToSVBT64(aCtrl
.getX(), aSVBT64
);
2507 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2508 DoubleToSVBT64(aCtrl
.getY(), aSVBT64
);
2509 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2515 sal_uInt8 tmp
= static_cast<sal_uInt8
>(rAct
.IsClipping());
2516 nCrc
= vcl_get_checksum(nCrc
, &tmp
, 1);
2520 pAction
->Write( aMemStm
, &aWriteData
);
2521 nCrc
= vcl_get_checksum( nCrc
, aMemStm
.GetData(), aMemStm
.Tell() );
2529 pAction
->Write( aMemStm
, &aWriteData
);
2530 nCrc
= vcl_get_checksum( nCrc
, aMemStm
.GetData(), aMemStm
.Tell() );
2540 sal_uLong
GDIMetaFile::GetSizeBytes() const
2542 sal_uLong nSizeBytes
= 0;
2544 for( size_t i
= 0, nObjCount
= GetActionSize(); i
< nObjCount
; ++i
)
2546 MetaAction
* pAction
= GetAction( i
);
2548 // default action size is set to 32 (=> not the exact value)
2551 // add sizes for large action content
2552 switch( pAction
->GetType() )
2554 case MetaActionType::BMP
: nSizeBytes
+= static_cast<MetaBmpAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2555 case MetaActionType::BMPSCALE
: nSizeBytes
+= static_cast<MetaBmpScaleAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2556 case MetaActionType::BMPSCALEPART
: nSizeBytes
+= static_cast<MetaBmpScalePartAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2558 case MetaActionType::BMPEX
: nSizeBytes
+= static_cast<MetaBmpExAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2559 case MetaActionType::BMPEXSCALE
: nSizeBytes
+= static_cast<MetaBmpExScaleAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2560 case MetaActionType::BMPEXSCALEPART
: nSizeBytes
+= static_cast<MetaBmpExScalePartAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2562 case MetaActionType::MASK
: nSizeBytes
+= static_cast<MetaMaskAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2563 case MetaActionType::MASKSCALE
: nSizeBytes
+= static_cast<MetaMaskScaleAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2564 case MetaActionType::MASKSCALEPART
: nSizeBytes
+= static_cast<MetaMaskScalePartAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2566 case MetaActionType::POLYLINE
: nSizeBytes
+= static_cast<MetaPolyLineAction
*>( pAction
)->GetPolygon().GetSize() * sizeof( Point
); break;
2567 case MetaActionType::POLYGON
: nSizeBytes
+= static_cast<MetaPolygonAction
*>( pAction
)->GetPolygon().GetSize() * sizeof( Point
); break;
2568 case MetaActionType::POLYPOLYGON
:
2570 const tools::PolyPolygon
& rPolyPoly
= static_cast<MetaPolyPolygonAction
*>( pAction
)->GetPolyPolygon();
2572 for( sal_uInt16 n
= 0; n
< rPolyPoly
.Count(); ++n
)
2573 nSizeBytes
+= ( rPolyPoly
[ n
].GetSize() * sizeof( Point
) );
2577 case MetaActionType::TEXT
: nSizeBytes
+= static_cast<MetaTextAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2578 case MetaActionType::STRETCHTEXT
: nSizeBytes
+= static_cast<MetaStretchTextAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2579 case MetaActionType::TEXTRECT
: nSizeBytes
+= static_cast<MetaTextRectAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2580 case MetaActionType::TEXTARRAY
:
2582 MetaTextArrayAction
* pTextArrayAction
= static_cast<MetaTextArrayAction
*>(pAction
);
2584 nSizeBytes
+= ( pTextArrayAction
->GetText().getLength() * sizeof( sal_Unicode
) );
2586 if( pTextArrayAction
->GetDXArray() )
2587 nSizeBytes
+= ( pTextArrayAction
->GetLen() << 2 );
2602 ImplMetaReadData
& m_rData
;
2603 rtl_TextEncoding
const m_eOrigCharSet
;
2605 DepthGuard(ImplMetaReadData
& rData
, SvStream
const & rIStm
)
2607 , m_eOrigCharSet(m_rData
.meActualCharSet
)
2609 ++m_rData
.mnParseDepth
;
2610 m_rData
.meActualCharSet
= rIStm
.GetStreamCharSet();
2612 bool TooDeep() const { return m_rData
.mnParseDepth
> 1024; }
2615 --m_rData
.mnParseDepth
;
2616 m_rData
.meActualCharSet
= m_eOrigCharSet
;
2621 SvStream
& ReadGDIMetaFile(SvStream
& rIStm
, GDIMetaFile
& rGDIMetaFile
, ImplMetaReadData
* pData
)
2623 if (rIStm
.GetError())
2625 SAL_WARN("vcl.gdi", "Stream error: " << rIStm
.GetError());
2629 sal_uLong nStmPos
= rIStm
.Tell();
2630 SvStreamEndian nOldFormat
= rIStm
.GetEndian();
2632 rIStm
.SetEndian( SvStreamEndian::LITTLE
);
2639 rIStm
.ReadBytes( aId
, 6 );
2641 if ( !strcmp( aId
, "VCLMTF" ) )
2644 sal_uInt32 nStmCompressMode
= 0;
2645 sal_uInt32 nCount
= 0;
2646 std::unique_ptr
<VersionCompat
> pCompat(new VersionCompat( rIStm
, StreamMode::READ
));
2648 rIStm
.ReadUInt32( nStmCompressMode
);
2649 ReadMapMode( rIStm
, rGDIMetaFile
.m_aPrefMapMode
);
2650 TypeSerializer
aSerializer(rIStm
);
2651 aSerializer
.readSize(rGDIMetaFile
.m_aPrefSize
);
2652 rIStm
.ReadUInt32( nCount
);
2654 pCompat
.reset(); // destructor writes stuff into the header
2656 std::unique_ptr
<ImplMetaReadData
> xReadData
;
2659 xReadData
.reset(new ImplMetaReadData
);
2660 pData
= xReadData
.get();
2662 DepthGuard
aDepthGuard(*pData
, rIStm
);
2664 if (aDepthGuard
.TooDeep())
2665 throw std::runtime_error("too much recursion");
2667 for( sal_uInt32 nAction
= 0; ( nAction
< nCount
) && !rIStm
.eof(); nAction
++ )
2669 MetaAction
* pAction
= MetaAction::ReadMetaAction(rIStm
, pData
);
2672 if (pAction
->GetType() == MetaActionType::COMMENT
)
2674 MetaCommentAction
* pCommentAct
= static_cast<MetaCommentAction
*>(pAction
);
2675 if ( pCommentAct
->GetComment() == "EMF_PLUS" )
2676 rGDIMetaFile
.UseCanvas( true );
2678 rGDIMetaFile
.AddAction( pAction
);
2684 rIStm
.Seek( nStmPos
);
2685 SVMConverter( rIStm
, rGDIMetaFile
);
2690 SAL_WARN("vcl", "GDIMetaFile exception during load");
2691 rIStm
.SetError(SVSTREAM_FILEFORMAT_ERROR
);
2695 if( rIStm
.GetError() )
2697 rGDIMetaFile
.Clear();
2698 rIStm
.Seek( nStmPos
);
2701 rIStm
.SetEndian( nOldFormat
);
2705 SvStream
& WriteGDIMetaFile( SvStream
& rOStm
, const GDIMetaFile
& rGDIMetaFile
)
2707 if( !rOStm
.GetError() )
2709 const_cast< GDIMetaFile
& >( rGDIMetaFile
).Write( rOStm
);
2714 SvStream
& GDIMetaFile::Read( SvStream
& rIStm
)
2717 ReadGDIMetaFile( rIStm
, *this );
2722 SvStream
& GDIMetaFile::Write( SvStream
& rOStm
)
2724 VersionCompat
* pCompat
;
2725 const SvStreamCompressFlags nStmCompressMode
= rOStm
.GetCompressMode();
2726 SvStreamEndian nOldFormat
= rOStm
.GetEndian();
2728 rOStm
.SetEndian( SvStreamEndian::LITTLE
);
2729 rOStm
.WriteBytes( "VCLMTF", 6 );
2731 pCompat
= new VersionCompat( rOStm
, StreamMode::WRITE
, 1 );
2733 rOStm
.WriteUInt32( static_cast<sal_uInt32
>(nStmCompressMode
) );
2734 WriteMapMode( rOStm
, m_aPrefMapMode
);
2735 TypeSerializer
aSerializer(rOStm
);
2736 aSerializer
.writeSize(m_aPrefSize
);
2737 rOStm
.WriteUInt32( GetActionSize() );
2741 ImplMetaWriteData aWriteData
;
2743 aWriteData
.meActualCharSet
= rOStm
.GetStreamCharSet();
2745 MetaAction
* pAct
= FirstAction();
2748 pAct
->Write( rOStm
, &aWriteData
);
2749 pAct
= NextAction();
2752 rOStm
.SetEndian( nOldFormat
);
2757 bool GDIMetaFile::CreateThumbnail(BitmapEx
& rBitmapEx
, BmpConversion eColorConversion
, BmpScaleFlag nScaleFlag
) const
2759 // initialization seems to be complicated but is used to avoid rounding errors
2760 ScopedVclPtrInstance
< VirtualDevice
> aVDev
;
2761 const Point aNullPt
;
2762 const Point
aTLPix( aVDev
->LogicToPixel( aNullPt
, GetPrefMapMode() ) );
2763 const Point
aBRPix( aVDev
->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2764 Size
aDrawSize( aVDev
->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2765 Size
aSizePix( labs( aBRPix
.X() - aTLPix
.X() ) + 1, labs( aBRPix
.Y() - aTLPix
.Y() ) + 1 );
2766 sal_uInt32 nMaximumExtent
= 256;
2768 if (!rBitmapEx
.IsEmpty())
2769 rBitmapEx
.SetEmpty();
2771 // determine size that has the same aspect ratio as image size and
2772 // fits into the rectangle determined by nMaximumExtent
2773 if ( aSizePix
.Width() && aSizePix
.Height()
2774 && ( sal::static_int_cast
< unsigned long >(aSizePix
.Width()) >
2776 sal::static_int_cast
< unsigned long >(aSizePix
.Height()) >
2779 const Size
aOldSizePix( aSizePix
);
2780 double fWH
= static_cast< double >( aSizePix
.Width() ) / aSizePix
.Height();
2784 aSizePix
.setWidth( FRound( nMaximumExtent
* fWH
) );
2785 aSizePix
.setHeight( nMaximumExtent
);
2789 aSizePix
.setWidth( nMaximumExtent
);
2790 aSizePix
.setHeight( FRound( nMaximumExtent
/ fWH
) );
2793 aDrawSize
.setWidth( FRound( ( static_cast< double >( aDrawSize
.Width() ) * aSizePix
.Width() ) / aOldSizePix
.Width() ) );
2794 aDrawSize
.setHeight( FRound( ( static_cast< double >( aDrawSize
.Height() ) * aSizePix
.Height() ) / aOldSizePix
.Height() ) );
2797 // draw image(s) into VDev and get resulting image
2798 // do it 4x larger to be able to scale it down & get beautiful antialias
2799 Size
aAntialiasSize(aSizePix
.Width() * 4, aSizePix
.Height() * 4);
2800 if (aVDev
->SetOutputSizePixel(aAntialiasSize
))
2802 // antialias: provide 4x larger size, and then scale down the result
2803 Size
aAntialias(aDrawSize
.Width() * 4, aDrawSize
.Height() * 4);
2805 // draw metafile into VDev
2806 const_cast<GDIMetaFile
*>(this)->WindStart();
2807 const_cast<GDIMetaFile
*>(this)->Play(aVDev
.get(), Point(), aAntialias
);
2810 BitmapEx
aBitmap( aVDev
->GetBitmapEx( aNullPt
, aVDev
->GetOutputSizePixel() ) );
2812 // scale down the image to the desired size - use the input scaler for the scaling operation
2813 aBitmap
.Scale(aDrawSize
, nScaleFlag
);
2815 // convert to desired bitmap color format
2816 Size
aSize(aBitmap
.GetSizePixel());
2817 if (aSize
.Width() && aSize
.Height())
2818 aBitmap
.Convert(eColorConversion
);
2820 rBitmapEx
= aBitmap
;
2823 return !rBitmapEx
.IsEmpty();
2826 void GDIMetaFile::UseCanvas( bool _bUseCanvas
)
2828 m_bUseCanvas
= _bUseCanvas
;
2831 void GDIMetaFile::dumpAsXml(const char* pFileName
) const
2833 SvFileStream
aStream(pFileName
? OUString::fromUtf8(pFileName
) : OUString("file:///tmp/metafile.xml"),
2834 StreamMode::STD_READWRITE
| StreamMode::TRUNC
);
2835 assert(aStream
.good());
2836 MetafileXmlDump aDumper
;
2837 aDumper
.dump(*this, aStream
);
2840 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */