Add editing langset feature.
The syntax to add any langset to the langset table looks like: <match target="scan"> <test name="family"> <string>Buggy Sans</string> </test> <edit name="lang" mode="assign"> <plus> <name>lang</name> <langset> <string>zh-cn</string> <string>zh-tw</string> </langset> </plus> </edit> </match> To remove any langset from the langset table: <match target="scan"> <test name="family"> <string>Buggy Sans</string> </test> <edit name="lang" mode="assign"> <minus> <name>lang</name> <langset> <string>ja</string> </langset> </minus> </edit> </match>
This commit is contained in:
parent
d975cdda78
commit
3c862aad9f
|
@ -584,6 +584,9 @@ FcLangSetCopy (const FcLangSet *ls);
|
|||
FcPublic FcBool
|
||||
FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang);
|
||||
|
||||
FcPublic FcBool
|
||||
FcLangSetDel (FcLangSet *ls, const FcChar8 *lang);
|
||||
|
||||
FcPublic FcLangResult
|
||||
FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang);
|
||||
|
||||
|
@ -602,6 +605,12 @@ FcLangSetHash (const FcLangSet *ls);
|
|||
FcPublic FcStrSet *
|
||||
FcLangSetGetLangs (const FcLangSet *ls);
|
||||
|
||||
FcLangSet *
|
||||
FcLangSetUnion (const FcLangSet *a, const FcLangSet *b);
|
||||
|
||||
FcLangSet *
|
||||
FcLangSetSubtract (const FcLangSet *a, const FcLangSet *b);
|
||||
|
||||
/* fclist.c */
|
||||
FcPublic FcObjectSet *
|
||||
FcObjectSetCreate (void);
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
|
||||
<!ELEMENT pattern (patelt)*>
|
||||
|
||||
<!ENTITY % constant 'int|double|string|matrix|bool|charset|const'>
|
||||
<!ENTITY % constant 'int|double|string|matrix|bool|charset|langset|const'>
|
||||
|
||||
<!ELEMENT patelt (%constant;)*>
|
||||
<!ATTLIST patelt
|
||||
|
@ -122,7 +122,7 @@
|
|||
<!ELEMENT family (#PCDATA)>
|
||||
<!ATTLIST family xml:space (default|preserve) 'preserve'>
|
||||
|
||||
<!ENTITY % expr 'int|double|string|matrix|bool|charset
|
||||
<!ENTITY % expr 'int|double|string|matrix|bool|charset|langset
|
||||
|name|const
|
||||
|or|and|eq|not_eq|less|less_eq|more|more_eq|contains|not_contains
|
||||
|plus|minus|times|divide|not|if|floor|ceil|round|trunc'>
|
||||
|
@ -198,6 +198,7 @@
|
|||
<!ELEMENT bool (#PCDATA)>
|
||||
<!ELEMENT charset (int|range)*>
|
||||
<!ELEMENT range (int,int)>
|
||||
<!ELEMENT langset (string)*>
|
||||
<!ELEMENT name (#PCDATA)>
|
||||
<!ATTLIST name xml:space (default|preserve) 'preserve'>
|
||||
<!ELEMENT const (#PCDATA)>
|
||||
|
|
24
src/fccfg.c
24
src/fccfg.c
|
@ -897,6 +897,11 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
|
|||
v.u.c = e->u.cval;
|
||||
v = FcValueSave (v);
|
||||
break;
|
||||
case FcOpLangSet:
|
||||
v.type = FcTypeLangSet;
|
||||
v.u.l = e->u.lval;
|
||||
v = FcValueSave (v);
|
||||
break;
|
||||
case FcOpBool:
|
||||
v.type = FcTypeBool;
|
||||
v.u.b = e->u.bval;
|
||||
|
@ -1055,6 +1060,25 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case FcTypeLangSet:
|
||||
switch (e->op) {
|
||||
case FcOpPlus:
|
||||
v.type = FcTypeLangSet;
|
||||
v.u.l = FcLangSetUnion (vl.u.l, vr.u.l);
|
||||
if (!v.u.l)
|
||||
v.type = FcTypeVoid;
|
||||
break;
|
||||
case FcOpMinus:
|
||||
v.type = FcTypeLangSet;
|
||||
v.u.l = FcLangSetSubtract (vl.u.l, vr.u.l);
|
||||
if (!v.u.l)
|
||||
v.type = FcTypeVoid;
|
||||
break;
|
||||
default:
|
||||
v.type = FcTypeVoid;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
v.type = FcTypeVoid;
|
||||
break;
|
||||
|
|
|
@ -163,6 +163,7 @@ FcOpPrint (FcOp op)
|
|||
case FcOpRange: printf ("Range"); break;
|
||||
case FcOpBool: printf ("Bool"); break;
|
||||
case FcOpCharSet: printf ("CharSet"); break;
|
||||
case FcOpLangSet: printf ("LangSet"); break;
|
||||
case FcOpField: printf ("Field"); break;
|
||||
case FcOpConst: printf ("Const"); break;
|
||||
case FcOpAssign: printf ("Assign"); break;
|
||||
|
@ -214,6 +215,11 @@ FcExprPrint (const FcExpr *expr)
|
|||
case FcOpRange: break;
|
||||
case FcOpBool: printf ("%s", expr->u.bval ? "true" : "false"); break;
|
||||
case FcOpCharSet: printf ("charset\n"); break;
|
||||
case FcOpLangSet:
|
||||
printf ("langset:");
|
||||
FcLangSetPrint(expr->u.lval);
|
||||
printf ("\n");
|
||||
break;
|
||||
case FcOpNil: printf ("nil\n"); break;
|
||||
case FcOpField: printf ("%s", FcObjectName(expr->u.object)); break;
|
||||
case FcOpConst: printf ("%s", expr->u.constant); break;
|
||||
|
|
|
@ -216,7 +216,7 @@ struct _FcPattern {
|
|||
fs->fonts[i])
|
||||
|
||||
typedef enum _FcOp {
|
||||
FcOpInteger, FcOpDouble, FcOpString, FcOpMatrix, FcOpRange, FcOpBool, FcOpCharSet,
|
||||
FcOpInteger, FcOpDouble, FcOpString, FcOpMatrix, FcOpRange, FcOpBool, FcOpCharSet, FcOpLangSet,
|
||||
FcOpNil,
|
||||
FcOpField, FcOpConst,
|
||||
FcOpAssign, FcOpAssignReplace,
|
||||
|
@ -239,6 +239,7 @@ typedef struct _FcExpr {
|
|||
FcMatrix *mval;
|
||||
FcBool bval;
|
||||
FcCharSet *cval;
|
||||
FcLangSet *lval;
|
||||
FcObject object;
|
||||
FcChar8 *constant;
|
||||
struct {
|
||||
|
|
62
src/fclang.c
62
src/fclang.c
|
@ -71,6 +71,20 @@ FcLangSetBitGet (const FcLangSet *ls,
|
|||
return ((ls->map[bucket] >> (id & 0x1f)) & 1) ? FcTrue : FcFalse;
|
||||
}
|
||||
|
||||
static void
|
||||
FcLangSetBitReset (FcLangSet *ls,
|
||||
unsigned int id)
|
||||
{
|
||||
int bucket;
|
||||
|
||||
id = fcLangCharSetIndices[id];
|
||||
bucket = id >> 5;
|
||||
if (bucket >= ls->map_size)
|
||||
return; /* shouldn't happen really */
|
||||
|
||||
ls->map[bucket] &= ~((FcChar32) 1 << (id & 0x1f));
|
||||
}
|
||||
|
||||
FcLangSet *
|
||||
FcFreeTypeLangSet (const FcCharSet *charset,
|
||||
const FcChar8 *exclusiveLang)
|
||||
|
@ -400,6 +414,23 @@ FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang)
|
|||
return FcStrSetAdd (ls->extra, lang);
|
||||
}
|
||||
|
||||
FcBool
|
||||
FcLangSetDel (FcLangSet *ls, const FcChar8 *lang)
|
||||
{
|
||||
int id;
|
||||
|
||||
id = FcLangSetIndex (lang);
|
||||
if (id >= 0)
|
||||
{
|
||||
FcLangSetBitReset (ls, id);
|
||||
}
|
||||
else if (ls->extra)
|
||||
{
|
||||
FcStrSetDel (ls->extra, lang);
|
||||
}
|
||||
return FcTrue;
|
||||
}
|
||||
|
||||
FcLangResult
|
||||
FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
|
||||
{
|
||||
|
@ -818,6 +849,37 @@ FcLangSetGetLangs (const FcLangSet *ls)
|
|||
return langs;
|
||||
}
|
||||
|
||||
static FcLangSet *
|
||||
FcLangSetOperate(const FcLangSet *a,
|
||||
const FcLangSet *b,
|
||||
FcBool (*func) (FcLangSet *ls,
|
||||
const FcChar8 *s))
|
||||
{
|
||||
FcLangSet *langset = FcLangSetCopy (a);
|
||||
FcStrList *sl = FcStrListCreate (FcLangSetGetLangs (b));
|
||||
FcChar8 *str;
|
||||
|
||||
while ((str = FcStrListNext (sl)))
|
||||
{
|
||||
func (langset, str);
|
||||
}
|
||||
FcStrListDone (sl);
|
||||
|
||||
return langset;
|
||||
}
|
||||
|
||||
FcLangSet *
|
||||
FcLangSetUnion (const FcLangSet *a, const FcLangSet *b)
|
||||
{
|
||||
return FcLangSetOperate(a, b, FcLangSetAdd);
|
||||
}
|
||||
|
||||
FcLangSet *
|
||||
FcLangSetSubtract (const FcLangSet *a, const FcLangSet *b)
|
||||
{
|
||||
return FcLangSetOperate(a, b, FcLangSetDel);
|
||||
}
|
||||
|
||||
#define __fclang__
|
||||
#include "fcaliastail.h"
|
||||
#include "fcftaliastail.h"
|
||||
|
|
80
src/fcxml.c
80
src/fcxml.c
|
@ -145,6 +145,18 @@ FcExprCreateCharSet (FcConfig *config, FcCharSet *charset)
|
|||
return e;
|
||||
}
|
||||
|
||||
static FcExpr *
|
||||
FcExprCreateLangSet (FcConfig *config, FcLangSet *langset)
|
||||
{
|
||||
FcExpr *e = FcConfigAllocExpr (config);
|
||||
if (e)
|
||||
{
|
||||
e->op = FcOpLangSet;
|
||||
e->u.lval = FcLangSetCopy (langset);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static FcExpr *
|
||||
FcExprCreateField (FcConfig *config, const char *field)
|
||||
{
|
||||
|
@ -202,6 +214,9 @@ FcExprDestroy (FcExpr *e)
|
|||
case FcOpCharSet:
|
||||
FcCharSetDestroy (e->u.cval);
|
||||
break;
|
||||
case FcOpLangSet:
|
||||
FcLangSetDestroy (e->u.lval);
|
||||
break;
|
||||
case FcOpBool:
|
||||
break;
|
||||
case FcOpField:
|
||||
|
@ -294,6 +309,7 @@ typedef enum _FcElement {
|
|||
FcElementRange,
|
||||
FcElementBool,
|
||||
FcElementCharSet,
|
||||
FcElementLangSet,
|
||||
FcElementName,
|
||||
FcElementConst,
|
||||
FcElementOr,
|
||||
|
@ -356,6 +372,7 @@ static const struct {
|
|||
{ "range", FcElementRange },
|
||||
{ "bool", FcElementBool },
|
||||
{ "charset", FcElementCharSet },
|
||||
{ "langset", FcElementLangSet },
|
||||
{ "name", FcElementName },
|
||||
{ "const", FcElementConst },
|
||||
{ "or", FcElementOr },
|
||||
|
@ -420,6 +437,7 @@ typedef enum _FcVStackTag {
|
|||
FcVStackRange,
|
||||
FcVStackBool,
|
||||
FcVStackCharSet,
|
||||
FcVStackLangSet,
|
||||
|
||||
FcVStackTest,
|
||||
FcVStackExpr,
|
||||
|
@ -439,6 +457,7 @@ typedef struct _FcVStack {
|
|||
FcRange range;
|
||||
FcBool bool_;
|
||||
FcCharSet *charset;
|
||||
FcLangSet *langset;
|
||||
|
||||
FcTest *test;
|
||||
FcQual qual;
|
||||
|
@ -571,6 +590,9 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
|
|||
case FcOpCharSet:
|
||||
FcTypecheckValue (parse, FcTypeCharSet, type);
|
||||
break;
|
||||
case FcOpLangSet:
|
||||
FcTypecheckValue (parse, FcTypeLangSet, type);
|
||||
break;
|
||||
case FcOpNil:
|
||||
break;
|
||||
case FcOpField:
|
||||
|
@ -798,6 +820,20 @@ FcVStackPushCharSet (FcConfigParse *parse, FcCharSet *charset)
|
|||
return FcTrue;
|
||||
}
|
||||
|
||||
static FcBool
|
||||
FcVStackPushLangSet (FcConfigParse *parse, FcLangSet *langset)
|
||||
{
|
||||
FcVStack *vstack;
|
||||
if (!langset)
|
||||
return FcFalse;
|
||||
vstack = FcVStackCreateAndPush (parse);
|
||||
if (!vstack)
|
||||
return FcFalse;
|
||||
vstack->u.langset = langset;
|
||||
vstack->tag = FcVStackLangSet;
|
||||
return FcTrue;
|
||||
}
|
||||
|
||||
static FcBool
|
||||
FcVStackPushTest (FcConfigParse *parse, FcTest *test)
|
||||
{
|
||||
|
@ -895,6 +931,9 @@ FcVStackPopAndDestroy (FcConfigParse *parse)
|
|||
case FcVStackCharSet:
|
||||
FcCharSetDestroy (vstack->u.charset);
|
||||
break;
|
||||
case FcVStackLangSet:
|
||||
FcLangSetDestroy (vstack->u.langset);
|
||||
break;
|
||||
case FcVStackTest:
|
||||
FcTestDestroy (vstack->u.test);
|
||||
break;
|
||||
|
@ -1411,6 +1450,36 @@ FcParseCharSet (FcConfigParse *parse)
|
|||
FcCharSetDestroy (charset);
|
||||
}
|
||||
|
||||
static void
|
||||
FcParseLangSet (FcConfigParse *parse)
|
||||
{
|
||||
FcVStack *vstack;
|
||||
FcLangSet *langset = FcLangSetCreate ();
|
||||
int n = 0;
|
||||
|
||||
while ((vstack = FcVStackPeek (parse)))
|
||||
{
|
||||
switch (vstack->tag) {
|
||||
case FcVStackString:
|
||||
if (!FcLangSetAdd (langset, vstack->u.string))
|
||||
{
|
||||
FcConfigMessage (parse, FcSevereWarning, "invalid langset: %s", vstack->u.string);
|
||||
}
|
||||
else
|
||||
n++;
|
||||
break;
|
||||
default:
|
||||
FcConfigMessage (parse, FcSevereError, "invalid element in langset");
|
||||
break;
|
||||
}
|
||||
FcVStackPopAndDestroy (parse);
|
||||
}
|
||||
if (n > 0)
|
||||
FcVStackPushLangSet (parse, langset);
|
||||
else
|
||||
FcLangSetDestroy (langset);
|
||||
}
|
||||
|
||||
static FcBool
|
||||
FcConfigLexBinding (FcConfigParse *parse,
|
||||
const FcChar8 *binding_string,
|
||||
|
@ -1665,6 +1734,9 @@ FcPopExpr (FcConfigParse *parse)
|
|||
case FcVStackCharSet:
|
||||
expr = FcExprCreateCharSet (parse->config, vstack->u.charset);
|
||||
break;
|
||||
case FcVStackLangSet:
|
||||
expr = FcExprCreateLangSet (parse->config, vstack->u.langset);
|
||||
break;
|
||||
case FcVStackTest:
|
||||
break;
|
||||
case FcVStackExpr:
|
||||
|
@ -2086,6 +2158,11 @@ FcPopValue (FcConfigParse *parse)
|
|||
if (value.u.c)
|
||||
value.type = FcTypeCharSet;
|
||||
break;
|
||||
case FcVStackLangSet:
|
||||
value.u.l = FcLangSetCopy (vstack->u.langset);
|
||||
if (value.u.l)
|
||||
value.type = FcTypeLangSet;
|
||||
break;
|
||||
default:
|
||||
FcConfigMessage (parse, FcSevereWarning, "unknown pattern element %d",
|
||||
vstack->tag);
|
||||
|
@ -2360,6 +2437,9 @@ FcEndElement(void *userData, const XML_Char *name)
|
|||
case FcElementCharSet:
|
||||
FcParseCharSet (parse);
|
||||
break;
|
||||
case FcElementLangSet:
|
||||
FcParseLangSet (parse);
|
||||
break;
|
||||
case FcElementSelectfont:
|
||||
break;
|
||||
case FcElementAcceptfont:
|
||||
|
|
Loading…
Reference in New Issue