Пример #1
0
	std::string FontConfig::match_font(const std::string &typeface_name, const FontDescription &desc) const
	{
		FcPattern * fc_pattern = nullptr;
		FcPattern * fc_match = nullptr;
		try
		{
			int weight = static_cast<int>(desc.get_weight());

			// Build font matching pattern.
			fc_pattern = FcPatternBuild(nullptr,
				FC_FAMILY, FcTypeString, typeface_name.c_str(),
				FC_PIXEL_SIZE, FcTypeDouble, (double)std::abs(desc.get_height()),
				FC_WEIGHT, FcTypeInteger, (weight > 0) ? (int)(weight * (FC_WEIGHT_HEAVY / 900.0)) : FC_WEIGHT_NORMAL,
				FC_SLANT, FcTypeInteger, (desc.get_style() == clan::FontStyle::italic) ? FC_SLANT_ITALIC : ((desc.get_style() == clan::FontStyle::oblique) ? FC_SLANT_OBLIQUE : FC_SLANT_ROMAN),
				FC_SPACING, FcTypeInteger, FC_PROPORTIONAL,
				(char*) nullptr
				);
			if (!fc_pattern)
			{
				throw Exception("CL_FontConfig: Building FontConfig pattern failed.");
			}

			// Execute any needed param substitutions required by the system config.
			if (FcTrue != FcConfigSubstitute(fc_config, fc_pattern, FcMatchPattern))
			{
				throw Exception("CL_FontConfig: Font config substitutions failed.");
			}

			// Supply default values for underspecified font patterns. Never fails.
			FcDefaultSubstitute(fc_pattern);

			// Find best match for pattern and extract filename.
			FcResult match_result; // Doesn't appear to be actually updated.
			fc_match = FcFontMatch(fc_config, fc_pattern, &match_result);
			FcChar8 * fc_font_file_path = nullptr;
			if (FcResultMatch != FcPatternGetString(fc_match, FC_FILE, 0, &fc_font_file_path))
			{
				throw Exception("CL_FontConfig: Could not resolve font pattern to a font file.");
			}

			// Release resources and return results.
			std::string cl_font_file_path((char*)fc_font_file_path);
			FcPatternDestroy(fc_match);
			FcPatternDestroy(fc_pattern);
			return cl_font_file_path;
		}
		catch (...)
		{
			// If any exceptions thrown, ensure fontconfig resources are released.
			if (fc_match) FcPatternDestroy(fc_match);
			if (fc_pattern) FcPatternDestroy(fc_pattern);
			throw;
		}
	}
FontFileLister::CollectionResult FontConfigFontFileLister::GetFontPaths(std::string const& facename, int bold, bool italic, std::set<wxUniChar> const& characters) {
	CollectionResult ret;

	std::string family(facename);
	if (family[0] == '@')
		family.erase(0, 1);
	boost::to_lower(family);

	int weight = bold == 0 ? 80 :
	             bold == 1 ? 200 :
	                         bold;
	int slant  = italic ? 110 : 0;

	// Create a fontconfig pattern to match the desired weight/slant
	agi::scoped_holder<FcPattern*> pat(FcPatternCreate(), FcPatternDestroy);
	if (!pat) return ret;

	FcPatternAddBool(pat, FC_OUTLINE, true);
	FcPatternAddInteger(pat, FC_SLANT, slant);
	FcPatternAddInteger(pat, FC_WEIGHT, weight);

	FcDefaultSubstitute(pat);
	if (!FcConfigSubstitute(config, pat, FcMatchPattern)) return ret;

	// Create a font set with only correctly named fonts
	// This is needed because the patterns returned by font matching only
	// include the first family and fullname, so we can't always verify that
	// we got the actual font we were asking for after the fact
	agi::scoped_holder<FcFontSet*> fset(FcFontSetCreate(), FcFontSetDestroy);
	find_font(FcConfigGetFonts(config, FcSetApplication), fset, family);
	find_font(FcConfigGetFonts(config, FcSetSystem), fset, family);

	// Get the best match from fontconfig
	FcResult result;
	FcFontSet *sets[] = { (FcFontSet*)fset };
	agi::scoped_holder<FcPattern*> match(FcFontSetMatch(config, sets, 1, pat, &result), FcPatternDestroy);
	if (!match)
		return ret;

	FcChar8 *file;
	if(FcPatternGetString(match, FC_FILE, 0, &file) != FcResultMatch)
		return ret;

	FcCharSet *charset;
	if (FcPatternGetCharSet(match, FC_CHARSET, 0, &charset) == FcResultMatch) {
		for (wxUniChar chr : characters) {
			if (!FcCharSetHasChar(charset, chr))
				ret.missing += chr;
		}
	}

	ret.paths.emplace_back((const char *)file);
	return ret;
}
Пример #3
0
std::string
XeTeXFontMgr_FC::getPlatformFontDesc(PlatformFontRef font) const
{
    std::string path;
    FcChar8* s;
    if (FcPatternGetString(font, FC_FILE, 0, (FcChar8**)&s) == FcResultMatch)
        path = (char*)s;
    else
        path = "[unknown]";
    return path;
}
Пример #4
0
// This method just need to bypass the cache as we could register our alternative font.
// This is a pity but is required to have asian fonts working.
PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
{
    // Avoid copying FontPlatformData.
    RefPtr<FontPlatformData> primaryFontPlatformData = font.primaryFont()->m_font;

    // Check if the cache was already filled.
    if (fallbacks.contains(&font)) {
        ASSERT(primaryFontPlatformData->m_fallbacks);
        FontFallbackCache::iterator it = fallbacks.find(&font);
        return it->second;
    }

    if (!primaryFontPlatformData->m_fallbacks) {
        FcResult fresult;
        primaryFontPlatformData->m_fallbacks = FcFontSort(NULL, primaryFontPlatformData->m_pattern, FcTrue, NULL, &fresult);
    }

    FcFontSet* fs = primaryFontPlatformData->m_fallbacks;
    
    for (int i = 0; i < fs->nfont; i++) {
        FcPattern* fin = FcFontRenderPrepare(0, primaryFontPlatformData->m_pattern, fs->fonts[i]);

        FcChar8* fc_filename;
        if (FcPatternGetString(fin, FC_FILE, 0, &fc_filename) != FcResultMatch)
            continue;

        char* filename = (char *) fc_filename; // Use C cast as FcChar is a fontconfig type.

        int id;
        if (FcPatternGetInteger(fin, FC_INDEX, 0, &id) != FcResultMatch)
            continue;

        FT_Face face;
        if (FT_Error error = FT_New_Face(FontPlatformData::m_library, filename, id, &face)) {
            printf("FT_New_Face failed for filename = %s with FT_Error = %d\n", filename, error);
            continue;
        }

        // FIXME: is it really necessary ?
        FT_Set_Pixel_Sizes(face, 0, static_cast<uint> (font.fontDescription().computedSize()));

        RefPtr<FontPlatformData> platformData = adoptRef(new FontPlatformData(face, font.fontDescription().computedPixelSize(), false, false));
        platformData->m_pattern = fin;

        if (platformData->containsCharacters(characters, length)) {
            RefPtr<SimpleFontData> fontData = adoptRef(new SimpleFontData(platformData.get()));
            fallbacks.add(&font, fontData);
            return fontData;
        }
    }
    // Fallback: use the font in the main cache.
    RefPtr<SimpleFontData> fontData = getCachedFontData(font.fontDescription(), font.family().family());
    return fontData;
}
Пример #5
0
static void family_info(const FcPattern *pattern, family_info_t *fi)
{
  FcChar8 *str;

  fi->fontformat[0] = '\0';
  fi->capability[0] = '\0';
  fi->foundry[0] = '\0';
  
  if (FcPatternGetString(pattern, FC_FONTFORMAT, 0, &str) == FcResultMatch)
    snprintf(fi->fontformat, FONTFORMAT_MAX, "%s", str);


  if (FcPatternGetString(pattern, FC_CAPABILITY, 0, &str) == FcResultMatch)
    snprintf(fi->capability, CAPABILITY_MAX, "%s", str);

  if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &str) == FcResultMatch)
    if (strcmp((char *)str, "unknown") != 0)
      snprintf(fi->foundry, FOUNDRY_MAX, "%s", str);

  return;
}
Пример #6
0
FcResult fcinfo_get_translated_string(const FcPattern *pattern, 
                                      const char *object, 
                                      const FcChar8 *lang, FcChar8 **s)
{
  FcChar8 *l;
  int n;
  FcResult r;
  const char *lang_object;

  if (strcmp(object, FC_FAMILY) == 0)
    lang_object = FC_FAMILYLANG;
  else if (strcmp(object, FC_STYLE) == 0)
    lang_object = FC_STYLELANG;
  else if (strcmp(object, FC_FULLNAME))
    lang_object = FC_FULLNAMELANG;
  else
  {
    fprintf(stderr, "fcinfo_get_translated_string():"
                    " no translatable string\n");
    exit (1);
  }

  if (FcPatternGetString(pattern, lang_object, 0, &l) != FcResultMatch)
  {
    /* no *_LANG element */
    return FcPatternGetString(pattern, object, 0, s);
  }

  n = 0;
  while ((r = FcPatternGetString(pattern, lang_object, n, &l)) == FcResultMatch)
    if (FcStrCmp(l, lang) == 0)
      break;
    else
      n++;
    
  if (r != FcResultMatch)
    n = 0; /* no lang found */
  
  return FcPatternGetString(pattern, object, n, s);
}
Пример #7
0
void Rcairo_set_font(int i, const char *fcname){
	FcFontSet	*fs;
	FcPattern   *pat, *match;
	FcResult	result;
	FcChar8	*file;
	int j;

	if (Rcairo_fonts[i].face != NULL){
		cairo_font_face_destroy(Rcairo_fonts[i].face);
		Rcairo_fonts[i].face = NULL;
	}

	pat = FcNameParse((FcChar8 *)fcname);
	if (!pat){
		error("Problem with font config library in Rcairo_set_font\n");
		return;
	}
	FcConfigSubstitute (0, pat, FcMatchPattern);
	FcDefaultSubstitute (pat);

	fs = FcFontSetCreate ();
	match = FcFontMatch (0, pat, &result);
	FcPatternDestroy (pat);
	if (match) {
		FcFontSetAdd (fs, match);
	} else {
		error("No font found in Rcairo_set_font");
		FcFontSetDestroy (fs);
		return;
	}

	/* should be at least one font face in fontset */
	if (fs) {

		for (j = 0; j < fs->nfont; j++) {

			/* Need to make sure a real font file exists */
			if (FcPatternGetString (fs->fonts[j], FC_FILE, 0, &file) == FcResultMatch){
				Rcairo_fonts[i].face = Rcairo_set_font_face(i,(const char *)file);
				break;
			}
		}
		FcFontSetDestroy (fs);
		Rcairo_fonts[i].updated = 1;
	} else {
		error("No font found Rcairo_set_font");
	}

}
Пример #8
0
const std::string find_font(const char* name) {
	std::string font_file;
	FcConfig* config = FcInitLoadConfigAndFonts();
	FcPattern* pattern = FcNameParse((const FcChar8*) (name));
	FcConfigSubstitute(config, pattern, FcMatchPattern);
	FcDefaultSubstitute(pattern);
	FcPattern* font = FcFontMatch(config, pattern, NULL);
	if (font) {
		FcChar8* file = NULL;
		if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch)
			font_file = std::string((char*) file);
		FcPatternDestroy(font);
	}
	FcPatternDestroy(pattern);
	return font_file;
}
Пример #9
0
/**
 * \brief Case-insensitive match ASS/SSA font family against full name. (also
 * known as "name for humans")
 *
 * \param lib library instance
 * \param priv fontconfig instance
 * \param family font fullname
 * \param bold weight attribute
 * \param italic italic attribute
 * \return font set
 */
