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

Last change on this file since 10495 was 10495, checked in by sandervl, 21 years ago

VP: Fixes for partial blits in SetDIBitsToDevice

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