libdgl/DGLBLIT.C

189 lines
6.5 KiB
C++
Raw Normal View History

#include "dglblit.h"
#include "dglclip.h"
static boolean clip_blit(const RECT *dest_clip_region,
RECT *src_blit_region,
int *dest_x,
int *dest_y) {
2017-11-26 13:18:33 -05:00
int dest_clip_right = rect_right(dest_clip_region);
int dest_clip_bottom = rect_bottom(dest_clip_region);
int offset;
// off the left edge?
if (*dest_x < dest_clip_region->x) {
// completely off the left edge?
if ((*dest_x + src_blit_region->width - 1) < dest_clip_region->x)
2017-11-26 13:18:33 -05:00
return FALSE;
offset = src_blit_region->x - *dest_x;
src_blit_region->x += offset;
src_blit_region->width -= offset;
*dest_x = dest_clip_region->x;
}
// off the right edge?
if (*dest_x > (dest_clip_region->width - src_blit_region->width)) {
// completely off the right edge?
if (*dest_x > dest_clip_right)
return FALSE;
offset = *dest_x + src_blit_region->width - dest_clip_region->width;
src_blit_region->width -= offset;
}
// off the top edge?
if (*dest_y < dest_clip_region->y) {
// completely off the top edge?
if ((*dest_y + src_blit_region->height - 1) < dest_clip_region->y)
2017-11-26 13:18:33 -05:00
return FALSE;
offset = dest_clip_region->y - *dest_y;
src_blit_region->y += offset;
src_blit_region->height -= offset;
*dest_y = dest_clip_region->y;
}
// off the bottom edge?
if (*dest_y > (dest_clip_region->height - src_blit_region->height)) {
// completely off the bottom edge?
if (*dest_y > dest_clip_bottom)
return FALSE;
offset = *dest_y + src_blit_region->height - dest_clip_region->height;
src_blit_region->height -= offset;
}
return TRUE;
}
void surface_blit_region(const SURFACE *src,
SURFACE *dest,
int src_x,
int src_y,
int src_width,
int src_height,
int dest_x,
int dest_y) {
RECT src_region = rect(src_x, src_y, src_width, src_height);
boolean on_screen = clip_blit(&dest->clip_region, &src_region, &dest_x, &dest_y);
if (!on_screen)
return;
surface_blit_region_f(src, dest,
src_region.x, src_region.y,
src_region.width, src_region.height,
dest_x, dest_y);
}
void surface_blit_region_f(const SURFACE *src,
SURFACE *dest,
int src_x,
int src_y,
int src_width,
int src_height,
int dest_x,
int dest_y) {
const byte *psrc;
byte *pdest;
int lines;
int src_y_inc = src->width - src_width;
int dest_y_inc = dest->width - src_width;
int width_4, width_remainder;
2017-11-26 13:18:33 -05:00
psrc = (const byte*)surface_pointer(src, src_x, src_y);
pdest = (byte*)surface_pointer(dest, dest_x, dest_y);
lines = src_height;
width_4 = src_width / 4;
width_remainder = src_width & 3;
if (width_4 && !width_remainder) {
// width is a multiple of 4 (no remainder)
direct_blit_4(width_4, lines, pdest, psrc, dest_y_inc, src_y_inc);
} else if (width_4 && width_remainder) {
// width is >= 4 and there is a remainder ( <= 3 )
direct_blit_4r(width_4, lines, width_remainder, pdest, psrc, dest_y_inc, src_y_inc);
2017-11-26 13:18:33 -05:00
} else {
// width is <= 3
direct_blit_r(width_remainder, lines, pdest, psrc, dest_y_inc, src_y_inc);
2017-11-26 13:18:33 -05:00
}
}
void surface_blit_sprite_region(const SURFACE *src,
SURFACE *dest,
int src_x,
int src_y,
int src_width,
int src_height,
int dest_x,
int dest_y) {
RECT src_region = rect(src_x, src_y, src_width, src_height);
boolean on_screen = clip_blit(&dest->clip_region, &src_region, &dest_x, &dest_y);
if (!on_screen)
return;
surface_blit_sprite_region_f(src, dest,
src_region.x, src_region.y,
src_region.width, src_region.height,
dest_x, dest_y);
}
void surface_blit_sprite_region_f(const SURFACE *src,
SURFACE *dest,
int src_x,
int src_y,
int src_width,
int src_height,
int dest_x,
int dest_y) {
const byte *psrc;
byte *pdest;
2017-11-26 13:18:33 -05:00
byte pixel;
int src_y_inc, dest_y_inc;
int width, width_4, width_8, width_remainder;
2017-11-26 13:18:33 -05:00
int lines_left;
int x;
psrc = (const byte*)surface_pointer(src, src_x, src_y);
2017-11-26 13:18:33 -05:00
src_y_inc = src->width;
pdest = (byte*)surface_pointer(dest, dest_x, dest_y);
2017-11-26 13:18:33 -05:00
dest_y_inc = dest->width;
width = src_width;
lines_left = src_height;
src_y_inc -= width;
dest_y_inc -= width;
width_4 = width / 4;
width_remainder = width & 3;
if (width_4 && !width_remainder) {
if ((width_4 & 1) == 0) {
// width is actually an even multiple of 8!
direct_blit_sprite_8(width_4 / 2, lines_left, pdest, psrc, dest_y_inc, src_y_inc);
} else {
// width is a multiple of 4 (no remainder)
direct_blit_sprite_4(width_4, lines_left, pdest, psrc, dest_y_inc, src_y_inc);
2017-11-26 13:18:33 -05:00
}
} else if (width_4 && width_remainder) {
if ((width_4 & 1) == 0) {
// width is _mostly_ made up of an even multiple of 8,
// plus a small remainder
direct_blit_sprite_8r(width_4 / 2, lines_left, pdest, psrc, width_remainder, dest_y_inc, src_y_inc);
} else {
// width is >= 4 and there is a remainder
direct_blit_sprite_4r(width_4, lines_left, pdest, psrc, width_remainder, dest_y_inc, src_y_inc);
2017-11-26 13:18:33 -05:00
}
2017-11-26 13:18:33 -05:00
} else {
// width is <= 3
direct_blit_sprite_r(width_remainder, lines_left, pdest, psrc, dest_y_inc, src_y_inc);
2017-11-26 13:18:33 -05:00
}
}