[gjs: 1/2] cairo: Add binding for cairo_text_extents()




commit ea52cf922f1150db967085ec98e67ac88447814b
Author: Philip Chimento <philip chimento gmail com>
Date:   Mon Feb 7 18:49:41 2022 -0800

    cairo: Add binding for cairo_text_extents()
    
    This function is pretty easy to bind. The cairo_text_extents_t type can
    just be represented as a plain object, since it doesn't have any methods
    of its own.

 installed-tests/js/testCairo.js | 19 +++++++++++++++++++
 modules/cairo-context.cpp       | 35 ++++++++++++++++++++++++++++++++++-
 2 files changed, 53 insertions(+), 1 deletion(-)
---
diff --git a/installed-tests/js/testCairo.js b/installed-tests/js/testCairo.js
index 5b55666f9..186d0519d 100644
--- a/installed-tests/js/testCairo.js
+++ b/installed-tests/js/testCairo.js
@@ -105,6 +105,25 @@ describe('Cairo', function () {
             expect(cr.deviceToUserDistance(0, 0).length).toEqual(2);
         });
 
+        it('computes text extents', function () {
+            expect(cr.textExtents('')).toEqual({
+                xBearing: 0,
+                yBearing: 0,
+                width: 0,
+                height: 0,
+                xAdvance: 0,
+                yAdvance: 0,
+            });
+            expect(cr.textExtents('trailing spaces   ')).toEqual({
+                xBearing: 0,
+                yBearing: -8,
+                width: 72,
+                height: 10,
+                xAdvance: 81,
+                yAdvance: 0,
+            });
+        });
+
         it('can call various, otherwise untested, methods without crashing', function () {
             expect(() => {
                 cr.save();
diff --git a/modules/cairo-context.cpp b/modules/cairo-context.cpp
index d6899622e..463e06215 100644
--- a/modules/cairo-context.cpp
+++ b/modules/cairo-context.cpp
@@ -793,6 +793,39 @@ getGroupTarget_func(JSContext *context,
     return true;
 }
 
+GJS_JSAPI_RETURN_CONVENTION
+static bool textExtents_func(JSContext* cx, unsigned argc, JS::Value* vp) {
+    _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(cx, argc, vp, args, this_obj);
+
+    JS::UniqueChars utf8;
+    if (!gjs_parse_call_args(cx, "textExtents", args, "s", "utf8", &utf8))
+        return false;
+
+    cairo_text_extents_t extents;
+    cairo_text_extents(cr, utf8.get(), &extents);
+    if (!gjs_cairo_check_status(cx, cairo_status(cr), "context"))
+        return false;
+
+    JS::RootedObject extents_obj(cx, JS_NewPlainObject(cx));
+    if (!extents_obj)
+        return false;
+
+    JSPropertySpec properties[] = {
+        JS_DOUBLE_PS("xBearing", extents.x_bearing, JSPROP_ENUMERATE),
+        JS_DOUBLE_PS("yBearing", extents.y_bearing, JSPROP_ENUMERATE),
+        JS_DOUBLE_PS("width", extents.width, JSPROP_ENUMERATE),
+        JS_DOUBLE_PS("height", extents.height, JSPROP_ENUMERATE),
+        JS_DOUBLE_PS("xAdvance", extents.x_advance, JSPROP_ENUMERATE),
+        JS_DOUBLE_PS("yAdvance", extents.y_advance, JSPROP_ENUMERATE),
+        JS_PS_END};
+
+    if (!JS_DefineProperties(cx, extents_obj, properties))
+        return false;
+
+    args.rval().setObject(*extents_obj);
+    return true;
+}
+
 // clang-format off
 const JSFunctionSpec CairoContext::proto_funcs[] = {
     JS_FN("$dispose", dispose_func, 0, 0),
@@ -888,7 +921,7 @@ const JSFunctionSpec CairoContext::proto_funcs[] = {
     JS_FN("strokeExtents", strokeExtents_func, 0, 0),
     JS_FN("strokePreserve", strokePreserve_func, 0, 0),
     // textPath
-    // textExtends
+    JS_FN("textExtents", textExtents_func, 1, 0),
     // transform
     JS_FN("translate", translate_func, 0, 0),
     JS_FN("userToDevice", userToDevice_func, 0, 0),


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