I’m trying to subclass PangoFontMap
to read fonts in a custom format from a custom directory (the TXF format which cannot be read by FreeType2, but by OSG). I have the following code:
PangoFontOSG.hxx
#ifndef PANGO_FONT_OSG_HXX
#define PANGO_FONT_OSG_HXX
#include <map>
#include <pango/pango-font.h>
#include <osgText/Font>
#include "PangoFontMapOSG.hxx"
struct FontOSG {
PangoFont parent_instance;
PangoFontMap* fontmap;
};
struct FontOSGClass {
PangoFontClass class_instance;
};
class PangoFontOSG {
public:
PangoFontOSG(PangoFontMapOSG* fontmap);
~PangoFontOSG();
static PangoFontOSG* getFont(PangoFont*);
PangoFont* _font;
private:
static std::map<PangoFont*, PangoFontOSG*> _fontMap;
};
#endif // PANGO_FONT_MAP_OSG_HXX
PangoFontOSG.cxx
#include <glib-object.h>
#include "PangoFontMapOSG.hxx"
#include "PangoFontOSG.hxx"
G_DEFINE_TYPE(FontOSG, font_osg, PANGO_TYPE_FONT);
#define TYPE_FONT_OSG (font_osg_get_type())
#define FONT_OSG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_FONT_OSG, FontOSG))
#define IS_FONT_OSG(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), TYPE_FONT_OSG))
static GObjectClass* _pangoClass = 0;
void font_osg_init(FontOSG* priv) {
}
void font_osg_finalize(GObject* object) {
// FontMap* priv = FONT_MAP(object);
G_OBJECT_CLASS(_pangoClass)->finalize(object);
}
void font_osg_class_init(FontOSGClass* klass) {
GObjectClass* object_class = G_OBJECT_CLASS(klass);
object_class->finalize = font_osg_finalize;
_pangoClass = static_cast<GObjectClass*>(g_type_class_peek_parent(klass));
}
std::map<PangoFont*, PangoFontOSG*> PangoFontOSG::_fontMap;
PangoFontOSG* PangoFontOSG::getFont(PangoFont* font) {
if (_fontMap.count(font)) {
return _fontMap[font];
} else {
return nullptr;
}
}
PangoFontOSG::PangoFontOSG(PangoFontMapOSG* fontmap) {
FontOSG* font = static_cast<FontOSG*>(g_object_new(TYPE_FONT_OSG, 0));
font->fontmap = fontmap->_fontmap;
_font = PANGO_FONT(font);
_fontMap[_font] = this;
}
PangoFontOSG::~PangoFontOSG() {
_fontMap.erase(_font);
}
PangoFontMapOSG.hxx
#ifndef PANGO_FONT_MAP_OSG_HXX
#define PANGO_FONT_MAP_OSG_HXX
#include <map>
#include <pango/pango-context.h>
#include <pango/pango-font.h>
#include <pango/pango-fontmap.h>
#include <osgText/Font>
struct FontMapOSG {
PangoFontMap parent_instance;
};
struct FontMapOSGClass {
PangoFontMapClass class_instance;
};
class PangoFontMapOSG {
public:
PangoFontMapOSG();
~PangoFontMapOSG();
static PangoFontMapOSG* getFontMap(PangoFontMap*);
static void c_list_families(PangoFontMap* fontmap, PangoFontFamily*** families, int* n_families) {
PangoFontMapOSG* fontmapOSG = getFontMap(fontmap);
if (!fontmapOSG) {
return;
}
fontmapOSG->list_families(families, n_families);
};
static PangoFont* c_load_font(PangoFontMap* fontmap, PangoContext* context, const PangoFontDescription* desc) {
PangoFontMapOSG* fontmapOSG = getFontMap(fontmap);
if (!fontmapOSG) {
return nullptr;
}
return fontmapOSG->load_font(context, desc);
};
static PangoFontset* c_load_fontset(PangoFontMap* fontmap, PangoContext* context, const PangoFontDescription* desc, PangoLanguage* language) {
PangoFontMapOSG* fontmapOSG = getFontMap(fontmap);
if (!fontmapOSG) {
return nullptr;
}
return fontmapOSG->load_fontset(context, desc, language);
};
PangoFont* load_font(PangoContext* context, const PangoFontDescription* desc);
PangoFontset* load_fontset(PangoContext* context, const PangoFontDescription* desc, PangoLanguage* language);
void list_families(PangoFontFamily*** families, int* n_families);
PangoFontMap* _fontmap;
private:
static std::map<PangoFontMap*, PangoFontMapOSG*> _fontmapMap;
};
#endif // PANGO_FONT_MAP_OSG_HXX
PangoFontMapOSG.cxx
#include <set>
#include <glib-object.h>
#include <pango/pango-fontmap.h>
#include <pango/pango-fontset-simple.h>
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/misc/ResourceManager.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include "PangoFontMapOSG.hxx"
#include "PangoFontOSG.hxx"
G_DEFINE_TYPE(FontMapOSG, font_map_osg, PANGO_TYPE_FONT_MAP);
#define TYPE_FONT_MAP_OSG (font_map_osg_get_type())
#define FONT_MAP_OSG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_FONT_MAP_OSG, FontMapOSG))
#define IS_FONT_MAP_OSG(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), TYPE_FONT_MAP_OSG))
static GObjectClass* _pangoClass = 0;
void font_map_osg_init(FontMapOSG* priv) {
}
void font_map_osg_finalize(GObject* object) {
G_OBJECT_CLASS(_pangoClass)->finalize(object);
}
void font_map_osg_class_init(FontMapOSGClass* klass) {
GObjectClass* object_class = G_OBJECT_CLASS(klass);
object_class->finalize = font_map_osg_finalize;
PangoFontMapClass* font_map_class = PANGO_FONT_MAP_CLASS(klass);
_pangoClass = static_cast<GObjectClass*>(g_type_class_peek_parent(klass));
font_map_class->list_families = &PangoFontMapOSG::c_list_families;
font_map_class->load_font = &PangoFontMapOSG::c_load_font;
font_map_class->load_fontset = &PangoFontMapOSG::c_load_fontset;
font_map_class->shape_engine_type = "PangoRendererCanvas";
}
std::map<PangoFontMap*, PangoFontMapOSG*> PangoFontMapOSG::_fontmapMap;
PangoFontMapOSG* PangoFontMapOSG::getFontMap(PangoFontMap* fontmap) {
if (_fontmapMap.count(fontmap)) {
return _fontmapMap[fontmap];
} else {
return nullptr;
}
}
PangoFontMapOSG::PangoFontMapOSG() {
_fontmap = PANGO_FONT_MAP(static_cast<FontMapOSG*>(g_object_new(TYPE_FONT_MAP_OSG, 0)));
_fontmapMap[_fontmap] = this;
}
PangoFontMapOSG::~PangoFontMapOSG() {
_fontmapMap.erase(_fontmap);
}
PangoFont* PangoFontMapOSG::load_font(PangoContext* context, const PangoFontDescription* desc) {
SG_LOG(SG_GENERAL, SG_ALERT, "PangoFontMapOSG::load_font family=" << pango_font_description_get_family(desc));
PangoFont* font = PangoFontOSG(this)._font;
return font;
}
PangoFontset* PangoFontMapOSG::load_fontset(PangoContext* context, const PangoFontDescription* desc, PangoLanguage* language) {
SG_LOG(SG_GENERAL, SG_ALERT, "PangoFontMapOSG::load_fontset family=" << pango_font_description_get_family(desc));
PangoFontsetSimple* fontset = pango_fontset_simple_new(language);
PangoFontDescription* tmp_desc = pango_font_description_copy_static(desc);
const char* family = pango_font_description_get_family(desc);
char** families = g_strsplit(family ? family : "", ",", -1);
for (int i = 0; families[i]; i++) {
char **aliases;
int n_aliases;
PangoFont *font;
pango_font_description_set_family_static((PangoFontDescription*)desc, family);
font = load_font(context, desc);
if (font) {
pango_fontset_simple_append(fontset, font);
}
}
g_strfreev (families);
return PANGO_FONTSET(fontset);
}
void PangoFontMapOSG::list_families(PangoFontFamily*** families, int* n_families) {
const SGPath fontmapXMLPath = simgear::ResourceManager::instance()->findPath("Fonts/fontmap.xml");
if (fontmapXMLPath.isNull()) {
simgear::reportFailure(
simgear::LoadFailure::NotFound,
simgear::ErrorCode::LoadingTexture,
"PangoFontMapOSG couldn't find fontmap file 'Fonts/fontmap.xml'"
);
return;
}
SGPropertyNode* fontmapXML = new SGPropertyNode();
readProperties(fontmapXMLPath, fontmapXML);
if (!fontmapXML) {
SG_LOG(SG_IO, SG_ALERT, "Failed loading fontmap from '" << fontmapXMLPath.utf8Str() << "'");
return;
}
simgear::PropertyList fonts = fontmapXML->getChildren("font");
std::set<std::string> familyNames;
for (simgear::PropertyList::iterator it = fonts.begin(); it != fonts.end(); it++) {
familyNames.insert((*it)->getStringValue("family", ""));
}
SG_LOG(SG_GENERAL, SG_ALERT, "families " << (*familyNames.begin()));
}
In the main function of my program PangoRenderer
, I have:
PangoContex* context = pango_context_new();
PangoFontMapOSG fmap = PangoFontMapOSG();
pango_context_set_font_map(_context, (PangoFontMap*)fmap._fontmap);
PangoLayout* layout = pango_layout_new(_context);
When I then call layout->set_markup(…)
, I get the following console output repeating forever:
(process:1250236): GLib-GObject-CRITICAL **: 17:57:30.114: g_object_get_qdata: assertion 'G_IS_OBJECT (object)' failed
(process:1250236): GLib-GObject-CRITICAL **: 17:57:30.114: g_object_replace_qdata: assertion 'G_IS_OBJECT (object)' failed
The last function before g_object_get_qdata
I could identify in gdb
is pango_renderer_draw_layout
.
The most important thing is, if I don’t override the load_fontset
function of PangoFont
, the console messages are not printed - instead, it says that All font fallbacks failed!!!
even though I am returning a non-null font from load_font
.
Now, the question: Where is the small mistake I made that causes either of the issues ? Am I missing a function that has to be implemented in FontOSG
?