ref: 307ba8a8d9d7c0088462bc4e947639b4593ce597
dir: /api.c/
#include "a.h" typedef struct Tmatrix Tmatrix; typedef struct Style Style; struct Tmatrix { Point origin; double angle; }; struct Style { int nostroke; int strokecap; Image *stroke; int strokeweight; int nofill; Image *fill; }; enum { Crgb, Chsv, }; int looping; int framerate; Image *canvas; int width; int height; int colormode; int nostroke; int strokecap; Image *stroke; int strokeweight; int nofill; Image *fill; Point origin; double angle; Tmatrix tstack[255] = {0}; int ntstack; Style sstack[255] = {0}; int nsstack; void initstate(lua_State *L) { Rectangle r; ntstack = 0; looping = 1; framerate = 90; width = 500; height = 500; r = Rect(0, 0, width, height); canvas = allocimage(display, r, screen->chan, 0, DWhite); colormode = Crgb; nostroke = 0; strokecap = Endsquare; stroke = display->black; strokeweight = 0; nofill = 0; fill = display->white; origin = ZP; angle = 0.0; lset(L, "mouseX", 0); lset(L, "mouseY", 0); lpushpixels(L); } void reset(void) { origin = ZP; angle = 0.0; } void drawcanvas(void) { draw(screen, screen->r, canvas, nil, ZP); flushimage(display, 1); } Point canvaspt(int x, int y) { Point p; p = Pt(x, y); if(fabs(angle) > 0.000001){ p.x = x * cos(angle) - y * sin(angle); p.y = x * sin(angle) + y * cos(angle); } p = addpt(p, origin); return p; } int cnoloop(lua_State*) { looping = 0; return 0; } int cloop(lua_State*) { looping = 1; return 0; } int cframerate(lua_State *L) { int n; n = luaL_checkinteger(L, 1); if(n < 0) return luaL_argerror(L, 1, "framerate should be greater than 0"); framerate = n; return 0; } int csize(lua_State *L) { int w, h; w = luaL_checkinteger(L, 1); h = luaL_checkinteger(L, 2); if(drawing) return 0; width = w; height = h; freeimage(canvas); canvas = allocimage(display, Rect(0, 0, w, h), screen->chan, 0, DNofill); lpushpixels(L); resize(L, w, h); return 0; } void checkcolor(lua_State *L, int index, int *r, int *g, int *b) { lua_pushstring(L, "r"); lua_gettable(L, index); *r = luaL_checkinteger(L, -1); lua_pushstring(L, "g"); lua_gettable(L, index); *g = luaL_checkinteger(L, -1); lua_pushstring(L, "b"); lua_gettable(L, index); *b = luaL_checkinteger(L, -1); } void pushcolor(lua_State *L, int r, int g, int b) { lua_newtable(L); lua_pushinteger(L, r); lua_setfield(L, -2, "r"); lua_pushinteger(L, g); lua_setfield(L, -2, "g"); lua_pushinteger(L, b); lua_setfield(L, -2, "b"); } Image* getcolor(lua_State *L) { Image *i; int c, r, g, b; c = lua_gettop(L); if(c == 1){ if(lua_istable(L, 1)) checkcolor(L, 1, &r, &g, &b); else r = g = b = luaL_checkinteger(L, 1); i = color(r, g, b, 0); }else if(c == 3){ r = luaL_checkinteger(L, 1); g = luaL_checkinteger(L, 2); b = luaL_checkinteger(L, 3); i = color(r, g, b, colormode == Chsv); }else{ luaL_error(L, "invalid argument count (expected 1 or 3 but received %d)", c); return nil; } return i; } int ccolormode(lua_State *L) { int n; n = luaL_checkinteger(L, 1); if(n != Crgb && n != Chsv) return luaL_argerror(L, 1, "expected RGB or HSV"); colormode = n; return 0; } int cbackground(lua_State *L) { Image *i; i = getcolor(L); draw(canvas, canvas->r, i, nil, ZP); return 0; } int cnostroke(lua_State*) { nostroke = 1; return 0; } int cstrokecap(lua_State *L) { int n; n = luaL_checkinteger(L, 1); if(n == Endsquare || n == Enddisc) strokecap = n; return 0; } int cstroke(lua_State *L) { Image *i; i = getcolor(L); stroke = i; nostroke = 0; return 0; } int cnofill(lua_State*) { nofill = 1; return 0; } int cfill(lua_State *L) { Image *i; i = getcolor(L); fill = i; nofill = 0; return 0; } int cstrokeweight(lua_State *L) { int n; n = luaL_checkinteger(L, 1); strokeweight = n/2; return 0; } int cpoint(lua_State *L) { Point p1, p2; int x, y; x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); p1 = canvaspt(x, y); p2 = canvaspt(x + strokeweight, y + strokeweight); if(!nostroke) if(strokecap == Endsquare) draw(canvas, Rpt(p1, p2), stroke, nil, ZP); else if(strokecap == Enddisc) fillellipse(canvas, p1, strokeweight/2.0, strokeweight/2.0, stroke, ZP); return 0; } int cline(lua_State *L) { Point p1, p2; int x1, x2, y1, y2; x1 = luaL_checkinteger(L, 1); y1 = luaL_checkinteger(L, 2); x2 = luaL_checkinteger(L, 3); y2 = luaL_checkinteger(L, 4); p1 = canvaspt(x1, y1); p2 = canvaspt(x2, y2); if(!nostroke) line(canvas, p1, p2, strokecap, strokecap, strokeweight, stroke, ZP); return 0; } int csquare(lua_State *L) { Point p[5]; int x, y, w; x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); w = luaL_checkinteger(L, 3); p[0] = canvaspt(x, y); p[1] = canvaspt(x + w, y); p[2] = canvaspt(x + w, y + w); p[3] = canvaspt(x, y+w); p[4] = p[0]; if(!nofill) fillpoly(canvas, p, 4, 0, fill, ZP); if(!nostroke) poly(canvas, p, 5, strokecap, strokecap, strokeweight, stroke, ZP); return 0; } int crect(lua_State *L) { Point p[5]; int x, y, w, h; x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); w = luaL_checkinteger(L, 3); h = luaL_checkinteger(L, 4); p[0] = canvaspt(x, y); p[1] = canvaspt(x + w, y); p[2] = canvaspt(x + w, y + h); p[3] = canvaspt(x, y + h); p[4] = p[0]; if(!nofill) fillpoly(canvas, p, 4, 0, fill, ZP); if(!nostroke) poly(canvas, p, 5, strokecap, strokecap, strokeweight, stroke, ZP); return 0; } int ccircle(lua_State *L) { Point p; int x, y, a; x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); a = luaL_checkinteger(L, 3) / 2; p = canvaspt(x, y); if(!nofill) fillellipse(canvas, p, a, a, fill, ZP); if(!nostroke) ellipse(canvas, p, a, a, strokeweight, stroke, ZP); return 0; } int cellipse(lua_State *L) { Point p; int x, y, a, b; x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); a = luaL_checkinteger(L, 3) / 2; b = luaL_checkinteger(L, 4) / 2; p = canvaspt(x, y); if(!nofill) fillellipse(canvas, p, a, b, fill, ZP); if(!nostroke) ellipse(canvas, p, a, b, strokeweight, stroke, ZP); return 0; } int carc(lua_State *L) { Point p; int x, y, a, b, c, d; x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); a = luaL_checkinteger(L, 3); b = luaL_checkinteger(L, 4); c = luaL_checknumber(L, 5) * 180.0/PI; d = luaL_checknumber(L, 6) * 180.0/PI; p = canvaspt(x, y); if(!nofill) fillarc(canvas, p, a, b, fill, ZP, c, d); if(!nostroke) arc(canvas, p, a, b, strokeweight, stroke, ZP, c, d); return 0; } int cbezier(lua_State *L) { Point p0, p1, p2, p3; int x1, y1, x2, y2, x3, y3, x4, y4; x1 = luaL_checkinteger(L, 1); y1 = luaL_checkinteger(L, 2); x2 = luaL_checkinteger(L, 3); y2 = luaL_checkinteger(L, 4); x3 = luaL_checkinteger(L, 5); y3 = luaL_checkinteger(L, 6); x4 = luaL_checkinteger(L, 7); y4 = luaL_checkinteger(L, 8); p0 = canvaspt(x1, y1); p1 = canvaspt(x2, y2); p2 = canvaspt(x3, y3); p3 = canvaspt(x4, y4); if(!nostroke) bezier(canvas, p0, p1, p2, p3, strokecap, strokecap, strokeweight, stroke, ZP); return 0; } int ctriangle(lua_State *L) { Point p[4]; int x1, y1, x2, y2, x3, y3; x1 = luaL_checkinteger(L, 1); y1 = luaL_checkinteger(L, 2); x2 = luaL_checkinteger(L, 3); y2 = luaL_checkinteger(L, 4); x3 = luaL_checkinteger(L, 5); y3 = luaL_checkinteger(L, 6); p[0] = canvaspt(x1, y1); p[1] = canvaspt(x2, y2); p[2] = canvaspt(x3, y3); p[3] = p[0]; if(!nofill) fillpoly(canvas, p, 3, 0, fill, ZP); if(!nostroke) poly(canvas, p, 4, strokecap, strokecap, strokeweight, stroke, ZP); return 0; } int cquad(lua_State *L) { Point p[5]; int x1, y1, x2, y2, x3, y3, x4, y4; x1 = luaL_checkinteger(L, 1); y1 = luaL_checkinteger(L, 2); x2 = luaL_checkinteger(L, 3); y2 = luaL_checkinteger(L, 4); x3 = luaL_checkinteger(L, 5); y3 = luaL_checkinteger(L, 6); x4 = luaL_checkinteger(L, 7); y4 = luaL_checkinteger(L, 8); p[0] = canvaspt(x1, y1); p[1] = canvaspt(x2, y2); p[2] = canvaspt(x3, y3); p[3] = canvaspt(x4, y4); p[4] = p[0]; if(!nofill) fillpoly(canvas, p, 4, 0, fill, ZP); if(!nostroke) poly(canvas, p, 5, strokecap, strokecap, strokeweight, stroke, ZP); return 0; } int ctranslate(lua_State *L) { int x, y; x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); origin = addpt(origin, Pt(x, y)); return 0; } int crotate(lua_State *L) { angle += luaL_checknumber(L, 1); return 0; } int cradians(lua_State *L) { int a; a = luaL_checkinteger(L, 1); lua_pushnumber(L, a*PI/180.0); return 1; } int cpushmatrix(lua_State *L) { if(ntstack == nelem(tstack) - 1) return luaL_error(L, "stack overflow"); tstack[ntstack].origin = origin; tstack[ntstack].angle = angle; ntstack++; return 0; } int cpopmatrix(lua_State *L) { if(ntstack == 0) return luaL_error(L, "stack underflow"); ntstack--; origin = tstack[ntstack].origin; angle = tstack[ntstack].angle; return 0; } int cpushstyle(lua_State *L) { if(nsstack == nelem(sstack) - 1) return luaL_error(L, "stack overflow"); sstack[nsstack].nostroke = nostroke; sstack[nsstack].strokecap = strokecap; sstack[nsstack].stroke = stroke; sstack[nsstack].strokeweight = strokeweight; sstack[nsstack].nofill = nofill; sstack[nsstack].fill = fill; nsstack++; return 0; } int cpopstyle(lua_State *L) { if(nsstack == 0) return luaL_error(L, "stack underflow"); nsstack--; nostroke = sstack[nsstack].nostroke; strokecap = sstack[nsstack].strokecap; stroke = sstack[nsstack].stroke; strokeweight = sstack[nsstack].strokeweight; nofill = sstack[nsstack].nofill; fill = sstack[nsstack].fill; return 0; } int cpush(lua_State *L) { cpushmatrix(L); cpushstyle(L); return 0; } int cpop(lua_State *L) { cpopmatrix(L); cpopstyle(L); return 0; } int ccolor(lua_State *L) { int r, g, b; r = luaL_checkinteger(L, 1); g = luaL_checkinteger(L, 2); b = luaL_checkinteger(L, 3); if(colormode == Chsv) hsvtorgb(r, g, b, &r, &g, &b); pushcolor(L, r, g, b); return 1; } int clerpcolor(lua_State *L) { int r0, g0, b0, r1, g1, b1, r, g, b; double f; checkcolor(L, 1, &r0, &g0, &b0); checkcolor(L, 2, &r1, &g1, &b1); f = luaL_checknumber(L, 3); if(f < 0.0) f = 0.0; else if(f > 1.0) f = 1.0; r = f * (r1 - r0) + r0; g = f * (g1 - g0) + g0; b = f * (b1 - b0) + b0; pushcolor(L, r, g, b); return 1; } int cloadpixels(lua_State *L) { char ebuf[ERRMAX]; if(unloadimage(canvas, canvas->r, pixels->data, pixels->ndata) < 0){ errstr(ebuf, sizeof ebuf); return luaL_error(L, "unable to load pixels: %s", ebuf); } return 0; } int cupdatepixels(lua_State *L) { char ebuf[ERRMAX]; if(loadimage(canvas, canvas->r, pixels->data, pixels->ndata) < 0){ errstr(ebuf, sizeof ebuf); return luaL_error(L, "unable to update pixels: %s", ebuf); } return 0; } int cconstrain(lua_State *L) { double fa, fm, fM; int ia, im, iM; if(lua_isinteger(L, 1)){ ia = luaL_checkinteger(L, 1); im = luaL_checkinteger(L, 2); iM = luaL_checkinteger(L, 3); if(ia < im) ia = im; else if(ia > iM) ia = iM; lua_pushinteger(L, ia); }else{ fa = luaL_checknumber(L, 1); fm = luaL_checknumber(L, 2); fM = luaL_checknumber(L, 3); if(fa < fm) fa = fm; else if(fa > fM) fa = fM; lua_pushnumber(L, fa); } return 1; } int cmap(lua_State *L) { double v, s1, e1, s2, e2; int n; n = lua_gettop(L); if(n != 5) return luaL_error(L, "invalid argument count (expected 5 but got %d)", n); v = luaL_checknumber(L, 1); s1 = luaL_checknumber(L, 2); e1 = luaL_checknumber(L, 3); s2 = luaL_checknumber(L, 4); e2 = luaL_checknumber(L, 5); lua_pushnumber(L, map(v, s1, e1, s2, e2)); return 1; } int cnorm(lua_State *L) { double v, s1, e1; int n; n = lua_gettop(L); if(n != 3) return luaL_error(L, "invalid argument count (expected 3 but got %d)", n); v = luaL_checknumber(L, 1); s1 = luaL_checknumber(L, 2); e1 = luaL_checknumber(L, 3); lua_pushnumber(L, map(v, s1, e1, 0.0, 1.0)); return 1; } int cdist(lua_State *L) { int n, x1, y1, x2, y2; n = lua_gettop(L); if(n != 4) return luaL_error(L, "invalid argument count (expected 4 but got %d)", n); x1 = luaL_checkinteger(L, 1); y1 = luaL_checkinteger(L, 2); x2 = luaL_checkinteger(L, 3); y2 = luaL_checkinteger(L, 4); lua_pushnumber(L, dist(x1, y1, x2, y2)); return 1; } int cmag(lua_State *L) { int n, x, y; n = lua_gettop(L); if(n != 2) return luaL_error(L, "invalid argument count (expected 2 but got %d)", n); x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); lua_pushnumber(L, dist(0, 0, x, y)); return 1; } int clerp(lua_State *L) { double r, a, b; int n; n = lua_gettop(L); if(n != 3) return luaL_error(L, "invalid argument count (expected 3 but got %d)", n); a = luaL_checknumber(L, 1); b = luaL_checknumber(L, 2); r = luaL_checknumber(L, 3); lua_pushnumber(L, lerp(a, b, r)); return 1; } int crandomgaussian(lua_State *L) { double m, s, g; int n; m = 0.0; s = 1.0; n = lua_gettop(L); switch(n){ case 2: s = luaL_checknumber(L, 2); case 1: m = luaL_checknumber(L, 1); break; case 0: break; default: luaL_error(L, "invalid argument count"); } g = randomgaussian(m, s); lua_pushnumber(L, g); return 1; } void registerfunc(lua_State *L, const char *name, int(*f)(lua_State*)) { lua_pushcfunction(L, f); lua_setglobal(L, name); } void registermathfunc(lua_State *L, const char *name, lua_CFunction f) { lua_getglobal(L, "math"); lua_pushcfunction(L, f); lua_setfield(L, 1, name); } void registerapi(lua_State *L) { lset(L, "RGB", Crgb); lset(L, "HSV", Chsv); lset(L, "SQUARE", Endsquare); lset(L, "ROUND", Enddisc); registerfunc(L, "noLoop", cnoloop); registerfunc(L, "loop", cloop); registerfunc(L, "frameRate", cframerate); registerfunc(L, "size", csize); registerfunc(L, "colorMode", ccolormode); registerfunc(L, "background", cbackground); registerfunc(L, "noStroke", cnostroke); registerfunc(L, "strokeCap", cstrokecap); registerfunc(L, "stroke", cstroke); registerfunc(L, "strokeWeight", cstrokeweight); registerfunc(L, "noFill", cnofill); registerfunc(L, "fill", cfill); registerfunc(L, "point", cpoint); registerfunc(L, "line", cline); registerfunc(L, "square", csquare); registerfunc(L, "rect", crect); registerfunc(L, "circle", ccircle); registerfunc(L, "ellipse", cellipse); registerfunc(L, "arc", carc); registerfunc(L, "bezier", cbezier); registerfunc(L, "triangle", ctriangle); registerfunc(L, "quad", cquad); registerfunc(L, "translate", ctranslate); registerfunc(L, "rotate", crotate); registerfunc(L, "radians", cradians); registerfunc(L, "pushMatrix", cpushmatrix); registerfunc(L, "popMatrix", cpopmatrix); registerfunc(L, "pushStyle", cpushstyle); registerfunc(L, "popStyle", cpopstyle); registerfunc(L, "push", cpush); registerfunc(L, "pop", cpop); registerfunc(L, "color", ccolor); registerfunc(L, "lerpColor", clerpcolor); registerfunc(L, "loadPixels", cloadpixels); registerfunc(L, "updatePixels", cupdatepixels); registermathfunc(L, "dist", cdist); registermathfunc(L, "mag", cmag); registermathfunc(L, "constrain", cconstrain); registermathfunc(L, "map", cmap); registermathfunc(L, "norm", cnorm); registermathfunc(L, "lerp", clerp); registermathfunc(L, "randomGaussian", crandomgaussian); }