aboutsummaryrefslogtreecommitdiff
path: root/src/lua/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua/graphics')
-rw-r--r--src/lua/graphics/luaopen_Canvas.cpp75
-rw-r--r--src/lua/graphics/luaopen_Font.cpp45
-rw-r--r--src/lua/graphics/luaopen_Image.cpp89
-rw-r--r--src/lua/graphics/luaopen_JSL.cpp146
-rw-r--r--src/lua/graphics/luaopen_graphics.cpp524
5 files changed, 879 insertions, 0 deletions
diff --git a/src/lua/graphics/luaopen_Canvas.cpp b/src/lua/graphics/luaopen_Canvas.cpp
new file mode 100644
index 0000000..5dede84
--- /dev/null
+++ b/src/lua/graphics/luaopen_Canvas.cpp
@@ -0,0 +1,75 @@
+#include "lua/luax.h"
+#include "lua/luaopen_types.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::render;
+
+ static inline Canvas* checkCanvas(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_CANVAS);
+ if (proxy != nullptr)
+ return (Canvas*)proxy->object;
+ return nullptr;
+ }
+
+ static int l_getWidth(lua_State* L)
+ {
+ Canvas* c = checkCanvas(L);
+ luax_pushnumber(L, c->getWidth());
+ return 1;
+ }
+
+ static int l_getHeight(lua_State* L)
+ {
+ Canvas* c = checkCanvas(L);
+ luax_pushnumber(L, c->getHeight());
+ return 1;
+ }
+
+ static int l_getSize(lua_State* L)
+ {
+ Canvas* c = checkCanvas(L);
+ luax_pushnumber(L, c->getWidth());
+ luax_pushnumber(L, c->getHeight());
+ return 2;
+ }
+
+ static int l_setAnchor(lua_State* L)
+ {
+ Canvas* c = checkCanvas(L);
+ int x = luax_checknumber(L, 1);
+ int y = luax_checknumber(L, 2);
+ c->setAnchor(x, y);
+ return 0;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_CANVAS);
+ Canvas* canvas = (Canvas*)proxy->object;
+ delete canvas;
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"__gc", l_gc},
+ {"getWidth", l_getWidth},
+ {"getHeight", l_getHeight},
+ {"getSize", l_getSize},
+ {"setAnchor", l_setAnchor},
+ {0, 0 }
+ };
+
+ int luaopen_Canvas(lua_State* L)
+ {
+ luax_newtype(L, TYPE_CANVAS, f);
+ return 0;
+ }
+
+}// lua
+}// jin \ No newline at end of file
diff --git a/src/lua/graphics/luaopen_Font.cpp b/src/lua/graphics/luaopen_Font.cpp
new file mode 100644
index 0000000..387b220
--- /dev/null
+++ b/src/lua/graphics/luaopen_Font.cpp
@@ -0,0 +1,45 @@
+#include "lua/luax.h"
+#include "lua/luaopen_types.h"
+#include "libjin/jin.h"
+
+using namespace jin::render;
+
+namespace jin
+{
+namespace lua
+{
+
+ static int l_gc(lua_State* L)
+ {
+ return 0;
+ }
+
+ static int l_box(lua_State* L)
+ {
+ Font* font = (Font*)luax_checktype(L, 1, TYPE_FONT);
+ const char* text = luax_checkstring(L, 2);
+ int fheight = luax_checknumber(L, 3);
+ int spacing = luax_checknumber(L, 4);
+ int lheight = luax_checknumber(L, 5);
+ int w, h;
+ font->box(text, fheight, lheight, spacing, &w, &h);
+ luax_pushnumber(L, w);
+ luax_pushnumber(L, h);
+ return 2;
+ }
+
+ static const luaL_Reg f[] = {
+ {"__gc", l_gc},
+ {"box", l_box},
+ {0, 0}
+ };
+
+ int luaopen_Font(lua_State* L)
+ {
+ luax_newtype(L, TYPE_FONT, f);
+
+ return 0;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/graphics/luaopen_Image.cpp b/src/lua/graphics/luaopen_Image.cpp
new file mode 100644
index 0000000..c5648a5
--- /dev/null
+++ b/src/lua/graphics/luaopen_Image.cpp
@@ -0,0 +1,89 @@
+#include "lua/luax.h"
+#include "libjin/jin.h"
+#include "lua/luaopen_types.h"
+
+using namespace jin::render;
+
+namespace jin
+{
+namespace lua
+{
+
+ static inline Image* checkImage(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_IMAGE);
+ if (proxy != 0 && proxy != nullptr)
+ return (Image*)proxy->object;
+ return nullptr;
+ }
+
+ static int l_getWidth(lua_State* L)
+ {
+ Image* i = checkImage(L);
+ luax_pushnumber(L, i->getWidth());
+ return 1;
+ }
+
+ static int l_getHeight(lua_State *L)
+ {
+ Image* i = checkImage(L);
+ luax_pushnumber(L, i->getHeight());
+ return 1;
+ }
+
+ static int l_getPixel(lua_State* L)
+ {
+ Image* i = checkImage(L);
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ color c = i->getPixel(x, y);
+ luax_pushnumber(L, c.rgba.r);
+ luax_pushnumber(L, c.rgba.g);
+ luax_pushnumber(L, c.rgba.b);
+ luax_pushnumber(L, c.rgba.a);
+ return 4;
+ }
+
+ static int l_setAnchor(lua_State* L)
+ {
+ Image* i = checkImage(L);
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ i->setAnchor(x, y);
+ return 0;
+ }
+
+ static int l_getSize(lua_State* L)
+ {
+ Image* i = checkImage(L);
+ luax_pushnumber(L, i->getWidth());
+ luax_pushnumber(L, i->getHeight());
+ return 2;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_IMAGE);
+ Image* img = (Image*)proxy->object;
+ delete img;
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"__gc", l_gc},
+ {"getWidth", l_getWidth},
+ {"getHeight", l_getHeight},
+ {"getSize", l_getSize},
+ {"getPixel", l_getPixel},
+ {"setAnchor", l_setAnchor},
+ {0, 0 }
+ };
+
+ int luaopen_Image(lua_State* L)
+ {
+ luax_newtype(L, TYPE_IMAGE, f);
+ return 0;
+ }
+
+}// graphics
+}// jin \ No newline at end of file
diff --git a/src/lua/graphics/luaopen_JSL.cpp b/src/lua/graphics/luaopen_JSL.cpp
new file mode 100644
index 0000000..93ca5d3
--- /dev/null
+++ b/src/lua/graphics/luaopen_JSL.cpp
@@ -0,0 +1,146 @@
+#include "lua/luax.h"
+#include "libjin/jin.h"
+#include "lua/luaopen_types.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace render;
+
+ static inline JSLProgram* checkJSLProgram(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_JSL);
+ if(proxy != nullptr)
+ return (JSLProgram*)proxy->object;
+ return nullptr;
+ }
+
+ static enum VARIABLE_TYPE
+ {
+ INVALID = 0,
+
+ NUMBER,
+ IMAGE,
+ CANVAS,
+ VEC2,
+ VEC3,
+ VEC4,
+ COLOR,
+ };
+
+ static VARIABLE_TYPE strtotype(const char* str)
+ {
+ std::string s = std::string(str);
+ if (s == "number") return NUMBER;
+ else if (s == "Image") return IMAGE;
+ else if (s == "Canvas") return CANVAS;
+ else if (s == "vec2") return VEC2;
+ else if (s == "vec3") return VEC3;
+ else if (s == "vec4") return VEC4;
+ else if (s == "Color") return COLOR;
+ else return INVALID;
+ }
+
+ /**
+ * Use send function send variables to JSL program.
+ */
+ static int l_send(lua_State* L)
+ {
+ JSLProgram* jsl = checkJSLProgram(L);
+ // number Image Texel
+ const char* typestr = luax_checkstring(L, 2);
+ // variable name
+ const char* variable = luax_checkstring(L, 3);
+ if (typestr != nullptr)
+ {
+ int type = strtotype(typestr);
+ switch (type)
+ {
+ case NUMBER:
+ {
+ float number = luax_checknumber(L, 4);
+ jsl->sendFloat(variable, number);
+ break;
+ }
+ case IMAGE:
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 4, TYPE_IMAGE);
+ Image* img = (Image*)proxy->object;
+ jsl->sendImage(variable, img);
+ break;
+ }
+ case CANVAS:
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 4, TYPE_IMAGE);
+ Canvas* canvas = (Canvas*)proxy->object;
+ jsl->sendCanvas(variable, canvas);
+ break;
+ }
+ case VEC2:
+ {
+ float x = luax_checknumber(L, 4);
+ float y = luax_checknumber(L, 5);
+ jsl->sendVec2(variable, x, y);
+ break;
+ }
+ case VEC3:
+ {
+ float x = luax_checknumber(L, 4);
+ float y = luax_checknumber(L, 5);
+ float z = luax_checknumber(L, 6);
+ jsl->sendVec3(variable, x, y, z);
+ break;
+ }
+ case VEC4:
+ {
+ float x = luax_checknumber(L, 4);
+ float y = luax_checknumber(L, 5);
+ float z = luax_checknumber(L, 6);
+ float w = luax_checknumber(L, 7);
+ jsl->sendVec4(variable, x, y, z, w);
+ break;
+ }
+ case COLOR:
+ {
+ color col;
+ col.rgba.r = luax_checkinteger(L, 4);
+ col.rgba.g = luax_checkinteger(L, 5);
+ col.rgba.b = luax_checkinteger(L, 6);
+ col.rgba.a = luax_checkinteger(L, 7);
+ jsl->sendColor(variable, &col);
+ break;
+ }
+ default:
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_JSL);
+ JSLProgram* jsl = (JSLProgram*)proxy->object;
+ delete jsl;
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"__gc", l_gc },
+ {"send", l_send},
+ {0, 0}
+ };
+
+ /**
+ * JSL program
+ */
+ int luaopen_JSL(lua_State* L)
+ {
+ luax_newtype(L, TYPE_JSL, f);
+ return 0;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/graphics/luaopen_graphics.cpp b/src/lua/graphics/luaopen_graphics.cpp
new file mode 100644
index 0000000..6fa5a4d
--- /dev/null
+++ b/src/lua/graphics/luaopen_graphics.cpp
@@ -0,0 +1,524 @@
+#include "libjin/jin.h"
+#include "lua/luax.h"
+#include "lua/luaopen_types.h"
+#include "lua/embed/graphics.lua.h"
+
+namespace jin
+{
+namespace lua
+{
+ using namespace render;
+ using namespace fs;
+
+ /**
+ * jin.graphics context, storge some module
+ * shared variables.
+ */
+ static struct
+ {
+ color curRenderColor;
+ Font* curFont = 0;
+ Font* defaultFont = 0;
+ } context;
+
+ /**
+ * Init video system.
+ * jin.graphics.init(width, height, title)
+ */
+ static int l_init(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ WindowSetting setting;
+ setting.width = luax_getfield_integer(L, 1, "width");
+ setting.height = luax_getfield_integer(L, 1, "height");
+ setting.title = luax_getfield_string(L, 1, "title");
+ setting.vsync = luax_getfield_bool(L, 1, "vsync");
+ luax_pushboolean(L, wnd->init(&setting));
+ return 1;
+ }
+
+ static int l_destroy(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ wnd->quit();
+ return 0;
+ }
+
+ /**
+ * Get windows size.
+ */
+ static int l_getSize(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ luax_pushnumber(L, wnd->getW());
+ luax_pushnumber(L, wnd->getH());
+ return 2;
+ }
+
+ /**
+ * Create a image userdata and set metatable for it.
+ */
+ static int l_newImage(lua_State* L)
+ {
+ Filesystem* fs = Filesystem::get();
+ const char* f = luax_checkstring(L, 1);
+ if (!fs->exists(f))
+ {
+ printf("Error: no such image %s\n", f);
+ exit(1);
+ }
+ Buffer b;
+ fs->read(f, &b);
+
+ Proxy* proxy = (Proxy*)luax_newinstance(L, TYPE_IMAGE, sizeof(Proxy));
+ Image* img = new Image((const char*)b.data, b.size);
+ proxy->bind(img);
+ return 1;
+ }
+
+ /**
+ * Create a new JSL program.
+ * graphics.Shader(program)
+ */
+ static int l_newShader(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_newinstance(L, TYPE_JSL, sizeof(JSLProgram));
+ const char* program = luax_checkstring(L, 1);
+ JSLProgram* jsl = new JSLProgram(program);
+ proxy->bind(jsl);
+ return 1;
+ }
+
+ /**
+ * Create a new Canvas, don't use it in loop, very slow.
+ * jin.graphics.newCanvas(w, h)
+ */
+ static int l_newCanvas(lua_State* L)
+ {
+ int w = luax_checknumber(L, 1);
+ int h = luax_checknumber(L, 2);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, TYPE_CANVAS, sizeof(Proxy));
+ Canvas* cvs = new Canvas(w, h);
+ proxy->bind(cvs);
+ return 1;
+ }
+
+ static int l_clear(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ glClearColor(0, 0, 0, 1);
+ }
+ else
+ {
+ int r = luax_checknumber(L, 1);
+ int g = luax_checknumber(L, 2);
+ int b = luax_checknumber(L, 3);
+ int a = luax_checknumber(L, 4);
+ glClearColor(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
+ }
+ glClear(GL_COLOR_BUFFER_BIT);
+ return 0;
+ }
+
+ /**
+ * Swap render buffers, present current buffer to front.
+ */
+ static int l_present(lua_State* L)
+ {
+ Window::get()->swapBuffers();
+ return 0;
+ }
+
+ // jin.graphics.draw(x, y, scalex, scaley, r)
+ static int l_draw(lua_State* L)
+ {
+ int x = luax_optnumber(L, 2, 0);
+ int y = luax_optnumber(L, 3, 0);
+ float sx = luax_optnumber(L, 4, 1);
+ float sy = luax_optnumber(L, 5, 1);
+ float r = luax_optnumber(L, 6, 0);
+ if (luax_istype(L, 1, TYPE_IMAGE))
+ {
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ Image* img = (Image*)proxy->object;
+ img->draw(x, y, sx, sy, r);
+ }
+ else if (luax_istype(L, 1, TYPE_CANVAS))
+ {
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ Canvas* p = (Canvas*)proxy->object;
+ p->draw(x, y, sx, sy, r);
+ }
+ else
+ {
+ /* wrong type */
+ luax_typerror(L, 1, "image or canvas");
+ }
+ return 0;
+ }
+
+ static int l_setColor(lua_State* L)
+ {
+ // jin.graphics.color() to set back to default
+ // render color
+ if (luax_gettop(L) == 0)
+ {
+ glColor4f(1, 1, 1, 1);
+ return 0;
+ }
+
+ context.curRenderColor.rgba.r = luax_checknumber(L, 1);
+ context.curRenderColor.rgba.g = luax_checknumber(L, 2);
+ context.curRenderColor.rgba.b = luax_checknumber(L, 3);
+ context.curRenderColor.rgba.a = luax_checknumber(L, 4);
+
+ glColor4f(context.curRenderColor.rgba.r / 255.f,
+ context.curRenderColor.rgba.g / 255.f,
+ context.curRenderColor.rgba.b / 255.f,
+ context.curRenderColor.rgba.a / 255.f);
+ return 0;
+ }
+
+ static int l_getColor(lua_State * L)
+ {
+ luax_pushnumber(L, context.curRenderColor.rgba.r);
+ luax_pushnumber(L, context.curRenderColor.rgba.g);
+ luax_pushnumber(L, context.curRenderColor.rgba.b);
+ luax_pushnumber(L, context.curRenderColor.rgba.a);
+ return 4;
+ }
+
+ static int l_bindCanvas(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ // bind to default canvas
+ Canvas::unbind();
+ return 0;
+ }
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_CANVAS);
+ Canvas* c = (Canvas*)proxy->object;
+ c->bind();
+ return 0;
+ }
+
+ static int l_unbindCanvas(lua_State* L)
+ {
+ Canvas::unbind();
+ return 0;
+ }
+
+ static int l_useShader(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ JSLProgram::unuse();
+ return 0;
+ }
+ if (luax_istype(L, 1, TYPE_JSL))
+ {
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ JSLProgram* jsl = (JSLProgram*)proxy->object;
+ jsl->use();
+ }
+ else
+ {
+ luax_typerror(L, 1, "JSL shader");
+ }
+ return 0;
+ }
+
+ static int l_unuseShader(lua_State* L)
+ {
+ JSLProgram::unuse();
+ return 0;
+ }
+
+ static int l_setBlend(lua_State* L)
+ {
+
+ return 0;
+ }
+
+ static RENDER_MODE strtomode(const char* str)
+ {
+ std::string s = std::string(str);
+ if (s == "fill") return FILL;
+ else if (s == "line") return LINE;
+ else return NONE;
+ }
+
+ /**
+ * draw pixel to screen
+ * jin.graphics.pixel(x, y)
+ */
+ static int l_drawpoint(lua_State* L)
+ {
+ int x = luax_checknumber(L, 1);
+ int y = luax_checknumber(L, 2);
+ render::point(x, y);
+
+ return 0;
+ }
+
+ static int l_drawLine(lua_State* L)
+ {
+ int x1 = luax_checknumber(L, 1);
+ int y1 = luax_checknumber(L, 2);
+ int x2 = luax_checknumber(L, 3);
+ int y2 = luax_checknumber(L, 4);
+ render::line(x1, y1, x2, y2);
+
+ return 0;
+ }
+
+ static int l_drawRect(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != NONE)
+ {
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ int w = luax_checknumber(L, 4);
+ int h = luax_checknumber(L, 5);
+ render::rect(mode, x, y, w, h);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int l_drawCircle(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != NONE)
+ {
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ float r = luax_checknumber(L, 4);
+ render::circle(mode, x, y, r);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int l_drawTriangle(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != NONE)
+ {
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+
+ int x2 = luax_checknumber(L, 3);
+ int y2 = luax_checknumber(L, 4);
+
+ int x3 = luax_checknumber(L, 5);
+ int y3 = luax_checknumber(L, 6);
+
+ render::triangle(mode, x, y, x2, y2, x3, y3);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * draw polygon.
+ * jin.graphics.polygon(mode, n, {{}, {}, {}...})
+ */
+ static int l_drawPolygon(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ int n = luax_checknumber(L, 2);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != NONE)
+ {
+ if (!luax_istable(L, 3))
+ {
+ luax_typerror(L, 3, "table");
+ return 1;
+ }
+ int tn = luax_tableidxlen(L, 3);
+ if (tn != n * 2)
+ {
+ static char* emsg = \
+ "number of polygon vertices doesn't match " \
+ "provided n, expect %d numbers but get %d";
+ luax_error(L, emsg, n * 2, tn);
+ return 1;
+ }
+ float* p = new float[2 * n];
+ for (int i = 1; i <= 2 * n; ++i)
+ p[i - 1] = luax_rawgetnumber(L, 3, i);
+ render::polygon(mode, p, n);
+ delete[] p;
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int l_newFont(lua_State* L)
+ {
+ Font* font = (Font*)luax_newinstance(L, TYPE_FONT, sizeof(Font));
+ const char* path = luax_checkstring(L, 1);
+ Filesystem* fs = Filesystem::get();
+ Buffer b = {};
+ if (!fs->exists(path))
+ {
+ printf("Error: no such font %s\n", path);
+ exit(1);
+ }
+ fs->read(path, &b);
+ font->loadb((const unsigned char*)b.data);
+
+ return 1;
+ }
+
+ /**
+ * study font, 0 args for study default font.
+ */
+ static int l_study(lua_State* L)
+ {
+ int n = luax_gettop(L);
+ if (n == 0)
+ {
+ if (context.defaultFont == 0)
+ {
+ #include "data/font.ttf.h"
+ // load default font
+ context.defaultFont = new Font();
+ context.defaultFont->loadb(font_ttf);
+ }
+ context.curFont = context.defaultFont;
+ return 0;
+ }
+ Font* font = (Font*)luax_checktype(L, 1, TYPE_FONT);
+ context.curFont = font;
+ return 0;
+ }
+
+ /**
+ * draw text with current font(after study). befor write, must
+ * study a font.
+ */
+ static int l_write(lua_State* L)
+ {
+ if (context.curFont == 0)
+ return 0;
+
+ const char* text = luax_checkstring(L, 1);
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+
+ int fh = luax_optnumber(L, 4, 15);
+ int spacing = luax_optnumber(L, 5, 1);
+ int lh = luax_optnumber(L, 6, 18);
+
+ context.curFont->render(text, x, y, fh, spacing, lh);
+
+ return 0;
+ }
+
+ /**
+ * get text bound box
+ */
+ static int l_box(lua_State* L)
+ {
+ const char* text = luax_checkstring(L, 1);
+ int fontheight = luax_checknumber(L, 2);
+ int spacing = luax_checknumber(L, 3);
+ int lineheight = luax_checknumber(L, 4);
+ int w, h;
+ context.curFont->box(text, fontheight, spacing, lineheight, &w, &h);
+ luax_pushnumber(L, w);
+ luax_pushnumber(L, h);
+ return 2;
+ }
+
+ static const luaL_Reg f[] = {
+ {"init", l_init},
+ {"size", l_getSize},
+ {"Image", l_newImage},
+ {"Shader", l_newShader},
+ {"Canvas", l_newCanvas},
+ {"Font", l_newFont},
+ /**
+ * before using box and write
+ * must call study to set
+ * current font
+ */
+ {"box", l_box},
+ {"write", l_write},
+ {"clear", l_clear},
+ {"draw", l_draw},
+ {"color", l_setColor},
+ {"palette", l_getColor},
+ {"present", l_present},
+ //{"blend", l_setBlend},
+ // study font
+ {"study", l_study},
+ // bind canvas
+ {"bind", l_bindCanvas},
+ {"unbind", l_unbindCanvas},
+ // use shader
+ {"use", l_useShader},
+ {"unuse", l_unuseShader},
+ // draw shapes
+ {"point", l_drawpoint},
+ {"line", l_drawLine},
+ {"rect", l_drawRect},
+ {"circle", l_drawCircle},
+ {"triangle", l_drawTriangle},
+ {"polygon", l_drawPolygon},
+ //
+ {"destroy", l_destroy},
+ {0, 0}
+ };
+
+ extern int luaopen_Image(lua_State* L);
+
+ extern int luaopen_Font(lua_State* L);
+
+ extern int luaopen_Canvas(lua_State* L);
+
+ extern int luaopen_JSL(lua_State* L);
+
+ int luaopen_graphics(lua_State* L)
+ {
+ // register types
+ luaopen_Image(L);
+ luaopen_Canvas(L);
+ luaopen_Font(L);
+ luaopen_JSL(L);
+
+ // load whole lib
+ luax_newlib(L, f);
+
+ return 1;
+ }
+
+}// lua
+}// jin