xref: /aoo41x/main/vcl/win/source/gdi/salbmp.cxx (revision d327e58a)
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
109f62ea84SAndrew Rist  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
129f62ea84SAndrew Rist  *
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.
199f62ea84SAndrew Rist  *
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>
335f27b83cSArmin Le Grand #include <vcl/timer.hxx>
345f27b83cSArmin Le Grand #include <comphelper/broadcasthelper.hxx>
355f27b83cSArmin Le Grand #include <map>
365f27b83cSArmin Le Grand 
375f27b83cSArmin Le Grand #ifndef min
385f27b83cSArmin Le Grand #define min(a,b)	(((a) < (b)) ? (a) : (b))
395f27b83cSArmin Le Grand #endif
405f27b83cSArmin Le Grand #ifndef max
415f27b83cSArmin Le Grand #define max(a,b)	(((a) > (b)) ? (a) : (b))
425f27b83cSArmin Le Grand #endif
43cdf0e10cSrcweir 
445f27b83cSArmin Le Grand #include <GdiPlus.h>
455f27b83cSArmin Le Grand 
465f27b83cSArmin Le Grand // ------------------------------------------------------------------
47cdf0e10cSrcweir // - Inlines -
48cdf0e10cSrcweir 
ImplSetPixel4(const HPBYTE pScanline,long nX,const BYTE cIndex)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 
575f27b83cSArmin Le Grand // ------------------------------------------------------------------
585f27b83cSArmin Le Grand // Helper class to manage Gdiplus::Bitmap instances inside of
595f27b83cSArmin Le Grand // WinSalBitmap
605f27b83cSArmin Le Grand 
615f27b83cSArmin Le Grand struct Comparator
625f27b83cSArmin Le Grand {
operator ()Comparator635f27b83cSArmin Le Grand     bool operator()(WinSalBitmap* pA, WinSalBitmap* pB) const
645f27b83cSArmin Le Grand     {
655f27b83cSArmin Le Grand         return pA < pB;
665f27b83cSArmin Le Grand     }
675f27b83cSArmin Le Grand };
685f27b83cSArmin Le Grand 
695f27b83cSArmin Le Grand typedef ::std::map< WinSalBitmap*, sal_uInt32, Comparator > EntryMap;
705f27b83cSArmin Le Grand static const sal_uInt32 nDefaultCycles(60);
715f27b83cSArmin Le Grand 
725f27b83cSArmin Le Grand class GdiPlusBuffer : protected comphelper::OBaseMutex, public Timer
735f27b83cSArmin Le Grand {
745f27b83cSArmin Le Grand private:
755f27b83cSArmin Le Grand     EntryMap        maEntries;
765f27b83cSArmin Le Grand 
775f27b83cSArmin Le Grand public:
GdiPlusBuffer()785f27b83cSArmin Le Grand     GdiPlusBuffer()
795f27b83cSArmin Le Grand     :   Timer(),
805f27b83cSArmin Le Grand         maEntries()
815f27b83cSArmin Le Grand     {
825f27b83cSArmin Le Grand         SetTimeout(1000);
835f27b83cSArmin Le Grand         Stop();
845f27b83cSArmin Le Grand     }
855f27b83cSArmin Le Grand 
~GdiPlusBuffer()865f27b83cSArmin Le Grand     ~GdiPlusBuffer()
875f27b83cSArmin Le Grand     {
885f27b83cSArmin Le Grand         Stop();
895f27b83cSArmin Le Grand     }
905f27b83cSArmin Le Grand 
addEntry(WinSalBitmap & rEntry)915f27b83cSArmin Le Grand     void addEntry(WinSalBitmap& rEntry)
925f27b83cSArmin Le Grand     {
935f27b83cSArmin Le Grand         ::osl::MutexGuard aGuard(m_aMutex);
945f27b83cSArmin Le Grand         EntryMap::iterator aFound = maEntries.find(&rEntry);
955f27b83cSArmin Le Grand 
965f27b83cSArmin Le Grand         if(aFound == maEntries.end())
975f27b83cSArmin Le Grand         {
985f27b83cSArmin Le Grand             if(maEntries.empty())
995f27b83cSArmin Le Grand             {
1005f27b83cSArmin Le Grand                 Start();
1015f27b83cSArmin Le Grand             }
1025f27b83cSArmin Le Grand 
1035f27b83cSArmin Le Grand             maEntries[&rEntry] = nDefaultCycles;
1045f27b83cSArmin Le Grand         }
1055f27b83cSArmin Le Grand     }
1065f27b83cSArmin Le Grand 
remEntry(WinSalBitmap & rEntry)1075f27b83cSArmin Le Grand     void remEntry(WinSalBitmap& rEntry)
1085f27b83cSArmin Le Grand     {
1095f27b83cSArmin Le Grand         ::osl::MutexGuard aGuard(m_aMutex);
1105f27b83cSArmin Le Grand         EntryMap::iterator aFound = maEntries.find(&rEntry);
1115f27b83cSArmin Le Grand 
1125f27b83cSArmin Le Grand         if(aFound != maEntries.end())
1135f27b83cSArmin Le Grand         {
1145f27b83cSArmin Le Grand             maEntries.erase(aFound);
1155f27b83cSArmin Le Grand 
1165f27b83cSArmin Le Grand             if(maEntries.empty())
1175f27b83cSArmin Le Grand             {
1185f27b83cSArmin Le Grand                 Stop();
1195f27b83cSArmin Le Grand             }
1205f27b83cSArmin Le Grand         }
1215f27b83cSArmin Le Grand     }
1225f27b83cSArmin Le Grand 
touchEntry(WinSalBitmap & rEntry)1235f27b83cSArmin Le Grand     void touchEntry(WinSalBitmap& rEntry)
1245f27b83cSArmin Le Grand     {
1255f27b83cSArmin Le Grand         ::osl::MutexGuard aGuard(m_aMutex);
1265f27b83cSArmin Le Grand         EntryMap::iterator aFound = maEntries.find(&rEntry);
1275f27b83cSArmin Le Grand 
1285f27b83cSArmin Le Grand         if(aFound != maEntries.end())
1295f27b83cSArmin Le Grand         {
1305f27b83cSArmin Le Grand             aFound->second = nDefaultCycles;
1315f27b83cSArmin Le Grand         }
1325f27b83cSArmin Le Grand     }
1335f27b83cSArmin Le Grand 
1345f27b83cSArmin Le Grand     // from parent Timer
Timeout()1355f27b83cSArmin Le Grand     virtual void Timeout()
1365f27b83cSArmin Le Grand     {
1375f27b83cSArmin Le Grand         ::osl::MutexGuard aGuard(m_aMutex);
1385f27b83cSArmin Le Grand         EntryMap::iterator aIter(maEntries.begin());
1395f27b83cSArmin Le Grand 
1405f27b83cSArmin Le Grand         while(aIter != maEntries.end())
1415f27b83cSArmin Le Grand         {
1425f27b83cSArmin Le Grand             if(aIter->second)
1435f27b83cSArmin Le Grand             {
1445f27b83cSArmin Le Grand                 aIter->second--;
1455f27b83cSArmin Le Grand                 aIter++;
1465f27b83cSArmin Le Grand             }
1475f27b83cSArmin Le Grand             else
1485f27b83cSArmin Le Grand             {
1495f27b83cSArmin Le Grand                 EntryMap::iterator aDelete(aIter);
1505f27b83cSArmin Le Grand                 WinSalBitmap* pSource = aDelete->first;
1515f27b83cSArmin Le Grand                 aIter++;
1525f27b83cSArmin Le Grand                 maEntries.erase(aDelete);
1535f27b83cSArmin Le Grand 
1545f27b83cSArmin Le Grand                 if(maEntries.empty())
1555f27b83cSArmin Le Grand                 {
1565f27b83cSArmin Le Grand                     Stop();
1575f27b83cSArmin Le Grand                 }
1585f27b83cSArmin Le Grand 
1595f27b83cSArmin Le Grand                 // delete at WinSalBitmap after entry is removed; this
1605f27b83cSArmin Le Grand                 // way it would not hurt to call remEntry from there, too
1615f27b83cSArmin Le Grand                 if(pSource->maGdiPlusBitmap.get())
1625f27b83cSArmin Le Grand                 {
1635f27b83cSArmin Le Grand                     pSource->maGdiPlusBitmap.reset();
164fa064a0dSArmin Le Grand                     pSource->mpAssociatedAlpha = 0;
1655f27b83cSArmin Le Grand                 }
1665f27b83cSArmin Le Grand             }
1675f27b83cSArmin Le Grand         }
1685f27b83cSArmin Le Grand 
1695f27b83cSArmin Le Grand         if(!maEntries.empty())
1705f27b83cSArmin Le Grand         {
1715f27b83cSArmin Le Grand             Start();
1725f27b83cSArmin Le Grand         }
1735f27b83cSArmin Le Grand     }
1745f27b83cSArmin Le Grand };
1755f27b83cSArmin Le Grand 
1765f27b83cSArmin Le Grand // ------------------------------------------------------------------
1775f27b83cSArmin Le Grand // Global instance of GdiPlusBuffer which manages Gdiplus::Bitmap
1785f27b83cSArmin Le Grand // instances
1795f27b83cSArmin Le Grand 
1805f27b83cSArmin Le Grand static GdiPlusBuffer aGdiPlusBuffer;
1815f27b83cSArmin Le Grand 
1825f27b83cSArmin Le Grand // ------------------------------------------------------------------
183cdf0e10cSrcweir // - WinSalBitmap -
184cdf0e10cSrcweir 
WinSalBitmap()1855f27b83cSArmin Le Grand WinSalBitmap::WinSalBitmap()
1865f27b83cSArmin Le Grand :   maSize(),
1875f27b83cSArmin Le Grand     mhDIB(0),
1885f27b83cSArmin Le Grand     mhDDB(0),
1895f27b83cSArmin Le Grand     maGdiPlusBitmap(),
190fa064a0dSArmin Le Grand     mpAssociatedAlpha(0),
1915f27b83cSArmin Le Grand     mnBitCount(0)
192cdf0e10cSrcweir {
193cdf0e10cSrcweir }
194cdf0e10cSrcweir 
195cdf0e10cSrcweir // ------------------------------------------------------------------
196cdf0e10cSrcweir 
~WinSalBitmap()197cdf0e10cSrcweir WinSalBitmap::~WinSalBitmap()
198cdf0e10cSrcweir {
199cdf0e10cSrcweir 	Destroy();
200cdf0e10cSrcweir }
201cdf0e10cSrcweir 
202cdf0e10cSrcweir // ------------------------------------------------------------------
203cdf0e10cSrcweir 
Destroy()2045f27b83cSArmin Le Grand void WinSalBitmap::Destroy()
2055f27b83cSArmin Le Grand {
2065f27b83cSArmin Le Grand     if(maGdiPlusBitmap.get())
2075f27b83cSArmin Le Grand     {
2085f27b83cSArmin Le Grand         aGdiPlusBuffer.remEntry(*this);
2095f27b83cSArmin Le Grand     }
2105f27b83cSArmin Le Grand 
2115f27b83cSArmin Le Grand     if( mhDIB )
2125f27b83cSArmin Le Grand 		GlobalFree( mhDIB );
2135f27b83cSArmin Le Grand 	else if( mhDDB )
2145f27b83cSArmin Le Grand 		DeleteObject( mhDDB );
2155f27b83cSArmin Le Grand 
2165f27b83cSArmin Le Grand 	maSize = Size();
2175f27b83cSArmin Le Grand 	mnBitCount = 0;
2185f27b83cSArmin Le Grand }
2195f27b83cSArmin Le Grand 
2205f27b83cSArmin Le Grand // ------------------------------------------------------------------
2215f27b83cSArmin Le Grand 
ImplGetGdiPlusBitmap(const WinSalBitmap * pAlphaSource) const2225f27b83cSArmin Le Grand GdiPlusBmpPtr WinSalBitmap::ImplGetGdiPlusBitmap(const WinSalBitmap* pAlphaSource) const
2235f27b83cSArmin Le Grand {
224fa064a0dSArmin Le Grand     WinSalBitmap* pThat = const_cast< WinSalBitmap* >(this);
225fa064a0dSArmin Le Grand 
226fa064a0dSArmin Le Grand     if(maGdiPlusBitmap.get() && pAlphaSource != mpAssociatedAlpha)
227fa064a0dSArmin Le Grand     {
228fa064a0dSArmin Le Grand         // #122350# if associated alpha with which the GDIPlus was constructed has changed
229fa064a0dSArmin Le Grand         // it is necessary to remove it from buffer, reset reference to it and reconstruct
230fa064a0dSArmin Le Grand         pThat->maGdiPlusBitmap.reset();
231fa064a0dSArmin Le Grand         aGdiPlusBuffer.remEntry(const_cast< WinSalBitmap& >(*this));
232fa064a0dSArmin Le Grand     }
233fa064a0dSArmin Le Grand 
2345f27b83cSArmin Le Grand     if(maGdiPlusBitmap.get())
2355f27b83cSArmin Le Grand     {
2365f27b83cSArmin Le Grand         aGdiPlusBuffer.touchEntry(const_cast< WinSalBitmap& >(*this));
2375f27b83cSArmin Le Grand     }
2385f27b83cSArmin Le Grand     else
2395f27b83cSArmin Le Grand     {
2405f27b83cSArmin Le Grand         if(maSize.Width() > 0 && maSize.Height() > 0)
2415f27b83cSArmin Le Grand         {
2425f27b83cSArmin Le Grand             if(pAlphaSource)
2435f27b83cSArmin Le Grand             {
2445f27b83cSArmin Le Grand                 pThat->maGdiPlusBitmap.reset(pThat->ImplCreateGdiPlusBitmap(*pAlphaSource));
245fa064a0dSArmin Le Grand                 pThat->mpAssociatedAlpha = pAlphaSource;
2465f27b83cSArmin Le Grand             }
2475f27b83cSArmin Le Grand             else
2485f27b83cSArmin Le Grand             {
2495f27b83cSArmin Le Grand                 pThat->maGdiPlusBitmap.reset(pThat->ImplCreateGdiPlusBitmap());
250fa064a0dSArmin Le Grand                 pThat->mpAssociatedAlpha = 0;
2515f27b83cSArmin Le Grand             }
2525f27b83cSArmin Le Grand 
2535f27b83cSArmin Le Grand             if(maGdiPlusBitmap.get())
2545f27b83cSArmin Le Grand             {
2555f27b83cSArmin Le Grand                 aGdiPlusBuffer.addEntry(*pThat);
2565f27b83cSArmin Le Grand             }
2575f27b83cSArmin Le Grand         }
2585f27b83cSArmin Le Grand     }
2595f27b83cSArmin Le Grand 
2605f27b83cSArmin Le Grand     return maGdiPlusBitmap;
2615f27b83cSArmin Le Grand }
2625f27b83cSArmin Le Grand 
2635f27b83cSArmin Le Grand // ------------------------------------------------------------------
2645f27b83cSArmin Le Grand 
ImplCreateGdiPlusBitmap()2655f27b83cSArmin Le Grand Gdiplus::Bitmap* WinSalBitmap::ImplCreateGdiPlusBitmap()
2665f27b83cSArmin Le Grand {
2675f27b83cSArmin Le Grand     Gdiplus::Bitmap* pRetval(0);
2685f27b83cSArmin Le Grand     WinSalBitmap* pSalRGB = const_cast< WinSalBitmap* >(this);
2695f27b83cSArmin Le Grand     WinSalBitmap* pExtraWinSalRGB = 0;
2705f27b83cSArmin Le Grand 
2715f27b83cSArmin Le Grand     if(!pSalRGB->ImplGethDIB())
2725f27b83cSArmin Le Grand     {
2735f27b83cSArmin Le Grand         // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap
2745f27b83cSArmin Le Grand         pExtraWinSalRGB = new WinSalBitmap();
2755f27b83cSArmin Le Grand         pExtraWinSalRGB->Create(*pSalRGB, pSalRGB->GetBitCount());
2765f27b83cSArmin Le Grand         pSalRGB = pExtraWinSalRGB;
2775f27b83cSArmin Le Grand     }
2785f27b83cSArmin Le Grand 
2795f27b83cSArmin Le Grand     BitmapBuffer* pRGB = pSalRGB->AcquireBuffer(true);
2805f27b83cSArmin Le Grand     BitmapBuffer* pExtraRGB = 0;
2815f27b83cSArmin Le Grand 
2825f27b83cSArmin Le Grand     if(pRGB && BMP_FORMAT_24BIT_TC_BGR != (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN))
2835f27b83cSArmin Le Grand     {
2845f27b83cSArmin Le Grand         // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format
2855f27b83cSArmin Le Grand         SalTwoRect aSalTwoRect;
2865f27b83cSArmin Le Grand 
2875f27b83cSArmin Le Grand         aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0;
2885f27b83cSArmin Le Grand         aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pRGB->mnWidth;
2895f27b83cSArmin Le Grand         aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pRGB->mnHeight;
2905f27b83cSArmin Le Grand 
2915f27b83cSArmin Le Grand         pExtraRGB = StretchAndConvert(
2925f27b83cSArmin Le Grand             *pRGB,
2935f27b83cSArmin Le Grand             aSalTwoRect,
2945f27b83cSArmin Le Grand             BMP_FORMAT_24BIT_TC_BGR,
2955f27b83cSArmin Le Grand             0);
2965f27b83cSArmin Le Grand 
2975f27b83cSArmin Le Grand         pSalRGB->ReleaseBuffer(pRGB, true);
2985f27b83cSArmin Le Grand         pRGB = pExtraRGB;
2995f27b83cSArmin Le Grand     }
3005f27b83cSArmin Le Grand 
3015f27b83cSArmin Le Grand     if(pRGB
3025f27b83cSArmin Le Grand         && pRGB->mnWidth > 0
3035f27b83cSArmin Le Grand         && pRGB->mnHeight > 0
3045f27b83cSArmin Le Grand         && BMP_FORMAT_24BIT_TC_BGR == (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN))
3055f27b83cSArmin Le Grand     {
3065f27b83cSArmin Le Grand         const sal_uInt32 nW(pRGB->mnWidth);
3075f27b83cSArmin Le Grand         const sal_uInt32 nH(pRGB->mnHeight);
3085f27b83cSArmin Le Grand 
3095f27b83cSArmin Le Grand         pRetval = new Gdiplus::Bitmap(nW, nH, PixelFormat24bppRGB);
3105f27b83cSArmin Le Grand 
3115f27b83cSArmin Le Grand         if(pRetval)
3125f27b83cSArmin Le Grand         {
3135ca7f190SOliver-Rainer Wittmann             if ( pRetval->GetLastStatus() == Gdiplus::Ok )
3145f27b83cSArmin Le Grand             {
3155ca7f190SOliver-Rainer Wittmann                 sal_uInt8* pSrcRGB(pRGB->mpBits);
3165ca7f190SOliver-Rainer Wittmann                 const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3));
3175ca7f190SOliver-Rainer Wittmann                 const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN);
3185ca7f190SOliver-Rainer Wittmann                 const Gdiplus::Rect aAllRect(0, 0, nW, nH);
3195ca7f190SOliver-Rainer Wittmann                 Gdiplus::BitmapData aGdiPlusBitmapData;
3205ca7f190SOliver-Rainer Wittmann                 pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, PixelFormat24bppRGB, &aGdiPlusBitmapData);
3215ca7f190SOliver-Rainer Wittmann 
3225ca7f190SOliver-Rainer Wittmann                 // copy data to Gdiplus::Bitmap; format is BGR here in both cases, so memcpy is possible
3235ca7f190SOliver-Rainer Wittmann                 for(sal_uInt32 y(0); y < nH; y++)
3245ca7f190SOliver-Rainer Wittmann                 {
3255ca7f190SOliver-Rainer Wittmann                     const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1);
3265ca7f190SOliver-Rainer Wittmann                     sal_uInt8* targetPixels = (sal_uInt8*)aGdiPlusBitmapData.Scan0 + (nYInsert * aGdiPlusBitmapData.Stride);
3275f27b83cSArmin Le Grand 
3285ca7f190SOliver-Rainer Wittmann                     memcpy(targetPixels, pSrcRGB, nW * 3);
3295ca7f190SOliver-Rainer Wittmann                     pSrcRGB += nW * 3 + nExtraRGB;
3305ca7f190SOliver-Rainer Wittmann                 }
33133c964a9SArmin Le Grand 
3325ca7f190SOliver-Rainer Wittmann                 pRetval->UnlockBits(&aGdiPlusBitmapData);
3335ca7f190SOliver-Rainer Wittmann             }
3345ca7f190SOliver-Rainer Wittmann             else
3355ca7f190SOliver-Rainer Wittmann             {
3365ca7f190SOliver-Rainer Wittmann                 delete pRetval;
3375ca7f190SOliver-Rainer Wittmann                 pRetval = NULL;
3385ca7f190SOliver-Rainer Wittmann             }
3395f27b83cSArmin Le Grand         }
3405f27b83cSArmin Le Grand     }
3415f27b83cSArmin Le Grand 
3425f27b83cSArmin Le Grand     if(pExtraRGB)
3435f27b83cSArmin Le Grand     {
3444c2391a1SArmin Le Grand         // #123478# shockingly, BitmapBuffer does not free the memory it is controlling
3454c2391a1SArmin Le Grand         // in it's destructor, this *has to be done handish*. Doing it here now
3464c2391a1SArmin Le Grand         delete[] pExtraRGB->mpBits;
3475f27b83cSArmin Le Grand         delete pExtraRGB;
3485f27b83cSArmin Le Grand     }
3495f27b83cSArmin Le Grand     else
3505f27b83cSArmin Le Grand     {
3515f27b83cSArmin Le Grand         pSalRGB->ReleaseBuffer(pRGB, true);
3525f27b83cSArmin Le Grand     }
3535f27b83cSArmin Le Grand 
3545f27b83cSArmin Le Grand     if(pExtraWinSalRGB)
3555f27b83cSArmin Le Grand     {
3565f27b83cSArmin Le Grand         delete pExtraWinSalRGB;
3575f27b83cSArmin Le Grand     }
3585f27b83cSArmin Le Grand 
3595f27b83cSArmin Le Grand     return pRetval;
3605f27b83cSArmin Le Grand }
3615f27b83cSArmin Le Grand 
3625f27b83cSArmin Le Grand // ------------------------------------------------------------------
3635f27b83cSArmin Le Grand 
ImplCreateGdiPlusBitmap(const WinSalBitmap & rAlphaSource)3645f27b83cSArmin Le Grand Gdiplus::Bitmap* WinSalBitmap::ImplCreateGdiPlusBitmap(const WinSalBitmap& rAlphaSource)
3655f27b83cSArmin Le Grand {
3665f27b83cSArmin Le Grand     Gdiplus::Bitmap* pRetval(0);
3675f27b83cSArmin Le Grand     WinSalBitmap* pSalRGB = const_cast< WinSalBitmap* >(this);
3685f27b83cSArmin Le Grand     WinSalBitmap* pExtraWinSalRGB = 0;
3695f27b83cSArmin Le Grand 
3705f27b83cSArmin Le Grand     if(!pSalRGB->ImplGethDIB())
3715f27b83cSArmin Le Grand     {
3725f27b83cSArmin Le Grand         // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap
3735f27b83cSArmin Le Grand         pExtraWinSalRGB = new WinSalBitmap();
3745f27b83cSArmin Le Grand         pExtraWinSalRGB->Create(*pSalRGB, pSalRGB->GetBitCount());
3755f27b83cSArmin Le Grand         pSalRGB = pExtraWinSalRGB;
3765f27b83cSArmin Le Grand     }
3775f27b83cSArmin Le Grand 
3785f27b83cSArmin Le Grand     BitmapBuffer* pRGB = pSalRGB->AcquireBuffer(true);
3795f27b83cSArmin Le Grand     BitmapBuffer* pExtraRGB = 0;
3805f27b83cSArmin Le Grand 
3815f27b83cSArmin Le Grand     if(pRGB && BMP_FORMAT_24BIT_TC_BGR != (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN))
3825f27b83cSArmin Le Grand     {
3835f27b83cSArmin Le Grand         // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format
3845f27b83cSArmin Le Grand         SalTwoRect aSalTwoRect;
3855f27b83cSArmin Le Grand 
3865f27b83cSArmin Le Grand         aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0;
3875f27b83cSArmin Le Grand         aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pRGB->mnWidth;
3885f27b83cSArmin Le Grand         aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pRGB->mnHeight;
3895f27b83cSArmin Le Grand 
3905f27b83cSArmin Le Grand         pExtraRGB = StretchAndConvert(
3915f27b83cSArmin Le Grand             *pRGB,
3925f27b83cSArmin Le Grand             aSalTwoRect,
3935f27b83cSArmin Le Grand             BMP_FORMAT_24BIT_TC_BGR,
3945f27b83cSArmin Le Grand             0);
3955f27b83cSArmin Le Grand 
3965f27b83cSArmin Le Grand         pSalRGB->ReleaseBuffer(pRGB, true);
3975f27b83cSArmin Le Grand         pRGB = pExtraRGB;
3985f27b83cSArmin Le Grand     }
3995f27b83cSArmin Le Grand 
4005f27b83cSArmin Le Grand     WinSalBitmap* pSalA = const_cast< WinSalBitmap* >(&rAlphaSource);
4015f27b83cSArmin Le Grand     WinSalBitmap* pExtraWinSalA = 0;
4025f27b83cSArmin Le Grand 
4035f27b83cSArmin Le Grand     if(!pSalA->ImplGethDIB())
4045f27b83cSArmin Le Grand     {
4055f27b83cSArmin Le Grand         // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap
4065f27b83cSArmin Le Grand         pExtraWinSalA = new WinSalBitmap();
4075f27b83cSArmin Le Grand         pExtraWinSalA->Create(*pSalA, pSalA->GetBitCount());
4085f27b83cSArmin Le Grand         pSalA = pExtraWinSalA;
4095f27b83cSArmin Le Grand     }
4105f27b83cSArmin Le Grand 
4115f27b83cSArmin Le Grand     BitmapBuffer* pA = pSalA->AcquireBuffer(true);
4125f27b83cSArmin Le Grand     BitmapBuffer* pExtraA = 0;
4135f27b83cSArmin Le Grand 
4145f27b83cSArmin Le Grand     if(pA && BMP_FORMAT_8BIT_PAL != (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN))
4155f27b83cSArmin Le Grand     {
4165f27b83cSArmin Le Grand         // convert alpha bitmap to BMP_FORMAT_8BIT_PAL format if not yet in that format
4175f27b83cSArmin Le Grand         SalTwoRect aSalTwoRect;
4185f27b83cSArmin Le Grand 
4195f27b83cSArmin Le Grand         aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0;
4205f27b83cSArmin Le Grand         aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pA->mnWidth;
4215f27b83cSArmin Le Grand         aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pA->mnHeight;
4225f27b83cSArmin Le Grand         const BitmapPalette& rTargetPalette = Bitmap::GetGreyPalette(256);
4235f27b83cSArmin Le Grand 
4245f27b83cSArmin Le Grand         pExtraA = StretchAndConvert(
4255f27b83cSArmin Le Grand             *pA,
4265f27b83cSArmin Le Grand             aSalTwoRect,
4275f27b83cSArmin Le Grand             BMP_FORMAT_8BIT_PAL,
4285f27b83cSArmin Le Grand             &rTargetPalette);
4295f27b83cSArmin Le Grand 
4305f27b83cSArmin Le Grand         pSalA->ReleaseBuffer(pA, true);
4315f27b83cSArmin Le Grand         pA = pExtraA;
4325f27b83cSArmin Le Grand     }
4335f27b83cSArmin Le Grand 
4345f27b83cSArmin Le Grand     if(pRGB
4355f27b83cSArmin Le Grand         && pA
4365f27b83cSArmin Le Grand         && pRGB->mnWidth > 0
4375f27b83cSArmin Le Grand         && pRGB->mnHeight > 0
4385f27b83cSArmin Le Grand         && pRGB->mnWidth == pA->mnWidth
4395f27b83cSArmin Le Grand         && pRGB->mnHeight == pA->mnHeight
4405f27b83cSArmin Le Grand         && BMP_FORMAT_24BIT_TC_BGR == (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN)
4415f27b83cSArmin Le Grand         && BMP_FORMAT_8BIT_PAL == (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN))
4425f27b83cSArmin Le Grand     {
4435f27b83cSArmin Le Grand         // we have alpha and bitmap in known formats, create GdiPlus Bitmap as 32bit ARGB
4445f27b83cSArmin Le Grand         const sal_uInt32 nW(pRGB->mnWidth);
4455f27b83cSArmin Le Grand         const sal_uInt32 nH(pRGB->mnHeight);
4465f27b83cSArmin Le Grand 
4475f27b83cSArmin Le Grand         pRetval = new Gdiplus::Bitmap(nW, nH, PixelFormat32bppARGB);
4485f27b83cSArmin Le Grand 
4495f27b83cSArmin Le Grand         if(pRetval)
4505f27b83cSArmin Le Grand         {
451*d327e58aSArmin Le Grand             if ( pRetval->GetLastStatus() == Gdiplus::Ok ) // 2nd place to secure with new Gdiplus::Bitmap
4525f27b83cSArmin Le Grand             {
453*d327e58aSArmin Le Grand                 sal_uInt8* pSrcRGB(pRGB->mpBits);
454*d327e58aSArmin Le Grand                 sal_uInt8* pSrcA(pA->mpBits);
455*d327e58aSArmin Le Grand                 const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3));
456*d327e58aSArmin Le Grand                 const sal_uInt32 nExtraA(pA->mnScanlineSize - nW);
457*d327e58aSArmin Le Grand                 const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN);
458*d327e58aSArmin Le Grand                 const Gdiplus::Rect aAllRect(0, 0, nW, nH);
459*d327e58aSArmin Le Grand                 Gdiplus::BitmapData aGdiPlusBitmapData;
460*d327e58aSArmin Le Grand                 pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &aGdiPlusBitmapData);
4615f27b83cSArmin Le Grand 
462*d327e58aSArmin Le Grand                 // copy data to Gdiplus::Bitmap; format is BGRA; need to mix BGR from Bitmap and
463*d327e58aSArmin Le Grand                 // A from alpha, so inner loop is needed (who invented BitmapEx..?)
464*d327e58aSArmin Le Grand                 for(sal_uInt32 y(0); y < nH; y++)
4655f27b83cSArmin Le Grand                 {
466*d327e58aSArmin Le Grand                     const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1);
467*d327e58aSArmin Le Grand                     sal_uInt8* targetPixels = (sal_uInt8*)aGdiPlusBitmapData.Scan0 + (nYInsert * aGdiPlusBitmapData.Stride);
468*d327e58aSArmin Le Grand 
469*d327e58aSArmin Le Grand                     for(sal_uInt32 x(0); x < nW; x++)
470*d327e58aSArmin Le Grand                     {
471*d327e58aSArmin Le Grand                         *targetPixels++ = *pSrcRGB++;
472*d327e58aSArmin Le Grand                         *targetPixels++ = *pSrcRGB++;
473*d327e58aSArmin Le Grand                         *targetPixels++ = *pSrcRGB++;
474*d327e58aSArmin Le Grand                         *targetPixels++ = 0xff - *pSrcA++;
475*d327e58aSArmin Le Grand                     }
476*d327e58aSArmin Le Grand 
477*d327e58aSArmin Le Grand                     pSrcRGB += nExtraRGB;
478*d327e58aSArmin Le Grand                     pSrcA += nExtraA;
4795f27b83cSArmin Le Grand                 }
4805f27b83cSArmin Le Grand 
481*d327e58aSArmin Le Grand                 pRetval->UnlockBits(&aGdiPlusBitmapData);
482*d327e58aSArmin Le Grand             }
483*d327e58aSArmin Le Grand             else
484*d327e58aSArmin Le Grand             {
485*d327e58aSArmin Le Grand                 delete pRetval;
486*d327e58aSArmin Le Grand                 pRetval = NULL;
4875f27b83cSArmin Le Grand             }
4885f27b83cSArmin Le Grand         }
4895f27b83cSArmin Le Grand     }
4905f27b83cSArmin Le Grand 
4915f27b83cSArmin Le Grand     if(pExtraA)
4925f27b83cSArmin Le Grand     {
4934c2391a1SArmin Le Grand         // #123478# shockingly, BitmapBuffer does not free the memory it is controlling
4944c2391a1SArmin Le Grand         // in it's destructor, this *has to be done handish*. Doing it here now
4954c2391a1SArmin Le Grand         delete[] pExtraA->mpBits;
4965f27b83cSArmin Le Grand         delete pExtraA;
4975f27b83cSArmin Le Grand     }
4985f27b83cSArmin Le Grand     else
4995f27b83cSArmin Le Grand     {
5005f27b83cSArmin Le Grand         pSalA->ReleaseBuffer(pA, true);
5015f27b83cSArmin Le Grand     }
5025f27b83cSArmin Le Grand 
5035f27b83cSArmin Le Grand     if(pExtraWinSalA)
5045f27b83cSArmin Le Grand     {
5055f27b83cSArmin Le Grand         delete pExtraWinSalA;
5065f27b83cSArmin Le Grand     }
5075f27b83cSArmin Le Grand 
5085f27b83cSArmin Le Grand     if(pExtraRGB)
5095f27b83cSArmin Le Grand     {
5104c2391a1SArmin Le Grand         // #123478# shockingly, BitmapBuffer does not free the memory it is controlling
5114c2391a1SArmin Le Grand         // in it's destructor, this *has to be done handish*. Doing it here now
5124c2391a1SArmin Le Grand         delete[] pExtraRGB->mpBits;
5135f27b83cSArmin Le Grand         delete pExtraRGB;
5145f27b83cSArmin Le Grand     }
5155f27b83cSArmin Le Grand     else
5165f27b83cSArmin Le Grand     {
5175f27b83cSArmin Le Grand         pSalRGB->ReleaseBuffer(pRGB, true);
5185f27b83cSArmin Le Grand     }
5195f27b83cSArmin Le Grand 
5205f27b83cSArmin Le Grand     if(pExtraWinSalRGB)
5215f27b83cSArmin Le Grand     {
5225f27b83cSArmin Le Grand         delete pExtraWinSalRGB;
5235f27b83cSArmin Le Grand     }
5245f27b83cSArmin Le Grand 
5255f27b83cSArmin Le Grand     return pRetval;
5265f27b83cSArmin Le Grand }
5275f27b83cSArmin Le Grand 
5285f27b83cSArmin Le Grand // ------------------------------------------------------------------
5295f27b83cSArmin Le Grand 
Create(HANDLE hBitmap,bool bDIB,bool bCopyHandle)530cdf0e10cSrcweir bool WinSalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle )
531cdf0e10cSrcweir {
532cdf0e10cSrcweir 	bool bRet = TRUE;
533cdf0e10cSrcweir 
534cdf0e10cSrcweir 	if( bDIB )
535cdf0e10cSrcweir 		mhDIB = (HGLOBAL) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap );
536cdf0e10cSrcweir 	else
537cdf0e10cSrcweir 		mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap );
538cdf0e10cSrcweir 
539cdf0e10cSrcweir 	if( mhDIB )
540cdf0e10cSrcweir 	{
541cdf0e10cSrcweir 		PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) GlobalLock( mhDIB );
542cdf0e10cSrcweir 
543cdf0e10cSrcweir 		maSize = Size( pBIH->biWidth, pBIH->biHeight );
544cdf0e10cSrcweir 		mnBitCount = pBIH->biBitCount;
545cdf0e10cSrcweir 
546cdf0e10cSrcweir 		if( mnBitCount )
547cdf0e10cSrcweir 			mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24;
548cdf0e10cSrcweir 
549cdf0e10cSrcweir 		GlobalUnlock( mhDIB );
550cdf0e10cSrcweir 	}
551cdf0e10cSrcweir 	else if( mhDDB )
552cdf0e10cSrcweir 	{
553cdf0e10cSrcweir 		BITMAP	aDDBInfo;
554cdf0e10cSrcweir 
555cdf0e10cSrcweir 		if( WIN_GetObject( mhDDB, sizeof( BITMAP ), &aDDBInfo ) )
556cdf0e10cSrcweir 		{
557cdf0e10cSrcweir 			maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight );
558cdf0e10cSrcweir 			mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel;
559cdf0e10cSrcweir 
560cdf0e10cSrcweir 			if( mnBitCount )
561cdf0e10cSrcweir 			{
562cdf0e10cSrcweir 				mnBitCount = ( mnBitCount <= 1 ) ? 1 :
563cdf0e10cSrcweir 							 ( mnBitCount <= 4 ) ? 4 :
564cdf0e10cSrcweir 							 ( mnBitCount <= 8 ) ? 8 : 24;
565cdf0e10cSrcweir 			}
566cdf0e10cSrcweir 		}
567cdf0e10cSrcweir 		else
568cdf0e10cSrcweir 		{
569cdf0e10cSrcweir 			mhDDB = 0;
570cdf0e10cSrcweir 			bRet = FALSE;
571cdf0e10cSrcweir 		}
572cdf0e10cSrcweir 	}
573cdf0e10cSrcweir 	else
574cdf0e10cSrcweir 		bRet = FALSE;
575cdf0e10cSrcweir 
576cdf0e10cSrcweir 	return bRet;
577cdf0e10cSrcweir }
578cdf0e10cSrcweir 
579cdf0e10cSrcweir // ------------------------------------------------------------------
580cdf0e10cSrcweir 
Create(const Size & rSize,sal_uInt16 nBitCount,const BitmapPalette & rPal)581cdf0e10cSrcweir bool WinSalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal )
582cdf0e10cSrcweir {
583cdf0e10cSrcweir 	bool bRet = FALSE;
584cdf0e10cSrcweir 
585cdf0e10cSrcweir 	mhDIB = ImplCreateDIB( rSize, nBitCount, rPal );
586cdf0e10cSrcweir 
587cdf0e10cSrcweir 	if( mhDIB )
588cdf0e10cSrcweir 	{
589cdf0e10cSrcweir 		maSize = rSize;
590cdf0e10cSrcweir 		mnBitCount = nBitCount;
591cdf0e10cSrcweir 		bRet = TRUE;
592cdf0e10cSrcweir 	}
593cdf0e10cSrcweir 
594cdf0e10cSrcweir 	return bRet;
595cdf0e10cSrcweir }
596cdf0e10cSrcweir 
597cdf0e10cSrcweir // ------------------------------------------------------------------
598cdf0e10cSrcweir 
Create(const SalBitmap & rSSalBitmap)599cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBitmap )
600cdf0e10cSrcweir {
601cdf0e10cSrcweir 	bool bRet = FALSE;
602cdf0e10cSrcweir     const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
603cdf0e10cSrcweir 
604cdf0e10cSrcweir 	if ( rSalBitmap.mhDIB || rSalBitmap.mhDDB )
605cdf0e10cSrcweir 	{
606cdf0e10cSrcweir 		HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : rSalBitmap.mhDDB,
607cdf0e10cSrcweir 										   rSalBitmap.mhDIB != 0 );
608cdf0e10cSrcweir 
609cdf0e10cSrcweir 		if ( hNewHdl )
610cdf0e10cSrcweir 		{
611cdf0e10cSrcweir 			if( rSalBitmap.mhDIB )
612cdf0e10cSrcweir 				mhDIB = (HGLOBAL) hNewHdl;
613cdf0e10cSrcweir 			else if( rSalBitmap.mhDDB )
614cdf0e10cSrcweir 				mhDDB = (HBITMAP) hNewHdl;
615cdf0e10cSrcweir 
616cdf0e10cSrcweir 			maSize = rSalBitmap.maSize;
617cdf0e10cSrcweir 			mnBitCount = rSalBitmap.mnBitCount;
618cdf0e10cSrcweir 
619cdf0e10cSrcweir 			bRet = TRUE;
620cdf0e10cSrcweir 		}
621cdf0e10cSrcweir 	}
622cdf0e10cSrcweir 
623cdf0e10cSrcweir 	return bRet;
624cdf0e10cSrcweir }
625cdf0e10cSrcweir 
626cdf0e10cSrcweir // ------------------------------------------------------------------
627cdf0e10cSrcweir 
Create(const SalBitmap & rSSalBmp,SalGraphics * pSGraphics)628cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics )
629cdf0e10cSrcweir {
630cdf0e10cSrcweir 	bool bRet = FALSE;
631cdf0e10cSrcweir 
632cdf0e10cSrcweir     const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp);
633cdf0e10cSrcweir     WinSalGraphics* pGraphics = static_cast<WinSalGraphics*>(pSGraphics);
634cdf0e10cSrcweir 
635cdf0e10cSrcweir 	if( rSalBmp.mhDIB )
636cdf0e10cSrcweir 	{
637cdf0e10cSrcweir 		PBITMAPINFO 		pBI = (PBITMAPINFO) GlobalLock( rSalBmp.mhDIB );
638cdf0e10cSrcweir 		PBITMAPINFOHEADER	pBIH = (PBITMAPINFOHEADER) pBI;
6395f27b83cSArmin Le Grand 		HDC 				hDC  = pGraphics->getHDC();
640cdf0e10cSrcweir 		HBITMAP 			hNewDDB;
641cdf0e10cSrcweir 		BITMAP				aDDBInfo;
642cdf0e10cSrcweir 		PBYTE				pBits = (PBYTE) pBI + *(DWORD*) pBI +
643cdf0e10cSrcweir 							ImplGetDIBColorCount( rSalBmp.mhDIB ) * sizeof( RGBQUAD );
644cdf0e10cSrcweir 
645cdf0e10cSrcweir 		if( pBIH->biBitCount == 1 )
646cdf0e10cSrcweir 		{
647cdf0e10cSrcweir 			hNewDDB = CreateBitmap( pBIH->biWidth, pBIH->biHeight, 1, 1, NULL );
648cdf0e10cSrcweir 
649cdf0e10cSrcweir 			if( hNewDDB )
650cdf0e10cSrcweir 				SetDIBits( hDC, hNewDDB, 0, pBIH->biHeight, pBits, pBI, DIB_RGB_COLORS );
651cdf0e10cSrcweir 		}
652cdf0e10cSrcweir 		else
653cdf0e10cSrcweir 			hNewDDB = CreateDIBitmap( hDC, (PBITMAPINFOHEADER) pBI, CBM_INIT, pBits, pBI, DIB_RGB_COLORS );
654cdf0e10cSrcweir 
655cdf0e10cSrcweir 		GlobalUnlock( rSalBmp.mhDIB );
656cdf0e10cSrcweir 
657cdf0e10cSrcweir 		if( hNewDDB && WIN_GetObject( hNewDDB, sizeof( BITMAP ), &aDDBInfo ) )
658cdf0e10cSrcweir 		{
659cdf0e10cSrcweir 			mhDDB = hNewDDB;
660cdf0e10cSrcweir 			maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight );
661cdf0e10cSrcweir 			mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel;
662cdf0e10cSrcweir 
663cdf0e10cSrcweir 			bRet = TRUE;
664cdf0e10cSrcweir 		}
665cdf0e10cSrcweir 		else if( hNewDDB )
666cdf0e10cSrcweir 			DeleteObject( hNewDDB );
667cdf0e10cSrcweir 	}
668cdf0e10cSrcweir 
669cdf0e10cSrcweir 	return bRet;
670cdf0e10cSrcweir }
671cdf0e10cSrcweir 
672cdf0e10cSrcweir // ------------------------------------------------------------------
673cdf0e10cSrcweir 
Create(const SalBitmap & rSSalBmp,sal_uInt16 nNewBitCount)674cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, sal_uInt16 nNewBitCount )
675cdf0e10cSrcweir {
676cdf0e10cSrcweir 	bool bRet = FALSE;
677cdf0e10cSrcweir 
678cdf0e10cSrcweir     const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp);
679cdf0e10cSrcweir 
680cdf0e10cSrcweir 	if( rSalBmp.mhDDB )
681cdf0e10cSrcweir 	{
682cdf0e10cSrcweir 		mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() );
683cdf0e10cSrcweir 
684cdf0e10cSrcweir 		if( mhDIB )
685cdf0e10cSrcweir 		{
686cdf0e10cSrcweir 			PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB );
687cdf0e10cSrcweir 			const int	nLines = (int) rSalBmp.maSize.Height();
688cdf0e10cSrcweir 			HDC 		hDC = GetDC( 0 );
689cdf0e10cSrcweir 			PBYTE		pBits = (PBYTE) pBI + *(DWORD*) pBI +
690cdf0e10cSrcweir 								ImplGetDIBColorCount( mhDIB ) * sizeof( RGBQUAD );
691cdf0e10cSrcweir 			SalData*	pSalData = GetSalData();
692cdf0e10cSrcweir 			HPALETTE	hOldPal = 0;
693cdf0e10cSrcweir 
694cdf0e10cSrcweir 			if ( pSalData->mhDitherPal )
695cdf0e10cSrcweir 			{
696cdf0e10cSrcweir 				hOldPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
697cdf0e10cSrcweir 				RealizePalette( hDC );
698cdf0e10cSrcweir 			}
699cdf0e10cSrcweir 
700cdf0e10cSrcweir 			if( GetDIBits( hDC, rSalBmp.mhDDB, 0, nLines, pBits, pBI, DIB_RGB_COLORS ) == nLines )
701cdf0e10cSrcweir 			{
702cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
703cdf0e10cSrcweir 				maSize = rSalBmp.maSize;
704cdf0e10cSrcweir 				mnBitCount = nNewBitCount;
705cdf0e10cSrcweir 				bRet = TRUE;
706cdf0e10cSrcweir 			}
707cdf0e10cSrcweir 			else
708cdf0e10cSrcweir 			{
709cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
710cdf0e10cSrcweir 				GlobalFree( mhDIB );
711cdf0e10cSrcweir 				mhDIB = 0;
712cdf0e10cSrcweir 			}
713cdf0e10cSrcweir 
714cdf0e10cSrcweir 			if( hOldPal )
715cdf0e10cSrcweir 				SelectPalette( hDC, hOldPal, TRUE );
716cdf0e10cSrcweir 
717cdf0e10cSrcweir 			ReleaseDC( 0, hDC );
718cdf0e10cSrcweir 		}
719cdf0e10cSrcweir 	}
720cdf0e10cSrcweir 
721cdf0e10cSrcweir 	return bRet;
722cdf0e10cSrcweir }
723cdf0e10cSrcweir 
724cdf0e10cSrcweir // ------------------------------------------------------------------
725cdf0e10cSrcweir 
ImplGetDIBColorCount(HGLOBAL hDIB)726cdf0e10cSrcweir sal_uInt16 WinSalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB )
727cdf0e10cSrcweir {
728cdf0e10cSrcweir 	sal_uInt16 nColors = 0;
729cdf0e10cSrcweir 
730cdf0e10cSrcweir 	if( hDIB )
731cdf0e10cSrcweir 	{
732cdf0e10cSrcweir 		PBITMAPINFO 		pBI = (PBITMAPINFO) GlobalLock( hDIB );
733cdf0e10cSrcweir 		PBITMAPINFOHEADER	pBIH = (PBITMAPINFOHEADER) pBI;
734cdf0e10cSrcweir 
735cdf0e10cSrcweir 		if ( pBIH->biSize != sizeof( BITMAPCOREHEADER ) )
736cdf0e10cSrcweir 		{
737cdf0e10cSrcweir 			if( pBIH->biBitCount <= 8 )
738cdf0e10cSrcweir 			{
739cdf0e10cSrcweir 				if ( pBIH->biClrUsed )
740cdf0e10cSrcweir 					nColors = (sal_uInt16) pBIH->biClrUsed;
741cdf0e10cSrcweir 				else
742cdf0e10cSrcweir 					nColors = 1 << pBIH->biBitCount;
743cdf0e10cSrcweir 			}
744cdf0e10cSrcweir 		}
745cdf0e10cSrcweir 		else if( ( (PBITMAPCOREHEADER) pBI )->bcBitCount <= 8 )
746cdf0e10cSrcweir 			nColors = 1 << ( (PBITMAPCOREHEADER) pBI )->bcBitCount;
747cdf0e10cSrcweir 
748cdf0e10cSrcweir 		GlobalUnlock( hDIB );
749cdf0e10cSrcweir 	}
750cdf0e10cSrcweir 
751cdf0e10cSrcweir 	return nColors;
752cdf0e10cSrcweir }
753cdf0e10cSrcweir 
754cdf0e10cSrcweir // ------------------------------------------------------------------
755cdf0e10cSrcweir 
ImplCreateDIB(const Size & rSize,sal_uInt16 nBits,const BitmapPalette & rPal)756cdf0e10cSrcweir HGLOBAL WinSalBitmap::ImplCreateDIB( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rPal )
757cdf0e10cSrcweir {
758cdf0e10cSrcweir 	DBG_ASSERT( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 16 || nBits == 24, "Unsupported BitCount!" );
759cdf0e10cSrcweir 
760cdf0e10cSrcweir 	HGLOBAL hDIB = 0;
761cdf0e10cSrcweir 
762562e22fbSHerbert Dürr 	if( rSize.Width() <= 0 || rSize.Height() <= 0 )
763562e22fbSHerbert Dürr 		return hDIB;
764562e22fbSHerbert Dürr 
765562e22fbSHerbert Dürr 	// calculate bitmap size in Bytes
766562e22fbSHerbert Dürr 	const sal_uLong nAlignedWidth4Bytes = AlignedWidth4Bytes( nBits * rSize.Width() );
767562e22fbSHerbert Dürr 	const sal_uLong nImageSize = nAlignedWidth4Bytes * rSize.Height();
768562e22fbSHerbert Dürr 	bool bOverflow = (nImageSize / nAlignedWidth4Bytes) != rSize.Height();
769562e22fbSHerbert Dürr 	if( bOverflow )
770562e22fbSHerbert Dürr 		return hDIB;
771562e22fbSHerbert Dürr 
772562e22fbSHerbert Dürr 	// allocate bitmap memory including header and palette
773562e22fbSHerbert Dürr 	const sal_uInt16 nColors = (nBits <= 8) ? (1 << nBits) : 0;
774562e22fbSHerbert Dürr 	const sal_uLong nHeaderSize = sizeof( BITMAPINFOHEADER ) + nColors * sizeof( RGBQUAD );
775562e22fbSHerbert Dürr 	bOverflow = (nHeaderSize + nImageSize) < nImageSize;
776562e22fbSHerbert Dürr 	if( bOverflow )
777562e22fbSHerbert Dürr 		return hDIB;
778562e22fbSHerbert Dürr 
779562e22fbSHerbert Dürr 	hDIB = GlobalAlloc( GHND, nHeaderSize + nImageSize );
780562e22fbSHerbert Dürr 	if( !hDIB )
781562e22fbSHerbert Dürr 		return hDIB;
782562e22fbSHerbert Dürr 
783562e22fbSHerbert Dürr 	PBITMAPINFO pBI = static_cast<PBITMAPINFO>( GlobalLock( hDIB ) );
7844fee1b5aSArmin Le Grand 	PBITMAPINFOHEADER pBIH = reinterpret_cast<PBITMAPINFOHEADER>( pBI );
785562e22fbSHerbert Dürr 
786562e22fbSHerbert Dürr 	pBIH->biSize = sizeof( BITMAPINFOHEADER );
787562e22fbSHerbert Dürr 	pBIH->biWidth = rSize.Width();
788562e22fbSHerbert Dürr 	pBIH->biHeight = rSize.Height();
789562e22fbSHerbert Dürr 	pBIH->biPlanes = 1;
790562e22fbSHerbert Dürr 	pBIH->biBitCount = nBits;
791562e22fbSHerbert Dürr 	pBIH->biCompression = BI_RGB;
792562e22fbSHerbert Dürr 	pBIH->biSizeImage = nImageSize;
793562e22fbSHerbert Dürr 	pBIH->biXPelsPerMeter = 0;
794562e22fbSHerbert Dürr 	pBIH->biYPelsPerMeter = 0;
795562e22fbSHerbert Dürr 	pBIH->biClrUsed = 0;
796562e22fbSHerbert Dürr 	pBIH->biClrImportant = 0;
797562e22fbSHerbert Dürr 
798562e22fbSHerbert Dürr 	if( nColors )
799cdf0e10cSrcweir 	{
800562e22fbSHerbert Dürr 		// copy the palette entries if any
801562e22fbSHerbert Dürr 		const sal_uInt16 nMinCount = Min( nColors, rPal.GetEntryCount() );
802562e22fbSHerbert Dürr 		if( nMinCount )
803562e22fbSHerbert Dürr 			memcpy( pBI->bmiColors, rPal.ImplGetColorBuffer(), nMinCount * sizeof(RGBQUAD) );
804cdf0e10cSrcweir 	}
805cdf0e10cSrcweir 
806562e22fbSHerbert Dürr 	GlobalUnlock( hDIB );
807562e22fbSHerbert Dürr 
808cdf0e10cSrcweir 	return hDIB;
809cdf0e10cSrcweir }
810cdf0e10cSrcweir 
811cdf0e10cSrcweir // ------------------------------------------------------------------
812cdf0e10cSrcweir 
ImplCopyDIBOrDDB(HANDLE hHdl,bool bDIB)813cdf0e10cSrcweir HANDLE WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB )
814cdf0e10cSrcweir {
815cdf0e10cSrcweir 	HANDLE	hCopy = 0;
816cdf0e10cSrcweir 
817cdf0e10cSrcweir 	if ( bDIB && hHdl )
818cdf0e10cSrcweir 	{
819cdf0e10cSrcweir 		const sal_uLong nSize = GlobalSize( hHdl );
820cdf0e10cSrcweir 
821cdf0e10cSrcweir 		if ( (hCopy = GlobalAlloc( GHND, nSize  )) != 0 )
822cdf0e10cSrcweir 		{
823cdf0e10cSrcweir 			memcpy( (LPSTR) GlobalLock( hCopy ), (LPSTR) GlobalLock( hHdl ), nSize );
824cdf0e10cSrcweir 
825cdf0e10cSrcweir 			GlobalUnlock( hCopy );
826cdf0e10cSrcweir 			GlobalUnlock( hHdl );
827cdf0e10cSrcweir 		}
828cdf0e10cSrcweir 	}
829cdf0e10cSrcweir 	else if ( hHdl )
830cdf0e10cSrcweir 	{
831cdf0e10cSrcweir 		BITMAP aBmp;
832cdf0e10cSrcweir 
833cdf0e10cSrcweir 		// Source-Bitmap nach Groesse befragen
834cdf0e10cSrcweir 		WIN_GetObject( hHdl, sizeof( BITMAP ), (LPSTR) &aBmp );
835cdf0e10cSrcweir 
836cdf0e10cSrcweir 		// Destination-Bitmap erzeugen
837cdf0e10cSrcweir 		if ( (hCopy = CreateBitmapIndirect( &aBmp )) != 0 )
838cdf0e10cSrcweir 		{
839cdf0e10cSrcweir 			HDC 	hBmpDC = CreateCompatibleDC( 0 );
840cdf0e10cSrcweir 			HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hHdl );
841cdf0e10cSrcweir 			HDC 	hCopyDC = CreateCompatibleDC( hBmpDC );
842cdf0e10cSrcweir 			HBITMAP hCopyOld = (HBITMAP) SelectObject( hCopyDC, hCopy );
843cdf0e10cSrcweir 
844cdf0e10cSrcweir 			BitBlt( hCopyDC, 0, 0, aBmp.bmWidth, aBmp.bmHeight, hBmpDC, 0, 0, SRCCOPY );
845cdf0e10cSrcweir 
846cdf0e10cSrcweir 			SelectObject( hCopyDC, hCopyOld );
847cdf0e10cSrcweir 			DeleteDC( hCopyDC );
848cdf0e10cSrcweir 
849cdf0e10cSrcweir 			SelectObject( hBmpDC, hBmpOld );
850cdf0e10cSrcweir 			DeleteDC( hBmpDC );
851cdf0e10cSrcweir 		}
852cdf0e10cSrcweir 	}
853cdf0e10cSrcweir 
854cdf0e10cSrcweir 	return hCopy;
855cdf0e10cSrcweir }
856cdf0e10cSrcweir 
857cdf0e10cSrcweir // ------------------------------------------------------------------
858cdf0e10cSrcweir 
AcquireBuffer(bool)859cdf0e10cSrcweir BitmapBuffer* WinSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
860cdf0e10cSrcweir {
861cdf0e10cSrcweir 	BitmapBuffer* pBuffer = NULL;
862cdf0e10cSrcweir 
863cdf0e10cSrcweir 	if( mhDIB )
864cdf0e10cSrcweir 	{
865cdf0e10cSrcweir 		PBITMAPINFO 		pBI = (PBITMAPINFO) GlobalLock( mhDIB );
866cdf0e10cSrcweir 		PBITMAPINFOHEADER	pBIH = (PBITMAPINFOHEADER) pBI;
867cdf0e10cSrcweir 
868cdf0e10cSrcweir 		if( ( pBIH->biCompression == BI_RLE4 ) || ( pBIH->biCompression == BI_RLE8 ) )
869cdf0e10cSrcweir 		{
870cdf0e10cSrcweir 			Size	aSizePix( pBIH->biWidth, pBIH->biHeight );
871cdf0e10cSrcweir 			HGLOBAL hNewDIB = ImplCreateDIB( aSizePix, pBIH->biBitCount, BitmapPalette() );
872cdf0e10cSrcweir 
873cdf0e10cSrcweir 			if( hNewDIB )
874cdf0e10cSrcweir 			{
875cdf0e10cSrcweir 				PBITMAPINFO 		pNewBI = (PBITMAPINFO) GlobalLock( hNewDIB );
876cdf0e10cSrcweir 				PBITMAPINFOHEADER	pNewBIH = (PBITMAPINFOHEADER) pNewBI;
877cdf0e10cSrcweir 				const sal_uInt16		nColorCount = ImplGetDIBColorCount( hNewDIB );
878cdf0e10cSrcweir 				const sal_uLong 		nOffset = *(DWORD*) pBI + nColorCount * sizeof( RGBQUAD );
879cdf0e10cSrcweir 				BYTE*				pOldBits = (PBYTE) pBI + nOffset;
880cdf0e10cSrcweir 				BYTE*				pNewBits = (PBYTE) pNewBI + nOffset;
881cdf0e10cSrcweir 
882cdf0e10cSrcweir 				memcpy( pNewBI, pBI, nOffset );
883cdf0e10cSrcweir 				pNewBIH->biCompression = 0;
884cdf0e10cSrcweir 				ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->biCompression == BI_RLE4 );
885cdf0e10cSrcweir 
886cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
887cdf0e10cSrcweir 				GlobalFree( mhDIB );
888cdf0e10cSrcweir 				mhDIB = hNewDIB;
889cdf0e10cSrcweir 				pBI = pNewBI;
890cdf0e10cSrcweir 				pBIH = pNewBIH;
891cdf0e10cSrcweir 			}
892cdf0e10cSrcweir 		}
893cdf0e10cSrcweir 
894cdf0e10cSrcweir 		if( pBIH->biPlanes == 1 )
895cdf0e10cSrcweir 		{
896cdf0e10cSrcweir 			pBuffer = new BitmapBuffer;
897cdf0e10cSrcweir 
898cdf0e10cSrcweir 			pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP |
899cdf0e10cSrcweir 								( pBIH->biBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL :
900cdf0e10cSrcweir 								  pBIH->biBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL :
901cdf0e10cSrcweir 								  pBIH->biBitCount == 8 ? BMP_FORMAT_8BIT_PAL :
902cdf0e10cSrcweir 								  pBIH->biBitCount == 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK :
903cdf0e10cSrcweir 								  pBIH->biBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR :
904cdf0e10cSrcweir 								  pBIH->biBitCount == 32 ? BMP_FORMAT_32BIT_TC_MASK : 0UL );
905cdf0e10cSrcweir 
906cdf0e10cSrcweir 			if( BMP_SCANLINE_FORMAT( pBuffer->mnFormat ) )
907cdf0e10cSrcweir 			{
908cdf0e10cSrcweir 				pBuffer->mnWidth = maSize.Width();
909cdf0e10cSrcweir 				pBuffer->mnHeight = maSize.Height();
910cdf0e10cSrcweir 				pBuffer->mnScanlineSize = AlignedWidth4Bytes( maSize.Width() * pBIH->biBitCount );
911cdf0e10cSrcweir 				pBuffer->mnBitCount = (sal_uInt16) pBIH->biBitCount;
912cdf0e10cSrcweir 
913cdf0e10cSrcweir 				if( pBuffer->mnBitCount <= 8 )
914cdf0e10cSrcweir 				{
915cdf0e10cSrcweir 					const sal_uInt16 nPalCount = ImplGetDIBColorCount( mhDIB );
916cdf0e10cSrcweir 
917cdf0e10cSrcweir 					pBuffer->maPalette.SetEntryCount( nPalCount );
918cdf0e10cSrcweir 					memcpy( pBuffer->maPalette.ImplGetColorBuffer(), pBI->bmiColors, nPalCount * sizeof( RGBQUAD ) );
919cdf0e10cSrcweir 					pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nPalCount * sizeof( RGBQUAD );
920cdf0e10cSrcweir 				}
921cdf0e10cSrcweir 				else if( ( pBIH->biBitCount == 16 ) || ( pBIH->biBitCount == 32 ) )
922cdf0e10cSrcweir 				{
923cdf0e10cSrcweir 					sal_uLong nOffset = 0UL;
924cdf0e10cSrcweir 
925cdf0e10cSrcweir 					if( pBIH->biCompression == BI_BITFIELDS )
926cdf0e10cSrcweir 					{
927cdf0e10cSrcweir 						nOffset = 3 * sizeof( RGBQUAD );
928cdf0e10cSrcweir 						pBuffer->maColorMask = ColorMask( *(UINT32*) &pBI->bmiColors[ 0 ],
929cdf0e10cSrcweir 														  *(UINT32*) &pBI->bmiColors[ 1 ],
930cdf0e10cSrcweir 														  *(UINT32*) &pBI->bmiColors[ 2 ] );
931cdf0e10cSrcweir 					}
932cdf0e10cSrcweir 					else if( pBIH->biBitCount == 16 )
933cdf0e10cSrcweir 						pBuffer->maColorMask = ColorMask( 0x00007c00UL, 0x000003e0UL, 0x0000001fUL );
934cdf0e10cSrcweir 					else
935cdf0e10cSrcweir 						pBuffer->maColorMask = ColorMask( 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL );
936cdf0e10cSrcweir 
937cdf0e10cSrcweir 					pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nOffset;
938cdf0e10cSrcweir 				}
939cdf0e10cSrcweir 				else
940cdf0e10cSrcweir 					pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI;
941cdf0e10cSrcweir 			}
942cdf0e10cSrcweir 			else
943cdf0e10cSrcweir 			{
944cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
945cdf0e10cSrcweir 				delete pBuffer;
946cdf0e10cSrcweir 				pBuffer = NULL;
947cdf0e10cSrcweir 			}
948cdf0e10cSrcweir 		}
949cdf0e10cSrcweir 		else
950cdf0e10cSrcweir 			GlobalUnlock( mhDIB );
951cdf0e10cSrcweir 	}
952cdf0e10cSrcweir 
953cdf0e10cSrcweir 	return pBuffer;
954cdf0e10cSrcweir }
955cdf0e10cSrcweir 
956cdf0e10cSrcweir // ------------------------------------------------------------------
957cdf0e10cSrcweir 
ReleaseBuffer(BitmapBuffer * pBuffer,bool bReadOnly)958cdf0e10cSrcweir void WinSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly )
959cdf0e10cSrcweir {
960cdf0e10cSrcweir 	if( pBuffer )
961cdf0e10cSrcweir 	{
962cdf0e10cSrcweir 		if( mhDIB )
963cdf0e10cSrcweir 		{
964cdf0e10cSrcweir 			if( !bReadOnly && !!pBuffer->maPalette )
965cdf0e10cSrcweir 			{
966cdf0e10cSrcweir 				PBITMAPINFO 	pBI = (PBITMAPINFO) GlobalLock( mhDIB );
967cdf0e10cSrcweir 				const sal_uInt16	nCount = pBuffer->maPalette.GetEntryCount();
968cdf0e10cSrcweir 				const sal_uInt16	nDIBColorCount = ImplGetDIBColorCount( mhDIB );
969cdf0e10cSrcweir 				memcpy( pBI->bmiColors, pBuffer->maPalette.ImplGetColorBuffer(), Min( nDIBColorCount, nCount ) * sizeof( RGBQUAD ) );
970cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
971cdf0e10cSrcweir 			}
972cdf0e10cSrcweir 
973cdf0e10cSrcweir 			GlobalUnlock( mhDIB );
974cdf0e10cSrcweir 		}
975cdf0e10cSrcweir 
976cdf0e10cSrcweir 		delete pBuffer;
977cdf0e10cSrcweir 	}
978cdf0e10cSrcweir }
979cdf0e10cSrcweir 
980cdf0e10cSrcweir // ------------------------------------------------------------------
981cdf0e10cSrcweir 
ImplDecodeRLEBuffer(const BYTE * pSrcBuf,BYTE * pDstBuf,const Size & rSizePixel,bool bRLE4)982cdf0e10cSrcweir void WinSalBitmap::ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf,
983cdf0e10cSrcweir 									 const Size& rSizePixel, bool bRLE4 )
984cdf0e10cSrcweir {
985cdf0e10cSrcweir 	HPBYTE			pRLE = (HPBYTE) pSrcBuf;
986cdf0e10cSrcweir 	HPBYTE			pDIB = (HPBYTE) pDstBuf;
987cdf0e10cSrcweir 	HPBYTE			pRow = (HPBYTE) pDstBuf;
988cdf0e10cSrcweir 	sal_uLong			nWidthAl = AlignedWidth4Bytes( rSizePixel.Width() * ( bRLE4 ? 4UL : 8UL ) );
989cdf0e10cSrcweir 	HPBYTE			pLast = pDIB + rSizePixel.Height() * nWidthAl - 1;
990cdf0e10cSrcweir 	sal_uLong			nCountByte;
991cdf0e10cSrcweir 	sal_uLong			nRunByte;
992cdf0e10cSrcweir 	sal_uLong			nX = 0;
993cdf0e10cSrcweir 	sal_uLong			i;
994cdf0e10cSrcweir 	BYTE			cTmp;
995cdf0e10cSrcweir 	bool			bEndDecoding = FALSE;
996cdf0e10cSrcweir 
997cdf0e10cSrcweir 	if( pRLE && pDIB )
998cdf0e10cSrcweir 	{
999cdf0e10cSrcweir 		do
1000cdf0e10cSrcweir 		{
1001cdf0e10cSrcweir 			if( ( nCountByte = *pRLE++ ) == 0 )
1002cdf0e10cSrcweir 			{
1003cdf0e10cSrcweir 				nRunByte = *pRLE++;
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir 				if( nRunByte > 2UL )
1006cdf0e10cSrcweir 				{
1007cdf0e10cSrcweir 					if( bRLE4 )
1008cdf0e10cSrcweir 					{
1009cdf0e10cSrcweir 						nCountByte = nRunByte >> 1UL;
1010cdf0e10cSrcweir 
1011cdf0e10cSrcweir 						for( i = 0; i < nCountByte; i++ )
1012cdf0e10cSrcweir 						{
1013cdf0e10cSrcweir 							cTmp = *pRLE++;
1014cdf0e10cSrcweir 							ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
1015cdf0e10cSrcweir 							ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
1016cdf0e10cSrcweir 						}
1017cdf0e10cSrcweir 
1018cdf0e10cSrcweir 						if( nRunByte & 1 )
1019cdf0e10cSrcweir 							ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 );
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir 						if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
1022cdf0e10cSrcweir 							pRLE++;
1023cdf0e10cSrcweir 					}
1024cdf0e10cSrcweir 					else
1025cdf0e10cSrcweir 					{
1026cdf0e10cSrcweir 						memcpy( &pDIB[ nX ], pRLE, nRunByte );
1027cdf0e10cSrcweir 						pRLE += nRunByte;
1028cdf0e10cSrcweir 						nX += nRunByte;
1029cdf0e10cSrcweir 
1030cdf0e10cSrcweir 						if( nRunByte & 1 )
1031cdf0e10cSrcweir 							pRLE++;
1032cdf0e10cSrcweir 					}
1033cdf0e10cSrcweir 				}
1034cdf0e10cSrcweir 				else if( !nRunByte )
1035cdf0e10cSrcweir 				{
1036cdf0e10cSrcweir 					pDIB = ( pRow += nWidthAl );
1037cdf0e10cSrcweir 					nX = 0UL;
1038cdf0e10cSrcweir 				}
1039cdf0e10cSrcweir 				else if( nRunByte == 1 )
1040cdf0e10cSrcweir 					bEndDecoding = TRUE;
1041cdf0e10cSrcweir 				else
1042cdf0e10cSrcweir 				{
1043cdf0e10cSrcweir 					nX += *pRLE++;
1044cdf0e10cSrcweir 					pDIB = ( pRow += ( *pRLE++ ) * nWidthAl );
1045cdf0e10cSrcweir 				}
1046cdf0e10cSrcweir 			}
1047cdf0e10cSrcweir 			else
1048cdf0e10cSrcweir 			{
1049cdf0e10cSrcweir 				cTmp = *pRLE++;
1050cdf0e10cSrcweir 
1051cdf0e10cSrcweir 				if( bRLE4 )
1052cdf0e10cSrcweir 				{
1053cdf0e10cSrcweir 					nRunByte = nCountByte >> 1;
1054cdf0e10cSrcweir 
1055cdf0e10cSrcweir 					for( i = 0; i < nRunByte; i++ )
1056cdf0e10cSrcweir 					{
1057cdf0e10cSrcweir 						ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
1058cdf0e10cSrcweir 						ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
1059cdf0e10cSrcweir 					}
1060cdf0e10cSrcweir 
1061cdf0e10cSrcweir 					if( nCountByte & 1 )
1062cdf0e10cSrcweir 						ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
1063cdf0e10cSrcweir 				}
1064cdf0e10cSrcweir 				else
1065cdf0e10cSrcweir 				{
1066cdf0e10cSrcweir 					for( i = 0; i < nCountByte; i++ )
1067cdf0e10cSrcweir 						pDIB[ nX++ ] = cTmp;
1068cdf0e10cSrcweir 				}
1069cdf0e10cSrcweir 			}
1070cdf0e10cSrcweir 		}
1071cdf0e10cSrcweir 		while( !bEndDecoding && ( pDIB <= pLast ) );
1072cdf0e10cSrcweir 	}
1073cdf0e10cSrcweir }
1074cdf0e10cSrcweir 
GetSystemData(BitmapSystemData & rData)1075cdf0e10cSrcweir bool WinSalBitmap::GetSystemData( BitmapSystemData& rData )
1076cdf0e10cSrcweir {
1077cdf0e10cSrcweir     bool bRet = false;
1078cdf0e10cSrcweir     if( mhDIB || mhDDB )
1079cdf0e10cSrcweir     {
1080cdf0e10cSrcweir         bRet = true;
1081cdf0e10cSrcweir         rData.pDIB = mhDIB;
1082cdf0e10cSrcweir         rData.pDDB = mhDDB;
1083cdf0e10cSrcweir         const Size& rSize = GetSize ();
1084cdf0e10cSrcweir         rData.mnWidth = rSize.Width();
1085cdf0e10cSrcweir         rData.mnHeight = rSize.Height();
1086cdf0e10cSrcweir     }
1087cdf0e10cSrcweir     return bRet;
1088cdf0e10cSrcweir }
1089