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(); 164*fa064a0dSArmin 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(), 190*fa064a0dSArmin 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 { 224*fa064a0dSArmin Le Grand WinSalBitmap* pThat = const_cast< WinSalBitmap* >(this); 225*fa064a0dSArmin Le Grand 226*fa064a0dSArmin Le Grand if(maGdiPlusBitmap.get() && pAlphaSource != mpAssociatedAlpha) 227*fa064a0dSArmin Le Grand { 228*fa064a0dSArmin Le Grand // #122350# if associated alpha with which the GDIPlus was constructed has changed 229*fa064a0dSArmin Le Grand // it is necessary to remove it from buffer, reset reference to it and reconstruct 230*fa064a0dSArmin Le Grand pThat->maGdiPlusBitmap.reset(); 231*fa064a0dSArmin Le Grand aGdiPlusBuffer.remEntry(const_cast< WinSalBitmap& >(*this)); 232*fa064a0dSArmin Le Grand } 233*fa064a0dSArmin 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)); 245*fa064a0dSArmin Le Grand pThat->mpAssociatedAlpha = pAlphaSource; 2465f27b83cSArmin Le Grand } 2475f27b83cSArmin Le Grand else 2485f27b83cSArmin Le Grand { 2495f27b83cSArmin Le Grand pThat->maGdiPlusBitmap.reset(pThat->ImplCreateGdiPlusBitmap()); 250*fa064a0dSArmin 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); 3165f27b83cSArmin Le Grand 3175f27b83cSArmin Le Grand for(sal_uInt32 y(0); y < nH; y++) 3185f27b83cSArmin Le Grand { 3195f27b83cSArmin Le Grand const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1); 3205f27b83cSArmin Le Grand 3215f27b83cSArmin Le Grand for(sal_uInt32 x(0); x < nW; x++) 3225f27b83cSArmin Le Grand { 3235f27b83cSArmin Le Grand const sal_uInt8 nB(*pSrcRGB++); 3245f27b83cSArmin Le Grand const sal_uInt8 nG(*pSrcRGB++); 3255f27b83cSArmin Le Grand const sal_uInt8 nR(*pSrcRGB++); 3265f27b83cSArmin Le Grand 3275f27b83cSArmin Le Grand pRetval->SetPixel(x, nYInsert, Gdiplus::Color(nR, nG, nB)); 3285f27b83cSArmin Le Grand } 3295f27b83cSArmin Le Grand 3305f27b83cSArmin Le Grand pSrcRGB += nExtraRGB; 3315f27b83cSArmin Le Grand } 3325f27b83cSArmin Le Grand } 3335f27b83cSArmin Le Grand } 3345f27b83cSArmin Le Grand 3355f27b83cSArmin Le Grand if(pExtraRGB) 3365f27b83cSArmin Le Grand { 3375f27b83cSArmin Le Grand delete pExtraRGB; 3385f27b83cSArmin Le Grand } 3395f27b83cSArmin Le Grand else 3405f27b83cSArmin Le Grand { 3415f27b83cSArmin Le Grand pSalRGB->ReleaseBuffer(pRGB, true); 3425f27b83cSArmin Le Grand } 3435f27b83cSArmin Le Grand 3445f27b83cSArmin Le Grand if(pExtraWinSalRGB) 3455f27b83cSArmin Le Grand { 3465f27b83cSArmin Le Grand delete pExtraWinSalRGB; 3475f27b83cSArmin Le Grand } 3485f27b83cSArmin Le Grand 3495f27b83cSArmin Le Grand return pRetval; 3505f27b83cSArmin Le Grand } 3515f27b83cSArmin Le Grand 3525f27b83cSArmin Le Grand // ------------------------------------------------------------------ 3535f27b83cSArmin Le Grand 3545f27b83cSArmin Le Grand Gdiplus::Bitmap* WinSalBitmap::ImplCreateGdiPlusBitmap(const WinSalBitmap& rAlphaSource) 3555f27b83cSArmin Le Grand { 3565f27b83cSArmin Le Grand Gdiplus::Bitmap* pRetval(0); 3575f27b83cSArmin Le Grand WinSalBitmap* pSalRGB = const_cast< WinSalBitmap* >(this); 3585f27b83cSArmin Le Grand WinSalBitmap* pExtraWinSalRGB = 0; 3595f27b83cSArmin Le Grand 3605f27b83cSArmin Le Grand if(!pSalRGB->ImplGethDIB()) 3615f27b83cSArmin Le Grand { 3625f27b83cSArmin Le Grand // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap 3635f27b83cSArmin Le Grand pExtraWinSalRGB = new WinSalBitmap(); 3645f27b83cSArmin Le Grand pExtraWinSalRGB->Create(*pSalRGB, pSalRGB->GetBitCount()); 3655f27b83cSArmin Le Grand pSalRGB = pExtraWinSalRGB; 3665f27b83cSArmin Le Grand } 3675f27b83cSArmin Le Grand 3685f27b83cSArmin Le Grand BitmapBuffer* pRGB = pSalRGB->AcquireBuffer(true); 3695f27b83cSArmin Le Grand BitmapBuffer* pExtraRGB = 0; 3705f27b83cSArmin Le Grand 3715f27b83cSArmin Le Grand if(pRGB && BMP_FORMAT_24BIT_TC_BGR != (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN)) 3725f27b83cSArmin Le Grand { 3735f27b83cSArmin Le Grand // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format 3745f27b83cSArmin Le Grand SalTwoRect aSalTwoRect; 3755f27b83cSArmin Le Grand 3765f27b83cSArmin Le Grand aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0; 3775f27b83cSArmin Le Grand aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pRGB->mnWidth; 3785f27b83cSArmin Le Grand aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pRGB->mnHeight; 3795f27b83cSArmin Le Grand 3805f27b83cSArmin Le Grand pExtraRGB = StretchAndConvert( 3815f27b83cSArmin Le Grand *pRGB, 3825f27b83cSArmin Le Grand aSalTwoRect, 3835f27b83cSArmin Le Grand BMP_FORMAT_24BIT_TC_BGR, 3845f27b83cSArmin Le Grand 0); 3855f27b83cSArmin Le Grand 3865f27b83cSArmin Le Grand pSalRGB->ReleaseBuffer(pRGB, true); 3875f27b83cSArmin Le Grand pRGB = pExtraRGB; 3885f27b83cSArmin Le Grand } 3895f27b83cSArmin Le Grand 3905f27b83cSArmin Le Grand WinSalBitmap* pSalA = const_cast< WinSalBitmap* >(&rAlphaSource); 3915f27b83cSArmin Le Grand WinSalBitmap* pExtraWinSalA = 0; 3925f27b83cSArmin Le Grand 3935f27b83cSArmin Le Grand if(!pSalA->ImplGethDIB()) 3945f27b83cSArmin Le Grand { 3955f27b83cSArmin Le Grand // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap 3965f27b83cSArmin Le Grand pExtraWinSalA = new WinSalBitmap(); 3975f27b83cSArmin Le Grand pExtraWinSalA->Create(*pSalA, pSalA->GetBitCount()); 3985f27b83cSArmin Le Grand pSalA = pExtraWinSalA; 3995f27b83cSArmin Le Grand } 4005f27b83cSArmin Le Grand 4015f27b83cSArmin Le Grand BitmapBuffer* pA = pSalA->AcquireBuffer(true); 4025f27b83cSArmin Le Grand BitmapBuffer* pExtraA = 0; 4035f27b83cSArmin Le Grand 4045f27b83cSArmin Le Grand if(pA && BMP_FORMAT_8BIT_PAL != (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN)) 4055f27b83cSArmin Le Grand { 4065f27b83cSArmin Le Grand // convert alpha bitmap to BMP_FORMAT_8BIT_PAL format if not yet in that format 4075f27b83cSArmin Le Grand SalTwoRect aSalTwoRect; 4085f27b83cSArmin Le Grand 4095f27b83cSArmin Le Grand aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0; 4105f27b83cSArmin Le Grand aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pA->mnWidth; 4115f27b83cSArmin Le Grand aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pA->mnHeight; 4125f27b83cSArmin Le Grand const BitmapPalette& rTargetPalette = Bitmap::GetGreyPalette(256); 4135f27b83cSArmin Le Grand 4145f27b83cSArmin Le Grand pExtraA = StretchAndConvert( 4155f27b83cSArmin Le Grand *pA, 4165f27b83cSArmin Le Grand aSalTwoRect, 4175f27b83cSArmin Le Grand BMP_FORMAT_8BIT_PAL, 4185f27b83cSArmin Le Grand &rTargetPalette); 4195f27b83cSArmin Le Grand 4205f27b83cSArmin Le Grand pSalA->ReleaseBuffer(pA, true); 4215f27b83cSArmin Le Grand pA = pExtraA; 4225f27b83cSArmin Le Grand } 4235f27b83cSArmin Le Grand 4245f27b83cSArmin Le Grand if(pRGB 4255f27b83cSArmin Le Grand && pA 4265f27b83cSArmin Le Grand && pRGB->mnWidth > 0 4275f27b83cSArmin Le Grand && pRGB->mnHeight > 0 4285f27b83cSArmin Le Grand && pRGB->mnWidth == pA->mnWidth 4295f27b83cSArmin Le Grand && pRGB->mnHeight == pA->mnHeight 4305f27b83cSArmin Le Grand && BMP_FORMAT_24BIT_TC_BGR == (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN) 4315f27b83cSArmin Le Grand && BMP_FORMAT_8BIT_PAL == (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN)) 4325f27b83cSArmin Le Grand { 4335f27b83cSArmin Le Grand // we have alpha and bitmap in known formats, create GdiPlus Bitmap as 32bit ARGB 4345f27b83cSArmin Le Grand const sal_uInt32 nW(pRGB->mnWidth); 4355f27b83cSArmin Le Grand const sal_uInt32 nH(pRGB->mnHeight); 4365f27b83cSArmin Le Grand 4375f27b83cSArmin Le Grand pRetval = new Gdiplus::Bitmap(nW, nH, PixelFormat32bppARGB); 4385f27b83cSArmin Le Grand 4395f27b83cSArmin Le Grand if(pRetval) 4405f27b83cSArmin Le Grand { 4415f27b83cSArmin Le Grand sal_uInt8* pSrcRGB(pRGB->mpBits); 4425f27b83cSArmin Le Grand sal_uInt8* pSrcA(pA->mpBits); 4435f27b83cSArmin Le Grand const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3)); 4445f27b83cSArmin Le Grand const sal_uInt32 nExtraA(pA->mnScanlineSize - nW); 4455f27b83cSArmin Le Grand const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN); 4465f27b83cSArmin Le Grand 4475f27b83cSArmin Le Grand for(sal_uInt32 y(0); y < nH; y++) 4485f27b83cSArmin Le Grand { 4495f27b83cSArmin Le Grand const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1); 4505f27b83cSArmin Le Grand 4515f27b83cSArmin Le Grand for(sal_uInt32 x(0); x < nW; x++) 4525f27b83cSArmin Le Grand { 4535f27b83cSArmin Le Grand const sal_uInt8 nB(*pSrcRGB++); 4545f27b83cSArmin Le Grand const sal_uInt8 nG(*pSrcRGB++); 4555f27b83cSArmin Le Grand const sal_uInt8 nR(*pSrcRGB++); 4565f27b83cSArmin Le Grand const sal_uInt8 nA(0xff - *pSrcA++); 4575f27b83cSArmin Le Grand 4585f27b83cSArmin Le Grand pRetval->SetPixel(x, nYInsert, Gdiplus::Color(nA, nR, nG, nB)); 4595f27b83cSArmin Le Grand } 4605f27b83cSArmin Le Grand 4615f27b83cSArmin Le Grand pSrcRGB += nExtraRGB; 4625f27b83cSArmin Le Grand pSrcA += nExtraA; 4635f27b83cSArmin Le Grand } 4645f27b83cSArmin Le Grand } 4655f27b83cSArmin Le Grand } 4665f27b83cSArmin Le Grand 4675f27b83cSArmin Le Grand if(pExtraA) 4685f27b83cSArmin Le Grand { 4695f27b83cSArmin Le Grand delete pExtraA; 4705f27b83cSArmin Le Grand } 4715f27b83cSArmin Le Grand else 4725f27b83cSArmin Le Grand { 4735f27b83cSArmin Le Grand pSalA->ReleaseBuffer(pA, true); 4745f27b83cSArmin Le Grand } 4755f27b83cSArmin Le Grand 4765f27b83cSArmin Le Grand if(pExtraWinSalA) 4775f27b83cSArmin Le Grand { 4785f27b83cSArmin Le Grand delete pExtraWinSalA; 4795f27b83cSArmin Le Grand } 4805f27b83cSArmin Le Grand 4815f27b83cSArmin Le Grand if(pExtraRGB) 4825f27b83cSArmin Le Grand { 4835f27b83cSArmin Le Grand delete pExtraRGB; 4845f27b83cSArmin Le Grand } 4855f27b83cSArmin Le Grand else 4865f27b83cSArmin Le Grand { 4875f27b83cSArmin Le Grand pSalRGB->ReleaseBuffer(pRGB, true); 4885f27b83cSArmin Le Grand } 4895f27b83cSArmin Le Grand 4905f27b83cSArmin Le Grand if(pExtraWinSalRGB) 4915f27b83cSArmin Le Grand { 4925f27b83cSArmin Le Grand delete pExtraWinSalRGB; 4935f27b83cSArmin Le Grand } 4945f27b83cSArmin Le Grand 4955f27b83cSArmin Le Grand return pRetval; 4965f27b83cSArmin Le Grand } 4975f27b83cSArmin Le Grand 4985f27b83cSArmin Le Grand // ------------------------------------------------------------------ 4995f27b83cSArmin Le Grand 500cdf0e10cSrcweir bool WinSalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle ) 501cdf0e10cSrcweir { 502cdf0e10cSrcweir bool bRet = TRUE; 503cdf0e10cSrcweir 504cdf0e10cSrcweir if( bDIB ) 505cdf0e10cSrcweir mhDIB = (HGLOBAL) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap ); 506cdf0e10cSrcweir else 507cdf0e10cSrcweir mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap ); 508cdf0e10cSrcweir 509cdf0e10cSrcweir if( mhDIB ) 510cdf0e10cSrcweir { 511cdf0e10cSrcweir PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) GlobalLock( mhDIB ); 512cdf0e10cSrcweir 513cdf0e10cSrcweir maSize = Size( pBIH->biWidth, pBIH->biHeight ); 514cdf0e10cSrcweir mnBitCount = pBIH->biBitCount; 515cdf0e10cSrcweir 516cdf0e10cSrcweir if( mnBitCount ) 517cdf0e10cSrcweir mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24; 518cdf0e10cSrcweir 519cdf0e10cSrcweir GlobalUnlock( mhDIB ); 520cdf0e10cSrcweir } 521cdf0e10cSrcweir else if( mhDDB ) 522cdf0e10cSrcweir { 523cdf0e10cSrcweir BITMAP aDDBInfo; 524cdf0e10cSrcweir 525cdf0e10cSrcweir if( WIN_GetObject( mhDDB, sizeof( BITMAP ), &aDDBInfo ) ) 526cdf0e10cSrcweir { 527cdf0e10cSrcweir maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight ); 528cdf0e10cSrcweir mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel; 529cdf0e10cSrcweir 530cdf0e10cSrcweir if( mnBitCount ) 531cdf0e10cSrcweir { 532cdf0e10cSrcweir mnBitCount = ( mnBitCount <= 1 ) ? 1 : 533cdf0e10cSrcweir ( mnBitCount <= 4 ) ? 4 : 534cdf0e10cSrcweir ( mnBitCount <= 8 ) ? 8 : 24; 535cdf0e10cSrcweir } 536cdf0e10cSrcweir } 537cdf0e10cSrcweir else 538cdf0e10cSrcweir { 539cdf0e10cSrcweir mhDDB = 0; 540cdf0e10cSrcweir bRet = FALSE; 541cdf0e10cSrcweir } 542cdf0e10cSrcweir } 543cdf0e10cSrcweir else 544cdf0e10cSrcweir bRet = FALSE; 545cdf0e10cSrcweir 546cdf0e10cSrcweir return bRet; 547cdf0e10cSrcweir } 548cdf0e10cSrcweir 549cdf0e10cSrcweir // ------------------------------------------------------------------ 550cdf0e10cSrcweir 551cdf0e10cSrcweir bool WinSalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal ) 552cdf0e10cSrcweir { 553cdf0e10cSrcweir bool bRet = FALSE; 554cdf0e10cSrcweir 555cdf0e10cSrcweir mhDIB = ImplCreateDIB( rSize, nBitCount, rPal ); 556cdf0e10cSrcweir 557cdf0e10cSrcweir if( mhDIB ) 558cdf0e10cSrcweir { 559cdf0e10cSrcweir maSize = rSize; 560cdf0e10cSrcweir mnBitCount = nBitCount; 561cdf0e10cSrcweir bRet = TRUE; 562cdf0e10cSrcweir } 563cdf0e10cSrcweir 564cdf0e10cSrcweir return bRet; 565cdf0e10cSrcweir } 566cdf0e10cSrcweir 567cdf0e10cSrcweir // ------------------------------------------------------------------ 568cdf0e10cSrcweir 569cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBitmap ) 570cdf0e10cSrcweir { 571cdf0e10cSrcweir bool bRet = FALSE; 572cdf0e10cSrcweir const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap); 573cdf0e10cSrcweir 574cdf0e10cSrcweir if ( rSalBitmap.mhDIB || rSalBitmap.mhDDB ) 575cdf0e10cSrcweir { 576cdf0e10cSrcweir HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : rSalBitmap.mhDDB, 577cdf0e10cSrcweir rSalBitmap.mhDIB != 0 ); 578cdf0e10cSrcweir 579cdf0e10cSrcweir if ( hNewHdl ) 580cdf0e10cSrcweir { 581cdf0e10cSrcweir if( rSalBitmap.mhDIB ) 582cdf0e10cSrcweir mhDIB = (HGLOBAL) hNewHdl; 583cdf0e10cSrcweir else if( rSalBitmap.mhDDB ) 584cdf0e10cSrcweir mhDDB = (HBITMAP) hNewHdl; 585cdf0e10cSrcweir 586cdf0e10cSrcweir maSize = rSalBitmap.maSize; 587cdf0e10cSrcweir mnBitCount = rSalBitmap.mnBitCount; 588cdf0e10cSrcweir 589cdf0e10cSrcweir bRet = TRUE; 590cdf0e10cSrcweir } 591cdf0e10cSrcweir } 592cdf0e10cSrcweir 593cdf0e10cSrcweir return bRet; 594cdf0e10cSrcweir } 595cdf0e10cSrcweir 596cdf0e10cSrcweir // ------------------------------------------------------------------ 597cdf0e10cSrcweir 598cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics ) 599cdf0e10cSrcweir { 600cdf0e10cSrcweir bool bRet = FALSE; 601cdf0e10cSrcweir 602cdf0e10cSrcweir const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp); 603cdf0e10cSrcweir WinSalGraphics* pGraphics = static_cast<WinSalGraphics*>(pSGraphics); 604cdf0e10cSrcweir 605cdf0e10cSrcweir if( rSalBmp.mhDIB ) 606cdf0e10cSrcweir { 607cdf0e10cSrcweir PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( rSalBmp.mhDIB ); 608cdf0e10cSrcweir PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 6095f27b83cSArmin Le Grand HDC hDC = pGraphics->getHDC(); 610cdf0e10cSrcweir HBITMAP hNewDDB; 611cdf0e10cSrcweir BITMAP aDDBInfo; 612cdf0e10cSrcweir PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + 613cdf0e10cSrcweir ImplGetDIBColorCount( rSalBmp.mhDIB ) * sizeof( RGBQUAD ); 614cdf0e10cSrcweir 615cdf0e10cSrcweir if( pBIH->biBitCount == 1 ) 616cdf0e10cSrcweir { 617cdf0e10cSrcweir hNewDDB = CreateBitmap( pBIH->biWidth, pBIH->biHeight, 1, 1, NULL ); 618cdf0e10cSrcweir 619cdf0e10cSrcweir if( hNewDDB ) 620cdf0e10cSrcweir SetDIBits( hDC, hNewDDB, 0, pBIH->biHeight, pBits, pBI, DIB_RGB_COLORS ); 621cdf0e10cSrcweir } 622cdf0e10cSrcweir else 623cdf0e10cSrcweir hNewDDB = CreateDIBitmap( hDC, (PBITMAPINFOHEADER) pBI, CBM_INIT, pBits, pBI, DIB_RGB_COLORS ); 624cdf0e10cSrcweir 625cdf0e10cSrcweir GlobalUnlock( rSalBmp.mhDIB ); 626cdf0e10cSrcweir 627cdf0e10cSrcweir if( hNewDDB && WIN_GetObject( hNewDDB, sizeof( BITMAP ), &aDDBInfo ) ) 628cdf0e10cSrcweir { 629cdf0e10cSrcweir mhDDB = hNewDDB; 630cdf0e10cSrcweir maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight ); 631cdf0e10cSrcweir mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel; 632cdf0e10cSrcweir 633cdf0e10cSrcweir bRet = TRUE; 634cdf0e10cSrcweir } 635cdf0e10cSrcweir else if( hNewDDB ) 636cdf0e10cSrcweir DeleteObject( hNewDDB ); 637cdf0e10cSrcweir } 638cdf0e10cSrcweir 639cdf0e10cSrcweir return bRet; 640cdf0e10cSrcweir } 641cdf0e10cSrcweir 642cdf0e10cSrcweir // ------------------------------------------------------------------ 643cdf0e10cSrcweir 644cdf0e10cSrcweir bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, sal_uInt16 nNewBitCount ) 645cdf0e10cSrcweir { 646cdf0e10cSrcweir bool bRet = FALSE; 647cdf0e10cSrcweir 648cdf0e10cSrcweir const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp); 649cdf0e10cSrcweir 650cdf0e10cSrcweir if( rSalBmp.mhDDB ) 651cdf0e10cSrcweir { 652cdf0e10cSrcweir mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() ); 653cdf0e10cSrcweir 654cdf0e10cSrcweir if( mhDIB ) 655cdf0e10cSrcweir { 656cdf0e10cSrcweir PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); 657cdf0e10cSrcweir const int nLines = (int) rSalBmp.maSize.Height(); 658cdf0e10cSrcweir HDC hDC = GetDC( 0 ); 659cdf0e10cSrcweir PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + 660cdf0e10cSrcweir ImplGetDIBColorCount( mhDIB ) * sizeof( RGBQUAD ); 661cdf0e10cSrcweir SalData* pSalData = GetSalData(); 662cdf0e10cSrcweir HPALETTE hOldPal = 0; 663cdf0e10cSrcweir 664cdf0e10cSrcweir if ( pSalData->mhDitherPal ) 665cdf0e10cSrcweir { 666cdf0e10cSrcweir hOldPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE ); 667cdf0e10cSrcweir RealizePalette( hDC ); 668cdf0e10cSrcweir } 669cdf0e10cSrcweir 670cdf0e10cSrcweir if( GetDIBits( hDC, rSalBmp.mhDDB, 0, nLines, pBits, pBI, DIB_RGB_COLORS ) == nLines ) 671cdf0e10cSrcweir { 672cdf0e10cSrcweir GlobalUnlock( mhDIB ); 673cdf0e10cSrcweir maSize = rSalBmp.maSize; 674cdf0e10cSrcweir mnBitCount = nNewBitCount; 675cdf0e10cSrcweir bRet = TRUE; 676cdf0e10cSrcweir } 677cdf0e10cSrcweir else 678cdf0e10cSrcweir { 679cdf0e10cSrcweir GlobalUnlock( mhDIB ); 680cdf0e10cSrcweir GlobalFree( mhDIB ); 681cdf0e10cSrcweir mhDIB = 0; 682cdf0e10cSrcweir } 683cdf0e10cSrcweir 684cdf0e10cSrcweir if( hOldPal ) 685cdf0e10cSrcweir SelectPalette( hDC, hOldPal, TRUE ); 686cdf0e10cSrcweir 687cdf0e10cSrcweir ReleaseDC( 0, hDC ); 688cdf0e10cSrcweir } 689cdf0e10cSrcweir } 690cdf0e10cSrcweir 691cdf0e10cSrcweir return bRet; 692cdf0e10cSrcweir } 693cdf0e10cSrcweir 694cdf0e10cSrcweir // ------------------------------------------------------------------ 695cdf0e10cSrcweir 696cdf0e10cSrcweir sal_uInt16 WinSalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB ) 697cdf0e10cSrcweir { 698cdf0e10cSrcweir sal_uInt16 nColors = 0; 699cdf0e10cSrcweir 700cdf0e10cSrcweir if( hDIB ) 701cdf0e10cSrcweir { 702cdf0e10cSrcweir PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDIB ); 703cdf0e10cSrcweir PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 704cdf0e10cSrcweir 705cdf0e10cSrcweir if ( pBIH->biSize != sizeof( BITMAPCOREHEADER ) ) 706cdf0e10cSrcweir { 707cdf0e10cSrcweir if( pBIH->biBitCount <= 8 ) 708cdf0e10cSrcweir { 709cdf0e10cSrcweir if ( pBIH->biClrUsed ) 710cdf0e10cSrcweir nColors = (sal_uInt16) pBIH->biClrUsed; 711cdf0e10cSrcweir else 712cdf0e10cSrcweir nColors = 1 << pBIH->biBitCount; 713cdf0e10cSrcweir } 714cdf0e10cSrcweir } 715cdf0e10cSrcweir else if( ( (PBITMAPCOREHEADER) pBI )->bcBitCount <= 8 ) 716cdf0e10cSrcweir nColors = 1 << ( (PBITMAPCOREHEADER) pBI )->bcBitCount; 717cdf0e10cSrcweir 718cdf0e10cSrcweir GlobalUnlock( hDIB ); 719cdf0e10cSrcweir } 720cdf0e10cSrcweir 721cdf0e10cSrcweir return nColors; 722cdf0e10cSrcweir } 723cdf0e10cSrcweir 724cdf0e10cSrcweir // ------------------------------------------------------------------ 725cdf0e10cSrcweir 726cdf0e10cSrcweir HGLOBAL WinSalBitmap::ImplCreateDIB( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rPal ) 727cdf0e10cSrcweir { 728cdf0e10cSrcweir DBG_ASSERT( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 16 || nBits == 24, "Unsupported BitCount!" ); 729cdf0e10cSrcweir 730cdf0e10cSrcweir HGLOBAL hDIB = 0; 731cdf0e10cSrcweir 732562e22fbSHerbert Dürr if( rSize.Width() <= 0 || rSize.Height() <= 0 ) 733562e22fbSHerbert Dürr return hDIB; 734562e22fbSHerbert Dürr 735562e22fbSHerbert Dürr // calculate bitmap size in Bytes 736562e22fbSHerbert Dürr const sal_uLong nAlignedWidth4Bytes = AlignedWidth4Bytes( nBits * rSize.Width() ); 737562e22fbSHerbert Dürr const sal_uLong nImageSize = nAlignedWidth4Bytes * rSize.Height(); 738562e22fbSHerbert Dürr bool bOverflow = (nImageSize / nAlignedWidth4Bytes) != rSize.Height(); 739562e22fbSHerbert Dürr if( bOverflow ) 740562e22fbSHerbert Dürr return hDIB; 741562e22fbSHerbert Dürr 742562e22fbSHerbert Dürr // allocate bitmap memory including header and palette 743cdf0e10cSrcweir const sal_uInt16 nColors = (nBits <= 8) ? (1 << nBits) : 0; 744562e22fbSHerbert Dürr const sal_uLong nHeaderSize = sizeof( BITMAPINFOHEADER ) + nColors * sizeof( RGBQUAD ); 745562e22fbSHerbert Dürr bOverflow = (nHeaderSize + nImageSize) < nImageSize; 746562e22fbSHerbert Dürr if( bOverflow ) 747562e22fbSHerbert Dürr return hDIB; 748cdf0e10cSrcweir 749562e22fbSHerbert Dürr hDIB = GlobalAlloc( GHND, nHeaderSize + nImageSize ); 750562e22fbSHerbert Dürr if( !hDIB ) 751562e22fbSHerbert Dürr return hDIB; 752cdf0e10cSrcweir 753562e22fbSHerbert Dürr PBITMAPINFO pBI = static_cast<PBITMAPINFO>( GlobalLock( hDIB ) ); 7544fee1b5aSArmin Le Grand PBITMAPINFOHEADER pBIH = reinterpret_cast<PBITMAPINFOHEADER>( pBI ); 755cdf0e10cSrcweir 756cdf0e10cSrcweir pBIH->biSize = sizeof( BITMAPINFOHEADER ); 757cdf0e10cSrcweir pBIH->biWidth = rSize.Width(); 758cdf0e10cSrcweir pBIH->biHeight = rSize.Height(); 759cdf0e10cSrcweir pBIH->biPlanes = 1; 760cdf0e10cSrcweir pBIH->biBitCount = nBits; 761cdf0e10cSrcweir pBIH->biCompression = BI_RGB; 762cdf0e10cSrcweir pBIH->biSizeImage = nImageSize; 763cdf0e10cSrcweir pBIH->biXPelsPerMeter = 0; 764cdf0e10cSrcweir pBIH->biYPelsPerMeter = 0; 765cdf0e10cSrcweir pBIH->biClrUsed = 0; 766cdf0e10cSrcweir pBIH->biClrImportant = 0; 767cdf0e10cSrcweir 768cdf0e10cSrcweir if( nColors ) 769cdf0e10cSrcweir { 770562e22fbSHerbert Dürr // copy the palette entries if any 771cdf0e10cSrcweir const sal_uInt16 nMinCount = Min( nColors, rPal.GetEntryCount() ); 772cdf0e10cSrcweir if( nMinCount ) 773cdf0e10cSrcweir memcpy( pBI->bmiColors, rPal.ImplGetColorBuffer(), nMinCount * sizeof(RGBQUAD) ); 774cdf0e10cSrcweir } 775cdf0e10cSrcweir 776cdf0e10cSrcweir GlobalUnlock( hDIB ); 777cdf0e10cSrcweir 778cdf0e10cSrcweir return hDIB; 779cdf0e10cSrcweir } 780cdf0e10cSrcweir 781cdf0e10cSrcweir // ------------------------------------------------------------------ 782cdf0e10cSrcweir 783cdf0e10cSrcweir HANDLE WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB ) 784cdf0e10cSrcweir { 785cdf0e10cSrcweir HANDLE hCopy = 0; 786cdf0e10cSrcweir 787cdf0e10cSrcweir if ( bDIB && hHdl ) 788cdf0e10cSrcweir { 789cdf0e10cSrcweir const sal_uLong nSize = GlobalSize( hHdl ); 790cdf0e10cSrcweir 791cdf0e10cSrcweir if ( (hCopy = GlobalAlloc( GHND, nSize )) != 0 ) 792cdf0e10cSrcweir { 793cdf0e10cSrcweir memcpy( (LPSTR) GlobalLock( hCopy ), (LPSTR) GlobalLock( hHdl ), nSize ); 794cdf0e10cSrcweir 795cdf0e10cSrcweir GlobalUnlock( hCopy ); 796cdf0e10cSrcweir GlobalUnlock( hHdl ); 797cdf0e10cSrcweir } 798cdf0e10cSrcweir } 799cdf0e10cSrcweir else if ( hHdl ) 800cdf0e10cSrcweir { 801cdf0e10cSrcweir BITMAP aBmp; 802cdf0e10cSrcweir 803cdf0e10cSrcweir // Source-Bitmap nach Groesse befragen 804cdf0e10cSrcweir WIN_GetObject( hHdl, sizeof( BITMAP ), (LPSTR) &aBmp ); 805cdf0e10cSrcweir 806cdf0e10cSrcweir // Destination-Bitmap erzeugen 807cdf0e10cSrcweir if ( (hCopy = CreateBitmapIndirect( &aBmp )) != 0 ) 808cdf0e10cSrcweir { 809cdf0e10cSrcweir HDC hBmpDC = CreateCompatibleDC( 0 ); 810cdf0e10cSrcweir HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hHdl ); 811cdf0e10cSrcweir HDC hCopyDC = CreateCompatibleDC( hBmpDC ); 812cdf0e10cSrcweir HBITMAP hCopyOld = (HBITMAP) SelectObject( hCopyDC, hCopy ); 813cdf0e10cSrcweir 814cdf0e10cSrcweir BitBlt( hCopyDC, 0, 0, aBmp.bmWidth, aBmp.bmHeight, hBmpDC, 0, 0, SRCCOPY ); 815cdf0e10cSrcweir 816cdf0e10cSrcweir SelectObject( hCopyDC, hCopyOld ); 817cdf0e10cSrcweir DeleteDC( hCopyDC ); 818cdf0e10cSrcweir 819cdf0e10cSrcweir SelectObject( hBmpDC, hBmpOld ); 820cdf0e10cSrcweir DeleteDC( hBmpDC ); 821cdf0e10cSrcweir } 822cdf0e10cSrcweir } 823cdf0e10cSrcweir 824cdf0e10cSrcweir return hCopy; 825cdf0e10cSrcweir } 826cdf0e10cSrcweir 827cdf0e10cSrcweir // ------------------------------------------------------------------ 828cdf0e10cSrcweir 829cdf0e10cSrcweir BitmapBuffer* WinSalBitmap::AcquireBuffer( bool /*bReadOnly*/ ) 830cdf0e10cSrcweir { 831cdf0e10cSrcweir BitmapBuffer* pBuffer = NULL; 832cdf0e10cSrcweir 833cdf0e10cSrcweir if( mhDIB ) 834cdf0e10cSrcweir { 835cdf0e10cSrcweir PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); 836cdf0e10cSrcweir PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 837cdf0e10cSrcweir 838cdf0e10cSrcweir if( ( pBIH->biCompression == BI_RLE4 ) || ( pBIH->biCompression == BI_RLE8 ) ) 839cdf0e10cSrcweir { 840cdf0e10cSrcweir Size aSizePix( pBIH->biWidth, pBIH->biHeight ); 841cdf0e10cSrcweir HGLOBAL hNewDIB = ImplCreateDIB( aSizePix, pBIH->biBitCount, BitmapPalette() ); 842cdf0e10cSrcweir 843cdf0e10cSrcweir if( hNewDIB ) 844cdf0e10cSrcweir { 845cdf0e10cSrcweir PBITMAPINFO pNewBI = (PBITMAPINFO) GlobalLock( hNewDIB ); 846cdf0e10cSrcweir PBITMAPINFOHEADER pNewBIH = (PBITMAPINFOHEADER) pNewBI; 847cdf0e10cSrcweir const sal_uInt16 nColorCount = ImplGetDIBColorCount( hNewDIB ); 848cdf0e10cSrcweir const sal_uLong nOffset = *(DWORD*) pBI + nColorCount * sizeof( RGBQUAD ); 849cdf0e10cSrcweir BYTE* pOldBits = (PBYTE) pBI + nOffset; 850cdf0e10cSrcweir BYTE* pNewBits = (PBYTE) pNewBI + nOffset; 851cdf0e10cSrcweir 852cdf0e10cSrcweir memcpy( pNewBI, pBI, nOffset ); 853cdf0e10cSrcweir pNewBIH->biCompression = 0; 854cdf0e10cSrcweir ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->biCompression == BI_RLE4 ); 855cdf0e10cSrcweir 856cdf0e10cSrcweir GlobalUnlock( mhDIB ); 857cdf0e10cSrcweir GlobalFree( mhDIB ); 858cdf0e10cSrcweir mhDIB = hNewDIB; 859cdf0e10cSrcweir pBI = pNewBI; 860cdf0e10cSrcweir pBIH = pNewBIH; 861cdf0e10cSrcweir } 862cdf0e10cSrcweir } 863cdf0e10cSrcweir 864cdf0e10cSrcweir if( pBIH->biPlanes == 1 ) 865cdf0e10cSrcweir { 866cdf0e10cSrcweir pBuffer = new BitmapBuffer; 867cdf0e10cSrcweir 868cdf0e10cSrcweir pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP | 869cdf0e10cSrcweir ( pBIH->biBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL : 870cdf0e10cSrcweir pBIH->biBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL : 871cdf0e10cSrcweir pBIH->biBitCount == 8 ? BMP_FORMAT_8BIT_PAL : 872cdf0e10cSrcweir pBIH->biBitCount == 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK : 873cdf0e10cSrcweir pBIH->biBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR : 874cdf0e10cSrcweir pBIH->biBitCount == 32 ? BMP_FORMAT_32BIT_TC_MASK : 0UL ); 875cdf0e10cSrcweir 876cdf0e10cSrcweir if( BMP_SCANLINE_FORMAT( pBuffer->mnFormat ) ) 877cdf0e10cSrcweir { 878cdf0e10cSrcweir pBuffer->mnWidth = maSize.Width(); 879cdf0e10cSrcweir pBuffer->mnHeight = maSize.Height(); 880cdf0e10cSrcweir pBuffer->mnScanlineSize = AlignedWidth4Bytes( maSize.Width() * pBIH->biBitCount ); 881cdf0e10cSrcweir pBuffer->mnBitCount = (sal_uInt16) pBIH->biBitCount; 882cdf0e10cSrcweir 883cdf0e10cSrcweir if( pBuffer->mnBitCount <= 8 ) 884cdf0e10cSrcweir { 885cdf0e10cSrcweir const sal_uInt16 nPalCount = ImplGetDIBColorCount( mhDIB ); 886cdf0e10cSrcweir 887cdf0e10cSrcweir pBuffer->maPalette.SetEntryCount( nPalCount ); 888cdf0e10cSrcweir memcpy( pBuffer->maPalette.ImplGetColorBuffer(), pBI->bmiColors, nPalCount * sizeof( RGBQUAD ) ); 889cdf0e10cSrcweir pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nPalCount * sizeof( RGBQUAD ); 890cdf0e10cSrcweir } 891cdf0e10cSrcweir else if( ( pBIH->biBitCount == 16 ) || ( pBIH->biBitCount == 32 ) ) 892cdf0e10cSrcweir { 893cdf0e10cSrcweir sal_uLong nOffset = 0UL; 894cdf0e10cSrcweir 895cdf0e10cSrcweir if( pBIH->biCompression == BI_BITFIELDS ) 896cdf0e10cSrcweir { 897cdf0e10cSrcweir nOffset = 3 * sizeof( RGBQUAD ); 898cdf0e10cSrcweir pBuffer->maColorMask = ColorMask( *(UINT32*) &pBI->bmiColors[ 0 ], 899cdf0e10cSrcweir *(UINT32*) &pBI->bmiColors[ 1 ], 900cdf0e10cSrcweir *(UINT32*) &pBI->bmiColors[ 2 ] ); 901cdf0e10cSrcweir } 902cdf0e10cSrcweir else if( pBIH->biBitCount == 16 ) 903cdf0e10cSrcweir pBuffer->maColorMask = ColorMask( 0x00007c00UL, 0x000003e0UL, 0x0000001fUL ); 904cdf0e10cSrcweir else 905cdf0e10cSrcweir pBuffer->maColorMask = ColorMask( 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL ); 906cdf0e10cSrcweir 907cdf0e10cSrcweir pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nOffset; 908cdf0e10cSrcweir } 909cdf0e10cSrcweir else 910cdf0e10cSrcweir pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI; 911cdf0e10cSrcweir } 912cdf0e10cSrcweir else 913cdf0e10cSrcweir { 914cdf0e10cSrcweir GlobalUnlock( mhDIB ); 915cdf0e10cSrcweir delete pBuffer; 916cdf0e10cSrcweir pBuffer = NULL; 917cdf0e10cSrcweir } 918cdf0e10cSrcweir } 919cdf0e10cSrcweir else 920cdf0e10cSrcweir GlobalUnlock( mhDIB ); 921cdf0e10cSrcweir } 922cdf0e10cSrcweir 923cdf0e10cSrcweir return pBuffer; 924cdf0e10cSrcweir } 925cdf0e10cSrcweir 926cdf0e10cSrcweir // ------------------------------------------------------------------ 927cdf0e10cSrcweir 928cdf0e10cSrcweir void WinSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly ) 929cdf0e10cSrcweir { 930cdf0e10cSrcweir if( pBuffer ) 931cdf0e10cSrcweir { 932cdf0e10cSrcweir if( mhDIB ) 933cdf0e10cSrcweir { 934cdf0e10cSrcweir if( !bReadOnly && !!pBuffer->maPalette ) 935cdf0e10cSrcweir { 936cdf0e10cSrcweir PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); 937cdf0e10cSrcweir const sal_uInt16 nCount = pBuffer->maPalette.GetEntryCount(); 938cdf0e10cSrcweir const sal_uInt16 nDIBColorCount = ImplGetDIBColorCount( mhDIB ); 939cdf0e10cSrcweir memcpy( pBI->bmiColors, pBuffer->maPalette.ImplGetColorBuffer(), Min( nDIBColorCount, nCount ) * sizeof( RGBQUAD ) ); 940cdf0e10cSrcweir GlobalUnlock( mhDIB ); 941cdf0e10cSrcweir } 942cdf0e10cSrcweir 943cdf0e10cSrcweir GlobalUnlock( mhDIB ); 944cdf0e10cSrcweir } 945cdf0e10cSrcweir 946cdf0e10cSrcweir delete pBuffer; 947cdf0e10cSrcweir } 948cdf0e10cSrcweir } 949cdf0e10cSrcweir 950cdf0e10cSrcweir // ------------------------------------------------------------------ 951cdf0e10cSrcweir 952cdf0e10cSrcweir void WinSalBitmap::ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf, 953cdf0e10cSrcweir const Size& rSizePixel, bool bRLE4 ) 954cdf0e10cSrcweir { 955cdf0e10cSrcweir HPBYTE pRLE = (HPBYTE) pSrcBuf; 956cdf0e10cSrcweir HPBYTE pDIB = (HPBYTE) pDstBuf; 957cdf0e10cSrcweir HPBYTE pRow = (HPBYTE) pDstBuf; 958cdf0e10cSrcweir sal_uLong nWidthAl = AlignedWidth4Bytes( rSizePixel.Width() * ( bRLE4 ? 4UL : 8UL ) ); 959cdf0e10cSrcweir HPBYTE pLast = pDIB + rSizePixel.Height() * nWidthAl - 1; 960cdf0e10cSrcweir sal_uLong nCountByte; 961cdf0e10cSrcweir sal_uLong nRunByte; 962cdf0e10cSrcweir sal_uLong nX = 0; 963cdf0e10cSrcweir sal_uLong i; 964cdf0e10cSrcweir BYTE cTmp; 965cdf0e10cSrcweir bool bEndDecoding = FALSE; 966cdf0e10cSrcweir 967cdf0e10cSrcweir if( pRLE && pDIB ) 968cdf0e10cSrcweir { 969cdf0e10cSrcweir do 970cdf0e10cSrcweir { 971cdf0e10cSrcweir if( ( nCountByte = *pRLE++ ) == 0 ) 972cdf0e10cSrcweir { 973cdf0e10cSrcweir nRunByte = *pRLE++; 974cdf0e10cSrcweir 975cdf0e10cSrcweir if( nRunByte > 2UL ) 976cdf0e10cSrcweir { 977cdf0e10cSrcweir if( bRLE4 ) 978cdf0e10cSrcweir { 979cdf0e10cSrcweir nCountByte = nRunByte >> 1UL; 980cdf0e10cSrcweir 981cdf0e10cSrcweir for( i = 0; i < nCountByte; i++ ) 982cdf0e10cSrcweir { 983cdf0e10cSrcweir cTmp = *pRLE++; 984cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); 985cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, cTmp & 0x0f ); 986cdf0e10cSrcweir } 987cdf0e10cSrcweir 988cdf0e10cSrcweir if( nRunByte & 1 ) 989cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 ); 990cdf0e10cSrcweir 991cdf0e10cSrcweir if( ( ( nRunByte + 1 ) >> 1 ) & 1 ) 992cdf0e10cSrcweir pRLE++; 993cdf0e10cSrcweir } 994cdf0e10cSrcweir else 995cdf0e10cSrcweir { 996cdf0e10cSrcweir memcpy( &pDIB[ nX ], pRLE, nRunByte ); 997cdf0e10cSrcweir pRLE += nRunByte; 998cdf0e10cSrcweir nX += nRunByte; 999cdf0e10cSrcweir 1000cdf0e10cSrcweir if( nRunByte & 1 ) 1001cdf0e10cSrcweir pRLE++; 1002cdf0e10cSrcweir } 1003cdf0e10cSrcweir } 1004cdf0e10cSrcweir else if( !nRunByte ) 1005cdf0e10cSrcweir { 1006cdf0e10cSrcweir pDIB = ( pRow += nWidthAl ); 1007cdf0e10cSrcweir nX = 0UL; 1008cdf0e10cSrcweir } 1009cdf0e10cSrcweir else if( nRunByte == 1 ) 1010cdf0e10cSrcweir bEndDecoding = TRUE; 1011cdf0e10cSrcweir else 1012cdf0e10cSrcweir { 1013cdf0e10cSrcweir nX += *pRLE++; 1014cdf0e10cSrcweir pDIB = ( pRow += ( *pRLE++ ) * nWidthAl ); 1015cdf0e10cSrcweir } 1016cdf0e10cSrcweir } 1017cdf0e10cSrcweir else 1018cdf0e10cSrcweir { 1019cdf0e10cSrcweir cTmp = *pRLE++; 1020cdf0e10cSrcweir 1021cdf0e10cSrcweir if( bRLE4 ) 1022cdf0e10cSrcweir { 1023cdf0e10cSrcweir nRunByte = nCountByte >> 1; 1024cdf0e10cSrcweir 1025cdf0e10cSrcweir for( i = 0; i < nRunByte; i++ ) 1026cdf0e10cSrcweir { 1027cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); 1028cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, cTmp & 0x0f ); 1029cdf0e10cSrcweir } 1030cdf0e10cSrcweir 1031cdf0e10cSrcweir if( nCountByte & 1 ) 1032cdf0e10cSrcweir ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); 1033cdf0e10cSrcweir } 1034cdf0e10cSrcweir else 1035cdf0e10cSrcweir { 1036cdf0e10cSrcweir for( i = 0; i < nCountByte; i++ ) 1037cdf0e10cSrcweir pDIB[ nX++ ] = cTmp; 1038cdf0e10cSrcweir } 1039cdf0e10cSrcweir } 1040cdf0e10cSrcweir } 1041cdf0e10cSrcweir while( !bEndDecoding && ( pDIB <= pLast ) ); 1042cdf0e10cSrcweir } 1043cdf0e10cSrcweir } 1044cdf0e10cSrcweir 1045cdf0e10cSrcweir bool WinSalBitmap::GetSystemData( BitmapSystemData& rData ) 1046cdf0e10cSrcweir { 1047cdf0e10cSrcweir bool bRet = false; 1048cdf0e10cSrcweir if( mhDIB || mhDDB ) 1049cdf0e10cSrcweir { 1050cdf0e10cSrcweir bRet = true; 1051cdf0e10cSrcweir rData.pDIB = mhDIB; 1052cdf0e10cSrcweir rData.pDDB = mhDDB; 1053cdf0e10cSrcweir const Size& rSize = GetSize (); 1054cdf0e10cSrcweir rData.mnWidth = rSize.Width(); 1055cdf0e10cSrcweir rData.mnHeight = rSize.Height(); 1056cdf0e10cSrcweir } 1057cdf0e10cSrcweir return bRet; 1058cdf0e10cSrcweir } 1059