From 3c862aad9f49be4b098cb679a67449c85b58f1f5 Mon Sep 17 00:00:00 2001 From: Akira TAGOH Date: Mon, 6 Dec 2010 12:38:18 +0900 Subject: [PATCH] Add editing langset feature. The syntax to add any langset to the langset table looks like: Buggy Sans lang zh-cn zh-tw To remove any langset from the langset table: Buggy Sans lang ja --- fontconfig/fontconfig.h | 9 +++++ fonts.dtd | 5 +-- src/fccfg.c | 24 +++++++++++++ src/fcdbg.c | 6 ++++ src/fcint.h | 3 +- src/fclang.c | 62 ++++++++++++++++++++++++++++++++ src/fcxml.c | 80 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 186 insertions(+), 3 deletions(-) diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h index 260955d..29a6ed4 100644 --- a/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig.h @@ -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); diff --git a/fonts.dtd b/fonts.dtd index 5f21e35..d9d4b22 100644 --- a/fonts.dtd +++ b/fonts.dtd @@ -107,7 +107,7 @@ - + - @@ -198,6 +198,7 @@ + diff --git a/src/fccfg.c b/src/fccfg.c index ad9f7d2..6812781 100644 --- a/src/fccfg.c +++ b/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; diff --git a/src/fcdbg.c b/src/fcdbg.c index 79e1953..cf2ff08 100644 --- a/src/fcdbg.c +++ b/src/fcdbg.c @@ -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; diff --git a/src/fcint.h b/src/fcint.h index 9519fff..3da6ec4 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -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 { diff --git a/src/fclang.c b/src/fclang.c index 1c78328..be42b58 100644 --- a/src/fclang.c +++ b/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" diff --git a/src/fcxml.c b/src/fcxml.c index 4d07f9d..1aa3e4c 100644 --- a/src/fcxml.c +++ b/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: -- 2.39.2