1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Functions for drawing to GDI without using DirectX.
12 *
13 * By Marian Dvorsky.
14 *
15 * See readme.txt for copyright information.
16 */
17
18
19 #include "allegro.h"
20 #include "allegro/internal/aintern.h"
21 #include "allegro/platform/aintwin.h"
22
23 #ifndef ALLEGRO_WINDOWS
24 #error something is wrong with the makefile
25 #endif
26
27
28 static HPALETTE current_hpalette = NULL;
29
30
31
32 /* set_gdi_color_format:
33 * Sets right values for pixel color format to work with GDI.
34 */
set_gdi_color_format(void)35 void set_gdi_color_format(void)
36 {
37 _rgb_r_shift_15 = 10;
38 _rgb_g_shift_15 = 5;
39 _rgb_b_shift_15 = 0;
40
41 _rgb_r_shift_16 = 11;
42 _rgb_g_shift_16 = 5;
43 _rgb_b_shift_16 = 0;
44
45 _rgb_r_shift_24 = 16;
46 _rgb_g_shift_24 = 8;
47 _rgb_b_shift_24 = 0;
48
49 _rgb_r_shift_32 = 16;
50 _rgb_g_shift_32 = 8;
51 _rgb_b_shift_32 = 0;
52 }
53
54
55
56 /* destroy_current_hpalette:
57 * Destroys the current Windows PALETTE.
58 */
destroy_current_hpalette(void)59 static void destroy_current_hpalette(void)
60 {
61 if (current_hpalette) {
62 DeleteObject(current_hpalette);
63 current_hpalette = NULL;
64 }
65
66 _remove_exit_func(destroy_current_hpalette);
67 }
68
69
70
71 /* set_palette_to_hdc:
72 * Selects and realizes an Allegro PALETTE to a Windows DC.
73 */
set_palette_to_hdc(HDC dc,PALETTE pal)74 void set_palette_to_hdc(HDC dc, PALETTE pal)
75 {
76 PALETTEENTRY palPalEntry[256];
77 int i;
78
79 if (current_hpalette) {
80 for (i = 0; i < 256; i++) {
81 palPalEntry[i].peRed = _rgb_scale_6[pal[i].r];
82 palPalEntry[i].peGreen = _rgb_scale_6[pal[i].g];
83 palPalEntry[i].peBlue = _rgb_scale_6[pal[i].b];
84 palPalEntry[i].peFlags = 0;
85 }
86
87 SetPaletteEntries(current_hpalette, 0, 256, (LPPALETTEENTRY) & palPalEntry);
88 }
89 else {
90 current_hpalette = convert_palette_to_hpalette(pal);
91 _add_exit_func(destroy_current_hpalette,
92 "destroy_current_hpalette");
93 }
94
95 SelectPalette(dc, current_hpalette, FALSE);
96 RealizePalette(dc);
97 select_palette(pal);
98 }
99
100
101
102 /* convert_palette_to_hpalette:
103 * Converts an Allegro PALETTE to a Windows PALETTE.
104 */
convert_palette_to_hpalette(PALETTE pal)105 HPALETTE convert_palette_to_hpalette(PALETTE pal)
106 {
107 HPALETTE hpal;
108 LOGPALETTE *lp;
109 int i;
110
111 lp = (LOGPALETTE *) _AL_MALLOC(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256);
112 if (!lp)
113 return NULL;
114
115 lp->palNumEntries = 256;
116 lp->palVersion = 0x300;
117
118 for (i = 0; i < 256; i++) {
119 lp->palPalEntry[i].peRed = _rgb_scale_6[pal[i].r];
120 lp->palPalEntry[i].peGreen = _rgb_scale_6[pal[i].g];
121 lp->palPalEntry[i].peBlue = _rgb_scale_6[pal[i].b];
122 lp->palPalEntry[i].peFlags = 0;
123 }
124
125 hpal = CreatePalette(lp);
126
127 _AL_FREE(lp);
128
129 return hpal;
130 }
131
132
133
134 /* convert_hpalette_to_palette:
135 * Converts a Windows PALETTE to an Allegro PALETTE.
136 */
convert_hpalette_to_palette(HPALETTE hpal,PALETTE pal)137 void convert_hpalette_to_palette(HPALETTE hpal, PALETTE pal)
138 {
139 PALETTEENTRY lp[256];
140 int i;
141
142 GetPaletteEntries(hpal, 0, 256, (LPPALETTEENTRY) & lp);
143
144 for (i = 0; i < 256; i++) {
145 pal[i].r = lp[i].peRed >> 2;
146 pal[i].g = lp[i].peGreen >> 2;
147 pal[i].b = lp[i].peBlue >> 2;
148 }
149 }
150
151
152
153 /* get_bitmap_info:
154 * Returns a BITMAPINFO structure suited to an Allegro BITMAP.
155 * You have to free the memory allocated by this function.
156 */
get_bitmap_info(BITMAP * bitmap,PALETTE pal)157 static BITMAPINFO *get_bitmap_info(BITMAP *bitmap, PALETTE pal)
158 {
159 BITMAPINFO *bi;
160 int bpp, i;
161
162 bi = (BITMAPINFO *) _AL_MALLOC(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256);
163
164 bpp = bitmap_color_depth(bitmap);
165 if (bpp == 15)
166 bpp = 16;
167
168 ZeroMemory(&bi->bmiHeader, sizeof(BITMAPINFOHEADER));
169
170 bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
171 bi->bmiHeader.biBitCount = bpp;
172 bi->bmiHeader.biPlanes = 1;
173 bi->bmiHeader.biWidth = bitmap->w;
174 bi->bmiHeader.biHeight = -bitmap->h;
175 bi->bmiHeader.biClrUsed = 256;
176 bi->bmiHeader.biCompression = BI_RGB;
177
178 if (pal) {
179 for (i = 0; i < 256; i++) {
180 bi->bmiColors[i].rgbRed = _rgb_scale_6[pal[i].r];
181 bi->bmiColors[i].rgbGreen = _rgb_scale_6[pal[i].g];
182 bi->bmiColors[i].rgbBlue = _rgb_scale_6[pal[i].b];
183 bi->bmiColors[i].rgbReserved = 0;
184 }
185 }
186
187 return bi;
188 }
189
190
191
192 /* get_dib_from_bitmap:
193 * Creates a Windows device-independent bitmap (DIB) from an Allegro BITMAP.
194 * You have to free the memory allocated by this function.
195 */
get_dib_from_bitmap(BITMAP * bitmap)196 static BYTE *get_dib_from_bitmap(BITMAP *bitmap)
197 {
198 int bpp;
199 int x, y;
200 int pitch;
201 int col;
202 BYTE *pixels;
203 BYTE *src, *dst;
204
205 bpp = bitmap_color_depth(bitmap);
206 pitch = bitmap->w * BYTES_PER_PIXEL(bpp);
207 pitch = (pitch + 3) & ~3; /* align on dword */
208
209 pixels = (BYTE *) _AL_MALLOC_ATOMIC(bitmap->h * pitch);
210 if (!pixels)
211 return NULL;
212
213 switch (bpp) {
214
215 case 8:
216 for (y = 0; y < bitmap->h; y++) {
217 memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w);
218 }
219 break;
220
221 case 15:
222 if ((_rgb_r_shift_15 == 10) && (_rgb_g_shift_15 == 5) && (_rgb_b_shift_15 == 0)) {
223 for (y = 0; y < bitmap->h; y++)
224 memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w * 2);
225 }
226 else {
227 for (y = 0; y < bitmap->h; y++) {
228 src = bitmap->line[y];
229 dst = pixels + y * pitch;
230
231 for (x = 0; x < bitmap->w; x++) {
232 col = *(WORD *) (src);
233 *((WORD *) (dst)) = (WORD) ((getb15(col) >> 3) | ((getg15(col) >> 3) << 5) | ((getr15(col) >> 3) << 10));
234 src += 2;
235 dst += 2;
236 }
237 }
238 }
239 break;
240
241 case 16:
242 /* the format of a 16-bit DIB is 5-5-5 as above */
243 for (y = 0; y < bitmap->h; y++) {
244 src = bitmap->line[y];
245 dst = pixels + y * pitch;
246
247 for (x = 0; x < bitmap->w; x++) {
248 col = *(WORD *) (src);
249 *((WORD *) (dst)) = (WORD) ((getb16(col) >> 3) | ((getg16(col) >> 3) << 5) | ((getr16(col) >> 3) << 10));
250 src += 2;
251 dst += 2;
252 }
253 }
254 break;
255
256 case 24:
257 if ((_rgb_r_shift_24 == 16) && (_rgb_g_shift_24 == 8) && (_rgb_b_shift_24 == 0)) {
258 for (y = 0; y < bitmap->h; y++)
259 memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w * 3);
260 }
261 else {
262 for (y = 0; y < bitmap->h; y++) {
263 src = bitmap->line[y];
264 dst = pixels + y * pitch;
265
266 for (x = 0; x < bitmap->w; x++) {
267 col = *(DWORD *) (src);
268 src += 3;
269 *(dst++) = getb24(col);
270 *(dst++) = getg24(col);
271 *(dst++) = getr24(col);
272 }
273 }
274 }
275 break;
276
277 case 32:
278 if ((_rgb_r_shift_32 == 16) && (_rgb_g_shift_32 == 8) && (_rgb_b_shift_32 == 0)) {
279 for (y = 0; y < bitmap->h; y++)
280 memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w * 4);
281 }
282 else {
283 for (y = 0; y < bitmap->h; y++) {
284 src = bitmap->line[y];
285 dst = pixels + y * pitch;
286
287 for (x = 0; x < bitmap->w; x++) {
288 col = *(DWORD *) (src);
289 src += 4;
290 *(dst++) = getb32(col);
291 *(dst++) = getg32(col);
292 *(dst++) = getr32(col);
293 dst++;
294 }
295 }
296 }
297 break;
298 }
299
300 return pixels;
301 }
302
303
304
305 /* get_dib_from_hbitmap:
306 * Creates a Windows device-independent bitmap (DIB) from a Windows BITMAP.
307 * You have to free the memory allocated by this function.
308 */
get_dib_from_hbitmap(int bpp,HBITMAP hbitmap)309 static BYTE *get_dib_from_hbitmap(int bpp, HBITMAP hbitmap)
310 {
311 BITMAPINFOHEADER bi;
312 BITMAPINFO *binfo;
313 HDC hdc;
314 HPALETTE hpal, holdpal;
315 int col;
316 WINDOWS_BITMAP bm;
317 int pitch;
318 BYTE *pixels;
319 BYTE *ptr;
320 int x, y;
321
322 if (!hbitmap)
323 return NULL;
324
325 if (bpp == 15)
326 bpp = 16;
327
328 if (!GetObject(hbitmap, sizeof(bm), (LPSTR) & bm))
329 return NULL;
330
331 pitch = bm.bmWidth * BYTES_PER_PIXEL(bpp);
332 pitch = (pitch + 3) & ~3; /* align on dword */
333
334 pixels = (BYTE *) _AL_MALLOC_ATOMIC(bm.bmHeight * pitch);
335 if (!pixels)
336 return NULL;
337
338 ZeroMemory(&bi, sizeof(BITMAPINFOHEADER));
339
340 bi.biSize = sizeof(BITMAPINFOHEADER);
341 bi.biBitCount = bpp;
342 bi.biPlanes = 1;
343 bi.biWidth = bm.bmWidth;
344 bi.biHeight = -abs(bm.bmHeight);
345 bi.biClrUsed = 256;
346 bi.biCompression = BI_RGB;
347
348 binfo = _AL_MALLOC(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256);
349 binfo->bmiHeader = bi;
350
351 hdc = GetDC(NULL);
352
353 hpal = convert_palette_to_hpalette(_current_palette);
354 holdpal = SelectPalette(hdc, hpal, TRUE);
355 RealizePalette(hdc);
356
357 GetDIBits(hdc, hbitmap, 0, bm.bmHeight, pixels, binfo, DIB_RGB_COLORS);
358
359 ptr = pixels;
360
361 /* This never occurs, because if screen or memory bitmap is 8-bit,
362 * we ask Windows to convert it to truecolor. It is safer, but a little
363 * bit slower.
364 */
365
366 if (bpp == 8) {
367 for (y = 0; y < bm.bmWidth; y++) {
368 for (x = 0; x < bm.bmHeight; x++) {
369 col = *ptr;
370
371 if ((col < 10) || (col >= 246)) {
372 /* we have to remap colors from system palette */
373 *(ptr++) = makecol8(binfo->bmiColors[col].rgbRed, binfo->bmiColors[col].rgbGreen, binfo->bmiColors[col].rgbBlue);
374 }
375 else {
376 /* our palette is shifted by 10 */
377 *(ptr++) = col - 10;
378 }
379 }
380 }
381 }
382
383 _AL_FREE(binfo);
384
385 SelectPalette(hdc, holdpal, TRUE);
386 DeleteObject(hpal);
387 ReleaseDC(NULL, hdc);
388
389 return pixels;
390 }
391
392
393
394 /* get_bitmap_from_dib:
395 * Creates an Allegro BITMAP from a Windows device-independent bitmap (DIB).
396 */
get_bitmap_from_dib(int bpp,int w,int h,BYTE * pixels)397 static BITMAP *get_bitmap_from_dib(int bpp, int w, int h, BYTE *pixels)
398 {
399 int x, y;
400 int pitch;
401 int col;
402 int b, g, r;
403 BYTE *src, *dst;
404 BITMAP *bitmap;
405
406 bitmap = create_bitmap_ex(bpp, w, h);
407 pitch = bitmap->w * BYTES_PER_PIXEL(bpp);
408 pitch = (pitch + 3) & ~3; /* align on dword */
409
410 switch (bpp) {
411
412 case 8:
413 for (y = 0; y < bitmap->h; y++) {
414 memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w);
415 }
416 break;
417
418 case 15:
419 if ((_rgb_r_shift_15 == 10) && (_rgb_g_shift_15 == 5) && (_rgb_b_shift_15 == 0)) {
420 for (y = 0; y < bitmap->h; y++)
421 memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w * 2);
422 }
423 else {
424 for (y = 0; y < bitmap->h; y++) {
425 dst = bitmap->line[y];
426 src = pixels + y * pitch;
427
428 for (x = 0; x < bitmap->w; x++) {
429 col = *(WORD *) (src);
430 *((WORD *) (dst)) = makecol15(_rgb_scale_5[(col >> 10) & 0x1F], _rgb_scale_5[(col >> 5) & 0x1F], _rgb_scale_5[col & 0x1F]);
431 src += 2;
432 dst += 2;
433 }
434 }
435 }
436 break;
437
438 case 16:
439 /* the format of a 16-bit DIB is 5-5-5 as above */
440 for (y = 0; y < bitmap->h; y++) {
441 dst = bitmap->line[y];
442 src = pixels + y * pitch;
443
444 for (x = 0; x < bitmap->w; x++) {
445 col = *(WORD *) (src);
446 *((WORD *) (dst)) = makecol16(_rgb_scale_5[(col >> 10) & 0x1F], _rgb_scale_5[(col >> 5) & 0x1F], _rgb_scale_5[col & 0x1F]);
447 src += 2;
448 dst += 2;
449 }
450 }
451 break;
452
453 case 24:
454 if ((_rgb_r_shift_24 == 16) && (_rgb_g_shift_24 == 8) && (_rgb_b_shift_24 == 0)) {
455 for (y = 0; y < bitmap->h; y++)
456 memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w * 3);
457 }
458 else {
459 for (y = 0; y < bitmap->h; y++) {
460 dst = bitmap->line[y];
461 src = pixels + y * pitch;
462
463 for (x = 0; x < bitmap->w; x++) {
464 r = *(src++);
465 g = *(src++);
466 b = *(src++);
467 col = makecol24(r, g, b);
468 *((WORD *) dst) = (col & 0xFFFF);
469 dst += 2;
470 *(dst++) = (col >> 16);
471 }
472 }
473 }
474 break;
475
476 case 32:
477 if ((_rgb_r_shift_32 == 16) && (_rgb_g_shift_32 == 8) && (_rgb_b_shift_32 == 0)) {
478 for (y = 0; y < bitmap->h; y++)
479 memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w * 4);
480 }
481 else {
482 for (y = 0; y < bitmap->h; y++) {
483 dst = bitmap->line[y];
484 src = pixels + y * pitch;
485
486 for (x = 0; x < bitmap->w; x++) {
487 b = *(src++);
488 g = *(src++);
489 r = *(src++);
490 col = makecol32(r, g, b);
491 src++;
492 *((DWORD *) dst) = col;
493 dst += 4;
494 }
495 }
496 }
497 break;
498 }
499
500 return bitmap;
501 }
502
503
504
505 /* convert_bitmap_to_hbitmap:
506 * Converts an Allegro BITMAP to a Windows BITMAP.
507 */
convert_bitmap_to_hbitmap(BITMAP * bitmap)508 HBITMAP convert_bitmap_to_hbitmap(BITMAP *bitmap)
509 {
510 HDC hdc;
511 HBITMAP hbmp;
512 BITMAPINFO *bi;
513 HPALETTE hpal, holdpal;
514 BYTE *pixels;
515
516 /* get the DIB first */
517 bi = get_bitmap_info(bitmap, NULL);
518 pixels = get_dib_from_bitmap(bitmap);
519 hpal = convert_palette_to_hpalette(_current_palette);
520
521 /* now that we have the DIB, convert it to a DDB */
522 hdc = GetDC(NULL);
523 holdpal = SelectPalette(hdc, hpal, TRUE);
524 RealizePalette(hdc);
525 hbmp = CreateDIBitmap(hdc, &bi->bmiHeader, CBM_INIT, pixels, bi, DIB_RGB_COLORS);
526 ReleaseDC(NULL, hdc);
527
528 SelectPalette(hdc, holdpal, TRUE);
529 DeleteObject(hpal);
530
531 _AL_FREE(pixels);
532 _AL_FREE(bi);
533
534 return hbmp;
535 }
536
537
538
539 /* convert_hbitmap_to_bitmap:
540 * Converts a Windows BITMAP to an Allegro BITMAP.
541 */
convert_hbitmap_to_bitmap(HBITMAP bitmap)542 BITMAP *convert_hbitmap_to_bitmap(HBITMAP bitmap)
543 {
544 BYTE *pixels;
545 BITMAP *bmp;
546 WINDOWS_BITMAP bm;
547 int bpp;
548
549 if (!GetObject(bitmap, sizeof(bm), (LPSTR) & bm))
550 return NULL;
551
552 if (bm.bmBitsPixel == 8) {
553 /* ask windows to save truecolor image, then convert to our format */
554 bpp = 24;
555 }
556 else
557 bpp = bm.bmBitsPixel;
558
559 /* get the DIB first */
560 pixels = get_dib_from_hbitmap(bpp, bitmap);
561
562 /* now that we have the DIB, convert it to a BITMAP */
563 bmp = get_bitmap_from_dib(bpp, bm.bmWidth, bm.bmHeight, pixels);
564
565 _AL_FREE(pixels);
566
567 return bmp;
568 }
569
570
571
572 /* draw_to_hdc:
573 * Draws an entire Allegro BITMAP to a Windows DC. Has a syntax similar to draw_sprite().
574 */
draw_to_hdc(HDC dc,BITMAP * bitmap,int x,int y)575 void draw_to_hdc(HDC dc, BITMAP *bitmap, int x, int y)
576 {
577 stretch_blit_to_hdc(bitmap, dc, 0, 0, bitmap->w, bitmap->h, x, y, bitmap->w, bitmap->h);
578 }
579
580
581
582 /* blit_to_hdc:
583 * Blits an Allegro BITMAP to a Windows DC. Has a syntax similar to blit().
584 */
blit_to_hdc(BITMAP * bitmap,HDC dc,int src_x,int src_y,int dest_x,int dest_y,int w,int h)585 void blit_to_hdc(BITMAP *bitmap, HDC dc, int src_x, int src_y, int dest_x, int dest_y, int w, int h)
586 {
587 stretch_blit_to_hdc(bitmap, dc, src_x, src_y, w, h, dest_x, dest_y, w, h);
588 }
589
590
591
592 /* stretch_blit_to_hdc:
593 * Blits an Allegro BITMAP to a Windows DC. Has a syntax similar to stretch_blit().
594 */
stretch_blit_to_hdc(BITMAP * bitmap,HDC dc,int src_x,int src_y,int src_w,int src_h,int dest_x,int dest_y,int dest_w,int dest_h)595 void stretch_blit_to_hdc(BITMAP *bitmap, HDC dc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h)
596 {
597 AL_CONST int bottom_up_src_y = bitmap->h - src_y - src_h;
598 BYTE *pixels;
599 BITMAPINFO *bi;
600
601 bi = get_bitmap_info(bitmap, _current_palette);
602 pixels = get_dib_from_bitmap(bitmap);
603
604 /* Windows treats all source bitmaps as bottom-up when using StretchDIBits
605 * unless the source (x,y) is (0,0). To work around this buggy behavior, we
606 * can use negative heights to reverse the direction of the blits.
607 *
608 * See <http://wiki.allegro.cc/StretchDIBits> for a detailed explanation.
609 */
610 if (bottom_up_src_y == 0 && src_x == 0 && src_h != bitmap->h) {
611 StretchDIBits(dc, dest_x, dest_h+dest_y-1, dest_w, -dest_h,
612 src_x, bitmap->h-src_y+1, src_w, -src_h, pixels, bi,
613 DIB_RGB_COLORS, SRCCOPY);
614 }
615 else {
616 StretchDIBits(dc, dest_x, dest_y, dest_w, dest_h,
617 src_x, bottom_up_src_y, src_w, src_h, pixels, bi,
618 DIB_RGB_COLORS, SRCCOPY);
619 }
620
621 _AL_FREE(pixels);
622 _AL_FREE(bi);
623 }
624
625
626
627 /* blit_from_hdc:
628 * Blits from a Windows DC to an Allegro BITMAP. Has a syntax similar to blit().
629 */
blit_from_hdc(HDC dc,BITMAP * bitmap,int src_x,int src_y,int dest_x,int dest_y,int w,int h)630 void blit_from_hdc(HDC dc, BITMAP *bitmap, int src_x, int src_y, int dest_x, int dest_y, int w, int h)
631 {
632 stretch_blit_from_hdc(dc, bitmap, src_x, src_y, w, h, dest_x, dest_y, w, h);
633 }
634
635
636
637 /* stretch_blit_from_hdc:
638 * Blits from a Windows DC to an Allegro BITMAP. Has a syntax similar to stretch_blit().
639 */
stretch_blit_from_hdc(HDC dc,BITMAP * bitmap,int src_x,int src_y,int src_w,int src_h,int dest_x,int dest_y,int dest_w,int dest_h)640 void stretch_blit_from_hdc(HDC dc, BITMAP *bitmap, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h)
641 {
642 HBITMAP hbmp, holdbmp;
643 HDC hmemdc;
644 BITMAP *newbmp;
645
646 hmemdc = CreateCompatibleDC(dc);
647 hbmp = CreateCompatibleBitmap(dc, dest_w, dest_h);
648
649 holdbmp = SelectObject(hmemdc, hbmp);
650
651 StretchBlt(hmemdc, 0, 0, dest_w, dest_h, dc, src_x, src_y, src_w, src_h, SRCCOPY);
652 SelectObject(hmemdc, holdbmp);
653
654 newbmp = convert_hbitmap_to_bitmap(hbmp);
655 blit(newbmp, bitmap, 0, 0, dest_x, dest_y, dest_w, dest_h);
656
657 destroy_bitmap(newbmp);
658 DeleteObject(hbmp);
659 DeleteDC(hmemdc);
660 }
661