static FcFontSet *
match_fullname(ASS_Library *lib, FCInstance *priv, const char *family,
               unsigned bold, unsigned italic)
{
    FcFontSet *sets[2];
    FcFontSet *result = FcFontSetCreate();
    int nsets = 0;
    int i, fi;

    if (!result)
        return NULL;

    if ((sets[nsets] = FcConfigGetFonts(priv->config, FcSetSystem)))
        nsets++;
    if ((sets[nsets] = FcConfigGetFonts(priv->config, FcSetApplication)))
        nsets++;

    // Run over font sets and patterns and try to match against full name
    for (i = 0; i < nsets; i++) {
        FcFontSet *set = sets[i];
        for (fi = 0; fi < set->nfont; fi++) {
            FcPattern *pat = set->fonts[fi];
            char *fullname;
            int pi = 0, at;
            FcBool ol;
            while (FcPatternGetString(pat, FC_FULLNAME, pi++,
                   (FcChar8 **) &fullname) == FcResultMatch) {
                if (FcPatternGetBool(pat, FC_OUTLINE, 0, &ol) != FcResultMatch
                    || ol != FcTrue)
                    continue;
                if (FcPatternGetInteger(pat, FC_SLANT, 0, &at) != FcResultMatch
                    || at < italic)
                    continue;
                if (FcPatternGetInteger(pat, FC_WEIGHT, 0, &at) != FcResultMatch
                    || at < bold)
                    continue;
                if (strcasecmp(fullname, family) == 0) {
                    FcFontSetAdd(result, FcPatternDuplicate(pat));
                    break;
                }
            }
        }
    }

    return result;
}
Пример #10
0
static const char * claro_ft2_get_family(claro_font_pattern_t * pattern)
{
    FcPattern * fc_pattern;
    FcResult res;
    FcChar8 * family;

    g_return_val_if_fail(pattern != NULL, NULL);

    fc_pattern = (FcPattern *)pattern->native;

    res = FcPatternGetString (fc_pattern, FC_FAMILY, 0, &family);

    if(res != FcResultMatch)
        return NULL;
    else
        return (const char *)family;
}
Пример #11
0
/**
 * using fontconfig for just getting the font file name by a wanted font name and style.
 */
