LCOV - code coverage report
Current view: top level - modules - cairo-region.cpp (source / functions) Coverage Total Hit
Test: gjs- Code Coverage Lines: 2.9 % 104 3
Test Date: 2025-01-23 05:25:52 Functions: 5.6 % 18 1
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0.0 % 110 0

             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.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
      34                 :             : fill_rectangle(JSContext             *context,
      35                 :             :                JS::HandleObject       obj,
      36                 :             :                cairo_rectangle_int_t *rect);
      37                 :             : 
      38                 :             : #define PRELUDE                                                            \
      39                 :             :     GJS_GET_THIS(context, argc, vp, argv, obj);                            \
      40                 :             :     cairo_region_t* this_region;                                           \
      41                 :             :     if (!CairoRegion::for_js_typecheck(context, obj, &this_region, &argv)) \
      42                 :             :         return false;
      43                 :             : 
      44                 :             : #define RETURN_STATUS                                           \
      45                 :             :     return gjs_cairo_check_status(context, cairo_region_status(this_region), "region");
      46                 :             : 
      47                 :             : #define REGION_DEFINE_REGION_FUNC(method)                                     \
      48                 :             :     GJS_JSAPI_RETURN_CONVENTION                                               \
      49                 :             :     static bool method##_func(JSContext* context, unsigned argc,              \
      50                 :             :                               JS::Value* vp) {                                \
      51                 :             :         PRELUDE;                                                              \
      52                 :             :         JS::RootedObject other_obj(context);                                  \
      53                 :             :         if (!gjs_parse_call_args(context, #method, argv, "o", "other_region", \
      54                 :             :                                  &other_obj))                                 \
      55                 :             :             return false;                                                     \
      56                 :             :                                                                               \
      57                 :             :         cairo_region_t* other_region =                                        \
      58                 :             :             CairoRegion::for_js(context, other_obj);                          \
      59                 :             :                                                                               \
      60                 :             :         cairo_region_##method(this_region, other_region);                     \
      61                 :             :         argv.rval().setUndefined();                                           \
      62                 :             :         RETURN_STATUS;                                                        \
      63                 :             :     }
      64                 :             : 
      65                 :             : #define REGION_DEFINE_RECT_FUNC(method)                                    \
      66                 :             :     GJS_JSAPI_RETURN_CONVENTION                                            \
      67                 :             :     static bool method##_rectangle_func(JSContext* context, unsigned argc, \
      68                 :             :                                         JS::Value* vp) {                   \
      69                 :             :         PRELUDE;                                                           \
      70                 :             :         JS::RootedObject rect_obj(context);                                \
      71                 :             :         if (!gjs_parse_call_args(context, #method, argv, "o", "rect",      \
      72                 :             :                                  &rect_obj))                               \
      73                 :             :             return false;                                                  \
      74                 :             :                                                                            \
      75                 :             :         cairo_rectangle_int_t rect;                                        \
      76                 :             :         if (!fill_rectangle(context, rect_obj, &rect))                     \
      77                 :             :             return false;                                                  \
      78                 :             :                                                                            \
      79                 :             :         cairo_region_##method##_rectangle(this_region, &rect);             \
      80                 :             :         argv.rval().setUndefined();                                        \
      81                 :             :         RETURN_STATUS;                                                     \
      82                 :             :     }
      83                 :             : 
      84   [ #  #  #  #  :           0 : REGION_DEFINE_REGION_FUNC(union)
                   #  # ]
      85   [ #  #  #  #  :           0 : REGION_DEFINE_REGION_FUNC(subtract)
                   #  # ]
      86   [ #  #  #  #  :           0 : REGION_DEFINE_REGION_FUNC(intersect)
                   #  # ]
      87   [ #  #  #  #  :           0 : REGION_DEFINE_REGION_FUNC(xor)
                   #  # ]
      88                 :             : 
      89   [ #  #  #  #  :           0 : REGION_DEFINE_RECT_FUNC(union)
             #  #  #  # ]
      90   [ #  #  #  #  :           0 : REGION_DEFINE_RECT_FUNC(subtract)
             #  #  #  # ]
      91   [ #  #  #  #  :           0 : REGION_DEFINE_RECT_FUNC(intersect)
             #  #  #  # ]
      92   [ #  #  #  #  :           0 : REGION_DEFINE_RECT_FUNC(xor)
             #  #  #  # ]
      93                 :             : 
      94                 :             : GJS_JSAPI_RETURN_CONVENTION
      95                 :             : static bool
      96                 :           0 : fill_rectangle(JSContext             *context,
      97                 :             :                JS::HandleObject       obj,
      98                 :             :                cairo_rectangle_int_t *rect)
      99                 :             : {
     100                 :           0 :     const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     101                 :           0 :     JS::RootedValue val(context);
     102                 :             : 
     103         [ #  # ]:           0 :     if (!JS_GetPropertyById(context, obj, atoms.x(), &val))
     104                 :           0 :         return false;
     105         [ #  # ]:           0 :     if (!JS::ToInt32(context, val, &rect->x))
     106                 :           0 :         return false;
     107                 :             : 
     108         [ #  # ]:           0 :     if (!JS_GetPropertyById(context, obj, atoms.y(), &val))
     109                 :           0 :         return false;
     110         [ #  # ]:           0 :     if (!JS::ToInt32(context, val, &rect->y))
     111                 :           0 :         return false;
     112                 :             : 
     113         [ #  # ]:           0 :     if (!JS_GetPropertyById(context, obj, atoms.width(), &val))
     114                 :           0 :         return false;
     115         [ #  # ]:           0 :     if (!JS::ToInt32(context, val, &rect->width))
     116                 :           0 :         return false;
     117                 :             : 
     118         [ #  # ]:           0 :     if (!JS_GetPropertyById(context, obj, atoms.height(), &val))
     119                 :           0 :         return false;
     120         [ #  # ]:           0 :     if (!JS::ToInt32(context, val, &rect->height))
     121                 :           0 :         return false;
     122                 :             : 
     123                 :           0 :     return true;
     124                 :           0 : }
     125                 :             : 
     126                 :             : GJS_JSAPI_RETURN_CONVENTION
     127                 :             : static JSObject *
     128                 :           0 : make_rectangle(JSContext *context,
     129                 :             :                cairo_rectangle_int_t *rect)
     130                 :             : {
     131                 :           0 :     const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     132                 :           0 :     JS::RootedObject rect_obj(context, JS_NewPlainObject(context));
     133         [ #  # ]:           0 :     if (!rect_obj)
     134                 :           0 :         return nullptr;
     135                 :           0 :     JS::RootedValue val(context);
     136                 :             : 
     137                 :           0 :     val = JS::Int32Value(rect->x);
     138         [ #  # ]:           0 :     if (!JS_SetPropertyById(context, rect_obj, atoms.x(), val))
     139                 :           0 :         return nullptr;
     140                 :             : 
     141                 :           0 :     val = JS::Int32Value(rect->y);
     142         [ #  # ]:           0 :     if (!JS_SetPropertyById(context, rect_obj, atoms.y(), val))
     143                 :           0 :         return nullptr;
     144                 :             : 
     145                 :           0 :     val = JS::Int32Value(rect->width);
     146         [ #  # ]:           0 :     if (!JS_SetPropertyById(context, rect_obj, atoms.width(), val))
     147                 :           0 :         return nullptr;
     148                 :             : 
     149                 :           0 :     val = JS::Int32Value(rect->height);
     150         [ #  # ]:           0 :     if (!JS_SetPropertyById(context, rect_obj, atoms.height(), val))
     151                 :           0 :         return nullptr;
     152                 :             : 
     153                 :           0 :     return rect_obj;
     154                 :           0 : }
     155                 :             : 
     156                 :             : GJS_JSAPI_RETURN_CONVENTION
     157                 :             : static bool
     158                 :           0 : num_rectangles_func(JSContext *context,
     159                 :             :                     unsigned argc,
     160                 :             :                     JS::Value *vp)
     161                 :             : {
     162   [ #  #  #  # ]:           0 :     PRELUDE;
     163                 :             :     int n_rects;
     164                 :             : 
     165         [ #  # ]:           0 :     if (!gjs_parse_call_args(context, "num_rectangles", argv, ""))
     166                 :           0 :         return false;
     167                 :             : 
     168                 :           0 :     n_rects = cairo_region_num_rectangles(this_region);
     169                 :           0 :     argv.rval().setInt32(n_rects);
     170                 :           0 :     RETURN_STATUS;
     171                 :           0 : }
     172                 :             : 
     173                 :             : GJS_JSAPI_RETURN_CONVENTION
     174                 :             : static bool
     175                 :           0 : get_rectangle_func(JSContext *context,
     176                 :             :                    unsigned argc,
     177                 :             :                    JS::Value *vp)
     178                 :             : {
     179   [ #  #  #  # ]:           0 :     PRELUDE;
     180                 :             :     int i;
     181                 :             :     JSObject *rect_obj;
     182                 :             :     cairo_rectangle_int_t rect;
     183                 :             : 
     184         [ #  # ]:           0 :     if (!gjs_parse_call_args(context, "get_rectangle", argv, "i",
     185                 :             :                              "rect", &i))
     186                 :           0 :         return false;
     187                 :             : 
     188                 :           0 :     cairo_region_get_rectangle(this_region, i, &rect);
     189                 :           0 :     rect_obj = make_rectangle(context, &rect);
     190                 :             : 
     191                 :           0 :     argv.rval().setObjectOrNull(rect_obj);
     192                 :           0 :     RETURN_STATUS;
     193                 :           0 : }
     194                 :             : 
     195                 :             : // clang-format off
     196                 :             : const JSPropertySpec CairoRegion::proto_props[] = {
     197                 :             :     JS_STRING_SYM_PS(toStringTag, "Region", JSPROP_READONLY),
     198                 :             :     JS_PS_END};
     199                 :             : // clang-format on
     200                 :             : 
     201                 :             : const JSFunctionSpec CairoRegion::proto_funcs[] = {
     202                 :             :     JS_FN("union", union_func, 0, 0),
     203                 :             :     JS_FN("subtract", subtract_func, 0, 0),
     204                 :             :     JS_FN("intersect", intersect_func, 0, 0),
     205                 :             :     JS_FN("xor", xor_func, 0, 0),
     206                 :             : 
     207                 :             :     JS_FN("unionRectangle", union_rectangle_func, 0, 0),
     208                 :             :     JS_FN("subtractRectangle", subtract_rectangle_func, 0, 0),
     209                 :             :     JS_FN("intersectRectangle", intersect_rectangle_func, 0, 0),
     210                 :             :     JS_FN("xorRectangle", xor_rectangle_func, 0, 0),
     211                 :             : 
     212                 :             :     JS_FN("numRectangles", num_rectangles_func, 0, 0),
     213                 :             :     JS_FN("getRectangle", get_rectangle_func, 0, 0),
     214                 :             :     JS_FS_END};
     215                 :             : 
     216                 :           0 : cairo_region_t* CairoRegion::constructor_impl(JSContext* context,
     217                 :             :                                               const JS::CallArgs& argv) {
     218         [ #  # ]:           0 :     if (!gjs_parse_call_args(context, "Region", argv, ""))
     219                 :           0 :         return nullptr;
     220                 :             : 
     221                 :           0 :     return cairo_region_create();
     222                 :             : }
     223                 :             : 
     224                 :           0 : void CairoRegion::finalize_impl(JS::GCContext*, cairo_region_t* region) {
     225         [ #  # ]:           0 :     if (!region)
     226                 :           0 :         return;
     227                 :             : 
     228                 :           0 :     cairo_region_destroy(region);
     229                 :             : }
     230                 :             : 
     231                 :           0 : [[nodiscard]] static bool region_to_gi_argument(
     232                 :             :     JSContext* context, JS::Value value, const char* arg_name,
     233                 :             :     GjsArgumentType argument_type, GITransfer transfer, GjsArgumentFlags flags,
     234                 :             :     GIArgument* arg) {
     235         [ #  # ]:           0 :     if (value.isNull()) {
     236         [ #  # ]:           0 :         if (!(flags & GjsArgumentFlags::MAY_BE_NULL)) {
     237                 :             :             Gjs::AutoChar display_name{
     238                 :           0 :                 gjs_argument_display_name(arg_name, argument_type)};
     239                 :           0 :             gjs_throw(context, "%s may not be null", display_name.get());
     240                 :           0 :             return false;
     241                 :           0 :         }
     242                 :             : 
     243                 :           0 :         gjs_arg_unset(arg);
     244                 :           0 :         return true;
     245                 :             :     }
     246                 :             : 
     247                 :           0 :     JS::RootedObject obj(context, &value.toObject());
     248                 :             :     cairo_region_t *region;
     249                 :             : 
     250         [ #  # ]:           0 :     if (!CairoRegion::for_js_typecheck(context, obj, &region))
     251                 :           0 :         return false;
     252         [ #  # ]:           0 :     if (transfer == GI_TRANSFER_EVERYTHING)
     253                 :           0 :         cairo_region_destroy(region);
     254                 :             : 
     255                 :           0 :     gjs_arg_set(arg, region);
     256                 :           0 :     return true;
     257                 :           0 : }
     258                 :             : 
     259                 :             : GJS_JSAPI_RETURN_CONVENTION
     260                 :           0 : static bool region_from_gi_argument(JSContext* context,
     261                 :             :                                     JS::MutableHandleValue value_p,
     262                 :             :                                     GIArgument* arg) {
     263                 :             :     JSObject* obj =
     264                 :           0 :         CairoRegion::from_c_ptr(context, gjs_arg_get<cairo_region_t*>(arg));
     265         [ #  # ]:           0 :     if (!obj)
     266                 :           0 :         return false;
     267                 :             : 
     268                 :           0 :     value_p.setObject(*obj);
     269                 :           0 :     return true;
     270                 :             : }
     271                 :             : 
     272                 :           0 : static bool region_release_argument(JSContext*, GITransfer transfer,
     273                 :             :                                     GIArgument* arg) {
     274         [ #  # ]:           0 :     if (transfer != GI_TRANSFER_NOTHING)
     275                 :           0 :         cairo_region_destroy(gjs_arg_get<cairo_region_t*>(arg));
     276                 :           0 :     return true;
     277                 :             : }
     278                 :             : 
     279                 :             : 
     280                 :           2 : void gjs_cairo_region_init(void) {
     281                 :             :     static GjsForeignInfo foreign_info = {region_to_gi_argument,
     282                 :             :                                           region_from_gi_argument,
     283                 :             :                                           region_release_argument};
     284                 :             : 
     285                 :           2 :     gjs_struct_foreign_register("cairo", "Region", &foreign_info);
     286                 :           2 : }
        

Generated by: LCOV version 2.0-1