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

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

SetDIBitsToDevice fix for inverted blitting

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