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:
create a Pango::Renderer instance
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:
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 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;
}