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