1851 lines
34 KiB
C
1851 lines
34 KiB
C
/*
|
|
//
|
|
// Blit operation pool for the SDL.
|
|
// Copyright (C) 2005 Strangebug (S.Miura) [strangebug art hotmail.co.jp]
|
|
//
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2.1 of the License, or (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
//
|
|
// SDL_BlitPool.c : 25/Feb/2005 : created
|
|
//
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h> /* malloc/free */
|
|
#include <assert.h>
|
|
|
|
#include "SDL.h"
|
|
#include "SDL_BlitPool.h"
|
|
|
|
|
|
|
|
|
|
/* <configure> */
|
|
|
|
|
|
|
|
#ifndef NO_ALLOC_FAIL /* allocator will not fail */
|
|
# define IF_ALLOC_FAIL(statement) /* empty */
|
|
#else
|
|
# define IF_ALLOC_FAIL(statement) statement
|
|
#endif
|
|
|
|
|
|
/* view divided surface (for debug). */
|
|
#ifdef PAINT_DIVIDED
|
|
# define IF_PAINT_DIVIDED(statement) statement
|
|
#else
|
|
# define IF_PAINT_DIVIDED(statement) /* empty */
|
|
#endif
|
|
|
|
/* view separated surface (for debug). */
|
|
#ifdef PAINT_SEPARATED
|
|
# define IF_PAINT_SEPARATED(statement) statement
|
|
#else
|
|
# define IF_PAINT_SEPARATED(statement) /* empty */
|
|
#endif
|
|
|
|
|
|
#ifndef IF_DEBUG
|
|
# ifdef NDEBUG
|
|
# define IF_DEBUG(statement) /* empty */
|
|
# else
|
|
# define IF_DEBUG(statement) statement
|
|
# endif
|
|
#endif
|
|
|
|
|
|
/* </configure> */
|
|
|
|
|
|
|
|
|
|
#if IF_DEBUG(1) + 0
|
|
# include <stdio.h>
|
|
#endif
|
|
|
|
|
|
|
|
|
|
typedef struct BlitEntry_tag {
|
|
|
|
SDL_Surface *srcsurf; /* BlitSurface */
|
|
Uint32 color; /* FillColor */
|
|
BlitEntryFlag type; /* Surface/Fill: BlitEntryFlag */
|
|
BlitEntryFlag trans; /* Transparency: BlitEntryFlag */
|
|
|
|
SDL_Rect srcrect;
|
|
BlitPool_BoundingBox destbox; /* Destination position bouding box (not rect) */
|
|
|
|
SDL_Rect destrect;
|
|
struct BlitEntry_tag *next, *prev; /* Double link list */
|
|
|
|
struct {
|
|
int optimize;
|
|
} flag;
|
|
|
|
} BlitEntry;
|
|
|
|
|
|
|
|
struct BlitPool_tag { /* typedefed BlitPool in SDL_BlitPool.h */
|
|
|
|
SDL_Surface *destsurf;
|
|
BlitEntry *head, *tail; /* Double link list */
|
|
|
|
int num_entry;
|
|
|
|
allocator_func allocator;
|
|
releaser_func releaser;
|
|
|
|
struct {
|
|
int converted_to_destrect;
|
|
} flag;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void *DefaultAllocator(unsigned long nbyte);
|
|
static void DefaultReleaser(void *p);
|
|
static BlitEntry *AllocateBlitEntry(BlitPool *pool);
|
|
static void ReleaseBlitEntry(BlitPool *pool, BlitEntry *entry);
|
|
static BlitEntry *DuplicateBlitEntry(BlitPool *pool, BlitEntry *base);
|
|
|
|
|
|
static void ConvertBBoxToRect(BlitPool *pool);
|
|
static int RemoveOverlapArea(BlitPool *pool);
|
|
static int RemoveOutsideEntry(BlitPool *pool);
|
|
|
|
|
|
|
|
static void AddEntryToTail(BlitPool *pool, BlitEntry *entry);
|
|
|
|
static void RemoveEntry(BlitPool *pool, BlitEntry *entry);
|
|
static void DeleteEntry(BlitPool *pool, BlitEntry *entry);
|
|
|
|
static int StrEq(unsigned char *str0, unsigned char *str1, int n);
|
|
static void AddEntryToNext(BlitPool *pool, BlitEntry *entry, BlitEntry *new_entry);
|
|
|
|
/* unuse
|
|
static void AddEntryToPrev(BlitPool *pool, BlitEntry *entry, BlitEntry *new_entry);
|
|
static void AddEntryToHead(BlitPool *pool, BlitEntry *entry);
|
|
*/
|
|
|
|
|
|
|
|
BlitPool *BlitPool_CreatePool(Optional SDL_Surface *destsurf)
|
|
/*
|
|
// This allocate a new pool.
|
|
*/
|
|
{
|
|
BlitPool *p;
|
|
|
|
|
|
p = (BlitPool *)malloc(sizeof(*p));
|
|
if (p == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
p->head = NULL;
|
|
p->tail = NULL;
|
|
p->num_entry = 0;
|
|
p->destsurf = destsurf;
|
|
p->flag.converted_to_destrect = 0;
|
|
p->allocator = DefaultAllocator;
|
|
p->releaser = DefaultReleaser;
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *DefaultAllocator(unsigned long nbyte)
|
|
{
|
|
return malloc(nbyte);
|
|
}
|
|
|
|
|
|
|
|
|
|
static void DefaultReleaser(void *p)
|
|
{
|
|
free(p);
|
|
}
|
|
|
|
|
|
|
|
|
|
void BlitPool_DeletePool(BlitPool *pool)
|
|
{
|
|
assert(pool != NULL);
|
|
|
|
BlitPool_ReleaseEntry(pool);
|
|
|
|
free(pool);
|
|
}
|
|
|
|
|
|
|
|
|
|
void BlitPool_SetAllocator(BlitPool *pool, allocator_func allocator, releaser_func releaser)
|
|
{
|
|
assert(pool != NULL);
|
|
assert(allocator != NULL);
|
|
assert(releaser != NULL);
|
|
|
|
assert(pool->head == NULL);
|
|
assert(pool->num_entry == 0);
|
|
|
|
pool->allocator = allocator;
|
|
pool->releaser = releaser;
|
|
}
|
|
|
|
|
|
|
|
|
|
void BlitPool_ReleaseEntry(BlitPool *pool)
|
|
{
|
|
BlitEntry *p, *next;
|
|
|
|
|
|
assert(pool != NULL);
|
|
|
|
|
|
for (p = pool->head; p != NULL; p = next) {
|
|
|
|
next = p->next;
|
|
|
|
ReleaseBlitEntry(pool, p);
|
|
}
|
|
|
|
pool->head = NULL;
|
|
pool->tail = NULL;
|
|
pool->num_entry = 0;
|
|
pool->flag.converted_to_destrect = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
int BlitPool_Post(
|
|
BlitPool *pool,
|
|
BlitEntryFlag flag,
|
|
SDL_Surface *src,
|
|
Optional SDL_Rect *srcrect,
|
|
Optional SDL_Rect *destrect,
|
|
Uint32 color
|
|
)
|
|
/*
|
|
// This post the new operation to a pool.
|
|
*/
|
|
{
|
|
BlitEntry *p;
|
|
|
|
|
|
assert(pool != NULL);
|
|
|
|
p = AllocateBlitEntry(pool);
|
|
if (p == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
assert(flag < BLIT_FLAG_TERM);
|
|
|
|
p->type = flag & BLIT_TYPE_MASK;
|
|
p->srcsurf = src;
|
|
p->color = color;
|
|
p->trans = flag & BLIT_ALPHA_MASK;
|
|
p->flag.optimize = flag & BLIT_EXEC_MASK;
|
|
if (p->flag.optimize == 0) {
|
|
p->flag.optimize = BLIT_EXEC_OPTIMIZE;
|
|
}
|
|
|
|
|
|
assert(p->type == BLIT_TYPE_SURFACE || p->type == BLIT_TYPE_COLORFILL || p->type == BLIT_TYPE_EMPTY);
|
|
assert(p->trans == BLIT_ALPHA_TRANSPARENT || p->trans == BLIT_ALPHA_OPAQUE);
|
|
assert(p->flag.optimize == BLIT_EXEC_OPTIMIZE || p->flag.optimize == BLIT_EXEC_NO_OPTIMIZE);
|
|
|
|
|
|
if (p->type == BLIT_TYPE_SURFACE) {
|
|
if (srcrect == NULL) {
|
|
p->srcrect.w = src->w;
|
|
p->srcrect.h = src->h;
|
|
p->srcrect.x = p->srcrect.y = 0;
|
|
|
|
} else {
|
|
p->srcrect = *srcrect;
|
|
}
|
|
} else {
|
|
assert(src == NULL);
|
|
assert(srcrect == NULL);
|
|
|
|
if (destrect == NULL) {
|
|
p->srcrect.w = pool->destsurf->w;
|
|
p->srcrect.h = pool->destsurf->h;
|
|
} else {
|
|
p->srcrect.w = destrect->w;
|
|
p->srcrect.h = destrect->h;
|
|
}
|
|
}
|
|
|
|
if (p->srcrect.w == 0 || p->srcrect.h == 0) {
|
|
ReleaseBlitEntry(pool, p);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
// Not use destrect in BlitPool.
|
|
// It will be update rect after.
|
|
*/
|
|
if (destrect == NULL) {
|
|
p->destbox.x0 = p->destbox.y0 = 0;
|
|
|
|
} else {
|
|
p->destbox.x0 = destrect->x;
|
|
p->destbox.y0 = destrect->y;
|
|
|
|
destrect->w = p->srcrect.w;
|
|
destrect->h = p->srcrect.h;
|
|
}
|
|
|
|
p->destbox.x1 = p->destbox.x0 + p->srcrect.w;
|
|
p->destbox.y1 = p->destbox.y0 + p->srcrect.h;
|
|
|
|
AddEntryToTail(pool, p);
|
|
pool->flag.converted_to_destrect = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int BlitPool_PostByDescription(
|
|
BlitPool *pool,
|
|
Optional SDL_Surface *surf,
|
|
unsigned char *area_description_str
|
|
)
|
|
/*
|
|
// area_description_str like: "pos=(45, 12):O:(0,0)-(12,12):(45,23)-(62, 24):pos=(0,0):T:(12,98)-(1,65)"
|
|
// pos=(x,y) : destination position.
|
|
// (x0,y0)-(x1,y1) : source surface rectangle.
|
|
// O/T : T=Transparens(default), O=Opaque.
|
|
// col=(r, g, b, a) : colorfill mode. it's format be surf->format.
|
|
//
|
|
// * Don't forget delimiter ':'.
|
|
*/
|
|
{
|
|
unsigned char *p;
|
|
SDL_Rect dest_rect, src_rect, blit_dest_rect;
|
|
BlitEntryFlag blit_type;
|
|
int flag_fillmode;
|
|
int post_result;
|
|
Uint32 color;
|
|
|
|
|
|
#define SkipSpace(p) while (*p == ' ' | *p == '\t' | *p == '\n') { p += 1; }
|
|
#define SkipDigit(p) while (*p == '0' | *p == '1' | *p == '2' | *p == '3' | *p == '4' | \
|
|
*p == '5' | *p == '6' | *p == '7' | *p == '8' | *p == '9') { p += 1; }
|
|
#define CheckAndSkip_OrDead(ch) if (*p != ch) { return 1; } else { p += 1; SkipSpace(p); }
|
|
|
|
|
|
assert(pool != NULL);
|
|
assert(surf != NULL);
|
|
assert(area_description_str != NULL);
|
|
|
|
p = area_description_str;
|
|
dest_rect.x = dest_rect.y = 0;
|
|
blit_type = BLIT_ALPHA_TRANSPARENT;
|
|
flag_fillmode = 0;
|
|
color = 0;
|
|
|
|
while (*p != '\0') {
|
|
|
|
if (*p == ':') {
|
|
p += 1;
|
|
}
|
|
|
|
SkipSpace(p);
|
|
if (StrEq(p, "pos", 3) == 0) {
|
|
p += 3;
|
|
assert(*(p-1) == 's');
|
|
SkipSpace(p);
|
|
|
|
CheckAndSkip_OrDead('=');
|
|
CheckAndSkip_OrDead('(');
|
|
dest_rect.x = atoi(p);
|
|
SkipDigit(p);
|
|
SkipSpace(p);
|
|
CheckAndSkip_OrDead(',');
|
|
|
|
dest_rect.y = atoi(p);
|
|
SkipDigit(p);
|
|
SkipSpace(p);
|
|
CheckAndSkip_OrDead(')');
|
|
continue;
|
|
}
|
|
|
|
if (StrEq(p, "col", 3) == 0) {
|
|
Uint8 r, g, b, a;
|
|
|
|
p += 3;
|
|
assert(*(p-1) == 'l');
|
|
SkipSpace(p);
|
|
|
|
#define GetCol(elem) \
|
|
elem = atoi(p);\
|
|
SkipDigit(p);\
|
|
SkipSpace(p);
|
|
|
|
CheckAndSkip_OrDead('=');
|
|
CheckAndSkip_OrDead('(');
|
|
GetCol(r);
|
|
CheckAndSkip_OrDead(',');
|
|
GetCol(g);
|
|
CheckAndSkip_OrDead(',');
|
|
GetCol(b);
|
|
CheckAndSkip_OrDead(',');
|
|
GetCol(a);
|
|
CheckAndSkip_OrDead(')');
|
|
|
|
color = SDL_MapRGBA(surf->format, r, g, b, a);
|
|
|
|
#undef GetCol
|
|
|
|
flag_fillmode = 1;
|
|
blit_type = BLIT_ALPHA_OPAQUE;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (flag_fillmode == 0 && (*p == 'T' || *p == 'O')) {
|
|
if (*p == 'T') {
|
|
blit_type = BLIT_ALPHA_TRANSPARENT;
|
|
} else if (*p == 'O') {
|
|
blit_type = BLIT_ALPHA_OPAQUE;
|
|
} else {
|
|
assert(0);
|
|
}
|
|
p += 1;
|
|
SkipSpace(p);
|
|
continue;
|
|
}
|
|
|
|
CheckAndSkip_OrDead('(');
|
|
src_rect.x = atoi(p);
|
|
SkipDigit(p);
|
|
SkipSpace(p);
|
|
|
|
CheckAndSkip_OrDead(',');
|
|
src_rect.y = atoi(p);
|
|
SkipDigit(p);
|
|
SkipSpace(p);
|
|
|
|
CheckAndSkip_OrDead(')');
|
|
CheckAndSkip_OrDead('-');
|
|
CheckAndSkip_OrDead('(');
|
|
src_rect.w = atoi(p);
|
|
SkipDigit(p);
|
|
SkipSpace(p);
|
|
|
|
CheckAndSkip_OrDead(',');
|
|
src_rect.h = atoi(p);
|
|
SkipDigit(p);
|
|
SkipSpace(p);
|
|
CheckAndSkip_OrDead(')');
|
|
|
|
assert((Sint32)src_rect.x < (Sint32)src_rect.w);
|
|
assert((Sint32)src_rect.y < (Sint32)src_rect.h);
|
|
|
|
|
|
src_rect.w -= src_rect.x;
|
|
src_rect.h -= src_rect.y;
|
|
blit_dest_rect.x = src_rect.x + dest_rect.x;
|
|
blit_dest_rect.y = src_rect.y + dest_rect.y;
|
|
|
|
if (flag_fillmode) {
|
|
blit_dest_rect.w = src_rect.w;
|
|
blit_dest_rect.h = src_rect.h;
|
|
post_result = BlitPool_PostFill(pool, &blit_dest_rect, color, blit_type);
|
|
} else {
|
|
post_result = BlitPool_PostSurface(pool, surf, &src_rect, &blit_dest_rect, blit_type);
|
|
}
|
|
|
|
if (post_result) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
#undef SkipSpace
|
|
#undef SkipDigit
|
|
#undef CheckAndSkip_OrDead
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
void BlitPool_PostPool(
|
|
BlitPool *dest_pool,
|
|
BlitPool *src_pool,
|
|
Optional SDL_Rect *offset
|
|
)
|
|
/*
|
|
// Commit(add) the entries.
|
|
*/
|
|
{
|
|
BlitEntry *new_entry, *src_entry;
|
|
SDL_Rect zerorect;
|
|
|
|
assert(dest_pool != NULL);
|
|
assert(src_pool != NULL);
|
|
|
|
if (offset == NULL) {
|
|
zerorect.x = zerorect.y = 0;
|
|
offset = &zerorect;
|
|
}
|
|
|
|
for (src_entry = src_pool->head; src_entry != NULL; src_entry = src_entry->next) {
|
|
|
|
new_entry = DuplicateBlitEntry(dest_pool, src_entry);
|
|
|
|
IF_ALLOC_FAIL( if (new_entry == NULL) return );
|
|
|
|
new_entry->destbox.x0 += offset->x;
|
|
new_entry->destbox.y0 += offset->y;
|
|
new_entry->destbox.x1 += offset->x;
|
|
new_entry->destbox.y1 += offset->y;
|
|
|
|
AddEntryToTail(dest_pool, new_entry);
|
|
dest_pool->flag.converted_to_destrect = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void BlitPool_Execute(BlitPool *pool)
|
|
/*
|
|
// This execute the blit_surface and the color_fill.
|
|
*/
|
|
{
|
|
BlitEntry *p;
|
|
|
|
|
|
assert(pool != NULL);
|
|
assert(pool->destsurf != NULL);
|
|
|
|
if (pool->num_entry == 0) {
|
|
return;
|
|
}
|
|
|
|
|
|
ConvertBBoxToRect(pool);
|
|
|
|
|
|
for (p = pool->head; p != NULL; p = p->next) {
|
|
|
|
/*
|
|
// if (type == BLIT_TYPE_SURFACE) {
|
|
// p->destrect: destination position.
|
|
// p->srcrect: source position and rectangle size.
|
|
// } else {
|
|
// p->destrect: destination position and rectangle size.
|
|
// }
|
|
*/
|
|
|
|
switch (p->type) {
|
|
|
|
case BLIT_TYPE_SURFACE:
|
|
SDL_BlitSurface(
|
|
p->srcsurf, &p->srcrect,
|
|
pool->destsurf, &p->destrect
|
|
);
|
|
break;
|
|
|
|
case BLIT_TYPE_COLORFILL:
|
|
SDL_FillRect(pool->destsurf, &p->destrect, p->color);
|
|
break;
|
|
|
|
case BLIT_TYPE_EMPTY:
|
|
/*
|
|
// Empty operation.
|
|
*/
|
|
break;
|
|
|
|
IF_DEBUG(default: assert(0));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void BlitPool_Optimize(BlitPool *pool, BlitOptimizeFlag flag)
|
|
/*
|
|
// Apply optimizations.
|
|
*/
|
|
{
|
|
|
|
if (flag & BLIT_OPT_REMOVEOUTSIDE) {
|
|
pool->flag.converted_to_destrect = 0;
|
|
RemoveOutsideEntry(pool);
|
|
}
|
|
|
|
if (flag & BLIT_OPT_REMOVEOVERLAP) {
|
|
pool->flag.converted_to_destrect = 0;
|
|
if (RemoveOverlapArea(pool)) {
|
|
/* allocation failed */;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ConvertBBoxToRect(BlitPool *pool)
|
|
{
|
|
BlitEntry *p;
|
|
|
|
|
|
assert(pool != NULL);
|
|
|
|
if (pool->flag.converted_to_destrect) {
|
|
return;
|
|
}
|
|
|
|
for (p = pool->head; p != NULL; p = p->next) {
|
|
|
|
BlitPoolUtil_BBoxToRect(&p->destbox, &p->destrect);
|
|
|
|
if (p->type == BLIT_TYPE_SURFACE) {
|
|
p->srcrect.w = p->destbox.x1 - p->destrect.x;
|
|
p->srcrect.h = p->destbox.y1 - p->destrect.y;
|
|
}
|
|
}
|
|
|
|
pool->flag.converted_to_destrect = 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
int BlitPool_GetRectCount(BlitPool *pool)
|
|
{
|
|
return pool->num_entry;
|
|
}
|
|
|
|
|
|
|
|
|
|
int BlitPool_GetUpdateRects(BlitPool *pool, SDL_Rect *rectbuf, int size, void **update_rects_obj)
|
|
/*
|
|
// This gets the rects of update, to the rectbuf.
|
|
// for SDL_UpdateRects.
|
|
// return number is count of the updated rects, < size
|
|
// example:
|
|
//
|
|
// BlitPool_Execute(pool);
|
|
// {
|
|
// int numrect;
|
|
// SDL_Rect rectbuf[10];
|
|
// void *p;
|
|
//
|
|
// p = BlitPool_GetUpdateRectsObj(pool);
|
|
// while ((numrect = BlitPool_GetUpdateRects(pool, rectbuf, sizeof(rectbuf)/sizeof(rectbuf[0]), &p)) > 0) {
|
|
// SDL_UpdateRects(screen, numrect, rectbuf);
|
|
// }
|
|
// }
|
|
*/
|
|
{
|
|
int n;
|
|
BlitEntry *p;
|
|
|
|
|
|
assert(pool != NULL);
|
|
assert(rectbuf != NULL);
|
|
assert(size > 0);
|
|
|
|
if (*update_rects_obj == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
if (pool->flag.converted_to_destrect) {
|
|
;
|
|
} else {
|
|
ConvertBBoxToRect(pool);
|
|
}
|
|
|
|
n = 0;
|
|
p = (BlitEntry *) *update_rects_obj;
|
|
|
|
while (p != NULL && n < size) {
|
|
rectbuf[n++] = p->destrect;
|
|
p = p->next;
|
|
}
|
|
|
|
*update_rects_obj = (p == NULL) ? NULL : p->prev;
|
|
|
|
return n;
|
|
}
|
|
|
|
|
|
|
|
|
|
void *BlitPool_GetUpdateRectsObj(BlitPool *pool)
|
|
{
|
|
assert(pool != NULL);
|
|
|
|
return (void *)pool->head;
|
|
}
|
|
|
|
|
|
|
|
|
|
Uint32 BlitPool_GetArea(BlitPool *pool)
|
|
{
|
|
BlitEntry *p;
|
|
Uint32 area;
|
|
|
|
|
|
assert(pool != NULL);
|
|
|
|
ConvertBBoxToRect(pool);
|
|
|
|
area = 0;
|
|
for (p = pool->head; p != NULL; p = p->next) {
|
|
|
|
if (p->type == BLIT_TYPE_SURFACE) {
|
|
area += p->srcrect.w * p->srcrect.h;
|
|
|
|
} else if (p->type == BLIT_TYPE_COLORFILL) {
|
|
area += p->destrect.w * p->destrect.h;
|
|
|
|
} else {
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
return area;
|
|
}
|
|
|
|
|
|
|
|
|
|
static int RemoveOverlapArea(BlitPool *pool)
|
|
/*
|
|
// This apply remove the overlapped rect and divide the back surface.
|
|
// If return not 0 then fail operation.
|
|
*/
|
|
{
|
|
Uint8 code;
|
|
SDL_Rect srcrect;
|
|
BlitPool_BoundingBox destbox;
|
|
BlitEntry *new_entry;
|
|
BlitEntry *front, *back, *back_next;
|
|
int is_overlapped;
|
|
int divided;
|
|
|
|
|
|
assert(pool != NULL);
|
|
|
|
|
|
for (back = pool->head; back != NULL; back = back_next) {
|
|
|
|
back_next = back->next;
|
|
|
|
/* skip no optimization entry */
|
|
if (back->flag.optimize == BLIT_EXEC_NO_OPTIMIZE) {
|
|
continue;
|
|
}
|
|
|
|
for (front = back->next; front != NULL; front = front->next) {
|
|
|
|
assert(back != front);
|
|
|
|
if (front->flag.optimize == BLIT_EXEC_NO_OPTIMIZE | /* skip no optimization entry */
|
|
front->trans == BLIT_ALPHA_TRANSPARENT /* skip transparent surface */
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
assert((back->destbox.x1 - back->destbox.x0) > 0);
|
|
assert((back->destbox.y1 - back->destbox.y0) > 0);
|
|
assert((front->destbox.x1 - front->destbox.x0) > 0);
|
|
assert((front->destbox.y1 - front->destbox.y0) > 0);
|
|
|
|
is_overlapped = BlitPoolUtil_GetOverlapCode(
|
|
&code,
|
|
&front->destbox,
|
|
&back->destbox
|
|
);
|
|
|
|
if (is_overlapped == 0) {
|
|
continue;
|
|
}
|
|
|
|
assert(code <= 0x0f);
|
|
|
|
|
|
/*
|
|
// Divide the back rects.
|
|
*/
|
|
|
|
divided = 0;
|
|
|
|
|
|
#define AddNewEntryBegin() \
|
|
srcrect.x = back->srcrect.x; \
|
|
srcrect.y = back->srcrect.y; \
|
|
destbox = back->destbox;
|
|
|
|
#define AddNewEntryEnd() \
|
|
assert(destbox.x1 >= destbox.x0); \
|
|
assert(destbox.y1 >= destbox.y0); \
|
|
if ((destbox.x1 - destbox.x0) <= 0 | \
|
|
(destbox.y1 - destbox.y0) <= 0 \
|
|
) { \
|
|
; \
|
|
} else { \
|
|
new_entry = DuplicateBlitEntry(pool, back); \
|
|
IF_ALLOC_FAIL(if (new_entry == NULL) return 1);\
|
|
AddEntryToNext(pool, back, new_entry); \
|
|
new_entry->srcrect.x = srcrect.x; \
|
|
new_entry->srcrect.y = srcrect.y; \
|
|
new_entry->destbox = destbox; \
|
|
IF_PAINT_DIVIDED(new_entry->type = BLIT_TYPE_COLORFILL);\
|
|
IF_PAINT_DIVIDED(new_entry->color = (Uint32)new_entry*80);\
|
|
assert(back->next == new_entry); \
|
|
back_next = new_entry; \
|
|
divided += 1; \
|
|
}
|
|
|
|
switch (code) {
|
|
case 0:
|
|
/*
|
|
// 00 00
|
|
//
|
|
// *----*
|
|
// | o----o
|
|
// *--|ffff|
|
|
// o----o
|
|
*/
|
|
|
|
|
|
/*
|
|
// Perfect overlapped?
|
|
// (back->destbox.x1 - back->destbox.x0) - (back->destbox.x1 - front->destbox.x0) == 0
|
|
// back width - overlapped rect width == 0
|
|
//
|
|
// = back->destbox.x1 - back->destbox.x0 - back->destbox.x1 + front->destbox.x0
|
|
// = front->destbox.x0 - back->destbox.x0
|
|
*/
|
|
if ((front->destbox.x0 - back->destbox.x0) | /* == || */
|
|
(front->destbox.y0 - back->destbox.y0)
|
|
) {
|
|
;
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
/* Top - Left */
|
|
AddNewEntryBegin();
|
|
destbox.y1 = front->destbox.y0;
|
|
AddNewEntryEnd();
|
|
|
|
/* Left */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y0 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y0;
|
|
destbox.x1 = front->destbox.x0;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 1:
|
|
/*
|
|
// 00 01
|
|
//
|
|
// *----------*
|
|
// | o----o |
|
|
// *--|ffff|--*
|
|
// o----o
|
|
*/
|
|
|
|
/* WholeTop */
|
|
AddNewEntryBegin();
|
|
destbox.y1 = front->destbox.y0;
|
|
AddNewEntryEnd();
|
|
|
|
/* Left */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y0 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y0;
|
|
destbox.x1 = front->destbox.x0;
|
|
AddNewEntryEnd();
|
|
|
|
/* Right */
|
|
AddNewEntryBegin();
|
|
srcrect.x += front->destbox.x1 - back->destbox.x0;
|
|
srcrect.y += front->destbox.y0 - back->destbox.y0;
|
|
destbox.x0 = front->destbox.x1;
|
|
destbox.y0 = front->destbox.y0;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 2:
|
|
/*
|
|
// 00 10
|
|
//
|
|
// *----*
|
|
// | |
|
|
// o----------o
|
|
// | ffff |
|
|
// o----------o
|
|
*/
|
|
|
|
/* Top */
|
|
AddNewEntryBegin();
|
|
destbox.y1 = front->destbox.y0;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 3:
|
|
/*
|
|
// 00 11
|
|
//
|
|
// *-----*
|
|
// | |
|
|
// o----o |
|
|
// |ffff|---*
|
|
// o----o
|
|
*/
|
|
|
|
/* Top - Right */
|
|
AddNewEntryBegin();
|
|
destbox.y1 = front->destbox.y0;
|
|
AddNewEntryEnd();
|
|
|
|
/* Right */
|
|
AddNewEntryBegin();
|
|
srcrect.x += front->destbox.x1 - back->destbox.x0;
|
|
srcrect.y += front->destbox.y0 - back->destbox.y0;
|
|
destbox.x0 = front->destbox.x1;
|
|
destbox.y0 = front->destbox.y0;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 4:
|
|
/*
|
|
// 00 11
|
|
//
|
|
// *----*
|
|
// | o---o
|
|
// | |fff|
|
|
// | o---o
|
|
// *----*
|
|
*/
|
|
|
|
|
|
/* Top - Left */
|
|
AddNewEntryBegin();
|
|
destbox.y1 = front->destbox.y0;
|
|
AddNewEntryEnd();
|
|
|
|
/* Bottom - Left */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y1 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
|
|
|
|
/* Left */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y0 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y0;
|
|
destbox.x1 = front->destbox.x0;
|
|
destbox.y1 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 5:
|
|
/*
|
|
// 01 01
|
|
//
|
|
// *-------*
|
|
// | o--o |
|
|
// | |ff| |
|
|
// | o--o |
|
|
// *-------*
|
|
*/
|
|
|
|
/* WholeTop */
|
|
AddNewEntryBegin();
|
|
destbox.y1 = front->destbox.y0;
|
|
AddNewEntryEnd();
|
|
|
|
/* WholeBottom */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y1 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
|
|
/* Left */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y0 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y0;
|
|
destbox.x1 = front->destbox.x0;
|
|
destbox.y1 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
|
|
/* Right */
|
|
AddNewEntryBegin();
|
|
srcrect.x += front->destbox.x1 - back->destbox.x0;
|
|
srcrect.y += front->destbox.y0 - back->destbox.y0;
|
|
destbox.x0 = front->destbox.x1;
|
|
destbox.y0 = front->destbox.y0;
|
|
destbox.y1 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 6:
|
|
/*
|
|
// 01 10
|
|
//
|
|
// *-*
|
|
// o-----o
|
|
// o-----o
|
|
// *-*
|
|
*/
|
|
|
|
/* Top */
|
|
AddNewEntryBegin();
|
|
destbox.y1 = front->destbox.y0;
|
|
AddNewEntryEnd();
|
|
|
|
/* Bottom */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y1 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 7:
|
|
/*
|
|
// 01 11
|
|
//
|
|
// *---*
|
|
// o---o |
|
|
// |fff| |
|
|
// o---o |
|
|
// *---*
|
|
*/
|
|
|
|
/* Top - Right */
|
|
AddNewEntryBegin();
|
|
destbox.y1 = front->destbox.y0;
|
|
AddNewEntryEnd();
|
|
|
|
/* Bottom - Right */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y1 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
|
|
/* Right */
|
|
AddNewEntryBegin();
|
|
srcrect.x += front->destbox.x1 - back->destbox.x0;
|
|
srcrect.y += front->destbox.y0 - back->destbox.y0;
|
|
destbox.x0 = front->destbox.x1;
|
|
destbox.y0 = front->destbox.y0;
|
|
destbox.y1 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 8:
|
|
/*
|
|
// 10 00
|
|
//
|
|
// o---o
|
|
// *-| |
|
|
// | |fff|
|
|
// *-| |
|
|
// o---o
|
|
*/
|
|
|
|
/* Left */
|
|
AddNewEntryBegin();
|
|
destbox.x1 = front->destbox.x0;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 9: /* 10 01 */
|
|
/*
|
|
// 10 01
|
|
//
|
|
// o---o
|
|
// *-| |-*
|
|
// | |fff| |
|
|
// *-| |-*
|
|
// o---o
|
|
*/
|
|
|
|
/* Left */
|
|
AddNewEntryBegin();
|
|
destbox.x1 = front->destbox.x0;
|
|
AddNewEntryEnd();
|
|
|
|
/* Right */
|
|
AddNewEntryBegin();
|
|
srcrect.x += front->destbox.x1 - back->destbox.x0;
|
|
destbox.x0 = front->destbox.x1;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 10: /* 10 10 */
|
|
/*
|
|
// 10 10
|
|
// Perfect Overlap.
|
|
*/
|
|
break;
|
|
|
|
case 11: /* 10 11 */
|
|
/*
|
|
// 10 11
|
|
//
|
|
// o---o
|
|
// | |-*
|
|
// |fff| |
|
|
// | |-*
|
|
// o---o
|
|
*/
|
|
|
|
/* Right */
|
|
AddNewEntryBegin();
|
|
srcrect.x += front->destbox.x1 - back->destbox.x0;
|
|
destbox.x0 = front->destbox.x1;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 12:
|
|
/*
|
|
// 11 00
|
|
//
|
|
// o-----o
|
|
// |ffff |
|
|
// *--| ffff|
|
|
// | o-----o
|
|
// *----*
|
|
*/
|
|
|
|
/* Bottom - Left */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y1 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
|
|
/* Left */
|
|
AddNewEntryBegin();
|
|
destbox.x1 = front->destbox.x0;
|
|
destbox.y1 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 13:
|
|
/*
|
|
// 11 01
|
|
//
|
|
// o-----o
|
|
// |ffff |
|
|
// *--| ffff|--*
|
|
// | o-----o |
|
|
// *-----------*
|
|
*/
|
|
|
|
/* WholeBottom */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y1 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
|
|
/* Left */
|
|
AddNewEntryBegin();
|
|
destbox.x1 = front->destbox.x0;
|
|
destbox.y1 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
|
|
/* Right */
|
|
AddNewEntryBegin();
|
|
srcrect.x += front->destbox.x1 - back->destbox.x0;
|
|
destbox.x0 = front->destbox.x1;
|
|
destbox.y1 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 14:
|
|
/*
|
|
// 11 10
|
|
//
|
|
// o----------o
|
|
// | ffff |
|
|
// o----------o
|
|
// *----*
|
|
*/
|
|
|
|
/* Bottom */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y1 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
case 15:
|
|
/*
|
|
// 11 11
|
|
//
|
|
// o----o
|
|
// |ffff|--*
|
|
// o----o |
|
|
// *----*
|
|
*/
|
|
|
|
/* Bottom - Right */
|
|
AddNewEntryBegin();
|
|
srcrect.y += front->destbox.y1 - back->destbox.y0;
|
|
destbox.y0 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
|
|
/* Right */
|
|
AddNewEntryBegin();
|
|
srcrect.x += front->destbox.x1 - back->destbox.x0;
|
|
destbox.x0 = front->destbox.x1;
|
|
destbox.y1 = front->destbox.y1;
|
|
AddNewEntryEnd();
|
|
break;
|
|
|
|
IF_DEBUG(default: assert(0 && "FATAL: in RemoveOverlapArea"));
|
|
}
|
|
|
|
assert(back != front);
|
|
|
|
DeleteEntry(pool, back);
|
|
|
|
if (divided) {
|
|
back = back_next;
|
|
back_next = back->next;
|
|
|
|
} else {
|
|
break; /* only deleted */
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
#undef AddNewEntryBegin
|
|
#undef AddNewEntryEnd
|
|
}
|
|
|
|
|
|
|
|
|
|
static int RemoveOutsideEntry(BlitPool *pool)
|
|
/*
|
|
// Remove outside of the destination surface.
|
|
// return removed entry count.
|
|
*/
|
|
{
|
|
BlitEntry *p, *next;
|
|
Uint8 code;
|
|
BlitPool_BoundingBox destsurfbox;
|
|
int is_overlapped;
|
|
int removed_count;
|
|
|
|
|
|
assert(pool != NULL);
|
|
|
|
if (pool->destsurf == NULL) {
|
|
/* impossible! */
|
|
return 0;
|
|
}
|
|
|
|
if (pool->head == NULL || pool->num_entry == 0) {
|
|
return 0;
|
|
}
|
|
|
|
destsurfbox.x0 = 0;
|
|
destsurfbox.y0 = 0;
|
|
destsurfbox.x1 = pool->destsurf->w;
|
|
destsurfbox.y1 = pool->destsurf->h;
|
|
|
|
removed_count = 0;
|
|
|
|
for (p = pool->head; p != NULL; p = next) {
|
|
|
|
next = p->next;
|
|
|
|
is_overlapped = BlitPoolUtil_GetOverlapCode(
|
|
&code,
|
|
&p->destbox, /* destination bouding box */
|
|
&destsurfbox /* destination surface box */
|
|
);
|
|
|
|
if (is_overlapped == 0) {
|
|
/*
|
|
// Outside of the destination surface.
|
|
*/
|
|
|
|
/*
|
|
// future: clipping p->destbox.
|
|
*/
|
|
|
|
removed_count += 1;
|
|
DeleteEntry(pool, p);
|
|
}
|
|
}
|
|
|
|
return removed_count;
|
|
}
|
|
|
|
|
|
|
|
|
|
int BlitPoolUtil_GetOverlapCode(
|
|
Uint8 *out_code, /* Must not NULL */
|
|
BlitPool_BoundingBox *f, /* front */
|
|
BlitPool_BoundingBox *b /* back */
|
|
)
|
|
/*
|
|
// This check the overlapped rect.
|
|
//
|
|
// if (overlapped(front_rect, back_rect)) {
|
|
// *out_code = code;
|
|
// return 1;
|
|
// } else {
|
|
// return 0;
|
|
// }
|
|
*/
|
|
{
|
|
Uint8 code; /* use low nibble */
|
|
|
|
enum {
|
|
Overlapped = 1,
|
|
NotOverlapped = 0
|
|
};
|
|
|
|
|
|
assert(out_code != NULL);
|
|
assert(f != NULL);
|
|
assert(b != NULL);
|
|
|
|
|
|
assert((f->x1 - f->x0) > 0);
|
|
assert((f->y1 - f->y0) > 0);
|
|
assert((b->x1 - b->x0) > 0);
|
|
assert((b->y1 - b->y0) > 0);
|
|
|
|
|
|
/*
|
|
// It's overlapped?
|
|
// If overlapped then make the overlap rect,
|
|
// by just switch jump.
|
|
*/
|
|
|
|
|
|
/*
|
|
// Get MSB of 32bit signed integer.
|
|
*/
|
|
#define GetMSB(val) ((Uint32)(val) & 0x80000000)
|
|
|
|
|
|
/*
|
|
// Y X
|
|
// code: ... b3 b2 b1 b0 bn == bit n
|
|
// b1,b0 = subtract back from front of X axis
|
|
// b3,b2 = of Y axis
|
|
*/
|
|
code = (GetMSB(f->x0 - b->x0) >> (2 + 28)) | /* b1 */
|
|
(GetMSB(f->x1 - b->x1) >> (3 + 28)) | /* b0 */
|
|
(GetMSB(f->y0 - b->y0) >> (0 + 28)) | /* b3 */
|
|
(GetMSB(f->y1 - b->y1) >> (1 + 28)); /* b2 */
|
|
|
|
|
|
assert(code <= 0x0f);
|
|
|
|
|
|
/*
|
|
// pattern: 00
|
|
// f: *----* *----*
|
|
// b: *----* or *----*
|
|
*/
|
|
#define OutsideCheck00(axis) ((b->axis##1 - f->axis##0) <= 0)
|
|
|
|
/*
|
|
// pattern: 01
|
|
// f: *--*
|
|
// b: *-------*
|
|
*/
|
|
#define OutsideCheck01(axis) ( IF_DEBUG((f->axis##1 - f->axis##0) <= 0) + 0 )
|
|
|
|
/*
|
|
// pattern: 11
|
|
// f: *----* *----*
|
|
// b: *----* or *----*
|
|
*/
|
|
#define OutsideCheck11(axis) ((f->axis##1 - b->axis##0) <= 0)
|
|
|
|
/*
|
|
// pattern: 10
|
|
// f: *-------*
|
|
// b: *---*
|
|
*/
|
|
#define OutsideCheck10(axis) ( IF_DEBUG((b->axis##1 - b->axis##0) <= 0) + 0 )
|
|
|
|
|
|
|
|
#define CaseOfCode_Overlap(codeval, codesymY, codesymX) \
|
|
case codeval: \
|
|
if (OutsideCheck##codesymX(x) | OutsideCheck##codesymY(y)) { /* == || */ \
|
|
return NotOverlapped; \
|
|
} \
|
|
*out_code = code; \
|
|
return Overlapped;
|
|
|
|
|
|
switch (code) {
|
|
CaseOfCode_Overlap(0, 00, 00);
|
|
CaseOfCode_Overlap(1, 00, 01);
|
|
CaseOfCode_Overlap(2, 00, 10);
|
|
CaseOfCode_Overlap(3, 00, 11);
|
|
|
|
CaseOfCode_Overlap(4, 01, 00);
|
|
CaseOfCode_Overlap(5, 01, 01);
|
|
CaseOfCode_Overlap(6, 01, 10);
|
|
CaseOfCode_Overlap(7, 01, 11);
|
|
|
|
CaseOfCode_Overlap(8, 10, 00);
|
|
CaseOfCode_Overlap(9, 10, 01);
|
|
CaseOfCode_Overlap(10, 10, 10);
|
|
CaseOfCode_Overlap(11, 10, 11);
|
|
|
|
CaseOfCode_Overlap(12, 11, 00);
|
|
CaseOfCode_Overlap(13, 11, 01);
|
|
CaseOfCode_Overlap(14, 11, 10);
|
|
CaseOfCode_Overlap(15, 11, 11);
|
|
}
|
|
|
|
|
|
#undef CaseOfCode_Overlap
|
|
#undef OutsideCheck00
|
|
#undef OutsideCheck01
|
|
#undef OutsideCheck11
|
|
#undef OutsideCheck10
|
|
|
|
/* Not comming */
|
|
assert(0 && "BlitPoolUtil_GetOverlapCode: Illigal area!");
|
|
|
|
return Overlapped;
|
|
}
|
|
|
|
|
|
|
|
|
|
void BlitPoolUtil_CalcOverlapArea(
|
|
BlitPool_BoundingBox *out_overlap_box,
|
|
Uint8 code,
|
|
BlitPool_BoundingBox *f,
|
|
BlitPool_BoundingBox *b
|
|
)
|
|
/*
|
|
// This calculate the overlapped rect.
|
|
// bouding box f and b must be overlapped.
|
|
*/
|
|
{
|
|
assert(out_overlap_box != NULL);
|
|
assert(f != NULL);
|
|
assert(b != NULL);
|
|
assert(code <= 0x0f);
|
|
|
|
|
|
#define CalcOverlapBox00(axis) \
|
|
out_overlap_box->axis##0 = f->axis##0; \
|
|
out_overlap_box->axis##1 = b->axis##1
|
|
|
|
#define CalcOverlapBox01(axis) \
|
|
out_overlap_box->axis##0 = f->axis##0; \
|
|
out_overlap_box->axis##1 = f->axis##1
|
|
|
|
#define CalcOverlapBox11(axis) \
|
|
out_overlap_box->axis##0 = b->axis##0; \
|
|
out_overlap_box->axis##1 = f->axis##1
|
|
|
|
#define CalcOverlapBox10(axis) \
|
|
out_overlap_box->axis##0 = b->axis##0; \
|
|
out_overlap_box->axis##1 = b->axis##1
|
|
|
|
|
|
|
|
#define CaseOfCode_CalcOverlap(codeval, codesymY, codesymX) \
|
|
case codeval: \
|
|
CalcOverlapBox##codesymX(x);\
|
|
CalcOverlapBox##codesymY(y);\
|
|
break;
|
|
|
|
|
|
switch (code) {
|
|
CaseOfCode_CalcOverlap(0, 00, 00);
|
|
CaseOfCode_CalcOverlap(1, 00, 01);
|
|
CaseOfCode_CalcOverlap(2, 00, 10);
|
|
CaseOfCode_CalcOverlap(3, 00, 11);
|
|
|
|
CaseOfCode_CalcOverlap(4, 01, 00);
|
|
CaseOfCode_CalcOverlap(5, 01, 01);
|
|
CaseOfCode_CalcOverlap(6, 01, 10);
|
|
CaseOfCode_CalcOverlap(7, 01, 11);
|
|
|
|
CaseOfCode_CalcOverlap(8, 10, 00);
|
|
CaseOfCode_CalcOverlap(9, 10, 01);
|
|
CaseOfCode_CalcOverlap(10, 10, 10);
|
|
CaseOfCode_CalcOverlap(11, 10, 11);
|
|
|
|
CaseOfCode_CalcOverlap(12, 11, 00);
|
|
CaseOfCode_CalcOverlap(13, 11, 01);
|
|
CaseOfCode_CalcOverlap(14, 11, 10);
|
|
CaseOfCode_CalcOverlap(15, 11, 11);
|
|
}
|
|
|
|
|
|
#undef CaseOfCode_CalcOverlap
|
|
#undef CalcOverlapBox00
|
|
#undef CalcOverlapBox01
|
|
#undef CalcOverlapBox11
|
|
#undef CalcOverlapBox10
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void AddEntryToNext(BlitPool *pool, BlitEntry *entry, BlitEntry *new_entry)
|
|
/*
|
|
// This add a new entry to a next node of a [entry].
|
|
//
|
|
// [entry] <-> [next]
|
|
// |
|
|
// V
|
|
// [entry] <-> [new_entry] <-> [next]
|
|
*/
|
|
{
|
|
assert(pool != NULL);
|
|
assert(entry != NULL);
|
|
assert(new_entry != NULL);
|
|
|
|
|
|
if (pool->head == NULL) {
|
|
AddEntryToTail(pool, entry);
|
|
return;
|
|
|
|
} else {
|
|
BlitEntry *next; /* next node of [entry] */
|
|
|
|
next = entry->next;
|
|
|
|
/* link: entry <-> new_entry */
|
|
entry->next = new_entry;
|
|
new_entry->prev = entry;
|
|
|
|
/* link: new_entry <-> next */
|
|
new_entry->next = next;
|
|
if (next != NULL) {
|
|
next->prev = new_entry;
|
|
}
|
|
|
|
pool->num_entry += 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
/* unuse */
|
|
static void AddEntryToPrev(BlitPool *pool, BlitEntry *entry, BlitEntry *new_entry)
|
|
/*
|
|
// This add a new entry to a prev node of a [entry].
|
|
//
|
|
// [prev] <-> [entry]
|
|
// |
|
|
// V
|
|
// [prev] <-> [new_entry] <-> [entry]
|
|
*/
|
|
{
|
|
assert(pool != NULL);
|
|
assert(entry != NULL);
|
|
assert(new_entry != NULL);
|
|
|
|
|
|
if (pool->head == NULL) {
|
|
AddEntryToHead(pool, entry);
|
|
return;
|
|
|
|
} else {
|
|
BlitEntry *prev; /* next node of [entry] */
|
|
|
|
prev = entry->prev;
|
|
|
|
/* link: entry <-> new_entry */
|
|
entry->prev = new_entry;
|
|
new_entry->next = entry;
|
|
|
|
/* link: new_entry <-> prev */
|
|
new_entry->prev = prev;
|
|
if (prev != NULL) {
|
|
prev->next = new_entry;
|
|
}
|
|
|
|
pool->num_entry += 1;
|
|
}
|
|
}
|
|
|
|
static void AddEntryToHead(BlitPool *pool, BlitEntry *entry)
|
|
/*
|
|
// This add a new entry to head of list.
|
|
*/
|
|
{
|
|
assert(pool != NULL);
|
|
assert(entry != NULL);
|
|
|
|
entry->next = NULL;
|
|
entry->prev = NULL;
|
|
|
|
if (pool->head == NULL) {
|
|
pool->head = entry;
|
|
pool->tail = entry;
|
|
|
|
} else {
|
|
pool->head->next = entry;
|
|
entry->next = pool->head;
|
|
|
|
pool->head = entry;
|
|
}
|
|
|
|
pool->num_entry += 1;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void AddEntryToTail(BlitPool *pool, BlitEntry *entry)
|
|
/*
|
|
// This add a new entry to tail of list.
|
|
*/
|
|
{
|
|
assert(pool != NULL);
|
|
assert(entry != NULL);
|
|
|
|
entry->next = NULL;
|
|
entry->prev = NULL;
|
|
|
|
if (pool->head == NULL) {
|
|
pool->head = entry;
|
|
pool->tail = entry;
|
|
|
|
} else {
|
|
pool->tail->next = entry;
|
|
entry->prev = pool->tail;
|
|
|
|
pool->tail = entry;
|
|
}
|
|
|
|
pool->num_entry += 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
static void RemoveEntry(BlitPool *pool, BlitEntry *entry)
|
|
/*
|
|
// This unlink a entry from a pool(list).
|
|
*/
|
|
{
|
|
BlitEntry *next ,*prev;
|
|
|
|
|
|
assert(pool != NULL);
|
|
assert(entry != NULL);
|
|
|
|
next = entry->next;
|
|
prev = entry->prev;
|
|
|
|
if (prev == NULL) {
|
|
assert(entry == pool->head);
|
|
pool->head = next;
|
|
if (next != NULL) {
|
|
next->prev = NULL;
|
|
}
|
|
|
|
} else {
|
|
prev->next = next;
|
|
}
|
|
|
|
if (next == NULL) {
|
|
assert(entry == pool->tail);
|
|
pool->tail = prev;
|
|
if (prev != NULL) {
|
|
prev->next = NULL;
|
|
}
|
|
|
|
} else {
|
|
next->prev = prev;
|
|
}
|
|
|
|
pool->num_entry -= 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
static void DeleteEntry(BlitPool *pool, BlitEntry *entry)
|
|
/*
|
|
// This delete a entry from a pool(list).
|
|
*/
|
|
{
|
|
assert(pool != NULL);
|
|
assert(entry != NULL);
|
|
|
|
|
|
RemoveEntry(pool, entry);
|
|
|
|
ReleaseBlitEntry(pool, entry);
|
|
}
|
|
|
|
|
|
|
|
|
|
void BlitPoolUtil_RectToBBox(SDL_Rect *srcrect, BlitPool_BoundingBox *destbox)
|
|
{
|
|
assert(destbox != NULL);
|
|
assert(srcrect != NULL);
|
|
|
|
destbox->x0 = srcrect->x;
|
|
destbox->y0 = srcrect->y;
|
|
destbox->x1 = destbox->x0 + srcrect->w;
|
|
destbox->y1 = destbox->y0 + srcrect->h;
|
|
}
|
|
|
|
|
|
|
|
|
|
void BlitPoolUtil_BBoxToRect(BlitPool_BoundingBox *srcbox, SDL_Rect *destrect)
|
|
{
|
|
assert(destrect != NULL);
|
|
assert(srcbox != NULL);
|
|
|
|
destrect->x = srcbox->x0;
|
|
destrect->y = srcbox->y0;
|
|
destrect->w = srcbox->x1 - destrect->x;
|
|
destrect->h = srcbox->y1 - destrect->y;
|
|
}
|
|
|
|
|
|
|
|
|
|
static BlitEntry *AllocateBlitEntry(BlitPool *pool)
|
|
{
|
|
assert(pool != NULL);
|
|
|
|
return (BlitEntry *)pool->allocator(sizeof(BlitEntry));
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ReleaseBlitEntry(BlitPool *pool, BlitEntry *entry)
|
|
{
|
|
assert(pool != NULL);
|
|
assert(entry != NULL);
|
|
|
|
pool->releaser(entry);
|
|
}
|
|
|
|
|
|
|
|
|
|
static BlitEntry *DuplicateBlitEntry(BlitPool *pool, BlitEntry *base)
|
|
{
|
|
BlitEntry *p;
|
|
|
|
|
|
assert(pool != NULL);
|
|
assert(base != NULL);
|
|
|
|
p = AllocateBlitEntry(pool);
|
|
|
|
|
|
#if IF_ALLOC_FAIL(1) + 0
|
|
|
|
if (p == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
*p = *base; /* or memcpy */
|
|
|
|
p->next = NULL;
|
|
p->prev = NULL;
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int StrEq(unsigned char *str0, unsigned char *str1, int n)
|
|
{
|
|
int i;
|
|
|
|
|
|
assert(str0 != NULL);
|
|
assert(str1 != NULL);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
if (str0[i] != str1[i]) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
static const unsigned char * const stg_BlitPool_Sign = "SDL_BlitPool by Strangebug";
|
|
|
|
|
|
|