How to subclass Pango::Renderer in C++

I’m trying to subclass the Pango::Renderer to draw text on an osg::Texture2D, but I cannot find a public constructor (except a copy-constructor) in its header file, neither another method to create a Pango::Renderer instance (like a static create method the Layout class for example provides).

So, how would I:

  1. create a Pango::Renderer instance
  2. subclass Pango::Renderer.

I’ve tried the following code for subclassing:

#include <pangomm/renderer.h>

class PangoRendererCanvas: public Pango::Renderer {
	public:
		PangoRendererCanvas() {}
};

but that gave the following compilation error:

error: no matching function for call to ‘Pango::Renderer::Renderer()’

        PangoRendererCanvas::PangoRendererCanvas() {
                                                                                   ^

According to the docs for Pango::Renderer, this should be possible:

Pango::Renderer API documentation

By subclassing Pango::Renderer and overriding operations such as draw_glyphs and draw_rectangle, renderers for particular font backends and destinations can be created.

I’m using PangoMM 2.46.2.

Solved: How to subclass Pango::Renderer in C++ - Stack Overflow

1 Like

I think there’s a problem in the m4 definition, I think it should have protected: CTOR_DEFAULT() like Gtk::CellRenderer, but it doesn’t. I suspect the reason is because the C PangoRenderer doesn’t have a _new() method and assumes you will use g_object_new instead, which is analogous to the Glib::ConstructParams constructor. However, the Glib::ConstructParams constructor can’t be used because there should only be one Pango::Renderer_Class, and it is a private static member variable; it can’t be accessed from the derived class.

I experimented with creating a derivedRenderer_Class, but the vfuncs() turn into an infinite loop when I try to chain up (or don’t override the vfunc). I think the reason is that making an xxx_Class who’s parent is a cppClass is illegal, but I might have be missing something key in Glib::Class. I think peek_parent() is always supposed to lead to the C Class, but in my definition MyRenderer’s parent class is the CppClass. peek_parent(get_class(gobj())) doesn’t work recursively, so its stuck. Here’s the code I was experimenting with:

#include <pangomm.h>
#include <pangomm/init.h>
#include <pangomm/renderer.h>
#include <pangomm/private/renderer_p.h>
#include <pango/pango.h>
#include <iostream>

class MyRenderer;

class MyRenderer_Class : public Glib::Class
{
public:
    using CppObjectType = MyRenderer;
    using CppClassParent = Pango::Renderer_Class;
    using BaseObjectType = PangoRenderer;
    using BaseClassType = PangoRendererClass;
    using BaseClassParent = GObjectClass;

    friend class MyRenderer;

    static void class_init_function(void* g_class, void* class_data)
    {
        const auto klass = static_cast<BaseClassType*>(g_class);
        CppClassParent::class_init_function(klass, class_data);
    }

    const Glib::Class& init()
    {
        if (!gtype_)
        {
            class_init_func_ = &MyRenderer_Class::class_init_function;
            register_derived_type(Pango::Renderer::get_type());
        }

        return *this;
    }

    static Glib::ObjectBase* wrap_new(GObject* object);
};

class MyRenderer : public Pango::Renderer
{
private:
    friend class MyRenderer_Class;
    static MyRenderer_Class myrenderer_class_;
public:
    MyRenderer() : Glib::ObjectBase(typeid(MyRenderer)), Pango::Renderer(Glib::ConstructParams(myrenderer_class_)) {}
    explicit MyRenderer(PangoRenderer *castitem) : Renderer::Renderer(castitem) {};
public:
    static GType get_type() { return myrenderer_class_.init().get_type(); }
    static GType get_base_type() { return Pango::Renderer::get_type(); }

    virtual void draw_glyph_vfunc(const Glib::RefPtr<Pango::Font>& font, Pango::Glyph glyph, double x, double y) override;
//    virtual void begin_vfunc() override { Pango::Renderer::begin_vfunc(); }; /* infinite loop when not overridden or chained up */

};

MyRenderer_Class MyRenderer::myrenderer_class_;

Glib::ObjectBase* MyRenderer_Class::wrap_new(GObject* object)
{
    return new MyRenderer((PangoRenderer*)object);
}

void
MyRenderer::draw_glyph_vfunc(const Glib::RefPtr<Pango::Font>& font, Pango::Glyph glyph, double x, double y)
{
    std::cerr << "MY vfunc!\n";
    Pango::Renderer::draw_glyph_vfunc(font, glyph, x, y);
}

int main()
{
    Pango::init();
    g_type_ensure(MyRenderer::get_type());

    MyRenderer r;
    r.activate(); // Infinite loop here, begin_vfunc() loops through
                  // Pango::Renderer_Class->begin_vfunc_callback() ->
                  // Pango::Renderer:begin_vfunc() ->
                  // Pango::Renderer_Class->begin_vfunc_callback()
    return 0;
}

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.