Пример #1
0
	std::string FindDefaultFont()
	{
		std::string answer("/usr/share/fonts/liberation/LiberationSans-Regular.ttf");
		FcFontSet	*fs;
		FcPattern   *pat;
		FcResult	result;
		if (!FcInit())
		{
			return answer;
		}
		pat = FcNameParse((FcChar8 *)"LiberationSans-Regular.ttf");
		FcConfigSubstitute(0, pat, FcMatchPattern);
		FcDefaultSubstitute(pat);

		fs = FcFontSetCreate();
		FcPattern   *match;
		match = FcFontMatch(0, pat, &result);
		if (match)
		{
			FcChar8 *file;
			if (FcPatternGetString(match, FC_FILE, 0, &file) == FcResultMatch)
			{
				answer = (const char *)file;
			}
			FcPatternDestroy(match);
		}
		FcPatternDestroy(pat);
		FcFini();
		return answer;
	}
Пример #2
0
FcBool
FcConfigBuildFonts (FcConfig *config)
{
    FcFontSet	    *fonts;

    if (!config)
    {
      config = FcConfigGetCurrent ();
      if (!config)
        return FcFalse;
    }
    fonts = FcFontSetCreate ();
    if (!fonts)
      return FcFalse;
    FcConfigSetFonts (config, fonts, FcSetSystem);

  if (!FcConfigAddDirList (config, FcSetSystem, config->fontDirs)) {
    if(FcDebug ())
      fprintf(stderr,"Failed to get list of available fonts.");
    return FcFalse;
  }
    //if (FcDebug () & FC_DBG_FONTSET)
#ifdef DEBUG
  FcFontSetPrint (fonts);
#endif
  return FcTrue;
}
Пример #3
0
FcFontSet *fcinfo_fontformat_family_index(const FcChar8 *format,
                                          const FcPattern *filter)
{
  FcFontSet *fontset, *result;
  FcPattern *pattern;
  FcPattern *font;
  FcResult r;
  int f;

  pattern = FcPatternDuplicate(filter);
  FcPatternAddString(pattern, FC_FONTFORMAT, format);

  fontset = fcinfo(NULL, pattern, FcTrue, 1, FC_FAMILY);

  result = FcFontSetCreate();
  for (f = 0; f < fontset->nfont; f++)
  {
    font = FcFontMatch(NULL, fontset->fonts[f], &r);
    assert(r == FcResultMatch);
    /* don't add ethio16f-uni.pcf, johabg16.pcf and similar with reported 
       empty charset */
    /* could be done with fcinfo_match(), but that is superfluous
       there like for fcinfo_language_font_index() - it will be needed
       when we will need to display some kind of specimen in fontformat 
       index */
    if (!empty_charset(font))
      FcFontSetAdd(result, FcPatternDuplicate(fontset->fonts[f]));
    FcPatternDestroy(font);
  }

  FcPatternDestroy(pattern);
  FcFontSetDestroy(fontset);
  return result;
}
static AliasStrength strengthOfFirstAlias(const FcPattern& original)
{
    // Ideally there would exist a call like
    // FcResult FcPatternIsWeak(pattern, object, id, FcBool* isWeak);
    //
    // However, there is no such call and as of Fc 2.11.0 even FcPatternEquals ignores the weak bit.
    // Currently, the only reliable way of finding the weak bit is by its effect on matching.
    // The weak bit only affects the matching of FC_FAMILY and FC_POSTSCRIPT_NAME object values.
    // A element with the weak bit is scored after FC_LANG, without the weak bit is scored before.
    // Note that the weak bit is stored on the element, not on the value it holds.
    FcValue value;
    FcResult result = FcPatternGet(&original, FC_FAMILY, 0, &value);
    if (result != FcResultMatch)
        return AliasStrength::Done;

    RefPtr<FcPattern> pattern = adoptRef(FcPatternDuplicate(&original));
    FcBool hasMultipleFamilies = true;
    while (hasMultipleFamilies)
        hasMultipleFamilies = FcPatternRemove(pattern.get(), FC_FAMILY, 1);

    // Create a font set with two patterns.
    // 1. the same FC_FAMILY as pattern and a lang object with only 'nomatchlang'.
    // 2. a different FC_FAMILY from pattern and a lang object with only 'matchlang'.
    FcUniquePtr<FcFontSet> fontSet(FcFontSetCreate());

    FcUniquePtr<FcLangSet> strongLangSet(FcLangSetCreate());
    FcLangSetAdd(strongLangSet.get(), reinterpret_cast<const FcChar8*>("nomatchlang"));
    // Ownership of this FcPattern will be transferred with FcFontSetAdd.
    FcPattern* strong = FcPatternDuplicate(pattern.get());
    FcPatternAddLangSet(strong, FC_LANG, strongLangSet.get());

    FcUniquePtr<FcLangSet> weakLangSet(FcLangSetCreate());
    FcLangSetAdd(weakLangSet.get(), reinterpret_cast<const FcChar8*>("matchlang"));
    // Ownership of this FcPattern will be transferred via FcFontSetAdd.
    FcPattern* weak = FcPatternCreate();
    FcPatternAddString(weak, FC_FAMILY, reinterpret_cast<const FcChar8*>("nomatchstring"));
    FcPatternAddLangSet(weak, FC_LANG, weakLangSet.get());

    FcFontSetAdd(fontSet.get(), strong);
    FcFontSetAdd(fontSet.get(), weak);

    // Add 'matchlang' to the copy of the pattern.
    FcPatternAddLangSet(pattern.get(), FC_LANG, weakLangSet.get());

    // Run a match against the copy of the pattern.
    // If the first element was weak, then we should match the pattern with 'matchlang'.
    // If the first element was strong, then we should match the pattern with 'nomatchlang'.

    // Note that this config is only used for FcFontRenderPrepare, which we don't even want.
    // However, there appears to be no way to match/sort without it.
    RefPtr<FcConfig> config = adoptRef(FcConfigCreate());
    FcFontSet* fontSets[1] = { fontSet.get() };
    RefPtr<FcPattern> match = adoptRef(FcFontSetMatch(config.get(), fontSets, 1, pattern.get(), &result));

    FcLangSet* matchLangSet;
    FcPatternGetLangSet(match.get(), FC_LANG, 0, &matchLangSet);
    return FcLangEqual == FcLangSetHasLang(matchLangSet, reinterpret_cast<const FcChar8*>("matchlang"))
        ? AliasStrength::Weak : AliasStrength::Strong;
}
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;
}
Пример #6
0
FcFontSet * fcinfo(const FcConfig *config, const FcPattern *pattern, 
                   FcBool remove_duplicities, int argnum, ...)
{
  va_list va;
  const char *elements[argnum + 1];
  int a;

  FcFontSet *fontset;
  FcObjectSet *objectset;

  FcInit();
  objectset = FcObjectSetCreate();

  va_start(va, argnum);
  for (a = 0; a < argnum; a++)
  {
    elements[a] = va_arg(va, const char *);
    FcObjectSetAdd(objectset, elements[a]);
  }
  va_end(va);

  fontset = FcFontList((FcConfig *)config, (FcPattern *)pattern, objectset);
  elements[argnum] = NULL;
  font_set_sort(fontset, elements);

  FcObjectSetDestroy(objectset);

  if (remove_duplicities)
  {
    FcFontSet *result = FcFontSetCreate();
    int f;
    FcPattern *added = NULL;

    /* fontlist is linearly ordered */
    f = 0;
    while (f < fontset->nfont)
    {
      FcFontSetAdd(result, FcPatternDuplicate(fontset->fonts[f]));
      added = fontset->fonts[f++];
      while (f < fontset->nfont &&
             !pattern_compare(&fontset->fonts[f], &added, elements))
        f++;
    }

    FcFontSetDestroy(fontset);
    return result;
  }

  return fontset;
}
Пример #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
/**
 * \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;
}
Пример #9
0
VALUE
shoes_load_font(const char *filename)
{
  FcConfig *fc = FcConfigGetCurrent();
  FcFontSet *fonts = FcFontSetCreate();
  if (!FcFileScan(fonts, NULL, NULL, NULL, (const FcChar8 *)filename, FcTrue))
    return Qnil;

  VALUE ary = rb_ary_new();
  shoes_make_font_list(fonts, ary);
  FcFontSetDestroy(fonts);

  if (!FcConfigAppFontAddFile(fc, (const FcChar8 *)filename))
    return Qnil;

  // refresh the FONTS list
  shoes_update_fonts(shoes_font_list());
  return ary;
}
Пример #10
0
FcBool
FcConfigBuildFonts (FcConfig *config)
{
    FcFontSet	    *fonts;

    if (!config)
    {
	config = FcConfigGetCurrent ();
	if (!config)
	    return FcFalse;
    }
	
    fonts = FcFontSetCreate ();
    if (!fonts)
	return FcFalse;

    FcConfigSetFonts (config, fonts, FcSetSystem);

    if (!FcConfigAddDirList (config, FcSetSystem, config->fontDirs))
	return FcFalse;
    if (FcDebug () & FC_DBG_FONTSET)
	FcFontSetPrint (fonts);
    return FcTrue;
}
Пример #11
0
int
main (int argc, char **argv)
{
    unsigned int id = (unsigned int) -1;
    int         brief = 0;
    FcFontSet   *fs;
    FcChar8     *format = NULL;
    int		err = 0;
    int		i;
#if HAVE_GETOPT_LONG || HAVE_GETOPT
    int		c;

    setlocale (LC_ALL, "");
#if HAVE_GETOPT_LONG
    while ((c = getopt_long (argc, argv, "i:bf:Vh", longopts, NULL)) != -1)
#else
    while ((c = getopt (argc, argv, "i:bf:Vh")) != -1)
#endif
    {
	switch (c) {
	case 'i':
	    id = (unsigned int) strtol (optarg, NULL, 0); /* strtol() To handle -1. */
	    break;
	case 'b':
	    brief = 1;
	    break;
	case 'f':
	    format = (FcChar8 *) strdup (optarg);
	    break;
	case 'V':
	    fprintf (stderr, "fontconfig version %d.%d.%d\n",
		     FC_MAJOR, FC_MINOR, FC_REVISION);
	    exit (0);
	case 'h':
	    usage (argv[0], 0);
	default:
	    usage (argv[0], 1);
	}
    }
    i = optind;
