Mercurial > malikania
view libmlk-client-js/malikania/client/js/painter_js_api.cpp @ 210:1599919b5de6
client: allow starting a Javascript file
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 07 Dec 2018 19:31:10 +0100 |
parents | 263122adef77 |
children |
line wrap: on
line source
/* * painter_js_api.cpp -- painter (JavaScript binding) * * Copyright (c) 2013-2018 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <cassert> #include <malikania/line.hpp> #include <malikania/rectangle.hpp> #include <malikania/point.hpp> #include <malikania/client/color.hpp> #include <malikania/client/painter.hpp> #include <malikania/js/line_js_api.hpp> #include <malikania/js/point_js_api.hpp> #include <malikania/js/rectangle_js_api.hpp> #include "color_js_api.hpp" #include "font_js_api.hpp" #include "painter_js_api.hpp" #include "window_js_api.hpp" #include "texture_js_api.hpp" namespace mlk::client::js { namespace { const std::string_view signature("\xff""\xff""Malikania.Painter.self"); const std::string_view prototype("\xff""\xff""Malikania.Painter.prototype"); auto self(duk_context* ctx) -> painter& { mlk::js::duk::stack_guard sa(ctx); duk_push_this(ctx); duk_get_prop_string(ctx, -1, signature.data()); auto ptr = duk_to_pointer(ctx, -1); duk_pop_2(ctx); if (!ptr) duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Painter object"); return *static_cast<painter*>(ptr); } auto Painter_constructor(duk_context* ctx) -> duk_ret_t { mlk::js::duk::stack_guard sa(ctx); if (!duk_is_constructor_call(ctx)) duk_error(ctx, DUK_ERR_ERROR, "painter must be new-constructed"); try { duk_push_this(ctx); if (duk_get_top(ctx) == 2) duk_push_pointer(ctx, new painter(mlk::js::duk::require<window>(ctx, 0))); else duk_push_pointer(ctx, new painter( mlk::js::duk::require<window>(ctx, 0), mlk::js::duk::require<texture>(ctx, 1) )); duk_put_prop_string(ctx, -2, signature.data()); duk_pop(ctx); } catch (const std::exception& ex) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } return 0; } auto Painter_prototype_clear(duk_context* ctx) -> duk_ret_t { try { self(ctx).clear(); } catch (const std::exception& ex) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } return 0; } auto Painter_prototype_use(duk_context* ctx) -> duk_ret_t { try { if (auto* w = mlk::js::duk::get<window>(ctx, 0); w) self(ctx).use(*w); else if (auto* t = mlk::js::duk::get<texture>(ctx, 0); t) self(ctx).use(*t); else throw std::runtime_error("expected Window or Texture"); } catch (const std::exception& ex) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } return 0; } auto Painter_prototype_present(duk_context* ctx) -> duk_ret_t { try { self(ctx).present(); } catch (const std::exception& ex) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } return 0; } auto Painter_prototype_drawingColor(duk_context* ctx) -> duk_ret_t { try { mlk::js::duk::push(ctx, self(ctx).get_drawing_color()); } catch (const std::exception& ex) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } return 1; } auto Painter_prototype_drawLine(duk_context* ctx) -> duk_ret_t { try { self(ctx).draw_line(mlk::js::duk::get<line>(ctx, 0)); } catch (const std::exception& ex) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } return 0; } auto Painter_prototype_drawPoint(duk_context* ctx) -> duk_ret_t { try { self(ctx).draw_point(mlk::js::duk::get<point>(ctx, 0)); } catch (const std::exception& ex) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } return 0; } auto Painter_prototype_drawRectangle(duk_context* ctx) -> duk_ret_t { try { self(ctx).draw_rectangle(mlk::js::duk::get<rectangle>(ctx, 0)); } catch (const std::exception& ex) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } return 0; } auto Painter_prototype_fillRectangle(duk_context* ctx) -> duk_ret_t { try { self(ctx).fill_rectangle(mlk::js::duk::get<rectangle>(ctx, 0)); } catch (const std::exception& ex) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } return 0; } auto Painter_prototype_setDrawingColor(duk_context* ctx) -> duk_ret_t { try { self(ctx).set_drawing_color(mlk::js::duk::get<color>(ctx, 0)); } catch (const std::exception& ex) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } return 0; } } // !namespace const duk_function_list_entry methods[] = { { "clear", Painter_prototype_clear, 0 }, { "use", Painter_prototype_use, 1 }, { "drawingColor", Painter_prototype_drawingColor, 0 }, { "drawLine", Painter_prototype_drawLine, 1 }, { "drawPoint", Painter_prototype_drawPoint, 1 }, { "drawRectangle", Painter_prototype_drawRectangle, 1 }, { "fillRectangle", Painter_prototype_fillRectangle, 1 }, { "present", Painter_prototype_present, 0 }, { "setDrawingColor", Painter_prototype_setDrawingColor, 1 }, { nullptr, nullptr, 0 } }; void load_painter_api(duk_context* ctx) { mlk::js::duk::stack_guard sa(ctx); duk_get_global_string(ctx, "Malikania"); duk_push_c_function(ctx, Painter_constructor, DUK_VARARGS); duk_push_object(ctx); duk_put_function_list(ctx, -1, methods); duk_put_prop_string(ctx, -2, "prototype"); duk_put_prop_string(ctx, -2, "Painter"); duk_pop(ctx); } } // !mlk::client::js namespace mlk::js::duk { auto type_traits<mlk::client::painter>::require(duk_context* ctx, duk_idx_t index) -> mlk::client::painter& { assert(ctx); mlk::js::duk::stack_guard sa(ctx); duk_get_prop_string(ctx, index, mlk::client::js::signature.data()); auto ptr = duk_to_pointer(ctx, -1); duk_pop(ctx); if (!ptr) duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Painter object"); return *static_cast<mlk::client::painter*>(ptr); } } // !mlk::js::duk