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

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

CreateDIBitmap: added workaround for DIB_PAL_COLORS mode

File size: 25.8 KB
Line 
1/* $Id: blit.cpp,v 1.51 2004-03-24 16:55:35 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 // GPI will crash when the app accidentally specifies PAL indexes with
187 // high bpp bitmap data
188 if(coloruse == DIB_PAL_COLORS && info->bmiHeader.biBitCount >= 15) {
189 dprintf(("WARNING: DIB_PAL_COLORS can't be used for high color bitmaps!!"));
190 coloruse = DIB_RGB_COLORS;
191 }
192
193 if(bitfields[1] == 0x3E0)
194 {//RGB 555?
195 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
196
197 newbits = (WORD *)malloc(imgsize);
198 pRGB555to565(newbits, (WORD *)bits, imgsize/sizeof(WORD));
199 bits = newbits;
200 dprintf(("RGB 555->565 new bits %x", newbits));
201 }
202
203 //SvL: Ignore BI_BITFIELDS type (SetDIBitsToDevice fails otherwise)
204 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
205 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
206 compression = BI_BITFIELDS;
207 }
208 if(startscan != 0 || lines != info->bmiHeader.biHeight) {
209 dprintf(("WARNING: SetDIBitsToDevice startscan != 0 || lines != info->bmiHeader.biHeight"));
210 dprintf(("info bmp (%d,%d)", info->bmiHeader.biWidth, info->bmiHeader.biHeight));
211 }
212
213 result = O32_StretchDIBits(hdc, xDest, yDest, cx, cy, xSrc, ySrc,
214 cx, cy, (void *)bits,
215 (PBITMAPINFO)info, coloruse, SRCCOPY);
216
217 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
218 if(result != info->bmiHeader.biHeight) {
219 dprintf(("SetDIBitsToDevice failed with rc %x", result));
220 }
221 else
222 {
223 result = info->bmiHeader.biHeight;
224
225 DIBSECTION_MARK_INVALID(hdc);
226 }
227 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",
228 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse, result));
229 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));
230
231 if(compression == BI_BITFIELDS) {
232 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
233 }
234 if(newbits) free(newbits);
235
236 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = bmpsize;
237 return result;
238}
239//******************************************************************************
240//******************************************************************************
241//always extract actual bits to be drawn and construct new bitmap before
242//calling O32_* API if only part of bitmap is drawn
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 INT height, width;
249 INT rc = 0;
250 char *newBits = NULL;
251
252 // save a copy of header as it will be changed probably
253 BITMAPINFOHEADER originalHeader = info->bmiHeader;
254
255 SetLastError(ERROR_SUCCESS);
256
257 if(info == NULL) {
258 goto invalid_parameter;
259 }
260
261 dprintf(("BITMAP: (%d,%d) %d bpp %d bytes",
262 info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount, info->bmiHeader.biSizeImage));
263
264 height = info->bmiHeader.biHeight;
265 width = info->bmiHeader.biWidth;
266
267 if (height < 0) height = -height;
268
269 if (!lines || (startscan >= height)) {
270 goto invalid_parameter;
271 }
272
273 if (startscan + lines > height) lines = height - startscan;
274
275 if (ySrc < startscan) { cy -= startscan - ySrc; ySrc = startscan; }
276 else if (ySrc >= startscan + lines) goto invalid_parameter;
277
278 if (xSrc >= width) goto invalid_parameter;
279
280 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
281
282 if (xSrc + cx >= width) cx = width - xSrc;
283
284 if (!cx || !cy) goto invalid_parameter;
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 // not zero if bpp < 8 and starting on an uneven pixel
299 UINT xOffset = (xSrc * info->bmiHeader.biBitCount) % 8;
300
301 // compute size of memory buffer
302 UINT lBytesPerLineOrig = DIB_GetDIBWidthBytes (info->bmiHeader.biWidth, info->bmiHeader.biBitCount);
303 UINT lBytesToCopyInLine = DIB_GetDIBWidthBytes (cx + xOffset, info->bmiHeader.biBitCount);
304
305 newBits = (char *)malloc (lBytesToCopyInLine * cy);
306
307 if (newBits)
308 {
309 // copy bits to new buffer
310 int i;
311
312 char *pNewBits = (char *)newBits;
313
314 if (info->bmiHeader.biHeight > 0)
315 {
316 // starting pointer
317 char *pBits = (char *)bits + // origin
318 (ySrc - startscan) * lBytesPerLineOrig + // y offset
319 (xSrc * info->bmiHeader.biBitCount) / 8; // x offset
320
321 for (i = 0; i < cy; i++)
322 {
323 memcpy (pNewBits, pBits, lBytesToCopyInLine);
324 pBits += lBytesPerLineOrig;
325 pNewBits += lBytesToCopyInLine;
326 }
327 }
328 else
329 {
330 // starting pointer
331 char *pBits = (char *)bits + // origin
332 (lines - 1 - (ySrc - startscan)) * lBytesPerLineOrig + // y offset
333 (xSrc * info->bmiHeader.biBitCount) / 8; // x offset
334
335 for (i = 0; i < cy; i++)
336 {
337 memcpy (pNewBits, pBits, lBytesToCopyInLine);
338 pBits -= lBytesPerLineOrig;
339 pNewBits += lBytesToCopyInLine;
340 }
341 }
342
343 // newBits contain partial bitmap, correct the header
344 // todo bitcount < 8
345 ((BITMAPINFO *)info)->bmiHeader.biWidth = cx + xOffset;
346 ((BITMAPINFO *)info)->bmiHeader.biHeight = cy;
347 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = lBytesToCopyInLine * cy;
348
349 ySrc = startscan = 0;
350 xSrc = xOffset;
351 lines = cy;
352 dprintf(("Converted BITMAP: (%d,%d) %d bytes xSrc %d ySrc %d",
353 info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biSizeImage, xSrc, ySrc));
354 }
355 }
356 }
357
358 // draw bits
359 rc = SetDIBitsToDevice_( hdc, xDest, yDest,
360 cx, cy, xSrc, ySrc, startscan, lines,
361 newBits? newBits: bits, info, coloruse );
362
363 if (newBits)
364 {
365 // restore original header
366 *(BITMAPINFOHEADER *)&info->bmiHeader = originalHeader;
367 free (newBits);
368 }
369
370 return rc;
371
372invalid_parameter:
373 SetLastError(ERROR_INVALID_PARAMETER);
374 return 0;
375}
376//******************************************************************************
377//******************************************************************************
378BOOL WIN32API PatBlt(HDC hdc,int nXLeft,int nYLeft,int nWidth,int nHeight,DWORD dwRop)
379{
380 BOOL rc;
381
382 dprintf(("PatBlt %x (%d,%d)(%d,%d) %x", hdc, nXLeft,nYLeft,nWidth,nHeight, dwRop));
383 //CB: Open32 bug: negative width/height not supported!
384 if (nWidth < 0)
385 {
386 nXLeft += nWidth+1;
387 nWidth = -nWidth;
388 }
389 if (nHeight < 0)
390 {
391 nYLeft += nHeight+1;
392 nHeight = -nHeight;
393 }
394 rc = O32_PatBlt(hdc,nXLeft,nYLeft,nWidth,nHeight,dwRop);
395 if(rc) {
396 DIBSECTION_MARK_INVALID(hdc);
397 }
398 return(rc);
399}
400//******************************************************************************
401//******************************************************************************
402BOOL 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)
403{
404 BOOL ret;
405
406 DIBSECTION_CHECK_IF_DIRTY(hdcSrc);
407
408 ret = O32_MaskBlt(hdcDest, arg2, arg3, arg4, arg5, hdcSrc, arg7, arg8, arg9, arg10, arg11, arg12);
409 if(ret) {
410 DIBSECTION_MARK_INVALID(hdcDest);
411 }
412 return ret;
413}
414//******************************************************************************
415//******************************************************************************
416BOOL WIN32API PlgBlt(HDC hdcDest, CONST POINT *lpPoint, HDC hdcSrc, int nXSrc,
417 int nYSrc, int nWidth, int nHeight, HBITMAP hbmMask,
418 int xMast, int yMask)
419{
420 dprintf(("GDI32: PlgBlt, not implemented\n"));
421 return(FALSE);
422}
423//******************************************************************************
424//******************************************************************************
425static INT StretchDIBits_(HDC hdc, INT xDst, INT yDst, INT widthDst,
426 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
427 INT heightSrc, const void *bits,
428 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
429{
430 INT rc;
431 DWORD bitfields[3], compression = 0;
432 WORD *newbits = NULL;
433
434 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));
435
436 if(info->bmiHeader.biBitCount == 1) {
437 dprintf(("WARNING: StretchDIBits does NOT work correctly for 1 bpp bitmaps!!"));
438 }
439#if 0
440 // SvL: I'm not sure what this was supposed to fix, but it breaks one
441 // application here
442 // SetDIBitsToDevice works with palette indexes, so this should not
443 // be necessary (anymore)
444 if(wUsage == DIB_PAL_COLORS && info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
445 {
446 // workaround for open32 bug.
447 // If syscolors > 256 and wUsage == DIB_PAL_COLORS.
448
449 int i;
450 UINT biClrUsed;
451 USHORT *pColorIndex = (USHORT *)info->bmiColors;
452 RGBQUAD *pColors;
453 BITMAPINFO *infoLoc;
454
455 biClrUsed = (info->bmiHeader.biClrUsed) ? info->bmiHeader.biClrUsed : (1<<info->bmiHeader.biBitCount);
456
457 pColors = (RGBQUAD *) alloca(biClrUsed * sizeof(RGBQUAD));
458 infoLoc = (BITMAPINFO *) alloca(sizeof(BITMAPINFO) + biClrUsed * sizeof(RGBQUAD));
459
460 memcpy(infoLoc, info, sizeof(BITMAPINFO));
461
462 if(GetDIBColorTable(hdc, 0, biClrUsed, pColors) == 0)
463 {
464 dprintf(("ERROR: StretchDIBits: GetDIBColorTable failed!!"));
465 return FALSE;
466 }
467 for(i=0;i<biClrUsed;i++, pColorIndex++)
468 {
469 infoLoc->bmiColors[i] = pColors[*pColorIndex];
470 }
471
472 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
473 widthSrc, heightSrc, (void *)bits,
474 (PBITMAPINFO)infoLoc, DIB_RGB_COLORS, dwRop);
475
476 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
477 if(rc != heightSrc && rc != infoLoc->bmiHeader.biHeight) {
478 dprintf(("StretchDIBits failed with rc %x", rc));
479 }
480 else {
481 rc = heightSrc;
482
483 DIBSECTION_MARK_INVALID(hdc);
484 }
485
486 return rc;
487 }
488#endif
489 switch(info->bmiHeader.biBitCount) {
490 case 15:
491 case 16: //Default if BI_BITFIELDS not set is RGB 555
492 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : DEFAULT_16BPP_RED_MASK;
493 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : DEFAULT_16BPP_GREEN_MASK;
494 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : DEFAULT_16BPP_BLUE_MASK;
495 break;
496 case 24:
497 case 32:
498 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : DEFAULT_24BPP_RED_MASK;
499 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : DEFAULT_24BPP_GREEN_MASK;
500 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : DEFAULT_24BPP_BLUE_MASK;
501 break;
502 default:
503 bitfields[0] = 0;
504 bitfields[1] = 0;
505 bitfields[2] = 0;
506 break;
507 }
508
509 // GPI will crash when the app accidentally specifies PAL indexes with
510 // high bpp bitmap data
511 if(wUsage == DIB_PAL_COLORS && info->bmiHeader.biBitCount >= 15) {
512 dprintf(("WARNING: DIB_PAL_COLORS can't be used for high color bitmaps!!"));
513 wUsage = DIB_RGB_COLORS;
514 }
515
516 if(bitfields[1] == RGB555_GREEN_MASK)
517 {//RGB 555?
518 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
519
520 ULONG imgsize = CalcBitmapSize(info->bmiHeader.biBitCount,
521 abs(info->bmiHeader.biWidth), heightSrc);
522 ULONG offset = CalcBitmapSize(info->bmiHeader.biBitCount,
523 abs(info->bmiHeader.biWidth), ySrc)/sizeof(WORD);
524 newbits = (WORD *) HeapAlloc(GetProcessHeap(), 0, imgsize);
525
526 //we still convert too much
527 pRGB555to565(newbits, (WORD *)bits+offset, imgsize/sizeof(WORD));
528 bits = newbits;
529
530 ySrc = 0;
531 }
532 //SvL: Ignore BI_BITFIELDS type (StretchDIBits fails otherwise)
533 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
534 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
535 compression = BI_BITFIELDS;
536 }
537
538 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
539 widthSrc, heightSrc, (void *)bits,
540 (PBITMAPINFO)info, wUsage, dwRop);
541
542 if(compression == BI_BITFIELDS) {
543 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
544 }
545 if(newbits) HeapFree(GetProcessHeap(), 0, newbits);
546
547 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
548 if(rc != heightSrc && rc != info->bmiHeader.biHeight) {
549 dprintf(("StretchDIBits failed with rc %x", rc));
550 }
551 else
552 {
553 rc = heightSrc;
554
555 DIBSECTION_MARK_INVALID(hdc);
556 }
557
558 return rc;
559}
560//******************************************************************************
561//******************************************************************************
562INT WIN32API StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
563 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
564 INT heightSrc, const void *bits,
565 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
566{
567 if(info->bmiHeader.biHeight < 0) {
568 // upside down
569 INT rc = 0;
570 BITMAPINFO newInfo;
571 newInfo.bmiHeader = info->bmiHeader;
572 long lLineByte = ((newInfo.bmiHeader.biWidth * (info->bmiHeader.biBitCount == 15 ? 16 : info->bmiHeader.biBitCount) + 31) / 32) * 4;
573 long lHeight = -newInfo.bmiHeader.biHeight;
574 newInfo.bmiHeader.biHeight = -newInfo.bmiHeader.biHeight;
575
576 //TODO: doesn't work if memory is readonly!!
577 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
578
579 char *newBits = (char *)malloc( lLineByte * lHeight );
580 if(newBits) {
581 unsigned char *pbSrc = (unsigned char *)bits + lLineByte * (lHeight - 1);
582 unsigned char *pbDst = (unsigned char *)newBits;
583 for(int y = 0; y < lHeight; y++) {
584 memcpy( pbDst, pbSrc, lLineByte );
585 pbDst += lLineByte;
586 pbSrc -= lLineByte;
587 }
588 rc = StretchDIBits_(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, newBits, info, wUsage, dwRop);
589 free( newBits );
590 }
591
592 //TODO: doesn't work if memory is readonly!!
593 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
594 return rc;
595 } else {
596 return StretchDIBits_(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, bits, info, wUsage, dwRop);
597 }
598}
599//******************************************************************************
600//******************************************************************************
601int WIN32API SetStretchBltMode( HDC arg1, int arg2)
602{
603#ifdef DEBUG
604 if(DIBSection::getSection() != NULL)
605 {
606 DIBSection *dsect = DIBSection::findHDC(arg1);
607 if(dsect)
608 {
609 dprintf((" - DC is DIBSection\n"));
610 }
611 }
612#endif
613 return O32_SetStretchBltMode(arg1, arg2);
614}
615//******************************************************************************
616//******************************************************************************
617int WIN32API GetStretchBltMode( HDC arg1)
618{
619 return O32_GetStretchBltMode(arg1);
620}
621//******************************************************************************
622//******************************************************************************
623static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr)
624{
625 ULONG cbPalette;
626
627 switch (pBHdr->biBitCount)
628 {
629 case 1:
630 case 4:
631 case 8:
632 cbPalette = (1 << pBHdr->biBitCount) * sizeof(RGBQUAD);
633 break;
634
635 case 16:
636 case 24:
637 case 32:
638 cbPalette = 0;
639 break;
640
641 default:
642 dprintf(("QueryPaletteSize: error pBHdr->biBitCount = %d", pBHdr->biBitCount));
643 cbPalette = -1;
644 }
645
646 return cbPalette;
647}
648//******************************************************************************
649//******************************************************************************
650ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy)
651{
652 ULONG alignment;
653 ULONG factor;
654 BOOL flag = TRUE; //true: '*' false: '/'
655
656 cy = cy < 0 ? -cy : cy;
657
658 switch(cBits)
659 {
660 case 1:
661 factor = 8;
662 flag = FALSE;
663 break;
664
665 case 4:
666 factor = 2;
667 flag = FALSE;
668 break;
669
670 case 8:
671 factor = 1;
672 break;
673
674 case 16:
675 factor = 2;
676 break;
677
678 case 24:
679 factor = 3;
680 break;
681
682 case 32:
683 return cx*cy*4;
684
685 default:
686 return 0;
687 }
688
689 if (flag)
690 alignment = (cx = (cx*factor)) % 4;
691 else
692 alignment = (cx = ((cx+factor-1)/factor)) % 4;
693
694 if (alignment != 0)
695 cx += 4 - alignment;
696
697 return cx*cy;
698}
699//******************************************************************************
700//******************************************************************************
Note: See TracBrowser for help on using the repository browser.