xref: /AOO41X/main/svtools/source/graphic/grfmgr2.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_svtools.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <vos/macros.hxx>
32*cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
33*cdf0e10cSrcweir #include <tools/poly.hxx>
34*cdf0e10cSrcweir #include <vcl/outdev.hxx>
35*cdf0e10cSrcweir #include <vcl/window.hxx>
36*cdf0e10cSrcweir #include <vcl/gdimtf.hxx>
37*cdf0e10cSrcweir #include <vcl/metaact.hxx>
38*cdf0e10cSrcweir #include <vcl/metric.hxx>
39*cdf0e10cSrcweir #include <vcl/animate.hxx>
40*cdf0e10cSrcweir #include <vcl/alpha.hxx>
41*cdf0e10cSrcweir #include <vcl/virdev.hxx>
42*cdf0e10cSrcweir #include "grfcache.hxx"
43*cdf0e10cSrcweir #include <svtools/grfmgr.hxx>
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir // -----------
46*cdf0e10cSrcweir // - defines -
47*cdf0e10cSrcweir // -----------
48*cdf0e10cSrcweir 
49*cdf0e10cSrcweir #define MAX_PRINTER_EXT				1024
50*cdf0e10cSrcweir #define MAP( cVal0, cVal1, nFrac )	((sal_uInt8)((((long)(cVal0)<<20L)+nFrac*((long)(cVal1)-(cVal0)))>>20L))
51*cdf0e10cSrcweir #define WATERMARK_LUM_OFFSET		50
52*cdf0e10cSrcweir #define WATERMARK_CON_OFFSET		-70
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir // -----------
55*cdf0e10cSrcweir // - helpers -
56*cdf0e10cSrcweir // -----------
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir namespace {
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir void muckWithBitmap( const Point&    rDestPoint,
61*cdf0e10cSrcweir                      const Size&     rDestSize,
62*cdf0e10cSrcweir                      const Size&     rRefSize,
63*cdf0e10cSrcweir                      bool&           o_rbNonBitmapActionEncountered )
64*cdf0e10cSrcweir {
65*cdf0e10cSrcweir     const Point aEmptyPoint;
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir     if( aEmptyPoint != rDestPoint ||
68*cdf0e10cSrcweir         rDestSize != rRefSize )
69*cdf0e10cSrcweir     {
70*cdf0e10cSrcweir         // non-fullscale, or offsetted bmp -> fallback to mtf
71*cdf0e10cSrcweir         // rendering
72*cdf0e10cSrcweir         o_rbNonBitmapActionEncountered = true;
73*cdf0e10cSrcweir     }
74*cdf0e10cSrcweir }
75*cdf0e10cSrcweir 
76*cdf0e10cSrcweir BitmapEx muckWithBitmap( const BitmapEx& rBmpEx,
77*cdf0e10cSrcweir                          const Point&    rSrcPoint,
78*cdf0e10cSrcweir                          const Size&     rSrcSize,
79*cdf0e10cSrcweir                          const Point&    rDestPoint,
80*cdf0e10cSrcweir                          const Size&     rDestSize,
81*cdf0e10cSrcweir                          const Size&     rRefSize,
82*cdf0e10cSrcweir                          bool&           o_rbNonBitmapActionEncountered )
83*cdf0e10cSrcweir {
84*cdf0e10cSrcweir     BitmapEx aBmpEx;
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir     muckWithBitmap(rDestPoint,
87*cdf0e10cSrcweir                    rDestSize,
88*cdf0e10cSrcweir                    rRefSize,
89*cdf0e10cSrcweir                    o_rbNonBitmapActionEncountered);
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir     if( o_rbNonBitmapActionEncountered )
92*cdf0e10cSrcweir         return aBmpEx;
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir     aBmpEx = rBmpEx;
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir     if( (rSrcPoint.X() != 0 && rSrcPoint.Y() != 0) ||
97*cdf0e10cSrcweir         rSrcSize != rBmpEx.GetSizePixel() )
98*cdf0e10cSrcweir     {
99*cdf0e10cSrcweir         // crop bitmap to given source rectangle (no
100*cdf0e10cSrcweir         // need to copy and convert the whole bitmap)
101*cdf0e10cSrcweir         const Rectangle aCropRect( rSrcPoint,
102*cdf0e10cSrcweir                                    rSrcSize );
103*cdf0e10cSrcweir         aBmpEx.Crop( aCropRect );
104*cdf0e10cSrcweir     }
105*cdf0e10cSrcweir 
106*cdf0e10cSrcweir     return aBmpEx;
107*cdf0e10cSrcweir }
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir } // namespace {
110*cdf0e10cSrcweir 
111*cdf0e10cSrcweir 
112*cdf0e10cSrcweir // ------------------
113*cdf0e10cSrcweir // - GraphicManager -
114*cdf0e10cSrcweir // ------------------
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir GraphicManager::GraphicManager( sal_uLong nCacheSize, sal_uLong nMaxObjCacheSize ) :
117*cdf0e10cSrcweir 		mpCache( new GraphicCache( *this, nCacheSize, nMaxObjCacheSize ) )
118*cdf0e10cSrcweir {
119*cdf0e10cSrcweir }
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir // -----------------------------------------------------------------------------
122*cdf0e10cSrcweir 
123*cdf0e10cSrcweir GraphicManager::~GraphicManager()
124*cdf0e10cSrcweir {
125*cdf0e10cSrcweir 	for( void* pObj = maObjList.First(); pObj; pObj = maObjList.Next() )
126*cdf0e10cSrcweir 		( (GraphicObject*) pObj )->GraphicManagerDestroyed();
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir 	delete mpCache;
129*cdf0e10cSrcweir }
130*cdf0e10cSrcweir 
131*cdf0e10cSrcweir // -----------------------------------------------------------------------------
132*cdf0e10cSrcweir 
133*cdf0e10cSrcweir void GraphicManager::SetMaxCacheSize( sal_uLong nNewCacheSize )
134*cdf0e10cSrcweir {
135*cdf0e10cSrcweir 	mpCache->SetMaxDisplayCacheSize( nNewCacheSize );
136*cdf0e10cSrcweir }
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir // -----------------------------------------------------------------------------
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir sal_uLong GraphicManager::GetMaxCacheSize() const
141*cdf0e10cSrcweir {
142*cdf0e10cSrcweir 	return mpCache->GetMaxDisplayCacheSize();
143*cdf0e10cSrcweir }
144*cdf0e10cSrcweir 
145*cdf0e10cSrcweir // -----------------------------------------------------------------------------
146*cdf0e10cSrcweir 
147*cdf0e10cSrcweir void GraphicManager::SetMaxObjCacheSize( sal_uLong nNewMaxObjSize, sal_Bool bDestroyGreaterCached )
148*cdf0e10cSrcweir {
149*cdf0e10cSrcweir 	mpCache->SetMaxObjDisplayCacheSize( nNewMaxObjSize, bDestroyGreaterCached );
150*cdf0e10cSrcweir }
151*cdf0e10cSrcweir 
152*cdf0e10cSrcweir // -----------------------------------------------------------------------------
153*cdf0e10cSrcweir 
154*cdf0e10cSrcweir sal_uLong GraphicManager::GetMaxObjCacheSize() const
155*cdf0e10cSrcweir {
156*cdf0e10cSrcweir 	return mpCache->GetMaxObjDisplayCacheSize();
157*cdf0e10cSrcweir }
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir // -----------------------------------------------------------------------------
160*cdf0e10cSrcweir 
161*cdf0e10cSrcweir sal_uLong GraphicManager::GetUsedCacheSize() const
162*cdf0e10cSrcweir {
163*cdf0e10cSrcweir 	return mpCache->GetUsedDisplayCacheSize();
164*cdf0e10cSrcweir }
165*cdf0e10cSrcweir 
166*cdf0e10cSrcweir // -----------------------------------------------------------------------------
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir sal_uLong GraphicManager::GetFreeCacheSize() const
169*cdf0e10cSrcweir {
170*cdf0e10cSrcweir 	return mpCache->GetFreeDisplayCacheSize();
171*cdf0e10cSrcweir }
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir // -----------------------------------------------------------------------------
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir void GraphicManager::SetCacheTimeout( sal_uLong nTimeoutSeconds )
176*cdf0e10cSrcweir {
177*cdf0e10cSrcweir 	mpCache->SetCacheTimeout( nTimeoutSeconds );
178*cdf0e10cSrcweir }
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir // -----------------------------------------------------------------------------
181*cdf0e10cSrcweir 
182*cdf0e10cSrcweir sal_uLong GraphicManager::GetCacheTimeout() const
183*cdf0e10cSrcweir {
184*cdf0e10cSrcweir 	return mpCache->GetCacheTimeout();
185*cdf0e10cSrcweir }
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir // -----------------------------------------------------------------------------
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir void GraphicManager::ClearCache()
190*cdf0e10cSrcweir {
191*cdf0e10cSrcweir 	mpCache->ClearDisplayCache();
192*cdf0e10cSrcweir }
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir // -----------------------------------------------------------------------------
195*cdf0e10cSrcweir 
196*cdf0e10cSrcweir void GraphicManager::ReleaseFromCache( const GraphicObject& /*rObj*/ )
197*cdf0e10cSrcweir {
198*cdf0e10cSrcweir 	// !!!
199*cdf0e10cSrcweir }
200*cdf0e10cSrcweir 
201*cdf0e10cSrcweir // -----------------------------------------------------------------------------
202*cdf0e10cSrcweir 
203*cdf0e10cSrcweir sal_Bool GraphicManager::IsInCache( OutputDevice* pOut, const Point& rPt,
204*cdf0e10cSrcweir 									const Size& rSz, const GraphicObject& rObj,
205*cdf0e10cSrcweir 									const GraphicAttr& rAttr ) const
206*cdf0e10cSrcweir {
207*cdf0e10cSrcweir 	return mpCache->IsInDisplayCache( pOut, rPt, rSz, rObj, rAttr );
208*cdf0e10cSrcweir }
209*cdf0e10cSrcweir 
210*cdf0e10cSrcweir // -----------------------------------------------------------------------------
211*cdf0e10cSrcweir 
212*cdf0e10cSrcweir sal_Bool GraphicManager::DrawObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
213*cdf0e10cSrcweir 							  GraphicObject& rObj, const GraphicAttr& rAttr,
214*cdf0e10cSrcweir 							  const sal_uLong nFlags, sal_Bool& rCached )
215*cdf0e10cSrcweir {
216*cdf0e10cSrcweir 	Point   aPt( rPt );
217*cdf0e10cSrcweir 	Size	aSz( rSz );
218*cdf0e10cSrcweir 	sal_Bool	bRet = sal_False;
219*cdf0e10cSrcweir 
220*cdf0e10cSrcweir 	rCached = sal_False;
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir 	if( ( rObj.GetType() == GRAPHIC_BITMAP ) || ( rObj.GetType() == GRAPHIC_GDIMETAFILE ) )
223*cdf0e10cSrcweir 	{
224*cdf0e10cSrcweir 		// create output and fill cache
225*cdf0e10cSrcweir 		const Size aOutSize( pOut->GetOutputSizePixel() );
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir 		if( rObj.IsAnimated() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) ||
228*cdf0e10cSrcweir 		    ( !( nFlags & GRFMGR_DRAW_NO_SUBSTITUTE ) &&
229*cdf0e10cSrcweir 		      ( ( nFlags & GRFMGR_DRAW_SUBSTITUTE ) ||
230*cdf0e10cSrcweir 		        !( nFlags & GRFMGR_DRAW_CACHED ) ||
231*cdf0e10cSrcweir 		        ( pOut->GetConnectMetaFile() && !pOut->IsOutputEnabled() ) ) ) )
232*cdf0e10cSrcweir 		{
233*cdf0e10cSrcweir 			// simple output of transformed graphic
234*cdf0e10cSrcweir 			const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) );
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir 			if( aGraphic.IsSupportedGraphic() )
237*cdf0e10cSrcweir 			{
238*cdf0e10cSrcweir 				const sal_uInt16 nRot10 = rAttr.GetRotation() % 3600;
239*cdf0e10cSrcweir 
240*cdf0e10cSrcweir 				if( nRot10 )
241*cdf0e10cSrcweir 				{
242*cdf0e10cSrcweir 					Polygon aPoly( Rectangle( aPt, aSz ) );
243*cdf0e10cSrcweir 
244*cdf0e10cSrcweir 					aPoly.Rotate( aPt, nRot10 );
245*cdf0e10cSrcweir 					const Rectangle aRotBoundRect( aPoly.GetBoundRect() );
246*cdf0e10cSrcweir 					aPt = aRotBoundRect.TopLeft();
247*cdf0e10cSrcweir 					aSz = aRotBoundRect.GetSize();
248*cdf0e10cSrcweir 				}
249*cdf0e10cSrcweir 
250*cdf0e10cSrcweir 				aGraphic.Draw( pOut, aPt, aSz );
251*cdf0e10cSrcweir 			}
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir 			bRet = sal_True;
254*cdf0e10cSrcweir 		}
255*cdf0e10cSrcweir 
256*cdf0e10cSrcweir 		if( !bRet )
257*cdf0e10cSrcweir 		{
258*cdf0e10cSrcweir 			// cached/direct drawing
259*cdf0e10cSrcweir 			if( !mpCache->DrawDisplayCacheObj( pOut, aPt, aSz, rObj, rAttr ) )
260*cdf0e10cSrcweir 				bRet = ImplDraw( pOut, aPt, aSz, rObj, rAttr, nFlags, rCached );
261*cdf0e10cSrcweir 			else
262*cdf0e10cSrcweir 				bRet = rCached = sal_True;
263*cdf0e10cSrcweir 		}
264*cdf0e10cSrcweir 	}
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir 	return bRet;
267*cdf0e10cSrcweir }
268*cdf0e10cSrcweir 
269*cdf0e10cSrcweir // -----------------------------------------------------------------------------
270*cdf0e10cSrcweir 
271*cdf0e10cSrcweir void GraphicManager::ImplRegisterObj( const GraphicObject& rObj, Graphic& rSubstitute,
272*cdf0e10cSrcweir                                       const ByteString* pID, const GraphicObject* pCopyObj )
273*cdf0e10cSrcweir {
274*cdf0e10cSrcweir 	maObjList.Insert( (void*) &rObj, LIST_APPEND );
275*cdf0e10cSrcweir 	mpCache->AddGraphicObject( rObj, rSubstitute, pID, pCopyObj );
276*cdf0e10cSrcweir }
277*cdf0e10cSrcweir 
278*cdf0e10cSrcweir // -----------------------------------------------------------------------------
279*cdf0e10cSrcweir 
280*cdf0e10cSrcweir void GraphicManager::ImplUnregisterObj( const GraphicObject& rObj )
281*cdf0e10cSrcweir {
282*cdf0e10cSrcweir 	mpCache->ReleaseGraphicObject( rObj );
283*cdf0e10cSrcweir 	maObjList.Remove( (void*) &rObj );
284*cdf0e10cSrcweir }
285*cdf0e10cSrcweir 
286*cdf0e10cSrcweir // -----------------------------------------------------------------------------
287*cdf0e10cSrcweir 
288*cdf0e10cSrcweir void GraphicManager::ImplGraphicObjectWasSwappedOut( const GraphicObject& rObj )
289*cdf0e10cSrcweir {
290*cdf0e10cSrcweir 	mpCache->GraphicObjectWasSwappedOut( rObj );
291*cdf0e10cSrcweir }
292*cdf0e10cSrcweir 
293*cdf0e10cSrcweir // -----------------------------------------------------------------------------
294*cdf0e10cSrcweir 
295*cdf0e10cSrcweir ByteString GraphicManager::ImplGetUniqueID( const GraphicObject& rObj ) const
296*cdf0e10cSrcweir {
297*cdf0e10cSrcweir 	return mpCache->GetUniqueID( rObj );
298*cdf0e10cSrcweir }
299*cdf0e10cSrcweir 
300*cdf0e10cSrcweir // -----------------------------------------------------------------------------
301*cdf0e10cSrcweir 
302*cdf0e10cSrcweir sal_Bool GraphicManager::ImplFillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute )
303*cdf0e10cSrcweir {
304*cdf0e10cSrcweir 	return( mpCache->FillSwappedGraphicObject( rObj, rSubstitute ) );
305*cdf0e10cSrcweir }
306*cdf0e10cSrcweir 
307*cdf0e10cSrcweir // -----------------------------------------------------------------------------
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir void GraphicManager::ImplGraphicObjectWasSwappedIn( const GraphicObject& rObj )
310*cdf0e10cSrcweir {
311*cdf0e10cSrcweir 	mpCache->GraphicObjectWasSwappedIn( rObj );
312*cdf0e10cSrcweir }
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir // -----------------------------------------------------------------------------
315*cdf0e10cSrcweir 
316*cdf0e10cSrcweir sal_Bool GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt,
317*cdf0e10cSrcweir 							   const Size& rSz, GraphicObject& rObj,
318*cdf0e10cSrcweir 							   const GraphicAttr& rAttr,
319*cdf0e10cSrcweir                                const sal_uLong nFlags, sal_Bool& rCached )
320*cdf0e10cSrcweir {
321*cdf0e10cSrcweir 	const Graphic&	rGraphic = rObj.GetGraphic();
322*cdf0e10cSrcweir 	sal_Bool			bRet = sal_False;
323*cdf0e10cSrcweir 
324*cdf0e10cSrcweir 	if( rGraphic.IsSupportedGraphic() && !rGraphic.IsSwapOut() )
325*cdf0e10cSrcweir 	{
326*cdf0e10cSrcweir 		if( GRAPHIC_BITMAP == rGraphic.GetType() )
327*cdf0e10cSrcweir 		{
328*cdf0e10cSrcweir 			const BitmapEx aSrcBmpEx( rGraphic.GetBitmapEx() );
329*cdf0e10cSrcweir 
330*cdf0e10cSrcweir             // #i46805# No point in caching a bitmap that is rendered
331*cdf0e10cSrcweir             // via RectFill on the OutDev
332*cdf0e10cSrcweir 			if( !(pOut->GetDrawMode() & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP )) &&
333*cdf0e10cSrcweir                 mpCache->IsDisplayCacheable( pOut, rPt, rSz, rObj, rAttr ) )
334*cdf0e10cSrcweir 			{
335*cdf0e10cSrcweir 				BitmapEx aDstBmpEx;
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir 				if( ImplCreateOutput( pOut, rPt, rSz, aSrcBmpEx, rAttr, nFlags, &aDstBmpEx ) )
338*cdf0e10cSrcweir 				{
339*cdf0e10cSrcweir 					rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstBmpEx );
340*cdf0e10cSrcweir 					bRet = sal_True;
341*cdf0e10cSrcweir 				}
342*cdf0e10cSrcweir 			}
343*cdf0e10cSrcweir 
344*cdf0e10cSrcweir 			if( !bRet )
345*cdf0e10cSrcweir 				bRet = ImplCreateOutput( pOut, rPt, rSz, aSrcBmpEx, rAttr, nFlags );
346*cdf0e10cSrcweir 		}
347*cdf0e10cSrcweir 		else
348*cdf0e10cSrcweir 		{
349*cdf0e10cSrcweir 			const GDIMetaFile& rSrcMtf = rGraphic.GetGDIMetaFile();
350*cdf0e10cSrcweir 
351*cdf0e10cSrcweir 			if( mpCache->IsDisplayCacheable( pOut, rPt, rSz, rObj, rAttr ) )
352*cdf0e10cSrcweir 			{
353*cdf0e10cSrcweir 				GDIMetaFile aDstMtf;
354*cdf0e10cSrcweir                 BitmapEx    aContainedBmpEx;
355*cdf0e10cSrcweir 
356*cdf0e10cSrcweir 				if( ImplCreateOutput( pOut, rPt, rSz, rSrcMtf, rAttr, nFlags, aDstMtf, aContainedBmpEx ) )
357*cdf0e10cSrcweir 				{
358*cdf0e10cSrcweir                     if( !!aContainedBmpEx )
359*cdf0e10cSrcweir                     {
360*cdf0e10cSrcweir                         // #117889# Use bitmap output method, if
361*cdf0e10cSrcweir                         // metafile basically contains only a single
362*cdf0e10cSrcweir                         // bitmap
363*cdf0e10cSrcweir                         BitmapEx aDstBmpEx;
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir                         if( ImplCreateOutput( pOut, rPt, rSz, aContainedBmpEx, rAttr, nFlags, &aDstBmpEx ) )
366*cdf0e10cSrcweir                         {
367*cdf0e10cSrcweir                             rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstBmpEx );
368*cdf0e10cSrcweir                             bRet = sal_True;
369*cdf0e10cSrcweir                         }
370*cdf0e10cSrcweir                     }
371*cdf0e10cSrcweir                     else
372*cdf0e10cSrcweir                     {
373*cdf0e10cSrcweir                         rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstMtf );
374*cdf0e10cSrcweir                         bRet = sal_True;
375*cdf0e10cSrcweir                     }
376*cdf0e10cSrcweir 				}
377*cdf0e10cSrcweir 			}
378*cdf0e10cSrcweir 
379*cdf0e10cSrcweir 			if( !bRet )
380*cdf0e10cSrcweir 			{
381*cdf0e10cSrcweir 				const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) );
382*cdf0e10cSrcweir 
383*cdf0e10cSrcweir 				if( aGraphic.IsSupportedGraphic() )
384*cdf0e10cSrcweir 				{
385*cdf0e10cSrcweir 					aGraphic.Draw( pOut, rPt, rSz );
386*cdf0e10cSrcweir 					bRet = sal_True;
387*cdf0e10cSrcweir 				}
388*cdf0e10cSrcweir 			}
389*cdf0e10cSrcweir 		}
390*cdf0e10cSrcweir 	}
391*cdf0e10cSrcweir 
392*cdf0e10cSrcweir 	return bRet;
393*cdf0e10cSrcweir }
394*cdf0e10cSrcweir 
395*cdf0e10cSrcweir // -----------------------------------------------------------------------------
396*cdf0e10cSrcweir 
397*cdf0e10cSrcweir sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
398*cdf0e10cSrcweir                                        const Point& rPt, const Size& rSz,
399*cdf0e10cSrcweir 									   const BitmapEx& rBmpEx, const GraphicAttr& rAttr,
400*cdf0e10cSrcweir 									   const sal_uLong nFlags, BitmapEx* pBmpEx )
401*cdf0e10cSrcweir {
402*cdf0e10cSrcweir 	sal_uInt16	nRot10 = rAttr.GetRotation() % 3600;
403*cdf0e10cSrcweir 	Point	aOutPtPix;
404*cdf0e10cSrcweir 	Size	aOutSzPix;
405*cdf0e10cSrcweir 	Size	aUnrotatedSzPix( pOut->LogicToPixel( rSz ) );
406*cdf0e10cSrcweir 	sal_Bool	bRet = sal_False;
407*cdf0e10cSrcweir 
408*cdf0e10cSrcweir 	if( nRot10 )
409*cdf0e10cSrcweir 	{
410*cdf0e10cSrcweir 		Polygon aPoly( Rectangle( rPt, rSz ) );
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir 		aPoly.Rotate( rPt, nRot10 );
413*cdf0e10cSrcweir 		const Rectangle aRotBoundRect( aPoly.GetBoundRect() );
414*cdf0e10cSrcweir 		aOutPtPix = pOut->LogicToPixel( aRotBoundRect.TopLeft() );
415*cdf0e10cSrcweir 		aOutSzPix = pOut->LogicToPixel( aRotBoundRect.GetSize() );
416*cdf0e10cSrcweir 	}
417*cdf0e10cSrcweir 	else
418*cdf0e10cSrcweir 	{
419*cdf0e10cSrcweir 		aOutPtPix = pOut->LogicToPixel( rPt );
420*cdf0e10cSrcweir 		aOutSzPix = aUnrotatedSzPix;
421*cdf0e10cSrcweir 	}
422*cdf0e10cSrcweir 
423*cdf0e10cSrcweir 	if( aUnrotatedSzPix.Width() && aUnrotatedSzPix.Height() )
424*cdf0e10cSrcweir 	{
425*cdf0e10cSrcweir 		BitmapEx		aBmpEx( rBmpEx );
426*cdf0e10cSrcweir 		BitmapEx		aOutBmpEx;
427*cdf0e10cSrcweir 		Point			aOutPt;
428*cdf0e10cSrcweir 		Size			aOutSz;
429*cdf0e10cSrcweir 		const Size&		rBmpSzPix = rBmpEx.GetSizePixel();
430*cdf0e10cSrcweir 		const long		nW = rBmpSzPix.Width();
431*cdf0e10cSrcweir 		const long		nH = rBmpSzPix.Height();
432*cdf0e10cSrcweir 		const long		nNewW = aUnrotatedSzPix.Width();
433*cdf0e10cSrcweir 		const long		nNewH = aUnrotatedSzPix.Height();
434*cdf0e10cSrcweir 		double			fTmp;
435*cdf0e10cSrcweir 		long*			pMapIX = new long[ nNewW ];
436*cdf0e10cSrcweir 		long*			pMapFX = new long[ nNewW ];
437*cdf0e10cSrcweir 		long*			pMapIY = new long[ nNewH ];
438*cdf0e10cSrcweir 		long*			pMapFY = new long[ nNewH ];
439*cdf0e10cSrcweir 		long			nStartX = -1, nStartY = -1, nEndX = -1, nEndY = -1;
440*cdf0e10cSrcweir 		long			nX, nY, nTmp, nTmpX, nTmpY;
441*cdf0e10cSrcweir 		sal_Bool			bHMirr = ( rAttr.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0;
442*cdf0e10cSrcweir 		sal_Bool			bVMirr = ( rAttr.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0;
443*cdf0e10cSrcweir 
444*cdf0e10cSrcweir         if( nFlags & GRFMGR_DRAW_BILINEAR )
445*cdf0e10cSrcweir         {
446*cdf0e10cSrcweir             const double	fRevScaleX = ( nNewW > 1L ) ? ( (double) ( nW - 1L ) / ( nNewW - 1L ) ) : 0.0;
447*cdf0e10cSrcweir             const double	fRevScaleY = ( nNewH > 1L ) ? ( (double) ( nH - 1L ) / ( nNewH - 1L ) ) : 0.0;
448*cdf0e10cSrcweir 
449*cdf0e10cSrcweir             // create horizontal mapping table
450*cdf0e10cSrcweir             for( nX = 0L, nTmpX = nW - 1L, nTmp = nW - 2L; nX < nNewW; nX++ )
451*cdf0e10cSrcweir             {
452*cdf0e10cSrcweir                 fTmp = nX * fRevScaleX;
453*cdf0e10cSrcweir 
454*cdf0e10cSrcweir                 if( bHMirr )
455*cdf0e10cSrcweir                     fTmp = nTmpX - fTmp;
456*cdf0e10cSrcweir 
457*cdf0e10cSrcweir                 pMapFX[ nX ] = (long) ( ( fTmp - ( pMapIX[ nX ] = MinMax( (long) fTmp, 0, nTmp ) ) ) * 1048576. );
458*cdf0e10cSrcweir             }
459*cdf0e10cSrcweir 
460*cdf0e10cSrcweir             // create vertical mapping table
461*cdf0e10cSrcweir             for( nY = 0L, nTmpY = nH - 1L, nTmp = nH - 2L; nY < nNewH; nY++ )
462*cdf0e10cSrcweir             {
463*cdf0e10cSrcweir                 fTmp = nY * fRevScaleY;
464*cdf0e10cSrcweir 
465*cdf0e10cSrcweir                 if( bVMirr )
466*cdf0e10cSrcweir                     fTmp = nTmpY - fTmp;
467*cdf0e10cSrcweir 
468*cdf0e10cSrcweir                 pMapFY[ nY ] = (long) ( ( fTmp - ( pMapIY[ nY ] = MinMax( (long) fTmp, 0, nTmp ) ) ) * 1048576. );
469*cdf0e10cSrcweir             }
470*cdf0e10cSrcweir         }
471*cdf0e10cSrcweir         else
472*cdf0e10cSrcweir         {
473*cdf0e10cSrcweir             // #98290# Use a different mapping for non-interpolating mode, to avoid missing rows/columns
474*cdf0e10cSrcweir             const double	fRevScaleX = ( nNewW > 1L ) ? ( (double) nW / nNewW ) : 0.0;
475*cdf0e10cSrcweir             const double	fRevScaleY = ( nNewH > 1L ) ? ( (double) nH / nNewH ) : 0.0;
476*cdf0e10cSrcweir 
477*cdf0e10cSrcweir             // create horizontal mapping table
478*cdf0e10cSrcweir             for( nX = 0L, nTmpX = nW - 1L, nTmp = nW - 2L; nX < nNewW; nX++ )
479*cdf0e10cSrcweir             {
480*cdf0e10cSrcweir                 fTmp = nX * fRevScaleX;
481*cdf0e10cSrcweir 
482*cdf0e10cSrcweir                 if( bHMirr )
483*cdf0e10cSrcweir                     fTmp = nTmpX - fTmp;
484*cdf0e10cSrcweir 
485*cdf0e10cSrcweir                 // #98290# Do not use round to zero, otherwise last column will be missing
486*cdf0e10cSrcweir                 pMapIX[ nX ] = MinMax( (long) fTmp, 0, nTmp );
487*cdf0e10cSrcweir                 pMapFX[ nX ] = fTmp >= nTmp+1 ? 1048576 : 0;
488*cdf0e10cSrcweir             }
489*cdf0e10cSrcweir 
490*cdf0e10cSrcweir             // create vertical mapping table
491*cdf0e10cSrcweir             for( nY = 0L, nTmpY = nH - 1L, nTmp = nH - 2L; nY < nNewH; nY++ )
492*cdf0e10cSrcweir             {
493*cdf0e10cSrcweir                 fTmp = nY * fRevScaleY;
494*cdf0e10cSrcweir 
495*cdf0e10cSrcweir                 if( bVMirr )
496*cdf0e10cSrcweir                     fTmp = nTmpY - fTmp;
497*cdf0e10cSrcweir 
498*cdf0e10cSrcweir                 // #98290# Do not use round to zero, otherwise last row will be missing
499*cdf0e10cSrcweir                 pMapIY[ nY ] = MinMax( (long) fTmp, 0, nTmp );
500*cdf0e10cSrcweir                 pMapFY[ nY ] = fTmp >= nTmp+1 ? 1048576 : 0;
501*cdf0e10cSrcweir             }
502*cdf0e10cSrcweir         }
503*cdf0e10cSrcweir 
504*cdf0e10cSrcweir         // calculate output sizes
505*cdf0e10cSrcweir 		if( !pBmpEx )
506*cdf0e10cSrcweir 		{
507*cdf0e10cSrcweir 			Point		aPt;
508*cdf0e10cSrcweir 			Rectangle	aOutRect( aPt, pOut->GetOutputSizePixel() );
509*cdf0e10cSrcweir 			Rectangle	aBmpRect( aOutPtPix, aOutSzPix );
510*cdf0e10cSrcweir 
511*cdf0e10cSrcweir 			if( pOut->GetOutDevType() == OUTDEV_WINDOW )
512*cdf0e10cSrcweir 			{
513*cdf0e10cSrcweir 				const Region aPaintRgn( ( (Window*) pOut )->GetPaintRegion() );
514*cdf0e10cSrcweir 				if( !aPaintRgn.IsNull() )
515*cdf0e10cSrcweir 					aOutRect.Intersection( pOut->LogicToPixel( aPaintRgn.GetBoundRect() ) );
516*cdf0e10cSrcweir 			}
517*cdf0e10cSrcweir 
518*cdf0e10cSrcweir 			aOutRect.Intersection( aBmpRect );
519*cdf0e10cSrcweir 
520*cdf0e10cSrcweir 			if( !aOutRect.IsEmpty() )
521*cdf0e10cSrcweir 			{
522*cdf0e10cSrcweir 				aOutPt = pOut->PixelToLogic( aOutRect.TopLeft() );
523*cdf0e10cSrcweir 				aOutSz = pOut->PixelToLogic( aOutRect.GetSize() );
524*cdf0e10cSrcweir 				nStartX = aOutRect.Left() - aBmpRect.Left();
525*cdf0e10cSrcweir 				nStartY = aOutRect.Top() - aBmpRect.Top();
526*cdf0e10cSrcweir 				nEndX = aOutRect.Right() - aBmpRect.Left();
527*cdf0e10cSrcweir 				nEndY = aOutRect.Bottom() - aBmpRect.Top();
528*cdf0e10cSrcweir 			}
529*cdf0e10cSrcweir 			else
530*cdf0e10cSrcweir 				nStartX = -1L; // invalid
531*cdf0e10cSrcweir 		}
532*cdf0e10cSrcweir 		else
533*cdf0e10cSrcweir 		{
534*cdf0e10cSrcweir 			aOutPt = pOut->PixelToLogic( aOutPtPix );
535*cdf0e10cSrcweir 			aOutSz = pOut->PixelToLogic( aOutSzPix );
536*cdf0e10cSrcweir 			nStartX = nStartY = 0;
537*cdf0e10cSrcweir 			nEndX = aOutSzPix.Width() - 1L;
538*cdf0e10cSrcweir 			nEndY = aOutSzPix.Height() - 1L;
539*cdf0e10cSrcweir 		}
540*cdf0e10cSrcweir 
541*cdf0e10cSrcweir 		// do transformation
542*cdf0e10cSrcweir 		if( nStartX >= 0L )
543*cdf0e10cSrcweir 		{
544*cdf0e10cSrcweir 			const sal_Bool bSimple = ( 1 == nW || 1 == nH );
545*cdf0e10cSrcweir 
546*cdf0e10cSrcweir 			if( nRot10 )
547*cdf0e10cSrcweir 			{
548*cdf0e10cSrcweir 				if( bSimple )
549*cdf0e10cSrcweir 				{
550*cdf0e10cSrcweir 					bRet = ( aOutBmpEx = aBmpEx ).Scale( aUnrotatedSzPix );
551*cdf0e10cSrcweir 
552*cdf0e10cSrcweir 					if( bRet )
553*cdf0e10cSrcweir 						aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT );
554*cdf0e10cSrcweir 				}
555*cdf0e10cSrcweir 				else
556*cdf0e10cSrcweir 				{
557*cdf0e10cSrcweir 					bRet = ImplCreateRotatedScaled( aBmpEx,
558*cdf0e10cSrcweir 													nRot10, aOutSzPix, aUnrotatedSzPix,
559*cdf0e10cSrcweir 													pMapIX, pMapFX, pMapIY, pMapFY, nStartX, nEndX, nStartY, nEndY,
560*cdf0e10cSrcweir 													aOutBmpEx );
561*cdf0e10cSrcweir 				}
562*cdf0e10cSrcweir 			}
563*cdf0e10cSrcweir 			else
564*cdf0e10cSrcweir 			{
565*cdf0e10cSrcweir                 // #105229# Don't scale if output size equals bitmap size
566*cdf0e10cSrcweir                 // #107226# Copy through only if we're not mirroring
567*cdf0e10cSrcweir                 if( !bHMirr && !bVMirr && aOutSzPix == rBmpSzPix )
568*cdf0e10cSrcweir                 {
569*cdf0e10cSrcweir                     // #107226# Use original dimensions when just copying through
570*cdf0e10cSrcweir                     aOutPt = pOut->PixelToLogic( aOutPtPix );
571*cdf0e10cSrcweir                     aOutSz = pOut->PixelToLogic( aOutSzPix );
572*cdf0e10cSrcweir                     aOutBmpEx = aBmpEx;
573*cdf0e10cSrcweir                     bRet = sal_True;
574*cdf0e10cSrcweir                 }
575*cdf0e10cSrcweir                 else
576*cdf0e10cSrcweir                 {
577*cdf0e10cSrcweir                     if( bSimple )
578*cdf0e10cSrcweir                         bRet = ( aOutBmpEx = aBmpEx ).Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ) );
579*cdf0e10cSrcweir                     else
580*cdf0e10cSrcweir                     {
581*cdf0e10cSrcweir                         bRet = ImplCreateScaled( aBmpEx,
582*cdf0e10cSrcweir                                                  pMapIX, pMapFX, pMapIY, pMapFY,
583*cdf0e10cSrcweir                                                  nStartX, nEndX, nStartY, nEndY,
584*cdf0e10cSrcweir                                                  aOutBmpEx );
585*cdf0e10cSrcweir                     }
586*cdf0e10cSrcweir                 }
587*cdf0e10cSrcweir 			}
588*cdf0e10cSrcweir 
589*cdf0e10cSrcweir 			if( bRet )
590*cdf0e10cSrcweir 			{
591*cdf0e10cSrcweir 				// attribute adjustment if neccessary
592*cdf0e10cSrcweir 				if( rAttr.IsSpecialDrawMode() || rAttr.IsAdjusted() || rAttr.IsTransparent() )
593*cdf0e10cSrcweir 					ImplAdjust( aOutBmpEx, rAttr, ADJUSTMENT_DRAWMODE | ADJUSTMENT_COLORS | ADJUSTMENT_TRANSPARENCY );
594*cdf0e10cSrcweir 
595*cdf0e10cSrcweir 				// OutDev adjustment if neccessary
596*cdf0e10cSrcweir 				if( pOut->GetOutDevType() != OUTDEV_PRINTER && pOut->GetBitCount() <= 8 && aOutBmpEx.GetBitCount() >= 8 )
597*cdf0e10cSrcweir 					aOutBmpEx.Dither( BMP_DITHER_MATRIX );
598*cdf0e10cSrcweir 			}
599*cdf0e10cSrcweir 		}
600*cdf0e10cSrcweir 
601*cdf0e10cSrcweir 		// delete lookup tables
602*cdf0e10cSrcweir 		delete[] pMapIX;
603*cdf0e10cSrcweir 		delete[] pMapFX;
604*cdf0e10cSrcweir 		delete[] pMapIY;
605*cdf0e10cSrcweir 		delete[] pMapFY;
606*cdf0e10cSrcweir 
607*cdf0e10cSrcweir 		// create output
608*cdf0e10cSrcweir 		if( bRet )
609*cdf0e10cSrcweir 		{
610*cdf0e10cSrcweir 			if( !pBmpEx )
611*cdf0e10cSrcweir 				pOut->DrawBitmapEx( aOutPt, aOutSz, aOutBmpEx );
612*cdf0e10cSrcweir 			else
613*cdf0e10cSrcweir 			{
614*cdf0e10cSrcweir 				if( !rAttr.IsTransparent() && !aOutBmpEx.IsAlpha() )
615*cdf0e10cSrcweir 					aOutBmpEx = BitmapEx( aOutBmpEx.GetBitmap().CreateDisplayBitmap( pOut ), aOutBmpEx.GetMask() );
616*cdf0e10cSrcweir 
617*cdf0e10cSrcweir 				pOut->DrawBitmapEx( aOutPt, aOutSz, *pBmpEx = aOutBmpEx );
618*cdf0e10cSrcweir 			}
619*cdf0e10cSrcweir 		}
620*cdf0e10cSrcweir 	}
621*cdf0e10cSrcweir 
622*cdf0e10cSrcweir 	return bRet;
623*cdf0e10cSrcweir }
624*cdf0e10cSrcweir 
625*cdf0e10cSrcweir // -----------------------------------------------------------------------------
626*cdf0e10cSrcweir 
627*cdf0e10cSrcweir sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
628*cdf0e10cSrcweir 									   const Point& rPt, const Size& rSz,
629*cdf0e10cSrcweir 									   const GDIMetaFile& rMtf, const GraphicAttr& rAttr,
630*cdf0e10cSrcweir 									   const sal_uLong /*nFlags*/, GDIMetaFile& rOutMtf, BitmapEx& rOutBmpEx )
631*cdf0e10cSrcweir {
632*cdf0e10cSrcweir     const Size aNewSize( rMtf.GetPrefSize() );
633*cdf0e10cSrcweir 
634*cdf0e10cSrcweir     rOutMtf = rMtf;
635*cdf0e10cSrcweir 
636*cdf0e10cSrcweir     // #117889# count bitmap actions, and flag actions that paint, but
637*cdf0e10cSrcweir     // are no bitmaps.
638*cdf0e10cSrcweir     sal_Int32   nNumBitmaps(0);
639*cdf0e10cSrcweir     bool        bNonBitmapActionEncountered(false);
640*cdf0e10cSrcweir     if( aNewSize.Width() && aNewSize.Height() && rSz.Width() && rSz.Height() )
641*cdf0e10cSrcweir     {
642*cdf0e10cSrcweir         const double fGrfWH = (double) aNewSize.Width() / aNewSize.Height();
643*cdf0e10cSrcweir         const double fOutWH = (double) rSz.Width() / rSz.Height();
644*cdf0e10cSrcweir 
645*cdf0e10cSrcweir         const double fScaleX = fOutWH / fGrfWH;
646*cdf0e10cSrcweir         const double fScaleY = 1.0;
647*cdf0e10cSrcweir 
648*cdf0e10cSrcweir         const MapMode& rPrefMapMode( rMtf.GetPrefMapMode() );
649*cdf0e10cSrcweir         const Size&    rSizePix( pOut->LogicToPixel( aNewSize,
650*cdf0e10cSrcweir                                                      rPrefMapMode ) );
651*cdf0e10cSrcweir 
652*cdf0e10cSrcweir         // taking care of font width default if scaling metafile.
653*cdf0e10cSrcweir         // #117889# use existing metafile scan, to determine whether
654*cdf0e10cSrcweir         // the metafile basically displays a single bitmap. Note that
655*cdf0e10cSrcweir         // the solution, as implemented here, is quite suboptimal (the
656*cdf0e10cSrcweir         // cases where a mtf consisting basically of a single bitmap,
657*cdf0e10cSrcweir         // that fail to pass the test below, are probably frequent). A
658*cdf0e10cSrcweir         // better solution would involve FSAA, but that's currently
659*cdf0e10cSrcweir         // expensive, and might trigger bugs on display drivers, if
660*cdf0e10cSrcweir         // VDevs get bigger than the actual screen.
661*cdf0e10cSrcweir         sal_uInt32  nCurPos;
662*cdf0e10cSrcweir         MetaAction* pAct;
663*cdf0e10cSrcweir         for( nCurPos = 0, pAct = (MetaAction*)rOutMtf.FirstAction(); pAct;
664*cdf0e10cSrcweir              pAct = (MetaAction*)rOutMtf.NextAction(), nCurPos++ )
665*cdf0e10cSrcweir         {
666*cdf0e10cSrcweir             MetaAction* pModAct = NULL;
667*cdf0e10cSrcweir             switch( pAct->GetType() )
668*cdf0e10cSrcweir             {
669*cdf0e10cSrcweir                 case META_FONT_ACTION:
670*cdf0e10cSrcweir                 {
671*cdf0e10cSrcweir                     MetaFontAction* pA = (MetaFontAction*)pAct;
672*cdf0e10cSrcweir                     Font aFont( pA->GetFont() );
673*cdf0e10cSrcweir                     if ( !aFont.GetWidth() )
674*cdf0e10cSrcweir                     {
675*cdf0e10cSrcweir                         FontMetric aFontMetric( pOut->GetFontMetric( aFont ) );
676*cdf0e10cSrcweir                         aFont.SetWidth( aFontMetric.GetWidth() );
677*cdf0e10cSrcweir                         pModAct = new MetaFontAction( aFont );
678*cdf0e10cSrcweir                     }
679*cdf0e10cSrcweir                 }
680*cdf0e10cSrcweir                     // FALLTHROUGH intended
681*cdf0e10cSrcweir                 case META_NULL_ACTION:
682*cdf0e10cSrcweir                     // FALLTHROUGH intended
683*cdf0e10cSrcweir 
684*cdf0e10cSrcweir                     // OutDev state changes (which don't affect bitmap
685*cdf0e10cSrcweir                     // output)
686*cdf0e10cSrcweir                 case META_LINECOLOR_ACTION:
687*cdf0e10cSrcweir                     // FALLTHROUGH intended
688*cdf0e10cSrcweir                 case META_FILLCOLOR_ACTION:
689*cdf0e10cSrcweir                     // FALLTHROUGH intended
690*cdf0e10cSrcweir                 case META_TEXTCOLOR_ACTION:
691*cdf0e10cSrcweir                     // FALLTHROUGH intended
692*cdf0e10cSrcweir                 case META_TEXTFILLCOLOR_ACTION:
693*cdf0e10cSrcweir                     // FALLTHROUGH intended
694*cdf0e10cSrcweir                 case META_TEXTALIGN_ACTION:
695*cdf0e10cSrcweir                     // FALLTHROUGH intended
696*cdf0e10cSrcweir                 case META_TEXTLINECOLOR_ACTION:
697*cdf0e10cSrcweir                     // FALLTHROUGH intended
698*cdf0e10cSrcweir                 case META_TEXTLINE_ACTION:
699*cdf0e10cSrcweir                     // FALLTHROUGH intended
700*cdf0e10cSrcweir                 case META_PUSH_ACTION:
701*cdf0e10cSrcweir                     // FALLTHROUGH intended
702*cdf0e10cSrcweir                 case META_POP_ACTION:
703*cdf0e10cSrcweir                     // FALLTHROUGH intended
704*cdf0e10cSrcweir                 case META_LAYOUTMODE_ACTION:
705*cdf0e10cSrcweir                     // FALLTHROUGH intended
706*cdf0e10cSrcweir                 case META_TEXTLANGUAGE_ACTION:
707*cdf0e10cSrcweir                     // FALLTHROUGH intended
708*cdf0e10cSrcweir                 case META_COMMENT_ACTION:
709*cdf0e10cSrcweir                     break;
710*cdf0e10cSrcweir 
711*cdf0e10cSrcweir                     // bitmap output methods
712*cdf0e10cSrcweir                 case META_BMP_ACTION:
713*cdf0e10cSrcweir                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
714*cdf0e10cSrcweir                     {
715*cdf0e10cSrcweir                         MetaBmpAction* pAction = (MetaBmpAction*)pAct;
716*cdf0e10cSrcweir 
717*cdf0e10cSrcweir                         rOutBmpEx = BitmapEx( pAction->GetBitmap() );
718*cdf0e10cSrcweir                         muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(),
719*cdf0e10cSrcweir                                                             rPrefMapMode ),
720*cdf0e10cSrcweir                                         pAction->GetBitmap().GetSizePixel(),
721*cdf0e10cSrcweir                                         rSizePix,
722*cdf0e10cSrcweir                                         bNonBitmapActionEncountered );
723*cdf0e10cSrcweir                         ++nNumBitmaps;
724*cdf0e10cSrcweir                     }
725*cdf0e10cSrcweir                     break;
726*cdf0e10cSrcweir 
727*cdf0e10cSrcweir                 case META_BMPSCALE_ACTION:
728*cdf0e10cSrcweir                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
729*cdf0e10cSrcweir                     {
730*cdf0e10cSrcweir                         MetaBmpScaleAction* pAction = (MetaBmpScaleAction*)pAct;
731*cdf0e10cSrcweir 
732*cdf0e10cSrcweir                         rOutBmpEx = BitmapEx( pAction->GetBitmap() );
733*cdf0e10cSrcweir                         muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(),
734*cdf0e10cSrcweir                                                             rPrefMapMode ),
735*cdf0e10cSrcweir                                         pOut->LogicToPixel( pAction->GetSize(),
736*cdf0e10cSrcweir                                                             rPrefMapMode ),
737*cdf0e10cSrcweir                                         rSizePix,
738*cdf0e10cSrcweir                                         bNonBitmapActionEncountered );
739*cdf0e10cSrcweir                         ++nNumBitmaps;
740*cdf0e10cSrcweir                     }
741*cdf0e10cSrcweir                     break;
742*cdf0e10cSrcweir 
743*cdf0e10cSrcweir                 case META_BMPSCALEPART_ACTION:
744*cdf0e10cSrcweir                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
745*cdf0e10cSrcweir                     {
746*cdf0e10cSrcweir                         MetaBmpScalePartAction* pAction = (MetaBmpScalePartAction*)pAct;
747*cdf0e10cSrcweir 
748*cdf0e10cSrcweir                         rOutBmpEx = muckWithBitmap( BitmapEx( pAction->GetBitmap() ),
749*cdf0e10cSrcweir                                                     pAction->GetSrcPoint(),
750*cdf0e10cSrcweir                                                     pAction->GetSrcSize(),
751*cdf0e10cSrcweir                                                     pOut->LogicToPixel( pAction->GetDestPoint(),
752*cdf0e10cSrcweir                                                                         rPrefMapMode ),
753*cdf0e10cSrcweir                                                     pOut->LogicToPixel( pAction->GetDestSize(),
754*cdf0e10cSrcweir                                                                         rPrefMapMode ),
755*cdf0e10cSrcweir                                                     rSizePix,
756*cdf0e10cSrcweir                                                     bNonBitmapActionEncountered );
757*cdf0e10cSrcweir                         ++nNumBitmaps;
758*cdf0e10cSrcweir                     }
759*cdf0e10cSrcweir                     break;
760*cdf0e10cSrcweir 
761*cdf0e10cSrcweir                 case META_BMPEX_ACTION:
762*cdf0e10cSrcweir                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
763*cdf0e10cSrcweir                     {
764*cdf0e10cSrcweir                         MetaBmpExAction* pAction = (MetaBmpExAction*)pAct;
765*cdf0e10cSrcweir 
766*cdf0e10cSrcweir                         rOutBmpEx = pAction->GetBitmapEx();
767*cdf0e10cSrcweir                         muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(),
768*cdf0e10cSrcweir                                                             rPrefMapMode ),
769*cdf0e10cSrcweir                                         pAction->GetBitmapEx().GetSizePixel(),
770*cdf0e10cSrcweir                                         rSizePix,
771*cdf0e10cSrcweir                                         bNonBitmapActionEncountered );
772*cdf0e10cSrcweir                         ++nNumBitmaps;
773*cdf0e10cSrcweir                     }
774*cdf0e10cSrcweir                     break;
775*cdf0e10cSrcweir 
776*cdf0e10cSrcweir                 case META_BMPEXSCALE_ACTION:
777*cdf0e10cSrcweir                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
778*cdf0e10cSrcweir                     {
779*cdf0e10cSrcweir                         MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*)pAct;
780*cdf0e10cSrcweir 
781*cdf0e10cSrcweir                         rOutBmpEx = pAction->GetBitmapEx();
782*cdf0e10cSrcweir                         muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(),
783*cdf0e10cSrcweir                                                             rPrefMapMode ),
784*cdf0e10cSrcweir                                         pOut->LogicToPixel( pAction->GetSize(),
785*cdf0e10cSrcweir                                                             rPrefMapMode ),
786*cdf0e10cSrcweir                                         rSizePix,
787*cdf0e10cSrcweir                                         bNonBitmapActionEncountered );
788*cdf0e10cSrcweir                         ++nNumBitmaps;
789*cdf0e10cSrcweir                     }
790*cdf0e10cSrcweir                     break;
791*cdf0e10cSrcweir 
792*cdf0e10cSrcweir                 case META_BMPEXSCALEPART_ACTION:
793*cdf0e10cSrcweir                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
794*cdf0e10cSrcweir                     {
795*cdf0e10cSrcweir                         MetaBmpExScalePartAction* pAction = (MetaBmpExScalePartAction*)pAct;
796*cdf0e10cSrcweir 
797*cdf0e10cSrcweir                         rOutBmpEx = muckWithBitmap( pAction->GetBitmapEx(),
798*cdf0e10cSrcweir                                                     pAction->GetSrcPoint(),
799*cdf0e10cSrcweir                                                     pAction->GetSrcSize(),
800*cdf0e10cSrcweir                                                     pOut->LogicToPixel( pAction->GetDestPoint(),
801*cdf0e10cSrcweir                                                                         rPrefMapMode ),
802*cdf0e10cSrcweir                                                     pOut->LogicToPixel( pAction->GetDestSize(),
803*cdf0e10cSrcweir                                                                         rPrefMapMode ),
804*cdf0e10cSrcweir                                                     rSizePix,
805*cdf0e10cSrcweir                                                     bNonBitmapActionEncountered );
806*cdf0e10cSrcweir                         ++nNumBitmaps;
807*cdf0e10cSrcweir                     }
808*cdf0e10cSrcweir                     break;
809*cdf0e10cSrcweir 
810*cdf0e10cSrcweir                     // these actions actually output something (that's
811*cdf0e10cSrcweir                     // different from a bitmap)
812*cdf0e10cSrcweir                 case META_RASTEROP_ACTION:
813*cdf0e10cSrcweir                     if( ((MetaRasterOpAction*)pAct)->GetRasterOp() == ROP_OVERPAINT )
814*cdf0e10cSrcweir                         break;
815*cdf0e10cSrcweir                     // FALLTHROUGH intended
816*cdf0e10cSrcweir                 case META_PIXEL_ACTION:
817*cdf0e10cSrcweir                     // FALLTHROUGH intended
818*cdf0e10cSrcweir                 case META_POINT_ACTION:
819*cdf0e10cSrcweir                     // FALLTHROUGH intended
820*cdf0e10cSrcweir                 case META_LINE_ACTION:
821*cdf0e10cSrcweir                     // FALLTHROUGH intended
822*cdf0e10cSrcweir                 case META_RECT_ACTION:
823*cdf0e10cSrcweir                     // FALLTHROUGH intended
824*cdf0e10cSrcweir                 case META_ROUNDRECT_ACTION:
825*cdf0e10cSrcweir                     // FALLTHROUGH intended
826*cdf0e10cSrcweir                 case META_ELLIPSE_ACTION:
827*cdf0e10cSrcweir                     // FALLTHROUGH intended
828*cdf0e10cSrcweir                 case META_ARC_ACTION:
829*cdf0e10cSrcweir                     // FALLTHROUGH intended
830*cdf0e10cSrcweir                 case META_PIE_ACTION:
831*cdf0e10cSrcweir                     // FALLTHROUGH intended
832*cdf0e10cSrcweir                 case META_CHORD_ACTION:
833*cdf0e10cSrcweir                     // FALLTHROUGH intended
834*cdf0e10cSrcweir                 case META_POLYLINE_ACTION:
835*cdf0e10cSrcweir                     // FALLTHROUGH intended
836*cdf0e10cSrcweir                 case META_POLYGON_ACTION:
837*cdf0e10cSrcweir                     // FALLTHROUGH intended
838*cdf0e10cSrcweir                 case META_POLYPOLYGON_ACTION:
839*cdf0e10cSrcweir                     // FALLTHROUGH intended
840*cdf0e10cSrcweir 
841*cdf0e10cSrcweir                 case META_TEXT_ACTION:
842*cdf0e10cSrcweir                     // FALLTHROUGH intended
843*cdf0e10cSrcweir                 case META_TEXTARRAY_ACTION:
844*cdf0e10cSrcweir                     // FALLTHROUGH intended
845*cdf0e10cSrcweir                 case META_STRETCHTEXT_ACTION:
846*cdf0e10cSrcweir                     // FALLTHROUGH intended
847*cdf0e10cSrcweir                 case META_TEXTRECT_ACTION:
848*cdf0e10cSrcweir                     // FALLTHROUGH intended
849*cdf0e10cSrcweir 
850*cdf0e10cSrcweir                 case META_MASK_ACTION:
851*cdf0e10cSrcweir                     // FALLTHROUGH intended
852*cdf0e10cSrcweir                 case META_MASKSCALE_ACTION:
853*cdf0e10cSrcweir                     // FALLTHROUGH intended
854*cdf0e10cSrcweir                 case META_MASKSCALEPART_ACTION:
855*cdf0e10cSrcweir                     // FALLTHROUGH intended
856*cdf0e10cSrcweir 
857*cdf0e10cSrcweir                 case META_GRADIENT_ACTION:
858*cdf0e10cSrcweir                     // FALLTHROUGH intended
859*cdf0e10cSrcweir                 case META_HATCH_ACTION:
860*cdf0e10cSrcweir                     // FALLTHROUGH intended
861*cdf0e10cSrcweir                 case META_WALLPAPER_ACTION:
862*cdf0e10cSrcweir                     // FALLTHROUGH intended
863*cdf0e10cSrcweir 
864*cdf0e10cSrcweir                 case META_TRANSPARENT_ACTION:
865*cdf0e10cSrcweir                     // FALLTHROUGH intended
866*cdf0e10cSrcweir                 case META_EPS_ACTION:
867*cdf0e10cSrcweir                     // FALLTHROUGH intended
868*cdf0e10cSrcweir                 case META_FLOATTRANSPARENT_ACTION:
869*cdf0e10cSrcweir                     // FALLTHROUGH intended
870*cdf0e10cSrcweir                 case META_GRADIENTEX_ACTION:
871*cdf0e10cSrcweir                     // FALLTHROUGH intended
872*cdf0e10cSrcweir                 case META_RENDERGRAPHIC_ACTION:
873*cdf0e10cSrcweir                     // FALLTHROUGH intended
874*cdf0e10cSrcweir 
875*cdf0e10cSrcweir                     // OutDev state changes that _do_ affect bitmap
876*cdf0e10cSrcweir                     // output
877*cdf0e10cSrcweir                 case META_CLIPREGION_ACTION:
878*cdf0e10cSrcweir                     // FALLTHROUGH intended
879*cdf0e10cSrcweir                 case META_ISECTRECTCLIPREGION_ACTION:
880*cdf0e10cSrcweir                     // FALLTHROUGH intended
881*cdf0e10cSrcweir                 case META_ISECTREGIONCLIPREGION_ACTION:
882*cdf0e10cSrcweir                     // FALLTHROUGH intended
883*cdf0e10cSrcweir                 case META_MOVECLIPREGION_ACTION:
884*cdf0e10cSrcweir                     // FALLTHROUGH intended
885*cdf0e10cSrcweir 
886*cdf0e10cSrcweir                 case META_MAPMODE_ACTION:
887*cdf0e10cSrcweir                     // FALLTHROUGH intended
888*cdf0e10cSrcweir                 case META_REFPOINT_ACTION:
889*cdf0e10cSrcweir                     // FALLTHROUGH intended
890*cdf0e10cSrcweir                 default:
891*cdf0e10cSrcweir                     bNonBitmapActionEncountered = true;
892*cdf0e10cSrcweir                     break;
893*cdf0e10cSrcweir             }
894*cdf0e10cSrcweir             if ( pModAct )
895*cdf0e10cSrcweir             {
896*cdf0e10cSrcweir                 rOutMtf.ReplaceAction( pModAct, nCurPos );
897*cdf0e10cSrcweir                 pAct->Delete();
898*cdf0e10cSrcweir             }
899*cdf0e10cSrcweir             else
900*cdf0e10cSrcweir             {
901*cdf0e10cSrcweir                 if( pAct->GetRefCount() > 1 )
902*cdf0e10cSrcweir                 {
903*cdf0e10cSrcweir                     rOutMtf.ReplaceAction( pModAct = pAct->Clone(), nCurPos );
904*cdf0e10cSrcweir                     pAct->Delete();
905*cdf0e10cSrcweir                 }
906*cdf0e10cSrcweir                 else
907*cdf0e10cSrcweir                     pModAct = pAct;
908*cdf0e10cSrcweir             }
909*cdf0e10cSrcweir             pModAct->Scale( fScaleX, fScaleY );
910*cdf0e10cSrcweir         }
911*cdf0e10cSrcweir         rOutMtf.SetPrefSize( Size( FRound( aNewSize.Width() * fScaleX ),
912*cdf0e10cSrcweir                                    FRound( aNewSize.Height() * fScaleY ) ) );
913*cdf0e10cSrcweir     }
914*cdf0e10cSrcweir 
915*cdf0e10cSrcweir     if( nNumBitmaps != 1 || bNonBitmapActionEncountered )
916*cdf0e10cSrcweir     {
917*cdf0e10cSrcweir         if( rAttr.IsSpecialDrawMode() || rAttr.IsAdjusted() || rAttr.IsMirrored() || rAttr.IsRotated() || rAttr.IsTransparent() )
918*cdf0e10cSrcweir             ImplAdjust( rOutMtf, rAttr, ADJUSTMENT_ALL );
919*cdf0e10cSrcweir 
920*cdf0e10cSrcweir         ImplDraw( pOut, rPt, rSz, rOutMtf, rAttr );
921*cdf0e10cSrcweir         rOutBmpEx = BitmapEx();
922*cdf0e10cSrcweir     }
923*cdf0e10cSrcweir 
924*cdf0e10cSrcweir     return sal_True;
925*cdf0e10cSrcweir }
926*cdf0e10cSrcweir 
927*cdf0e10cSrcweir // -----------------------------------------------------------------------------
928*cdf0e10cSrcweir 
929*cdf0e10cSrcweir sal_Bool GraphicManager::ImplCreateScaled( const BitmapEx& rBmpEx,
930*cdf0e10cSrcweir 									   long* pMapIX, long* pMapFX, long* pMapIY, long* pMapFY,
931*cdf0e10cSrcweir 									   long nStartX, long nEndX, long nStartY, long nEndY,
932*cdf0e10cSrcweir 									   BitmapEx& rOutBmpEx )
933*cdf0e10cSrcweir {
934*cdf0e10cSrcweir 	Bitmap				aBmp( rBmpEx.GetBitmap() );
935*cdf0e10cSrcweir 	Bitmap				aOutBmp;
936*cdf0e10cSrcweir 	BitmapReadAccess*	pAcc = aBmp.AcquireReadAccess();
937*cdf0e10cSrcweir 	BitmapWriteAccess*	pWAcc;
938*cdf0e10cSrcweir 	BitmapColor			aCol0, aCol1, aColRes;
939*cdf0e10cSrcweir 	const long			nDstW = nEndX - nStartX + 1L;
940*cdf0e10cSrcweir 	const long			nDstH = nEndY - nStartY + 1L;
941*cdf0e10cSrcweir 	long				nX, nY, nTmpX, nTmpY, nTmpFX, nTmpFY;
942*cdf0e10cSrcweir 	long				nXDst, nYDst;
943*cdf0e10cSrcweir 	sal_uInt8				cR0, cG0, cB0, cR1, cG1, cB1;
944*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
945*cdf0e10cSrcweir 
946*cdf0e10cSrcweir     DBG_ASSERT( aBmp.GetSizePixel() == rBmpEx.GetSizePixel(),
947*cdf0e10cSrcweir                 "GraphicManager::ImplCreateScaled(): bmp size inconsistent" );
948*cdf0e10cSrcweir 
949*cdf0e10cSrcweir 	if( pAcc )
950*cdf0e10cSrcweir 	{
951*cdf0e10cSrcweir 		aOutBmp = Bitmap( Size( nDstW, nDstH ), 24 );
952*cdf0e10cSrcweir 		pWAcc = aOutBmp.AcquireWriteAccess();
953*cdf0e10cSrcweir 
954*cdf0e10cSrcweir 		if( pWAcc )
955*cdf0e10cSrcweir 		{
956*cdf0e10cSrcweir 			if( pAcc->HasPalette() )
957*cdf0e10cSrcweir 			{
958*cdf0e10cSrcweir 				if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
959*cdf0e10cSrcweir 				{
960*cdf0e10cSrcweir 					Scanline pLine0, pLine1;
961*cdf0e10cSrcweir 
962*cdf0e10cSrcweir 					for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
963*cdf0e10cSrcweir 					{
964*cdf0e10cSrcweir 						nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ];
965*cdf0e10cSrcweir 						pLine0 = pAcc->GetScanline( nTmpY );
966*cdf0e10cSrcweir 						pLine1 = pAcc->GetScanline( ++nTmpY );
967*cdf0e10cSrcweir 
968*cdf0e10cSrcweir 						for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
969*cdf0e10cSrcweir 						{
970*cdf0e10cSrcweir 							nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ];
971*cdf0e10cSrcweir 
972*cdf0e10cSrcweir 							const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTmpX ] );
973*cdf0e10cSrcweir 							const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTmpX ] );
974*cdf0e10cSrcweir 							const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTmpX ] );
975*cdf0e10cSrcweir 							const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTmpX ] );
976*cdf0e10cSrcweir 
977*cdf0e10cSrcweir 							cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTmpFX );
978*cdf0e10cSrcweir 							cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTmpFX );
979*cdf0e10cSrcweir 							cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTmpFX );
980*cdf0e10cSrcweir 
981*cdf0e10cSrcweir 							cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTmpFX );
982*cdf0e10cSrcweir 							cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTmpFX );
983*cdf0e10cSrcweir 							cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTmpFX );
984*cdf0e10cSrcweir 
985*cdf0e10cSrcweir 							aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) );
986*cdf0e10cSrcweir 							aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) );
987*cdf0e10cSrcweir 							aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) );
988*cdf0e10cSrcweir 							pWAcc->SetPixel( nYDst, nXDst++, aColRes );
989*cdf0e10cSrcweir 						}
990*cdf0e10cSrcweir 					}
991*cdf0e10cSrcweir 				}
992*cdf0e10cSrcweir 				else
993*cdf0e10cSrcweir 				{
994*cdf0e10cSrcweir 					for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
995*cdf0e10cSrcweir 					{
996*cdf0e10cSrcweir 						nTmpY = pMapIY[ nY ], nTmpFY = pMapFY[ nY ];
997*cdf0e10cSrcweir 
998*cdf0e10cSrcweir 						for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
999*cdf0e10cSrcweir 						{
1000*cdf0e10cSrcweir 							nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ];
1001*cdf0e10cSrcweir 
1002*cdf0e10cSrcweir 							aCol0 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, nTmpX ) );
1003*cdf0e10cSrcweir 							aCol1 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, ++nTmpX ) );
1004*cdf0e10cSrcweir 							cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX );
1005*cdf0e10cSrcweir 							cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX );
1006*cdf0e10cSrcweir 							cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX );
1007*cdf0e10cSrcweir 
1008*cdf0e10cSrcweir 							aCol1 = pAcc->GetPaletteColor( pAcc->GetPixel( ++nTmpY, nTmpX ) );
1009*cdf0e10cSrcweir 							aCol0 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY--, --nTmpX ) );
1010*cdf0e10cSrcweir 							cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX );
1011*cdf0e10cSrcweir 							cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX );
1012*cdf0e10cSrcweir 							cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX );
1013*cdf0e10cSrcweir 
1014*cdf0e10cSrcweir 							aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) );
1015*cdf0e10cSrcweir 							aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) );
1016*cdf0e10cSrcweir 							aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) );
1017*cdf0e10cSrcweir 							pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1018*cdf0e10cSrcweir 						}
1019*cdf0e10cSrcweir 					}
1020*cdf0e10cSrcweir 				}
1021*cdf0e10cSrcweir 			}
1022*cdf0e10cSrcweir 			else
1023*cdf0e10cSrcweir 			{
1024*cdf0e10cSrcweir 				if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
1025*cdf0e10cSrcweir 				{
1026*cdf0e10cSrcweir 					Scanline	pLine0, pLine1, pTmp0, pTmp1;
1027*cdf0e10cSrcweir 					long		nOff;
1028*cdf0e10cSrcweir 
1029*cdf0e10cSrcweir 					for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1030*cdf0e10cSrcweir 					{
1031*cdf0e10cSrcweir 						nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ];
1032*cdf0e10cSrcweir 						pLine0 = pAcc->GetScanline( nTmpY );
1033*cdf0e10cSrcweir 						pLine1 = pAcc->GetScanline( ++nTmpY );
1034*cdf0e10cSrcweir 
1035*cdf0e10cSrcweir 						for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1036*cdf0e10cSrcweir 						{
1037*cdf0e10cSrcweir 							nOff = 3L * ( nTmpX = pMapIX[ nX ] );
1038*cdf0e10cSrcweir 							nTmpFX = pMapFX[ nX ];
1039*cdf0e10cSrcweir 
1040*cdf0e10cSrcweir 							pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
1041*cdf0e10cSrcweir 							cB0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++;
1042*cdf0e10cSrcweir 							cG0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++;
1043*cdf0e10cSrcweir 							cR0 = MAP( *pTmp0, *pTmp1, nTmpFX );
1044*cdf0e10cSrcweir 
1045*cdf0e10cSrcweir 							pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
1046*cdf0e10cSrcweir 							cB1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++;
1047*cdf0e10cSrcweir 							cG1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++;
1048*cdf0e10cSrcweir 							cR1 = MAP( *pTmp0, *pTmp1, nTmpFX );
1049*cdf0e10cSrcweir 
1050*cdf0e10cSrcweir 							aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) );
1051*cdf0e10cSrcweir 							aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) );
1052*cdf0e10cSrcweir 							aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) );
1053*cdf0e10cSrcweir 							pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1054*cdf0e10cSrcweir 						}
1055*cdf0e10cSrcweir 					}
1056*cdf0e10cSrcweir 				}
1057*cdf0e10cSrcweir 				else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
1058*cdf0e10cSrcweir 				{
1059*cdf0e10cSrcweir 					Scanline	pLine0, pLine1, pTmp0, pTmp1;
1060*cdf0e10cSrcweir 					long		nOff;
1061*cdf0e10cSrcweir 
1062*cdf0e10cSrcweir 					for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1063*cdf0e10cSrcweir 					{
1064*cdf0e10cSrcweir 						nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ];
1065*cdf0e10cSrcweir 						pLine0 = pAcc->GetScanline( nTmpY );
1066*cdf0e10cSrcweir 						pLine1 = pAcc->GetScanline( ++nTmpY );
1067*cdf0e10cSrcweir 
1068*cdf0e10cSrcweir 						for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1069*cdf0e10cSrcweir 						{
1070*cdf0e10cSrcweir 							nOff = 3L * ( nTmpX = pMapIX[ nX ] );
1071*cdf0e10cSrcweir 							nTmpFX = pMapFX[ nX ];
1072*cdf0e10cSrcweir 
1073*cdf0e10cSrcweir 							pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
1074*cdf0e10cSrcweir 							cR0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++;
1075*cdf0e10cSrcweir 							cG0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++;
1076*cdf0e10cSrcweir 							cB0 = MAP( *pTmp0, *pTmp1, nTmpFX );
1077*cdf0e10cSrcweir 
1078*cdf0e10cSrcweir 							pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
1079*cdf0e10cSrcweir 							cR1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++;
1080*cdf0e10cSrcweir 							cG1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++;
1081*cdf0e10cSrcweir 							cB1 = MAP( *pTmp0, *pTmp1, nTmpFX );
1082*cdf0e10cSrcweir 
1083*cdf0e10cSrcweir 							aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) );
1084*cdf0e10cSrcweir 							aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) );
1085*cdf0e10cSrcweir 							aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) );
1086*cdf0e10cSrcweir 							pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1087*cdf0e10cSrcweir 						}
1088*cdf0e10cSrcweir 					}
1089*cdf0e10cSrcweir 				}
1090*cdf0e10cSrcweir 				else
1091*cdf0e10cSrcweir 				{
1092*cdf0e10cSrcweir 					for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1093*cdf0e10cSrcweir 					{
1094*cdf0e10cSrcweir 						nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ];
1095*cdf0e10cSrcweir 
1096*cdf0e10cSrcweir 						for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1097*cdf0e10cSrcweir 						{
1098*cdf0e10cSrcweir 							nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ];
1099*cdf0e10cSrcweir 
1100*cdf0e10cSrcweir 							aCol0 = pAcc->GetPixel( nTmpY, nTmpX );
1101*cdf0e10cSrcweir 							aCol1 = pAcc->GetPixel( nTmpY, ++nTmpX );
1102*cdf0e10cSrcweir 							cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX );
1103*cdf0e10cSrcweir 							cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX );
1104*cdf0e10cSrcweir 							cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX );
1105*cdf0e10cSrcweir 
1106*cdf0e10cSrcweir 							aCol1 = pAcc->GetPixel( ++nTmpY, nTmpX );
1107*cdf0e10cSrcweir 							aCol0 = pAcc->GetPixel( nTmpY--, --nTmpX );
1108*cdf0e10cSrcweir 							cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX );
1109*cdf0e10cSrcweir 							cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX );
1110*cdf0e10cSrcweir 							cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX );
1111*cdf0e10cSrcweir 
1112*cdf0e10cSrcweir 							aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) );
1113*cdf0e10cSrcweir 							aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) );
1114*cdf0e10cSrcweir 							aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) );
1115*cdf0e10cSrcweir 							pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1116*cdf0e10cSrcweir 						}
1117*cdf0e10cSrcweir 					}
1118*cdf0e10cSrcweir 				}
1119*cdf0e10cSrcweir 			}
1120*cdf0e10cSrcweir 
1121*cdf0e10cSrcweir 			aOutBmp.ReleaseAccess( pWAcc );
1122*cdf0e10cSrcweir 			bRet = sal_True;
1123*cdf0e10cSrcweir 		}
1124*cdf0e10cSrcweir 
1125*cdf0e10cSrcweir 		aBmp.ReleaseAccess( pAcc );
1126*cdf0e10cSrcweir 	}
1127*cdf0e10cSrcweir 
1128*cdf0e10cSrcweir 	if( bRet && rBmpEx.IsTransparent() )
1129*cdf0e10cSrcweir 	{
1130*cdf0e10cSrcweir 		bRet = sal_False;
1131*cdf0e10cSrcweir 
1132*cdf0e10cSrcweir 		if( rBmpEx.IsAlpha() )
1133*cdf0e10cSrcweir 		{
1134*cdf0e10cSrcweir             DBG_ASSERT( rBmpEx.GetAlpha().GetSizePixel() == rBmpEx.GetSizePixel(),
1135*cdf0e10cSrcweir                         "GraphicManager::ImplCreateScaled(): alpha mask size inconsistent" );
1136*cdf0e10cSrcweir 
1137*cdf0e10cSrcweir 			AlphaMask	aAlpha( rBmpEx.GetAlpha() );
1138*cdf0e10cSrcweir 			AlphaMask	aOutAlpha;
1139*cdf0e10cSrcweir 
1140*cdf0e10cSrcweir 			pAcc = aAlpha.AcquireReadAccess();
1141*cdf0e10cSrcweir 
1142*cdf0e10cSrcweir 			if( pAcc )
1143*cdf0e10cSrcweir 			{
1144*cdf0e10cSrcweir 				aOutAlpha = AlphaMask( Size( nDstW, nDstH ) );
1145*cdf0e10cSrcweir 				pWAcc = aOutAlpha.AcquireWriteAccess();
1146*cdf0e10cSrcweir 
1147*cdf0e10cSrcweir 				if( pWAcc )
1148*cdf0e10cSrcweir 				{
1149*cdf0e10cSrcweir 					if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL &&
1150*cdf0e10cSrcweir 						pWAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
1151*cdf0e10cSrcweir 					{
1152*cdf0e10cSrcweir 						Scanline pLine0, pLine1, pLineW;
1153*cdf0e10cSrcweir 
1154*cdf0e10cSrcweir 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1155*cdf0e10cSrcweir 						{
1156*cdf0e10cSrcweir 							nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ];
1157*cdf0e10cSrcweir 							pLine0 = pAcc->GetScanline( nTmpY );
1158*cdf0e10cSrcweir 							pLine1 = pAcc->GetScanline( ++nTmpY );
1159*cdf0e10cSrcweir 							pLineW = pWAcc->GetScanline( nYDst );
1160*cdf0e10cSrcweir 
1161*cdf0e10cSrcweir 							for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++, nXDst++ )
1162*cdf0e10cSrcweir 							{
1163*cdf0e10cSrcweir 								nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ];
1164*cdf0e10cSrcweir 
1165*cdf0e10cSrcweir 								const long	nAlpha0 = pLine0[ nTmpX ];
1166*cdf0e10cSrcweir 								const long	nAlpha2 = pLine1[ nTmpX ];
1167*cdf0e10cSrcweir 								const long	nAlpha1 = pLine0[ ++nTmpX ];
1168*cdf0e10cSrcweir 								const long	nAlpha3 = pLine1[ nTmpX ];
1169*cdf0e10cSrcweir 								const long	n0 = MAP( nAlpha0, nAlpha1, nTmpFX );
1170*cdf0e10cSrcweir 								const long	n1 = MAP( nAlpha2, nAlpha3, nTmpFX );
1171*cdf0e10cSrcweir 
1172*cdf0e10cSrcweir 								*pLineW++ = MAP( n0, n1, nTmpFY );
1173*cdf0e10cSrcweir 							}
1174*cdf0e10cSrcweir 						}
1175*cdf0e10cSrcweir 					}
1176*cdf0e10cSrcweir 					else
1177*cdf0e10cSrcweir 					{
1178*cdf0e10cSrcweir 						BitmapColor aAlphaValue( 0 );
1179*cdf0e10cSrcweir 
1180*cdf0e10cSrcweir 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1181*cdf0e10cSrcweir 						{
1182*cdf0e10cSrcweir 							nTmpY = pMapIY[ nY ], nTmpFY = pMapFY[ nY ];
1183*cdf0e10cSrcweir 
1184*cdf0e10cSrcweir 							for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1185*cdf0e10cSrcweir 							{
1186*cdf0e10cSrcweir 								nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ];
1187*cdf0e10cSrcweir 
1188*cdf0e10cSrcweir 								long		nAlpha0 = pAcc->GetPixel( nTmpY, nTmpX ).GetIndex();
1189*cdf0e10cSrcweir 								long		nAlpha1 = pAcc->GetPixel( nTmpY, ++nTmpX ).GetIndex();
1190*cdf0e10cSrcweir 								const long	n0 = MAP( nAlpha0, nAlpha1, nTmpFX );
1191*cdf0e10cSrcweir 
1192*cdf0e10cSrcweir 								nAlpha1 = pAcc->GetPixel( ++nTmpY, nTmpX ).GetIndex();
1193*cdf0e10cSrcweir 								nAlpha0 = pAcc->GetPixel( nTmpY--, --nTmpX ).GetIndex();
1194*cdf0e10cSrcweir 								const long	n1 = MAP( nAlpha0, nAlpha1, nTmpFX );
1195*cdf0e10cSrcweir 
1196*cdf0e10cSrcweir 								aAlphaValue.SetIndex( MAP( n0, n1, nTmpFY ) );
1197*cdf0e10cSrcweir 								pWAcc->SetPixel( nYDst, nXDst++, aAlphaValue );
1198*cdf0e10cSrcweir 							}
1199*cdf0e10cSrcweir 						}
1200*cdf0e10cSrcweir 					}
1201*cdf0e10cSrcweir 
1202*cdf0e10cSrcweir 					aOutAlpha.ReleaseAccess( pWAcc );
1203*cdf0e10cSrcweir 					bRet = sal_True;
1204*cdf0e10cSrcweir 				}
1205*cdf0e10cSrcweir 
1206*cdf0e10cSrcweir 				aAlpha.ReleaseAccess( pAcc );
1207*cdf0e10cSrcweir 
1208*cdf0e10cSrcweir 				if( bRet )
1209*cdf0e10cSrcweir 					rOutBmpEx = BitmapEx( aOutBmp, aOutAlpha );
1210*cdf0e10cSrcweir 			}
1211*cdf0e10cSrcweir 		}
1212*cdf0e10cSrcweir 		else
1213*cdf0e10cSrcweir 		{
1214*cdf0e10cSrcweir             DBG_ASSERT( rBmpEx.GetMask().GetSizePixel() == rBmpEx.GetSizePixel(),
1215*cdf0e10cSrcweir                         "GraphicManager::ImplCreateScaled(): mask size inconsistent" );
1216*cdf0e10cSrcweir 
1217*cdf0e10cSrcweir 			Bitmap	aMsk( rBmpEx.GetMask() );
1218*cdf0e10cSrcweir 			Bitmap	aOutMsk;
1219*cdf0e10cSrcweir 
1220*cdf0e10cSrcweir 			pAcc = aMsk.AcquireReadAccess();
1221*cdf0e10cSrcweir 
1222*cdf0e10cSrcweir 			if( pAcc )
1223*cdf0e10cSrcweir 			{
1224*cdf0e10cSrcweir                 // #i40115# Use the same palette for destination
1225*cdf0e10cSrcweir                 // bitmap. Otherwise, we'd have to color-map even the
1226*cdf0e10cSrcweir                 // case below, when both masks are one bit deep.
1227*cdf0e10cSrcweir                 if( pAcc->HasPalette() )
1228*cdf0e10cSrcweir                     aOutMsk = Bitmap( Size( nDstW, nDstH ),
1229*cdf0e10cSrcweir                                       1,
1230*cdf0e10cSrcweir                                       &pAcc->GetPalette() );
1231*cdf0e10cSrcweir                 else
1232*cdf0e10cSrcweir                     aOutMsk = Bitmap( Size( nDstW, nDstH ), 1 );
1233*cdf0e10cSrcweir 
1234*cdf0e10cSrcweir 				pWAcc = aOutMsk.AcquireWriteAccess();
1235*cdf0e10cSrcweir 
1236*cdf0e10cSrcweir 				if( pWAcc )
1237*cdf0e10cSrcweir 				{
1238*cdf0e10cSrcweir 					long* pMapLX = new long[ nDstW ];
1239*cdf0e10cSrcweir 					long* pMapLY = new long[ nDstH ];
1240*cdf0e10cSrcweir 
1241*cdf0e10cSrcweir 					// create new horizontal mapping table
1242*cdf0e10cSrcweir 					for( nX = 0UL, nTmpX = nStartX; nX < nDstW; nTmpX++ )
1243*cdf0e10cSrcweir 						pMapLX[ nX++ ] = FRound( (double) pMapIX[ nTmpX ] + pMapFX[ nTmpX ] / 1048576. );
1244*cdf0e10cSrcweir 
1245*cdf0e10cSrcweir 					// create new vertical mapping table
1246*cdf0e10cSrcweir 					for( nY = 0UL, nTmpY = nStartY; nY < nDstH; nTmpY++ )
1247*cdf0e10cSrcweir 						pMapLY[ nY++ ] = FRound( (double) pMapIY[ nTmpY ] + pMapFY[ nTmpY ] / 1048576. );
1248*cdf0e10cSrcweir 
1249*cdf0e10cSrcweir 					// do normal scaling
1250*cdf0e10cSrcweir 					if( pAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
1251*cdf0e10cSrcweir 						pWAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL )
1252*cdf0e10cSrcweir 					{
1253*cdf0e10cSrcweir 						// optimized
1254*cdf0e10cSrcweir 						for( nY = 0; nY < nDstH; nY++ )
1255*cdf0e10cSrcweir 						{
1256*cdf0e10cSrcweir 							Scanline pSrc = pAcc->GetScanline( pMapLY[ nY ] );
1257*cdf0e10cSrcweir 							Scanline pDst = pWAcc->GetScanline( nY );
1258*cdf0e10cSrcweir 
1259*cdf0e10cSrcweir 							for( nX = 0L; nX < nDstW; nX++ )
1260*cdf0e10cSrcweir 							{
1261*cdf0e10cSrcweir 								const long nSrcX = pMapLX[ nX ];
1262*cdf0e10cSrcweir 
1263*cdf0e10cSrcweir 								if( pSrc[ nSrcX >> 3 ] & ( 1 << ( 7 - ( nSrcX & 7 ) ) ) )
1264*cdf0e10cSrcweir 									pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
1265*cdf0e10cSrcweir 								else
1266*cdf0e10cSrcweir 									pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
1267*cdf0e10cSrcweir 							}
1268*cdf0e10cSrcweir 						}
1269*cdf0e10cSrcweir 					}
1270*cdf0e10cSrcweir 					else
1271*cdf0e10cSrcweir 					{
1272*cdf0e10cSrcweir 						const BitmapColor aB( pAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
1273*cdf0e10cSrcweir 						const BitmapColor aWB( pWAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
1274*cdf0e10cSrcweir 						const BitmapColor aWW( pWAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1275*cdf0e10cSrcweir 
1276*cdf0e10cSrcweir 						if( pAcc->HasPalette() )
1277*cdf0e10cSrcweir 						{
1278*cdf0e10cSrcweir 							for( nY = 0L; nY < nDstH; nY++ )
1279*cdf0e10cSrcweir 							{
1280*cdf0e10cSrcweir 								for( nX = 0L; nX < nDstW; nX++ )
1281*cdf0e10cSrcweir 								{
1282*cdf0e10cSrcweir 									if( pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( pMapLY[ nY ], pMapLX[ nX ] ) ) == aB )
1283*cdf0e10cSrcweir 										pWAcc->SetPixel( nY, nX, aWB );
1284*cdf0e10cSrcweir 									else
1285*cdf0e10cSrcweir 										pWAcc->SetPixel( nY, nX, aWW );
1286*cdf0e10cSrcweir 								}
1287*cdf0e10cSrcweir 							}
1288*cdf0e10cSrcweir 						}
1289*cdf0e10cSrcweir 						else
1290*cdf0e10cSrcweir 						{
1291*cdf0e10cSrcweir 							for( nY = 0L; nY < nDstH; nY++ )
1292*cdf0e10cSrcweir 							{
1293*cdf0e10cSrcweir 								for( nX = 0L; nX < nDstW; nX++ )
1294*cdf0e10cSrcweir 								{
1295*cdf0e10cSrcweir 									if( pAcc->GetPixel( pMapLY[ nY ], pMapLX[ nX ] ) == aB )
1296*cdf0e10cSrcweir 										pWAcc->SetPixel( nY, nX, aWB );
1297*cdf0e10cSrcweir 									else
1298*cdf0e10cSrcweir 										pWAcc->SetPixel( nY, nX, aWW );
1299*cdf0e10cSrcweir 								}
1300*cdf0e10cSrcweir 							}
1301*cdf0e10cSrcweir 						}
1302*cdf0e10cSrcweir 					}
1303*cdf0e10cSrcweir 
1304*cdf0e10cSrcweir 					delete[] pMapLX;
1305*cdf0e10cSrcweir 					delete[] pMapLY;
1306*cdf0e10cSrcweir 					aOutMsk.ReleaseAccess( pWAcc );
1307*cdf0e10cSrcweir 					bRet = sal_True;
1308*cdf0e10cSrcweir 				}
1309*cdf0e10cSrcweir 
1310*cdf0e10cSrcweir 				aMsk.ReleaseAccess( pAcc );
1311*cdf0e10cSrcweir 
1312*cdf0e10cSrcweir 				if( bRet )
1313*cdf0e10cSrcweir 					rOutBmpEx = BitmapEx( aOutBmp, aOutMsk );
1314*cdf0e10cSrcweir 			}
1315*cdf0e10cSrcweir 		}
1316*cdf0e10cSrcweir 
1317*cdf0e10cSrcweir 		if( !bRet )
1318*cdf0e10cSrcweir 			rOutBmpEx = aOutBmp;
1319*cdf0e10cSrcweir 	}
1320*cdf0e10cSrcweir 	else
1321*cdf0e10cSrcweir 		rOutBmpEx = aOutBmp;
1322*cdf0e10cSrcweir 
1323*cdf0e10cSrcweir 	return bRet;
1324*cdf0e10cSrcweir }
1325*cdf0e10cSrcweir 
1326*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1327*cdf0e10cSrcweir 
1328*cdf0e10cSrcweir sal_Bool GraphicManager::ImplCreateRotatedScaled( const BitmapEx& rBmpEx,
1329*cdf0e10cSrcweir 											  sal_uInt16 nRot10, const Size& /*rOutSzPix*/, const Size& rUnrotatedSzPix,
1330*cdf0e10cSrcweir 											  long* pMapIX, long* pMapFX, long* pMapIY, long* pMapFY,
1331*cdf0e10cSrcweir 											  long nStartX, long nEndX, long nStartY, long nEndY,
1332*cdf0e10cSrcweir 											  BitmapEx& rOutBmpEx )
1333*cdf0e10cSrcweir {
1334*cdf0e10cSrcweir 	Point				aPt;
1335*cdf0e10cSrcweir 	Bitmap				aBmp( rBmpEx.GetBitmap() );
1336*cdf0e10cSrcweir 	Bitmap				aOutBmp;
1337*cdf0e10cSrcweir 	BitmapReadAccess*	pAcc = aBmp.AcquireReadAccess();
1338*cdf0e10cSrcweir 	BitmapWriteAccess*	pWAcc;
1339*cdf0e10cSrcweir 	Polygon				aPoly( Rectangle( aPt, rUnrotatedSzPix ) ); aPoly.Rotate( Point(), nRot10 );
1340*cdf0e10cSrcweir 	Rectangle			aNewBound( aPoly.GetBoundRect() );
1341*cdf0e10cSrcweir 	const double		fCosAngle = cos( nRot10 * F_PI1800 ), fSinAngle = sin( nRot10 * F_PI1800 );
1342*cdf0e10cSrcweir 	double				fTmp;
1343*cdf0e10cSrcweir 	const long			nDstW = nEndX - nStartX + 1L;
1344*cdf0e10cSrcweir 	const long			nDstH = nEndY - nStartY + 1L;
1345*cdf0e10cSrcweir 	const long			nUnRotW = rUnrotatedSzPix.Width();
1346*cdf0e10cSrcweir 	const long			nUnRotH = rUnrotatedSzPix.Height();
1347*cdf0e10cSrcweir 	long*				pCosX = new long[ nDstW ];
1348*cdf0e10cSrcweir 	long*				pSinX = new long[ nDstW ];
1349*cdf0e10cSrcweir 	long*				pCosY = new long[ nDstH ];
1350*cdf0e10cSrcweir 	long*				pSinY = new long[ nDstH ];
1351*cdf0e10cSrcweir 	long				nX, nY, nTmpX, nTmpY, nTmpFX, nTmpFY, nUnRotX, nUnRotY, nSinY, nCosY;
1352*cdf0e10cSrcweir 	sal_uInt8				cR0, cG0, cB0, cR1, cG1, cB1;
1353*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
1354*cdf0e10cSrcweir 
1355*cdf0e10cSrcweir 	// create horizontal mapping table
1356*cdf0e10cSrcweir 	for( nX = 0L, nTmpX = aNewBound.Left() + nStartX; nX < nDstW; nX++ )
1357*cdf0e10cSrcweir 	{
1358*cdf0e10cSrcweir 		pCosX[ nX ] = FRound( fCosAngle * ( fTmp = nTmpX++ << 8 ) );
1359*cdf0e10cSrcweir 		pSinX[ nX ] = FRound( fSinAngle * fTmp );
1360*cdf0e10cSrcweir 	}
1361*cdf0e10cSrcweir 
1362*cdf0e10cSrcweir 	// create vertical mapping table
1363*cdf0e10cSrcweir 	for( nY = 0L, nTmpY = aNewBound.Top() + nStartY; nY < nDstH; nY++ )
1364*cdf0e10cSrcweir 	{
1365*cdf0e10cSrcweir 		pCosY[ nY ] = FRound( fCosAngle * ( fTmp = nTmpY++ << 8 ) );
1366*cdf0e10cSrcweir 		pSinY[ nY ] = FRound( fSinAngle * fTmp );
1367*cdf0e10cSrcweir 	}
1368*cdf0e10cSrcweir 
1369*cdf0e10cSrcweir 	if( pAcc )
1370*cdf0e10cSrcweir 	{
1371*cdf0e10cSrcweir 		aOutBmp = Bitmap( Size( nDstW, nDstH ), 24 );
1372*cdf0e10cSrcweir 		pWAcc = aOutBmp.AcquireWriteAccess();
1373*cdf0e10cSrcweir 
1374*cdf0e10cSrcweir 		if( pWAcc )
1375*cdf0e10cSrcweir 		{
1376*cdf0e10cSrcweir 			BitmapColor aColRes;
1377*cdf0e10cSrcweir 
1378*cdf0e10cSrcweir 			if( pAcc->HasPalette() )
1379*cdf0e10cSrcweir 			{
1380*cdf0e10cSrcweir 				for( nY = 0; nY < nDstH; nY++ )
1381*cdf0e10cSrcweir 				{
1382*cdf0e10cSrcweir 					nSinY = pSinY[ nY ];
1383*cdf0e10cSrcweir 					nCosY = pCosY[ nY ];
1384*cdf0e10cSrcweir 
1385*cdf0e10cSrcweir 					for( nX = 0; nX < nDstW; nX++ )
1386*cdf0e10cSrcweir 					{
1387*cdf0e10cSrcweir 						nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8;
1388*cdf0e10cSrcweir 						nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8;
1389*cdf0e10cSrcweir 
1390*cdf0e10cSrcweir 						if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) &&
1391*cdf0e10cSrcweir 							( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) )
1392*cdf0e10cSrcweir 						{
1393*cdf0e10cSrcweir 							nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ];
1394*cdf0e10cSrcweir 							nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ];
1395*cdf0e10cSrcweir 
1396*cdf0e10cSrcweir 							const BitmapColor& rCol0 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, nTmpX ) );
1397*cdf0e10cSrcweir 							const BitmapColor& rCol1 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, ++nTmpX ) );
1398*cdf0e10cSrcweir 							cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTmpFX );
1399*cdf0e10cSrcweir 							cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTmpFX );
1400*cdf0e10cSrcweir 							cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTmpFX );
1401*cdf0e10cSrcweir 
1402*cdf0e10cSrcweir 							const BitmapColor& rCol3 = pAcc->GetPaletteColor( pAcc->GetPixel( ++nTmpY, nTmpX ) );
1403*cdf0e10cSrcweir 							const BitmapColor& rCol2 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, --nTmpX ) );
1404*cdf0e10cSrcweir 							cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTmpFX );
1405*cdf0e10cSrcweir 							cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTmpFX );
1406*cdf0e10cSrcweir 							cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTmpFX );
1407*cdf0e10cSrcweir 
1408*cdf0e10cSrcweir 							aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) );
1409*cdf0e10cSrcweir 							aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) );
1410*cdf0e10cSrcweir 							aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) );
1411*cdf0e10cSrcweir 							pWAcc->SetPixel( nY, nX, aColRes );
1412*cdf0e10cSrcweir 						}
1413*cdf0e10cSrcweir 					}
1414*cdf0e10cSrcweir 				}
1415*cdf0e10cSrcweir 			}
1416*cdf0e10cSrcweir 			else
1417*cdf0e10cSrcweir 			{
1418*cdf0e10cSrcweir 				BitmapColor	aCol0, aCol1;
1419*cdf0e10cSrcweir 
1420*cdf0e10cSrcweir 				for( nY = 0; nY < nDstH; nY++ )
1421*cdf0e10cSrcweir 				{
1422*cdf0e10cSrcweir 					nSinY = pSinY[ nY ];
1423*cdf0e10cSrcweir 					nCosY = pCosY[ nY ];
1424*cdf0e10cSrcweir 
1425*cdf0e10cSrcweir 					for( nX = 0; nX < nDstW; nX++ )
1426*cdf0e10cSrcweir 					{
1427*cdf0e10cSrcweir 						nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8;
1428*cdf0e10cSrcweir 						nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8;
1429*cdf0e10cSrcweir 
1430*cdf0e10cSrcweir 						if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) &&
1431*cdf0e10cSrcweir 							( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) )
1432*cdf0e10cSrcweir 						{
1433*cdf0e10cSrcweir 							nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ];
1434*cdf0e10cSrcweir 							nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ];
1435*cdf0e10cSrcweir 
1436*cdf0e10cSrcweir 							aCol0 = pAcc->GetPixel( nTmpY, nTmpX );
1437*cdf0e10cSrcweir 							aCol1 = pAcc->GetPixel( nTmpY, ++nTmpX );
1438*cdf0e10cSrcweir 							cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX );
1439*cdf0e10cSrcweir 							cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX );
1440*cdf0e10cSrcweir 							cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX );
1441*cdf0e10cSrcweir 
1442*cdf0e10cSrcweir 							aCol1 = pAcc->GetPixel( ++nTmpY, nTmpX );
1443*cdf0e10cSrcweir 							aCol0 = pAcc->GetPixel( nTmpY, --nTmpX );
1444*cdf0e10cSrcweir 							cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX );
1445*cdf0e10cSrcweir 							cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX );
1446*cdf0e10cSrcweir 							cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX );
1447*cdf0e10cSrcweir 
1448*cdf0e10cSrcweir 							aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) );
1449*cdf0e10cSrcweir 							aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) );
1450*cdf0e10cSrcweir 							aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) );
1451*cdf0e10cSrcweir 							pWAcc->SetPixel( nY, nX, aColRes );
1452*cdf0e10cSrcweir 						}
1453*cdf0e10cSrcweir 					}
1454*cdf0e10cSrcweir 				}
1455*cdf0e10cSrcweir 			}
1456*cdf0e10cSrcweir 
1457*cdf0e10cSrcweir 			aOutBmp.ReleaseAccess( pWAcc );
1458*cdf0e10cSrcweir 			bRet = sal_True;
1459*cdf0e10cSrcweir 		}
1460*cdf0e10cSrcweir 
1461*cdf0e10cSrcweir 		aBmp.ReleaseAccess( pAcc );
1462*cdf0e10cSrcweir 	}
1463*cdf0e10cSrcweir 
1464*cdf0e10cSrcweir 	// mask processing
1465*cdf0e10cSrcweir 	if( bRet && ( rBmpEx.IsTransparent() || ( nRot10 != 900 && nRot10 != 1800 && nRot10 != 2700 ) ) )
1466*cdf0e10cSrcweir 	{
1467*cdf0e10cSrcweir 		bRet = sal_False;
1468*cdf0e10cSrcweir 
1469*cdf0e10cSrcweir 		if( rBmpEx.IsAlpha() )
1470*cdf0e10cSrcweir 		{
1471*cdf0e10cSrcweir 			AlphaMask	aAlpha( rBmpEx.GetAlpha() );
1472*cdf0e10cSrcweir 			AlphaMask	aOutAlpha;
1473*cdf0e10cSrcweir 
1474*cdf0e10cSrcweir 			pAcc = aAlpha.AcquireReadAccess();
1475*cdf0e10cSrcweir 
1476*cdf0e10cSrcweir 			if( pAcc )
1477*cdf0e10cSrcweir 			{
1478*cdf0e10cSrcweir 				aOutAlpha = AlphaMask( Size( nDstW, nDstH ) );
1479*cdf0e10cSrcweir 				pWAcc = aOutAlpha.AcquireWriteAccess();
1480*cdf0e10cSrcweir 
1481*cdf0e10cSrcweir 				if( pWAcc )
1482*cdf0e10cSrcweir 				{
1483*cdf0e10cSrcweir 					if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL &&
1484*cdf0e10cSrcweir 						pWAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
1485*cdf0e10cSrcweir 					{
1486*cdf0e10cSrcweir 						Scanline pLine0, pLine1, pLineW;
1487*cdf0e10cSrcweir 
1488*cdf0e10cSrcweir 						for( nY = 0; nY < nDstH; nY++ )
1489*cdf0e10cSrcweir 						{
1490*cdf0e10cSrcweir 							nSinY = pSinY[ nY ], nCosY = pCosY[ nY ];
1491*cdf0e10cSrcweir 							pLineW = pWAcc->GetScanline( nY );
1492*cdf0e10cSrcweir 
1493*cdf0e10cSrcweir 							for( nX = 0; nX < nDstW; nX++ )
1494*cdf0e10cSrcweir 							{
1495*cdf0e10cSrcweir 								nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8;
1496*cdf0e10cSrcweir 								nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8;
1497*cdf0e10cSrcweir 
1498*cdf0e10cSrcweir 								if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) &&
1499*cdf0e10cSrcweir 									( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) )
1500*cdf0e10cSrcweir 								{
1501*cdf0e10cSrcweir 									nTmpX = pMapIX[ nUnRotX ], nTmpFX = pMapFX[ nUnRotX ];
1502*cdf0e10cSrcweir 									nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ];
1503*cdf0e10cSrcweir 
1504*cdf0e10cSrcweir 									pLine0 = pAcc->GetScanline( nTmpY++ );
1505*cdf0e10cSrcweir 									pLine1 = pAcc->GetScanline( nTmpY );
1506*cdf0e10cSrcweir 
1507*cdf0e10cSrcweir 									const long	nAlpha0 = pLine0[ nTmpX ];
1508*cdf0e10cSrcweir 									const long	nAlpha2 = pLine1[ nTmpX++ ];
1509*cdf0e10cSrcweir 									const long	nAlpha1 = pLine0[ nTmpX ];
1510*cdf0e10cSrcweir 									const long	nAlpha3 = pLine1[ nTmpX ];
1511*cdf0e10cSrcweir 									const long	n0 = MAP( nAlpha0, nAlpha1, nTmpFX );
1512*cdf0e10cSrcweir 									const long	n1 = MAP( nAlpha2, nAlpha3, nTmpFX );
1513*cdf0e10cSrcweir 
1514*cdf0e10cSrcweir 									*pLineW++ = MAP( n0, n1, nTmpFY );
1515*cdf0e10cSrcweir 								}
1516*cdf0e10cSrcweir 								else
1517*cdf0e10cSrcweir 									*pLineW++ = 255;
1518*cdf0e10cSrcweir 							}
1519*cdf0e10cSrcweir 						}
1520*cdf0e10cSrcweir 					}
1521*cdf0e10cSrcweir 					else
1522*cdf0e10cSrcweir 					{
1523*cdf0e10cSrcweir 						const BitmapColor	aTrans( pWAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1524*cdf0e10cSrcweir 						BitmapColor			aAlphaVal( 0 );
1525*cdf0e10cSrcweir 
1526*cdf0e10cSrcweir 						for( nY = 0; nY < nDstH; nY++ )
1527*cdf0e10cSrcweir 						{
1528*cdf0e10cSrcweir 							nSinY = pSinY[ nY ], nCosY = pCosY[ nY ];
1529*cdf0e10cSrcweir 
1530*cdf0e10cSrcweir 							for( nX = 0; nX < nDstW; nX++ )
1531*cdf0e10cSrcweir 							{
1532*cdf0e10cSrcweir 								nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8;
1533*cdf0e10cSrcweir 								nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8;
1534*cdf0e10cSrcweir 
1535*cdf0e10cSrcweir 								if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) &&
1536*cdf0e10cSrcweir 									( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) )
1537*cdf0e10cSrcweir 								{
1538*cdf0e10cSrcweir 									nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ];
1539*cdf0e10cSrcweir 									nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ];
1540*cdf0e10cSrcweir 
1541*cdf0e10cSrcweir 									const long	nAlpha0 = pAcc->GetPixel( nTmpY, nTmpX ).GetIndex();
1542*cdf0e10cSrcweir 									const long	nAlpha1 = pAcc->GetPixel( nTmpY, ++nTmpX ).GetIndex();
1543*cdf0e10cSrcweir 									const long	nAlpha3 = pAcc->GetPixel( ++nTmpY, nTmpX ).GetIndex();
1544*cdf0e10cSrcweir 									const long	nAlpha2 = pAcc->GetPixel( nTmpY, --nTmpX ).GetIndex();
1545*cdf0e10cSrcweir 									const long 	n0 = MAP( nAlpha0, nAlpha1, nTmpFX );
1546*cdf0e10cSrcweir 									const long 	n1 = MAP( nAlpha2, nAlpha3, nTmpFX );
1547*cdf0e10cSrcweir 
1548*cdf0e10cSrcweir 									aAlphaVal.SetIndex( MAP( n0, n1, nTmpFY ) );
1549*cdf0e10cSrcweir 									pWAcc->SetPixel( nY, nX, aAlphaVal );
1550*cdf0e10cSrcweir 								}
1551*cdf0e10cSrcweir 								else
1552*cdf0e10cSrcweir 									pWAcc->SetPixel( nY, nX, aTrans );
1553*cdf0e10cSrcweir 							}
1554*cdf0e10cSrcweir 						}
1555*cdf0e10cSrcweir 					}
1556*cdf0e10cSrcweir 
1557*cdf0e10cSrcweir 					aOutAlpha.ReleaseAccess( pWAcc );
1558*cdf0e10cSrcweir 					bRet = sal_True;
1559*cdf0e10cSrcweir 				}
1560*cdf0e10cSrcweir 
1561*cdf0e10cSrcweir 				aAlpha.ReleaseAccess( pAcc );
1562*cdf0e10cSrcweir 			}
1563*cdf0e10cSrcweir 
1564*cdf0e10cSrcweir 			if( bRet )
1565*cdf0e10cSrcweir 				rOutBmpEx = BitmapEx( aOutBmp, aOutAlpha );
1566*cdf0e10cSrcweir 		}
1567*cdf0e10cSrcweir 		else
1568*cdf0e10cSrcweir 		{
1569*cdf0e10cSrcweir 			Bitmap aOutMsk( Size( nDstW, nDstH ), 1 );
1570*cdf0e10cSrcweir 			pWAcc = aOutMsk.AcquireWriteAccess();
1571*cdf0e10cSrcweir 
1572*cdf0e10cSrcweir 			if( pWAcc )
1573*cdf0e10cSrcweir 			{
1574*cdf0e10cSrcweir 				Bitmap				aMsk( rBmpEx.GetMask() );
1575*cdf0e10cSrcweir 				const BitmapColor	aB( pWAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
1576*cdf0e10cSrcweir 				const BitmapColor	aW( pWAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1577*cdf0e10cSrcweir 				BitmapReadAccess*	pMAcc = NULL;
1578*cdf0e10cSrcweir 
1579*cdf0e10cSrcweir 				if( !aMsk || ( ( pMAcc = aMsk.AcquireReadAccess() ) != NULL ) )
1580*cdf0e10cSrcweir 				{
1581*cdf0e10cSrcweir 					long*		pMapLX = new long[ nUnRotW ];
1582*cdf0e10cSrcweir 					long*		pMapLY = new long[ nUnRotH ];
1583*cdf0e10cSrcweir 					BitmapColor	aTestB;
1584*cdf0e10cSrcweir 
1585*cdf0e10cSrcweir 					if( pMAcc )
1586*cdf0e10cSrcweir 						aTestB = pMAcc->GetBestMatchingColor( Color( COL_BLACK ) );
1587*cdf0e10cSrcweir 
1588*cdf0e10cSrcweir 					// create new horizontal mapping table
1589*cdf0e10cSrcweir 					for( nX = 0UL; nX < nUnRotW; nX++ )
1590*cdf0e10cSrcweir 						pMapLX[ nX ] = FRound( (double) pMapIX[ nX ] + pMapFX[ nX ] / 1048576. );
1591*cdf0e10cSrcweir 
1592*cdf0e10cSrcweir 					// create new vertical mapping table
1593*cdf0e10cSrcweir 					for( nY = 0UL; nY < nUnRotH; nY++ )
1594*cdf0e10cSrcweir 						pMapLY[ nY ] = FRound( (double) pMapIY[ nY ] + pMapFY[ nY ] / 1048576. );
1595*cdf0e10cSrcweir 
1596*cdf0e10cSrcweir 					// do mask rotation
1597*cdf0e10cSrcweir 					for( nY = 0; nY < nDstH; nY++ )
1598*cdf0e10cSrcweir 					{
1599*cdf0e10cSrcweir 						nSinY = pSinY[ nY ];
1600*cdf0e10cSrcweir 						nCosY = pCosY[ nY ];
1601*cdf0e10cSrcweir 
1602*cdf0e10cSrcweir 						for( nX = 0; nX < nDstW; nX++ )
1603*cdf0e10cSrcweir 						{
1604*cdf0e10cSrcweir 							nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8;
1605*cdf0e10cSrcweir 							nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8;
1606*cdf0e10cSrcweir 
1607*cdf0e10cSrcweir 							if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) &&
1608*cdf0e10cSrcweir 								( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) )
1609*cdf0e10cSrcweir 							{
1610*cdf0e10cSrcweir 								if( pMAcc )
1611*cdf0e10cSrcweir 								{
1612*cdf0e10cSrcweir 									if( pMAcc->GetPixel( pMapLY[ nUnRotY ], pMapLX[ nUnRotX ] ) == aTestB )
1613*cdf0e10cSrcweir 										pWAcc->SetPixel( nY, nX, aB );
1614*cdf0e10cSrcweir 									else
1615*cdf0e10cSrcweir 										pWAcc->SetPixel( nY, nX, aW );
1616*cdf0e10cSrcweir 								}
1617*cdf0e10cSrcweir 								else
1618*cdf0e10cSrcweir 									pWAcc->SetPixel( nY, nX, aB );
1619*cdf0e10cSrcweir 							}
1620*cdf0e10cSrcweir 							else
1621*cdf0e10cSrcweir 								pWAcc->SetPixel( nY, nX, aW );
1622*cdf0e10cSrcweir 						}
1623*cdf0e10cSrcweir 					}
1624*cdf0e10cSrcweir 
1625*cdf0e10cSrcweir 					delete[] pMapLX;
1626*cdf0e10cSrcweir 					delete[] pMapLY;
1627*cdf0e10cSrcweir 
1628*cdf0e10cSrcweir 					if( pMAcc )
1629*cdf0e10cSrcweir 						aMsk.ReleaseAccess( pMAcc );
1630*cdf0e10cSrcweir 
1631*cdf0e10cSrcweir 					bRet = sal_True;
1632*cdf0e10cSrcweir 				}
1633*cdf0e10cSrcweir 
1634*cdf0e10cSrcweir 				aOutMsk.ReleaseAccess( pWAcc );
1635*cdf0e10cSrcweir 			}
1636*cdf0e10cSrcweir 
1637*cdf0e10cSrcweir 			if( bRet )
1638*cdf0e10cSrcweir 				rOutBmpEx = BitmapEx( aOutBmp, aOutMsk );
1639*cdf0e10cSrcweir 		}
1640*cdf0e10cSrcweir 
1641*cdf0e10cSrcweir 		if( !bRet )
1642*cdf0e10cSrcweir 			rOutBmpEx = aOutBmp;
1643*cdf0e10cSrcweir 	}
1644*cdf0e10cSrcweir 	else
1645*cdf0e10cSrcweir 		rOutBmpEx = aOutBmp;
1646*cdf0e10cSrcweir 
1647*cdf0e10cSrcweir 	delete[] pSinX;
1648*cdf0e10cSrcweir 	delete[] pCosX;
1649*cdf0e10cSrcweir 	delete[] pSinY;
1650*cdf0e10cSrcweir 	delete[] pCosY;
1651*cdf0e10cSrcweir 
1652*cdf0e10cSrcweir 	return bRet;
1653*cdf0e10cSrcweir }
1654*cdf0e10cSrcweir 
1655*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1656*cdf0e10cSrcweir 
1657*cdf0e10cSrcweir void GraphicManager::ImplAdjust( BitmapEx& rBmpEx, const GraphicAttr& rAttr, sal_uLong nAdjustmentFlags )
1658*cdf0e10cSrcweir {
1659*cdf0e10cSrcweir 	GraphicAttr aAttr( rAttr );
1660*cdf0e10cSrcweir 
1661*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() )
1662*cdf0e10cSrcweir 	{
1663*cdf0e10cSrcweir 		switch( aAttr.GetDrawMode() )
1664*cdf0e10cSrcweir 		{
1665*cdf0e10cSrcweir 			case( GRAPHICDRAWMODE_MONO ):
1666*cdf0e10cSrcweir 				rBmpEx.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
1667*cdf0e10cSrcweir 			break;
1668*cdf0e10cSrcweir 
1669*cdf0e10cSrcweir 			case( GRAPHICDRAWMODE_GREYS ):
1670*cdf0e10cSrcweir 				rBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS );
1671*cdf0e10cSrcweir 			break;
1672*cdf0e10cSrcweir 
1673*cdf0e10cSrcweir 			case( GRAPHICDRAWMODE_WATERMARK ):
1674*cdf0e10cSrcweir 			{
1675*cdf0e10cSrcweir 				aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET );
1676*cdf0e10cSrcweir 				aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET );
1677*cdf0e10cSrcweir 			}
1678*cdf0e10cSrcweir 			break;
1679*cdf0e10cSrcweir 
1680*cdf0e10cSrcweir 			default:
1681*cdf0e10cSrcweir 			break;
1682*cdf0e10cSrcweir 		}
1683*cdf0e10cSrcweir 	}
1684*cdf0e10cSrcweir 
1685*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() )
1686*cdf0e10cSrcweir 	{
1687*cdf0e10cSrcweir 		rBmpEx.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(),
1688*cdf0e10cSrcweir 					   aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(),
1689*cdf0e10cSrcweir 					   aAttr.GetGamma(), aAttr.IsInvert() );
1690*cdf0e10cSrcweir 	}
1691*cdf0e10cSrcweir 
1692*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() )
1693*cdf0e10cSrcweir 	{
1694*cdf0e10cSrcweir 		rBmpEx.Mirror( aAttr.GetMirrorFlags() );
1695*cdf0e10cSrcweir 	}
1696*cdf0e10cSrcweir 
1697*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() )
1698*cdf0e10cSrcweir 	{
1699*cdf0e10cSrcweir 		rBmpEx.Rotate( aAttr.GetRotation(), Color( COL_TRANSPARENT ) );
1700*cdf0e10cSrcweir 	}
1701*cdf0e10cSrcweir 
1702*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() )
1703*cdf0e10cSrcweir 	{
1704*cdf0e10cSrcweir 		AlphaMask	aAlpha;
1705*cdf0e10cSrcweir 		sal_uInt8		cTrans = aAttr.GetTransparency();
1706*cdf0e10cSrcweir 
1707*cdf0e10cSrcweir 		if( !rBmpEx.IsTransparent() )
1708*cdf0e10cSrcweir 			aAlpha = AlphaMask( rBmpEx.GetSizePixel(), &cTrans );
1709*cdf0e10cSrcweir 		else if( !rBmpEx.IsAlpha() )
1710*cdf0e10cSrcweir 		{
1711*cdf0e10cSrcweir 			aAlpha = rBmpEx.GetMask();
1712*cdf0e10cSrcweir 			aAlpha.Replace( 0, cTrans );
1713*cdf0e10cSrcweir 		}
1714*cdf0e10cSrcweir 		else
1715*cdf0e10cSrcweir 		{
1716*cdf0e10cSrcweir 			aAlpha = rBmpEx.GetAlpha();
1717*cdf0e10cSrcweir 			BitmapWriteAccess* pA = aAlpha.AcquireWriteAccess();
1718*cdf0e10cSrcweir 
1719*cdf0e10cSrcweir 			if( pA )
1720*cdf0e10cSrcweir 			{
1721*cdf0e10cSrcweir 				sal_uLong		nTrans = cTrans, nNewTrans;
1722*cdf0e10cSrcweir 				const long	nWidth = pA->Width(), nHeight = pA->Height();
1723*cdf0e10cSrcweir 
1724*cdf0e10cSrcweir 				if( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
1725*cdf0e10cSrcweir 				{
1726*cdf0e10cSrcweir 					for( long nY = 0; nY < nHeight; nY++ )
1727*cdf0e10cSrcweir 					{
1728*cdf0e10cSrcweir 						Scanline pAScan = pA->GetScanline( nY );
1729*cdf0e10cSrcweir 
1730*cdf0e10cSrcweir 						for( long nX = 0; nX < nWidth; nX++ )
1731*cdf0e10cSrcweir 						{
1732*cdf0e10cSrcweir 							nNewTrans = nTrans + *pAScan;
1733*cdf0e10cSrcweir 							*pAScan++ = (sal_uInt8) ( ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans );
1734*cdf0e10cSrcweir 						}
1735*cdf0e10cSrcweir 					}
1736*cdf0e10cSrcweir 				}
1737*cdf0e10cSrcweir 				else
1738*cdf0e10cSrcweir 				{
1739*cdf0e10cSrcweir 					BitmapColor aAlphaValue( 0 );
1740*cdf0e10cSrcweir 
1741*cdf0e10cSrcweir 					for( long nY = 0; nY < nHeight; nY++ )
1742*cdf0e10cSrcweir 					{
1743*cdf0e10cSrcweir 						for( long nX = 0; nX < nWidth; nX++ )
1744*cdf0e10cSrcweir 						{
1745*cdf0e10cSrcweir 							nNewTrans = nTrans + pA->GetPixel( nY, nX ).GetIndex();
1746*cdf0e10cSrcweir 							aAlphaValue.SetIndex( (sal_uInt8) ( ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans ) );
1747*cdf0e10cSrcweir 							pA->SetPixel( nY, nX, aAlphaValue );
1748*cdf0e10cSrcweir 						}
1749*cdf0e10cSrcweir 					}
1750*cdf0e10cSrcweir 				}
1751*cdf0e10cSrcweir 
1752*cdf0e10cSrcweir 				aAlpha.ReleaseAccess( pA );
1753*cdf0e10cSrcweir 			}
1754*cdf0e10cSrcweir 		}
1755*cdf0e10cSrcweir 
1756*cdf0e10cSrcweir 		rBmpEx = BitmapEx( rBmpEx.GetBitmap(), aAlpha );
1757*cdf0e10cSrcweir 	}
1758*cdf0e10cSrcweir }
1759*cdf0e10cSrcweir 
1760*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1761*cdf0e10cSrcweir 
1762*cdf0e10cSrcweir void GraphicManager::ImplAdjust( GDIMetaFile& rMtf, const GraphicAttr& rAttr, sal_uLong nAdjustmentFlags )
1763*cdf0e10cSrcweir {
1764*cdf0e10cSrcweir 	GraphicAttr aAttr( rAttr );
1765*cdf0e10cSrcweir 
1766*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() )
1767*cdf0e10cSrcweir 	{
1768*cdf0e10cSrcweir 		switch( aAttr.GetDrawMode() )
1769*cdf0e10cSrcweir 		{
1770*cdf0e10cSrcweir 			case( GRAPHICDRAWMODE_MONO ):
1771*cdf0e10cSrcweir 				rMtf.Convert( MTF_CONVERSION_1BIT_THRESHOLD );
1772*cdf0e10cSrcweir 			break;
1773*cdf0e10cSrcweir 
1774*cdf0e10cSrcweir 			case( GRAPHICDRAWMODE_GREYS ):
1775*cdf0e10cSrcweir 				rMtf.Convert( MTF_CONVERSION_8BIT_GREYS );
1776*cdf0e10cSrcweir 			break;
1777*cdf0e10cSrcweir 
1778*cdf0e10cSrcweir 			case( GRAPHICDRAWMODE_WATERMARK ):
1779*cdf0e10cSrcweir 			{
1780*cdf0e10cSrcweir 				aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET );
1781*cdf0e10cSrcweir 				aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET );
1782*cdf0e10cSrcweir 			}
1783*cdf0e10cSrcweir 			break;
1784*cdf0e10cSrcweir 
1785*cdf0e10cSrcweir 			default:
1786*cdf0e10cSrcweir 			break;
1787*cdf0e10cSrcweir 		}
1788*cdf0e10cSrcweir 	}
1789*cdf0e10cSrcweir 
1790*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() )
1791*cdf0e10cSrcweir 	{
1792*cdf0e10cSrcweir 		rMtf.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(),
1793*cdf0e10cSrcweir 					 aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(),
1794*cdf0e10cSrcweir 					 aAttr.GetGamma(), aAttr.IsInvert() );
1795*cdf0e10cSrcweir 	}
1796*cdf0e10cSrcweir 
1797*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() )
1798*cdf0e10cSrcweir 	{
1799*cdf0e10cSrcweir         rMtf.Mirror( aAttr.GetMirrorFlags() );
1800*cdf0e10cSrcweir 	}
1801*cdf0e10cSrcweir 
1802*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() )
1803*cdf0e10cSrcweir 	{
1804*cdf0e10cSrcweir 		rMtf.Rotate( aAttr.GetRotation() );
1805*cdf0e10cSrcweir 	}
1806*cdf0e10cSrcweir 
1807*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() )
1808*cdf0e10cSrcweir 	{
1809*cdf0e10cSrcweir 		DBG_ERROR( "Missing implementation: Mtf-Transparency" );
1810*cdf0e10cSrcweir 	}
1811*cdf0e10cSrcweir }
1812*cdf0e10cSrcweir 
1813*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1814*cdf0e10cSrcweir 
1815*cdf0e10cSrcweir void GraphicManager::ImplAdjust( Animation& rAnimation, const GraphicAttr& rAttr, sal_uLong nAdjustmentFlags )
1816*cdf0e10cSrcweir {
1817*cdf0e10cSrcweir 	GraphicAttr aAttr( rAttr );
1818*cdf0e10cSrcweir 
1819*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() )
1820*cdf0e10cSrcweir 	{
1821*cdf0e10cSrcweir 		switch( aAttr.GetDrawMode() )
1822*cdf0e10cSrcweir 		{
1823*cdf0e10cSrcweir 			case( GRAPHICDRAWMODE_MONO ):
1824*cdf0e10cSrcweir 				rAnimation.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
1825*cdf0e10cSrcweir 			break;
1826*cdf0e10cSrcweir 
1827*cdf0e10cSrcweir 			case( GRAPHICDRAWMODE_GREYS ):
1828*cdf0e10cSrcweir 				rAnimation.Convert( BMP_CONVERSION_8BIT_GREYS );
1829*cdf0e10cSrcweir 			break;
1830*cdf0e10cSrcweir 
1831*cdf0e10cSrcweir 			case( GRAPHICDRAWMODE_WATERMARK ):
1832*cdf0e10cSrcweir 			{
1833*cdf0e10cSrcweir 				aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET );
1834*cdf0e10cSrcweir 				aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET );
1835*cdf0e10cSrcweir 			}
1836*cdf0e10cSrcweir 			break;
1837*cdf0e10cSrcweir 
1838*cdf0e10cSrcweir 			default:
1839*cdf0e10cSrcweir 			break;
1840*cdf0e10cSrcweir 		}
1841*cdf0e10cSrcweir 	}
1842*cdf0e10cSrcweir 
1843*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() )
1844*cdf0e10cSrcweir 	{
1845*cdf0e10cSrcweir 		rAnimation.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(),
1846*cdf0e10cSrcweir 						   aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(),
1847*cdf0e10cSrcweir 						   aAttr.GetGamma(), aAttr.IsInvert() );
1848*cdf0e10cSrcweir 	}
1849*cdf0e10cSrcweir 
1850*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() )
1851*cdf0e10cSrcweir     {
1852*cdf0e10cSrcweir 		rAnimation.Mirror( aAttr.GetMirrorFlags() );
1853*cdf0e10cSrcweir     }
1854*cdf0e10cSrcweir 
1855*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() )
1856*cdf0e10cSrcweir 	{
1857*cdf0e10cSrcweir 		DBG_ERROR( "Missing implementation: Animation-Rotation" );
1858*cdf0e10cSrcweir 	}
1859*cdf0e10cSrcweir 
1860*cdf0e10cSrcweir 	if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() )
1861*cdf0e10cSrcweir 	{
1862*cdf0e10cSrcweir 		DBG_ERROR( "Missing implementation: Animation-Transparency" );
1863*cdf0e10cSrcweir 	}
1864*cdf0e10cSrcweir }
1865*cdf0e10cSrcweir 
1866*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1867*cdf0e10cSrcweir 
1868*cdf0e10cSrcweir void GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt, const Size& rSz,
1869*cdf0e10cSrcweir 							   const GDIMetaFile& rMtf, const GraphicAttr& rAttr )
1870*cdf0e10cSrcweir {
1871*cdf0e10cSrcweir    	sal_uInt16	nRot10 = rAttr.GetRotation() % 3600;
1872*cdf0e10cSrcweir     Point	aOutPt( rPt );
1873*cdf0e10cSrcweir     Size	aOutSz( rSz );
1874*cdf0e10cSrcweir 
1875*cdf0e10cSrcweir     if( nRot10 )
1876*cdf0e10cSrcweir     {
1877*cdf0e10cSrcweir 		Polygon aPoly( Rectangle( aOutPt, aOutSz ) );
1878*cdf0e10cSrcweir 
1879*cdf0e10cSrcweir 		aPoly.Rotate( aOutPt, nRot10 );
1880*cdf0e10cSrcweir 		const Rectangle aRotBoundRect( aPoly.GetBoundRect() );
1881*cdf0e10cSrcweir 		aOutPt = aRotBoundRect.TopLeft();
1882*cdf0e10cSrcweir 		aOutSz = aRotBoundRect.GetSize();
1883*cdf0e10cSrcweir 	}
1884*cdf0e10cSrcweir 
1885*cdf0e10cSrcweir 	pOut->Push( PUSH_CLIPREGION );
1886*cdf0e10cSrcweir 	pOut->IntersectClipRegion( Rectangle( aOutPt, aOutSz ) );
1887*cdf0e10cSrcweir 
1888*cdf0e10cSrcweir 	( (GDIMetaFile&) rMtf ).WindStart();
1889*cdf0e10cSrcweir 	( (GDIMetaFile&) rMtf ).Play( pOut, aOutPt, aOutSz );
1890*cdf0e10cSrcweir 	( (GDIMetaFile&) rMtf ).WindStart();
1891*cdf0e10cSrcweir 
1892*cdf0e10cSrcweir 	pOut->Pop();
1893*cdf0e10cSrcweir }
1894*cdf0e10cSrcweir 
1895*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1896*cdf0e10cSrcweir 
1897*cdf0e10cSrcweir struct ImplTileInfo
1898*cdf0e10cSrcweir {
1899*cdf0e10cSrcweir     ImplTileInfo() : aTileTopLeft(), aNextTileTopLeft(), aTileSizePixel(), nTilesEmptyX(0), nTilesEmptyY(0) {}
1900*cdf0e10cSrcweir 
1901*cdf0e10cSrcweir     Point aTileTopLeft;   	// top, left position of the rendered tile
1902*cdf0e10cSrcweir     Point aNextTileTopLeft; // top, left position for next recursion
1903*cdf0e10cSrcweir                             // level's tile
1904*cdf0e10cSrcweir     Size  aTileSizePixel;   // size of the generated tile (might
1905*cdf0e10cSrcweir                             // differ from
1906*cdf0e10cSrcweir                             // aNextTileTopLeft-aTileTopLeft, because
1907*cdf0e10cSrcweir                             // this is nExponent*prevTileSize. The
1908*cdf0e10cSrcweir                             // generated tile is always nExponent
1909*cdf0e10cSrcweir                             // times the previous tile, such that it
1910*cdf0e10cSrcweir                             // can be used in the next stage. The
1911*cdf0e10cSrcweir                             // required area coverage is often
1912*cdf0e10cSrcweir                             // less. The extraneous area covered is
1913*cdf0e10cSrcweir                             // later overwritten by the next stage)
1914*cdf0e10cSrcweir     int	  nTilesEmptyX;     // number of original tiles empty right of
1915*cdf0e10cSrcweir                             // this tile. This counts from
1916*cdf0e10cSrcweir                             // aNextTileTopLeft, i.e. the additional
1917*cdf0e10cSrcweir                             // area covered by aTileSizePixel is not
1918*cdf0e10cSrcweir                             // considered here. This is for
1919*cdf0e10cSrcweir                             // unification purposes, as the iterative
1920*cdf0e10cSrcweir                             // calculation of the next level's empty
1921*cdf0e10cSrcweir                             // tiles has to be based on this value.
1922*cdf0e10cSrcweir     int	  nTilesEmptyY;     // as above, for Y
1923*cdf0e10cSrcweir };
1924*cdf0e10cSrcweir 
1925*cdf0e10cSrcweir 
1926*cdf0e10cSrcweir bool GraphicObject::ImplRenderTempTile( VirtualDevice& rVDev, int nExponent,
1927*cdf0e10cSrcweir                                         int nNumTilesX, int nNumTilesY,
1928*cdf0e10cSrcweir                                         const Size& rTileSizePixel,
1929*cdf0e10cSrcweir                                         const GraphicAttr* pAttr, sal_uLong nFlags )
1930*cdf0e10cSrcweir {
1931*cdf0e10cSrcweir     if( nExponent <= 1 )
1932*cdf0e10cSrcweir         return false;
1933*cdf0e10cSrcweir 
1934*cdf0e10cSrcweir     // determine MSB factor
1935*cdf0e10cSrcweir     int nMSBFactor( 1 );
1936*cdf0e10cSrcweir     while( nNumTilesX / nMSBFactor != 0 ||
1937*cdf0e10cSrcweir            nNumTilesY / nMSBFactor != 0 )
1938*cdf0e10cSrcweir     {
1939*cdf0e10cSrcweir         nMSBFactor *= nExponent;
1940*cdf0e10cSrcweir     }
1941*cdf0e10cSrcweir 
1942*cdf0e10cSrcweir     // one less
1943*cdf0e10cSrcweir     nMSBFactor /= nExponent;
1944*cdf0e10cSrcweir 
1945*cdf0e10cSrcweir     ImplTileInfo aTileInfo;
1946*cdf0e10cSrcweir 
1947*cdf0e10cSrcweir     // #105229# Switch off mapping (converting to logic and back to
1948*cdf0e10cSrcweir     // pixel might cause roundoff errors)
1949*cdf0e10cSrcweir     sal_Bool bOldMap( rVDev.IsMapModeEnabled() );
1950*cdf0e10cSrcweir     rVDev.EnableMapMode( sal_False );
1951*cdf0e10cSrcweir 
1952*cdf0e10cSrcweir     bool bRet( ImplRenderTileRecursive( rVDev, nExponent, nMSBFactor, nNumTilesX, nNumTilesY,
1953*cdf0e10cSrcweir                                         nNumTilesX, nNumTilesY, rTileSizePixel, pAttr, nFlags, aTileInfo ) );
1954*cdf0e10cSrcweir 
1955*cdf0e10cSrcweir     rVDev.EnableMapMode( bOldMap );
1956*cdf0e10cSrcweir 
1957*cdf0e10cSrcweir     return bRet;
1958*cdf0e10cSrcweir }
1959*cdf0e10cSrcweir 
1960*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1961*cdf0e10cSrcweir 
1962*cdf0e10cSrcweir // define for debug drawings
1963*cdf0e10cSrcweir //#define DBG_TEST
1964*cdf0e10cSrcweir 
1965*cdf0e10cSrcweir // see header comment. this works similar to base conversion of a
1966*cdf0e10cSrcweir // number, i.e. if the exponent is 10, then the number for every tile
1967*cdf0e10cSrcweir // size is given by the decimal place of the corresponding decimal
1968*cdf0e10cSrcweir // representation.
1969*cdf0e10cSrcweir bool GraphicObject::ImplRenderTileRecursive( VirtualDevice& rVDev, int nExponent, int nMSBFactor,
1970*cdf0e10cSrcweir                                              int nNumOrigTilesX, int nNumOrigTilesY,
1971*cdf0e10cSrcweir                                              int nRemainderTilesX, int nRemainderTilesY,
1972*cdf0e10cSrcweir                                              const Size& rTileSizePixel, const GraphicAttr* pAttr,
1973*cdf0e10cSrcweir                                              sal_uLong nFlags, ImplTileInfo& rTileInfo )
1974*cdf0e10cSrcweir {
1975*cdf0e10cSrcweir     // gets loaded with our tile bitmap
1976*cdf0e10cSrcweir     GraphicObject aTmpGraphic;
1977*cdf0e10cSrcweir 
1978*cdf0e10cSrcweir     // stores a flag that renders the zero'th tile position
1979*cdf0e10cSrcweir     // (i.e. (0,0)+rCurrPos) only if we're at the bottom of the
1980*cdf0e10cSrcweir     // recursion stack. All other position already have that tile
1981*cdf0e10cSrcweir     // rendered, because the lower levels painted their generated tile
1982*cdf0e10cSrcweir     // there.
1983*cdf0e10cSrcweir     bool bNoFirstTileDraw( false );
1984*cdf0e10cSrcweir 
1985*cdf0e10cSrcweir     // what's left when we're done with our tile size
1986*cdf0e10cSrcweir     const int nNewRemainderX( nRemainderTilesX % nMSBFactor );
1987*cdf0e10cSrcweir     const int nNewRemainderY( nRemainderTilesY % nMSBFactor );
1988*cdf0e10cSrcweir 
1989*cdf0e10cSrcweir     // gets filled out from the recursive call with info of what's
1990*cdf0e10cSrcweir     // been generated
1991*cdf0e10cSrcweir     ImplTileInfo aTileInfo;
1992*cdf0e10cSrcweir 
1993*cdf0e10cSrcweir     // current output position while drawing
1994*cdf0e10cSrcweir     Point aCurrPos;
1995*cdf0e10cSrcweir     int nX, nY;
1996*cdf0e10cSrcweir 
1997*cdf0e10cSrcweir     // check for recursion's end condition: LSB place reached?
1998*cdf0e10cSrcweir     if( nMSBFactor == 1 )
1999*cdf0e10cSrcweir     {
2000*cdf0e10cSrcweir         aTmpGraphic = *this;
2001*cdf0e10cSrcweir 
2002*cdf0e10cSrcweir         // set initial tile size -> orig size
2003*cdf0e10cSrcweir         aTileInfo.aTileSizePixel = rTileSizePixel;
2004*cdf0e10cSrcweir         aTileInfo.nTilesEmptyX = nNumOrigTilesX;
2005*cdf0e10cSrcweir         aTileInfo.nTilesEmptyY = nNumOrigTilesY;
2006*cdf0e10cSrcweir     }
2007*cdf0e10cSrcweir     else if( ImplRenderTileRecursive( rVDev, nExponent, nMSBFactor/nExponent,
2008*cdf0e10cSrcweir                                       nNumOrigTilesX, nNumOrigTilesY,
2009*cdf0e10cSrcweir                                       nNewRemainderX, nNewRemainderY,
2010*cdf0e10cSrcweir                                       rTileSizePixel, pAttr, nFlags, aTileInfo ) )
2011*cdf0e10cSrcweir     {
2012*cdf0e10cSrcweir         // extract generated tile -> see comment on the first loop below
2013*cdf0e10cSrcweir         BitmapEx aTileBitmap( rVDev.GetBitmap( aTileInfo.aTileTopLeft, aTileInfo.aTileSizePixel ) );
2014*cdf0e10cSrcweir 
2015*cdf0e10cSrcweir         aTmpGraphic = GraphicObject( aTileBitmap );
2016*cdf0e10cSrcweir 
2017*cdf0e10cSrcweir         // fill stripes left over from upstream levels:
2018*cdf0e10cSrcweir         //
2019*cdf0e10cSrcweir         //  x0000
2020*cdf0e10cSrcweir         //  0
2021*cdf0e10cSrcweir         //  0
2022*cdf0e10cSrcweir         //  0
2023*cdf0e10cSrcweir         //  0
2024*cdf0e10cSrcweir         //
2025*cdf0e10cSrcweir         // where x denotes the place filled by our recursive predecessors
2026*cdf0e10cSrcweir 
2027*cdf0e10cSrcweir         // check whether we have to fill stripes here. Although not
2028*cdf0e10cSrcweir         // obvious, there is one case where we can skip this step: if
2029*cdf0e10cSrcweir         // the previous recursion level (the one who filled our
2030*cdf0e10cSrcweir         // aTileInfo) had zero area to fill, then there are no white
2031*cdf0e10cSrcweir         // stripes left, naturally. This happens if the digit
2032*cdf0e10cSrcweir         // associated to that level has a zero, and can be checked via
2033*cdf0e10cSrcweir         // aTileTopLeft==aNextTileTopLeft.
2034*cdf0e10cSrcweir         if( aTileInfo.aTileTopLeft != aTileInfo.aNextTileTopLeft )
2035*cdf0e10cSrcweir         {
2036*cdf0e10cSrcweir             // now fill one row from aTileInfo.aNextTileTopLeft.X() all
2037*cdf0e10cSrcweir             // the way to the right
2038*cdf0e10cSrcweir             aCurrPos.X() = aTileInfo.aNextTileTopLeft.X();
2039*cdf0e10cSrcweir             aCurrPos.Y() = aTileInfo.aTileTopLeft.Y();
2040*cdf0e10cSrcweir             for( nX=0; nX < aTileInfo.nTilesEmptyX; nX += nMSBFactor )
2041*cdf0e10cSrcweir             {
2042*cdf0e10cSrcweir                 if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) )
2043*cdf0e10cSrcweir                     return false;
2044*cdf0e10cSrcweir 
2045*cdf0e10cSrcweir                 aCurrPos.X() += aTileInfo.aTileSizePixel.Width();
2046*cdf0e10cSrcweir             }
2047*cdf0e10cSrcweir 
2048*cdf0e10cSrcweir #ifdef DBG_TEST
2049*cdf0e10cSrcweir //    		rVDev.SetFillColor( COL_WHITE );
2050*cdf0e10cSrcweir             rVDev.SetFillColor();
2051*cdf0e10cSrcweir             rVDev.SetLineColor( Color( 255 * nExponent / nMSBFactor, 255 - 255 * nExponent / nMSBFactor, 128 - 255 * nExponent / nMSBFactor ) );
2052*cdf0e10cSrcweir             rVDev.DrawEllipse( Rectangle(aTileInfo.aNextTileTopLeft.X(), aTileInfo.aTileTopLeft.Y(),
2053*cdf0e10cSrcweir                                          aTileInfo.aNextTileTopLeft.X() - 1 + (aTileInfo.nTilesEmptyX/nMSBFactor)*aTileInfo.aTileSizePixel.Width(),
2054*cdf0e10cSrcweir                                          aTileInfo.aTileTopLeft.Y() + aTileInfo.aTileSizePixel.Height() - 1) );
2055*cdf0e10cSrcweir #endif
2056*cdf0e10cSrcweir 
2057*cdf0e10cSrcweir             // now fill one column from aTileInfo.aNextTileTopLeft.Y() all
2058*cdf0e10cSrcweir             // the way to the bottom
2059*cdf0e10cSrcweir             aCurrPos.X() = aTileInfo.aTileTopLeft.X();
2060*cdf0e10cSrcweir             aCurrPos.Y() = aTileInfo.aNextTileTopLeft.Y();
2061*cdf0e10cSrcweir             for( nY=0; nY < aTileInfo.nTilesEmptyY; nY += nMSBFactor )
2062*cdf0e10cSrcweir             {
2063*cdf0e10cSrcweir                 if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) )
2064*cdf0e10cSrcweir                     return false;
2065*cdf0e10cSrcweir 
2066*cdf0e10cSrcweir                 aCurrPos.Y() += aTileInfo.aTileSizePixel.Height();
2067*cdf0e10cSrcweir             }
2068*cdf0e10cSrcweir 
2069*cdf0e10cSrcweir #ifdef DBG_TEST
2070*cdf0e10cSrcweir             rVDev.DrawEllipse( Rectangle(aTileInfo.aTileTopLeft.X(), aTileInfo.aNextTileTopLeft.Y(),
2071*cdf0e10cSrcweir                                          aTileInfo.aTileTopLeft.X() + aTileInfo.aTileSizePixel.Width() - 1,
2072*cdf0e10cSrcweir                                          aTileInfo.aNextTileTopLeft.Y() - 1 + (aTileInfo.nTilesEmptyY/nMSBFactor)*aTileInfo.aTileSizePixel.Height()) );
2073*cdf0e10cSrcweir #endif
2074*cdf0e10cSrcweir         }
2075*cdf0e10cSrcweir         else
2076*cdf0e10cSrcweir         {
2077*cdf0e10cSrcweir             // Thought that aTileInfo.aNextTileTopLeft tile has always
2078*cdf0e10cSrcweir             // been drawn already, but that's wrong: typically,
2079*cdf0e10cSrcweir             // _parts_ of that tile have been drawn, since the
2080*cdf0e10cSrcweir             // previous level generated the tile there. But when
2081*cdf0e10cSrcweir             // aTileInfo.aNextTileTopLeft!=aTileInfo.aTileTopLeft, the
2082*cdf0e10cSrcweir             // difference between these two values is missing in the
2083*cdf0e10cSrcweir             // lower right corner of this first tile. So, can do that
2084*cdf0e10cSrcweir             // only here.
2085*cdf0e10cSrcweir             bNoFirstTileDraw = true;
2086*cdf0e10cSrcweir         }
2087*cdf0e10cSrcweir     }
2088*cdf0e10cSrcweir     else
2089*cdf0e10cSrcweir     {
2090*cdf0e10cSrcweir         return false;
2091*cdf0e10cSrcweir     }
2092*cdf0e10cSrcweir 
2093*cdf0e10cSrcweir     // calc number of original tiles in our drawing area without
2094*cdf0e10cSrcweir     // remainder
2095*cdf0e10cSrcweir     nRemainderTilesX -= nNewRemainderX;
2096*cdf0e10cSrcweir     nRemainderTilesY -= nNewRemainderY;
2097*cdf0e10cSrcweir 
2098*cdf0e10cSrcweir     // fill tile info for calling method
2099*cdf0e10cSrcweir     rTileInfo.aTileTopLeft 	   = aTileInfo.aNextTileTopLeft;
2100*cdf0e10cSrcweir     rTileInfo.aNextTileTopLeft = Point( rTileInfo.aTileTopLeft.X() + rTileSizePixel.Width()*nRemainderTilesX,
2101*cdf0e10cSrcweir                                         rTileInfo.aTileTopLeft.Y() + rTileSizePixel.Height()*nRemainderTilesY );
2102*cdf0e10cSrcweir     rTileInfo.aTileSizePixel   = Size( rTileSizePixel.Width()*nMSBFactor*nExponent,
2103*cdf0e10cSrcweir                                        rTileSizePixel.Height()*nMSBFactor*nExponent );
2104*cdf0e10cSrcweir     rTileInfo.nTilesEmptyX	   = aTileInfo.nTilesEmptyX - nRemainderTilesX;
2105*cdf0e10cSrcweir     rTileInfo.nTilesEmptyY	   = aTileInfo.nTilesEmptyY - nRemainderTilesY;
2106*cdf0e10cSrcweir 
2107*cdf0e10cSrcweir     // init output position
2108*cdf0e10cSrcweir     aCurrPos = aTileInfo.aNextTileTopLeft;
2109*cdf0e10cSrcweir 
2110*cdf0e10cSrcweir     // fill our drawing area. Fill possibly more, to create the next
2111*cdf0e10cSrcweir     // bigger tile size -> see bitmap extraction above. This does no
2112*cdf0e10cSrcweir     // harm, since everything right or below our actual area is
2113*cdf0e10cSrcweir     // overdrawn by our caller. Just in case we're in the last level,
2114*cdf0e10cSrcweir     // we don't draw beyond the right or bottom border.
2115*cdf0e10cSrcweir     for( nY=0; nY < aTileInfo.nTilesEmptyY && nY < nExponent*nMSBFactor; nY += nMSBFactor )
2116*cdf0e10cSrcweir     {
2117*cdf0e10cSrcweir         aCurrPos.X() = aTileInfo.aNextTileTopLeft.X();
2118*cdf0e10cSrcweir 
2119*cdf0e10cSrcweir         for( nX=0; nX < aTileInfo.nTilesEmptyX && nX < nExponent*nMSBFactor; nX += nMSBFactor )
2120*cdf0e10cSrcweir         {
2121*cdf0e10cSrcweir             if( bNoFirstTileDraw )
2122*cdf0e10cSrcweir                 bNoFirstTileDraw = false; // don't draw first tile position
2123*cdf0e10cSrcweir             else if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) )
2124*cdf0e10cSrcweir                 return false;
2125*cdf0e10cSrcweir 
2126*cdf0e10cSrcweir             aCurrPos.X() += aTileInfo.aTileSizePixel.Width();
2127*cdf0e10cSrcweir         }
2128*cdf0e10cSrcweir 
2129*cdf0e10cSrcweir         aCurrPos.Y() += aTileInfo.aTileSizePixel.Height();
2130*cdf0e10cSrcweir     }
2131*cdf0e10cSrcweir 
2132*cdf0e10cSrcweir #ifdef DBG_TEST
2133*cdf0e10cSrcweir //  rVDev.SetFillColor( COL_WHITE );
2134*cdf0e10cSrcweir     rVDev.SetFillColor();
2135*cdf0e10cSrcweir     rVDev.SetLineColor( Color( 255 * nExponent / nMSBFactor, 255 - 255 * nExponent / nMSBFactor, 128 - 255 * nExponent / nMSBFactor ) );
2136*cdf0e10cSrcweir     rVDev.DrawRect( Rectangle((rTileInfo.aTileTopLeft.X())*rTileSizePixel.Width(),
2137*cdf0e10cSrcweir                               (rTileInfo.aTileTopLeft.Y())*rTileSizePixel.Height(),
2138*cdf0e10cSrcweir                               (rTileInfo.aNextTileTopLeft.X())*rTileSizePixel.Width()-1,
2139*cdf0e10cSrcweir                               (rTileInfo.aNextTileTopLeft.Y())*rTileSizePixel.Height()-1) );
2140*cdf0e10cSrcweir #endif
2141*cdf0e10cSrcweir 
2142*cdf0e10cSrcweir     return true;
2143*cdf0e10cSrcweir }
2144*cdf0e10cSrcweir 
2145*cdf0e10cSrcweir // -----------------------------------------------------------------------------
2146*cdf0e10cSrcweir 
2147*cdf0e10cSrcweir bool GraphicObject::ImplDrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSizePixel,
2148*cdf0e10cSrcweir                                    const Size& rOffset, const GraphicAttr* pAttr, sal_uLong nFlags, int nTileCacheSize1D )
2149*cdf0e10cSrcweir {
2150*cdf0e10cSrcweir     // how many tiles to generate per recursion step
2151*cdf0e10cSrcweir     enum{ SubdivisionExponent=2 };
2152*cdf0e10cSrcweir 
2153*cdf0e10cSrcweir     const MapMode 	aOutMapMode( pOut->GetMapMode() );
2154*cdf0e10cSrcweir     const MapMode	aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() );
2155*cdf0e10cSrcweir     bool 			bRet( false );
2156*cdf0e10cSrcweir 
2157*cdf0e10cSrcweir     // #i42643# Casting to Int64, to avoid integer overflow for
2158*cdf0e10cSrcweir     // huge-DPI output devices
2159*cdf0e10cSrcweir     if( GetGraphic().GetType() == GRAPHIC_BITMAP &&
2160*cdf0e10cSrcweir         static_cast<sal_Int64>(rSizePixel.Width()) * rSizePixel.Height() <
2161*cdf0e10cSrcweir         static_cast<sal_Int64>(nTileCacheSize1D)*nTileCacheSize1D )
2162*cdf0e10cSrcweir     {
2163*cdf0e10cSrcweir         // First combine very small bitmaps into a larger tile
2164*cdf0e10cSrcweir         // ===================================================
2165*cdf0e10cSrcweir 
2166*cdf0e10cSrcweir         VirtualDevice	aVDev;
2167*cdf0e10cSrcweir         const int		nNumTilesInCacheX( (nTileCacheSize1D + rSizePixel.Width()-1) / rSizePixel.Width() );
2168*cdf0e10cSrcweir         const int		nNumTilesInCacheY( (nTileCacheSize1D + rSizePixel.Height()-1) / rSizePixel.Height() );
2169*cdf0e10cSrcweir 
2170*cdf0e10cSrcweir         aVDev.SetOutputSizePixel( Size( nNumTilesInCacheX*rSizePixel.Width(),
2171*cdf0e10cSrcweir                                         nNumTilesInCacheY*rSizePixel.Height() ) );
2172*cdf0e10cSrcweir         aVDev.SetMapMode( aMapMode );
2173*cdf0e10cSrcweir 
2174*cdf0e10cSrcweir         // draw bitmap content
2175*cdf0e10cSrcweir         if( ImplRenderTempTile( aVDev, SubdivisionExponent, nNumTilesInCacheX,
2176*cdf0e10cSrcweir                                 nNumTilesInCacheY, rSizePixel, pAttr, nFlags ) )
2177*cdf0e10cSrcweir         {
2178*cdf0e10cSrcweir             BitmapEx aTileBitmap( aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ) );
2179*cdf0e10cSrcweir 
2180*cdf0e10cSrcweir             // draw alpha content, if any
2181*cdf0e10cSrcweir             if( IsTransparent() )
2182*cdf0e10cSrcweir             {
2183*cdf0e10cSrcweir                 GraphicObject aAlphaGraphic;
2184*cdf0e10cSrcweir 
2185*cdf0e10cSrcweir                 if( GetGraphic().IsAlpha() )
2186*cdf0e10cSrcweir                     aAlphaGraphic.SetGraphic( GetGraphic().GetBitmapEx().GetAlpha().GetBitmap() );
2187*cdf0e10cSrcweir                 else
2188*cdf0e10cSrcweir                     aAlphaGraphic.SetGraphic( GetGraphic().GetBitmapEx().GetMask() );
2189*cdf0e10cSrcweir 
2190*cdf0e10cSrcweir                 if( aAlphaGraphic.ImplRenderTempTile( aVDev, SubdivisionExponent, nNumTilesInCacheX,
2191*cdf0e10cSrcweir                                                       nNumTilesInCacheY, rSizePixel, pAttr, nFlags ) )
2192*cdf0e10cSrcweir                 {
2193*cdf0e10cSrcweir                     // Combine bitmap and alpha/mask
2194*cdf0e10cSrcweir                     if( GetGraphic().IsAlpha() )
2195*cdf0e10cSrcweir                         aTileBitmap = BitmapEx( aTileBitmap.GetBitmap(),
2196*cdf0e10cSrcweir                                                 AlphaMask( aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ) ) );
2197*cdf0e10cSrcweir                     else
2198*cdf0e10cSrcweir                         aTileBitmap = BitmapEx( aTileBitmap.GetBitmap(),
2199*cdf0e10cSrcweir                                                 aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ).CreateMask( Color(COL_WHITE) ) );
2200*cdf0e10cSrcweir                 }
2201*cdf0e10cSrcweir             }
2202*cdf0e10cSrcweir 
2203*cdf0e10cSrcweir             // paint generated tile
2204*cdf0e10cSrcweir             GraphicObject aTmpGraphic( aTileBitmap );
2205*cdf0e10cSrcweir             bRet = aTmpGraphic.ImplDrawTiled( pOut, rArea,
2206*cdf0e10cSrcweir                                               aTileBitmap.GetSizePixel(),
2207*cdf0e10cSrcweir                                               rOffset, pAttr, nFlags, nTileCacheSize1D );
2208*cdf0e10cSrcweir         }
2209*cdf0e10cSrcweir     }
2210*cdf0e10cSrcweir     else
2211*cdf0e10cSrcweir     {
2212*cdf0e10cSrcweir         const Size		aOutOffset( pOut->LogicToPixel( rOffset, aOutMapMode ) );
2213*cdf0e10cSrcweir         const Rectangle	aOutArea( pOut->LogicToPixel( rArea, aOutMapMode ) );
2214*cdf0e10cSrcweir 
2215*cdf0e10cSrcweir         // number of invisible (because out-of-area) tiles
2216*cdf0e10cSrcweir         int nInvisibleTilesX;
2217*cdf0e10cSrcweir         int nInvisibleTilesY;
2218*cdf0e10cSrcweir 
2219*cdf0e10cSrcweir         // round towards -infty for negative offset
2220*cdf0e10cSrcweir         if( aOutOffset.Width() < 0 )
2221*cdf0e10cSrcweir             nInvisibleTilesX = (aOutOffset.Width() - rSizePixel.Width() + 1) / rSizePixel.Width();
2222*cdf0e10cSrcweir         else
2223*cdf0e10cSrcweir             nInvisibleTilesX = aOutOffset.Width() / rSizePixel.Width();
2224*cdf0e10cSrcweir 
2225*cdf0e10cSrcweir         // round towards -infty for negative offset
2226*cdf0e10cSrcweir         if( aOutOffset.Height() < 0 )
2227*cdf0e10cSrcweir             nInvisibleTilesY = (aOutOffset.Height() - rSizePixel.Height() + 1) / rSizePixel.Height();
2228*cdf0e10cSrcweir         else
2229*cdf0e10cSrcweir             nInvisibleTilesY = aOutOffset.Height() / rSizePixel.Height();
2230*cdf0e10cSrcweir 
2231*cdf0e10cSrcweir         // origin from where to 'virtually' start drawing in pixel
2232*cdf0e10cSrcweir         const Point aOutOrigin( pOut->LogicToPixel( Point( rArea.Left() - rOffset.Width(),
2233*cdf0e10cSrcweir                                                            rArea.Top() - rOffset.Height() ) ) );
2234*cdf0e10cSrcweir         // position in pixel from where to really start output
2235*cdf0e10cSrcweir         const Point aOutStart( aOutOrigin.X() + nInvisibleTilesX*rSizePixel.Width(),
2236*cdf0e10cSrcweir                                aOutOrigin.Y() + nInvisibleTilesY*rSizePixel.Height() );
2237*cdf0e10cSrcweir 
2238*cdf0e10cSrcweir         pOut->Push( PUSH_CLIPREGION );
2239*cdf0e10cSrcweir         pOut->IntersectClipRegion( rArea );
2240*cdf0e10cSrcweir 
2241*cdf0e10cSrcweir         // Paint all tiles
2242*cdf0e10cSrcweir         // ===============
2243*cdf0e10cSrcweir 
2244*cdf0e10cSrcweir         bRet = ImplDrawTiled( *pOut, aOutStart,
2245*cdf0e10cSrcweir                               (aOutArea.GetWidth() + aOutArea.Left() - aOutStart.X() + rSizePixel.Width() - 1) / rSizePixel.Width(),
2246*cdf0e10cSrcweir                               (aOutArea.GetHeight() + aOutArea.Top() - aOutStart.Y() + rSizePixel.Height() - 1) / rSizePixel.Height(),
2247*cdf0e10cSrcweir                               rSizePixel, pAttr, nFlags );
2248*cdf0e10cSrcweir 
2249*cdf0e10cSrcweir         pOut->Pop();
2250*cdf0e10cSrcweir     }
2251*cdf0e10cSrcweir 
2252*cdf0e10cSrcweir     return bRet;
2253*cdf0e10cSrcweir }
2254*cdf0e10cSrcweir 
2255*cdf0e10cSrcweir // -----------------------------------------------------------------------------
2256*cdf0e10cSrcweir 
2257*cdf0e10cSrcweir bool GraphicObject::ImplDrawTiled( OutputDevice& rOut, const Point& rPosPixel,
2258*cdf0e10cSrcweir                                    int nNumTilesX, int nNumTilesY,
2259*cdf0e10cSrcweir                                    const Size& rTileSizePixel, const GraphicAttr* pAttr, sal_uLong nFlags )
2260*cdf0e10cSrcweir {
2261*cdf0e10cSrcweir     Point 	aCurrPos( rPosPixel );
2262*cdf0e10cSrcweir     Size	aTileSizeLogic( rOut.PixelToLogic( rTileSizePixel ) );
2263*cdf0e10cSrcweir     int 	nX, nY;
2264*cdf0e10cSrcweir 
2265*cdf0e10cSrcweir     // #107607# Use logical coordinates for metafile playing, too
2266*cdf0e10cSrcweir     bool	bDrawInPixel( rOut.GetConnectMetaFile() == NULL && GRAPHIC_BITMAP == GetType() );
2267*cdf0e10cSrcweir     sal_Bool	bRet( sal_False );
2268*cdf0e10cSrcweir 
2269*cdf0e10cSrcweir     // #105229# Switch off mapping (converting to logic and back to
2270*cdf0e10cSrcweir     // pixel might cause roundoff errors)
2271*cdf0e10cSrcweir     sal_Bool bOldMap( rOut.IsMapModeEnabled() );
2272*cdf0e10cSrcweir 
2273*cdf0e10cSrcweir     if( bDrawInPixel )
2274*cdf0e10cSrcweir         rOut.EnableMapMode( sal_False );
2275*cdf0e10cSrcweir 
2276*cdf0e10cSrcweir     for( nY=0; nY < nNumTilesY; ++nY )
2277*cdf0e10cSrcweir     {
2278*cdf0e10cSrcweir         aCurrPos.X() = rPosPixel.X();
2279*cdf0e10cSrcweir 
2280*cdf0e10cSrcweir         for( nX=0; nX < nNumTilesX; ++nX )
2281*cdf0e10cSrcweir         {
2282*cdf0e10cSrcweir             // #105229# work with pixel coordinates here, mapping is disabled!
2283*cdf0e10cSrcweir             // #104004# don't disable mapping for metafile recordings
2284*cdf0e10cSrcweir             // #108412# don't quit the loop if one draw fails
2285*cdf0e10cSrcweir 
2286*cdf0e10cSrcweir             // update return value. This method should return true, if
2287*cdf0e10cSrcweir             // at least one of the looped Draws succeeded.
2288*cdf0e10cSrcweir             bRet |= Draw( &rOut,
2289*cdf0e10cSrcweir                           bDrawInPixel ? aCurrPos : rOut.PixelToLogic( aCurrPos ),
2290*cdf0e10cSrcweir                           bDrawInPixel ? rTileSizePixel : aTileSizeLogic,
2291*cdf0e10cSrcweir                           pAttr, nFlags );
2292*cdf0e10cSrcweir 
2293*cdf0e10cSrcweir             aCurrPos.X() += rTileSizePixel.Width();
2294*cdf0e10cSrcweir         }
2295*cdf0e10cSrcweir 
2296*cdf0e10cSrcweir         aCurrPos.Y() += rTileSizePixel.Height();
2297*cdf0e10cSrcweir     }
2298*cdf0e10cSrcweir 
2299*cdf0e10cSrcweir     if( bDrawInPixel )
2300*cdf0e10cSrcweir         rOut.EnableMapMode( bOldMap );
2301*cdf0e10cSrcweir 
2302*cdf0e10cSrcweir     return bRet;
2303*cdf0e10cSrcweir }
2304*cdf0e10cSrcweir 
2305*cdf0e10cSrcweir // -----------------------------------------------------------------------------
2306*cdf0e10cSrcweir 
2307*cdf0e10cSrcweir void GraphicObject::ImplTransformBitmap( BitmapEx& 			rBmpEx,
2308*cdf0e10cSrcweir                                          const GraphicAttr& rAttr,
2309*cdf0e10cSrcweir                                          const Size&		rCropLeftTop,
2310*cdf0e10cSrcweir                                          const Size&		rCropRightBottom,
2311*cdf0e10cSrcweir                                          const Rectangle&	rCropRect,
2312*cdf0e10cSrcweir                                          const Size& 		rDstSize,
2313*cdf0e10cSrcweir                                          sal_Bool				bEnlarge ) const
2314*cdf0e10cSrcweir {
2315*cdf0e10cSrcweir     // #107947# Extracted from svdograf.cxx
2316*cdf0e10cSrcweir 
2317*cdf0e10cSrcweir     // #104115# Crop the bitmap
2318*cdf0e10cSrcweir     if( rAttr.IsCropped() )
2319*cdf0e10cSrcweir     {
2320*cdf0e10cSrcweir         rBmpEx.Crop( rCropRect );
2321*cdf0e10cSrcweir 
2322*cdf0e10cSrcweir         // #104115# Negative crop sizes mean: enlarge bitmap and pad
2323*cdf0e10cSrcweir         if( bEnlarge && (
2324*cdf0e10cSrcweir             rCropLeftTop.Width() < 0 ||
2325*cdf0e10cSrcweir             rCropLeftTop.Height() < 0 ||
2326*cdf0e10cSrcweir             rCropRightBottom.Width() < 0 ||
2327*cdf0e10cSrcweir             rCropRightBottom.Height() < 0 ) )
2328*cdf0e10cSrcweir         {
2329*cdf0e10cSrcweir             Size aBmpSize( rBmpEx.GetSizePixel() );
2330*cdf0e10cSrcweir             sal_Int32 nPadLeft( rCropLeftTop.Width() < 0 ? -rCropLeftTop.Width() : 0 );
2331*cdf0e10cSrcweir             sal_Int32 nPadTop( rCropLeftTop.Height() < 0 ? -rCropLeftTop.Height() : 0 );
2332*cdf0e10cSrcweir             sal_Int32 nPadTotalWidth( aBmpSize.Width() + nPadLeft + (rCropRightBottom.Width() < 0 ? -rCropRightBottom.Width() : 0) );
2333*cdf0e10cSrcweir             sal_Int32 nPadTotalHeight( aBmpSize.Height() + nPadTop + (rCropRightBottom.Height() < 0 ? -rCropRightBottom.Height() : 0) );
2334*cdf0e10cSrcweir 
2335*cdf0e10cSrcweir             BitmapEx aBmpEx2;
2336*cdf0e10cSrcweir 
2337*cdf0e10cSrcweir             if( rBmpEx.IsTransparent() )
2338*cdf0e10cSrcweir             {
2339*cdf0e10cSrcweir                 if( rBmpEx.IsAlpha() )
2340*cdf0e10cSrcweir                     aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetAlpha() );
2341*cdf0e10cSrcweir                 else
2342*cdf0e10cSrcweir                     aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetMask() );
2343*cdf0e10cSrcweir             }
2344*cdf0e10cSrcweir             else
2345*cdf0e10cSrcweir             {
2346*cdf0e10cSrcweir                 // #104115# Generate mask bitmap and init to zero
2347*cdf0e10cSrcweir                 Bitmap aMask( aBmpSize, 1 );
2348*cdf0e10cSrcweir                 aMask.Erase( Color(0,0,0) );
2349*cdf0e10cSrcweir 
2350*cdf0e10cSrcweir                 // #104115# Always generate transparent bitmap, we need the border transparent
2351*cdf0e10cSrcweir                 aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), aMask );
2352*cdf0e10cSrcweir 
2353*cdf0e10cSrcweir                 // #104115# Add opaque mask to source bitmap, otherwise the destination remains transparent
2354*cdf0e10cSrcweir                 rBmpEx = aBmpEx2;
2355*cdf0e10cSrcweir             }
2356*cdf0e10cSrcweir 
2357*cdf0e10cSrcweir             aBmpEx2.SetSizePixel( Size(nPadTotalWidth, nPadTotalHeight) );
2358*cdf0e10cSrcweir             aBmpEx2.Erase( Color(0xFF,0,0,0) );
2359*cdf0e10cSrcweir             aBmpEx2.CopyPixel( Rectangle( Point(nPadLeft, nPadTop), aBmpSize ), Rectangle( Point(0, 0), aBmpSize ), &rBmpEx );
2360*cdf0e10cSrcweir             rBmpEx = aBmpEx2;
2361*cdf0e10cSrcweir         }
2362*cdf0e10cSrcweir     }
2363*cdf0e10cSrcweir 
2364*cdf0e10cSrcweir     const Size 	aSizePixel( rBmpEx.GetSizePixel() );
2365*cdf0e10cSrcweir 
2366*cdf0e10cSrcweir     if( rAttr.GetRotation() != 0 && !IsAnimated() )
2367*cdf0e10cSrcweir     {
2368*cdf0e10cSrcweir         if( aSizePixel.Width() && aSizePixel.Height() && rDstSize.Width() && rDstSize.Height() )
2369*cdf0e10cSrcweir         {
2370*cdf0e10cSrcweir             double fSrcWH = (double) aSizePixel.Width() / aSizePixel.Height();
2371*cdf0e10cSrcweir             double fDstWH = (double) rDstSize.Width() / rDstSize.Height();
2372*cdf0e10cSrcweir             double fScaleX = 1.0, fScaleY = 1.0;
2373*cdf0e10cSrcweir 
2374*cdf0e10cSrcweir             // always choose scaling to shrink bitmap
2375*cdf0e10cSrcweir             if( fSrcWH < fDstWH )
2376*cdf0e10cSrcweir                 fScaleY = aSizePixel.Width() / ( fDstWH * aSizePixel.Height() );
2377*cdf0e10cSrcweir             else
2378*cdf0e10cSrcweir                 fScaleX = fDstWH * aSizePixel.Height() / aSizePixel.Width();
2379*cdf0e10cSrcweir 
2380*cdf0e10cSrcweir             rBmpEx.Scale( fScaleX, fScaleY );
2381*cdf0e10cSrcweir         }
2382*cdf0e10cSrcweir     }
2383*cdf0e10cSrcweir }
2384