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