source: trunk/src/gdi32/blit.cpp@ 7713

Last change on this file since 7713 was 7713, checked in by sandervl, 24 years ago

BitBlt, StretchBlt: sync dib section if selected into destination HDC

File size: 27.5 KB
Line 
1/* $Id: blit.cpp,v 1.36 2001-12-30 22:19:04 sandervl Exp $ */
2
3/*
4 * GDI32 blit code
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#include <os2win.h>
13#include <stdlib.h>
14#include <stdarg.h>
15#include <string.h>
16#include <cpuhlp.h>
17#include "misc.h"
18#include "dibsect.h"
19#include "rgbcvt.h"
20
21#define DBG_LOCALLOG DBG_blit
22#include "dbglocal.h"
23
24static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr);
25ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy);
26
27//******************************************************************************
28//******************************************************************************
29BOOL WIN32API StretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest,
30 int nWidthDest, int nHeightDest,
31 HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
32 int nWidthSrc, int nHeightSrc, DWORD dwRop)
33{
34 BOOL rc;
35
36 dprintf(("GDI32: StretchBlt Dest: %x (%d, %d) size (%d, %d) ROP %x",
37 hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, dwRop));
38 dprintf(("GDI32: StretchBlt Src : %x (%d, %d) size (%d, %d)\n",
39 hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc));
40 SetLastError(ERROR_SUCCESS);
41 if(DIBSection::getSection() != NULL)
42 {
43 DIBSection *dsect = DIBSection::findHDC(hdcSrc);
44 if(dsect)
45 {
46 rc = dsect->BitBlt( hdcDest,
47 nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
48 nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
49 dwRop);
50 return rc;
51 }
52 }
53 rc = O32_StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, dwRop);
54 if(DIBSection::getSection() != NULL) {
55 DIBSection *destdib = DIBSection::findHDC(hdcDest);
56 if(destdib) {
57 destdib->sync(hdcDest, nYOriginDest, nHeightDest);
58 }
59 }
60 return rc;
61}
62//******************************************************************************
63//******************************************************************************
64BOOL WIN32API BitBlt(HDC hdcDest,
65 int nXDest,
66 int nYDest,
67 int nWidth,
68 int nHeight,
69 HDC hdcSrc,
70 int nXSrc,
71 int nYSrc,
72 DWORD dwRop)
73{
74 BOOL rc;
75
76 SetLastError(ERROR_SUCCESS);
77 if(DIBSection::getSection() != NULL)
78 {
79 DIBSection *dsect = DIBSection::findHDC(hdcSrc);
80 if(dsect)
81 {
82 return dsect->BitBlt(hdcDest,
83 nXDest,
84 nYDest,
85 nWidth,
86 nHeight,
87 nXSrc,
88 nYSrc,
89 nWidth,
90 nHeight,
91 dwRop);
92 }
93 }
94 dprintf(("GDI32: BitBlt to hdc %X from hdc %x (%d,%d) to (%d,%d), (%d,%d) rop %X\n",
95 hdcDest, hdcSrc, nXSrc, nYSrc, nXDest, nYDest, nWidth, nHeight, dwRop));
96
97 rc = O32_BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop);
98
99 if(DIBSection::getSection() != NULL) {
100 DIBSection *destdib = DIBSection::findHDC(hdcDest);
101 if(destdib) {
102 destdib->sync(hdcDest, nYDest, nHeight);
103 }
104 }
105 return rc;
106}
107//******************************************************************************
108//******************************************************************************
109static INT SetDIBitsToDevice_(HDC hdc, INT xDest, INT yDest, DWORD cx,
110 DWORD cy, INT xSrc, INT ySrc,
111 UINT startscan, UINT lines, LPCVOID bits,
112 const BITMAPINFO *info, UINT coloruse)
113{
114 INT result, imgsize, palsize, height, width;
115 char *ptr;
116 ULONG compression = 0, bmpsize;
117 WORD *newbits = NULL;
118 DWORD bitfields[3];
119
120 dprintf(("GDI32: SetDIBitsToDevice hdc:%X xDest:%d yDest:%d, cx:%d, cy:%d, xSrc:%d, ySrc:%d, startscan:%d, lines:%d \nGDI32: bits 0x%X, info 0x%X, coloruse %d",
121 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse));
122
123 SetLastError(ERROR_SUCCESS);
124 if(info == NULL) {
125 goto invalid_parameter;
126 }
127 height = info->bmiHeader.biHeight;
128 width = info->bmiHeader.biWidth;
129
130 if (height < 0) height = -height;
131 if (!lines || (startscan >= height)) {
132 goto invalid_parameter;
133 }
134 if (startscan + lines > height) lines = height - startscan;
135
136 if (ySrc < startscan) ySrc = startscan;
137 else if (ySrc >= startscan + lines) goto invalid_parameter;
138
139 if (xSrc >= width) goto invalid_parameter;
140
141 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
142
143 if (xSrc + cx >= width) cx = width - xSrc;
144
145 if (!cx || !cy) goto invalid_parameter;
146
147 //SvL: RP7's bitmap size is not correct; fix it here or else
148 // the blit is messed up in Open32
149 imgsize = CalcBitmapSize(info->bmiHeader.biBitCount,
150 info->bmiHeader.biWidth, info->bmiHeader.biHeight);
151 bmpsize = info->bmiHeader.biSizeImage;
152 if(info->bmiHeader.biCompression == 0 && info->bmiHeader.biSizeImage &&
153 info->bmiHeader.biSizeImage < imgsize)
154 {
155 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = imgsize;
156 }
157
158 switch(info->bmiHeader.biBitCount) {
159 case 15:
160 case 16: //Default if BI_BITFIELDS not set is RGB 555
161 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
162 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
163 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
164 break;
165
166 case 24:
167 case 32:
168 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
169 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
170 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
171 break;
172 default:
173 bitfields[0] = 0;
174 bitfields[1] = 0;
175 bitfields[2] = 0;
176 break;
177 }
178
179 if(bitfields[1] == 0x3E0)
180 {//RGB 555?
181 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
182
183 newbits = (WORD *)malloc(imgsize);
184 if(CPUFeatures & CPUID_MMX) {
185 RGB555to565MMX(newbits, (WORD *)bits, imgsize/sizeof(WORD));
186 }
187 else RGB555to565(newbits, (WORD *)bits, imgsize/sizeof(WORD));
188 bits = newbits;
189 }
190
191 //SvL: Ignore BI_BITFIELDS type (SetDIBitsToDevice fails otherwise)
192 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
193 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
194 compression = BI_BITFIELDS;
195
196 }
197 if(startscan != 0 || lines != info->bmiHeader.biHeight) {
198 dprintf(("WARNING: SetDIBitsToDevice startscan != 0 || lines != info->bmiHeader.biHeight"));
199 }
200
201 result = O32_StretchDIBits(hdc, xDest, yDest, cx, cy, xSrc, ySrc,
202 cx, cy, (void *)bits,
203 (PBITMAPINFO)info, coloruse, SRCCOPY);
204
205 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
206 if(result != info->bmiHeader.biHeight) {
207 dprintf(("SetDIBitsToDevice failed with rc %x", result));
208 }
209 else
210 {
211 result = info->bmiHeader.biHeight;
212
213 DIBSection *destdib = DIBSection::findHDC(hdc);
214 if(destdib) {
215 if(cx == info->bmiHeader.biWidth && cy == info->bmiHeader.biHeight &&
216 destdib->GetBitCount() == info->bmiHeader.biBitCount &&
217 destdib->GetBitCount() == 8)
218 {
219 destdib->sync(xDest, yDest, cx, cy, (PVOID)bits);
220 }
221 else destdib->sync(hdc, yDest, cy);
222 }
223 }
224 dprintf(("GDI32: SetDIBitsToDevice hdc:%X xDest:%d yDest:%d, cx:%d, cy:%d, xSrc:%d, ySrc:%d, startscan:%d, lines:%d \nGDI32: bits 0x%X, info 0x%X, coloruse %d returned %d",
225 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse, result));
226 dprintf(("GDI32: SetDIBitsToDevice %d %d %d %d %x %d", info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biPlanes, info->bmiHeader.biBitCount, info->bmiHeader.biCompression, info->bmiHeader.biSizeImage));
227
228 if(compression == BI_BITFIELDS) {
229 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
230 }
231 if(newbits) free(newbits);
232 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = bmpsize;
233 return result;
234
235invalid_parameter:
236 SetLastError(ERROR_INVALID_PARAMETER);
237 return 0;
238}
239//******************************************************************************
240//******************************************************************************
241INT WIN32API SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
242 DWORD cy, INT xSrc, INT ySrc,
243 UINT startscan, UINT lines, LPCVOID bits,
244 const BITMAPINFO *info, UINT coloruse)
245{
246 static BOOL fMatrox32BppBug = FALSE;
247 INT rc = 0;
248 char *newBits = NULL;
249
250 //If upside down, reverse scanlines and call SetDIBitsToDevice again
251 if(info->bmiHeader.biHeight < 0 && info->bmiHeader.biBitCount != 8 && info->bmiHeader.biCompression == 0) {
252 // upside down
253 INT rc = -1;
254 BITMAPINFO newInfo;
255 newInfo.bmiHeader = info->bmiHeader;
256 long lLineByte = ((newInfo.bmiHeader.biWidth * (info->bmiHeader.biBitCount == 15 ? 16 : info->bmiHeader.biBitCount) + 31) / 32) * 4;
257 long lHeight = -newInfo.bmiHeader.biHeight;
258 newInfo.bmiHeader.biHeight = -info->bmiHeader.biHeight;
259
260 char *newBits = (char *)malloc( lLineByte * lHeight );
261 if(newBits) {
262 unsigned char *pbSrc = (unsigned char *)bits + lLineByte * (lHeight - 1);
263 unsigned char *pbDst = (unsigned char *)newBits;
264 for(int y = 0; y < lHeight; y++) {
265 memcpy( pbDst, pbSrc, lLineByte );
266 pbDst += lLineByte;
267 pbSrc -= lLineByte;
268 }
269 rc = SetDIBitsToDevice( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (void *)newBits, &newInfo, coloruse );
270 free( newBits );
271 }
272 else DebugInt3();
273
274 return rc;
275 }
276
277 //We must convert 32 bpp bitmap data to 24 bpp on systems with the Matrox
278 //display driver. (GpiDrawBits for 32 bpp fails with insufficient memory error)
279 if(info->bmiHeader.biBitCount == 32 && fMatrox32BppBug)
280 {
281 BITMAPINFO newInfo;
282 newInfo.bmiHeader = info->bmiHeader;
283
284 long lLineWidth;
285 long lHeight = (newInfo.bmiHeader.biHeight > 0) ? newInfo.bmiHeader.biHeight : -newInfo.bmiHeader.biHeight;
286 long lWidth = newInfo.bmiHeader.biWidth;
287
288 newInfo.bmiHeader.biBitCount = 24;
289 newInfo.bmiHeader.biSizeImage = CalcBitmapSize(24, newInfo.bmiHeader.biWidth,
290 newInfo.bmiHeader.biHeight);
291
292 lLineWidth = newInfo.bmiHeader.biSizeImage / lHeight;
293
294 //convert 32 bits bitmap data to 24 bits
295 newBits = (char *)malloc(newInfo.bmiHeader.biSizeImage+16); //extra room needed for copying (too much)
296 if(!newBits) {
297 DebugInt3();
298 return -1;
299 }
300 unsigned char *pbSrc = (unsigned char *)bits;
301 unsigned char *pbDst = (unsigned char *)newBits;
302 //not very efficient
303 for(int i = 0; i < lHeight; i++) {
304 for(int j=0;j<lWidth;j++) {
305 *(DWORD *)pbDst = *(DWORD *)pbSrc;
306 pbSrc += 4;
307 pbDst += 3;
308 }
309 //24 bpp scanline must be aligned at 4 byte boundary
310 pbDst += (lLineWidth - 3*lWidth);
311 }
312 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, newBits, &newInfo, coloruse );
313 free(newBits);
314 return rc;
315 }
316 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, bits, info, coloruse );
317
318 if(rc == -1 && info->bmiHeader.biBitCount == 32 && !fMatrox32BppBug)
319 {
320 //The Matrox driver seems to have some difficulty blitting 32bpp
321 //data. (out of memory error) The same operation works fine with SDD.
322 fMatrox32BppBug = TRUE;
323 return SetDIBitsToDevice(hdc, xDest, yDest, cx,
324 cy, xSrc, ySrc,
325 startscan, lines, bits,
326 info, coloruse);
327 }
328 return rc;
329
330//SvL: Breaks startup bitmap of Acrobat Reader 4.05
331#if 0
332 else
333 if(info->bmiHeader.biBitCount == 8 && info->bmiHeader.biCompression == 0 && !(GetDeviceCaps( hdc, RASTERCAPS ) & RC_PALETTE)) {
334 INT rc = 0;
335 // convert 8bit to 24bit
336
337 BITMAPINFO newInfo;
338 newInfo.bmiHeader = info->bmiHeader;
339 newInfo.bmiHeader.biBitCount = 24;
340 long lLineByte24 = ((newInfo.bmiHeader.biWidth * 24 + 31) / 32) * 4;
341 long lLineByte8 = ((newInfo.bmiHeader.biWidth * 8 + 31) / 32) * 4;
342 long lHeight = newInfo.bmiHeader.biHeight;
343 if(lHeight < 0) lHeight = -lHeight;
344
345 char *newBits = (char *)malloc( lLineByte24 * lHeight );
346 if(newBits) {
347 //
348 // Get Palette Entries
349 //
350 PALETTEENTRY aEntries[256];
351 LOGPALETTE *pLog = (LOGPALETTE *)malloc( sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256 );
352 pLog->palVersion = 0x300;
353 pLog->palNumEntries = 256;
354
355 HPALETTE hPaletteDummy = CreatePalette( pLog );
356 free( pLog );
357 HPALETTE hPalette = SelectPalette( hdc, hPaletteDummy, FALSE );
358 GetPaletteEntries( hPalette, 0, 255, aEntries );
359 SelectPalette( hdc, hPalette, FALSE );
360 DeleteObject( hPaletteDummy );
361
362 //
363 // convert 8bit to 24bit
364 //
365 if(newInfo.bmiHeader.biHeight > 0) {
366 unsigned char *pbSrc = (unsigned char *)bits;
367 unsigned char *pbDst = (unsigned char *)newBits;
368 for(int y = 0; y < lHeight; y++) {
369 for(int x = 0; x < newInfo.bmiHeader.biWidth; x++) {
370 PALETTEENTRY src = aEntries[pbSrc[x]];
371 pbDst[x * 3 + 0] = src.peBlue;
372 pbDst[x * 3 + 1] = src.peGreen;
373 pbDst[x * 3 + 2] = src.peRed;
374 }
375 pbDst += lLineByte24;
376 pbSrc += lLineByte8;
377 }
378 } else {
379 // upside down
380 newInfo.bmiHeader.biHeight = -info->bmiHeader.biHeight;
381 unsigned char *pbSrc = (unsigned char *)bits + lLineByte8 * (lHeight - 1);
382 unsigned char *pbDst = (unsigned char *)newBits;
383 for(int y = 0; y < lHeight; y++) {
384 for(int x = 0; x < newInfo.bmiHeader.biWidth; x++) {
385 PALETTEENTRY src = aEntries[pbSrc[x]];
386 pbDst[x * 3 + 0] = src.peBlue;
387 pbDst[x * 3 + 1] = src.peGreen;
388 pbDst[x * 3 + 2] = src.peRed;
389 }
390 pbDst += lLineByte24;
391 pbSrc -= lLineByte8;
392 }
393 }
394 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (void *)newBits, &newInfo, DIB_RGB_COLORS );
395 free( newBits );
396 }
397 return rc;
398 }
399#endif
400}
401//******************************************************************************
402//******************************************************************************
403BOOL WIN32API PatBlt(HDC hdc,int nXLeft,int nYLeft,int nWidth,int nHeight,DWORD dwRop)
404{
405 BOOL rc;
406
407 dprintf(("PatBlt %x (%d,%d)(%d,%d) %x", hdc, nXLeft,nYLeft,nWidth,nHeight, dwRop));
408 //CB: Open32 bug: negative width/height not supported!
409 if (nWidth < 0)
410 {
411 nXLeft += nWidth+1;
412 nWidth = -nWidth;
413 }
414 if (nHeight < 0)
415 {
416 nYLeft += nHeight+1;
417 nHeight = -nHeight;
418 }
419 rc = O32_PatBlt(hdc,nXLeft,nYLeft,nWidth,nHeight,dwRop);
420 if(rc) {
421 DIBSection *destdib = DIBSection::findHDC(hdc);
422 if(destdib) {
423 destdib->sync(hdc, nYLeft, nHeight);
424 }
425 }
426
427 dprintf(("GDI32: PatBlt hdc %x (%d,%d) (%d,%d) returned %d\n",hdc, nXLeft,nYLeft,nWidth,nHeight,rc));
428 return(rc);
429}
430//******************************************************************************
431//******************************************************************************
432BOOL WIN32API MaskBlt( HDC arg1, int arg2, int arg3, int arg4, int arg5, HDC arg6, int arg7, int arg8, HBITMAP arg9, int arg10, int arg11, DWORD arg12)
433{
434 dprintf(("GDI32: MaskBlt"));
435 return O32_MaskBlt(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
436}
437//******************************************************************************
438//******************************************************************************
439BOOL WIN32API PlgBlt(HDC hdcDest, CONST POINT *lpPoint, HDC hdcSrc, int nXSrc,
440 int nYSrc, int nWidth, int nHeight, HBITMAP hbmMask,
441 int xMast, int yMask)
442{
443 dprintf(("GDI32: PlgBlt, not implemented\n"));
444 return(FALSE);
445}
446//******************************************************************************
447//******************************************************************************
448static INT StretchDIBits_(HDC hdc, INT xDst, INT yDst, INT widthDst,
449 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
450 INT heightSrc, const void *bits,
451 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
452{
453 INT rc;
454 DWORD bitfields[3], compression = 0;
455 WORD *newbits = NULL;
456
457 dprintf(("GDI32: StretchDIBits %x to (%d,%d) (%d,%d) from (%d,%d) (%d,%d), %x %x %x %x", hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, bits, info, wUsage, dwRop));
458
459 if(info->bmiHeader.biBitCount == 1) {
460 dprintf(("WARNING: StretchDIBits does NOT work correctly for 1 bpp bitmaps!!"));
461 }
462
463 if(wUsage == DIB_PAL_COLORS && info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
464 {
465 // workaround for open32 bug.
466 // If syscolors > 256 and wUsage == DIB_PAL_COLORS.
467
468 int i;
469 USHORT *pColorIndex = (USHORT *)info->bmiColors;
470 RGBQUAD *pColors = (RGBQUAD *) alloca(info->bmiHeader.biClrUsed *
471 sizeof(RGBQUAD));
472 BITMAPINFO *infoLoc = (BITMAPINFO *) alloca(sizeof(BITMAPINFO) +
473 info->bmiHeader.biClrUsed * sizeof(RGBQUAD));
474
475 memcpy(infoLoc, info, sizeof(BITMAPINFO));
476
477 if(GetDIBColorTable(hdc, 0, info->bmiHeader.biClrUsed, pColors) == 0) {
478 dprintf(("ERROR: StretchDIBits: GetDIBColorTable failed!!"));
479 return FALSE;
480 }
481 for(i=0;i<info->bmiHeader.biClrUsed;i++, pColorIndex++)
482 {
483 infoLoc->bmiColors[i] = pColors[*pColorIndex];
484 }
485
486 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
487 widthSrc, heightSrc, (void *)bits,
488 (PBITMAPINFO)infoLoc, DIB_RGB_COLORS, dwRop);
489
490 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
491 if(rc != heightSrc && rc != infoLoc->bmiHeader.biHeight) {
492 dprintf(("StretchDIBits failed with rc %x", rc));
493 }
494 else {
495 rc = heightSrc;
496
497 DIBSection *destdib = DIBSection::findHDC(hdc);
498 if(destdib) {
499 if(widthDst == widthSrc && heightDst == heightSrc &&
500 destdib->GetBitCount() == infoLoc->bmiHeader.biBitCount &&
501 destdib->GetBitCount() == 8)
502 {
503 destdib->sync(xDst, yDst, widthDst, heightDst, (PVOID)bits);
504 }
505 else destdib->sync(hdc, yDst, heightDst);
506 }
507 }
508
509 return rc;
510 }
511
512 switch(info->bmiHeader.biBitCount) {
513 case 15:
514 case 16: //Default if BI_BITFIELDS not set is RGB 555
515 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
516 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
517 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
518 break;
519 case 24:
520 case 32:
521 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
522 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
523 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
524 break;
525 default:
526 bitfields[0] = 0;
527 bitfields[1] = 0;
528 bitfields[2] = 0;
529 break;
530 }
531 if(bitfields[1] == 0x3E0)
532 {//RGB 555?
533 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
534
535 int imgsize = CalcBitmapSize(info->bmiHeader.biBitCount,
536 info->bmiHeader.biWidth, info->bmiHeader.biHeight);
537
538 newbits = (WORD *)malloc(imgsize);
539 if(CPUFeatures & CPUID_MMX) {
540 RGB555to565MMX(newbits, (WORD *)bits, imgsize/sizeof(WORD));
541 }
542 else RGB555to565(newbits, (WORD *)bits, imgsize/sizeof(WORD));
543 bits = newbits;
544 }
545 //SvL: Ignore BI_BITFIELDS type (SetDIBitsToDevice fails otherwise)
546 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
547 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
548 compression = BI_BITFIELDS;
549 }
550
551 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
552 widthSrc, heightSrc, (void *)bits,
553 (PBITMAPINFO)info, wUsage, dwRop);
554
555 if(compression == BI_BITFIELDS) {
556 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
557 }
558 if(newbits) free(newbits);
559
560 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
561 if(rc != heightSrc && rc != info->bmiHeader.biHeight) {
562 dprintf(("StretchDIBits failed with rc %x", rc));
563 }
564 else
565 {
566 rc = heightSrc;
567
568 DIBSection *destdib = DIBSection::findHDC(hdc);
569 if(destdib) {
570 if(widthDst == widthSrc && heightDst == heightSrc &&
571 destdib->GetBitCount() == info->bmiHeader.biBitCount &&
572 destdib->GetBitCount() == 8)
573 {
574 destdib->sync(xDst, yDst, widthDst, heightDst, (PVOID)bits);
575 }
576 else destdib->sync(hdc, yDst, heightDst);
577 }
578 }
579
580 return rc;
581}
582//******************************************************************************
583//******************************************************************************
584INT WIN32API StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
585 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
586 INT heightSrc, const void *bits,
587 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
588{
589
590 if(info->bmiHeader.biHeight < 0) {
591 // upside down
592 INT rc = 0;
593 BITMAPINFO newInfo;
594 newInfo.bmiHeader = info->bmiHeader;
595 long lLineByte = ((newInfo.bmiHeader.biWidth * (info->bmiHeader.biBitCount == 15 ? 16 : info->bmiHeader.biBitCount) + 31) / 32) * 4;
596 long lHeight = -newInfo.bmiHeader.biHeight;
597 newInfo.bmiHeader.biHeight = -newInfo.bmiHeader.biHeight;
598
599 //TODO: doesn't work if memory is readonly!!
600 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
601
602 char *newBits = (char *)malloc( lLineByte * lHeight );
603 if(newBits) {
604 unsigned char *pbSrc = (unsigned char *)bits + lLineByte * (lHeight - 1);
605 unsigned char *pbDst = (unsigned char *)newBits;
606 for(int y = 0; y < lHeight; y++) {
607 memcpy( pbDst, pbSrc, lLineByte );
608 pbDst += lLineByte;
609 pbSrc -= lLineByte;
610 }
611 rc = StretchDIBits_(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, newBits, info, wUsage, dwRop);
612 free( newBits );
613 }
614
615 //TODO: doesn't work if memory is readonly!!
616 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
617 return rc;
618 } else {
619 return StretchDIBits_(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, bits, info, wUsage, dwRop);
620 }
621}
622//******************************************************************************
623//******************************************************************************
624int WIN32API SetStretchBltMode( HDC arg1, int arg2)
625{
626 dprintf(("GDI32: SetStretchBltMode 0x%08X, 0x%08X\n",arg1, arg2));
627
628 if(DIBSection::getSection() != NULL)
629 {
630 DIBSection *dsect = DIBSection::findHDC(arg1);
631 if(dsect)
632 {
633 dprintf((" - DC is DIBSection\n"));
634 }
635 }
636 return O32_SetStretchBltMode(arg1, arg2);
637}
638//******************************************************************************
639//******************************************************************************
640int WIN32API GetStretchBltMode( HDC arg1)
641{
642 dprintf(("GDI32: GetStretchBltMode"));
643 return O32_GetStretchBltMode(arg1);
644}
645//******************************************************************************
646//******************************************************************************
647static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr)
648{
649 ULONG cbPalette;
650
651 switch (pBHdr->biBitCount)
652 {
653 case 1:
654 case 4:
655 case 8:
656 cbPalette = (1 << pBHdr->biBitCount) * sizeof(RGBQUAD);
657 break;
658
659 case 16:
660 case 24:
661 case 32:
662 cbPalette = 0;
663 break;
664
665 default:
666 dprintf(("QueryPaletteSize: error pBHdr->biBitCount = %d", pBHdr->biBitCount));
667 cbPalette = -1;
668 }
669
670 return cbPalette;
671}
672//******************************************************************************
673//******************************************************************************
674ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy)
675{
676 ULONG alignment;
677 ULONG factor;
678 BOOL flag = TRUE; //true: '*' false: '/'
679
680 cy = cy < 0 ? -cy : cy;
681
682 switch(cBits)
683 {
684 case 1:
685 factor = 8;
686 flag = FALSE;
687 break;
688
689 case 4:
690 factor = 2;
691 flag = FALSE;
692 break;
693
694 case 8:
695 factor = 1;
696 break;
697
698 case 16:
699 factor = 2;
700 break;
701
702 case 24:
703 factor = 3;
704 break;
705
706 case 32:
707 return cx*cy*4;
708
709 default:
710 return 0;
711 }
712
713 if (flag)
714 alignment = (cx = (cx*factor)) % 4;
715 else
716 alignment = (cx = ((cx+factor-1)/factor)) % 4;
717
718 if (alignment != 0)
719 cx += 4 - alignment;
720
721 return cx*cy;
722}
723//******************************************************************************
724//******************************************************************************
Note: See TracBrowser for help on using the repository browser.