Le lundi 12 juin 2006 à 17:25 +0200, Ben Laenen a écrit : ... > Okay, my personal views on this issue now: ... > Behold the three features which would make the whole discussion about > the "omnibus font" completely unnecessary: > > * BASE tables > * locl feature > * and most importantly: more control in the way the aliases are defined > in fonts.conf > > (well, basically only number 3 would be sufficient to stop most people > discussing about it) > * more control in fonts.conf aliases. What I mean with that: if you > define "Sans" for example, being able to have different lists for each > locale, and to cut out ranges which should not be used when the alias > is selected (when you have Arabic locale, you could have "dejavu" as > number 1 in the list and e.g. cut out the arabic block). Some work has > been done on this apparently, I don't know if everything is possible > now. Well this is *exactly* what Jay's patch intends to do, and since he is willing to massage it to get it included in fontconfig proper, we may soon all forget about this particular problem. It's past midnight here so I'll stop working on it, but if someone wants to take the relay here is the current state of the patch (not building here, but seems easy to fix) As our exchange proved the choice of restrict for the tag may be ambiguous (Jay meant it as restrict from, I understood it as restrict to) so another verb may be better. I suggested Hide. For those on the same timezone as me, good night -- Nicolas Mailhot
diff -uNr fontconfig-2.3.95.orig/src/fccfg.c fontconfig-2.3.95/src/fccfg.c --- fontconfig-2.3.95.orig/src/fccfg.c 2006-04-25 07:51:35.000000000 +0200 +++ fontconfig-2.3.95/src/fccfg.c 2006-06-12 23:31:37.000000000 +0200 @@ -117,6 +117,7 @@ config->rescanTime = time(0); config->rescanInterval = 30; + config->restrictFont = NULL; return config; @@ -243,6 +244,7 @@ for (set = FcSetSystem; set <= FcSetApplication; set++) if (config->fonts[set]) FcFontSetDestroy (config->fonts[set]); + FcRestrictDestroy (config->restrictFont); free (config); FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig)); diff -uNr fontconfig-2.3.95.orig/src/fcint.h fontconfig-2.3.95/src/fcint.h --- fontconfig-2.3.95.orig/src/fcint.h 2006-04-11 07:00:33.000000000 +0200 +++ fontconfig-2.3.95/src/fcint.h 2006-06-12 23:32:21.000000000 +0200 @@ -369,6 +369,19 @@ FcChar32 *blanks; }; +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; + struct _FcConfig { /* * File names loaded from the configuration -- saved here as the @@ -423,6 +436,14 @@ */ time_t rescanTime; /* last time information was scanned */ int rescanInterval; /* interval between scans */ + /* + * 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; }; extern FcConfig *_fcConfig; @@ -747,6 +768,9 @@ void FcEditDestroy (FcEdit *e); +void +FcRestrictDestroy ( FcRestrict *r ); + /* fcinit.c */ void @@ -797,6 +821,12 @@ void * FcLangSetUnserialize (FcCache * metadata, void *block_ptr); +FcBool +FcLangSetRemove (FcLangSet *ls, const FcChar8 *lang); + +FcBool +FcLangSetRemoveLangs (FcLangSet *ls, FcStrSet *langs); + /* fclist.c */ FcBool diff -uNr fontconfig-2.3.95.orig/src/fclang.c fontconfig-2.3.95/src/fclang.c --- fontconfig-2.3.95.orig/src/fclang.c 2006-04-13 06:22:25.000000000 +0200 +++ fontconfig-2.3.95/src/fclang.c 2006-06-12 23:32:48.000000000 +0200 @@ -43,6 +43,7 @@ #define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f))) #define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1) +#define FcLangSetBitUnset(ls, id) ((ls)->map[(id)>>5] &= ~((FcChar32) 1 << ((id) & 0x1f))) static FcBool langsets_populated = FcFalse; @@ -355,6 +356,34 @@ return FcStrSetAdd (ls->extra, lang); } +FcBool +FcLangSetRemove (FcLangSet *ls, const FcChar8 *lang) +{ + int id; + + id = FcLangSetIndex (lang); + if (id >= 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 = 0; i < langs->num; i++ ) + { + FcLangSetRemove ( ls, langs->strs[i] ); + } + return FcTrue; +} + FcLangResult FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang) { diff -uNr fontconfig-2.3.95.orig/src/fcmatch.c fontconfig-2.3.95/src/fcmatch.c --- fontconfig-2.3.95.orig/src/fcmatch.c 2006-04-25 07:51:35.000000000 +0200 +++ fontconfig-2.3.95/src/fcmatch.c 2006-06-12 23:54:34.000000000 +0200 @@ -502,6 +502,113 @@ return new; } +static FcRestrict * +FcRestrictGetList (FcConfig *config, FcPattern *p) +{ + FcRestrict *r = NULL; + + if ( config->restrictFont ) + { + FcPatternElt *pe = FcPatternFindElt (p, "family"); + + r = config->restrictFont; + + /* + * Find the base family (alias) and see if it is in the + * restrict list + */ + if ( pe ) + { + FcValueList *vlist = pe->values; + + while ( vlist->next ) + vlist = vlist->next; + + while ( r ) + { + if ( !strcasecmp ( (char *)r->alias, (char *)vlist->value.u.s )) break; + else + r = r->next; + } + } + + /* + * 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. + */ + } + + return r; +} + +static int +FcRestrictFont (FcRestrict *r, FcPatternElt *pe, FcPattern *fnt, FcPatternElt **ppe, FcLangSet **pls) +{ + FcFontLang *fl; + int ret = 0; + + if ( r && pe ) + { + FcLangSet *ls; + int pos = (int)(FcToLower(pe->values->value.u.s[0])) - 'a'; + + fl = r->az[pos]; + + while ( fl ) + { + FcValueList *vlist = pe->values; + int cmp = strcasecmp ( (char *)fl->family, + (char *)vlist->value.u.s ); + + if ( !cmp ) + break; + else if ( cmp > 0 ) + fl = NULL; + else + fl = fl->next; + } + + if ( fl ) + { + *ppe = FcPatternFindElt (fnt, "lang"); + if ( *ppe ) + { + ret = 1; + if ( (*ppe)->values->value.type == FcTypeLangSet ) + { + ls = FcLangSetCopy ( (*ppe)->values->value.u.l ); + FcLangSetRemoveLangs ( ls, fl->langs ); + + (*pls) = (FcLangSet *)(*ppe)->values->value.u.l; + (*ppe)->values->value.u.l = ls; + } + else + { + + } + } + } + } + + return ret; +} + +static void +FcFontResetLangs (int restrictFont, + FcPatternElt *pe2, + FcLangSet *oldLangSet) +{ + if ( restrictFont ) + { + if ( pe2->values->value.type == FcTypeLangSet ) + { + FcLangSetDestroy ((FcLangSet *) pe2->values->value.u.l ); + pe2->values->value.u.l = oldLangSet; + } + } +} + FcPattern * FcFontSetMatch (FcConfig *config, FcFontSet **sets, @@ -526,6 +633,7 @@ int pat_elt; int *match_blocked; int block_start; + FcRestrict *r = NULL; if (!nsets || !sets || !p) { @@ -548,6 +656,8 @@ } } + r = FcRestrictGetList ( config, p ); + sets_offset = (int *)calloc(nsets, sizeof (int)); nfonts = 0; @@ -630,10 +740,15 @@ { int cand_elt; FcPatternElt *cand_elts; + FcLangSet *oldLangSet = NULL; + FcPatternElt *pe = FcPatternFindElt (s->fonts[f], "family"), *pe2; + int restrictFont = 0; + if (match_blocked[f + sets_offset[set]] == 1) continue; + restrictFont = FcRestrictFont ( r, pe, s->fonts[f], &pe2, &oldLangSet); score = 1e99; cand_elts = FcPatternEltU(s->fonts[f]->elts); @@ -657,6 +772,7 @@ *result = FcResultTypeMismatch; free (match_blocked); free (sets_offset); + FcFontResetLangs (restrictFont, pe2, oldLangSet); return 0; } @@ -673,6 +789,8 @@ } } + FcFontResetLangs (restrictFont, pe2, oldLangSet); + /* We had no matching, just try the next one */ if (score == 1e99) { @@ -867,6 +985,7 @@ int nPatternLang; FcBool *patternLangSat; FcValue patternLang; + FcRestrict *r = NULL; if (FcDebug () & FC_DBG_MATCH) { @@ -900,6 +1019,9 @@ new = nodes; nodep = nodeps; + + r = FcRestrictGetList ( config, p ); + for (set = 0; set < nsets; set++) { s = sets[set]; @@ -907,6 +1029,11 @@ continue; for (f = 0; f < s->nfont; f++) { + FcLangSet *oldLangSet = NULL; + FcPatternElt *pe = FcPatternFindElt (s->fonts[f], "family"), *pe2; + int restrictFont = FcRestrictFont ( r, pe, s->fonts[f], &pe2, &oldLangSet); + int res = 1; + if (FcDebug () & FC_DBG_MATCHV) { printf ("Font %d ", f); @@ -914,6 +1041,11 @@ } new->pattern = s->fonts[f]; if (!FcCompare (p, new->pattern, new->score, result)) + res = 0; + + FcFontResetLangs (restrictFont, pe2, oldLangSet); + + if ( !res ) goto bail1; if (FcDebug () & FC_DBG_MATCHV) { diff -uNr fontconfig-2.3.95.orig/src/fcxml.c fontconfig-2.3.95/src/fcxml.c --- fontconfig-2.3.95.orig/src/fcxml.c 2006-04-25 07:51:35.000000000 +0200 +++ fontconfig-2.3.95/src/fcxml.c 2006-06-12 23:34:55.000000000 +0200 @@ -299,6 +299,9 @@ FcElementDefault, FcElementFamily, + FcElementRestrict, + FcElementLang, + FcElementSelectfont, FcElementAcceptfont, FcElementRejectfont, @@ -359,6 +362,9 @@ { "default", FcElementDefault }, { "family", FcElementFamily }, + { "restrict", FcElementRestrict }, + { "lang", FcElementLang }, + { "selectfont", FcElementSelectfont }, { "acceptfont", FcElementAcceptfont }, { "rejectfont", FcElementRejectfont }, @@ -430,6 +436,9 @@ FcVStackPrefer, FcVStackAccept, FcVStackDefault, + + FcVStackRestrict, + FcVStackLang, FcVStackInteger, FcVStackDouble, @@ -730,6 +739,7 @@ case FcVStackField: case FcVStackConstant: case FcVStackGlob: + case FcVStackLang: FcStrFree (vstack->u.string); break; case FcVStackPattern: @@ -737,6 +747,7 @@ break; case FcVStackInteger: case FcVStackDouble: + case FcVStackRestrict: break; case FcVStackMatrix: FcMatrixFree (vstack->u.matrix); @@ -1346,12 +1357,200 @@ } static void +FcParseLang (FcConfigParse *parse) +{ + FcChar8 *s; + FcExpr *expr; + + if (!parse->pstack) + return; + s = FcStrBufDone (&parse->pstack->str); + if (!s) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + return; + } + expr = FcExprCreateString (s); + FcStrFree (s); + if (expr) + FcVStackPushExpr (parse, FcVStackLang, expr); +} + +static void +FcParseRestrict (FcConfigParse *parse, FcVStackTag tag) +{ + FcExpr *family = 0; + FcStrSet *lang = 0; + FcVStack *vstack; + FcFontLang *fl = NULL; + FcExpr *expr; + + while ((vstack = FcVStackPop (parse))) + { + switch (vstack->tag) { + case FcVStackFamily: + if (family) + FcExprDestroy (family); + family = vstack->u.expr; + vstack->tag = FcVStackNone; + break; + case FcVStackLang: + if (!lang) + lang = 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 restrict"); + } + if ( lang ) + { + fl = (FcFontLang *)malloc (sizeof (FcFontLang)); + + if ( fl ) + { + int len = strlen ( (char *)family->u.sval ); + fl->family = (FcChar8 *)malloc ( sizeof ( char ) * ( len + 1 )); + strncpy ( (char *)fl->family, (char *)family->u.sval, len ); + fl->family[len] = '\0'; + fl->langs = lang; + fl->next = NULL; + } + } + if ( fl ) + { + expr = FcExprCreateInteger ((int)fl); + if (expr) + FcVStackPushExpr (parse, FcVStackRestrict, expr); + } +} + +static void +FcFontLangDestroy(FcFontLang *fl) +{ + FcFontLang *cur = fl; + + while (fl) + { + cur = fl; + fl = 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 = (FcRestrict *)malloc ( sizeof ( FcRestrict )); + + if ( new ) + { + int len = strlen ( (char *)family->u.sval ); + int i; + + new->alias = (FcChar8 *)malloc ( sizeof ( char ) * ( len + 1 )); + if ( new->alias ) + { + strncpy ((char *)new->alias, (char *)family->u.sval, len); + new->alias[len] = '\0'; + } + else + { + free (new); + return; + } + new->family = NULL; + new->next = parse->config->restrictFont; + parse->config->restrictFont = new; + + /* + * Add FontLang structure in alphabetical order based on family + * to the restrict list + */ + while ( fl ) + { + FcFontLang *next = fl->next; + + fl->next = NULL; + + if ( !new->family ) + new->family = fl; + else + { + FcFontLang *ptr = new->family; + FcFontLang *last = NULL; + + while ( ptr ) + { + if ( strcasecmp ( (char *)fl->family, (char *)ptr->family) < 0) + { + fl->next = ptr; + if ( !last ) + new->family = fl; + else + last->next = fl; + break; + } + else + { + last = ptr; + ptr = ptr->next; + + if ( !ptr ) + last->next = fl; + } + } + } + fl = next; + } + + for ( i = 0; i < 26; i++ ) + new->az[i] = NULL; + + fl = new->family; + while ( fl ) + { + int pos = (int)(fl->family[0]) - (int)'A'; + if ( !new->az[pos] ) + { + new->az[pos] = fl; + } + fl = fl->next; + } + } +} + +static void FcParseAlias (FcConfigParse *parse) { FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0; FcEdit *edit = 0, *next; FcVStack *vstack; FcTest *test; + FcFontLang *fl = NULL; + FcFontLang *tmp; while ((vstack = FcVStackPop (parse))) { @@ -1373,6 +1572,13 @@ vstack->tag = FcVStackNone; } break; + case FcVStackRestrict: + tmp = (FcFontLang *)(vstack->u.expr->u.ival); + FcExprDestroy (vstack->u.expr); + tmp->next = fl; + fl = tmp; + vstack->tag = FcVStackNone; + break; case FcVStackPrefer: if (prefer) FcExprDestroy (prefer); @@ -1446,6 +1652,11 @@ else FcExprDestroy (def); } + if (fl) + { + FcRestrictCreate(parse, fl, family); + FcExprDestroy (family); + } if (edit) { test = FcTestCreate (parse, FcMatchPattern, @@ -1473,6 +1684,7 @@ break; case FcVStackString: case FcVStackFamily: + case FcVStackLang: expr = FcExprCreateString (vstack->u.string); break; case FcVStackField: @@ -2099,6 +2311,12 @@ case FcElementFamily: FcParseFamily (parse); break; + case FcElementRestrict: + FcParseRestrict (parse, FcVStackLang); + break; + case FcElementLang: + FcParseLang (parse); + break; case FcElementTest: FcParseTest (parse);
Attachment:
signature.asc
Description: Ceci est une partie de message =?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e?=
_______________________________________________ Fontconfig mailing list Fontconfig@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/fontconfig