From: Jay H. <Jay.Hobson@Sun.COM> - 2006-06-27 20:21:07
|
Nicolas, Now that I have a solution that works for you, I have modified the patch=20 to use the "hide" tag instead of "restrict" as we had discussed earlier.=20 I also added an "only" tag in case there are fonts that you want to only=20 use for particular languages. (It's alot easier to specify a single, or=20 few languages that you want supported rather than dig into the font and=20 remove all the ones you don't). The new patch is attached. Syntax for the new commands is shown in the following example: <alias> <family>Sans-serif</family> <only> <family>Arial</family> <lang>en</lang> <lang>de</lang> </only> <hide> <family>DejaVuSans</family> <lang>ar</lang> </hide> </alias> <alias> <family>Serif</family> <hide> <family>Times</family> <lang>en</lang> <lang>de</lang> <lang>es</lang> </hide> </alias> The above XML would only allow Arial to be used for English and German,=20 disallow DejaVu for Arabic, and disallow Times with English, German and=20 Spanish. Give it a try and let me know what you think. Jay Nicolas Mailhot wrote: >Le mardi 27 juin 2006 =C3=A0 23:36 +0200, Davide Viti a =C3=A9crit : > > =20 > >>>BTW DejaVu is not as central in Fedora as in Debian today, mainly beca= use >>>the Red Hat pango maintainers feel its arabic and farsi support is bad >>>(and they are farsi speakers).=20 >>> =20 >>> >>well, Dejavu is now default for the debian installer, not (yet) the def= ault >>font after the system has been installed. As for farsi support it's bee= n said >>to be "too young", so we're using nazli font for arabic/persian. >> =20 >> > >Fedora is too, the problem if you use the full dejavu version and make >it higher prio in Sans than nazli, nazli glyphs will never be used for >the sans alias > > =20 > >>>So I've been testing a patch by Jay Hobson >>>to teach fontconfig selective font blacklisting. Maybe you'd be intere= sted >>>in doing some testing on the Debian fontconfig version before we push = the >>>patch upstream ? What the patch does is : >>>"ignore the glyphs of font foo when foo is evaluated through fontconfi= g >>>alias bar and lang=3Dbaz" >>> =20 >>> >>that sounds interesting; since size matters alot for the installer, we >>strip unused glyphs out of the font files (for example we currently >>strip arabic/farsi glyphs out of dejavu).=20 >> =20 >> > >Well, I'm targeting Fedora after it's installed, so my problem is not to >strip fonts but have a single font version and no dejavu-without-farsi >for farsi users, dejavu-with-arabic for arabic users and so on. So >install one single ttf version with all the glyphs, and let users >blacklist the font for languages they feel are not well supported yet. > >Right now we have to choose between butchering the font and making it >the default, and I'd like us to be able to use the full font *and* make >it the Fedora default. > > =20 > >>Is there a link for the fontconfig patch? >> =20 >> > >Here is the latest version Jay sent me (and the first to work on my >box). You need to define restrict for it to work (make >CFLAGS=3D"usual_distro_flags -D RESTRICT", and add something like > > <alias> > <family>sans-serif</family> > <restrict> > <family>DejaVu Sans</family> > <lang>ar</lang> > </restrict> > </alias> > >for it to work. (when evaluating the sans-serif fontconfig alias with >lan=3Dar, ignore DejaVu Sans) > >Regards, > > =20 > >------------------------------------------------------------------------ > >--- fcint.h.orig Tue Jun 13 10:29:50 2006 >+++ fcint.h Wed Jun 21 15:17:10 2006 >@@ -369,6 +369,21 @@ > FcChar32 *blanks; > }; >=20 >+#ifdef RESTRICT >+typedef struct _FcFontLang { >+ FcChar8 *family; /* Name of font family */ >+ FcStrSet *langs; /* list of restricted languages= */ >+ struct _FcFontLang *next; /* Next font family */ >+} FcFontLang; >+ >+typedef struct _FcRestrict { >+ FcChar8 *alias; /* Name of alias Sans/Serif */ >+ FcFontLang *family; /* Restricted languages struct = */ >+ FcFontLang *az[26]; /* Quick pointers */ >+ struct _FcRestrict *next; /* Next alias */ >+} FcRestrict; >+#endif >+ > struct _FcConfig { > /* > * File names loaded from the configuration -- saved here as the >@@ -423,6 +438,16 @@ > */ > time_t rescanTime; /* last time information was scanned */ > int rescanInterval; /* interval between scans */ >+#ifdef RESTRICT >+ /* >+ * Languages can be selectively turned off for some fonts to allow >+ * fonts to be used for specific languages only even if the font >+ * supports the language. This allows best fonts to be used per >+ * language where two fonts that both support the same language >+ * cannot be placed in the preference list appropriately. >+ */ >+ FcRestrict *restrictFont; >+#endif > }; > =20 > extern FcConfig *_fcConfig; >@@ -747,6 +772,11 @@ > void > FcEditDestroy (FcEdit *e); >=20 >+#ifdef RESTRICT >+void >+FcRestrictDestroy ( FcRestrict *r ); >+#endif >+ > /* fcinit.c */ >=20 > void >@@ -778,6 +808,14 @@ > FcBool > FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls); >=20 >+#ifdef RESTRICT >+FcBool >+FcLangSetRemove (FcLangSet *ls, const FcChar8 *lang); >+ >+FcBool >+FcLangSetRemoveLangs (FcLangSet *ls, FcStrSet *langs); >+#endif >+ > void > FcLangSetNewBank (void); >=20 >--- fccfg.c.orig Tue Jun 13 10:28:46 2006 >+++ fccfg.c Wed Jun 21 14:32:49 2006 >@@ -117,6 +117,9 @@ >=20 > config->rescanTime =3D time(0); > config->rescanInterval =3D 30; =20 >+#ifdef RESTRICT >+ config->restrictFont =3D NULL; >+#endif > =20 > return config; >=20 >@@ -243,6 +246,9 @@ > for (set =3D FcSetSystem; set <=3D FcSetApplication; set++) > if (config->fonts[set]) > FcFontSetDestroy (config->fonts[set]); >+#ifdef RESTRICT >+ FcRestrictDestroy (config->restrictFont); >+#endif >=20 > free (config); > FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig)); >--- fclang.c.orig Tue Jun 13 10:28:40 2006 >+++ fclang.c Wed Jun 21 14:32:49 2006 >@@ -43,6 +43,9 @@ >=20 > #define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |=3D ((FcChar32) 1 = << ((id) & 0x1f))) > #define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) = & 1) >+#ifdef RESTRICT >+#define FcLangSetBitUnset(ls, id) ((ls)->map[(id)>>5] &=3D ~((FcC= har32) 1 << ((id) & 0x1f))) >+#endif >=20 > static FcBool langsets_populated =3D FcFalse; >=20 >@@ -355,6 +358,36 @@ > return FcStrSetAdd (ls->extra, lang); > } >=20 >+#ifdef RESTRICT >+FcBool >+FcLangSetRemove (FcLangSet *ls, const FcChar8 *lang) >+{ >+ int id; >+ >+ id =3D FcLangSetIndex (lang); >+ if (id >=3D 0) >+ { >+ FcLangSetBitUnset (ls, id); >+ return FcTrue; >+ } >+ if (ls->extra) >+ return FcStrSetDel (ls->extra, lang); >+ return FcFalse; >+} >+ >+FcBool >+FcLangSetRemoveLangs (FcLangSet *ls, FcStrSet *langs) >+{ >+ int i; >+ >+ for ( i =3D 0; i < langs->num; i++ ) >+ { >+ FcLangSetRemove ( ls, langs->strs[i] ); >+ } >+ return FcTrue; >+} >+#endif >+ > FcLangResult > FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang) > { >--- fcmatch.c.orig Tue Jun 13 10:28:35 2006 >+++ fcmatch.c Mon Jun 26 15:24:42 2006 >@@ -465,7 +465,7 @@ > FcPatternElt *fe, *pe; > FcValue v; > FcResult result; >- =20 >+ > new =3D FcPatternCreate (); > if (!new) > return 0; >@@ -502,6 +502,137 @@ > return new; > } >=20 >+#ifdef RESTRICT >+static FcRestrict * >+FcRestrictGetList (FcConfig *config, FcPattern *p) >+{ >+ FcRestrict *r =3D NULL; >+ >+ if ( config->restrictFont ) >+ { >+ FcPatternElt *pe =3D FcPatternFindElt (p, "family"); >+ >+ r =3D config->restrictFont; >+ >+ /* >+ * Find the base family (alias) and see if it is in the >+ * restrict list >+ */ >+ if ( pe ) >+ { >+ FcValueListPtr v1; >+ FcValueList *v1_ptrU; >+ int found =3D 0; >+ >+ while ( r ) >+ { >+ for ( v1 =3D pe->values, v1_ptrU =3D FcValueListPtrU(v1= ); >+ v1_ptrU; >+ v1 =3D v1_ptrU->next, v1_ptrU =3D FcValueListPtrU= (v1)) >+ { >+ const FcChar8* v1_string =3D fc_value_string ( &(v1_ptrU->value) = ); >+if (FcDebug() & 2048) >+{ >+ printf ( "Compare family name: %s to Restrict name: %s\n", (char *)v1_= string, (char *)r->alias ); >+} >+ if ( !strcasecmp ( (char *)r->alias, (char *)v1_str= ing )) >+ found =3D 1; >+ } >+ >+ if ( !found ) >+ r =3D r->next; >+ else >+ break; >+ } >+ } >+ >+ /* >+ * At this point, we have the list of restricted fonts >+ * for the alias. We now need to check and see if the >+ * font we are comparing is on the restrict list. >+ */ >+ } >+if (FcDebug () & 2048) >+{ >+ if ( r ) >+ printf ( "Restriction list for alias %s exists\n", r->alias ); >+ else >+ printf ( "No restriction list exists\n" ); >+} >+ return r; >+} >+ >+static FcPattern * >+FcRestrictFont (FcRestrict *r, FcPatternElt *pe, FcPattern *fnt) >+{ >+ FcPattern *new =3D NULL; >+ FcFontLang *fl; >+ >+ if ( r && pe ) >+ { >+ FcValueListPtr ev =3D pe->values; >+ FcValueList *ev_ptrU =3D FcValueListPtrU(ev); >+ const FcChar8 *ev_string =3D fc_value_string(& (ev_ptrU->value) ); >+ int pos =3D (int)(FcToLower(*ev_string)) - (in= t)'a'; >+ >+ fl =3D r->az[pos]; >+ >+ while ( fl ) >+ { >+ int cmp =3D strcasecmp ( (char *)fl->family, (char *)ev_str= ing ); >+ >+ if ( !cmp ) >+ break; >+ else if ( cmp > 0 ) >+ fl =3D NULL; >+ else >+ fl =3D fl->next; >+ } >+ >+ if ( fl ) >+ { >+ FcPatternElt *ppe; >+if (FcDebug () & 2048) >+{ >+ printf ( "Found matching restriction family: %s\n", (char *)fl->fam= ily); >+} >+ new =3D FcPatternDuplicate (fnt); >+ if ( new ) >+ { >+ ppe =3D FcPatternFindElt (new, "lang"); >+ if ( ppe ) >+ { >+ FcValueList *fv_ptrU =3D FcValueListPtrU(ppe->values); >+ if ( fv_ptrU->value.type =3D=3D FcTypeLangSet ) >+ { >+if (FcDebug () & 2048) >+{ >+ int i; >+ printf ( "Removing languages from family:", (char *)fl->family); >+ for ( i =3D 0; i < fl->langs->num; i++ ) >+ printf ( " %s,", fl->langs->strs[i]); >+ printf("\n"); >+} >+ FcLangSetRemoveLangs ( (FcLangSet *)fv_ptrU->va= lue.u.l, fl->langs ); >+ } >+ else >+ { >+ >+ } >+ } >+ else >+ { >+ FcPatternDestroy (new); >+ new =3D NULL; >+ } >+ } >+ } >+ } >+ >+ return new; >+} >+#endif >+ > FcPattern * > FcFontSetMatch (FcConfig *config, > FcFontSet **sets, >@@ -526,7 +657,11 @@ > int pat_elt; > int *match_blocked; > int block_start; >+#ifdef RESTRICT >+ FcRestrict *r =3D NULL; >+#endif >=20 >+ > if (!nsets || !sets || !p) > { > *result =3D FcResultNoMatch; >@@ -548,6 +683,10 @@ > } > } >=20 >+#ifdef RESTRICT >+ r =3D FcRestrictGetList ( config, p ); >+#endif >+ > sets_offset =3D (int *)calloc(nsets, sizeof (int)); >=20 > nfonts =3D 0; >@@ -630,11 +769,23 @@ > { > int cand_elt; > FcPatternElt *cand_elts; >+#ifdef RESTRICT >+ FcPatternElt *pe =3D FcPatternFindElt (s->fonts[f],= "family"); >+ FcPattern *restrictFont =3D NULL; >+#endif >=20 >+ > if (match_blocked[f + sets_offset[set]] =3D=3D 1) > continue; >=20 > score =3D 1e99; >+#ifdef RESTRICT >+ if ( scoring_index =3D=3D MATCH_LANG_INDEX ) >+ restrictFont =3D FcRestrictFont ( r, pe, s->fon= ts[f]); >+ if ( restrictFont ) >+ cand_elts =3D FcPatternEltU (restrictFont->elts ); >+ else >+#endif > cand_elts =3D FcPatternEltU(s->fonts[f]->elts); >=20 > /* Look for the appropriate element in this candidate >@@ -657,6 +808,10 @@ > *result =3D FcResultTypeMismatch; > free (match_blocked); > free (sets_offset); >+#ifdef RESTRICT >+ if ( restrictFont ) >+ FcPatternDestroy ( restrictFont ); >+#endif > return 0; > } >=20 >@@ -673,6 +828,11 @@ > } > } >=20 >+#ifdef RESTRICT >+ if ( restrictFont ) >+ FcPatternDestroy ( restrictFont ); >+#endif >+ > /* We had no matching, just try the next one */ > if (score =3D=3D 1e99) > { >@@ -867,6 +1027,9 @@ > int nPatternLang; > FcBool *patternLangSat; > FcValue patternLang; >+#ifdef RESTRICT >+ FcRestrict *r =3D NULL; >+#endif >=20 > if (FcDebug () & FC_DBG_MATCH) > { >@@ -900,6 +1063,11 @@ > =20 > new =3D nodes; > nodep =3D nodeps; >+ >+#ifdef RESTRICT >+ r =3D FcRestrictGetList ( config, p ); >+#endif >+ > for (set =3D 0; set < nsets; set++) > { > s =3D sets[set]; >@@ -907,14 +1075,33 @@ > continue; > for (f =3D 0; f < s->nfont; f++) > { >+#ifdef RESTRICT >+ FcPatternElt *pe =3D FcPatternFindElt (s->fonts[f], "family= "); >+ FcPattern *restrictFont =3D FcRestrictFont ( r, pe, s->f= onts[f]); >+ int res =3D 1; >+#endif > if (FcDebug () & FC_DBG_MATCHV) > { > printf ("Font %d ", f); > FcPatternPrint (s->fonts[f]); > } >+#ifdef RESTRICT >+ if ( restrictFont ) >+ new->pattern =3D restrictFont; >+ else >+#endif > new->pattern =3D s->fonts[f]; > if (!FcCompare (p, new->pattern, new->score, result)) >+#ifdef RESTRICT >+ res =3D 0; >+ >+ if ( restrictFont ) >+ FcPatternDestroy ( restrictFont ); >+ >+ if ( !res ) >+#endif > goto bail1; >+ > if (FcDebug () & FC_DBG_MATCHV) > { > printf ("Score"); >--- fcxml.c.orig Tue Jun 13 10:28:29 2006 >+++ fcxml.c Fri Jun 23 14:23:37 2006 >@@ -299,6 +299,11 @@ > FcElementDefault, > FcElementFamily, >=20 >+#ifdef RESTRICT >+ FcElementRestrict, >+ FcElementLang, >+#endif >+ > FcElementSelectfont, > FcElementAcceptfont, > FcElementRejectfont, >@@ -359,6 +364,11 @@ > { "default", FcElementDefault }, > { "family", FcElementFamily }, >=20 >+#ifdef RESTRICT >+ { "restrict", FcElementRestrict }, >+ { "lang", FcElementLang }, >+#endif >+ > { "selectfont", FcElementSelectfont }, > { "acceptfont", FcElementAcceptfont }, > { "rejectfont", FcElementRejectfont }, >@@ -430,6 +440,11 @@ > FcVStackPrefer, > FcVStackAccept, > FcVStackDefault, >+ >+#ifdef RESTRICT >+ FcVStackRestrict, >+ FcVStackLang, >+#endif > =20 > FcVStackInteger, > FcVStackDouble, >@@ -730,6 +745,9 @@ > case FcVStackField: > case FcVStackConstant: > case FcVStackGlob: >+#ifdef RESTRICT >+ case FcVStackLang: >+#endif > FcStrFree (vstack->u.string); > break; > case FcVStackPattern: >@@ -737,6 +755,9 @@ > break; > case FcVStackInteger: > case FcVStackDouble: >+#ifdef RESTRICT >+ case FcVStackRestrict: >+#endif > break; > case FcVStackMatrix: > FcMatrixFree (vstack->u.matrix); >@@ -1345,7 +1366,261 @@ > FcVStackPushExpr (parse, FcVStackFamily, expr); > } >=20 >+#ifdef RESTRICT > static void >+FcParseLang (FcConfigParse *parse) >+{ >+ FcChar8 *s; >+ FcExpr *expr; >+ >+ if (!parse->pstack) >+ return; >+ s =3D FcStrBufDone (&parse->pstack->str); >+ if (!s) >+ { >+ FcConfigMessage (parse, FcSevereError, "out of memory"); >+ return; >+ } >+ expr =3D FcExprCreateString (s); >+ FcStrFree (s); >+ if (expr) >+ FcVStackPushExpr (parse, FcVStackLang, expr); >+} >+ >+static void >+FcParseRestrict (FcConfigParse *parse, FcVStackTag tag) >+{ >+ FcExpr *family =3D 0; >+ FcStrSet *lang =3D 0; >+ FcVStack *vstack; >+ FcFontLang *fl =3D NULL; >+ FcExpr *expr; >+ >+ while ((vstack =3D FcVStackPop (parse))) >+ { >+ switch (vstack->tag) { >+ case FcVStackFamily: >+ if (family) >+ FcExprDestroy (family); >+ family =3D vstack->u.expr; >+ vstack->tag =3D FcVStackNone; >+ break; >+ case FcVStackLang: >+ if (!lang) >+ lang =3D FcStrSetCreate (); >+ FcStrSetAdd (lang, vstack->u.expr->u.sval); >+ break; >+ default: >+ FcConfigMessage (parse, FcSevereWarning, "bad alias"); >+ break; >+ } >+ FcVStackDestroy (vstack); >+ } >+ if (!family) >+ { >+ FcConfigMessage (parse, FcSevereError, "missing family in restr= ict"); >+ } >+ if ( lang ) >+ { >+ fl =3D (FcFontLang *)malloc (sizeof (FcFontLang)); >+ >+ if ( fl ) >+ { >+ int len =3D strlen ( (char *)family->u.sval ); >+ fl->family =3D (FcChar8 *)malloc ( sizeof ( char ) * ( len = + 1 )); >+ strncpy ( (char *)fl->family, (char *)family->u.sval, len )= ; >+ fl->family[len] =3D '\0'; >+ fl->langs =3D lang; >+ fl->next =3D NULL; >+ } >+ } >+ if ( fl ) >+ { >+ expr =3D FcExprCreateNil (); >+ if (expr) >+ { >+ expr->u.sval =3D (FcChar8 *)fl; >+ FcVStackPushExpr (parse, FcVStackRestrict, expr); >+ } >+ } >+} >+ >+static void >+FcFontLangDestroy(FcFontLang *fl) >+{ >+ FcFontLang *cur =3D fl; >+ >+ while (fl) >+ { >+ cur =3D fl; >+ fl =3D fl->next; >+ free (cur->family); >+ FcStrSetDestroy (cur->langs); >+ free (cur); >+ } >+} >+ >+void >+FcRestrictDestroy ( FcRestrict *r ) >+{ >+ if ( r ) >+ { >+ if ( r->alias ) >+ free ( r->alias ); >+ FcFontLangDestroy ( r->family ); >+ FcRestrictDestroy ( r->next ); >+ free ( r ); >+ } >+} >+ >+static void >+FcRestrictCreate(FcConfigParse *parse, FcFontLang *fl, FcExpr *family) >+{ >+ FcRestrict *new =3D parse->config->restrictFont; >+ int i; >+ >+ /* >+ * Check to see if user has already restricted something in this al= ias >+ */ >+ while ( new !=3D NULL ) >+ { >+ if ( !strcasecmp ( (char *)new->alias, (char *)family->u.sval )) >+ break; >+ else >+ new =3D new->next; >+ } >+ >+ /* >+ * If no alias restrictions exist, then create an FcRestrict struct= ure and >+ * fill in the base values. >+ */ >+ if ( !new ) >+ { >+ new =3D (FcRestrict *)malloc ( sizeof ( FcRestrict )); >+ if ( new ) >+ { >+ int len =3D strlen ( (char *)family->u.sval ); >+ new->alias =3D (FcChar8 *)malloc ( sizeof ( char ) * ( len= + 1 )); >+ if ( new->alias ) >+ { >+ strncpy ((char *)new->alias, (char *)family->u.sval, le= n); >+ new->alias[len] =3D '\0'; >+ } >+ else >+ { >+ free (new); >+ return; >+ } >+ new->family =3D NULL; >+ new->next =3D parse->config->restrictFont; >+ parse->config->restrictFont =3D new; >+if (FcDebug () & 2048) >+{ >+ printf("Add new restriction for alias: %s\n", (char *)family->u.sva= l); >+} >+ } >+ else >+ return; >+ } >+ >+ /* >+ * Add FontLang structure in alphabetical order based on family >+ * to the restrict list >+ */ >+ while ( fl ) >+ { >+ FcFontLang *next =3D fl->next; >+ >+ fl->next =3D NULL; >+ >+ if ( !new->family ) >+ { >+ new->family =3D fl; >+if (FcDebug () & 2048) >+{ >+ printf("Add restriction for family %s with langs", (char *)fl->fami= ly); >+ for ( i =3D 0; i < fl->langs->num; i++ ) >+ printf ( " %s,", fl->langs->strs[i]); >+ printf("\n"); >+} >+ } >+ else >+ { >+ FcFontLang *ptr =3D new->family; >+ FcFontLang *last =3D NULL; >+ >+ while ( ptr ) >+ { >+ int cmp =3D strcasecmp ( (char *)fl->family, (char *)ptr->family); >+ /* >+ * Find out if new family is before current alphabetically >+ */ >+ if ( cmp < 0 ) >+ { >+ fl->next =3D ptr; >+ if ( !last ) >+ new->family =3D fl; >+ else >+ last->next =3D fl; >+if (FcDebug () & 2048) >+{ >+ printf("Add restriction for family %s with langs", (char *)fl->fami= ly); >+ for ( i =3D 0; i < fl->langs->num; i++ ) >+ printf ( " %s,", fl->langs->strs[i]); >+ printf("\n"); >+} >+ break; >+ } >+ /* >+ * If it already exists, then just add new lang(s) >+ */ >+ else if ( cmp =3D=3D 0 ) >+ { >+ for ( i =3D 0; i < fl->langs->num; i++ ) >+ { >+ if ( !FcStrSetMember ( ptr->langs, fl->langs->strs[i] )) >+ FcStrSetAdd ( ptr->langs, fl->langs->strs[i] ); >+ } >+ FcFontLangDestroy ( fl ); >+if (FcDebug () & 2048) >+{ >+ printf("Restriction already exists for family %s\n", (char *)ptr->f= amily); >+} >+ break; >+ } >+ /* >+ * If it is after, then continue moving down the list >+ */ >+ else >+ { >+ last =3D ptr; >+ ptr =3D ptr->next; >+ >+ if ( !ptr ) >+ last->next =3D fl; >+ } >+ } >+ } >+ fl =3D next; >+ } >+ >+ for ( i =3D 0; i < 26; i++ ) >+ new->az[i] =3D NULL; >+ >+ fl =3D new->family; >+ while ( fl ) >+ { >+ int pos =3D (int)(fl->family[0]) - (int)'A'; >+ if ( !new->az[pos] ) >+ { >+ new->az[pos] =3D fl; >+ } >+ fl =3D fl->next; >+ } >+} >+#endif >+ >+static void > FcParseAlias (FcConfigParse *parse) > { > FcExpr *family =3D 0, *accept =3D 0, *prefer =3D 0, *def =3D 0, *ne= w =3D 0; >@@ -1352,6 +1627,10 @@ > FcEdit *edit =3D 0, *next; > FcVStack *vstack; > FcTest *test; >+#ifdef RESTRICT >+ FcFontLang *fl =3D NULL; >+ FcFontLang *tmp; >+#endif >=20 > while ((vstack =3D FcVStackPop (parse)))=20 > { >@@ -1373,6 +1652,15 @@ > vstack->tag =3D FcVStackNone; > } > break; >+#ifdef RESTRICT >+ case FcVStackRestrict: >+ tmp =3D (FcFontLang *)(vstack->u.expr->u.sval); >+ FcExprDestroy (vstack->u.expr); >+ tmp->next =3D fl; >+ fl =3D tmp; >+ vstack->tag =3D FcVStackNone; >+ break; >+#endif > case FcVStackPrefer: > if (prefer) > FcExprDestroy (prefer); >@@ -1446,6 +1734,12 @@ > else > FcExprDestroy (def); > } >+#ifdef RESTRICT >+ if (fl) >+ { >+ FcRestrictCreate(parse, fl, family); >+ } >+#endif > if (edit) > { > test =3D FcTestCreate (parse, FcMatchPattern, >@@ -1473,6 +1767,9 @@ > break; > case FcVStackString: > case FcVStackFamily: >+#ifdef RESTRICT >+ case FcVStackLang: >+#endif > expr =3D FcExprCreateString (vstack->u.string); > break; > case FcVStackField: >@@ -2099,6 +2396,14 @@ > case FcElementFamily: > FcParseFamily (parse); > break; >+#ifdef RESTRICT >+ case FcElementRestrict: >+ FcParseRestrict (parse, FcVStackLang); >+ break; >+ case FcElementLang: >+ FcParseLang (parse); >+ break; >+#endif >=20 > case FcElementTest: > FcParseTest (parse); > =20 > |