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);
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);
<!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
<!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'>
<!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)>
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;
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;
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;
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;
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,
FcMatrix *mval;
FcBool bval;
FcCharSet *cval;
+ FcLangSet *lval;
FcObject object;
FcChar8 *constant;
struct {
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)
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)
{
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"
}
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)
{
FcExpr *e = FcConfigAllocExpr (config);
case FcOpCharSet:
FcCharSetDestroy (e->u.cval);
break;
+ case FcOpLangSet:
+ FcLangSetDestroy (e->u.lval);
+ break;
case FcOpBool:
break;
case FcOpField:
FcElementRange,
FcElementBool,
FcElementCharSet,
+ FcElementLangSet,
FcElementName,
FcElementConst,
FcElementOr,
{ "range", FcElementRange },
{ "bool", FcElementBool },
{ "charset", FcElementCharSet },
+ { "langset", FcElementLangSet },
{ "name", FcElementName },
{ "const", FcElementConst },
{ "or", FcElementOr },
FcVStackRange,
FcVStackBool,
FcVStackCharSet,
+ FcVStackLangSet,
FcVStackTest,
FcVStackExpr,
FcRange range;
FcBool bool_;
FcCharSet *charset;
+ FcLangSet *langset;
FcTest *test;
FcQual qual;
case FcOpCharSet:
FcTypecheckValue (parse, FcTypeCharSet, type);
break;
+ case FcOpLangSet:
+ FcTypecheckValue (parse, FcTypeLangSet, type);
+ break;
case FcOpNil:
break;
case FcOpField:
}
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)
{
FcVStack *vstack = FcVStackCreateAndPush (parse);
case FcVStackCharSet:
FcCharSetDestroy (vstack->u.charset);
break;
+ case FcVStackLangSet:
+ FcLangSetDestroy (vstack->u.langset);
+ break;
case FcVStackTest:
FcTestDestroy (vstack->u.test);
break;
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,
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:
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);
case FcElementCharSet:
FcParseCharSet (parse);
break;
+ case FcElementLangSet:
+ FcParseLangSet (parse);
+ break;
case FcElementSelectfont:
break;
case FcElementAcceptfont: