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

Last change on this file since 9355 was 9355, checked in by sandervl, 23 years ago

PF: StretchDIBits fix for partial blits & RGB conversion

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