[gjs] Add a new wrapper type for cairo regions



commit 24f8a69fa06cd64d3aff5f69047b3cfef23e9084
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Thu Aug 9 15:41:20 2012 -0300

    Add a new wrapper type for cairo regions
    
    https://bugzilla.gnome.org/show_bug.cgi?id=682303

 Makefile-modules.am      |    1 +
 gjs/context.cpp          |    1 +
 gjs/jsapi-util.h         |    4 +
 modules/cairo-private.h  |    7 +
 modules/cairo-region.cpp |  350 ++++++++++++++++++++++++++++++++++++++++++++++
 modules/cairo.cpp        |    6 +
 6 files changed, 369 insertions(+), 0 deletions(-)
---
diff --git a/Makefile-modules.am b/Makefile-modules.am
index 468fc9d..d17ca6d 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 fb73df4..64d651a 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 f4e8b8c..8336c43 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 411c33e..50cf28d 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 0000000..ce48d45
--- /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 0565169..1fd51b6 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))


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]