summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2012-08-09 15:41:20 -0300
committerJasper St. Pierre <jstpierre@mecheye.net>2014-04-10 12:37:39 -0700
commit24f8a69fa06cd64d3aff5f69047b3cfef23e9084 (patch)
treeda0688b8d4b5a155552a48171d680439f281be5c
parent64a7221d3f44fe539beae4428827125acc9c88f8 (diff)
downloadgjs-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.am1
-rw-r--r--gjs/context.cpp1
-rw-r--r--gjs/jsapi-util.h4
-rw-r--r--modules/cairo-private.h7
-rw-r--r--modules/cairo-region.cpp350
-rw-r--r--modules/cairo.cpp6
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))