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

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

SetDIBitsToDevice: fixes for xSrc offset

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