changeset 37:702e0a2b9e5e

Misc: make JavaScript different libraries, Closes T3
author David Demelier <markand@malikania.fr>
date Thu, 18 Aug 2016 11:07:34 +0200
parents 9af360f34c7d
children ecf316d52f5d
files CMakeLists.txt client/CMakeLists.txt libclient-js/CMakeLists.txt libclient-js/malikania/js-animation.cpp libclient-js/malikania/js-animation.hpp libclient-js/malikania/js-animator.cpp libclient-js/malikania/js-animator.hpp libclient-js/malikania/js-client-resources-loader.cpp libclient-js/malikania/js-client-resources-loader.hpp libclient-js/malikania/js-client-target.cpp libclient-js/malikania/js-client-target.hpp libclient-js/malikania/js-client.cpp libclient-js/malikania/js-client.hpp libclient-js/malikania/js-color.cpp libclient-js/malikania/js-color.hpp libclient-js/malikania/js-font.cpp libclient-js/malikania/js-font.hpp libclient-js/malikania/js-image.cpp libclient-js/malikania/js-image.hpp libclient-js/malikania/js-line.cpp libclient-js/malikania/js-line.hpp libclient-js/malikania/js-point.cpp libclient-js/malikania/js-point.hpp libclient-js/malikania/js-rectangle.cpp libclient-js/malikania/js-rectangle.hpp libclient-js/malikania/js-size.cpp libclient-js/malikania/js-size.hpp libclient-js/malikania/js-sprite.cpp libclient-js/malikania/js-sprite.hpp libclient-js/malikania/js-window.cpp libclient-js/malikania/js-window.hpp libclient/CMakeLists.txt libclient/malikania/js-animation.cpp libclient/malikania/js-animation.hpp libclient/malikania/js-animator.cpp libclient/malikania/js-animator.hpp libclient/malikania/js-client-resources-loader.cpp libclient/malikania/js-client-resources-loader.hpp libclient/malikania/js-client-target.cpp libclient/malikania/js-client-target.hpp libclient/malikania/js-client.cpp libclient/malikania/js-client.hpp libclient/malikania/js-color.cpp libclient/malikania/js-color.hpp libclient/malikania/js-font.cpp libclient/malikania/js-font.hpp libclient/malikania/js-image.cpp libclient/malikania/js-image.hpp libclient/malikania/js-line.cpp libclient/malikania/js-line.hpp libclient/malikania/js-point.cpp libclient/malikania/js-point.hpp libclient/malikania/js-rectangle.cpp libclient/malikania/js-rectangle.hpp libclient/malikania/js-size.cpp libclient/malikania/js-size.hpp libclient/malikania/js-sprite.cpp libclient/malikania/js-sprite.hpp libclient/malikania/js-window.cpp libclient/malikania/js-window.hpp libcommon-js/CMakeLists.txt libcommon-js/malikania/js-elapsed-timer.cpp libcommon-js/malikania/js-elapsed-timer.hpp libcommon-js/malikania/js-resources-loader.cpp libcommon-js/malikania/js-resources-loader.hpp libcommon/CMakeLists.txt libcommon/malikania/js-elapsed-timer.cpp libcommon/malikania/js-elapsed-timer.hpp libcommon/malikania/js-resources-loader.cpp libcommon/malikania/js-resources-loader.hpp tests/libclient/js-animation/CMakeLists.txt tests/libclient/js-color/CMakeLists.txt tests/libclient/js-font/CMakeLists.txt tests/libclient/js-image/CMakeLists.txt tests/libclient/js-line/CMakeLists.txt tests/libclient/js-point/CMakeLists.txt tests/libclient/js-rectangle/CMakeLists.txt tests/libclient/js-size/CMakeLists.txt tests/libclient/js-sprite/CMakeLists.txt tests/libclient/js-window/CMakeLists.txt tests/libcommon/js-elapsed-timer/CMakeLists.txt
diffstat 81 files changed, 3058 insertions(+), 2982 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -50,7 +50,9 @@
 add_subdirectory(database)
 add_subdirectory(docs)
 add_subdirectory(libcommon)
+add_subdirectory(libcommon-js)
 add_subdirectory(libclient)
+add_subdirectory(libclient-js)
 add_subdirectory(libserver)
 add_subdirectory(client)
 add_subdirectory(server)
--- a/client/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/client/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -25,4 +25,4 @@
 
 add_executable(mlk-client ${FILES})
 target_include_directories(mlk-client PRIVATE ${client_SOURCE_DIR})
-target_link_libraries(mlk-client libcommon libclient)
+target_link_libraries(mlk-client libclient-js)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,63 @@
+#
+# CMakeLists.txt -- CMake build system for malikania
+#
+# Copyright (c) 2013-2016 Malikania Authors
+#
+# 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.
+#
+
+project(libclient-js)
+
+set(
+    HEADERS
+    ${libclient-js_SOURCE_DIR}/malikania/js-animation.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-animator.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-client.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-client-resources-loader.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-client-target.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-color.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-font.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-image.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-line.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-point.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-rectangle.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-sprite.hpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-window.hpp
+)
+
+set(
+    SOURCES
+    ${libclient-js_SOURCE_DIR}/malikania/js-animation.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-animator.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-client.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-client-resources-loader.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-client-target.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-color.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-font.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-image.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-line.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-point.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-rectangle.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-sprite.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-size.cpp
+    ${libclient-js_SOURCE_DIR}/malikania/js-window.cpp
+)
+
+malikania_create_library(
+    PROJECT libclient-js
+    TARGET libclient-js
+    SOURCES ${HEADERS} ${SOURCES}
+    LIBRARIES libclient libcommon-js
+    PUBLIC_INCLUDES
+        $<BUILD_INTERFACE:${libclient-js_SOURCE_DIR}/malikania>
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-animation.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,104 @@
+/*
+ * js-animation.cpp -- animation description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-client-resources-loader.hpp"
+#include "js-animation.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Signature("\xff""\xff""malikania-animation-ptr");
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    if (!duk_is_constructor_call(ctx))
+        duk_error(ctx, DUK_ERR_ERROR, "animation must be new-constructed");
+
+    try {
+        auto loader = dukx_get_client_loader(ctx);
+        auto animation = loader->loadAnimation(duk_require_string(ctx, 0));
+
+        dukx_new_animation(ctx, new Animation(std::move(animation)));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t destructor(duk_context *ctx)
+{
+    duk_get_prop_string(ctx, 0, Signature.c_str());
+    delete static_cast<Animation *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+    duk_del_prop_string(ctx, 0, Signature.c_str());
+
+    return 0;
+}
+
+} // !namespace
+
+void dukx_new_animation(duk_context *ctx, Animation *animation)
+{
+    assert(ctx);
+    assert(animation);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, animation);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+}
+
+Animation *dukx_require_animation(duk_context *ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_prop_string(ctx, index, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animation object");
+
+    return static_cast<Animation *>(ptr);
+}
+
+void dukx_load_animation(duk_context *ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_push_c_function(ctx, destructor, 1);
+    duk_set_finalizer(ctx, -2);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Animation");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-animation.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,58 @@
+/*
+ * js-animation.hpp -- animation description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_ANIMATION_HPP
+#define MALIKANIA_JS_ANIMATION_HPP
+
+#include <malikania/duktape.hpp>
+
+#include "animation.hpp"
+
+namespace malikania {
+
+/**
+ * Construct an Animation object as this.
+ *
+ * \pre ctx != nullptr
+ * \pre animation != nullptr
+ * \param ctx the context
+ * \param animation the animation
+ */
+void dukx_new_animation(duk_context *ctx, Animation *animation);
+
+/**
+ * Get an Animation object at the given index or raise a JavaScript error.
+ *
+ * \pre ctx != nullptr
+ * \param ctx the context
+ * \param index the value index
+ * \return the Animation object
+ */
+Animation *dukx_require_animation(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Load the Animation module into the context.
+ *
+ * \pre ctx != nullptr
+ * \param ctx the context
+ */
+void dukx_load_animation(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_ANIMATION_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-animator.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,144 @@
+/*
+ * js-animator.cpp -- animation drawing object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 <string>
+
+#include "js-animation.hpp"
+#include "js-animator.hpp"
+#include "js-point.hpp"
+#include "js-window.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Signature("\xff""\xff""malikania-animator-ptr");
+
+Animator *self(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
+
+    return static_cast<Animator *>(ptr);
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    if (!duk_is_constructor_call(ctx))
+        duk_error(ctx, DUK_ERR_ERROR, "animator must be new-constructed");
+
+    // Be sure animation get not collected before.
+    dukx_new_animator(ctx, new Animator(*dukx_require_animation(ctx, 0)));
+    duk_push_this(ctx);
+    duk_dup(ctx, 0);
+    duk_put_prop_string(ctx, -2, "\xff""\xff""animation-ref");
+
+    return 0;
+}
+
+duk_ret_t destructor(duk_context *ctx)
+{
+    duk_get_prop_string(ctx, 0, Signature.c_str());
+    delete static_cast<Animator *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+    duk_del_prop_string(ctx, 0, Signature.c_str());
+
+    return 0;
+}
+
+duk_ret_t draw(duk_context *ctx)
+{
+    try {
+        self(ctx)->draw(*dukx_require_window(ctx, 0), dukx_get_point(ctx, 1));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t update(duk_context *ctx)
+{
+    self(ctx)->update();
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "draw",   draw,       2 },
+    { "update", update,     0 },
+    { nullptr,  nullptr,    0 }
+};
+
+} // !namespace
+
+void dukx_new_animator(duk_context *ctx, Animator *animator)
+{
+    assert(ctx);
+    assert(animator);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, animator);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+}
+
+Animator *dukx_require_animator(duk_context *ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_prop_string(ctx, index, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
+
+    return static_cast<Animator *>(ptr);
+}
+
+void dukx_load_animator(duk_context *ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_push_c_function(ctx, destructor, 1);
+    duk_set_finalizer(ctx, -2);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Animator");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-animator.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,51 @@
+/*
+ * js-animator.hpp -- animation drawing object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_ANIMATOR_HPP
+#define MALIKANIA_JS_ANIMATOR_HPP
+
+#include "animator.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+/**
+ * Construct an Animator object as this.
+ *
+ * \pre ctx != nullptr
+ * \pre animator != nullptr
+ * \param ctx the context
+ * \param animator the animator
+ */
+void dukx_new_animator(duk_context *ctx, Animator *animator);
+
+/**
+ * Get the animator at the given index.
+ *
+ * \pre ctx != nullptr
+ * \param ctx the context
+ * \param index the value index
+ * \return the animator
+ */
+Animator *dukx_require_animator(duk_context *ctx, duk_idx_t index);
+
+void dukx_load_animator(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_ANIMATOR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-client-resources-loader.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,59 @@
+/*
+ * js-client-resources-loader.cpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-client-resources-loader.hpp"
+#include "js-resources-loader.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Variable("\xff""\xff""malikania-client-resources-loader");
+
+} // !namespace
+
+void dukx_put_client_loader(duk_context *ctx, ClientResourcesLoader *loader)
+{
+    assert(ctx);
+    assert(loader);
+
+    // Also store as parent.
+    dukx_put_loader(ctx, loader);
+
+    StackAssert sa(ctx);
+
+    duk_push_pointer(ctx, loader);
+    duk_put_global_string(ctx, Variable.c_str());
+}
+
+ClientResourcesLoader *dukx_get_client_loader(duk_context *ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, Variable.c_str());
+    auto ptr = static_cast<ClientResourcesLoader *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+
+    return static_cast<ClientResourcesLoader *>(ptr);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-client-resources-loader.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,33 @@
+/*
+ * js-client-resources-loader.hpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
+#define MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
+
+#include "client-resources-loader.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+void dukx_put_client_loader(duk_context *ctx, ClientResourcesLoader *);
+
+ClientResourcesLoader *dukx_get_client_loader(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-client-target.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,55 @@
+/*
+ * js-client-target.cpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-client-target.hpp"
+
+namespace malikania {
+
+class JsTarget : public Client::Target {
+public:
+
+};
+
+namespace {
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    return 0;
+}
+
+duk_ret_t draw(duk_context *ctx)
+{
+    return 0;
+}
+
+} // !namespace
+
+void dukx_load_client_target(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_get_prop_string(ctx, -1, "Client");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_prop_string(ctx, -1, "prototype");
+    duk_put_prop_string(ctx, -2, "Target");
+    duk_pop_2(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-client-target.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,31 @@
+/*
+ * js-client-target.hpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_CLIENT_TARGET_HPP
+#define MALIKANIA_JS_CLIENT_TARGET_HPP
+
+#include "client-target.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+void dukx_load_client_target(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_CLIENT_TARGET_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-client.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,93 @@
+/*
+ * js-client.cpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-client.hpp"
+#include "js-client-target.hpp"
+#include "js-window.hpp"
+
+namespace malikania {
+
+namespace {
+
+duk_ret_t draw(duk_context *)
+{
+#if 0
+    try {
+        duk::self<std::shared_ptr<Client>>(ctx)->draw();
+    } catch (const std::exception &ex) {
+        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+#endif
+
+    return 0;
+}
+
+duk_ret_t setTarget(duk_context *)
+{
+#if 0
+    auto self = duk::self<Client *>(ctx);
+    auto target = duk::get<std::shared_ptr<Client::Target>>(ctx, 0);
+
+    self->setTarget(std::move(target));
+#endif
+
+    return 0;
+}
+
+duk_ret_t update(duk_context *)
+{
+#if 0
+    try {
+        duk::self<std::shared_ptr<Client>>(ctx)->update();
+    } catch (const std::exception &ex) {
+        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+#endif
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "draw",       draw,       0 },
+    { "setTarget",  setTarget,  1 },
+    { "update",     update,     0 },
+    { nullptr,      nullptr,    0 }
+};
+
+} // !namespace
+
+void dukx_load_client(duk_context *ctx)
+{
+#if 0
+    duk::StackAssert sa(ctx);
+
+    duk::getGlobal<void>(ctx, "Malikania");
+    duk::push(ctx, duk::Object());
+    duk::push(ctx, duk::Object());
+    duk::TypeTraits<Window>::prototype(ctx);
+    duk::setPrototype(ctx, -2);
+    duk::put(ctx, methods);
+    duk::putProperty(ctx, -2, "prototype");
+    duk::putProperty(ctx, -2, "Client");
+    duk::pop(ctx);
+#endif
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-client.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,31 @@
+/*
+ * js-client.hpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_CLIENT_HPP
+#define MALIKANIA_JS_CLIENT_HPP
+
+#include "client.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+void dukx_load_client(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_CLIENT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-color.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,191 @@
+/*
+ * js-color.cpp -- color description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-color.hpp"
+#include "util.hpp"
+
+namespace malikania {
+
+namespace {
+
+std::uint8_t clampComponent(duk_context *ctx, int value, bool required)
+{
+    if (value < 0 || value > 255) {
+        if (required)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range (0, 255)", value);
+        else
+            value = util::clamp(value, 0, 255);
+    }
+
+    return static_cast<std::uint8_t>(value);
+}
+
+Color parseString(duk_context *ctx, duk_idx_t index, bool required)
+{
+    assert(duk_is_string(ctx, index));
+
+    Color color;
+
+    try {
+        color = Color(duk_get_string(ctx, index));
+    } catch (const std::exception &ex) {
+        if (required)
+            duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return color;
+}
+
+Color parseObject(duk_context *ctx, duk_idx_t index, bool required)
+{
+    assert(duk_is_object(ctx, index));
+
+    auto require = [&] (const auto prop) -> std::uint8_t {
+        if (required && !duk_has_prop_string(ctx, index, prop))
+            duk_error(ctx, DUK_ERR_ERROR, "missing %s property in color description", prop);
+
+        duk_get_prop_string(ctx, index, prop);
+        auto comp = duk_get_int(ctx, -1);
+        duk_pop(ctx);
+
+        return clampComponent(ctx, comp, required);
+    };
+
+    // Alpha is optional.
+    duk_get_prop_string(ctx, index, "alpha");
+    auto alpha = duk_is_number(ctx, -1) ? duk_to_int(ctx, -1) : 255;
+    duk_pop(ctx);
+
+    return Color(
+        require("red"),
+        require("green"),
+        require("blue"),
+        clampComponent(ctx, alpha, required)
+    );
+}
+
+Color parse(duk_context *ctx, duk_idx_t index, bool required, Color color = {})
+{
+    switch (duk_get_type(ctx, index)) {
+    case DUK_TYPE_STRING:
+        color = parseString(ctx, index, required);
+        break;
+    case DUK_TYPE_OBJECT:
+        color = parseObject(ctx, index, required);
+        break;
+    default:
+        if (required)
+            duk_error(ctx, DUK_ERR_TYPE_ERROR, "color (string, object) expected");
+
+        break;
+    }
+
+    return color;
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    Color color;
+
+    /*
+     * The constructor allows an additional signature that takes 4 number
+     * arguments, otherwise use the literal parsing functions.
+     */
+    if (duk_get_top(ctx) >= 3) {
+        // Alpha is optional.
+        auto alpha = duk_is_number(ctx, 3) ? duk_to_int(ctx, 3) : 255;
+
+        color = Color(
+            clampComponent(ctx, duk_require_int(ctx, 0), true),
+            clampComponent(ctx, duk_require_int(ctx, 1), true),
+            clampComponent(ctx, duk_require_int(ctx, 2), true),
+            clampComponent(ctx, alpha, true)
+        );
+    } else if (duk_get_top(ctx) == 1)
+        color = parse(ctx, 0, true);
+
+    duk_ret_t ret;
+
+    // Allow both constructor and non constructor calls.
+    if (duk_is_constructor_call(ctx)) {
+        duk_push_this(ctx);
+        dukx_put_color(ctx, color);
+        duk_pop(ctx);
+        ret = 0;
+    } else {
+        dukx_push_color(ctx, color);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+} //! namespace
+
+Color dukx_get_color(duk_context *ctx, duk_idx_t index)
+{
+    return parse(ctx, index, false);
+}
+
+Color dukx_require_color(duk_context *ctx, duk_idx_t index)
+{
+    return parse(ctx, index, true);
+}
+
+Color dukx_optional_color(duk_context *ctx, duk_idx_t index, Color def)
+{
+    return parse(ctx, index, false, std::move(def));
+}
+
+void dukx_push_color(duk_context *ctx, const Color &color)
+{
+    StackAssert sa(ctx, 1);
+
+    duk_push_object(ctx);
+    dukx_put_color(ctx, color);
+}
+
+void dukx_put_color(duk_context *ctx, const Color &color)
+{
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx, 0);
+
+    duk_push_uint(ctx, color.red());
+    duk_put_prop_string(ctx, -2, "red");
+    duk_push_uint(ctx, color.green());
+    duk_put_prop_string(ctx, -2, "green");
+    duk_push_uint(ctx, color.blue());
+    duk_put_prop_string(ctx, -2, "blue");
+    duk_push_uint(ctx, color.alpha());
+    duk_put_prop_string(ctx, -2, "alpha");
+}
+
+void dukx_load_color(duk_context *ctx)
+{
+    StackAssert sa(ctx, 0);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Color");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-color.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,96 @@
+/*
+ * js-color.hpp -- color description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_COLOR_HPP
+#define MALIKANIA_JS_COLOR_HPP
+
+/**
+ * \file js-color.h
+ * \brief JavaScript binding for Color.
+ *
+ * Colors can be created from plain JavaScript object.
+ *
+ * ````
+ * {
+ *   red: 0,
+ *   green: 255,
+ *   blue: 255,
+ *   alpha: 255
+ * }
+ * ````
+ *
+ * It can also takes strings like "#rrggbbaa" and SVG names.
+ */
+
+#include "color.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+/**
+ * Get a color.
+ *
+ * May return a default value or a color with adjusted components.
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+Color dukx_get_color(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Require a color.
+ *
+ * If the color has any invalid component, raise a JavaScript error.
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+Color dukx_require_color(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Like get, but return the default value only if the value at the given
+ * index is not an object or not a string, otherwise, adjust invalid values.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @param def the default value
+ */
+Color dukx_optional_color(duk_context *ctx, duk_idx_t index, Color def);
+
+/**
+ * Push the color as object.
+ *
+ * @param ctx the context
+ * @param color the color
+ */
+void dukx_push_color(duk_context *ctx, const Color &color);
+
+/**
+ * Put the color properties into the object at the top of the stack.
+ *
+ * @pre the top value must be an object
+ * @param ctx the context
+ * @param color the color
+ */
+void dukx_put_color(duk_context *ctx, const Color &color);
+
+void dukx_load_color(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_COLOR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-font.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,129 @@
+/*
+ * js-font.cpp -- font object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-client-resources-loader.hpp"
+#include "js-font.hpp"
+#include "js-size.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Signature("\xff""\xff""malikania-font-ptr");
+
+Font *self(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Font object");
+
+    return static_cast<Font *>(ptr);
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    if (!duk_is_constructor_call(ctx))
+        duk_error(ctx, DUK_ERR_ERROR, "font must be new-constructed");
+
+    try {
+        auto loader = dukx_get_client_loader(ctx);
+        auto id = duk_require_string(ctx, 0);
+        auto size = duk_require_int(ctx, 1);
+
+        if (size < 0)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d must not be negative", size);
+
+        dukx_new_font(ctx, new Font(loader->loadFont(id, static_cast<unsigned>(size))));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t clip(duk_context *ctx)
+{
+    try {
+        dukx_push_size(ctx, self(ctx)->clip(duk_require_string(ctx, 0)));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 1;
+}
+
+const duk_function_list_entry methods[] = {
+    { "clip",   clip,       1 },
+    { nullptr,  nullptr,    0 }
+};
+
+} // !namespace
+
+void dukx_new_font(duk_context *ctx, Font *font)
+{
+    assert(ctx);
+    assert(font);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, font);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+}
+
+Font *dukx_require_font(duk_context *ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_prop_string(ctx, index, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Font object");
+
+    return static_cast<Font *>(ptr);
+}
+
+void dukx_load_font(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 2);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Font");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-font.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,35 @@
+/*
+ * js-font.hpp -- font object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_FONT_HPP
+#define MALIKANIA_JS_FONT_HPP
+
+#include "duktape.hpp"
+#include "font.hpp"
+
+namespace malikania {
+
+void dukx_new_font(duk_context *ctx, Font *font);
+
+Font *dukx_require_font(duk_context *ctx, duk_idx_t index);
+
+void dukx_load_font(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_FONT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-image.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,132 @@
+/*
+ * js-image.cpp -- image object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-client-resources-loader.hpp"
+#include "js-image.hpp"
+#include "js-point.hpp"
+#include "js-rectangle.hpp"
+#include "js-size.hpp"
+#include "js-window.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Signature("\xff""\xff""malikania-image-ptr");
+
+Image *self(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
+
+    return static_cast<Image *>(ptr);
+}
+
+duk_ret_t size(duk_context *ctx)
+{
+    try {
+        dukx_push_size(ctx, self(ctx)->size());
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 1;
+}
+
+duk_ret_t draw(duk_context *ctx)
+{
+    try {
+        auto image = self(ctx);
+        auto window = dukx_require_window(ctx, 0);
+
+        if (duk_get_top(ctx) == 2)
+            image->draw(*window, dukx_get_point(ctx, 1));
+        else if (duk_get_top(ctx) == 3)
+            image->draw(*window, dukx_get_rect(ctx, 1), dukx_get_rect(ctx, 2));
+        else
+            duk_error(ctx, DUK_ERR_TYPE_ERROR, "invalid number of arguments: #%d", duk_get_top(ctx));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    if (!duk_is_constructor_call(ctx))
+        duk_error(ctx, DUK_ERR_ERROR, "image must be new-constructed");
+
+    try {
+        auto loader = dukx_get_client_loader(ctx);
+        auto image = new Image(loader->loadImage(duk_require_string(ctx, 0)));
+
+        dukx_new_image(ctx, image);
+        duk_push_this(ctx);
+        duk_push_string(ctx, "size");
+        duk_push_c_function(ctx, size, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+        duk_pop(ctx);
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "draw",   draw,       DUK_VARARGS },
+    { nullptr,  nullptr,    0           }
+};
+
+} // !namespace
+
+void dukx_new_image(duk_context *ctx, Image *image)
+{
+    assert(ctx);
+    assert(image);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, image);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+}
+
+void dukx_load_image(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Image");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-image.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,33 @@
+/*
+ * js-image.hpp -- image object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_IMAGE_HPP
+#define MALIKANIA_JS_IMAGE_HPP
+
+#include "duktape.hpp"
+#include "image.hpp"
+
+namespace malikania {
+
+void dukx_new_image(duk_context *ctx, Image *image);
+
+void dukx_load_image(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_IMAGE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-line.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,135 @@
+/*
+ * js-line.cpp -- line description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-line.hpp"
+
+namespace malikania {
+
+namespace {
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    Line line;
+
+    if (duk_get_top(ctx) == 4) {
+        line = Line(
+            duk_get_int(ctx, 0),
+            duk_get_int(ctx, 1),
+            duk_get_int(ctx, 2),
+            duk_get_int(ctx, 3)
+        );
+    } else if (duk_get_top(ctx) == 1)
+        line = dukx_require_line(ctx, 0);
+
+    duk_ret_t ret;
+
+    /* Allow both constructor and non constructor calls */
+    if (duk_is_constructor_call(ctx)) {
+        duk_push_this(ctx);
+        dukx_put_line(ctx, line);
+        ret = 0;
+    } else {
+        dukx_push_line(ctx, line);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+} // !namespace
+
+Line dukx_get_line(duk_context *ctx, duk_idx_t index)
+{
+    auto get = [&] (auto name) {
+        StackAssert sa(ctx);
+
+        duk_get_prop_string(ctx, index, name);
+        auto v = duk_get_int(ctx, -1);
+        duk_pop(ctx);
+
+        return v;
+    };
+
+    return Line(get("x1"), get("y1"), get("x2"), get("y2"));
+}
+
+Line dukx_require_line(duk_context *ctx, duk_idx_t index)
+{
+    auto get = [&] (auto prop) {
+        if (!duk_has_prop_string(ctx, index, prop))
+            duk_error(ctx, DUK_ERR_ERROR, "missing %s property in line description", prop);
+
+        duk_get_prop_string(ctx, index, prop);
+
+        if (!duk_is_number(ctx, -1)) {
+            duk_pop(ctx);
+            duk_error(ctx, DUK_ERR_TYPE_ERROR, "property %s is not an int", prop);
+        }
+
+        auto value = duk_to_int(ctx, -1);
+
+        duk_pop(ctx);
+
+        return value;
+    };
+
+    return Line(get("x1"), get("y1"), get("x2"), get("y2"));
+}
+
+Line dukx_optional_line(duk_context *ctx, duk_idx_t index, Line def)
+{
+    return duk_is_object(ctx, index) ? dukx_get_line(ctx, index) : def;
+}
+
+void dukx_push_line(duk_context *ctx, const Line &line)
+{
+    StackAssert sa(ctx, 1);
+
+    duk_push_object(ctx);
+    dukx_put_line(ctx, line);
+}
+
+void dukx_put_line(duk_context *ctx, const Line &line)
+{
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx);
+
+    duk_push_int(ctx, line.x1());
+    duk_put_prop_string(ctx, -2, "x1");
+    duk_push_int(ctx, line.y1());
+    duk_put_prop_string(ctx, -2, "y1");
+    duk_push_int(ctx, line.x2());
+    duk_put_prop_string(ctx, -2, "x2");
+    duk_push_int(ctx, line.y2());
+    duk_put_prop_string(ctx, -2, "y2");
+}
+
+void dukx_load_line(duk_context *ctx)
+{
+    StackAssert sa(ctx, 0);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Line");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-line.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,93 @@
+/*
+ * js-line.hpp -- line description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_LINE_HPP
+#define MALIKANIA_JS_LINE_HPP
+
+/**
+ * \file js-line.h
+ * \brief JavaScript binding for Line.
+ *
+ * Lines are plain objects.
+ *
+ * ````
+ * {
+ *   x1: 10,
+ *   y1: 10,
+ *   x2: 50,
+ *   y2: 50
+ * }
+ * ````
+ */
+
+#include "duktape.hpp"
+#include "line.hpp"
+
+namespace malikania {
+
+/**
+ * Get a line.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @return the line
+ */
+Line dukx_get_line(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Require a line.
+ *
+ * If value is not an object or any property is invalid, raise a JavaScript error.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @return the line
+ */
+Line dukx_require_line(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Like get but return def if the value at the given index is not an object.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @param def the default value
+ * @return the line
+ */
+Line dukx_optional_line(duk_context *ctx, duk_idx_t index, Line def);
+
+/**
+ * Push the line as object.
+ *
+ * @param ctx the context
+ * @param line the line
+ */
+void dukx_push_line(duk_context *ctx, const Line &line);
+
+/**
+ * Put the line properties into the object at the top of the stack.
+ *
+ * @param ctx the context
+ * @param line the line
+ */
+void dukx_put_line(duk_context *ctx, const Line &line);
+
+void dukx_load_line(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_LINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-point.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,127 @@
+/*
+ * js-point.cpp -- point description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-point.hpp"
+
+namespace malikania {
+
+namespace {
+
+Point parse(duk_context *ctx, duk_idx_t index, bool required, Point point = {})
+{
+    StackAssert sa(ctx);
+
+    if (duk_is_object(ctx, index)) {
+        if (required && !duk_has_prop_string(ctx, index, "x"))
+            duk_error(ctx, DUK_ERR_ERROR, "missing x property in point description");
+        else if (required && !duk_has_prop_string(ctx, index, "y"))
+            duk_error(ctx, DUK_ERR_ERROR, "missing y property in point description");
+
+        //point = Point(duk::getProperty<int>(ctx, index, "x"), duk::getProperty<int>(ctx, index, "y"));
+        int x;
+        int y;
+
+        duk_get_prop_string(ctx, index, "x");
+        x = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+        duk_get_prop_string(ctx, index, "y");
+        y = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+
+        point = Point(x, y);
+    } else if (required)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "point object expected");
+
+    return point;
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    Point point;
+
+    if (duk_get_top(ctx) == 2)
+        point = Point(duk_require_int(ctx, 0), duk_require_int(ctx, 1));
+    else if (duk_get_top(ctx) == 1)
+        point = parse(ctx, 0, true);
+
+    duk_ret_t ret;
+
+    // Allow both constructor and non constructor calls.
+    if (duk_is_constructor_call(ctx)) {
+        duk_push_this(ctx);
+        dukx_put_point(ctx, point);
+        duk_pop(ctx);
+        ret = 0;
+    } else {
+        dukx_push_point(ctx, point);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+} // !namespace
+
+Point dukx_get_point(duk_context *ctx, duk_idx_t index)
+{
+    return parse(ctx, index, false);
+}
+
+Point dukx_require_point(duk_context *ctx, duk_idx_t index)
+{
+    return parse(ctx, index, true);
+}
+
+Point dukx_optional_point(duk_context *ctx, duk_idx_t index, Point def)
+{
+    return parse(ctx, index, false, std::move(def));
+}
+
+void dukx_push_point(duk_context *ctx, const Point &point)
+{
+    StackAssert sa(ctx, 1);
+
+    duk_push_object(ctx);
+    dukx_put_point(ctx, point);
+}
+
+void dukx_put_point(duk_context *ctx, const Point &point)
+{
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx);
+
+    duk_push_int(ctx, point.x());
+    duk_put_prop_string(ctx, -2, "x");
+    duk_push_int(ctx, point.y());
+    duk_put_prop_string(ctx, -2, "y");
+}
+
+void dukx_load_point(duk_context *ctx)
+{
+    StackAssert sa(ctx, 0);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Point");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-point.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,39 @@
+/*
+ * js-point.hpp -- point description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_POINT_HPP
+#define MALIKANIA_JS_POINT_HPP
+
+#include "duktape.hpp"
+#include "point.hpp"
+
+namespace malikania {
+
+Point dukx_require_point(duk_context *ctx, duk_idx_t index);
+
+Point dukx_get_point(duk_context *ctx, duk_idx_t index);
+
+void dukx_push_point(duk_context *ctx, const Point &point);
+
+void dukx_put_point(duk_context *ctx, const Point &point);
+
+void dukx_load_point(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_POINT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-rectangle.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,151 @@
+/*
+ * js-rectangle.cpp -- rectangle description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-rectangle.hpp"
+
+namespace malikania {
+
+namespace {
+
+unsigned clamp(duk_context *ctx, int value, bool required)
+{
+    if (value < 0) {
+        if (required)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d can not be negative", value);
+        else
+            value = 0;
+    }
+
+    return static_cast<unsigned>(value);
+}
+
+Rectangle parse(duk_context *ctx, duk_idx_t index, bool required, Rectangle rect = {})
+{
+    StackAssert sa(ctx);
+
+    if (duk_is_object(ctx, index)) {
+        auto get = [&] (auto prop) {
+            if (required && !duk_has_prop_string(ctx, index, prop))
+                duk_error(ctx, DUK_ERR_ERROR, "missing '%s' property", prop);
+
+            duk_get_prop_string(ctx, index, prop);
+
+            if (required && !duk_is_number(ctx, -1)) {
+                duk_pop(ctx);
+                duk_error(ctx, DUK_ERR_ERROR, "invalid '%s' property (number expected)", prop);
+            }
+
+            auto value = duk_to_int(ctx, -1);
+
+            duk_pop(ctx);
+
+            return value;
+        };
+
+        rect = Rectangle(get("x"), get("y"),
+            clamp(ctx, get("width"), required), clamp(ctx, get("height"), required));
+    } else if (required)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "rectangle object expected");
+
+    return rect;
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    Rectangle rect;
+
+    if (duk_get_top(ctx) == 4) {
+        rect = Rectangle(
+            duk_require_int(ctx, 0),
+            duk_require_int(ctx, 1),
+            clamp(ctx, duk_require_int(ctx, 2), true),
+            clamp(ctx, duk_require_int(ctx, 3), true)
+        );
+    } else if (duk_get_top(ctx) == 1)
+        rect = parse(ctx, 0, true);
+
+    duk_ret_t ret;
+
+    // Allow both constructor and non constructor calls.
+    if (duk_is_constructor_call(ctx)) {
+        duk_push_this(ctx);
+        dukx_put_rect(ctx, rect);
+        duk_pop(ctx);
+        ret = 0;
+    } else {
+        dukx_push_rect(ctx, rect);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+} // !namespace
+
+Rectangle dukx_get_rect(duk_context *ctx, duk_idx_t index)
+{
+    return parse(ctx, index, false);
+}
+
+Rectangle dukx_require_rect(duk_context *ctx, duk_idx_t index)
+{
+    return parse(ctx, index, true);
+}
+
+Rectangle dukx_optional_rect(duk_context *ctx, duk_idx_t index, Rectangle def)
+{
+    return parse(ctx, index, false, std::move(def));
+}
+
+void dukx_push_rect(duk_context *ctx, const Rectangle &rect)
+{
+    StackAssert sa(ctx, 1);
+
+    duk_push_object(ctx);
+    dukx_put_rect(ctx, rect);
+}
+
+void dukx_put_rect(duk_context *ctx, const Rectangle &rect)
+{
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx);
+
+    duk_push_int(ctx, rect.x());
+    duk_put_prop_string(ctx, -2, "x");
+    duk_push_int(ctx, rect.y());
+    duk_put_prop_string(ctx, -2, "y");
+    duk_push_uint(ctx, rect.width());
+    duk_put_prop_string(ctx, -2, "width");
+    duk_push_uint(ctx, rect.height());
+    duk_put_prop_string(ctx, -2, "height");
+}
+
+void dukx_load_rect(duk_context *ctx)
+{
+    StackAssert sa(ctx, 0);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Rectangle");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-rectangle.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,95 @@
+/*
+ * js-rectangle.hpp -- rectangle description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_RECTANGLE_HPP
+#define MALIKANIA_JS_RECTANGLE_HPP
+
+/**
+ * \file js-rectangle.hpp
+ * \brief JavaScript binding for Rectangle.
+ *
+ * Rectangles are plain objects.
+ *
+ * ````
+ * {
+ *   x: 10,
+ *   y: 20,
+ *   width: 100,
+ *   height: 200
+ * }
+ * ````
+ */
+
+#include "duktape.hpp"
+#include "rectangle.hpp"
+
+namespace malikania {
+
+/**
+ * Get a rectangle.
+ *
+ * The rectangle may be adjusted if any values are incorrect.
+ *
+ * @param ctx the context
+ * @param index the value index
+ * @return the rectangle
+ */
+Rectangle dukx_get_rect(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Require a rectangle.
+ *
+ * If the object is not a rectangle or if width, height are invalid, raise a JavaScript error.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @return the rectangle
+ */
+Rectangle dukx_require_rect(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Like get but return the default value if the value at the given index is not an object or invalid
+ *
+ * @param ctx the context
+ * @param index the idnex
+ * @param def the default value
+ * @return the rectangle
+ */
+Rectangle dukx_optional_rect(duk_context *ctx, duk_idx_t index, Rectangle def);
+
+/**
+ * Push the rectangle as object.
+ *
+ * @param ctx the context
+ * @param rect the rectangle
+ */
+void dukx_push_rect(duk_context *ctx, const Rectangle &rect);
+
+/**
+ * Put the rectangle properties into the object at the top of the stack.
+ *
+ * @param ctx the context
+ * @param rect the rectangle
+ */
+void dukx_put_rect(duk_context *ctx, const Rectangle &rect);
+
+void dukx_load_rect(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_RECTANGLE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-size.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,139 @@
+/*
+ * js-size.cpp -- size description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-size.hpp"
+
+namespace malikania {
+
+namespace {
+
+Size parse(duk_context *ctx, duk_idx_t index, bool required, Size size = {})
+{
+    StackAssert sa(ctx);
+
+    if (duk_is_object(ctx, index)) {
+        if (required && !duk_has_prop_string(ctx, index, "width"))
+            duk_error(ctx, DUK_ERR_ERROR, "missing width property in size description");
+        else if (required && !duk_has_prop_string(ctx, index, "height"))
+            duk_error(ctx, DUK_ERR_ERROR, "missing height property in size description");
+
+        int width;
+        int height;
+
+        duk_get_prop_string(ctx, index, "width");
+        width = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+        duk_get_prop_string(ctx, index, "height");
+        height = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+
+        if (width < 0)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "width can not be negative");
+        if (height < 0)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "height can not be negative");
+
+        size = Size(width, height);
+    } else if (required)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "size object expected");
+
+    return size;
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    Size size;
+
+    if (duk_get_top(ctx) == 2) {
+        int width;
+        int height;
+
+        if ((width = duk_require_int(ctx, 0)) < 0)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #0 can not be negative");
+        if ((height = duk_require_int(ctx, 1)) < 0)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #1 can not be negative");
+
+        size = Size(static_cast<unsigned>(width), static_cast<unsigned>(height));
+    } else if (duk_get_top(ctx) == 1)
+        size = parse(ctx, 0, true);
+
+    duk_ret_t ret;
+
+    // Allow both constructor and non constructor calls.
+    if (duk_is_constructor_call(ctx)) {
+        duk_push_this(ctx);
+        dukx_put_size(ctx, size);
+        duk_pop(ctx);
+        ret = 0;
+    } else {
+        dukx_push_size(ctx, size);
+        ret = 1;
+    }
+
+    return ret;
+}
+
+} // !namespace
+
+Size dukx_get_size(duk_context *ctx, duk_idx_t index)
+{
+    return parse(ctx, index, false);
+}
+
+Size dukx_require_size(duk_context *ctx, duk_idx_t index)
+{
+    return parse(ctx, index, true);
+}
+
+Size dukx_optional_size(duk_context *ctx, duk_idx_t index, Size def)
+{
+    return parse(ctx, index, false, std::move(def));
+}
+
+void dukx_push_size(duk_context *ctx, const Size &size)
+{
+    StackAssert sa(ctx, 1);
+
+    duk_push_object(ctx);
+    dukx_put_size(ctx, size);
+}
+
+void dukx_put_size(duk_context *ctx, const Size &size)
+{
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx, 0);
+
+    duk_push_uint(ctx, size.width());
+    duk_put_prop_string(ctx, -2, "width");
+    duk_push_uint(ctx, size.height());
+    duk_put_prop_string(ctx, -2, "height");
+}
+
+void dukx_load_size(duk_context *ctx)
+{
+    StackAssert sa(ctx, 0);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Size");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-size.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,93 @@
+/*
+ * js-size.hpp -- size description (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_SIZE_HPP
+#define MALIKANIA_JS_SIZE_HPP
+
+/**
+ * \file js-size.h
+ * \brief JavaScript binding for Size.
+ *
+ * Size are plain objects.
+ *
+ * ````
+ * {
+ *   width: 1000,
+ *   height: 2000
+ * }
+ * ````
+ */
+
+#include "duktape.hpp"
+#include "size.hpp"
+
+namespace malikania {
+
+/**
+ * Get a size.
+ *
+ * The size may be adjusted if any values are incorrect.
+ *
+ * @param ctx the context
+ * @param index the value index
+ * @return the size
+ */
+Size dukx_get_size(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Require a size
+ *
+ * If the object is not a size, raise a JavaScript error.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @return the size
+ */
+Size dukx_require_size(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Like get but return the default value if the value at the given index is not an object.
+ *
+ * @param ctx the context
+ * @param index the idnex
+ * @param def the default value
+ * @return the size
+ */
+Size dukx_optional_size(duk_context *ctx, duk_idx_t index, Size def);
+
+/**
+ * Push the size as object.
+ *
+ * @param ctx the context
+ * @param size the size
+ */
+void dukx_push_size(duk_context *ctx, const Size &size);
+
+/**
+ * Put the size properties into the object at the top of the stack.
+ *
+ * @param ctx the context
+ * @param size the size
+ */
+void dukx_put_size(duk_context *ctx, const Size &size);
+
+void dukx_load_size(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_SIZE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-sprite.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,166 @@
+/*
+ * js-sprite.cpp -- sprite object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-client-resources-loader.hpp"
+#include "js-point.hpp"
+#include "js-size.hpp"
+#include "js-sprite.hpp"
+#include "js-window.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Signature("\xff""\xff""malikania-sprite-ptr");
+
+Sprite *self(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Sprite object");
+
+    return static_cast<Sprite *>(ptr);
+}
+
+duk_ret_t cell(duk_context *ctx)
+{
+    dukx_push_size(ctx, self(ctx)->cell());
+
+    return 1;
+}
+
+duk_ret_t columns(duk_context *ctx)
+{
+    duk_push_uint(ctx, self(ctx)->columns());
+
+    return 1;
+}
+
+duk_ret_t margins(duk_context *ctx)
+{
+    dukx_push_size(ctx, self(ctx)->margin());
+
+    return 1;
+}
+
+duk_ret_t rows(duk_context *ctx)
+{
+    duk_push_uint(ctx, self(ctx)->rows());
+
+    return 1;
+}
+
+duk_ret_t space(duk_context *ctx)
+{
+    dukx_push_size(ctx, self(ctx)->space());
+
+    return 1;
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    if (!duk_is_constructor_call(ctx))
+        duk_error(ctx, DUK_ERR_ERROR, "sprite must be new-constructed");
+
+    try {
+        auto loader = dukx_get_client_loader(ctx);
+        auto sprite = loader->loadSprite(duk_require_string(ctx, 0));
+
+        duk_push_this(ctx);
+        duk_push_pointer(ctx, new Sprite(std::move(sprite)));
+        duk_put_prop_string(ctx, -2, Signature.c_str());
+
+        // Cell.
+        duk_push_string(ctx, "cell");
+        duk_push_c_function(ctx, cell, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+
+        // Columns.
+        duk_push_string(ctx, "columns");
+        duk_push_c_function(ctx, columns, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+
+        // Margins.
+        duk_push_string(ctx, "margins");
+        duk_push_c_function(ctx, margins, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+
+        // Rows.
+        duk_push_string(ctx, "rows");
+        duk_push_c_function(ctx, rows, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+
+        // Space.
+        duk_push_string(ctx, "space");
+        duk_push_c_function(ctx, space, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+
+        duk_pop(ctx);
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t draw(duk_context *ctx)
+{
+    try {
+        auto sprite = self(ctx);
+        auto window = dukx_require_window(ctx, 0);
+        auto cell = duk_require_uint(ctx, 1);
+        auto point = dukx_get_point(ctx, 2);
+
+        if (cell >= (sprite->rows() * sprite->columns()))
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range", cell);
+
+        sprite->draw(*window, cell, point);
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "draw",   draw,       3 },
+    { nullptr,  nullptr,    0 }
+};
+
+} // !namespace
+
+void dukx_load_sprite(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Sprite");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-sprite.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,31 @@
+/*
+ * js-sprite.hpp -- sprite object (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_SPRITE_HPP
+#define MALIKANIA_JS_SPRITE_HPP
+
+#include "duktape.hpp"
+#include "sprite.hpp"
+
+namespace malikania {
+
+void dukx_load_sprite(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_SPRITE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-window.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,284 @@
+/*
+ * js-window.cpp -- window management (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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 "js-color.hpp"
+#include "js-font.hpp"
+#include "js-line.hpp"
+#include "js-point.hpp"
+#include "js-rectangle.hpp"
+#include "js-window.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Signature("\xff""\xff""malikania-window-ptr");
+const std::string Prototype("\xff""\xff""malikania-window-prototype");
+
+Window *self(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Window object");
+
+    return static_cast<Window *>(ptr);
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    if (!duk_is_constructor_call(ctx))
+        duk_error(ctx, DUK_ERR_ERROR, "window must be new-constructed");
+
+    // TODO: add parameters.
+    try {
+        auto win = new Window;
+
+        duk_push_this(ctx);
+        duk_push_pointer(ctx, win);
+        duk_put_prop_string(ctx, -2, Signature.c_str());
+        duk_pop(ctx);
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t clear(duk_context *ctx)
+{
+    try {
+        self(ctx)->clear();
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t present(duk_context *ctx)
+{
+    try {
+        self(ctx)->present();
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawingColor(duk_context *ctx)
+{
+    try {
+        dukx_push_color(ctx, self(ctx)->drawingColor());
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 1;
+}
+
+duk_ret_t drawLine(duk_context *ctx)
+{
+    try {
+        self(ctx)->drawLine(dukx_require_line(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawLines(duk_context *ctx)
+{
+    try {
+        self(ctx)->drawLines(dukx_get_array(ctx, 0, dukx_get_point));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawPoint(duk_context *ctx)
+{
+    try {
+        self(ctx)->drawPoint(dukx_require_point(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawPoints(duk_context *ctx)
+{
+    try {
+        self(ctx)->drawPoints(dukx_get_array(ctx, 0, dukx_get_point));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawRectangle(duk_context *ctx)
+{
+    try {
+        self(ctx)->drawRectangle(dukx_require_rect(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawRectangles(duk_context *ctx)
+{
+    try {
+        self(ctx)->drawRectangles(dukx_get_array(ctx, 0, dukx_get_rect));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawText(duk_context *ctx)
+{
+    try {
+        auto win = self(ctx);
+        auto text = duk_require_string(ctx, 0);
+        auto font = dukx_require_font(ctx, 1);
+        auto rect = dukx_get_rect(ctx, 2);
+
+        if (!rect.isNull())
+            win->drawText(text, *font, rect);
+        else
+            win->drawText(text, *font, Point(rect.x(), rect.y()));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t fillRectangle(duk_context *ctx)
+{
+    try {
+        self(ctx)->fillRectangle(dukx_require_rect(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t fillRectangles(duk_context *ctx)
+{
+    try {
+        self(ctx)->fillRectangles(dukx_get_array(ctx, 0, dukx_get_rect));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t setDrawingColor(duk_context *ctx)
+{
+    try {
+        self(ctx)->setDrawingColor(dukx_require_color(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "clear",              clear,              0 },
+    { "drawingColor",       drawingColor,       0 },
+    { "drawLine",           drawLine,           1 },
+    { "drawLines",          drawLines,          1 },
+    { "drawPoint",          drawPoint,          1 },
+    { "drawPoints",         drawPoints,         1 },
+    { "drawRectangle",      drawRectangle,      1 },
+    { "drawRectangles",     drawRectangles,     1 },
+    { "drawText",           drawText,           3 },
+    { "fillRectangle",      fillRectangle,      1 },
+    { "fillRectangles",     fillRectangles,     1 },
+    { "present",            present,            0 },
+    { "setDrawingColor",    setDrawingColor,    1 },
+    { nullptr,              nullptr,            0 }
+};
+
+} // !namespace
+
+void dukx_new_window(duk_context *ctx, Window *window)
+{
+    assert(ctx);
+    assert(window);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, window);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+}
+
+Window *dukx_require_window(duk_context *ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_prop_string(ctx, index, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Window object");
+
+    return static_cast<Window *>(ptr);
+}
+
+void dukx_load_window(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 0);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Window");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient-js/malikania/js-window.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,33 @@
+/*
+ * js-window.hpp -- window management (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * 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.
+ */
+
+#ifndef MALIKANIA_JS_WINDOW_HPP
+#define MALIKANIA_JS_WINDOW_HPP
+
+#include "duktape.hpp"
+#include "window.hpp"
+
+namespace malikania {
+
+Window *dukx_require_window(duk_context *ctx, duk_idx_t index);
+
+void dukx_load_window(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_WINDOW_HPP
--- a/libclient/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/libclient/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -28,19 +28,6 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/color.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/font.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/image.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-animation.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-animator.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client-resources-loader.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client-target.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-color.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-font.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-image.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-line.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-point.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-rectangle.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-sprite.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-window.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/label.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/line.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/point.hpp
@@ -63,20 +50,6 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/color.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/font.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/image.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-animation.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-animator.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client-resources-loader.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client-target.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-color.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-font.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-image.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-line.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-point.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-rectangle.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-sprite.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-size.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-window.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/label.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/sprite.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/window.cpp
@@ -94,6 +67,7 @@
     TARGET libclient
     SOURCES ${HEADERS} ${SOURCES}
     PUBLIC_INCLUDES
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/malikania>
         ${SDL2_INCLUDE_DIRS}
         ${SDL2_IMAGE_INCLUDE_DIRS}
         ${SDL2_TTF_INCLUDE_DIRS}
--- a/libclient/malikania/js-animation.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * js-animation.cpp -- animation description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client-resources-loader.hpp"
-#include "js-animation.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-animation-ptr");
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "animation must be new-constructed");
-
-    try {
-        auto loader = dukx_get_client_loader(ctx);
-        auto animation = loader->loadAnimation(duk_require_string(ctx, 0));
-
-        dukx_new_animation(ctx, new Animation(std::move(animation)));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t destructor(duk_context *ctx)
-{
-    duk_get_prop_string(ctx, 0, Signature.c_str());
-    delete static_cast<Animation *>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-    duk_del_prop_string(ctx, 0, Signature.c_str());
-
-    return 0;
-}
-
-} // !namespace
-
-void dukx_new_animation(duk_context *ctx, Animation *animation)
-{
-    assert(ctx);
-    assert(animation);
-
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, animation);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-}
-
-Animation *dukx_require_animation(duk_context *ctx, duk_idx_t index)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_prop_string(ctx, index, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animation object");
-
-    return static_cast<Animation *>(ptr);
-}
-
-void dukx_load_animation(duk_context *ctx)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 1);
-    duk_push_object(ctx);
-    duk_push_c_function(ctx, destructor, 1);
-    duk_set_finalizer(ctx, -2);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Animation");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-animation.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * js-animation.hpp -- animation description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_ANIMATION_HPP
-#define MALIKANIA_JS_ANIMATION_HPP
-
-#include <malikania/duktape.hpp>
-
-#include "animation.hpp"
-
-namespace malikania {
-
-/**
- * Construct an Animation object as this.
- *
- * \pre ctx != nullptr
- * \pre animation != nullptr
- * \param ctx the context
- * \param animation the animation
- */
-void dukx_new_animation(duk_context *ctx, Animation *animation);
-
-/**
- * Get an Animation object at the given index or raise a JavaScript error.
- *
- * \pre ctx != nullptr
- * \param ctx the context
- * \param index the value index
- * \return the Animation object
- */
-Animation *dukx_require_animation(duk_context *ctx, duk_idx_t index);
-
-/**
- * Load the Animation module into the context.
- *
- * \pre ctx != nullptr
- * \param ctx the context
- */
-void dukx_load_animation(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_ANIMATION_HPP
--- a/libclient/malikania/js-animator.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * js-animator.cpp -- animation drawing object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 <string>
-
-#include "js-animation.hpp"
-#include "js-animator.hpp"
-#include "js-point.hpp"
-#include "js-window.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-animator-ptr");
-
-Animator *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
-
-    return static_cast<Animator *>(ptr);
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "animator must be new-constructed");
-
-    // Be sure animation get not collected before.
-    dukx_new_animator(ctx, new Animator(*dukx_require_animation(ctx, 0)));
-    duk_push_this(ctx);
-    duk_dup(ctx, 0);
-    duk_put_prop_string(ctx, -2, "\xff""\xff""animation-ref");
-
-    return 0;
-}
-
-duk_ret_t destructor(duk_context *ctx)
-{
-    duk_get_prop_string(ctx, 0, Signature.c_str());
-    delete static_cast<Animator *>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-    duk_del_prop_string(ctx, 0, Signature.c_str());
-
-    return 0;
-}
-
-duk_ret_t draw(duk_context *ctx)
-{
-    try {
-        self(ctx)->draw(*dukx_require_window(ctx, 0), dukx_get_point(ctx, 1));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t update(duk_context *ctx)
-{
-    self(ctx)->update();
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "draw",   draw,       2 },
-    { "update", update,     0 },
-    { nullptr,  nullptr,    0 }
-};
-
-} // !namespace
-
-void dukx_new_animator(duk_context *ctx, Animator *animator)
-{
-    assert(ctx);
-    assert(animator);
-
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, animator);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-}
-
-Animator *dukx_require_animator(duk_context *ctx, duk_idx_t index)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_prop_string(ctx, index, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
-
-    return static_cast<Animator *>(ptr);
-}
-
-void dukx_load_animator(duk_context *ctx)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 1);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_push_c_function(ctx, destructor, 1);
-    duk_set_finalizer(ctx, -2);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Animator");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-animator.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * js-animator.hpp -- animation drawing object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_ANIMATOR_HPP
-#define MALIKANIA_JS_ANIMATOR_HPP
-
-#include "animator.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-/**
- * Construct an Animator object as this.
- *
- * \pre ctx != nullptr
- * \pre animator != nullptr
- * \param ctx the context
- * \param animator the animator
- */
-void dukx_new_animator(duk_context *ctx, Animator *animator);
-
-/**
- * Get the animator at the given index.
- *
- * \pre ctx != nullptr
- * \param ctx the context
- * \param index the value index
- * \return the animator
- */
-Animator *dukx_require_animator(duk_context *ctx, duk_idx_t index);
-
-void dukx_load_animator(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_ANIMATOR_HPP
--- a/libclient/malikania/js-client-resources-loader.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * js-client-resources-loader.cpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client-resources-loader.hpp"
-#include "js-resources-loader.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Variable("\xff""\xff""malikania-client-resources-loader");
-
-} // !namespace
-
-void dukx_put_client_loader(duk_context *ctx, ClientResourcesLoader *loader)
-{
-    assert(ctx);
-    assert(loader);
-
-    // Also store as parent.
-    dukx_put_loader(ctx, loader);
-
-    StackAssert sa(ctx);
-
-    duk_push_pointer(ctx, loader);
-    duk_put_global_string(ctx, Variable.c_str());
-}
-
-ClientResourcesLoader *dukx_get_client_loader(duk_context *ctx)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, Variable.c_str());
-    auto ptr = static_cast<ClientResourcesLoader *>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-
-    return static_cast<ClientResourcesLoader *>(ptr);
-}
-
-} // !malikania
--- a/libclient/malikania/js-client-resources-loader.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * js-client-resources-loader.hpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
-#define MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
-
-#include "client-resources-loader.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-void dukx_put_client_loader(duk_context *ctx, ClientResourcesLoader *);
-
-ClientResourcesLoader *dukx_get_client_loader(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
--- a/libclient/malikania/js-client-target.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * js-client-target.cpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client-target.hpp"
-
-namespace malikania {
-
-class JsTarget : public Client::Target {
-public:
-
-};
-
-namespace {
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    return 0;
-}
-
-duk_ret_t draw(duk_context *ctx)
-{
-    return 0;
-}
-
-} // !namespace
-
-void dukx_load_client_target(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_get_prop_string(ctx, -1, "Client");
-    duk_push_c_function(ctx, constructor, 1);
-    duk_push_object(ctx);
-    duk_put_prop_string(ctx, -1, "prototype");
-    duk_put_prop_string(ctx, -2, "Target");
-    duk_pop_2(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-client-target.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * js-client-target.hpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_CLIENT_TARGET_HPP
-#define MALIKANIA_JS_CLIENT_TARGET_HPP
-
-#include "client-target.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-void dukx_load_client_target(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_CLIENT_TARGET_HPP
--- a/libclient/malikania/js-client.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * js-client.cpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client.hpp"
-#include "js-client-target.hpp"
-#include "js-window.hpp"
-
-namespace malikania {
-
-namespace {
-
-duk_ret_t draw(duk_context *)
-{
-#if 0
-    try {
-        duk::self<std::shared_ptr<Client>>(ctx)->draw();
-    } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-#endif
-
-    return 0;
-}
-
-duk_ret_t setTarget(duk_context *)
-{
-#if 0
-    auto self = duk::self<Client *>(ctx);
-    auto target = duk::get<std::shared_ptr<Client::Target>>(ctx, 0);
-
-    self->setTarget(std::move(target));
-#endif
-
-    return 0;
-}
-
-duk_ret_t update(duk_context *)
-{
-#if 0
-    try {
-        duk::self<std::shared_ptr<Client>>(ctx)->update();
-    } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-#endif
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "draw",       draw,       0 },
-    { "setTarget",  setTarget,  1 },
-    { "update",     update,     0 },
-    { nullptr,      nullptr,    0 }
-};
-
-} // !namespace
-
-void dukx_load_client(duk_context *ctx)
-{
-#if 0
-    duk::StackAssert sa(ctx);
-
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::push(ctx, duk::Object());
-    duk::push(ctx, duk::Object());
-    duk::TypeTraits<Window>::prototype(ctx);
-    duk::setPrototype(ctx, -2);
-    duk::put(ctx, methods);
-    duk::putProperty(ctx, -2, "prototype");
-    duk::putProperty(ctx, -2, "Client");
-    duk::pop(ctx);
-#endif
-}
-
-} // !malikania
--- a/libclient/malikania/js-client.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * js-client.hpp -- client resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_CLIENT_HPP
-#define MALIKANIA_JS_CLIENT_HPP
-
-#include "client.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-void dukx_load_client(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_CLIENT_HPP
--- a/libclient/malikania/js-color.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * js-color.cpp -- color description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-color.hpp"
-#include "util.hpp"
-
-namespace malikania {
-
-namespace {
-
-std::uint8_t clampComponent(duk_context *ctx, int value, bool required)
-{
-    if (value < 0 || value > 255) {
-        if (required)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range (0, 255)", value);
-        else
-            value = util::clamp(value, 0, 255);
-    }
-
-    return static_cast<std::uint8_t>(value);
-}
-
-Color parseString(duk_context *ctx, duk_idx_t index, bool required)
-{
-    assert(duk_is_string(ctx, index));
-
-    Color color;
-
-    try {
-        color = Color(duk_get_string(ctx, index));
-    } catch (const std::exception &ex) {
-        if (required)
-            duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return color;
-}
-
-Color parseObject(duk_context *ctx, duk_idx_t index, bool required)
-{
-    assert(duk_is_object(ctx, index));
-
-    auto require = [&] (const auto prop) -> std::uint8_t {
-        if (required && !duk_has_prop_string(ctx, index, prop))
-            duk_error(ctx, DUK_ERR_ERROR, "missing %s property in color description", prop);
-
-        duk_get_prop_string(ctx, index, prop);
-        auto comp = duk_get_int(ctx, -1);
-        duk_pop(ctx);
-
-        return clampComponent(ctx, comp, required);
-    };
-
-    // Alpha is optional.
-    duk_get_prop_string(ctx, index, "alpha");
-    auto alpha = duk_is_number(ctx, -1) ? duk_to_int(ctx, -1) : 255;
-    duk_pop(ctx);
-
-    return Color(
-        require("red"),
-        require("green"),
-        require("blue"),
-        clampComponent(ctx, alpha, required)
-    );
-}
-
-Color parse(duk_context *ctx, duk_idx_t index, bool required, Color color = {})
-{
-    switch (duk_get_type(ctx, index)) {
-    case DUK_TYPE_STRING:
-        color = parseString(ctx, index, required);
-        break;
-    case DUK_TYPE_OBJECT:
-        color = parseObject(ctx, index, required);
-        break;
-    default:
-        if (required)
-            duk_error(ctx, DUK_ERR_TYPE_ERROR, "color (string, object) expected");
-
-        break;
-    }
-
-    return color;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    Color color;
-
-    /*
-     * The constructor allows an additional signature that takes 4 number
-     * arguments, otherwise use the literal parsing functions.
-     */
-    if (duk_get_top(ctx) >= 3) {
-        // Alpha is optional.
-        auto alpha = duk_is_number(ctx, 3) ? duk_to_int(ctx, 3) : 255;
-
-        color = Color(
-            clampComponent(ctx, duk_require_int(ctx, 0), true),
-            clampComponent(ctx, duk_require_int(ctx, 1), true),
-            clampComponent(ctx, duk_require_int(ctx, 2), true),
-            clampComponent(ctx, alpha, true)
-        );
-    } else if (duk_get_top(ctx) == 1)
-        color = parse(ctx, 0, true);
-
-    duk_ret_t ret;
-
-    // Allow both constructor and non constructor calls.
-    if (duk_is_constructor_call(ctx)) {
-        duk_push_this(ctx);
-        dukx_put_color(ctx, color);
-        duk_pop(ctx);
-        ret = 0;
-    } else {
-        dukx_push_color(ctx, color);
-        ret = 1;
-    }
-
-    return ret;
-}
-
-} //! namespace
-
-Color dukx_get_color(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, false);
-}
-
-Color dukx_require_color(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, true);
-}
-
-Color dukx_optional_color(duk_context *ctx, duk_idx_t index, Color def)
-{
-    return parse(ctx, index, false, std::move(def));
-}
-
-void dukx_push_color(duk_context *ctx, const Color &color)
-{
-    StackAssert sa(ctx, 1);
-
-    duk_push_object(ctx);
-    dukx_put_color(ctx, color);
-}
-
-void dukx_put_color(duk_context *ctx, const Color &color)
-{
-    assert(duk_is_object(ctx, -1));
-
-    StackAssert sa(ctx, 0);
-
-    duk_push_uint(ctx, color.red());
-    duk_put_prop_string(ctx, -2, "red");
-    duk_push_uint(ctx, color.green());
-    duk_put_prop_string(ctx, -2, "green");
-    duk_push_uint(ctx, color.blue());
-    duk_put_prop_string(ctx, -2, "blue");
-    duk_push_uint(ctx, color.alpha());
-    duk_put_prop_string(ctx, -2, "alpha");
-}
-
-void dukx_load_color(duk_context *ctx)
-{
-    StackAssert sa(ctx, 0);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "Color");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-color.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * js-color.hpp -- color description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_COLOR_HPP
-#define MALIKANIA_JS_COLOR_HPP
-
-/**
- * \file js-color.h
- * \brief JavaScript binding for Color.
- *
- * Colors can be created from plain JavaScript object.
- *
- * ````
- * {
- *   red: 0,
- *   green: 255,
- *   blue: 255,
- *   alpha: 255
- * }
- * ````
- *
- * It can also takes strings like "#rrggbbaa" and SVG names.
- */
-
-#include "color.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-/**
- * Get a color.
- *
- * May return a default value or a color with adjusted components.
- *
- * @param ctx the context
- * @param index the index
- */
-Color dukx_get_color(duk_context *ctx, duk_idx_t index);
-
-/**
- * Require a color.
- *
- * If the color has any invalid component, raise a JavaScript error.
- *
- * @param ctx the context
- * @param index the index
- */
-Color dukx_require_color(duk_context *ctx, duk_idx_t index);
-
-/**
- * Like get, but return the default value only if the value at the given
- * index is not an object or not a string, otherwise, adjust invalid values.
- *
- * @param ctx the context
- * @param index the index
- * @param def the default value
- */
-Color dukx_optional_color(duk_context *ctx, duk_idx_t index, Color def);
-
-/**
- * Push the color as object.
- *
- * @param ctx the context
- * @param color the color
- */
-void dukx_push_color(duk_context *ctx, const Color &color);
-
-/**
- * Put the color properties into the object at the top of the stack.
- *
- * @pre the top value must be an object
- * @param ctx the context
- * @param color the color
- */
-void dukx_put_color(duk_context *ctx, const Color &color);
-
-void dukx_load_color(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_COLOR_HPP
--- a/libclient/malikania/js-font.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * js-font.cpp -- font object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client-resources-loader.hpp"
-#include "js-font.hpp"
-#include "js-size.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-font-ptr");
-
-Font *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Font object");
-
-    return static_cast<Font *>(ptr);
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "font must be new-constructed");
-
-    try {
-        auto loader = dukx_get_client_loader(ctx);
-        auto id = duk_require_string(ctx, 0);
-        auto size = duk_require_int(ctx, 1);
-
-        if (size < 0)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d must not be negative", size);
-
-        dukx_new_font(ctx, new Font(loader->loadFont(id, static_cast<unsigned>(size))));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t clip(duk_context *ctx)
-{
-    try {
-        dukx_push_size(ctx, self(ctx)->clip(duk_require_string(ctx, 0)));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 1;
-}
-
-const duk_function_list_entry methods[] = {
-    { "clip",   clip,       1 },
-    { nullptr,  nullptr,    0 }
-};
-
-} // !namespace
-
-void dukx_new_font(duk_context *ctx, Font *font)
-{
-    assert(ctx);
-    assert(font);
-
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, font);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-}
-
-Font *dukx_require_font(duk_context *ctx, duk_idx_t index)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_prop_string(ctx, index, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Font object");
-
-    return static_cast<Font *>(ptr);
-}
-
-void dukx_load_font(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 2);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Font");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-font.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * js-font.hpp -- font object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_FONT_HPP
-#define MALIKANIA_JS_FONT_HPP
-
-#include "duktape.hpp"
-#include "font.hpp"
-
-namespace malikania {
-
-void dukx_new_font(duk_context *ctx, Font *font);
-
-Font *dukx_require_font(duk_context *ctx, duk_idx_t index);
-
-void dukx_load_font(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_FONT_HPP
--- a/libclient/malikania/js-image.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * js-image.cpp -- image object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client-resources-loader.hpp"
-#include "js-image.hpp"
-#include "js-point.hpp"
-#include "js-rectangle.hpp"
-#include "js-size.hpp"
-#include "js-window.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-image-ptr");
-
-Image *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
-
-    return static_cast<Image *>(ptr);
-}
-
-duk_ret_t size(duk_context *ctx)
-{
-    try {
-        dukx_push_size(ctx, self(ctx)->size());
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 1;
-}
-
-duk_ret_t draw(duk_context *ctx)
-{
-    try {
-        auto image = self(ctx);
-        auto window = dukx_require_window(ctx, 0);
-
-        if (duk_get_top(ctx) == 2)
-            image->draw(*window, dukx_get_point(ctx, 1));
-        else if (duk_get_top(ctx) == 3)
-            image->draw(*window, dukx_get_rect(ctx, 1), dukx_get_rect(ctx, 2));
-        else
-            duk_error(ctx, DUK_ERR_TYPE_ERROR, "invalid number of arguments: #%d", duk_get_top(ctx));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "image must be new-constructed");
-
-    try {
-        auto loader = dukx_get_client_loader(ctx);
-        auto image = new Image(loader->loadImage(duk_require_string(ctx, 0)));
-
-        dukx_new_image(ctx, image);
-        duk_push_this(ctx);
-        duk_push_string(ctx, "size");
-        duk_push_c_function(ctx, size, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-        duk_pop(ctx);
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "draw",   draw,       DUK_VARARGS },
-    { nullptr,  nullptr,    0           }
-};
-
-} // !namespace
-
-void dukx_new_image(duk_context *ctx, Image *image)
-{
-    assert(ctx);
-    assert(image);
-
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, image);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-}
-
-void dukx_load_image(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 1);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Image");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-image.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * js-image.hpp -- image object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_IMAGE_HPP
-#define MALIKANIA_JS_IMAGE_HPP
-
-#include "duktape.hpp"
-#include "image.hpp"
-
-namespace malikania {
-
-void dukx_new_image(duk_context *ctx, Image *image);
-
-void dukx_load_image(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_IMAGE_HPP
--- a/libclient/malikania/js-line.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * js-line.cpp -- line description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-line.hpp"
-
-namespace malikania {
-
-namespace {
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    Line line;
-
-    if (duk_get_top(ctx) == 4) {
-        line = Line(
-            duk_get_int(ctx, 0),
-            duk_get_int(ctx, 1),
-            duk_get_int(ctx, 2),
-            duk_get_int(ctx, 3)
-        );
-    } else if (duk_get_top(ctx) == 1)
-        line = dukx_require_line(ctx, 0);
-
-    duk_ret_t ret;
-
-    /* Allow both constructor and non constructor calls */
-    if (duk_is_constructor_call(ctx)) {
-        duk_push_this(ctx);
-        dukx_put_line(ctx, line);
-        ret = 0;
-    } else {
-        dukx_push_line(ctx, line);
-        ret = 1;
-    }
-
-    return ret;
-}
-
-} // !namespace
-
-Line dukx_get_line(duk_context *ctx, duk_idx_t index)
-{
-    auto get = [&] (auto name) {
-        StackAssert sa(ctx);
-
-        duk_get_prop_string(ctx, index, name);
-        auto v = duk_get_int(ctx, -1);
-        duk_pop(ctx);
-
-        return v;
-    };
-
-    return Line(get("x1"), get("y1"), get("x2"), get("y2"));
-}
-
-Line dukx_require_line(duk_context *ctx, duk_idx_t index)
-{
-    auto get = [&] (auto prop) {
-        if (!duk_has_prop_string(ctx, index, prop))
-            duk_error(ctx, DUK_ERR_ERROR, "missing %s property in line description", prop);
-
-        duk_get_prop_string(ctx, index, prop);
-
-        if (!duk_is_number(ctx, -1)) {
-            duk_pop(ctx);
-            duk_error(ctx, DUK_ERR_TYPE_ERROR, "property %s is not an int", prop);
-        }
-
-        auto value = duk_to_int(ctx, -1);
-
-        duk_pop(ctx);
-
-        return value;
-    };
-
-    return Line(get("x1"), get("y1"), get("x2"), get("y2"));
-}
-
-Line dukx_optional_line(duk_context *ctx, duk_idx_t index, Line def)
-{
-    return duk_is_object(ctx, index) ? dukx_get_line(ctx, index) : def;
-}
-
-void dukx_push_line(duk_context *ctx, const Line &line)
-{
-    StackAssert sa(ctx, 1);
-
-    duk_push_object(ctx);
-    dukx_put_line(ctx, line);
-}
-
-void dukx_put_line(duk_context *ctx, const Line &line)
-{
-    assert(duk_is_object(ctx, -1));
-
-    StackAssert sa(ctx);
-
-    duk_push_int(ctx, line.x1());
-    duk_put_prop_string(ctx, -2, "x1");
-    duk_push_int(ctx, line.y1());
-    duk_put_prop_string(ctx, -2, "y1");
-    duk_push_int(ctx, line.x2());
-    duk_put_prop_string(ctx, -2, "x2");
-    duk_push_int(ctx, line.y2());
-    duk_put_prop_string(ctx, -2, "y2");
-}
-
-void dukx_load_line(duk_context *ctx)
-{
-    StackAssert sa(ctx, 0);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "Line");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-line.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * js-line.hpp -- line description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_LINE_HPP
-#define MALIKANIA_JS_LINE_HPP
-
-/**
- * \file js-line.h
- * \brief JavaScript binding for Line.
- *
- * Lines are plain objects.
- *
- * ````
- * {
- *   x1: 10,
- *   y1: 10,
- *   x2: 50,
- *   y2: 50
- * }
- * ````
- */
-
-#include "duktape.hpp"
-#include "line.hpp"
-
-namespace malikania {
-
-/**
- * Get a line.
- *
- * @param ctx the context
- * @param index the index
- * @return the line
- */
-Line dukx_get_line(duk_context *ctx, duk_idx_t index);
-
-/**
- * Require a line.
- *
- * If value is not an object or any property is invalid, raise a JavaScript error.
- *
- * @param ctx the context
- * @param index the index
- * @return the line
- */
-Line dukx_require_line(duk_context *ctx, duk_idx_t index);
-
-/**
- * Like get but return def if the value at the given index is not an object.
- *
- * @param ctx the context
- * @param index the index
- * @param def the default value
- * @return the line
- */
-Line dukx_optional_line(duk_context *ctx, duk_idx_t index, Line def);
-
-/**
- * Push the line as object.
- *
- * @param ctx the context
- * @param line the line
- */
-void dukx_push_line(duk_context *ctx, const Line &line);
-
-/**
- * Put the line properties into the object at the top of the stack.
- *
- * @param ctx the context
- * @param line the line
- */
-void dukx_put_line(duk_context *ctx, const Line &line);
-
-void dukx_load_line(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_LINE_HPP
--- a/libclient/malikania/js-point.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * js-point.cpp -- point description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-point.hpp"
-
-namespace malikania {
-
-namespace {
-
-Point parse(duk_context *ctx, duk_idx_t index, bool required, Point point = {})
-{
-    StackAssert sa(ctx);
-
-    if (duk_is_object(ctx, index)) {
-        if (required && !duk_has_prop_string(ctx, index, "x"))
-            duk_error(ctx, DUK_ERR_ERROR, "missing x property in point description");
-        else if (required && !duk_has_prop_string(ctx, index, "y"))
-            duk_error(ctx, DUK_ERR_ERROR, "missing y property in point description");
-
-        //point = Point(duk::getProperty<int>(ctx, index, "x"), duk::getProperty<int>(ctx, index, "y"));
-        int x;
-        int y;
-
-        duk_get_prop_string(ctx, index, "x");
-        x = duk_to_int(ctx, -1);
-        duk_pop(ctx);
-        duk_get_prop_string(ctx, index, "y");
-        y = duk_to_int(ctx, -1);
-        duk_pop(ctx);
-
-        point = Point(x, y);
-    } else if (required)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "point object expected");
-
-    return point;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    Point point;
-
-    if (duk_get_top(ctx) == 2)
-        point = Point(duk_require_int(ctx, 0), duk_require_int(ctx, 1));
-    else if (duk_get_top(ctx) == 1)
-        point = parse(ctx, 0, true);
-
-    duk_ret_t ret;
-
-    // Allow both constructor and non constructor calls.
-    if (duk_is_constructor_call(ctx)) {
-        duk_push_this(ctx);
-        dukx_put_point(ctx, point);
-        duk_pop(ctx);
-        ret = 0;
-    } else {
-        dukx_push_point(ctx, point);
-        ret = 1;
-    }
-
-    return ret;
-}
-
-} // !namespace
-
-Point dukx_get_point(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, false);
-}
-
-Point dukx_require_point(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, true);
-}
-
-Point dukx_optional_point(duk_context *ctx, duk_idx_t index, Point def)
-{
-    return parse(ctx, index, false, std::move(def));
-}
-
-void dukx_push_point(duk_context *ctx, const Point &point)
-{
-    StackAssert sa(ctx, 1);
-
-    duk_push_object(ctx);
-    dukx_put_point(ctx, point);
-}
-
-void dukx_put_point(duk_context *ctx, const Point &point)
-{
-    assert(duk_is_object(ctx, -1));
-
-    StackAssert sa(ctx);
-
-    duk_push_int(ctx, point.x());
-    duk_put_prop_string(ctx, -2, "x");
-    duk_push_int(ctx, point.y());
-    duk_put_prop_string(ctx, -2, "y");
-}
-
-void dukx_load_point(duk_context *ctx)
-{
-    StackAssert sa(ctx, 0);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "Point");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-point.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * js-point.hpp -- point description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_POINT_HPP
-#define MALIKANIA_JS_POINT_HPP
-
-#include "duktape.hpp"
-#include "point.hpp"
-
-namespace malikania {
-
-Point dukx_require_point(duk_context *ctx, duk_idx_t index);
-
-Point dukx_get_point(duk_context *ctx, duk_idx_t index);
-
-void dukx_push_point(duk_context *ctx, const Point &point);
-
-void dukx_put_point(duk_context *ctx, const Point &point);
-
-void dukx_load_point(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_POINT_HPP
--- a/libclient/malikania/js-rectangle.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * js-rectangle.cpp -- rectangle description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-rectangle.hpp"
-
-namespace malikania {
-
-namespace {
-
-unsigned clamp(duk_context *ctx, int value, bool required)
-{
-    if (value < 0) {
-        if (required)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d can not be negative", value);
-        else
-            value = 0;
-    }
-
-    return static_cast<unsigned>(value);
-}
-
-Rectangle parse(duk_context *ctx, duk_idx_t index, bool required, Rectangle rect = {})
-{
-    StackAssert sa(ctx);
-
-    if (duk_is_object(ctx, index)) {
-        auto get = [&] (auto prop) {
-            if (required && !duk_has_prop_string(ctx, index, prop))
-                duk_error(ctx, DUK_ERR_ERROR, "missing '%s' property", prop);
-
-            duk_get_prop_string(ctx, index, prop);
-
-            if (required && !duk_is_number(ctx, -1)) {
-                duk_pop(ctx);
-                duk_error(ctx, DUK_ERR_ERROR, "invalid '%s' property (number expected)", prop);
-            }
-
-            auto value = duk_to_int(ctx, -1);
-
-            duk_pop(ctx);
-
-            return value;
-        };
-
-        rect = Rectangle(get("x"), get("y"),
-            clamp(ctx, get("width"), required), clamp(ctx, get("height"), required));
-    } else if (required)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "rectangle object expected");
-
-    return rect;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    Rectangle rect;
-
-    if (duk_get_top(ctx) == 4) {
-        rect = Rectangle(
-            duk_require_int(ctx, 0),
-            duk_require_int(ctx, 1),
-            clamp(ctx, duk_require_int(ctx, 2), true),
-            clamp(ctx, duk_require_int(ctx, 3), true)
-        );
-    } else if (duk_get_top(ctx) == 1)
-        rect = parse(ctx, 0, true);
-
-    duk_ret_t ret;
-
-    // Allow both constructor and non constructor calls.
-    if (duk_is_constructor_call(ctx)) {
-        duk_push_this(ctx);
-        dukx_put_rect(ctx, rect);
-        duk_pop(ctx);
-        ret = 0;
-    } else {
-        dukx_push_rect(ctx, rect);
-        ret = 1;
-    }
-
-    return ret;
-}
-
-} // !namespace
-
-Rectangle dukx_get_rect(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, false);
-}
-
-Rectangle dukx_require_rect(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, true);
-}
-
-Rectangle dukx_optional_rect(duk_context *ctx, duk_idx_t index, Rectangle def)
-{
-    return parse(ctx, index, false, std::move(def));
-}
-
-void dukx_push_rect(duk_context *ctx, const Rectangle &rect)
-{
-    StackAssert sa(ctx, 1);
-
-    duk_push_object(ctx);
-    dukx_put_rect(ctx, rect);
-}
-
-void dukx_put_rect(duk_context *ctx, const Rectangle &rect)
-{
-    assert(duk_is_object(ctx, -1));
-
-    StackAssert sa(ctx);
-
-    duk_push_int(ctx, rect.x());
-    duk_put_prop_string(ctx, -2, "x");
-    duk_push_int(ctx, rect.y());
-    duk_put_prop_string(ctx, -2, "y");
-    duk_push_uint(ctx, rect.width());
-    duk_put_prop_string(ctx, -2, "width");
-    duk_push_uint(ctx, rect.height());
-    duk_put_prop_string(ctx, -2, "height");
-}
-
-void dukx_load_rect(duk_context *ctx)
-{
-    StackAssert sa(ctx, 0);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "Rectangle");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-rectangle.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * js-rectangle.hpp -- rectangle description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_RECTANGLE_HPP
-#define MALIKANIA_JS_RECTANGLE_HPP
-
-/**
- * \file js-rectangle.hpp
- * \brief JavaScript binding for Rectangle.
- *
- * Rectangles are plain objects.
- *
- * ````
- * {
- *   x: 10,
- *   y: 20,
- *   width: 100,
- *   height: 200
- * }
- * ````
- */
-
-#include "duktape.hpp"
-#include "rectangle.hpp"
-
-namespace malikania {
-
-/**
- * Get a rectangle.
- *
- * The rectangle may be adjusted if any values are incorrect.
- *
- * @param ctx the context
- * @param index the value index
- * @return the rectangle
- */
-Rectangle dukx_get_rect(duk_context *ctx, duk_idx_t index);
-
-/**
- * Require a rectangle.
- *
- * If the object is not a rectangle or if width, height are invalid, raise a JavaScript error.
- *
- * @param ctx the context
- * @param index the index
- * @return the rectangle
- */
-Rectangle dukx_require_rect(duk_context *ctx, duk_idx_t index);
-
-/**
- * Like get but return the default value if the value at the given index is not an object or invalid
- *
- * @param ctx the context
- * @param index the idnex
- * @param def the default value
- * @return the rectangle
- */
-Rectangle dukx_optional_rect(duk_context *ctx, duk_idx_t index, Rectangle def);
-
-/**
- * Push the rectangle as object.
- *
- * @param ctx the context
- * @param rect the rectangle
- */
-void dukx_push_rect(duk_context *ctx, const Rectangle &rect);
-
-/**
- * Put the rectangle properties into the object at the top of the stack.
- *
- * @param ctx the context
- * @param rect the rectangle
- */
-void dukx_put_rect(duk_context *ctx, const Rectangle &rect);
-
-void dukx_load_rect(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_RECTANGLE_HPP
--- a/libclient/malikania/js-size.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * js-size.cpp -- size description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-size.hpp"
-
-namespace malikania {
-
-namespace {
-
-Size parse(duk_context *ctx, duk_idx_t index, bool required, Size size = {})
-{
-    StackAssert sa(ctx);
-
-    if (duk_is_object(ctx, index)) {
-        if (required && !duk_has_prop_string(ctx, index, "width"))
-            duk_error(ctx, DUK_ERR_ERROR, "missing width property in size description");
-        else if (required && !duk_has_prop_string(ctx, index, "height"))
-            duk_error(ctx, DUK_ERR_ERROR, "missing height property in size description");
-
-        int width;
-        int height;
-
-        duk_get_prop_string(ctx, index, "width");
-        width = duk_to_int(ctx, -1);
-        duk_pop(ctx);
-        duk_get_prop_string(ctx, index, "height");
-        height = duk_to_int(ctx, -1);
-        duk_pop(ctx);
-
-        if (width < 0)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "width can not be negative");
-        if (height < 0)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "height can not be negative");
-
-        size = Size(width, height);
-    } else if (required)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "size object expected");
-
-    return size;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    Size size;
-
-    if (duk_get_top(ctx) == 2) {
-        int width;
-        int height;
-
-        if ((width = duk_require_int(ctx, 0)) < 0)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #0 can not be negative");
-        if ((height = duk_require_int(ctx, 1)) < 0)
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #1 can not be negative");
-
-        size = Size(static_cast<unsigned>(width), static_cast<unsigned>(height));
-    } else if (duk_get_top(ctx) == 1)
-        size = parse(ctx, 0, true);
-
-    duk_ret_t ret;
-
-    // Allow both constructor and non constructor calls.
-    if (duk_is_constructor_call(ctx)) {
-        duk_push_this(ctx);
-        dukx_put_size(ctx, size);
-        duk_pop(ctx);
-        ret = 0;
-    } else {
-        dukx_push_size(ctx, size);
-        ret = 1;
-    }
-
-    return ret;
-}
-
-} // !namespace
-
-Size dukx_get_size(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, false);
-}
-
-Size dukx_require_size(duk_context *ctx, duk_idx_t index)
-{
-    return parse(ctx, index, true);
-}
-
-Size dukx_optional_size(duk_context *ctx, duk_idx_t index, Size def)
-{
-    return parse(ctx, index, false, std::move(def));
-}
-
-void dukx_push_size(duk_context *ctx, const Size &size)
-{
-    StackAssert sa(ctx, 1);
-
-    duk_push_object(ctx);
-    dukx_put_size(ctx, size);
-}
-
-void dukx_put_size(duk_context *ctx, const Size &size)
-{
-    assert(duk_is_object(ctx, -1));
-
-    StackAssert sa(ctx, 0);
-
-    duk_push_uint(ctx, size.width());
-    duk_put_prop_string(ctx, -2, "width");
-    duk_push_uint(ctx, size.height());
-    duk_put_prop_string(ctx, -2, "height");
-}
-
-void dukx_load_size(duk_context *ctx)
-{
-    StackAssert sa(ctx, 0);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "Size");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-size.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * js-size.hpp -- size description (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_SIZE_HPP
-#define MALIKANIA_JS_SIZE_HPP
-
-/**
- * \file js-size.h
- * \brief JavaScript binding for Size.
- *
- * Size are plain objects.
- *
- * ````
- * {
- *   width: 1000,
- *   height: 2000
- * }
- * ````
- */
-
-#include "duktape.hpp"
-#include "size.hpp"
-
-namespace malikania {
-
-/**
- * Get a size.
- *
- * The size may be adjusted if any values are incorrect.
- *
- * @param ctx the context
- * @param index the value index
- * @return the size
- */
-Size dukx_get_size(duk_context *ctx, duk_idx_t index);
-
-/**
- * Require a size
- *
- * If the object is not a size, raise a JavaScript error.
- *
- * @param ctx the context
- * @param index the index
- * @return the size
- */
-Size dukx_require_size(duk_context *ctx, duk_idx_t index);
-
-/**
- * Like get but return the default value if the value at the given index is not an object.
- *
- * @param ctx the context
- * @param index the idnex
- * @param def the default value
- * @return the size
- */
-Size dukx_optional_size(duk_context *ctx, duk_idx_t index, Size def);
-
-/**
- * Push the size as object.
- *
- * @param ctx the context
- * @param size the size
- */
-void dukx_push_size(duk_context *ctx, const Size &size);
-
-/**
- * Put the size properties into the object at the top of the stack.
- *
- * @param ctx the context
- * @param size the size
- */
-void dukx_put_size(duk_context *ctx, const Size &size);
-
-void dukx_load_size(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_SIZE_HPP
--- a/libclient/malikania/js-sprite.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*
- * js-sprite.cpp -- sprite object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-client-resources-loader.hpp"
-#include "js-point.hpp"
-#include "js-size.hpp"
-#include "js-sprite.hpp"
-#include "js-window.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-sprite-ptr");
-
-Sprite *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Sprite object");
-
-    return static_cast<Sprite *>(ptr);
-}
-
-duk_ret_t cell(duk_context *ctx)
-{
-    dukx_push_size(ctx, self(ctx)->cell());
-
-    return 1;
-}
-
-duk_ret_t columns(duk_context *ctx)
-{
-    duk_push_uint(ctx, self(ctx)->columns());
-
-    return 1;
-}
-
-duk_ret_t margins(duk_context *ctx)
-{
-    dukx_push_size(ctx, self(ctx)->margin());
-
-    return 1;
-}
-
-duk_ret_t rows(duk_context *ctx)
-{
-    duk_push_uint(ctx, self(ctx)->rows());
-
-    return 1;
-}
-
-duk_ret_t space(duk_context *ctx)
-{
-    dukx_push_size(ctx, self(ctx)->space());
-
-    return 1;
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "sprite must be new-constructed");
-
-    try {
-        auto loader = dukx_get_client_loader(ctx);
-        auto sprite = loader->loadSprite(duk_require_string(ctx, 0));
-
-        duk_push_this(ctx);
-        duk_push_pointer(ctx, new Sprite(std::move(sprite)));
-        duk_put_prop_string(ctx, -2, Signature.c_str());
-
-        // Cell.
-        duk_push_string(ctx, "cell");
-        duk_push_c_function(ctx, cell, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-
-        // Columns.
-        duk_push_string(ctx, "columns");
-        duk_push_c_function(ctx, columns, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-
-        // Margins.
-        duk_push_string(ctx, "margins");
-        duk_push_c_function(ctx, margins, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-
-        // Rows.
-        duk_push_string(ctx, "rows");
-        duk_push_c_function(ctx, rows, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-
-        // Space.
-        duk_push_string(ctx, "space");
-        duk_push_c_function(ctx, space, 0);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-
-        duk_pop(ctx);
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t draw(duk_context *ctx)
-{
-    try {
-        auto sprite = self(ctx);
-        auto window = dukx_require_window(ctx, 0);
-        auto cell = duk_require_uint(ctx, 1);
-        auto point = dukx_get_point(ctx, 2);
-
-        if (cell >= (sprite->rows() * sprite->columns()))
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range", cell);
-
-        sprite->draw(*window, cell, point);
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "draw",   draw,       3 },
-    { nullptr,  nullptr,    0 }
-};
-
-} // !namespace
-
-void dukx_load_sprite(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 1);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Sprite");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-sprite.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * js-sprite.hpp -- sprite object (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_SPRITE_HPP
-#define MALIKANIA_JS_SPRITE_HPP
-
-#include "duktape.hpp"
-#include "sprite.hpp"
-
-namespace malikania {
-
-void dukx_load_sprite(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_SPRITE_HPP
--- a/libclient/malikania/js-window.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,284 +0,0 @@
-/*
- * js-window.cpp -- window management (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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 "js-color.hpp"
-#include "js-font.hpp"
-#include "js-line.hpp"
-#include "js-point.hpp"
-#include "js-rectangle.hpp"
-#include "js-window.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff""\xff""malikania-window-ptr");
-const std::string Prototype("\xff""\xff""malikania-window-prototype");
-
-Window *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Window object");
-
-    return static_cast<Window *>(ptr);
-}
-
-duk_ret_t constructor(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    if (!duk_is_constructor_call(ctx))
-        duk_error(ctx, DUK_ERR_ERROR, "window must be new-constructed");
-
-    // TODO: add parameters.
-    try {
-        auto win = new Window;
-
-        duk_push_this(ctx);
-        duk_push_pointer(ctx, win);
-        duk_put_prop_string(ctx, -2, Signature.c_str());
-        duk_pop(ctx);
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t clear(duk_context *ctx)
-{
-    try {
-        self(ctx)->clear();
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t present(duk_context *ctx)
-{
-    try {
-        self(ctx)->present();
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawingColor(duk_context *ctx)
-{
-    try {
-        dukx_push_color(ctx, self(ctx)->drawingColor());
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 1;
-}
-
-duk_ret_t drawLine(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawLine(dukx_require_line(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawLines(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawLines(dukx_get_array(ctx, 0, dukx_get_point));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawPoint(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawPoint(dukx_require_point(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawPoints(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawPoints(dukx_get_array(ctx, 0, dukx_get_point));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawRectangle(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawRectangle(dukx_require_rect(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawRectangles(duk_context *ctx)
-{
-    try {
-        self(ctx)->drawRectangles(dukx_get_array(ctx, 0, dukx_get_rect));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t drawText(duk_context *ctx)
-{
-    try {
-        auto win = self(ctx);
-        auto text = duk_require_string(ctx, 0);
-        auto font = dukx_require_font(ctx, 1);
-        auto rect = dukx_get_rect(ctx, 2);
-
-        if (!rect.isNull())
-            win->drawText(text, *font, rect);
-        else
-            win->drawText(text, *font, Point(rect.x(), rect.y()));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t fillRectangle(duk_context *ctx)
-{
-    try {
-        self(ctx)->fillRectangle(dukx_require_rect(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t fillRectangles(duk_context *ctx)
-{
-    try {
-        self(ctx)->fillRectangles(dukx_get_array(ctx, 0, dukx_get_rect));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk_ret_t setDrawingColor(duk_context *ctx)
-{
-    try {
-        self(ctx)->setDrawingColor(dukx_require_color(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "clear",              clear,              0 },
-    { "drawingColor",       drawingColor,       0 },
-    { "drawLine",           drawLine,           1 },
-    { "drawLines",          drawLines,          1 },
-    { "drawPoint",          drawPoint,          1 },
-    { "drawPoints",         drawPoints,         1 },
-    { "drawRectangle",      drawRectangle,      1 },
-    { "drawRectangles",     drawRectangles,     1 },
-    { "drawText",           drawText,           3 },
-    { "fillRectangle",      fillRectangle,      1 },
-    { "fillRectangles",     fillRectangles,     1 },
-    { "present",            present,            0 },
-    { "setDrawingColor",    setDrawingColor,    1 },
-    { nullptr,              nullptr,            0 }
-};
-
-} // !namespace
-
-void dukx_new_window(duk_context *ctx, Window *window)
-{
-    assert(ctx);
-    assert(window);
-
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, window);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-}
-
-Window *dukx_require_window(duk_context *ctx, duk_idx_t index)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_prop_string(ctx, index, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Window object");
-
-    return static_cast<Window *>(ptr);
-}
-
-void dukx_load_window(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 0);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "Window");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libclient/malikania/js-window.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * js-window.hpp -- window management (JavaScript binding)
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * 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.
- */
-
-#ifndef MALIKANIA_JS_WINDOW_HPP
-#define MALIKANIA_JS_WINDOW_HPP
-
-#include "duktape.hpp"
-#include "window.hpp"
-
-namespace malikania {
-
-Window *dukx_require_window(duk_context *ctx, duk_idx_t index);
-
-void dukx_load_window(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_WINDOW_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon-js/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,41 @@
+#
+# CMakeLists.txt -- CMake build system for malikania
+#
+# Copyright (c) 2013-2016 Malikania Authors
+#
+# 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.
+#
+
+project(libcommon-js)
+
+set(
+    HEADERS
+    ${libcommon-js_SOURCE_DIR}/malikania/js-elapsed-timer.hpp
+    ${libcommon-js_SOURCE_DIR}/malikania/js-resources-loader.hpp
+)
+
+set(
+    SOURCES
+    ${libcommon-js_SOURCE_DIR}/malikania/js-elapsed-timer.cpp
+    ${libcommon-js_SOURCE_DIR}/malikania/js-resources-loader.cpp
+)
+
+malikania_create_library(
+    PROJECT libcommon-js
+    TARGET libcommon-js
+    SOURCES ${HEADERS} ${SOURCES}
+    FLAGS "MALIKANIA_COMMON_BUILD"
+    PUBLIC_INCLUDES
+        $<BUILD_INTERFACE:${libcommon-js_SOURCE_DIR}/malikania>
+    LIBRARIES json libcommon
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon-js/malikania/js-elapsed-timer.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,158 @@
+/*
+ * js-elapsed-timer.cpp --
+ *
+ * Copyright (c) 2013-2016 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 <string>
+
+#include "elapsed-timer.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Signature("\xff" "\xff" "malikania-elapsed-timer-ptr");
+
+ElapsedTimer *self(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an ElapsedTimer object");
+
+    return static_cast<ElapsedTimer *>(ptr);
+}
+
+/*
+ * Method: ElapsedTimer.pause
+ * ------------------------------------------------------------------
+ *
+ * Pause the timer, without resetting the current elapsed time stored.
+ */
+duk_ret_t pause(duk_context *ctx)
+{
+    self(ctx)->pause();
+
+    return 0;
+}
+
+/*
+ * Method: ElapsedTimer.reset
+ * ------------------------------------------------------------------
+ *
+ * Reset the elapsed time to 0, the status is not modified.
+ */
+duk_ret_t reset(duk_context *ctx)
+{
+    self(ctx)->reset();
+
+    return 0;
+}
+
+/*
+ * Method: ElapsedTimer.restart
+ * ------------------------------------------------------------------
+ *
+ * Restart the timer without resetting the current elapsed time.
+ */
+duk_ret_t restart(duk_context *ctx)
+{
+    self(ctx)->restart();
+
+    return 0;
+}
+
+/*
+ * Method: ElapsedTimer.elapsed
+ * ------------------------------------------------------------------
+ *
+ * Get the number of elapsed milliseconds.
+ *
+ * Returns:
+ *   The time elapsed.
+ */
+duk_ret_t elapsed(duk_context *ctx)
+{
+    duk_push_uint(ctx, self(ctx)->elapsed());
+
+    return 1;
+}
+
+/*
+ * Function: Malikania.ElapsedTimer() [constructor]
+ * ------------------------------------------------------------------
+ *
+ * Construct a new ElapsedTimer object.
+ */
+duk_ret_t constructor(duk_context *ctx)
+{
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, new ElapsedTimer);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+
+    return 0;
+}
+
+/*
+ * Function: Malikania.ElapsedTimer() [destructor]
+ * ------------------------------------------------------------------
+ *
+ * Destroy the timer.
+ */
+duk_ret_t destructor(duk_context *ctx)
+{
+    duk_get_prop_string(ctx, 0, Signature.c_str());
+    delete static_cast<ElapsedTimer *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+    duk_del_prop_string(ctx, 0, Signature.c_str());
+
+    return 0;
+}
+
+const duk_function_list_entry methods[] = {
+    { "elapsed",    elapsed,    0 },
+    { "pause",      pause,      0 },
+    { "reset",      reset,      0 },
+    { "restart",    restart,    0 },
+    { nullptr,      nullptr,    0 }
+};
+
+} // !namespace
+
+void dukx_load_elapsedtimer(duk_context *ctx) noexcept
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 0);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_push_c_function(ctx, destructor, 1);
+    duk_set_finalizer(ctx, -2);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "ElapsedTimer");
+    duk_pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon-js/malikania/js-elapsed-timer.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,31 @@
+/*
+ * js-elapsed-timer.hpp --
+ *
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef MALIKANIA_JS_ELAPSED_TIMER_HPP
+#define MALIKANIA_JS_ELAPSED_TIMER_HPP
+
+#include "duktape.hpp"
+
+namespace malikania {
+
+void dukx_load_elapsedtimer(duk_context *ctx) noexcept;
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_ELAPSED_TIMER_HPP
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon-js/malikania/js-resources-loader.cpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,55 @@
+/*
+ * js-resources-loader.cpp --resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 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 "js-resources-loader.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Variable("\xff""\xff""malikania-resources-loader");
+
+} // !namespace
+
+void dukx_put_loader(duk_context *ctx, ResourcesLoader *loader)
+{
+    assert(ctx);
+    assert(loader);
+
+    StackAssert sa(ctx);
+
+    duk_push_pointer(ctx, loader);
+    duk_put_global_string(ctx, Variable.c_str());
+}
+
+ResourcesLoader *duk_require_loader(duk_context *ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, Variable.c_str());
+    auto ptr = static_cast<ResourcesLoader *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+
+    return static_cast<ResourcesLoader *>(ptr);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon-js/malikania/js-resources-loader.hpp	Thu Aug 18 11:07:34 2016 +0200
@@ -0,0 +1,33 @@
+/*
+ * js-resources-loader.hpp --resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 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.
+ */
+
+#ifndef MALIKANIA_JS_RESOURCES_LOADER_H
+#define MALIKANIA_JS_RESOURCES_LOADER_H
+
+#include "duktape.hpp"
+#include "resources-loader.hpp"
+
+namespace malikania {
+
+void dukx_put_loader(duk_context *ctx, ResourcesLoader *);
+
+ResourcesLoader *dukx_get_loader(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_RESOURCES_LOADER_H
--- a/libcommon/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/libcommon/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -23,8 +23,6 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/elapsed-timer.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/game.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/id.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-elapsed-timer.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-resources-loader.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-loader.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-locator.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/util.hpp
@@ -34,8 +32,6 @@
     SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/application.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/elapsed-timer.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-elapsed-timer.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-resources-loader.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-loader.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-locator.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/util.cpp
--- a/libcommon/malikania/js-elapsed-timer.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * js-elapsed-timer.cpp --
- *
- * Copyright (c) 2013-2016 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 <string>
-
-#include "elapsed-timer.hpp"
-#include "duktape.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Signature("\xff" "\xff" "malikania-elapsed-timer-ptr");
-
-ElapsedTimer *self(duk_context *ctx)
-{
-    StackAssert sa(ctx);
-
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, Signature.c_str());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
-
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an ElapsedTimer object");
-
-    return static_cast<ElapsedTimer *>(ptr);
-}
-
-/*
- * Method: ElapsedTimer.pause
- * ------------------------------------------------------------------
- *
- * Pause the timer, without resetting the current elapsed time stored.
- */
-duk_ret_t pause(duk_context *ctx)
-{
-    self(ctx)->pause();
-
-    return 0;
-}
-
-/*
- * Method: ElapsedTimer.reset
- * ------------------------------------------------------------------
- *
- * Reset the elapsed time to 0, the status is not modified.
- */
-duk_ret_t reset(duk_context *ctx)
-{
-    self(ctx)->reset();
-
-    return 0;
-}
-
-/*
- * Method: ElapsedTimer.restart
- * ------------------------------------------------------------------
- *
- * Restart the timer without resetting the current elapsed time.
- */
-duk_ret_t restart(duk_context *ctx)
-{
-    self(ctx)->restart();
-
-    return 0;
-}
-
-/*
- * Method: ElapsedTimer.elapsed
- * ------------------------------------------------------------------
- *
- * Get the number of elapsed milliseconds.
- *
- * Returns:
- *   The time elapsed.
- */
-duk_ret_t elapsed(duk_context *ctx)
-{
-    duk_push_uint(ctx, self(ctx)->elapsed());
-
-    return 1;
-}
-
-/*
- * Function: Malikania.ElapsedTimer() [constructor]
- * ------------------------------------------------------------------
- *
- * Construct a new ElapsedTimer object.
- */
-duk_ret_t constructor(duk_context *ctx)
-{
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, new ElapsedTimer);
-    duk_put_prop_string(ctx, -2, Signature.c_str());
-    duk_pop(ctx);
-
-    return 0;
-}
-
-/*
- * Function: Malikania.ElapsedTimer() [destructor]
- * ------------------------------------------------------------------
- *
- * Destroy the timer.
- */
-duk_ret_t destructor(duk_context *ctx)
-{
-    duk_get_prop_string(ctx, 0, Signature.c_str());
-    delete static_cast<ElapsedTimer *>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-    duk_del_prop_string(ctx, 0, Signature.c_str());
-
-    return 0;
-}
-
-const duk_function_list_entry methods[] = {
-    { "elapsed",    elapsed,    0 },
-    { "pause",      pause,      0 },
-    { "reset",      reset,      0 },
-    { "restart",    restart,    0 },
-    { nullptr,      nullptr,    0 }
-};
-
-} // !namespace
-
-void dukx_load_elapsedtimer(duk_context *ctx) noexcept
-{
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, "Malikania");
-    duk_push_c_function(ctx, constructor, 0);
-    duk_push_object(ctx);
-    duk_put_function_list(ctx, -1, methods);
-    duk_push_c_function(ctx, destructor, 1);
-    duk_set_finalizer(ctx, -2);
-    duk_put_prop_string(ctx, -2, "prototype");
-    duk_put_prop_string(ctx, -2, "ElapsedTimer");
-    duk_pop(ctx);
-}
-
-} // !malikania
--- a/libcommon/malikania/js-elapsed-timer.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * js-elapsed-timer.hpp --
- *
- * Copyright (c) 2013-2016 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.
- */
-
-#ifndef MALIKANIA_JS_ELAPSED_TIMER_HPP
-#define MALIKANIA_JS_ELAPSED_TIMER_HPP
-
-#include "duktape.hpp"
-
-namespace malikania {
-
-void dukx_load_elapsedtimer(duk_context *ctx) noexcept;
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_ELAPSED_TIMER_HPP
-
--- a/libcommon/malikania/js-resources-loader.cpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * js-resources-loader.cpp --resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 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 "js-resources-loader.hpp"
-
-namespace malikania {
-
-namespace {
-
-const std::string Variable("\xff""\xff""malikania-resources-loader");
-
-} // !namespace
-
-void dukx_put_loader(duk_context *ctx, ResourcesLoader *loader)
-{
-    assert(ctx);
-    assert(loader);
-
-    StackAssert sa(ctx);
-
-    duk_push_pointer(ctx, loader);
-    duk_put_global_string(ctx, Variable.c_str());
-}
-
-ResourcesLoader *duk_require_loader(duk_context *ctx)
-{
-    assert(ctx);
-
-    StackAssert sa(ctx);
-
-    duk_get_global_string(ctx, Variable.c_str());
-    auto ptr = static_cast<ResourcesLoader *>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-
-    return static_cast<ResourcesLoader *>(ptr);
-}
-
-} // !malikania
--- a/libcommon/malikania/js-resources-loader.hpp	Wed Aug 10 14:30:51 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * js-resources-loader.hpp --resources loader (JavaScript binding)
- *
- * Copyright (c) 2013-2016 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.
- */
-
-#ifndef MALIKANIA_JS_RESOURCES_LOADER_H
-#define MALIKANIA_JS_RESOURCES_LOADER_H
-
-#include "duktape.hpp"
-#include "resources-loader.hpp"
-
-namespace malikania {
-
-void dukx_put_loader(duk_context *ctx, ResourcesLoader *);
-
-ResourcesLoader *dukx_get_loader(duk_context *ctx);
-
-} // !malikania
-
-#endif // !MALIKANIA_JS_RESOURCES_LOADER_H
--- a/tests/libclient/js-animation/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libclient/js-animation/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,7 +18,7 @@
 
 malikania_create_test(
     NAME js-animation
-    LIBRARIES libclient
+    LIBRARIES libclient-js
     SOURCES main.cpp
     RESOURCES
         resources/animations/margins.json
--- a/tests/libclient/js-color/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libclient/js-color/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,6 +18,6 @@
 
 malikania_create_test(
     NAME js-color
-    LIBRARIES libclient
+    LIBRARIES libclient-js
     SOURCES main.cpp
-)
\ No newline at end of file
+)
--- a/tests/libclient/js-font/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libclient/js-font/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,7 +18,7 @@
 
 malikania_create_test(
     NAME js-font
-    LIBRARIES libclient
+    LIBRARIES libclient-js
     SOURCES main.cpp
     RESOURCES
         resources/DejaVuSans.ttf
--- a/tests/libclient/js-image/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libclient/js-image/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,7 +18,7 @@
 
 malikania_create_test(
     NAME js-image
-    LIBRARIES libclient
+    LIBRARIES libclient-js
     SOURCES main.cpp
     RESOURCES
         resources/images/smiley.png
--- a/tests/libclient/js-line/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libclient/js-line/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,6 +18,6 @@
 
 malikania_create_test(
     NAME js-line
-    LIBRARIES libclient
+    LIBRARIES libclient-js
     SOURCES main.cpp
 )
--- a/tests/libclient/js-point/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libclient/js-point/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,6 +18,6 @@
 
 malikania_create_test(
     NAME js-point
-    LIBRARIES libclient
+    LIBRARIES libclient-js
     SOURCES main.cpp
 )
--- a/tests/libclient/js-rectangle/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libclient/js-rectangle/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,6 +18,6 @@
 
 malikania_create_test(
     NAME js-rectangle
-    LIBRARIES libclient
+    LIBRARIES libclient-js
     SOURCES main.cpp
 )
--- a/tests/libclient/js-size/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libclient/js-size/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,6 +18,6 @@
 
 malikania_create_test(
     NAME js-size
-    LIBRARIES libclient
+    LIBRARIES libclient-js
     SOURCES main.cpp
 )
--- a/tests/libclient/js-sprite/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libclient/js-sprite/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,7 +18,7 @@
 
 malikania_create_test(
     NAME js-sprite
-    LIBRARIES libclient
+    LIBRARIES libclient-js
     SOURCES main.cpp
     RESOURCES
         resources/images/margins.png
--- a/tests/libclient/js-window/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libclient/js-window/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,6 +18,6 @@
 
 malikania_create_test(
     NAME js-window
-    LIBRARIES libclient
+    LIBRARIES libclient-js
     SOURCES main.cpp
 )
--- a/tests/libcommon/js-elapsed-timer/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
+++ b/tests/libcommon/js-elapsed-timer/CMakeLists.txt	Thu Aug 18 11:07:34 2016 +0200
@@ -18,7 +18,7 @@
 
 malikania_create_test(
     NAME js-elapsed-timer
-    LIBRARIES libcommon
+    LIBRARIES libcommon-js
     SOURCES main.cpp
 )