char *get_font_filename(const char *family, const char *style) {
	//initialize fontconfig
	if (!FcInit()) {
		throw util::Error{MSG(err) << "Failed to initialize fontconfig."};
	}

	//FcPattern *font_pattern = FcNameParse((const unsigned char *)"DejaVu Serif:style=Book");
	FcPattern *font_pattern = FcPatternBuild(nullptr, FC_FAMILY, FcTypeString, family, nullptr);
	FcPatternBuild(font_pattern, FC_STYLE, FcTypeString, style, nullptr);

	//debug output: display above pattern as parsable string.
	FcChar8 *query_string = FcNameUnparse(font_pattern);
	log::log(MSG(info) << "Font queried: " << query_string);
	free(query_string);

	//tell fontconfig to find the best match
	FcResult font_match_result;
	FcPattern *font_match = FcFontMatch(nullptr, font_pattern, &font_match_result);

	/*
	//debug output: display matching font pattern as parsable string
	FcChar8 *match_string = FcNameUnparse(font_match);
	log::dbg2("resulting font: %s", match_string);
	free(match_string);
	*/

	//get attibute FC_FILE (= filename) of best-matched font
	FcChar8 *font_filename_tmp;
	if (FcPatternGetString(font_match, FC_FILE, 0, &font_filename_tmp) != FcResultMatch) {
		throw util::Error(MSG(err) << "Fontconfig could not provide font " << family << " " << style);
	}

	//copy the font filename because it will be freed when the pattern is destroyed.
	char *font_filename = util::copy((const char *)font_filename_tmp);

	log::log(MSG(info) << "Font file: " << font_filename);

	//deinitialize fontconfig.
	FcPatternDestroy(font_match);
	FcPatternDestroy(font_pattern);
	FcFini();

	return font_filename;
}
Пример #12
0
XeTeXFont
createFont(PlatformFontRef fontRef, Fixed pointSize)
{
    int status = 0;
#ifdef XETEX_MAC
    XeTeXFontInst* font = new XeTeXFontInst_Mac(fontRef, Fix2D(pointSize), status);
#else
    FcChar8* pathname = 0;
    FcPatternGetString(fontRef, FC_FILE, 0, &pathname);
    int index;
    FcPatternGetInteger(fontRef, FC_INDEX, 0, &index);
    XeTeXFontInst* font = new XeTeXFontInst((const char*)pathname, index, Fix2D(pointSize), status);
#endif
    if (status != 0) {
        delete font;
        return NULL;
    }
    return (XeTeXFont)font;
}
Пример #13
0
/** 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 = 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;
}
Пример #14
0
static Bool
hasPropertyWithStringValue(FcPattern *pattern, const char *object, char *value)
{
    FcChar8 *str;
    int id;

    if (!value || value[0]==0)
        return True;

    id = 0;
    while (FcPatternGetString(pattern, object, id, &str)==FcResultMatch) {
        if (strcasecmp(value, (char*)str) == 0) {
            return True;
        }
        id++;
    }

    return False;
}
Пример #15
0
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
{
    FcResult fresult;
    // Avoid copying FontPlatformData.
    FontPlatformData* prim = const_cast<FontPlatformData*>(&font.primaryFont()->m_font);

    if (!prim->m_fallbacks)
        prim->m_fallbacks = FcFontSort(NULL, prim->m_pattern, FcTrue, NULL, &fresult);

    FcFontSet* fs = prim->m_fallbacks;
    
    FT_Library library = FontPlatformData::m_library;

    FcChar8* fc_filename;
    char* filename;
    int id;
    FT_Face face;
    for (int i = 0; i < fs->nfont; i++) {
        FcPattern* fin = FcFontRenderPrepare(0, prim->m_pattern, fs->fonts[i]);

        if (FcPatternGetString(fin, FC_FILE, 0, &fc_filename) != FcResultMatch)
            continue;

        filename = (char *) fc_filename; // Use C cast as FcChar is a fontconfig type.

        if (FcPatternGetInteger(fin, FC_INDEX, 0, &id) != FcResultMatch)
            continue;

        if (FT_Error error = FT_New_Face(library, filename, id, &face))
            continue;

        // FIXME: is it really necessary ?
        FT_Set_Pixel_Sizes(face, 0, static_cast<uint> (font.fontDescription().computedSize()));

        FontPlatformData alternateFont(face, font.fontDescription().computedPixelSize(), false, false);
        // FIXME: FT_Done_Face(face); we should clean the face correctly the FT_Face but we can't do that here...
        alternateFont.m_pattern = fin;
        SimpleFontData* sfd = getCachedFontData(&alternateFont);
        if (sfd->containsCharacters(characters, length))
            return sfd;
    }
    return 0;
}
Пример #16
0
Vector<String> FontCache::systemFontFamilies()
{
    RefPtr<FcPattern> scalablesOnlyPattern = adoptRef(FcPatternCreate());
    FcPatternAddBool(scalablesOnlyPattern.get(), FC_SCALABLE, FcTrue);

    FcUniquePtr<FcObjectSet> familiesOnly(FcObjectSetBuild(FC_FAMILY, nullptr));
    FcUniquePtr<FcFontSet> fontSet(FcFontList(nullptr, scalablesOnlyPattern.get(), familiesOnly.get()));

    Vector<String> fontFamilies;
    for (int i = 0; i < fontSet->nfont; i++) {
        FcPattern* pattern = fontSet->fonts[i];
        FcChar8* family = nullptr;
        FcPatternGetString(pattern, FC_FAMILY, 0, &family);
        if (family)
            fontFamilies.appendVector(patternToFamilies(*pattern));
    }

    return fontFamilies;
}
Пример #17
0
FcStrSet *fcinfo_fontformats(const FcPattern *filter)
{
  FcFontSet *fontset;
  FcStrSet *result;
  FcChar8 *format;
  int f;

  FcInit();
  fontset = fcinfo(NULL, filter, FcFalse, 1, FC_FONTFORMAT);

  result = FcStrSetCreate();
  for (f = 0; f < fontset->nfont; f++)
  {
    assert(FcPatternGetString(fontset->fonts[f], FC_FONTFORMAT, 0, &format)
             == FcResultMatch);
    FcStrSetAdd(result, format);
  }

  return result;
}
Пример #18
0
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
{
    assert(buffer != NULL);
    assert(font != NULL);

    log_verbose("Looking for font %s with FontConfig.", font->font_name);
    FcConfig* config = FcInitLoadConfigAndFonts();
    if (!config)
    {
        log_error("Failed to initialize FontConfig library");
        FcFini();
        return false;
    }
    FcPattern* pat = FcNameParse((const FcChar8*) font->font_name);

    FcConfigSubstitute(config, pat, FcMatchPattern);
    FcDefaultSubstitute(pat);

    bool found = false;
    FcResult result = FcResultNoMatch;
    FcPattern* match = FcFontMatch(config, pat, &result);

    if (match)
    {
        FcChar8* filename = NULL;
        if (FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch)
        {
            found = true;
            safe_strcpy(buffer, (utf8*) filename, size);
            log_verbose("FontConfig provided font %s", filename);
        }
        FcPatternDestroy(match);
    } else {
        log_warning("Failed to find required font.");
    }

    FcPatternDestroy(pat);
    FcConfigDestroy(config);
    FcFini();
    return found;
}
Пример #19
0
FcFontSet *fcinfo_uinterval_statistics(const FcPattern *filter, 
                                       double *uinterval_stat[],
                                       uinterval_type_t uintype)
{
  FcFontSet *fontset, *tmp;
  FcCharSet *charset;
  int s, f;
  FcChar8 *file;

  FcInit(); /* bitmap font files sort according to FC_LANG, identified by FC_FILE */
  fontset = fcinfo(NULL, filter, FcFalse, 5, FC_FAMILY, FC_STYLE, FC_CHARSET, FC_LANG, FC_FILE);

  tmp = fcinfo_match(fontset, filter); /* wipe duplicite (family, style)s */
  FcFontSetDestroy(fontset);
  fontset = tmp;

  for (s = 0; s < uinterval_num(uintype); s++)
  {
    uinterval_stat[s] = malloc(sizeof(double)*fontset->nfont);
    if (! uinterval_stat[s])
    {
      fprintf(stderr, "fcinfo_uinterval_statistics(): out of memory\n");
      exit(1);
    }
  }

  for (f = 0; f < fontset->nfont; f++)
  {
    FcPatternGetString(fontset->fonts[f], FC_FILE, 0, &file);
    assert(FcPatternGetCharSet(fontset->fonts[f], FC_CHARSET, 0, &charset)
           == FcResultMatch);
    for (s = 0; s < uinterval_num(uintype); s++)
      uinterval_stat[s][f] = 
        charset_uinterval_coverage(charset, 
                                   uinterval_name(s, uintype), 
                                   uintype,
                                   NULL, NULL);
  }

  return fontset; /* holds one of table headers */
}
Пример #20
0
static int find_font(info_rec* info, char* family, char* path)
{
    FcPattern*	pattern;
    FcPattern*	matchedPattern;
    FcResult	result;
    FcChar8*	s;

    pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, family,
                             (char*) NULL);
    if (pattern == NULL)
        return YUV_fontconfig;
    if (FcConfigSubstitute(info->config, pattern, FcMatchPattern) != FcTrue)
        return YUV_fontconfig;
    FcDefaultSubstitute(pattern);
    matchedPattern = FcFontMatch(info->config, pattern, &result);
    FcPatternDestroy(pattern);
    if (FcPatternGetString(matchedPattern, FC_FILE, 0, &s) != FcResultMatch)
        return YUV_fontconfig;
    strcpy(path, (char*)s);
    FcPatternDestroy(matchedPattern);
    return YUV_OK;
}
Пример #21
0
value fcFindFont( value _familyName, value _weight, value _slant, value _size ) {
	val_check(_familyName,string);
	val_check(_weight,number);
	val_check(_slant,number);
	val_check(_size,number);
    
    const char *familyName = val_string(_familyName);
    int weight = val_number(_weight);
    int slant = val_number(_slant);
    float size = val_number(_size);
    
	FcPattern *pattern;

	pattern = FcNameParse( (FcChar8*)familyName );

	FcDefaultSubstitute( pattern );
	FcConfigSubstitute( FcConfigGetCurrent(), pattern, FcMatchPattern );
	
	FcResult result;
	FcPattern *match = FcFontMatch( 0, pattern, &result );
	
	FcPatternDestroy( pattern );
	
	if( !match ) val_throw(alloc_string("Could not find font"));
	
	FcChar8 *temp;
	int id;
	pattern = FcPatternDuplicate(match);
	if( FcPatternGetString( pattern, FC_FILE, 0, &temp ) != FcResultMatch ||
	    FcPatternGetInteger( pattern, FC_INDEX, 0, &id ) != FcResultMatch ) {
		val_throw(alloc_string("Could not load font"));
	}
	value ret = alloc_string((const char *)temp);

	FcPatternDestroy( pattern );
	FcPatternDestroy( match );
	
	return ret;
}
Пример #22
0
Файл: util.c Проект: eXeC64/imv
TTF_Font *load_font(const char *font_spec)
{
  int font_size;
  char *font_name;

  /* figure out font size from name, or default to 24 */
  char *sep = strchr(font_spec, ':');
  if(sep) {
    font_name = strndup(font_spec, sep - font_spec);
    font_size = strtol(sep+1, NULL, 10);
  } else {
    font_name = strdup(font_spec);
    font_size = 24;
  }


  FcConfig *cfg = FcInitLoadConfigAndFonts();
  FcPattern *pattern = FcNameParse((const FcChar8*)font_name);
  FcConfigSubstitute(cfg, pattern, FcMatchPattern);
  FcDefaultSubstitute(pattern);

  TTF_Font *ret = NULL;

  FcResult result = FcResultNoMatch;
  FcPattern* font = FcFontMatch(cfg, pattern, &result);
  if (font) {
    FcChar8 *path = NULL;
    if (FcPatternGetString(font, FC_FILE, 0, &path) == FcResultMatch) {
      ret = TTF_OpenFont((char*)path, font_size);
    }
    FcPatternDestroy(font);
  }
  FcPatternDestroy(pattern);
  FcConfigDestroy(cfg);

  free(font_name);
  return ret;
}
Пример #23
0
GeeArrayList *
FcListFamilies(void)
{
    int          i;
    FcPattern    * pattern;
    FcFontSet    * fontset;
    FcObjectSet  * objectset = 0;
    GeeArrayList * famlist = gee_array_list_new(G_TYPE_STRING,
                                                (GBoxedCopyFunc) g_strdup,
                                                (GDestroyNotify) g_free0,
                                                NULL,
                                                NULL,
                                                NULL);
    g_assert(FcInit());
    pattern = FcNameParse((FcChar8 *) ":");
    objectset = FcObjectSetBuild (FC_FAMILY, NULL);
    fontset = FcFontList(NULL, pattern, objectset);

    for (i = 0; i < fontset->nfont; i++) {
        FcChar8 * family;
        if (FcPatternGetString(fontset->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch) {
            if (gee_abstract_collection_contains((GeeAbstractCollection *) famlist, family))
                continue;
            else
                gee_abstract_collection_add((GeeAbstractCollection *) famlist, family);
        }
    }

    if (objectset)
        FcObjectSetDestroy(objectset);
    if (pattern)
        FcPatternDestroy(pattern);
    if (fontset)
        FcFontSetDestroy(fontset);

    return famlist;
}
Пример #24
0
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font,
                                                          const UChar* characters,
                                                          int length)
{
    FcCharSet* cset = FcCharSetCreate();
    for (int i = 0; i < length; ++i)
        FcCharSetAddChar(cset, characters[i]);

    FcPattern* pattern = FcPatternCreate();

    FcValue fcvalue;
    fcvalue.type = FcTypeCharSet;
    fcvalue.u.c = cset;
    FcPatternAdd(pattern, FC_CHARSET, fcvalue, 0);

    FcConfigSubstitute(0, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);

    FcResult result;
    FcPattern* match = FcFontMatch(0, pattern, &result);
    FcPatternDestroy(pattern);

    SimpleFontData* ret = 0;

    if (match) {
        FcChar8* family;
        if (FcPatternGetString(match, FC_FAMILY, 0, &family) == FcResultMatch) {
            AtomicString fontFamily(reinterpret_cast<char*>(family));
            ret = getCachedFontData(getCachedFontPlatformData(font.fontDescription(), fontFamily, false));
        }
        FcPatternDestroy(match);
    }

    FcCharSetDestroy(cset);

    return ret;
}
Пример #25
0
int BC_Resources::find_font_by_char(FT_ULong char_code, char *path_new, const FT_Face oldface)
{
	FcPattern *font, *ofont;
	FcChar8 *file;
	int result = 0;

	*path_new = 0;

	// Do not search control codes
	if(char_code < ' ')
		return 0;

	if( (ofont = FcFreeTypeQueryFace(oldface, (const FcChar8*)"", 4097, 0)) != 0 ) {
		if( (font = find_similar_font(char_code, ofont)) != 0 ) {
			if(FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch) {
				strcpy(path_new, (char*)file);
				result = 1;
			}
			FcPatternDestroy(font);
		}
		FcPatternDestroy(ofont);
	}
	return result;
}
Пример #26
0
Файл: font.c Проект: nenau/naev
/**
 * @brief Tries to find a system font.
 */
