* /\ _ \ /\_ \ /\_ \
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
* /\____/
* \_/__/
*
* Memory bitmap drawing routines
*
*/
#define _AL_NO_BLEND_INLINE_FUNC
#include "allegro5/allegro.h"
#include "allegro5/internal/aintern_bitmap.h"
#include "allegro5/internal/aintern_blend.h"
#include "allegro5/internal/aintern_convert.h"
#include "allegro5/internal/aintern_memblit.h"
#include "allegro5/internal/aintern_transform.h"
#include "allegro5/internal/aintern_tri_soft.h"
#include <math.h>
#define MIN _ALLEGRO_MIN
#define MAX _ALLEGRO_MAX
static void _al_draw_transformed_scaled_bitmap_memory(
ALLEGRO_BITMAP *src, ALLEGRO_COLOR tint,
int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh,
int flags);
static void _al_draw_bitmap_region_memory_fast(ALLEGRO_BITMAP *bitmap,
int sx, int sy, int sw, int sh,
int dx, int dy, int flags);
* and destination bitmaps and clips them as necessary, taking sub-
* bitmaps into consideration. The wr and hr parameters are the ratio of
* source width & height to destination width & height _before_ clipping.
*
* First the left (top) coordinates are moved inward. Then the right
* (bottom) coordinates are moved inward. The changes are applied
* simultaneously to the complementary bitmap with scaling taken into
* consideration.
*
* The coordinates are modified, and the sub-bitmaps are set to the
* parent bitmaps. If nothing needs to be drawn, the macro exits the
* function.
*/
#define CLIPPER(src, sx, sy, sw, sh, dest, dx, dy, dw, dh, wr, hr, flags)\
{ \
float cl = dest->cl, cr = dest->cr_excl; \
float ct = dest->ct, cb = dest->cb_excl; \
float sx_ = 0, sy_ = 0, sw_ = 0, sh_ = 0; \
bool hflip = false, vflip = false; \
if (dw < 0) { \
hflip = true; \
dx += dw; \
dw = -dw; \
sx_ = sx; sw_ = sw; \
} \
if (dh < 0) { \
vflip = true; \
dy += dh; \
dh = -dh; \
sy_ = sy; sh_ = sh; \
} \
\
if (dest->parent) { \
dx += dest->xofs; \
dy += dest->yofs; \
\
cl += dest->xofs; \
if (cl >= dest->parent->w) { \
return; \
} \
else if (cl < 0) { \
cl = 0; \
} \
\
ct += dest->yofs; \
if (ct >= dest->parent->h) { \
return; \
} \
else if (ct < 0) { \
ct = 0; \
} \
\
cr = MIN(dest->parent->w, cr + dest->xofs); \
cb = MIN(dest->parent->h, cb + dest->yofs); \
\
dest = dest->parent; \
} \
\
if (dx < cl) { \
const int d = cl - dx; \
dx = cl; \
dw -= d; \
sx += d * wr; \
sw -= d * wr; \
} \
\
if (dx + dw > cr) { \
const int d = dx + dw - cr; \
dw -= d; \
sw -= d * wr; \
} \
\
if (dy < ct) { \
const int d = ct - dy; \
dy = ct; \
dh -= d; \
sy += d * hr; \
sh -= d * hr; \
} \
\
if (dy + dh > cb) { \
const int d = dy + dh - cb; \
dh -= d; \
sh -= d * hr; \
} \
\
if (sh <= 0 || sw <= 0) return; \
\
if (hflip) {dx += dw; dw = -dw; sx = sx_ + sw_ - sw + sx_ - sx; dx--;} \
if (vflip) {dy += dh; dh = -dh; sy = sy_ + sh_ - sh + sy_ - sy; dy--;} \
}
void _al_draw_bitmap_region_memory(ALLEGRO_BITMAP *src,
ALLEGRO_COLOR tint,
int sx, int sy, int sw, int sh,
int dx, int dy, int flags)
{
int op, src_mode, dst_mode;
int op_alpha, src_alpha, dst_alpha;
float xtrans, ytrans;
ASSERT(src->parent == NULL);
al_get_separate_bitmap_blender(&op,
&src_mode, &dst_mode, &op_alpha, &src_alpha, &dst_alpha);
if (_AL_DEST_IS_ZERO && _AL_SRC_NOT_MODIFIED_TINT_WHITE &&
_al_transform_is_translation(al_get_current_transform(), &xtrans, &ytrans))
{
_al_draw_bitmap_region_memory_fast(src, sx, sy, sw, sh,
dx + xtrans, dy + ytrans, flags);
return;
}
* general version received much more optimisation and ended up being
* faster.
*/
_al_draw_transformed_scaled_bitmap_memory(src, tint, sx, sy,
sw, sh, dx, dy, sw, sh, flags);
}
static void _al_draw_transformed_bitmap_memory(ALLEGRO_BITMAP *src,
ALLEGRO_COLOR tint,
int sx, int sy, int sw, int sh, int dw, int dh,
ALLEGRO_TRANSFORM* local_trans, int flags)
{
float xsf[4], ysf[4];
int tl = 0, tr = 1, bl = 3, br = 2;
int tmp;
ALLEGRO_VERTEX v[4];
ASSERT(_al_pixel_format_is_real(al_get_bitmap_format(src)));
if (flags & ALLEGRO_FLIP_VERTICAL) {
tl = 3;
tr = 2;
bl = 0;
br = 1;
}
else {
tl = 0;
tr = 1;
bl = 3;
br = 2;
}
if (flags & ALLEGRO_FLIP_HORIZONTAL) {
tmp = tl;
tl = tr;
tr = tmp;
tmp = bl;
bl = br;
br = tmp;
}
xsf[0] = 0;
ysf[0] = 0;
xsf[1] = dw;
ysf[1] = 0;
xsf[2] = 0;
ysf[2] = dh;
al_transform_coordinates(local_trans, &xsf[0], &ysf[0]);
al_transform_coordinates(local_trans, &xsf[1], &ysf[1]);
al_transform_coordinates(local_trans, &xsf[2], &ysf[2]);
v[tl].x = xsf[0];
v[tl].y = ysf[0];
v[tl].z = 0;
v[tl].u = sx;
v[tl].v = sy;
v[tl].color = tint;
v[tr].x = xsf[1];
v[tr].y = ysf[1];
v[tr].z = 0;
v[tr].u = sx + sw;
v[tr].v = sy;
v[tr].color = tint;
v[br].x = xsf[2] + xsf[1] - xsf[0];
v[br].y = ysf[2] + ysf[1] - ysf[0];
v[br].z = 0;
v[br].u = sx + sw;
v[br].v = sy + sh;
v[br].color = tint;
v[bl].x = xsf[2];
v[bl].y = ysf[2];
v[bl].z = 0;
v[bl].u = sx;
v[bl].v = sy + sh;
v[bl].color = tint;
al_lock_bitmap(src, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY);
_al_triangle_2d(src, &v[tl], &v[tr], &v[br]);
_al_triangle_2d(src, &v[tl], &v[br], &v[bl]);
al_unlock_bitmap(src);
}
static void _al_draw_transformed_scaled_bitmap_memory(
ALLEGRO_BITMAP *src, ALLEGRO_COLOR tint,
int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int flags)
{
ALLEGRO_TRANSFORM local_trans;
al_identity_transform(&local_trans);
al_translate_transform(&local_trans, dx, dy);
al_compose_transform(&local_trans, al_get_current_transform());
_al_draw_transformed_bitmap_memory(src, tint, sx, sy, sw, sh, dw, dh,
&local_trans, flags);
}
static void _al_draw_bitmap_region_memory_fast(ALLEGRO_BITMAP *bitmap,
int sx, int sy, int sw, int sh,
int dx, int dy, int flags)
{
ALLEGRO_LOCKED_REGION *src_region;
ALLEGRO_LOCKED_REGION *dst_region;
ALLEGRO_BITMAP *dest = al_get_target_bitmap();
int dw = sw, dh = sh;
ASSERT(_al_pixel_format_is_real(al_get_bitmap_format(bitmap)));
ASSERT(_al_pixel_format_is_real(al_get_bitmap_format(dest)));
ASSERT(bitmap->parent == NULL);
* scaling.
*/
ASSERT(flags == 0);
(void)flags;
CLIPPER(bitmap, sx, sy, sw, sh, dest, dx, dy, dw, dh, 1, 1, flags)
if (!(src_region = al_lock_bitmap_region(bitmap, sx, sy, sw, sh,
ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY))) {
return;
}
if (!(dst_region = al_lock_bitmap_region(dest, dx, dy, sw, sh,
ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY))) {
al_unlock_bitmap(bitmap);
return;
}
_al_convert_bitmap_data(
src_region->data, src_region->format, src_region->pitch,
dst_region->data, dst_region->format, dst_region->pitch,
0, 0, 0, 0, sw, sh);
al_unlock_bitmap(bitmap);
al_unlock_bitmap(dest);
}