diff --git a/blitbuffer.c b/blitbuffer.c index 0e4d30b69..670c5f4be 100644 --- a/blitbuffer.c +++ b/blitbuffer.c @@ -20,14 +20,19 @@ #include #include "blitbuffer.h" - -inline int setPixel(lua_State *L, BlitBuffer *bb, int x, int y, int c) { - uint8_t *dstptr = (uint8_t*)(bb->data) + (y * bb->pitch) + (x / 2); -#ifndef NO_CHECK_BOUNDS - if(x < 0 || x >= bb->w || y < 0 || y >= bb->h) { - return luaL_error(L, "out of bounds in blitbuffer.setPixel()"); +/* debugging statements, switch as needed */ +#ifdef DEBUG +#define ASSERT_BLITBUFFER_BOUNDARIES(bb,bb_ptr) \ + if((bb_ptr < bb->data) || (bb_ptr >= (bb->data + bb->pitch * bb->h))) { \ + fprintf(stderr, "violated blitbuffer constraints in file %s, line %d!\r\n", __FILE__, __LINE__); exit(1); \ } -#endif +#else // DEBUG +#define ASSERT_BLITBUFFER_BOUNDARIES(bb,bb_ptr) {} +#endif // DEBUG + +inline int setPixel(BlitBuffer *bb, int x, int y, int c) { + uint8_t *dstptr = (uint8_t*)(bb->data) + (y * bb->pitch) + (x / 2); + ASSERT_BLITBUFFER_BOUNDARIES(bb, dstptr); if(x % 2 == 0) { *dstptr &= 0x0F; @@ -173,6 +178,8 @@ static int blitToBuffer(lua_State *L) { xoffs / 2 ); if(xoffs & 1) { for(y = 0; y < h; y++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); + ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); *dstptr &= 0xF0; *dstptr |= *srcptr & 0x0F; dstptr += dst->pitch; @@ -180,6 +187,8 @@ static int blitToBuffer(lua_State *L) { } } else { for(y = 0; y < h; y++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); + ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); *dstptr &= 0xF0; *dstptr |= *srcptr >> 4; dstptr += dst->pitch; @@ -200,6 +209,8 @@ static int blitToBuffer(lua_State *L) { if(xoffs & 1) { for(y = 0; y < h; y++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); + ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); for(x = 0; x < (w / 2); x++) { dstptr[x] = (srcptr[x] << 4) | (srcptr[x+1] >> 4); } @@ -212,6 +223,8 @@ static int blitToBuffer(lua_State *L) { } } else { for(y = 0; y < h; y++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); + ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); memcpy(dstptr, srcptr, w / 2); if(w & 1) { dstptr[w/2] &= 0x0F; @@ -270,6 +283,8 @@ static int addblitToBuffer(lua_State *L) { xoffs / 2 ); if(xoffs & 1) { for(y = 0; y < h; y++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); + ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); uint8_t v = (*dstptr & 0x0F) + (*srcptr & 0x0F); *dstptr = (*dstptr & 0xF0) | (v < 0x0F ? v : 0x0F); dstptr += dst->pitch; @@ -277,6 +292,8 @@ static int addblitToBuffer(lua_State *L) { } } else { for(y = 0; y < h; y++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); + ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); uint8_t v = (*dstptr & 0x0F) + (*srcptr >> 4); *dstptr = (*dstptr & 0xF0) | (v < 0x0F ? v : 0x0F); dstptr += dst->pitch; @@ -298,11 +315,15 @@ static int addblitToBuffer(lua_State *L) { if(xoffs & 1) { for(y = 0; y < h; y++) { for(x = 0; x < (w / 2); x++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); + ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); uint16_t v1 = (dstptr[x] & 0xF0) + ((srcptr[x] & 0x0F) << 4); uint8_t v2 = (dstptr[x] & 0x0F) + (srcptr[x+1] >> 4); dstptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F); } if(w & 1) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); + ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); uint16_t v1 = (dstptr[x] & 0xF0) + ((srcptr[x] & 0x0F) << 4); dstptr[x] = (dstptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0); } @@ -312,11 +333,15 @@ static int addblitToBuffer(lua_State *L) { } else { for(y = 0; y < h; y++) { for(x = 0; x < (w / 2); x++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); + ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); uint16_t v1 = (dstptr[x] & 0xF0) + (srcptr[x] & 0xF0); uint8_t v2 = (dstptr[x] & 0x0F) + (srcptr[x] & 0x0F); dstptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F); } if(w & 1) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); + ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); uint16_t v1 = (dstptr[x] & 0xF0) + (srcptr[x] & 0xF0); dstptr[x] = (dstptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0); } @@ -337,9 +362,25 @@ static int paintRect(lua_State *L) { uint8_t *dstptr; int cy; - if(w <= 0 || h <= 0 || x >= dst->w || y >= dst->h) { - return 0; + + if(x < 0) { + if (x+w > 0) { + w += x; + x = 0; + } else { + return 0; + } } + + if(y < 0) { + if (y+h > 0) { + h += y; + y = 0; + } else { + return 0; + } + } + if(x + w > dst->w) { w = dst->w - x; } @@ -347,6 +388,10 @@ static int paintRect(lua_State *L) { h = dst->h - y; } + if(w <= 0 || h <= 0 || x >= dst->w || y >= dst->h) { + return 0; + } + if(x & 1) { /* This will render the leftmost column * in the case when x is odd. After this, @@ -355,6 +400,7 @@ static int paintRect(lua_State *L) { y * dst->pitch + x / 2); for(cy = 0; cy < h; cy++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); *dstptr &= 0xF0; *dstptr |= c; dstptr += dst->pitch; @@ -366,6 +412,7 @@ static int paintRect(lua_State *L) { y * dst->pitch + x / 2); for(cy = 0; cy < h; cy++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); memset(dstptr, c | (c << 4), w / 2); dstptr += dst->pitch; } @@ -377,6 +424,7 @@ static int paintRect(lua_State *L) { y * dst->pitch + (x + w) / 2); for(cy = 0; cy < h; cy++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); *dstptr &= 0x0F; *dstptr |= (c << 4); dstptr += dst->pitch; @@ -435,6 +483,7 @@ static int invertRect(lua_State *L) { y * dst->pitch + x / 2); for(cy = 0; cy < h; cy++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); *dstptr ^= 0x0F; dstptr += dst->pitch; } @@ -446,6 +495,7 @@ static int invertRect(lua_State *L) { x / 2); for(cy = 0; cy < h; cy++) { for(cx = 0; cx < w/2; cx++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, (dstptr+cx)); *(dstptr+cx) ^= 0xFF; } dstptr += dst->pitch; @@ -458,6 +508,7 @@ static int invertRect(lua_State *L) { y * dst->pitch + (x + w) / 2); for(cy = 0; cy < h; cy++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); *dstptr ^= 0xF0; dstptr += dst->pitch; } @@ -474,6 +525,27 @@ static int dimRect(lua_State *L) { uint8_t *dstptr; int cy, cx; + + if (x < 0) { + if ( x + w > 0 ) { + w = w + x; + x = 0; + } else { + //printf("## invertRect x out of bound\n"); + return 0; + } + } + + if (y < 0) { + if ( y + h > 0 ) { + h = h + y; + y = 0; + } else { + //printf("## invertRect y out of bound\n"); + return 0; + } + } + if(w <= 0 || h <= 0 || x >= dst->w || y >= dst->h) { return 0; } @@ -492,6 +564,7 @@ static int dimRect(lua_State *L) { y * dst->pitch + x / 2); for(cy = 0; cy < h; cy++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); int px = *dstptr & 0x0F; *dstptr &= 0xF0 | px >> 1; dstptr += dst->pitch; @@ -504,6 +577,7 @@ static int dimRect(lua_State *L) { x / 2); for(cy = 0; cy < h; cy++) { for(cx = 0; cx < w/2; cx++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, (dstptr+cx)); *(dstptr+cx) = ( *(dstptr+cx) >> 1 ) & 0xF0 | ( *(dstptr+cx) & 0x0F ) >> 1; @@ -518,6 +592,7 @@ static int dimRect(lua_State *L) { y * dst->pitch + (x + w) / 2); for(cy = 0; cy < h; cy++) { + ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); int px = *dstptr & 0xF0; *dstptr &= 0x0F | ( px >> 1 & 0xF0 ); dstptr += dst->pitch; @@ -560,10 +635,10 @@ static int paintCircle(lua_State *L) { /* draw two axles */ for(tmp_y = r; tmp_y > r2; tmp_y--) { - setPixel(L, dst, center_x+0, center_y+tmp_y, c); - setPixel(L, dst, center_x-0, center_y-tmp_y, c); - setPixel(L, dst, center_x+tmp_y, center_y+0, c); - setPixel(L, dst, center_x-tmp_y, center_y-0, c); + setPixel(dst, center_x+0, center_y+tmp_y, c); + setPixel(dst, center_x-0, center_y-tmp_y, c); + setPixel(dst, center_x+tmp_y, center_y+0, c); + setPixel(dst, center_x-tmp_y, center_y-0, c); } while(x < y) { @@ -591,21 +666,21 @@ static int paintCircle(lua_State *L) { } for(tmp_y = y; tmp_y > y2; tmp_y--) { - setPixel(L, dst, center_x+x, center_y+tmp_y, c); - setPixel(L, dst, center_x+tmp_y, center_y+x, c); + setPixel(dst, center_x+x, center_y+tmp_y, c); + setPixel(dst, center_x+tmp_y, center_y+x, c); - setPixel(L, dst, center_x+tmp_y, center_y-x, c); - setPixel(L, dst, center_x+x, center_y-tmp_y, c); + setPixel(dst, center_x+tmp_y, center_y-x, c); + setPixel(dst, center_x+x, center_y-tmp_y, c); - setPixel(L, dst, center_x-x, center_y-tmp_y, c); - setPixel(L, dst, center_x-tmp_y, center_y-x, c); + setPixel(dst, center_x-x, center_y-tmp_y, c); + setPixel(dst, center_x-tmp_y, center_y-x, c); - setPixel(L, dst, center_x-tmp_y, center_y+x, c); - setPixel(L, dst, center_x-x, center_y+tmp_y, c); + setPixel(dst, center_x-tmp_y, center_y+x, c); + setPixel(dst, center_x-x, center_y+tmp_y, c); } } if(r == w) { - setPixel(L, dst, center_x, center_y, c); + setPixel(dst, center_x, center_y, c); } return 0; } @@ -645,10 +720,10 @@ static int paintRoundedCorner(lua_State *L) { /* draw two axles */ /*for(tmp_y = r; tmp_y > r2; tmp_y--) {*/ - /*setPixel(L, dst, (w-r)+off_x+0, (h-r)+off_y+tmp_y-1, c);*/ - /*setPixel(L, dst, (w-r)+off_x-0, (r)+off_y-tmp_y, c);*/ - /*setPixel(L, dst, (w-r)+off_x+tmp_y, (h-r)+off_y+0, c);*/ - /*setPixel(L, dst, (r)+off_x-tmp_y, (h-r)+off_y-0-1, c);*/ + /*setPixel(dst, (w-r)+off_x+0, (h-r)+off_y+tmp_y-1, c);*/ + /*setPixel(dst, (w-r)+off_x-0, (r)+off_y-tmp_y, c);*/ + /*setPixel(dst, (w-r)+off_x+tmp_y, (h-r)+off_y+0, c);*/ + /*setPixel(dst, (r)+off_x-tmp_y, (h-r)+off_y-0-1, c);*/ /*}*/ while(x < y) { @@ -676,17 +751,17 @@ static int paintRoundedCorner(lua_State *L) { } for(tmp_y = y; tmp_y > y2; tmp_y--) { - setPixel(L, dst, (w-r)+off_x+x-1, (h-r)+off_y+tmp_y-1, c); - setPixel(L, dst, (w-r)+off_x+tmp_y-1, (h-r)+off_y+x-1, c); + setPixel(dst, (w-r)+off_x+x-1, (h-r)+off_y+tmp_y-1, c); + setPixel(dst, (w-r)+off_x+tmp_y-1, (h-r)+off_y+x-1, c); - setPixel(L, dst, (w-r)+off_x+tmp_y-1, (r)+off_y-x, c); - setPixel(L, dst, (w-r)+off_x+x-1, (r)+off_y-tmp_y, c); + setPixel(dst, (w-r)+off_x+tmp_y-1, (r)+off_y-x, c); + setPixel(dst, (w-r)+off_x+x-1, (r)+off_y-tmp_y, c); - setPixel(L, dst, (r)+off_x-x, (r)+off_y-tmp_y, c); - setPixel(L, dst, (r)+off_x-tmp_y, (r)+off_y-x, c); + setPixel(dst, (r)+off_x-x, (r)+off_y-tmp_y, c); + setPixel(dst, (r)+off_x-tmp_y, (r)+off_y-x, c); - setPixel(L, dst, (r)+off_x-tmp_y, (h-r)+off_y+x-1, c); - setPixel(L, dst, (r)+off_x-x, (h-r)+off_y+tmp_y-1, c); + setPixel(dst, (r)+off_x-tmp_y, (h-r)+off_y+x-1, c); + setPixel(dst, (r)+off_x-x, (h-r)+off_y+tmp_y-1, c); } } return 0;