xref: /trunk/main/vcl/os2/source/gdi/salbmp.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <svpm.h>
29 
30 #define _SV_SALBMP_CXX
31 #include <rtl/alloc.h>
32 #include <vcl/salbtype.hxx>
33 #include <salgdi.h>
34 #include <saldata.hxx>
35 #include <salbmp.h>
36 #include <vcl/bitmap.hxx> // for BitmapSystemData
37 #include <string.h>
38 
39 #ifndef __H_FT2LIB
40 #include <wingdi.h>
41 #include <ft2lib.h>
42 #endif
43 
44 // -----------
45 // - Inlines -
46 // -----------
47 
48 inline void ImplSetPixel4( const HPBYTE pScanline, long nX, const BYTE cIndex )
49 {
50     BYTE& rByte = pScanline[ nX >> 1 ];
51 
52     ( nX & 1 ) ? ( rByte &= 0xf0, rByte |= ( cIndex & 0x0f ) ) :
53                  ( rByte &= 0x0f, rByte |= ( cIndex << 4 ) );
54 }
55 
56 // -------------
57 // - Os2SalBitmap -
58 // -------------
59 
60 Os2SalBitmap::Os2SalBitmap() :
61         mhDIB       ( 0 ),
62         mhDIB1Subst ( 0 ),
63         mhDDB       ( 0 ),
64         mnBitCount  ( 0 )
65 {
66 }
67 
68 // ------------------------------------------------------------------
69 
70 Os2SalBitmap::~Os2SalBitmap()
71 {
72     Destroy();
73 }
74 
75 // ------------------------------------------------------------------
76 
77 bool Os2SalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle )
78 {
79     BOOL bRet = TRUE;
80 
81     if( bDIB )
82         mhDIB = (HANDLE) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap );
83     else
84         mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap );
85 
86     if( mhDIB )
87     {
88         // bitmap-header is the beginning of memory block
89         PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) mhDIB;
90 
91         maSize = Size( pBIH->cx, pBIH->cy );
92         mnBitCount = pBIH->cBitCount;
93 
94         if( mnBitCount )
95             mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24;
96     }
97     else if( mhDDB )
98     {
99         BITMAPINFOHEADER2 aDDBInfoHeader;
100 
101         aDDBInfoHeader.cbFix = sizeof( aDDBInfoHeader );
102 
103         if( GpiQueryBitmapInfoHeader( mhDDB, &aDDBInfoHeader ) )
104         {
105             maSize = Size( aDDBInfoHeader.cx, aDDBInfoHeader.cy );
106             mnBitCount = aDDBInfoHeader.cPlanes * aDDBInfoHeader.cBitCount;
107 
108             if( mnBitCount )
109             {
110                 mnBitCount = ( mnBitCount <= 1 ) ? 1 :
111                              ( mnBitCount <= 4 ) ? 4 :
112                              ( mnBitCount <= 8 ) ? 8 : 24;
113             }
114         }
115         else
116         {
117             mhDDB = 0;
118             bRet = FALSE;
119         }
120 
121     }
122     else
123         bRet = FALSE;
124 
125     return bRet;
126 }
127 
128 // ------------------------------------------------------------------
129 
130 bool Os2SalBitmap::Create( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal )
131 {
132     bool bRet = FALSE;
133 
134     mhDIB = ImplCreateDIB( rSize, nBitCount, rPal );
135 
136     if( mhDIB )
137     {
138         maSize = rSize;
139         mnBitCount = nBitCount;
140         bRet = TRUE;
141     }
142 
143     return bRet;
144 }
145 
146 // ------------------------------------------------------------------
147 
148 bool Os2SalBitmap::Create( const SalBitmap& rSSalBitmap )
149 {
150     bool bRet = FALSE;
151     const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap);
152 
153     if ( rSalBitmap.mhDIB || rSalBitmap.mhDDB )
154     {
155         HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : rSalBitmap.mhDDB,
156                                            rSalBitmap.mhDIB != 0 );
157 
158         if( hNewHdl )
159         {
160             if( rSalBitmap.mhDIB )
161                 mhDIB = (HANDLE) hNewHdl;
162             else if( rSalBitmap.mhDDB )
163                 mhDDB = (HBITMAP) hNewHdl;
164 
165             maSize = rSalBitmap.maSize;
166             mnBitCount = rSalBitmap.mnBitCount;
167             bRet = TRUE;
168         }
169     }
170 
171     return bRet;
172 }
173 
174 // ------------------------------------------------------------------
175 
176 bool Os2SalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics )
177 {
178     bool bRet = FALSE;
179     const Os2SalBitmap& rSalBmp = static_cast<const Os2SalBitmap&>(rSSalBmp);
180     Os2SalGraphics* pGraphics = static_cast<Os2SalGraphics*>(pSGraphics);
181 
182     if( rSalBmp.mhDIB )
183     {
184         HPS						hPS = pGraphics->mhPS;
185         HBITMAP					hNewDDB;
186         BITMAPINFOHEADER2		aInfoHeader;
187         const Size				aSize( rSalBmp.GetSize() );
188         long					nFormat[ 2 ];
189 
190 		memset( &aInfoHeader, 0, sizeof( aInfoHeader ) );
191         aInfoHeader.cbFix = 16;
192         aInfoHeader.cx = aSize.Width();
193         aInfoHeader.cy = aSize.Height();
194 
195         GpiQueryDeviceBitmapFormats( hPS, 2L, (PLONG) &nFormat );
196         aInfoHeader.cPlanes = nFormat[ 0 ];
197         aInfoHeader.cBitCount = nFormat[ 1 ];
198 
199     	// ! wegen Postscript-Treiber
200 		if( !aInfoHeader.cBitCount )
201             aInfoHeader.cBitCount = 24;
202         else if( ( aInfoHeader.cPlanes == 1 ) && ( aInfoHeader.cBitCount == 1 ) )
203 	        aInfoHeader.cBitCount = 4;
204 
205         // BitCount == 1 ist wegen aller moeglichen Treiberfehler nicht moeglich
206         if( rSalBmp.GetBitCount() == 1 )
207         {
208 	        HANDLE 	hTmp = ImplCreateDIB4FromDIB1( rSalBmp.mhDIB );
209             PBYTE	pBits = (PBYTE) hTmp + *(ULONG*) hTmp + ImplGetDIBColorCount( hTmp ) * sizeof( RGB2 );
210 
211 	        hNewDDB = GpiCreateBitmap( hPS, &aInfoHeader, CBM_INIT, pBits, (PBITMAPINFO2) hTmp );
212 			rtl_freeMemory( (void*)hTmp );
213         }
214         else
215         {
216 	        PBYTE pBits = (PBYTE) rSalBmp.mhDIB + *(ULONG*) rSalBmp.mhDIB + ImplGetDIBColorCount( rSalBmp.mhDIB ) * sizeof( RGB2 );
217 	        hNewDDB = GpiCreateBitmap( hPS, &aInfoHeader, CBM_INIT, pBits, (PBITMAPINFO2) rSalBmp.mhDIB );
218 		}
219 
220 		aInfoHeader.cbFix = sizeof( aInfoHeader );
221 
222         if( hNewDDB && GpiQueryBitmapInfoHeader( hNewDDB, &aInfoHeader ) )
223         {
224             mhDDB = hNewDDB;
225             maSize = Size( aInfoHeader.cx, aInfoHeader.cy );
226             mnBitCount = aInfoHeader.cPlanes * aInfoHeader.cBitCount;
227 
228             if( mnBitCount )
229             {
230                 mnBitCount = ( mnBitCount <= 1 ) ? 1 :
231                              ( mnBitCount <= 4 ) ? 4 :
232                              ( mnBitCount <= 8 ) ? 8 : 24;
233             }
234 
235             bRet = TRUE;
236         }
237         else if( hNewDDB )
238             GpiDeleteBitmap( hNewDDB );
239     }
240 
241     return bRet;
242 }
243 
244 // ------------------------------------------------------------------
245 
246 bool Os2SalBitmap::Create( const SalBitmap& rSSalBmp, USHORT nNewBitCount )
247 {
248     bool bRet = FALSE;
249     const Os2SalBitmap& rSalBmp = static_cast<const Os2SalBitmap&>(rSSalBmp);
250 
251     if( rSalBmp.mhDDB )
252     {
253         mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() );
254 
255         if( mhDIB )
256         {
257             // bitmap-header is the beginning of memory block
258             PBITMAPINFO2    pBI = (PBITMAPINFO2) mhDIB;
259             const int       nLines = (int) rSalBmp.maSize.Height();
260             PBYTE           pBits = (PBYTE) pBI + *(ULONG*) pBI + ImplGetDIBColorCount( mhDIB ) * sizeof( RGB2 );
261             SIZEL           aSizeL = { rSalBmp.maSize.Width(), nLines };
262             HAB             hAB = GetSalData()->mhAB;
263             DEVOPENSTRUC    aDevOpenStruc = { NULL, (PSZ)"DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
264             HDC             hMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 );
265             HPS             hMemPS = Ft2CreatePS( hAB, hMemDC, &aSizeL, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
266             HBITMAP         hMemOld = (HBITMAP) Ft2SetBitmap( hMemPS, rSalBmp.mhDDB );
267 
268             if( GpiQueryBitmapBits( hMemPS, 0, nLines, pBits, pBI ) == nLines )
269             {
270                 maSize = rSalBmp.maSize;
271                 mnBitCount = nNewBitCount;
272                 bRet = TRUE;
273             }
274             else
275             {
276                 rtl_freeMemory( (void*)mhDIB );
277                 mhDIB = 0;
278             }
279 
280             Ft2SetBitmap( hMemPS, hMemOld );
281             Ft2DestroyPS( hMemPS );
282             DevCloseDC( hMemDC );
283         }
284     }
285 
286     return bRet;
287 }
288 
289 // ------------------------------------------------------------------
290 
291 void Os2SalBitmap::Destroy()
292 {
293     if( mhDIB )
294         rtl_freeMemory( (void*)mhDIB );
295     else if( mhDDB )
296         GpiDeleteBitmap( mhDDB );
297 
298     if( mhDIB1Subst )
299     {
300         rtl_freeMemory( (void*)mhDIB1Subst );
301         mhDIB1Subst = NULL;
302 	}
303 
304     maSize = Size();
305     mnBitCount = 0;
306 }
307 
308 // ------------------------------------------------------------------
309 
310 void Os2SalBitmap::ImplReplacehDIB1Subst( HANDLE hDIB1Subst )
311 {
312     if( mhDIB1Subst )
313         rtl_freeMemory( (void*)mhDIB1Subst );
314 
315     mhDIB1Subst = hDIB1Subst;
316 }
317 
318 // ------------------------------------------------------------------
319 
320 USHORT Os2SalBitmap::ImplGetDIBColorCount( HANDLE hDIB )
321 {
322     USHORT nColors = 0;
323 
324     if( hDIB )
325     {
326         // bitmap infos can be found at the beginning of the memory
327         PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) hDIB;
328 
329         if( pBIH->cBitCount <= 8 )
330         {
331             if( pBIH->cclrUsed )
332                 nColors = (USHORT) pBIH->cclrUsed;
333             else
334                 nColors = 1 << pBIH->cBitCount;
335         }
336     }
337 
338     return nColors;
339 }
340 
341 // ------------------------------------------------------------------
342 
343 HANDLE Os2SalBitmap::ImplCreateDIB( const Size& rSize, USHORT nBits, const BitmapPalette& rPal )
344 {
345     DBG_ASSERT( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 24, "Unsupported BitCount!" );
346 
347     HANDLE hDIB = 0;
348 
349     if ( rSize.Width() && rSize.Height() && ( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 24 ) )
350     {
351         const ULONG		nImageSize = AlignedWidth4Bytes( nBits * rSize.Width() ) * rSize.Height();
352         const USHORT	nColors = ( nBits <= 8 ) ? ( 1 << nBits ) : 0;
353 
354         hDIB = (HANDLE) rtl_allocateZeroMemory( sizeof( BITMAPINFOHEADER2 ) + nColors * sizeof( RGB2 ) + nImageSize );
355 
356         if( hDIB )
357         {
358             // bitmap infos can be found at the beginning of the memory
359             PBITMAPINFO2		pBI = (PBITMAPINFO2) hDIB;
360             PBITMAPINFOHEADER2	pBIH = (PBITMAPINFOHEADER2) pBI;
361 
362             pBIH->cbFix = sizeof( BITMAPINFOHEADER2 );
363             pBIH->cx = rSize.Width();
364             pBIH->cy = rSize.Height();
365             pBIH->cPlanes = 1;
366             pBIH->cBitCount = nBits;
367             pBIH->ulCompression = BCA_UNCOMP; // BI_RGB;
368             pBIH->cbImage = nImageSize;
369             pBIH->cxResolution = 0;
370             pBIH->cyResolution = 0;
371             pBIH->cclrUsed = 0;
372             pBIH->cclrImportant = 0;
373 
374             // Rest auf 0 setzen
375             memset( (PBYTE) &pBIH->usUnits, 0, (PBYTE) pBI->argbColor - (PBYTE) &pBIH->usUnits );
376 
377             if( nColors )
378             {
379                 const USHORT nMinCount = Min( nColors, rPal.GetEntryCount() );
380 
381                 if( nMinCount )
382                 	memcpy( pBI->argbColor, rPal.ImplGetColorBuffer(), nMinCount * sizeof( RGB2 ) );
383             }
384         }
385     }
386 
387     return hDIB;
388 }
389 
390 // ------------------------------------------------------------------
391 
392 HANDLE Os2SalBitmap::ImplCreateDIB4FromDIB1( HANDLE hDIB1 )
393 {
394     PBITMAPINFO2        pBI = (PBITMAPINFO2) hDIB1;
395     PBITMAPINFOHEADER2  pBIH = (PBITMAPINFOHEADER2) pBI;
396     PBYTE               pBits = (PBYTE) pBI + *(ULONG*) pBIH + Os2SalBitmap::ImplGetDIBColorCount( hDIB1 ) * sizeof( RGB2 );
397     ULONG               nWidth = pBIH->cx, nHeight = pBIH->cy;
398     ULONG               nAligned = AlignedWidth4Bytes( nWidth );
399     ULONG               nAligned4 = AlignedWidth4Bytes( nWidth << 2 );
400     ULONG               nSize4 = sizeof( BITMAPINFOHEADER2 ) + ( sizeof( RGB2 ) << 4 ) + nAligned4 * nHeight;
401     PBYTE               pDIB4 = (PBYTE) rtl_allocateZeroMemory( nSize4 );
402     PBITMAPINFO2        pBI4 = (PBITMAPINFO2) pDIB4;
403     PBITMAPINFOHEADER2  pBIH4 = (PBITMAPINFOHEADER2) pBI4;
404     BYTE                aMap[ 4 ] = { 0x00, 0x01, 0x10, 0x11 };
405 
406     memset( pBIH4, 0, sizeof( BITMAPINFOHEADER2 ) );
407     pBIH4->cbFix = sizeof( BITMAPINFOHEADER2 );
408     pBIH4->cx = nWidth;
409     pBIH4->cy = nHeight;
410     pBIH4->cPlanes = 1;
411     pBIH4->cBitCount = 4;
412 
413     // die ersten beiden Eintraege der 1Bit-Farbtabelle kopieren
414     memcpy( pBI4->argbColor, pBI->argbColor, sizeof( RGB2 ) << 1 );
415 
416     PBYTE pBits4 = (PBYTE) pBI4 + *(ULONG*) pBIH4 + ( sizeof( RGB2 ) << 4 );
417 
418     // 4Bit-DIB-Bilddaten setzen
419     for( ULONG nY = 0UL; nY < nHeight; nY++ )
420     {
421         PBYTE pTmp = pBits; pBits += nAligned;
422         PBYTE pTmp4 = pBits4; pBits4 += nAligned4;
423 
424         for( ULONG nX = 0UL; nX < nWidth; nX += 8UL )
425         {
426             *pTmp4++ = aMap[ ( *pTmp >> 6 ) & 3 ];
427             *pTmp4++ = aMap[ ( *pTmp >> 4 ) & 3 ];
428             *pTmp4++ = aMap[ ( *pTmp >> 2 ) & 3 ];
429             *pTmp4++ = aMap[ *pTmp++ & 3 ];
430         }
431     }
432 
433     return (HANDLE) pDIB4;
434 }
435 
436 // ------------------------------------------------------------------
437 
438 HANDLE Os2SalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, BOOL bDIB )
439 {
440     HANDLE hCopy = 0;
441 
442     if( bDIB && hHdl )
443     {
444         PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) hHdl;
445            const ULONG nSize = sizeof( BITMAPINFOHEADER2 )
446                             + ImplGetDIBColorCount( hHdl ) * sizeof( RGB2 ) +
447                             ( pBIH->cbImage ? pBIH->cbImage : AlignedWidth4Bytes( pBIH->cx * pBIH->cBitCount ) );
448 
449         BYTE* pCopy = (BYTE*)rtl_allocateZeroMemory( nSize );
450         memcpy( pCopy, (BYTE*) hHdl, nSize );
451         hCopy = (HANDLE) pCopy;
452     }
453     else if( hHdl )
454     {
455         HAB                 hAB = GetSalData()->mhAB;
456         HDC                 hSrcMemDC;
457         HDC                 hDestMemDC;
458         HPS                 hSrcMemPS;
459         HPS                 hDestMemPS;
460         HBITMAP             hCopyBitmap;
461         BITMAPINFOHEADER2   aInfoHeader;
462         DEVOPENSTRUC        aDevOpenStruc;
463         SIZEL               size;
464 
465         aInfoHeader.cbFix = sizeof( BITMAPINFOHEADER2 );
466         GpiQueryBitmapInfoHeader( hHdl, &aInfoHeader );
467         size.cx = aInfoHeader.cx;
468         size.cy = aInfoHeader.cy;
469 
470         // Memory DCs erzeugen
471         aDevOpenStruc.pszLogAddress = 0;
472         aDevOpenStruc.pszDriverName = (PSZ)"DISPLAY";
473 
474         hSrcMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 2, (PDEVOPENDATA)&aDevOpenStruc, 0 );
475         hDestMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 2, (PDEVOPENDATA)&aDevOpenStruc, 0 );
476 
477         // Memory PSs erzeugen
478         hSrcMemPS = Ft2CreatePS( hAB, hSrcMemDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
479         hDestMemPS = Ft2CreatePS( hAB, hDestMemDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
480 
481         Ft2SetBitmap( hSrcMemPS, hHdl );
482 
483         if( !hHdl )
484         {
485             memset( &aInfoHeader, 0, sizeof( BITMAPINFOHEADER2 ) );
486             aInfoHeader.cbFix     = sizeof( BITMAPINFOHEADER2 );
487             aInfoHeader.cx        = 0;
488             aInfoHeader.cy        = 0;
489             aInfoHeader.cPlanes   = 1;
490             aInfoHeader.cBitCount = 1;
491         }
492 
493         hCopy = GpiCreateBitmap( hDestMemPS, &aInfoHeader, 0, NULL, NULL );
494         Ft2SetBitmap( hDestMemPS, hCopy );
495 
496         POINTL pts[3];
497 
498         pts[0].x = 0;
499         pts[0].y = 0;
500         pts[1].x = size.cx;
501         pts[1].y = size.cy;
502         pts[2].x = 0;
503         pts[2].y = 0;
504 
505         GpiBitBlt( hDestMemPS, hSrcMemPS, 3, pts, ROP_SRCCOPY, BBO_IGNORE );
506 
507         Ft2SetBitmap( hSrcMemPS, (HBITMAP)0L);
508         Ft2SetBitmap( hDestMemPS, (HBITMAP)0L);
509         Ft2Associate( hSrcMemPS, NULLHANDLE );
510         Ft2Associate( hDestMemPS, NULLHANDLE );
511         Ft2DestroyPS( hSrcMemPS );
512         Ft2DestroyPS( hDestMemPS );
513         DevCloseDC( hSrcMemDC );
514         DevCloseDC( hDestMemDC );
515     }
516 
517     return hCopy;
518 }
519 
520 // ------------------------------------------------------------------
521 
522 BitmapBuffer* Os2SalBitmap::AcquireBuffer( bool bReadOnly )
523 {
524     BitmapBuffer* pBuffer = NULL;
525 
526     if( mhDIB )
527     {
528         // bitmap infos can be found at the beginning of the memory
529         PBITMAPINFO2        pBI = (PBITMAPINFO2) mhDIB;
530         PBITMAPINFOHEADER2    pBIH = (PBITMAPINFOHEADER2) pBI;
531 
532         if( ( pBIH->ulCompression == BCA_RLE4 ) || ( pBIH->ulCompression == BCA_RLE8 ) )
533         {
534             Size    aSizePix( pBIH->cx, pBIH->cy );
535             HANDLE    hNewDIB = ImplCreateDIB( aSizePix, pBIH->cBitCount, BitmapPalette() );
536 
537             if( hNewDIB )
538             {
539                 // bitmap infos can be found at the beginning of the memory
540                 PBITMAPINFO2        pNewBI = (PBITMAPINFO2) hNewDIB;
541                 PBITMAPINFOHEADER2    pNewBIH = (PBITMAPINFOHEADER2) pNewBI;
542                 const USHORT        nColorCount = ImplGetDIBColorCount( hNewDIB );
543                 const ULONG            nOffset = *(ULONG*) pBI + nColorCount * sizeof( RGB2 );
544                 BYTE*                pOldBits = (BYTE*) pBI + nOffset;
545                 BYTE*                pNewBits = (BYTE*) pNewBI + nOffset;
546 
547                 memcpy( pNewBI, pBI, nOffset );
548                 pNewBIH->ulCompression = 0;
549                 ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->ulCompression == BCA_RLE4 );
550 
551                 rtl_freeMemory( (void*)mhDIB );
552 
553                 mhDIB = hNewDIB;
554                 pBI = pNewBI;
555                 pBIH = pNewBIH;
556             }
557         }
558 
559         if( pBIH->cPlanes == 1 )
560         {
561             pBuffer = new BitmapBuffer;
562 
563             pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP |
564                                 ( pBIH->cBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL :
565                                   pBIH->cBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL :
566                                   pBIH->cBitCount == 8 ? BMP_FORMAT_8BIT_PAL :
567                                   pBIH->cBitCount == 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK :
568                                   pBIH->cBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR :
569                                   pBIH->cBitCount == 32 ? BMP_FORMAT_32BIT_TC_MASK : 0UL );
570 
571             if( BMP_SCANLINE_FORMAT( pBuffer->mnFormat ) )
572             {
573                 pBuffer->mnWidth = maSize.Width();
574                 pBuffer->mnHeight = maSize.Height();
575                 pBuffer->mnScanlineSize = AlignedWidth4Bytes( maSize.Width() * pBIH->cBitCount );
576                 pBuffer->mnBitCount = (USHORT) pBIH->cBitCount;
577 
578                 if( pBuffer->mnBitCount <= 8 )
579                 {
580                     const USHORT nPalCount = ImplGetDIBColorCount( mhDIB );
581 
582                     pBuffer->maPalette.SetEntryCount( nPalCount );
583 
584                     if( nPalCount )
585                     	memcpy( pBuffer->maPalette.ImplGetColorBuffer(), pBI->argbColor, nPalCount * sizeof( RGB2 ) );
586 
587                     pBuffer->mpBits = (BYTE*) pBI + *(ULONG*) pBI + nPalCount * sizeof( RGB2 );
588                 }
589                 else
590                     pBuffer->mpBits = (BYTE*) pBI + *(ULONG*) pBI;
591             }
592             else
593             {
594                 delete pBuffer;
595                 pBuffer = NULL;
596             }
597         }
598     }
599 
600     if( pBuffer && mhDIB1Subst )
601     {
602         rtl_freeMemory( (void*)mhDIB1Subst );
603         mhDIB1Subst = 0;
604      }
605 
606     return pBuffer;
607 }
608 
609 // ------------------------------------------------------------------
610 
611 void Os2SalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly )
612 {
613     if( pBuffer )
614     {
615         if( mhDIB )
616         {
617             if( !bReadOnly && !!pBuffer->maPalette )
618             {
619                 // bitmap infos can be found at the beginning of the memory
620                 PBITMAPINFO2    pBI = (PBITMAPINFO2) mhDIB;
621                 const USHORT    nCount = pBuffer->maPalette.GetEntryCount();
622 
623                 if( nCount )
624                 	memcpy( pBI->argbColor, pBuffer->maPalette.ImplGetColorBuffer(), nCount * sizeof( RGB2 ) );
625             }
626         }
627 
628         delete pBuffer;
629     }
630 }
631 
632 // ------------------------------------------------------------------
633 
634 void Os2SalBitmap::ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf,
635                                      const Size& rSizePixel, BOOL bRLE4 )
636 {
637     HPBYTE    pRLE = (HPBYTE) pSrcBuf;
638     HPBYTE    pDIB = (HPBYTE) pDstBuf;
639     HPBYTE    pRow = (HPBYTE) pDstBuf;
640     ULONG    nWidthAl = AlignedWidth4Bytes( rSizePixel.Width() * ( bRLE4 ? 4UL : 8UL ) );
641     HPBYTE    pLast = pDIB + rSizePixel.Height() * nWidthAl - 1;
642     ULONG    nCountByte;
643     ULONG    nRunByte;
644     ULONG    nX = 0;
645     ULONG    i;
646     BYTE    cTmp;
647     BOOL    bEndDecoding = FALSE;
648 
649     if( pRLE && pDIB )
650     {
651         do
652         {
653             if( !( nCountByte = *pRLE++ ) )
654             {
655                 nRunByte = *pRLE++;
656 
657                 if( nRunByte > 2UL )
658                 {
659                     if( bRLE4 )
660                     {
661                         nCountByte = nRunByte >> 1UL;
662 
663                         for( i = 0; i < nCountByte; i++ )
664                         {
665                             cTmp = *pRLE++;
666                             ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
667                             ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
668                         }
669 
670                         if( nRunByte & 1 )
671                             ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 );
672 
673                         if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
674                             pRLE++;
675                     }
676                     else
677                     {
678                         memcpy( &pDIB[ nX ], pRLE, nRunByte );
679                         pRLE += nRunByte;
680                         nX += nRunByte;
681 
682                         if( nRunByte & 1 )
683                             pRLE++;
684                     }
685                 }
686                 else if( !nRunByte )
687                 {
688                     pDIB = ( pRow += nWidthAl );
689                     nX = 0UL;
690                 }
691                 else if( nRunByte == 1 )
692                     bEndDecoding = TRUE;
693                 else
694                 {
695                     nX += *pRLE++;
696                     pDIB = ( pRow += ( *pRLE++ ) * nWidthAl );
697                 }
698             }
699             else
700             {
701                 cTmp = *pRLE++;
702 
703                 if( bRLE4 )
704                 {
705                     nRunByte = nCountByte >> 1;
706 
707                     for( i = 0; i < nRunByte; i++ )
708                     {
709                         ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
710                         ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
711                     }
712 
713                     if( nCountByte & 1 )
714                         ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
715                 }
716                 else
717                 {
718                     for( i = 0; i < nCountByte; i++ )
719                         pDIB[ nX++ ] = cTmp;
720                 }
721             }
722         }
723         while( !bEndDecoding && ( pDIB <= pLast ) );
724     }
725 }
726 
727 bool Os2SalBitmap::GetSystemData( BitmapSystemData& rData )
728 {
729     bool bRet = false;
730     if( mhDIB || mhDDB )
731     {
732         bRet = true;
733         rData.pDIB = (void*)mhDIB;
734         rData.pDDB = (void*)mhDDB;
735     }
736     return bRet;
737 }
738