Esempio n. 1
0
// Thanks to http://stackoverflow.com/a/14634033/1447751
const std::string get_font_path(const std::string &name) {
	std::string path;
	const FcChar8 *fcname = reinterpret_cast<const FcChar8 *>(name.c_str());
	FcConfig *config      = FcInitLoadConfigAndFonts();

	// configure the search pattern,
	// assume "name" is a std::string with the desired font name in it
	FcPattern *pat = FcNameParse(fcname);
	FcConfigSubstitute(config, pat, FcMatchPattern);
	FcDefaultSubstitute(pat);

	FcResult result;
	// find the font
	FcPattern *font = FcFontMatch(config, pat, &result);
	if (font) {
		FcChar8 *fcpath   = NULL;
		FcChar8 *fcfamily = NULL;
		if (FcPatternGetString(font, FC_FAMILY, 0, &fcfamily) == FcResultMatch &&
		    (name.empty() || !FcStrCmpIgnoreCase(fcname, fcfamily)) // Empty name means searching for default font, otherwise make
		                                                            // sure the returned font is exactly what we searched for
		    &&
		    FcPatternGetString(font, FC_FILE, 0, &fcpath) == FcResultMatch)
			path = std::string(reinterpret_cast<char *>(fcpath));
		FcPatternDestroy(font);
	}

	FcPatternDestroy(pat);
	return path;
}
Esempio n. 2
0
static double
FcCompareString (char *object, FcValue value1, FcValue value2)
{
    if (value2.type != FcTypeString || value1.type != FcTypeString)
	return -1.0;
    return (double) FcStrCmpIgnoreCase (value1.u.s, value2.u.s) != 0;
}
Esempio n. 3
0
const FcConstant *
FcNameGetConstant (const FcChar8 *string)
{
    unsigned int	    i;

    for (i = 0; i < NUM_FC_CONSTANTS; i++)
	if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name))
	    return &_FcBaseConstants[i];

    return 0;
}
Esempio n. 4
0
const FcConstant *
FcNameGetConstant (FcChar8 *string)
{
    const FcConstantList    *l;
    int			    i;
    
    for (l = _FcConstants; l; l = l->next)
    {
	for (i = 0; i < l->nconsts; i++)
	    if (!FcStrCmpIgnoreCase (string, l->consts[i].name))
		return &l->consts[i];
    }
    return 0;
}
Esempio n. 5
0
static double
FcCompareFilename (FcValue *v1, FcValue *v2)
{
	const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
	if (FcStrCmp (s1, s2) == 0)
	    return 0.0;
	else if (FcStrCmpIgnoreCase (s1, s2) == 0)
	    return 1.0;
	else if (FcStrRegexCmp (s2, s1))
	    return 2.0;
	else if (FcStrRegexCmpIgnoreCase (s2, s1))
	    return 3.0;
	else
	    return 4.0;
}
Esempio n. 6
0
FcBool
FcConfigCompareValue (const FcValue	*left_o,
		      FcOp		op,
		      const FcValue	*right_o)
{
    FcValue	left = FcValueCanonicalize(left_o);
    FcValue	right = FcValueCanonicalize(right_o);
    FcBool	ret = FcFalse;
    
    left = FcConfigPromote (left, right);
    right = FcConfigPromote (right, left);
    if (left.type == right.type) 
    {
	switch (left.type) {
	case FcTypeInteger:
	    break;	/* FcConfigPromote prevents this from happening */
	case FcTypeDouble:
	    switch (op) {
	    case FcOpEqual:
	    case FcOpContains:
	    case FcOpListing:
		ret = left.u.d == right.u.d;
		break;
	    case FcOpNotEqual:
	    case FcOpNotContains:
		ret = left.u.d != right.u.d;
		break;
	    case FcOpLess:    
		ret = left.u.d < right.u.d;
		break;
	    case FcOpLessEqual:    
		ret = left.u.d <= right.u.d;
		break;
	    case FcOpMore:    
		ret = left.u.d > right.u.d;
		break;
	    case FcOpMoreEqual:    
		ret = left.u.d >= right.u.d;
		break;
	    default:
		break;
	    }
	    break;
	case FcTypeBool:
	    switch (op) {
	    case FcOpEqual:    
	    case FcOpContains:
	    case FcOpListing:
		ret = left.u.b == right.u.b;
		break;
	    case FcOpNotEqual:
	    case FcOpNotContains:
		ret = left.u.b != right.u.b;
		break;
	    default:
		break;
	    }
	    break;
	case FcTypeString:
	    switch (op) {
	    case FcOpEqual:    
	    case FcOpListing:
		ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
		break;
	    case FcOpContains:
		ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
		break;
	    case FcOpNotEqual:
		ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
		break;
	    case FcOpNotContains:
		ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0;
		break;
	    default:
		break;
	    }
	    break;
	case FcTypeMatrix:
	    switch (op) {
	    case FcOpEqual:
	    case FcOpContains:
	    case FcOpListing:
		ret = FcMatrixEqual (left.u.m, right.u.m);
		break;
	    case FcOpNotEqual:
	    case FcOpNotContains:
		ret = !FcMatrixEqual (left.u.m, right.u.m);
		break;
	    default:
		break;
	    }
	    break;
	case FcTypeCharSet:
	    switch (op) {
	    case FcOpContains:
	    case FcOpListing:
		/* left contains right if right is a subset of left */
		ret = FcCharSetIsSubset (right.u.c, left.u.c);
		break;
	    case FcOpNotContains:
		/* left contains right if right is a subset of left */
		ret = !FcCharSetIsSubset (right.u.c, left.u.c);
		break;
	    case FcOpEqual:
		ret = FcCharSetEqual (left.u.c, right.u.c);
		break;
	    case FcOpNotEqual:
		ret = !FcCharSetEqual (left.u.c, right.u.c);
		break;
	    default:
		break;
	    }
	    break;
	case FcTypeLangSet:
	    switch (op) {
	    case FcOpContains:
	    case FcOpListing:
		ret = FcLangSetContains (left.u.l, right.u.l);
		break;
	    case FcOpNotContains:
		ret = !FcLangSetContains (left.u.l, right.u.l);
		break;
	    case FcOpEqual:
		ret = FcLangSetEqual (left.u.l, right.u.l);
		break;
	    case FcOpNotEqual:
		ret = !FcLangSetEqual (left.u.l, right.u.l);
		break;
	    default:
		break;
	    }
	    break;
	case FcTypeVoid:
	    switch (op) {
	    case FcOpEqual:
	    case FcOpContains:
	    case FcOpListing:
		ret = FcTrue;
		break;
	    default:
		break;
	    }
	    break;
	case FcTypeFTFace:
	    switch (op) {
	    case FcOpEqual:
	    case FcOpContains:
	    case FcOpListing:
		ret = left.u.f == right.u.f;
		break;
	    case FcOpNotEqual:
	    case FcOpNotContains:
		ret = left.u.f != right.u.f;
		break;
	    default:
		break;
	    }
	    break;
	}
    }
    else
    {
	if (op == FcOpNotEqual || op == FcOpNotContains)
	    ret = FcTrue;
    }
    return ret;
}
Esempio n. 7
0
static double
FcCompareString (FcValue *v1, FcValue *v2)
{
    return (double) FcStrCmpIgnoreCase (FcValueString(v1), FcValueString(v2)) != 0;
}
Esempio n. 8
0
static int compare (const void *a, const void *b)
{
    const Entry *as = a, *bs = b;
    return FcStrCmpIgnoreCase ((const FcChar8 *) as->file, (const FcChar8 *) bs->file);
}
Esempio n. 9
0
static int compare (const void *a, const void *b)
{
    const FcChar8    *const *as = a, *const *bs = b;
    return FcStrCmpIgnoreCase (*as, *bs);
}
Esempio n. 10
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;
}
Esempio n. 11
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;
}
Esempio n. 12
0
static FcBool
FcCompareValueList (const char  *object,
		    FcValueList	*v1orig,	/* pattern */
		    FcValueList *v2orig,	/* target */
		    FcValue	*bestValue,
		    double	*value,
		    FcResult	*result)
{
    FcValueList    *v1, *v2;
    double    	    v, best, bestStrong, bestWeak;
    int		    i;
    int		    j;
    
    /*
     * Locate the possible matching entry by examining the
     * first few characters in object
     */
    i = -1;
    switch (FcToLower (object[0])) {
    case 'f':
	switch (FcToLower (object[1])) {
	case 'o':
	    switch (FcToLower (object[2])) {
	    case 'u':
		i = MATCH_FOUNDRY; break;
	    case 'n':
		i = MATCH_FONTVERSION; break;
	    }
	    break;
	case 'a':
	    i = MATCH_FAMILY; break;
	}
	break;
    case 'c':
	i = MATCH_CHARSET; break;
    case 'a':
	i = MATCH_ANTIALIAS; break;
    case 'l':
	i = MATCH_LANG; break;
    case 's':
	switch (FcToLower (object[1])) {
	case 'p':
	    i = MATCH_SPACING; break;
	case 't':
	    i = MATCH_STYLE; break;
	case 'l':
	    i = MATCH_SLANT; break;
	}
	break;
    case 'p':
	i = MATCH_PIXEL_SIZE; break;
    case 'w':
	switch (FcToLower (object[1])) {
	case 'i':
	    i = MATCH_WIDTH; break;
	case 'e':
	    i = MATCH_WEIGHT; break;
	}
	break;
    case 'r':
	i = MATCH_RASTERIZER; break;
    case 'o':
	i = MATCH_OUTLINE; break;
    }
    if (i == -1 || 
	FcStrCmpIgnoreCase ((FcChar8 *) _FcMatchers[i].object,
			    (FcChar8 *) object) != 0)
    {
	if (bestValue)
	    *bestValue = v2orig->value;
	return FcTrue;
    }
#if 0
    for (i = 0; i < NUM_MATCHER; i++)
    {
	if (!FcStrCmpIgnoreCase ((FcChar8 *) _FcMatchers[i].object,
				 (FcChar8 *) object))
	    break;
    }
    if (i == NUM_MATCHER)
    {
	if (bestValue)
	    *bestValue = v2orig->value;
	return FcTrue;
    }
#endif
    best = 1e99;
    bestStrong = 1e99;
    bestWeak = 1e99;
    j = 0;
    for (v1 = v1orig; v1; v1 = v1->next)
    {
	for (v2 = v2orig; v2; v2 = v2->next)
	{
	    v = (*_FcMatchers[i].compare) (_FcMatchers[i].object,
					    v1->value,
					    v2->value);
	    if (v < 0)
	    {
		*result = FcResultTypeMismatch;
		return FcFalse;
	    }
	    if (FcDebug () & FC_DBG_MATCHV)
		printf (" v %g j %d ", v, j);
	    v = v * 100 + j;
	    if (v < best)
	    {
		if (bestValue)
		    *bestValue = v2->value;
		best = v;
	    }
	    if (v1->binding == FcValueBindingStrong)
	    {
		if (v < bestStrong)
		    bestStrong = v;
	    }
	    else
	    {
		if (v < bestWeak)
		    bestWeak = v;
	    }
	}
	j++;
    }
    if (FcDebug () & FC_DBG_MATCHV)
    {
	printf (" %s: %g ", object, best);
	FcValueListPrint (v1orig);
	printf (", ");
	FcValueListPrint (v2orig);
	printf ("\n");
    }
    if (value)
    {
	int weak    = _FcMatchers[i].weak;
	int strong  = _FcMatchers[i].strong;
	if (weak == strong)
	    value[strong] += best;
	else
	{
	    value[weak] += bestWeak;
	    value[strong] += bestStrong;
	}
    }
    return FcTrue;
}