From 7b52cc13af4e85f1ca2deb6b6c77de9c95ea0dcf Mon Sep 17 00:00:00 2001 From: scuri Date: Fri, 17 Oct 2008 06:10:33 +0000 Subject: First commit - moving from LuaForge to SourceForge --- src/lua5/cdlua5.c | 1819 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1819 insertions(+) create mode 100644 src/lua5/cdlua5.c (limited to 'src/lua5/cdlua5.c') diff --git a/src/lua5/cdlua5.c b/src/lua5/cdlua5.c new file mode 100644 index 0000000..9ee3d4e --- /dev/null +++ b/src/lua5/cdlua5.c @@ -0,0 +1,1819 @@ +/** \file + * \brief Lua Binding + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include + +#include "cd.h" +#include "cdgdiplus.h" +#include "cdnative.h" +#include "cdps.h" + +#include +#include + +#include "cdlua.h" +#include "cdlua5_private.h" + + +/***************************************************************************\ +* Initialization * +\***************************************************************************/ + +static const char* cdlua_key = "cdlua5"; + +static void cdlua_SetState(lua_State * L, cdluaLuaState* cdL) +{ + lua_pushlightuserdata(L, (void*)cdlua_key); + lua_pushlightuserdata(L, (void*)cdL); + lua_settable(L, LUA_REGISTRYINDEX); /* registry[address("cdlua5")]=cdL */ + lua_pop(L, 1); +} + +cdluaLuaState* cdlua_getstate(lua_State * L) +{ + cdluaLuaState* cdL; + lua_pushlightuserdata(L, (void*)cdlua_key); + lua_gettable(L, LUA_REGISTRYINDEX); + cdL = (cdluaLuaState*)lua_touserdata(L, -1); + lua_pop(L, 1); + return cdL; +} + +cdluaContext* cdlua_getcontext(lua_State * L, int param) +{ + cdluaLuaState* cdL = cdlua_getstate(L); + + int driver = luaL_checkint(L, param); + if ((driver < 0) || (driver >= cdL->numdrivers)) + luaL_argerror(L, param, "unknown driver"); + + return cdL->drivers[driver]; +} + +static lua_State* cdlua5_play_luaState = NULL; + +lua_State* cdlua_getplaystate(void) +{ + return cdlua5_play_luaState; +} + +void cdlua_setplaystate(lua_State* L) +{ + cdlua5_play_luaState = L; +} + +static cdluaPalette* cdlua_rawcheckpalette(lua_State *L, int param) +{ + void *p = lua_touserdata(L, param); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, param)) { /* does it have a metatable? */ + lua_getfield(L, LUA_REGISTRYINDEX, "cdPalette"); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_pop(L, 2); /* remove both metatables */ + return (cdluaPalette*)p; + } + lua_pop(L, 1); /* remove previous metatable */ + + /* check also for IM palette */ + lua_getfield(L, LUA_REGISTRYINDEX, "imPalette"); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_pop(L, 2); /* remove both metatables */ + return (cdluaPalette*)p; + } + } + } + luaL_typerror(L, param, "cdPalette"); /* else error */ + return NULL; /* to avoid warnings */ +} + +cdluaPalette * cdlua_checkpalette(lua_State * L, int param) +{ + cdluaPalette * pal = cdlua_rawcheckpalette(L, param); + if (!pal->color) + luaL_argerror(L, param, "killed cdPalette"); + return pal; +} + +void cdlua_pushpalette(lua_State* L, long* palette, int size) +{ + cdluaPalette* pal = (cdluaPalette*)lua_newuserdata(L, sizeof(cdluaPalette)); + luaL_getmetatable(L, "cdPalette"); + lua_setmetatable(L, -2); + + pal->count = size; + pal->color = palette; +} + +cdState * cdlua_checkstate(lua_State* L, int param) +{ + cdState** state_p = (cdState**)luaL_checkudata(L, param, "cdState"); + if (!(*state_p)) + luaL_argerror(L, param, "released cdState"); + return *state_p; +} + +void cdlua_pushstate(lua_State* L, cdState* state) +{ + cdState** state_p = (cdState**)lua_newuserdata(L, sizeof(cdState*)); + luaL_getmetatable(L, "cdState"); + lua_setmetatable(L, -2); + + *state_p = state; +} + +cdluaPattern* cdlua_checkpattern(lua_State* L, int param) +{ + cdluaPattern* pattern_p = (cdluaPattern*) luaL_checkudata(L, param, "cdPattern"); + if (!pattern_p->pattern) + luaL_argerror(L, param, "killed cdPattern"); + return pattern_p; +} + +void cdlua_pushpattern(lua_State* L, long int* pattern, int width, int height) +{ + cdluaPattern* pattern_p = (cdluaPattern*)lua_newuserdata(L, sizeof(cdluaPattern)); + luaL_getmetatable(L, "cdPattern"); + lua_setmetatable(L, -2); + + pattern_p->pattern = pattern; + pattern_p->width = width; + pattern_p->height = height; + pattern_p->size = width * height; +} + +cdluaStipple* cdlua_checkstipple(lua_State* L, int param) +{ + cdluaStipple* stipple_p = (cdluaStipple*) luaL_checkudata(L, param, "cdStipple"); + if (!stipple_p->stipple) + luaL_argerror(L, param, "killed cdStipple"); + return stipple_p; +} + +void cdlua_pushstipple(lua_State* L, unsigned char* stipple, int width, int height) +{ + cdluaStipple* stipple_p = (cdluaStipple*)lua_newuserdata(L, sizeof(cdluaStipple)); + luaL_getmetatable(L, "cdStipple"); + lua_setmetatable(L, -2); + + stipple_p->stipple = stipple; + stipple_p->width = width; + stipple_p->height = height; + stipple_p->size = width * height; +} + +cdluaImageRGB* cdlua_checkimagergb(lua_State* L, int param) +{ + cdluaImageRGB* imagergb_p = (cdluaImageRGB*) luaL_checkudata(L, param, "cdImageRGB"); + if (!imagergb_p->red) + luaL_argerror(L, param, "killed cdImageRGB"); + return imagergb_p; +} + +void cdlua_pushimagergb(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, int width, int height) +{ + cdluaImageRGB* imagergb_p = (cdluaImageRGB*)lua_newuserdata(L, sizeof(cdluaImageRGB)); + luaL_getmetatable(L, "cdImageRGB"); + lua_setmetatable(L, -2); + + imagergb_p->red = red; + imagergb_p->green = green; + imagergb_p->blue = blue; + imagergb_p->width = width; + imagergb_p->height = height; + imagergb_p->size = width * height; + imagergb_p->free = 1; +} + +void cdlua_pushimagergb_ex(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, int width, int height) +{ + cdluaImageRGB* imagergb_p = (cdluaImageRGB*)lua_newuserdata(L, sizeof(cdluaImageRGB)); + luaL_getmetatable(L, "cdImageRGB"); + lua_setmetatable(L, -2); + + imagergb_p->red = red; + imagergb_p->green = green; + imagergb_p->blue = blue; + imagergb_p->width = width; + imagergb_p->height = height; + imagergb_p->size = width * height; + imagergb_p->free = 0; +} + +cdluaImageRGBA* cdlua_checkimagergba(lua_State* L, int param) +{ + cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*) luaL_checkudata(L, param, "cdImageRGBA"); + if (!imagergba_p->red) + luaL_argerror(L, param, "killed cdImageRGBA"); + return imagergba_p; +} + +void cdlua_pushimagergba(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha, int width, int height) +{ + cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)lua_newuserdata(L, sizeof(cdluaImageRGBA)); + luaL_getmetatable(L, "cdImageRGBA"); + lua_setmetatable(L, -2); + + imagergba_p->red = red; + imagergba_p->green = green; + imagergba_p->blue = blue; + imagergba_p->alpha = alpha; + imagergba_p->width = width; + imagergba_p->height = height; + imagergba_p->size = width * height; + imagergba_p->free = 1; +} + +void cdlua_pushimagergba_ex(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha, int width, int height) +{ + cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)lua_newuserdata(L, sizeof(cdluaImageRGBA)); + luaL_getmetatable(L, "cdImageRGBA"); + lua_setmetatable(L, -2); + + imagergba_p->red = red; + imagergba_p->green = green; + imagergba_p->blue = blue; + imagergba_p->alpha = alpha; + imagergba_p->width = width; + imagergba_p->height = height; + imagergba_p->size = width * height; + imagergba_p->free = 0; +} + +cdluaImageMap* cdlua_checkimagemap(lua_State* L, int param) +{ + cdluaImageMap* imagemap_p = (cdluaImageMap*) luaL_checkudata(L, param, "cdImageMap"); + if (!imagemap_p->index) + luaL_argerror(L, param, "killed cdImageMap"); + return imagemap_p; +} + +void cdlua_pushimagemap(lua_State* L, unsigned char* index, int width, int height) +{ + cdluaImageMap* imagemap_p = (cdluaImageMap*)lua_newuserdata(L, sizeof(cdluaImageMap)); + luaL_getmetatable(L, "cdImageMap"); + lua_setmetatable(L, -2); + + imagemap_p->index = index; + imagemap_p->width = width; + imagemap_p->height = height; + imagemap_p->size = width * height; +} + +cdluaImageChannel* cdlua_checkchannel(lua_State* L, int param) +{ + cdluaImageChannel* channel_p = (cdluaImageChannel*) luaL_checkudata(L, param, "cdImageChannel"); + if (!channel_p->channel) + luaL_argerror(L, param, "killed cdImageChannel"); + return channel_p; +} + +void cdlua_pushchannel(lua_State* L, unsigned char* channel, int size) +{ + cdluaImageChannel* channel_p = (cdluaImageChannel*)lua_newuserdata(L, sizeof(cdluaImageChannel)); + luaL_getmetatable(L, "cdImageChannel"); + lua_setmetatable(L, -2); + + channel_p->channel = channel; + channel_p->size = size; +} + +long cdlua_checkcolor(lua_State* L, int param) +{ + if (!lua_islightuserdata(L, param)) + luaL_argerror(L, param, "invalid color, must be a light user data"); + + return (long int)lua_touserdata(L, param); +} + +cdImage* cdlua_checkimage(lua_State* L, int param) +{ + cdImage** image_p = (cdImage**)luaL_checkudata(L, param, "cdImage"); + if (!(*image_p)) + luaL_argerror(L, param, "killed cdImage"); + return *image_p; +} + +void cdlua_pushimage(lua_State* L, cdImage* image) +{ + cdImage** image_p = (cdImage**)lua_newuserdata(L, sizeof(cdImage*)); + luaL_getmetatable(L, "cdImage"); + lua_setmetatable(L, -2); + + *image_p = image; +} + +cdBitmap * cdlua_checkbitmap(lua_State* L, int param) +{ + cdBitmap** bitmap_p = (cdBitmap**)luaL_checkudata(L, param, "cdBitmap"); + if (!(*bitmap_p)) + luaL_argerror(L, param, "killed cdBitmap"); + return *bitmap_p; +} + +void cdlua_pushbitmap(lua_State* L, cdBitmap* bitmap) +{ + cdBitmap** bitmap_p = (cdBitmap**)lua_newuserdata(L, sizeof(cdBitmap*)); + luaL_getmetatable(L, "cdBitmap"); + lua_setmetatable(L, -2); + + *bitmap_p = bitmap; +} + +/***************************************************************************\ +* cd.ContextCaps(ctx: number) -> (caps: number) * +\***************************************************************************/ +static int cdlua5_contextcaps(lua_State * L) +{ + cdluaContext* cdlua_ctx = cdlua_getcontext(L, 1); + lua_pushnumber(L, cdContextCaps(cdlua_ctx->ctx())); + return 1; +} + +static int cdlua5_releasestate(lua_State * L) +{ + cdState* *state_p = (cdState* *) luaL_checkudata(L, 1, "cdState"); + if (*state_p) + { + cdReleaseState(*state_p); + *state_p = NULL; /* mark as released */ + } + + return 0; +} + +static int cdlua5_createstipple(lua_State *L) +{ + int size; + unsigned char* stipple; + + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "stipple dimensions should be positive integers"); + + size = width * height; + stipple = (unsigned char *) malloc(size); + memset(stipple, '\0', size); + + cdlua_pushstipple(L, stipple, width, height); + + return 1; +} + +static int cdlua5_killstipple(lua_State *L) +{ + cdluaStipple *stipple_p = (cdluaStipple*)luaL_checkudata(L, 1, "cdStipple"); + if (stipple_p->stipple) + { + free(stipple_p->stipple); + stipple_p->stipple = NULL; /* mark as killed */ + } + + return 0; +} + +/***************************************************************************\ +* number = stipple[i] * +\***************************************************************************/ +static int cdlua5_indexstipple(lua_State *L) +{ + cdluaStipple* stipple_p = cdlua_checkstipple(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= stipple_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + lua_pushnumber(L, stipple_p->stipple[index]); + return 1; +} + +/***************************************************************************\ +* stipple[i] = number . * +\***************************************************************************/ +static int cdlua5_newindexstipple(lua_State *L) +{ + unsigned char value; + + cdluaStipple* stipple_p = cdlua_checkstipple(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= stipple_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + value = (unsigned char)luaL_checkint(L, 3); + if ((value != 0 && value != 1)) + luaL_argerror(L, 3, "value must be 0 or 1"); + + stipple_p->stipple[index] = value; + return 0; +} + +static int cdlua5_createpattern(lua_State *L) +{ + int size; + long int *pattern; + + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "pattern dimensions should be positive integers"); + + size = width * height; + pattern = (long int *) malloc(size * sizeof(long int)); + memset(pattern, 255, size * sizeof(long int)); + + cdlua_pushpattern(L, pattern, width, height); + + return 1; +} + +static int cdlua5_killpattern(lua_State *L) +{ + cdluaPattern *pattern_p = (cdluaPattern *) luaL_checkudata(L, 1, "cdPattern"); + if (pattern_p->pattern) + { + free(pattern_p->pattern); + pattern_p->pattern = NULL; /* mark as killed */ + } + + return 0; +} + +/***************************************************************************\ +* color = pattern[i] * +\***************************************************************************/ +static int cdlua5_indexpattern(lua_State *L) +{ + cdluaPattern* pattern_p = cdlua_checkpattern(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= pattern_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + lua_pushlightuserdata(L, (void *) pattern_p->pattern[index]); + return 1; +} + +/***************************************************************************\ +* pattern[i] = color * +\***************************************************************************/ +static int cdlua5_newindexpattern(lua_State *L) +{ + long int color; + + cdluaPattern* pattern_p = cdlua_checkpattern(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= pattern_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + color = cdlua_checkcolor(L, 3); + + pattern_p->pattern[index] = color; + return 0; +} + +static int cdlua5_rgb2map(lua_State *L) +{ + cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1); + cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 2); + cdluaPalette* pal = cdlua_checkpalette(L, 3); + cdRGB2Map(imagergb_p->width, imagergb_p->height, + imagergb_p->red, imagergb_p->green, imagergb_p->blue, + imagemap_p->index, pal->count, pal->color); + return 0; +} + +static int cdlua5_createbitmap(lua_State *L) +{ + cdBitmap *bitmap; + + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + int type = luaL_checkint(L, 3); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "bitmap dimensions should be positive integers"); + + bitmap = cdCreateBitmap(width, height, type); + if (bitmap) + cdlua_pushbitmap(L, bitmap); + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_killbitmap(lua_State *L) +{ + cdBitmap* *bitmap_p = (cdBitmap* *) luaL_checkudata(L, 1, "cdBitmap"); + if (*bitmap_p) + { + cdKillBitmap(*bitmap_p); + *bitmap_p = NULL; /* mark as killed */ + } + + return 0; +} + +static int cdlua5_bitmapgetdata(lua_State *L) +{ + cdBitmap* bitmap = cdlua_checkbitmap(L, 1); + int dataptr = luaL_checkint(L, 2); + + unsigned char *data = cdBitmapGetData(bitmap, dataptr); + if (data) + cdlua_pushchannel(L, data, bitmap->w * bitmap->h); + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_bitmapsetrect(lua_State *L) +{ + cdBitmap* bitmap = cdlua_checkbitmap(L, 1); + int xmin = (int) luaL_checkint(L, 2); + int xmax = (int) luaL_checkint(L, 3); + int ymin = (int) luaL_checkint(L, 4); + int ymax = (int) luaL_checkint(L, 5); + + cdBitmapSetRect(bitmap, xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_bitmaprgb2map(lua_State *L) +{ + cdBitmap* bitmaprgb = cdlua_checkbitmap(L, 1); + cdBitmap* bitmapmap = cdlua_checkbitmap(L, 2); + + if (bitmaprgb->type != CD_RGB) + luaL_argerror(L, 1, "invalid bitmap type, must be RGB"); + if (bitmapmap->type != CD_MAP) + luaL_argerror(L, 2, "invalid bitmap type, must be Map"); + + cdBitmapRGB2Map(bitmaprgb, bitmapmap); + return 0; +} + +static int cdlua5_createimagergb(lua_State * L) +{ + unsigned char *red, *green, *blue; + int size; + int width = luaL_checkint(L,1); + int height = luaL_checkint(L,2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "image dimensions should be positive integers"); + + size = width*height; + red = (unsigned char*)malloc(3*size); + + if (red) + { + memset(red, 255, 3*size); /* white */ + green = red + size; + blue = red + 2*size; + cdlua_pushimagergb(L, red, green, blue, width, height); + } + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_killimagergb(lua_State *L) +{ + cdluaImageRGB* imagergb_p = (cdluaImageRGB*)luaL_checkudata(L, 1, "cdImageRGB"); + if (imagergb_p->red && imagergb_p->free) + { + free(imagergb_p->red); + imagergb_p->red = NULL; /* mark as killed */ + imagergb_p->green = NULL; + imagergb_p->blue = NULL; + } + + return 0; +} + +static int cdlua5_createimagergba(lua_State * L) +{ + unsigned char *red, *green, *blue, *alpha; + int size; + int width = luaL_checkint(L,1); + int height = luaL_checkint(L,2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "image dimensions should be positive integers"); + + size = width*height; + red = (unsigned char*)malloc(4*size); + + if (red) + { + memset(red, 255, 3*size); /* white */ + green = red + size; + blue = red + 2*size; + alpha = red + 3*size; + memset(alpha, 0, size); /* transparent */ + cdlua_pushimagergba(L, red, green, blue, alpha, width, height); + } + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_killimagergba(lua_State *L) +{ + cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)luaL_checkudata(L, 1, "cdImageRGBA"); + if (imagergba_p->red && imagergba_p->free) + { + free(imagergba_p->red); + imagergba_p->red = NULL; /* mark as killed */ + imagergba_p->green = NULL; + imagergba_p->blue = NULL; + imagergba_p->alpha = NULL; + } + + return 0; +} + +static int cdlua5_createimagemap(lua_State *L) +{ + int size; + unsigned char *index; + int width = luaL_checkint(L,1); + int height = luaL_checkint(L,2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "imagemap dimensions should be positive integers"); + + size = width * height; + index = (unsigned char *) malloc(size); + + if (index) + { + memset(index, 0, size); + cdlua_pushimagemap(L, index, width, height); + } + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_killimagemap(lua_State *L) +{ + cdluaImageMap *imagemap_p = (cdluaImageMap *) luaL_checkudata(L, 1, "cdImageMap"); + if (imagemap_p->index) + { + free(imagemap_p->index); + imagemap_p->index = NULL; /* mark as killed */ + } + + return 0; +} + +/***************************************************************************\ +* number = imagemap[i] * +\***************************************************************************/ +static int cdlua5_indeximagemap(lua_State *L) +{ + cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= imagemap_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + lua_pushnumber(L, imagemap_p->index[index]); + return 1; +} + +/***************************************************************************\ +* imagemap[i] = number * +\***************************************************************************/ +static int cdlua5_newindeximagemap(lua_State *L) +{ + int value; + + cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= imagemap_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + value = luaL_checkint(L, 3); + if ((value < 0 || value > 255)) + luaL_argerror(L, 3, "value should be in range [0, 255]"); + + imagemap_p->index[index] = (unsigned char) value; + return 0; +} + +/***************************************************************************\ +* channel "gettable" fallback. This fallback is called when a LUA line like * +* "c = imagergb.r[y*w + x]" is executed. The imagergb "gettable" fallback * +* fills and returns a channel structure with info about the buffer. This * +* structure is consulted and the appropriate value is returned. * +\***************************************************************************/ +static int cdlua5_indexchannel(lua_State *L) +{ + cdluaImageChannel* channel_p = cdlua_checkchannel(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || + (channel_p->size > 0 && index >= channel_p->size) || + (channel_p->size == -1 && index >= 256)) { + luaL_argerror(L, 2, "index is out of bounds"); + } + + if (channel_p->size == -1) /* COLORS */ + lua_pushlightuserdata(L, (void *)((long int*)channel_p->channel)[index]); + else + lua_pushnumber(L, channel_p->channel[index]); + + return 1; +} + +/***************************************************************************\ +* channel "settable" fallback. This fallback is called when a LUA line like * +* "imagergb.r[y*w + x] = c" is executed. The imagergb "gettable" fallback * +* fills and returns a channel structure with info about the buffer. This * +* structure is consulted and the value is assigned where it should. * +\***************************************************************************/ +static int cdlua5_newindexchannel(lua_State *L) +{ + int value; + + cdluaImageChannel* channel_p = cdlua_checkchannel(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || + (channel_p->size > 0 && index >= channel_p->size) || + (channel_p->size == -1 && index >= 256)) { + luaL_argerror(L, 2, "index is out of bounds"); + } + + if (channel_p->size > 0) + { + value = luaL_checkint(L, 3); + if ((value < 0 || value > 255)) + luaL_argerror(L, 3, "value should be in range [0, 255]"); + channel_p->channel[index] = (unsigned char) value; + } + else /* COLORS */ + { + value = (long int) cdlua_checkcolor(L, 3); + ((long int*)channel_p->channel)[index] = value; + } + return 0; +} + +/***************************************************************************\ +* imagergb "gettable" fallback. This fallback is called when a LUA line * +* like "c = imagergb.r[y*w + x]" or "imagergb.r[y*w + x] = c" is executed. * +* The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static int cdlua5_indeximagergb(lua_State *L) +{ + unsigned char* channel = NULL; + cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1); + const char *index_s = luaL_checkstring(L, 2); + + if (*index_s == 'r' || *index_s == 'R') + channel = imagergb_p->red; + else if (*index_s == 'g' || *index_s == 'G') + channel = imagergb_p->green; + else if (*index_s == 'b' || *index_s == 'B') + channel = imagergb_p->blue; + else + luaL_argerror(L, 2, "index is an invalid channel name"); + + cdlua_pushchannel(L, channel, imagergb_p->size); + + return 1; +} + +/***************************************************************************\ +* imagergba "gettable" fallback. This fallback is called when a LUA line * +* like "c = imagergba.r[y*w + x]" or "imagergba.r[y*w + x] = c" is executed.* +* The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static int cdlua5_indeximagergba(lua_State *L) +{ + unsigned char* channel = NULL; + cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 1); + const char *index_s = luaL_checkstring(L, 2); + + if (*index_s == 'r' || *index_s == 'R') + channel = imagergba_p->red; + else if (*index_s == 'g' || *index_s == 'G') + channel = imagergba_p->green; + else if (*index_s == 'b' || *index_s == 'B') + channel = imagergba_p->blue; + else if (*index_s == 'a' || *index_s == 'A') + channel = imagergba_p->alpha; + else + luaL_argerror(L, 2, "index is an invalid channel name"); + + cdlua_pushchannel(L, channel, imagergba_p->size); + + return 1; +} + +/***************************************************************************\ +* bitmap "gettable" fallback. This fallback is called when a LUA line * +* like "c = bitmap.r[y*w + x]" or "bitmap.r[y*w + x] = c" is executed. * +* The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static int cdlua5_indexbitmap(lua_State *L) +{ + unsigned char* channel = NULL; + + cdBitmap* bitmap = cdlua_checkbitmap(L, 1); + const char *index_s = luaL_checkstring(L, 2); + + int size = bitmap->w * bitmap->h; + + if (*index_s == 'r' || *index_s == 'R') + channel = cdBitmapGetData(bitmap, CD_IRED); + else if (*index_s == 'g' || *index_s == 'G') + channel = cdBitmapGetData(bitmap, CD_IGREEN); + else if (*index_s == 'b' || *index_s == 'B') + channel = cdBitmapGetData(bitmap, CD_IBLUE); + else if (*index_s == 'a' || *index_s == 'A') + channel = cdBitmapGetData(bitmap, CD_IALPHA); + else if (*index_s == 'i' || *index_s == 'I') + channel = cdBitmapGetData(bitmap, CD_INDEX); + else if (*index_s == 'c' || *index_s == 'C') + { + channel = cdBitmapGetData(bitmap, CD_COLORS); + size = -1; + } + else + luaL_argerror(L, 2, "index is an invalid channel name"); + + cdlua_pushchannel(L, channel, size); + + return 1; +} + +static int cdlua5_killimage(lua_State *L) +{ + cdImage* *image_p = (cdImage* *) luaL_checkudata(L, 1, "cdImage"); + if (*image_p) + { + cdKillImage(*image_p); + *image_p = NULL; /* mark as killed */ + } + return 0; +} + +/***************************************************************************\ +* cd.Version() -> (version: string) * +\***************************************************************************/ +static int cdlua5_version(lua_State *L) +{ + lua_pushstring(L, cdVersion()); + return 1; +} + +/***************************************************************************\ +* Register callback functions. * +* cd.ContextRegisterCallback(ctx, cb: number, func: function) -> (status: number) * +\***************************************************************************/ +static int cdlua5_registercallback(lua_State *L) +{ + int cb_i, func_lock; + cdluaCallback* cdCB; + cdluaContext* cdlua_ctx; + + cdlua_ctx = cdlua_getcontext(L, 1); + + cb_i = luaL_checkint(L, 2); + if (cb_i >= cdlua_ctx->cb_n) + luaL_argerror(L, 2, "invalid callback parameter"); + + if (lua_isnil(L, 3)) + func_lock = -1; + else if (!lua_isfunction(L, 3)) + luaL_argerror(L, 3, "invalid function parameter"); + else + lua_pushvalue(L, 3); + func_lock = lua_ref(L, 1); + + cdCB = &cdlua_ctx->cb_list[cb_i]; + + if (cdCB->lock != -1) + { + lua_unref(L,cdCB->lock); + cdCB->lock = func_lock; + if (func_lock == -1) + { + cdContextRegisterCallback(cdlua_ctx->ctx(), cb_i, NULL); + } + } + else + { + if (func_lock != -1) + { + cdContextRegisterCallback(cdlua_ctx->ctx(), cb_i, (cdCallback)cdCB->func); + cdCB->lock = func_lock; + } + } + return 0; +} + + + +/***************************************************************************\ +* Color Coding * +\***************************************************************************/ + +/***************************************************************************\ +* Creates a color as a light userdata. The color value is * +* placed in the (void *) value. Not beautiful, but works best. * +* cd.EncodeColor(r, g, b: number) -> (old_color: color) * +\***************************************************************************/ +static int cdlua5_encodecolor(lua_State *L) +{ + int red_f, green_f, blue_f; + unsigned char red_i, green_i, blue_i; + long int color; + + red_f = luaL_checkint(L, 1); + green_f = luaL_checkint(L, 2); + blue_f = luaL_checkint(L, 3); + + if (red_f < 0 || red_f > 255) + luaL_argerror(L, 1, "color components values should be in range [0, 255]"); + if (green_f < 0 || green_f > 255) + luaL_argerror(L, 2, "color components values should be in range [0, 255]"); + if (blue_f < 0 || blue_f > 255) + luaL_argerror(L, 3, "color components values should be in range [0, 255]"); + + red_i = (unsigned char) (red_f); + green_i = (unsigned char) (green_f); + blue_i = (unsigned char) (blue_f); + + color = cdEncodeColor(red_i, green_i, blue_i); + lua_pushlightuserdata(L, (void *)color); + + return 1; +} + +/***************************************************************************\ +* Decodes a color previously created. * +* cd.DecodeColor(color: color) -> (r, g, b: number) * +\***************************************************************************/ +static int cdlua5_decodecolor(lua_State *L) +{ + unsigned char red_i, green_i, blue_i; + long int color = cdlua_checkcolor(L, 1); + cdDecodeColor(color, &red_i, &green_i, &blue_i); + lua_pushnumber(L, red_i); + lua_pushnumber(L, green_i); + lua_pushnumber(L, blue_i); + + return 3; +} + +/***************************************************************************\ +* cd.EncodeAlpha(color: color_tag, alpha: number) -> (color: color) * +\***************************************************************************/ +static int cdlua5_encodealpha(lua_State *L) +{ + float alpha_f; + unsigned char alpha_i; + long int color; + + color = cdlua_checkcolor(L, 1); + + if (!lua_isnumber(L, 2)) + luaL_argerror(L, 2, "invalid alpha parameter"); + + alpha_f = (float) lua_tonumber(L, 2); + + if (alpha_f < 0 || alpha_f > 255) + luaL_argerror(L, 2, "alpha components values should be in range [0, 255]"); + + alpha_i = (unsigned char) (alpha_f); + + color = cdEncodeAlpha(color, alpha_i); + lua_pushlightuserdata(L, (void *) color); + return 1; +} + +/***************************************************************************\ +* cd.DecodeAlpha(color: color) -> (a: number) * +\***************************************************************************/ +static int cdlua5_decodealpha(lua_State* L) +{ + long int color = cdlua_checkcolor(L, 1); + unsigned char alpha_i = cdDecodeAlpha(color); + lua_pushnumber(L, alpha_i); + return 1; +} + +/***************************************************************************\ +* cd.Alpha(color: color) -> (r: number) * +\***************************************************************************/ +static int cdlua5_alpha(lua_State* L) +{ + long int color = cdlua_checkcolor(L, 1); + lua_pushnumber(L, cdAlpha(color)); + return 1; +} + +/***************************************************************************\ +* cd.Red(color: color) -> (r: number) * +\***************************************************************************/ +static int cdlua5_red(lua_State* L) +{ + long int color = cdlua_checkcolor(L, 1); + lua_pushnumber(L, cdRed(color)); + return 1; +} + +/***************************************************************************\ +* cd.Blue(color: color) -> (r: number) * +\***************************************************************************/ +static int cdlua5_blue(lua_State *L) +{ + long int color = cdlua_checkcolor(L, 1); + lua_pushnumber(L, cdBlue(color)); + return 1; +} + +/***************************************************************************\ +* cd.Green(color: color) -> (r: number) * +\***************************************************************************/ +static int cdlua5_green(lua_State *L) +{ + long int color = cdlua_checkcolor(L, 1); + lua_pushnumber(L, cdGreen(color)); + return 1; +} + +static int cdlua5_createpalette(lua_State *L) +{ + int size_i; + long int *palette; + + size_i = luaL_checkint(L, 1); + if (size_i < 1) + luaL_argerror(L, 1, "palette size should be a positive integer"); + + palette = (long int *) malloc(256 * sizeof(long int)); + memset(palette, 0, 256 * sizeof(long int)); + + cdlua_pushpalette(L, palette, size_i); + + return 1; +} + +static int cdlua5_killpalette(lua_State *L) +{ + cdluaPalette* pal = (cdluaPalette *)luaL_checkudata(L, 1, "cdPalette"); + if (pal->color) + { + free(pal->color); + pal->color = NULL; /* mark as killed */ + } + + return 0; +} + +/***************************************************************************\ +* color = palette[i] * +\***************************************************************************/ +static int cdlua5_indexpalette(lua_State *L) +{ + cdluaPalette* pal = cdlua_checkpalette(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= pal->count) + luaL_argerror(L, 2, "index is out of bounds"); + + lua_pushlightuserdata(L, (void*) pal->color[index]); + return 1; +} + +/***************************************************************************\ +* palette[i] = color * +\***************************************************************************/ +static int cdlua5_newindexpalette(lua_State *L) +{ + long int color; + cdluaPalette* pal = cdlua_checkpalette(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= pal->count) + luaL_argerror(L, 2, "index is out of bounds"); + + color = cdlua_checkcolor(L, 3); + + pal->color[index] = color; + return 0; +} + +/*****************************************************************************\ + len +\*****************************************************************************/ +static int cdluaPalette_len(lua_State *L) +{ + cdluaPalette *pal = (cdluaPalette*)lua_touserdata(L, 1); + lua_pushinteger(L, pal->count); + return 1; +} + +/*****************************************************************************\ + tostring +\*****************************************************************************/ +static int cdlua5_tostringpalette (lua_State *L) +{ + cdluaPalette *pal = (cdluaPalette*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdPalette(%p)%s", pal, (pal->color)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringimage (lua_State *L) +{ + cdImage* *image_p = (cdImage**)lua_touserdata(L, 1); + lua_pushfstring(L, "cdImage(%p)%s", image_p, (*image_p)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringbitmap (lua_State *L) +{ + cdBitmap* *bitmap_p = (cdBitmap**)lua_touserdata(L, 1); + lua_pushfstring(L, "cdBitmap(%p)%s", bitmap_p, (*bitmap_p)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringchannel (lua_State *L) +{ + cdluaImageChannel *imagechannel_p = (cdluaImageChannel*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdImageChannel(%p)%s", imagechannel_p, (imagechannel_p->channel)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringstate (lua_State *L) +{ + cdState* *state_p = (cdState**)lua_touserdata(L, 1); + lua_pushfstring(L, "cdState(%p)%s", state_p, (*state_p)? "": "-released"); + return 1; +} + +static int cdlua5_tostringpattern (lua_State *L) +{ + cdluaPattern *pattern_p = (cdluaPattern*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdPattern(%p)%s", pattern_p, (pattern_p->pattern)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringstipple (lua_State *L) +{ + cdluaStipple *stipple_p = (cdluaStipple*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdStipple(%p)%s", stipple_p, (stipple_p->stipple)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringimagergba (lua_State *L) +{ + cdluaImageRGBA *imagergba_p = (cdluaImageRGBA*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdImageRGBA(%p)%s", imagergba_p, (imagergba_p->red)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringimagergb (lua_State *L) +{ + cdluaImageRGB *imagergb_p = (cdluaImageRGB*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdImageRGB(%p)%s", imagergb_p, (imagergb_p->red)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringimagemap (lua_State *L) +{ + cdluaImageMap *imagemap_p = (cdluaImageMap*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdImageMap(%p)%s", imagemap_p, (imagemap_p->index)? "": "-killed"); + return 1; +} + +/***************************************************************************\ +* cd.Reserved * +\***************************************************************************/ +static int cdlua5_reserved(lua_State *L) +{ + long int color = cdlua_checkcolor(L, 1); + lua_pushnumber(L, cdReserved(color)); + return 1; +} + +/***************************************************************************\ +* cd.GetScreenColorPlanes * +\***************************************************************************/ +static int cdlua5_getscreencolorplanes(lua_State *L) +{ + lua_pushnumber(L, cdGetScreenColorPlanes()); + return 1; +} + +/***************************************************************************\ +* cd.GetScreenSize * +\***************************************************************************/ +static int cdlua5_getscreensize(lua_State *L) +{ + int width; + int height; + double mm_width; + double mm_height; + cdGetScreenSize(&width, &height, &mm_width, &mm_height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + lua_pushnumber(L, mm_width); + lua_pushnumber(L, mm_height); + return 4; +} + +/***************************************************************************\ +* cd.UseContextPlus * +\***************************************************************************/ +static int cdlua5_usecontextplus(lua_State *L) +{ + lua_pushnumber(L, cdUseContextPlus(luaL_checkint(L, 1))); + return 1; +} + + +/********************************************************************************\ +* CDLua Exported functions * +\********************************************************************************/ +static const struct luaL_reg cdlib[] = { + + /* Initialization */ + {"ContextCaps" , cdlua5_contextcaps}, + + /* Control */ + {"ReleaseState" , cdlua5_releasestate}, + + /* Stipple */ + {"CreateStipple", cdlua5_createstipple}, + {"KillStipple" , cdlua5_killstipple}, + + /* Pattern */ + {"CreatePattern", cdlua5_createpattern}, + {"KillPattern" , cdlua5_killpattern}, + + /* Client Images */ + {"RGB2Map" , cdlua5_rgb2map}, + {"CreateBitmap" , cdlua5_createbitmap}, + {"KillBitmap" , cdlua5_killbitmap}, + {"BitmapGetData" , cdlua5_bitmapgetdata}, + {"BitmapSetRect" , cdlua5_bitmapsetrect}, + {"BitmapRGB2Map" , cdlua5_bitmaprgb2map}, + + {"CreateImageRGB" , cdlua5_createimagergb}, + {"KillImageRGB" , cdlua5_killimagergb}, + {"CreateImageRGBA" , cdlua5_createimagergba}, + {"KillImageRGBA" , cdlua5_killimagergba}, + {"CreateImageMap" , cdlua5_createimagemap}, + {"KillImageMap" , cdlua5_killimagemap}, + + /* Server Images */ + {"KillImage" , cdlua5_killimage}, + + /* Other */ + {"Version" , cdlua5_version}, + {"RegisterCallback" , cdlua5_registercallback}, + {"ContextRegisterCallback" , cdlua5_registercallback}, + + /* Color Coding */ + {"EncodeColor" , cdlua5_encodecolor}, + {"DecodeColor" , cdlua5_decodecolor}, + {"EncodeAlpha" , cdlua5_encodealpha}, + {"DecodeAlpha" , cdlua5_decodealpha}, + {"Alpha" , cdlua5_alpha}, + {"Red" , cdlua5_red}, + {"Blue" , cdlua5_blue}, + {"Green" , cdlua5_green}, + {"Reserved" , cdlua5_reserved}, + + /* Palette */ + {"CreatePalette", cdlua5_createpalette}, + {"KillPalette" , cdlua5_killpalette}, + + /* native window functions */ + {"GetScreenColorPlanes" , cdlua5_getscreencolorplanes}, + {"GetScreenSize" , cdlua5_getscreensize}, + + /* gdi+ functions */ + {"UseContextPlus" , cdlua5_usecontextplus}, + + {NULL, NULL}, +}; + +void cdlua_addcontext(lua_State *L, cdluaLuaState* cdL, cdluaContext *cdlua_ctx) +{ + int i; + cdlua_ctx->id = cdL->numdrivers; + cdL->drivers[cdL->numdrivers] = cdlua_ctx; + + lua_pushstring(L, cdlua_ctx->name); + lua_pushnumber(L, cdL->numdrivers); + lua_settable(L, -3); + + /* skip CD_SIZECB, register other callbacks */ + for (i=1; i < cdlua_ctx->cb_n; i++) + { + lua_pushstring(L, cdlua_ctx->cb_list[i].name); + lua_pushnumber(L, i); + lua_settable(L, -3); + } + + cdL->numdrivers++; +} + + +/********************************************************************************\ +* Exports all CD constants * +\********************************************************************************/ +typedef struct cdlua5_constant { + const char *name; + lua_Number value; +} cdlua5_constant; + +typedef struct cdlua5_color { + const char *name; + long int value; +} cdlua5_color; + +static const struct cdlua5_constant cdlibconstant[] = { + /* query value */ + {"QUERY", CD_QUERY}, + + /* these definitions are compatible with the IM library */ + {"RGB" , CD_RGB}, + {"MAP" , CD_MAP}, + {"RGBA", CD_RGBA}, + + {"IRED" , CD_IRED}, + {"IGREEN", CD_IGREEN}, + {"IBLUE" , CD_IBLUE}, + {"IALPHA", CD_IALPHA}, + {"INDEX" , CD_INDEX}, + {"COLORS", CD_COLORS}, + + /* status report */ + {"ERROR", CD_ERROR}, + {"OK" , CD_OK}, + + /* clip mode */ + {"CLIPOFF" , CD_CLIPOFF}, + {"CLIPAREA" , CD_CLIPAREA}, + {"CLIPPOLYGON", CD_CLIPPOLYGON}, + {"CLIPREGION" , CD_CLIPREGION}, + + /* region combine mode */ + {"UNION" , CD_UNION}, + {"INTERSECT" , CD_INTERSECT}, + {"DIFFERENCE" , CD_DIFFERENCE}, + {"NOTINTERSECT", CD_NOTINTERSECT}, + + /* polygon mode (begin...end) */ + {"FILL" , CD_FILL}, + {"OPEN_LINES" , CD_OPEN_LINES}, + {"CLOSED_LINES", CD_CLOSED_LINES}, + {"CLIP" , CD_CLIP}, + {"BEZIER" , CD_BEZIER}, + {"REGION" , CD_REGION}, + {"POLYCUSTOM" , CD_POLYCUSTOM}, + + /* fill mode */ + {"EVENODD", CD_EVENODD}, + {"WINDING", CD_WINDING}, + + /* line join */ + {"MITER", CD_MITER}, + {"BEVEL", CD_BEVEL}, + {"ROUND", CD_ROUND}, + + /* line cap */ + {"CAPFLAT" , CD_CAPFLAT}, + {"CAPSQUARE", CD_CAPSQUARE}, + {"CAPROUND" , CD_CAPROUND}, + + /* background opacity mode */ + {"OPAQUE" , CD_OPAQUE}, + {"TRANSPARENT", CD_TRANSPARENT}, + + /* write mode */ + {"REPLACE", CD_REPLACE}, + {"XOR" , CD_XOR}, + {"NOT_XOR", CD_NOT_XOR}, + + /* color allocation mode (palette) */ + {"POLITE", CD_POLITE}, + {"FORCE" , CD_FORCE}, + + /* line style */ + {"CONTINUOUS" , CD_CONTINUOUS}, + {"DASHED" , CD_DASHED}, + {"DOTTED" , CD_DOTTED}, + {"DASH_DOT" , CD_DASH_DOT}, + {"DASH_DOT_DOT", CD_DASH_DOT_DOT}, + {"CUSTOM" , CD_CUSTOM}, + + /* marker type */ + {"PLUS" , CD_PLUS}, + {"STAR" , CD_STAR}, + {"CIRCLE" , CD_CIRCLE}, + {"X" , CD_X}, + {"BOX" , CD_BOX}, + {"DIAMOND" , CD_DIAMOND}, + {"HOLLOW_CIRCLE" , CD_HOLLOW_CIRCLE}, + {"HOLLOW_BOX" , CD_HOLLOW_BOX}, + {"HOLLOW_DIAMOND", CD_HOLLOW_DIAMOND}, + + /* hatch type */ + {"HORIZONTAL", CD_HORIZONTAL}, + {"VERTICAL" , CD_VERTICAL}, + {"FDIAGONAL" , CD_FDIAGONAL}, + {"BDIAGONAL" , CD_BDIAGONAL}, + {"CROSS" , CD_CROSS}, + {"DIAGCROSS" , CD_DIAGCROSS}, + + /* interior style */ + {"SOLID" , CD_SOLID}, + {"HATCH" , CD_HATCH}, + {"STIPPLE", CD_STIPPLE}, + {"PATTERN", CD_PATTERN}, + {"HOLLOW" , CD_HOLLOW}, + + /* text alignment */ + {"NORTH" , CD_NORTH}, + {"SOUTH" , CD_SOUTH}, + {"EAST" , CD_EAST}, + {"WEST" , CD_WEST}, + {"NORTH_EAST" , CD_NORTH_EAST}, + {"NORTH_WEST" , CD_NORTH_WEST}, + {"SOUTH_EAST" , CD_SOUTH_EAST}, + {"SOUTH_WEST" , CD_SOUTH_WEST}, + {"CENTER" , CD_CENTER}, + {"BASE_LEFT" , CD_BASE_LEFT}, + {"BASE_CENTER", CD_BASE_CENTER}, + {"BASE_RIGHT" , CD_BASE_RIGHT}, + + /* style */ + {"PLAIN" , CD_PLAIN}, + {"BOLD" , CD_BOLD}, + {"ITALIC" , CD_ITALIC}, + {"BOLD_ITALIC", CD_BOLD_ITALIC}, + {"UNDERLINE" , CD_UNDERLINE}, + {"STRIKEOUT" , CD_STRIKEOUT}, + + /* font size */ + {"SMALL" , CD_SMALL}, + {"STANDARD", CD_STANDARD}, + {"LARGE" , CD_LARGE}, + + /* Canvas Capabilities */ + {"CAP_NONE" , CD_CAP_NONE}, + {"CAP_FLUSH" , CD_CAP_FLUSH}, + {"CAP_CLEAR" , CD_CAP_CLEAR}, + {"CAP_PLAY" , CD_CAP_PLAY}, + {"CAP_YAXIS" , CD_CAP_YAXIS}, + {"CAP_CLIPAREA" , CD_CAP_CLIPAREA}, + {"CAP_CLIPPOLY" , CD_CAP_CLIPPOLY}, + {"CAP_RECT" , CD_CAP_RECT}, + {"CAP_IMAGERGB" , CD_CAP_IMAGERGB}, + {"CAP_IMAGERGBA" , CD_CAP_IMAGERGBA}, + {"CAP_IMAGEMAP" , CD_CAP_IMAGEMAP}, + {"CAP_GETIMAGERGB" , CD_CAP_GETIMAGERGB}, + {"CAP_IMAGESRV" , CD_CAP_IMAGESRV}, + {"CAP_BACKGROUND" , CD_CAP_BACKGROUND}, + {"CAP_BACKOPACITY" , CD_CAP_BACKOPACITY}, + {"CAP_WRITEMODE" , CD_CAP_WRITEMODE}, + {"CAP_LINESTYLE" , CD_CAP_LINESTYLE}, + {"CAP_LINEWITH" , CD_CAP_LINEWITH}, + {"CAP_WD" , CD_CAP_FPRIMTIVES}, + {"CAP_HATCH" , CD_CAP_HATCH}, + {"CAP_STIPPLE" , CD_CAP_STIPPLE}, + {"CAP_PATTERN" , CD_CAP_PATTERN}, + {"CAP_FONT" , CD_CAP_FONT}, + {"CAP_FONTDIM" , CD_CAP_FONTDIM}, + {"CAP_TEXTSIZE" , CD_CAP_TEXTSIZE}, + {"CAP_TEXTORIENTATION", CD_CAP_TEXTORIENTATION}, + {"CAP_PALETTE" , CD_CAP_PALETTE}, + {"CAP_LINECAP" , CD_CAP_LINECAP}, + {"CAP_LINEJOIN" , CD_CAP_LINEJOIN}, + {"CAP_REGION" , CD_CAP_REGION}, + {"CAP_CHORD" , CD_CAP_CHORD}, + {"CAP_ALL" , CD_CAP_ALL}, + + /* cdPlay definitions */ + {"SIZECB", CD_SIZECB}, + {"ABORT", CD_ABORT}, + {"CONTINUE", CD_CONTINUE}, + + /* simulation flags */ + {"SIM_NONE" , CD_SIM_NONE}, + {"SIM_TEXT" , CD_SIM_TEXT}, + {"SIM_LINE" , CD_SIM_LINE}, + {"SIM_RECT" , CD_SIM_RECT}, + {"SIM_ARC" , CD_SIM_ARC}, + {"SIM_POLYLINE" , CD_SIM_POLYLINE}, + {"SIM_BOX" , CD_SIM_BOX}, + {"SIM_SECTOR" , CD_SIM_SECTOR}, + {"SIM_POLYGON" , CD_SIM_POLYGON}, + {"SIM_CHORD" , CD_SIM_CHORD}, + {"SIM_ALL" , CD_SIM_ALL}, + {"SIM_LINES" , CD_SIM_LINES}, + {"SIM_FILLS" , CD_SIM_FILLS}, + + /* some conversion factors */ + {"MM2PT" , CD_MM2PT}, + {"RAD2DEG", CD_RAD2DEG}, + + /* cdcgm.h (the callback names are registered in cdlua_addcontext) */ + + /* cdgdiplus.h */ + {"SPLINE" , CD_SPLINE}, + {"FILLSPLINE" , CD_FILLSPLINE}, + {"FILLGRADIENT", CD_FILLGRADIENT}, + + /* cdps.h */ + {"A0" , CD_A0}, + {"A1" , CD_A1}, + {"A2" , CD_A2}, + {"A3" , CD_A3}, + {"A4" , CD_A4}, + {"A5" , CD_A5}, + {"LETTER", CD_LETTER}, + {"LEGAL" , CD_LEGAL}, + + {NULL, -1}, +}; + +static void initconst(lua_State *L) +{ + const cdlua5_constant *l = cdlibconstant; + for (; l->name; l++) { + lua_pushstring(L, l->name); + lua_pushnumber(L, l->value); + lua_settable(L, -3); + } +} + +/* some predefined colors for convenience */ +static const struct cdlua5_color cdlibcolor[] = { + {"RED" , CD_RED}, + {"DARK_RED" , CD_DARK_RED}, + {"GREEN" , CD_GREEN}, + {"DARK_GREEN" , CD_DARK_GREEN}, + {"BLUE" , CD_BLUE}, + {"DARK_BLUE" , CD_DARK_BLUE}, + {"YELLOW" , CD_YELLOW}, + {"DARK_YELLOW" , CD_DARK_YELLOW}, + {"MAGENTA" , CD_MAGENTA}, + {"DARK_MAGENTA", CD_DARK_MAGENTA}, + {"CYAN" , CD_CYAN}, + {"DARK_CYAN" , CD_DARK_CYAN}, + {"WHITE" , CD_WHITE}, + {"BLACK" , CD_BLACK}, + {"DARK_GRAY" , CD_DARK_GRAY}, + {"GRAY" , CD_GRAY}, + {NULL, -1}, +}; + +static void initcolor(lua_State *L) +{ + const cdlua5_color *l = cdlibcolor; + for (; l->name; l++) + { + lua_pushstring(L, l->name); + lua_pushlightuserdata(L, (void*) l->value); + lua_settable(L, -3); + } +} + +static void initmetatables(lua_State *L) +{ + /* there is no object orientation for these metatables, + only gc and optionaly array access */ + + luaL_newmetatable(L, "cdState"); /* create new metatable for cdState handles */ + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_releasestate); /* register the method */ + lua_settable (L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringstate); + lua_settable(L, -3); + lua_pop(L, 1); /* removes the metatable from the top of the stack */ + + luaL_newmetatable(L, "cdImage"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killimage); + lua_settable (L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringimage); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdBitmap"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killbitmap); + lua_settable (L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indexbitmap); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringbitmap); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdImageRGB"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killimagergb); + lua_settable (L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indeximagergb); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringimagergb); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdImageRGBA"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killimagergba); + lua_settable (L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indeximagergba); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringimagergba); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdImageChannel"); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indexchannel); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cdlua5_newindexchannel); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringchannel); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdStipple"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killstipple); + lua_settable (L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indexstipple); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cdlua5_newindexstipple); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringstipple); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdPattern"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killpattern); + lua_settable (L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indexpattern); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cdlua5_newindexpattern); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringpattern); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdPalette"); + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, cdlua5_killpalette); + lua_settable(L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indexpalette); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cdlua5_newindexpalette); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringpalette); + lua_settable(L, -3); + lua_pushliteral(L, "__len"); + lua_pushcfunction(L, cdluaPalette_len); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdImageMap"); + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, cdlua5_killimagemap); + lua_settable(L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indeximagemap); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cdlua5_newindeximagemap); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringimagemap); + lua_settable(L, -3); + lua_pop(L, 1); +} + +static void setinfo (lua_State *L) +{ + lua_pushliteral (L, "_COPYRIGHT"); + lua_pushliteral (L, CD_COPYRIGHT); + lua_settable (L, -3); + + lua_pushliteral (L, "_DESCRIPTION"); + lua_pushliteral (L, CD_DESCRIPTION); + lua_settable (L, -3); + + lua_pushliteral (L, "_NAME"); + lua_pushliteral (L, CD_NAME); + lua_settable (L, -3); + + lua_pushliteral (L, "_VERSION"); + lua_pushliteral (L, CD_VERSION); + lua_settable (L, -3); + + lua_pushliteral (L, "_VERSION_DATE"); + lua_pushliteral(L, CD_VERSION_DATE); + lua_settable (L, -3); + + lua_pushliteral (L, "_VERSION_NUMBER"); + lua_pushinteger(L, CD_VERSION_NUMBER); + lua_settable (L, -3); +} + + +/********************************************************************************\ +* CDLua OpenLib * +\********************************************************************************/ + + +int cdlua_open (lua_State *L) +{ + cdluaLuaState* cdL = malloc(sizeof(cdluaLuaState)); + memset(cdL, 0, sizeof(cdluaLuaState)); + cdlua_SetState(L, cdL); + + initmetatables(L); + + luaL_register(L, "cd", cdlib); /* leave "cd" table at the top of the stack */ + setinfo(L); + + cdlua_open_active(L, cdL); + cdlua_open_canvas(L); + + cdlua_initdrivers(L, cdL); + initconst(L); + initcolor(L); + + return 1; +} + +int cdlua_close(lua_State *L) +{ + cdluaLuaState* cdL = cdlua_getstate(L); + if (cdL) + { + cdKillCanvas(cdL->void_canvas); + free(cdL); + } + return 0; +} + +int luaopen_cdlua(lua_State* L) +{ + return cdlua_open(L); +} + +int luaopen_cdlua51(lua_State* L) +{ + return cdlua_open(L); +} -- cgit v1.2.3