[Fontconfig] fontconfig: Branch 'master'

Akira TAGOH tagoh at kemper.freedesktop.org
Mon Apr 23 20:56:11 PDT 2012


 doc/fontconfig-devel.sgml |    3 +
 fontconfig/fontconfig.h   |    1 
 src/fcdefault.c           |   37 ++++++++++++++-
 src/fcint.h               |    3 -
 src/fclist.c              |   47 +++++++++++++++----
 src/fcmatch.c             |  113 +++++++++++++++++++++++++++++++++++++++-------
 src/fcname.c              |    1 
 7 files changed, 178 insertions(+), 27 deletions(-)

New commits:
commit 7587d1c99d9476b6dd4dbe523c0204da700fed8d
Author: Akira TAGOH <akira at tagoh.org>
Date:   Mon Mar 26 16:34:34 2012 +0900

    Bug 27765 - FcMatch() returns style in wrong language
    
    Add "namelang" object to obtain the localized name in the font regardless
    of the lang object. it's applied to "familylang", "stylelang" and
    "fullnamelang" alltogether. this would helps if one wants to enforce
    selecting them in the specific language if any.  the default value for
    the namelang object is determined from current locale.

diff --git a/doc/fontconfig-devel.sgml b/doc/fontconfig-devel.sgml
index 8733951..ab39092 100644
--- a/doc/fontconfig-devel.sgml
+++ b/doc/fontconfig-devel.sgml
@@ -190,6 +190,9 @@ convenience for the application's rendering mechanism.
                                                   the font
     embolden       FC_EMBOLDEN            Bool    Rasterizer should
                                                   synthetically embolden the font
+    namelang       FC_NAMELANG            String  Language name to be used for the
+                                                  default value of familylang,
+                                                  stylelang and fullnamelang
     </programlisting>
   </sect2>
 </sect1>
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index e4d5708..2671da7 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -111,6 +111,7 @@ typedef int		FcBool;
 #define FC_EMBEDDED_BITMAP  "embeddedbitmap"	/* Bool - true to enable embedded bitmaps */
 #define FC_DECORATIVE	    "decorative"	/* Bool - true if style is a decorative variant */
 #define FC_LCD_FILTER	    "lcdfilter"		/* Int */
+#define FC_NAMELANG	    "namelang"		/* String RFC 3866 langs */
 
 #define FC_CACHE_SUFFIX		    ".cache-" FC_CACHE_VERSION
 #define FC_DIR_CACHE_FILE	    "fonts.cache-" FC_CACHE_VERSION
diff --git a/src/fcdefault.c b/src/fcdefault.c
index a9165fa..170a8a4 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -119,7 +119,7 @@ FcGetDefaultLang (void)
 void
 FcDefaultSubstitute (FcPattern *pattern)
 {
-    FcValue v;
+    FcValue v, namelang, v2;
     int	    i;
 
     if (FcPatternObjectGet (pattern, FC_WEIGHT_OBJECT, 0, &v) == FcResultNoMatch )
@@ -175,6 +175,41 @@ FcDefaultSubstitute (FcPattern *pattern)
     {
 	FcPatternObjectAddInteger (pattern, FC_HINT_STYLE_OBJECT, FC_HINT_FULL);
     }
+    if (FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &v) == FcResultNoMatch)
+    {
+	FcPatternObjectAddString (pattern, FC_NAMELANG_OBJECT, FcGetDefaultLang ());
+    }
+    /* shouldn't be failed. */
+    FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &namelang);
+    /* Add a fallback to ensure the english name when the requested language
+     * isn't available. this would helps for the fonts that have non-English
+     * name at the beginning.
+     */
+    /* Set "en-us" instead of "en" to avoid giving higher score to "en".
+     * This is a hack for the case that the orth is not like ll-cc, because,
+     * if no namelang isn't explicitly set, it will has something like ll-cc
+     * according to current locale. which may causes FcLangDifferentTerritory
+     * at FcLangCompare(). thus, the English name is selected so that
+     * exact matched "en" has higher score than ll-cc.
+     */
+    v2.type = FcTypeString;
+    v2.u.s = FcSharedStr ((FcChar8 *)"en-us");
+    if (FcPatternObjectGet (pattern, FC_FAMILYLANG_OBJECT, 0, &v) == FcResultNoMatch)
+    {
+	FcPatternObjectAdd (pattern, FC_FAMILYLANG_OBJECT, namelang, FcTrue);
+	FcPatternObjectAddWithBinding (pattern, FC_FAMILYLANG_OBJECT, v2, FcValueBindingWeak, FcTrue);
+    }
+    if (FcPatternObjectGet (pattern, FC_STYLELANG_OBJECT, 0, &v) == FcResultNoMatch)
+    {
+	FcPatternObjectAdd (pattern, FC_STYLELANG_OBJECT, namelang, FcTrue);
+	FcPatternObjectAddWithBinding (pattern, FC_STYLELANG_OBJECT, v2, FcValueBindingWeak, FcTrue);
+    }
+    if (FcPatternObjectGet (pattern, FC_FULLNAMELANG_OBJECT, 0, &v) == FcResultNoMatch)
+    {
+	FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue);
+	FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue);
+    }
+    FcSharedStrFree (v2.u.s);
 }
 #define __fcdefault__
 #include "fcaliastail.h"
