19f62ea84SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 39f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 49f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file 59f62ea84SAndrew Rist * distributed with this work for additional information 69f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file 79f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the 89f62ea84SAndrew Rist * "License"); you may not use this file except in compliance 99f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 119f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 139f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing, 149f62ea84SAndrew Rist * software distributed under the License is distributed on an 159f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 169f62ea84SAndrew Rist * KIND, either express or implied. See the License for the 179f62ea84SAndrew Rist * specific language governing permissions and limitations 189f62ea84SAndrew Rist * under the License. 19cdf0e10cSrcweir * 209f62ea84SAndrew Rist *************************************************************/ 219f62ea84SAndrew Rist 22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 23cdf0e10cSrcweir #include "precompiled_vcl.hxx" 24cdf0e10cSrcweir 25cdf0e10cSrcweir #include <tools/svwin.h> 26cdf0e10cSrcweir #include <vcl/bitmap.hxx> // for BitmapSystemData 27cdf0e10cSrcweir #include <vcl/salbtype.hxx> 28cdf0e10cSrcweir #include <win/wincomp.hxx> 29cdf0e10cSrcweir #include <win/salgdi.h> 30cdf0e10cSrcweir #include <win/saldata.hxx> 31cdf0e10cSrcweir #include <win/salbmp.h> 32cdf0e10cSrcweir #include <string.h> 335f27b83cSArmin Le Grand #include <vcl/timer.hxx> 345f27b83cSArmin Le Grand #include <comphelper/broadcasthelper.hxx> 355f27b83cSArmin Le Grand #include <map> 36cdf0e10cSrcweir 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 435f27b83cSArmin Le Grand 445f27b83cSArmin Le Grand #include <GdiPlus.h> 455f27b83cSArmin Le Grand 465f27b83cSArmin Le Grand // ------------------------------------------------------------------ 47cdf0e10cSrcweir // - Inlines - 48cdf0e10cSrcweir 49cdf0e10cSrcweir inline void ImplSetPixel4( const HPBYTE pScanline, long nX, const BYTE cIndex ) 50cdf0e10cSrcweir { 51cdf0e10cSrcweir BYTE& rByte = pScanline[ nX >> 1 ]; 52cdf0e10cSrcweir 53cdf0e10cSrcweir ( nX & 1 ) ? ( rByte &= 0xf0, rByte |= ( cIndex & 0x0f ) ) : 54cdf0e10cSrcweir ( rByte &= 0x0f, rByte |= ( cIndex << 4 ) ); 55cdf0e10cSrcweir } 56cdf0e10cSrcweir 575f27b83cSArmin Le Grand // ------------------------------------------------------------------ 585f27b83cSArmin Le Grand // Helper class to manage Gdiplus::Bitmap instances inside of 595f27b83cSArmin Le Grand // WinSalBitmap 60cdf0e10cSrcweir 615f27b83cSArmin Le Grand struct Comparator 625f27b83cSArmin Le Grand { 635f27b83cSArmin 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: 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 865f27b83cSArmin Le Grand ~GdiPlusBuffer() 875f27b83cSArmin Le Grand { 885f27b83cSArmin Le Grand Stop(); 895f27b83cSArmin Le Grand } 905f27b83cSArmin Le Grand 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 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 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 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 // ------------------------------------------------------------------ 1835f27b83cSArmin Le Grand // - WinSalBitmap - 1845f27b83cSArmin Le Grand 1855f27b83cSArmin Le Grand WinSalBitmap::WinSalBitmap() 1865f27b83cSArmin Le Grand : maSize(), 187cdf0e10cSrcweir mhDIB(0), 188cdf0e10cSrcweir mhDDB(0), 1895f27b83cSArmin Le Grand maGdiPlusBitmap(), 190fa064a0dSArmin Le Grand mpAssociatedAlpha(0), 191cdf0e10cSrcweir mnBitCount(0) 192cdf0e10cSrcweir { 193cdf0e10cSrcweir } 194cdf0e10cSrcweir 195cdf0e10cSrcweir // ------------------------------------------------------------------ 196cdf0e10cSrcweir 197cdf0e10cSrcweir WinSalBitmap::~WinSalBitmap() 198cdf0e10cSrcweir { 199cdf0e10cSrcweir Destroy(); 200cdf0e10cSrcweir } 201cdf0e10cSrcweir 202cdf0e10cSrcweir // ------------------------------------------------------------------ 203cdf0e10cSrcweir 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 2225f27b83cSArmin 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 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 { 3135f27b83cSArmin Le Grand sal_uInt8* pSrcRGB(pRGB->mpBits); 3145f27b83cSArmin Le Grand const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3)); 3155f27b83cSArmin Le Grand const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN); 316*33c964a9SArmin Le Grand const Gdiplus::Rect aAllRect(0, 0, nW, nH); 317*33c964a9SArmin Le Grand Gdiplus::BitmapData aGdiPlusBitmapData; 318*33c964a9SArmin Le Grand pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, PixelFormat24bppRGB, &aGdiPlusBitmapData); 3195f27b83cSArmin Le Grand 320*33c964a9SArmin Le Grand // copy data to Gdiplus::Bitmap; format is BGR here in both cases, so memcpy is possible 3215f27b83cSArmin Le Grand for(sal_uInt32 y(0); y < nH; y++) 3225f27b83cSArmin Le Grand { 3235f27b83cSArmin Le Grand const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1); 324*33c964a9SArmin Le Grand sal_uInt8* targetPixels = (sal_uInt8*)aGdiPlusBitmapData.Scan0 + (nYInsert * aGdiPlusBitmapData.Stride); 3255f27b83cSArmin Le Grand 326*33c964a9SArmin Le Grand memcpy(targetPixels, pSrcRGB, nW * 3); 327*33c964a9SArmin Le Grand pSrcRGB += nW * 3 + nExtraRGB; 3285f27b83cSArmin Le Grand } 3295f27b83cSArmin Le Grand 330*33c964a9SArmin Le Grand pRetval->UnlockBits(&aGdiPlusBitmapData); 3315f27b83cSArmin Le Grand } 3325f27b83cSArmin Le Grand } 3335f27b83cSArmin Le Grand 3345f27b83cSArmin Le Grand if(pExtraRGB) 3355f27b83cSArmin Le Grand { 3365f27b83cSArmin Le Grand delete pExtraRGB; 3375f27b83cSArmin Le Grand } 3385f27b83cSArmin Le Grand else 3395f27b83cSArmin Le Grand { 3405f27b83cSArmin Le Grand pSalRGB->ReleaseBuffer(pRGB, true); 3415f27b83cSArmin Le Grand } 3425f27b83cSArmin Le Grand 3435f27b83cSArmin Le Grand if(pExtraWinSalRGB) 3445f27b83cSArmin Le Grand { 3455f27b83cSArmin Le Grand delete pExtraWinSalRGB; 3465f27b83cSArmin Le Grand } 3475f27b83cSArmin Le Grand 3485f27b83cSArmin Le Grand return pRetval; 3495f27b83cSArmin Le Grand } 3505f27b83cSArmin Le Grand 3515f27b83cSArmin Le Grand // ------------------------------------------------------------------ 3525f27b83cSArmin Le Grand 3535f27b83cSArmin Le Grand Gdiplus::Bitmap* WinSalBitmap::ImplCreateGdiPlusBitmap(const WinSalBitmap& rAlphaSource) 3545f27b83cSArmin Le Grand { 3555f27b83cSArmin Le Grand Gdiplus::Bitmap* pRetval(0); 3565f27b83cSArmin Le Grand WinSalBitmap* pSalRGB = const_cast< WinSalBitmap* >(this); 3575f27b83cSArmin Le Grand WinSalBitmap* pExtraWinSalRGB = 0; 3585f27b83cSArmin Le Grand 3595f27b83cSArmin Le Grand if(!pSalRGB->ImplGethDIB()) 3605f27b83cSArmin Le Grand { 3615f27b83cSArmin Le Grand // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap 3625f27b83cSArmin Le Grand pExtraWinSalRGB = new WinSalBitmap(); 3635f27b83cSArmin Le Grand pExtraWinSalRGB->Create(*pSalRGB, pSalRGB->GetBitCount()); 3645f27b83cSArmin Le Grand pSalRGB = pExtraWinSalRGB; 3655f27b83cSArmin Le Grand } 3665f27b83cSArmin Le Grand 3675f27b83cSArmin Le Grand BitmapBuffer* pRGB = pSalRGB->AcquireBuffer(true); 3685f27b83cSArmin Le Grand BitmapBuffer* pExtraRGB = 0; 3695f27b83cSArmin Le Grand 3705f27b83cSArmin Le Grand if(pRGB && BMP_FORMAT_24BIT_TC_BGR != (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN)) 3715f27b83cSArmin Le Grand { 3725f27b83cSArmin Le Grand // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format 3735f27b83cSArmin Le Grand SalTwoRect aSalTwoRect; 3745f27b83cSArmin Le Grand 3755f27b83cSArmin Le Grand aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0; 3765f27b83cSArmin Le Grand aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pRGB->mnWidth; 3775f27b83cSArmin Le Grand aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pRGB->mnHeight; 3785f27b83cSArmin Le Grand 3795f27b83cSArmin Le Grand pExtraRGB = StretchAndConvert( 3805f27b83cSArmin Le Grand *pRGB, 3815f27b83cSArmin Le Grand aSalTwoRect, 3825f27b83cSArmin Le Grand BMP_FORMAT_24BIT_TC_BGR, 3835f27b83cSArmin Le Grand 0); 3845f27b83cSArmin Le Grand 3855f27b83cSArmin Le Grand pSalRGB->ReleaseBuffer(pRGB, true); 3865f27b83cSArmin Le Grand pRGB = pExtraRGB; 3875f27b83cSArmin Le Grand } 3885f27b83cSArmin Le Grand 3895f27b83cSArmin Le Grand WinSalBitmap* pSalA = const_cast< WinSalBitmap* >(&rAlphaSource); 3905f27b83cSArmin Le Grand WinSalBitmap* pExtraWinSalA = 0; 3915f27b83cSArmin Le Grand 3925f27b83cSArmin Le Grand if(!pSalA->ImplGethDIB()) 3935f27b83cSArmin Le Grand { 3945f27b83cSArmin Le Grand // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap 3955f27b83cSArmin Le Grand pExtraWinSalA = new WinSalBitmap(); 3965f27b83cSArmin Le Grand pExtraWinSalA->Create(*pSalA, pSalA->GetBitCount()); 3975f27b83cSArmin Le Grand pSalA = pExtraWinSalA; 3985f27b83cSArmin Le Grand } 3995f27b83cSArmin Le Grand 4005f27b83cSArmin Le Grand BitmapBuffer* pA = pSalA->AcquireBuffer(true); 4015f27b83cSArmin Le Grand BitmapBuffer* pExtraA = 0; 4025f27b83cSArmin Le Grand 4035f27b83cSArmin Le Grand if(pA && BMP_FORMAT_8BIT_PAL != (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN)) 4045f27b83cSArmin Le Grand { 4055f27b83cSArmin Le Grand // convert alpha bitmap to BMP_FORMAT_8BIT_PAL format if not yet in that format 4065f27b83cSArmin Le Grand SalTwoRect aSalTwoRect; 4075f27b83cSArmin Le Grand 4085f27b83cSArmin Le Grand aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0; 4095f27b83cSArmin Le Grand aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pA->mnWidth; 4105f27b83cSArmin Le Grand aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pA->mnHeight; 4115f27b83cSArmin Le Grand const BitmapPalette& rTargetPalette = Bitmap::GetGreyPalette(256); 4125f27b83cSArmin Le Grand 4135f27b83cSArmin Le Grand pExtraA = StretchAndConvert( 4145f27b83cSArmin Le Grand *pA, 4155f27b83cSArmin Le Grand aSalTwoRect, 4165f27b83cSArmin Le Grand BMP_FORMAT_8BIT_PAL, 4175f27b83cSArmin Le Grand &rTargetPalette); 4185f27b83cSArmin Le Grand 4195f27b83cSArmin Le Grand pSalA->ReleaseBuffer(pA, true); 4205f27b83cSArmin Le Grand pA = pExtraA; 4215f27b83cSArmin Le Grand } 4225f27b83cSArmin Le Grand 4235f27b83cSArmin Le Grand if(pRGB 4245f27b83cSArmin Le Grand && pA 4255f27b83cSArmin Le Grand && pRGB->mnWidth > 0 4265f27b83cSArmin Le Grand && pRGB->mnHeight > 0 4275f27b83cSArmin Le Grand && pRGB->mnWidth == pA->mnWidth 4285f27b83cSArmin Le Grand && pRGB->mnHeight == pA->mnHeight 4295f27b83cSArmin Le Grand && BMP_FORMAT_24BIT_TC_BGR == (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN) 4305f27b83cSArmin Le Grand && BMP_FORMAT_8BIT_PAL == (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN)) 4315f27b83cSArmin Le Grand { 4325f27b83cSArmin Le Grand // we have alpha and bitmap in known formats, create GdiPlus Bitmap as 32bit ARGB 4335f27b83cSArmin Le Grand const sal_uInt32 nW(pRGB->mnWidth); 4345f27b83cSArmin Le Grand const sal_uInt32 nH(pRGB->mnHeight); 4355f27b83cSArmin Le Grand 4365f27b83cSArmin Le Grand pRetval = new Gdiplus::Bitmap(nW, nH, PixelFormat32bppARGB); 4375f27b83cSArmin Le Grand 4385f27b83cSArmin Le Grand if(pRetval) 4395f27b83cSArmin Le Grand { 4405f27b83cSArmin Le Grand sal_uInt8* pSrcRGB(pRGB->mpBits); 4415f27b83cSArmin Le Grand sal_uInt8* pSrcA(pA->mpBits); 4425f27b83cSArmin Le Grand const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3)); 4435f27b83cSArmin Le Grand const sal_uInt32 nExtraA(pA->mnScanlineSize - nW); 4445f27b83cSArmin Le Grand const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN); 445*33c964a9SArmin Le Grand const Gdiplus::Rect aAllRect(0, 0, nW, nH); 446*33c964a9SArmin Le Grand Gdiplus::BitmapData aGdiPlusBitmapData; 447*33c964a9SArmin Le Grand pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &aGdiPlusBitmapData); 4485f27b83cSArmin Le Grand 449*33c964a9SArmin Le Grand // copy data to Gdiplus::Bitmap; format is BGRA; need to mix BGR from Bitmap and 450*33c964a9SArmin Le Grand // A from alpha, so inner loop is needed (who invented BitmapEx..?) 4515f27b83cSArmin Le Grand for(sal_uInt32 y(0); y < nH; y++) 4525f27b83cSArmin Le Grand { 4535f27b83cSArmin Le Grand const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1); 454*33c964a9SArmin Le Grand sal_uInt8* targetPixels = (sal_uInt8*)aGdiPlusBitmapData.Scan0 + (nYInsert * aGdiPlusBitmapData.Stride); 4555f27b83cSArmin Le Grand 4565f27b83cSArmin Le Grand for(sal_uInt32 x(0); x < nW; x++) 4575f27b83cSArmin Le Grand { 458*33c964a9SArmin Le Grand *targetPixels++ = *pSrcRGB++; 459*33c964a9SArmin Le Grand *targetPixels++ = *pSrcRGB++; 460*33c964a9SArmin Le Grand *targetPixels++ = *pSrcRGB++; 461*33c964a9SArmin Le Grand *targetPixels++ = 0xff - *pSrcA++; 4625f27b83cSArmin Le Grand } 4635f27b83cSArmin Le Grand 4645f27b83cSArmin Le Grand pSrcRGB += nExtraRGB; 4655f27b83cSArmin Le Grand pSrcA += nExtraA; 4665f27b83cSArmin Le Grand } 467*33c964a9SArmin Le Grand 468*33c964a9SArmin Le Grand pRetval->UnlockBits(&aGdiPlusBitmapData); 4695f27b83cSArmin Le Grand } 4705f27b83cSArmin Le Grand } 4715f27b83cSArmin Le Grand 4725f27b83cSArmin Le Grand if(pExtraA) 4735f27b83cSArmin Le Grand { 4745f27b83cSArmin Le Grand delete pExtraA; 4755f27b83cSArmin Le Grand } 4765f27b83cSArmin Le Grand else 4775f27b83cSArmin Le Grand { 4785f27b83cSArmin Le Grand pSalA->ReleaseBuffer(pA, true); 4795f27b83cSArmin Le Grand } 4805f27b83cSArmin Le Grand 4815f27b83cSArmin Le Grand if(pExtraWinSalA) 4825f27b83cSArmin Le Grand { 4835f27b83cSArmin Le Grand delete pExtraWinSalA; 4845f27b83cSArmin Le Grand } 4855f27b83cSArmin Le Grand 4865f27b83cSArmin Le Grand if(pExtraRGB) 4875f27b83cSArmin Le Grand { 4885f27b83cSArmin Le Grand delete pExtraRGB; 4895f27b83cSArmin Le Grand } 4905f27b83cSArmin Le Grand else 4915f27b83cSArmin Le Grand { 4925f27b83cSArmin Le Grand pSalRGB->ReleaseBuffer(pRGB, true); 4935f27b83cSArmin Le Grand } 4945f27b83cSArmin Le Grand 4955f27b83cSArmin Le Grand if(pExtraWinSalRGB) 4965f27b83cSArmin Le Grand { 4975f27b83cSArmin Le Grand delete pExtraWinSalRGB; 4985f27b83cSArmin Le Grand } 4995f27b83cSArmin Le Grand 5005f27b83cSArmin Le Grand return pRetval; 5015f27b83cSArmin Le Grand } 5025f27b83cSArmin Le Grand 5035f27b83cSArmin Le Grand // ------------------------------------------------------------------ 5045f27b83cSArmin Le Grand 505cdf0e10cSrcweir bool WinSalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle ) 506cdf0e10cSrcweir { 507cdf0e10cSrcweir bool bRet = TRUE; 508cdf0e10cSrcweir 509cdf0e10cSrcweir if( bDIB ) 510cdf0e10cSrcweir mhDIB = (HGLOBAL) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap ); 511cdf0e10cSrcweir else 512cdf0e10cSrcweir mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap ); 513cdf0e10cSrcweir 514cdf0e10cSrcweir if( mhDIB ) 515cdf0e10cSrcweir { 516cdf0e10cSrcweir PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) GlobalLock( mhDIB ); 517cdf0e10cSrcweir 518cdf0e10cSrcweir maSize = Size( pBIH->biWidth, pBIH->biHeight ); 519cdf0e10cSrcweir mnBitCount = pBIH->biBitCount; 520cdf0e10cSrcweir 521cdf0e10cSrcweir if( mnBitCount ) 522cdf0e10cSrcweir mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24; 523cdf0e10cSrcweir 524cdf0e10cSrcweir GlobalUnlock( mhDIB ); 525cdf0e10cSrcweir } 526cdf0e10cSrcweir else if( mhDDB ) 527cdf0e10cSrcweir { 528cdf0e10cSrcweir BITMAP aDDBInfo; 529cdf0e10cSrcweir 530cdf0e10cSrcweir if( WIN_GetObject( mhDDB, sizeof( BITMAP ), &aDDBInfo ) ) 531cdf0e10cSrcweir { 532cdf0e10cSrcweir maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight ); 533cdf0e10cSrcweir mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel; 534cdf0e10cSrcweir 535cdf0e10cSrcweir if( mnBitCount ) 536cdf0e10cSrcweir { 537cdf0e10cSrcweir mnBitCount = ( mnBitCount <= 1 ) ? 1 : 538cdf0e10cSrcweir ( mnBitCount <= 4 ) ? 4 : 539cdf0e10cSrcweir ( mnBitCount <= 8 ) ? 8 : 24; 540cdf0e10cSrcweir } 541cdf0e10cSrcweir } 542cdf0e10cSrcweir else 543cdf0e10cSrcweir { 544cdf0e10cSrcweir mhDDB = 0; 545cdf0e10cSrcweir bRet = FALSE; 546cdf0e10cSrcweir } 547cdf0e10cSrcweir } 548cdf0e10cSrcweir else 549cdf0e10cSrcweir bRet = FALSE; 550cdf0e10cSrcweir 551cdf0e10cSrcweir return bRet; 552cdf0e10cSrcweir } 553cdf0e10cSrcweir 554cdf0e10cSrcweir // ------------------------------------------------------------------ 555cdf0e10cSrcweir 556cdf0e10cSrcweir bool WinSalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal ) 557cdf0e10cSrcweir { 558cdf0e10cSrcweir bool bRet = FALSE; 559cdf0e10cSrcweir 560cdf0e10cSrcweir mhDIB = ImplCreateDIB( rSize, nBitCount, rPal ); 561cdf0e10cSrcweir 562cdf0e10cSrcweir if( mhDIB ) 563cdf0e10cSrcweir { 564cdf0e10cSrcweir maSize = rSize; 565cdf0e10cSrcweir mnBitCount = nBitCount; 566cdf0e10cSrcweir bRet = TRUE; 567cdf0e10cSrcweir } 568cdf0e10cSrcweir 569cdf0e10cSrcweir return bRet; 570cdf0e10cSrcweir } 571cdf0e10cSrcweir 572cdf0e10cSrcweir // ------------------------------------------------------------------ 573cdf0e10cSrcweir 574cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBitmap ) 575cdf0e10cSrcweir { 576cdf0e10cSrcweir bool bRet = FALSE; 577cdf0e10cSrcweir const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap); 578cdf0e10cSrcweir 579cdf0e10cSrcweir if ( rSalBitmap.mhDIB || rSalBitmap.mhDDB ) 580cdf0e10cSrcweir { 581cdf0e10cSrcweir HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : rSalBitmap.mhDDB, 582cdf0e10cSrcweir rSalBitmap.mhDIB != 0 ); 583cdf0e10cSrcweir 584cdf0e10cSrcweir if ( hNewHdl ) 585cdf0e10cSrcweir { 586cdf0e10cSrcweir if( rSalBitmap.mhDIB ) 587cdf0e10cSrcweir mhDIB = (HGLOBAL) hNewHdl; 588cdf0e10cSrcweir else if( rSalBitmap.mhDDB ) 589cdf0e10cSrcweir mhDDB = (HBITMAP) hNewHdl; 590cdf0e10cSrcweir 591cdf0e10cSrcweir maSize = rSalBitmap.maSize; 592cdf0e10cSrcweir mnBitCount = rSalBitmap.mnBitCount; 593cdf0e10cSrcweir 594cdf0e10cSrcweir bRet = TRUE; 595cdf0e10cSrcweir } 596cdf0e10cSrcweir } 597cdf0e10cSrcweir 598cdf0e10cSrcweir return bRet; 599cdf0e10cSrcweir } 600cdf0e10cSrcweir 601cdf0e10cSrcweir // ------------------------------------------------------------------ 602cdf0e10cSrcweir 603cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics ) 604cdf0e10cSrcweir { 605cdf0e10cSrcweir bool bRet = FALSE; 606cdf0e10cSrcweir 607cdf0e10cSrcweir const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp); 608cdf0e10cSrcweir WinSalGraphics* pGraphics = static_cast<WinSalGraphics*>(pSGraphics); 609cdf0e10cSrcweir 610cdf0e10cSrcweir if( rSalBmp.mhDIB ) 611cdf0e10cSrcweir { 612cdf0e10cSrcweir PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( rSalBmp.mhDIB ); 613cdf0e10cSrcweir PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 6145f27b83cSArmin Le Grand HDC hDC = pGraphics->getHDC(); 615cdf0e10cSrcweir HBITMAP hNewDDB; 616cdf0e10cSrcweir BITMAP aDDBInfo; 617cdf0e10cSrcweir PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + 618cdf0e10cSrcweir ImplGetDIBColorCount( rSalBmp.mhDIB ) * sizeof( RGBQUAD ); 619cdf0e10cSrcweir 620cdf0e10cSrcweir if( pBIH->biBitCount == 1 ) 621cdf0e10cSrcweir { 622cdf0e10cSrcweir hNewDDB = CreateBitmap( pBIH->biWidth, pBIH->biHeight, 1, 1, NULL ); 623cdf0e10cSrcweir 624cdf0e10cSrcweir if( hNewDDB ) 625cdf0e10cSrcweir SetDIBits( hDC, hNewDDB, 0, pBIH->biHeight, pBits, pBI, DIB_RGB_COLORS ); 626cdf0e10cSrcweir } 627cdf0e10cSrcweir else 628cdf0e10cSrcweir hNewDDB = CreateDIBitmap( hDC, (PBITMAPINFOHEADER) pBI, CBM_INIT, pBits, pBI, DIB_RGB_COLORS ); 629cdf0e10cSrcweir 630cdf0e10cSrcweir GlobalUnlock( rSalBmp.mhDIB ); 631cdf0e10cSrcweir 632cdf0e10cSrcweir if( hNewDDB && WIN_GetObject( hNewDDB, sizeof( BITMAP ), &aDDBInfo ) ) 633cdf0e10cSrcweir { 634cdf0e10cSrcweir mhDDB = hNewDDB; 635cdf0e10cSrcweir maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight ); 636cdf0e10cSrcweir mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel; 637cdf0e10cSrcweir 638cdf0e10cSrcweir bRet = TRUE; 639cdf0e10cSrcweir } 640cdf0e10cSrcweir else if( hNewDDB ) 641cdf0e10cSrcweir DeleteObject( hNewDDB ); 642cdf0e10cSrcweir } 643cdf0e10cSrcweir 644cdf0e10cSrcweir return bRet; 645cdf0e10cSrcweir } 646cdf0e10cSrcweir 647cdf0e10cSrcweir // ------------------------------------------------------------------ 648cdf0e10cSrcweir 649cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, sal_uInt16 nNewBitCount ) 650cdf0e10cSrcweir { 651cdf0e10cSrcweir bool bRet = FALSE; 652cdf0e10cSrcweir 653cdf0e10cSrcweir const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp); 654cdf0e10cSrcweir 655cdf0e10cSrcweir if( rSalBmp.mhDDB ) 656cdf0e10cSrcweir { 657cdf0e10cSrcweir mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() ); 658cdf0e10cSrcweir 659cdf0e10cSrcweir if( mhDIB ) 660cdf0e10cSrcweir { 661cdf0e10cSrcweir PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); 662cdf0e10cSrcweir const int nLines = (int) rSalBmp.maSize.Height(); 663cdf0e10cSrcweir HDC hDC = GetDC( 0 ); 664cdf0e10cSrcweir PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + 665cdf0e10cSrcweir ImplGetDIBColorCount( mhDIB ) * sizeof( RGBQUAD ); 666cdf0e10cSrcweir SalData* pSalData = GetSalData(); 667cdf0e10cSrcweir HPALETTE hOldPal = 0; 668cdf0e10cSrcweir 669cdf0e10cSrcweir if ( pSalData->mhDitherPal ) 670cdf0e10cSrcweir { 671cdf0e10cSrcweir hOldPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE ); 672cdf0e10cSrcweir RealizePalette( hDC ); 673cdf0e10cSrcweir } 674cdf0e10cSrcweir 675cdf0e10cSrcweir if( GetDIBits( hDC, rSalBmp.mhDDB, 0, nLines, pBits, pBI, DIB_RGB_COLORS ) == nLines ) 676cdf0e10cSrcweir { 677cdf0e10cSrcweir GlobalUnlock( mhDIB ); 678cdf0e10cSrcweir maSize = rSalBmp.maSize; 679cdf0e10cSrcweir mnBitCount = nNewBitCount; 680cdf0e10cSrcweir bRet = TRUE; 681cdf0e10cSrcweir } 682cdf0e10cSrcweir else 683cdf0e10cSrcweir { 684cdf0e10cSrcweir GlobalUnlock( mhDIB ); 685cdf0e10cSrcweir GlobalFree( mhDIB ); 686cdf0e10cSrcweir mhDIB = 0; 687cdf0e10cSrcweir } 688cdf0e10cSrcweir 689cdf0e10cSrcweir if( hOldPal ) 690cdf0e10cSrcweir SelectPalette( hDC, hOldPal, TRUE ); 691cdf0e10cSrcweir 692cdf0e10cSrcweir ReleaseDC( 0, hDC ); 693cdf0e10cSrcweir } 694cdf0e10cSrcweir } 695cdf0e10cSrcweir 696cdf0e10cSrcweir return bRet; 697cdf0e10cSrcweir } 698cdf0e10cSrcweir 699cdf0e10cSrcweir // ------------------------------------------------------------------ 700cdf0e10cSrcweir 701cdf0e10cSrcweir sal_uInt16 WinSalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB ) 702cdf0e10cSrcweir { 703cdf0e10cSrcweir sal_uInt16 nColors = 0; 704cdf0e10cSrcweir 705cdf0e10cSrcweir if( hDIB ) 706cdf0e10cSrcweir { 707cdf0e10cSrcweir PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDIB ); 708cdf0e10cSrcweir PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 709cdf0e10cSrcweir 710cdf0e10cSrcweir if ( pBIH->biSize != sizeof( BITMAPCOREHEADER ) ) 711cdf0e10cSrcweir { 712cdf0e10cSrcweir if( pBIH->biBitCount <= 8 ) 713cdf0e10cSrcweir { 714cdf0e10cSrcweir if ( pBIH->biClrUsed ) 715cdf0e10cSrcweir nColors = (sal_uInt16) pBIH->biClrUsed; 716cdf0e10cSrcweir else 717cdf0e10cSrcweir nColors = 1 << pBIH->biBitCount; 718cdf0e10cSrcweir } 719cdf0e10cSrcweir } 720cdf0e10cSrcweir else if( ( (PBITMAPCOREHEADER) pBI )->bcBitCount <= 8 ) 721cdf0e10cSrcweir nColors = 1 << ( (PBITMAPCOREHEADER) pBI )->bcBitCount; 722cdf0e10cSrcweir 723cdf0e10cSrcweir GlobalUnlock( hDIB ); 724cdf0e10cSrcweir } 725cdf0e10cSrcweir 726cdf0e10cSrcweir return nColors; 727cdf0e10cSrcweir } 728cdf0e10cSrcweir 729cdf0e10cSrcweir // ------------------------------------------------------------------ 730cdf0e10cSrcweir 731cdf0e10cSrcweir HGLOBAL WinSalBitmap::ImplCreateDIB( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rPal ) 732cdf0e10cSrcweir { 733cdf0e10cSrcweir DBG_ASSERT( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 16 || nBits == 24, "Unsupported BitCount!" ); 734cdf0e10cSrcweir 735cdf0e10cSrcweir HGLOBAL hDIB = 0; 736cdf0e10cSrcweir 737562e22fbSHerbert Dürr if( rSize.Width() <= 0 || rSize.Height() <= 0 ) 738562e22fbSHerbert Dürr return hDIB; 739562e22fbSHerbert Dürr 740562e22fbSHerbert Dürr // calculate bitmap size in Bytes 741562e22fbSHerbert Dürr const sal_uLong nAlignedWidth4Bytes = AlignedWidth4Bytes( nBits * rSize.Width() ); 742562e22fbSHerbert Dürr const sal_uLong nImageSize = nAlignedWidth4Bytes * rSize.Height(); 743562e22fbSHerbert Dürr bool bOverflow = (nImageSize / nAlignedWidth4Bytes) != rSize.Height(); 744562e22fbSHerbert Dürr if( bOverflow ) 745562e22fbSHerbert Dürr return hDIB; 746562e22fbSHerbert Dürr 747562e22fbSHerbert Dürr // allocate bitmap memory including header and palette 748cdf0e10cSrcweir const sal_uInt16 nColors = (nBits <= 8) ? (1 << nBits) : 0; 749562e22fbSHerbert Dürr const sal_uLong nHeaderSize = sizeof( BITMAPINFOHEADER ) + nColors * sizeof( RGBQUAD ); 750562e22fbSHerbert Dürr bOverflow = (nHeaderSize + nImageSize) < nImageSize; 751562e22fbSHerbert Dürr if( bOverflow ) 752562e22fbSHerbert Dürr return hDIB; 753cdf0e10cSrcweir 754562e22fbSHerbert Dürr hDIB = GlobalAlloc( GHND, nHeaderSize + nImageSize ); 755562e22fbSHerbert Dürr if( !hDIB ) 756562e22fbSHerbert Dürr return hDIB; 757cdf0e10cSrcweir 758562e22fbSHerbert Dürr PBITMAPINFO pBI = static_cast<PBITMAPINFO>( GlobalLock( hDIB ) ); 7594fee1b5aSArmin Le Grand PBITMAPINFOHEADER pBIH = reinterpret_cast<PBITMAPINFOHEADER>( pBI ); 760cdf0e10cSrcweir 761cdf0e10cSrcweir pBIH->biSize = sizeof( BITMAPINFOHEADER ); 762cdf0e10cSrcweir pBIH->biWidth = rSize.Width(); 763cdf0e10cSrcweir pBIH->biHeight = rSize.Height(); 764cdf0e10cSrcweir pBIH->biPlanes = 1; 765cdf0e10cSrcweir pBIH->biBitCount = nBits; 766cdf0e10cSrcweir pBIH->biCompression = BI_RGB; 767cdf0e10cSrcweir pBIH->biSizeImage = nImageSize; 768cdf0e10cSrcweir pBIH->biXPelsPerMeter = 0; 769cdf0e10cSrcweir pBIH->biYPelsPerMeter = 0; 770cdf0e10cSrcweir pBIH->biClrUsed = 0; 771cdf0e10cSrcweir pBIH->biClrImportant = 0; 772cdf0e10cSrcweir 773cdf0e10cSrcweir if( nColors ) 774cdf0e10cSrcweir { 775562e22fbSHerbert Dürr // copy the palette entries if any 776cdf0e10cSrcweir const sal_uInt16 nMinCount = Min( nColors, rPal.GetEntryCount() ); 777cdf0e10cSrcweir if( nMinCount ) 778cdf0e10cSrcweir memcpy( pBI->bmiColors, rPal.ImplGetColorBuffer(), nMinCount * sizeof(RGBQUAD) ); 779cdf0e10cSrcweir } 780cdf0e10cSrcweir 781cdf0e10cSrcweir GlobalUnlock( hDIB ); 782cdf0e10cSrcweir 783cdf0e10cSrcweir return hDIB; 784cdf0e10cSrcweir } 785cdf0e10cSrcweir 786cdf0e10cSrcweir // ------------------------------------------------------------------ 787cdf0e10cSrcweir 788cdf0e10cSrcweir HANDLE WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB ) 789cdf0e10cSrcweir { 790cdf0e10cSrcweir HANDLE hCopy = 0; 791cdf0e10cSrcweir 792cdf0e10cSrcweir if ( bDIB && hHdl ) 793cdf0e10cSrcweir { 794cdf0e10cSrcweir const sal_uLong nSize = GlobalSize( hHdl ); 795cdf0e10cSrcweir 796cdf0e10cSrcweir if ( (hCopy = GlobalAlloc( GHND, nSize )) != 0 ) 797cdf0e10cSrcweir { 798cdf0e10cSrcweir memcpy( (LPSTR) GlobalLock( hCopy ), (LPSTR) GlobalLock( hHdl ), nSize ); 799cdf0e10cSrcweir 800cdf0e10cSrcweir GlobalUnlock( hCopy ); 801cdf0e10cSrcweir GlobalUnlock( hHdl ); 802cdf0e10cSrcweir } 803cdf0e10cSrcweir } 804cdf0e10cSrcweir else if ( hHdl ) 805cdf0e10cSrcweir { 806cdf0e10cSrcweir BITMAP aBmp; 807cdf0e10cSrcweir 808cdf0e10cSrcweir // Source-Bitmap nach Groesse befragen 809cdf0e10cSrcweir WIN_GetObject( hHdl, sizeof( BITMAP ), (LPSTR) &aBmp ); 810cdf0e10cSrcweir 811cdf0e10cSrcweir // Destination-Bitmap erzeugen 812cdf0e10cSrcweir if ( (hCopy = CreateBitmapIndirect( &aBmp )) != 0 ) 813cdf0e10cSrcweir { 814cdf0e10cSrcweir HDC hBmpDC = CreateCompatibleDC( 0 ); 815cdf0e10cSrcweir HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hHdl ); 816cdf0e10cSrcweir HDC hCopyDC = CreateCompatibleDC( hBmpDC ); 817cdf0e10cSrcweir HBITMAP hCopyOld = (HBITMAP) SelectObject( hCopyDC, hCopy ); 818cdf0e10cSrcweir 819cdf0e10cSrcweir BitBlt( hCopyDC, 0, 0, aBmp.bmWidth, aBmp.bmHeight, hBmpDC, 0, 0, SRCCOPY ); 820cdf0e10cSrcweir 821cdf0e10cSrcweir SelectObject( hCopyDC, hCopyOld ); 822cdf0e10cSrcweir DeleteDC( hCopyDC ); 823cdf0e10cSrcweir 824cdf0e10cSrcweir SelectObject( hBmpDC, hBmpOld ); 825cdf0e10cSrcweir DeleteDC( hBmpDC ); 826cdf0e10cSrcweir } 827cdf0e10cSrcweir } 828cdf0e10cSrcweir 829cdf0e10cSrcweir return hCopy; 830cdf0e10cSrcweir } 831cdf0e10cSrcweir 832cdf0e10cSrcweir // ------------------------------------------------------------------ 833cdf0e10cSrcweir 834cdf0e10cSrcweir BitmapBuffer* WinSalBitmap::AcquireBuffer( bool /*bReadOnly*/ ) 835cdf0e10cSrcweir { 836cdf0e10cSrcweir BitmapBuffer* pBuffer = NULL; 837cdf0e10cSrcweir 838cdf0e10cSrcweir if( mhDIB ) 839cdf0e10cSrcweir { 840cdf0e10cSrcweir PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); 841cdf0e10cSrcweir PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 842cdf0e10cSrcweir 843cdf0e10cSrcweir if( ( pBIH->biCompression == BI_RLE4 ) || ( pBIH->biCompression == BI_RLE8 ) ) 844cdf0e10cSrcweir { 845cdf0e10cSrcweir Size aSizePix( pBIH->biWidth, pBIH->biHeight ); 846cdf0e10cSrcweir HGLOBAL hNewDIB = ImplCreateDIB( aSizePix, pBIH->biBitCount, BitmapPalette() ); 847cdf0e10cSrcweir 848cdf0e10cSrcweir if( hNewDIB ) 849cdf0e10cSrcweir { 850cdf0e10cSrcweir PBITMAPINFO pNewBI = (PBITMAPINFO) GlobalLock( hNewDIB ); 851cdf0e10cSrcweir PBITMAPINFOHEADER pNewBIH = (PBITMAPINFOHEADER) pNewBI; 852cdf0e10cSrcweir const sal_uInt16 nColorCount = ImplGetDIBColorCount( hNewDIB ); 853cdf0e10cSrcweir const sal_uLong nOffset = *(DWORD*) pBI + nColorCount * sizeof( RGBQUAD ); 854cdf0e10cSrcweir BYTE* pOldBits = (PBYTE) pBI + nOffset; 855cdf0e10cSrcweir BYTE* pNewBits = (PBYTE) pNewBI + nOffset; 856cdf0e10cSrcweir 857cdf0e10cSrcweir memcpy( pNewBI, pBI, nOffset ); 858cdf0e10cSrcweir pNewBIH->biCompression = 0; 859cdf0e10cSrcweir ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->biCompression == BI_RLE4 ); 860cdf0e10cSrcweir 861cdf0e10cSrcweir GlobalUnlock( mhDIB ); 862cdf0e10cSrcweir GlobalFree( mhDIB ); 863cdf0e10cSrcweir mhDIB = hNewDIB; 864cdf0e10cSrcweir pBI = pNewBI; 865cdf0e10cSrcweir pBIH = pNewBIH; 866cdf0e10cSrcweir } 867cdf0e10cSrcweir } 868cdf0e10cSrcweir 869cdf0e10cSrcweir if( pBIH->biPlanes == 1 ) 870cdf0e10cSrcweir { 871cdf0e10cSrcweir pBuffer = new BitmapBuffer; 872cdf0e10cSrcweir 873cdf0e10cSrcweir pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP | 874cdf0e10cSrcweir ( pBIH->biBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL : 875cdf0e10cSrcweir pBIH->biBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL : 876cdf0e10cSrcweir pBIH->biBitCount == 8 ? BMP_FORMAT_8BIT_PAL : 877cdf0e10cSrcweir pBIH->biBitCount == 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK : 878cdf0e10cSrcweir pBIH->biBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR : 879cdf0e10cSrcweir pBIH->biBitCount == 32 ? BMP_FORMAT_32BIT_TC_MASK : 0UL ); 880cdf0e10cSrcweir 881cdf0e10cSrcweir if( BMP_SCANLINE_FORMAT( pBuffer->mnFormat ) ) 882cdf0e10cSrcweir { 883cdf0e10cSrcweir pBuffer->mnWidth = maSize.Width(); 884cdf0e10cSrcweir pBuffer->mnHeight = maSize.Height(); 885cdf0e10cSrcweir pBuffer->mnScanlineSize = AlignedWidth4Bytes( maSize.Width() * pBIH->biBitCount ); 886cdf0e10cSrcweir pBuffer->mnBitCount = (sal_uInt16) pBIH->biBitCount; 887cdf0e10cSrcweir 888cdf0e10cSrcweir if( pBuffer->mnBitCount <= 8 ) 889cdf0e10cSrcweir { 890cdf0e10cSrcweir const sal_uInt16 nPalCount = ImplGetDIBColorCount( mhDIB ); 891cdf0e10cSrcweir 892cdf0e10cSrcweir pBuffer->maPalette.SetEntryCount( nPalCount ); 893cdf0e10cSrcweir memcpy( pBuffer->maPalette.ImplGetColorBuffer(), pBI->bmiColors, nPalCount * sizeof( RGBQUAD ) ); 894cdf0e10cSrcweir pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nPalCount * sizeof( RGBQUAD ); 895cdf0e10cSrcweir } 896cdf0e10cSrcweir else if( ( pBIH->biBitCount == 16 ) || ( pBIH->biBitCount == 32 ) ) 897cdf0e10cSrcweir { 898cdf0e10cSrcweir sal_uLong nOffset = 0UL; 899cdf0e10cSrcweir 900cdf0e10cSrcweir if( pBIH->biCompression == BI_BITFIELDS ) 901cdf0e10cSrcweir { 902cdf0e10cSrcweir nOffset = 3 * sizeof( RGBQUAD ); 903cdf0e10cSrcweir pBuffer->maColorMask = ColorMask( *(UINT32*) &pBI->bmiColors[ 0 ], 904cdf0e10cSrcweir *(UINT32*) &pBI->bmiColors[ 1 ], 905cdf0e10cSrcweir *(UINT32*) &pBI->bmiColors[ 2 ] ); 906cdf0e10cSrcweir } 907cdf0e10cSrcweir else if( pBIH->biBitCount == 16 ) 908cdf0e10cSrcweir pBuffer->maColorMask = ColorMask( 0x00007c00UL, 0x000003e0UL, 0x0000001fUL ); 909cdf0e10cSrcweir else 910cdf0e10cSrcweir pBuffer->maColorMask = ColorMask( 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL ); 911cdf0e10cSrcweir 912cdf0e10cSrcweir pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nOffset; 913cdf0e10cSrcweir } 914cdf0e10cSrcweir else 915cdf0e10cSrcweir pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI; 916cdf0e10cSrcweir } 917cdf0e10cSrcweir else 918cdf0e10cSrcweir { 919cdf0e10cSrcweir GlobalUnlock( mhDIB ); 920cdf0e10cSrcweir delete pBuffer; 921cdf0e10cSrcweir pBuffer = NULL; 922cdf0e10cSrcweir } 923cdf0e10cSrcweir } 924cdf0e10cSrcweir else 925cdf0e10cSrcweir GlobalUnlock( mhDIB ); 926cdf0e10cSrcweir } 927cdf0e10cSrcweir 928cdf0e10cSrcweir return pBuffer; 929cdf0e10cSrcweir } 930cdf0e10cSrcweir 931cdf0e10cSrcweir // ------------------------------------------------------------------ 932cdf0e10cSrcweir 933cdf0e10cSrcweir void WinSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly ) 934cdf0e10cSrcweir { 935cdf0e10cSrcweir if( pBuffer ) 936cdf0e10cSrcweir { 937cdf0e10cSrcweir if( mhDIB ) 938cdf0e10cSrcweir { 939cdf0e10cSrcweir if( !bReadOnly && !!pBuffer->maPalette ) 940cdf0e10cSrcweir { 941cdf0e10cSrcweir PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); 942cdf0e10cSrcweir const sal_uInt16 nCount = pBuffer->maPalette.GetEntryCount(); 943cdf0e10cSrcweir const sal_uInt16 nDIBColorCount = ImplGetDIBColorCount( mhDIB ); 944cdf0e10cSrcweir memcpy( pBI->bmiColors, pBuffer->maPalette.ImplGetColorBuffer(), Min( nDIBColorCount, nCount ) * sizeof( RGBQUAD ) ); 945cdf0e10cSrcweir GlobalUnlock( mhDIB ); 946cdf0e10cSrcweir } 947cdf0e10cSrcweir 948cdf0e10cSrcweir GlobalUnlock( mhDIB ); 949cdf0e10cSrcweir } 950cdf0e10cSrcweir 951cdf0e10cSrcweir delete pBuffer; 952cdf0e10cSrcweir } 953cdf0e10cSrcweir } 954cdf0e10cSrcweir 955cdf0e10cSrcweir // ------------------------------------------------------------------ 956cdf0e10cSrcweir 957cdf0e10cSrcweir void WinSalBitmap::ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf, 958cdf0e10cSrcweir const Size& rSizePixel, bool bRLE4 ) 959cdf0e10cSrcweir { 960cdf0e10cSrcweir HPBYTE pRLE = (HPBYTE) pSrcBuf; 961cdf0e10cSrcweir HPBYTE pDIB = (HPBYTE) pDstBuf; 962cdf0e10cSrcweir HPBYTE pRow = (HPBYTE) pDstBuf; 963cdf0e10cSrcweir sal_uLong nWidthAl = AlignedWidth4Bytes( rSizePixel.Width() * ( bRLE4 ? 4UL : 8UL ) ); 964cdf0e10cSrcweir HPBYTE pLast = pDIB + rSizePixel.Height() * nWidthAl - 1; 965cdf0e10cSrcweir sal_uLong nCountByte; 966cdf0e10cSrcweir sal_uLong nRunByte; 967cdf0e10cSrcweir sal_uLong nX = 0; 968cdf0e10cSrcweir sal_uLong i; 969cdf0e10cSrcweir BYTE cTmp; 970cdf0e10cSrcweir bool bEndDecoding = FALSE; 971cdf0e10cSrcweir 972cdf0e10cSrcweir if( pRLE && pDIB ) 973cdf0e10cSrcweir { 974cdf0e10cSrcweir do 975cdf0e10cSrcweir { 976cdf0e10cSrcweir if( ( nCountByte = *pRLE++ ) == 0 ) 977cdf0e10cSrcweir { 978cdf0e10cSrcweir nRunByte = *pRLE++; 979cdf0e10cSrcweir 980cdf0e10cSrcweir if( nRunByte > 2UL ) 981cdf0e10cSrcweir { 982cdf0e10cSrcweir if( bRLE4 ) 983cdf0e10cSrcweir { 984cdf0e10cSrcweir nCountByte = nRunByte >> 1UL; 985cdf0e10cSrcweir 986cdf0e10cSrcweir for( i = 0; i < nCountByte; i++ ) 987cdf0e10cSrcweir { 988cdf0e10cSrcweir cTmp = *pRLE++; 989cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); 990cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, cTmp & 0x0f ); 991cdf0e10cSrcweir } 992cdf0e10cSrcweir 993cdf0e10cSrcweir if( nRunByte & 1 ) 994cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 ); 995cdf0e10cSrcweir 996cdf0e10cSrcweir if( ( ( nRunByte + 1 ) >> 1 ) & 1 ) 997cdf0e10cSrcweir pRLE++; 998cdf0e10cSrcweir } 999cdf0e10cSrcweir else 1000cdf0e10cSrcweir { 1001cdf0e10cSrcweir memcpy( &pDIB[ nX ], pRLE, nRunByte ); 1002cdf0e10cSrcweir pRLE += nRunByte; 1003cdf0e10cSrcweir nX += nRunByte; 1004cdf0e10cSrcweir 1005cdf0e10cSrcweir if( nRunByte & 1 ) 1006cdf0e10cSrcweir pRLE++; 1007cdf0e10cSrcweir } 1008cdf0e10cSrcweir } 1009cdf0e10cSrcweir else if( !nRunByte ) 1010cdf0e10cSrcweir { 1011cdf0e10cSrcweir pDIB = ( pRow += nWidthAl ); 1012cdf0e10cSrcweir nX = 0UL; 1013cdf0e10cSrcweir } 1014cdf0e10cSrcweir else if( nRunByte == 1 ) 1015cdf0e10cSrcweir bEndDecoding = TRUE; 1016cdf0e10cSrcweir else 1017cdf0e10cSrcweir { 1018cdf0e10cSrcweir nX += *pRLE++; 1019cdf0e10cSrcweir pDIB = ( pRow += ( *pRLE++ ) * nWidthAl ); 1020cdf0e10cSrcweir } 1021cdf0e10cSrcweir } 1022cdf0e10cSrcweir else 1023cdf0e10cSrcweir { 1024cdf0e10cSrcweir cTmp = *pRLE++; 1025cdf0e10cSrcweir 1026cdf0e10cSrcweir if( bRLE4 ) 1027cdf0e10cSrcweir { 1028cdf0e10cSrcweir nRunByte = nCountByte >> 1; 1029cdf0e10cSrcweir 1030cdf0e10cSrcweir for( i = 0; i < nRunByte; i++ ) 1031cdf0e10cSrcweir { 1032cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); 1033cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, cTmp & 0x0f ); 1034cdf0e10cSrcweir } 1035cdf0e10cSrcweir 1036cdf0e10cSrcweir if( nCountByte & 1 ) 1037cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); 1038cdf0e10cSrcweir } 1039cdf0e10cSrcweir else 1040cdf0e10cSrcweir { 1041cdf0e10cSrcweir for( i = 0; i < nCountByte; i++ ) 1042cdf0e10cSrcweir pDIB[ nX++ ] = cTmp; 1043cdf0e10cSrcweir } 1044cdf0e10cSrcweir } 1045cdf0e10cSrcweir } 1046cdf0e10cSrcweir while( !bEndDecoding && ( pDIB <= pLast ) ); 1047cdf0e10cSrcweir } 1048cdf0e10cSrcweir } 1049cdf0e10cSrcweir 1050cdf0e10cSrcweir bool WinSalBitmap::GetSystemData( BitmapSystemData& rData ) 1051cdf0e10cSrcweir { 1052cdf0e10cSrcweir bool bRet = false; 1053cdf0e10cSrcweir if( mhDIB || mhDDB ) 1054cdf0e10cSrcweir { 1055cdf0e10cSrcweir bRet = true; 1056cdf0e10cSrcweir rData.pDIB = mhDIB; 1057cdf0e10cSrcweir rData.pDDB = mhDDB; 1058cdf0e10cSrcweir const Size& rSize = GetSize (); 1059cdf0e10cSrcweir rData.mnWidth = rSize.Width(); 1060cdf0e10cSrcweir rData.mnHeight = rSize.Height(); 1061cdf0e10cSrcweir } 1062cdf0e10cSrcweir return bRet; 1063cdf0e10cSrcweir } 1064