summaryrefslogtreecommitdiff
path: root/src/nvg
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvg')
-rw-r--r--src/nvg/CMakeLists.txt3
-rw-r--r--src/nvg/color.c117
-rw-r--r--src/nvg/composite.c35
-rw-r--r--src/nvg/context.c23
-rw-r--r--src/nvg/frame.c32
-rw-r--r--src/nvg/image.c39
-rw-r--r--src/nvg/nvg.h143
-rw-r--r--src/nvg/path.c117
-rw-r--r--src/nvg/render.c95
-rw-r--r--src/nvg/setup.c30
-rw-r--r--src/nvg/state.c29
-rw-r--r--src/nvg/transform.c86
12 files changed, 749 insertions, 0 deletions
diff --git a/src/nvg/CMakeLists.txt b/src/nvg/CMakeLists.txt
new file mode 100644
index 0000000..8003158
--- /dev/null
+++ b/src/nvg/CMakeLists.txt
@@ -0,0 +1,3 @@
+project(honey_engine)
+
+target_sources(honey PUBLIC ${CMAKE_CURRENT_LIST_DIR}/nvg.c)
diff --git a/src/nvg/color.c b/src/nvg/color.c
new file mode 100644
index 0000000..05f3535
--- /dev/null
+++ b/src/nvg/color.c
@@ -0,0 +1,117 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include "nvg.h"
+
+
+static NVGcolor * create_color(lua_State *L)
+{
+ NVGcolor *color = lua_newuserdata(L, sizeof(NVGcolor));
+ luaL_getmetatable(L, nvg_color_tname);
+ lua_setmetatable(L, -2);
+ return color;
+}
+
+
+int nvgRGB_bind(lua_State *L)
+{
+ unsigned char r, g, b;
+ r = luaL_checkinteger(L, 1);
+ g = luaL_checkinteger(L, 2);
+ b = luaL_checkinteger(L, 3);
+ NVGcolor *c = create_color(L);
+ *c = nvgRGB(r, g, b);
+ return 1;
+}
+
+
+int nvgRGBf_bind(lua_State *L)
+{
+ float r, g, b;
+ r = luaL_checknumber(L, 1);
+ g = luaL_checknumber(L, 2);
+ b = luaL_checknumber(L, 3);
+ NVGcolor *c = create_color(L);
+ *c = nvgRGBf(r, g, b);
+ return 1;
+}
+
+
+int nvgRGBA_bind(lua_State *L)
+{
+ unsigned char r, g, b, a;
+ r = luaL_checkinteger(L, 1);
+ g = luaL_checkinteger(L, 2);
+ b = luaL_checkinteger(L, 3);
+ a = luaL_checkinteger(L, 4);
+ NVGcolor *c = create_color(L);
+ *c = nvgRGBA(r, g, b, a);
+ return 1;
+}
+
+
+int nvgRGBAf_bind(lua_State *L)
+{
+ float r, g, b, a;
+ r = luaL_checknumber(L, 1);
+ g = luaL_checknumber(L, 2);
+ b = luaL_checknumber(L, 3);
+ a = luaL_checknumber(L, 4);
+ NVGcolor *c = create_color(L);
+ *c = nvgRGBAf(r, g, b, a);
+ return 1;
+}
+
+
+int nvgLerpRGBA_bind(lua_State *L)
+{
+ NVGcolor *c0 = luaL_checkudata(L, 1, nvg_color_tname);
+ NVGcolor *c1 = luaL_checkudata(L, 2, nvg_color_tname);
+ float u = luaL_checknumber(L, 3);
+ NVGcolor *result = create_color(L);
+ *result = nvgLerpRGBA(*c0, *c1, u);
+ return 1;
+}
+
+
+int nvgTransRGBA_bind(lua_State *L)
+{
+ NVGcolor *c0 = luaL_checkudata(L, 1, nvg_color_tname);
+ unsigned char a = luaL_checkinteger(L, 2);
+ NVGcolor *result = create_color(L);
+ *result = nvgTransRGBA(*c0, a);
+ return 1;
+}
+
+
+int nvgTransRGBAf_bind(lua_State *L)
+{
+ NVGcolor *c0 = luaL_checkudata(L, 1, nvg_color_tname);
+ float a = luaL_checknumber(L, 2);
+ NVGcolor *result = create_color(L);
+ *result = nvgTransRGBAf(*c0, a);
+ return 1;
+}
+
+
+int nvgHSL_bind(lua_State *L)
+{
+ float h = luaL_checknumber(L, 1);
+ float s = luaL_checknumber(L, 2);
+ float l = luaL_checknumber(L, 3);
+ NVGcolor *result = create_color(L);
+ *result = nvgHSL(h, s, l);
+ return 1;
+}
+
+
+int nvgHSLA_bind(lua_State *L)
+{
+ float h = luaL_checknumber(L, 1);
+ float s = luaL_checknumber(L, 2);
+ float l = luaL_checknumber(L, 3);
+ unsigned char a = luaL_checkinteger(L, 4);
+ NVGcolor *result = create_color(L);
+ *result = nvgHSLA(h, s, l, a);
+ return 1;
+}
diff --git a/src/nvg/composite.c b/src/nvg/composite.c
new file mode 100644
index 0000000..be5ff1f
--- /dev/null
+++ b/src/nvg/composite.c
@@ -0,0 +1,35 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include "nvg.h"
+
+
+int nvgGlobalCompositeOperation_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int op = luaL_checkinteger(L, 2);
+ nvgGlobalCompositeOperation(*ctx, op);
+ return 0;
+}
+
+
+int nvgGlobalCompositeBlendFunc_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int sfactor = luaL_checkinteger(L, 2);
+ int dfactor = luaL_checkinteger(L, 3);
+ nvgGlobalCompositeBlendFunc(*ctx, sfactor, dfactor);
+ return 0;
+}
+
+
+int nvgGlobalCompositeBlendFuncSeparate_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int src_rgb = luaL_checkinteger(L, 2);
+ int dst_rgb = luaL_checkinteger(L, 3);
+ int src_alpha = luaL_checkinteger(L, 4);
+ int dst_alpha = luaL_checkinteger(L, 5);
+ nvgGlobalCompositeBlendFuncSeparate(*ctx, src_rgb, dst_rgb, src_alpha, dst_alpha);
+ return 0;
+}
diff --git a/src/nvg/context.c b/src/nvg/context.c
new file mode 100644
index 0000000..48a7282
--- /dev/null
+++ b/src/nvg/context.c
@@ -0,0 +1,23 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "nvg.h"
+
+
+int nvgCreateContext_bind(lua_State *L)
+{
+ struct NVGcontext **vg = lua_newuserdata(L, sizeof(struct NVGcontext *));
+ *vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
+ luaL_getmetatable(L, nvg_ctx_tname);
+ lua_setmetatable(L, -2);
+ return 1;
+}
+
+
+int nvgDeleteContext_bind(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgDeleteGL3(*vg);
+ return 0;
+}
diff --git a/src/nvg/frame.c b/src/nvg/frame.c
new file mode 100644
index 0000000..0012431
--- /dev/null
+++ b/src/nvg/frame.c
@@ -0,0 +1,32 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include "nvg.h"
+
+
+int nvgBeginFrame_bind(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
+ float width = luaL_checknumber(L, 2);
+ float height = luaL_checknumber(L, 3);
+ float pixelRatio = luaL_checknumber(L, 4);
+
+ nvgBeginFrame(*vg, width, height, pixelRatio);
+ return 0;
+}
+
+
+int nvgCancelFrame_bind(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgCancelFrame(*vg);
+ return 0;
+}
+
+
+int nvgEndFrame_bind(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgEndFrame(*vg);
+ return 0;
+}
diff --git a/src/nvg/image.c b/src/nvg/image.c
new file mode 100644
index 0000000..e7f39c2
--- /dev/null
+++ b/src/nvg/image.c
@@ -0,0 +1,39 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "nvg.h"
+
+
+int CreateImage_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ const char *filename = luaL_checkstring(L, 2);
+ int flags = luaL_checkinteger(L, 3);
+ int *handle = lua_newuserdata(L, sizeof(int));
+ luaL_getmetatable(L, nvg_image_tname);
+ lua_setmetatable(L, -2);
+ *handle = nvgCreateImage(*ctx, filename, flags);
+ return 1;
+}
+
+
+int nvgImageSize_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int *handle = luaL_checkudata(L, 2, nvg_image_tname);
+ int w, h;
+ nvgImageSize(*ctx, *handle, &w, &h);
+ lua_pushinteger(L, w);
+ lua_pushinteger(L, h);
+ return 2;
+}
+
+
+int nvgDeleteImage_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int *handle = luaL_checkudata(L, 2, nvg_image_tname);
+ nvgDeleteImage(*ctx, *handle);
+ return 0;
+}
diff --git a/src/nvg/nvg.h b/src/nvg/nvg.h
new file mode 100644
index 0000000..33a2420
--- /dev/null
+++ b/src/nvg/nvg.h
@@ -0,0 +1,143 @@
+#ifndef HONEY_VECTOR_H
+#define HONEY_VECTOR_H
+
+#include <lua.h>
+
+
+extern const char *nvg_ctx_tname;
+extern const char *nvg_color_tname;
+extern const char *nvg_paint_tname;
+
+
+#define NVG_FUNCTIONS \
+ /* context */ \
+ X("CreateContext", nvgCreateContext_bind) \
+ X("DeleteContext", nvgDeleteContext_bind) \
+ \
+ /* frame control */ \
+ X("BeginFrame", nvgBeginFrame_bind) \
+ X("CancelFrame", nvgCancelFrame_bind) \
+ X("EndFrame", nvgEndFrame_bind) \
+ \
+ /* composite operation */ \
+ X("GlobalCompositeOperation", nvgGlobalCompositeOperation_bind) \
+ X("GlobalCompositeBlendFunc", nvgGlobalCompositeBlendFunc_bind) \
+ X("GlobalCompositeBlendFuncSeparate", nvgGlobalCompositeBlendFuncSeparate_bind) \
+ \
+ /* color utils */ \
+ X("RGB", nvgRGB_bind) \
+ X("RGBf", nvgRGBf_bind) \
+ X("RGBA", nvgRGBA_bind) \
+ X("RGBAf", nvgRGBAf_bind) \
+ X("LerpRGBA", nvgLerpRGBA_bind) \
+ X("TransRGBA", nvgTransRGBA_bind) \
+ X("TransRGBAf", nvgTransRGBAf_bind) \
+ X("HSL", nvgHSL_bind) \
+ X("HSLA", nvgHSLA_bind) \
+ \
+ /* state handling */ \
+ X("Save", nvgSave_bind) \
+ X("Restore", nvgRestore_bind) \
+ X("Reset", nvgReset_bind) \
+ \
+ /* render styles */ \
+ X("ShapeAntiAlias", nvgShapeAntiAlias_bind) \
+ X("StrokeColor", nvgStrokeColor_bind) \
+ X("StrokePaint", nvgStrokePaint_bind) \
+ X("FillColor", nvgFillColor_bind) \
+ X("FillPaint", nvgFillPaint_bind) \
+ X("MiterLimit", nvgMiterLimit_bind) \
+ X("StrokeWidth", nvgStrokeWidth_bind) \
+ X("LineCap", nvgLineCap_bind) \
+ X("LineJoin", nvgLineJoin_bind) \
+ X("GlobalAlpha", nvgGlobalAlpha_bind) \
+ \
+ /* transforms */ \
+ X("ResetTransform", nvgResetTransform_bind) \
+ X("Transform", nvgTransform_bind) \
+ X("Translate", nvgTranslate_bind) \
+ X("Rotate", nvgRotate_bind) \
+ X("SkewX", nvgSkewX_bind) \
+ X("SkewY", nvgSkewY_bind) \
+ X("Scale", nvgScale_bind) \
+ X("CurrentTransform", nvgCurrentTransform_bind) \
+ /* X("TransformIdentity", nvgTransformIdentity_bind) */ \
+ /* X("TransformTranslate", nvgTransformTranslate_bind) */ \
+ /* X("TransformScale", nvgTransformScale_bind) */ \
+ /* X("TransformRotate", nvgTransformRotate_bind) */ \
+ /* X("TransformSkewX", nvgTransformSkewX_bind) */ \
+ /* X("TransformSkewY", nvgTransformSkewY_bind) */ \
+ /* X("TransformMultiply", nvgTransformMultiply_bind) */ \
+ /* X("TransformPremultiply", nvgTransformPremultiply_bind) */ \
+ /* X("TransformInverse", nvgTransformInverse_bind) */ \
+ /* X("TransformPoint", nvgTransformPoint_bind) */ \
+ \
+ /* images */ \
+ X("CreateImage", nvgCreateImage_bind) \
+ /* X("CreateImageMem", nvgCreateImageMem_bind) */ \
+ /* X("CreateImageRGBA", nvgCreateImageRGBA_bind) */ \
+ /* X("UpdateImage", nvgUpdateImage_bind) */ \
+ X("ImageSize", nvgImageSize_bind) \
+ X("DeleteImage", nvgDeleteImage_bind) \
+ \
+ /* paints */ \
+ X("LinearGradient", nvgLinearGradient_bind) \
+ X("BoxGradient", nvgBoxGradient_bind) \
+ X("RadialGradient", nvgRadialGradient_bind) \
+ X("ImagePattern", nvgImagePattern_bind) \
+ \
+ /* scissoring */ \
+ X("Scissor", nvgScissor_bind) \
+ X("IntersectScissor", nvgIntersectScissor_bind) \
+ X("ResetScissor", nvgResetScissor_bind) \
+ \
+ /* paths */ \
+ X("BeginPath", nvgBeginPath_bind) \
+ X("MoveTo", nvgMoveTo_bind) \
+ X("LineTo", nvgLineTo_bind) \
+ X("BezierTo", nvgBezierTo_bind) \
+ X("QuadTo", nvgQuadTo_bind) \
+ X("ArcTo", nvgArcTo_bind) \
+ X("ClosePath", nvgClosePath_bind) \
+ X("PathWinding", nvgPathWinding_bind) \
+ X("Arc", nvgArc_bind) \
+ X("Rect", nvgRect_bind) \
+ X("RoundedRect", nvgRoundedRect_bind) \
+ X("RoundedRectVarying", nvgRoundedRectVarying_bind) \
+ X("Ellipse", nvgEllipse_bind) \
+ X("Circle", nvgCircle_bind) \
+ X("Fill", nvgFill_bind) \
+ X("Stroke", nvgStroke_bind) \
+ \
+ /* text */ \
+ X("CreateFont", nvgCreateFont_bind) \
+ X("CreateFontAtIndex", nvgCreateFontAtIndex_bind) \
+ X("CreateFontMem", nvgCreateFontMem_bind) \
+ X("CreateFontMemAtIndex", nvgCreateFontMemAtIndex_bind) \
+ X("FindFont", nvgFindFont_bind) \
+ X("AddFallbackFontId", nvgAddFallbackFontId_bind) \
+ X("AddFallbackFont", nvgAddFallbackFont_bind) \
+ X("ResetFallbackFontsId", nvgResetFallbackFontsId_bind) \
+ X("ResetFallbackFonts", nvgResetFallbackFonts_bind) \
+ X("FontSize", nvgFontSize_bind) \
+ X("FontBlur", nvgFontBlur_bind) \
+ X("TextLetterSpacing", nvgTextLetterSpacing_bind) \
+ X("TextLineHeight", nvgTextLineHeight_bind) \
+ X("TextAlign", nvgTextAlign_bind) \
+ X("FontFaceId", nvgFontFaceId_bind) \
+ X("FontFace", nvgFontFace_bind) \
+ X("Text", nvgText_bind) \
+ X("TextBox", nvgTextBox_bind) \
+ X("TextBounds", nvgTextBounds_bind) \
+ X("TextBoxBounds", nvgTextBoxBounds_bind) \
+ X("TextGlyphPositions", nvgTextGlyphPositions_bind) \
+ X("TextMetrics", nvgTextMetrics_bind) \
+ X("TextBreakLines", nvgTextBreakLines_bind) \
+
+
+/* function declarations */
+#define X(unused, name) int name(lua_State *L);
+NVG_FUNCTIONS
+#undef X
+
+#endif
diff --git a/src/nvg/path.c b/src/nvg/path.c
new file mode 100644
index 0000000..1e0f527
--- /dev/null
+++ b/src/nvg/path.c
@@ -0,0 +1,117 @@
+/* --===== paths =====-- */
+
+int nvg_begin_path(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ nvgBeginPath(*vg);
+ return 0;
+}
+
+
+int nvg_move_to(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float x = luaL_checknumber(L, 2);
+ float y = luaL_checknumber(L, 3);
+ nvgMoveTo(*vg, x, y);
+ return 0;
+}
+
+
+int nvg_line_to(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float x = luaL_checknumber(L, 2);
+ float y = luaL_checknumber(L, 3);
+ nvgLineTo(*vg, x, y);
+ return 0;
+}
+
+
+int nvg_bezier_to(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float c1x = luaL_checknumber(L, 2);
+ float c1y = luaL_checknumber(L, 3);
+ float c2x = luaL_checknumber(L, 4);
+ float c2y = luaL_checknumber(L, 5);
+ float x = luaL_checknumber(L, 6);
+ float y = luaL_checknumber(L, 7);
+ nvgBezierTo(*vg, c1x, c1y, c2x, c2y, x, y);
+ return 0;
+}
+
+
+int nvg_quad_to(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float cx = luaL_checknumber(L, 2);
+ float cy = luaL_checknumber(L, 3);
+ float x = luaL_checknumber(L, 4);
+ float y = luaL_checknumber(L, 5);
+ nvgQuadTo(*vg, cx, cy, x, y);
+ return 0;
+}
+
+
+int nvg_arc_to(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float x1 = luaL_checknumber(L, 2);
+ float y1 = luaL_checknumber(L, 3);
+ float x2 = luaL_checknumber(L, 4);
+ float y2 = luaL_checknumber(L, 5);
+ float radius = luaL_checknumber(L, 6);
+ nvgArcTo(*vg, x1, y1, x2, y2, radius);
+ return 0;
+}
+
+
+int nvg_close_path(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ nvgClosePath(*vg);
+ return 0;
+}
+
+
+int nvg_path_winding(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ int dir = luaL_checkinteger(L, 2);
+ nvgPathWinding(*vg, dir);
+ return 0;
+}
+
+
+int nvg_arc(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float cx = luaL_checknumber(L, 2);
+ float cy = luaL_checknumber(L, 3);
+ float r = luaL_checknumber(L, 4);
+ float a0 = luaL_checknumber(L, 5);
+ float a1 = luaL_checknumber(L, 6);
+ int dir = luaL_checkinteger(L, 7);
+ nvgArc(*vg, cx, cy, r, a0, a1, dir);
+ return 0;
+}
+
+/* ... */
+
+int nvg_fill(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ nvgFill(*vg);
+ return 0;
+}
+
+
+int nvg_stroke(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ nvgStroke(*vg);
+ return 0;
+}
+
+
diff --git a/src/nvg/render.c b/src/nvg/render.c
new file mode 100644
index 0000000..f28da90
--- /dev/null
+++ b/src/nvg/render.c
@@ -0,0 +1,95 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "nvg.h"
+
+
+int ShapeAntiAlias_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int enabled = luaL_toboolean(L, 2);
+ nvgShapeAntiAlias(*ctx, enabled);
+ return 0;
+}
+
+
+int nvgStrokeColor_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ NVGcolor *color = luaL_checkudata(L, 2, nvg_color_tname);
+ nvgStrokeColor(*ctx, *color);
+ return 0;
+}
+
+
+int nvgStrokePaint_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ NVGpaint *paint = luaL_checkudata(L, 2, nvg_paint_tname);
+ nvgStrokePaint(*ctx, *paint);
+ return 0;
+}
+
+
+int nvgFillColor_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ NVGcolor *color = luaL_checkudata(L, 2, nvg_color_tname);
+ nvgFillColor(*ctx, *color);
+ return 0;
+}
+
+
+int nvgFillPaint_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ NVGpaint *paint = luaL_checkudata(L, 2, nvg_paint_tname);
+ nvgFillPaint(*ctx, *paint);
+ return 0;
+}
+
+
+int nvgMiterLimit_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ float limit = luaL_checknumber(L, 2);
+ nvgMiterLimit(*ctx, limit);
+ return 0;
+}
+
+
+int nvgStrokeWidth_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ float width = luaL_checknumber(L, 2);
+ nvgStrokeWidth(*ctx, width);
+ return 0;
+}
+
+
+int nvgLineCap_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int cap = luaL_checkinteger(L, 2);
+ nvgLineCap(*ctx, cap);
+ return 0;
+}
+
+
+int nvgLineJoin_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int join = luaL_checkinteger(L, 2);
+ nvgLineJoin(*ctx, join);
+ return 0;
+}
+
+
+int nvgGlobalAlpha_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ float alpha = luaL_checknumber(L, 2);
+ nvgGlobalAlpha(*ctx, alpha);
+ return 0;
+}
diff --git a/src/nvg/setup.c b/src/nvg/setup.c
new file mode 100644
index 0000000..16766c0
--- /dev/null
+++ b/src/nvg/setup.c
@@ -0,0 +1,30 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include "gl/glad/glad.h"
+#include <GLFW/glfw3.h>
+#define NANOVG_GL3_IMPLEMENTATION
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "util/util.h"
+#include "nvg.h"
+
+
+const char *nvg_ctx_tname = "nvg.Context";
+const char *nvg_color_tname = "nvg.Color";
+
+
+void setup_nvg(lua_State *L, int honey_tbl)
+{
+ luaL_newmetatable(L, nvg_ctx_tname); lua_pop(L, 1);
+ luaL_newmetatable(L, nvg_color_tname); lua_pop(L, 1);
+
+ struct honey_tbl_t nvg[] = {
+ #define X(name, func) H_FUNC(name, func),
+ NVG_FUNCTIONS
+ #undef X
+ H_END,
+ };
+ create_table(L, nvg);
+
+ lua_setfield(L, honey_tbl, "nvg");
+}
diff --git a/src/nvg/state.c b/src/nvg/state.c
new file mode 100644
index 0000000..e2ab73a
--- /dev/null
+++ b/src/nvg/state.c
@@ -0,0 +1,29 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "nvg.h"
+
+
+int nvgSave_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgSave(*ctx);
+ return 0;
+}
+
+
+int nvgRestore_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgRestore(*ctx);
+ return 0;
+}
+
+
+int nvgReset_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgReset(*ctx);
+ return 0;
+}
diff --git a/src/nvg/transform.c b/src/nvg/transform.c
new file mode 100644
index 0000000..a4ab1eb
--- /dev/null
+++ b/src/nvg/transform.c
@@ -0,0 +1,86 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "nvg.h"
+
+
+int nvgResetTransform_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ nvgResetTransform(*ctx);
+ return 0;
+}
+
+
+int nvgTransform_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float a = luaL_checknumber(L, 2);
+ float b = luaL_checknumber(L, 3);
+ float c = luaL_checknumber(L, 4);
+ float d = luaL_checknumber(L, 5);
+ float e = luaL_checknumber(L, 6);
+ float f = luaL_checknumber(L, 7);
+ nvgTransform(ctx, a, b, c, d, e, f);
+ return 0;
+}
+
+
+int nvgTranslate_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float x = luaL_checknumber(L, 2);
+ float y = luaL_checknumber(L, 3);
+ nvgTranslate(*ctx, x, y);
+ return 0;
+}
+
+
+int nvgRotate_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float angle = luaL_checknumber(L, 2);
+ nvgRotate(*ctx, angle);
+ return 0;
+}
+
+
+int nvgSkewX_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float angle = luaL_checknumber(L, 2);
+ nvgSkewX(*ctx, angle);
+ return 0;
+}
+
+
+int nvgSkewY_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float angle = luaL_checknumber(L, 2);
+ nvgSkewY(*ctx, angle);
+ return 0;
+}
+
+
+int nvgScale_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float x = luaL_checknumber(L, 2);
+ float y = luaL_checknumber(L, 3);
+ nvgScale(*ctx, x, y);
+ return 0;
+}
+
+
+int nvgCurrentTransform_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudate(L, 1, nvg_ctx_tname);
+ float xform[6];
+ nvgCurrentTransform(*ctx, xform);
+ for (int i=0; i<6; i++) {
+ lua_pushnumber(L, xform[i]);
+ }
+ return 6;
+}