Пример #1
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;
}
Пример #2
0
FcBool
FcConfigAddCache (FcConfig *config, FcCache *cache,
		  FcSetName set, FcStrSet *dirSet)
{
    FcFontSet	*fs;
    intptr_t	*dirs;
    int		i;

    /*
     * Add fonts
     */
    fs = FcCacheSet (cache);
    if (fs)
    {
	int	nref = 0;
	
	for (i = 0; i < fs->nfont; i++)
	{
	    FcPattern	*font = FcFontSetFont (fs, i);
	    FcChar8	*font_file;

	    /*
	     * Check to see if font is banned by filename
	     */
	    if (FcPatternObjectGetString (font, FC_FILE_OBJECT,
					  0, &font_file) == FcResultMatch &&
		!FcConfigAcceptFilename (config, font_file))
	    {
		continue;
	    }
		
	    /*
	     * Check to see if font is banned by pattern
	     */
	    if (!FcConfigAcceptFont (config, font))
		continue;
		
	    if (FcFontSetAdd (config->fonts[set], font))
		nref++;
	}
	FcDirCacheReference (cache, nref);
    }

    /*
     * Add directories
     */
    dirs = FcCacheDirs (cache);
    if (dirs)
    {
	for (i = 0; i < cache->dirs_count; i++)
	{
	    FcChar8	*dir = FcOffsetToPtr (dirs, dirs[i], FcChar8);
	    if (FcConfigAcceptFilename (config, dir))
		FcStrSetAddFilename (dirSet, dir);
	}
    }
    return FcTrue;
}
Пример #3
0
/**
 * \brief Process memory font.
 * \param priv private data
 * \param library library object
 * \param ftlibrary freetype library object
 * \param idx index of the processed font in library->fontdata
 *
 * Builds a font pattern in memory via FT_New_Memory_Face/FcFreeTypeQueryFace.
*/
static void process_fontdata(FCInstance *priv, ASS_Library *library,
                             FT_Library ftlibrary, int idx)
{
    int rc;
    const char *name = library->fontdata[idx].name;
    const char *data = library->fontdata[idx].data;
    int data_size = library->fontdata[idx].size;

    FT_Face face;
    FcPattern *pattern;
    FcFontSet *fset;
    FcBool res;
    int face_index, num_faces = 1;

    for (face_index = 0; face_index < num_faces; ++face_index) {
        ass_msg(library, MSGL_V, "Adding memory font '%s'", name);

        rc = FT_New_Memory_Face(ftlibrary, (unsigned char *) data,
                                data_size, face_index, &face);
        if (rc) {
            ass_msg(library, MSGL_WARN, "Error opening memory font: %s",
                   name);
            return;
        }
        num_faces = face->num_faces;

        pattern =
            FcFreeTypeQueryFace(face, (unsigned char *) name, face_index,
                                FcConfigGetBlanks(priv->config));
        if (!pattern) {
            ass_msg(library, MSGL_WARN, "%s failed", "FcFreeTypeQueryFace");
            FT_Done_Face(face);
            return;
        }

        fset = FcConfigGetFonts(priv->config, FcSetSystem);     // somehow it failes when asked for FcSetApplication
        if (!fset) {
            ass_msg(library, MSGL_WARN, "%s failed", "FcConfigGetFonts");
            FT_Done_Face(face);
            return;
        }

        res = FcFontSetAdd(fset, pattern);
        if (!res) {
            ass_msg(library, MSGL_WARN, "%s failed", "FcFontSetAdd");
            FT_Done_Face(face);
            return;
        }

        FT_Done_Face(face);
    }
}
Пример #4
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;
}
Пример #5
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");
	}

}
Пример #6
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;
}
Пример #7
0
nsresult
gfxQtPlatform::ResolveFontName(const nsAString& aFontName,
                                FontResolverCallback aCallback,
                                void *aClosure,
                                PRBool& aAborted)
{

    nsAutoString name(aFontName);
    ToLowerCase(name);

    nsRefPtr<FontFamily> ff;
    if (gPlatformFonts->Get(name, &ff) ||
        gPlatformFontAliases->Get(name, &ff)) {
        aAborted = !(*aCallback)(ff->Name(), aClosure);
        return NS_OK;
    }

    nsCAutoString utf8Name = NS_ConvertUTF16toUTF8(aFontName);

    FcPattern *npat = FcPatternCreate();
    FcPatternAddString(npat, FC_FAMILY, (FcChar8*)utf8Name.get());
    FcObjectSet *nos = FcObjectSetBuild(FC_FAMILY, NULL);
    FcFontSet *nfs = FcFontList(NULL, npat, nos);

    for (int k = 0; k < nfs->nfont; k++) {
        FcChar8 *str;
        if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
            continue;
        nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
        ToLowerCase(altName);
        if (gPlatformFonts->Get(altName, &ff)) {
            printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
            gPlatformFontAliases->Put(name, ff);
            aAborted = !(*aCallback)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str))), aClosure);
            goto DONE;
        }
    }

    FcPatternDestroy(npat);
    FcObjectSetDestroy(nos);
    FcFontSetDestroy(nfs);

    {
    npat = FcPatternCreate();
    FcPatternAddString(npat, FC_FAMILY, (FcChar8*)utf8Name.get());
    FcPatternDel(npat, FC_LANG);
    FcConfigSubstitute(NULL, npat, FcMatchPattern);
    FcDefaultSubstitute(npat);

    nos = FcObjectSetBuild(FC_FAMILY, NULL);
    nfs = FcFontList(NULL, npat, nos);

    FcResult fresult;

    FcPattern *match = FcFontMatch(NULL, npat, &fresult);
    if (match)
        FcFontSetAdd(nfs, match);

    for (int k = 0; k < nfs->nfont; k++) {
        FcChar8 *str;
        if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
            continue;
        nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
        ToLowerCase(altName);
        if (gPlatformFonts->Get(altName, &ff)) {
            printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
            gPlatformFontAliases->Put(name, ff);
            aAborted = !(*aCallback)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str))), aClosure);
            goto DONE;
        }
    }
    }
 DONE:
    FcPatternDestroy(npat);
    FcObjectSetDestroy(nos);
    FcFontSetDestroy(nfs);

    return NS_OK;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