static char *gl_fontFind( const char *fname )
{
   FcConfig* config;
   FcPattern *pat, *font;
   FcResult result;
   FcChar8* file;
   char *fontFile;
   
   config = FcInitLoadConfigAndFonts();
   pat = FcNameParse( (const FcChar8*)fname );
   FcConfigSubstitute( config, pat, FcMatchPattern );
   FcDefaultSubstitute(pat);
   font = FcFontMatch(config, pat, &result);
   if (font) {
      file = NULL;
      if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch) {
         fontFile = strdup( (char*)file );
         FcPatternDestroy(pat);
         return fontFile;
      }
   }
   FcPatternDestroy(pat);
   return NULL;
}
Пример #27
0
void
XeTeXFontMgr_FC::cacheFamilyMembers(const std::list<std::string>& familyNames)
{
	if (familyNames.size() == 0)
		return;
	for (int f = 0; f < allFonts->nfont; ++f) {
		FcPattern*	pat = allFonts->fonts[f];
		if (platformRefToFont.find(pat) != platformRefToFont.end())
			continue;
		char*	s;
		for (int i = 0; FcPatternGetString(pat, FC_FAMILY, i, (FcChar8**)&s) == FcResultMatch; ++i) {
			for (std::list<std::string>::const_iterator j = familyNames.begin(); j != familyNames.end(); ++j) {
				if (*j == s) {
					NameCollection*	names = readNames(pat);
					addToMaps(pat, names);
					delete names;
					goto cached;
				}
			}
		}
	cached:
		;
	}
}
Пример #28
0
Common::SeekableReadStream *FontconfigFontProvider::createReadStreamForFont(const Common::String &name, uint32 style) {
	if (!_config)
		return 0;

	Common::String styleName = makeStyleString(style);

	FcPattern *pattern = FcPatternCreate();

	// Match on the family name
	FcValue value;
	value.type = FcTypeString;
	value.u.s = reinterpret_cast<const FcChar8 *>(name.c_str());
	if (!FcPatternAdd(pattern, FC_FAMILY, value, FcFalse)) {
		FcPatternDestroy(pattern);
		return 0;
	}

	// Match on the style string
	value.u.s = reinterpret_cast<const FcChar8 *>(styleName.c_str());
	if (!FcPatternAdd(pattern, FC_STYLE, value, FcFalse)) {
		FcPatternDestroy(pattern);
		return 0;
	}

	// Only allow TrueType fonts
	// Might change in the future.
	value.u.s = reinterpret_cast<const FcChar8 *>("TrueType");
	if (!FcPatternAdd(pattern, FC_FONTFORMAT, value, FcFalse)) {
		FcPatternDestroy(pattern);
		return 0;
	}

	// Call these functions
	// Might be doing pattern matching. Documentation is awful.
	FcConfigSubstitute(0, pattern, FcMatchPattern);
	FcDefaultSubstitute(pattern);

	// Fetch the match
	FcResult result;
	FcFontSet* fontSet = FcFontSort(0, pattern, 0, 0, &result);
	FcPatternDestroy(pattern);

	if (!fontSet)
		return 0;

	for (int i = 0; i < fontSet->nfont; i++) {
		FcPattern *foundPattern = fontSet->fonts[i];

		// Get the family name of the font
		FcChar8 *familyName;
		if (FcPatternGetString(foundPattern, FC_FAMILY, 0, &familyName) != FcResultMatch)
			continue;

		// If we don't actually match, bail out. We don't want to end
		// up with the default fontconfig font, which would look horrible.
		if (!name.equalsIgnoreCase(reinterpret_cast<const char *>(familyName)))
			continue;

		// Get the name of the font
		FcChar8 *fileName;
		if (FcPatternGetString(foundPattern, FC_FILE, 0, &fileName) != FcResultMatch)
			continue;

		// Let's make sure we can actually get that
		Common::FSNode fontNode(reinterpret_cast<const char *>(fileName));
		if (!fontNode.exists() || !fontNode.isReadable())
			continue;

		debug(1, "Matched %s %s -> '%s'", name.c_str(), styleName.c_str(), fontNode.getPath().c_str());

		FcFontSetDestroy(fontSet);
		return fontNode.createReadStream();
	}

	// We ain't found s#&t
	FcFontSetDestroy(fontSet);
	return 0;
}
Пример #29
0
MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_list,
  ExceptionInfo *exception)
{
#if !defined(FC_FULLNAME)
#define FC_FULLNAME "fullname"
#endif

  char
    extension[MaxTextExtent],
    name[MaxTextExtent];

  FcChar8
    *family,
    *file,
    *fullname,
    *style;

  FcConfig
    *font_config;

  FcFontSet
    *font_set;

  FcObjectSet
    *object_set;

  FcPattern
    *pattern;

  FcResult
    status;

  int
    slant,
    width,
    weight;

  register ssize_t
    i;

  TypeInfo
    *type_info;

  /*
    Load system fonts.
  */
  (void) exception;
  font_config=FcInitLoadConfigAndFonts();
  if (font_config == (FcConfig *) NULL)
    return(MagickFalse);
  font_set=(FcFontSet *) NULL;
  object_set=FcObjectSetBuild(FC_FULLNAME,FC_FAMILY,FC_STYLE,FC_SLANT,
    FC_WIDTH,FC_WEIGHT,FC_FILE,(char *) NULL);
  if (object_set != (FcObjectSet *) NULL)
    {
      pattern=FcPatternCreate();
      if (pattern != (FcPattern *) NULL)
        {
          font_set=FcFontList(0,pattern,object_set);
          FcPatternDestroy(pattern);
        }
      FcObjectSetDestroy(object_set);
    }
  if (font_set == (FcFontSet *) NULL)
    {
      FcConfigDestroy(font_config);
      return(MagickFalse);
    }
  for (i=0; i < (ssize_t) font_set->nfont; i++)
  {
    status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
    if (status != FcResultMatch)
      continue;
    status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
    if (status != FcResultMatch)
      continue;
    *extension='\0';
    GetPathComponent((const char *) file,ExtensionPath,extension);
    if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0))
      continue;
    type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
    if (type_info == (TypeInfo *) NULL)
      continue;
    (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
    type_info->path=ConstantString("System Fonts");
    type_info->signature=MagickSignature;
    (void) CopyMagickString(name,"Unknown",MaxTextExtent);
    status=FcPatternGetString(font_set->fonts[i],FC_FULLNAME,0,&fullname);
    if ((status == FcResultMatch) && (fullname != (FcChar8 *) NULL))
      (void) CopyMagickString(name,(const char *) fullname,MaxTextExtent);
    else
      {
        if (family != (FcChar8 *) NULL)
          (void) CopyMagickString(name,(const char *) family,MaxTextExtent);
        status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style);
        if ((status == FcResultMatch) && (style != (FcChar8 *) NULL) &&
            (LocaleCompare((const char *) style,"Regular") != 0))
          {
            (void) ConcatenateMagickString(name," ",MaxTextExtent);
            (void) ConcatenateMagickString(name,(const char *) style,
              MaxTextExtent);
          }
      }
    type_info->name=ConstantString(name);
    (void) SubstituteString(&type_info->name," ","-");
    type_info->family=ConstantString((const char *) family);
    status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant);
    type_info->style=NormalStyle;
    if (slant == FC_SLANT_ITALIC)
      type_info->style=ItalicStyle;
    if (slant == FC_SLANT_OBLIQUE)
      type_info->style=ObliqueStyle;
    status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width);
    type_info->stretch=NormalStretch;
    if (width >= FC_WIDTH_ULTRACONDENSED)
      type_info->stretch=UltraCondensedStretch;
    if (width >= FC_WIDTH_EXTRACONDENSED)
      type_info->stretch=ExtraCondensedStretch;
    if (width >= FC_WIDTH_CONDENSED)
      type_info->stretch=CondensedStretch;
    if (width >= FC_WIDTH_SEMICONDENSED)
      type_info->stretch=SemiCondensedStretch;
    if (width >= FC_WIDTH_NORMAL)
      type_info->stretch=NormalStretch;
    if (width >= FC_WIDTH_SEMIEXPANDED)
      type_info->stretch=SemiExpandedStretch;
    if (width >= FC_WIDTH_EXPANDED)
      type_info->stretch=ExpandedStretch;
    if (width >= FC_WIDTH_EXTRAEXPANDED)
      type_info->stretch=ExtraExpandedStretch;
    if (width >= FC_WIDTH_ULTRAEXPANDED)
      type_info->stretch=UltraExpandedStretch;
    type_info->weight=400;
    status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight);
    if (weight >= FC_WEIGHT_THIN)
      type_info->weight=100;
    if (weight >= FC_WEIGHT_EXTRALIGHT)
      type_info->weight=200;
    if (weight >= FC_WEIGHT_LIGHT)
      type_info->weight=300;
    if (weight >= FC_WEIGHT_NORMAL)
      type_info->weight=400;
    if (weight >= FC_WEIGHT_MEDIUM)
      type_info->weight=500;
    if (weight >= FC_WEIGHT_DEMIBOLD)
      type_info->weight=600;
    if (weight >= FC_WEIGHT_BOLD)
      type_info->weight=700;
    if (weight >= FC_WEIGHT_EXTRABOLD)
      type_info->weight=800;
    if (weight >= FC_WEIGHT_BLACK)
      type_info->weight=900;
    type_info->glyphs=ConstantString((const char *) file);
    (void) AddValueToSplayTree(type_list,type_info->name,type_info);
  }
  FcFontSetDestroy(font_set);
  FcConfigDestroy(font_config);
  return(MagickTrue);
}
Пример #30
0
int BC_Resources::init_fontconfig(const char *search_path)
{
	if( fontlist ) return 0;
	fontlist = new ArrayList<BC_FontEntry*>;

#define get_str(str,sep,ptr,cond) do { char *out = str; \
  while( *ptr && !strchr(sep,*ptr) && (cond) ) *out++ = *ptr++; \
  *out = 0; \
} while(0)

