* Example program for the Allegro library.
*
* This program blitting to/from sub-bitmaps.
*
*/
#include "allegro5/allegro.h"
#include "allegro5/allegro_image.h"
#include <allegro5/allegro_primitives.h>
#include "common.c"
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
#define CLAMP(x,y,z) MAX((x), MIN((y), (z)))
typedef enum {
PLAIN_BLIT,
SCALED_BLIT
} Mode;
enum {
SRC_WIDTH = 640,
SRC_HEIGHT = 480,
SRC_X = 160,
SRC_Y = 120,
DST_WIDTH = 640,
DST_HEIGHT = 480
};
ALLEGRO_DISPLAY *src_display;
ALLEGRO_DISPLAY *dst_display;
ALLEGRO_EVENT_QUEUE *queue;
ALLEGRO_BITMAP *src_bmp;
int src_x1 = SRC_X;
int src_y1 = SRC_Y;
int src_x2 = SRC_X + 319;
int src_y2 = SRC_Y + 199;
int dst_x1 = 0;
int dst_y1 = 0;
int dst_x2 = DST_WIDTH-1;
int dst_y2 = DST_HEIGHT-1;
Mode mode = PLAIN_BLIT;
int draw_flags = 0;
int main(int argc, char **argv)
{
ALLEGRO_BITMAP *src_subbmp[2] = {NULL, NULL};
ALLEGRO_BITMAP *dst_subbmp[2] = {NULL, NULL};
ALLEGRO_EVENT event;
bool mouse_down;
bool recreate_subbitmaps;
bool redraw;
bool use_memory;
const char *image_filename = NULL;
if (!al_init()) {
abort_example("Could not init Allegro.\n");
}
al_init_primitives_addon();
al_init_image_addon();
init_platform_specific();
open_log();
al_set_new_display_flags(ALLEGRO_GENERATE_EXPOSE_EVENTS);
src_display = al_create_display(SRC_WIDTH, SRC_HEIGHT);
if (!src_display) {
abort_example("Error creating display\n");
}
al_set_window_title(src_display, "Source");
dst_display = al_create_display(DST_WIDTH, DST_HEIGHT);
if (!dst_display) {
abort_example("Error creating display\n");
}
al_set_window_title(dst_display, "Destination");
{
int i;
for (i = 1; i < argc; ++i) {
if (!image_filename)
image_filename = argv[i];
else
abort_example("Unknown argument: %s\n", argv[i]);
}
if (!image_filename) {
image_filename = "data/mysha.pcx";
}
}
src_bmp = al_load_bitmap(image_filename);
if (!src_bmp) {
abort_example("Could not load image file\n");
}
src_x2 = src_x1 + al_get_bitmap_width(src_bmp);
src_y2 = src_y1 + al_get_bitmap_height(src_bmp);
al_install_keyboard();
al_install_mouse();
queue = al_create_event_queue();
al_register_event_source(queue, al_get_keyboard_event_source());
al_register_event_source(queue, al_get_mouse_event_source());
al_register_event_source(queue, al_get_display_event_source(src_display));
al_register_event_source(queue, al_get_display_event_source(dst_display));
mouse_down = false;
recreate_subbitmaps = true;
redraw = true;
use_memory = false;
log_printf("Highlight sub-bitmap regions with left mouse button.\n");
log_printf("Press 'm' to toggle memory bitmaps.\n");
log_printf("Press '1' to perform plain blits.\n");
log_printf("Press 's' to perform scaled blits.\n");
log_printf("Press 'h' to flip horizontally.\n");
log_printf("Press 'v' to flip vertically.\n");
while (true) {
if (recreate_subbitmaps) {
int l, r, t, b, sw, sh;
al_destroy_bitmap(src_subbmp[0]);
al_destroy_bitmap(dst_subbmp[0]);
al_destroy_bitmap(src_subbmp[1]);
al_destroy_bitmap(dst_subbmp[1]);
l = MIN(src_x1, src_x2);
r = MAX(src_x1, src_x2);
t = MIN(src_y1, src_y2);
b = MAX(src_y1, src_y2);
l -= SRC_X;
t -= SRC_Y;
r -= SRC_X;
b -= SRC_Y;
src_subbmp[0] = al_create_sub_bitmap(src_bmp, l, t, r - l + 1,
b - t + 1);
sw = al_get_bitmap_width(src_subbmp[0]);
sh = al_get_bitmap_height(src_subbmp[0]);
src_subbmp[1] = al_create_sub_bitmap(src_subbmp[0], 2, 2,
sw - 4, sh - 4);
l = MIN(dst_x1, dst_x2);
r = MAX(dst_x1, dst_x2);
t = MIN(dst_y1, dst_y2);
b = MAX(dst_y1, dst_y2);
al_set_target_backbuffer(dst_display);
dst_subbmp[0] = al_create_sub_bitmap(al_get_backbuffer(dst_display),
l, t, r - l + 1, b - t + 1);
dst_subbmp[1] = al_create_sub_bitmap(dst_subbmp[0],
2, 2, r - l - 3, b - t - 3);
recreate_subbitmaps = false;
}
if (redraw && al_is_event_queue_empty(queue)) {
al_set_target_backbuffer(dst_display);
al_clear_to_color(al_map_rgb(0, 0, 0));
al_set_target_bitmap(dst_subbmp[1]);
switch (mode) {
case PLAIN_BLIT:
{
al_draw_bitmap(src_subbmp[1], 0, 0, draw_flags);
break;
}
case SCALED_BLIT:
{
al_draw_scaled_bitmap(src_subbmp[1],
0, 0, al_get_bitmap_width(src_subbmp[1]),
al_get_bitmap_height(src_subbmp[1]),
0, 0, al_get_bitmap_width(dst_subbmp[1]),
al_get_bitmap_height(dst_subbmp[1]),
draw_flags);
break;
}
}
#define SWAP_GREATER(f1, f2) { \
if (f1 > f2) { \
float tmp = f1; \
f1 = f2; \
f2 = tmp; \
} \
}
{
float x = dst_x1 + 0.5;
float y = dst_y1 + 0.5;
float x_ = dst_x2 + 0.5;
float y_ = dst_y2 + 0.5;
SWAP_GREATER(x, x_)
SWAP_GREATER(y, y_)
al_set_target_backbuffer(dst_display);
al_draw_rectangle(x, y, x_, y_,
al_map_rgb(0, 255, 255), 0);
al_draw_rectangle(x + 2, y + 2, x_ - 2, y_ - 2,
al_map_rgb(255, 255, 0), 0);
al_flip_display();
}
{
float x = src_x1 + 0.5;
float y = src_y1 + 0.5;
float x_ = src_x2 + 0.5;
float y_ = src_y2 + 0.5;
SWAP_GREATER(x, x_)
SWAP_GREATER(y, y_)
al_set_target_backbuffer(src_display);
al_clear_to_color(al_map_rgb(0, 0, 0));
al_draw_bitmap(src_bmp, SRC_X, SRC_Y, 0);
al_draw_rectangle(x, y, x_, y_,
al_map_rgb(0, 255, 255), 0);
al_draw_rectangle(x + 2, y + 2, x_ - 2, y_ - 2,
al_map_rgb(255, 255, 0), 0);
al_flip_display();
}
#undef SWAP_GREATER
redraw = false;
}
al_wait_for_event(queue, &event);
if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
break;
}
if (event.type == ALLEGRO_EVENT_KEY_CHAR) {
if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
break;
}
if (event.keyboard.unichar == '1') {
mode = PLAIN_BLIT;
redraw = true;
}
else if (event.keyboard.unichar == 's') {
mode = SCALED_BLIT;
redraw = true;
}
else if (event.keyboard.unichar == 'h') {
draw_flags ^= ALLEGRO_FLIP_HORIZONTAL;
redraw = true;
}
else if (event.keyboard.unichar == 'v') {
draw_flags ^= ALLEGRO_FLIP_VERTICAL;
redraw = true;
}
else if (event.keyboard.unichar == 'm') {
ALLEGRO_BITMAP *temp = src_bmp;
use_memory = !use_memory;
log_printf("Using a %s bitmap.\n", use_memory ? "memory" : "video");
al_set_new_bitmap_flags(use_memory ?
ALLEGRO_MEMORY_BITMAP : ALLEGRO_VIDEO_BITMAP);
src_bmp = al_clone_bitmap(temp);
al_destroy_bitmap(temp);
redraw = true;
recreate_subbitmaps = true;
}
}
else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN &&
event.mouse.button == 1) {
if (event.mouse.display == src_display) {
src_x1 = src_x2 = event.mouse.x;
src_y1 = src_y2 = event.mouse.y;
}
else if (event.mouse.display == dst_display) {
dst_x1 = dst_x2 = event.mouse.x;
dst_y1 = dst_y2 = event.mouse.y;
}
mouse_down = true;
redraw = true;
}
else if (event.type == ALLEGRO_EVENT_MOUSE_AXES) {
if (mouse_down) {
if (event.mouse.display == src_display) {
src_x2 = event.mouse.x;
src_y2 = event.mouse.y;
}
else if (event.mouse.display == dst_display) {
dst_x2 = event.mouse.x;
dst_y2 = event.mouse.y;
}
redraw = true;
}
}
else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP &&
event.mouse.button == 1) {
mouse_down = false;
recreate_subbitmaps = true;
redraw = true;
}
else if (event.type == ALLEGRO_EVENT_DISPLAY_EXPOSE) {
redraw = true;
}
}
al_destroy_event_queue(queue);
close_log(false);
return 0;
}