0
/**
 * \brief Process memory font.
 * \param priv private data
 * \param library library object
 * \param ftlibrary freetype library object
 * \param idx index of the processed font in library->fontdata
 * With FontConfig >= 2.4.2, builds a font pattern in memory via FT_New_Memory_Face/FcFreeTypeQueryFace.
 * With older FontConfig versions, save the font to ~/.mplayer/fonts.
*/ 
static void process_fontdata(fc_instance_t* priv, ass_library_t* library, FT_Library ftlibrary, int idx)
{
	int rc;
	const char* name = library->fontdata[idx].name;
	const char* data = library->fontdata[idx].data;
	int data_size = library->fontdata[idx].size;

#if (FC_VERSION < 20402)
	struct stat st;
	char* fname;
	const char* fonts_dir = library->fonts_dir;
	char buf[1000];
	FILE* fp = 0;

	if (!fonts_dir)
		return;
	rc = stat(fonts_dir, &st);
	if (rc) {
		int res;
#ifndef __MINGW32__
		res = mkdir(fonts_dir, 0700);
#else
		res = mkdir(fonts_dir);
#endif
		if (res) {
			mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FailedToCreateDirectory, fonts_dir);
		}
	} else if (!S_ISDIR(st.st_mode)) {
		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NotADirectory, fonts_dir);
	}
	
	fname = validate_fname((char*)name);

	snprintf(buf, 1000, "%s/%s", fonts_dir, fname);
	free(fname);

	fp = fopen(buf, "wb");
	if (!fp) return;

	fwrite(data, data_size, 1, fp);
	fclose(fp);

#else // (FC_VERSION >= 20402)
	FT_Face face;
	FcPattern* pattern;
	FcFontSet* fset;
	FcBool res;

	rc = FT_New_Memory_Face(ftlibrary, (unsigned char*)data, data_size, 0, &face);
	if (rc) {
		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningMemoryFont, name);
		return;
	}

	pattern = FcFreeTypeQueryFace(face, (unsigned char*)name, 0, FcConfigGetBlanks(priv->config));
	if (!pattern) {
		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FunctionCallFailed, "FcFreeTypeQueryFace");
		FT_Done_Face(face);
		return;
	}

	fset = FcConfigGetFonts(priv->config, FcSetSystem); // somehow it failes when asked for FcSetApplication
	if (!fset) {
		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FunctionCallFailed, "FcConfigGetFonts");
		FT_Done_Face(face);
		return;
	}

	res = FcFontSetAdd(fset, pattern);
	if (!res) {
		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FunctionCallFailed, "FcFontSetAdd");
		FT_Done_Face(face);
		return;
	}

	FT_Done_Face(face);
#endif
}
Пример #11
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;
}
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;
}
Пример #13
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;
}
Пример #14
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;
}
Пример #15
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;
}
Пример #16
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;
}