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