#include "livecode/api/api.h" namespace Inkscape { namespace Livecode { static Context *_context = nullptr; Context &ctx() { if (!_context) { janet_panic("Livecode Context uninitialized!!"); } return *_context; } extern "C" Janet cfun_input_point(int32_t argc, Janet *argv) { janet_fixarity(argc, 2); ctx().input_point(janet_getcstring(argv, 0), &janet_unwrap_point(argv[1])); return janet_wrap_nil(); } extern "C" Janet cfun_input_line(int32_t argc, Janet *argv) { janet_fixarity(argc, 3); ctx().input_line(janet_getcstring(argv, 0), &janet_unwrap_point(argv[1]), &janet_unwrap_point(argv[2])); return janet_wrap_nil(); } extern "C" Janet cfun_input_arrow(int32_t argc, Janet *argv) { janet_fixarity(argc, 3); ctx().input_arrow(janet_getcstring(argv, 0), &janet_unwrap_point(argv[1]), &janet_unwrap_point(argv[2])); return janet_wrap_nil(); } SPCSSAttr *get_css(Janet table) { JanetKV const *kv = NULL; SPCSSAttr *css = sp_repr_css_attr_new(); JanetDictView style = janet_getdictionary(&table, 0); while ((kv = janet_dictionary_next(style.kvs, style.cap, kv))) { if (!janet_checktype(kv->key, JANET_KEYWORD)) { janet_panic(":style keys have to be keywords"); } if (!janet_checktype(kv->value, JANET_STRING)) { janet_panic(":style values have to be strings"); } char const *key = (char const *)janet_unwrap_keyword(kv->key); char const *value = (char const *)janet_unwrap_string(kv->value); sp_repr_css_set_property(css, key, value); } return css; } Inkscape::XML::Node *get_node(int32_t argc, Janet *argv) { janet_fixarity(argc, 2); char const *element = (char const *)janet_unwrap_keyword(argv[0]); JanetDictView attrs = janet_getdictionary(argv, 1); Inkscape::XML::Node *repr = ctx().createElement(element); g_message("+ new node '%s'", element); JanetKV const *kv = NULL; while ((kv = janet_dictionary_next(attrs.kvs, attrs.cap, kv))) { if (!janet_checktype(kv->key, JANET_KEYWORD)) { janet_panic("attribute keys have to be keywords"); } char const *key = (char const *)janet_unwrap_keyword(kv->key); switch (janet_type(kv->value)) { case JANET_NUMBER: g_message(" setting '%s' = %f", key, janet_unwrap_number(kv->value)); sp_repr_set_svg_double(repr, key, janet_unwrap_number(kv->value)); break; case JANET_STRING: g_message(" setting '%s' = '%s'", key, janet_unwrap_string(kv->value)); repr->setAttribute(key, (gchar const *)janet_unwrap_string(kv->value)); break; case JANET_STRUCT: case JANET_TABLE: { if (strcmp(key, "style") != 0) { janet_panic("struct/table values are only allowed for :style"); } Glib::ustring css_str; SPCSSAttr *css = get_css(kv->value); sp_repr_css_write_string(css, css_str); sp_repr_css_attr_unref(css); repr->setAttribute("style", css_str.c_str()); g_message(" setting '%s' = '%s'", key, css_str.c_str()); break; } default: janet_panic("unsupported value type in attributes dict!"); break; } } return repr; } extern "C" Janet cfun_draw_doc(int32_t argc, Janet *argv) { char const *id = janet_getcstring(argv, 0); ctx().draw_doc(id, get_node(argc - 1, argv + 1)); g_message("+ draw_doc id=%s", id); return argv[0]; } extern "C" Janet cfun_draw_ui(int32_t argc, Janet *argv) { char const *id = janet_getcstring(argv, 0); ctx().draw_ui(id, get_node(argc - 1, argv + 1)); g_message("+ draw_ui id=%s", id); return argv[0]; } const JanetReg it_cfuns[] = { { "input/point", cfun_input_point, "(input/point id p)\n\nMake p modifiable via a handle.\n" "This function mutates p." }, { "input/line", cfun_input_line, "(input/line id p1 p2)\n\nMake a modifiable line between p1 and p2\n" "This function mutates p1 and p2." }, { "input/arrow", cfun_input_arrow, "(input/arrow id from to)\n\nMake a modifiable arrow between from and to\n" "This function mutates from and to." }, { "draw/doc", cfun_draw_doc, "(draw/doc id elem [attrs])\n\nDraw an SVG element to the document layer" }, { "draw/ui", cfun_draw_ui, "(draw/ui id elem [attrs])\n\nDraw an SVG element to the UI layer" }, {NULL, NULL, NULL} }; void janet_lib_context(JanetTable *env, Context &context) { _context = &context; janet_cfuns(env, NULL, it_cfuns); } } }