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

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

Update

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