diff --git a/src/fcint.h b/src/fcint.h
index bada325..fb4a64b 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -858,7 +858,8 @@ FcListPatternMatchAny (const FcPattern *p,
 #define FC_EMBEDDED_BITMAP_OBJECT	39
 #define FC_DECORATIVE_OBJECT	40
 #define FC_LCD_FILTER_OBJECT	41
-#define FC_MAX_BASE_OBJECT	FC_LCD_FILTER_OBJECT
+#define FC_NAMELANG_OBJECT	42
+#define FC_MAX_BASE_OBJECT	FC_NAMELANG_OBJECT
 
 FcPrivate FcBool
 FcNameBool (const FcChar8 *v, FcBool *result);
diff --git a/src/fclist.c b/src/fclist.c
index 88025e9..331352c 100644
--- a/src/fclist.c
+++ b/src/fclist.c
@@ -221,7 +221,18 @@ FcListPatternMatchAny (const FcPattern *p,
     for (i = 0; i < p->num; i++)
     {
 	FcPatternElt	*pe = &FcPatternElts(p)[i];
-	FcPatternElt	*fe = FcPatternObjectFindElt (font, pe->object);
+	FcPatternElt	*fe;
+
+	if (pe->object == FC_NAMELANG_OBJECT)
+	{
+	    /* "namelang" object is the alias object to change "familylang",
+	     * "stylelang" and "fullnamelang" object alltogether. it won't be
+	     * available on the font pattern. so checking its availability
+	     * causes no results. we should ignore it here.
+	     */
+	    continue;
+	}
+	fe = FcPatternObjectFindElt (font, pe->object);
 	if (!fe)
 	    return FcFalse;
 	if (!FcListValueListMatchAny (FcPatternEltValues(pe),    /* pat elts */
@@ -340,13 +351,13 @@ FcListHashTableCleanup (FcListHashTable *table)
 }
 
 static int
-FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object)
+FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object, const FcChar8 *lang)
 {
-    FcChar8	   *lang = FcGetDefaultLang ();
     FcPatternElt   *e = FcPatternObjectFindElt (font, object);
     FcValueListPtr  v;
     FcValue         value;
     int             idx = -1;
+    int             defidx = -1;
     int             i;
 
     if (e)
@@ -363,17 +374,27 @@ FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object)
 
 		if (res == FcLangDifferentCountry && idx < 0)
 		    idx = i;
+		if (defidx < 0)
+		{
+		    /* workaround for fonts that has non-English value
+		     * at the head of values.
+		     */
+		    res = FcLangCompare (value.u.s, (FcChar8 *)"en");
+		    if (res == FcLangEqual)
+			defidx = i;
+		}
 	    }
 	}
     }
 
-    return (idx > 0) ? idx : 0;
+    return (idx > 0) ? idx : (defidx > 0) ? defidx : 0;
 }
 
 static FcBool
 FcListAppend (FcListHashTable	*table,
 	      FcPattern		*font,
-	      FcObjectSet	*os)
+	      FcObjectSet	*os,
+	      const FcChar8	*lang)
 {
     int		    o;
     FcPatternElt    *e;
@@ -409,19 +430,19 @@ FcListAppend (FcListHashTable	*table,
 	if (!strcmp (os->objects[o], FC_FAMILY) || !strcmp (os->objects[o], FC_FAMILYLANG))
 	{
 	    if (familyidx < 0)
-		familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT);
+		familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT, lang);
 	    defidx = familyidx;
 	}
 	else if (!strcmp (os->objects[o], FC_FULLNAME) || !strcmp (os->objects[o], FC_FULLNAMELANG))
 	{
 	    if (fullnameidx < 0)
-		fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT);
+		fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT, lang);
 	    defidx = fullnameidx;
 	}
 	else if (!strcmp (os->objects[o], FC_STYLE) || !strcmp (os->objects[o], FC_STYLELANG))
 	{
 	    if (styleidx < 0)
-		styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT);
+		styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT, lang);
 	    defidx = styleidx;
 	}
 	else
