source: trunk/src/gdi32/dibsect.cpp@ 2706

Last change on this file since 2706 was 2706, checked in by sandervl, 26 years ago

fix 1 & 4 bits alignment

File size: 12.4 KB
Line 
1/* $Id: dibsect.cpp,v 1.16 2000-02-09 23:34:30 sandervl Exp $ */
2
3/*
4 * GDI32 DIB sections
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Patrick Haller
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#define INCL_GPI
13#define INCL_WIN
14#include <os2wrap.h> //Odin32 OS/2 api wrappers
15#include <stdlib.h>
16#include <string.h>
17#include <win32type.h>
18#include <misc.h>
19#define OS2_ONLY
20#include "dibsect.h"
21#include <vmutex.h>
22#include <winconst.h>
23
24HWND WIN32API WindowFromDC(HDC hdc);
25HWND Win32ToOS2Handle(HWND hwnd);
26
27BOOL APIENTRY _GpiEnableYInversion (HPS hps, LONG lHeight);
28
29inline BOOL APIENTRY GpiEnableYInversion (HPS hps, LONG lHeight)
30{
31 BOOL yyrc;
32 USHORT sel = RestoreOS2FS();
33
34 yyrc = _GpiEnableYInversion(hps, lHeight);
35 SetFS(sel);
36
37 return yyrc;
38}
39
40static VMutex dibMutex;
41
42//NOTE:
43//This is not a complete solution for CreateDIBSection, but enough for Quake 2!
44//******************************************************************************
45//******************************************************************************
46DIBSection::DIBSection(BITMAPINFOHEADER_W *pbmi, char *pColors, DWORD iUsage, DWORD handle, int fFlip)
47 : bmpBits(NULL), pOS2bmp(NULL), next(NULL)
48{
49 int os2bmpsize;
50
51 bmpsize = pbmi->biWidth;
52 /* @@@PH 98/06/07 -- high-color bitmaps don't have palette */
53
54 this->fFlip = fFlip;
55 os2bmpsize = sizeof(BITMAPINFO2);
56
57 switch(pbmi->biBitCount)
58 {
59 case 1:
60 bmpsize = ((bmpsize + 31) & ~31) / 8;
61 os2bmpsize += ((1 << pbmi->biBitCount)-1)*sizeof(RGB2);
62 break;
63 case 4:
64 bmpsize = ((bmpsize + 7) & ~7) / 2;
65 os2bmpsize += ((1 << pbmi->biBitCount)-1)*sizeof(RGB2);
66 break;
67 case 8:
68 os2bmpsize += ((1 << pbmi->biBitCount)-1)*sizeof(RGB2);
69 break;
70 case 16:
71 bmpsize *= 2;
72 break;
73 case 24:
74 bmpsize *= 3;
75 break;
76 case 32:
77 bmpsize *= 4;
78 break;
79 }
80 if(bmpsize & 3) {
81 bmpsize = (bmpsize + 3) & ~3;
82 }
83
84 bmpBits = (char *)malloc(bmpsize*pbmi->biHeight);
85 memset(bmpBits, 0, bmpsize*pbmi->biHeight);
86
87 pOS2bmp = (BITMAPINFO2 *)malloc(os2bmpsize);
88
89 memset(pOS2bmp, /* set header + palette entries to zero */
90 0,
91 os2bmpsize);
92
93 pOS2bmp->cbFix = sizeof(BITMAPINFO2) - sizeof(RGB2);
94 pOS2bmp->cx = pbmi->biWidth;
95 pOS2bmp->cy = pbmi->biHeight;
96 pOS2bmp->cPlanes = pbmi->biPlanes;
97 pOS2bmp->cBitCount = pbmi->biBitCount;
98 pOS2bmp->ulCompression = pbmi->biCompression;
99 //SvL: Ignore BI_BITFIELDS type (GpiDrawBits fails otherwise)
100 if(pOS2bmp->ulCompression == BI_BITFIELDS) {
101 pOS2bmp->ulCompression = 0;
102 }
103 pOS2bmp->cbImage = pbmi->biSizeImage;
104 dprintf(("handle %x", handle));
105 dprintf(("pOS2bmp->cx %d\n", pOS2bmp->cx));
106 dprintf(("pOS2bmp->cy %d\n", pOS2bmp->cy));
107 dprintf(("pOS2bmp->cPlanes %d\n", pOS2bmp->cPlanes));
108 dprintf(("pOS2bmp->cBitCount %d\n", pOS2bmp->cBitCount));
109 dprintf(("pOS2bmp->ulCompression %d\n", pOS2bmp->ulCompression));
110 dprintf(("pOS2bmp->cbImage %d\n", pOS2bmp->cbImage));
111 dprintf(("Bits at %x, size %d",bmpBits, bmpsize*pbmi->biHeight));
112
113 // clear DIBSECTION structure
114 memset(&dibinfo, 0, sizeof(dibinfo));
115
116 // copy BITMAPINFOHEADER data into DIBSECTION structure
117 memcpy(&dibinfo.dsBmih, pbmi, sizeof(*pbmi));
118 dibinfo.dsBm.bmType = 0;
119 dibinfo.dsBm.bmWidth = pbmi->biWidth;
120 dibinfo.dsBm.bmHeight = pbmi->biHeight;
121 dibinfo.dsBm.bmWidthBytes= bmpsize;
122 dibinfo.dsBm.bmPlanes = pbmi->biPlanes;
123 dibinfo.dsBm.bmBitsPixel = pbmi->biBitCount;
124 dibinfo.dsBm.bmBits = bmpBits;
125
126 dibinfo.dshSection = handle;
127 dibinfo.dsOffset = 0; // TODO: put the correct value here (if createdibsection with file handle)
128
129 if(pbmi->biCompression == BI_BITFIELDS) {
130 dibinfo.dsBitfields[0] = *((DWORD *)pColors);
131 dibinfo.dsBitfields[1] = *((DWORD *)pColors+1);
132 dibinfo.dsBitfields[2] = *((DWORD *)pColors+2);
133 dprintf(("BI_BITFIELDS %x %x %x", dibinfo.dsBitfields[0], dibinfo.dsBitfields[1], dibinfo.dsBitfields[2]));
134 }
135
136 this->handle = handle;
137 this->iUsage = iUsage;
138
139 dibMutex.enter();
140 if(section == NULL)
141 {
142 dprintf(("section was NULL\n"));
143 section = this;
144 }
145 else
146 {
147 DIBSection *dsect = section;
148 dprintf2(("Increment section starting at %08X\n",dsect));
149
150 /* @@@PH 98/07/11 fix for dsect->next == NULL */
151 while ( (dsect->next != this) &&
152 (dsect->next != NULL) )
153 {
154 dprintf2(("Increment section to %08X\n",dsect->next));
155 dsect = dsect->next;
156 }
157 dsect->next = this;
158 }
159 dibMutex.leave();
160}
161//******************************************************************************
162//******************************************************************************
163DIBSection::~DIBSection()
164{
165 dprintf(("Delete DIBSection %x", handle));
166 if(bmpBits)
167 free(bmpBits);
168 if(pOS2bmp)
169 free(pOS2bmp);
170
171 dibMutex.enter();
172 if(section == this)
173 {
174 section = this->next;
175 }
176 else
177 {
178 DIBSection *dsect = section;
179
180 while(dsect->next != this)
181 {
182 dsect = dsect->next;
183 }
184 dsect->next = this->next;
185 }
186 dibMutex.leave();
187}
188//******************************************************************************
189//******************************************************************************
190int DIBSection::SetDIBits(HDC hdc, HBITMAP hbitmap, UINT startscan, UINT
191 lines, const VOID *bits, BITMAPINFOHEADER_W *pbmi,
192 UINT coloruse)
193{
194 lines = (int)lines >= 0 ? (int)lines : (int)-lines;
195 int os2bmpsize;
196 int palsize=0;
197
198 bmpsize = pbmi->biWidth;
199 os2bmpsize = sizeof(BITMAPINFO2);
200
201 switch(pbmi->biBitCount)
202 {
203 case 1:
204 bmpsize = ((bmpsize + 31) & ~31) / 8;
205 palsize = ((1 << pbmi->biBitCount))*sizeof(RGB2);
206 os2bmpsize += palsize;
207 break;
208 case 4:
209 bmpsize = ((bmpsize + 7) & ~7) / 2;
210 palsize = ((1 << pbmi->biBitCount))*sizeof(RGB2);
211 os2bmpsize += palsize;
212 break;
213 case 8:
214 palsize = ((1 << pbmi->biBitCount))*sizeof(RGB2);
215 os2bmpsize += palsize;
216 break;
217 case 16:
218 bmpsize *= 2;
219 break;
220 case 24:
221 bmpsize *= 3;
222 break;
223 case 32:
224 bmpsize *= 4;
225 break;
226 }
227
228 if(bmpsize & 3)
229 {
230 bmpsize = (bmpsize + 3) & ~3;
231 }
232
233 bmpBits = (char *)realloc(bmpBits, bmpsize*pbmi->biHeight);
234 pOS2bmp = (BITMAPINFO2 *)realloc(pOS2bmp, os2bmpsize);
235
236 pOS2bmp->cbFix = sizeof(BITMAPINFO2) - sizeof(RGB2);
237 pOS2bmp->cx = pbmi->biWidth;
238 pOS2bmp->cy = pbmi->biHeight;
239 pOS2bmp->cPlanes = pbmi->biPlanes;
240 pOS2bmp->cBitCount = pbmi->biBitCount;
241 pOS2bmp->ulCompression = pbmi->biCompression;
242 pOS2bmp->cbImage = pbmi->biSizeImage;
243
244 if(palsize)
245 memcpy(pOS2bmp->argbColor, (char *)pbmi + 1 , palsize);
246
247 if(bits)
248 {
249 int size = bmpsize*lines;
250 memcpy(bmpBits+bmpsize*startscan, bits, size);
251 }
252 return(lines);
253}
254//******************************************************************************
255//******************************************************************************
256int DIBSection::SetDIBColorTable(int startIdx, int cEntries, RGBQUAD *rgb)
257{
258 int i;
259
260 if(startIdx + cEntries > (1 << pOS2bmp->cBitCount))
261 {
262 dprintf(("DIBSection::SetDIBColorTable, invalid nr of entries %d %d\n", startIdx, cEntries));
263 return(0);
264 }
265
266 memcpy(&pOS2bmp->argbColor[startIdx], rgb, cEntries*sizeof(RGB2));
267
268 for(i=startIdx;i<cEntries;i++)
269 {
270 pOS2bmp->argbColor[i].fcOptions = 0;
271 dprintf2(("Index %d : 0x%08X\n",i, *((ULONG*)(&pOS2bmp->argbColor[i])) ));
272 }
273
274 return(cEntries);
275}
276//******************************************************************************
277//******************************************************************************
278BOOL DIBSection::BitBlt(HDC hdcDest, int nXdest, int nYdest, int nDestWidth,
279 int nDestHeight, int nXsrc, int nYsrc,
280 int nSrcWidth, int nSrcHeight, DWORD Rop)
281{
282 HPS hps = (HPS)hdcDest;
283 POINTL point[4];
284 LONG rc;
285
286 HWND hwndDest = WindowFromDC(hdcDest);
287 hwndDest = Win32ToOS2Handle(hwndDest);
288 if(hwndDest != 0)
289 {
290 hps = WinGetPS(hwndDest);
291 }
292 if(hps == 0)
293 {
294 dprintf(("ERROR: DIBSection::BitBlt, hps == 0 hwndDest = %X", hwndDest));
295 return(FALSE);
296 }
297
298 dprintf(("DIBSection::BitBlt %x %X (hps %x) %x to(%d,%d)(%d,%d) from (%d,%d)(%d,%d) rop %x flip %x",
299 handle, hdcDest, hps, hwndDest, nXdest, nYdest, nDestWidth, nDestHeight,
300 nXsrc, nYsrc, nSrcWidth, nSrcHeight, Rop, fFlip));
301
302 point[0].x = nXdest;
303 point[0].y = nYdest;
304 point[1].x = nXdest + nDestWidth - 1;
305 point[1].y = nYdest + nDestHeight - 1;
306 point[2].x = nXsrc;
307 point[2].y = nYsrc;
308 if(nXsrc + nSrcWidth > pOS2bmp->cx)
309 {
310 point[3].x = pOS2bmp->cx;
311 }
312 else
313 point[3].x = nXsrc + nSrcWidth;
314
315 if(nYsrc + nSrcHeight > pOS2bmp->cy)
316 {
317 point[3].y = pOS2bmp->cy;
318 }
319 else
320 point[3].y = nYsrc + nSrcHeight;
321
322#if 1
323 if(fFlip & FLIP_VERT)
324 {
325 GpiEnableYInversion(hps, nDestHeight);
326 }
327
328 if(fFlip & FLIP_HOR)
329 {
330 ULONG x;
331 x = point[0].x;
332 point[0].x = point[1].x;
333 point[1].x = x;
334 }
335#endif
336
337 rc = GpiDrawBits(hps, bmpBits, pOS2bmp, 4, &point[0], ROP_SRCCOPY, BBO_OR);
338
339 if(hwndDest != 0)
340 {
341 WinReleasePS(hps);
342 }
343 if(rc == GPI_OK) {
344 return(TRUE);
345 }
346 dprintf(("DIBSection::BitBlt %X (%d,%d) (%d,%d) to (%d,%d) (%d,%d) returned %d\n", hps, point[0].x, point[0].y, point[1].x, point[1].y, point[2].x, point[2].y, point[3].x, point[3].y, rc));
347 dprintf(("WinGetLastError returned %X\n", WinGetLastError(WinQueryAnchorBlock(hwndDest)) & 0xFFFF));
348 return(FALSE);
349}
350//******************************************************************************
351//******************************************************************************
352void DIBSection::SelectDIBObject(HDC hdc)
353{
354 this->hdc = hdc;
355 hwndParent = WinWindowFromDC(hdc);
356 dprintf(("SelectDIBObject %x into %x hwndParent = %x", handle, hdc, hwndParent));
357}
358//******************************************************************************
359//******************************************************************************
360DIBSection *DIBSection::find(DWORD handle)
361{
362 DIBSection *dsect = section;
363
364 dibMutex.enter();
365 while(dsect)
366 {
367 if(dsect->handle == handle)
368 {
369 dibMutex.leave();
370 return(dsect);
371 }
372 dsect = dsect->next;
373 }
374 dibMutex.leave();
375 return(NULL);
376}
377//******************************************************************************
378//A bitmap can only be selected into one DC, so this works.
379//******************************************************************************
380DIBSection *DIBSection::findHDC(HDC hdc)
381{
382 DIBSection *dsect = section;
383
384 while(dsect)
385 {
386 if(dsect->hdc == hdc)
387 {
388 return(dsect);
389 }
390 dsect = dsect->next;
391 }
392 return(NULL);
393}
394//******************************************************************************
395//******************************************************************************
396void DIBSection::deleteSection(DWORD handle)
397{
398 DIBSection *dsect = find(handle);
399
400 if(dsect)
401 delete dsect;
402
403}
404//******************************************************************************
405//******************************************************************************
406int DIBSection::GetDIBSection(int iSize, void *lpBuffer)
407{
408 DIBSECTION *pDIBSection = (DIBSECTION *)lpBuffer;
409 LPBITMAP_W dsBm = (LPBITMAP_W)lpBuffer;
410
411 dprintf2(("GetDIBSection %x %d %x", handle, iSize, lpBuffer));
412 if(iSize == sizeof(DIBSECTION))
413 {
414 memcpy(pDIBSection, &dibinfo, sizeof(dibinfo));
415 return sizeof(DIBSECTION);
416 }
417 else
418 if(iSize == sizeof(BITMAP_W))
419 {
420 memcpy(dsBm, &dibinfo.dsBm, sizeof(dibinfo.dsBm));
421 return sizeof(BITMAP_W);
422 }
423 return 0;
424
425}
426//******************************************************************************
427//******************************************************************************
428char DIBSection::GetBitCount()
429{
430 if(pOS2bmp == NULL)
431 return 0;
432 else
433 return pOS2bmp->cBitCount;
434}
435//******************************************************************************
436//******************************************************************************
437DIBSection *DIBSection::section = NULL;
Note: See TracBrowser for help on using the repository browser.