Clone in a terminal:
fontconfig.c
/*
	Copyright (C) 2015 Johan Mattsson

	This library is free software; you can redistribute it and/or modify 
	it under the terms of the GNU Lesser General Public License as 
	published by the Free Software Foundation; either version 3 of the 
	License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful, but 
	WITHOUT ANY WARRANTY; without even the implied warranty of 
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
	Lesser General Public License for more details.
*/

#include <stdio.h>
#include <glib.h>
#include <fontconfig/fontconfig.h>

gchar* find_font_with_property (FcConfig* fontconfig, const gchar* characters, const gchar* property) {
	FcPattern* pattern;
	FcCharSet* character_set;
	FcObjectSet* font_properties;
	FcFontSet* fonts;
	FcPattern* font;
	FcChar8* path;
	gchar* result;
	gchar* remaining_characters;
	gunichar character;
	
	if (fontconfig == NULL) {
		g_warning("Font config not loaded.");
		return NULL;
	}
	
	result = NULL;
	pattern = FcPatternCreate ();
	
	character_set = FcCharSetCreate ();
	
	remaining_characters = (gchar*) characters;
	while (TRUE) {
		character = g_utf8_get_char (remaining_characters);
		
		if (character == '\0') {
			break;
		}
		
		FcCharSetAddChar(character_set, character);
				
		remaining_characters = g_utf8_next_char (remaining_characters);
	}

	FcPatternAddCharSet (pattern, FC_CHARSET, character_set);
	FcCharSetDestroy (character_set);
	FcPatternAddInteger (pattern, FC_SLANT, FC_SLANT_ROMAN);
	
	FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
	font_properties = FcObjectSetBuild (property, NULL);	
	fonts = FcFontList (fontconfig, pattern, font_properties);
	
	if (fonts && fonts->nfont > 0) {
		font = fonts->fonts[0];
		if (FcPatternGetString(font, property, 0, &path) == FcResultMatch) {
			result = g_strdup ((gchar*) path);
		}
	}

	if (fonts) {
		FcFontSetDestroy(fonts);
	}

	if (pattern) {
		FcPatternDestroy(pattern);
	}

	return result;
}

/** Find a fallback font for a set of characters.
 * @return A path to the font file.
 */
gchar* find_font (FcConfig* fontconfig, const gchar* characters) {
	return find_font_with_property (fontconfig, characters, FC_FILE);
}

/** Find a fallback font for a set of characters.
 * @return Family name of the font.
 */
gchar* find_font_family (FcConfig* fontconfig, const gchar* characters) {
	return find_font_with_property (fontconfig, characters, FC_FAMILY);
}

/** Find a font file from its family name.
 * @param font_config fontconfig instance
 * @param font_name name of the font
 * @return full path to the font file
 */
gchar* find_font_file (FcConfig* font_config, const gchar* font_name) {
	const FcChar8* name;
	FcPattern* search_pattern;
	FcPattern* font;
	FcChar8* file;
	gchar* path;
	FcObjectSet* font_properties;
	FcFontSet* fonts;
	int i;

	if (font_config == NULL) {
		g_warning("Font config not loaded.");
		return NULL;
	}
	
	path = NULL;
	name = (FcChar8*) font_name;

	search_pattern = FcPatternCreate ();
	FcPatternAddString (search_pattern, FC_FAMILY, name);
	FcPatternAddBool (search_pattern, FC_SCALABLE, FcTrue);
	FcPatternAddInteger (search_pattern, FC_WEIGHT, FC_WEIGHT_MEDIUM);
	FcPatternAddInteger (search_pattern, FC_SLANT, FC_SLANT_ROMAN);
		
	font_properties = FcObjectSetBuild (FC_FILE, NULL);
	fonts = FcFontList (font_config, search_pattern, font_properties);
	
	if (fonts->nfont > 0) {
		for (i = 0; i < fonts->nfont; i++) {
			font = fonts->fonts[i];
			
			if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch) {
				path = g_strdup ((gchar*) file);
				break;
			}
		}
		FcPatternDestroy (font);
	}

	FcPatternDestroy (search_pattern);
	
	return path;
}

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112