#define skip_str(sep, ptr) do { \
  while( *ptr && strchr(sep,*ptr) ) ++ptr; \
} while(0)

	char find_command[BCTEXTLEN];
	sprintf(find_command,
		"find %s -name 'fonts.dir' -print -exec cat {} \\;",
		search_path);
	FILE *in = popen(find_command, "r");

	FT_Library freetype_library = 0;
//	FT_Face freetype_face = 0;
//	FT_Init_FreeType(&freetype_library);

	char line[BCTEXTLEN], current_dir[BCTEXTLEN];
	current_dir[0] = 0;

	while( !feof(in) && fgets(line, BCTEXTLEN, in) ) {
		if(!strlen(line)) break;

		char *in_ptr = line;

// Get current directory
		if(line[0] == '/') {
			get_str(current_dir, "\n", in_ptr,1);
			for( int i=strlen(current_dir); --i>=0 && current_dir[i]!='/'; )
				current_dir[i] = 0;
			continue;
		}

//printf("TitleMain::build_fonts %s\n", line);
		BC_FontEntry *entry = new BC_FontEntry;
		char string[BCTEXTLEN];
// Path
		get_str(string, "\n", in_ptr, in_ptr[0]!=' ' || in_ptr[1]!='-');
		entry->path = cstrcat(2, current_dir, string);
// Foundary
		skip_str(" -", in_ptr);
		get_str(string, " -\n", in_ptr, 1);
		if( !string[0] ) { delete entry;  continue; }
		entry->foundry = cstrdup(string);
		if(*in_ptr == '-') in_ptr++;
// Family
		get_str(string, "-\n", in_ptr, 1);
		if( !string[0] ) { delete entry;  continue; }
		entry->family = cstrdup(string);
		if(*in_ptr == '-') in_ptr++;
// Weight
		get_str(string, "-\n", in_ptr, 1);
		entry->weight = cstrdup(string);
		if(*in_ptr == '-') in_ptr++;
// Slant
		get_str(string, "-\n", in_ptr, 1);
		entry->slant = cstrdup(string);
		if(*in_ptr == '-') in_ptr++;
// SWidth
		get_str(string, "-\n", in_ptr, 1);
		entry->swidth = cstrdup(string);
		if(*in_ptr == '-') in_ptr++;
// Adstyle
		get_str(string, "-\n", in_ptr, 1);
		entry->adstyle = cstrdup(string);
		if(*in_ptr == '-') in_ptr++;
// pixelsize
		get_str(string, "-\n", in_ptr, 1);
		entry->pixelsize = atol(string);
		if(*in_ptr == '-') in_ptr++;
// pointsize
		get_str(string, "-\n", in_ptr, 1);
		entry->pointsize = atol(string);
		if(*in_ptr == '-') in_ptr++;
// xres
		get_str(string, "-\n", in_ptr, 1);
		entry->xres = atol(string);
		if(*in_ptr == '-') in_ptr++;
// yres
		get_str(string, "-\n", in_ptr, 1);
		entry->yres = atol(string);
		if(*in_ptr == '-') in_ptr++;
// spacing
		get_str(string, "-\n", in_ptr, 1);
		entry->spacing = cstrdup(string);
		if(*in_ptr == '-') in_ptr++;
// avg_width
		get_str(string, "-\n", in_ptr, 1);
		entry->avg_width = atol(string);
		if(*in_ptr == '-') in_ptr++;
// registry
		get_str(string, "-\n", in_ptr, 1);
		entry->registry = cstrdup(string);
		if(*in_ptr == '-') in_ptr++;
// encoding
		get_str(string, "-\n", in_ptr, 1);
		entry->encoding = cstrdup(string);
		if(*in_ptr == '-') in_ptr++;

// Add to list
//printf("TitleMain::build_fonts 1 %s\n", entry->path);
// This takes a real long time to do.  Instead just take all fonts
// 		if(!load_freetype_face(freetype_library,
// 			freetype_face, entry->path) )
// Fix parameters
		sprintf(line, "%s (%s)", entry->family, entry->foundry);
		entry->displayname = cstrdup(line);

		if(!strcasecmp(entry->weight, "demibold")) {
			entry->fixed_style |= BC_FONT_BOLD;
			entry->style |= FL_WEIGHT_DEMIBOLD;
		}
		else if(!strcasecmp(entry->weight, "bold")) {
			entry->fixed_style |= BC_FONT_BOLD;
			entry->style |= FL_WEIGHT_BOLD;
		}
		else {
			entry->style |= FL_WEIGHT_NORMAL;
		}

		if(!strcasecmp(entry->slant, "r")) {
			entry->style |= FL_SLANT_ROMAN;
		}
		else if(!strcasecmp(entry->slant, "i")) {
			entry->style |= FL_SLANT_ITALIC;
			entry->fixed_style |= BC_FONT_ITALIC;
		}
		else if(!strcasecmp(entry->slant, "o")) {
			entry->style |= FL_SLANT_OBLIQUE;
			entry->fixed_style |= BC_FONT_ITALIC;
		}

		if(!strcasecmp(entry->swidth, "normal"))
			entry->style = FL_WIDTH_NORMAL;
		else if(!strcasecmp(entry->swidth, "ultracondensed"))
			entry->style = FL_WIDTH_ULTRACONDENSED;
		else if(!strcasecmp(entry->swidth, "extracondensed"))
			entry->style = FL_WIDTH_EXTRACONDENSED;
		else if(!strcasecmp(entry->swidth, "condensed"))
			entry->style = FL_WIDTH_CONDENSED;
		else if(!strcasecmp(entry->swidth, "semicondensed"))
			entry->style = FL_WIDTH_SEMICONDENSED;
		else if(!strcasecmp(entry->swidth, "semiexpanded"))
			entry->style = FL_WIDTH_SEMIEXPANDED;
		else if(!strcasecmp(entry->swidth, "expanded"))
			entry->style = FL_WIDTH_EXPANDED;
		else if(!strcasecmp(entry->swidth, "extraexpanded"))
			entry->style = FL_WIDTH_EXTRAEXPANDED;
		else if(!strcasecmp(entry->swidth, "ultraexpanded"))
			entry->style = FL_WIDTH_ULTRAEXPANDED;
		else
			entry->style = FL_WIDTH_NORMAL;

		fontlist->append(entry);
//		printf("TitleMain::build_fonts %s: success\n",	entry->path);
//printf("TitleMain::build_fonts 2\n");
	}
	pclose(in);


