Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gjs cairo context drawing not displaying in clutter window

I'm trying to get a simple cairo drawing drawn to a clutter window using the javascript bindings. My problem is, apart from half the functions being named slightly differently, is no matter what I try, the cairo drawing does not show up. I used a example from python, which does work, and ported it to javascript. I'm also using introspection to get the Clutter module instance. I'm also using gjs version 0.7.14. Can anyone tell me what is going wrong.

Below is the example code I'm using.


const cairo = imports.cairo;
const clutter =  imports.gi.Clutter;

function on_button_press_event (stage, event) {
    clutter.main_quit();
}

function draw(cairo_tex) {
    var context = cairo_tex.create();


    context.scale(200, 200);
    context.setLineWidth(0.1);
    var colour2 = new clutter.Color();
    colour2.from_string('#dd000088');
    clutter.cairo_set_source_color(context, colour2);
    context.translate(0.5, 0.5);
    context.arc(0, 0, 0.4, 0, Math.PI * 2);
    context.stroke();
}

function main () {
    clutter.init(0, null);
    var stage = new clutter.Stage();
    var colour = new clutter.Color();
    colour.from_string("#ffccccff");
    stage.set_color(colour);
    stage.set_size(400, 300);
    stage.connect('button-press-event',  on_button_press_event);
    stage.connect('destroy', clutter.main_quit);

    var cairo_tex = new clutter.CairoTexture.new(200, 200);
    cairo_tex.set_position((stage.get_width() - 200) / 2,
                       (stage.get_height() - 200) / 2);

    draw(cairo_tex);


    var center_x = cairo_tex.get_width() / 2;
    var center_z = cairo_tex.get_height() / 2;
    cairo_tex.set_rotation(clutter.AlignAxis.Y_AXIS, 45.0, center_x, 0, center_z);
    stage.add_actor(cairo_tex);
    cairo_tex.show();

    stage.show();

    clutter.main();
}

main();

I think the reason this is not working has to do with the deletion of the cairo context in javascript. context.destroy does not exist and using delete doesn't either. Infact if I use delete then I get the warning

WARNING: 'applying the 'delete' operator to an unqualified name is deprecated'

which does not help at all. According to what some of the developers involved in gjs have posted about it, assigning to null should have the same effect, due to it being garbage collected. I'm having my doubts as to whether there is anything to collect behind the scenes.

If someone could say if this is true or not, then I would accept this as a answer.

UPDATE:

I have narrowed down the problem area to imports.gi.Clutter. I tried another example, but this time using Gtk instead of Clutter, and the following code actually works

cairo = imports.cairo;
Gtk = imports.gi.Gtk;
Gdk = imports.gi.Gdk;

function draw_arc(drawing_area){
    var cr = Gdk.cairo_create(drawing_area.get_window());

    cr.scale(2, 2);

    cr.operator = cairo.Operator.CLEAR;
    cr.paint();
    cr.operator = cairo.Operator.OVER;

    cr.setSourceRGB(0,255,0);
    cr.arc(128, 128, 76.8, 0, 2*Math.PI);
    cr.fill();

    return false;
}

Gtk.init(0, null);

var w = new Gtk.Window();
w.connect('delete-event', Gtk.main_quit);

var d = new Gtk.DrawingArea();
w.add(d);

w.resize(500,600);
w.decorated = false;

d.connect('draw', draw_arc);

w.show_all();
Gtk.main();

This leads me to believe that the problem is not with the gjs implementation of cairo, but with the gjs introspection methods for Clutter Cairo implementation. I'm thinking that clutter.CairoTexture.new or clutter.CairoTexture.create is not implemented properly. I suspect it is the clutter.CairoTexture.create which is causing the problem.

like image 467
James Hurford Avatar asked Oct 11 '22 14:10

James Hurford


1 Answers

Using the newer integration between Clutter, and Cairo, specifically the Clutter.Canvas this will draw a circle to the screen:

const Clutter = imports.gi.Clutter;
const Cairo = imports.cairo;

const draw_stuff = function (canvas, cr, width, height) {
    cr.save ();
    cr.setOperator (Cairo.Operator.CLEAR);
    cr.paint ();
    cr.restore ();
    cr.setOperator (Cairo.Operator.OVER);
    cr.scale (width, height);
    cr.setLineCap (Cairo.LineCap.ROUND);
    cr.setLineWidth (0.1);

    cr.translate (0.5, 0.5);
    cr.arc (0, 0, 0.4, 0, Math.PI * 2);
    cr.stroke ();

    return true;
};

const test = function () {
    Clutter.init(null);

    let stage = new Clutter.Stage();
    stage.set_title ("Circle!");

    let color = new Clutter.Color({
        red : 255,
        green : 0,
        blue : 0,
        alpha : 128 // Just for the heck of it.
});
stage.set_background_color(color);
stage.set_size(300, 300);

let canvas = new Clutter.Canvas ();
canvas.set_size (155, 155);

let dummy = new Clutter.Actor ();
dummy.set_content (canvas);
dummy.set_size(155, 155);
stage.add_child (dummy);

stage.connect ("destroy", Clutter.main_quit);
canvas.connect ("draw", draw_stuff);
canvas.invalidate ();
stage.show_all();

Clutter.main ();
};

test ();
like image 123
BlackVegetable Avatar answered Oct 13 '22 04:10

BlackVegetable