@@ -499,8 +520,16 @@ FcFontSetList (FcConfig	    *config,
 	for (f = 0; f < s->nfont; f++)
 	    if (FcListPatternMatchAny (p,		/* pattern */
 				       s->fonts[f]))	/* font */
-		if (!FcListAppend (&table, s->fonts[f], os))
+	    {
+		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
     {
diff --git a/src/fcmatch.c b/src/fcmatch.c
index 655e62c..623538b 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -240,7 +240,8 @@ static const FcMatcher _FcMatchers [] = {
 #define NUM_MATCH_VALUES    17
 
 static const FcMatcher*
-FcObjectToMatcher (FcObject object)
+FcObjectToMatcher (FcObject object,
+		   FcBool   include_lang)
 {
     int 	i;
 
@@ -278,6 +279,16 @@ FcObjectToMatcher (FcObject object)
 	i = MATCH_OUTLINE; break;
     case FC_DECORATIVE_OBJECT:
 	i = MATCH_DECORATIVE; break;
+    default:
+	if (include_lang)
+	{
+	    switch (object) {
+	    case FC_FAMILYLANG_OBJECT:
+	    case FC_STYLELANG_OBJECT:
+	    case FC_FULLNAMELANG_OBJECT:
+		i = MATCH_LANG; break;
+	    }
+	}
     }
 
     if (i < 0)
@@ -287,22 +298,25 @@ FcObjectToMatcher (FcObject object)
 }
 
 static FcBool
-FcCompareValueList (FcObject	 object,
-		    FcValueListPtr v1orig,	/* pattern */
-		    FcValueListPtr v2orig,	/* target */
-		    FcValue	*bestValue,
-		    double	*value,
-		    FcResult	*result)
+FcCompareValueList (FcObject	     object,
+		    const FcMatcher *match,
+		    FcValueListPtr   v1orig,	/* pattern */
+		    FcValueListPtr   v2orig,	/* target */
+		    FcValue         *bestValue,
+		    double          *value,
+		    int             *n,
+		    FcResult        *result)
 {
     FcValueListPtr  v1, v2;
     double    	    v, best, bestStrong, bestWeak;
-    int		    j;
-    const FcMatcher *match = FcObjectToMatcher(object);
+    int		    j, k, pos = 0;
 
     if (!match)
     {
 	if (bestValue)
 	    *bestValue = FcValueCanonicalize(&v2orig->value);
+	if (n)
+	    *n = 0;
 	return FcTrue;
     }
 
@@ -312,7 +326,7 @@ FcCompareValueList (FcObject	 object,
     j = 1;
     for (v1 = v1orig; v1; v1 = FcValueListNext(v1))
     {
-	for (v2 = v2orig; v2; v2 = FcValueListNext(v2))
+	for (v2 = v2orig, k = 0; v2; v2 = FcValueListNext(v2), k++)
 	{
 	    v = (match->compare) (&v1->value, &v2->value);
 	    if (v < 0)
@@ -326,6 +340,7 @@ FcCompareValueList (FcObject	 object,
 		if (bestValue)
 		    *bestValue = FcValueCanonicalize(&v2->value);
 		best = v;
+		pos = k;
 	    }
 	    if (v1->binding == FcValueBindingStrong)
 	    {
@@ -360,6 +375,9 @@ FcCompareValueList (FcObject	 object,
 	    value[strong] += bestStrong;
 	}
     }
+    if (n)
+	*n = pos;
+
     return FcTrue;
 }
 
@@ -393,10 +411,11 @@ FcCompare (FcPattern	*pat,
 	    i1++;
 	else
 	{
-	    if (!FcCompareValueList (elt_i1->object,
+	    const FcMatcher *match = FcObjectToMatcher (elt_i1->object, FcFalse);
+	    if (!FcCompareValueList (elt_i1->object, match,
 				     FcPatternEltValues(elt_i1),
 				     FcPatternEltValues(elt_i2),
-				     0, value, result))
+				     NULL, value, NULL, result))
 		return FcFalse;
 	    i1++;
 	    i2++;
@@ -412,8 +431,8 @@ FcFontRenderPrepare (FcConfig	    *config,
 {
     FcPattern	    *new;
     int		    i;
-    FcPatternElt    *fe, *pe;
-    FcValue	    v;
+    FcPatternElt    *fe, *pe, *fel, *pel;
+    FcValue	    v, vl;
     FcResult	    result;
 
     assert (pat != NULL);
@@ -425,19 +444,81 @@ FcFontRenderPrepare (FcConfig	    *config,
     for (i = 0; i < font->num; i++)
     {
 	fe = &FcPatternElts(font)[i];
+	if (fe->object == FC_FAMILYLANG_OBJECT ||
+	    fe->object == FC_STYLELANG_OBJECT ||
+	    fe->object == FC_FULLNAMELANG_OBJECT)
+	{
+	    /* ignore those objects. we need to deal with them
+	     * another way */
+	    continue;
+	}
+	if (fe->object == FC_FAMILY_OBJECT ||
+	    fe->object == FC_STYLE_OBJECT ||
+	    fe->object == FC_FULLNAME_OBJECT)
+	{
+	    FC_ASSERT_STATIC ((FC_FAMILY_OBJECT + 1) == FC_FAMILYLANG_OBJECT);
+	    FC_ASSERT_STATIC ((FC_STYLE_OBJECT + 1) == FC_STYLELANG_OBJECT);
+	    FC_ASSERT_STATIC ((FC_FULLNAME_OBJECT + 1) == FC_FULLNAMELANG_OBJECT);
+
+	    fel = FcPatternObjectFindElt (font, fe->object + 1);
+	    pel = FcPatternObjectFindElt (pat, fe->object + 1);
+	}
+	else
+	{
+	    fel = NULL;
+	    pel = NULL;
+	}
 	pe = FcPatternObjectFindElt (pat, fe->object);
 	if (pe)
 	{
-	    if (!FcCompareValueList (pe->object, FcPatternEltValues(pe),
-				     FcPatternEltValues(fe), &v, 0, &result))
+	    const FcMatcher *match = FcObjectToMatcher (pe->object, FcFalse);
+
+	    if (!FcCompareValueList (pe->object, match,
+				     FcPatternEltValues(pe),
+				     FcPatternEltValues(fe), &v, NULL, NULL, &result))
 	    {
 		FcPatternDestroy (new);
 		return 0;
 	    }
+	    if (fel && pel)
+	    {
+		int n = 1, j;
+
+		match = FcObjectToMatcher (pel->object, FcTrue);
+		if (!FcCompareValueList (pel->object, match,
+					 FcPatternEltValues (pel),
+					 FcPatternEltValues (fel), &vl, NULL, &n, &result))
+		{
+		    FcPatternDestroy (new);
+		    return NULL;
+		}
+		else
+		{
+		    FcValueListPtr l;
+
+		    for (j = 0, l = FcPatternEltValues (fe);
+			 j < n && l != NULL;
+			 j++, l = FcValueListNext (l));
+		    if (l)
+			v = FcValueCanonicalize (&l->value);
+		    else
+			v = FcValueCanonicalize (&FcPatternEltValues (fe)->value);
+		}
+	    }
+	    else if (fel)
+	    {
+		vl = FcValueCanonicalize (&FcPatternEltValues (fel)->value);
+	    }
 	}
 	else
+	{
 	    v = FcValueCanonicalize(&FcPatternEltValues (fe)->value);
+	    if (fel)
+		vl = FcValueCanonicalize (&FcPatternEltValues (fel)->value);
+	}
 	FcPatternObjectAdd (new, fe->object, v, FcFalse);
+	if (fel)
+	    FcPatternObjectAdd (new, fel->object, vl, FcFalse);
     }
     for (i = 0; i < pat->num; i++)
     {
diff --git a/src/fcname.c b/src/fcname.c
index d0b1ca8..d51307b 100644
--- a/src/fcname.c
+++ b/src/fcname.c
@@ -76,6 +76,7 @@ static const FcObjectType _FcBaseObjectTypes[] = {
     { FC_EMBEDDED_BITMAP,   FcTypeBool },
     { FC_DECORATIVE,	FcTypeBool },
     { FC_LCD_FILTER,	FcTypeInteger }, /* 41 */
+    { FC_NAMELANG,	FcTypeString }, /* 42 */
 };
 
 #define NUM_OBJECT_TYPES    (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])


More information about the Fontconfig mailing list