1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Bitmap drawing routines.
12  *
13  *      See LICENSE.txt for copyright information.
14  */
15 
16 
17 #include "allegro5/allegro.h"
18 #include "allegro5/internal/aintern_bitmap.h"
19 #include "allegro5/internal/aintern_display.h"
20 #include "allegro5/internal/aintern_memblit.h"
21 #include "allegro5/internal/aintern_pixels.h"
22 
23 
24 static ALLEGRO_COLOR solid_white = {1, 1, 1, 1};
25 
26 
_bitmap_drawer(ALLEGRO_BITMAP * bitmap,ALLEGRO_COLOR tint,float sx,float sy,float sw,float sh,int flags)27 static void _bitmap_drawer(ALLEGRO_BITMAP *bitmap, ALLEGRO_COLOR tint,
28    float sx, float sy, float sw, float sh, int flags)
29 {
30    ALLEGRO_BITMAP *dest = al_get_target_bitmap();
31    ALLEGRO_DISPLAY *display = _al_get_bitmap_display(dest);
32    ASSERT(bitmap->parent == NULL);
33    ASSERT(!(flags & (ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL)));
34    ASSERT(bitmap != dest && bitmap != dest->parent);
35 
36    /* If destination is memory, do a memory blit */
37    if (al_get_bitmap_flags(dest) & ALLEGRO_MEMORY_BITMAP ||
38        _al_pixel_format_is_compressed(al_get_bitmap_format(dest))) {
39       _al_draw_bitmap_region_memory(bitmap, tint, sx, sy, sw, sh, 0, 0, flags);
40    }
41    else {
42       /* if source is memory or incompatible */
43       if ((al_get_bitmap_flags(bitmap) & ALLEGRO_MEMORY_BITMAP) ||
44           (!al_is_compatible_bitmap(bitmap)))
45       {
46          if (display && display->vt->draw_memory_bitmap_region) {
47             display->vt->draw_memory_bitmap_region(display, bitmap,
48                sx, sy, sw, sh, flags);
49          }
50          else {
51             _al_draw_bitmap_region_memory(bitmap, tint, sx, sy, sw, sh, 0, 0, flags);
52          }
53       }
54       else {
55          /* Compatible display bitmap, use full acceleration */
56          bitmap->vt->draw_bitmap_region(bitmap, tint, sx, sy, sw, sh, flags);
57       }
58    }
59 }
60 
61 
_draw_tinted_rotated_scaled_bitmap_region(ALLEGRO_BITMAP * bitmap,ALLEGRO_COLOR tint,float cx,float cy,float angle,float xscale,float yscale,float sx,float sy,float sw,float sh,float dx,float dy,int flags)62 static void _draw_tinted_rotated_scaled_bitmap_region(ALLEGRO_BITMAP *bitmap,
63    ALLEGRO_COLOR tint, float cx, float cy, float angle,
64    float xscale, float yscale,
65    float sx, float sy, float sw, float sh, float dx, float dy,
66    int flags)
67 {
68    ALLEGRO_TRANSFORM backup;
69    ALLEGRO_TRANSFORM t;
70    ALLEGRO_BITMAP *parent = bitmap;
71    float const orig_sw = sw;
72    float const orig_sh = sh;
73    ASSERT(bitmap);
74 
75    al_copy_transform(&backup, al_get_current_transform());
76    al_identity_transform(&t);
77 
78    if (bitmap->parent) {
79       parent = bitmap->parent;
80       sx += bitmap->xofs;
81       sy += bitmap->yofs;
82    }
83 
84    if (sx < 0) {
85       sw += sx;
86       al_translate_transform(&t, -sx, 0);
87       sx = 0;
88    }
89    if (sy < 0) {
90       sh += sy;
91       al_translate_transform(&t, 0, -sy);
92       sy = 0;
93    }
94    if (sx + sw > parent->w)
95       sw = parent->w - sx;
96    if (sy + sh > parent->h)
97       sh = parent->h - sy;
98 
99    if (flags & ALLEGRO_FLIP_HORIZONTAL) {
100       al_scale_transform(&t, -1, 1);
101       al_translate_transform(&t, orig_sw, 0);
102       flags &= ~ALLEGRO_FLIP_HORIZONTAL;
103    }
104 
105    if (flags & ALLEGRO_FLIP_VERTICAL) {
106       al_scale_transform(&t, 1, -1);
107       al_translate_transform(&t, 0, orig_sh);
108       flags &= ~ALLEGRO_FLIP_VERTICAL;
109    }
110 
111    al_translate_transform(&t, -cx, -cy);
112    al_scale_transform(&t, xscale, yscale);
113    al_rotate_transform(&t, angle);
114    al_translate_transform(&t, dx, dy);
115    al_compose_transform(&t, &backup);
116 
117    al_use_transform(&t);
118    _bitmap_drawer(parent, tint, sx, sy, sw, sh, flags);
119    al_use_transform(&backup);
120 }
121 
122 
123 /* Function: al_draw_tinted_bitmap_region
124  */
al_draw_tinted_bitmap_region(ALLEGRO_BITMAP * bitmap,ALLEGRO_COLOR tint,float sx,float sy,float sw,float sh,float dx,float dy,int flags)125 void al_draw_tinted_bitmap_region(ALLEGRO_BITMAP *bitmap,
126    ALLEGRO_COLOR tint,
127    float sx, float sy, float sw, float sh, float dx, float dy,
128    int flags)
129 {
130    _draw_tinted_rotated_scaled_bitmap_region(bitmap, tint,
131       0, 0, 0, 1, 1, sx, sy, sw, sh, dx, dy, flags);
132 }
133 
134 
135 /* Function: al_draw_tinted_bitmap
136  */
al_draw_tinted_bitmap(ALLEGRO_BITMAP * bitmap,ALLEGRO_COLOR tint,float dx,float dy,int flags)137 void al_draw_tinted_bitmap(ALLEGRO_BITMAP *bitmap, ALLEGRO_COLOR tint,
138    float dx, float dy, int flags)
139 {
140    ASSERT(bitmap);
141    al_draw_tinted_bitmap_region(bitmap, tint, 0, 0,
142       bitmap->w, bitmap->h, dx, dy, flags);
143 }
144 
145 
146 /* Function: al_draw_bitmap
147  */
al_draw_bitmap(ALLEGRO_BITMAP * bitmap,float dx,float dy,int flags)148 void al_draw_bitmap(ALLEGRO_BITMAP *bitmap, float dx, float dy, int flags)
149 {
150    al_draw_tinted_bitmap(bitmap, solid_white, dx, dy, flags);
151 }
152 
153 
154 /* Function: al_draw_bitmap_region
155  */
al_draw_bitmap_region(ALLEGRO_BITMAP * bitmap,float sx,float sy,float sw,float sh,float dx,float dy,int flags)156 void al_draw_bitmap_region(ALLEGRO_BITMAP *bitmap,
157    float sx, float sy, float sw, float sh, float dx, float dy, int flags)
158 {
159    al_draw_tinted_bitmap_region(bitmap, solid_white, sx, sy, sw, sh,
160       dx, dy, flags);
161 }
162 
163 
164 /* Function: al_draw_tinted_scaled_bitmap
165  */
al_draw_tinted_scaled_bitmap(ALLEGRO_BITMAP * bitmap,ALLEGRO_COLOR tint,float sx,float sy,float sw,float sh,float dx,float dy,float dw,float dh,int flags)166 void al_draw_tinted_scaled_bitmap(ALLEGRO_BITMAP *bitmap,
167    ALLEGRO_COLOR tint,
168    float sx, float sy, float sw, float sh,
169    float dx, float dy, float dw, float dh, int flags)
170 {
171    _draw_tinted_rotated_scaled_bitmap_region(bitmap, tint,
172       0, 0, 0,
173       dw / sw, dh / sh,
174       sx, sy, sw, sh, dx, dy, flags);
175 }
176 
177 
178 /* Function: al_draw_scaled_bitmap
179  */
al_draw_scaled_bitmap(ALLEGRO_BITMAP * bitmap,float sx,float sy,float sw,float sh,float dx,float dy,float dw,float dh,int flags)180 void al_draw_scaled_bitmap(ALLEGRO_BITMAP *bitmap,
181    float sx, float sy, float sw, float sh,
182    float dx, float dy, float dw, float dh, int flags)
183 {
184    al_draw_tinted_scaled_bitmap(bitmap, solid_white, sx, sy, sw, sh,
185       dx, dy, dw, dh, flags);
186 }
187 
188 
189 /* Function: al_draw_tinted_rotated_bitmap
190  *
191  * angle is specified in radians and moves clockwise
192  * on the screen.
193  */
al_draw_tinted_rotated_bitmap(ALLEGRO_BITMAP * bitmap,ALLEGRO_COLOR tint,float cx,float cy,float dx,float dy,float angle,int flags)194 void al_draw_tinted_rotated_bitmap(ALLEGRO_BITMAP *bitmap,
195    ALLEGRO_COLOR tint,
196    float cx, float cy, float dx, float dy, float angle, int flags)
197 {
198    al_draw_tinted_scaled_rotated_bitmap(bitmap, tint, cx, cy, dx, dy,
199       1, 1, angle, flags);
200 }
201 
202 
203 /* Function: al_draw_rotated_bitmap
204  */
al_draw_rotated_bitmap(ALLEGRO_BITMAP * bitmap,float cx,float cy,float dx,float dy,float angle,int flags)205 void al_draw_rotated_bitmap(ALLEGRO_BITMAP *bitmap,
206    float cx, float cy, float dx, float dy, float angle, int flags)
207 {
208    al_draw_tinted_rotated_bitmap(bitmap, solid_white, cx, cy, dx, dy,
209       angle, flags);
210 }
211 
212 
213 /* Function: al_draw_tinted_scaled_rotated_bitmap
214  */
al_draw_tinted_scaled_rotated_bitmap(ALLEGRO_BITMAP * bitmap,ALLEGRO_COLOR tint,float cx,float cy,float dx,float dy,float xscale,float yscale,float angle,int flags)215 void al_draw_tinted_scaled_rotated_bitmap(ALLEGRO_BITMAP *bitmap,
216    ALLEGRO_COLOR tint,
217    float cx, float cy, float dx, float dy, float xscale, float yscale,
218    float angle, int flags)
219 {
220    _draw_tinted_rotated_scaled_bitmap_region(bitmap, tint,
221       cx, cy, angle,
222       xscale, yscale,
223       0, 0, bitmap->w, bitmap->h, dx, dy, flags);
224 }
225 
226 
227 /* Function: al_draw_tinted_scaled_rotated_bitmap_region
228  */
al_draw_tinted_scaled_rotated_bitmap_region(ALLEGRO_BITMAP * bitmap,float sx,float sy,float sw,float sh,ALLEGRO_COLOR tint,float cx,float cy,float dx,float dy,float xscale,float yscale,float angle,int flags)229 void al_draw_tinted_scaled_rotated_bitmap_region(ALLEGRO_BITMAP *bitmap,
230    float sx, float sy, float sw, float sh,
231    ALLEGRO_COLOR tint,
232    float cx, float cy, float dx, float dy, float xscale, float yscale,
233    float angle, int flags)
234 {
235    _draw_tinted_rotated_scaled_bitmap_region(bitmap, tint,
236       cx, cy, angle,
237       xscale, yscale,
238       sx, sy, sw, sh, dx, dy, flags);
239 }
240 
241 
242 /* Function: al_draw_scaled_rotated_bitmap
243  */
al_draw_scaled_rotated_bitmap(ALLEGRO_BITMAP * bitmap,float cx,float cy,float dx,float dy,float xscale,float yscale,float angle,int flags)244 void al_draw_scaled_rotated_bitmap(ALLEGRO_BITMAP *bitmap,
245    float cx, float cy, float dx, float dy, float xscale, float yscale,
246    float angle, int flags)
247 {
248    al_draw_tinted_scaled_rotated_bitmap(bitmap, solid_white,
249       cx, cy, dx, dy, xscale, yscale, angle, flags);
250 }
251 
252 
253 /* vim: set ts=8 sts=3 sw=3 et: */
254