// Load all the fonts from fontconfig
	FcPattern *pat;
	FcFontSet *fs;
	FcObjectSet *os;
	FcChar8 *family, *file, *foundry, *style, *format;
	int slant, spacing, width, weight;
	int force_style = 0;
// if you want limit search to TrueType put 1
	int limit_to_trutype = 1;
	FcConfig *config;
	int i;
	char tmpstring[BCTEXTLEN];
	if(!FcInit())
		return 1;
	config = FcConfigGetCurrent();
	FcConfigSetRescanInterval(config, 0);

	pat = FcPatternCreate();
	os = FcObjectSetBuild ( FC_FAMILY, FC_FILE, FC_FOUNDRY, FC_WEIGHT,
		FC_WIDTH, FC_SLANT, FC_FONTFORMAT, FC_SPACING, FC_STYLE, (char *) 0);
	FcPatternAddBool(pat, FC_SCALABLE, true);

	if(language[0]) {
		char langstr[LEN_LANG * 3];
		strcpy(langstr, language);

		if(region[0]) {
			strcat(langstr, "-");
			strcat(langstr, region);
		}

		FcLangSet *ls =  FcLangSetCreate();
		if(FcLangSetAdd(ls, (const FcChar8*)langstr))
		if(FcPatternAddLangSet(pat, FC_LANG, ls))
		FcLangSetDestroy(ls);
	}

	fs = FcFontList(config, pat, os);
	FcPatternDestroy(pat);
	FcObjectSetDestroy(os);

	for (i = 0; fs && i < fs->nfont; i++) {
		FcPattern *font = fs->fonts[i];
		force_style = 0;
		FcPatternGetString(font, FC_FONTFORMAT, 0, &format);
		//on this point you can limit font search
		if(limit_to_trutype && strcmp((char *)format, "TrueType"))
			continue;

		sprintf(tmpstring, "%s", format);
		BC_FontEntry *entry = new BC_FontEntry;
		if(FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch) {
			entry->path = cstrdup((char*)file);
		}

		if(FcPatternGetString(font, FC_FOUNDRY, 0, &foundry) == FcResultMatch) {
			entry->foundry = cstrdup((char*)foundry);
		}

		if(FcPatternGetInteger(font, FC_WEIGHT, 0, &weight) == FcResultMatch) {
			switch(weight) {
			case FC_WEIGHT_THIN:
			case FC_WEIGHT_EXTRALIGHT:
			case FC_WEIGHT_LIGHT:
			case FC_WEIGHT_BOOK:
				force_style = 1;
				entry->weight = cstrdup("medium");
				break;

			case FC_WEIGHT_NORMAL:
			case FC_WEIGHT_MEDIUM:
			default:
				entry->weight = cstrdup("medium");
				break;

			case FC_WEIGHT_BLACK:
			case FC_WEIGHT_SEMIBOLD:
			case FC_WEIGHT_BOLD:
				entry->weight = cstrdup("bold");
				entry->fixed_style |= BC_FONT_BOLD;
				break;

			case FC_WEIGHT_EXTRABOLD:
			case FC_WEIGHT_EXTRABLACK:
				force_style = 1;
				entry->weight = cstrdup("bold");
				entry->fixed_style |= BC_FONT_BOLD;
				break;
			}
		}

		if(FcPatternGetString(font, FC_FAMILY, 0, &family) == FcResultMatch)
			entry->family = cstrdup((char*)family);

		if(FcPatternGetInteger(font, FC_SLANT, 0, &slant) == FcResultMatch) {
			switch(slant) {
			case FC_SLANT_ROMAN:
			default:
				entry->slant = cstrdup("r");
				entry->style |= FL_SLANT_ROMAN;
				break;
			case FC_SLANT_ITALIC:
				entry->slant = cstrdup("i");
				entry->style |= FL_SLANT_ITALIC;
				entry->fixed_style |= BC_FONT_ITALIC;
				break;
			case FC_SLANT_OBLIQUE:
				entry->slant = cstrdup("o");
				entry->style |= FL_SLANT_OBLIQUE;
				entry->fixed_style |= BC_FONT_ITALIC;
				break;
			}
		}

		if(FcPatternGetInteger(font, FC_WIDTH, 0, &width) == FcResultMatch) {
			switch(width) {
			case FC_WIDTH_ULTRACONDENSED:
				entry->swidth = cstrdup("ultracondensed");
				break;

			case FC_WIDTH_EXTRACONDENSED:
				entry->swidth = cstrdup("extracondensed");
				break;

			case FC_WIDTH_CONDENSED:
				entry->swidth = cstrdup("condensed");
				break;
			case FC_WIDTH_SEMICONDENSED:
				entry->swidth = cstrdup("semicondensed");
				break;

			case FC_WIDTH_NORMAL:
			default:
				entry->swidth = cstrdup("normal");
				break;

			case FC_WIDTH_SEMIEXPANDED:
				entry->swidth = cstrdup("semiexpanded");
				break;

			case FC_WIDTH_EXPANDED:
				entry->swidth = cstrdup("expanded");
				break;

			case FC_WIDTH_EXTRAEXPANDED:
				entry->swidth = cstrdup("extraexpanded");
				break;

			case FC_WIDTH_ULTRAEXPANDED:
				entry->swidth = cstrdup("ultraexpanded");
				break;
			}
		}

		if(FcPatternGetInteger(font, FC_SPACING, 0, &spacing) == FcResultMatch) {
			switch(spacing) {
			case 0:
			default:
				entry->spacing = cstrdup("p");
				break;

			case 90:
				entry->spacing = cstrdup("d");
				break;

			case 100:
				entry->spacing = cstrdup("m");
				break;

			case 110:
				entry->spacing = cstrdup("c");
				break;
			}
		}

		// Add fake stuff for compatibility
		entry->adstyle = cstrdup(" ");
		entry->pixelsize = 0;
		entry->pointsize = 0;
		entry->xres = 0;
		entry->yres = 0;
		entry->avg_width = 0;
		entry->registry = cstrdup("utf");
		entry->encoding = cstrdup("8");

		if(!FcPatternGetString(font, FC_STYLE, 0, &style) == FcResultMatch)
			force_style = 0;

		// If font has a style unmanaged by titler plugin, force style to be displayed on name
		// in this way we can shown all available fonts styles.
		if(force_style) {
			sprintf(tmpstring, "%s (%s)", entry->family, style);
			entry->displayname = cstrdup(tmpstring);
		}
		else {
			if(strcmp(entry->foundry, "unknown")) {
				sprintf(tmpstring, "%s (%s)", entry->family, entry->foundry);
				entry->displayname = cstrdup(tmpstring);
			}
			else {
				sprintf(tmpstring, "%s", entry->family);
				entry->displayname = cstrdup(tmpstring);
			}

		}
		fontlist->append(entry);
	}

	FcFontSetDestroy(fs);
	if(freetype_library)
		FT_Done_FreeType(freetype_library);