#else
    i = 1;
#endif

    if (i == argc)
	usage (argv[0], 1);

    fs = FcFontSetCreate ();

#if defined(MIKTEX_WINDOWS)
    _setmode(_fileno(stdout), _O_BINARY);
#endif
    for (; i < argc; i++)
    {
	if (!FcFreeTypeQueryAll ((FcChar8*) argv[i], id, NULL, NULL, fs))
	{
	    fprintf (stderr, _("Can't query face %u of font file %s\n"), id, argv[i]);
	    err = 1;
	}
    }

    for (i = 0; i < fs->nfont; i++)
    {
	FcPattern *pat = fs->fonts[i];

	if (brief)
	{
	    FcPatternDel (pat, FC_CHARSET);
	    FcPatternDel (pat, FC_LANG);
	}

	if (format)
	{
	    FcChar8 *s;

	    s = FcPatternFormat (pat, format);
	    if (s)
	    {
		printf ("%s", s);
		FcStrFree (s);
	    }
	}
	else
	{
	    FcPatternPrint (pat);
	}
    }

    FcFontSetDestroy (fs);

    FcFini ();
    return err;
}
Пример #12
0
/**
 * \brief Low-level font selection.
 * \param priv private data
 * \param family font family
 * \param treat_family_as_pattern treat family as fontconfig pattern
 * \param bold font weight value
 * \param italic font slant value
 * \param index out: font index inside a file
 * \param code: the character that should be present in the font, can be 0
 * \return font file path
*/
static char *select_font(ASS_Library *library, FCInstance *priv,
                          const char *family, int treat_family_as_pattern,
                          unsigned bold, unsigned italic, int *index,
                          uint32_t code)
{
    FcBool rc;
    FcResult result;
    FcPattern *pat = NULL, *rpat = NULL;
    int r_index, r_slant, r_weight;
    FcChar8 *r_family, *r_style, *r_file, *r_fullname;
    FcBool r_outline, r_embolden;
    FcCharSet *r_charset;
    FcFontSet *ffullname = NULL, *fsorted = NULL, *fset = NULL;
    int curf;
    char *retval = NULL;
    int family_cnt = 0;

    *index = 0;

    if (treat_family_as_pattern)
        pat = FcNameParse((const FcChar8 *) family);
    else
        pat = FcPatternCreate();

    if (!pat)
        goto error;

    if (!treat_family_as_pattern) {
        FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) family);

        // In SSA/ASS fonts are sometimes referenced by their "full name",
        // which is usually a concatenation of family name and font
        // style (ex. Ottawa Bold). Full name is available from
        // FontConfig pattern element FC_FULLNAME, but it is never
        // used for font matching.
        // Therefore, I'm removing words from the end of the name one
        // by one, and adding shortened names to the pattern. It seems
        // that the first value (full name in this case) has
        // precedence in matching.
        // An alternative approach could be to reimplement FcFontSort
        // using FC_FULLNAME instead of FC_FAMILY.
        family_cnt = 1;
        {
            char *s = strdup(family);
            char *p = s + strlen(s);
            while (--p > s)
                if (*p == ' ' || *p == '-') {
                    *p = '\0';
                    FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) s);
                    ++family_cnt;
                }
            free(s);
        }
    }
    FcPatternAddBool(pat, FC_OUTLINE, FcTrue);
    FcPatternAddInteger(pat, FC_SLANT, italic);
    FcPatternAddInteger(pat, FC_WEIGHT, bold);

    FcDefaultSubstitute(pat);

    rc = FcConfigSubstitute(priv->config, pat, FcMatchPattern);
    if (!rc)
        goto error;
    /* Fontconfig defaults include a language setting, which it sets based on
     * some environment variables or defaults to "en". Unset this as we don't
     * know the real language, and because some some attached fonts lack
     * non-ascii characters included in fontconfig's list of characters
     * required for English support and therefore don't match the lang=en
     * criterion.
     */
    FcPatternDel(pat, "lang");

    fsorted = FcFontSort(priv->config, pat, FcTrue, NULL, &result);
    ffullname = match_fullname(library, priv, family, bold, italic);
    if (!fsorted || !ffullname)
        goto error;

    fset = FcFontSetCreate();
    for (curf = 0; curf < ffullname->nfont; ++curf) {
        FcPattern *curp = ffullname->fonts[curf];
        FcPatternReference(curp);
        FcFontSetAdd(fset, curp);
    }
    for (curf = 0; curf < fsorted->nfont; ++curf) {
        FcPattern *curp = fsorted->fonts[curf];
        FcPatternReference(curp);
        FcFontSetAdd(fset, curp);
    }

    for (curf = 0; curf < fset->nfont; ++curf) {
        FcPattern *curp = fset->fonts[curf];

        result = FcPatternGetBool(curp, FC_OUTLINE, 0, &r_outline);
        if (result != FcResultMatch)
            continue;
        if (r_outline != FcTrue)
            continue;
        if (!code)
            break;
        result = FcPatternGetCharSet(curp, FC_CHARSET, 0, &r_charset);
        if (result != FcResultMatch)
            continue;
        if (FcCharSetHasChar(r_charset, code))
            break;
    }

    if (curf >= fset->nfont)
        goto error;

    if (!treat_family_as_pattern) {
        // Remove all extra family names from original pattern.
        // After this, FcFontRenderPrepare will select the most relevant family
        // name in case there are more than one of them.
        for (; family_cnt > 1; --family_cnt)
            FcPatternRemove(pat, FC_FAMILY, family_cnt - 1);
    }

    rpat = FcFontRenderPrepare(priv->config, pat, fset->fonts[curf]);
    if (!rpat)
        goto error;

    result = FcPatternGetInteger(rpat, FC_INDEX, 0, &r_index);
    if (result != FcResultMatch)
        goto error;
    *index = r_index;

    result = FcPatternGetString(rpat, FC_FILE, 0, &r_file);
    if (result != FcResultMatch)
        goto error;
    retval = strdup((const char *) r_file);

    result = FcPatternGetString(rpat, FC_FAMILY, 0, &r_family);
    if (result != FcResultMatch)
        r_family = NULL;

    result = FcPatternGetString(rpat, FC_FULLNAME, 0, &r_fullname);
    if (result != FcResultMatch)
        r_fullname = NULL;

    if (!treat_family_as_pattern &&
        !(r_family && strcasecmp((const char *) r_family, family) == 0) &&
        !(r_fullname && strcasecmp((const char *) r_fullname, family) == 0)) {
        char *fallback = (char *) (r_fullname ? r_fullname : r_family);
        if (code) {
            ass_msg(library, MSGL_WARN,
                    "fontconfig: cannot find glyph U+%04X in font '%s', falling back to '%s'",
                    (unsigned int)code, family, fallback);
        } else {
            ass_msg(library, MSGL_WARN,
                    "fontconfig: cannot find font '%s', falling back to '%s'",
                    family, fallback);
        }
    }

    result = FcPatternGetString(rpat, FC_STYLE, 0, &r_style);
    if (result != FcResultMatch)
        r_style = NULL;

    result = FcPatternGetInteger(rpat, FC_SLANT, 0, &r_slant);
    if (result != FcResultMatch)
        r_slant = 0;

    result = FcPatternGetInteger(rpat, FC_WEIGHT, 0, &r_weight);
    if (result != FcResultMatch)
        r_weight = 0;

    result = FcPatternGetBool(rpat, FC_EMBOLDEN, 0, &r_embolden);
    if (result != FcResultMatch)
        r_embolden = 0;

    ass_msg(library, MSGL_V,
           "Font info: family '%s', style '%s', fullname '%s',"
           " slant %d, weight %d%s", (const char *) r_family,
           (const char *) r_style, (const char *) r_fullname, r_slant,
           r_weight, r_embolden ? ", embolden" : "");

  error:
    if (pat)
        FcPatternDestroy(pat);
    if (rpat)
        FcPatternDestroy(rpat);
    if (fsorted)
        FcFontSetDestroy(fsorted);
    if (ffullname)
        FcFontSetDestroy(ffullname);
    if (fset)
        FcFontSetDestroy(fset);
    return retval;
}
Пример #13
0
FcFontSet *fcinfo_families_index(const FcPattern *filter)
{
  int unused_int, f, nfamilies;

  FcPattern *pattern, *match;
  FcFontSet *fontset, *tmp, 
            *families;
  FcResult r;

  FcChar8 *family, *next_family, *normal_style, *style;

  FcInit();
  pattern = FcPatternDuplicate(filter);
  fontset = fcinfo(NULL, filter, FcFalse, 5,
                   FC_FAMILY,
                   FC_STYLE,
                   FC_LANG,/* fonts like Misc Fixed need 
                              to be sorted by LANG (subset-like) */
                   FC_PIXEL_SIZE,
                   FC_FILE); /* for identifying the best font in 
                                FC_LANG terms */
  if (fontset->nfont == 0)
    return fontset;

  tmp = fcinfo_match(fontset, pattern);
  FcFontSetDestroy(fontset);
  fontset = tmp;

  if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &unused_int) != FcResultMatch)
    FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR);
  if (FcPatternGetInteger(pattern, FC_SLANT, 0, &unused_int) != FcResultMatch)
    FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN);
  if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &unused_int) != FcResultMatch)
    FcPatternAddInteger(pattern, FC_WIDTH, FC_WIDTH_NORMAL);

  /* choose 'normal' styles according to pattern */
  families = FcFontSetCreate();
  nfamilies = 0;
  for (f = 0; f < fontset->nfont; )
  {
    assert(fcinfo_get_translated_string(fontset->fonts[f], FC_FAMILY, 
                                        LANG_EN, &family)
           == FcResultMatch);

    FcPatternDel(pattern, FC_FAMILY);
    FcPatternAddString(pattern, FC_FAMILY, family);
    match = FcFontSetMatch(NULL, &fontset, 1, pattern, &r);
    assert(fcinfo_get_translated_string(match, FC_STYLE, LANG_EN, &normal_style)
            == FcResultMatch);
    do
    {
      assert(fcinfo_get_translated_string(fontset->fonts[f], FC_STYLE, 
                                          LANG_EN, &style)
             == FcResultMatch);
      
      if (FcStrCmpIgnoreCase(style, normal_style) == 0)
        FcFontSetAdd(families, FcPatternDuplicate(fontset->fonts[f]));

      if (++f == fontset->nfont)
        break;

      assert(fcinfo_get_translated_string(fontset->fonts[f], FC_FAMILY, 
                                          LANG_EN, &next_family)
             == FcResultMatch);
    }
    while (FcStrCmpIgnoreCase(family, next_family) == 0);
    nfamilies++;
  }

  FcPatternDestroy(pattern);
  FcFontSetDestroy(fontset);

  return families;
}
Пример #14
0
FcFontSet * fcinfo_match(FcFontSet *fontset, const FcPattern *filter)
{
  int f;

  FcFontSet *result;

  FcChar8 *family, *style, *file;
  FcChar8 *next_family, *next_style;

  double size;

  FcBool scalable;
  FcPattern *pat, *match = NULL;
  FcResult r;

  FcInit();

  if (fontset->nfont == 0)
  {
    result = FcFontSetCreate();
    return result;
  }

  /* fc-match "Misc Fixed:style=Bold" gives many files with 
     various pixelsizes plus two "encodings" ('general' and 
     'ISO8859-1', ISO8859-1 is subset of general) 

     we want only one card for family,style pair

     for MiscFixedBold.html we will take informations from
     file 9x18B.pcf.gz (biggest size and general encoding)

     from fcinfo(), fontset is sorted a way that pattern
     created from 9x18B.pcf.gz comes first in 
     "Misc Fixed:style=Bold" interval (the biggest pixel size
     and subset of supported languages, see pattern_compare()). */

  result = FcFontSetCreate();
  for (f = 0; f < fontset->nfont; )
  {
    /* bitmap fonts: */
    /* we are here always on the best file in FC_LANG terms */
    /* we need it for displaying the widest range of supported languages */
    /* identify it by FC_FILE for FcFontMatch() */
    if (filter)
      pat = FcPatternDuplicate(filter);
    else
      pat = FcPatternCreate();
    assert(fcinfo_get_translated_string(fontset->fonts[f], FC_FAMILY, 
                                        LANG_EN, &family) == FcResultMatch);
    FcPatternAddString(pat, FC_FAMILY, family);
    if (fcinfo_get_translated_string(fontset->fonts[f], FC_STYLE, 
                                     LANG_EN, &style) == FcResultMatch)
      FcPatternAddString(pat, FC_STYLE, style);
    if (FcPatternGetString(fontset->fonts[f], FC_FILE, 0, &file)
        == FcResultMatch)
      FcPatternAddString(pat, FC_FILE, file);

    FcConfigSubstitute(NULL, pat, FcMatchPattern);
    FcDefaultSubstitute(pat);
    match = FcFontMatch(NULL, pat, &r);
    assert(r == FcResultMatch);
    /* should not be needed: FcConfigSubstitute(NULL, match, FcMatchFont); */
    FcPatternDestroy(pat);

    assert(FcPatternGetBool(match, FC_SCALABLE, 0, &scalable)  
           == FcResultMatch);

/*    fprintf(stdout, "Family: %s Style: %s\n", next_family, next_style);
    fprintf(stdout, "        %s\n", file);*/

    /* figure out sizes font provide (needed for specimen) and skip same */
    /* family,style pairs (see e. g. Misc Fixed) */
    if (! scalable)
    {
      next_family = family;
      next_style  = style;
      /* unfortunately e. g. 'ETL Fixed' and 'ETL fixed' 
         are present on my system */

      while (FcStrCmpIgnoreCase(next_family, family) == 0 &&
             FcStrCmpIgnoreCase(next_style, style) == 0)
      {
        if (FcPatternGetDouble(fontset->fonts[f], FC_PIXEL_SIZE, 0, &size)
                 == FcResultMatch)
        {
          if (! pattern_contains_size(match, size))
          {
            FcPatternAddDouble(match, FC_PIXEL_SIZE, size);
            if (FcPatternGetString(fontset->fonts[f], FC_FILE, 0, &file)
                     == FcResultMatch)
              FcPatternAddString(match, FC_FILE, file);
            /*fprintf(stdout, "       %s\n", file);*/
          }
        }

        if (f + 1 == fontset->nfont)  /* last family,style pair at all */
        {
          f++;
          break;
        }

        assert(fcinfo_get_translated_string(fontset->fonts[f + 1], FC_FAMILY, 
                                            LANG_EN, &next_family)
               == FcResultMatch);
        assert(fcinfo_get_translated_string(fontset->fonts[f + 1], FC_STYLE,
                                            LANG_EN, &next_style)
               == FcResultMatch);
        f++;
      }
    }
    else /* family Efont Serif Regular is spread (unintentionally) over */
    {    /* 5 files (Efont Serif <X> should be spread over 2 files,  */
         /* normal and 'Alternate'), so this is needed anyway: */
      FcPatternDel(match, FC_FILE);
      next_family = family;
      next_style  = style;

      while (FcStrCmpIgnoreCase(next_family, family) == 0 &&
             FcStrCmpIgnoreCase(next_style, style) == 0)
      {
        if (FcPatternGetString(fontset->fonts[f], FC_FILE, 0, &file)
                == FcResultMatch)
          FcPatternAddString(match, FC_FILE, file);

        if (f + 1 == fontset->nfont)  /* last family,style pair at all */
        {
          f++;
          break;
        }

        assert(fcinfo_get_translated_string(fontset->fonts[f + 1], FC_FAMILY, 
                                            LANG_EN, &next_family)
               == FcResultMatch);
        assert(fcinfo_get_translated_string(fontset->fonts[f + 1], FC_STYLE,
                                            LANG_EN, &next_style)
               == FcResultMatch);

        f++;
      }
    }

    /* don't add ethio16f-uni.pcf, johabg16.pcf and similar with reported 
       empty charset */
    if (! empty_charset(match))
      FcFontSetAdd(result, FcPatternDuplicate(match));
  }

  if (match)
    FcPatternDestroy(match);
  return result;
}
Пример #15
0
/* ========================================================================================
 * FontConfig (unix) support
 * ======================================================================================== */
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
{
	FT_Error err = FT_Err_Cannot_Open_Resource;

	if (!FcInit()) {
		ShowInfoF("Unable to load font configuration");
	} else {
		FcPattern *match;
		FcPattern *pat;
		FcFontSet *fs;
		FcResult  result;
		char *font_style;
		char *font_family;

		/* Split & strip the font's style */
		font_family = stredup(font_name);
		font_style = strchr(font_family, ',');
		if (font_style != NULL) {
			font_style[0] = '\0';
			font_style++;
			while (*font_style == ' ' || *font_style == '\t') font_style++;
		}

		/* Resolve the name and populate the information structure */
		pat = FcNameParse((FcChar8*)font_family);
		if (font_style != NULL) FcPatternAddString(pat, FC_STYLE, (FcChar8*)font_style);
		FcConfigSubstitute(0, pat, FcMatchPattern);
		FcDefaultSubstitute(pat);
		fs = FcFontSetCreate();
		match = FcFontMatch(0, pat, &result);

		if (fs != NULL && match != NULL) {
			int i;
			FcChar8 *family;
			FcChar8 *style;
			FcChar8 *file;
			FcFontSetAdd(fs, match);

			for (i = 0; err != FT_Err_Ok && i < fs->nfont; i++) {
				/* Try the new filename */
				if (FcPatternGetString(fs->fonts[i], FC_FILE,   0, &file)   == FcResultMatch &&
						FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch &&
						FcPatternGetString(fs->fonts[i], FC_STYLE,  0, &style)  == FcResultMatch) {

					/* The correct style? */
					if (font_style != NULL && strcasecmp(font_style, (char*)style) != 0) continue;

					/* Font config takes the best shot, which, if the family name is spelled
					 * wrongly a 'random' font, so check whether the family name is the
					 * same as the supplied name */
					if (strcasecmp(font_family, (char*)family) == 0) {
						err = FT_New_Face(_library, (char *)file, 0, face);
					}
				}
			}
		}

		free(font_family);
		FcPatternDestroy(pat);
		FcFontSetDestroy(fs);
		FcFini();
	}

	return err;
}
Пример #16
0
/**
 * \brief Init fontconfig.
 * \param library libass library object
 * \param ftlibrary freetype library object
 * \param family default font family
 * \param path default font path
 * \return pointer to fontconfig private data
*/ 
fc_instance_t* fontconfig_init(ass_library_t* library, FT_Library ftlibrary, const char* family, const char* path)
{
	int rc;
	fc_instance_t* priv = calloc(1, sizeof(fc_instance_t));
	const char* dir = library->fonts_dir;
	int i;
	
	rc = FcInit();
	assert(rc);

	priv->config = FcConfigGetCurrent();
	if (!priv->config) {
		mp_msg(MSGT_ASS, MSGL_FATAL, MSGTR_LIBASS_FcInitLoadConfigAndFontsFailed);
		return 0;
	}

	for (i = 0; i < library->num_fontdata; ++i)
		process_fontdata(priv, library, ftlibrary, i);

	if (FcDirCacheValid((const FcChar8 *)dir) == FcFalse)
	{
		mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_UpdatingFontCache);
		if (FcGetVersion() >= 20390 && FcGetVersion() < 20400)
			mp_msg(MSGT_ASS, MSGL_WARN,
			       MSGTR_LIBASS_BetaVersionsOfFontconfigAreNotSupported);
		// FontConfig >= 2.4.0 updates cache automatically in FcConfigAppFontAddDir()
		if (FcGetVersion() < 20390) {
			FcFontSet* fcs;
			FcStrSet* fss;
			fcs = FcFontSetCreate();
			fss = FcStrSetCreate();
			rc = FcStrSetAdd(fss, (const FcChar8*)dir);
			if (!rc) {
				mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FcStrSetAddFailed);
				goto ErrorFontCache;
			}

			rc = FcDirScan(fcs, fss, NULL, FcConfigGetBlanks(priv->config), (const FcChar8 *)dir, FcFalse);
			if (!rc) {
				mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FcDirScanFailed);
				goto ErrorFontCache;
			}

			rc = FcDirSave(fcs, fss, (const FcChar8 *)dir);
			if (!rc) {
				mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FcDirSave);
				goto ErrorFontCache;
			}
		ErrorFontCache:
			;
		}
	}

	rc = FcConfigAppFontAddDir(priv->config, (const FcChar8*)dir);
	if (!rc) {
		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FcConfigAppFontAddDirFailed);
	}

	priv->family_default = family ? strdup(family) : 0;
	priv->path_default = path ? strdup(path) : 0;
	priv->index_default = 0;

	return priv;
}
Пример #17
0
/*
 * Scan the specified directory and construct a cache of its contents
 */
