diff options
author | Jasper St. Pierre <jstpierre@mecheye.net> | 2012-08-09 15:41:20 -0300 |
---|---|---|
committer | Jasper St. Pierre <jstpierre@mecheye.net> | 2014-04-10 12:37:39 -0700 |
commit | 24f8a69fa06cd64d3aff5f69047b3cfef23e9084 (patch) | |
tree | da0688b8d4b5a155552a48171d680439f281be5c | |
parent | 64a7221d3f44fe539beae4428827125acc9c88f8 (diff) | |
download | gjs-24f8a69fa06cd64d3aff5f69047b3cfef23e9084.tar.gz |
Add a new wrapper type for cairo regions
https://bugzilla.gnome.org/show_bug.cgi?id=682303
-rw-r--r-- | Makefile-modules.am | 1 | ||||
-rw-r--r-- | gjs/context.cpp | 1 | ||||
-rw-r--r-- | gjs/jsapi-util.h | 4 | ||||
-rw-r--r-- | modules/cairo-private.h | 7 | ||||
-rw-r--r-- | modules/cairo-region.cpp | 350 | ||||
-rw-r--r-- | modules/cairo.cpp | 6 |
6 files changed, 369 insertions, 0 deletions
diff --git a/Makefile-modules.am b/Makefile-modules.am index 468fc9d7..d17ca6d1 100644 --- a/Makefile-modules.am +++ b/Makefile-modules.am @@ -32,6 +32,7 @@ libcairoNative_la_LIBADD = $(JS_NATIVE_MODULE_LIBADD) $(GJS_CAIRO_LIBS) libcairoNative_la_SOURCES = \ modules/cairo-private.h \ modules/cairo-module.h \ + modules/cairo-region.cpp \ modules/cairo-context.cpp \ modules/cairo-path.cpp \ modules/cairo-surface.cpp \ diff --git a/gjs/context.cpp b/gjs/context.cpp index fb73df48..64d651a9 100644 --- a/gjs/context.cpp +++ b/gjs/context.cpp @@ -79,6 +79,7 @@ static const char *const_strings[] = { "gi", "versions", "overrides", "_init", "_new_internal", "new", "message", "code", "stack", "fileName", "lineNumber", "name", + "x", "y", "width", "height", }; G_STATIC_ASSERT(G_N_ELEMENTS(const_strings) == GJS_STRING_LAST); diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h index f4e8b8cd..8336c439 100644 --- a/gjs/jsapi-util.h +++ b/gjs/jsapi-util.h @@ -428,6 +428,10 @@ typedef enum { GJS_STRING_FILENAME, GJS_STRING_LINE_NUMBER, GJS_STRING_NAME, + GJS_STRING_X, + GJS_STRING_Y, + GJS_STRING_WIDTH, + GJS_STRING_HEIGHT, GJS_STRING_LAST } GjsConstString; diff --git a/modules/cairo-private.h b/modules/cairo-private.h index 411c33ef..50cf28d4 100644 --- a/modules/cairo-private.h +++ b/modules/cairo-private.h @@ -30,6 +30,13 @@ JSBool gjs_cairo_check_status (JSContext *contex cairo_status_t status, const char *name); +jsval gjs_cairo_region_create_proto (JSContext *context, + JSObject *module, + const char *proto_name, + JSObject *parent); +void gjs_cairo_region_init (JSContext *context); + + jsval gjs_cairo_context_create_proto (JSContext *context, JSObject *module, const char *proto_name, diff --git a/modules/cairo-region.cpp b/modules/cairo-region.cpp new file mode 100644 index 00000000..ce48d45e --- /dev/null +++ b/modules/cairo-region.cpp @@ -0,0 +1,350 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* Copyright 2014 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <config.h> + +#include <gjs/gjs-module.h> +#include <gjs/compat.h> +#include <gi/foreign.h> + +#include <cairo.h> +#include <cairo-gobject.h> +#include "cairo-private.h" + +typedef struct { + JSContext *context; + JSObject *object; + cairo_region_t *region; +} GjsCairoRegion; + +GJS_DEFINE_PROTO_WITH_GTYPE("CairoRegion", cairo_region, CAIRO_GOBJECT_TYPE_REGION) +GJS_DEFINE_PRIV_FROM_JS(GjsCairoRegion, gjs_cairo_region_class); + +static cairo_region_t * +get_region(JSContext *context, + JSObject *obj) { + GjsCairoRegion *priv = priv_from_js(context, obj); + if (priv == NULL) + return NULL; + else + return priv->region; +} + +static JSBool +fill_rectangle(JSContext *context, JSObject *obj, + cairo_rectangle_int_t *rect); + +#define PRELUDE \ + JSObject *obj = JS_THIS_OBJECT(context, vp); \ + cairo_region_t *this_region = get_region(context, obj); + +#define RETURN_STATUS \ + return gjs_cairo_check_status(context, cairo_region_status(this_region), "region"); + +#define REGION_DEFINE_REGION_FUNC(method) \ + static JSBool \ + method##_func(JSContext *context, \ + unsigned argc, \ + jsval *vp) \ + { \ + PRELUDE; \ + JSObject *other_obj; \ + cairo_region_t *other_region; \ + if (!gjs_parse_args(context, #method, "o", argc, \ + JS_ARGV(context, vp), \ + "other_region", &other_obj)) \ + return JS_FALSE; \ + \ + this_region = get_region(context, obj); \ + other_region = get_region(context, other_obj); \ + \ + cairo_region_##method(this_region, other_region); \ + JS_SET_RVAL(context, vp, JSVAL_VOID); \ + RETURN_STATUS; \ + } + +#define REGION_DEFINE_RECT_FUNC(method) \ + static JSBool \ + method##_rectangle_func(JSContext *context, \ + unsigned argc, \ + jsval *vp) \ + { \ + PRELUDE; \ + JSObject *rect_obj; \ + cairo_rectangle_int_t rect; \ + if (!gjs_parse_args(context, #method, "o", argc, \ + JS_ARGV(context, vp), \ + "rect", &rect_obj)) \ + return JS_FALSE; \ + \ + if (!fill_rectangle(context, rect_obj, &rect)) \ + return JS_FALSE; \ + \ + cairo_region_##method##_rectangle(this_region, &rect); \ + JS_SET_RVAL(context, vp, JSVAL_VOID); \ + RETURN_STATUS; \ + } + +REGION_DEFINE_REGION_FUNC(union) +REGION_DEFINE_REGION_FUNC(subtract) +REGION_DEFINE_REGION_FUNC(intersect) +REGION_DEFINE_REGION_FUNC(xor) + +REGION_DEFINE_RECT_FUNC(union) +REGION_DEFINE_RECT_FUNC(subtract) +REGION_DEFINE_RECT_FUNC(intersect) +REGION_DEFINE_RECT_FUNC(xor) + +static JSBool +fill_rectangle(JSContext *context, JSObject *obj, + cairo_rectangle_int_t *rect) +{ + jsval val; + + if (!gjs_object_get_property_const(context, obj, GJS_STRING_X, &val)) + return JS_FALSE; + if (!JS_ValueToInt32(context, val, &rect->x)) + return JS_FALSE; + + if (!gjs_object_get_property_const(context, obj, GJS_STRING_Y, &val)) + return JS_FALSE; + if (!JS_ValueToInt32(context, val, &rect->y)) + return JS_FALSE; + + if (!gjs_object_get_property_const(context, obj, GJS_STRING_WIDTH, &val)) + return JS_FALSE; + if (!JS_ValueToInt32(context, val, &rect->width)) + return JS_FALSE; + + if (!gjs_object_get_property_const(context, obj, GJS_STRING_HEIGHT, &val)) + return JS_FALSE; + if (!JS_ValueToInt32(context, val, &rect->height)) + return JS_FALSE; + + return JS_TRUE; +} + +static JSObject * +make_rectangle(JSContext *context, + cairo_rectangle_int_t *rect) +{ + JSObject *rect_obj = JS_NewObject(context, NULL, NULL, NULL); + jsval val; + + val = INT_TO_JSVAL(rect->x); + JS_SetProperty(context, rect_obj, "x", &val); + + val = INT_TO_JSVAL(rect->y); + JS_SetProperty(context, rect_obj, "y", &val); + + val = INT_TO_JSVAL(rect->width); + JS_SetProperty(context, rect_obj, "width", &val); + + val = INT_TO_JSVAL(rect->height); + JS_SetProperty(context, rect_obj, "height", &val); + + return rect_obj; +} + +static JSBool +num_rectangles_func(JSContext *context, + unsigned argc, + jsval *vp) +{ + PRELUDE; + int n_rects; + jsval retval; + + if (!gjs_parse_args(context, "num_rectangles", "", argc, JS_ARGV(context, vp))) + return JS_FALSE; + + n_rects = cairo_region_num_rectangles(this_region); + retval = INT_TO_JSVAL(n_rects); + JS_SET_RVAL (context, vp, retval); + RETURN_STATUS; +} + +static JSBool +get_rectangle_func(JSContext *context, + unsigned argc, + jsval *vp) +{ + PRELUDE; + int i; + JSObject *rect_obj; + cairo_rectangle_int_t rect; + jsval retval; + + if (!gjs_parse_args(context, "get_rectangle", "i", argc, JS_ARGV(context, vp), "rect", &i)) + return JS_FALSE; + + cairo_region_get_rectangle(this_region, i, &rect); + rect_obj = make_rectangle(context, &rect); + + retval = OBJECT_TO_JSVAL(rect_obj); + JS_SET_RVAL (context, vp, retval); + RETURN_STATUS; +} + +JSPropertySpec gjs_cairo_region_proto_props[] = { + { NULL } +}; + +JSFunctionSpec gjs_cairo_region_proto_funcs[] = { + { "union", (JSNative)union_func, 0, 0 }, + { "subtract", (JSNative)subtract_func, 0, 0 }, + { "intersect", (JSNative)intersect_func, 0, 0 }, + { "xor", (JSNative)xor_func, 0, 0 }, + + { "unionRectangle", (JSNative)union_rectangle_func, 0, 0 }, + { "subtractRectangle", (JSNative)subtract_rectangle_func, 0, 0 }, + { "intersectRectangle", (JSNative)intersect_rectangle_func, 0, 0 }, + { "xorRectangle", (JSNative)xor_rectangle_func, 0, 0 }, + + { "numRectangles", (JSNative)num_rectangles_func, 0, 0 }, + { "getRectangle", (JSNative)get_rectangle_func, 0, 0 }, + { NULL } +}; + +static void +_gjs_cairo_region_construct_internal(JSContext *context, + JSObject *obj, + cairo_region_t *region) +{ + GjsCairoRegion *priv; + + priv = g_slice_new0(GjsCairoRegion); + + g_assert(priv_from_js(context, obj) == NULL); + JS_SetPrivate(obj, priv); + + priv->context = context; + priv->object = obj; + priv->region = cairo_region_reference(region); +} + +GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_region) +{ + GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_region) + cairo_region_t *region; + + GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_region); + + if (!gjs_parse_args(context, "Region", "", argc, argv)) + return JS_FALSE; + + region = cairo_region_create(); + + _gjs_cairo_region_construct_internal(context, object, region); + cairo_region_destroy(region); + + GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_region); + + return JS_TRUE; +} + +static void +gjs_cairo_region_finalize(JSFreeOp *fop, + JSObject *obj) +{ + GjsCairoRegion *priv; + priv = (GjsCairoRegion*) JS_GetPrivate(obj); + if (priv == NULL) + return; + + cairo_region_destroy(priv->region); + g_slice_free(GjsCairoRegion, priv); +} + +static JSObject * +gjs_cairo_region_from_region(JSContext *context, + cairo_region_t *region) +{ + JSObject *object; + + object = JS_NewObject(context, &gjs_cairo_region_class, NULL, NULL); + if (!object) + return NULL; + + _gjs_cairo_region_construct_internal(context, object, region); + + return object; +} + +static JSBool +region_to_g_argument(JSContext *context, + jsval value, + const char *arg_name, + GjsArgumentType argument_type, + GITransfer transfer, + gboolean may_be_null, + GArgument *arg) +{ + JSObject *obj; + cairo_region_t *region; + + obj = JSVAL_TO_OBJECT(value); + region = get_region(context, obj); + if (!region) + return JS_FALSE; + if (transfer == GI_TRANSFER_EVERYTHING) + cairo_region_destroy(region); + + arg->v_pointer = region; + return JS_TRUE; +} + +static JSBool +region_from_g_argument(JSContext *context, + jsval *value_p, + GArgument *arg) +{ + JSObject *obj; + + obj = gjs_cairo_region_from_region(context, (cairo_region_t*)arg->v_pointer); + if (!obj) + return JS_FALSE; + + *value_p = OBJECT_TO_JSVAL(obj); + return JS_TRUE; +} + +static JSBool +region_release_argument(JSContext *context, + GITransfer transfer, + GArgument *arg) +{ + cairo_region_destroy((cairo_region_t*)arg->v_pointer); + return JS_TRUE; +} + +static GjsForeignInfo foreign_info = { + region_to_g_argument, + region_from_g_argument, + region_release_argument +}; + +void +gjs_cairo_region_init(JSContext *context) +{ + gjs_struct_foreign_register("cairo", "Region", &foreign_info); +} diff --git a/modules/cairo.cpp b/modules/cairo.cpp index 05651692..1fd51b6b 100644 --- a/modules/cairo.cpp +++ b/modules/cairo.cpp @@ -53,6 +53,12 @@ gjs_js_define_cairo_stuff(JSContext *context, module = JS_NewObject (context, NULL, NULL, NULL); + obj = gjs_cairo_region_create_proto(context, module, + "Region", NULL); + if (JSVAL_IS_NULL(obj)) + return JS_FALSE; + gjs_cairo_region_init(context); + obj = gjs_cairo_context_create_proto(context, module, "Context", NULL); if (JSVAL_IS_NULL(obj)) |