diff options
Diffstat (limited to 'src/livecode/api/point.cpp')
| -rw-r--r-- | src/livecode/api/point.cpp | 298 |
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); +} + +} +} |