FcCache *
FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
{
    FcStrSet		*dirs;
    FcBool		ret = FcTrue;
    FcFontSet		*set;
    FcCache		*cache = NULL;
    struct stat		dir_stat;

    if (FcDebug () & FC_DBG_FONTSET)
	printf ("cache scan dir %s\n", dir);

    if (FcStatChecksum ((char *) dir, &dir_stat) < 0)
    {
	if (errno != ENOENT)
	    ret = FcFalse;
	goto bail;
    }

    set = FcFontSetCreate();
    if (!set)
    {
	ret = FcFalse;
	goto bail;
    }

    dirs = FcStrSetCreate ();
    if (!dirs)
    {
	ret = FcFalse;
	goto bail1;
    }

    /*
     * Scan the dir
     */
    if (!FcDirScanConfig (set, dirs, NULL, dir, FcTrue, config))
    {
	ret = FcFalse;
	goto bail2;
    }

    /*
     * Build the cache object
     */
    cache = FcDirCacheBuild (set, dir, &dir_stat, dirs);
    if (!cache)
    {
	ret = FcFalse;
	goto bail2;
    }
    
    /*
     * Write out the cache file, ignoring any troubles
     */
    FcDirCacheWrite (cache, config);
    
 bail2:
    FcStrSetDestroy (dirs);
 bail1:
    FcFontSetDestroy (set);
 bail:
    return cache;
}
Пример #18
0
FcFontSet *
FcFontSetList (FcConfig	    *config,
	       FcFontSet    **sets,
	       int	    nsets,
	       FcPattern    *p,
	       FcObjectSet  *os)
{
    FcFontSet	    *ret;
    FcFontSet	    *s;
    int		    f;
    int		    set;
    FcListHashTable table;
    int		    i;
    FcListBucket    *bucket;
    int             destroy_os = 0;

    if (!config)
    {
	if (!FcInitBringUptoDate ())
	    goto bail0;

	config = FcConfigGetCurrent ();
	if (!config)
	    goto bail0;
    }
    FcListHashTableInit (&table);

    if (!os)
    {
	os = FcObjectGetSet ();
	destroy_os = 1;
    }

    /*
     * Walk all available fonts adding those that
     * match to the hash table
     */
    for (set = 0; set < nsets; set++)
    {
	s = sets[set];
	if (!s)
	    continue;
	for (f = 0; f < s->nfont; f++)
	    if (FcListPatternMatchAny (p,		/* pattern */
				       s->fonts[f]))	/* font */
	    {
		FcChar8 *lang;

		if (FcPatternObjectGetString (p, FC_NAMELANG_OBJECT, 0, &lang) != FcResultMatch)
		{
			lang = FcGetDefaultLang ();
		}
		if (!FcListAppend (&table, s->fonts[f], os, lang))
		    goto bail1;
	    }
    }
#if 0
    {
	int	max = 0;
	int	full = 0;
	int	ents = 0;
	int	len;
	for (i = 0; i < FC_LIST_HASH_SIZE; i++)
	{
	    if ((bucket = table.buckets[i]))
	    {
		len = 0;
		for (; bucket; bucket = bucket->next)
		{
		    ents++;
		    len++;
		}
		if (len > max)
		    max = len;
		full++;
	    }
	}
	printf ("used: %d max: %d avg: %g\n", full, max,
		(double) ents / FC_LIST_HASH_SIZE);
    }
#endif
    /*
     * Walk the hash table and build
     * a font set
     */
    ret = FcFontSetCreate ();
    if (!ret)
	goto bail0;
    for (i = 0; i < FC_LIST_HASH_SIZE; i++)
	while ((bucket = table.buckets[i]))
	{
	    if (!FcFontSetAdd (ret, bucket->pattern))
		goto bail2;
	    table.buckets[i] = bucket->next;
	    FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
	    free (bucket);
	}

    return ret;

bail2:
    FcFontSetDestroy (ret);
bail1:
    FcListHashTableCleanup (&table);
bail0:
    if (destroy_os)
	FcObjectSetDestroy (os);
    return 0;
}
Пример #19
0
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, const char *str)
{
	if (!FcInit()) return false;

	bool ret = false;

	/* Fontconfig doesn't handle full language isocodes, only the part
	 * before the _ of e.g. en_GB is used, so "remove" everything after
	 * the _. */
	char lang[16];
	strecpy(lang, language_isocode, lastof(lang));
	char *split = strchr(lang, '_');
	if (split != NULL) *split = '\0';

	FcPattern *pat;
	FcPattern *match;
	FcResult result;
	FcChar8 *file;
	FcFontSet *fs;
	FcValue val;
	val.type = FcTypeString;
	val.u.s = (FcChar8*)lang;

	/* First create a pattern to match the wanted language */
	pat = FcPatternCreate();
	/* And fill it with the language and other defaults */
	if (pat == NULL ||
			!FcPatternAdd(pat, "lang", val, false) ||
			!FcConfigSubstitute(0, pat, FcMatchPattern)) {
		goto error_pattern;
	}

	FcDefaultSubstitute(pat);

	/* Then create a font set and match that */
	match = FcFontMatch(0, pat, &result);

	if (match == NULL) {
		goto error_pattern;
	}

	/* Find all fonts that do match */
	fs = FcFontSetCreate();
	FcFontSetAdd(fs, match);

	/* And take the first, if it exists */
	if (fs->nfont <= 0 || FcPatternGetString(fs->fonts[0], FC_FILE, 0, &file)) {
		goto error_fontset;
	}

	strecpy(settings->small_font,  (const char*)file, lastof(settings->small_font));
	strecpy(settings->medium_font, (const char*)file, lastof(settings->medium_font));
	strecpy(settings->large_font,  (const char*)file, lastof(settings->large_font));

	ret = true;

error_fontset:
	FcFontSetDestroy(fs);
error_pattern:
	if (pat != NULL) FcPatternDestroy(pat);
	FcFini();
	return ret;
}
Пример #20
0
FcConfig *
FcConfigCreate (void)
{
    FcSetName	set;
    FcConfig	*config;

    config = malloc (sizeof (FcConfig));
    if (!config)
	goto bail0;

    config->configDirs = FcStrSetCreate ();
    if (!config->configDirs)
	goto bail1;

    config->configFiles = FcStrSetCreate ();
    if (!config->configFiles)
	goto bail2;

    config->fontDirs = FcStrSetCreate ();
    if (!config->fontDirs)
	goto bail3;

    config->acceptGlobs = FcStrSetCreate ();
    if (!config->acceptGlobs)
	goto bail4;

    config->rejectGlobs = FcStrSetCreate ();
    if (!config->rejectGlobs)
	goto bail5;

    config->acceptPatterns = FcFontSetCreate ();
    if (!config->acceptPatterns)
	goto bail6;

    config->rejectPatterns = FcFontSetCreate ();
    if (!config->rejectPatterns)
	goto bail7;

    config->cacheDirs = FcStrSetCreate ();
    if (!config->cacheDirs)
	goto bail8;

    config->blanks = 0;

    config->substPattern = 0;
    config->substFont = 0;
    config->substScan = 0;
    config->maxObjects = 0;
    for (set = FcSetSystem; set <= FcSetApplication; set++)
	config->fonts[set] = 0;

    config->rescanTime = time(0);
    config->rescanInterval = 30;

    config->expr_pool = NULL;

    config->sysRoot = NULL;

    FcRefInit (&config->ref, 1);

    return config;

bail8:
    FcFontSetDestroy (config->rejectPatterns);
bail7:
    FcFontSetDestroy (config->acceptPatterns);
bail6:
    FcStrSetDestroy (config->rejectGlobs);
bail5:
    FcStrSetDestroy (config->acceptGlobs);
bail4:
    FcStrSetDestroy (config->fontDirs);
bail3:
    FcStrSetDestroy (config->configFiles);
bail2:
    FcStrSetDestroy (config->configDirs);
bail1:
    free (config);
bail0:
    return 0;
}
int
main (int argc, char **argv)
{
    int			verbose = 0;
    int			sort = 0, all = 0;
    const FcChar8	*format = NULL;
    int			i;
    FcObjectSet		*os = 0;
    FcFontSet		*fs;
    FcPattern		*pat;
    FcResult		result;
#if HAVE_GETOPT_LONG || HAVE_GETOPT
    int			c;

#if HAVE_GETOPT_LONG
    while ((c = getopt_long (argc, argv, "asvf:Vh", longopts, NULL)) != -1)
#else
    while ((c = getopt (argc, argv, "asvf:Vh")) != -1)
#endif
    {
	switch (c) {
	case 'a':
	    all = 1;
	    break;
	case 's':
	    sort = 1;
	    break;
	case 'v':
	    verbose = 1;
	    break;
	case 'f':
	    format = (FcChar8 *) strdup (optarg);
	    break;
	case 'V':
	    fprintf (stderr, "fontconfig version %d.%d.%d\n", 
		     FC_MAJOR, FC_MINOR, FC_REVISION);
	    exit (0);
	case 'h':
	    usage (argv[0], 0);
	default:
	    usage (argv[0], 1);
	}
    }
    i = optind;
#else
    i = 1;
#endif

    if (!FcInit ())
    {
	fprintf (stderr, "Can't init font config library\n");
	return 1;
    }
    if (argv[i])
    {
	pat = FcNameParse ((FcChar8 *) argv[i]);
	while (argv[++i])
	{
	    if (!os)
		os = FcObjectSetCreate ();
	    FcObjectSetAdd (os, argv[i]);
	}
    }
    else
	pat = FcPatternCreate ();

    if (!pat)
	return 1;

    FcConfigSubstitute (0, pat, FcMatchPattern);
    FcDefaultSubstitute (pat);
    
    fs = FcFontSetCreate ();

    if (sort || all)
    {
	FcFontSet	*font_patterns;
	int	j;
	font_patterns = FcFontSort (0, pat, all ? FcFalse : FcTrue, 0, &result);

	if (!font_patterns || font_patterns->nfont == 0)
	{
	    fputs("No fonts installed on the system\n", stderr);
	    return 1;
	}
	for (j = 0; j < font_patterns->nfont; j++)
	{
	    FcPattern  *font_pattern;

	    font_pattern = FcFontRenderPrepare (NULL, pat, font_patterns->fonts[j]);
	    if (font_pattern)
		FcFontSetAdd (fs, font_pattern);
	}

	FcFontSetSortDestroy (font_patterns);
    }
    else
    {
	FcPattern   *match;
	match = FcFontMatch (0, pat, &result);
	if (match)
	    FcFontSetAdd (fs, match);
    }
    FcPatternDestroy (pat);

    if (!format)
    {
	if (os)
	    format = (const FcChar8 *) "%{=unparse}\n";
	else
	    format = (const FcChar8 *) "%{=fcmatch}\n";
    }

    if (fs)
    {
	int	j;

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

	    font = FcPatternFilter (fs->fonts[j], os);

	    if (verbose)
	    {
		FcPatternPrint (font);
	    }
	    else
	    {
	        FcChar8 *s;

		s = FcPatternFormat (font, format);
		if (s)
		{
		    printf ("%s", s);
		    free (s);
		}
	    }

	    FcPatternDestroy (font);
	}
	FcFontSetDestroy (fs);
    }

    if (os)
	FcObjectSetDestroy (os);

    FcFini ();

    return 0;
}
Пример #22
0
int
main (int argc, char **argv)
{
    int         brief = 0;
    FcChar8     *format = NULL;
    int		i;
    FcFontSet   *fs;
#if HAVE_GETOPT_LONG || HAVE_GETOPT
    int		c;

    setlocale (LC_ALL, "");
#if HAVE_GETOPT_LONG
    while ((c = getopt_long (argc, argv, "bf:Vh", longopts, NULL)) != -1)
#else
    while ((c = getopt (argc, argv, "bf:Vh")) != -1)
#endif
    {
	switch (c) {
	case 'b':
	    brief = 1;
	    break;
	case 'f':
	    format = (FcChar8 *) strdup (optarg);
	    break;
	case 'V':
	    fprintf (stderr, "fontconfig version %d.%d.%d\n",
		     FC_MAJOR, FC_MINOR, FC_REVISION);
	    exit (0);
	case 'h':
	    usage (argv[0], 0);
	default:
	    usage (argv[0], 1);
	}
    }
    i = optind;
#else
    i = 1;
#endif

    if (i == argc)
	usage (argv[0], 1);

    fs = FcFontSetCreate ();

    for (; i < argc; i++)
    {
	const FcChar8 *file = (FcChar8*) argv[i];

	if (!FcFileIsDir (file))
	    FcFileScan (fs, NULL, NULL, NULL, file, FcTrue);
	else
	{
	    FcStrSet *dirs = FcStrSetCreate ();
	    FcStrList *strlist = FcStrListCreate (dirs);
	    do
	    {
		FcDirScan (fs, dirs, NULL, NULL, file, FcTrue);
	    }
	    while ((file = FcStrListNext (strlist)));
	    FcStrListDone (strlist);
	    FcStrSetDestroy (dirs);
	}
    }

    for (i = 0; i < fs->nfont; i++)
    {
	FcPattern *pat = fs->fonts[i];

	if (brief)
	{
	    FcPatternDel (pat, FC_CHARSET);
	    FcPatternDel (pat, FC_LANG);
	}

	if (format)
	{
	    FcChar8 *s;

	    s = FcPatternFormat (pat, format);
	    if (s)
	    {
		printf ("%s", s);
		FcStrFree (s);
	    }
	}
	else
	{
	    FcPatternPrint (pat);
	}
    }

    FcFontSetDestroy (fs);

    FcFini ();
    return i > 0 ? 0 : 1;
}
Пример #23
0
int
main (int argc, char **argv)
{
    int		verbose = 0;
    int		sort = 0;
    int		i;
    FcFontSet	*fs;
    FcPattern   *pat;
    FcResult	result;
#if HAVE_GETOPT_LONG || HAVE_GETOPT
    int		c;

#if HAVE_GETOPT_LONG
    while ((c = getopt_long (argc, argv, "Vv?", longopts, NULL)) != -1)
#else
    while ((c = getopt (argc, argv, "sVv?")) != -1)
#endif
    {
	switch (c) {
	case 's':
	    sort = 1;
	    break;
	case 'V':
	    fprintf (stderr, "fontconfig version %d.%d.%d\n", 
		     FC_MAJOR, FC_MINOR, FC_REVISION);
	    exit (0);
	case 'v':
	    verbose = 1;
	    break;
	default:
	    usage (argv[0]);
	}
    }
    i = optind;
#else
    i = 1;
#endif

    if (!FcInit ())
    {
	fprintf (stderr, "Can't init font config library\n");
	return 1;
    }
    if (argv[i])
	pat = FcNameParse ((FcChar8 *) argv[i]);
    else
	pat = FcPatternCreate ();

    FcConfigSubstitute (0, pat, FcMatchPattern);
    FcDefaultSubstitute (pat);
    
    if (sort)
	fs = FcFontSort (0, pat, FcTrue, 0, &result);
    else
    {
	FcPattern   *match;
	fs = FcFontSetCreate ();
	match = FcFontMatch (0, pat, &result);
	if (match)
	    FcFontSetAdd (fs, match);
    }
    if (pat)
	FcPatternDestroy (pat);

    if (fs)
    {
	int	j;

	for (j = 0; j < fs->nfont; j++)
	{
	    if (verbose)
	    {
		FcPatternPrint (fs->fonts[j]);
	    }
	    else
	    {
		FcChar8	*family;
		FcChar8	*style;
		FcChar8	*file;

		if (FcPatternGetString (fs->fonts[j], FC_FILE, 0, &file) != FcResultMatch)
		    file = "<unknown filename>";
		else
		{
		    FcChar8 *slash = strrchr (file, '/');
		    if (slash)
			file = slash+1;
		}
		if (FcPatternGetString (fs->fonts[j], FC_FAMILY, 0, &family) != FcResultMatch)
		    family = "<unknown family>";
		if (FcPatternGetString (fs->fonts[j], FC_STYLE, 0, &style) != FcResultMatch)
		    file = "<unknown style>";

		printf ("%s: \"%s\" \"%s\"\n", file, family, style);
	    }
	}
	FcFontSetDestroy (fs);
    }
    return 0;
}