xref: /AOO41X/main/vcl/source/gdi/gdimtf.cxx (revision 9f62ea84a806e17e6f2bbff75724a7257a0eb5d9)
1*9f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*9f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*9f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*9f62ea84SAndrew Rist  * distributed with this work for additional information
6*9f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*9f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*9f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
9*9f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*9f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*9f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*9f62ea84SAndrew Rist  * software distributed under the License is distributed on an
15*9f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
17*9f62ea84SAndrew Rist  * specific language governing permissions and limitations
18*9f62ea84SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*9f62ea84SAndrew Rist  *************************************************************/
21*9f62ea84SAndrew Rist 
22*9f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir #include <vos/macros.hxx>
27cdf0e10cSrcweir #include <rtl/crc.h>
28cdf0e10cSrcweir #include <tools/stream.hxx>
29cdf0e10cSrcweir #include <tools/vcompat.hxx>
30cdf0e10cSrcweir #include <vcl/metaact.hxx>
31cdf0e10cSrcweir #include <vcl/salbtype.hxx>
32cdf0e10cSrcweir #include <vcl/outdev.hxx>
33cdf0e10cSrcweir #include <vcl/window.hxx>
34cdf0e10cSrcweir #ifndef _SV_CVTSVM_HXX
35cdf0e10cSrcweir #include <vcl/cvtsvm.hxx>
36cdf0e10cSrcweir #endif
37cdf0e10cSrcweir #include <vcl/virdev.hxx>
38cdf0e10cSrcweir #include <vcl/gdimtf.hxx>
39cdf0e10cSrcweir #include <vcl/graphictools.hxx>
40cdf0e10cSrcweir 
41cdf0e10cSrcweir // -----------
42cdf0e10cSrcweir // - Defines -
43cdf0e10cSrcweir // -----------
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #define GAMMA( _def_cVal, _def_InvGamma )	((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
46cdf0e10cSrcweir 
47cdf0e10cSrcweir // --------------------------
48cdf0e10cSrcweir // - Color exchange structs -
49cdf0e10cSrcweir // --------------------------
50cdf0e10cSrcweir 
51cdf0e10cSrcweir struct ImplColAdjustParam
52cdf0e10cSrcweir {
53cdf0e10cSrcweir 	sal_uInt8*	pMapR;
54cdf0e10cSrcweir 	sal_uInt8*	pMapG;
55cdf0e10cSrcweir 	sal_uInt8*	pMapB;
56cdf0e10cSrcweir };
57cdf0e10cSrcweir 
58cdf0e10cSrcweir struct ImplBmpAdjustParam
59cdf0e10cSrcweir {
60cdf0e10cSrcweir 	short	nLuminancePercent;
61cdf0e10cSrcweir 	short	nContrastPercent;
62cdf0e10cSrcweir 	short	nChannelRPercent;
63cdf0e10cSrcweir 	short	nChannelGPercent;
64cdf0e10cSrcweir 	short	nChannelBPercent;
65cdf0e10cSrcweir 	double	fGamma;
66cdf0e10cSrcweir 	sal_Bool	bInvert;
67cdf0e10cSrcweir };
68cdf0e10cSrcweir 
69cdf0e10cSrcweir // -----------------------------------------------------------------------------
70cdf0e10cSrcweir 
71cdf0e10cSrcweir struct ImplColConvertParam
72cdf0e10cSrcweir {
73cdf0e10cSrcweir 	MtfConversion	eConversion;
74cdf0e10cSrcweir };
75cdf0e10cSrcweir 
76cdf0e10cSrcweir struct ImplBmpConvertParam
77cdf0e10cSrcweir {
78cdf0e10cSrcweir 	BmpConversion	eConversion;
79cdf0e10cSrcweir };
80cdf0e10cSrcweir 
81cdf0e10cSrcweir // -----------------------------------------------------------------------------
82cdf0e10cSrcweir 
83cdf0e10cSrcweir struct ImplColMonoParam
84cdf0e10cSrcweir {
85cdf0e10cSrcweir 	Color aColor;
86cdf0e10cSrcweir };
87cdf0e10cSrcweir 
88cdf0e10cSrcweir struct ImplBmpMonoParam
89cdf0e10cSrcweir {
90cdf0e10cSrcweir 	Color aColor;
91cdf0e10cSrcweir };
92cdf0e10cSrcweir 
93cdf0e10cSrcweir // -----------------------------------------------------------------------------
94cdf0e10cSrcweir 
95cdf0e10cSrcweir struct ImplColReplaceParam
96cdf0e10cSrcweir {
97cdf0e10cSrcweir 	sal_uLong*			pMinR;
98cdf0e10cSrcweir 	sal_uLong*			pMaxR;
99cdf0e10cSrcweir 	sal_uLong*			pMinG;
100cdf0e10cSrcweir 	sal_uLong*			pMaxG;
101cdf0e10cSrcweir 	sal_uLong*			pMinB;
102cdf0e10cSrcweir 	sal_uLong*			pMaxB;
103cdf0e10cSrcweir 	const Color*	pDstCols;
104cdf0e10cSrcweir 	sal_uLong			nCount;
105cdf0e10cSrcweir };
106cdf0e10cSrcweir 
107cdf0e10cSrcweir struct ImplBmpReplaceParam
108cdf0e10cSrcweir {
109cdf0e10cSrcweir 	const Color*	pSrcCols;
110cdf0e10cSrcweir 	const Color*	pDstCols;
111cdf0e10cSrcweir 	sal_uLong			nCount;
112cdf0e10cSrcweir 	const sal_uLong*	pTols;
113cdf0e10cSrcweir };
114cdf0e10cSrcweir 
115cdf0e10cSrcweir 
116cdf0e10cSrcweir // ---------
117cdf0e10cSrcweir // - Label -
118cdf0e10cSrcweir // ---------
119cdf0e10cSrcweir 
120cdf0e10cSrcweir struct ImpLabel
121cdf0e10cSrcweir {
122cdf0e10cSrcweir 	String	aLabelName;
123cdf0e10cSrcweir 	sal_uLong	nActionPos;
124cdf0e10cSrcweir 
125cdf0e10cSrcweir 			ImpLabel( const String& rLabelName, sal_uLong _nActionPos ) :
126cdf0e10cSrcweir 				aLabelName( rLabelName ),
127cdf0e10cSrcweir 				nActionPos( _nActionPos ) {}
128cdf0e10cSrcweir };
129cdf0e10cSrcweir 
130cdf0e10cSrcweir // -------------
131cdf0e10cSrcweir // - LabelList -
132cdf0e10cSrcweir // -------------
133cdf0e10cSrcweir 
134cdf0e10cSrcweir class ImpLabelList : private List
135cdf0e10cSrcweir {
136cdf0e10cSrcweir public:
137cdf0e10cSrcweir 
138cdf0e10cSrcweir 				ImpLabelList() : List( 8, 4, 4 ) {}
139cdf0e10cSrcweir 				ImpLabelList( const ImpLabelList& rList );
140cdf0e10cSrcweir 				~ImpLabelList();
141cdf0e10cSrcweir 
142cdf0e10cSrcweir 	void		ImplInsert( ImpLabel* p ) { Insert( p, LIST_APPEND ); }
143cdf0e10cSrcweir 	ImpLabel*	ImplRemove( sal_uLong nPos ) { return (ImpLabel*) Remove( nPos ); }
144cdf0e10cSrcweir 	void		ImplReplace( ImpLabel* p ) { Replace( (void*)p ); }
145cdf0e10cSrcweir 	ImpLabel*	ImplFirst() { return (ImpLabel*) First(); }
146cdf0e10cSrcweir 	ImpLabel*	ImplNext() { return (ImpLabel*) Next(); }
147cdf0e10cSrcweir 	ImpLabel*	ImplGetLabel( sal_uLong nPos ) const { return (ImpLabel*) GetObject( nPos ); }
148cdf0e10cSrcweir 	sal_uLong		ImplGetLabelPos( const String& rLabelName );
149cdf0e10cSrcweir 	sal_uLong		ImplCount() const { return Count(); }
150cdf0e10cSrcweir };
151cdf0e10cSrcweir 
152cdf0e10cSrcweir // ------------------------------------------------------------------------
153cdf0e10cSrcweir 
154cdf0e10cSrcweir ImpLabelList::ImpLabelList( const ImpLabelList& rList ) :
155cdf0e10cSrcweir 		List( rList )
156cdf0e10cSrcweir {
157cdf0e10cSrcweir 	for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
158cdf0e10cSrcweir 		ImplReplace( new ImpLabel( *pLabel ) );
159cdf0e10cSrcweir }
160cdf0e10cSrcweir 
161cdf0e10cSrcweir // ------------------------------------------------------------------------
162cdf0e10cSrcweir 
163cdf0e10cSrcweir ImpLabelList::~ImpLabelList()
164cdf0e10cSrcweir {
165cdf0e10cSrcweir 	for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
166cdf0e10cSrcweir 		delete pLabel;
167cdf0e10cSrcweir }
168cdf0e10cSrcweir 
169cdf0e10cSrcweir // ------------------------------------------------------------------------
170cdf0e10cSrcweir 
171cdf0e10cSrcweir sal_uLong ImpLabelList::ImplGetLabelPos( const String& rLabelName )
172cdf0e10cSrcweir {
173cdf0e10cSrcweir 	sal_uLong nLabelPos = METAFILE_LABEL_NOTFOUND;
174cdf0e10cSrcweir 
175cdf0e10cSrcweir 	for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
176cdf0e10cSrcweir 	{
177cdf0e10cSrcweir 		if ( rLabelName == pLabel->aLabelName )
178cdf0e10cSrcweir 		{
179cdf0e10cSrcweir 			nLabelPos = GetCurPos();
180cdf0e10cSrcweir 			break;
181cdf0e10cSrcweir 		}
182cdf0e10cSrcweir 	}
183cdf0e10cSrcweir 
184cdf0e10cSrcweir 	return nLabelPos;
185cdf0e10cSrcweir }
186cdf0e10cSrcweir 
187cdf0e10cSrcweir // ---------------
188cdf0e10cSrcweir // - GDIMetaFile -
189cdf0e10cSrcweir // ---------------
190cdf0e10cSrcweir 
191cdf0e10cSrcweir GDIMetaFile::GDIMetaFile() :
192cdf0e10cSrcweir 	List		( 0x3EFF, 64, 64 ),
193cdf0e10cSrcweir 	aPrefSize	( 1, 1 ),
194cdf0e10cSrcweir 	pPrev		( NULL ),
195cdf0e10cSrcweir 	pNext		( NULL ),
196cdf0e10cSrcweir 	pOutDev 	( NULL ),
197cdf0e10cSrcweir 	pLabelList	( NULL ),
198cdf0e10cSrcweir 	bPause		( sal_False ),
199cdf0e10cSrcweir 	bRecord 	( sal_False )
200cdf0e10cSrcweir {
201cdf0e10cSrcweir }
202cdf0e10cSrcweir 
203cdf0e10cSrcweir // ------------------------------------------------------------------------
204cdf0e10cSrcweir 
205cdf0e10cSrcweir GDIMetaFile::GDIMetaFile( const GDIMetaFile& rMtf ) :
206cdf0e10cSrcweir 	List			( rMtf ),
207cdf0e10cSrcweir 	aPrefMapMode	( rMtf.aPrefMapMode ),
208cdf0e10cSrcweir 	aPrefSize		( rMtf.aPrefSize ),
209cdf0e10cSrcweir 	aHookHdlLink	( rMtf.aHookHdlLink ),
210cdf0e10cSrcweir 	pPrev			( rMtf.pPrev ),
211cdf0e10cSrcweir 	pNext			( rMtf.pNext ),
212cdf0e10cSrcweir 	pOutDev 		( NULL ),
213cdf0e10cSrcweir 	bPause			( sal_False ),
214cdf0e10cSrcweir 	bRecord 		( sal_False )
215cdf0e10cSrcweir {
216cdf0e10cSrcweir 	// RefCount der MetaActions erhoehen
217cdf0e10cSrcweir 	for( void* pAct = First(); pAct; pAct = Next() )
218cdf0e10cSrcweir 		( (MetaAction*) pAct )->Duplicate();
219cdf0e10cSrcweir 
220cdf0e10cSrcweir 	if( rMtf.pLabelList )
221cdf0e10cSrcweir 		pLabelList = new ImpLabelList( *rMtf.pLabelList );
222cdf0e10cSrcweir 	else
223cdf0e10cSrcweir 		pLabelList = NULL;
224cdf0e10cSrcweir 
225cdf0e10cSrcweir 	if( rMtf.bRecord )
226cdf0e10cSrcweir 	{
227cdf0e10cSrcweir 		Record( rMtf.pOutDev );
228cdf0e10cSrcweir 
229cdf0e10cSrcweir 		if ( rMtf.bPause )
230cdf0e10cSrcweir 			Pause( sal_True );
231cdf0e10cSrcweir 	}
232cdf0e10cSrcweir }
233cdf0e10cSrcweir 
234cdf0e10cSrcweir // ------------------------------------------------------------------------
235cdf0e10cSrcweir 
236cdf0e10cSrcweir GDIMetaFile::~GDIMetaFile()
237cdf0e10cSrcweir {
238cdf0e10cSrcweir 	Clear();
239cdf0e10cSrcweir }
240cdf0e10cSrcweir 
241cdf0e10cSrcweir // ------------------------------------------------------------------------
242cdf0e10cSrcweir 
243cdf0e10cSrcweir GDIMetaFile& GDIMetaFile::operator=( const GDIMetaFile& rMtf )
244cdf0e10cSrcweir {
245cdf0e10cSrcweir 	if( this != &rMtf )
246cdf0e10cSrcweir 	{
247cdf0e10cSrcweir 		Clear();
248cdf0e10cSrcweir 
249cdf0e10cSrcweir 		List::operator=( rMtf );
250cdf0e10cSrcweir 
251cdf0e10cSrcweir 		// RefCount der MetaActions erhoehen
252cdf0e10cSrcweir 		for( void* pAct = First(); pAct; pAct = Next() )
253cdf0e10cSrcweir 			( (MetaAction*) pAct )->Duplicate();
254cdf0e10cSrcweir 
255cdf0e10cSrcweir 		if( rMtf.pLabelList )
256cdf0e10cSrcweir 			pLabelList = new ImpLabelList( *rMtf.pLabelList );
257cdf0e10cSrcweir 		else
258cdf0e10cSrcweir 		   pLabelList = NULL;
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 		aPrefMapMode = rMtf.aPrefMapMode;
261cdf0e10cSrcweir 		aPrefSize = rMtf.aPrefSize;
262cdf0e10cSrcweir 		aHookHdlLink = rMtf.aHookHdlLink;
263cdf0e10cSrcweir 		pPrev = rMtf.pPrev;
264cdf0e10cSrcweir 		pNext = rMtf.pNext;
265cdf0e10cSrcweir 		pOutDev = NULL;
266cdf0e10cSrcweir 		bPause = sal_False;
267cdf0e10cSrcweir 		bRecord = sal_False;
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 		if( rMtf.bRecord )
270cdf0e10cSrcweir 		{
271cdf0e10cSrcweir 			Record( rMtf.pOutDev );
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 			if( rMtf.bPause )
274cdf0e10cSrcweir 				Pause( sal_True );
275cdf0e10cSrcweir 		}
276cdf0e10cSrcweir 	}
277cdf0e10cSrcweir 
278cdf0e10cSrcweir 	return *this;
279cdf0e10cSrcweir }
280cdf0e10cSrcweir 
281cdf0e10cSrcweir // ------------------------------------------------------------------------
282cdf0e10cSrcweir 
283cdf0e10cSrcweir sal_Bool GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const
284cdf0e10cSrcweir {
285cdf0e10cSrcweir 	const sal_uLong nObjCount = Count();
286cdf0e10cSrcweir 	sal_Bool		bRet = sal_False;
287cdf0e10cSrcweir 
288cdf0e10cSrcweir 	if( this == &rMtf )
289cdf0e10cSrcweir 		bRet = sal_True;
290cdf0e10cSrcweir 	else if( rMtf.GetActionCount() == nObjCount &&
291cdf0e10cSrcweir 			 rMtf.GetPrefSize() == aPrefSize &&
292cdf0e10cSrcweir 			 rMtf.GetPrefMapMode() == aPrefMapMode )
293cdf0e10cSrcweir 	{
294cdf0e10cSrcweir 		bRet = sal_True;
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 		for( sal_uLong n = 0UL; n < nObjCount; n++ )
297cdf0e10cSrcweir 		{
298cdf0e10cSrcweir 			if( GetObject( n ) != rMtf.GetObject( n ) )
299cdf0e10cSrcweir 			{
300cdf0e10cSrcweir 				bRet = sal_False;
301cdf0e10cSrcweir 				break;
302cdf0e10cSrcweir 			}
303cdf0e10cSrcweir 		}
304cdf0e10cSrcweir 	}
305cdf0e10cSrcweir 
306cdf0e10cSrcweir 	return bRet;
307cdf0e10cSrcweir }
308cdf0e10cSrcweir 
309cdf0e10cSrcweir // ------------------------------------------------------------------------
310cdf0e10cSrcweir 
311cdf0e10cSrcweir sal_Bool GDIMetaFile::IsEqual( const GDIMetaFile& rMtf ) const
312cdf0e10cSrcweir {
313cdf0e10cSrcweir 	const sal_uLong nObjCount = Count();
314cdf0e10cSrcweir 	sal_Bool		bRet = sal_False;
315cdf0e10cSrcweir 
316cdf0e10cSrcweir 	if( this == &rMtf )
317cdf0e10cSrcweir 		bRet = sal_True;
318cdf0e10cSrcweir 	else if( rMtf.GetActionCount() == nObjCount &&
319cdf0e10cSrcweir 			 rMtf.GetPrefSize() == aPrefSize &&
320cdf0e10cSrcweir 			 rMtf.GetPrefMapMode() == aPrefMapMode )
321cdf0e10cSrcweir 	{
322cdf0e10cSrcweir 		bRet = sal_True;
323cdf0e10cSrcweir 
324cdf0e10cSrcweir 		for( sal_uLong n = 0UL; n < nObjCount; n++ )
325cdf0e10cSrcweir 		{
326cdf0e10cSrcweir 			if(!((MetaAction*)GetObject( n ))->IsEqual(*((MetaAction*)rMtf.GetObject( n ))))
327cdf0e10cSrcweir 			{
328cdf0e10cSrcweir 				bRet = sal_False;
329cdf0e10cSrcweir 				break;
330cdf0e10cSrcweir 			}
331cdf0e10cSrcweir 		}
332cdf0e10cSrcweir 	}
333cdf0e10cSrcweir 
334cdf0e10cSrcweir 	return bRet;
335cdf0e10cSrcweir }
336cdf0e10cSrcweir 
337cdf0e10cSrcweir // ------------------------------------------------------------------------
338cdf0e10cSrcweir 
339cdf0e10cSrcweir void GDIMetaFile::Clear()
340cdf0e10cSrcweir {
341cdf0e10cSrcweir 	if( bRecord )
342cdf0e10cSrcweir 		Stop();
343cdf0e10cSrcweir 
344cdf0e10cSrcweir 	for( void* pAct = First(); pAct; pAct = Next() )
345cdf0e10cSrcweir 		( (MetaAction*) pAct )->Delete();
346cdf0e10cSrcweir 
347cdf0e10cSrcweir 	List::Clear();
348cdf0e10cSrcweir 
349cdf0e10cSrcweir 	delete pLabelList;
350cdf0e10cSrcweir 	pLabelList = NULL;
351cdf0e10cSrcweir }
352cdf0e10cSrcweir 
353cdf0e10cSrcweir // ------------------------------------------------------------------------
354cdf0e10cSrcweir 
355cdf0e10cSrcweir void GDIMetaFile::Linker( OutputDevice* pOut, sal_Bool bLink )
356cdf0e10cSrcweir {
357cdf0e10cSrcweir 	if( bLink )
358cdf0e10cSrcweir 	{
359cdf0e10cSrcweir 		pNext = NULL;
360cdf0e10cSrcweir 		pPrev = pOut->GetConnectMetaFile();
361cdf0e10cSrcweir 		pOut->SetConnectMetaFile( this );
362cdf0e10cSrcweir 
363cdf0e10cSrcweir 		if( pPrev )
364cdf0e10cSrcweir 			pPrev->pNext = this;
365cdf0e10cSrcweir 	}
366cdf0e10cSrcweir 	else
367cdf0e10cSrcweir 	{
368cdf0e10cSrcweir 		if( pNext )
369cdf0e10cSrcweir 		{
370cdf0e10cSrcweir 			pNext->pPrev = pPrev;
371cdf0e10cSrcweir 
372cdf0e10cSrcweir 			if( pPrev )
373cdf0e10cSrcweir 				pPrev->pNext = pNext;
374cdf0e10cSrcweir 		}
375cdf0e10cSrcweir 		else
376cdf0e10cSrcweir 		{
377cdf0e10cSrcweir 			if( pPrev )
378cdf0e10cSrcweir 				pPrev->pNext = NULL;
379cdf0e10cSrcweir 
380cdf0e10cSrcweir 			pOut->SetConnectMetaFile( pPrev );
381cdf0e10cSrcweir 		}
382cdf0e10cSrcweir 
383cdf0e10cSrcweir 		pPrev = NULL;
384cdf0e10cSrcweir 		pNext = NULL;
385cdf0e10cSrcweir 	}
386cdf0e10cSrcweir }
387cdf0e10cSrcweir 
388cdf0e10cSrcweir // ------------------------------------------------------------------------
389cdf0e10cSrcweir 
390cdf0e10cSrcweir long GDIMetaFile::Hook()
391cdf0e10cSrcweir {
392cdf0e10cSrcweir 	return aHookHdlLink.Call( this );
393cdf0e10cSrcweir }
394cdf0e10cSrcweir 
395cdf0e10cSrcweir // ------------------------------------------------------------------------
396cdf0e10cSrcweir 
397cdf0e10cSrcweir void GDIMetaFile::Record( OutputDevice* pOut )
398cdf0e10cSrcweir {
399cdf0e10cSrcweir 	if( bRecord )
400cdf0e10cSrcweir 		Stop();
401cdf0e10cSrcweir 
402cdf0e10cSrcweir 	Last();
403cdf0e10cSrcweir 	pOutDev = pOut;
404cdf0e10cSrcweir 	bRecord = sal_True;
405cdf0e10cSrcweir 	Linker( pOut, sal_True );
406cdf0e10cSrcweir }
407cdf0e10cSrcweir 
408cdf0e10cSrcweir // ------------------------------------------------------------------------
409cdf0e10cSrcweir 
410cdf0e10cSrcweir void GDIMetaFile::Play( GDIMetaFile& rMtf, sal_uLong nPos )
411cdf0e10cSrcweir {
412cdf0e10cSrcweir 	if ( !bRecord && !rMtf.bRecord )
413cdf0e10cSrcweir 	{
414cdf0e10cSrcweir 		MetaAction* pAction = GetCurAction();
415cdf0e10cSrcweir 		const sal_uLong nObjCount = Count();
416cdf0e10cSrcweir 
417cdf0e10cSrcweir 		if( nPos > nObjCount )
418cdf0e10cSrcweir 			nPos = nObjCount;
419cdf0e10cSrcweir 
420cdf0e10cSrcweir 		for( sal_uLong nCurPos = GetCurPos(); nCurPos < nPos; nCurPos++ )
421cdf0e10cSrcweir 		{
422cdf0e10cSrcweir 			if( !Hook() )
423cdf0e10cSrcweir 			{
424cdf0e10cSrcweir 				pAction->Duplicate();
425cdf0e10cSrcweir 				rMtf.AddAction( pAction );
426cdf0e10cSrcweir 			}
427cdf0e10cSrcweir 
428cdf0e10cSrcweir 			pAction = (MetaAction*) Next();
429cdf0e10cSrcweir 		}
430cdf0e10cSrcweir 	}
431cdf0e10cSrcweir }
432cdf0e10cSrcweir 
433cdf0e10cSrcweir // ------------------------------------------------------------------------
434cdf0e10cSrcweir 
435cdf0e10cSrcweir void GDIMetaFile::Play( OutputDevice* pOut, sal_uLong nPos )
436cdf0e10cSrcweir {
437cdf0e10cSrcweir 	if( !bRecord )
438cdf0e10cSrcweir 	{
439cdf0e10cSrcweir 		MetaAction* pAction = GetCurAction();
440cdf0e10cSrcweir 		const sal_uLong nObjCount = Count();
441cdf0e10cSrcweir 		sal_uLong		i  = 0, nSyncCount = ( pOut->GetOutDevType() == OUTDEV_WINDOW ) ? 0x000000ff : 0xffffffff;
442cdf0e10cSrcweir 
443cdf0e10cSrcweir         if( nPos > nObjCount )
444cdf0e10cSrcweir 			nPos = nObjCount;
445cdf0e10cSrcweir 
446cdf0e10cSrcweir         // #i23407# Set backwards-compatible text language and layout mode
447cdf0e10cSrcweir         // This is necessary, since old metafiles don't even know of these
448cdf0e10cSrcweir 		// recent add-ons. Newer metafiles must of course explicitely set
449cdf0e10cSrcweir         // those states.
450cdf0e10cSrcweir         pOut->Push( PUSH_TEXTLAYOUTMODE|PUSH_TEXTLANGUAGE );
451cdf0e10cSrcweir         pOut->SetLayoutMode( 0 );
452cdf0e10cSrcweir         pOut->SetDigitLanguage( 0 );
453cdf0e10cSrcweir 
454cdf0e10cSrcweir 		for( sal_uLong nCurPos = GetCurPos(); nCurPos < nPos; nCurPos++ )
455cdf0e10cSrcweir 		{
456cdf0e10cSrcweir 			if( !Hook() )
457cdf0e10cSrcweir 			{
458cdf0e10cSrcweir 				pAction->Execute( pOut );
459cdf0e10cSrcweir 
460cdf0e10cSrcweir 				// flush output from time to time
461cdf0e10cSrcweir 				if( i++ > nSyncCount )
462cdf0e10cSrcweir 					( (Window*) pOut )->Flush(), i = 0;
463cdf0e10cSrcweir 			}
464cdf0e10cSrcweir 
465cdf0e10cSrcweir 			pAction = (MetaAction*) Next();
466cdf0e10cSrcweir 		}
467cdf0e10cSrcweir 
468cdf0e10cSrcweir         pOut->Pop();
469cdf0e10cSrcweir 	}
470cdf0e10cSrcweir }
471cdf0e10cSrcweir 
472cdf0e10cSrcweir // ------------------------------------------------------------------------
473cdf0e10cSrcweir 
474cdf0e10cSrcweir void GDIMetaFile::Play( OutputDevice* pOut, const Point& rPos,
475cdf0e10cSrcweir 						const Size& rSize, sal_uLong nPos )
476cdf0e10cSrcweir {
477cdf0e10cSrcweir 	Region	aDrawClipRegion;
478cdf0e10cSrcweir 	MapMode aDrawMap( GetPrefMapMode() );
479cdf0e10cSrcweir 	Size	aDestSize( pOut->LogicToPixel( rSize ) );
480cdf0e10cSrcweir 
481cdf0e10cSrcweir 	if( aDestSize.Width() && aDestSize.Height() )
482cdf0e10cSrcweir 	{
483cdf0e10cSrcweir 		Size			aTmpPrefSize( pOut->LogicToPixel( GetPrefSize(), aDrawMap ) );
484cdf0e10cSrcweir 		GDIMetaFile*	pMtf = pOut->GetConnectMetaFile();
485cdf0e10cSrcweir 
486cdf0e10cSrcweir 		if( !aTmpPrefSize.Width() )
487cdf0e10cSrcweir 			aTmpPrefSize.Width() = aDestSize.Width();
488cdf0e10cSrcweir 
489cdf0e10cSrcweir 		if( !aTmpPrefSize.Height() )
490cdf0e10cSrcweir 			aTmpPrefSize.Height() = aDestSize.Height();
491cdf0e10cSrcweir 
492cdf0e10cSrcweir 		Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
493cdf0e10cSrcweir 		Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
494cdf0e10cSrcweir 
495cdf0e10cSrcweir 		aScaleX *= aDrawMap.GetScaleX(); aDrawMap.SetScaleX( aScaleX );
496cdf0e10cSrcweir 		aScaleY *= aDrawMap.GetScaleY(); aDrawMap.SetScaleY( aScaleY );
497cdf0e10cSrcweir 
498cdf0e10cSrcweir         // #i47260# Convert logical output position to offset within
499cdf0e10cSrcweir         // the metafile's mapmode. Therefore, disable pixel offset on
500cdf0e10cSrcweir         // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
501cdf0e10cSrcweir         // different mapmode (the one currently set on pOut, that is)
502cdf0e10cSrcweir         // - thus, aDrawMap's origin would generally be wrong. And
503cdf0e10cSrcweir         // even _if_ aDrawMap is similar to pOutDev's current mapmode,
504cdf0e10cSrcweir         // it's _still_ undesirable to have pixel offset unequal zero,
505cdf0e10cSrcweir         // because one would still get round-off errors (the
506cdf0e10cSrcweir         // round-trip error for LogicToPixel( PixelToLogic() ) was the
507cdf0e10cSrcweir         // reason for having pixel offset in the first place).
508cdf0e10cSrcweir         const Size& rOldOffset( pOut->GetPixelOffset() );
509cdf0e10cSrcweir         const Size  aEmptySize;
510cdf0e10cSrcweir         pOut->SetPixelOffset( aEmptySize );
511cdf0e10cSrcweir 		aDrawMap.SetOrigin( pOut->PixelToLogic( pOut->LogicToPixel( rPos ), aDrawMap ) );
512cdf0e10cSrcweir         pOut->SetPixelOffset( rOldOffset );
513cdf0e10cSrcweir 
514cdf0e10cSrcweir 		pOut->Push();
515cdf0e10cSrcweir 
516cdf0e10cSrcweir 		if ( pMtf && pMtf->IsRecord() && ( pOut->GetOutDevType() != OUTDEV_PRINTER ) )
517cdf0e10cSrcweir 			pOut->SetRelativeMapMode( aDrawMap );
518cdf0e10cSrcweir 		else
519cdf0e10cSrcweir 			pOut->SetMapMode( aDrawMap );
520cdf0e10cSrcweir 
521cdf0e10cSrcweir         // #i23407# Set backwards-compatible text language and layout mode
522cdf0e10cSrcweir         // This is necessary, since old metafiles don't even know of these
523cdf0e10cSrcweir 		// recent add-ons. Newer metafiles must of course explicitely set
524cdf0e10cSrcweir         // those states.
525cdf0e10cSrcweir         pOut->SetLayoutMode( 0 );
526cdf0e10cSrcweir         pOut->SetDigitLanguage( 0 );
527cdf0e10cSrcweir 
528cdf0e10cSrcweir 		Play( pOut, nPos );
529cdf0e10cSrcweir 
530cdf0e10cSrcweir 		pOut->Pop();
531cdf0e10cSrcweir 	}
532cdf0e10cSrcweir }
533cdf0e10cSrcweir 
534cdf0e10cSrcweir // ------------------------------------------------------------------------
535cdf0e10cSrcweir 
536cdf0e10cSrcweir void GDIMetaFile::Pause( sal_Bool _bPause )
537cdf0e10cSrcweir {
538cdf0e10cSrcweir 	if( bRecord )
539cdf0e10cSrcweir 	{
540cdf0e10cSrcweir 		if( _bPause )
541cdf0e10cSrcweir 		{
542cdf0e10cSrcweir 			if( !bPause )
543cdf0e10cSrcweir 				Linker( pOutDev, sal_False );
544cdf0e10cSrcweir 		}
545cdf0e10cSrcweir 		else
546cdf0e10cSrcweir 		{
547cdf0e10cSrcweir 			if( bPause )
548cdf0e10cSrcweir 				Linker( pOutDev, sal_True );
549cdf0e10cSrcweir 		}
550cdf0e10cSrcweir 
551cdf0e10cSrcweir 		bPause = _bPause;
552cdf0e10cSrcweir 	}
553cdf0e10cSrcweir }
554cdf0e10cSrcweir 
555cdf0e10cSrcweir // ------------------------------------------------------------------------
556cdf0e10cSrcweir 
557cdf0e10cSrcweir void GDIMetaFile::Stop()
558cdf0e10cSrcweir {
559cdf0e10cSrcweir 	if( bRecord )
560cdf0e10cSrcweir 	{
561cdf0e10cSrcweir 		bRecord = sal_False;
562cdf0e10cSrcweir 
563cdf0e10cSrcweir 		if( !bPause )
564cdf0e10cSrcweir 			Linker( pOutDev, sal_False );
565cdf0e10cSrcweir 		else
566cdf0e10cSrcweir 			bPause = sal_False;
567cdf0e10cSrcweir 	}
568cdf0e10cSrcweir }
569cdf0e10cSrcweir 
570cdf0e10cSrcweir // ------------------------------------------------------------------------
571cdf0e10cSrcweir 
572cdf0e10cSrcweir void GDIMetaFile::WindStart()
573cdf0e10cSrcweir {
574cdf0e10cSrcweir 	if( !bRecord )
575cdf0e10cSrcweir 		First();
576cdf0e10cSrcweir }
577cdf0e10cSrcweir 
578cdf0e10cSrcweir // ------------------------------------------------------------------------
579cdf0e10cSrcweir 
580cdf0e10cSrcweir void GDIMetaFile::WindEnd()
581cdf0e10cSrcweir {
582cdf0e10cSrcweir 	if( !bRecord )
583cdf0e10cSrcweir 		Last();
584cdf0e10cSrcweir }
585cdf0e10cSrcweir 
586cdf0e10cSrcweir // ------------------------------------------------------------------------
587cdf0e10cSrcweir 
588cdf0e10cSrcweir void GDIMetaFile::Wind( sal_uLong nActionPos )
589cdf0e10cSrcweir {
590cdf0e10cSrcweir 	if( !bRecord )
591cdf0e10cSrcweir 		Seek( nActionPos );
592cdf0e10cSrcweir }
593cdf0e10cSrcweir 
594cdf0e10cSrcweir // ------------------------------------------------------------------------
595cdf0e10cSrcweir 
596cdf0e10cSrcweir void GDIMetaFile::WindPrev()
597cdf0e10cSrcweir {
598cdf0e10cSrcweir 	if( !bRecord )
599cdf0e10cSrcweir 		Prev();
600cdf0e10cSrcweir }
601cdf0e10cSrcweir 
602cdf0e10cSrcweir // ------------------------------------------------------------------------
603cdf0e10cSrcweir 
604cdf0e10cSrcweir void GDIMetaFile::WindNext()
605cdf0e10cSrcweir {
606cdf0e10cSrcweir 	if( !bRecord )
607cdf0e10cSrcweir 		Next();
608cdf0e10cSrcweir }
609cdf0e10cSrcweir 
610cdf0e10cSrcweir // ------------------------------------------------------------------------
611cdf0e10cSrcweir 
612cdf0e10cSrcweir void GDIMetaFile::AddAction( MetaAction* pAction )
613cdf0e10cSrcweir {
614cdf0e10cSrcweir 	Insert( pAction, LIST_APPEND );
615cdf0e10cSrcweir 
616cdf0e10cSrcweir 	if( pPrev )
617cdf0e10cSrcweir 	{
618cdf0e10cSrcweir 		pAction->Duplicate();
619cdf0e10cSrcweir 		pPrev->AddAction( pAction );
620cdf0e10cSrcweir 	}
621cdf0e10cSrcweir }
622cdf0e10cSrcweir 
623cdf0e10cSrcweir // ------------------------------------------------------------------------
624cdf0e10cSrcweir 
625cdf0e10cSrcweir void GDIMetaFile::AddAction( MetaAction* pAction, sal_uLong nPos )
626cdf0e10cSrcweir {
627cdf0e10cSrcweir 	Insert( pAction, nPos );
628cdf0e10cSrcweir 
629cdf0e10cSrcweir 	if( pPrev )
630cdf0e10cSrcweir 	{
631cdf0e10cSrcweir 		pAction->Duplicate();
632cdf0e10cSrcweir 		pPrev->AddAction( pAction, nPos );
633cdf0e10cSrcweir 	}
634cdf0e10cSrcweir }
635cdf0e10cSrcweir 
636cdf0e10cSrcweir // ------------------------------------------------------------------------
637cdf0e10cSrcweir 
638cdf0e10cSrcweir // @since #110496#
639cdf0e10cSrcweir void GDIMetaFile::RemoveAction( sal_uLong nPos )
640cdf0e10cSrcweir {
641cdf0e10cSrcweir 	Remove( nPos );
642cdf0e10cSrcweir 
643cdf0e10cSrcweir 	if( pPrev )
644cdf0e10cSrcweir 		pPrev->RemoveAction( nPos );
645cdf0e10cSrcweir }
646cdf0e10cSrcweir 
647cdf0e10cSrcweir // ------------------------------------------------------------------------
648cdf0e10cSrcweir 
649cdf0e10cSrcweir MetaAction* GDIMetaFile::CopyAction( sal_uLong nPos ) const
650cdf0e10cSrcweir {
651cdf0e10cSrcweir 	return ( (MetaAction*) GetObject( nPos ) )->Clone();
652cdf0e10cSrcweir }
653cdf0e10cSrcweir 
654cdf0e10cSrcweir // ------------------------------------------------------------------------
655cdf0e10cSrcweir 
656cdf0e10cSrcweir sal_uLong GDIMetaFile::GetActionPos( const String& rLabel )
657cdf0e10cSrcweir {
658cdf0e10cSrcweir 	ImpLabel* pLabel = NULL;
659cdf0e10cSrcweir 
660cdf0e10cSrcweir 	if( pLabelList )
661cdf0e10cSrcweir 		pLabel = pLabelList->ImplGetLabel( pLabelList->ImplGetLabelPos( rLabel ) );
662cdf0e10cSrcweir 	else
663cdf0e10cSrcweir 		pLabel = NULL;
664cdf0e10cSrcweir 
665cdf0e10cSrcweir 	return( pLabel ? pLabel->nActionPos : METAFILE_LABEL_NOTFOUND );
666cdf0e10cSrcweir }
667cdf0e10cSrcweir 
668cdf0e10cSrcweir // ------------------------------------------------------------------------
669cdf0e10cSrcweir 
670cdf0e10cSrcweir sal_Bool GDIMetaFile::InsertLabel( const String& rLabel, sal_uLong nActionPos )
671cdf0e10cSrcweir {
672cdf0e10cSrcweir 	sal_Bool bRet = sal_False;
673cdf0e10cSrcweir 
674cdf0e10cSrcweir 	if( !pLabelList )
675cdf0e10cSrcweir 		pLabelList = new ImpLabelList;
676cdf0e10cSrcweir 
677cdf0e10cSrcweir 	if( pLabelList->ImplGetLabelPos( rLabel ) == METAFILE_LABEL_NOTFOUND )
678cdf0e10cSrcweir 	{
679cdf0e10cSrcweir 		pLabelList->ImplInsert( new ImpLabel( rLabel, nActionPos ) );
680cdf0e10cSrcweir 		bRet = sal_True;
681cdf0e10cSrcweir 	}
682cdf0e10cSrcweir 
683cdf0e10cSrcweir 	return bRet;
684cdf0e10cSrcweir }
685cdf0e10cSrcweir 
686cdf0e10cSrcweir // ------------------------------------------------------------------------
687cdf0e10cSrcweir 
688cdf0e10cSrcweir void GDIMetaFile::RemoveLabel( const String& rLabel )
689cdf0e10cSrcweir {
690cdf0e10cSrcweir 	if( pLabelList )
691cdf0e10cSrcweir 	{
692cdf0e10cSrcweir 		const sal_uLong nLabelPos = pLabelList->ImplGetLabelPos( rLabel );
693cdf0e10cSrcweir 
694cdf0e10cSrcweir 		if( nLabelPos != METAFILE_LABEL_NOTFOUND )
695cdf0e10cSrcweir 			delete pLabelList->ImplRemove( nLabelPos );
696cdf0e10cSrcweir 	}
697cdf0e10cSrcweir }
698cdf0e10cSrcweir 
699cdf0e10cSrcweir // ------------------------------------------------------------------------
700cdf0e10cSrcweir 
701cdf0e10cSrcweir void GDIMetaFile::RenameLabel( const String& rLabel, const String& rNewLabel )
702cdf0e10cSrcweir {
703cdf0e10cSrcweir 	if( pLabelList )
704cdf0e10cSrcweir 	{
705cdf0e10cSrcweir 		const sal_uLong nLabelPos = pLabelList->ImplGetLabelPos( rLabel );
706cdf0e10cSrcweir 
707cdf0e10cSrcweir 		if ( nLabelPos != METAFILE_LABEL_NOTFOUND )
708cdf0e10cSrcweir 			pLabelList->ImplGetLabel( nLabelPos )->aLabelName = rNewLabel;
709cdf0e10cSrcweir 	}
710cdf0e10cSrcweir }
711cdf0e10cSrcweir 
712cdf0e10cSrcweir // ------------------------------------------------------------------------
713cdf0e10cSrcweir 
714cdf0e10cSrcweir sal_uLong GDIMetaFile::GetLabelCount() const
715cdf0e10cSrcweir {
716cdf0e10cSrcweir 	return( pLabelList ? pLabelList->ImplCount() : 0UL );
717cdf0e10cSrcweir }
718cdf0e10cSrcweir 
719cdf0e10cSrcweir // ------------------------------------------------------------------------
720cdf0e10cSrcweir 
721cdf0e10cSrcweir String GDIMetaFile::GetLabel( sal_uLong nLabel )
722cdf0e10cSrcweir {
723cdf0e10cSrcweir 	String aString;
724cdf0e10cSrcweir 
725cdf0e10cSrcweir 	if( pLabelList )
726cdf0e10cSrcweir 	{
727cdf0e10cSrcweir 		const ImpLabel* pLabel = pLabelList->ImplGetLabel( nLabel );
728cdf0e10cSrcweir 
729cdf0e10cSrcweir 		if( pLabel )
730cdf0e10cSrcweir 			aString = pLabel->aLabelName;
731cdf0e10cSrcweir 	}
732cdf0e10cSrcweir 
733cdf0e10cSrcweir 	return aString;
734cdf0e10cSrcweir }
735cdf0e10cSrcweir 
736cdf0e10cSrcweir // ------------------------------------------------------------------------
737cdf0e10cSrcweir 
738cdf0e10cSrcweir sal_Bool GDIMetaFile::SaveStatus()
739cdf0e10cSrcweir {
740cdf0e10cSrcweir 	if ( bRecord )
741cdf0e10cSrcweir 	{
742cdf0e10cSrcweir 		if ( bPause )
743cdf0e10cSrcweir 			Linker( pOutDev, sal_True );
744cdf0e10cSrcweir 
745cdf0e10cSrcweir 		AddAction( new MetaLineColorAction( pOutDev->GetLineColor(),
746cdf0e10cSrcweir 											pOutDev->IsLineColor() ) );
747cdf0e10cSrcweir 		AddAction( new MetaFillColorAction( pOutDev->GetFillColor(),
748cdf0e10cSrcweir 											pOutDev->IsFillColor() ) );
749cdf0e10cSrcweir 		AddAction( new MetaFontAction( pOutDev->GetFont() ) );
750cdf0e10cSrcweir 		AddAction( new MetaTextColorAction( pOutDev->GetTextColor() ) );
751cdf0e10cSrcweir 		AddAction( new MetaTextFillColorAction( pOutDev->GetTextFillColor(),
752cdf0e10cSrcweir 												pOutDev->IsTextFillColor() ) );
753cdf0e10cSrcweir 		AddAction( new MetaTextLineColorAction( pOutDev->GetTextLineColor(),
754cdf0e10cSrcweir 												pOutDev->IsTextLineColor() ) );
755cdf0e10cSrcweir 		AddAction( new MetaOverlineColorAction( pOutDev->GetOverlineColor(),
756cdf0e10cSrcweir 												pOutDev->IsOverlineColor() ) );
757cdf0e10cSrcweir 		AddAction( new MetaTextAlignAction( pOutDev->GetTextAlign() ) );
758cdf0e10cSrcweir 		AddAction( new MetaRasterOpAction( pOutDev->GetRasterOp() ) );
759cdf0e10cSrcweir 		AddAction( new MetaMapModeAction( pOutDev->GetMapMode() ) );
760cdf0e10cSrcweir 		AddAction( new MetaClipRegionAction( pOutDev->GetClipRegion(),
761cdf0e10cSrcweir 											 pOutDev->IsClipRegion() ) );
762cdf0e10cSrcweir 
763cdf0e10cSrcweir 		if ( bPause )
764cdf0e10cSrcweir 			Linker( pOutDev, sal_False );
765cdf0e10cSrcweir 
766cdf0e10cSrcweir 		return sal_True;
767cdf0e10cSrcweir 	}
768cdf0e10cSrcweir 	else
769cdf0e10cSrcweir 		return sal_False;
770cdf0e10cSrcweir }
771cdf0e10cSrcweir 
772cdf0e10cSrcweir // ------------------------------------------------------------------------
773cdf0e10cSrcweir 
774cdf0e10cSrcweir sal_Bool GDIMetaFile::Mirror( sal_uLong nMirrorFlags )
775cdf0e10cSrcweir {
776cdf0e10cSrcweir 	const Size	aOldPrefSize( GetPrefSize() );
777cdf0e10cSrcweir 	long	    nMoveX, nMoveY;
778cdf0e10cSrcweir 	double	    fScaleX, fScaleY;
779cdf0e10cSrcweir     sal_Bool        bRet;
780cdf0e10cSrcweir 
781cdf0e10cSrcweir 	if( nMirrorFlags & MTF_MIRROR_HORZ )
782cdf0e10cSrcweir 		nMoveX = VOS_ABS( aOldPrefSize.Width() ) - 1, fScaleX = -1.0;
783cdf0e10cSrcweir 	else
784cdf0e10cSrcweir 		nMoveX = 0, fScaleX = 1.0;
785cdf0e10cSrcweir 
786cdf0e10cSrcweir 	if( nMirrorFlags & MTF_MIRROR_VERT )
787cdf0e10cSrcweir 		nMoveY = VOS_ABS( aOldPrefSize.Height() ) - 1, fScaleY = -1.0;
788cdf0e10cSrcweir 	else
789cdf0e10cSrcweir 		nMoveY = 0, fScaleY = 1.0;
790cdf0e10cSrcweir 
791cdf0e10cSrcweir     if( ( fScaleX != 1.0 ) || ( fScaleY != 1.0 ) )
792cdf0e10cSrcweir     {
793cdf0e10cSrcweir 	    Scale( fScaleX, fScaleY );
794cdf0e10cSrcweir 	    Move( nMoveX, nMoveY );
795cdf0e10cSrcweir 	    SetPrefSize( aOldPrefSize );
796cdf0e10cSrcweir         bRet = sal_True;
797cdf0e10cSrcweir     }
798cdf0e10cSrcweir     else
799cdf0e10cSrcweir         bRet = sal_False;
800cdf0e10cSrcweir 
801cdf0e10cSrcweir     return bRet;
802cdf0e10cSrcweir }
803cdf0e10cSrcweir 
804cdf0e10cSrcweir // ------------------------------------------------------------------------
805cdf0e10cSrcweir 
806cdf0e10cSrcweir void GDIMetaFile::Move( long nX, long nY )
807cdf0e10cSrcweir {
808cdf0e10cSrcweir     const Size      aBaseOffset( nX, nY );
809cdf0e10cSrcweir     Size            aOffset( aBaseOffset );
810cdf0e10cSrcweir     VirtualDevice   aMapVDev;
811cdf0e10cSrcweir 
812cdf0e10cSrcweir     aMapVDev.EnableOutput( sal_False );
813cdf0e10cSrcweir     aMapVDev.SetMapMode( GetPrefMapMode() );
814cdf0e10cSrcweir 
815cdf0e10cSrcweir 	for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() )
816cdf0e10cSrcweir 	{
817cdf0e10cSrcweir 		const long  nType = pAct->GetType();
818cdf0e10cSrcweir         MetaAction* pModAct;
819cdf0e10cSrcweir 
820cdf0e10cSrcweir 		if( pAct->GetRefCount() > 1 )
821cdf0e10cSrcweir 		{
822cdf0e10cSrcweir 			Replace( pModAct = pAct->Clone(), GetCurPos() );
823cdf0e10cSrcweir 			pAct->Delete();
824cdf0e10cSrcweir 		}
825cdf0e10cSrcweir 		else
826cdf0e10cSrcweir 			pModAct = pAct;
827cdf0e10cSrcweir 
828cdf0e10cSrcweir         if( ( META_MAPMODE_ACTION == nType ) ||
829cdf0e10cSrcweir             ( META_PUSH_ACTION == nType ) ||
830cdf0e10cSrcweir             ( META_POP_ACTION == nType ) )
831cdf0e10cSrcweir         {
832cdf0e10cSrcweir             pModAct->Execute( &aMapVDev );
833cdf0e10cSrcweir             aOffset = aMapVDev.LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev.GetMapMode() );
834cdf0e10cSrcweir         }
835cdf0e10cSrcweir 
836cdf0e10cSrcweir 		pModAct->Move( aOffset.Width(), aOffset.Height() );
837cdf0e10cSrcweir 	}
838cdf0e10cSrcweir }
839cdf0e10cSrcweir 
840cdf0e10cSrcweir void GDIMetaFile::Move( long nX, long nY, long nDPIX, long nDPIY )
841cdf0e10cSrcweir {
842cdf0e10cSrcweir     const Size      aBaseOffset( nX, nY );
843cdf0e10cSrcweir     Size            aOffset( aBaseOffset );
844cdf0e10cSrcweir     VirtualDevice   aMapVDev;
845cdf0e10cSrcweir 
846cdf0e10cSrcweir     aMapVDev.EnableOutput( sal_False );
847cdf0e10cSrcweir     aMapVDev.SetReferenceDevice( nDPIX, nDPIY );
848cdf0e10cSrcweir     aMapVDev.SetMapMode( GetPrefMapMode() );
849cdf0e10cSrcweir 
850cdf0e10cSrcweir 	for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() )
851cdf0e10cSrcweir 	{
852cdf0e10cSrcweir 		const long  nType = pAct->GetType();
853cdf0e10cSrcweir         MetaAction* pModAct;
854cdf0e10cSrcweir 
855cdf0e10cSrcweir 		if( pAct->GetRefCount() > 1 )
856cdf0e10cSrcweir 		{
857cdf0e10cSrcweir 			Replace( pModAct = pAct->Clone(), GetCurPos() );
858cdf0e10cSrcweir 			pAct->Delete();
859cdf0e10cSrcweir 		}
860cdf0e10cSrcweir 		else
861cdf0e10cSrcweir 			pModAct = pAct;
862cdf0e10cSrcweir 
863cdf0e10cSrcweir         if( ( META_MAPMODE_ACTION == nType ) ||
864cdf0e10cSrcweir             ( META_PUSH_ACTION == nType ) ||
865cdf0e10cSrcweir             ( META_POP_ACTION == nType ) )
866cdf0e10cSrcweir         {
867cdf0e10cSrcweir             pModAct->Execute( &aMapVDev );
868cdf0e10cSrcweir             if( aMapVDev.GetMapMode().GetMapUnit() == MAP_PIXEL )
869cdf0e10cSrcweir             {
870cdf0e10cSrcweir                 aOffset = aMapVDev.LogicToPixel( aBaseOffset, GetPrefMapMode() );
871cdf0e10cSrcweir                 MapMode aMap( aMapVDev.GetMapMode() );
872cdf0e10cSrcweir                 aOffset.Width() = static_cast<long>(aOffset.Width() * (double)aMap.GetScaleX());
873cdf0e10cSrcweir                 aOffset.Height() = static_cast<long>(aOffset.Height() * (double)aMap.GetScaleY());
874cdf0e10cSrcweir             }
875cdf0e10cSrcweir             else
876cdf0e10cSrcweir                 aOffset = aMapVDev.LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev.GetMapMode() );
877cdf0e10cSrcweir         }
878cdf0e10cSrcweir 
879cdf0e10cSrcweir 		pModAct->Move( aOffset.Width(), aOffset.Height() );
880cdf0e10cSrcweir 	}
881cdf0e10cSrcweir }
882cdf0e10cSrcweir 
883cdf0e10cSrcweir // ------------------------------------------------------------------------
884cdf0e10cSrcweir 
885cdf0e10cSrcweir void GDIMetaFile::Scale( double fScaleX, double fScaleY )
886cdf0e10cSrcweir {
887cdf0e10cSrcweir 	for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() )
888cdf0e10cSrcweir 	{
889cdf0e10cSrcweir 		MetaAction* pModAct;
890cdf0e10cSrcweir 
891cdf0e10cSrcweir 		if( pAct->GetRefCount() > 1 )
892cdf0e10cSrcweir 		{
893cdf0e10cSrcweir             Replace( pModAct = pAct->Clone(), GetCurPos() );
894cdf0e10cSrcweir 			pAct->Delete();
895cdf0e10cSrcweir 		}
896cdf0e10cSrcweir 		else
897cdf0e10cSrcweir 			pModAct = pAct;
898cdf0e10cSrcweir 
899cdf0e10cSrcweir 		pModAct->Scale( fScaleX, fScaleY );
900cdf0e10cSrcweir 	}
901cdf0e10cSrcweir 
902cdf0e10cSrcweir 	aPrefSize.Width() = FRound( aPrefSize.Width() * fScaleX );
903cdf0e10cSrcweir 	aPrefSize.Height() = FRound( aPrefSize.Height() * fScaleY );
904cdf0e10cSrcweir }
905cdf0e10cSrcweir 
906cdf0e10cSrcweir // ------------------------------------------------------------------------
907cdf0e10cSrcweir 
908cdf0e10cSrcweir void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
909cdf0e10cSrcweir {
910cdf0e10cSrcweir 	Scale( (double) rScaleX, (double) rScaleY );
911cdf0e10cSrcweir }
912cdf0e10cSrcweir 
913cdf0e10cSrcweir // ------------------------------------------------------------------------
914cdf0e10cSrcweir 
915cdf0e10cSrcweir void GDIMetaFile::Clip( const Rectangle& i_rClipRect )
916cdf0e10cSrcweir {
917cdf0e10cSrcweir     Rectangle aCurRect( i_rClipRect );
918cdf0e10cSrcweir     VirtualDevice   aMapVDev;
919cdf0e10cSrcweir 
920cdf0e10cSrcweir     aMapVDev.EnableOutput( sal_False );
921cdf0e10cSrcweir     aMapVDev.SetMapMode( GetPrefMapMode() );
922cdf0e10cSrcweir 
923cdf0e10cSrcweir     for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() )
924cdf0e10cSrcweir     {
925cdf0e10cSrcweir         const long  nType = pAct->GetType();
926cdf0e10cSrcweir 
927cdf0e10cSrcweir         if( ( META_MAPMODE_ACTION == nType ) ||
928cdf0e10cSrcweir             ( META_PUSH_ACTION == nType ) ||
929cdf0e10cSrcweir             ( META_POP_ACTION == nType ) )
930cdf0e10cSrcweir         {
931cdf0e10cSrcweir             pAct->Execute( &aMapVDev );
932cdf0e10cSrcweir             aCurRect = aMapVDev.LogicToLogic( i_rClipRect, GetPrefMapMode(), aMapVDev.GetMapMode() );
933cdf0e10cSrcweir         }
934cdf0e10cSrcweir         else if( nType == META_CLIPREGION_ACTION )
935cdf0e10cSrcweir         {
936cdf0e10cSrcweir             MetaClipRegionAction* pOldAct = (MetaClipRegionAction*)pAct;
937cdf0e10cSrcweir             Region aNewReg( aCurRect );
938cdf0e10cSrcweir             if( pOldAct->IsClipping() )
939cdf0e10cSrcweir                 aNewReg.Intersect( pOldAct->GetRegion() );
940cdf0e10cSrcweir             MetaClipRegionAction* pNewAct = new MetaClipRegionAction( aNewReg, sal_True );
941cdf0e10cSrcweir             Replace( pNewAct, GetCurPos() );
942cdf0e10cSrcweir             pOldAct->Delete();
943cdf0e10cSrcweir         }
944cdf0e10cSrcweir     }
945cdf0e10cSrcweir }
946cdf0e10cSrcweir 
947cdf0e10cSrcweir // ------------------------------------------------------------------------
948cdf0e10cSrcweir 
949cdf0e10cSrcweir Point GDIMetaFile::ImplGetRotatedPoint( const Point& rPt, const Point& rRotatePt,
950cdf0e10cSrcweir                                         const Size& rOffset, double fSin, double fCos )
951cdf0e10cSrcweir {
952cdf0e10cSrcweir     const long nX = rPt.X() - rRotatePt.X();
953cdf0e10cSrcweir     const long nY = rPt.Y() - rRotatePt.Y();
954cdf0e10cSrcweir 
955cdf0e10cSrcweir     return Point( FRound( fCos * nX + fSin * nY ) + rRotatePt.X() + rOffset.Width(),
956cdf0e10cSrcweir                   -FRound( fSin * nX - fCos * nY ) + rRotatePt.Y() + rOffset.Height() );
957cdf0e10cSrcweir }
958cdf0e10cSrcweir 
959cdf0e10cSrcweir // ------------------------------------------------------------------------
960cdf0e10cSrcweir 
961cdf0e10cSrcweir Polygon GDIMetaFile::ImplGetRotatedPolygon( const Polygon& rPoly, const Point& rRotatePt,
962cdf0e10cSrcweir                                             const Size& rOffset, double fSin, double fCos )
963cdf0e10cSrcweir {
964cdf0e10cSrcweir     Polygon aRet( rPoly );
965cdf0e10cSrcweir 
966cdf0e10cSrcweir     aRet.Rotate( rRotatePt, fSin, fCos );
967cdf0e10cSrcweir     aRet.Move( rOffset.Width(), rOffset.Height() );
968cdf0e10cSrcweir 
969cdf0e10cSrcweir     return aRet;
970cdf0e10cSrcweir }
971cdf0e10cSrcweir 
972cdf0e10cSrcweir // ------------------------------------------------------------------------
973cdf0e10cSrcweir 
974cdf0e10cSrcweir PolyPolygon GDIMetaFile::ImplGetRotatedPolyPolygon( const PolyPolygon& rPolyPoly, const Point& rRotatePt,
975cdf0e10cSrcweir                                                     const Size& rOffset, double fSin, double fCos )
976cdf0e10cSrcweir {
977cdf0e10cSrcweir     PolyPolygon aRet( rPolyPoly );
978cdf0e10cSrcweir 
979cdf0e10cSrcweir     aRet.Rotate( rRotatePt, fSin, fCos );
980cdf0e10cSrcweir     aRet.Move( rOffset.Width(), rOffset.Height() );
981cdf0e10cSrcweir 
982cdf0e10cSrcweir     return aRet;
983cdf0e10cSrcweir }
984cdf0e10cSrcweir 
985cdf0e10cSrcweir // ------------------------------------------------------------------------
986cdf0e10cSrcweir 
987cdf0e10cSrcweir void GDIMetaFile::ImplAddGradientEx( GDIMetaFile& 		  rMtf,
988cdf0e10cSrcweir                                      const OutputDevice&  rMapDev,
989cdf0e10cSrcweir                                      const PolyPolygon&   rPolyPoly,
990cdf0e10cSrcweir                                      const Gradient&	  rGrad 	)
991cdf0e10cSrcweir {
992cdf0e10cSrcweir     // #105055# Generate comment, GradientEx and Gradient actions
993cdf0e10cSrcweir     // (within DrawGradient)
994cdf0e10cSrcweir     VirtualDevice aVDev( rMapDev, 0 );
995cdf0e10cSrcweir     aVDev.EnableOutput( sal_False );
996cdf0e10cSrcweir     GDIMetaFile	aGradMtf;
997cdf0e10cSrcweir 
998cdf0e10cSrcweir     aGradMtf.Record( &aVDev );
999cdf0e10cSrcweir     aVDev.DrawGradient( rPolyPoly, rGrad );
1000cdf0e10cSrcweir     aGradMtf.Stop();
1001cdf0e10cSrcweir 
1002cdf0e10cSrcweir     int i, nAct( aGradMtf.GetActionCount() );
1003cdf0e10cSrcweir     for( i=0; i<nAct; ++i )
1004cdf0e10cSrcweir     {
1005cdf0e10cSrcweir         MetaAction* pMetaAct = aGradMtf.GetAction(i);
1006cdf0e10cSrcweir         pMetaAct->Duplicate();
1007cdf0e10cSrcweir         rMtf.AddAction( pMetaAct );
1008cdf0e10cSrcweir     }
1009cdf0e10cSrcweir }
1010cdf0e10cSrcweir 
1011cdf0e10cSrcweir // ------------------------------------------------------------------------
1012cdf0e10cSrcweir 
1013cdf0e10cSrcweir void GDIMetaFile::Rotate( long nAngle10 )
1014cdf0e10cSrcweir {
1015cdf0e10cSrcweir 	nAngle10 %= 3600L;
1016cdf0e10cSrcweir 	nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
1017cdf0e10cSrcweir 
1018cdf0e10cSrcweir     if( nAngle10 )
1019cdf0e10cSrcweir     {
1020cdf0e10cSrcweir 	    GDIMetaFile     aMtf;
1021cdf0e10cSrcweir         VirtualDevice   aMapVDev;
1022cdf0e10cSrcweir 	    const double    fAngle = F_PI1800 * nAngle10;
1023cdf0e10cSrcweir         const double    fSin = sin( fAngle );
1024cdf0e10cSrcweir         const double    fCos = cos( fAngle );
1025cdf0e10cSrcweir 		Rectangle		aRect=Rectangle( Point(), GetPrefSize() );
1026cdf0e10cSrcweir         Polygon         aPoly( aRect );
1027cdf0e10cSrcweir 
1028cdf0e10cSrcweir         aPoly.Rotate( Point(), fSin, fCos );
1029cdf0e10cSrcweir 
1030cdf0e10cSrcweir         aMapVDev.EnableOutput( sal_False );
1031cdf0e10cSrcweir         aMapVDev.SetMapMode( GetPrefMapMode() );
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir         const Rectangle aNewBound( aPoly.GetBoundRect() );
1034cdf0e10cSrcweir 
1035cdf0e10cSrcweir         const Point aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
1036cdf0e10cSrcweir         const Size  aOffset( -aNewBound.Left(), -aNewBound.Top() );
1037cdf0e10cSrcweir 
1038cdf0e10cSrcweir         Point     aRotAnchor( aOrigin );
1039cdf0e10cSrcweir         Size      aRotOffset( aOffset );
1040cdf0e10cSrcweir 
1041cdf0e10cSrcweir 	    for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() )
1042cdf0e10cSrcweir 	    {
1043cdf0e10cSrcweir 		    const sal_uInt16 nActionType = pAction->GetType();
1044cdf0e10cSrcweir 
1045cdf0e10cSrcweir 		    switch( nActionType )
1046cdf0e10cSrcweir 		    {
1047cdf0e10cSrcweir 			    case( META_PIXEL_ACTION ):
1048cdf0e10cSrcweir 			    {
1049cdf0e10cSrcweir 				    MetaPixelAction* pAct = (MetaPixelAction*) pAction;
1050cdf0e10cSrcweir 				    aMtf.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1051cdf0e10cSrcweir                                                                               pAct->GetColor() ) );
1052cdf0e10cSrcweir 			    }
1053cdf0e10cSrcweir 			    break;
1054cdf0e10cSrcweir 
1055cdf0e10cSrcweir 			    case( META_POINT_ACTION ):
1056cdf0e10cSrcweir 			    {
1057cdf0e10cSrcweir 				    MetaPointAction* pAct = (MetaPointAction*) pAction;
1058cdf0e10cSrcweir 				    aMtf.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1059cdf0e10cSrcweir 			    }
1060cdf0e10cSrcweir 			    break;
1061cdf0e10cSrcweir 
1062cdf0e10cSrcweir                 case( META_LINE_ACTION ):
1063cdf0e10cSrcweir                 {
1064cdf0e10cSrcweir 				    MetaLineAction* pAct = (MetaLineAction*) pAction;
1065cdf0e10cSrcweir                     aMtf.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1066cdf0e10cSrcweir                                                         ImplGetRotatedPoint( pAct->GetEndPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1067cdf0e10cSrcweir                                                         pAct->GetLineInfo() ) );
1068cdf0e10cSrcweir                 }
1069cdf0e10cSrcweir                 break;
1070cdf0e10cSrcweir 
1071cdf0e10cSrcweir                 case( META_RECT_ACTION ):
1072cdf0e10cSrcweir                 {
1073cdf0e10cSrcweir 				    MetaRectAction* pAct = (MetaRectAction*) pAction;
1074cdf0e10cSrcweir                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1075cdf0e10cSrcweir                 }
1076cdf0e10cSrcweir                 break;
1077cdf0e10cSrcweir 
1078cdf0e10cSrcweir                 case( META_ROUNDRECT_ACTION ):
1079cdf0e10cSrcweir                 {
1080cdf0e10cSrcweir 				    MetaRoundRectAction*    pAct = (MetaRoundRectAction*) pAction;
1081cdf0e10cSrcweir                     const Polygon           aRoundRectPoly( pAct->GetRect(), pAct->GetHorzRound(), pAct->GetVertRound() );
1082cdf0e10cSrcweir 
1083cdf0e10cSrcweir                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1084cdf0e10cSrcweir                 }
1085cdf0e10cSrcweir                 break;
1086cdf0e10cSrcweir 
1087cdf0e10cSrcweir                 case( META_ELLIPSE_ACTION ):
1088cdf0e10cSrcweir                 {
1089cdf0e10cSrcweir 				    MetaEllipseAction*      pAct = (MetaEllipseAction*) pAction;
1090cdf0e10cSrcweir                     const Polygon           aEllipsePoly( pAct->GetRect().Center(), pAct->GetRect().GetWidth() >> 1, pAct->GetRect().GetHeight() >> 1 );
1091cdf0e10cSrcweir 
1092cdf0e10cSrcweir                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1093cdf0e10cSrcweir                 }
1094cdf0e10cSrcweir                 break;
1095cdf0e10cSrcweir 
1096cdf0e10cSrcweir                 case( META_ARC_ACTION ):
1097cdf0e10cSrcweir                 {
1098cdf0e10cSrcweir 				    MetaArcAction*  pAct = (MetaArcAction*) pAction;
1099cdf0e10cSrcweir                     const Polygon   aArcPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_ARC );
1100cdf0e10cSrcweir 
1101cdf0e10cSrcweir                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1102cdf0e10cSrcweir                 }
1103cdf0e10cSrcweir                 break;
1104cdf0e10cSrcweir 
1105cdf0e10cSrcweir                 case( META_PIE_ACTION ):
1106cdf0e10cSrcweir                 {
1107cdf0e10cSrcweir 				    MetaPieAction*  pAct = (MetaPieAction*) pAction;
1108cdf0e10cSrcweir                     const Polygon   aPiePoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_PIE );
1109cdf0e10cSrcweir 
1110cdf0e10cSrcweir                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1111cdf0e10cSrcweir                 }
1112cdf0e10cSrcweir                 break;
1113cdf0e10cSrcweir 
1114cdf0e10cSrcweir                 case( META_CHORD_ACTION	):
1115cdf0e10cSrcweir                 {
1116cdf0e10cSrcweir 				    MetaChordAction*    pAct = (MetaChordAction*) pAction;
1117cdf0e10cSrcweir                     const Polygon       aChordPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_CHORD );
1118cdf0e10cSrcweir 
1119cdf0e10cSrcweir                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1120cdf0e10cSrcweir                 }
1121cdf0e10cSrcweir                 break;
1122cdf0e10cSrcweir 
1123cdf0e10cSrcweir                 case( META_POLYLINE_ACTION ):
1124cdf0e10cSrcweir                 {
1125cdf0e10cSrcweir 				    MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction;
1126cdf0e10cSrcweir                     aMtf.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->GetLineInfo() ) );
1127cdf0e10cSrcweir                 }
1128cdf0e10cSrcweir                 break;
1129cdf0e10cSrcweir 
1130cdf0e10cSrcweir                 case( META_POLYGON_ACTION ):
1131cdf0e10cSrcweir                 {
1132cdf0e10cSrcweir 				    MetaPolygonAction* pAct = (MetaPolygonAction*) pAction;
1133cdf0e10cSrcweir                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1134cdf0e10cSrcweir                 }
1135cdf0e10cSrcweir                 break;
1136cdf0e10cSrcweir 
1137cdf0e10cSrcweir                 case( META_POLYPOLYGON_ACTION ):
1138cdf0e10cSrcweir                 {
1139cdf0e10cSrcweir 				    MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction;
1140cdf0e10cSrcweir                     aMtf.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1141cdf0e10cSrcweir                 }
1142cdf0e10cSrcweir                 break;
1143cdf0e10cSrcweir 
1144cdf0e10cSrcweir                 case( META_TEXT_ACTION ):
1145cdf0e10cSrcweir                 {
1146cdf0e10cSrcweir 				    MetaTextAction* pAct = (MetaTextAction*) pAction;
1147cdf0e10cSrcweir                     aMtf.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1148cdf0e10cSrcweir                                                                              pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
1149cdf0e10cSrcweir                 }
1150cdf0e10cSrcweir                 break;
1151cdf0e10cSrcweir 
1152cdf0e10cSrcweir                 case( META_TEXTARRAY_ACTION	):
1153cdf0e10cSrcweir                 {
1154cdf0e10cSrcweir 				    MetaTextArrayAction* pAct = (MetaTextArrayAction*) pAction;
1155cdf0e10cSrcweir                     aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1156cdf0e10cSrcweir                                                                                   pAct->GetText(), pAct->GetDXArray(), pAct->GetIndex(), pAct->GetLen() ) );
1157cdf0e10cSrcweir                 }
1158cdf0e10cSrcweir                 break;
1159cdf0e10cSrcweir 
1160cdf0e10cSrcweir                 case( META_STRETCHTEXT_ACTION ):
1161cdf0e10cSrcweir                 {
1162cdf0e10cSrcweir 				    MetaStretchTextAction* pAct = (MetaStretchTextAction*) pAction;
1163cdf0e10cSrcweir                     aMtf.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1164cdf0e10cSrcweir                                                                                     pAct->GetWidth(), pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
1165cdf0e10cSrcweir                 }
1166cdf0e10cSrcweir                 break;
1167cdf0e10cSrcweir 
1168cdf0e10cSrcweir                 case( META_TEXTLINE_ACTION ):
1169cdf0e10cSrcweir                 {
1170cdf0e10cSrcweir 				    MetaTextLineAction* pAct = (MetaTextLineAction*) pAction;
1171cdf0e10cSrcweir                     aMtf.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1172cdf0e10cSrcweir                                                                                  pAct->GetWidth(), pAct->GetStrikeout(), pAct->GetUnderline(), pAct->GetOverline() ) );
1173cdf0e10cSrcweir                 }
1174cdf0e10cSrcweir                 break;
1175cdf0e10cSrcweir 
1176cdf0e10cSrcweir 			    case( META_BMPSCALE_ACTION ):
1177cdf0e10cSrcweir 			    {
1178cdf0e10cSrcweir 				    MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
1179cdf0e10cSrcweir                     Polygon             aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1180cdf0e10cSrcweir                     Rectangle           aBmpRect( aBmpPoly.GetBoundRect() );
1181cdf0e10cSrcweir                     BitmapEx            aBmpEx( pAct->GetBitmap() );
1182cdf0e10cSrcweir 
1183cdf0e10cSrcweir                     aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1184cdf0e10cSrcweir                     aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(),
1185cdf0e10cSrcweir                                                               aBmpEx ) );
1186cdf0e10cSrcweir 			    }
1187cdf0e10cSrcweir 			    break;
1188cdf0e10cSrcweir 
1189cdf0e10cSrcweir 			    case( META_BMPSCALEPART_ACTION ):
1190cdf0e10cSrcweir 			    {
1191cdf0e10cSrcweir 				    MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
1192cdf0e10cSrcweir                     Polygon                 aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1193cdf0e10cSrcweir                     Rectangle               aBmpRect( aBmpPoly.GetBoundRect() );
1194cdf0e10cSrcweir                     BitmapEx                aBmpEx( pAct->GetBitmap() );
1195cdf0e10cSrcweir 
1196cdf0e10cSrcweir                     aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1197cdf0e10cSrcweir                     aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1198cdf0e10cSrcweir 
1199cdf0e10cSrcweir                     aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1200cdf0e10cSrcweir 			    }
1201cdf0e10cSrcweir 			    break;
1202cdf0e10cSrcweir 
1203cdf0e10cSrcweir 			    case( META_BMPEXSCALE_ACTION ):
1204cdf0e10cSrcweir 			    {
1205cdf0e10cSrcweir 				    MetaBmpExScaleAction*   pAct = (MetaBmpExScaleAction*) pAction;
1206cdf0e10cSrcweir                     Polygon                 aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1207cdf0e10cSrcweir                     Rectangle               aBmpRect( aBmpPoly.GetBoundRect() );
1208cdf0e10cSrcweir                     BitmapEx                aBmpEx( pAct->GetBitmapEx() );
1209cdf0e10cSrcweir 
1210cdf0e10cSrcweir                     aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1211cdf0e10cSrcweir 
1212cdf0e10cSrcweir                     aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1213cdf0e10cSrcweir 			    }
1214cdf0e10cSrcweir 			    break;
1215cdf0e10cSrcweir 
1216cdf0e10cSrcweir 			    case( META_BMPEXSCALEPART_ACTION ):
1217cdf0e10cSrcweir 			    {
1218cdf0e10cSrcweir 				    MetaBmpExScalePartAction*   pAct = (MetaBmpExScalePartAction*) pAction;
1219cdf0e10cSrcweir                     Polygon                     aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1220cdf0e10cSrcweir                     Rectangle                   aBmpRect( aBmpPoly.GetBoundRect() );
1221cdf0e10cSrcweir                     BitmapEx                    aBmpEx( pAct->GetBitmapEx() );
1222cdf0e10cSrcweir 
1223cdf0e10cSrcweir                     aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1224cdf0e10cSrcweir                     aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1225cdf0e10cSrcweir 
1226cdf0e10cSrcweir                     aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1227cdf0e10cSrcweir 			    }
1228cdf0e10cSrcweir 			    break;
1229cdf0e10cSrcweir 
1230cdf0e10cSrcweir 			    case( META_GRADIENT_ACTION ):
1231cdf0e10cSrcweir 			    {
1232cdf0e10cSrcweir 				    MetaGradientAction* pAct = (MetaGradientAction*) pAction;
1233cdf0e10cSrcweir 
1234cdf0e10cSrcweir                     ImplAddGradientEx( aMtf, aMapVDev,
1235cdf0e10cSrcweir                                        ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ),
1236cdf0e10cSrcweir                                        pAct->GetGradient() );
1237cdf0e10cSrcweir 			    }
1238cdf0e10cSrcweir 			    break;
1239cdf0e10cSrcweir 
1240cdf0e10cSrcweir 			    case( META_GRADIENTEX_ACTION ):
1241cdf0e10cSrcweir 			    {
1242cdf0e10cSrcweir 				    MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
1243cdf0e10cSrcweir 				    aMtf.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1244cdf0e10cSrcweir                                                               pAct->GetGradient() ) );
1245cdf0e10cSrcweir 			    }
1246cdf0e10cSrcweir 			    break;
1247cdf0e10cSrcweir 
1248cdf0e10cSrcweir                 // #105055# Handle gradientex comment block correctly
1249cdf0e10cSrcweir                 case( META_COMMENT_ACTION ):
1250cdf0e10cSrcweir                 {
1251cdf0e10cSrcweir 				    MetaCommentAction* pCommentAct = (MetaCommentAction*) pAction;
1252cdf0e10cSrcweir                     if( pCommentAct->GetComment().Equals( "XGRAD_SEQ_BEGIN" ) )
1253cdf0e10cSrcweir                     {
1254cdf0e10cSrcweir                         int nBeginComments( 1 );
1255cdf0e10cSrcweir                         pAction = (MetaAction*) Next();
1256cdf0e10cSrcweir 
1257cdf0e10cSrcweir                         // skip everything, except gradientex action
1258cdf0e10cSrcweir                         while( pAction )
1259cdf0e10cSrcweir                         {
1260cdf0e10cSrcweir                             const sal_uInt16 nType = pAction->GetType();
1261cdf0e10cSrcweir 
1262cdf0e10cSrcweir                             if( META_GRADIENTEX_ACTION == nType )
1263cdf0e10cSrcweir                             {
1264cdf0e10cSrcweir                                 // Add rotated gradientex
1265cdf0e10cSrcweir                                 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
1266cdf0e10cSrcweir                                 ImplAddGradientEx( aMtf, aMapVDev,
1267cdf0e10cSrcweir                                                    ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1268cdf0e10cSrcweir                                                    pAct->GetGradient() );
1269cdf0e10cSrcweir                             }
1270cdf0e10cSrcweir                             else if( META_COMMENT_ACTION == nType)
1271cdf0e10cSrcweir                             {
1272cdf0e10cSrcweir                                 MetaCommentAction* pAct = (MetaCommentAction*) pAction;
1273cdf0e10cSrcweir                                 if( pAct->GetComment().Equals( "XGRAD_SEQ_END" ) )
1274cdf0e10cSrcweir                                 {
1275cdf0e10cSrcweir                                     // handle nested blocks
1276cdf0e10cSrcweir                                     --nBeginComments;
1277cdf0e10cSrcweir 
1278cdf0e10cSrcweir                                     // gradientex comment block: end reached, done.
1279cdf0e10cSrcweir                                     if( !nBeginComments )
1280cdf0e10cSrcweir                                         break;
1281cdf0e10cSrcweir                                 }
1282cdf0e10cSrcweir                                 else if( pAct->GetComment().Equals( "XGRAD_SEQ_BEGIN" ) )
1283cdf0e10cSrcweir                                 {
1284cdf0e10cSrcweir                                     // handle nested blocks
1285cdf0e10cSrcweir                                     ++nBeginComments;
1286cdf0e10cSrcweir                                 }
1287cdf0e10cSrcweir 
1288cdf0e10cSrcweir                             }
1289cdf0e10cSrcweir 
1290cdf0e10cSrcweir                             pAction = (MetaAction*) Next();
1291cdf0e10cSrcweir                         }
1292cdf0e10cSrcweir                     }
1293cdf0e10cSrcweir 					else
1294cdf0e10cSrcweir 					{
1295cdf0e10cSrcweir 						sal_Bool bPathStroke = pCommentAct->GetComment().Equals( "XPATHSTROKE_SEQ_BEGIN" );
1296cdf0e10cSrcweir 						if ( bPathStroke || pCommentAct->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) )
1297cdf0e10cSrcweir 						{
1298cdf0e10cSrcweir 							if ( pCommentAct->GetDataSize() )
1299cdf0e10cSrcweir 							{
1300cdf0e10cSrcweir 								SvMemoryStream aMemStm( (void*)pCommentAct->GetData(), pCommentAct->GetDataSize(), STREAM_READ );
1301cdf0e10cSrcweir 								SvMemoryStream aDest;
1302cdf0e10cSrcweir 								if ( bPathStroke )
1303cdf0e10cSrcweir 								{
1304cdf0e10cSrcweir 									SvtGraphicStroke aStroke;
1305cdf0e10cSrcweir 									aMemStm >> aStroke;
1306cdf0e10cSrcweir 									Polygon aPath;
1307cdf0e10cSrcweir 									aStroke.getPath( aPath );
1308cdf0e10cSrcweir 									aStroke.setPath( ImplGetRotatedPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1309cdf0e10cSrcweir 									aDest << aStroke;
1310cdf0e10cSrcweir 									aMtf.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1311cdf0e10cSrcweir 														static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1312cdf0e10cSrcweir 								}
1313cdf0e10cSrcweir 								else
1314cdf0e10cSrcweir 								{
1315cdf0e10cSrcweir 									SvtGraphicFill aFill;
1316cdf0e10cSrcweir 									aMemStm >> aFill;
1317cdf0e10cSrcweir 									PolyPolygon aPath;
1318cdf0e10cSrcweir 									aFill.getPath( aPath );
1319cdf0e10cSrcweir 									aFill.setPath( ImplGetRotatedPolyPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1320cdf0e10cSrcweir 									aDest << aFill;
1321cdf0e10cSrcweir 									aMtf.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1322cdf0e10cSrcweir 														static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1323cdf0e10cSrcweir 								}
1324cdf0e10cSrcweir 							}
1325cdf0e10cSrcweir 						}
1326cdf0e10cSrcweir 						else if ( pCommentAct->GetComment().Equals( "XPATHSTROKE_SEQ_END" )
1327cdf0e10cSrcweir 							   || pCommentAct->GetComment().Equals( "XPATHFILL_SEQ_END" ) )
1328cdf0e10cSrcweir 						{
1329cdf0e10cSrcweir 						    pAction->Execute( &aMapVDev );
1330cdf0e10cSrcweir 						    pAction->Duplicate();
1331cdf0e10cSrcweir 						    aMtf.AddAction( pAction );
1332cdf0e10cSrcweir 						}
1333cdf0e10cSrcweir 					}
1334cdf0e10cSrcweir                 }
1335cdf0e10cSrcweir                 break;
1336cdf0e10cSrcweir 
1337cdf0e10cSrcweir 			    case( META_HATCH_ACTION ):
1338cdf0e10cSrcweir 			    {
1339cdf0e10cSrcweir 				    MetaHatchAction*	pAct = (MetaHatchAction*) pAction;
1340cdf0e10cSrcweir 				    Hatch				aHatch( pAct->GetHatch() );
1341cdf0e10cSrcweir 
1342cdf0e10cSrcweir                     aHatch.SetAngle( aHatch.GetAngle() + (sal_uInt16) nAngle10 );
1343cdf0e10cSrcweir 				    aMtf.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1344cdf0e10cSrcweir                                                                                     aHatch ) );
1345cdf0e10cSrcweir 			    }
1346cdf0e10cSrcweir 			    break;
1347cdf0e10cSrcweir 
1348cdf0e10cSrcweir                 case( META_TRANSPARENT_ACTION ):
1349cdf0e10cSrcweir                 {
1350cdf0e10cSrcweir 				    MetaTransparentAction* pAct = (MetaTransparentAction*) pAction;
1351cdf0e10cSrcweir 				    aMtf.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1352cdf0e10cSrcweir                                                                                           pAct->GetTransparence() ) );
1353cdf0e10cSrcweir                 }
1354cdf0e10cSrcweir                 break;
1355cdf0e10cSrcweir 
1356cdf0e10cSrcweir 			    case( META_FLOATTRANSPARENT_ACTION ):
1357cdf0e10cSrcweir 			    {
1358cdf0e10cSrcweir 				    MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction;
1359cdf0e10cSrcweir 				    GDIMetaFile					aTransMtf( pAct->GetGDIMetaFile() );
1360cdf0e10cSrcweir                     Polygon                     aMtfPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1361cdf0e10cSrcweir                     Rectangle                   aMtfRect( aMtfPoly.GetBoundRect() );
1362cdf0e10cSrcweir 
1363cdf0e10cSrcweir                     aTransMtf.Rotate( nAngle10 );
1364cdf0e10cSrcweir 				    aMtf.AddAction( new MetaFloatTransparentAction( aTransMtf, aMtfRect.TopLeft(), aMtfRect.GetSize(),
1365cdf0e10cSrcweir                                                                     pAct->GetGradient() ) );
1366cdf0e10cSrcweir 			    }
1367cdf0e10cSrcweir 			    break;
1368cdf0e10cSrcweir 
1369cdf0e10cSrcweir 			    case( META_EPS_ACTION ):
1370cdf0e10cSrcweir 			    {
1371cdf0e10cSrcweir 				    MetaEPSAction*	pAct = (MetaEPSAction*) pAction;
1372cdf0e10cSrcweir 				    GDIMetaFile		aEPSMtf( pAct->GetSubstitute() );
1373cdf0e10cSrcweir                     Polygon         aEPSPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1374cdf0e10cSrcweir                     Rectangle       aEPSRect( aEPSPoly.GetBoundRect() );
1375cdf0e10cSrcweir 
1376cdf0e10cSrcweir                     aEPSMtf.Rotate( nAngle10 );
1377cdf0e10cSrcweir 				    aMtf.AddAction( new MetaEPSAction( aEPSRect.TopLeft(), aEPSRect.GetSize(),
1378cdf0e10cSrcweir 												       pAct->GetLink(), aEPSMtf ) );
1379cdf0e10cSrcweir 			    }
1380cdf0e10cSrcweir 			    break;
1381cdf0e10cSrcweir 
1382cdf0e10cSrcweir                 case( META_CLIPREGION_ACTION ):
1383cdf0e10cSrcweir                 {
1384cdf0e10cSrcweir 				    MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction;
1385cdf0e10cSrcweir 
1386cdf0e10cSrcweir                     if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygon() )
1387cdf0e10cSrcweir                         aMtf.AddAction( new MetaClipRegionAction( Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), sal_True ) );
1388cdf0e10cSrcweir                     else
1389cdf0e10cSrcweir                     {
1390cdf0e10cSrcweir 				        pAction->Duplicate();
1391cdf0e10cSrcweir 				        aMtf.AddAction( pAction );
1392cdf0e10cSrcweir                     }
1393cdf0e10cSrcweir                 }
1394cdf0e10cSrcweir                 break;
1395cdf0e10cSrcweir 
1396cdf0e10cSrcweir                 case( META_ISECTRECTCLIPREGION_ACTION ):
1397cdf0e10cSrcweir                 {
1398cdf0e10cSrcweir 				    MetaISectRectClipRegionAction*	pAct = (MetaISectRectClipRegionAction*) pAction;
1399cdf0e10cSrcweir                     aMtf.AddAction( new MetaISectRegionClipRegionAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1400cdf0e10cSrcweir                 }
1401cdf0e10cSrcweir                 break;
1402cdf0e10cSrcweir 
1403cdf0e10cSrcweir                 case( META_ISECTREGIONCLIPREGION_ACTION	):
1404cdf0e10cSrcweir                 {
1405cdf0e10cSrcweir 				    MetaISectRegionClipRegionAction*    pAct = (MetaISectRegionClipRegionAction*) pAction;
1406cdf0e10cSrcweir                     const Region&                       rRegion = pAct->GetRegion();
1407cdf0e10cSrcweir 
1408cdf0e10cSrcweir                     if( rRegion.HasPolyPolygon() )
1409cdf0e10cSrcweir                         aMtf.AddAction( new MetaISectRegionClipRegionAction( Region( ImplGetRotatedPolyPolygon( rRegion.GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
1410cdf0e10cSrcweir                     else
1411cdf0e10cSrcweir                     {
1412cdf0e10cSrcweir 				        pAction->Duplicate();
1413cdf0e10cSrcweir 				        aMtf.AddAction( pAction );
1414cdf0e10cSrcweir                     }
1415cdf0e10cSrcweir                 }
1416cdf0e10cSrcweir                 break;
1417cdf0e10cSrcweir 
1418cdf0e10cSrcweir                 case( META_REFPOINT_ACTION ):
1419cdf0e10cSrcweir                 {
1420cdf0e10cSrcweir 				    MetaRefPointAction* pAct = (MetaRefPointAction*) pAction;
1421cdf0e10cSrcweir                     aMtf.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct->GetRefPoint(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->IsSetting() ) );
1422cdf0e10cSrcweir                 }
1423cdf0e10cSrcweir                 break;
1424cdf0e10cSrcweir 
1425cdf0e10cSrcweir 			    case( META_FONT_ACTION ):
1426cdf0e10cSrcweir 			    {
1427cdf0e10cSrcweir 				    MetaFontAction* pAct = (MetaFontAction*) pAction;
1428cdf0e10cSrcweir 				    Font			aFont( pAct->GetFont() );
1429cdf0e10cSrcweir 
1430cdf0e10cSrcweir 				    aFont.SetOrientation( aFont.GetOrientation() + (sal_uInt16) nAngle10 );
1431cdf0e10cSrcweir 				    aMtf.AddAction( new MetaFontAction( aFont ) );
1432cdf0e10cSrcweir 			    }
1433cdf0e10cSrcweir 			    break;
1434cdf0e10cSrcweir 
1435cdf0e10cSrcweir 			    case( META_BMP_ACTION ):
1436cdf0e10cSrcweir 			    case( META_BMPEX_ACTION ):
1437cdf0e10cSrcweir 			    case( META_MASK_ACTION ):
1438cdf0e10cSrcweir 			    case( META_MASKSCALE_ACTION ):
1439cdf0e10cSrcweir 			    case( META_MASKSCALEPART_ACTION ):
1440cdf0e10cSrcweir                 case( META_WALLPAPER_ACTION ):
1441cdf0e10cSrcweir                 case( META_TEXTRECT_ACTION ):
1442cdf0e10cSrcweir                 case( META_MOVECLIPREGION_ACTION ):
1443cdf0e10cSrcweir 			    {
1444cdf0e10cSrcweir 				    DBG_ERROR( "GDIMetaFile::Rotate(): unsupported action" );
1445cdf0e10cSrcweir 			    }
1446cdf0e10cSrcweir 			    break;
1447cdf0e10cSrcweir 
1448cdf0e10cSrcweir 			    case( META_RENDERGRAPHIC_ACTION ):
1449cdf0e10cSrcweir                 {
1450cdf0e10cSrcweir                     OSL_TRACE( "Rotate not supported for RenderGraphic MetaActions yet" );
1451cdf0e10cSrcweir 
1452cdf0e10cSrcweir 				    pAction->Duplicate();
1453cdf0e10cSrcweir 				    aMtf.AddAction( pAction );
1454cdf0e10cSrcweir                 }
1455cdf0e10cSrcweir                 break;
1456cdf0e10cSrcweir 
1457cdf0e10cSrcweir 			    default:
1458cdf0e10cSrcweir 			    {
1459cdf0e10cSrcweir                     pAction->Execute( &aMapVDev );
1460cdf0e10cSrcweir 				    pAction->Duplicate();
1461cdf0e10cSrcweir 				    aMtf.AddAction( pAction );
1462cdf0e10cSrcweir 
1463cdf0e10cSrcweir                     // update rotation point and offset, if necessary
1464cdf0e10cSrcweir                     if( ( META_MAPMODE_ACTION == nActionType ) ||
1465cdf0e10cSrcweir                         ( META_PUSH_ACTION == nActionType ) ||
1466cdf0e10cSrcweir                         ( META_POP_ACTION == nActionType ) )
1467cdf0e10cSrcweir                     {
1468cdf0e10cSrcweir                         aRotAnchor = aMapVDev.LogicToLogic( aOrigin, aPrefMapMode, aMapVDev.GetMapMode() );
1469cdf0e10cSrcweir                         aRotOffset = aMapVDev.LogicToLogic( aOffset, aPrefMapMode, aMapVDev.GetMapMode() );
1470cdf0e10cSrcweir                     }
1471cdf0e10cSrcweir 			    }
1472cdf0e10cSrcweir 			    break;
1473cdf0e10cSrcweir 		    }
1474cdf0e10cSrcweir 	    }
1475cdf0e10cSrcweir 
1476cdf0e10cSrcweir 	    aMtf.aPrefMapMode = aPrefMapMode;
1477cdf0e10cSrcweir 	    aMtf.aPrefSize = aNewBound.GetSize();
1478cdf0e10cSrcweir 
1479cdf0e10cSrcweir 	    *this = aMtf;
1480cdf0e10cSrcweir     }
1481cdf0e10cSrcweir }
1482cdf0e10cSrcweir 
1483cdf0e10cSrcweir // ------------------------------------------------------------------------
1484cdf0e10cSrcweir 
1485cdf0e10cSrcweir static void ImplActionBounds( Rectangle& o_rOutBounds,
1486cdf0e10cSrcweir                               const Rectangle& i_rInBounds,
1487cdf0e10cSrcweir                               const std::vector<Rectangle>& i_rClipStack )
1488cdf0e10cSrcweir {
1489cdf0e10cSrcweir     Rectangle aBounds( i_rInBounds );
1490cdf0e10cSrcweir     if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() )
1491cdf0e10cSrcweir         aBounds.Intersection( i_rClipStack.back() );
1492cdf0e10cSrcweir     if( ! aBounds.IsEmpty() )
1493cdf0e10cSrcweir     {
1494cdf0e10cSrcweir         if( ! o_rOutBounds.IsEmpty() )
1495cdf0e10cSrcweir             o_rOutBounds.Union( aBounds );
1496cdf0e10cSrcweir         else
1497cdf0e10cSrcweir             o_rOutBounds = aBounds;
1498cdf0e10cSrcweir     }
1499cdf0e10cSrcweir }
1500cdf0e10cSrcweir 
1501cdf0e10cSrcweir Rectangle GDIMetaFile::GetBoundRect( OutputDevice& i_rReference )
1502cdf0e10cSrcweir {
1503cdf0e10cSrcweir     GDIMetaFile     aMtf;
1504cdf0e10cSrcweir     VirtualDevice   aMapVDev( i_rReference );
1505cdf0e10cSrcweir 
1506cdf0e10cSrcweir     aMapVDev.EnableOutput( sal_False );
1507cdf0e10cSrcweir     aMapVDev.SetMapMode( GetPrefMapMode() );
1508cdf0e10cSrcweir 
1509cdf0e10cSrcweir     std::vector<Rectangle> aClipStack( 1, Rectangle() );
1510cdf0e10cSrcweir     std::vector<sal_uInt16> aPushFlagStack;
1511cdf0e10cSrcweir 
1512cdf0e10cSrcweir     Rectangle aBound;
1513cdf0e10cSrcweir 
1514cdf0e10cSrcweir     for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() )
1515cdf0e10cSrcweir     {
1516cdf0e10cSrcweir         const sal_uInt16 nActionType = pAction->GetType();
1517cdf0e10cSrcweir 
1518cdf0e10cSrcweir         switch( nActionType )
1519cdf0e10cSrcweir         {
1520cdf0e10cSrcweir         case( META_PIXEL_ACTION ):
1521cdf0e10cSrcweir         {
1522cdf0e10cSrcweir             MetaPixelAction* pAct = (MetaPixelAction*) pAction;
1523cdf0e10cSrcweir             ImplActionBounds( aBound,
1524cdf0e10cSrcweir                              Rectangle( aMapVDev.LogicToLogic( pAct->GetPoint(), aMapVDev.GetMapMode(), GetPrefMapMode() ),
1525cdf0e10cSrcweir                                        aMapVDev.PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1526cdf0e10cSrcweir                              aClipStack );
1527cdf0e10cSrcweir         }
1528cdf0e10cSrcweir         break;
1529cdf0e10cSrcweir 
1530cdf0e10cSrcweir         case( META_POINT_ACTION ):
1531cdf0e10cSrcweir         {
1532cdf0e10cSrcweir             MetaPointAction* pAct = (MetaPointAction*) pAction;
1533cdf0e10cSrcweir             ImplActionBounds( aBound,
1534cdf0e10cSrcweir                              Rectangle( aMapVDev.LogicToLogic( pAct->GetPoint(), aMapVDev.GetMapMode(), GetPrefMapMode() ),
1535cdf0e10cSrcweir                                        aMapVDev.PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1536cdf0e10cSrcweir                              aClipStack );
1537cdf0e10cSrcweir         }
1538cdf0e10cSrcweir         break;
1539cdf0e10cSrcweir 
1540cdf0e10cSrcweir         case( META_LINE_ACTION ):
1541cdf0e10cSrcweir         {
1542cdf0e10cSrcweir             MetaLineAction* pAct = (MetaLineAction*) pAction;
1543cdf0e10cSrcweir             Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() );
1544cdf0e10cSrcweir             Rectangle aRect( aP1, aP2 );
1545cdf0e10cSrcweir             aRect.Justify();
1546cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1547cdf0e10cSrcweir         }
1548cdf0e10cSrcweir         break;
1549cdf0e10cSrcweir 
1550cdf0e10cSrcweir         case( META_RECT_ACTION ):
1551cdf0e10cSrcweir         {
1552cdf0e10cSrcweir             MetaRectAction* pAct = (MetaRectAction*) pAction;
1553cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1554cdf0e10cSrcweir         }
1555cdf0e10cSrcweir         break;
1556cdf0e10cSrcweir 
1557cdf0e10cSrcweir         case( META_ROUNDRECT_ACTION ):
1558cdf0e10cSrcweir         {
1559cdf0e10cSrcweir             MetaRoundRectAction*    pAct = (MetaRoundRectAction*) pAction;
1560cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1561cdf0e10cSrcweir         }
1562cdf0e10cSrcweir         break;
1563cdf0e10cSrcweir 
1564cdf0e10cSrcweir         case( META_ELLIPSE_ACTION ):
1565cdf0e10cSrcweir         {
1566cdf0e10cSrcweir             MetaEllipseAction*      pAct = (MetaEllipseAction*) pAction;
1567cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1568cdf0e10cSrcweir         }
1569cdf0e10cSrcweir         break;
1570cdf0e10cSrcweir 
1571cdf0e10cSrcweir         case( META_ARC_ACTION ):
1572cdf0e10cSrcweir         {
1573cdf0e10cSrcweir             MetaArcAction*  pAct = (MetaArcAction*) pAction;
1574cdf0e10cSrcweir             // FIXME: this is imprecise
1575cdf0e10cSrcweir             // e.g. for small arcs the whole rectangle is WAY too large
1576cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1577cdf0e10cSrcweir         }
1578cdf0e10cSrcweir         break;
1579cdf0e10cSrcweir 
1580cdf0e10cSrcweir         case( META_PIE_ACTION ):
1581cdf0e10cSrcweir         {
1582cdf0e10cSrcweir             MetaPieAction*  pAct = (MetaPieAction*) pAction;
1583cdf0e10cSrcweir             // FIXME: this is imprecise
1584cdf0e10cSrcweir             // e.g. for small arcs the whole rectangle is WAY too large
1585cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1586cdf0e10cSrcweir         }
1587cdf0e10cSrcweir         break;
1588cdf0e10cSrcweir 
1589cdf0e10cSrcweir         case( META_CHORD_ACTION	):
1590cdf0e10cSrcweir         {
1591cdf0e10cSrcweir             MetaChordAction*    pAct = (MetaChordAction*) pAction;
1592cdf0e10cSrcweir             // FIXME: this is imprecise
1593cdf0e10cSrcweir             // e.g. for small arcs the whole rectangle is WAY too large
1594cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1595cdf0e10cSrcweir         }
1596cdf0e10cSrcweir         break;
1597cdf0e10cSrcweir 
1598cdf0e10cSrcweir         case( META_POLYLINE_ACTION ):
1599cdf0e10cSrcweir         {
1600cdf0e10cSrcweir             MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction;
1601cdf0e10cSrcweir             Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1602cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1603cdf0e10cSrcweir         }
1604cdf0e10cSrcweir         break;
1605cdf0e10cSrcweir 
1606cdf0e10cSrcweir         case( META_POLYGON_ACTION ):
1607cdf0e10cSrcweir         {
1608cdf0e10cSrcweir             MetaPolygonAction* pAct = (MetaPolygonAction*) pAction;
1609cdf0e10cSrcweir             Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1610cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1611cdf0e10cSrcweir         }
1612cdf0e10cSrcweir         break;
1613cdf0e10cSrcweir 
1614cdf0e10cSrcweir         case( META_POLYPOLYGON_ACTION ):
1615cdf0e10cSrcweir         {
1616cdf0e10cSrcweir             MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction;
1617cdf0e10cSrcweir             Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1618cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1619cdf0e10cSrcweir         }
1620cdf0e10cSrcweir         break;
1621cdf0e10cSrcweir 
1622cdf0e10cSrcweir         case( META_TEXT_ACTION ):
1623cdf0e10cSrcweir         {
1624cdf0e10cSrcweir             MetaTextAction* pAct = (MetaTextAction*) pAction;
1625cdf0e10cSrcweir             Rectangle aRect;
1626cdf0e10cSrcweir             // hdu said base = index
1627cdf0e10cSrcweir             aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() );
1628cdf0e10cSrcweir             Point aPt( pAct->GetPoint() );
1629cdf0e10cSrcweir             aRect.Move( aPt.X(), aPt.Y() );
1630cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1631cdf0e10cSrcweir         }
1632cdf0e10cSrcweir         break;
1633cdf0e10cSrcweir 
1634cdf0e10cSrcweir         case( META_TEXTARRAY_ACTION	):
1635cdf0e10cSrcweir         {
1636cdf0e10cSrcweir             MetaTextArrayAction* pAct = (MetaTextArrayAction*) pAction;
1637cdf0e10cSrcweir             Rectangle aRect;
1638cdf0e10cSrcweir             // hdu said base = index
1639cdf0e10cSrcweir             aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1640cdf0e10cSrcweir                                        0, pAct->GetDXArray() );
1641cdf0e10cSrcweir             Point aPt( pAct->GetPoint() );
1642cdf0e10cSrcweir             aRect.Move( aPt.X(), aPt.Y() );
1643cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1644cdf0e10cSrcweir         }
1645cdf0e10cSrcweir         break;
1646cdf0e10cSrcweir 
1647cdf0e10cSrcweir         case( META_STRETCHTEXT_ACTION ):
1648cdf0e10cSrcweir         {
1649cdf0e10cSrcweir             MetaStretchTextAction* pAct = (MetaStretchTextAction*) pAction;
1650cdf0e10cSrcweir             Rectangle aRect;
1651cdf0e10cSrcweir             // hdu said base = index
1652cdf0e10cSrcweir             aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1653cdf0e10cSrcweir                                        pAct->GetWidth(), NULL );
1654cdf0e10cSrcweir             Point aPt( pAct->GetPoint() );
1655cdf0e10cSrcweir             aRect.Move( aPt.X(), aPt.Y() );
1656cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1657cdf0e10cSrcweir         }
1658cdf0e10cSrcweir         break;
1659cdf0e10cSrcweir 
1660cdf0e10cSrcweir         case( META_TEXTLINE_ACTION ):
1661cdf0e10cSrcweir         {
1662cdf0e10cSrcweir             MetaTextLineAction* pAct = (MetaTextLineAction*) pAction;
1663cdf0e10cSrcweir             // measure a test string to get ascend and descent right
1664cdf0e10cSrcweir             static const sal_Unicode pStr[] = { 0xc4, 0x67, 0 };
1665cdf0e10cSrcweir             String aStr( pStr );
1666cdf0e10cSrcweir 
1667cdf0e10cSrcweir             Rectangle aRect;
1668cdf0e10cSrcweir             aMapVDev.GetTextBoundRect( aRect, aStr, 0, 0, aStr.Len(), 0, NULL );
1669cdf0e10cSrcweir             Point aPt( pAct->GetStartPoint() );
1670cdf0e10cSrcweir             aRect.Move( aPt.X(), aPt.Y() );
1671cdf0e10cSrcweir             aRect.Right() = aRect.Left() + pAct->GetWidth();
1672cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1673cdf0e10cSrcweir         }
1674cdf0e10cSrcweir         break;
1675cdf0e10cSrcweir 
1676cdf0e10cSrcweir         case( META_BMPSCALE_ACTION ):
1677cdf0e10cSrcweir         {
1678cdf0e10cSrcweir             MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
1679cdf0e10cSrcweir             Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1680cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1681cdf0e10cSrcweir         }
1682cdf0e10cSrcweir         break;
1683cdf0e10cSrcweir 
1684cdf0e10cSrcweir         case( META_BMPSCALEPART_ACTION ):
1685cdf0e10cSrcweir         {
1686cdf0e10cSrcweir             MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
1687cdf0e10cSrcweir             Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1688cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1689cdf0e10cSrcweir         }
1690cdf0e10cSrcweir         break;
1691cdf0e10cSrcweir 
1692cdf0e10cSrcweir         case( META_BMPEXSCALE_ACTION ):
1693cdf0e10cSrcweir         {
1694cdf0e10cSrcweir             MetaBmpExScaleAction*   pAct = (MetaBmpExScaleAction*) pAction;
1695cdf0e10cSrcweir             Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1696cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1697cdf0e10cSrcweir         }
1698cdf0e10cSrcweir         break;
1699cdf0e10cSrcweir 
1700cdf0e10cSrcweir         case( META_BMPEXSCALEPART_ACTION ):
1701cdf0e10cSrcweir         {
1702cdf0e10cSrcweir             MetaBmpExScalePartAction*   pAct = (MetaBmpExScalePartAction*) pAction;
1703cdf0e10cSrcweir             Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1704cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1705cdf0e10cSrcweir         }
1706cdf0e10cSrcweir         break;
1707cdf0e10cSrcweir 
1708cdf0e10cSrcweir         case( META_GRADIENT_ACTION ):
1709cdf0e10cSrcweir         {
1710cdf0e10cSrcweir             MetaGradientAction* pAct = (MetaGradientAction*) pAction;
1711cdf0e10cSrcweir             Rectangle aRect( pAct->GetRect() );
1712cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1713cdf0e10cSrcweir         }
1714cdf0e10cSrcweir         break;
1715cdf0e10cSrcweir 
1716cdf0e10cSrcweir         case( META_GRADIENTEX_ACTION ):
1717cdf0e10cSrcweir         {
1718cdf0e10cSrcweir             MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
1719cdf0e10cSrcweir             Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1720cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1721cdf0e10cSrcweir         }
1722cdf0e10cSrcweir         break;
1723cdf0e10cSrcweir 
1724cdf0e10cSrcweir         case( META_COMMENT_ACTION ):
1725cdf0e10cSrcweir         {
1726cdf0e10cSrcweir             // nothing to do
1727cdf0e10cSrcweir         };
1728cdf0e10cSrcweir         break;
1729cdf0e10cSrcweir 
1730cdf0e10cSrcweir         case( META_HATCH_ACTION ):
1731cdf0e10cSrcweir         {
1732cdf0e10cSrcweir             MetaHatchAction*	pAct = (MetaHatchAction*) pAction;
1733cdf0e10cSrcweir             Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1734cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1735cdf0e10cSrcweir         }
1736cdf0e10cSrcweir         break;
1737cdf0e10cSrcweir 
1738cdf0e10cSrcweir         case( META_TRANSPARENT_ACTION ):
1739cdf0e10cSrcweir         {
1740cdf0e10cSrcweir             MetaTransparentAction* pAct = (MetaTransparentAction*) pAction;
1741cdf0e10cSrcweir             Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1742cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1743cdf0e10cSrcweir         }
1744cdf0e10cSrcweir         break;
1745cdf0e10cSrcweir 
1746cdf0e10cSrcweir         case( META_FLOATTRANSPARENT_ACTION ):
1747cdf0e10cSrcweir         {
1748cdf0e10cSrcweir             MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction;
1749cdf0e10cSrcweir             GDIMetaFile					aTransMtf( pAct->GetGDIMetaFile() );
1750cdf0e10cSrcweir             // get the bound rect of the contained metafile
1751cdf0e10cSrcweir             Rectangle aRect( aTransMtf.GetBoundRect( i_rReference ) );
1752cdf0e10cSrcweir             // scale the rect now on the assumption that the correct top left of the metafile
1753cdf0e10cSrcweir             // (not its bounds !) is (0,0)
1754cdf0e10cSrcweir             Size aPSize( aTransMtf.GetPrefSize() );
1755cdf0e10cSrcweir             aPSize = aMapVDev.LogicToLogic( aPSize, aTransMtf.GetPrefMapMode(), aMapVDev.GetMapMode() );
1756cdf0e10cSrcweir             Size aActSize( pAct->GetSize() );
1757cdf0e10cSrcweir             double fX = double(aActSize.Width())/double(aPSize.Width());
1758cdf0e10cSrcweir             double fY = double(aActSize.Height())/double(aPSize.Height());
1759cdf0e10cSrcweir             aRect.Left()   = long(double(aRect.Left())*fX);
1760cdf0e10cSrcweir             aRect.Right()  = long(double(aRect.Right())*fX);
1761cdf0e10cSrcweir             aRect.Top()    = long(double(aRect.Top())*fY);
1762cdf0e10cSrcweir             aRect.Bottom() = long(double(aRect.Bottom())*fY);
1763cdf0e10cSrcweir 
1764cdf0e10cSrcweir             // transform the rect to current VDev state
1765cdf0e10cSrcweir             aRect = aMapVDev.LogicToLogic( aRect, aTransMtf.GetPrefMapMode(), aMapVDev.GetMapMode() );
1766cdf0e10cSrcweir 
1767cdf0e10cSrcweir             ImplActionBounds( aBound, aRect, aClipStack );
1768cdf0e10cSrcweir         }
1769cdf0e10cSrcweir         break;
1770cdf0e10cSrcweir 
1771cdf0e10cSrcweir         case( META_EPS_ACTION ):
1772cdf0e10cSrcweir         {
1773cdf0e10cSrcweir             MetaEPSAction*	pAct = (MetaEPSAction*) pAction;
1774cdf0e10cSrcweir             Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1775cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1776cdf0e10cSrcweir         }
1777cdf0e10cSrcweir         break;
1778cdf0e10cSrcweir 
1779cdf0e10cSrcweir         case( META_CLIPREGION_ACTION ):
1780cdf0e10cSrcweir         {
1781cdf0e10cSrcweir             MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction;
1782cdf0e10cSrcweir             if( pAct->IsClipping() )
1783cdf0e10cSrcweir                 aClipStack.back() = aMapVDev.LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev.GetMapMode(), GetPrefMapMode() );
1784cdf0e10cSrcweir             else
1785cdf0e10cSrcweir                 aClipStack.back() = Rectangle();
1786cdf0e10cSrcweir         }
1787cdf0e10cSrcweir         break;
1788cdf0e10cSrcweir 
1789cdf0e10cSrcweir         case( META_ISECTRECTCLIPREGION_ACTION ):
1790cdf0e10cSrcweir         {
1791cdf0e10cSrcweir             MetaISectRectClipRegionAction* pAct = (MetaISectRectClipRegionAction*) pAction;
1792cdf0e10cSrcweir             Rectangle aRect( aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ) );
1793cdf0e10cSrcweir             if( aClipStack.back().IsEmpty() )
1794cdf0e10cSrcweir                 aClipStack.back() = aRect;
1795cdf0e10cSrcweir             else
1796cdf0e10cSrcweir                 aClipStack.back().Intersection( aRect );
1797cdf0e10cSrcweir         }
1798cdf0e10cSrcweir         break;
1799cdf0e10cSrcweir 
1800cdf0e10cSrcweir         case( META_ISECTREGIONCLIPREGION_ACTION	):
1801cdf0e10cSrcweir         {
1802cdf0e10cSrcweir             MetaISectRegionClipRegionAction*    pAct = (MetaISectRegionClipRegionAction*) pAction;
1803cdf0e10cSrcweir             Rectangle aRect( aMapVDev.LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ) );
1804cdf0e10cSrcweir             if( aClipStack.back().IsEmpty() )
1805cdf0e10cSrcweir                 aClipStack.back() = aRect;
1806cdf0e10cSrcweir             else
1807cdf0e10cSrcweir                 aClipStack.back().Intersection( aRect );
1808cdf0e10cSrcweir         }
1809cdf0e10cSrcweir         break;
1810cdf0e10cSrcweir 
1811cdf0e10cSrcweir         case( META_BMP_ACTION ):
1812cdf0e10cSrcweir         {
1813cdf0e10cSrcweir             MetaBmpAction* pAct = (MetaBmpAction*) pAction;
1814cdf0e10cSrcweir             Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1815cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1816cdf0e10cSrcweir         }
1817cdf0e10cSrcweir         break;
1818cdf0e10cSrcweir 
1819cdf0e10cSrcweir         case( META_BMPEX_ACTION ):
1820cdf0e10cSrcweir         {
1821cdf0e10cSrcweir             MetaBmpExAction* pAct = (MetaBmpExAction*) pAction;
1822cdf0e10cSrcweir             Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) );
1823cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1824cdf0e10cSrcweir         }
1825cdf0e10cSrcweir         break;
1826cdf0e10cSrcweir 
1827cdf0e10cSrcweir         case( META_MASK_ACTION ):
1828cdf0e10cSrcweir         {
1829cdf0e10cSrcweir             MetaMaskAction* pAct = (MetaMaskAction*) pAction;
1830cdf0e10cSrcweir             Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1831cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1832cdf0e10cSrcweir         }
1833cdf0e10cSrcweir         break;
1834cdf0e10cSrcweir 
1835cdf0e10cSrcweir         case( META_MASKSCALE_ACTION ):
1836cdf0e10cSrcweir         {
1837cdf0e10cSrcweir             MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
1838cdf0e10cSrcweir             Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1839cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1840cdf0e10cSrcweir         }
1841cdf0e10cSrcweir         break;
1842cdf0e10cSrcweir 
1843cdf0e10cSrcweir         case( META_MASKSCALEPART_ACTION ):
1844cdf0e10cSrcweir         {
1845cdf0e10cSrcweir             MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
1846cdf0e10cSrcweir             Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1847cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1848cdf0e10cSrcweir         }
1849cdf0e10cSrcweir         break;
1850cdf0e10cSrcweir 
1851cdf0e10cSrcweir         case( META_WALLPAPER_ACTION ):
1852cdf0e10cSrcweir         {
1853cdf0e10cSrcweir             MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction;
1854cdf0e10cSrcweir             Rectangle aRect( pAct->GetRect() );
1855cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1856cdf0e10cSrcweir         }
1857cdf0e10cSrcweir         break;
1858cdf0e10cSrcweir 
1859cdf0e10cSrcweir         case( META_TEXTRECT_ACTION ):
1860cdf0e10cSrcweir         {
1861cdf0e10cSrcweir             MetaTextRectAction* pAct = (MetaTextRectAction*) pAction;
1862cdf0e10cSrcweir             Rectangle aRect( pAct->GetRect() );
1863cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1864cdf0e10cSrcweir         }
1865cdf0e10cSrcweir         break;
1866cdf0e10cSrcweir 
1867cdf0e10cSrcweir         case( META_MOVECLIPREGION_ACTION ):
1868cdf0e10cSrcweir         {
1869cdf0e10cSrcweir             MetaMoveClipRegionAction* pAct = (MetaMoveClipRegionAction*) pAction;
1870cdf0e10cSrcweir             if( ! aClipStack.back().IsEmpty() )
1871cdf0e10cSrcweir             {
1872cdf0e10cSrcweir                 Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() );
1873cdf0e10cSrcweir                 aDelta = aMapVDev.LogicToLogic( aDelta, aMapVDev.GetMapMode(), GetPrefMapMode() );
1874cdf0e10cSrcweir                 aClipStack.back().Move( aDelta.Width(), aDelta.Width() );
1875cdf0e10cSrcweir             }
1876cdf0e10cSrcweir         }
1877cdf0e10cSrcweir         break;
1878cdf0e10cSrcweir 
1879cdf0e10cSrcweir         case( META_RENDERGRAPHIC_ACTION ):
1880cdf0e10cSrcweir         {
1881cdf0e10cSrcweir             MetaRenderGraphicAction* pAct = (MetaRenderGraphicAction*) pAction;
1882cdf0e10cSrcweir             Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1883cdf0e10cSrcweir             ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1884cdf0e10cSrcweir         }
1885cdf0e10cSrcweir         break;
1886cdf0e10cSrcweir 
1887cdf0e10cSrcweir         default:
1888cdf0e10cSrcweir             {
1889cdf0e10cSrcweir                 pAction->Execute( &aMapVDev );
1890cdf0e10cSrcweir 
1891cdf0e10cSrcweir                 if( nActionType == META_PUSH_ACTION )
1892cdf0e10cSrcweir                 {
1893cdf0e10cSrcweir                     MetaPushAction* pAct = (MetaPushAction*) pAction;
1894cdf0e10cSrcweir                     aPushFlagStack.push_back( pAct->GetFlags() );
1895cdf0e10cSrcweir                     if( (aPushFlagStack.back() & PUSH_CLIPREGION) != 0 )
1896cdf0e10cSrcweir                     {
1897cdf0e10cSrcweir                         Rectangle aRect( aClipStack.back() );
1898cdf0e10cSrcweir                         aClipStack.push_back( aRect );
1899cdf0e10cSrcweir                     }
1900cdf0e10cSrcweir                 }
1901cdf0e10cSrcweir                 else if( nActionType == META_POP_ACTION )
1902cdf0e10cSrcweir                 {
1903cdf0e10cSrcweir                     // sanity check
1904cdf0e10cSrcweir                     if( ! aPushFlagStack.empty() )
1905cdf0e10cSrcweir                     {
1906cdf0e10cSrcweir                         if( (aPushFlagStack.back() & PUSH_CLIPREGION) != 0 )
1907cdf0e10cSrcweir                         {
1908cdf0e10cSrcweir                             if( aClipStack.size() > 1 )
1909cdf0e10cSrcweir                                 aClipStack.pop_back();
1910cdf0e10cSrcweir                         }
1911cdf0e10cSrcweir                         aPushFlagStack.pop_back();
1912cdf0e10cSrcweir                     }
1913cdf0e10cSrcweir                 }
1914cdf0e10cSrcweir             }
1915cdf0e10cSrcweir             break;
1916cdf0e10cSrcweir         }
1917cdf0e10cSrcweir     }
1918cdf0e10cSrcweir     return aBound;
1919cdf0e10cSrcweir }
1920cdf0e10cSrcweir 
1921cdf0e10cSrcweir // ------------------------------------------------------------------------
1922cdf0e10cSrcweir 
1923cdf0e10cSrcweir Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
1924cdf0e10cSrcweir {
1925cdf0e10cSrcweir 	return Color( rColor.GetTransparency(),
1926cdf0e10cSrcweir 				  ( (const ImplColAdjustParam*) pColParam )->pMapR[ rColor.GetRed() ],
1927cdf0e10cSrcweir 				  ( (const ImplColAdjustParam*) pColParam )->pMapG[ rColor.GetGreen() ],
1928cdf0e10cSrcweir 				  ( (const ImplColAdjustParam*) pColParam )->pMapB[ rColor.GetBlue() ] );
1929cdf0e10cSrcweir 
1930cdf0e10cSrcweir }
1931cdf0e10cSrcweir 
1932cdf0e10cSrcweir // ------------------------------------------------------------------------
1933cdf0e10cSrcweir 
1934cdf0e10cSrcweir BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1935cdf0e10cSrcweir {
1936cdf0e10cSrcweir 	const ImplBmpAdjustParam*	p = (const ImplBmpAdjustParam*) pBmpParam;
1937cdf0e10cSrcweir 	BitmapEx					aRet( rBmpEx );
1938cdf0e10cSrcweir 
1939cdf0e10cSrcweir 	aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
1940cdf0e10cSrcweir 				 p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
1941cdf0e10cSrcweir 				 p->fGamma, p->bInvert );
1942cdf0e10cSrcweir 
1943cdf0e10cSrcweir 	return aRet;
1944cdf0e10cSrcweir }
1945cdf0e10cSrcweir 
1946cdf0e10cSrcweir // ------------------------------------------------------------------------
1947cdf0e10cSrcweir 
1948cdf0e10cSrcweir Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
1949cdf0e10cSrcweir {
1950cdf0e10cSrcweir 	sal_uInt8 cLum = rColor.GetLuminance();
1951cdf0e10cSrcweir 
1952cdf0e10cSrcweir 	if( MTF_CONVERSION_1BIT_THRESHOLD == ( (const ImplColConvertParam*) pColParam )->eConversion )
1953cdf0e10cSrcweir 		cLum = ( cLum < 128 ) ? 0 : 255;
1954cdf0e10cSrcweir 
1955cdf0e10cSrcweir 	return Color( rColor.GetTransparency(), cLum, cLum, cLum );
1956cdf0e10cSrcweir }
1957cdf0e10cSrcweir 
1958cdf0e10cSrcweir // ------------------------------------------------------------------------
1959cdf0e10cSrcweir 
1960cdf0e10cSrcweir BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1961cdf0e10cSrcweir {
1962cdf0e10cSrcweir 	BitmapEx aRet( rBmpEx );
1963cdf0e10cSrcweir 
1964cdf0e10cSrcweir 	aRet.Convert( ( (const ImplBmpConvertParam*) pBmpParam )->eConversion );
1965cdf0e10cSrcweir 
1966cdf0e10cSrcweir 	return aRet;
1967cdf0e10cSrcweir }
1968cdf0e10cSrcweir 
1969cdf0e10cSrcweir // ------------------------------------------------------------------------
1970cdf0e10cSrcweir 
1971cdf0e10cSrcweir Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam )
1972cdf0e10cSrcweir {
1973cdf0e10cSrcweir 	return( ( (const ImplColMonoParam*) pColParam )->aColor );
1974cdf0e10cSrcweir }
1975cdf0e10cSrcweir 
1976cdf0e10cSrcweir // ------------------------------------------------------------------------
1977cdf0e10cSrcweir 
1978cdf0e10cSrcweir BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1979cdf0e10cSrcweir {
1980cdf0e10cSrcweir 	BitmapPalette aPal( 3 );
1981cdf0e10cSrcweir 
1982cdf0e10cSrcweir 	aPal[ 0 ] = Color( COL_BLACK );
1983cdf0e10cSrcweir 	aPal[ 1 ] = Color( COL_WHITE );
1984cdf0e10cSrcweir 	aPal[ 2 ] = ( (const ImplBmpMonoParam*) pBmpParam )->aColor;
1985cdf0e10cSrcweir 
1986cdf0e10cSrcweir 	Bitmap aBmp( rBmpEx.GetSizePixel(), 4, &aPal );
1987cdf0e10cSrcweir 	aBmp.Erase( ( (const ImplBmpMonoParam*) pBmpParam )->aColor );
1988cdf0e10cSrcweir 
1989cdf0e10cSrcweir 	if( rBmpEx.IsAlpha() )
1990cdf0e10cSrcweir 		return BitmapEx( aBmp, rBmpEx.GetAlpha() );
1991cdf0e10cSrcweir 	else if( rBmpEx.IsTransparent() )
1992cdf0e10cSrcweir 		return BitmapEx( aBmp, rBmpEx.GetMask() );
1993cdf0e10cSrcweir 	else
1994cdf0e10cSrcweir 		return aBmp;
1995cdf0e10cSrcweir }
1996cdf0e10cSrcweir 
1997cdf0e10cSrcweir // ------------------------------------------------------------------------
1998cdf0e10cSrcweir 
1999cdf0e10cSrcweir Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
2000cdf0e10cSrcweir {
2001cdf0e10cSrcweir 	const sal_uLong nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
2002cdf0e10cSrcweir 
2003cdf0e10cSrcweir 	for( sal_uLong i = 0; i < ( (const ImplColReplaceParam*) pColParam )->nCount; i++ )
2004cdf0e10cSrcweir 	{
2005cdf0e10cSrcweir 		if( ( ( (const ImplColReplaceParam*) pColParam )->pMinR[ i ] <= nR ) &&
2006cdf0e10cSrcweir 			( ( (const ImplColReplaceParam*) pColParam )->pMaxR[ i ] >= nR ) &&
2007cdf0e10cSrcweir 			( ( (const ImplColReplaceParam*) pColParam )->pMinG[ i ] <= nG ) &&
2008cdf0e10cSrcweir 			( ( (const ImplColReplaceParam*) pColParam )->pMaxG[ i ] >= nG ) &&
2009cdf0e10cSrcweir 			( ( (const ImplColReplaceParam*) pColParam )->pMinB[ i ] <= nB ) &&
2010cdf0e10cSrcweir 			( ( (const ImplColReplaceParam*) pColParam )->pMaxB[ i ] >= nB ) )
2011cdf0e10cSrcweir 		{
2012cdf0e10cSrcweir 			return( ( (const ImplColReplaceParam*) pColParam )->pDstCols[ i ] );
2013cdf0e10cSrcweir 		}
2014cdf0e10cSrcweir 	}
2015cdf0e10cSrcweir 
2016cdf0e10cSrcweir 	return rColor;
2017cdf0e10cSrcweir }
2018cdf0e10cSrcweir 
2019cdf0e10cSrcweir // ------------------------------------------------------------------------
2020cdf0e10cSrcweir 
2021cdf0e10cSrcweir BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
2022cdf0e10cSrcweir {
2023cdf0e10cSrcweir 	const ImplBmpReplaceParam*	p = (const ImplBmpReplaceParam*) pBmpParam;
2024cdf0e10cSrcweir 	BitmapEx					aRet( rBmpEx );
2025cdf0e10cSrcweir 
2026cdf0e10cSrcweir 	aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount, p->pTols );
2027cdf0e10cSrcweir 
2028cdf0e10cSrcweir 	return aRet;
2029cdf0e10cSrcweir }
2030cdf0e10cSrcweir 
2031cdf0e10cSrcweir // ------------------------------------------------------------------------
2032cdf0e10cSrcweir 
2033cdf0e10cSrcweir void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
2034cdf0e10cSrcweir 									  BmpExchangeFnc pFncBmp, const void* pBmpParam )
2035cdf0e10cSrcweir {
2036cdf0e10cSrcweir 	GDIMetaFile aMtf;
2037cdf0e10cSrcweir 
2038cdf0e10cSrcweir 	aMtf.aPrefSize = aPrefSize;
2039cdf0e10cSrcweir 	aMtf.aPrefMapMode = aPrefMapMode;
2040cdf0e10cSrcweir 
2041cdf0e10cSrcweir 	for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() )
2042cdf0e10cSrcweir 	{
2043cdf0e10cSrcweir 		const sal_uInt16 nType = pAction->GetType();
2044cdf0e10cSrcweir 
2045cdf0e10cSrcweir 		switch( nType )
2046cdf0e10cSrcweir 		{
2047cdf0e10cSrcweir 			case( META_PIXEL_ACTION ):
2048cdf0e10cSrcweir 			{
2049cdf0e10cSrcweir 				MetaPixelAction* pAct = (MetaPixelAction*) pAction;
2050cdf0e10cSrcweir 				aMtf.Insert( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND );
2051cdf0e10cSrcweir 			}
2052cdf0e10cSrcweir 			break;
2053cdf0e10cSrcweir 
2054cdf0e10cSrcweir 			case( META_LINECOLOR_ACTION ):
2055cdf0e10cSrcweir 			{
2056cdf0e10cSrcweir 				MetaLineColorAction* pAct = (MetaLineColorAction*) pAction;
2057cdf0e10cSrcweir 
2058cdf0e10cSrcweir 				if( !pAct->IsSetting() )
2059cdf0e10cSrcweir 					pAct->Duplicate();
2060cdf0e10cSrcweir 				else
2061cdf0e10cSrcweir 					pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True );
2062cdf0e10cSrcweir 
2063cdf0e10cSrcweir 				aMtf.Insert( pAct, LIST_APPEND );
2064cdf0e10cSrcweir 			}
2065cdf0e10cSrcweir 			break;
2066cdf0e10cSrcweir 
2067cdf0e10cSrcweir 			case( META_FILLCOLOR_ACTION ):
2068cdf0e10cSrcweir 			{
2069cdf0e10cSrcweir 				MetaFillColorAction* pAct = (MetaFillColorAction*) pAction;
2070cdf0e10cSrcweir 
2071cdf0e10cSrcweir 				if( !pAct->IsSetting() )
2072cdf0e10cSrcweir 					pAct->Duplicate();
2073cdf0e10cSrcweir 				else
2074cdf0e10cSrcweir 					pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True );
2075cdf0e10cSrcweir 
2076cdf0e10cSrcweir 				aMtf.Insert( pAct, LIST_APPEND );
2077cdf0e10cSrcweir 			}
2078cdf0e10cSrcweir 			break;
2079cdf0e10cSrcweir 
2080cdf0e10cSrcweir 			case( META_TEXTCOLOR_ACTION ):
2081cdf0e10cSrcweir 			{
2082cdf0e10cSrcweir 				MetaTextColorAction* pAct = (MetaTextColorAction*) pAction;
2083cdf0e10cSrcweir 				aMtf.Insert( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND );
2084cdf0e10cSrcweir 			}
2085cdf0e10cSrcweir 			break;
2086cdf0e10cSrcweir 
2087cdf0e10cSrcweir 			case( META_TEXTFILLCOLOR_ACTION ):
2088cdf0e10cSrcweir 			{
2089cdf0e10cSrcweir 				MetaTextFillColorAction* pAct = (MetaTextFillColorAction*) pAction;
2090cdf0e10cSrcweir 
2091cdf0e10cSrcweir 				if( !pAct->IsSetting() )
2092cdf0e10cSrcweir 					pAct->Duplicate();
2093cdf0e10cSrcweir 				else
2094cdf0e10cSrcweir 					pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True );
2095cdf0e10cSrcweir 
2096cdf0e10cSrcweir 				aMtf.Insert( pAct, LIST_APPEND );
2097cdf0e10cSrcweir 			}
2098cdf0e10cSrcweir 			break;
2099cdf0e10cSrcweir 
2100cdf0e10cSrcweir 			case( META_TEXTLINECOLOR_ACTION ):
2101cdf0e10cSrcweir 			{
2102cdf0e10cSrcweir 				MetaTextLineColorAction* pAct = (MetaTextLineColorAction*) pAction;
2103cdf0e10cSrcweir 
2104cdf0e10cSrcweir 				if( !pAct->IsSetting() )
2105cdf0e10cSrcweir 					pAct->Duplicate();
2106cdf0e10cSrcweir 				else
2107cdf0e10cSrcweir 					pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True );
2108cdf0e10cSrcweir 
2109cdf0e10cSrcweir 				aMtf.Insert( pAct, LIST_APPEND );
2110cdf0e10cSrcweir 			}
2111cdf0e10cSrcweir 			break;
2112cdf0e10cSrcweir 
2113cdf0e10cSrcweir 			case( META_OVERLINECOLOR_ACTION ):
2114cdf0e10cSrcweir 			{
2115cdf0e10cSrcweir 				MetaOverlineColorAction* pAct = (MetaOverlineColorAction*) pAction;
2116cdf0e10cSrcweir 
2117cdf0e10cSrcweir 				if( !pAct->IsSetting() )
2118cdf0e10cSrcweir 					pAct->Duplicate();
2119cdf0e10cSrcweir 				else
2120cdf0e10cSrcweir 					pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), sal_True );
2121cdf0e10cSrcweir 
2122cdf0e10cSrcweir 				aMtf.Insert( pAct, LIST_APPEND );
2123cdf0e10cSrcweir 			}
2124cdf0e10cSrcweir 			break;
2125cdf0e10cSrcweir 
2126cdf0e10cSrcweir 			case( META_FONT_ACTION ):
2127cdf0e10cSrcweir 			{
2128cdf0e10cSrcweir 				MetaFontAction* pAct = (MetaFontAction*) pAction;
2129cdf0e10cSrcweir 				Font			aFont( pAct->GetFont() );
2130cdf0e10cSrcweir 
2131cdf0e10cSrcweir 				aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
2132cdf0e10cSrcweir 				aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
2133cdf0e10cSrcweir 				aMtf.Insert( new MetaFontAction( aFont ), LIST_APPEND );
2134cdf0e10cSrcweir 			}
2135cdf0e10cSrcweir 			break;
2136cdf0e10cSrcweir 
2137cdf0e10cSrcweir 			case( META_WALLPAPER_ACTION ):
2138cdf0e10cSrcweir 			{
2139cdf0e10cSrcweir 				MetaWallpaperAction*	pAct = (MetaWallpaperAction*) pAction;
2140cdf0e10cSrcweir 				Wallpaper				aWall( pAct->GetWallpaper() );
2141cdf0e10cSrcweir 				const Rectangle&		rRect = pAct->GetRect();
2142cdf0e10cSrcweir 
2143cdf0e10cSrcweir 				aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
2144cdf0e10cSrcweir 
2145cdf0e10cSrcweir 				if( aWall.IsBitmap() )
2146cdf0e10cSrcweir 					aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
2147cdf0e10cSrcweir 
2148cdf0e10cSrcweir 				if( aWall.IsGradient() )
2149cdf0e10cSrcweir 				{
2150cdf0e10cSrcweir 					Gradient aGradient( aWall.GetGradient() );
2151cdf0e10cSrcweir 
2152cdf0e10cSrcweir 					aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2153cdf0e10cSrcweir 					aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2154cdf0e10cSrcweir 					aWall.SetGradient( aGradient );
2155cdf0e10cSrcweir 				}
2156cdf0e10cSrcweir 
2157cdf0e10cSrcweir 				aMtf.Insert( new MetaWallpaperAction( rRect, aWall ), LIST_APPEND );
2158cdf0e10cSrcweir 			}
2159cdf0e10cSrcweir 			break;
2160cdf0e10cSrcweir 
2161cdf0e10cSrcweir 			case( META_BMP_ACTION ):
2162cdf0e10cSrcweir 			case( META_BMPEX_ACTION ):
2163cdf0e10cSrcweir 			case( META_MASK_ACTION ):
2164cdf0e10cSrcweir 			{
2165cdf0e10cSrcweir 				DBG_ERROR( "Don't use bitmap actions of this type in metafiles!" );
2166cdf0e10cSrcweir 			}
2167cdf0e10cSrcweir 			break;
2168cdf0e10cSrcweir 
2169cdf0e10cSrcweir 			case( META_BMPSCALE_ACTION ):
2170cdf0e10cSrcweir 			{
2171cdf0e10cSrcweir 				MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
2172cdf0e10cSrcweir 				aMtf.Insert( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
2173cdf0e10cSrcweir 													 pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ),
2174cdf0e10cSrcweir 													 LIST_APPEND );
2175cdf0e10cSrcweir 			}
2176cdf0e10cSrcweir 			break;
2177cdf0e10cSrcweir 
2178cdf0e10cSrcweir 			case( META_BMPSCALEPART_ACTION ):
2179cdf0e10cSrcweir 			{
2180cdf0e10cSrcweir 				MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
2181cdf0e10cSrcweir 				aMtf.Insert( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2182cdf0e10cSrcweir 														 pAct->GetSrcPoint(), pAct->GetSrcSize(),
2183cdf0e10cSrcweir 														 pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ),
2184cdf0e10cSrcweir 														 LIST_APPEND );
2185cdf0e10cSrcweir 			}
2186cdf0e10cSrcweir 			break;
2187cdf0e10cSrcweir 
2188cdf0e10cSrcweir 			case( META_BMPEXSCALE_ACTION ):
2189cdf0e10cSrcweir 			{
2190cdf0e10cSrcweir 				MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
2191cdf0e10cSrcweir 				aMtf.Insert( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
2192cdf0e10cSrcweir 													   pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ),
2193cdf0e10cSrcweir 													   LIST_APPEND );
2194cdf0e10cSrcweir 			}
2195cdf0e10cSrcweir 			break;
2196cdf0e10cSrcweir 
2197cdf0e10cSrcweir 			case( META_BMPEXSCALEPART_ACTION ):
2198cdf0e10cSrcweir 			{
2199cdf0e10cSrcweir 				MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
2200cdf0e10cSrcweir 				aMtf.Insert( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2201cdf0e10cSrcweir 														   pAct->GetSrcPoint(), pAct->GetSrcSize(),
2202cdf0e10cSrcweir 														   pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ),
2203cdf0e10cSrcweir 														   LIST_APPEND );
2204cdf0e10cSrcweir 			}
2205cdf0e10cSrcweir 			break;
2206cdf0e10cSrcweir 
2207cdf0e10cSrcweir 			case( META_MASKSCALE_ACTION ):
2208cdf0e10cSrcweir 			{
2209cdf0e10cSrcweir 				MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
2210cdf0e10cSrcweir 				aMtf.Insert( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
2211cdf0e10cSrcweir 													  pAct->GetBitmap(),
2212cdf0e10cSrcweir 													  pFncCol( pAct->GetColor(), pColParam ) ),
2213cdf0e10cSrcweir 													  LIST_APPEND );
2214cdf0e10cSrcweir 			}
2215cdf0e10cSrcweir 			break;
2216cdf0e10cSrcweir 
2217cdf0e10cSrcweir 			case( META_MASKSCALEPART_ACTION ):
2218cdf0e10cSrcweir 			{
2219cdf0e10cSrcweir 				MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
2220cdf0e10cSrcweir 				aMtf.Insert( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2221cdf0e10cSrcweir 														  pAct->GetSrcPoint(), pAct->GetSrcSize(),
2222cdf0e10cSrcweir 														  pAct->GetBitmap(),
2223cdf0e10cSrcweir 														  pFncCol( pAct->GetColor(), pColParam ) ),
2224cdf0e10cSrcweir 														  LIST_APPEND );
2225cdf0e10cSrcweir 			}
2226cdf0e10cSrcweir 			break;
2227cdf0e10cSrcweir 
2228cdf0e10cSrcweir 			case( META_GRADIENT_ACTION ):
2229cdf0e10cSrcweir 			{
2230cdf0e10cSrcweir 				MetaGradientAction* pAct = (MetaGradientAction*) pAction;
2231cdf0e10cSrcweir 				Gradient			aGradient( pAct->GetGradient() );
2232cdf0e10cSrcweir 
2233cdf0e10cSrcweir 				aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2234cdf0e10cSrcweir 				aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2235cdf0e10cSrcweir 				aMtf.Insert( new MetaGradientAction( pAct->GetRect(), aGradient ), LIST_APPEND );
2236cdf0e10cSrcweir 			}
2237cdf0e10cSrcweir 			break;
2238cdf0e10cSrcweir 
2239cdf0e10cSrcweir 			case( META_GRADIENTEX_ACTION ):
2240cdf0e10cSrcweir 			{
2241cdf0e10cSrcweir 				MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
2242cdf0e10cSrcweir 				Gradient			  aGradient( pAct->GetGradient() );
2243cdf0e10cSrcweir 
2244cdf0e10cSrcweir 				aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2245cdf0e10cSrcweir 				aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2246cdf0e10cSrcweir 				aMtf.Insert( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ), LIST_APPEND );
2247cdf0e10cSrcweir 			}
2248cdf0e10cSrcweir 			break;
2249cdf0e10cSrcweir 
2250cdf0e10cSrcweir 			case( META_HATCH_ACTION ):
2251cdf0e10cSrcweir 			{
2252cdf0e10cSrcweir 				MetaHatchAction*	pAct = (MetaHatchAction*) pAction;
2253cdf0e10cSrcweir 				Hatch				aHatch( pAct->GetHatch() );
2254cdf0e10cSrcweir 
2255cdf0e10cSrcweir 				aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
2256cdf0e10cSrcweir 				aMtf.Insert( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ), LIST_APPEND );
2257cdf0e10cSrcweir 			}
2258cdf0e10cSrcweir 			break;
2259cdf0e10cSrcweir 
2260cdf0e10cSrcweir 			case( META_FLOATTRANSPARENT_ACTION ):
2261cdf0e10cSrcweir 			{
2262cdf0e10cSrcweir 				MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction;
2263cdf0e10cSrcweir 				GDIMetaFile					aTransMtf( pAct->GetGDIMetaFile() );
2264cdf0e10cSrcweir 
2265cdf0e10cSrcweir 				aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2266cdf0e10cSrcweir 				aMtf.Insert( new MetaFloatTransparentAction( aTransMtf,
2267cdf0e10cSrcweir 															 pAct->GetPoint(), pAct->GetSize(),
2268cdf0e10cSrcweir 															 pAct->GetGradient() ),
2269cdf0e10cSrcweir 															 LIST_APPEND );
2270cdf0e10cSrcweir 			}
2271cdf0e10cSrcweir 			break;
2272cdf0e10cSrcweir 
2273cdf0e10cSrcweir 			case( META_EPS_ACTION ):
2274cdf0e10cSrcweir 			{
2275cdf0e10cSrcweir 				MetaEPSAction*	pAct = (MetaEPSAction*) pAction;
2276cdf0e10cSrcweir 				GDIMetaFile		aSubst( pAct->GetSubstitute() );
2277cdf0e10cSrcweir 
2278cdf0e10cSrcweir 				aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2279cdf0e10cSrcweir 				aMtf.Insert( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
2280cdf0e10cSrcweir 												pAct->GetLink(), aSubst ),
2281cdf0e10cSrcweir 												LIST_APPEND );
2282cdf0e10cSrcweir 			}
2283cdf0e10cSrcweir 			break;
2284cdf0e10cSrcweir 
2285cdf0e10cSrcweir             case( META_RENDERGRAPHIC_ACTION ):
2286cdf0e10cSrcweir             {
2287cdf0e10cSrcweir                 OSL_TRACE( "ExchangeColors not supported for RenderGraphic MetaActions yet" );
2288cdf0e10cSrcweir 
2289cdf0e10cSrcweir 				pAction->Duplicate();
2290cdf0e10cSrcweir 				aMtf.Insert( pAction, LIST_APPEND );
2291cdf0e10cSrcweir             }
2292cdf0e10cSrcweir             break;
2293cdf0e10cSrcweir 
2294cdf0e10cSrcweir 			default:
2295cdf0e10cSrcweir 			{
2296cdf0e10cSrcweir 				pAction->Duplicate();
2297cdf0e10cSrcweir 				aMtf.Insert( pAction, LIST_APPEND );
2298cdf0e10cSrcweir 			}
2299cdf0e10cSrcweir 			break;
2300cdf0e10cSrcweir 		}
2301cdf0e10cSrcweir 	}
2302cdf0e10cSrcweir 
2303cdf0e10cSrcweir 	*this = aMtf;
2304cdf0e10cSrcweir }
2305cdf0e10cSrcweir 
2306cdf0e10cSrcweir // ------------------------------------------------------------------------
2307cdf0e10cSrcweir 
2308cdf0e10cSrcweir void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
2309cdf0e10cSrcweir 						  short nChannelRPercent, short nChannelGPercent,
2310cdf0e10cSrcweir 						  short nChannelBPercent, double fGamma, sal_Bool bInvert )
2311cdf0e10cSrcweir {
2312cdf0e10cSrcweir 	// nothing to do? => return quickly
2313cdf0e10cSrcweir 	if( nLuminancePercent || nContrastPercent ||
2314cdf0e10cSrcweir 		nChannelRPercent || nChannelGPercent || nChannelBPercent ||
2315cdf0e10cSrcweir 		( fGamma != 1.0 ) || bInvert )
2316cdf0e10cSrcweir 	{
2317cdf0e10cSrcweir 		double				fM, fROff, fGOff, fBOff, fOff;
2318cdf0e10cSrcweir 		ImplColAdjustParam	aColParam;
2319cdf0e10cSrcweir 		ImplBmpAdjustParam	aBmpParam;
2320cdf0e10cSrcweir 
2321cdf0e10cSrcweir 		aColParam.pMapR = new sal_uInt8[ 256 ];
2322cdf0e10cSrcweir 		aColParam.pMapG = new sal_uInt8[ 256 ];
2323cdf0e10cSrcweir 		aColParam.pMapB = new sal_uInt8[ 256 ];
2324cdf0e10cSrcweir 
2325cdf0e10cSrcweir 		// calculate slope
2326cdf0e10cSrcweir 		if( nContrastPercent >= 0 )
2327cdf0e10cSrcweir 			fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
2328cdf0e10cSrcweir 		else
2329cdf0e10cSrcweir 			fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
2330cdf0e10cSrcweir 
2331cdf0e10cSrcweir 		// total offset = luminance offset + contrast offset
2332cdf0e10cSrcweir 		fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
2333cdf0e10cSrcweir 
2334cdf0e10cSrcweir 		// channel offset = channel offset	+ total offset
2335cdf0e10cSrcweir 		fROff = nChannelRPercent * 2.55 + fOff;
2336cdf0e10cSrcweir 		fGOff = nChannelGPercent * 2.55 + fOff;
2337cdf0e10cSrcweir 		fBOff = nChannelBPercent * 2.55 + fOff;
2338cdf0e10cSrcweir 
2339cdf0e10cSrcweir 		// calculate gamma value
2340cdf0e10cSrcweir 		fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
2341cdf0e10cSrcweir 		const sal_Bool bGamma = ( fGamma != 1.0 );
2342cdf0e10cSrcweir 
2343cdf0e10cSrcweir 		// create mapping table
2344cdf0e10cSrcweir 		for( long nX = 0L; nX < 256L; nX++ )
2345cdf0e10cSrcweir 		{
2346cdf0e10cSrcweir 			aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
2347cdf0e10cSrcweir 			aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
2348cdf0e10cSrcweir 			aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
2349cdf0e10cSrcweir 
2350cdf0e10cSrcweir 			if( bGamma )
2351cdf0e10cSrcweir 			{
2352cdf0e10cSrcweir 				aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
2353cdf0e10cSrcweir 				aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
2354cdf0e10cSrcweir 				aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
2355cdf0e10cSrcweir 			}
2356cdf0e10cSrcweir 
2357cdf0e10cSrcweir 			if( bInvert )
2358cdf0e10cSrcweir 			{
2359cdf0e10cSrcweir 				aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
2360cdf0e10cSrcweir 				aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
2361cdf0e10cSrcweir 				aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
2362cdf0e10cSrcweir 			}
2363cdf0e10cSrcweir 		}
2364cdf0e10cSrcweir 
2365cdf0e10cSrcweir 		aBmpParam.nLuminancePercent = nLuminancePercent;
2366cdf0e10cSrcweir 		aBmpParam.nContrastPercent = nContrastPercent;
2367cdf0e10cSrcweir 		aBmpParam.nChannelRPercent = nChannelRPercent;
2368cdf0e10cSrcweir 		aBmpParam.nChannelGPercent = nChannelGPercent;
2369cdf0e10cSrcweir 		aBmpParam.nChannelBPercent = nChannelBPercent;
2370cdf0e10cSrcweir 		aBmpParam.fGamma = fGamma;
2371cdf0e10cSrcweir 		aBmpParam.bInvert = bInvert;
2372cdf0e10cSrcweir 
2373cdf0e10cSrcweir 		// do color adjustment
2374cdf0e10cSrcweir 		ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
2375cdf0e10cSrcweir 
2376cdf0e10cSrcweir 		delete[] aColParam.pMapR;
2377cdf0e10cSrcweir 		delete[] aColParam.pMapG;
2378cdf0e10cSrcweir 		delete[] aColParam.pMapB;
2379cdf0e10cSrcweir 	}
2380cdf0e10cSrcweir }
2381cdf0e10cSrcweir 
2382cdf0e10cSrcweir // ------------------------------------------------------------------------
2383cdf0e10cSrcweir 
2384cdf0e10cSrcweir void GDIMetaFile::Convert( MtfConversion eConversion )
2385cdf0e10cSrcweir {
2386cdf0e10cSrcweir 	// nothing to do? => return quickly
2387cdf0e10cSrcweir 	if( eConversion != MTF_CONVERSION_NONE )
2388cdf0e10cSrcweir 	{
2389cdf0e10cSrcweir 		ImplColConvertParam	aColParam;
2390cdf0e10cSrcweir 		ImplBmpConvertParam	aBmpParam;
2391cdf0e10cSrcweir 
2392cdf0e10cSrcweir 		aColParam.eConversion = eConversion;
2393cdf0e10cSrcweir 		aBmpParam.eConversion = ( MTF_CONVERSION_1BIT_THRESHOLD == eConversion ) ? BMP_CONVERSION_1BIT_THRESHOLD : BMP_CONVERSION_8BIT_GREYS;
2394cdf0e10cSrcweir 
2395cdf0e10cSrcweir 		ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
2396cdf0e10cSrcweir 	}
2397cdf0e10cSrcweir }
2398cdf0e10cSrcweir 
2399cdf0e10cSrcweir // ------------------------------------------------------------------------
2400cdf0e10cSrcweir 
2401cdf0e10cSrcweir void GDIMetaFile::ReplaceColors( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
2402cdf0e10cSrcweir {
2403cdf0e10cSrcweir 	ReplaceColors( &rSearchColor, &rReplaceColor, 1, &nTol );
2404cdf0e10cSrcweir }
2405cdf0e10cSrcweir 
2406cdf0e10cSrcweir // ------------------------------------------------------------------------
2407cdf0e10cSrcweir 
2408cdf0e10cSrcweir void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, sal_uLong* pTols )
2409cdf0e10cSrcweir {
2410cdf0e10cSrcweir 	ImplColReplaceParam aColParam;
2411cdf0e10cSrcweir 	ImplBmpReplaceParam aBmpParam;
2412cdf0e10cSrcweir 
2413cdf0e10cSrcweir 	aColParam.pMinR = new sal_uLong[ nColorCount ];
2414cdf0e10cSrcweir 	aColParam.pMaxR = new sal_uLong[ nColorCount ];
2415cdf0e10cSrcweir 	aColParam.pMinG = new sal_uLong[ nColorCount ];
2416cdf0e10cSrcweir 	aColParam.pMaxG = new sal_uLong[ nColorCount ];
2417cdf0e10cSrcweir 	aColParam.pMinB = new sal_uLong[ nColorCount ];
2418cdf0e10cSrcweir 	aColParam.pMaxB = new sal_uLong[ nColorCount ];
2419cdf0e10cSrcweir 
2420cdf0e10cSrcweir 	for( sal_uLong i = 0; i < nColorCount; i++ )
2421cdf0e10cSrcweir 	{
2422cdf0e10cSrcweir 		const long	nTol = pTols ? ( pTols[ i ] * 255 ) / 100 : 0;
2423cdf0e10cSrcweir 		long		nVal;
2424cdf0e10cSrcweir 
2425cdf0e10cSrcweir 		nVal = pSearchColors[ i ].GetRed();
2426cdf0e10cSrcweir 		aColParam.pMinR[ i ] = (sal_uLong) Max( nVal - nTol, 0L );
2427cdf0e10cSrcweir 		aColParam.pMaxR[ i ] = (sal_uLong) Min( nVal + nTol, 255L );
2428cdf0e10cSrcweir 
2429cdf0e10cSrcweir 		nVal = pSearchColors[ i ].GetGreen();
2430cdf0e10cSrcweir 		aColParam.pMinG[ i ] = (sal_uLong) Max( nVal - nTol, 0L );
2431cdf0e10cSrcweir 		aColParam.pMaxG[ i ] = (sal_uLong) Min( nVal + nTol, 255L );
2432cdf0e10cSrcweir 
2433cdf0e10cSrcweir 		nVal = pSearchColors[ i ].GetBlue();
2434cdf0e10cSrcweir 		aColParam.pMinB[ i ] = (sal_uLong) Max( nVal - nTol, 0L );
2435cdf0e10cSrcweir 		aColParam.pMaxB[ i ] = (sal_uLong) Min( nVal + nTol, 255L );
2436cdf0e10cSrcweir 	}
2437cdf0e10cSrcweir 
2438cdf0e10cSrcweir 	aColParam.pDstCols = pReplaceColors;
2439cdf0e10cSrcweir 	aColParam.nCount = nColorCount;
2440cdf0e10cSrcweir 
2441cdf0e10cSrcweir 	aBmpParam.pSrcCols = pSearchColors;
2442cdf0e10cSrcweir 	aBmpParam.pDstCols = pReplaceColors;
2443cdf0e10cSrcweir 	aBmpParam.nCount = nColorCount;
2444cdf0e10cSrcweir 	aBmpParam.pTols = pTols;
2445cdf0e10cSrcweir 
2446cdf0e10cSrcweir 	ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
2447cdf0e10cSrcweir 
2448cdf0e10cSrcweir 	delete[] aColParam.pMinR;
2449cdf0e10cSrcweir 	delete[] aColParam.pMaxR;
2450cdf0e10cSrcweir 	delete[] aColParam.pMinG;
2451cdf0e10cSrcweir 	delete[] aColParam.pMaxG;
2452cdf0e10cSrcweir 	delete[] aColParam.pMinB;
2453cdf0e10cSrcweir 	delete[] aColParam.pMaxB;
2454cdf0e10cSrcweir };
2455cdf0e10cSrcweir 
2456cdf0e10cSrcweir // ------------------------------------------------------------------------
2457cdf0e10cSrcweir 
2458cdf0e10cSrcweir GDIMetaFile GDIMetaFile::GetMonochromeMtf( const Color& rColor ) const
2459cdf0e10cSrcweir {
2460cdf0e10cSrcweir 	GDIMetaFile aRet( *this );
2461cdf0e10cSrcweir 
2462cdf0e10cSrcweir 	ImplColMonoParam	aColParam;
2463cdf0e10cSrcweir 	ImplBmpMonoParam	aBmpParam;
2464cdf0e10cSrcweir 
2465cdf0e10cSrcweir 	aColParam.aColor = rColor;
2466cdf0e10cSrcweir 	aBmpParam.aColor = rColor;
2467cdf0e10cSrcweir 
2468cdf0e10cSrcweir 	aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
2469cdf0e10cSrcweir 
2470cdf0e10cSrcweir 	return aRet;
2471cdf0e10cSrcweir }
2472cdf0e10cSrcweir 
2473cdf0e10cSrcweir // ------------------------------------------------------------------------
2474cdf0e10cSrcweir 
2475cdf0e10cSrcweir sal_uLong GDIMetaFile::GetChecksum() const
2476cdf0e10cSrcweir {
2477cdf0e10cSrcweir 	GDIMetaFile			aMtf;
2478cdf0e10cSrcweir 	SvMemoryStream		aMemStm( 65535, 65535 );
2479cdf0e10cSrcweir 	ImplMetaWriteData	aWriteData;
2480cdf0e10cSrcweir 	SVBT16				aBT16;
2481cdf0e10cSrcweir 	SVBT32				aBT32;
2482cdf0e10cSrcweir 	sal_uLong				nCrc = 0;
2483cdf0e10cSrcweir 
2484cdf0e10cSrcweir 	aWriteData.meActualCharSet = aMemStm.GetStreamCharSet();
2485cdf0e10cSrcweir 
2486cdf0e10cSrcweir 	for( sal_uLong i = 0, nObjCount = GetActionCount(); i < nObjCount; i++ )
2487cdf0e10cSrcweir 	{
2488cdf0e10cSrcweir 		MetaAction* pAction = GetAction( i );
2489cdf0e10cSrcweir 
2490cdf0e10cSrcweir 		switch( pAction->GetType() )
2491cdf0e10cSrcweir 		{
2492cdf0e10cSrcweir 			case( META_BMP_ACTION ):
2493cdf0e10cSrcweir 			{
2494cdf0e10cSrcweir 				MetaBmpAction* pAct = (MetaBmpAction*) pAction;
2495cdf0e10cSrcweir 
2496cdf0e10cSrcweir 				ShortToSVBT16( pAct->GetType(), aBT16 );
2497cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT16, 2 );
2498cdf0e10cSrcweir 
2499cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2500cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2501cdf0e10cSrcweir 
2502cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2503cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2504cdf0e10cSrcweir 
2505cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2506cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2507cdf0e10cSrcweir 			}
2508cdf0e10cSrcweir 			break;
2509cdf0e10cSrcweir 
2510cdf0e10cSrcweir 			case( META_BMPSCALE_ACTION ):
2511cdf0e10cSrcweir 			{
2512cdf0e10cSrcweir 				MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
2513cdf0e10cSrcweir 
2514cdf0e10cSrcweir 				ShortToSVBT16( pAct->GetType(), aBT16 );
2515cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT16, 2 );
2516cdf0e10cSrcweir 
2517cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2518cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2519cdf0e10cSrcweir 
2520cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2521cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2522cdf0e10cSrcweir 
2523cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2524cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2525cdf0e10cSrcweir 
2526cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2527cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2528cdf0e10cSrcweir 
2529cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2530cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2531cdf0e10cSrcweir 			}
2532cdf0e10cSrcweir 			break;
2533cdf0e10cSrcweir 
2534cdf0e10cSrcweir 			case( META_BMPSCALEPART_ACTION ):
2535cdf0e10cSrcweir 			{
2536cdf0e10cSrcweir 				MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
2537cdf0e10cSrcweir 
2538cdf0e10cSrcweir 				ShortToSVBT16( pAct->GetType(), aBT16 );
2539cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT16, 2 );
2540cdf0e10cSrcweir 
2541cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2542cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2543cdf0e10cSrcweir 
2544cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2545cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2546cdf0e10cSrcweir 
2547cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2548cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2549cdf0e10cSrcweir 
2550cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2551cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2552cdf0e10cSrcweir 
2553cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2554cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2555cdf0e10cSrcweir 
2556cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2557cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2558cdf0e10cSrcweir 
2559cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2560cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2561cdf0e10cSrcweir 
2562cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2563cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2564cdf0e10cSrcweir 
2565cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2566cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2567cdf0e10cSrcweir 			}
2568cdf0e10cSrcweir 			break;
2569cdf0e10cSrcweir 
2570cdf0e10cSrcweir 			case( META_BMPEX_ACTION ):
2571cdf0e10cSrcweir 			{
2572cdf0e10cSrcweir 				MetaBmpExAction* pAct = (MetaBmpExAction*) pAction;
2573cdf0e10cSrcweir 
2574cdf0e10cSrcweir 				ShortToSVBT16( pAct->GetType(), aBT16 );
2575cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT16, 2 );
2576cdf0e10cSrcweir 
2577cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
2578cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2579cdf0e10cSrcweir 
2580cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2581cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2582cdf0e10cSrcweir 
2583cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2584cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2585cdf0e10cSrcweir 			}
2586cdf0e10cSrcweir 			break;
2587cdf0e10cSrcweir 
2588cdf0e10cSrcweir 			case( META_BMPEXSCALE_ACTION ):
2589cdf0e10cSrcweir 			{
2590cdf0e10cSrcweir 				MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
2591cdf0e10cSrcweir 
2592cdf0e10cSrcweir 				ShortToSVBT16( pAct->GetType(), aBT16 );
2593cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT16, 2 );
2594cdf0e10cSrcweir 
2595cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
2596cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2597cdf0e10cSrcweir 
2598cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2599cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2600cdf0e10cSrcweir 
2601cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2602cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2603cdf0e10cSrcweir 
2604cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2605cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2606cdf0e10cSrcweir 
2607cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2608cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2609cdf0e10cSrcweir 			}
2610cdf0e10cSrcweir 			break;
2611cdf0e10cSrcweir 
2612cdf0e10cSrcweir 			case( META_BMPEXSCALEPART_ACTION ):
2613cdf0e10cSrcweir 			{
2614cdf0e10cSrcweir 				MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
2615cdf0e10cSrcweir 
2616cdf0e10cSrcweir 				ShortToSVBT16( pAct->GetType(), aBT16 );
2617cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT16, 2 );
2618cdf0e10cSrcweir 
2619cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
2620cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2621cdf0e10cSrcweir 
2622cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2623cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2624cdf0e10cSrcweir 
2625cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2626cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2627cdf0e10cSrcweir 
2628cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2629cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2630cdf0e10cSrcweir 
2631cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2632cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2633cdf0e10cSrcweir 
2634cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2635cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2636cdf0e10cSrcweir 
2637cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2638cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2639cdf0e10cSrcweir 
2640cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2641cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2642cdf0e10cSrcweir 
2643cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2644cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2645cdf0e10cSrcweir 			}
2646cdf0e10cSrcweir 			break;
2647cdf0e10cSrcweir 
2648cdf0e10cSrcweir 			case( META_MASK_ACTION ):
2649cdf0e10cSrcweir 			{
2650cdf0e10cSrcweir 				MetaMaskAction* pAct = (MetaMaskAction*) pAction;
2651cdf0e10cSrcweir 
2652cdf0e10cSrcweir 				ShortToSVBT16( pAct->GetType(), aBT16 );
2653cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT16, 2 );
2654cdf0e10cSrcweir 
2655cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2656cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2657cdf0e10cSrcweir 
2658cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2659cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2660cdf0e10cSrcweir 
2661cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2662cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2663cdf0e10cSrcweir 
2664cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2665cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2666cdf0e10cSrcweir 			}
2667cdf0e10cSrcweir 			break;
2668cdf0e10cSrcweir 
2669cdf0e10cSrcweir 			case( META_MASKSCALE_ACTION ):
2670cdf0e10cSrcweir 			{
2671cdf0e10cSrcweir 				MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
2672cdf0e10cSrcweir 
2673cdf0e10cSrcweir 				ShortToSVBT16( pAct->GetType(), aBT16 );
2674cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT16, 2 );
2675cdf0e10cSrcweir 
2676cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2677cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2678cdf0e10cSrcweir 
2679cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2680cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2681cdf0e10cSrcweir 
2682cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2683cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2684cdf0e10cSrcweir 
2685cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2686cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2687cdf0e10cSrcweir 
2688cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2689cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2690cdf0e10cSrcweir 
2691cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2692cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2693cdf0e10cSrcweir 			}
2694cdf0e10cSrcweir 			break;
2695cdf0e10cSrcweir 
2696cdf0e10cSrcweir 			case( META_MASKSCALEPART_ACTION ):
2697cdf0e10cSrcweir 			{
2698cdf0e10cSrcweir 				MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
2699cdf0e10cSrcweir 
2700cdf0e10cSrcweir 				ShortToSVBT16( pAct->GetType(), aBT16 );
2701cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT16, 2 );
2702cdf0e10cSrcweir 
2703cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2704cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2705cdf0e10cSrcweir 
2706cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2707cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2708cdf0e10cSrcweir 
2709cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2710cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2711cdf0e10cSrcweir 
2712cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2713cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2714cdf0e10cSrcweir 
2715cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2716cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2717cdf0e10cSrcweir 
2718cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2719cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2720cdf0e10cSrcweir 
2721cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2722cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2723cdf0e10cSrcweir 
2724cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2725cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2726cdf0e10cSrcweir 
2727cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2728cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2729cdf0e10cSrcweir 
2730cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2731cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2732cdf0e10cSrcweir 			}
2733cdf0e10cSrcweir 			break;
2734cdf0e10cSrcweir 
2735cdf0e10cSrcweir 			case META_EPS_ACTION :
2736cdf0e10cSrcweir 			{
2737cdf0e10cSrcweir 				MetaEPSAction* pAct = (MetaEPSAction*) pAction;
2738cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, pAct->GetLink().GetData(), pAct->GetLink().GetDataSize() );
2739cdf0e10cSrcweir 			}
2740cdf0e10cSrcweir 			break;
2741cdf0e10cSrcweir 
2742cdf0e10cSrcweir             case( META_RENDERGRAPHIC_ACTION ):
2743cdf0e10cSrcweir             {
2744cdf0e10cSrcweir                 MetaRenderGraphicAction*    pAct = (MetaRenderGraphicAction*) pAction;
2745cdf0e10cSrcweir 				const ::vcl::RenderGraphic& rRenderGraphic = pAct->GetRenderGraphic();
2746cdf0e10cSrcweir 
2747cdf0e10cSrcweir 				ShortToSVBT16( pAct->GetType(), aBT16 );
2748cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT16, 2 );
2749cdf0e10cSrcweir 
2750cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, rRenderGraphic.GetGraphicData().get(), rRenderGraphic.GetGraphicDataLength() );
2751cdf0e10cSrcweir 
2752cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2753cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2754cdf0e10cSrcweir 
2755cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2756cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2757cdf0e10cSrcweir 
2758cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2759cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2760cdf0e10cSrcweir 
2761cdf0e10cSrcweir 				UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2762cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
2763cdf0e10cSrcweir             }
2764cdf0e10cSrcweir             break;
2765cdf0e10cSrcweir 
2766cdf0e10cSrcweir 			default:
2767cdf0e10cSrcweir 			{
2768cdf0e10cSrcweir 				pAction->Write( aMemStm, &aWriteData );
2769cdf0e10cSrcweir 				nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() );
2770cdf0e10cSrcweir 				aMemStm.Seek( 0 );
2771cdf0e10cSrcweir 			}
2772cdf0e10cSrcweir 			break;
2773cdf0e10cSrcweir 		}
2774cdf0e10cSrcweir 	}
2775cdf0e10cSrcweir 
2776cdf0e10cSrcweir 	return nCrc;
2777cdf0e10cSrcweir }
2778cdf0e10cSrcweir 
2779cdf0e10cSrcweir // ------------------------------------------------------------------------
2780cdf0e10cSrcweir 
2781cdf0e10cSrcweir sal_uLong GDIMetaFile::GetSizeBytes() const
2782cdf0e10cSrcweir {
2783cdf0e10cSrcweir     sal_uLong nSizeBytes = 0;
2784cdf0e10cSrcweir 
2785cdf0e10cSrcweir     for( sal_uLong i = 0, nObjCount = GetActionCount(); i < nObjCount; ++i )
2786cdf0e10cSrcweir     {
2787cdf0e10cSrcweir         MetaAction* pAction = GetAction( i );
2788cdf0e10cSrcweir 
2789cdf0e10cSrcweir         // default action size is set to 32 (=> not the exact value)
2790cdf0e10cSrcweir         nSizeBytes += 32;
2791cdf0e10cSrcweir 
2792cdf0e10cSrcweir         // add sizes for large action content
2793cdf0e10cSrcweir         switch( pAction->GetType() )
2794cdf0e10cSrcweir         {
2795cdf0e10cSrcweir             case( META_BMP_ACTION ): nSizeBytes += ( (MetaBmpAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2796cdf0e10cSrcweir             case( META_BMPSCALE_ACTION ): nSizeBytes += ( (MetaBmpScaleAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2797cdf0e10cSrcweir             case( META_BMPSCALEPART_ACTION ): nSizeBytes += ( (MetaBmpScalePartAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2798cdf0e10cSrcweir 
2799cdf0e10cSrcweir             case( META_BMPEX_ACTION ): nSizeBytes += ( (MetaBmpExAction*) pAction )->GetBitmapEx().GetSizeBytes(); break;
2800cdf0e10cSrcweir             case( META_BMPEXSCALE_ACTION ): nSizeBytes += ( (MetaBmpExScaleAction*) pAction )->GetBitmapEx().GetSizeBytes(); break;
2801cdf0e10cSrcweir             case( META_BMPEXSCALEPART_ACTION ): nSizeBytes += ( (MetaBmpExScalePartAction*) pAction )->GetBitmapEx().GetSizeBytes(); break;
2802cdf0e10cSrcweir 
2803cdf0e10cSrcweir             case( META_MASK_ACTION ): nSizeBytes += ( (MetaMaskAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2804cdf0e10cSrcweir             case( META_MASKSCALE_ACTION ): nSizeBytes += ( (MetaMaskScaleAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2805cdf0e10cSrcweir             case( META_MASKSCALEPART_ACTION ): nSizeBytes += ( (MetaMaskScalePartAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2806cdf0e10cSrcweir 
2807cdf0e10cSrcweir             case( META_POLYLINE_ACTION ): nSizeBytes += ( ( (MetaPolyLineAction*) pAction )->GetPolygon().GetSize() * sizeof( Point ) ); break;
2808cdf0e10cSrcweir             case( META_POLYGON_ACTION ): nSizeBytes += ( ( (MetaPolygonAction*) pAction )->GetPolygon().GetSize() * sizeof( Point ) ); break;
2809cdf0e10cSrcweir             case( META_POLYPOLYGON_ACTION ):
2810cdf0e10cSrcweir             {
2811cdf0e10cSrcweir                 const PolyPolygon& rPolyPoly = ( (MetaPolyPolygonAction*) pAction )->GetPolyPolygon();
2812cdf0e10cSrcweir 
2813cdf0e10cSrcweir                 for( sal_uInt16 n = 0; n < rPolyPoly.Count(); ++n )
2814cdf0e10cSrcweir                     nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) );
2815cdf0e10cSrcweir             }
2816cdf0e10cSrcweir             break;
2817cdf0e10cSrcweir 
2818cdf0e10cSrcweir             case( META_TEXT_ACTION ): nSizeBytes += ( ( (MetaTextAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break;
2819cdf0e10cSrcweir             case( META_STRETCHTEXT_ACTION ): nSizeBytes += ( ( (MetaStretchTextAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break;
2820cdf0e10cSrcweir             case( META_TEXTRECT_ACTION ): nSizeBytes += ( ( (MetaTextRectAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break;
2821cdf0e10cSrcweir             case( META_TEXTARRAY_ACTION ):
2822cdf0e10cSrcweir             {
2823cdf0e10cSrcweir                 MetaTextArrayAction* pTextArrayAction = (MetaTextArrayAction*) pAction;
2824cdf0e10cSrcweir 
2825cdf0e10cSrcweir                 nSizeBytes += ( pTextArrayAction->GetText().Len() * sizeof( sal_Unicode ) );
2826cdf0e10cSrcweir 
2827cdf0e10cSrcweir                 if( pTextArrayAction->GetDXArray() )
2828cdf0e10cSrcweir                     nSizeBytes += ( pTextArrayAction->GetLen() << 2 );
2829cdf0e10cSrcweir             }
2830cdf0e10cSrcweir             break;
2831cdf0e10cSrcweir 
2832cdf0e10cSrcweir             case( META_RENDERGRAPHIC_ACTION ): nSizeBytes += ( ( (MetaRenderGraphicAction*) pAction )->GetRenderGraphic() ).GetGraphicDataLength(); break;
2833cdf0e10cSrcweir         }
2834cdf0e10cSrcweir     }
2835cdf0e10cSrcweir 
2836cdf0e10cSrcweir     return( nSizeBytes );
2837cdf0e10cSrcweir }
2838cdf0e10cSrcweir 
2839cdf0e10cSrcweir // ------------------------------------------------------------------------
2840cdf0e10cSrcweir 
2841cdf0e10cSrcweir SvStream& operator>>( SvStream& rIStm, GDIMetaFile& rGDIMetaFile )
2842cdf0e10cSrcweir {
2843cdf0e10cSrcweir 	if( !rIStm.GetError() )
2844cdf0e10cSrcweir 	{
2845cdf0e10cSrcweir 		char	aId[ 7 ];
2846cdf0e10cSrcweir 		sal_uLong	nStmPos = rIStm.Tell();
2847cdf0e10cSrcweir 		sal_uInt16	nOldFormat = rIStm.GetNumberFormatInt();
2848cdf0e10cSrcweir 
2849cdf0e10cSrcweir 		rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
2850cdf0e10cSrcweir 
2851cdf0e10cSrcweir 		aId[ 0 ] = 0;
2852cdf0e10cSrcweir 		aId[ 6 ] = 0;
2853cdf0e10cSrcweir 		rIStm.Read( aId, 6 );
2854cdf0e10cSrcweir 
2855cdf0e10cSrcweir 		if ( !strcmp( aId, "VCLMTF" ) )
2856cdf0e10cSrcweir 		{
2857cdf0e10cSrcweir 			// new format
2858cdf0e10cSrcweir 			VersionCompat*	pCompat;
2859cdf0e10cSrcweir 			MetaAction* 	pAction;
2860cdf0e10cSrcweir 			sal_uInt32		nStmCompressMode = 0;
2861cdf0e10cSrcweir 			sal_uInt32		nCount = 0;
2862cdf0e10cSrcweir 			sal_uInt8		bRenderGraphicReplacements = 0;
2863cdf0e10cSrcweir 
2864cdf0e10cSrcweir 			pCompat = new VersionCompat( rIStm, STREAM_READ );
2865cdf0e10cSrcweir 			{
2866cdf0e10cSrcweir 				// version 1
2867cdf0e10cSrcweir 				rIStm >> nStmCompressMode;
2868cdf0e10cSrcweir 				rIStm >> rGDIMetaFile.aPrefMapMode;
2869cdf0e10cSrcweir 				rIStm >> rGDIMetaFile.aPrefSize;
2870cdf0e10cSrcweir 				rIStm >> nCount;
2871cdf0e10cSrcweir 
2872cdf0e10cSrcweir 				if( pCompat->GetVersion() >= 2 )
2873cdf0e10cSrcweir 				{
2874cdf0e10cSrcweir 					// version 2
2875cdf0e10cSrcweir 					// =========
2876cdf0e10cSrcweir 					// contains an additional flag to indicate that RenderGraphic
2877cdf0e10cSrcweir 					// actions are immediately followed by a replacement image, that
2878cdf0e10cSrcweir 					// needs to be skipped in case the flag is set (KA 01/2011)
2879cdf0e10cSrcweir 
2880cdf0e10cSrcweir 					rIStm >> bRenderGraphicReplacements;
2881cdf0e10cSrcweir 				}
2882cdf0e10cSrcweir 			}
2883cdf0e10cSrcweir 			delete pCompat;
2884cdf0e10cSrcweir 
2885cdf0e10cSrcweir 			ImplMetaReadData aReadData;
2886cdf0e10cSrcweir 			aReadData.meActualCharSet = rIStm.GetStreamCharSet();
2887cdf0e10cSrcweir 
2888cdf0e10cSrcweir 			for( sal_uInt32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); ++nAction )
2889cdf0e10cSrcweir 			{
2890cdf0e10cSrcweir 				pAction = MetaAction::ReadMetaAction( rIStm, &aReadData );
2891cdf0e10cSrcweir 
2892cdf0e10cSrcweir 				if( pAction )
2893cdf0e10cSrcweir 				{
2894cdf0e10cSrcweir 					rGDIMetaFile.AddAction( pAction );
2895cdf0e10cSrcweir 
2896cdf0e10cSrcweir 					// if the MetaFile was written in RenderGraphics replacement mode
2897cdf0e10cSrcweir 					// and we just read a RenderGraphic action, skip the following
2898cdf0e10cSrcweir 					// META_BMPEXSCALE_ACTION, since this is the replacement image,
2899cdf0e10cSrcweir 					// just needed for old implementations; don't forget to increment
2900cdf0e10cSrcweir 					// the action read counter! (KA 01/2011)
2901cdf0e10cSrcweir 					if( bRenderGraphicReplacements &&
2902cdf0e10cSrcweir 						( META_RENDERGRAPHIC_ACTION == pAction->GetType() ) &&
2903cdf0e10cSrcweir 						( ++nAction < nCount ) && !rIStm.IsEof() )
2904cdf0e10cSrcweir 					{
2905cdf0e10cSrcweir 						sal_uInt16 nFollowingType;
2906cdf0e10cSrcweir 
2907cdf0e10cSrcweir 						// dummy read of the next following META_BMPEXSCALE_ACTION
2908cdf0e10cSrcweir 						// RenderGraphic replacement action (KA 01/2011)
2909cdf0e10cSrcweir 						rIStm >> nFollowingType;
2910cdf0e10cSrcweir 						delete ( new VersionCompat( rIStm, STREAM_READ ) );
2911cdf0e10cSrcweir 
2912cdf0e10cSrcweir 						OSL_ENSURE( META_BMPEXSCALE_ACTION == nFollowingType, \
2913cdf0e10cSrcweir "META_RENDERGRAPHIC_ACTION read in RenderGraphic replacement mode \
2914cdf0e10cSrcweir without following META_BMPEXSCALE_ACTION replacement" );
2915cdf0e10cSrcweir 					}
2916cdf0e10cSrcweir 				}
2917cdf0e10cSrcweir 			}
2918cdf0e10cSrcweir 		}
2919cdf0e10cSrcweir 		else
2920cdf0e10cSrcweir 		{
2921cdf0e10cSrcweir 			// to avoid possible compiler optimizations => new/delete
2922cdf0e10cSrcweir 			rIStm.Seek( nStmPos );
2923cdf0e10cSrcweir 			delete( new SVMConverter( rIStm, rGDIMetaFile, CONVERT_FROM_SVM1 ) );
2924cdf0e10cSrcweir 		}
2925cdf0e10cSrcweir 
2926cdf0e10cSrcweir 		// check for errors
2927cdf0e10cSrcweir 		if( rIStm.GetError() )
2928cdf0e10cSrcweir 		{
2929cdf0e10cSrcweir 			rGDIMetaFile.Clear();
2930cdf0e10cSrcweir 			rIStm.Seek( nStmPos );
2931cdf0e10cSrcweir 		}
2932cdf0e10cSrcweir 
2933cdf0e10cSrcweir 		rIStm.SetNumberFormatInt( nOldFormat );
2934cdf0e10cSrcweir 	}
2935cdf0e10cSrcweir 
2936cdf0e10cSrcweir 	return rIStm;
2937cdf0e10cSrcweir }
2938cdf0e10cSrcweir 
2939cdf0e10cSrcweir // ------------------------------------------------------------------------
2940cdf0e10cSrcweir 
2941cdf0e10cSrcweir SvStream& operator<<( SvStream& rOStm, const GDIMetaFile& rGDIMetaFile )
2942cdf0e10cSrcweir {
2943cdf0e10cSrcweir 	if( !rOStm.GetError() )
2944cdf0e10cSrcweir 	{
2945cdf0e10cSrcweir         static const char*  pEnableSVM1 = getenv( "SAL_ENABLE_SVM1" );
2946cdf0e10cSrcweir         static const bool   bNoSVM1 = (NULL == pEnableSVM1 ) || ( '0' == *pEnableSVM1 );
2947cdf0e10cSrcweir 
2948cdf0e10cSrcweir         if( bNoSVM1 || rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50  )
2949cdf0e10cSrcweir         {
2950cdf0e10cSrcweir             const_cast< GDIMetaFile& >( rGDIMetaFile ).Write( rOStm );
2951cdf0e10cSrcweir         }
2952cdf0e10cSrcweir         else
2953cdf0e10cSrcweir         {
2954cdf0e10cSrcweir             delete( new SVMConverter( rOStm, const_cast< GDIMetaFile& >( rGDIMetaFile ), CONVERT_TO_SVM1 ) );
2955cdf0e10cSrcweir         }
2956cdf0e10cSrcweir 
2957cdf0e10cSrcweir #ifdef DEBUG
2958cdf0e10cSrcweir         if( !bNoSVM1 && rOStm.GetVersion() < SOFFICE_FILEFORMAT_50 )
2959cdf0e10cSrcweir         {
2960cdf0e10cSrcweir OSL_TRACE( \
2961cdf0e10cSrcweir "GDIMetaFile would normally be written in old SVM1 format by this call. \
2962cdf0e10cSrcweir The current implementation always writes in VCLMTF format. \
2963cdf0e10cSrcweir Please set environment variable SAL_ENABLE_SVM1 to '1' to reenable old behavior" );
2964cdf0e10cSrcweir 		}
2965cdf0e10cSrcweir #endif // DEBUG
2966cdf0e10cSrcweir 	}
2967cdf0e10cSrcweir 
2968cdf0e10cSrcweir 	return rOStm;
2969cdf0e10cSrcweir }
2970cdf0e10cSrcweir 
2971cdf0e10cSrcweir // ------------------------------------------------------------------------
2972cdf0e10cSrcweir 
2973cdf0e10cSrcweir SvStream& GDIMetaFile::Read( SvStream& rIStm )
2974cdf0e10cSrcweir {
2975cdf0e10cSrcweir 	Clear();
2976cdf0e10cSrcweir 	rIStm >> *this;
2977cdf0e10cSrcweir 
2978cdf0e10cSrcweir 	return rIStm;
2979cdf0e10cSrcweir }
2980cdf0e10cSrcweir 
2981cdf0e10cSrcweir // ------------------------------------------------------------------------
2982cdf0e10cSrcweir 
2983cdf0e10cSrcweir SvStream& GDIMetaFile::Write( SvStream& rOStm, GDIMetaFileWriteFlags nWriteFlags )
2984cdf0e10cSrcweir {
2985cdf0e10cSrcweir 	VersionCompat*	pCompat;
2986cdf0e10cSrcweir 	const sal_uInt32    nStmCompressMode = rOStm.GetCompressMode();
2987cdf0e10cSrcweir 	sal_uInt16		    nOldFormat = rOStm.GetNumberFormatInt();
2988cdf0e10cSrcweir 	const 			    sal_uInt8 bRenderGraphicReplacements =
2989cdf0e10cSrcweir 								( ( ( GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC & nWriteFlags ) != 0 ) ? 1 : 0 );
2990cdf0e10cSrcweir 
2991cdf0e10cSrcweir 	// With the introduction of the META_RENDERGRAPHIC_ACTION, it is neccessary
2992cdf0e10cSrcweir 	// to provide some kind of document backward compatibility:
2993cdf0e10cSrcweir 	//
2994cdf0e10cSrcweir 	//	If the flag GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC is set in
2995cdf0e10cSrcweir 	//	parameter nWriteFlags, each META_RENDERGRAPHIC_ACTION is followed by
2996cdf0e10cSrcweir 	//  an additional META_BMPEXSCALE_ACTION, that contains a replacement
2997cdf0e10cSrcweir 	//	image for the new RenderGraphic action.
2998cdf0e10cSrcweir 	//
2999cdf0e10cSrcweir 	//	Old implementations, not knowing anything about META_RENDERGRAPHIC_ACTION,
3000cdf0e10cSrcweir 	//  will skip this new action and read the META_BMPEXSCALE_ACTION instead
3001cdf0e10cSrcweir 	//
3002cdf0e10cSrcweir 	//  Since the current implementation is able to handle the new action, the
3003cdf0e10cSrcweir 	//  then following image replacement action needs to be skipped by this
3004cdf0e10cSrcweir 	//  implementation, if the metafile was written in the RenderGraphic
3005cdf0e10cSrcweir 	//  replacement mode.
3006cdf0e10cSrcweir 	//
3007cdf0e10cSrcweir 	//  To be able to detect this compatibility mode, the header needs to
3008cdf0e10cSrcweir 	//  be extended by a corresponding flag, resulting in version 2 of
3009cdf0e10cSrcweir 	//  the header. The surrounding VersionCompat of the header
3010cdf0e10cSrcweir 	//  allows to add such new data without any problems (KA 01/2011)
3011cdf0e10cSrcweir 
3012cdf0e10cSrcweir 	rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
3013cdf0e10cSrcweir 	rOStm.Write( "VCLMTF", 6 );
3014cdf0e10cSrcweir 
3015cdf0e10cSrcweir 	pCompat = new VersionCompat( rOStm, STREAM_WRITE, 2 );
3016cdf0e10cSrcweir 
3017cdf0e10cSrcweir 	{
3018cdf0e10cSrcweir 		// version 1
3019cdf0e10cSrcweir 		sal_uInt32 nActionCount = 0;
3020cdf0e10cSrcweir 
3021cdf0e10cSrcweir 		// calculate correct action count and watch for
3022cdf0e10cSrcweir 		// additional RenderGraphic replacement actions, if the
3023cdf0e10cSrcweir 		// GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC is set
3024cdf0e10cSrcweir 		// and META_RENDERGRAPHIC_ACTION are encountered (KA 01/2011)
3025cdf0e10cSrcweir 		for( MetaAction* pAct = static_cast< MetaAction* >( First() ); pAct; pAct = static_cast< MetaAction* >( Next() ) )
3026cdf0e10cSrcweir 		{
3027cdf0e10cSrcweir 			nActionCount += ( bRenderGraphicReplacements && ( META_RENDERGRAPHIC_ACTION == pAct->GetType() ) ? 2 : 1 );
3028cdf0e10cSrcweir 		}
3029cdf0e10cSrcweir 
3030cdf0e10cSrcweir 		rOStm << nStmCompressMode << aPrefMapMode << aPrefSize << nActionCount;
3031cdf0e10cSrcweir 
3032cdf0e10cSrcweir 		{
3033cdf0e10cSrcweir 			// version 2
3034cdf0e10cSrcweir 			// =========
3035cdf0e10cSrcweir 			// since version 2, a GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC flag
3036cdf0e10cSrcweir 			// is written, to indicate that each META_BMPEXSCALE_ACTION following
3037cdf0e10cSrcweir 			// a META_RENDERGRAPHIC_ACTION needs to be skipped, in case the flag is
3038cdf0e10cSrcweir 			// set (KA 01/2011)
3039cdf0e10cSrcweir 			rOStm << bRenderGraphicReplacements;
3040cdf0e10cSrcweir 		}
3041cdf0e10cSrcweir 	}
3042cdf0e10cSrcweir 
3043cdf0e10cSrcweir 	delete pCompat;
3044cdf0e10cSrcweir 
3045cdf0e10cSrcweir 	ImplMetaWriteData aWriteData;
3046cdf0e10cSrcweir 
3047cdf0e10cSrcweir 	aWriteData.meActualCharSet = rOStm.GetStreamCharSet();
3048cdf0e10cSrcweir 	aWriteData.mnWriteFlags = nWriteFlags;
3049cdf0e10cSrcweir 
3050cdf0e10cSrcweir 	for( MetaAction* pAct = static_cast< MetaAction* >( First() ); pAct; pAct = static_cast< MetaAction* >( Next() ) )
3051cdf0e10cSrcweir 	{
3052cdf0e10cSrcweir 		pAct->Write( rOStm, &aWriteData );
3053cdf0e10cSrcweir 
3054cdf0e10cSrcweir 		// write the RenderGraphic replacement image, if the
3055cdf0e10cSrcweir 		// GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC flag is set
3056cdf0e10cSrcweir 		// and if a META_RENDERGRAPHIC_ACTION is encountered (KA 01/2011)
3057cdf0e10cSrcweir 		if( bRenderGraphicReplacements && ( META_RENDERGRAPHIC_ACTION == pAct->GetType() ) )
3058cdf0e10cSrcweir 		{
3059cdf0e10cSrcweir 			MetaRenderGraphicAction* 	pRenderAction = static_cast< MetaRenderGraphicAction* >( pAct );
3060cdf0e10cSrcweir 			MetaBmpExScaleAction*		pBmpExScaleAction = new MetaBmpExScaleAction(
3061cdf0e10cSrcweir 											pRenderAction->GetPoint(), pRenderAction->GetSize(),
3062cdf0e10cSrcweir 											pRenderAction->GetRenderGraphic().GetReplacement() );
3063cdf0e10cSrcweir 
3064cdf0e10cSrcweir 			pBmpExScaleAction->Write( rOStm, &aWriteData );
3065cdf0e10cSrcweir 			pBmpExScaleAction->Delete();
3066cdf0e10cSrcweir 		}
3067cdf0e10cSrcweir 	}
3068cdf0e10cSrcweir 
3069cdf0e10cSrcweir 	rOStm.SetNumberFormatInt( nOldFormat );
3070cdf0e10cSrcweir 
3071cdf0e10cSrcweir 	return rOStm;
3072cdf0e10cSrcweir }
3073cdf0e10cSrcweir 
3074cdf0e10cSrcweir // ------------------------------------------------------------------------
3075cdf0e10cSrcweir 
3076cdf0e10cSrcweir sal_Bool GDIMetaFile::CreateThumbnail( sal_uInt32 nMaximumExtent,
3077cdf0e10cSrcweir 									BitmapEx& rBmpEx,
3078cdf0e10cSrcweir 									const BitmapEx* pOverlay,
3079cdf0e10cSrcweir 									const Rectangle* pOverlayRect ) const
3080cdf0e10cSrcweir {
3081cdf0e10cSrcweir 	// the implementation is provided by KA
3082cdf0e10cSrcweir 
3083cdf0e10cSrcweir 	// initialization seems to be complicated but is used to avoid rounding errors
3084cdf0e10cSrcweir 	VirtualDevice	aVDev;
3085cdf0e10cSrcweir 	const Point     aNullPt;
3086cdf0e10cSrcweir 	const Point     aTLPix( aVDev.LogicToPixel( aNullPt, GetPrefMapMode() ) );
3087cdf0e10cSrcweir 	const Point     aBRPix( aVDev.LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
3088cdf0e10cSrcweir 	Size            aDrawSize( aVDev.LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
3089cdf0e10cSrcweir 	Size			aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
3090cdf0e10cSrcweir 	Point			aPosPix;
3091cdf0e10cSrcweir 
3092cdf0e10cSrcweir 	if ( !rBmpEx.IsEmpty() )
3093cdf0e10cSrcweir 		rBmpEx.SetEmpty();
3094cdf0e10cSrcweir 
3095cdf0e10cSrcweir 	// determine size that has the same aspect ratio as image size and
3096cdf0e10cSrcweir 	// fits into the rectangle determined by nMaximumExtent
3097cdf0e10cSrcweir 	if ( aSizePix.Width() && aSizePix.Height()
3098cdf0e10cSrcweir 	  && ( sal::static_int_cast< unsigned long >(aSizePix.Width()) >
3099cdf0e10cSrcweir                nMaximumExtent ||
3100cdf0e10cSrcweir            sal::static_int_cast< unsigned long >(aSizePix.Height()) >
3101cdf0e10cSrcweir                nMaximumExtent ) )
3102cdf0e10cSrcweir 	{
3103cdf0e10cSrcweir 		const Size  aOldSizePix( aSizePix );
3104cdf0e10cSrcweir 		double      fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
3105cdf0e10cSrcweir 
3106cdf0e10cSrcweir 		if ( fWH <= 1.0 )
3107cdf0e10cSrcweir 		{
3108cdf0e10cSrcweir 			aSizePix.Width() = FRound( nMaximumExtent * fWH );
3109cdf0e10cSrcweir 			aSizePix.Height() = nMaximumExtent;
3110cdf0e10cSrcweir 		}
3111cdf0e10cSrcweir 		else
3112cdf0e10cSrcweir 		{
3113cdf0e10cSrcweir 			aSizePix.Width() = nMaximumExtent;
3114cdf0e10cSrcweir 			aSizePix.Height() = FRound(  nMaximumExtent / fWH );
3115cdf0e10cSrcweir 		}
3116cdf0e10cSrcweir 
3117cdf0e10cSrcweir 		aDrawSize.Width() = FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() );
3118cdf0e10cSrcweir 		aDrawSize.Height() = FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() );
3119cdf0e10cSrcweir 	}
3120cdf0e10cSrcweir 
3121cdf0e10cSrcweir 	Size 		aFullSize;
3122cdf0e10cSrcweir 	Point		aBackPosPix;
3123cdf0e10cSrcweir 	Rectangle 	aOverlayRect;
3124cdf0e10cSrcweir 
3125cdf0e10cSrcweir 	// calculate addigtional positions and sizes if an overlay image is used
3126cdf0e10cSrcweir 	if (  pOverlay )
3127cdf0e10cSrcweir 	{
3128cdf0e10cSrcweir 		aFullSize = Size( nMaximumExtent, nMaximumExtent );
3129cdf0e10cSrcweir 		aOverlayRect = Rectangle( aNullPt, aFullSize  );
3130cdf0e10cSrcweir 
3131cdf0e10cSrcweir 		aOverlayRect.Intersection( pOverlayRect ? *pOverlayRect : Rectangle( aNullPt, pOverlay->GetSizePixel() ) );
3132cdf0e10cSrcweir 
3133cdf0e10cSrcweir 		if ( !aOverlayRect.IsEmpty() )
3134cdf0e10cSrcweir 			aBackPosPix = Point( ( nMaximumExtent - aSizePix.Width() ) >> 1, ( nMaximumExtent - aSizePix.Height() ) >> 1 );
3135cdf0e10cSrcweir 		else
3136cdf0e10cSrcweir 			pOverlay = NULL;
3137cdf0e10cSrcweir 	}
3138cdf0e10cSrcweir 	else
3139cdf0e10cSrcweir 	{
3140cdf0e10cSrcweir 		aFullSize = aSizePix;
3141cdf0e10cSrcweir 		pOverlay = NULL;
3142cdf0e10cSrcweir 	}
3143cdf0e10cSrcweir 
3144cdf0e10cSrcweir 	// draw image(s) into VDev and get resulting image
3145cdf0e10cSrcweir 	if ( aVDev.SetOutputSizePixel( aFullSize ) )
3146cdf0e10cSrcweir 	{
3147cdf0e10cSrcweir 		// draw metafile into VDev
3148cdf0e10cSrcweir 		const_cast<GDIMetaFile *>(this)->WindStart();
3149cdf0e10cSrcweir 		const_cast<GDIMetaFile *>(this)->Play( &aVDev, aBackPosPix, aDrawSize );
3150cdf0e10cSrcweir 
3151cdf0e10cSrcweir 		// draw overlay if neccessary
3152cdf0e10cSrcweir 		if ( pOverlay )
3153cdf0e10cSrcweir 			aVDev.DrawBitmapEx( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), *pOverlay );
3154cdf0e10cSrcweir 
3155cdf0e10cSrcweir 		// get paint bitmap
3156cdf0e10cSrcweir 		Bitmap aBmp( aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) );
3157cdf0e10cSrcweir 
3158cdf0e10cSrcweir 		// assure that we have a true color image
3159cdf0e10cSrcweir 		if ( aBmp.GetBitCount() != 24 )
3160cdf0e10cSrcweir 			aBmp.Convert( BMP_CONVERSION_24BIT );
3161cdf0e10cSrcweir 
3162cdf0e10cSrcweir 		// create resulting mask bitmap with metafile output set to black
3163cdf0e10cSrcweir 		GDIMetaFile aMonchromeMtf( GetMonochromeMtf( COL_BLACK ) );
3164cdf0e10cSrcweir 		aVDev.DrawWallpaper( Rectangle( aNullPt, aSizePix ), Wallpaper( Color( COL_WHITE ) ) );
3165cdf0e10cSrcweir 		aMonchromeMtf.WindStart();
3166cdf0e10cSrcweir 		aMonchromeMtf.Play( &aVDev, aBackPosPix, aDrawSize );
3167cdf0e10cSrcweir 
3168cdf0e10cSrcweir 		// watch for overlay mask
3169cdf0e10cSrcweir 		if ( pOverlay  )
3170cdf0e10cSrcweir 		{
3171cdf0e10cSrcweir 			Bitmap aOverlayMergeBmp( aVDev.GetBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize() ) );
3172cdf0e10cSrcweir 
3173cdf0e10cSrcweir 			// create ANDed resulting mask at overlay area
3174cdf0e10cSrcweir 			if ( pOverlay->IsTransparent() )
3175cdf0e10cSrcweir 				aVDev.DrawBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), pOverlay->GetMask() );
3176cdf0e10cSrcweir 			else
3177cdf0e10cSrcweir 			{
3178cdf0e10cSrcweir 				aVDev.SetLineColor( COL_BLACK );
3179cdf0e10cSrcweir 				aVDev.SetFillColor( COL_BLACK );
3180cdf0e10cSrcweir 				aVDev.DrawRect( aOverlayRect);
3181cdf0e10cSrcweir 			}
3182cdf0e10cSrcweir 
3183cdf0e10cSrcweir 			aOverlayMergeBmp.CombineSimple( aVDev.GetBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize() ), BMP_COMBINE_AND );
3184cdf0e10cSrcweir 			aVDev.DrawBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), aOverlayMergeBmp );
3185cdf0e10cSrcweir 		}
3186cdf0e10cSrcweir 
3187cdf0e10cSrcweir 		rBmpEx = BitmapEx( aBmp, aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) );
3188cdf0e10cSrcweir 	}
3189cdf0e10cSrcweir 
3190cdf0e10cSrcweir 	return !rBmpEx.IsEmpty();
3191cdf0e10cSrcweir }
3192