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

Last change on this file since 10167 was 10167, checked in by sandervl, 22 years ago

DT: Fix for partial blits in StretchDIBits; optimized rgb conversion calls

File size: 25.5 KB
Line 
1/* $Id: blit.cpp,v 1.45 2003-07-16 10:46:16 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 <winuser32.h>
18#include <dbglog.h>
19#include "dibsect.h"
20#include "rgbcvt.h"
21
22#define DBG_LOCALLOG DBG_blit
23#include "dbglocal.h"
24
25static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr);
26ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy);
27
28//******************************************************************************
29//******************************************************************************
30BOOL WIN32API StretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest,
31 int nWidthDest, int nHeightDest,
32 HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
33 int nWidthSrc, int nHeightSrc, DWORD dwRop)
34{
35 BOOL rc;
36
37 dprintf(("GDI32: StretchBlt Dest: %x (%d, %d) size (%d, %d) ROP %x",
38 hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, dwRop));
39 dprintf(("GDI32: StretchBlt Src : %x (%d, %d) size (%d, %d)\n",
40 hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc));
41
42 SetLastError(ERROR_SUCCESS);
43 if(DIBSection::getSection() != NULL)
44 {
45 DIBSection *dsect = DIBSection::findHDC(hdcSrc);
46 if(dsect)
47 {
48 rc = dsect->BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
49 nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, 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 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 pRGB555to565(newbits, (WORD *)bits, imgsize/sizeof(WORD));
186 bits = newbits;
187 }
188
189 //SvL: Ignore BI_BITFIELDS type (SetDIBitsToDevice fails otherwise)
190 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
191 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
192 compression = BI_BITFIELDS;
193 }
194 if(startscan != 0 || lines != info->bmiHeader.biHeight) {
195 dprintf(("WARNING: SetDIBitsToDevice startscan != 0 || lines != info->bmiHeader.biHeight"));
196 dprintf(("info bmp (%d,%d)", info->bmiHeader.biWidth, info->bmiHeader.biHeight));
197 }
198
199 result = O32_StretchDIBits(hdc, xDest, yDest, cx, cy, xSrc, ySrc,
200 cx, cy, (void *)bits,
201 (PBITMAPINFO)info, coloruse, SRCCOPY);
202
203 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
204 if(result != info->bmiHeader.biHeight) {
205 dprintf(("SetDIBitsToDevice failed with rc %x", result));
206 }
207 else
208 {
209 result = info->bmiHeader.biHeight;
210
211 DIBSection *destdib = DIBSection::findHDC(hdc);
212 if(destdib) {
213 if(cx == info->bmiHeader.biWidth && cy == info->bmiHeader.biHeight &&
214 destdib->GetBitCount() == info->bmiHeader.biBitCount &&
215 destdib->GetBitCount() == 8)
216 {
217 destdib->sync(xDest, yDest, cx, cy, (PVOID)bits);
218 }
219 else destdib->sync(hdc, yDest, cy);
220 }
221 }
222 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",
223 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse, result));
224 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));
225
226 if(compression == BI_BITFIELDS) {
227 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
228 }
229 if(newbits) free(newbits);
230
231 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = bmpsize;
232 return result;
233
234invalid_parameter:
235 SetLastError(ERROR_INVALID_PARAMETER);
236 return 0;
237}
238//******************************************************************************
239//******************************************************************************
240INT WIN32API SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
241 DWORD cy, INT xSrc, INT ySrc,
242 UINT startscan, UINT lines, LPCVOID bits,
243 const BITMAPINFO *info, UINT coloruse)
244{
245 static BOOL fMatrox32BppBug = FALSE;
246 INT rc = 0;
247 char *newBits = NULL;
248
249 if(startscan != 0 || lines != abs(info->bmiHeader.biHeight)) {
250 dprintf(("WARNING: SetDIBitsToDevice: startscan != 0 || lines != abs(info->bmiHeader.biHeight"));
251 }
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 if(info->bmiHeader.biHeight < 0 && (info->bmiHeader.biCompression == BI_RGB ||
256 info->bmiHeader.biCompression == BI_BITFIELDS))
257 {
258 // upside down
259 INT rc = -1;
260 long lLineByte = DIB_GetDIBWidthBytes(info->bmiHeader.biWidth, info->bmiHeader.biBitCount);
261 long lHeight = -info->bmiHeader.biHeight;
262
263 //TODO: doesn't work if memory is readonly!!
264 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
265
266 char *newBits = (char *)malloc( lLineByte * lHeight );
267 if(newBits) {
268 unsigned char *pbSrc = (unsigned char *)bits + xSrc + lLineByte * (ySrc + lHeight - 1);
269 unsigned char *pbDst = (unsigned char *)newBits;
270 for(int y = 0; y < lHeight; y++) {
271 memcpy( pbDst, pbSrc, lLineByte );
272 pbDst += lLineByte;
273 pbSrc -= lLineByte;
274 }
275 //We only convert the necessary data so xSrc & ySrc are now 0
276 rc = SetDIBitsToDevice( hdc, xDest, yDest, cx, cy, 0, 0, startscan, lines, (void *)newBits, info, coloruse );
277 free( newBits );
278 }
279 else DebugInt3();
280
281 //TODO: doesn't work if memory is readonly!!
282 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
283
284 return rc;
285 }
286
287 //We must convert 32 bpp bitmap data to 24 bpp on systems with the Matrox
288 //display driver. (GpiDrawBits for 32 bpp fails with insufficient memory error)
289 if(info->bmiHeader.biBitCount == 32 && fMatrox32BppBug)
290 {
291 BITMAPINFO newInfo;
292 newInfo.bmiHeader = info->bmiHeader;
293
294 long lLineWidth;
295 long lHeight = (newInfo.bmiHeader.biHeight > 0) ? newInfo.bmiHeader.biHeight : -newInfo.bmiHeader.biHeight;
296 long lWidth = newInfo.bmiHeader.biWidth;
297
298 newInfo.bmiHeader.biBitCount = 24;
299 newInfo.bmiHeader.biSizeImage = CalcBitmapSize(24, newInfo.bmiHeader.biWidth,
300 newInfo.bmiHeader.biHeight);
301
302 lLineWidth = newInfo.bmiHeader.biSizeImage / lHeight;
303
304 //convert 32 bits bitmap data to 24 bits
305 newBits = (char *)malloc(newInfo.bmiHeader.biSizeImage+16); //extra room needed for copying (too much)
306 if(!newBits) {
307 DebugInt3();
308 return -1;
309 }
310 unsigned char *pbSrc = (unsigned char *)bits;
311 unsigned char *pbDst = (unsigned char *)newBits;
312 //not very efficient
313 for(int i = 0; i < lHeight; i++) {
314 for(int j=0;j<lWidth;j++) {
315 *(DWORD *)pbDst = *(DWORD *)pbSrc;
316 pbSrc += 4;
317 pbDst += 3;
318 }
319 //24 bpp scanline must be aligned at 4 byte boundary
320 pbDst += (lLineWidth - 3*lWidth);
321 }
322 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, newBits, &newInfo, coloruse );
323 free(newBits);
324 return rc;
325 }
326 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, bits, info, coloruse );
327
328 if(rc == -1 && info->bmiHeader.biBitCount == 32 && !fMatrox32BppBug)
329 {
330 //The Matrox driver seems to have some difficulty blitting 32bpp
331 //data. (out of memory error) The same operation works fine with SDD.
332 fMatrox32BppBug = TRUE;
333 return SetDIBitsToDevice(hdc, xDest, yDest, cx,
334 cy, xSrc, ySrc,
335 startscan, lines, bits,
336 info, coloruse);
337 }
338 return rc;
339}
340//******************************************************************************
341//******************************************************************************
342BOOL WIN32API PatBlt(HDC hdc,int nXLeft,int nYLeft,int nWidth,int nHeight,DWORD dwRop)
343{
344 BOOL rc;
345
346 dprintf(("PatBlt %x (%d,%d)(%d,%d) %x", hdc, nXLeft,nYLeft,nWidth,nHeight, dwRop));
347 //CB: Open32 bug: negative width/height not supported!
348 if (nWidth < 0)
349 {
350 nXLeft += nWidth+1;
351 nWidth = -nWidth;
352 }
353 if (nHeight < 0)
354 {
355 nYLeft += nHeight+1;
356 nHeight = -nHeight;
357 }
358 rc = O32_PatBlt(hdc,nXLeft,nYLeft,nWidth,nHeight,dwRop);
359 if(rc) {
360 DIBSection *destdib = DIBSection::findHDC(hdc);
361 if(destdib) {
362 destdib->sync(hdc, nYLeft, nHeight);
363 }
364 }
365 return(rc);
366}
367//******************************************************************************
368//******************************************************************************
369BOOL 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)
370{
371 return O32_MaskBlt(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
372}
373//******************************************************************************
374//******************************************************************************
375BOOL WIN32API PlgBlt(HDC hdcDest, CONST POINT *lpPoint, HDC hdcSrc, int nXSrc,
376 int nYSrc, int nWidth, int nHeight, HBITMAP hbmMask,
377 int xMast, int yMask)
378{
379 dprintf(("GDI32: PlgBlt, not implemented\n"));
380 return(FALSE);
381}
382//******************************************************************************
383//******************************************************************************
384static INT StretchDIBits_(HDC hdc, INT xDst, INT yDst, INT widthDst,
385 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
386 INT heightSrc, const void *bits,
387 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
388{
389 INT rc;
390 DWORD bitfields[3], compression = 0;
391 WORD *newbits = NULL;
392
393 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));
394
395 if(info->bmiHeader.biBitCount == 1) {
396 dprintf(("WARNING: StretchDIBits does NOT work correctly for 1 bpp bitmaps!!"));
397 }
398
399 if(wUsage == DIB_PAL_COLORS && info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
400 {
401 // workaround for open32 bug.
402 // If syscolors > 256 and wUsage == DIB_PAL_COLORS.
403
404 int i;
405 USHORT *pColorIndex = (USHORT *)info->bmiColors;
406 RGBQUAD *pColors = (RGBQUAD *) alloca(info->bmiHeader.biClrUsed *
407 sizeof(RGBQUAD));
408 BITMAPINFO *infoLoc = (BITMAPINFO *) alloca(sizeof(BITMAPINFO) +
409 info->bmiHeader.biClrUsed * sizeof(RGBQUAD));
410
411 memcpy(infoLoc, info, sizeof(BITMAPINFO));
412
413 if(GetDIBColorTable(hdc, 0, info->bmiHeader.biClrUsed, pColors) == 0) {
414 dprintf(("ERROR: StretchDIBits: GetDIBColorTable failed!!"));
415 return FALSE;
416 }
417 for(i=0;i<info->bmiHeader.biClrUsed;i++, pColorIndex++)
418 {
419 infoLoc->bmiColors[i] = pColors[*pColorIndex];
420 }
421
422 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
423 widthSrc, heightSrc, (void *)bits,
424 (PBITMAPINFO)infoLoc, DIB_RGB_COLORS, dwRop);
425
426 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
427 if(rc != heightSrc && rc != infoLoc->bmiHeader.biHeight) {
428 dprintf(("StretchDIBits failed with rc %x", rc));
429 }
430 else {
431 rc = heightSrc;
432
433 DIBSection *destdib = DIBSection::findHDC(hdc);
434 if(destdib) {
435 if(widthDst == widthSrc && heightDst == heightSrc &&
436 destdib->GetBitCount() == infoLoc->bmiHeader.biBitCount &&
437 destdib->GetBitCount() == 8)
438 {
439 destdib->sync(xDst, yDst, widthDst, heightDst, (PVOID)bits);
440 }
441 else destdib->sync(hdc, yDst, heightDst);
442 }
443 }
444
445 return rc;
446 }
447
448 switch(info->bmiHeader.biBitCount) {
449 case 15:
450 case 16: //Default if BI_BITFIELDS not set is RGB 555
451 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : DEFAULT_16BPP_RED_MASK;
452 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : DEFAULT_16BPP_GREEN_MASK;
453 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : DEFAULT_16BPP_BLUE_MASK;
454 break;
455 case 24:
456 case 32:
457 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : DEFAULT_24BPP_RED_MASK;
458 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : DEFAULT_24BPP_GREEN_MASK;
459 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : DEFAULT_24BPP_BLUE_MASK;
460 break;
461 default:
462 bitfields[0] = 0;
463 bitfields[1] = 0;
464 bitfields[2] = 0;
465 break;
466 }
467
468 if(bitfields[1] == RGB555_GREEN_MASK)
469 {//RGB 555?
470 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
471
472 ULONG imgsize = CalcBitmapSize(info->bmiHeader.biBitCount,
473 abs(info->bmiHeader.biWidth), heightSrc);
474 ULONG offset = CalcBitmapSize(info->bmiHeader.biBitCount,
475 abs(info->bmiHeader.biWidth), ySrc)/sizeof(WORD);
476 newbits = (WORD *) HeapAlloc(GetProcessHeap(), 0, imgsize);
477
478 //we still convert too much
479 pRGB555to565(newbits, (WORD *)bits+offset, imgsize/sizeof(WORD));
480 bits = newbits;
481
482 ySrc = 0;
483 }
484 //SvL: Ignore BI_BITFIELDS type (StretchDIBits fails otherwise)
485 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
486 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
487 compression = BI_BITFIELDS;
488 }
489
490 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
491 widthSrc, heightSrc, (void *)bits,
492 (PBITMAPINFO)info, wUsage, dwRop);
493
494 if(compression == BI_BITFIELDS) {
495 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
496 }
497 if(newbits) HeapFree(GetProcessHeap(), 0, newbits);
498
499 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
500 if(rc != heightSrc && rc != info->bmiHeader.biHeight) {
501 dprintf(("StretchDIBits failed with rc %x", rc));
502 }
503 else
504 {
505 rc = heightSrc;
506
507 DIBSection *destdib = DIBSection::findHDC(hdc);
508 if(destdib) {
509 if(widthDst == widthSrc && heightDst == heightSrc &&
510 destdib->GetBitCount() == info->bmiHeader.biBitCount &&
511 destdib->GetBitCount() == 8)
512 {
513 destdib->sync(xDst, yDst, widthDst, heightDst, (PVOID)bits);
514 }
515 else destdib->sync(hdc, yDst, heightDst);
516 }
517 }
518
519 return rc;
520}
521//******************************************************************************
522//******************************************************************************
523INT WIN32API StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
524 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
525 INT heightSrc, const void *bits,
526 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
527{
528
529 if(info->bmiHeader.biHeight < 0) {
530 // upside down
531 INT rc = 0;
532 BITMAPINFO newInfo;
533 newInfo.bmiHeader = info->bmiHeader;
534 long lLineByte = ((newInfo.bmiHeader.biWidth * (info->bmiHeader.biBitCount == 15 ? 16 : info->bmiHeader.biBitCount) + 31) / 32) * 4;
535 long lHeight = -newInfo.bmiHeader.biHeight;
536 newInfo.bmiHeader.biHeight = -newInfo.bmiHeader.biHeight;
537
538 //TODO: doesn't work if memory is readonly!!
539 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
540
541 char *newBits = (char *)malloc( lLineByte * lHeight );
542 if(newBits) {
543 unsigned char *pbSrc = (unsigned char *)bits + lLineByte * (lHeight - 1);
544 unsigned char *pbDst = (unsigned char *)newBits;
545 for(int y = 0; y < lHeight; y++) {
546 memcpy( pbDst, pbSrc, lLineByte );
547 pbDst += lLineByte;
548 pbSrc -= lLineByte;
549 }
550 rc = StretchDIBits_(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, newBits, info, wUsage, dwRop);
551 free( newBits );
552 }
553
554 //TODO: doesn't work if memory is readonly!!
555 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
556 return rc;
557 } else {
558 return StretchDIBits_(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, bits, info, wUsage, dwRop);
559 }
560}
561//******************************************************************************
562//******************************************************************************
563int WIN32API SetStretchBltMode( HDC arg1, int arg2)
564{
565 if(DIBSection::getSection() != NULL)
566 {
567 DIBSection *dsect = DIBSection::findHDC(arg1);
568 if(dsect)
569 {
570 dprintf((" - DC is DIBSection\n"));
571 }
572 }
573 return O32_SetStretchBltMode(arg1, arg2);
574}
575//******************************************************************************
576//******************************************************************************
577int WIN32API GetStretchBltMode( HDC arg1)
578{
579 return O32_GetStretchBltMode(arg1);
580}
581//******************************************************************************
582//******************************************************************************
583static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr)
584{
585 ULONG cbPalette;
586
587 switch (pBHdr->biBitCount)
588 {
589 case 1:
590 case 4:
591 case 8:
592 cbPalette = (1 << pBHdr->biBitCount) * sizeof(RGBQUAD);
593 break;
594
595 case 16:
596 case 24:
597 case 32:
598 cbPalette = 0;
599 break;
600
601 default:
602 dprintf(("QueryPaletteSize: error pBHdr->biBitCount = %d", pBHdr->biBitCount));
603 cbPalette = -1;
604 }
605
606 return cbPalette;
607}
608//******************************************************************************
609//******************************************************************************
610ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy)
611{
612 ULONG alignment;
613 ULONG factor;
614 BOOL flag = TRUE; //true: '*' false: '/'
615
616 cy = cy < 0 ? -cy : cy;
617
618 switch(cBits)
619 {
620 case 1:
621 factor = 8;
622 flag = FALSE;
623 break;
624
625 case 4:
626 factor = 2;
627 flag = FALSE;
628 break;
629
630 case 8:
631 factor = 1;
632 break;
633
634 case 16:
635 factor = 2;
636 break;
637
638 case 24:
639 factor = 3;
640 break;
641
642 case 32:
643 return cx*cy*4;
644
645 default:
646 return 0;
647 }
648
649 if (flag)
650 alignment = (cx = (cx*factor)) % 4;
651 else
652 alignment = (cx = ((cx+factor-1)/factor)) % 4;
653
654 if (alignment != 0)
655 cx += 4 - alignment;
656
657 return cx*cy;
658}
659//******************************************************************************
660//******************************************************************************
Note: See TracBrowser for help on using the repository browser.