xref: /AOO41X/main/vcl/win/source/gdi/salbmp.cxx (revision 5f27b83cee6e25e8a00edc4ae51b88fe9d2801da)
19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
39f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
59f62ea84SAndrew Rist  * distributed with this work for additional information
69f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
79f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
139f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist  * software distributed under the License is distributed on an
159f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
179f62ea84SAndrew Rist  * specific language governing permissions and limitations
189f62ea84SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
209f62ea84SAndrew Rist  *************************************************************/
219f62ea84SAndrew Rist 
22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
23cdf0e10cSrcweir #include "precompiled_vcl.hxx"
24cdf0e10cSrcweir 
25cdf0e10cSrcweir #include <tools/svwin.h>
26cdf0e10cSrcweir #include <vcl/bitmap.hxx> // for BitmapSystemData
27cdf0e10cSrcweir #include <vcl/salbtype.hxx>
28cdf0e10cSrcweir #include <win/wincomp.hxx>
29cdf0e10cSrcweir #include <win/salgdi.h>
30cdf0e10cSrcweir #include <win/saldata.hxx>
31cdf0e10cSrcweir #include <win/salbmp.h>
32cdf0e10cSrcweir #include <string.h>
33*5f27b83cSArmin Le Grand #include <vcl/timer.hxx>
34*5f27b83cSArmin Le Grand #include <comphelper/broadcasthelper.hxx>
35*5f27b83cSArmin Le Grand #include <map>
36cdf0e10cSrcweir 
37*5f27b83cSArmin Le Grand #ifndef min
38*5f27b83cSArmin Le Grand #define min(a,b)	(((a) < (b)) ? (a) : (b))
39*5f27b83cSArmin Le Grand #endif
40*5f27b83cSArmin Le Grand #ifndef max
41*5f27b83cSArmin Le Grand #define max(a,b)	(((a) > (b)) ? (a) : (b))
42*5f27b83cSArmin Le Grand #endif
43*5f27b83cSArmin Le Grand 
44*5f27b83cSArmin Le Grand #include <GdiPlus.h>
45*5f27b83cSArmin Le Grand 
46*5f27b83cSArmin Le Grand // ------------------------------------------------------------------
47cdf0e10cSrcweir // - Inlines -
48cdf0e10cSrcweir 
49cdf0e10cSrcweir inline void ImplSetPixel4( const HPBYTE pScanline, long nX, const BYTE cIndex )
50cdf0e10cSrcweir {
51cdf0e10cSrcweir 	BYTE& rByte = pScanline[ nX >> 1 ];
52cdf0e10cSrcweir 
53cdf0e10cSrcweir 	( nX & 1 ) ? ( rByte &= 0xf0, rByte |= ( cIndex & 0x0f ) ) :
54cdf0e10cSrcweir 				 ( rByte &= 0x0f, rByte |= ( cIndex << 4 ) );
55cdf0e10cSrcweir }
56cdf0e10cSrcweir 
57*5f27b83cSArmin Le Grand // ------------------------------------------------------------------
58*5f27b83cSArmin Le Grand // Helper class to manage Gdiplus::Bitmap instances inside of
59*5f27b83cSArmin Le Grand // WinSalBitmap
60cdf0e10cSrcweir 
61*5f27b83cSArmin Le Grand struct Comparator
62*5f27b83cSArmin Le Grand {
63*5f27b83cSArmin Le Grand     bool operator()(WinSalBitmap* pA, WinSalBitmap* pB) const
64*5f27b83cSArmin Le Grand     {
65*5f27b83cSArmin Le Grand         return pA < pB;
66*5f27b83cSArmin Le Grand     }
67*5f27b83cSArmin Le Grand };
68*5f27b83cSArmin Le Grand 
69*5f27b83cSArmin Le Grand typedef ::std::map< WinSalBitmap*, sal_uInt32, Comparator > EntryMap;
70*5f27b83cSArmin Le Grand static const sal_uInt32 nDefaultCycles(60);
71*5f27b83cSArmin Le Grand 
72*5f27b83cSArmin Le Grand class GdiPlusBuffer : protected comphelper::OBaseMutex, public Timer
73*5f27b83cSArmin Le Grand {
74*5f27b83cSArmin Le Grand private:
75*5f27b83cSArmin Le Grand     EntryMap        maEntries;
76*5f27b83cSArmin Le Grand 
77*5f27b83cSArmin Le Grand public:
78*5f27b83cSArmin Le Grand     GdiPlusBuffer()
79*5f27b83cSArmin Le Grand     :   Timer(),
80*5f27b83cSArmin Le Grand         maEntries()
81*5f27b83cSArmin Le Grand     {
82*5f27b83cSArmin Le Grand         SetTimeout(1000);
83*5f27b83cSArmin Le Grand         Stop();
84*5f27b83cSArmin Le Grand     }
85*5f27b83cSArmin Le Grand 
86*5f27b83cSArmin Le Grand     ~GdiPlusBuffer()
87*5f27b83cSArmin Le Grand     {
88*5f27b83cSArmin Le Grand         Stop();
89*5f27b83cSArmin Le Grand     }
90*5f27b83cSArmin Le Grand 
91*5f27b83cSArmin Le Grand     void addEntry(WinSalBitmap& rEntry)
92*5f27b83cSArmin Le Grand     {
93*5f27b83cSArmin Le Grand         ::osl::MutexGuard aGuard(m_aMutex);
94*5f27b83cSArmin Le Grand         EntryMap::iterator aFound = maEntries.find(&rEntry);
95*5f27b83cSArmin Le Grand 
96*5f27b83cSArmin Le Grand         if(aFound == maEntries.end())
97*5f27b83cSArmin Le Grand         {
98*5f27b83cSArmin Le Grand             if(maEntries.empty())
99*5f27b83cSArmin Le Grand             {
100*5f27b83cSArmin Le Grand                 Start();
101*5f27b83cSArmin Le Grand             }
102*5f27b83cSArmin Le Grand 
103*5f27b83cSArmin Le Grand             maEntries[&rEntry] = nDefaultCycles;
104*5f27b83cSArmin Le Grand         }
105*5f27b83cSArmin Le Grand     }
106*5f27b83cSArmin Le Grand 
107*5f27b83cSArmin Le Grand     void remEntry(WinSalBitmap& rEntry)
108*5f27b83cSArmin Le Grand     {
109*5f27b83cSArmin Le Grand         ::osl::MutexGuard aGuard(m_aMutex);
110*5f27b83cSArmin Le Grand         EntryMap::iterator aFound = maEntries.find(&rEntry);
111*5f27b83cSArmin Le Grand 
112*5f27b83cSArmin Le Grand         if(aFound != maEntries.end())
113*5f27b83cSArmin Le Grand         {
114*5f27b83cSArmin Le Grand             maEntries.erase(aFound);
115*5f27b83cSArmin Le Grand 
116*5f27b83cSArmin Le Grand             if(maEntries.empty())
117*5f27b83cSArmin Le Grand             {
118*5f27b83cSArmin Le Grand                 Stop();
119*5f27b83cSArmin Le Grand             }
120*5f27b83cSArmin Le Grand         }
121*5f27b83cSArmin Le Grand     }
122*5f27b83cSArmin Le Grand 
123*5f27b83cSArmin Le Grand     void touchEntry(WinSalBitmap& rEntry)
124*5f27b83cSArmin Le Grand     {
125*5f27b83cSArmin Le Grand         ::osl::MutexGuard aGuard(m_aMutex);
126*5f27b83cSArmin Le Grand         EntryMap::iterator aFound = maEntries.find(&rEntry);
127*5f27b83cSArmin Le Grand 
128*5f27b83cSArmin Le Grand         if(aFound != maEntries.end())
129*5f27b83cSArmin Le Grand         {
130*5f27b83cSArmin Le Grand             aFound->second = nDefaultCycles;
131*5f27b83cSArmin Le Grand         }
132*5f27b83cSArmin Le Grand     }
133*5f27b83cSArmin Le Grand 
134*5f27b83cSArmin Le Grand     // from parent Timer
135*5f27b83cSArmin Le Grand     virtual void Timeout()
136*5f27b83cSArmin Le Grand     {
137*5f27b83cSArmin Le Grand         ::osl::MutexGuard aGuard(m_aMutex);
138*5f27b83cSArmin Le Grand         EntryMap::iterator aIter(maEntries.begin());
139*5f27b83cSArmin Le Grand 
140*5f27b83cSArmin Le Grand         while(aIter != maEntries.end())
141*5f27b83cSArmin Le Grand         {
142*5f27b83cSArmin Le Grand             if(aIter->second)
143*5f27b83cSArmin Le Grand             {
144*5f27b83cSArmin Le Grand                 aIter->second--;
145*5f27b83cSArmin Le Grand                 aIter++;
146*5f27b83cSArmin Le Grand             }
147*5f27b83cSArmin Le Grand             else
148*5f27b83cSArmin Le Grand             {
149*5f27b83cSArmin Le Grand                 EntryMap::iterator aDelete(aIter);
150*5f27b83cSArmin Le Grand                 WinSalBitmap* pSource = aDelete->first;
151*5f27b83cSArmin Le Grand                 aIter++;
152*5f27b83cSArmin Le Grand                 maEntries.erase(aDelete);
153*5f27b83cSArmin Le Grand 
154*5f27b83cSArmin Le Grand                 if(maEntries.empty())
155*5f27b83cSArmin Le Grand                 {
156*5f27b83cSArmin Le Grand                     Stop();
157*5f27b83cSArmin Le Grand                 }
158*5f27b83cSArmin Le Grand 
159*5f27b83cSArmin Le Grand                 // delete at WinSalBitmap after entry is removed; this
160*5f27b83cSArmin Le Grand                 // way it would not hurt to call remEntry from there, too
161*5f27b83cSArmin Le Grand                 if(pSource->maGdiPlusBitmap.get())
162*5f27b83cSArmin Le Grand                 {
163*5f27b83cSArmin Le Grand                     pSource->maGdiPlusBitmap.reset();
164*5f27b83cSArmin Le Grand                 }
165*5f27b83cSArmin Le Grand             }
166*5f27b83cSArmin Le Grand         }
167*5f27b83cSArmin Le Grand 
168*5f27b83cSArmin Le Grand         if(!maEntries.empty())
169*5f27b83cSArmin Le Grand         {
170*5f27b83cSArmin Le Grand             Start();
171*5f27b83cSArmin Le Grand         }
172*5f27b83cSArmin Le Grand     }
173*5f27b83cSArmin Le Grand };
174*5f27b83cSArmin Le Grand 
175*5f27b83cSArmin Le Grand // ------------------------------------------------------------------
176*5f27b83cSArmin Le Grand // Global instance of GdiPlusBuffer which manages Gdiplus::Bitmap
177*5f27b83cSArmin Le Grand // instances
178*5f27b83cSArmin Le Grand 
179*5f27b83cSArmin Le Grand static GdiPlusBuffer aGdiPlusBuffer;
180*5f27b83cSArmin Le Grand 
181*5f27b83cSArmin Le Grand // ------------------------------------------------------------------
182*5f27b83cSArmin Le Grand // - WinSalBitmap -
183*5f27b83cSArmin Le Grand 
184*5f27b83cSArmin Le Grand WinSalBitmap::WinSalBitmap()
185*5f27b83cSArmin Le Grand :   maSize(),
186cdf0e10cSrcweir     mhDIB(0),
187cdf0e10cSrcweir     mhDDB(0),
188*5f27b83cSArmin Le Grand     maGdiPlusBitmap(),
189cdf0e10cSrcweir     mnBitCount(0)
190cdf0e10cSrcweir {
191cdf0e10cSrcweir }
192cdf0e10cSrcweir 
193cdf0e10cSrcweir // ------------------------------------------------------------------
194cdf0e10cSrcweir 
195cdf0e10cSrcweir WinSalBitmap::~WinSalBitmap()
196cdf0e10cSrcweir {
197cdf0e10cSrcweir 	Destroy();
198cdf0e10cSrcweir }
199cdf0e10cSrcweir 
200cdf0e10cSrcweir // ------------------------------------------------------------------
201cdf0e10cSrcweir 
202*5f27b83cSArmin Le Grand void WinSalBitmap::Destroy()
203*5f27b83cSArmin Le Grand {
204*5f27b83cSArmin Le Grand     if(maGdiPlusBitmap.get())
205*5f27b83cSArmin Le Grand     {
206*5f27b83cSArmin Le Grand         aGdiPlusBuffer.remEntry(*this);
207*5f27b83cSArmin Le Grand     }
208*5f27b83cSArmin Le Grand 
209*5f27b83cSArmin Le Grand     if( mhDIB )
210*5f27b83cSArmin Le Grand 		GlobalFree( mhDIB );
211*5f27b83cSArmin Le Grand 	else if( mhDDB )
212*5f27b83cSArmin Le Grand 		DeleteObject( mhDDB );
213*5f27b83cSArmin Le Grand 
214*5f27b83cSArmin Le Grand 	maSize = Size();
215*5f27b83cSArmin Le Grand 	mnBitCount = 0;
216*5f27b83cSArmin Le Grand }
217*5f27b83cSArmin Le Grand 
218*5f27b83cSArmin Le Grand // ------------------------------------------------------------------
219*5f27b83cSArmin Le Grand 
220*5f27b83cSArmin Le Grand GdiPlusBmpPtr WinSalBitmap::ImplGetGdiPlusBitmap(const WinSalBitmap* pAlphaSource) const
221*5f27b83cSArmin Le Grand {
222*5f27b83cSArmin Le Grand     if(maGdiPlusBitmap.get())
223*5f27b83cSArmin Le Grand     {
224*5f27b83cSArmin Le Grand         aGdiPlusBuffer.touchEntry(const_cast< WinSalBitmap& >(*this));
225*5f27b83cSArmin Le Grand     }
226*5f27b83cSArmin Le Grand     else
227*5f27b83cSArmin Le Grand     {
228*5f27b83cSArmin Le Grand         if(maSize.Width() > 0 && maSize.Height() > 0)
229*5f27b83cSArmin Le Grand         {
230*5f27b83cSArmin Le Grand             WinSalBitmap* pThat = const_cast< WinSalBitmap* >(this);
231*5f27b83cSArmin Le Grand 
232*5f27b83cSArmin Le Grand             if(pAlphaSource)
233*5f27b83cSArmin Le Grand             {
234*5f27b83cSArmin Le Grand                 pThat->maGdiPlusBitmap.reset(pThat->ImplCreateGdiPlusBitmap(*pAlphaSource));
235*5f27b83cSArmin Le Grand             }
236*5f27b83cSArmin Le Grand             else
237*5f27b83cSArmin Le Grand             {
238*5f27b83cSArmin Le Grand                 pThat->maGdiPlusBitmap.reset(pThat->ImplCreateGdiPlusBitmap());
239*5f27b83cSArmin Le Grand             }
240*5f27b83cSArmin Le Grand 
241*5f27b83cSArmin Le Grand             if(maGdiPlusBitmap.get())
242*5f27b83cSArmin Le Grand             {
243*5f27b83cSArmin Le Grand                 aGdiPlusBuffer.addEntry(*pThat);
244*5f27b83cSArmin Le Grand             }
245*5f27b83cSArmin Le Grand         }
246*5f27b83cSArmin Le Grand     }
247*5f27b83cSArmin Le Grand 
248*5f27b83cSArmin Le Grand     return maGdiPlusBitmap;
249*5f27b83cSArmin Le Grand }
250*5f27b83cSArmin Le Grand 
251*5f27b83cSArmin Le Grand // ------------------------------------------------------------------
252*5f27b83cSArmin Le Grand 
253*5f27b83cSArmin Le Grand Gdiplus::Bitmap* WinSalBitmap::ImplCreateGdiPlusBitmap()
254*5f27b83cSArmin Le Grand {
255*5f27b83cSArmin Le Grand     Gdiplus::Bitmap* pRetval(0);
256*5f27b83cSArmin Le Grand     WinSalBitmap* pSalRGB = const_cast< WinSalBitmap* >(this);
257*5f27b83cSArmin Le Grand     WinSalBitmap* pExtraWinSalRGB = 0;
258*5f27b83cSArmin Le Grand 
259*5f27b83cSArmin Le Grand     if(!pSalRGB->ImplGethDIB())
260*5f27b83cSArmin Le Grand     {
261*5f27b83cSArmin Le Grand         // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap
262*5f27b83cSArmin Le Grand         pExtraWinSalRGB = new WinSalBitmap();
263*5f27b83cSArmin Le Grand         pExtraWinSalRGB->Create(*pSalRGB, pSalRGB->GetBitCount());
264*5f27b83cSArmin Le Grand         pSalRGB = pExtraWinSalRGB;
265*5f27b83cSArmin Le Grand     }
266*5f27b83cSArmin Le Grand 
267*5f27b83cSArmin Le Grand     BitmapBuffer* pRGB = pSalRGB->AcquireBuffer(true);
268*5f27b83cSArmin Le Grand     BitmapBuffer* pExtraRGB = 0;
269*5f27b83cSArmin Le Grand 
270*5f27b83cSArmin Le Grand     if(pRGB && BMP_FORMAT_24BIT_TC_BGR != (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN))
271*5f27b83cSArmin Le Grand     {
272*5f27b83cSArmin Le Grand         // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format
273*5f27b83cSArmin Le Grand         SalTwoRect aSalTwoRect;
274*5f27b83cSArmin Le Grand 
275*5f27b83cSArmin Le Grand         aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0;
276*5f27b83cSArmin Le Grand         aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pRGB->mnWidth;
277*5f27b83cSArmin Le Grand         aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pRGB->mnHeight;
278*5f27b83cSArmin Le Grand 
279*5f27b83cSArmin Le Grand         pExtraRGB = StretchAndConvert(
280*5f27b83cSArmin Le Grand             *pRGB,
281*5f27b83cSArmin Le Grand             aSalTwoRect,
282*5f27b83cSArmin Le Grand             BMP_FORMAT_24BIT_TC_BGR,
283*5f27b83cSArmin Le Grand             0);
284*5f27b83cSArmin Le Grand 
285*5f27b83cSArmin Le Grand         pSalRGB->ReleaseBuffer(pRGB, true);
286*5f27b83cSArmin Le Grand         pRGB = pExtraRGB;
287*5f27b83cSArmin Le Grand     }
288*5f27b83cSArmin Le Grand 
289*5f27b83cSArmin Le Grand     if(pRGB
290*5f27b83cSArmin Le Grand         && pRGB->mnWidth > 0
291*5f27b83cSArmin Le Grand         && pRGB->mnHeight > 0
292*5f27b83cSArmin Le Grand         && BMP_FORMAT_24BIT_TC_BGR == (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN))
293*5f27b83cSArmin Le Grand     {
294*5f27b83cSArmin Le Grand         const sal_uInt32 nW(pRGB->mnWidth);
295*5f27b83cSArmin Le Grand         const sal_uInt32 nH(pRGB->mnHeight);
296*5f27b83cSArmin Le Grand 
297*5f27b83cSArmin Le Grand         pRetval = new Gdiplus::Bitmap(nW, nH, PixelFormat24bppRGB);
298*5f27b83cSArmin Le Grand 
299*5f27b83cSArmin Le Grand         if(pRetval)
300*5f27b83cSArmin Le Grand         {
301*5f27b83cSArmin Le Grand             sal_uInt8* pSrcRGB(pRGB->mpBits);
302*5f27b83cSArmin Le Grand             const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3));
303*5f27b83cSArmin Le Grand             const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN);
304*5f27b83cSArmin Le Grand 
305*5f27b83cSArmin Le Grand             for(sal_uInt32 y(0); y < nH; y++)
306*5f27b83cSArmin Le Grand             {
307*5f27b83cSArmin Le Grand                 const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1);
308*5f27b83cSArmin Le Grand 
309*5f27b83cSArmin Le Grand                 for(sal_uInt32 x(0); x < nW; x++)
310*5f27b83cSArmin Le Grand                 {
311*5f27b83cSArmin Le Grand                     const sal_uInt8 nB(*pSrcRGB++);
312*5f27b83cSArmin Le Grand                     const sal_uInt8 nG(*pSrcRGB++);
313*5f27b83cSArmin Le Grand                     const sal_uInt8 nR(*pSrcRGB++);
314*5f27b83cSArmin Le Grand 
315*5f27b83cSArmin Le Grand                     pRetval->SetPixel(x, nYInsert, Gdiplus::Color(nR, nG, nB));
316*5f27b83cSArmin Le Grand                 }
317*5f27b83cSArmin Le Grand 
318*5f27b83cSArmin Le Grand                 pSrcRGB += nExtraRGB;
319*5f27b83cSArmin Le Grand             }
320*5f27b83cSArmin Le Grand         }
321*5f27b83cSArmin Le Grand     }
322*5f27b83cSArmin Le Grand 
323*5f27b83cSArmin Le Grand     if(pExtraRGB)
324*5f27b83cSArmin Le Grand     {
325*5f27b83cSArmin Le Grand         delete pExtraRGB;
326*5f27b83cSArmin Le Grand     }
327*5f27b83cSArmin Le Grand     else
328*5f27b83cSArmin Le Grand     {
329*5f27b83cSArmin Le Grand         pSalRGB->ReleaseBuffer(pRGB, true);
330*5f27b83cSArmin Le Grand     }
331*5f27b83cSArmin Le Grand 
332*5f27b83cSArmin Le Grand     if(pExtraWinSalRGB)
333*5f27b83cSArmin Le Grand     {
334*5f27b83cSArmin Le Grand         delete pExtraWinSalRGB;
335*5f27b83cSArmin Le Grand     }
336*5f27b83cSArmin Le Grand 
337*5f27b83cSArmin Le Grand     return pRetval;
338*5f27b83cSArmin Le Grand }
339*5f27b83cSArmin Le Grand 
340*5f27b83cSArmin Le Grand // ------------------------------------------------------------------
341*5f27b83cSArmin Le Grand 
342*5f27b83cSArmin Le Grand Gdiplus::Bitmap* WinSalBitmap::ImplCreateGdiPlusBitmap(const WinSalBitmap& rAlphaSource)
343*5f27b83cSArmin Le Grand {
344*5f27b83cSArmin Le Grand     Gdiplus::Bitmap* pRetval(0);
345*5f27b83cSArmin Le Grand     WinSalBitmap* pSalRGB = const_cast< WinSalBitmap* >(this);
346*5f27b83cSArmin Le Grand     WinSalBitmap* pExtraWinSalRGB = 0;
347*5f27b83cSArmin Le Grand 
348*5f27b83cSArmin Le Grand     if(!pSalRGB->ImplGethDIB())
349*5f27b83cSArmin Le Grand     {
350*5f27b83cSArmin Le Grand         // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap
351*5f27b83cSArmin Le Grand         pExtraWinSalRGB = new WinSalBitmap();
352*5f27b83cSArmin Le Grand         pExtraWinSalRGB->Create(*pSalRGB, pSalRGB->GetBitCount());
353*5f27b83cSArmin Le Grand         pSalRGB = pExtraWinSalRGB;
354*5f27b83cSArmin Le Grand     }
355*5f27b83cSArmin Le Grand 
356*5f27b83cSArmin Le Grand     BitmapBuffer* pRGB = pSalRGB->AcquireBuffer(true);
357*5f27b83cSArmin Le Grand     BitmapBuffer* pExtraRGB = 0;
358*5f27b83cSArmin Le Grand 
359*5f27b83cSArmin Le Grand     if(pRGB && BMP_FORMAT_24BIT_TC_BGR != (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN))
360*5f27b83cSArmin Le Grand     {
361*5f27b83cSArmin Le Grand         // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format
362*5f27b83cSArmin Le Grand         SalTwoRect aSalTwoRect;
363*5f27b83cSArmin Le Grand 
364*5f27b83cSArmin Le Grand         aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0;
365*5f27b83cSArmin Le Grand         aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pRGB->mnWidth;
366*5f27b83cSArmin Le Grand         aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pRGB->mnHeight;
367*5f27b83cSArmin Le Grand 
368*5f27b83cSArmin Le Grand         pExtraRGB = StretchAndConvert(
369*5f27b83cSArmin Le Grand             *pRGB,
370*5f27b83cSArmin Le Grand             aSalTwoRect,
371*5f27b83cSArmin Le Grand             BMP_FORMAT_24BIT_TC_BGR,
372*5f27b83cSArmin Le Grand             0);
373*5f27b83cSArmin Le Grand 
374*5f27b83cSArmin Le Grand         pSalRGB->ReleaseBuffer(pRGB, true);
375*5f27b83cSArmin Le Grand         pRGB = pExtraRGB;
376*5f27b83cSArmin Le Grand     }
377*5f27b83cSArmin Le Grand 
378*5f27b83cSArmin Le Grand     WinSalBitmap* pSalA = const_cast< WinSalBitmap* >(&rAlphaSource);
379*5f27b83cSArmin Le Grand     WinSalBitmap* pExtraWinSalA = 0;
380*5f27b83cSArmin Le Grand 
381*5f27b83cSArmin Le Grand     if(!pSalA->ImplGethDIB())
382*5f27b83cSArmin Le Grand     {
383*5f27b83cSArmin Le Grand         // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap
384*5f27b83cSArmin Le Grand         pExtraWinSalA = new WinSalBitmap();
385*5f27b83cSArmin Le Grand         pExtraWinSalA->Create(*pSalA, pSalA->GetBitCount());
386*5f27b83cSArmin Le Grand         pSalA = pExtraWinSalA;
387*5f27b83cSArmin Le Grand     }
388*5f27b83cSArmin Le Grand 
389*5f27b83cSArmin Le Grand     BitmapBuffer* pA = pSalA->AcquireBuffer(true);
390*5f27b83cSArmin Le Grand     BitmapBuffer* pExtraA = 0;
391*5f27b83cSArmin Le Grand 
392*5f27b83cSArmin Le Grand     if(pA && BMP_FORMAT_8BIT_PAL != (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN))
393*5f27b83cSArmin Le Grand     {
394*5f27b83cSArmin Le Grand         // convert alpha bitmap to BMP_FORMAT_8BIT_PAL format if not yet in that format
395*5f27b83cSArmin Le Grand         SalTwoRect aSalTwoRect;
396*5f27b83cSArmin Le Grand 
397*5f27b83cSArmin Le Grand         aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0;
398*5f27b83cSArmin Le Grand         aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pA->mnWidth;
399*5f27b83cSArmin Le Grand         aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pA->mnHeight;
400*5f27b83cSArmin Le Grand         const BitmapPalette& rTargetPalette = Bitmap::GetGreyPalette(256);
401*5f27b83cSArmin Le Grand 
402*5f27b83cSArmin Le Grand         pExtraA = StretchAndConvert(
403*5f27b83cSArmin Le Grand             *pA,
404*5f27b83cSArmin Le Grand             aSalTwoRect,
405*5f27b83cSArmin Le Grand             BMP_FORMAT_8BIT_PAL,
406*5f27b83cSArmin Le Grand             &rTargetPalette);
407*5f27b83cSArmin Le Grand 
408*5f27b83cSArmin Le Grand         pSalA->ReleaseBuffer(pA, true);
409*5f27b83cSArmin Le Grand         pA = pExtraA;
410*5f27b83cSArmin Le Grand     }
411*5f27b83cSArmin Le Grand 
412*5f27b83cSArmin Le Grand     if(pRGB
413*5f27b83cSArmin Le Grand         && pA
414*5f27b83cSArmin Le Grand         && pRGB->mnWidth > 0
415*5f27b83cSArmin Le Grand         && pRGB->mnHeight > 0
416*5f27b83cSArmin Le Grand         && pRGB->mnWidth == pA->mnWidth
417*5f27b83cSArmin Le Grand         && pRGB->mnHeight == pA->mnHeight
418*5f27b83cSArmin Le Grand         && BMP_FORMAT_24BIT_TC_BGR == (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN)
419*5f27b83cSArmin Le Grand         && BMP_FORMAT_8BIT_PAL == (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN))
420*5f27b83cSArmin Le Grand     {
421*5f27b83cSArmin Le Grand         // we have alpha and bitmap in known formats, create GdiPlus Bitmap as 32bit ARGB
422*5f27b83cSArmin Le Grand         const sal_uInt32 nW(pRGB->mnWidth);
423*5f27b83cSArmin Le Grand         const sal_uInt32 nH(pRGB->mnHeight);
424*5f27b83cSArmin Le Grand 
425*5f27b83cSArmin Le Grand         pRetval = new Gdiplus::Bitmap(nW, nH, PixelFormat32bppARGB);
426*5f27b83cSArmin Le Grand 
427*5f27b83cSArmin Le Grand         if(pRetval)
428*5f27b83cSArmin Le Grand         {
429*5f27b83cSArmin Le Grand             sal_uInt8* pSrcRGB(pRGB->mpBits);
430*5f27b83cSArmin Le Grand             sal_uInt8* pSrcA(pA->mpBits);
431*5f27b83cSArmin Le Grand             const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3));
432*5f27b83cSArmin Le Grand             const sal_uInt32 nExtraA(pA->mnScanlineSize - nW);
433*5f27b83cSArmin Le Grand             const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN);
434*5f27b83cSArmin Le Grand 
435*5f27b83cSArmin Le Grand             for(sal_uInt32 y(0); y < nH; y++)
436*5f27b83cSArmin Le Grand             {
437*5f27b83cSArmin Le Grand                 const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1);
438*5f27b83cSArmin Le Grand 
439*5f27b83cSArmin Le Grand                 for(sal_uInt32 x(0); x < nW; x++)
440*5f27b83cSArmin Le Grand                 {
441*5f27b83cSArmin Le Grand                     const sal_uInt8 nB(*pSrcRGB++);
442*5f27b83cSArmin Le Grand                     const sal_uInt8 nG(*pSrcRGB++);
443*5f27b83cSArmin Le Grand                     const sal_uInt8 nR(*pSrcRGB++);
444*5f27b83cSArmin Le Grand                     const sal_uInt8 nA(0xff - *pSrcA++);
445*5f27b83cSArmin Le Grand 
446*5f27b83cSArmin Le Grand                     pRetval->SetPixel(x, nYInsert, Gdiplus::Color(nA, nR, nG, nB));
447*5f27b83cSArmin Le Grand                 }
448*5f27b83cSArmin Le Grand 
449*5f27b83cSArmin Le Grand                 pSrcRGB += nExtraRGB;
450*5f27b83cSArmin Le Grand                 pSrcA += nExtraA;
451*5f27b83cSArmin Le Grand             }
452*5f27b83cSArmin Le Grand         }
453*5f27b83cSArmin Le Grand     }
454*5f27b83cSArmin Le Grand 
455*5f27b83cSArmin Le Grand     if(pExtraA)
456*5f27b83cSArmin Le Grand     {
457*5f27b83cSArmin Le Grand         delete pExtraA;
458*5f27b83cSArmin Le Grand     }
459*5f27b83cSArmin Le Grand     else
460*5f27b83cSArmin Le Grand     {
461*5f27b83cSArmin Le Grand         pSalA->ReleaseBuffer(pA, true);
462*5f27b83cSArmin Le Grand     }
463*5f27b83cSArmin Le Grand 
464*5f27b83cSArmin Le Grand     if(pExtraWinSalA)
465*5f27b83cSArmin Le Grand     {
466*5f27b83cSArmin Le Grand         delete pExtraWinSalA;
467*5f27b83cSArmin Le Grand     }
468*5f27b83cSArmin Le Grand 
469*5f27b83cSArmin Le Grand     if(pExtraRGB)
470*5f27b83cSArmin Le Grand     {
471*5f27b83cSArmin Le Grand         delete pExtraRGB;
472*5f27b83cSArmin Le Grand     }
473*5f27b83cSArmin Le Grand     else
474*5f27b83cSArmin Le Grand     {
475*5f27b83cSArmin Le Grand         pSalRGB->ReleaseBuffer(pRGB, true);
476*5f27b83cSArmin Le Grand     }
477*5f27b83cSArmin Le Grand 
478*5f27b83cSArmin Le Grand     if(pExtraWinSalRGB)
479*5f27b83cSArmin Le Grand     {
480*5f27b83cSArmin Le Grand         delete pExtraWinSalRGB;
481*5f27b83cSArmin Le Grand     }
482*5f27b83cSArmin Le Grand 
483*5f27b83cSArmin Le Grand     return pRetval;
484*5f27b83cSArmin Le Grand }
485*5f27b83cSArmin Le Grand 
486*5f27b83cSArmin Le Grand // ------------------------------------------------------------------
487*5f27b83cSArmin Le Grand 
488cdf0e10cSrcweir bool WinSalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle )
489cdf0e10cSrcweir {
490cdf0e10cSrcweir 	bool bRet = TRUE;
491cdf0e10cSrcweir 
492cdf0e10cSrcweir 	if( bDIB )
493cdf0e10cSrcweir 		mhDIB = (HGLOBAL) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap );
494cdf0e10cSrcweir 	else
495cdf0e10cSrcweir 		mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap );
496cdf0e10cSrcweir 
497cdf0e10cSrcweir 	if( mhDIB )
498cdf0e10cSrcweir 	{
499cdf0e10cSrcweir 		PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) GlobalLock( mhDIB );
500cdf0e10cSrcweir 
501cdf0e10cSrcweir 		maSize = Size( pBIH->biWidth, pBIH->biHeight );
502cdf0e10cSrcweir 		mnBitCount = pBIH->biBitCount;
503cdf0e10cSrcweir 
504cdf0e10cSrcweir 		if( mnBitCount )
505cdf0e10cSrcweir 			mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24;
506cdf0e10cSrcweir 
507cdf0e10cSrcweir 		GlobalUnlock( mhDIB );
508cdf0e10cSrcweir 	}
509cdf0e10cSrcweir 	else if( mhDDB )
510cdf0e10cSrcweir 	{
511cdf0e10cSrcweir 		BITMAP	aDDBInfo;
512cdf0e10cSrcweir 
513cdf0e10cSrcweir 		if( WIN_GetObject( mhDDB, sizeof( BITMAP ), &aDDBInfo ) )
514cdf0e10cSrcweir 		{
515cdf0e10cSrcweir 			maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight );
516cdf0e10cSrcweir 			mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel;
517cdf0e10cSrcweir 
518cdf0e10cSrcweir 			if( mnBitCount )
519cdf0e10cSrcweir 			{
520cdf0e10cSrcweir 				mnBitCount = ( mnBitCount <= 1 ) ? 1 :
521cdf0e10cSrcweir 							 ( mnBitCount <= 4 ) ? 4 :
522cdf0e10cSrcweir 							 ( mnBitCount <= 8 ) ? 8 : 24;
523cdf0e10cSrcweir 			}
524cdf0e10cSrcweir 		}
525cdf0e10cSrcweir 		else
526cdf0e10cSrcweir 		{
527cdf0e10cSrcweir 			mhDDB = 0;
528cdf0e10cSrcweir 			bRet = FALSE;
529cdf0e10cSrcweir 		}
530cdf0e10cSrcweir 	}
531cdf0e10cSrcweir 	else
532cdf0e10cSrcweir 		bRet = FALSE;
533cdf0e10cSrcweir 
534cdf0e10cSrcweir 	return bRet;
535cdf0e10cSrcweir }
536cdf0e10cSrcweir 
537cdf0e10cSrcweir // ------------------------------------------------------------------
538cdf0e10cSrcweir 
539cdf0e10cSrcweir bool WinSalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal )
540cdf0e10cSrcweir {
541cdf0e10cSrcweir 	bool bRet = FALSE;
542cdf0e10cSrcweir 
543cdf0e10cSrcweir 	mhDIB = ImplCreateDIB( rSize, nBitCount, rPal );
544cdf0e10cSrcweir 
545cdf0e10cSrcweir 	if( mhDIB )
546cdf0e10cSrcweir 	{
547cdf0e10cSrcweir 		maSize = rSize;
548cdf0e10cSrcweir 		mnBitCount = nBitCount;
549cdf0e10cSrcweir 		bRet = TRUE;
550cdf0e10cSrcweir 	}
551cdf0e10cSrcweir 
552cdf0e10cSrcweir 	return bRet;
553cdf0e10cSrcweir }
554cdf0e10cSrcweir 
555cdf0e10cSrcweir // ------------------------------------------------------------------
556cdf0e10cSrcweir 
557cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBitmap )
558cdf0e10cSrcweir {
559cdf0e10cSrcweir 	bool bRet = FALSE;
560cdf0e10cSrcweir     const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
561cdf0e10cSrcweir 
562cdf0e10cSrcweir 	if ( rSalBitmap.mhDIB || rSalBitmap.mhDDB )
563cdf0e10cSrcweir 	{
564cdf0e10cSrcweir 		HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : rSalBitmap.mhDDB,
565cdf0e10cSrcweir 										   rSalBitmap.mhDIB != 0 );
566cdf0e10cSrcweir 
567cdf0e10cSrcweir 		if ( hNewHdl )
568cdf0e10cSrcweir 		{
569cdf0e10cSrcweir 			if( rSalBitmap.mhDIB )
570cdf0e10cSrcweir 				mhDIB = (HGLOBAL) hNewHdl;
571cdf0e10cSrcweir 			else if( rSalBitmap.mhDDB )
572cdf0e10cSrcweir 				mhDDB = (HBITMAP) hNewHdl;
573cdf0e10cSrcweir 
574cdf0e10cSrcweir 			maSize = rSalBitmap.maSize;
575cdf0e10cSrcweir 			mnBitCount = rSalBitmap.mnBitCount;
576cdf0e10cSrcweir 
577cdf0e10cSrcweir 			bRet = TRUE;
578cdf0e10cSrcweir 		}
579cdf0e10cSrcweir 	}
580cdf0e10cSrcweir 
581cdf0e10cSrcweir 	return bRet;
582cdf0e10cSrcweir }
583cdf0e10cSrcweir 
584cdf0e10cSrcweir // ------------------------------------------------------------------
585cdf0e10cSrcweir 
586cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics )
587cdf0e10cSrcweir {
588cdf0e10cSrcweir 	bool bRet = FALSE;
589cdf0e10cSrcweir 
590cdf0e10cSrcweir     const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp);
591cdf0e10cSrcweir     WinSalGraphics* pGraphics = static_cast<WinSalGraphics*>(pSGraphics);
592cdf0e10cSrcweir 
593cdf0e10cSrcweir 	if( rSalBmp.mhDIB )
594cdf0e10cSrcweir 	{
595cdf0e10cSrcweir 		PBITMAPINFO 		pBI = (PBITMAPINFO) GlobalLock( rSalBmp.mhDIB );
596cdf0e10cSrcweir 		PBITMAPINFOHEADER	pBIH = (PBITMAPINFOHEADER) pBI;
597*5f27b83cSArmin Le Grand 		HDC 				hDC  = pGraphics->getHDC();
598cdf0e10cSrcweir 		HBITMAP 			hNewDDB;
599cdf0e10cSrcweir 		BITMAP				aDDBInfo;
600cdf0e10cSrcweir 		PBYTE				pBits = (PBYTE) pBI + *(DWORD*) pBI +
601cdf0e10cSrcweir 							ImplGetDIBColorCount( rSalBmp.mhDIB ) * sizeof( RGBQUAD );
602cdf0e10cSrcweir 
603cdf0e10cSrcweir 		if( pBIH->biBitCount == 1 )
604cdf0e10cSrcweir 		{
605cdf0e10cSrcweir 			hNewDDB = CreateBitmap( pBIH->biWidth, pBIH->biHeight, 1, 1, NULL );
606cdf0e10cSrcweir 
607cdf0e10cSrcweir 			if( hNewDDB )
608cdf0e10cSrcweir 				SetDIBits( hDC, hNewDDB, 0, pBIH->biHeight, pBits, pBI, DIB_RGB_COLORS );
609cdf0e10cSrcweir 		}
610cdf0e10cSrcweir 		else
611cdf0e10cSrcweir 			hNewDDB = CreateDIBitmap( hDC, (PBITMAPINFOHEADER) pBI, CBM_INIT, pBits, pBI, DIB_RGB_COLORS );
612cdf0e10cSrcweir 
613cdf0e10cSrcweir 		GlobalUnlock( rSalBmp.mhDIB );
614cdf0e10cSrcweir 
615cdf0e10cSrcweir 		if( hNewDDB && WIN_GetObject( hNewDDB, sizeof( BITMAP ), &aDDBInfo ) )
616cdf0e10cSrcweir 		{
617cdf0e10cSrcweir 			mhDDB = hNewDDB;
618cdf0e10cSrcweir 			maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight );
619cdf0e10cSrcweir 			mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel;
620cdf0e10cSrcweir 
621cdf0e10cSrcweir 			bRet = TRUE;
622cdf0e10cSrcweir 		}
623cdf0e10cSrcweir 		else if( hNewDDB )
624cdf0e10cSrcweir 			DeleteObject( hNewDDB );
625cdf0e10cSrcweir 	}
626cdf0e10cSrcweir 
627cdf0e10cSrcweir 	return bRet;
628cdf0e10cSrcweir }
629cdf0e10cSrcweir 
630cdf0e10cSrcweir // ------------------------------------------------------------------
631cdf0e10cSrcweir 
632cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, sal_uInt16 nNewBitCount )
633cdf0e10cSrcweir {
634cdf0e10cSrcweir 	bool bRet = FALSE;
635cdf0e10cSrcweir 
636cdf0e10cSrcweir     const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp);
637cdf0e10cSrcweir 
638cdf0e10cSrcweir 	if( rSalBmp.mhDDB )
639cdf0e10cSrcweir 	{
640cdf0e10cSrcweir 		mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() );
641cdf0e10cSrcweir 
642cdf0e10cSrcweir 		if( mhDIB )
643cdf0e10cSrcweir 		{
644cdf0e10cSrcweir 			PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB );
645cdf0e10cSrcweir 			const int	nLines = (int) rSalBmp.maSize.Height();
646cdf0e10cSrcweir 			HDC 		hDC = GetDC( 0 );
647cdf0e10cSrcweir 			PBYTE		pBits = (PBYTE) pBI + *(DWORD*) pBI +
648cdf0e10cSrcweir 								ImplGetDIBColorCount( mhDIB ) * sizeof( RGBQUAD );
649cdf0e10cSrcweir 			SalData*	pSalData = GetSalData();
650cdf0e10cSrcweir 			HPALETTE	hOldPal = 0;
651cdf0e10cSrcweir 
652cdf0e10cSrcweir 			if ( pSalData->mhDitherPal )
653cdf0e10cSrcweir 			{
654cdf0e10cSrcweir 				hOldPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
655cdf0e10cSrcweir 				RealizePalette( hDC );
656cdf0e10cSrcweir 			}
657cdf0e10cSrcweir 
658cdf0e10cSrcweir 			if( GetDIBits( hDC, rSalBmp.mhDDB, 0, nLines, pBits, pBI, DIB_RGB_COLORS ) == nLines )
659cdf0e10cSrcweir 			{
660cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
661cdf0e10cSrcweir 				maSize = rSalBmp.maSize;
662cdf0e10cSrcweir 				mnBitCount = nNewBitCount;
663cdf0e10cSrcweir 				bRet = TRUE;
664cdf0e10cSrcweir 			}
665cdf0e10cSrcweir 			else
666cdf0e10cSrcweir 			{
667cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
668cdf0e10cSrcweir 				GlobalFree( mhDIB );
669cdf0e10cSrcweir 				mhDIB = 0;
670cdf0e10cSrcweir 			}
671cdf0e10cSrcweir 
672cdf0e10cSrcweir 			if( hOldPal )
673cdf0e10cSrcweir 				SelectPalette( hDC, hOldPal, TRUE );
674cdf0e10cSrcweir 
675cdf0e10cSrcweir 			ReleaseDC( 0, hDC );
676cdf0e10cSrcweir 		}
677cdf0e10cSrcweir 	}
678cdf0e10cSrcweir 
679cdf0e10cSrcweir 	return bRet;
680cdf0e10cSrcweir }
681cdf0e10cSrcweir 
682cdf0e10cSrcweir // ------------------------------------------------------------------
683cdf0e10cSrcweir 
684cdf0e10cSrcweir sal_uInt16 WinSalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB )
685cdf0e10cSrcweir {
686cdf0e10cSrcweir 	sal_uInt16 nColors = 0;
687cdf0e10cSrcweir 
688cdf0e10cSrcweir 	if( hDIB )
689cdf0e10cSrcweir 	{
690cdf0e10cSrcweir 		PBITMAPINFO 		pBI = (PBITMAPINFO) GlobalLock( hDIB );
691cdf0e10cSrcweir 		PBITMAPINFOHEADER	pBIH = (PBITMAPINFOHEADER) pBI;
692cdf0e10cSrcweir 
693cdf0e10cSrcweir 		if ( pBIH->biSize != sizeof( BITMAPCOREHEADER ) )
694cdf0e10cSrcweir 		{
695cdf0e10cSrcweir 			if( pBIH->biBitCount <= 8 )
696cdf0e10cSrcweir 			{
697cdf0e10cSrcweir 				if ( pBIH->biClrUsed )
698cdf0e10cSrcweir 					nColors = (sal_uInt16) pBIH->biClrUsed;
699cdf0e10cSrcweir 				else
700cdf0e10cSrcweir 					nColors = 1 << pBIH->biBitCount;
701cdf0e10cSrcweir 			}
702cdf0e10cSrcweir 		}
703cdf0e10cSrcweir 		else if( ( (PBITMAPCOREHEADER) pBI )->bcBitCount <= 8 )
704cdf0e10cSrcweir 			nColors = 1 << ( (PBITMAPCOREHEADER) pBI )->bcBitCount;
705cdf0e10cSrcweir 
706cdf0e10cSrcweir 		GlobalUnlock( hDIB );
707cdf0e10cSrcweir 	}
708cdf0e10cSrcweir 
709cdf0e10cSrcweir 	return nColors;
710cdf0e10cSrcweir }
711cdf0e10cSrcweir 
712cdf0e10cSrcweir // ------------------------------------------------------------------
713cdf0e10cSrcweir 
714cdf0e10cSrcweir HGLOBAL WinSalBitmap::ImplCreateDIB( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rPal )
715cdf0e10cSrcweir {
716cdf0e10cSrcweir 	DBG_ASSERT( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 16 || nBits == 24, "Unsupported BitCount!" );
717cdf0e10cSrcweir 
718cdf0e10cSrcweir 	HGLOBAL hDIB = 0;
719cdf0e10cSrcweir 
720562e22fbSHerbert Dürr 	if( rSize.Width() <= 0 || rSize.Height() <= 0 )
721562e22fbSHerbert Dürr 		return hDIB;
722562e22fbSHerbert Dürr 
723562e22fbSHerbert Dürr 	// calculate bitmap size in Bytes
724562e22fbSHerbert Dürr 	const sal_uLong nAlignedWidth4Bytes = AlignedWidth4Bytes( nBits * rSize.Width() );
725562e22fbSHerbert Dürr 	const sal_uLong nImageSize = nAlignedWidth4Bytes * rSize.Height();
726562e22fbSHerbert Dürr 	bool bOverflow = (nImageSize / nAlignedWidth4Bytes) != rSize.Height();
727562e22fbSHerbert Dürr 	if( bOverflow )
728562e22fbSHerbert Dürr 		return hDIB;
729562e22fbSHerbert Dürr 
730562e22fbSHerbert Dürr 	// allocate bitmap memory including header and palette
731cdf0e10cSrcweir 	const sal_uInt16 nColors = (nBits <= 8) ? (1 << nBits) : 0;
732562e22fbSHerbert Dürr 	const sal_uLong nHeaderSize = sizeof( BITMAPINFOHEADER ) + nColors * sizeof( RGBQUAD );
733562e22fbSHerbert Dürr 	bOverflow = (nHeaderSize + nImageSize) < nImageSize;
734562e22fbSHerbert Dürr 	if( bOverflow )
735562e22fbSHerbert Dürr 		return hDIB;
736cdf0e10cSrcweir 
737562e22fbSHerbert Dürr 	hDIB = GlobalAlloc( GHND, nHeaderSize + nImageSize );
738562e22fbSHerbert Dürr 	if( !hDIB )
739562e22fbSHerbert Dürr 		return hDIB;
740cdf0e10cSrcweir 
741562e22fbSHerbert Dürr 	PBITMAPINFO pBI = static_cast<PBITMAPINFO>( GlobalLock( hDIB ) );
7424fee1b5aSArmin Le Grand 	PBITMAPINFOHEADER pBIH = reinterpret_cast<PBITMAPINFOHEADER>( pBI );
743cdf0e10cSrcweir 
744cdf0e10cSrcweir 	pBIH->biSize = sizeof( BITMAPINFOHEADER );
745cdf0e10cSrcweir 	pBIH->biWidth = rSize.Width();
746cdf0e10cSrcweir 	pBIH->biHeight = rSize.Height();
747cdf0e10cSrcweir 	pBIH->biPlanes = 1;
748cdf0e10cSrcweir 	pBIH->biBitCount = nBits;
749cdf0e10cSrcweir 	pBIH->biCompression = BI_RGB;
750cdf0e10cSrcweir 	pBIH->biSizeImage = nImageSize;
751cdf0e10cSrcweir 	pBIH->biXPelsPerMeter = 0;
752cdf0e10cSrcweir 	pBIH->biYPelsPerMeter = 0;
753cdf0e10cSrcweir 	pBIH->biClrUsed = 0;
754cdf0e10cSrcweir 	pBIH->biClrImportant = 0;
755cdf0e10cSrcweir 
756cdf0e10cSrcweir 	if( nColors )
757cdf0e10cSrcweir 	{
758562e22fbSHerbert Dürr 		// copy the palette entries if any
759cdf0e10cSrcweir 		const sal_uInt16 nMinCount = Min( nColors, rPal.GetEntryCount() );
760cdf0e10cSrcweir 		if( nMinCount )
761cdf0e10cSrcweir 			memcpy( pBI->bmiColors, rPal.ImplGetColorBuffer(), nMinCount * sizeof(RGBQUAD) );
762cdf0e10cSrcweir 	}
763cdf0e10cSrcweir 
764cdf0e10cSrcweir 	GlobalUnlock( hDIB );
765cdf0e10cSrcweir 
766cdf0e10cSrcweir 	return hDIB;
767cdf0e10cSrcweir }
768cdf0e10cSrcweir 
769cdf0e10cSrcweir // ------------------------------------------------------------------
770cdf0e10cSrcweir 
771cdf0e10cSrcweir HANDLE WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB )
772cdf0e10cSrcweir {
773cdf0e10cSrcweir 	HANDLE	hCopy = 0;
774cdf0e10cSrcweir 
775cdf0e10cSrcweir 	if ( bDIB && hHdl )
776cdf0e10cSrcweir 	{
777cdf0e10cSrcweir 		const sal_uLong nSize = GlobalSize( hHdl );
778cdf0e10cSrcweir 
779cdf0e10cSrcweir 		if ( (hCopy = GlobalAlloc( GHND, nSize  )) != 0 )
780cdf0e10cSrcweir 		{
781cdf0e10cSrcweir 			memcpy( (LPSTR) GlobalLock( hCopy ), (LPSTR) GlobalLock( hHdl ), nSize );
782cdf0e10cSrcweir 
783cdf0e10cSrcweir 			GlobalUnlock( hCopy );
784cdf0e10cSrcweir 			GlobalUnlock( hHdl );
785cdf0e10cSrcweir 		}
786cdf0e10cSrcweir 	}
787cdf0e10cSrcweir 	else if ( hHdl )
788cdf0e10cSrcweir 	{
789cdf0e10cSrcweir 		BITMAP aBmp;
790cdf0e10cSrcweir 
791cdf0e10cSrcweir 		// Source-Bitmap nach Groesse befragen
792cdf0e10cSrcweir 		WIN_GetObject( hHdl, sizeof( BITMAP ), (LPSTR) &aBmp );
793cdf0e10cSrcweir 
794cdf0e10cSrcweir 		// Destination-Bitmap erzeugen
795cdf0e10cSrcweir 		if ( (hCopy = CreateBitmapIndirect( &aBmp )) != 0 )
796cdf0e10cSrcweir 		{
797cdf0e10cSrcweir 			HDC 	hBmpDC = CreateCompatibleDC( 0 );
798cdf0e10cSrcweir 			HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hHdl );
799cdf0e10cSrcweir 			HDC 	hCopyDC = CreateCompatibleDC( hBmpDC );
800cdf0e10cSrcweir 			HBITMAP hCopyOld = (HBITMAP) SelectObject( hCopyDC, hCopy );
801cdf0e10cSrcweir 
802cdf0e10cSrcweir 			BitBlt( hCopyDC, 0, 0, aBmp.bmWidth, aBmp.bmHeight, hBmpDC, 0, 0, SRCCOPY );
803cdf0e10cSrcweir 
804cdf0e10cSrcweir 			SelectObject( hCopyDC, hCopyOld );
805cdf0e10cSrcweir 			DeleteDC( hCopyDC );
806cdf0e10cSrcweir 
807cdf0e10cSrcweir 			SelectObject( hBmpDC, hBmpOld );
808cdf0e10cSrcweir 			DeleteDC( hBmpDC );
809cdf0e10cSrcweir 		}
810cdf0e10cSrcweir 	}
811cdf0e10cSrcweir 
812cdf0e10cSrcweir 	return hCopy;
813cdf0e10cSrcweir }
814cdf0e10cSrcweir 
815cdf0e10cSrcweir // ------------------------------------------------------------------
816cdf0e10cSrcweir 
817cdf0e10cSrcweir BitmapBuffer* WinSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
818cdf0e10cSrcweir {
819cdf0e10cSrcweir 	BitmapBuffer* pBuffer = NULL;
820cdf0e10cSrcweir 
821cdf0e10cSrcweir 	if( mhDIB )
822cdf0e10cSrcweir 	{
823cdf0e10cSrcweir 		PBITMAPINFO 		pBI = (PBITMAPINFO) GlobalLock( mhDIB );
824cdf0e10cSrcweir 		PBITMAPINFOHEADER	pBIH = (PBITMAPINFOHEADER) pBI;
825cdf0e10cSrcweir 
826cdf0e10cSrcweir 		if( ( pBIH->biCompression == BI_RLE4 ) || ( pBIH->biCompression == BI_RLE8 ) )
827cdf0e10cSrcweir 		{
828cdf0e10cSrcweir 			Size	aSizePix( pBIH->biWidth, pBIH->biHeight );
829cdf0e10cSrcweir 			HGLOBAL hNewDIB = ImplCreateDIB( aSizePix, pBIH->biBitCount, BitmapPalette() );
830cdf0e10cSrcweir 
831cdf0e10cSrcweir 			if( hNewDIB )
832cdf0e10cSrcweir 			{
833cdf0e10cSrcweir 				PBITMAPINFO 		pNewBI = (PBITMAPINFO) GlobalLock( hNewDIB );
834cdf0e10cSrcweir 				PBITMAPINFOHEADER	pNewBIH = (PBITMAPINFOHEADER) pNewBI;
835cdf0e10cSrcweir 				const sal_uInt16		nColorCount = ImplGetDIBColorCount( hNewDIB );
836cdf0e10cSrcweir 				const sal_uLong 		nOffset = *(DWORD*) pBI + nColorCount * sizeof( RGBQUAD );
837cdf0e10cSrcweir 				BYTE*				pOldBits = (PBYTE) pBI + nOffset;
838cdf0e10cSrcweir 				BYTE*				pNewBits = (PBYTE) pNewBI + nOffset;
839cdf0e10cSrcweir 
840cdf0e10cSrcweir 				memcpy( pNewBI, pBI, nOffset );
841cdf0e10cSrcweir 				pNewBIH->biCompression = 0;
842cdf0e10cSrcweir 				ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->biCompression == BI_RLE4 );
843cdf0e10cSrcweir 
844cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
845cdf0e10cSrcweir 				GlobalFree( mhDIB );
846cdf0e10cSrcweir 				mhDIB = hNewDIB;
847cdf0e10cSrcweir 				pBI = pNewBI;
848cdf0e10cSrcweir 				pBIH = pNewBIH;
849cdf0e10cSrcweir 			}
850cdf0e10cSrcweir 		}
851cdf0e10cSrcweir 
852cdf0e10cSrcweir 		if( pBIH->biPlanes == 1 )
853cdf0e10cSrcweir 		{
854cdf0e10cSrcweir 			pBuffer = new BitmapBuffer;
855cdf0e10cSrcweir 
856cdf0e10cSrcweir 			pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP |
857cdf0e10cSrcweir 								( pBIH->biBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL :
858cdf0e10cSrcweir 								  pBIH->biBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL :
859cdf0e10cSrcweir 								  pBIH->biBitCount == 8 ? BMP_FORMAT_8BIT_PAL :
860cdf0e10cSrcweir 								  pBIH->biBitCount == 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK :
861cdf0e10cSrcweir 								  pBIH->biBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR :
862cdf0e10cSrcweir 								  pBIH->biBitCount == 32 ? BMP_FORMAT_32BIT_TC_MASK : 0UL );
863cdf0e10cSrcweir 
864cdf0e10cSrcweir 			if( BMP_SCANLINE_FORMAT( pBuffer->mnFormat ) )
865cdf0e10cSrcweir 			{
866cdf0e10cSrcweir 				pBuffer->mnWidth = maSize.Width();
867cdf0e10cSrcweir 				pBuffer->mnHeight = maSize.Height();
868cdf0e10cSrcweir 				pBuffer->mnScanlineSize = AlignedWidth4Bytes( maSize.Width() * pBIH->biBitCount );
869cdf0e10cSrcweir 				pBuffer->mnBitCount = (sal_uInt16) pBIH->biBitCount;
870cdf0e10cSrcweir 
871cdf0e10cSrcweir 				if( pBuffer->mnBitCount <= 8 )
872cdf0e10cSrcweir 				{
873cdf0e10cSrcweir 					const sal_uInt16 nPalCount = ImplGetDIBColorCount( mhDIB );
874cdf0e10cSrcweir 
875cdf0e10cSrcweir 					pBuffer->maPalette.SetEntryCount( nPalCount );
876cdf0e10cSrcweir 					memcpy( pBuffer->maPalette.ImplGetColorBuffer(), pBI->bmiColors, nPalCount * sizeof( RGBQUAD ) );
877cdf0e10cSrcweir 					pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nPalCount * sizeof( RGBQUAD );
878cdf0e10cSrcweir 				}
879cdf0e10cSrcweir 				else if( ( pBIH->biBitCount == 16 ) || ( pBIH->biBitCount == 32 ) )
880cdf0e10cSrcweir 				{
881cdf0e10cSrcweir 					sal_uLong nOffset = 0UL;
882cdf0e10cSrcweir 
883cdf0e10cSrcweir 					if( pBIH->biCompression == BI_BITFIELDS )
884cdf0e10cSrcweir 					{
885cdf0e10cSrcweir 						nOffset = 3 * sizeof( RGBQUAD );
886cdf0e10cSrcweir 						pBuffer->maColorMask = ColorMask( *(UINT32*) &pBI->bmiColors[ 0 ],
887cdf0e10cSrcweir 														  *(UINT32*) &pBI->bmiColors[ 1 ],
888cdf0e10cSrcweir 														  *(UINT32*) &pBI->bmiColors[ 2 ] );
889cdf0e10cSrcweir 					}
890cdf0e10cSrcweir 					else if( pBIH->biBitCount == 16 )
891cdf0e10cSrcweir 						pBuffer->maColorMask = ColorMask( 0x00007c00UL, 0x000003e0UL, 0x0000001fUL );
892cdf0e10cSrcweir 					else
893cdf0e10cSrcweir 						pBuffer->maColorMask = ColorMask( 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL );
894cdf0e10cSrcweir 
895cdf0e10cSrcweir 					pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nOffset;
896cdf0e10cSrcweir 				}
897cdf0e10cSrcweir 				else
898cdf0e10cSrcweir 					pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI;
899cdf0e10cSrcweir 			}
900cdf0e10cSrcweir 			else
901cdf0e10cSrcweir 			{
902cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
903cdf0e10cSrcweir 				delete pBuffer;
904cdf0e10cSrcweir 				pBuffer = NULL;
905cdf0e10cSrcweir 			}
906cdf0e10cSrcweir 		}
907cdf0e10cSrcweir 		else
908cdf0e10cSrcweir 			GlobalUnlock( mhDIB );
909cdf0e10cSrcweir 	}
910cdf0e10cSrcweir 
911cdf0e10cSrcweir 	return pBuffer;
912cdf0e10cSrcweir }
913cdf0e10cSrcweir 
914cdf0e10cSrcweir // ------------------------------------------------------------------
915cdf0e10cSrcweir 
916cdf0e10cSrcweir void WinSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly )
917cdf0e10cSrcweir {
918cdf0e10cSrcweir 	if( pBuffer )
919cdf0e10cSrcweir 	{
920cdf0e10cSrcweir 		if( mhDIB )
921cdf0e10cSrcweir 		{
922cdf0e10cSrcweir 			if( !bReadOnly && !!pBuffer->maPalette )
923cdf0e10cSrcweir 			{
924cdf0e10cSrcweir 				PBITMAPINFO 	pBI = (PBITMAPINFO) GlobalLock( mhDIB );
925cdf0e10cSrcweir 				const sal_uInt16	nCount = pBuffer->maPalette.GetEntryCount();
926cdf0e10cSrcweir 				const sal_uInt16	nDIBColorCount = ImplGetDIBColorCount( mhDIB );
927cdf0e10cSrcweir 				memcpy( pBI->bmiColors, pBuffer->maPalette.ImplGetColorBuffer(), Min( nDIBColorCount, nCount ) * sizeof( RGBQUAD ) );
928cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
929cdf0e10cSrcweir 			}
930cdf0e10cSrcweir 
931cdf0e10cSrcweir 			GlobalUnlock( mhDIB );
932cdf0e10cSrcweir 		}
933cdf0e10cSrcweir 
934cdf0e10cSrcweir 		delete pBuffer;
935cdf0e10cSrcweir 	}
936cdf0e10cSrcweir }
937cdf0e10cSrcweir 
938cdf0e10cSrcweir // ------------------------------------------------------------------
939cdf0e10cSrcweir 
940cdf0e10cSrcweir void WinSalBitmap::ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf,
941cdf0e10cSrcweir 									 const Size& rSizePixel, bool bRLE4 )
942cdf0e10cSrcweir {
943cdf0e10cSrcweir 	HPBYTE			pRLE = (HPBYTE) pSrcBuf;
944cdf0e10cSrcweir 	HPBYTE			pDIB = (HPBYTE) pDstBuf;
945cdf0e10cSrcweir 	HPBYTE			pRow = (HPBYTE) pDstBuf;
946cdf0e10cSrcweir 	sal_uLong			nWidthAl = AlignedWidth4Bytes( rSizePixel.Width() * ( bRLE4 ? 4UL : 8UL ) );
947cdf0e10cSrcweir 	HPBYTE			pLast = pDIB + rSizePixel.Height() * nWidthAl - 1;
948cdf0e10cSrcweir 	sal_uLong			nCountByte;
949cdf0e10cSrcweir 	sal_uLong			nRunByte;
950cdf0e10cSrcweir 	sal_uLong			nX = 0;
951cdf0e10cSrcweir 	sal_uLong			i;
952cdf0e10cSrcweir 	BYTE			cTmp;
953cdf0e10cSrcweir 	bool			bEndDecoding = FALSE;
954cdf0e10cSrcweir 
955cdf0e10cSrcweir 	if( pRLE && pDIB )
956cdf0e10cSrcweir 	{
957cdf0e10cSrcweir 		do
958cdf0e10cSrcweir 		{
959cdf0e10cSrcweir 			if( ( nCountByte = *pRLE++ ) == 0 )
960cdf0e10cSrcweir 			{
961cdf0e10cSrcweir 				nRunByte = *pRLE++;
962cdf0e10cSrcweir 
963cdf0e10cSrcweir 				if( nRunByte > 2UL )
964cdf0e10cSrcweir 				{
965cdf0e10cSrcweir 					if( bRLE4 )
966cdf0e10cSrcweir 					{
967cdf0e10cSrcweir 						nCountByte = nRunByte >> 1UL;
968cdf0e10cSrcweir 
969cdf0e10cSrcweir 						for( i = 0; i < nCountByte; i++ )
970cdf0e10cSrcweir 						{
971cdf0e10cSrcweir 							cTmp = *pRLE++;
972cdf0e10cSrcweir 							ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
973cdf0e10cSrcweir 							ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
974cdf0e10cSrcweir 						}
975cdf0e10cSrcweir 
976cdf0e10cSrcweir 						if( nRunByte & 1 )
977cdf0e10cSrcweir 							ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 );
978cdf0e10cSrcweir 
979cdf0e10cSrcweir 						if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
980cdf0e10cSrcweir 							pRLE++;
981cdf0e10cSrcweir 					}
982cdf0e10cSrcweir 					else
983cdf0e10cSrcweir 					{
984cdf0e10cSrcweir 						memcpy( &pDIB[ nX ], pRLE, nRunByte );
985cdf0e10cSrcweir 						pRLE += nRunByte;
986cdf0e10cSrcweir 						nX += nRunByte;
987cdf0e10cSrcweir 
988cdf0e10cSrcweir 						if( nRunByte & 1 )
989cdf0e10cSrcweir 							pRLE++;
990cdf0e10cSrcweir 					}
991cdf0e10cSrcweir 				}
992cdf0e10cSrcweir 				else if( !nRunByte )
993cdf0e10cSrcweir 				{
994cdf0e10cSrcweir 					pDIB = ( pRow += nWidthAl );
995cdf0e10cSrcweir 					nX = 0UL;
996cdf0e10cSrcweir 				}
997cdf0e10cSrcweir 				else if( nRunByte == 1 )
998cdf0e10cSrcweir 					bEndDecoding = TRUE;
999cdf0e10cSrcweir 				else
1000cdf0e10cSrcweir 				{
1001cdf0e10cSrcweir 					nX += *pRLE++;
1002cdf0e10cSrcweir 					pDIB = ( pRow += ( *pRLE++ ) * nWidthAl );
1003cdf0e10cSrcweir 				}
1004cdf0e10cSrcweir 			}
1005cdf0e10cSrcweir 			else
1006cdf0e10cSrcweir 			{
1007cdf0e10cSrcweir 				cTmp = *pRLE++;
1008cdf0e10cSrcweir 
1009cdf0e10cSrcweir 				if( bRLE4 )
1010cdf0e10cSrcweir 				{
1011cdf0e10cSrcweir 					nRunByte = nCountByte >> 1;
1012cdf0e10cSrcweir 
1013cdf0e10cSrcweir 					for( i = 0; i < nRunByte; i++ )
1014cdf0e10cSrcweir 					{
1015cdf0e10cSrcweir 						ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
1016cdf0e10cSrcweir 						ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
1017cdf0e10cSrcweir 					}
1018cdf0e10cSrcweir 
1019cdf0e10cSrcweir 					if( nCountByte & 1 )
1020cdf0e10cSrcweir 						ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
1021cdf0e10cSrcweir 				}
1022cdf0e10cSrcweir 				else
1023cdf0e10cSrcweir 				{
1024cdf0e10cSrcweir 					for( i = 0; i < nCountByte; i++ )
1025cdf0e10cSrcweir 						pDIB[ nX++ ] = cTmp;
1026cdf0e10cSrcweir 				}
1027cdf0e10cSrcweir 			}
1028cdf0e10cSrcweir 		}
1029cdf0e10cSrcweir 		while( !bEndDecoding && ( pDIB <= pLast ) );
1030cdf0e10cSrcweir 	}
1031cdf0e10cSrcweir }
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir bool WinSalBitmap::GetSystemData( BitmapSystemData& rData )
1034cdf0e10cSrcweir {
1035cdf0e10cSrcweir     bool bRet = false;
1036cdf0e10cSrcweir     if( mhDIB || mhDDB )
1037cdf0e10cSrcweir     {
1038cdf0e10cSrcweir         bRet = true;
1039cdf0e10cSrcweir         rData.pDIB = mhDIB;
1040cdf0e10cSrcweir         rData.pDDB = mhDDB;
1041cdf0e10cSrcweir         const Size& rSize = GetSize ();
1042cdf0e10cSrcweir         rData.mnWidth = rSize.Width();
1043cdf0e10cSrcweir         rData.mnHeight = rSize.Height();
1044cdf0e10cSrcweir     }
1045cdf0e10cSrcweir     return bRet;
1046cdf0e10cSrcweir }
1047