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