LCOV - code coverage report
Current view: top level - modules - cairo-region.cpp (source / functions) Coverage Total Hit
Test: gjs-1.88.0 Code Coverage Lines: 16.8 % 107 18
Test Date: 2026-06-07 00:56:06 Functions: 22.2 % 18 4
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 4.5 % 112 5

             Branch data     Line data    Source code
       1                 :             : /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
       2                 :             : // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
       3                 :             : // SPDX-FileCopyrightText: 2014 Red Hat, Inc.
       4                 :             : 
       5                 :             : #include <config.h>
       6                 :             : 
       7                 :             : #include <cairo.h>
       8                 :             : #include <girepository/girepository.h>
       9                 :             : 
      10                 :             : #include <js/CallArgs.h>
      11                 :             : #include <js/Conversions.h>
      12                 :             : #include <js/PropertyAndElement.h>
      13                 :             : #include <js/PropertyDescriptor.h>  // for JSPROP_READONLY
      14                 :             : #include <js/PropertySpec.h>
      15                 :             : #include <js/RootingAPI.h>
      16                 :             : #include <js/TypeDecls.h>
      17                 :             : #include <js/Value.h>
      18                 :             : #include <jsapi.h>  // for JS_NewPlainObject
      19                 :             : 
      20                 :             : #include "gi/arg-inl.h"
      21                 :             : #include "gi/arg.h"
      22                 :             : #include "gi/foreign.h"
      23                 :             : #include "gjs/atoms.h"
      24                 :             : #include "gjs/auto.h"
      25                 :             : #include "gjs/context-private.h"
      26                 :             : #include "gjs/enum-utils.h"
      27                 :             : #include "gjs/jsapi-util-args.h"
      28                 :             : #include "gjs/jsapi-util.h"
      29                 :             : #include "gjs/macros.h"
      30                 :             : #include "modules/cairo-private.h"
      31                 :             : 
      32                 :             : GJS_JSAPI_RETURN_CONVENTION
      33                 :             : static bool fill_rectangle(JSContext* cx, JS::HandleObject obj,
      34                 :             :                            cairo_rectangle_int_t* rect);
      35                 :             : 
      36                 :             : #define PRELUDE                                                       \
      37                 :             :     GJS_GET_THIS(cx, argc, vp, argv, obj);                            \
      38                 :             :     cairo_region_t* this_region;                                      \
      39                 :             :     if (!CairoRegion::for_js_typecheck(cx, obj, &this_region, &argv)) \
      40                 :             :         return false;
      41                 :             : 
      42                 :             : #define RETURN_STATUS                                                   \
      43                 :             :     return gjs_cairo_check_status(cx, cairo_region_status(this_region), \
      44                 :             :                                   "region");
      45                 :             : 
      46                 :             : #define REGION_DEFINE_REGION_FUNC(method)                                    \
      47                 :             :     GJS_JSAPI_RETURN_CONVENTION                                              \
      48                 :             :     static bool method##_func(JSContext* cx, unsigned argc, JS::Value* vp) { \
      49                 :             :         PRELUDE;                                                             \
      50                 :             :         JS::RootedObject other_obj{cx};                                      \
      51                 :             :         if (!gjs_parse_call_args(cx, #method, argv, "o", "other_region",     \
      52                 :             :                                  &other_obj))                                \
      53                 :             :             return false;                                                    \
      54                 :             :                                                                              \
      55                 :             :         cairo_region_t* other_region = CairoRegion::for_js(cx, other_obj);   \
      56                 :             :                                                                              \
      57                 :             :         cairo_region_##method(this_region, other_region);                    \
      58                 :             :         argv.rval().setUndefined();                                          \
      59                 :             :         RETURN_STATUS;                                                       \
      60                 :             :     }
      61                 :             : 
      62                 :             : #define REGION_DEFINE_RECT_FUNC(method)                                      \
      63                 :             :     GJS_JSAPI_RETURN_CONVENTION                                              \
      64                 :             :     static bool method##_rectangle_func(JSContext* cx, unsigned argc,        \
      65                 :             :                                         JS::Value* vp) {                     \
      66                 :             :         PRELUDE;                                                             \
      67                 :             :         JS::RootedObject rect_obj{cx};                                       \
      68                 :             :         if (!gjs_parse_call_args(cx, #method, argv, "o", "rect", &rect_obj)) \
      69                 :             :             return false;                                                    \
      70                 :             :                                                                              \
      71                 :             :         cairo_rectangle_int_t rect;                                          \
      72                 :             :         if (!fill_rectangle(cx, rect_obj, &rect))                            \
      73                 :             :             return false;                                                    \
      74                 :             :                                                                              \
      75                 :             :         cairo_region_##method##_rectangle(this_region, &rect);               \
      76                 :             :         argv.rval().setUndefined();                                          \
      77                 :             :         RETURN_STATUS;                                                       \
      78                 :             :     }
      79                 :             : 
      80   [ #  #  #  #  :           0 : REGION_DEFINE_REGION_FUNC(union)
                   #  # ]
      81   [ #  #  #  #  :           0 : REGION_DEFINE_REGION_FUNC(subtract)
                   #  # ]
      82   [ #  #  #  #  :           0 : REGION_DEFINE_REGION_FUNC(intersect)
                   #  # ]
      83   [ #  #  #  #  :           0 : REGION_DEFINE_REGION_FUNC(xor)
                   #  # ]
      84                 :             : 
      85   [ #  #  #  #  :           0 : REGION_DEFINE_RECT_FUNC(union)
             #  #  #  # ]
      86   [ #  #  #  #  :           0 : REGION_DEFINE_RECT_FUNC(subtract)
             #  #  #  # ]
      87   [ #  #  #  #  :           0 : REGION_DEFINE_RECT_FUNC(intersect)
             #  #  #  # ]
      88   [ #  #  #  #  :           0 : REGION_DEFINE_RECT_FUNC(xor)
             #  #  #  # ]
      89                 :             : 
      90                 :             : GJS_JSAPI_RETURN_CONVENTION
      91                 :           0 : static bool fill_rectangle(JSContext* cx, JS::HandleObject obj,
      92                 :             :                            cairo_rectangle_int_t* rect) {
      93                 :           0 :     const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
      94                 :           0 :     JS::RootedValue val{cx};
      95                 :             : 
      96         [ #  # ]:           0 :     if (!JS_GetPropertyById(cx, obj, atoms.x(), &val))
      97                 :           0 :         return false;
      98         [ #  # ]:           0 :     if (!JS::ToInt32(cx, val, &rect->x))
      99                 :           0 :         return false;
     100                 :             : 
     101         [ #  # ]:           0 :     if (!JS_GetPropertyById(cx, obj, atoms.y(), &val))
     102                 :           0 :         return false;
     103         [ #  # ]:           0 :     if (!JS::ToInt32(cx, val, &rect->y))
     104                 :           0 :         return false;
     105                 :             : 
     106         [ #  # ]:           0 :     if (!JS_GetPropertyById(cx, obj, atoms.width(), &val))
     107                 :           0 :         return false;
     108         [ #  # ]:           0 :     if (!JS::ToInt32(cx, val, &rect->width))
     109                 :           0 :         return false;
     110                 :             : 
     111         [ #  # ]:           0 :     if (!JS_GetPropertyById(cx, obj, atoms.height(), &val))
     112                 :           0 :         return false;
     113         [ #  # ]:           0 :     if (!JS::ToInt32(cx, val, &rect->height))
     114                 :           0 :         return false;
     115                 :             : 
     116                 :           0 :     return true;
     117                 :           0 : }
     118                 :             : 
     119                 :             : GJS_JSAPI_RETURN_CONVENTION
     120                 :           0 : static JSObject* make_rectangle(JSContext* cx, cairo_rectangle_int_t* rect) {
     121                 :           0 :     const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
     122                 :           0 :     JS::RootedObject rect_obj{cx, JS_NewPlainObject(cx)};
     123         [ #  # ]:           0 :     if (!rect_obj)
     124                 :           0 :         return nullptr;
     125                 :           0 :     JS::RootedValue val{cx};
     126                 :             : 
     127                 :           0 :     val = JS::Int32Value(rect->x);
     128         [ #  # ]:           0 :     if (!JS_SetPropertyById(cx, rect_obj, atoms.x(), val))
     129                 :           0 :         return nullptr;
     130                 :             : 
     131                 :           0 :     val = JS::Int32Value(rect->y);
     132         [ #  # ]:           0 :     if (!JS_SetPropertyById(cx, rect_obj, atoms.y(), val))
     133                 :           0 :         return nullptr;
     134                 :             : 
     135                 :           0 :     val = JS::Int32Value(rect->width);
     136         [ #  # ]:           0 :     if (!JS_SetPropertyById(cx, rect_obj, atoms.width(), val))
     137                 :           0 :         return nullptr;
     138                 :             : 
     139                 :           0 :     val = JS::Int32Value(rect->height);
     140         [ #  # ]:           0 :     if (!JS_SetPropertyById(cx, rect_obj, atoms.height(), val))
     141                 :           0 :         return nullptr;
     142                 :             : 
     143                 :           0 :     return rect_obj;
     144                 :           0 : }
     145                 :             : 
     146                 :             : GJS_JSAPI_RETURN_CONVENTION
     147                 :           0 : static bool num_rectangles_func(JSContext* cx, unsigned argc, JS::Value* vp) {
     148   [ #  #  #  # ]:           0 :     PRELUDE;
     149                 :             : 
     150         [ #  # ]:           0 :     if (!gjs_parse_call_args(cx, "num_rectangles", argv, ""))
     151                 :           0 :         return false;
     152                 :             : 
     153                 :           0 :     int n_rects = cairo_region_num_rectangles(this_region);
     154                 :           0 :     argv.rval().setInt32(n_rects);
     155                 :           0 :     RETURN_STATUS;
     156                 :           0 : }
     157                 :             : 
     158                 :             : GJS_JSAPI_RETURN_CONVENTION
     159                 :           0 : static bool get_rectangle_func(JSContext* cx, unsigned argc, JS::Value* vp) {
     160   [ #  #  #  # ]:           0 :     PRELUDE;
     161                 :             :     int i;
     162                 :             :     cairo_rectangle_int_t rect;
     163                 :             : 
     164         [ #  # ]:           0 :     if (!gjs_parse_call_args(cx, "get_rectangle", argv, "i", "rect", &i))
     165                 :           0 :         return false;
     166                 :             : 
     167                 :           0 :     cairo_region_get_rectangle(this_region, i, &rect);
     168                 :           0 :     JSObject* rect_obj = make_rectangle(cx, &rect);
     169         [ #  # ]:           0 :     if (!rect_obj)
     170                 :           0 :         return false;
     171                 :             : 
     172                 :           0 :     argv.rval().setObject(*rect_obj);
     173                 :           0 :     RETURN_STATUS;
     174                 :           0 : }
     175                 :             : 
     176                 :             : // clang-format off
     177                 :             : const JSPropertySpec CairoRegion::proto_props[] = {
     178                 :             :     JS_STRING_SYM_PS(toStringTag, "Region", JSPROP_READONLY),
     179                 :             :     JS_PS_END};
     180                 :             : // clang-format on
     181                 :             : 
     182                 :             : const JSFunctionSpec CairoRegion::proto_funcs[] = {
     183                 :             :     JS_FN("union", union_func, 0, 0),
     184                 :             :     JS_FN("subtract", subtract_func, 0, 0),
     185                 :             :     JS_FN("intersect", intersect_func, 0, 0),
     186                 :             :     JS_FN("xor", xor_func, 0, 0),
     187                 :             : 
     188                 :             :     JS_FN("unionRectangle", union_rectangle_func, 0, 0),
     189                 :             :     JS_FN("subtractRectangle", subtract_rectangle_func, 0, 0),
     190                 :             :     JS_FN("intersectRectangle", intersect_rectangle_func, 0, 0),
     191                 :             :     JS_FN("xorRectangle", xor_rectangle_func, 0, 0),
     192                 :             : 
     193                 :             :     JS_FN("numRectangles", num_rectangles_func, 0, 0),
     194                 :             :     JS_FN("getRectangle", get_rectangle_func, 0, 0),
     195                 :             :     JS_FS_END};
     196                 :             : 
     197                 :           1 : cairo_region_t* CairoRegion::constructor_impl(JSContext* cx,
     198                 :             :                                               const JS::CallArgs& args) {
     199         [ -  + ]:           1 :     if (!gjs_parse_call_args(cx, "Region", args, ""))
     200                 :           0 :         return nullptr;
     201                 :             : 
     202                 :           1 :     return cairo_region_create();
     203                 :             : }
     204                 :             : 
     205                 :           1 : void CairoRegion::finalize_impl(JS::GCContext*, cairo_region_t* region) {
     206         [ -  + ]:           1 :     if (!region)
     207                 :           0 :         return;
     208                 :             : 
     209                 :           1 :     cairo_region_destroy(region);
     210                 :             : }
     211                 :             : 
     212                 :             : GJS_JSAPI_RETURN_CONVENTION
     213                 :           1 : static bool region_to_gi_argument(JSContext* cx, JS::Value value,
     214                 :             :                                   const char* arg_name,
     215                 :             :                                   GjsArgumentType argument_type,
     216                 :             :                                   GITransfer transfer, GjsArgumentFlags flags,
     217                 :             :                                   GIArgument* arg) {
     218         [ -  + ]:           1 :     if (value.isNull()) {
     219         [ #  # ]:           0 :         if (!(flags & GjsArgumentFlags::MAY_BE_NULL)) {
     220                 :           0 :             Gjs::AutoChar display_name{
     221                 :           0 :                 gjs_argument_display_name(arg_name, argument_type)};
     222                 :           0 :             gjs_throw(cx, "%s may not be null", display_name.get());
     223                 :           0 :             return false;
     224                 :           0 :         }
     225                 :             : 
     226                 :           0 :         gjs_arg_unset(arg);
     227                 :           0 :         return true;
     228                 :             :     }
     229                 :             : 
     230                 :           1 :     JS::RootedObject obj{cx, &value.toObject()};
     231                 :             :     cairo_region_t* region;
     232                 :             : 
     233         [ -  + ]:           1 :     if (!CairoRegion::for_js_typecheck(cx, obj, &region))
     234                 :           0 :         return false;
     235         [ +  - ]:           1 :     if (transfer == GI_TRANSFER_EVERYTHING)
     236                 :           1 :         cairo_region_reference(region);
     237                 :             : 
     238                 :           1 :     gjs_arg_set(arg, region);
     239                 :           1 :     return true;
     240                 :           1 : }
     241                 :             : 
     242                 :             : GJS_JSAPI_RETURN_CONVENTION
     243                 :           0 : static bool region_from_gi_argument(JSContext* cx,
     244                 :             :                                     JS::MutableHandleValue value_p,
     245                 :             :                                     GIArgument* arg) {
     246                 :             :     JSObject* obj =
     247                 :           0 :         CairoRegion::from_c_ptr(cx, gjs_arg_get<cairo_region_t*>(arg));
     248         [ #  # ]:           0 :     if (!obj)
     249                 :           0 :         return false;
     250                 :             : 
     251                 :           0 :     value_p.setObject(*obj);
     252                 :           0 :     return true;
     253                 :             : }
     254                 :             : 
     255                 :           0 : static bool region_release_argument(JSContext*, GITransfer transfer,
     256                 :             :                                     GIArgument* arg) {
     257         [ #  # ]:           0 :     if (transfer != GI_TRANSFER_NOTHING)
     258                 :           0 :         cairo_region_destroy(gjs_arg_get<cairo_region_t*>(arg));
     259                 :           0 :     return true;
     260                 :             : }
     261                 :             : 
     262                 :           2 : void gjs_cairo_region_init() {
     263                 :             :     static GjsForeignInfo foreign_info = {region_to_gi_argument,
     264                 :             :                                           region_from_gi_argument,
     265                 :             :                                           region_release_argument};
     266                 :             : 
     267                 :           2 :     gjs_struct_foreign_register("cairo", "Region", &foreign_info);
     268                 :           2 : }
        

Generated by: LCOV version 2.0-1