mirror of
https://github.com/love2d/love.git
synced 2026-08-15 07:41:11 +02:00
ImageData:mapPixel can now take optional x,y,w,h parameters to constrain it to a rectangle in the ImageData
This commit is contained in:
@@ -115,36 +115,55 @@ int w_ImageData_setPixel(lua_State *L)
|
||||
}
|
||||
|
||||
// Gets the result of luaL_where as a string.
|
||||
static std::string luax_getwhere(lua_State *L, int lvl)
|
||||
static std::string luax_getwhere(lua_State *L, int level)
|
||||
{
|
||||
std::string where;
|
||||
luaL_where(L, level);
|
||||
|
||||
luaL_where(L, lvl);
|
||||
|
||||
const char *str = lua_tostring(L, -1);
|
||||
std::string where;
|
||||
if (str)
|
||||
where = str;
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
return where;
|
||||
}
|
||||
|
||||
// Generates a Lua error with a nice error string when a return value of a
|
||||
// called function is not a number.
|
||||
static int luax_retnumbererror(lua_State *L, int level, int retnum, int ttype)
|
||||
{
|
||||
if (ttype == LUA_TNUMBER)
|
||||
return 0;
|
||||
|
||||
const char *where = luax_getwhere(L, level).c_str();
|
||||
const char *ttypename = lua_typename(L, ttype);
|
||||
|
||||
return luaL_error(L, "%sbad return value #%d (number expected, got %s)",
|
||||
where, retnum, ttypename);
|
||||
}
|
||||
|
||||
// ImageData:mapPixel. Not thread-safe! See the wrapper function below.
|
||||
static int w_ImageData_mapPixelUnsafe(lua_State *L)
|
||||
{
|
||||
ImageData *t = luax_checkimagedata(L, 1);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
|
||||
int w = t->getWidth();
|
||||
int h = t->getHeight();
|
||||
// No optints because we assume they're done in the wrapper function.
|
||||
int sx = (int) lua_tonumber(L, 3);
|
||||
int sy = (int) lua_tonumber(L, 4);
|
||||
int w = (int) lua_tonumber(L, 5);
|
||||
int h = (int) lua_tonumber(L, 6);
|
||||
|
||||
if (!(t->inside(sx, sy) && t->inside(sx+w-1, sy+h-1)))
|
||||
return luaL_error(L, "Invalid rectangle dimensions.");
|
||||
|
||||
// Default pixel component values (r, g, b, a.)
|
||||
const unsigned char pixel_defaults[4] = {0, 0, 0, 255};
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
// Cache-friendlier loop. :)
|
||||
for (int y = sy; y < sy+h; y++)
|
||||
{
|
||||
for (int x = 0; x < w; x++)
|
||||
for (int x = sx; x < sx+w; x++)
|
||||
{
|
||||
lua_pushvalue(L, 2);
|
||||
lua_pushnumber(L, x);
|
||||
@@ -168,15 +187,16 @@ static int w_ImageData_mapPixelUnsafe(lua_State *L)
|
||||
switch (ttype)
|
||||
{
|
||||
case LUA_TNUMBER:
|
||||
parray[i] = lua_tointeger(L, -4 + i);
|
||||
parray[i] = (unsigned char) lua_tonumber(L, -4 + i);
|
||||
break;
|
||||
case LUA_TNONE:
|
||||
case LUA_TNIL:
|
||||
parray[i] = pixel_defaults[i];
|
||||
break;
|
||||
|
||||
default:
|
||||
return luaL_error(L, "%sbad return value #%d (number expected, got %s)",
|
||||
luax_getwhere(L, 2).c_str(), i+1, lua_typename(L, ttype));
|
||||
// Level 2 because this is function will be wrapped.
|
||||
return luax_retnumbererror(L, 2, i + 1, ttype);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,18 +214,27 @@ int w_ImageData_mapPixel(lua_State *L)
|
||||
{
|
||||
ImageData *t = luax_checkimagedata(L, 1);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
|
||||
love::thread::Mutex *mutex = t->getMutex();
|
||||
int sx = luaL_optint(L, 3, 0);
|
||||
int sy = luaL_optint(L, 4, 0);
|
||||
int w = luaL_optint(L, 5, t->getWidth());
|
||||
int h = luaL_optint(L, 6, t->getHeight());
|
||||
|
||||
lua_pushcfunction(L, w_ImageData_mapPixelUnsafe);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_pushvalue(L, 2);
|
||||
lua_pushinteger(L, sx);
|
||||
lua_pushinteger(L, sy);
|
||||
lua_pushinteger(L, w);
|
||||
lua_pushinteger(L, h);
|
||||
|
||||
// Manually lock this ImageData's mutex during the entire mapPixel.
|
||||
// Using the lock methods because lua_error won't trigger object destructors.
|
||||
mutex->lock();
|
||||
int ret = lua_pcall(L, 2, 0, 0);
|
||||
mutex->unlock();
|
||||
int ret = 0;
|
||||
|
||||
// Lock this ImageData's mutex during the entire mapPixel. We pcall instead
|
||||
// of call because lua_error longjmp's without calling object destructors.
|
||||
{
|
||||
love::thread::Lock lock(t->getMutex());
|
||||
ret = lua_pcall(L, 6, 0, 0);
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
return lua_error(L);
|
||||
|
||||
Reference in New Issue
Block a user