summaryrefslogtreecommitdiffstats
path: root/src/livecode/api/point.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/livecode/api/point.cpp')
-rw-r--r--src/livecode/api/point.cpp298
1 files changed, 298 insertions, 0 deletions
diff --git a/src/livecode/api/point.cpp b/src/livecode/api/point.cpp
new file mode 100644
index 000000000..6eab6af1d
--- /dev/null
+++ b/src/livecode/api/point.cpp
@@ -0,0 +1,298 @@
+#include "livecode/api/api.h"
+
+#include <sstream>
+
+namespace Inkscape {
+namespace Livecode {
+
+extern "C" Janet geom_point_get(void *p, Janet key);
+extern "C" void geom_point_set(void *p, Janet key, Janet value);
+
+extern "C" void geom_point_tostring(void *p, JanetBuffer *buffer) {
+ std::stringstream stream;
+ stream << "<2geom/point " << *static_cast<Geom::Point *>(p) << ">";
+ janet_buffer_push_cstring(buffer, stream.str().c_str());
+}
+
+
+const JanetAbstractType geom_point_type = {
+ "2geom/point",
+ NULL,
+ NULL,
+ geom_point_get,
+ geom_point_set,
+ NULL,
+ NULL,
+ geom_point_tostring
+};
+
+
+Janet janet_wrap_point(Geom::Point const &x) {
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = Geom::Point(x);
+ return janet_wrap_abstract(box);
+}
+
+Janet janet_wrap_point(Geom::IntPoint const &x) {
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = Geom::Point(x);
+ return janet_wrap_abstract(box);
+}
+
+Geom::Point janet_unwrap_point(Janet x) {
+ if (janet_checktype(x, JANET_ABSTRACT)) {
+ void *abst = janet_unwrap_abstract(x);
+ if (janet_abstract_type(abst) == &geom_point_type)
+ return *(Geom::Point *)abst;
+ }
+
+ janet_panic("expected a geom/point");
+}
+
+Geom::Point janet_unwrap_point_or_scalar(Janet x) {
+ if (janet_checktype(x, JANET_ABSTRACT)) {
+ void *abst = janet_unwrap_abstract(x);
+ if (janet_abstract_type(abst) == &geom_point_type)
+ return *(Geom::Point *)abst;
+ } else if (janet_checktype(x, JANET_NUMBER)) {
+ double val = janet_unwrap_number(x);
+ return Geom::Point(val, val);
+ }
+
+ janet_panic("expected a geom/point");
+}
+
+
+Geom::Point& janet_unwrap_point_ref(Janet x) {
+ if (janet_checktype(x, JANET_ABSTRACT)) {
+ void *abst = janet_unwrap_abstract(x);
+ if (janet_abstract_type(abst) == &geom_point_type)
+ return *(Geom::Point *)abst;
+ }
+
+ janet_panic("expected a geom/point");
+}
+
+extern "C" Janet cfun_geom_point_new(int32_t argc, Janet *argv) {
+ janet_arity(argc, 0, 2);
+ double x = 0;
+ double y = 0;
+ if (argc == 2) {
+ x = janet_getnumber(argv, 0);
+ y = janet_getnumber(argv, 1);
+ } else if (argc == 1) {
+ x = janet_getnumber(argv, 0);
+ y = x;
+ }
+ return janet_wrap_point(Geom::Point(x, y));
+}
+
+const JanetReg it_cfuns[] = {
+ {
+ "point", cfun_geom_point_new,
+ "(geom/point x y)\n\nCreate a Point from x/y coordinate values."
+ },
+ {NULL, NULL, NULL}
+};
+
+static Janet cfun_geom_point_add(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = janet_unwrap_point(argv[0]);
+ for (int i = 1; i < argc; i++)
+ *box += janet_unwrap_point(argv[i]);
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_add_mut(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
+ for (int i = 1; i < argc; i++)
+ *box += janet_unwrap_point(argv[i]);
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_sub(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = janet_unwrap_point(argv[0]);
+ for (int i = 1; i < argc; i++)
+ *box -= janet_unwrap_point(argv[i]);
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_sub_mut(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
+ for (int i = 1; i < argc; i++)
+ *box -= janet_unwrap_point(argv[i]);
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_mul(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = janet_unwrap_point(argv[0]);
+ for (int i = 1; i < argc; i++) {
+ Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
+ (*box)[0] *= arg[0];
+ (*box)[1] *= arg[1];
+ }
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_mul_mut(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
+ for (int i = 1; i < argc; i++) {
+ Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
+ (*box)[0] *= arg[0];
+ (*box)[1] *= arg[1];
+ }
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_div(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = janet_unwrap_point(argv[0]);
+ for (int i = 1; i < argc; i++) {
+ Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
+ (*box)[0] /= arg[0];
+ (*box)[1] /= arg[1];
+ }
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_div_mut(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
+ for (int i = 1; i < argc; i++) {
+ Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
+ (*box)[0] /= arg[0];
+ (*box)[1] /= arg[1];
+ }
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_eq(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 2);
+ Geom::Point& v1 = janet_unwrap_point_ref(argv[0]);
+ Geom::Point& v2 = janet_unwrap_point_ref(argv[1]);
+ return janet_wrap_boolean(v1 == v2);
+}
+
+static Janet cfun_geom_point_lt(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 2);
+ Geom::Point& v1 = janet_unwrap_point_ref(argv[0]);
+ Geom::Point& v2 = janet_unwrap_point_ref(argv[1]);
+ return janet_wrap_boolean(v1 < v2);
+}
+
+#define CONSTMETHOD(name, method, type) \
+static Janet cfun_geom_point_##name(int32_t argc, Janet *argv) { \
+ janet_fixarity(argc, 1); \
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type); \
+ return janet_wrap_##type(box->method()); \
+}
+
+CONSTMETHOD(is_zero, isZero, boolean)
+CONSTMETHOD(is_finite, isFinite, boolean)
+CONSTMETHOD(is_normalized, isNormalized, boolean)
+
+CONSTMETHOD(x, x, number)
+CONSTMETHOD(y, y, number)
+CONSTMETHOD(length, length, number)
+
+CONSTMETHOD(cw, cw, point)
+CONSTMETHOD(ccw, ccw, point)
+CONSTMETHOD(round, round, point)
+CONSTMETHOD(floor, floor, point)
+CONSTMETHOD(ceil, ceil, point)
+CONSTMETHOD(normalize, normalized, point)
+
+static Janet cfun_geom_point_normalize_mut(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 1);
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
+ box->normalize();
+ return janet_wrap_point(*box);
+}
+
+static JanetMethod geom_point_methods[] = {
+ {"+", cfun_geom_point_add},
+ {"-", cfun_geom_point_sub},
+ {"*", cfun_geom_point_mul},
+ {"/", cfun_geom_point_div},
+ {"<", cfun_geom_point_lt},
+ {"==", cfun_geom_point_eq},
+
+ {"+!", cfun_geom_point_add_mut},
+ {"-!", cfun_geom_point_sub_mut},
+ {"*!", cfun_geom_point_mul_mut},
+ {"/!", cfun_geom_point_div_mut},
+
+ {"zero?", cfun_geom_point_is_zero},
+ {"finite?", cfun_geom_point_is_finite},
+ {"normalized?", cfun_geom_point_is_normalized},
+
+ {"x", cfun_geom_point_x},
+ {"y", cfun_geom_point_y},
+ {"length", cfun_geom_point_length},
+
+ {"cw", cfun_geom_point_cw},
+ {"ccw", cfun_geom_point_ccw},
+ {"round", cfun_geom_point_round},
+ {"floor", cfun_geom_point_floor},
+ {"ceil", cfun_geom_point_ceil},
+ {"normalize", cfun_geom_point_normalize},
+
+ {"normalize!", cfun_geom_point_normalize_mut},
+
+ {NULL, NULL}
+};
+
+extern "C" Janet geom_point_get(void *p, Janet key) {
+ Geom::Point *box = (Geom::Point *)p;
+
+ if (janet_checktype(key, JANET_KEYWORD))
+ return janet_getmethod(janet_unwrap_keyword(key), geom_point_methods);
+
+ if (!janet_checksize(key)) janet_panic("expected size as key");
+
+ size_t const index = (size_t) janet_unwrap_number(key);
+ switch (index) {
+ case 0:
+ return janet_wrap_number((*box)[0]);
+ case 1:
+ return janet_wrap_number((*box)[1]);
+ default:
+ return janet_wrap_nil();
+ }
+}
+
+extern "C" void geom_point_set(void *p, Janet key, Janet value) {
+ Geom::Point *box = (Geom::Point *)p;
+
+ if (!janet_checksize(key)) janet_panic("expected size as key");
+ if (!janet_checktype(key, JANET_NUMBER)) janet_panic("expected number as value");
+
+ size_t const index = (size_t) janet_unwrap_number(key);
+ switch (index) {
+ case 0:
+ (*box)[0] = janet_unwrap_number(value);
+ break;
+ case 1:
+ (*box)[1] = janet_unwrap_number(value);
+ break;
+ default:
+ janet_panic("index out of bounds");
+ }
+}
+
+void janet_lib_geom_point(JanetTable *env) {
+ janet_cfuns(env, NULL, it_cfuns);
+ janet_register_abstract_type(&geom_point_type);
+}
+
+}
+}