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 .
21 #include <tools/stream.hxx>
22 #include <tools/vcompat.hxx>
23 #include <tools/fract.hxx>
24 #include <vcl/metaact.hxx>
25 #include <vcl/salbtype.hxx>
26 #include <vcl/outdev.hxx>
27 #include <vcl/window.hxx>
28 #include <vcl/virdev.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/gdimtf.hxx>
31 #include <vcl/graphictools.hxx>
32 #include <basegfx/polygon/b2dpolygon.hxx>
33 #include <vcl/canvastools.hxx>
37 #include <salinst.hxx>
40 #include <com/sun/star/beans/XFastPropertySet.hpp>
41 #include <com/sun/star/rendering/MtfRenderer.hpp>
42 #include <com/sun/star/rendering/XBitmapCanvas.hpp>
43 #include <com/sun/star/rendering/XCanvas.hpp>
44 #include <comphelper/processfactory.hxx>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/lang/XInitialization.hpp>
47 #include <com/sun/star/awt/XGraphics.hpp>
48 #include <com/sun/star/graphic/XGraphic.hpp>
49 #include <com/sun/star/graphic/XGraphicRenderer.hpp>
51 using namespace com::sun::star
;
53 #define GAMMA( _def_cVal, _def_InvGamma ) ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
55 struct ImplColAdjustParam
62 struct ImplBmpAdjustParam
64 short nLuminancePercent
;
65 short nContrastPercent
;
66 short nChannelRPercent
;
67 short nChannelGPercent
;
68 short nChannelBPercent
;
73 struct ImplColConvertParam
75 MtfConversion eConversion
;
78 struct ImplBmpConvertParam
80 BmpConversion eConversion
;
83 struct ImplColMonoParam
88 struct ImplBmpMonoParam
93 struct ImplColReplaceParam
101 const Color
* pDstCols
;
105 struct ImplBmpReplaceParam
107 const Color
* pSrcCols
;
108 const Color
* pDstCols
;
110 const sal_uLong
* pTols
;
113 GDIMetaFile::GDIMetaFile() :
114 nCurrentActionElement( 0 ),
125 GDIMetaFile::GDIMetaFile( const GDIMetaFile
& rMtf
) :
126 nCurrentActionElement( rMtf
.nCurrentActionElement
),
127 aPrefMapMode ( rMtf
.aPrefMapMode
),
128 aPrefSize ( rMtf
.aPrefSize
),
129 aHookHdlLink ( rMtf
.aHookHdlLink
),
130 pPrev ( rMtf
.pPrev
),
131 pNext ( rMtf
.pNext
),
135 bUseCanvas ( rMtf
.bUseCanvas
)
137 // Increment RefCount of MetaActions
138 for( size_t i
= 0, n
= rMtf
.GetActionSize(); i
< n
; ++i
)
140 rMtf
.GetAction( i
)->Duplicate();
141 aList
.push_back( rMtf
.GetAction( i
) );
146 Record( rMtf
.pOutDev
);
153 GDIMetaFile::~GDIMetaFile()
158 size_t GDIMetaFile::GetActionSize() const
163 MetaAction
* GDIMetaFile::GetAction( size_t nAction
) const
165 return (nAction
< aList
.size()) ? aList
[ nAction
] : NULL
;
168 MetaAction
* GDIMetaFile::FirstAction()
170 nCurrentActionElement
= 0;
171 return aList
.empty() ? NULL
: aList
[ 0 ];
174 MetaAction
* GDIMetaFile::NextAction()
176 return ( nCurrentActionElement
+ 1 < aList
.size() ) ? aList
[ ++nCurrentActionElement
] : NULL
;
179 MetaAction
* GDIMetaFile::ReplaceAction( MetaAction
* pAction
, size_t nAction
)
181 if ( nAction
>= aList
.size() )
183 // this method takes ownership of pAction and is
184 // therefore responsible for deleting it
188 //fdo#39995 This does't increment the incoming action ref-count nor does it
189 //decrement the outgoing action ref-count
190 std::swap(pAction
, aList
[nAction
]);
194 GDIMetaFile
& GDIMetaFile::operator=( const GDIMetaFile
& rMtf
)
200 // Increment RefCount of MetaActions
201 for( size_t i
= 0, n
= rMtf
.GetActionSize(); i
< n
; ++i
)
203 rMtf
.GetAction( i
)->Duplicate();
204 aList
.push_back( rMtf
.GetAction( i
) );
207 aPrefMapMode
= rMtf
.aPrefMapMode
;
208 aPrefSize
= rMtf
.aPrefSize
;
209 aHookHdlLink
= rMtf
.aHookHdlLink
;
215 bUseCanvas
= rMtf
.bUseCanvas
;
219 Record( rMtf
.pOutDev
);
229 bool GDIMetaFile::operator==( const GDIMetaFile
& rMtf
) const
231 const size_t nObjCount
= aList
.size();
236 else if( rMtf
.GetActionSize() == nObjCount
&&
237 rMtf
.GetPrefSize() == aPrefSize
&&
238 rMtf
.GetPrefMapMode() == aPrefMapMode
)
242 for( size_t n
= 0; n
< nObjCount
; n
++ )
244 if( aList
[ n
] != rMtf
.GetAction( n
) )
255 void GDIMetaFile::Clear()
260 for( size_t i
= 0, n
= aList
.size(); i
< n
; ++i
)
261 aList
[ i
]->Delete();
265 void GDIMetaFile::Linker( OutputDevice
* pOut
, bool bLink
)
270 pPrev
= pOut
->GetConnectMetaFile();
271 pOut
->SetConnectMetaFile( this );
280 pNext
->pPrev
= pPrev
;
283 pPrev
->pNext
= pNext
;
290 pOut
->SetConnectMetaFile( pPrev
);
298 long GDIMetaFile::Hook()
300 return aHookHdlLink
.Call( this );
303 void GDIMetaFile::Record( OutputDevice
* pOut
)
308 nCurrentActionElement
= aList
.empty() ? 0 : (aList
.size() - 1);
311 Linker( pOut
, true );
314 void GDIMetaFile::Play( GDIMetaFile
& rMtf
, size_t nPos
)
316 if ( !bRecord
&& !rMtf
.bRecord
)
318 MetaAction
* pAction
= GetCurAction();
319 const size_t nObjCount
= aList
.size();
321 rMtf
.UseCanvas( rMtf
.GetUseCanvas() || bUseCanvas
);
323 if( nPos
> nObjCount
)
326 for( size_t nCurPos
= nCurrentActionElement
; nCurPos
< nPos
; nCurPos
++ )
328 if( !Hook() && pAction
)
330 pAction
->Duplicate();
331 rMtf
.AddAction( pAction
);
334 pAction
= NextAction();
339 void GDIMetaFile::Play( OutputDevice
* pOut
, size_t nPos
)
343 MetaAction
* pAction
= GetCurAction();
344 const size_t nObjCount
= aList
.size();
345 size_t nSyncCount
= ( pOut
->GetOutDevType() == OUTDEV_WINDOW
) ? 0x000000ff : 0xffffffff;
347 if( nPos
> nObjCount
)
350 // #i23407# Set backwards-compatible text language and layout mode
351 // This is necessary, since old metafiles don't even know of these
352 // recent add-ons. Newer metafiles must of course explicitly set
354 pOut
->Push( PushFlags::TEXTLAYOUTMODE
|PushFlags::TEXTLANGUAGE
);
355 pOut
->SetLayoutMode( TEXT_LAYOUT_DEFAULT
);
356 pOut
->SetDigitLanguage( 0 );
358 OSL_TRACE("GDIMetaFile::Play on device of size: %ld x %ld", pOut
->GetOutputSizePixel().Width(), pOut
->GetOutputSizePixel().Height());
360 if( !ImplPlayWithRenderer( pOut
, Point(0,0), pOut
->GetOutputSize() ) ) {
362 for( size_t nCurPos
= nCurrentActionElement
; nCurPos
< nPos
; nCurPos
++ )
364 if( !Hook() && pAction
)
366 if( pAction
->GetType() == MetaActionType::COMMENT
&&
367 static_cast<MetaCommentAction
*>(pAction
)->GetComment() == "DELEGATE_PLUGGABLE_RENDERER" )
369 ImplDelegate2PluggableRenderer(static_cast<MetaCommentAction
*>(pAction
), pOut
);
373 pAction
->Execute( pOut
);
376 // flush output from time to time
377 if( i
++ > nSyncCount
)
379 static_cast<vcl::Window
*>( pOut
)->Flush();
384 pAction
= NextAction();
391 bool GDIMetaFile::ImplPlayWithRenderer( OutputDevice
* pOut
, const Point
& rPos
, Size rLogicDestSize
)
396 Size
rDestSize( pOut
->LogicToPixel( rLogicDestSize
) );
398 const vcl::Window
* win
= dynamic_cast <vcl::Window
*> ( pOut
);
401 win
= Application::GetActiveTopWindow();
403 win
= Application::GetFirstTopLevelWindow();
410 uno::Reference
<rendering::XCanvas
> xCanvas
= win
->GetCanvas ();
415 Size
aSize (rDestSize
.Width () + 1, rDestSize
.Height () + 1);
416 uno::Reference
<rendering::XBitmap
> xBitmap
= xCanvas
->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize
));
419 uno::Reference
< rendering::XBitmapCanvas
> xBitmapCanvas( xBitmap
, uno::UNO_QUERY
);
420 if( xBitmapCanvas
.is() )
422 uno::Reference
< uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
423 uno::Reference
< rendering::XMtfRenderer
> xMtfRenderer
= rendering::MtfRenderer::createWithBitmapCanvas( xContext
, xBitmapCanvas
);
425 xBitmapCanvas
->clear();
426 uno::Reference
< beans::XFastPropertySet
> xMtfFastPropertySet( xMtfRenderer
, uno::UNO_QUERY
);
427 if( xMtfFastPropertySet
.is() )
428 // set this metafile to the renderer to
429 // speedup things (instead of copying data to
430 // sequence of bytes passed to renderer)
431 xMtfFastPropertySet
->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64
>( this ) ) );
433 xMtfRenderer
->draw( rDestSize
.Width(), rDestSize
.Height() );
436 if( aBitmapEx
.Create( xBitmapCanvas
, aSize
) )
438 if ( pOut
->GetMapMode() == MAP_PIXEL
)
439 pOut
->DrawBitmapEx( rPos
, aBitmapEx
);
441 pOut
->DrawBitmapEx( rPos
, rLogicDestSize
, aBitmapEx
);
447 catch (const uno::RuntimeException
& )
449 throw; // runtime errors are fatal
451 catch (const uno::Exception
& e
)
453 // ignore errors, no way of reporting them here
455 "GDIMetaFile::ImplPlayWithRenderer: exception: " << e
.Message
);
461 void GDIMetaFile::ImplDelegate2PluggableRenderer( const MetaCommentAction
* pAct
, OutputDevice
* pOut
)
463 OSL_ASSERT( pAct
->GetComment() == "DELEGATE_PLUGGABLE_RENDERER" );
465 // read payload - string of service name, followed by raw render input
466 const sal_uInt8
* pData
= pAct
->GetData();
467 const sal_uInt8
* const pEndData
= pData
+ pAct
->GetDataSize();
471 OUStringBuffer aBuffer
;
472 while( pData
<pEndData
&& *pData
)
473 aBuffer
.append(static_cast<sal_Unicode
>(*pData
++));
474 const OUString aRendererServiceName
=aBuffer
.makeStringAndClear();
477 while( pData
<pEndData
&& *pData
)
478 aBuffer
.append(static_cast<sal_Unicode
>(*pData
++));
479 const OUString aGraphicServiceName
=aBuffer
.makeStringAndClear();
482 uno::Reference
< lang::XMultiServiceFactory
> xFactory
= comphelper::getProcessServiceFactory();
487 // instantiate render service
488 uno::Sequence
<uno::Any
> aRendererArgs(1);
489 aRendererArgs
[0] = makeAny(uno::Reference
<awt::XGraphics
>(pOut
->CreateUnoGraphics()));
490 uno::Reference
<graphic::XGraphicRenderer
> xRenderer(
491 xFactory
->createInstanceWithArguments(
492 aRendererServiceName
,
496 // instantiate graphic service
497 uno::Reference
<graphic::XGraphic
> xGraphic(
498 xFactory
->createInstance(
499 aGraphicServiceName
),
502 uno::Reference
<lang::XInitialization
> xInit(
503 xGraphic
, uno::UNO_QUERY
);
505 if(xGraphic
.is() && xRenderer
.is() && xInit
.is())
507 // delay intialization of XGraphic, to only expose
508 // XGraphic-generating services to arbitrary binary data
509 uno::Sequence
< sal_Int8
> aSeq(
510 reinterpret_cast<sal_Int8
const *>(pData
), pEndData
-pData
);
511 uno::Sequence
<uno::Any
> aGraphicsArgs(1);
512 aGraphicsArgs
[0] = makeAny(aSeq
);
513 xInit
->initialize(aGraphicsArgs
);
515 xRenderer
->render(xGraphic
);
518 catch (const uno::RuntimeException
&)
520 // runtime errors are fatal
523 catch (const uno::Exception
& e
)
525 // ignore errors, no way of reporting them here
526 SAL_WARN("vcl", "GDIMetaFile::ImplDelegate2PluggableRenderer:"
527 " exception: " << e
.Message
);
532 void GDIMetaFile::Play( OutputDevice
* pOut
, const Point
& rPos
,
533 const Size
& rSize
, size_t nPos
)
535 vcl::Region aDrawClipRegion
;
536 MapMode
aDrawMap( GetPrefMapMode() );
537 Size
aDestSize( pOut
->LogicToPixel( rSize
) );
539 if( aDestSize
.Width() && aDestSize
.Height() )
541 GDIMetaFile
* pMtf
= pOut
->GetConnectMetaFile();
543 if( ImplPlayWithRenderer( pOut
, rPos
, rSize
) )
546 Size
aTmpPrefSize( pOut
->LogicToPixel( GetPrefSize(), aDrawMap
) );
548 if( !aTmpPrefSize
.Width() )
549 aTmpPrefSize
.Width() = aDestSize
.Width();
551 if( !aTmpPrefSize
.Height() )
552 aTmpPrefSize
.Height() = aDestSize
.Height();
554 Fraction
aScaleX( aDestSize
.Width(), aTmpPrefSize
.Width() );
555 Fraction
aScaleY( aDestSize
.Height(), aTmpPrefSize
.Height() );
557 aScaleX
*= aDrawMap
.GetScaleX(); aDrawMap
.SetScaleX( aScaleX
);
558 aScaleY
*= aDrawMap
.GetScaleY(); aDrawMap
.SetScaleY( aScaleY
);
560 // #i47260# Convert logical output position to offset within
561 // the metafile's mapmode. Therefore, disable pixel offset on
562 // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
563 // different mapmode (the one currently set on pOut, that is)
564 // - thus, aDrawMap's origin would generally be wrong. And
565 // even _if_ aDrawMap is similar to pOutDev's current mapmode,
566 // it's _still_ undesirable to have pixel offset unequal zero,
567 // because one would still get round-off errors (the
568 // round-trip error for LogicToPixel( PixelToLogic() ) was the
569 // reason for having pixel offset in the first place).
570 const Size
& rOldOffset( pOut
->GetPixelOffset() );
571 const Size aEmptySize
;
572 pOut
->SetPixelOffset( aEmptySize
);
573 aDrawMap
.SetOrigin( pOut
->PixelToLogic( pOut
->LogicToPixel( rPos
), aDrawMap
) );
574 pOut
->SetPixelOffset( rOldOffset
);
578 if ( pMtf
&& pMtf
->IsRecord() && ( pOut
->GetOutDevType() != OUTDEV_PRINTER
) )
579 pOut
->SetRelativeMapMode( aDrawMap
);
581 pOut
->SetMapMode( aDrawMap
);
583 // #i23407# Set backwards-compatible text language and layout mode
584 // This is necessary, since old metafiles don't even know of these
585 // recent add-ons. Newer metafiles must of course explicitly set
587 pOut
->SetLayoutMode( TEXT_LAYOUT_DEFAULT
);
588 pOut
->SetDigitLanguage( 0 );
596 void GDIMetaFile::Pause( bool _bPause
)
603 Linker( pOutDev
, false );
608 Linker( pOutDev
, true );
615 void GDIMetaFile::Stop()
622 Linker( pOutDev
, false );
628 void GDIMetaFile::WindStart()
631 nCurrentActionElement
= 0;
634 void GDIMetaFile::WindPrev()
637 if ( nCurrentActionElement
> 0 )
638 --nCurrentActionElement
;
641 void GDIMetaFile::AddAction( MetaAction
* pAction
)
643 aList
.push_back( pAction
);
647 pAction
->Duplicate();
648 pPrev
->AddAction( pAction
);
652 void GDIMetaFile::AddAction( MetaAction
* pAction
, size_t nPos
)
654 if ( nPos
< aList
.size() )
656 ::std::vector
< MetaAction
* >::iterator it
= aList
.begin();
657 ::std::advance( it
, nPos
);
658 aList
.insert( it
, pAction
);
662 aList
.push_back( pAction
);
667 pAction
->Duplicate();
668 pPrev
->AddAction( pAction
, nPos
);
672 void GDIMetaFile::push_back( MetaAction
* pAction
)
674 aList
.push_back( pAction
);
677 void GDIMetaFile::RemoveAction( size_t nPos
)
679 if ( nPos
< aList
.size() )
681 ::std::vector
< MetaAction
* >::iterator it
= aList
.begin();
682 ::std::advance( it
, nPos
);
689 pPrev
->RemoveAction( nPos
);
692 bool GDIMetaFile::Mirror( BmpMirrorFlags nMirrorFlags
)
694 const Size
aOldPrefSize( GetPrefSize() );
696 double fScaleX
, fScaleY
;
699 if( nMirrorFlags
& BmpMirrorFlags::Horizontal
)
700 nMoveX
= SAL_ABS( aOldPrefSize
.Width() ) - 1, fScaleX
= -1.0;
702 nMoveX
= 0, fScaleX
= 1.0;
704 if( nMirrorFlags
& BmpMirrorFlags::Vertical
)
705 nMoveY
= SAL_ABS( aOldPrefSize
.Height() ) - 1, fScaleY
= -1.0;
707 nMoveY
= 0, fScaleY
= 1.0;
709 if( ( fScaleX
!= 1.0 ) || ( fScaleY
!= 1.0 ) )
711 Scale( fScaleX
, fScaleY
);
712 Move( nMoveX
, nMoveY
);
713 SetPrefSize( aOldPrefSize
);
722 void GDIMetaFile::Move( long nX
, long nY
)
724 const Size
aBaseOffset( nX
, nY
);
725 Size
aOffset( aBaseOffset
);
726 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
728 aMapVDev
->EnableOutput( false );
729 aMapVDev
->SetMapMode( GetPrefMapMode() );
731 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
733 const MetaActionType nType
= pAct
->GetType();
736 if( pAct
->GetRefCount() > 1 )
738 aList
[ nCurrentActionElement
] = pModAct
= pAct
->Clone();
744 if( ( MetaActionType::MAPMODE
== nType
) ||
745 ( MetaActionType::PUSH
== nType
) ||
746 ( MetaActionType::POP
== nType
) )
748 pModAct
->Execute( aMapVDev
.get() );
749 aOffset
= OutputDevice::LogicToLogic( aBaseOffset
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
752 pModAct
->Move( aOffset
.Width(), aOffset
.Height() );
756 void GDIMetaFile::Move( long nX
, long nY
, long nDPIX
, long nDPIY
)
758 const Size
aBaseOffset( nX
, nY
);
759 Size
aOffset( aBaseOffset
);
760 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
762 aMapVDev
->EnableOutput( false );
763 aMapVDev
->SetReferenceDevice( nDPIX
, nDPIY
);
764 aMapVDev
->SetMapMode( GetPrefMapMode() );
766 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
768 const MetaActionType nType
= pAct
->GetType();
771 if( pAct
->GetRefCount() > 1 )
773 aList
[ nCurrentActionElement
] = pModAct
= pAct
->Clone();
779 if( ( MetaActionType::MAPMODE
== nType
) ||
780 ( MetaActionType::PUSH
== nType
) ||
781 ( MetaActionType::POP
== nType
) )
783 pModAct
->Execute( aMapVDev
.get() );
784 if( aMapVDev
->GetMapMode().GetMapUnit() == MAP_PIXEL
)
786 aOffset
= aMapVDev
->LogicToPixel( aBaseOffset
, GetPrefMapMode() );
787 MapMode
aMap( aMapVDev
->GetMapMode() );
788 aOffset
.Width() = static_cast<long>(aOffset
.Width() * (double)aMap
.GetScaleX());
789 aOffset
.Height() = static_cast<long>(aOffset
.Height() * (double)aMap
.GetScaleY());
792 aOffset
= OutputDevice::LogicToLogic( aBaseOffset
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
795 pModAct
->Move( aOffset
.Width(), aOffset
.Height() );
799 void GDIMetaFile::Scale( double fScaleX
, double fScaleY
)
801 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
805 if( pAct
->GetRefCount() > 1 )
807 aList
[ nCurrentActionElement
] = pModAct
= pAct
->Clone();
813 pModAct
->Scale( fScaleX
, fScaleY
);
816 aPrefSize
.Width() = FRound( aPrefSize
.Width() * fScaleX
);
817 aPrefSize
.Height() = FRound( aPrefSize
.Height() * fScaleY
);
820 void GDIMetaFile::Scale( const Fraction
& rScaleX
, const Fraction
& rScaleY
)
822 Scale( (double) rScaleX
, (double) rScaleY
);
825 void GDIMetaFile::Clip( const Rectangle
& i_rClipRect
)
827 Rectangle
aCurRect( i_rClipRect
);
828 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
830 aMapVDev
->EnableOutput( false );
831 aMapVDev
->SetMapMode( GetPrefMapMode() );
833 for( MetaAction
* pAct
= FirstAction(); pAct
; pAct
= NextAction() )
835 const MetaActionType nType
= pAct
->GetType();
837 if( ( MetaActionType::MAPMODE
== nType
) ||
838 ( MetaActionType::PUSH
== nType
) ||
839 ( MetaActionType::POP
== nType
) )
841 pAct
->Execute( aMapVDev
.get() );
842 aCurRect
= OutputDevice::LogicToLogic( i_rClipRect
, GetPrefMapMode(), aMapVDev
->GetMapMode() );
844 else if( nType
== MetaActionType::CLIPREGION
)
846 MetaClipRegionAction
* pOldAct
= static_cast<MetaClipRegionAction
*>(pAct
);
847 vcl::Region
aNewReg( aCurRect
);
848 if( pOldAct
->IsClipping() )
849 aNewReg
.Intersect( pOldAct
->GetRegion() );
850 MetaClipRegionAction
* pNewAct
= new MetaClipRegionAction( aNewReg
, true );
851 aList
[ nCurrentActionElement
] = pNewAct
;
857 Point
GDIMetaFile::ImplGetRotatedPoint( const Point
& rPt
, const Point
& rRotatePt
,
858 const Size
& rOffset
, double fSin
, double fCos
)
860 const long nX
= rPt
.X() - rRotatePt
.X();
861 const long nY
= rPt
.Y() - rRotatePt
.Y();
863 return Point( FRound( fCos
* nX
+ fSin
* nY
) + rRotatePt
.X() + rOffset
.Width(),
864 -FRound( fSin
* nX
- fCos
* nY
) + rRotatePt
.Y() + rOffset
.Height() );
867 Polygon
GDIMetaFile::ImplGetRotatedPolygon( const Polygon
& rPoly
, const Point
& rRotatePt
,
868 const Size
& rOffset
, double fSin
, double fCos
)
870 Polygon
aRet( rPoly
);
872 aRet
.Rotate( rRotatePt
, fSin
, fCos
);
873 aRet
.Move( rOffset
.Width(), rOffset
.Height() );
878 tools::PolyPolygon
GDIMetaFile::ImplGetRotatedPolyPolygon( const tools::PolyPolygon
& rPolyPoly
, const Point
& rRotatePt
,
879 const Size
& rOffset
, double fSin
, double fCos
)
881 tools::PolyPolygon
aRet( rPolyPoly
);
883 aRet
.Rotate( rRotatePt
, fSin
, fCos
);
884 aRet
.Move( rOffset
.Width(), rOffset
.Height() );
889 void GDIMetaFile::ImplAddGradientEx( GDIMetaFile
& rMtf
,
890 const OutputDevice
& rMapDev
,
891 const tools::PolyPolygon
& rPolyPoly
,
892 const Gradient
& rGrad
)
894 // Generate comment, GradientEx and Gradient actions (within DrawGradient)
895 ScopedVclPtrInstance
< VirtualDevice
> aVDev( rMapDev
, 0 );
896 aVDev
->EnableOutput( false );
897 GDIMetaFile aGradMtf
;
899 aGradMtf
.Record( aVDev
.get() );
900 aVDev
->DrawGradient( rPolyPoly
, rGrad
);
903 size_t i
, nAct( aGradMtf
.GetActionSize() );
904 for( i
=0; i
< nAct
; ++i
)
906 MetaAction
* pMetaAct
= aGradMtf
.GetAction( i
);
907 pMetaAct
->Duplicate();
908 rMtf
.AddAction( pMetaAct
);
912 void GDIMetaFile::Rotate( long nAngle10
)
915 nAngle10
= ( nAngle10
< 0L ) ? ( 3599L + nAngle10
) : nAngle10
;
920 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev
;
921 const double fAngle
= F_PI1800
* nAngle10
;
922 const double fSin
= sin( fAngle
);
923 const double fCos
= cos( fAngle
);
924 Rectangle aRect
=Rectangle( Point(), GetPrefSize() );
925 Polygon
aPoly( aRect
);
927 aPoly
.Rotate( Point(), fSin
, fCos
);
929 aMapVDev
->EnableOutput( false );
930 aMapVDev
->SetMapMode( GetPrefMapMode() );
932 const Rectangle
aNewBound( aPoly
.GetBoundRect() );
934 const Point
aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
935 const Size
aOffset( -aNewBound
.Left(), -aNewBound
.Top() );
937 Point
aRotAnchor( aOrigin
);
938 Size
aRotOffset( aOffset
);
940 for( MetaAction
* pAction
= FirstAction(); pAction
; pAction
= NextAction() )
942 const MetaActionType nActionType
= pAction
->GetType();
944 switch( nActionType
)
946 case( MetaActionType::PIXEL
):
948 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
949 aMtf
.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
950 pAct
->GetColor() ) );
954 case( MetaActionType::POINT
):
956 MetaPointAction
* pAct
= static_cast<MetaPointAction
*>(pAction
);
957 aMtf
.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
961 case( MetaActionType::LINE
):
963 MetaLineAction
* pAct
= static_cast<MetaLineAction
*>(pAction
);
964 aMtf
.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct
->GetStartPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
965 ImplGetRotatedPoint( pAct
->GetEndPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
966 pAct
->GetLineInfo() ) );
970 case( MetaActionType::RECT
):
972 MetaRectAction
* pAct
= static_cast<MetaRectAction
*>(pAction
);
973 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
977 case( MetaActionType::ROUNDRECT
):
979 MetaRoundRectAction
* pAct
= static_cast<MetaRoundRectAction
*>(pAction
);
980 const Polygon
aRoundRectPoly( pAct
->GetRect(), pAct
->GetHorzRound(), pAct
->GetVertRound() );
982 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
986 case( MetaActionType::ELLIPSE
):
988 MetaEllipseAction
* pAct
= static_cast<MetaEllipseAction
*>(pAction
);
989 const Polygon
aEllipsePoly( pAct
->GetRect().Center(), pAct
->GetRect().GetWidth() >> 1, pAct
->GetRect().GetHeight() >> 1 );
991 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
995 case( MetaActionType::ARC
):
997 MetaArcAction
* pAct
= static_cast<MetaArcAction
*>(pAction
);
998 const Polygon
aArcPoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), POLY_ARC
);
1000 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
1004 case( MetaActionType::PIE
):
1006 MetaPieAction
* pAct
= static_cast<MetaPieAction
*>(pAction
);
1007 const Polygon
aPiePoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), POLY_PIE
);
1009 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
1013 case( MetaActionType::CHORD
):
1015 MetaChordAction
* pAct
= static_cast<MetaChordAction
*>(pAction
);
1016 const Polygon
aChordPoly( pAct
->GetRect(), pAct
->GetStartPoint(), pAct
->GetEndPoint(), POLY_CHORD
);
1018 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly
, aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
1022 case( MetaActionType::POLYLINE
):
1024 MetaPolyLineAction
* pAct
= static_cast<MetaPolyLineAction
*>(pAction
);
1025 aMtf
.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct
->GetPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
), pAct
->GetLineInfo() ) );
1029 case( MetaActionType::POLYGON
):
1031 MetaPolygonAction
* pAct
= static_cast<MetaPolygonAction
*>(pAction
);
1032 aMtf
.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct
->GetPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
1036 case( MetaActionType::POLYPOLYGON
):
1038 MetaPolyPolygonAction
* pAct
= static_cast<MetaPolyPolygonAction
*>(pAction
);
1039 aMtf
.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) );
1043 case( MetaActionType::TEXT
):
1045 MetaTextAction
* pAct
= static_cast<MetaTextAction
*>(pAction
);
1046 aMtf
.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1047 pAct
->GetText(), pAct
->GetIndex(), pAct
->GetLen() ) );
1051 case( MetaActionType::TEXTARRAY
):
1053 MetaTextArrayAction
* pAct
= static_cast<MetaTextArrayAction
*>(pAction
);
1054 aMtf
.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1055 pAct
->GetText(), pAct
->GetDXArray(), pAct
->GetIndex(), pAct
->GetLen() ) );
1059 case( MetaActionType::STRETCHTEXT
):
1061 MetaStretchTextAction
* pAct
= static_cast<MetaStretchTextAction
*>(pAction
);
1062 aMtf
.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct
->GetPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1063 pAct
->GetWidth(), pAct
->GetText(), pAct
->GetIndex(), pAct
->GetLen() ) );
1067 case( MetaActionType::TEXTLINE
):
1069 MetaTextLineAction
* pAct
= static_cast<MetaTextLineAction
*>(pAction
);
1070 aMtf
.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct
->GetStartPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1071 pAct
->GetWidth(), pAct
->GetStrikeout(), pAct
->GetUnderline(), pAct
->GetOverline() ) );
1075 case( MetaActionType::BMPSCALE
):
1077 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1078 Polygon
aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1079 Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1080 BitmapEx
aBmpEx( pAct
->GetBitmap() );
1082 aBmpEx
.Rotate( nAngle10
, Color( COL_TRANSPARENT
) );
1083 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(),
1088 case( MetaActionType::BMPSCALEPART
):
1090 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1091 Polygon
aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct
->GetDestPoint(), pAct
->GetDestSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1092 Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1093 BitmapEx
aBmpEx( pAct
->GetBitmap() );
1095 aBmpEx
.Crop( Rectangle( pAct
->GetSrcPoint(), pAct
->GetSrcSize() ) );
1096 aBmpEx
.Rotate( nAngle10
, Color( COL_TRANSPARENT
) );
1098 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1102 case( MetaActionType::BMPEXSCALE
):
1104 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1105 Polygon
aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1106 Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1107 BitmapEx
aBmpEx( pAct
->GetBitmapEx() );
1109 aBmpEx
.Rotate( nAngle10
, Color( COL_TRANSPARENT
) );
1111 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1115 case( MetaActionType::BMPEXSCALEPART
):
1117 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1118 Polygon
aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct
->GetDestPoint(), pAct
->GetDestSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1119 Rectangle
aBmpRect( aBmpPoly
.GetBoundRect() );
1120 BitmapEx
aBmpEx( pAct
->GetBitmapEx() );
1122 aBmpEx
.Crop( Rectangle( pAct
->GetSrcPoint(), pAct
->GetSrcSize() ) );
1123 aBmpEx
.Rotate( nAngle10
, Color( COL_TRANSPARENT
) );
1125 aMtf
.AddAction( new MetaBmpExScaleAction( aBmpRect
.TopLeft(), aBmpRect
.GetSize(), aBmpEx
) );
1129 case( MetaActionType::GRADIENT
):
1131 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1133 ImplAddGradientEx( aMtf
, *aMapVDev
.get(),
1134 ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1135 pAct
->GetGradient() );
1139 case( MetaActionType::GRADIENTEX
):
1141 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1142 aMtf
.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1143 pAct
->GetGradient() ) );
1147 // Handle gradientex comment block correctly
1148 case( MetaActionType::COMMENT
):
1150 MetaCommentAction
* pCommentAct
= static_cast<MetaCommentAction
*>(pAction
);
1151 if( pCommentAct
->GetComment() == "XGRAD_SEQ_BEGIN" )
1153 int nBeginComments( 1 );
1154 pAction
= NextAction();
1156 // skip everything, except gradientex action
1159 const MetaActionType nType
= pAction
->GetType();
1161 if( MetaActionType::GRADIENTEX
== nType
)
1163 // Add rotated gradientex
1164 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1165 ImplAddGradientEx( aMtf
, *aMapVDev
.get(),
1166 ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1167 pAct
->GetGradient() );
1169 else if( MetaActionType::COMMENT
== nType
)
1171 MetaCommentAction
* pAct
= static_cast<MetaCommentAction
*>(pAction
);
1172 if( pAct
->GetComment() == "XGRAD_SEQ_END" )
1174 // handle nested blocks
1177 // gradientex comment block: end reached, done.
1178 if( !nBeginComments
)
1181 else if( pAct
->GetComment() == "XGRAD_SEQ_BEGIN" )
1183 // handle nested blocks
1189 pAction
=NextAction();
1194 bool bPathStroke
= (pCommentAct
->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1195 if ( bPathStroke
|| pCommentAct
->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1197 if ( pCommentAct
->GetDataSize() )
1199 SvMemoryStream
aMemStm( (void*)pCommentAct
->GetData(), pCommentAct
->GetDataSize(), StreamMode::READ
);
1200 SvMemoryStream aDest
;
1203 SvtGraphicStroke aStroke
;
1204 ReadSvtGraphicStroke( aMemStm
, aStroke
);
1206 aStroke
.getPath( aPath
);
1207 aStroke
.setPath( ImplGetRotatedPolygon( aPath
, aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1208 WriteSvtGraphicStroke( aDest
, aStroke
);
1209 aMtf
.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1210 static_cast<const sal_uInt8
*>( aDest
.GetData()), aDest
.Tell() ) );
1214 SvtGraphicFill aFill
;
1215 ReadSvtGraphicFill( aMemStm
, aFill
);
1216 tools::PolyPolygon aPath
;
1217 aFill
.getPath( aPath
);
1218 aFill
.setPath( ImplGetRotatedPolyPolygon( aPath
, aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1219 WriteSvtGraphicFill( aDest
, aFill
);
1220 aMtf
.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1221 static_cast<const sal_uInt8
*>( aDest
.GetData()), aDest
.Tell() ) );
1225 else if ( pCommentAct
->GetComment() == "XPATHSTROKE_SEQ_END"
1226 || pCommentAct
->GetComment() == "XPATHFILL_SEQ_END" )
1228 pAction
->Execute( aMapVDev
.get() );
1229 pAction
->Duplicate();
1230 aMtf
.AddAction( pAction
);
1236 case( MetaActionType::HATCH
):
1238 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
1239 Hatch
aHatch( pAct
->GetHatch() );
1241 aHatch
.SetAngle( aHatch
.GetAngle() + (sal_uInt16
) nAngle10
);
1242 aMtf
.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1247 case( MetaActionType::Transparent
):
1249 MetaTransparentAction
* pAct
= static_cast<MetaTransparentAction
*>(pAction
);
1250 aMtf
.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct
->GetPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
),
1251 pAct
->GetTransparence() ) );
1255 case( MetaActionType::FLOATTRANSPARENT
):
1257 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
1258 GDIMetaFile
aTransMtf( pAct
->GetGDIMetaFile() );
1259 Polygon
aMtfPoly( ImplGetRotatedPolygon( Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1260 Rectangle
aMtfRect( aMtfPoly
.GetBoundRect() );
1262 aTransMtf
.Rotate( nAngle10
);
1263 aMtf
.AddAction( new MetaFloatTransparentAction( aTransMtf
, aMtfRect
.TopLeft(), aMtfRect
.GetSize(),
1264 pAct
->GetGradient() ) );
1268 case( MetaActionType::EPS
):
1270 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
1271 GDIMetaFile
aEPSMtf( pAct
->GetSubstitute() );
1272 Polygon
aEPSPoly( ImplGetRotatedPolygon( Rectangle( pAct
->GetPoint(), pAct
->GetSize() ), aRotAnchor
, aRotOffset
, fSin
, fCos
) );
1273 Rectangle
aEPSRect( aEPSPoly
.GetBoundRect() );
1275 aEPSMtf
.Rotate( nAngle10
);
1276 aMtf
.AddAction( new MetaEPSAction( aEPSRect
.TopLeft(), aEPSRect
.GetSize(),
1277 pAct
->GetLink(), aEPSMtf
) );
1281 case( MetaActionType::CLIPREGION
):
1283 MetaClipRegionAction
* pAct
= static_cast<MetaClipRegionAction
*>(pAction
);
1285 if( pAct
->IsClipping() && pAct
->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1286 aMtf
.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct
->GetRegion().GetAsPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ), true ) );
1289 pAction
->Duplicate();
1290 aMtf
.AddAction( pAction
);
1295 case( MetaActionType::ISECTRECTCLIPREGION
):
1297 MetaISectRectClipRegionAction
* pAct
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
1298 aMtf
.AddAction( new MetaISectRegionClipRegionAction(vcl::Region(
1299 ImplGetRotatedPolygon( pAct
->GetRect(), aRotAnchor
,
1300 aRotOffset
, fSin
, fCos
)) ) );
1304 case( MetaActionType::ISECTREGIONCLIPREGION
):
1306 MetaISectRegionClipRegionAction
* pAct
= static_cast<MetaISectRegionClipRegionAction
*>(pAction
);
1307 const vcl::Region
& rRegion
= pAct
->GetRegion();
1309 if( rRegion
.HasPolyPolygonOrB2DPolyPolygon() )
1310 aMtf
.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion
.GetAsPolyPolygon(), aRotAnchor
, aRotOffset
, fSin
, fCos
) ) ) );
1313 pAction
->Duplicate();
1314 aMtf
.AddAction( pAction
);
1319 case( MetaActionType::REFPOINT
):
1321 MetaRefPointAction
* pAct
= static_cast<MetaRefPointAction
*>(pAction
);
1322 aMtf
.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct
->GetRefPoint(), aRotAnchor
, aRotOffset
, fSin
, fCos
), pAct
->IsSetting() ) );
1326 case( MetaActionType::FONT
):
1328 MetaFontAction
* pAct
= static_cast<MetaFontAction
*>(pAction
);
1329 vcl::Font
aFont( pAct
->GetFont() );
1331 aFont
.SetOrientation( aFont
.GetOrientation() + (sal_uInt16
) nAngle10
);
1332 aMtf
.AddAction( new MetaFontAction( aFont
) );
1336 case( MetaActionType::BMP
):
1337 case( MetaActionType::BMPEX
):
1338 case( MetaActionType::MASK
):
1339 case( MetaActionType::MASKSCALE
):
1340 case( MetaActionType::MASKSCALEPART
):
1341 case( MetaActionType::WALLPAPER
):
1342 case( MetaActionType::TEXTRECT
):
1343 case( MetaActionType::MOVECLIPREGION
):
1345 OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1351 pAction
->Execute( aMapVDev
.get() );
1352 pAction
->Duplicate();
1353 aMtf
.AddAction( pAction
);
1355 // update rotation point and offset, if necessary
1356 if( ( MetaActionType::MAPMODE
== nActionType
) ||
1357 ( MetaActionType::PUSH
== nActionType
) ||
1358 ( MetaActionType::POP
== nActionType
) )
1360 aRotAnchor
= OutputDevice::LogicToLogic( aOrigin
, aPrefMapMode
, aMapVDev
->GetMapMode() );
1361 aRotOffset
= OutputDevice::LogicToLogic( aOffset
, aPrefMapMode
, aMapVDev
->GetMapMode() );
1368 aMtf
.aPrefMapMode
= aPrefMapMode
;
1369 aMtf
.aPrefSize
= aNewBound
.GetSize();
1375 static void ImplActionBounds( Rectangle
& o_rOutBounds
,
1376 const Rectangle
& i_rInBounds
,
1377 const std::vector
<Rectangle
>& i_rClipStack
,
1378 Rectangle
* o_pHairline
)
1380 Rectangle
aBounds( i_rInBounds
);
1381 if( ! i_rInBounds
.IsEmpty() && ! i_rClipStack
.empty() && ! i_rClipStack
.back().IsEmpty() )
1382 aBounds
.Intersection( i_rClipStack
.back() );
1383 if( ! aBounds
.IsEmpty() )
1385 if( ! o_rOutBounds
.IsEmpty() )
1386 o_rOutBounds
.Union( aBounds
);
1388 o_rOutBounds
= aBounds
;
1392 if( ! o_pHairline
->IsEmpty() )
1393 o_pHairline
->Union( aBounds
);
1395 *o_pHairline
= aBounds
;
1400 Rectangle
GDIMetaFile::GetBoundRect( OutputDevice
& i_rReference
, Rectangle
* pHairline
) const
1403 ScopedVclPtrInstance
< VirtualDevice
> aMapVDev( i_rReference
);
1405 aMapVDev
->EnableOutput( false );
1406 aMapVDev
->SetMapMode( GetPrefMapMode() );
1408 std::vector
<Rectangle
> aClipStack( 1, Rectangle() );
1409 std::vector
<PushFlags
> aPushFlagStack
;
1414 *pHairline
= Rectangle();
1416 const sal_uLong
nCount(GetActionSize());
1418 for(sal_uLong
a(0); a
< nCount
; a
++)
1420 MetaAction
* pAction
= GetAction(a
);
1421 const MetaActionType nActionType
= pAction
->GetType();
1422 Rectangle
* pUseHairline
= (pHairline
&& aMapVDev
->IsLineColor()) ? pHairline
: 0;
1424 switch( nActionType
)
1426 case( MetaActionType::PIXEL
):
1428 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
1429 ImplActionBounds( aBound
,
1430 Rectangle( OutputDevice::LogicToLogic( pAct
->GetPoint(), aMapVDev
->GetMapMode(), GetPrefMapMode() ),
1431 aMapVDev
->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1432 aClipStack
, pUseHairline
);
1436 case( MetaActionType::POINT
):
1438 MetaPointAction
* pAct
= static_cast<MetaPointAction
*>(pAction
);
1439 ImplActionBounds( aBound
,
1440 Rectangle( OutputDevice::LogicToLogic( pAct
->GetPoint(), aMapVDev
->GetMapMode(), GetPrefMapMode() ),
1441 aMapVDev
->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1442 aClipStack
, pUseHairline
);
1446 case( MetaActionType::LINE
):
1448 MetaLineAction
* pAct
= static_cast<MetaLineAction
*>(pAction
);
1449 Point
aP1( pAct
->GetStartPoint() ), aP2( pAct
->GetEndPoint() );
1450 Rectangle
aRect( aP1
, aP2
);
1455 const LineInfo
& rLineInfo
= pAct
->GetLineInfo();
1457 if(0 != rLineInfo
.GetWidth())
1461 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1465 case( MetaActionType::RECT
):
1467 MetaRectAction
* pAct
= static_cast<MetaRectAction
*>(pAction
);
1468 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1472 case( MetaActionType::ROUNDRECT
):
1474 MetaRoundRectAction
* pAct
= static_cast<MetaRoundRectAction
*>(pAction
);
1475 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1479 case( MetaActionType::ELLIPSE
):
1481 MetaEllipseAction
* pAct
= static_cast<MetaEllipseAction
*>(pAction
);
1482 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1486 case( MetaActionType::ARC
):
1488 MetaArcAction
* pAct
= static_cast<MetaArcAction
*>(pAction
);
1489 // FIXME: this is imprecise
1490 // e.g. for small arcs the whole rectangle is WAY too large
1491 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1495 case( MetaActionType::PIE
):
1497 MetaPieAction
* pAct
= static_cast<MetaPieAction
*>(pAction
);
1498 // FIXME: this is imprecise
1499 // e.g. for small arcs the whole rectangle is WAY too large
1500 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1504 case( MetaActionType::CHORD
):
1506 MetaChordAction
* pAct
= static_cast<MetaChordAction
*>(pAction
);
1507 // FIXME: this is imprecise
1508 // e.g. for small arcs the whole rectangle is WAY too large
1509 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1513 case( MetaActionType::POLYLINE
):
1515 MetaPolyLineAction
* pAct
= static_cast<MetaPolyLineAction
*>(pAction
);
1516 Rectangle
aRect( pAct
->GetPolygon().GetBoundRect() );
1520 const LineInfo
& rLineInfo
= pAct
->GetLineInfo();
1522 if(0 != rLineInfo
.GetWidth())
1526 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1530 case( MetaActionType::POLYGON
):
1532 MetaPolygonAction
* pAct
= static_cast<MetaPolygonAction
*>(pAction
);
1533 Rectangle
aRect( pAct
->GetPolygon().GetBoundRect() );
1534 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1538 case( MetaActionType::POLYPOLYGON
):
1540 MetaPolyPolygonAction
* pAct
= static_cast<MetaPolyPolygonAction
*>(pAction
);
1541 Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1542 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, pUseHairline
);
1546 case( MetaActionType::TEXT
):
1548 MetaTextAction
* pAct
= static_cast<MetaTextAction
*>(pAction
);
1550 // hdu said base = index
1551 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen() );
1552 Point
aPt( pAct
->GetPoint() );
1553 aRect
.Move( aPt
.X(), aPt
.Y() );
1554 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1558 case( MetaActionType::TEXTARRAY
):
1560 MetaTextArrayAction
* pAct
= static_cast<MetaTextArrayAction
*>(pAction
);
1562 // hdu said base = index
1563 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen(),
1564 0, pAct
->GetDXArray() );
1565 Point
aPt( pAct
->GetPoint() );
1566 aRect
.Move( aPt
.X(), aPt
.Y() );
1567 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1571 case( MetaActionType::STRETCHTEXT
):
1573 MetaStretchTextAction
* pAct
= static_cast<MetaStretchTextAction
*>(pAction
);
1575 // hdu said base = index
1576 aMapVDev
->GetTextBoundRect( aRect
, pAct
->GetText(), pAct
->GetIndex(), pAct
->GetIndex(), pAct
->GetLen(),
1577 pAct
->GetWidth(), NULL
);
1578 Point
aPt( pAct
->GetPoint() );
1579 aRect
.Move( aPt
.X(), aPt
.Y() );
1580 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1584 case( MetaActionType::TEXTLINE
):
1586 MetaTextLineAction
* pAct
= static_cast<MetaTextLineAction
*>(pAction
);
1587 // measure a test string to get ascend and descent right
1588 static const sal_Unicode pStr
[] = { 0xc4, 0x67, 0 };
1589 OUString
aStr( pStr
);
1592 aMapVDev
->GetTextBoundRect( aRect
, aStr
, 0, 0, aStr
.getLength(), 0, NULL
);
1593 Point
aPt( pAct
->GetStartPoint() );
1594 aRect
.Move( aPt
.X(), aPt
.Y() );
1595 aRect
.Right() = aRect
.Left() + pAct
->GetWidth();
1596 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1600 case( MetaActionType::BMPSCALE
):
1602 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
1603 Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1604 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1608 case( MetaActionType::BMPSCALEPART
):
1610 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
1611 Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1612 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1616 case( MetaActionType::BMPEXSCALE
):
1618 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
1619 Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1620 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1624 case( MetaActionType::BMPEXSCALEPART
):
1626 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
1627 Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1628 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1632 case( MetaActionType::GRADIENT
):
1634 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
1635 Rectangle
aRect( pAct
->GetRect() );
1636 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1640 case( MetaActionType::GRADIENTEX
):
1642 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
1643 Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1644 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1648 case( MetaActionType::COMMENT
):
1654 case( MetaActionType::HATCH
):
1656 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
1657 Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1658 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1662 case( MetaActionType::Transparent
):
1664 MetaTransparentAction
* pAct
= static_cast<MetaTransparentAction
*>(pAction
);
1665 Rectangle
aRect( pAct
->GetPolyPolygon().GetBoundRect() );
1666 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1670 case( MetaActionType::FLOATTRANSPARENT
):
1672 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
1673 // MetaFloatTransparentAction is defined limiting it's content Metafile
1674 // to it's geometry definition(Point, Size), so use these directly
1675 const Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1676 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1680 case( MetaActionType::EPS
):
1682 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
1683 Rectangle
aRect( pAct
->GetPoint(), pAct
->GetSize() );
1684 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1688 case( MetaActionType::CLIPREGION
):
1690 MetaClipRegionAction
* pAct
= static_cast<MetaClipRegionAction
*>(pAction
);
1691 if( pAct
->IsClipping() )
1692 aClipStack
.back() = OutputDevice::LogicToLogic( pAct
->GetRegion().GetBoundRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() );
1694 aClipStack
.back() = Rectangle();
1698 case( MetaActionType::ISECTRECTCLIPREGION
):
1700 MetaISectRectClipRegionAction
* pAct
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
1701 Rectangle
aRect( OutputDevice::LogicToLogic( pAct
->GetRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ) );
1702 if( aClipStack
.back().IsEmpty() )
1703 aClipStack
.back() = aRect
;
1705 aClipStack
.back().Intersection( aRect
);
1709 case( MetaActionType::ISECTREGIONCLIPREGION
):
1711 MetaISectRegionClipRegionAction
* pAct
= static_cast<MetaISectRegionClipRegionAction
*>(pAction
);
1712 Rectangle
aRect( OutputDevice::LogicToLogic( pAct
->GetRegion().GetBoundRect(), aMapVDev
->GetMapMode(), GetPrefMapMode() ) );
1713 if( aClipStack
.back().IsEmpty() )
1714 aClipStack
.back() = aRect
;
1716 aClipStack
.back().Intersection( aRect
);
1720 case( MetaActionType::BMP
):
1722 MetaBmpAction
* pAct
= static_cast<MetaBmpAction
*>(pAction
);
1723 Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmap().GetSizePixel() ) );
1724 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1728 case( MetaActionType::BMPEX
):
1730 MetaBmpExAction
* pAct
= static_cast<MetaBmpExAction
*>(pAction
);
1731 Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmapEx().GetSizePixel() ) );
1732 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1736 case( MetaActionType::MASK
):
1738 MetaMaskAction
* pAct
= static_cast<MetaMaskAction
*>(pAction
);
1739 Rectangle
aRect( pAct
->GetPoint(), aMapVDev
->PixelToLogic( pAct
->GetBitmap().GetSizePixel() ) );
1740 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1744 case( MetaActionType::MASKSCALE
):
1746 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1747 Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1748 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1752 case( MetaActionType::MASKSCALEPART
):
1754 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
1755 Rectangle
aRect( pAct
->GetDestPoint(), pAct
->GetDestSize() );
1756 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1760 case( MetaActionType::WALLPAPER
):
1762 MetaWallpaperAction
* pAct
= static_cast<MetaWallpaperAction
*>(pAction
);
1763 Rectangle
aRect( pAct
->GetRect() );
1764 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1768 case( MetaActionType::TEXTRECT
):
1770 MetaTextRectAction
* pAct
= static_cast<MetaTextRectAction
*>(pAction
);
1771 Rectangle
aRect( pAct
->GetRect() );
1772 ImplActionBounds( aBound
, OutputDevice::LogicToLogic( aRect
, aMapVDev
->GetMapMode(), GetPrefMapMode() ), aClipStack
, 0 );
1776 case( MetaActionType::MOVECLIPREGION
):
1778 MetaMoveClipRegionAction
* pAct
= static_cast<MetaMoveClipRegionAction
*>(pAction
);
1779 if( ! aClipStack
.back().IsEmpty() )
1781 Size
aDelta( pAct
->GetHorzMove(), pAct
->GetVertMove() );
1782 aDelta
= OutputDevice::LogicToLogic( aDelta
, aMapVDev
->GetMapMode(), GetPrefMapMode() );
1783 aClipStack
.back().Move( aDelta
.Width(), aDelta
.Width() );
1790 pAction
->Execute( aMapVDev
.get() );
1792 if( nActionType
== MetaActionType::PUSH
)
1794 MetaPushAction
* pAct
= static_cast<MetaPushAction
*>(pAction
);
1795 aPushFlagStack
.push_back( pAct
->GetFlags() );
1796 if( aPushFlagStack
.back() & PushFlags::CLIPREGION
)
1798 Rectangle
aRect( aClipStack
.back() );
1799 aClipStack
.push_back( aRect
);
1802 else if( nActionType
== MetaActionType::POP
)
1805 if( ! aPushFlagStack
.empty() )
1807 if( aPushFlagStack
.back() & PushFlags::CLIPREGION
)
1809 if( aClipStack
.size() > 1 )
1810 aClipStack
.pop_back();
1812 aPushFlagStack
.pop_back();
1822 Color
GDIMetaFile::ImplColAdjustFnc( const Color
& rColor
, const void* pColParam
)
1824 return Color( rColor
.GetTransparency(),
1825 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapR
[ rColor
.GetRed() ],
1826 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapG
[ rColor
.GetGreen() ],
1827 static_cast<const ImplColAdjustParam
*>(pColParam
)->pMapB
[ rColor
.GetBlue() ] );
1831 BitmapEx
GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1833 const ImplBmpAdjustParam
* p
= static_cast<const ImplBmpAdjustParam
*>(pBmpParam
);
1834 BitmapEx
aRet( rBmpEx
);
1836 aRet
.Adjust( p
->nLuminancePercent
, p
->nContrastPercent
,
1837 p
->nChannelRPercent
, p
->nChannelGPercent
, p
->nChannelBPercent
,
1838 p
->fGamma
, p
->bInvert
);
1843 Color
GDIMetaFile::ImplColConvertFnc( const Color
& rColor
, const void* pColParam
)
1845 sal_uInt8 cLum
= rColor
.GetLuminance();
1847 if( MTF_CONVERSION_1BIT_THRESHOLD
== static_cast<const ImplColConvertParam
*>(pColParam
)->eConversion
)
1848 cLum
= ( cLum
< 128 ) ? 0 : 255;
1850 return Color( rColor
.GetTransparency(), cLum
, cLum
, cLum
);
1853 BitmapEx
GDIMetaFile::ImplBmpConvertFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1855 BitmapEx
aRet( rBmpEx
);
1857 aRet
.Convert( static_cast<const ImplBmpConvertParam
*>(pBmpParam
)->eConversion
);
1862 Color
GDIMetaFile::ImplColMonoFnc( const Color
&, const void* pColParam
)
1864 return static_cast<const ImplColMonoParam
*>(pColParam
)->aColor
;
1867 BitmapEx
GDIMetaFile::ImplBmpMonoFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1869 BitmapPalette
aPal( 3 );
1871 aPal
[ 0 ] = Color( COL_BLACK
);
1872 aPal
[ 1 ] = Color( COL_WHITE
);
1873 aPal
[ 2 ] = static_cast<const ImplBmpMonoParam
*>(pBmpParam
)->aColor
;
1875 Bitmap
aBmp( rBmpEx
.GetSizePixel(), 4, &aPal
);
1876 aBmp
.Erase( static_cast<const ImplBmpMonoParam
*>(pBmpParam
)->aColor
);
1878 if( rBmpEx
.IsAlpha() )
1879 return BitmapEx( aBmp
, rBmpEx
.GetAlpha() );
1880 else if( rBmpEx
.IsTransparent() )
1881 return BitmapEx( aBmp
, rBmpEx
.GetMask() );
1886 Color
GDIMetaFile::ImplColReplaceFnc( const Color
& rColor
, const void* pColParam
)
1888 const sal_uLong nR
= rColor
.GetRed(), nG
= rColor
.GetGreen(), nB
= rColor
.GetBlue();
1890 for( sal_uLong i
= 0; i
< static_cast<const ImplColReplaceParam
*>(pColParam
)->nCount
; i
++ )
1892 if( ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinR
[ i
] <= nR
) &&
1893 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxR
[ i
] >= nR
) &&
1894 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinG
[ i
] <= nG
) &&
1895 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxG
[ i
] >= nG
) &&
1896 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMinB
[ i
] <= nB
) &&
1897 ( static_cast<const ImplColReplaceParam
*>(pColParam
)->pMaxB
[ i
] >= nB
) )
1899 return static_cast<const ImplColReplaceParam
*>(pColParam
)->pDstCols
[ i
];
1906 BitmapEx
GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx
& rBmpEx
, const void* pBmpParam
)
1908 const ImplBmpReplaceParam
* p
= static_cast<const ImplBmpReplaceParam
*>(pBmpParam
);
1909 BitmapEx
aRet( rBmpEx
);
1911 aRet
.Replace( p
->pSrcCols
, p
->pDstCols
, p
->nCount
, p
->pTols
);
1916 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol
, const void* pColParam
,
1917 BmpExchangeFnc pFncBmp
, const void* pBmpParam
)
1921 aMtf
.aPrefSize
= aPrefSize
;
1922 aMtf
.aPrefMapMode
= aPrefMapMode
;
1923 aMtf
.bUseCanvas
= bUseCanvas
;
1925 for( MetaAction
* pAction
= FirstAction(); pAction
; pAction
= NextAction() )
1927 const MetaActionType nType
= pAction
->GetType();
1931 case( MetaActionType::PIXEL
):
1933 MetaPixelAction
* pAct
= static_cast<MetaPixelAction
*>(pAction
);
1934 aMtf
.push_back( new MetaPixelAction( pAct
->GetPoint(), pFncCol( pAct
->GetColor(), pColParam
) ) );
1938 case( MetaActionType::LINECOLOR
):
1940 MetaLineColorAction
* pAct
= static_cast<MetaLineColorAction
*>(pAction
);
1942 if( !pAct
->IsSetting() )
1945 pAct
= new MetaLineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1947 aMtf
.push_back( pAct
);
1951 case( MetaActionType::FILLCOLOR
):
1953 MetaFillColorAction
* pAct
= static_cast<MetaFillColorAction
*>(pAction
);
1955 if( !pAct
->IsSetting() )
1958 pAct
= new MetaFillColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1960 aMtf
.push_back( pAct
);
1964 case( MetaActionType::TEXTCOLOR
):
1966 MetaTextColorAction
* pAct
= static_cast<MetaTextColorAction
*>(pAction
);
1967 aMtf
.push_back( new MetaTextColorAction( pFncCol( pAct
->GetColor(), pColParam
) ) );
1971 case( MetaActionType::TEXTFILLCOLOR
):
1973 MetaTextFillColorAction
* pAct
= static_cast<MetaTextFillColorAction
*>(pAction
);
1975 if( !pAct
->IsSetting() )
1978 pAct
= new MetaTextFillColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1980 aMtf
.push_back( pAct
);
1984 case( MetaActionType::TEXTLINECOLOR
):
1986 MetaTextLineColorAction
* pAct
= static_cast<MetaTextLineColorAction
*>(pAction
);
1988 if( !pAct
->IsSetting() )
1991 pAct
= new MetaTextLineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
1993 aMtf
.push_back( pAct
);
1997 case( MetaActionType::OVERLINECOLOR
):
1999 MetaOverlineColorAction
* pAct
= static_cast<MetaOverlineColorAction
*>(pAction
);
2001 if( !pAct
->IsSetting() )
2004 pAct
= new MetaOverlineColorAction( pFncCol( pAct
->GetColor(), pColParam
), true );
2006 aMtf
.push_back( pAct
);
2010 case( MetaActionType::FONT
):
2012 MetaFontAction
* pAct
= static_cast<MetaFontAction
*>(pAction
);
2013 vcl::Font
aFont( pAct
->GetFont() );
2015 aFont
.SetColor( pFncCol( aFont
.GetColor(), pColParam
) );
2016 aFont
.SetFillColor( pFncCol( aFont
.GetFillColor(), pColParam
) );
2017 aMtf
.push_back( new MetaFontAction( aFont
) );
2021 case( MetaActionType::WALLPAPER
):
2023 MetaWallpaperAction
* pAct
= static_cast<MetaWallpaperAction
*>(pAction
);
2024 Wallpaper
aWall( pAct
->GetWallpaper() );
2025 const Rectangle
& rRect
= pAct
->GetRect();
2027 aWall
.SetColor( pFncCol( aWall
.GetColor(), pColParam
) );
2029 if( aWall
.IsBitmap() )
2030 aWall
.SetBitmap( pFncBmp( aWall
.GetBitmap(), pBmpParam
) );
2032 if( aWall
.IsGradient() )
2034 Gradient
aGradient( aWall
.GetGradient() );
2036 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
2037 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
2038 aWall
.SetGradient( aGradient
);
2041 aMtf
.push_back( new MetaWallpaperAction( rRect
, aWall
) );
2045 case( MetaActionType::BMP
):
2046 case( MetaActionType::BMPEX
):
2047 case( MetaActionType::MASK
):
2049 OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
2053 case( MetaActionType::BMPSCALE
):
2055 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
2056 aMtf
.push_back( new MetaBmpScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
2057 pFncBmp( pAct
->GetBitmap(), pBmpParam
).GetBitmap() ) );
2061 case( MetaActionType::BMPSCALEPART
):
2063 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
2064 aMtf
.push_back( new MetaBmpScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
2065 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
2066 pFncBmp( pAct
->GetBitmap(), pBmpParam
).GetBitmap() )
2071 case( MetaActionType::BMPEXSCALE
):
2073 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
2074 aMtf
.push_back( new MetaBmpExScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
2075 pFncBmp( pAct
->GetBitmapEx(), pBmpParam
) )
2080 case( MetaActionType::BMPEXSCALEPART
):
2082 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
2083 aMtf
.push_back( new MetaBmpExScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
2084 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
2085 pFncBmp( pAct
->GetBitmapEx(), pBmpParam
) )
2090 case( MetaActionType::MASKSCALE
):
2092 MetaMaskScaleAction
* pAct
= static_cast<MetaMaskScaleAction
*>(pAction
);
2093 aMtf
.push_back( new MetaMaskScaleAction( pAct
->GetPoint(), pAct
->GetSize(),
2095 pFncCol( pAct
->GetColor(), pColParam
) )
2100 case( MetaActionType::MASKSCALEPART
):
2102 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
2103 aMtf
.push_back( new MetaMaskScalePartAction( pAct
->GetDestPoint(), pAct
->GetDestSize(),
2104 pAct
->GetSrcPoint(), pAct
->GetSrcSize(),
2106 pFncCol( pAct
->GetColor(), pColParam
) )
2111 case( MetaActionType::GRADIENT
):
2113 MetaGradientAction
* pAct
= static_cast<MetaGradientAction
*>(pAction
);
2114 Gradient
aGradient( pAct
->GetGradient() );
2116 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
2117 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
2118 aMtf
.push_back( new MetaGradientAction( pAct
->GetRect(), aGradient
) );
2122 case( MetaActionType::GRADIENTEX
):
2124 MetaGradientExAction
* pAct
= static_cast<MetaGradientExAction
*>(pAction
);
2125 Gradient
aGradient( pAct
->GetGradient() );
2127 aGradient
.SetStartColor( pFncCol( aGradient
.GetStartColor(), pColParam
) );
2128 aGradient
.SetEndColor( pFncCol( aGradient
.GetEndColor(), pColParam
) );
2129 aMtf
.push_back( new MetaGradientExAction( pAct
->GetPolyPolygon(), aGradient
) );
2133 case( MetaActionType::HATCH
):
2135 MetaHatchAction
* pAct
= static_cast<MetaHatchAction
*>(pAction
);
2136 Hatch
aHatch( pAct
->GetHatch() );
2138 aHatch
.SetColor( pFncCol( aHatch
.GetColor(), pColParam
) );
2139 aMtf
.push_back( new MetaHatchAction( pAct
->GetPolyPolygon(), aHatch
) );
2143 case( MetaActionType::FLOATTRANSPARENT
):
2145 MetaFloatTransparentAction
* pAct
= static_cast<MetaFloatTransparentAction
*>(pAction
);
2146 GDIMetaFile
aTransMtf( pAct
->GetGDIMetaFile() );
2148 aTransMtf
.ImplExchangeColors( pFncCol
, pColParam
, pFncBmp
, pBmpParam
);
2149 aMtf
.push_back( new MetaFloatTransparentAction( aTransMtf
,
2150 pAct
->GetPoint(), pAct
->GetSize(),
2151 pAct
->GetGradient() )
2156 case( MetaActionType::EPS
):
2158 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
2159 GDIMetaFile
aSubst( pAct
->GetSubstitute() );
2161 aSubst
.ImplExchangeColors( pFncCol
, pColParam
, pFncBmp
, pBmpParam
);
2162 aMtf
.push_back( new MetaEPSAction( pAct
->GetPoint(), pAct
->GetSize(),
2163 pAct
->GetLink(), aSubst
)
2170 pAction
->Duplicate();
2171 aMtf
.push_back( pAction
);
2180 void GDIMetaFile::Adjust( short nLuminancePercent
, short nContrastPercent
,
2181 short nChannelRPercent
, short nChannelGPercent
,
2182 short nChannelBPercent
, double fGamma
, bool bInvert
, bool msoBrightness
)
2184 // nothing to do? => return quickly
2185 if( nLuminancePercent
|| nContrastPercent
||
2186 nChannelRPercent
|| nChannelGPercent
|| nChannelBPercent
||
2187 ( fGamma
!= 1.0 ) || bInvert
)
2189 double fM
, fROff
, fGOff
, fBOff
, fOff
;
2190 ImplColAdjustParam aColParam
;
2191 ImplBmpAdjustParam aBmpParam
;
2193 aColParam
.pMapR
= new sal_uInt8
[ 256 ];
2194 aColParam
.pMapG
= new sal_uInt8
[ 256 ];
2195 aColParam
.pMapB
= new sal_uInt8
[ 256 ];
2198 if( nContrastPercent
>= 0 )
2199 fM
= 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent
, 0L, 100L ) );
2201 fM
= ( 128.0 + 1.27 * MinMax( nContrastPercent
, -100L, 0L ) ) / 128.0;
2204 // total offset = luminance offset + contrast offset
2205 fOff
= MinMax( nLuminancePercent
, -100L, 100L ) * 2.55 + 128.0 - fM
* 128.0;
2207 fOff
= MinMax( nLuminancePercent
, -100L, 100L ) * 2.55;
2209 // channel offset = channel offset + total offset
2210 fROff
= nChannelRPercent
* 2.55 + fOff
;
2211 fGOff
= nChannelGPercent
* 2.55 + fOff
;
2212 fBOff
= nChannelBPercent
* 2.55 + fOff
;
2214 // calculate gamma value
2215 fGamma
= ( fGamma
<= 0.0 || fGamma
> 10.0 ) ? 1.0 : ( 1.0 / fGamma
);
2216 const bool bGamma
= ( fGamma
!= 1.0 );
2218 // create mapping table
2219 for( long nX
= 0L; nX
< 256L; nX
++ )
2223 aColParam
.pMapR
[ nX
] = (sal_uInt8
) MinMax( FRound( nX
* fM
+ fROff
), 0L, 255L );
2224 aColParam
.pMapG
[ nX
] = (sal_uInt8
) MinMax( FRound( nX
* fM
+ fGOff
), 0L, 255L );
2225 aColParam
.pMapB
[ nX
] = (sal_uInt8
) MinMax( FRound( nX
* fM
+ fBOff
), 0L, 255L );
2229 aColParam
.pMapR
[ nX
] = (sal_uInt8
) MinMax( FRound( (nX
+fROff
/2-128) * fM
+ 128 + fROff
/2 ), 0L, 255L );
2230 aColParam
.pMapG
[ nX
] = (sal_uInt8
) MinMax( FRound( (nX
+fGOff
/2-128) * fM
+ 128 + fGOff
/2 ), 0L, 255L );
2231 aColParam
.pMapB
[ nX
] = (sal_uInt8
) MinMax( FRound( (nX
+fBOff
/2-128) * fM
+ 128 + fBOff
/2 ), 0L, 255L );
2235 aColParam
.pMapR
[ nX
] = GAMMA( aColParam
.pMapR
[ nX
], fGamma
);
2236 aColParam
.pMapG
[ nX
] = GAMMA( aColParam
.pMapG
[ nX
], fGamma
);
2237 aColParam
.pMapB
[ nX
] = GAMMA( aColParam
.pMapB
[ nX
], fGamma
);
2242 aColParam
.pMapR
[ nX
] = ~aColParam
.pMapR
[ nX
];
2243 aColParam
.pMapG
[ nX
] = ~aColParam
.pMapG
[ nX
];
2244 aColParam
.pMapB
[ nX
] = ~aColParam
.pMapB
[ nX
];
2248 aBmpParam
.nLuminancePercent
= nLuminancePercent
;
2249 aBmpParam
.nContrastPercent
= nContrastPercent
;
2250 aBmpParam
.nChannelRPercent
= nChannelRPercent
;
2251 aBmpParam
.nChannelGPercent
= nChannelGPercent
;
2252 aBmpParam
.nChannelBPercent
= nChannelBPercent
;
2253 aBmpParam
.fGamma
= fGamma
;
2254 aBmpParam
.bInvert
= bInvert
;
2256 // do color adjustment
2257 ImplExchangeColors( ImplColAdjustFnc
, &aColParam
, ImplBmpAdjustFnc
, &aBmpParam
);
2259 delete[] aColParam
.pMapR
;
2260 delete[] aColParam
.pMapG
;
2261 delete[] aColParam
.pMapB
;
2265 void GDIMetaFile::Convert( MtfConversion eConversion
)
2267 // nothing to do? => return quickly
2268 if( eConversion
!= MTF_CONVERSION_NONE
)
2270 ImplColConvertParam aColParam
;
2271 ImplBmpConvertParam aBmpParam
;
2273 aColParam
.eConversion
= eConversion
;
2274 aBmpParam
.eConversion
= ( MTF_CONVERSION_1BIT_THRESHOLD
== eConversion
) ? BMP_CONVERSION_1BIT_THRESHOLD
: BMP_CONVERSION_8BIT_GREYS
;
2276 ImplExchangeColors( ImplColConvertFnc
, &aColParam
, ImplBmpConvertFnc
, &aBmpParam
);
2280 void GDIMetaFile::ReplaceColors( const Color
* pSearchColors
, const Color
* pReplaceColors
, sal_uLong nColorCount
, sal_uLong
* pTols
)
2282 ImplColReplaceParam aColParam
;
2283 ImplBmpReplaceParam aBmpParam
;
2285 aColParam
.pMinR
= new sal_uLong
[ nColorCount
];
2286 aColParam
.pMaxR
= new sal_uLong
[ nColorCount
];
2287 aColParam
.pMinG
= new sal_uLong
[ nColorCount
];
2288 aColParam
.pMaxG
= new sal_uLong
[ nColorCount
];
2289 aColParam
.pMinB
= new sal_uLong
[ nColorCount
];
2290 aColParam
.pMaxB
= new sal_uLong
[ nColorCount
];
2292 for( sal_uLong i
= 0; i
< nColorCount
; i
++ )
2294 const long nTol
= pTols
? ( pTols
[ i
] * 255 ) / 100 : 0;
2297 nVal
= pSearchColors
[ i
].GetRed();
2298 aColParam
.pMinR
[ i
] = (sal_uLong
) std::max( nVal
- nTol
, 0L );
2299 aColParam
.pMaxR
[ i
] = (sal_uLong
) std::min( nVal
+ nTol
, 255L );
2301 nVal
= pSearchColors
[ i
].GetGreen();
2302 aColParam
.pMinG
[ i
] = (sal_uLong
) std::max( nVal
- nTol
, 0L );
2303 aColParam
.pMaxG
[ i
] = (sal_uLong
) std::min( nVal
+ nTol
, 255L );
2305 nVal
= pSearchColors
[ i
].GetBlue();
2306 aColParam
.pMinB
[ i
] = (sal_uLong
) std::max( nVal
- nTol
, 0L );
2307 aColParam
.pMaxB
[ i
] = (sal_uLong
) std::min( nVal
+ nTol
, 255L );
2310 aColParam
.pDstCols
= pReplaceColors
;
2311 aColParam
.nCount
= nColorCount
;
2313 aBmpParam
.pSrcCols
= pSearchColors
;
2314 aBmpParam
.pDstCols
= pReplaceColors
;
2315 aBmpParam
.nCount
= nColorCount
;
2316 aBmpParam
.pTols
= pTols
;
2318 ImplExchangeColors( ImplColReplaceFnc
, &aColParam
, ImplBmpReplaceFnc
, &aBmpParam
);
2320 delete[] aColParam
.pMinR
;
2321 delete[] aColParam
.pMaxR
;
2322 delete[] aColParam
.pMinG
;
2323 delete[] aColParam
.pMaxG
;
2324 delete[] aColParam
.pMinB
;
2325 delete[] aColParam
.pMaxB
;
2328 GDIMetaFile
GDIMetaFile::GetMonochromeMtf( const Color
& rColor
) const
2330 GDIMetaFile
aRet( *this );
2332 ImplColMonoParam aColParam
;
2333 ImplBmpMonoParam aBmpParam
;
2335 aColParam
.aColor
= rColor
;
2336 aBmpParam
.aColor
= rColor
;
2338 aRet
.ImplExchangeColors( ImplColMonoFnc
, &aColParam
, ImplBmpMonoFnc
, &aBmpParam
);
2343 BitmapChecksum
GDIMetaFile::GetChecksum() const
2346 SvMemoryStream
aMemStm( 65535, 65535 );
2347 ImplMetaWriteData aWriteData
;
2350 BitmapChecksumOctetArray aBCOA
;
2351 BitmapChecksum nCrc
= 0;
2353 aWriteData
.meActualCharSet
= aMemStm
.GetStreamCharSet();
2354 for( size_t i
= 0, nObjCount
= GetActionSize(); i
< nObjCount
; i
++ )
2356 MetaAction
* pAction
= GetAction( i
);
2358 switch( pAction
->GetType() )
2360 case( MetaActionType::BMP
):
2362 MetaBmpAction
* pAct
= static_cast<MetaBmpAction
*>(pAction
);
2364 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2365 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2367 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2368 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2370 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2371 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2373 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2374 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2378 case( MetaActionType::BMPSCALE
):
2380 MetaBmpScaleAction
* pAct
= static_cast<MetaBmpScaleAction
*>(pAction
);
2382 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2383 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2385 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2386 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2388 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2389 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2391 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2392 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2394 UInt32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2395 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2397 UInt32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2398 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2402 case( MetaActionType::BMPSCALEPART
):
2404 MetaBmpScalePartAction
* pAct
= static_cast<MetaBmpScalePartAction
*>(pAction
);
2406 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2407 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2409 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2410 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2412 UInt32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2413 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2415 UInt32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2416 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2418 UInt32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2419 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2421 UInt32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2422 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2424 UInt32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2425 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2427 UInt32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2428 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2430 UInt32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2431 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2433 UInt32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2434 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2438 case( MetaActionType::BMPEX
):
2440 MetaBmpExAction
* pAct
= static_cast<MetaBmpExAction
*>(pAction
);
2442 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2443 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2445 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2446 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2448 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2449 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2451 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2452 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2456 case( MetaActionType::BMPEXSCALE
):
2458 MetaBmpExScaleAction
* pAct
= static_cast<MetaBmpExScaleAction
*>(pAction
);
2460 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2461 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2463 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2464 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2466 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2467 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2469 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2470 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2472 UInt32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2473 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2475 UInt32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2476 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2480 case( MetaActionType::BMPEXSCALEPART
):
2482 MetaBmpExScalePartAction
* pAct
= static_cast<MetaBmpExScalePartAction
*>(pAction
);
2484 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2485 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2487 BCToBCOA( pAct
->GetBitmapEx().GetChecksum(), aBCOA
);
2488 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2490 UInt32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2491 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2493 UInt32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2494 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2496 UInt32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2497 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2499 UInt32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2500 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2502 UInt32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2503 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2505 UInt32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2506 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2508 UInt32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2509 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2511 UInt32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2512 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2516 case( MetaActionType::MASK
):
2518 MetaMaskAction
* pAct
= static_cast<MetaMaskAction
*>(pAction
);
2520 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2521 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2523 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2524 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2526 UInt32ToSVBT32( pAct
->GetColor().GetColor(), aBT32
);
2527 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2529 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2530 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2532 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2533 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2537 case( MetaActionType::MASKSCALE
):
2539 MetaMaskScaleAction
* pAct
= static_cast<MetaMaskScaleAction
*>(pAction
);
2541 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2542 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2544 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2545 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2547 UInt32ToSVBT32( pAct
->GetColor().GetColor(), aBT32
);
2548 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2550 UInt32ToSVBT32( pAct
->GetPoint().X(), aBT32
);
2551 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2553 UInt32ToSVBT32( pAct
->GetPoint().Y(), aBT32
);
2554 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2556 UInt32ToSVBT32( pAct
->GetSize().Width(), aBT32
);
2557 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2559 UInt32ToSVBT32( pAct
->GetSize().Height(), aBT32
);
2560 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2564 case( MetaActionType::MASKSCALEPART
):
2566 MetaMaskScalePartAction
* pAct
= static_cast<MetaMaskScalePartAction
*>(pAction
);
2568 ShortToSVBT16( static_cast<sal_uInt16
>(pAct
->GetType()), aBT16
);
2569 nCrc
= vcl_get_checksum( nCrc
, aBT16
, 2 );
2571 BCToBCOA( pAct
->GetBitmap().GetChecksum(), aBCOA
);
2572 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
2574 UInt32ToSVBT32( pAct
->GetColor().GetColor(), aBT32
);
2575 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2577 UInt32ToSVBT32( pAct
->GetDestPoint().X(), aBT32
);
2578 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2580 UInt32ToSVBT32( pAct
->GetDestPoint().Y(), aBT32
);
2581 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2583 UInt32ToSVBT32( pAct
->GetDestSize().Width(), aBT32
);
2584 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2586 UInt32ToSVBT32( pAct
->GetDestSize().Height(), aBT32
);
2587 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2589 UInt32ToSVBT32( pAct
->GetSrcPoint().X(), aBT32
);
2590 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2592 UInt32ToSVBT32( pAct
->GetSrcPoint().Y(), aBT32
);
2593 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2595 UInt32ToSVBT32( pAct
->GetSrcSize().Width(), aBT32
);
2596 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2598 UInt32ToSVBT32( pAct
->GetSrcSize().Height(), aBT32
);
2599 nCrc
= vcl_get_checksum( nCrc
, aBT32
, 4 );
2603 case MetaActionType::EPS
:
2605 MetaEPSAction
* pAct
= static_cast<MetaEPSAction
*>(pAction
);
2606 nCrc
= vcl_get_checksum( nCrc
, pAct
->GetLink().GetData(), pAct
->GetLink().GetDataSize() );
2610 case MetaActionType::CLIPREGION
:
2612 MetaClipRegionAction
& rAct
= static_cast<MetaClipRegionAction
&>(*pAction
);
2613 const vcl::Region
& rRegion
= rAct
.GetRegion();
2615 if(rRegion
.HasPolyPolygonOrB2DPolyPolygon())
2617 // It has shown that this is a possible bottleneck for checksum calculation.
2618 // In worst case a very expensive RegionHandle representation gets created.
2619 // In this case it's cheaper to use the PolyPolygon
2620 const basegfx::B2DPolyPolygon
aPolyPolygon(rRegion
.GetAsB2DPolyPolygon());
2621 const sal_uInt32
nPolyCount(aPolyPolygon
.count());
2624 for(sal_uInt32
a(0); a
< nPolyCount
; a
++)
2626 const basegfx::B2DPolygon
aPolygon(aPolyPolygon
.getB2DPolygon(a
));
2627 const sal_uInt32
nPointCount(aPolygon
.count());
2628 const bool bControl(aPolygon
.areControlPointsUsed());
2630 for(sal_uInt32
b(0); b
< nPointCount
; b
++)
2632 const basegfx::B2DPoint
aPoint(aPolygon
.getB2DPoint(b
));
2634 DoubleToSVBT64(aPoint
.getX(), aSVBT64
);
2635 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2636 DoubleToSVBT64(aPoint
.getY(), aSVBT64
);
2637 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2641 if(aPolygon
.isPrevControlPointUsed(b
))
2643 const basegfx::B2DPoint
aCtrl(aPolygon
.getPrevControlPoint(b
));
2645 DoubleToSVBT64(aCtrl
.getX(), aSVBT64
);
2646 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2647 DoubleToSVBT64(aCtrl
.getY(), aSVBT64
);
2648 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2651 if(aPolygon
.isNextControlPointUsed(b
))
2653 const basegfx::B2DPoint
aCtrl(aPolygon
.getNextControlPoint(b
));
2655 DoubleToSVBT64(aCtrl
.getX(), aSVBT64
);
2656 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2657 DoubleToSVBT64(aCtrl
.getY(), aSVBT64
);
2658 nCrc
= vcl_get_checksum(nCrc
, aSVBT64
, 8);
2664 sal_uInt8 tmp
= (sal_uInt8
)rAct
.IsClipping();
2665 nCrc
= vcl_get_checksum(nCrc
, &tmp
, 1);
2669 pAction
->Write( aMemStm
, &aWriteData
);
2670 nCrc
= vcl_get_checksum( nCrc
, aMemStm
.GetData(), aMemStm
.Tell() );
2678 pAction
->Write( aMemStm
, &aWriteData
);
2679 nCrc
= vcl_get_checksum( nCrc
, aMemStm
.GetData(), aMemStm
.Tell() );
2689 sal_uLong
GDIMetaFile::GetSizeBytes() const
2691 sal_uLong nSizeBytes
= 0;
2693 for( size_t i
= 0, nObjCount
= GetActionSize(); i
< nObjCount
; ++i
)
2695 MetaAction
* pAction
= GetAction( i
);
2697 // default action size is set to 32 (=> not the exact value)
2700 // add sizes for large action content
2701 switch( pAction
->GetType() )
2703 case( MetaActionType::BMP
): nSizeBytes
+= static_cast<MetaBmpAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2704 case( MetaActionType::BMPSCALE
): nSizeBytes
+= static_cast<MetaBmpScaleAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2705 case( MetaActionType::BMPSCALEPART
): nSizeBytes
+= static_cast<MetaBmpScalePartAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2707 case( MetaActionType::BMPEX
): nSizeBytes
+= static_cast<MetaBmpExAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2708 case( MetaActionType::BMPEXSCALE
): nSizeBytes
+= static_cast<MetaBmpExScaleAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2709 case( MetaActionType::BMPEXSCALEPART
): nSizeBytes
+= static_cast<MetaBmpExScalePartAction
*>( pAction
)->GetBitmapEx().GetSizeBytes(); break;
2711 case( MetaActionType::MASK
): nSizeBytes
+= static_cast<MetaMaskAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2712 case( MetaActionType::MASKSCALE
): nSizeBytes
+= static_cast<MetaMaskScaleAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2713 case( MetaActionType::MASKSCALEPART
): nSizeBytes
+= static_cast<MetaMaskScalePartAction
*>( pAction
)->GetBitmap().GetSizeBytes(); break;
2715 case( MetaActionType::POLYLINE
): nSizeBytes
+= static_cast<MetaPolyLineAction
*>( pAction
)->GetPolygon().GetSize() * sizeof( Point
); break;
2716 case( MetaActionType::POLYGON
): nSizeBytes
+= static_cast<MetaPolygonAction
*>( pAction
)->GetPolygon().GetSize() * sizeof( Point
); break;
2717 case( MetaActionType::POLYPOLYGON
):
2719 const tools::PolyPolygon
& rPolyPoly
= static_cast<MetaPolyPolygonAction
*>( pAction
)->GetPolyPolygon();
2721 for( sal_uInt16 n
= 0; n
< rPolyPoly
.Count(); ++n
)
2722 nSizeBytes
+= ( rPolyPoly
[ n
].GetSize() * sizeof( Point
) );
2726 case( MetaActionType::TEXT
): nSizeBytes
+= static_cast<MetaTextAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2727 case( MetaActionType::STRETCHTEXT
): nSizeBytes
+= static_cast<MetaStretchTextAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2728 case( MetaActionType::TEXTRECT
): nSizeBytes
+= static_cast<MetaTextRectAction
*>( pAction
)->GetText().getLength() * sizeof( sal_Unicode
); break;
2729 case( MetaActionType::TEXTARRAY
):
2731 MetaTextArrayAction
* pTextArrayAction
= static_cast<MetaTextArrayAction
*>(pAction
);
2733 nSizeBytes
+= ( pTextArrayAction
->GetText().getLength() * sizeof( sal_Unicode
) );
2735 if( pTextArrayAction
->GetDXArray() )
2736 nSizeBytes
+= ( pTextArrayAction
->GetLen() << 2 );
2746 SvStream
& ReadGDIMetaFile( SvStream
& rIStm
, GDIMetaFile
& rGDIMetaFile
)
2748 if( !rIStm
.GetError() )
2751 sal_uLong nStmPos
= rIStm
.Tell();
2752 SvStreamEndian nOldFormat
= rIStm
.GetEndian();
2754 rIStm
.SetEndian( SvStreamEndian::LITTLE
);
2758 rIStm
.Read( aId
, 6 );
2760 if ( !strcmp( aId
, "VCLMTF" ) )
2763 VersionCompat
* pCompat
;
2764 MetaAction
* pAction
;
2765 sal_uInt32 nStmCompressMode
= 0;
2766 sal_uInt32 nCount
= 0;
2768 pCompat
= new VersionCompat( rIStm
, StreamMode::READ
);
2770 rIStm
.ReadUInt32( nStmCompressMode
);
2771 ReadMapMode( rIStm
, rGDIMetaFile
.aPrefMapMode
);
2772 ReadPair( rIStm
, rGDIMetaFile
.aPrefSize
);
2773 rIStm
.ReadUInt32( nCount
);
2777 ImplMetaReadData aReadData
;
2778 aReadData
.meActualCharSet
= rIStm
.GetStreamCharSet();
2780 for( sal_uInt32 nAction
= 0UL; ( nAction
< nCount
) && !rIStm
.IsEof(); nAction
++ )
2782 pAction
= MetaAction::ReadMetaAction( rIStm
, &aReadData
);
2786 if (pAction
->GetType() == MetaActionType::COMMENT
)
2788 MetaCommentAction
* pCommentAct
= static_cast<MetaCommentAction
*>(pAction
);
2789 if ( pCommentAct
->GetComment() == "EMF_PLUS" )
2790 rGDIMetaFile
.UseCanvas( true );
2792 rGDIMetaFile
.AddAction( pAction
);
2798 // to avoid possible compiler optimizations => new/delete
2799 rIStm
.Seek( nStmPos
);
2800 delete( new SVMConverter( rIStm
, rGDIMetaFile
, CONVERT_FROM_SVM1
) );
2804 if( rIStm
.GetError() )
2806 rGDIMetaFile
.Clear();
2807 rIStm
.Seek( nStmPos
);
2810 rIStm
.SetEndian( nOldFormat
);
2814 SAL_WARN("vcl.gdi", "Stream error: " << rIStm
.GetError());
2820 SvStream
& WriteGDIMetaFile( SvStream
& rOStm
, const GDIMetaFile
& rGDIMetaFile
)
2822 if( !rOStm
.GetError() )
2824 static const char* pEnableSVM1
= getenv( "SAL_ENABLE_SVM1" );
2825 static const bool bNoSVM1
= (NULL
== pEnableSVM1
) || ( '0' == *pEnableSVM1
);
2827 if( bNoSVM1
|| rOStm
.GetVersion() >= SOFFICE_FILEFORMAT_50
)
2829 const_cast< GDIMetaFile
& >( rGDIMetaFile
).Write( rOStm
);
2833 delete( new SVMConverter( rOStm
, const_cast< GDIMetaFile
& >( rGDIMetaFile
), CONVERT_TO_SVM1
) );
2837 if( !bNoSVM1
&& rOStm
.GetVersion() < SOFFICE_FILEFORMAT_50
)
2840 "GDIMetaFile would normally be written in old SVM1 format by this call. \
2841 The current implementation always writes in VCLMTF format. \
2842 Please set environment variable SAL_ENABLE_SVM1 to '1' to reenable old behavior" );
2850 SvStream
& GDIMetaFile::Read( SvStream
& rIStm
)
2853 ReadGDIMetaFile( rIStm
, *this );
2858 SvStream
& GDIMetaFile::Write( SvStream
& rOStm
)
2860 VersionCompat
* pCompat
;
2861 const SvStreamCompressFlags nStmCompressMode
= rOStm
.GetCompressMode();
2862 SvStreamEndian nOldFormat
= rOStm
.GetEndian();
2864 rOStm
.SetEndian( SvStreamEndian::LITTLE
);
2865 rOStm
.Write( "VCLMTF", 6 );
2867 pCompat
= new VersionCompat( rOStm
, StreamMode::WRITE
, 1 );
2869 rOStm
.WriteUInt32( static_cast<sal_uInt32
>(nStmCompressMode
) );
2870 WriteMapMode( rOStm
, aPrefMapMode
);
2871 WritePair( rOStm
, aPrefSize
);
2872 rOStm
.WriteUInt32( GetActionSize() );
2876 ImplMetaWriteData aWriteData
;
2878 aWriteData
.meActualCharSet
= rOStm
.GetStreamCharSet();
2880 MetaAction
* pAct
= FirstAction();
2883 pAct
->Write( rOStm
, &aWriteData
);
2884 pAct
= NextAction();
2887 rOStm
.SetEndian( nOldFormat
);
2892 bool GDIMetaFile::CreateThumbnail(BitmapEx
& rBitmapEx
, sal_uInt32 nMaximumExtent
, BmpConversion eColorConversion
, BmpScaleFlag nScaleFlag
) const
2894 // initialization seems to be complicated but is used to avoid rounding errors
2895 ScopedVclPtrInstance
< VirtualDevice
> aVDev
;
2896 const Point aNullPt
;
2897 const Point
aTLPix( aVDev
->LogicToPixel( aNullPt
, GetPrefMapMode() ) );
2898 const Point
aBRPix( aVDev
->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2899 Size
aDrawSize( aVDev
->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2900 Size
aSizePix( labs( aBRPix
.X() - aTLPix
.X() ) + 1, labs( aBRPix
.Y() - aTLPix
.Y() ) + 1 );
2902 if (!rBitmapEx
.IsEmpty())
2903 rBitmapEx
.SetEmpty();
2905 // determine size that has the same aspect ratio as image size and
2906 // fits into the rectangle determined by nMaximumExtent
2907 if ( aSizePix
.Width() && aSizePix
.Height()
2908 && ( sal::static_int_cast
< unsigned long >(aSizePix
.Width()) >
2910 sal::static_int_cast
< unsigned long >(aSizePix
.Height()) >
2913 const Size
aOldSizePix( aSizePix
);
2914 double fWH
= static_cast< double >( aSizePix
.Width() ) / aSizePix
.Height();
2918 aSizePix
.Width() = FRound( nMaximumExtent
* fWH
);
2919 aSizePix
.Height() = nMaximumExtent
;
2923 aSizePix
.Width() = nMaximumExtent
;
2924 aSizePix
.Height() = FRound( nMaximumExtent
/ fWH
);
2927 aDrawSize
.Width() = FRound( ( static_cast< double >( aDrawSize
.Width() ) * aSizePix
.Width() ) / aOldSizePix
.Width() );
2928 aDrawSize
.Height() = FRound( ( static_cast< double >( aDrawSize
.Height() ) * aSizePix
.Height() ) / aOldSizePix
.Height() );
2931 // draw image(s) into VDev and get resulting image
2932 // do it 4x larger to be able to scale it down & get beautiful antialias
2933 Size
aAntialiasSize(aSizePix
.Width() * 4, aSizePix
.Height() * 4);
2934 if (aVDev
->SetOutputSizePixel(aAntialiasSize
))
2936 // antialias: provide 4x larger size, and then scale down the result
2937 Size
aAntialias(aDrawSize
.Width() * 4, aDrawSize
.Height() * 4);
2939 // draw metafile into VDev
2941 const_cast<GDIMetaFile
*>(this)->WindStart();
2942 const_cast<GDIMetaFile
*>(this)->Play(aVDev
.get(), aBackPosPix
, aAntialias
);
2945 Bitmap
aBitmap( aVDev
->GetBitmap( aNullPt
, aVDev
->GetOutputSizePixel() ) );
2947 // scale down the image to the desired size - use the input scaler for the scaling operation
2948 aBitmap
.Scale(aDrawSize
, nScaleFlag
);
2950 // convert to desired bitmap color format
2951 aBitmap
.Convert(eColorConversion
);
2953 rBitmapEx
= BitmapEx(aBitmap
);
2956 return !rBitmapEx
.IsEmpty();
2959 void GDIMetaFile::UseCanvas( bool _bUseCanvas
)
2961 bUseCanvas
= _bUseCanvas
;
2964 MetaCommentAction
* makePluggableRendererAction( const OUString
& rRendererServiceName
,
2965 const OUString
& rGraphicServiceName
,
2967 sal_uInt32 nDataSize
)
2969 const sal_uInt8
* pData
=static_cast<sal_uInt8
const *>(_pData
);
2971 // FIXME: Data gets copied twice, unfortunately
2972 OString
aRendererServiceName(
2973 rRendererServiceName
.getStr(),
2974 rRendererServiceName
.getLength(),
2975 RTL_TEXTENCODING_ASCII_US
);
2976 OString
aGraphicServiceName(
2977 rGraphicServiceName
.getStr(),
2978 rGraphicServiceName
.getLength(),
2979 RTL_TEXTENCODING_ASCII_US
);
2981 std::vector
<sal_uInt8
> aMem(
2982 aRendererServiceName
.getLength()+
2983 aGraphicServiceName
.getLength()+2+nDataSize
);
2984 sal_uInt8
* pMem
=&aMem
[0];
2986 std::copy(aRendererServiceName
.getStr(),
2987 aRendererServiceName
.getStr()+aRendererServiceName
.getLength()+1,
2989 pMem
+=aRendererServiceName
.getLength()+1;
2990 std::copy(aGraphicServiceName
.getStr(),
2991 aGraphicServiceName
.getStr()+aGraphicServiceName
.getLength()+1,
2993 pMem
+=aGraphicServiceName
.getLength()+1;
2995 std::copy(pData
,pData
+nDataSize
,
2998 return new MetaCommentAction(
2999 "DELEGATE_PLUGGABLE_RENDERER",
3005 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */