Mercurial > malikania
view libclient-js/malikania/js_color.cpp @ 63:96ba0c5cf893
Misc: update duktape.hpp to new style
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 16 Dec 2016 16:11:24 +0100 |
parents | fabbe1759cec |
children | 858621081b95 |
line wrap: on
line source
/* * 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 mlk { namespace { std::uint8_t clamp_component(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 parse_string(duk_context* ctx, duk_idx_t index, bool required) { assert(duk_is_string(ctx, index)); color ret; try { ret = color(duk_get_string(ctx, index)); } catch (const std::exception &ex) { if (required) { duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); } } return ret; } color parse_object(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 clamp_component(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"), clamp_component(ctx, alpha, required) ); } color parse(duk_context* ctx, duk_idx_t index, bool required, color ret = {}) { switch (duk_get_type(ctx, index)) { case DUK_TYPE_STRING: ret = parse_string(ctx, index, required); break; case DUK_TYPE_OBJECT: ret = parse_object(ctx, index, required); break; default: if (required) { duk_error(ctx, DUK_ERR_TYPE_ERROR, "color (string, object) expected"); } break; } return ret; } duk_ret_t constructor(duk_context* ctx) { color obj; /* * 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; obj = color( clamp_component(ctx, duk_require_int(ctx, 0), true), clamp_component(ctx, duk_require_int(ctx, 1), true), clamp_component(ctx, duk_require_int(ctx, 2), true), clamp_component(ctx, alpha, true) ); } else if (duk_get_top(ctx) == 1) { obj = 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, obj); duk_pop(ctx); ret = 0; } else { dukx_push_color(ctx, obj); 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) { dukx_stack_assert 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)); dukx_stack_assert 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) { dukx_stack_assert 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); } } // !mlk