// for(int i = 0; i < fonts->total; i++)
//	fonts->values[i]->dump();

	FcConfigAppFontAddDir(0, (const FcChar8*)search_path);
	FcConfigSetRescanInterval(0, 0);

	os = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_FOUNDRY, FC_WEIGHT,
		FC_WIDTH, FC_SLANT, FC_SPACING, FC_STYLE, (char *)0);
	pat = FcPatternCreate();
	FcPatternAddBool(pat, FC_SCALABLE, true);

	if(language[0])
	{
		char langstr[LEN_LANG * 3];
		strcpy(langstr, language);

		if(region[0])
		{
			strcat(langstr, "-");
			strcat(langstr, region);
		}

		FcLangSet *ls =  FcLangSetCreate();
		if(FcLangSetAdd(ls, (const FcChar8*)langstr))
			if(FcPatternAddLangSet(pat, FC_LANG, ls))
		FcLangSetDestroy(ls);
	}

	fs = FcFontList(0, pat, os);
	FcPatternDestroy(pat);
	FcObjectSetDestroy(os);

	for(int i = 0; i < fs->nfont; i++)
	{
		FcPattern *font = fs->fonts[i];
		BC_FontEntry *entry = new BC_FontEntry;

		FcChar8 *strvalue;
		if(FcPatternGetString(font, FC_FILE, 0, &strvalue) == FcResultMatch)
		{
			entry->path = new char[strlen((char*)strvalue) + 1];
			strcpy(entry->path, (char*)strvalue);
		}

		if(FcPatternGetString(font, FC_FOUNDRY, 0, &strvalue) == FcResultMatch)
		{
			entry->foundry = new char[strlen((char*)strvalue) + 1];
			strcpy(entry->foundry, (char *)strvalue);
		}

		if(FcPatternGetString(font, FC_FAMILY, 0, &strvalue) == FcResultMatch)
		{
			entry->family = new char[strlen((char*)strvalue) + 2];
			strcpy(entry->family, (char*)strvalue);
		}

		int intvalue;
		if(FcPatternGetInteger(font, FC_SLANT, 0, &intvalue) == FcResultMatch)
		{
			switch(intvalue)
			{
			case FC_SLANT_ROMAN:
			default:
				entry->style |= FL_SLANT_ROMAN;
				break;

			case FC_SLANT_ITALIC:
				entry->style |= FL_SLANT_ITALIC;
				break;

			case FC_SLANT_OBLIQUE:
				entry->style |= FL_SLANT_OBLIQUE;
				break;
			}
		}

		if(FcPatternGetInteger(font, FC_WEIGHT, 0, &intvalue) == FcResultMatch)
		{
			switch(intvalue)
			{
			case FC_WEIGHT_THIN:
				entry->style |= FL_WEIGHT_THIN;
				break;

			case FC_WEIGHT_EXTRALIGHT:
				entry->style |= FL_WEIGHT_EXTRALIGHT;
				break;

			case FC_WEIGHT_LIGHT:
				entry->style |= FL_WEIGHT_LIGHT;
				break;

			case FC_WEIGHT_BOOK:
				entry->style |= FL_WEIGHT_BOOK;
				break;

			case FC_WEIGHT_NORMAL:
			default:
				entry->style |= FL_WEIGHT_NORMAL;
				break;

			case FC_WEIGHT_MEDIUM:
				entry->style |= FL_WEIGHT_MEDIUM;
				break;

			case FC_WEIGHT_DEMIBOLD:
				entry->style |= FL_WEIGHT_DEMIBOLD;
				break;

			case FC_WEIGHT_BOLD:
				entry->style |= FL_WEIGHT_BOLD;
				break;

			case FC_WEIGHT_EXTRABOLD:
				entry->style |= FL_WEIGHT_EXTRABOLD;
				break;

			case FC_WEIGHT_BLACK:
				entry->style |= FL_WEIGHT_BLACK;
				break;

			case FC_WEIGHT_EXTRABLACK:
				entry->style |= FL_WEIGHT_EXTRABLACK;
				break;
			}
		}

		if(FcPatternGetInteger(font, FC_WIDTH, 0, &intvalue) == FcResultMatch)
		{
			switch(intvalue)
			{
			case FC_WIDTH_ULTRACONDENSED:
				entry->style |= FL_WIDTH_ULTRACONDENSED;
				break;

			case FC_WIDTH_EXTRACONDENSED:
				entry->style |= FL_WIDTH_EXTRACONDENSED;
				break;

			case FC_WIDTH_CONDENSED:
				entry->style |= FL_WIDTH_CONDENSED;
				break;

			case FC_WIDTH_SEMICONDENSED:
				entry->style = FL_WIDTH_SEMICONDENSED;
				break;

			case FC_WIDTH_NORMAL:
			default:
				entry->style |= FL_WIDTH_NORMAL;
				break;

			case FC_WIDTH_SEMIEXPANDED:
				entry->style |= FL_WIDTH_SEMIEXPANDED;
				break;

			case FC_WIDTH_EXPANDED:
				entry->style |= FL_WIDTH_EXPANDED;
				break;

			case FC_WIDTH_EXTRAEXPANDED:
				entry->style |= FL_WIDTH_EXTRAEXPANDED;
				break;

			case FC_WIDTH_ULTRAEXPANDED:
				entry->style |= FL_WIDTH_ULTRAEXPANDED;
				break;
			}
		}
		if(FcPatternGetInteger(font, FC_SPACING, 0, &intvalue) == FcResultMatch)
		{
			switch(intvalue)
			{
			case FC_PROPORTIONAL:
			default:
				entry->style |= FL_PROPORTIONAL;
				break;

			case FC_DUAL:
				entry->style |= FL_DUAL;
				break;

			case FC_MONO:
				entry->style |= FL_MONO;
				break;

			case FC_CHARCELL:
				entry->style |= FL_CHARCELL;
				break;
			}
		}
		if(entry->foundry && strcmp(entry->foundry, "unknown"))
		{
			char tempstr[BCTEXTLEN];
			sprintf(tempstr, "%s (%s)", entry->family, entry->foundry);
			entry->displayname = new char[strlen(tempstr) + 1];
			strcpy(entry->displayname, tempstr);
		}
		else
		{
			entry->displayname = new char[strlen(entry->family) + 1];
			strcpy(entry->displayname, entry->family);
		}
		fontlist->append(entry);
	}
	FcFontSetDestroy(fs);
	return 0;
}