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