Behdad Esfahbod
2010-Dec-28 09:01 UTC
[Fontconfig] fontconfig: Branch ''master'' - 10 commits
configure.in | 2 doc/fclangset.fncs | 30 +++++ doc/fontconfig-user.sgml | 12 ++ fontconfig/fontconfig.h | 9 + fonts.dtd | 11 + src/Makefile.am | 4 src/fccfg.c | 43 +++++++ src/fcdbg.c | 8 + src/fcint.h | 10 + src/fclang.c | 62 ++++++++++ src/fcxml.c | 277 +++++++++++++++++++++++++++++++++++++++++++---- 11 files changed, 441 insertions(+), 27 deletions(-) New commits: commit e63f90ce74d1f2c1e22959cb2ed97120eff3867f Author: Behdad Esfahbod <behdad at behdad.org> Date: Tue Dec 28 02:58:16 2010 -0600 Doc nit diff --git a/doc/fclangset.fncs b/doc/fclangset.fncs index fd1634f..8f9678e 100644 --- a/doc/fclangset.fncs +++ b/doc/fclangset.fncs @@ -62,7 +62,7 @@ two or three letter language from ISO 639 and Tt is a territory from ISO @FUNC@ FcLangSetDel @TYPE1@ FcLangSet * @ARG1@ ls @TYPE2@ const FcChar8 * @ARG2@ lang - at PURPOSE@ remove a language from a langset + at PURPOSE@ delete a language from a langset @DESC@ <parameter>lang</parameter> is removed from <parameter>ls</parameter>. <parameter>lang</parameter> should be of the form Ll-Tt where Ll is a @@ -85,7 +85,7 @@ Returns a set including only those languages found in either <parameter>ls_a</pa @TYPE2@ const FcLangSet * @ARG2@ ls_b @PURPOSE@ Subtract langsets @DESC@ -Returns a set including only those languages found in <parameter>ls_a</parameter> but not <parameter>ls_b</parameter>. +Returns a set including only those languages found in <parameter>ls_a</parameter> but not in <parameter>ls_b</parameter>. @@ @RET@ FcLangResult commit 43bf659eedb3eeff75d219864af475dcadcf6983 Author: Behdad Esfahbod <behdad at behdad.org> Date: Tue Dec 28 02:55:31 2010 -0600 Skip <range> elements with begin > end diff --git a/src/fcxml.c b/src/fcxml.c index 1aa3e4c..ff30b7b 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -1148,10 +1148,13 @@ FcParseBlank (FcConfigParse *parse) goto bail; break; case FcVStackRange: - for (i = v->u.range.begin; i <= v->u.range.end; i++) + if (v->u.range.begin <= v->u.range.end) { - if (!FcBlanksAdd (parse->config->blanks, i)) - goto bail; + for (i = v->u.range.begin; i <= v->u.range.end; i++) + { + if (!FcBlanksAdd (parse->config->blanks, i)) + goto bail; + } } break; default: @@ -1428,14 +1431,17 @@ FcParseCharSet (FcConfigParse *parse) n++; break; case FcVStackRange: - for (i = vstack->u.range.begin; i <= vstack->u.range.end; i++) + if (vstack->u.range.begin <= vstack->u.range.end) { - if (!FcCharSetAddChar (charset, i)) - { - FcConfigMessage (parse, FcSevereWarning, "invalid character: 0x%04x", i); - } - else - n++; + for (i = vstack->u.range.begin; i <= vstack->u.range.end; i++) + { + if (!FcCharSetAddChar (charset, i)) + { + FcConfigMessage (parse, FcSevereWarning, "invalid character: 0x%04x", i); + } + else + n++; + } } break; default: commit 8c625aa01f0ad95b1c06acb079921c209906f3b4 Author: Behdad Esfahbod <behdad at behdad.org> Date: Tue Dec 28 02:52:06 2010 -0600 Add <range> support for <blank> into the DTD diff --git a/fonts.dtd b/fonts.dtd index d9d4b22..5f072ee 100644 --- a/fonts.dtd +++ b/fonts.dtd @@ -63,7 +63,7 @@ the set of valid Unicode chars. This idea was borrowed from Mozilla --> -<!ELEMENT blank (int)*> +<!ELEMENT blank (int|range)*> <!-- Aliases are just a special case for multiple match elements commit 549c9962a48cd728116c8f39db31c58043236ff0 Merge: 30fd4fa... fa269cf... Author: Behdad Esfahbod <behdad at behdad.org> Date: Tue Dec 28 02:50:16 2010 -0600 Allow editing charset and lang in target="scan" Merge commit ''fa269cf812ee304534b0e4c44662202496008db0'' Fixes: Bug 31969 - Can''t modify charset in target="scan" Bug 23758 - Can''t modify lang in target="scan" commit 30fd4fac9ca2238f84608c23836cab219640d9c1 Author: Behdad Esfahbod <behdad at behdad.org> Date: Tue Dec 28 01:28:39 2010 -0600 Bump version diff --git a/configure.in b/configure.in index 5d92b5f..d128fb0 100644 --- a/configure.in +++ b/configure.in @@ -33,7 +33,7 @@ dnl This is the package version number, not the shared library dnl version. This same version number must appear in fontconfig/fontconfig.h dnl Yes, it is a pain to synchronize version numbers. Unfortunately, it''s dnl not possible to extract the version number here from fontconfig.h -AM_INIT_AUTOMAKE(fontconfig, 2.8.0) +AM_INIT_AUTOMAKE(fontconfig, 2.8.90) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) AM_MAINTAINER_MODE commit fa269cf812ee304534b0e4c44662202496008db0 Author: Akira TAGOH <akira at tagoh.org> Date: Thu Dec 9 11:57:24 2010 +0900 add some documents diff --git a/doc/fclangset.fncs b/doc/fclangset.fncs index f9d578e..fd1634f 100644 --- a/doc/fclangset.fncs +++ b/doc/fclangset.fncs @@ -58,6 +58,36 @@ two or three letter language from ISO 639 and Tt is a territory from ISO 3166. @@ + at RET@ FcBool + at FUNC@ FcLangSetDel + at TYPE1@ FcLangSet * @ARG1@ ls + at TYPE2@ const FcChar8 * @ARG2@ lang + at PURPOSE@ remove a language from a langset + at DESC@ +<parameter>lang</parameter> is removed from <parameter>ls</parameter>. +<parameter>lang</parameter> should be of the form Ll-Tt where Ll is a +two or three letter language from ISO 639 and Tt is a territory from ISO +3166. +@@ + + at RET@ FcLangSet * + at FUNC@ FcLangSetUnion + at TYPE1@ const FcLangSet * @ARG1@ ls_a + at TYPE2@ const FcLangSet * @ARG2@ ls_b + at PURPOSE@ Add langsets + at DESC@ +Returns a set including only those languages found in either <parameter>ls_a</parameter> or <parameter>ls_b</parameter>. +@@ + + at RET@ FcLangSet * + at FUNC@ FcLangSetSubtract + at TYPE1@ const FcLangSet * @ARG1@ ls_a + at TYPE2@ const FcLangSet * @ARG2@ ls_b + at PURPOSE@ Subtract langsets + at DESC@ +Returns a set including only those languages found in <parameter>ls_a</parameter> but not <parameter>ls_b</parameter>. +@@ + @RET@ FcLangResult @FUNC@ FcLangSetCompare @TYPE1@ const FcLangSet * @ARG1@ ls_a diff --git a/doc/fontconfig-user.sgml b/doc/fontconfig-user.sgml index ce6f158..b870825 100644 --- a/doc/fontconfig-user.sgml +++ b/doc/fontconfig-user.sgml @@ -440,6 +440,10 @@ representation. This element holds at least one <literal><int></literal> element of an Unicode code point or more. </para></refsect2> + <refsect2><title><literal><langset></literal></title><para> +This element holds at least one <literal><string></literal> element of +a RFC-3066-style languages or more. + </para></refsect2> <refsect2><title><literal><name></literal></title><para> Holds a property name. Evaluates to the first value from the property of the font, not the pattern. commit 3c862aad9f49be4b098cb679a67449c85b58f1f5 Author: Akira TAGOH <akira at tagoh.org> Date: Mon Dec 6 12:38:18 2010 +0900 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> 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 @@ <!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)> 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 @@ -146,6 +146,18 @@ FcExprCreateCharSet (FcConfig *config, FcCharSet *charset) } 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); @@ -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: @@ -799,6 +821,20 @@ FcVStackPushCharSet (FcConfigParse *parse, FcCharSet *charset) } 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); @@ -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: commit d975cdda782bb88c8bb6706889a554b2afb9f939 Author: Akira TAGOH <akira at tagoh.org> Date: Mon Dec 6 12:18:23 2010 +0900 Add the range support in blank element diff --git a/src/fcxml.c b/src/fcxml.c index 94e2d4b..4d07f9d 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -1092,30 +1092,37 @@ FcStartElement(void *userData, const XML_Char *name, const XML_Char **attr) static void FcParseBlank (FcConfigParse *parse) { - int n = FcVStackElements (parse); + int n = FcVStackElements (parse); + FcChar32 i; while (n-- > 0) { FcVStack *v = FcVStackFetch (parse, n); - if (v->tag != FcVStackInteger) - FcConfigMessage (parse, FcSevereError, "non-integer blank"); - else + if (!parse->config->blanks) { + parse->config->blanks = FcBlanksCreate (); if (!parse->config->blanks) - { - parse->config->blanks = FcBlanksCreate (); - if (!parse->config->blanks) - { - FcConfigMessage (parse, FcSevereError, "out of memory"); - break; - } - } + goto bail; + } + switch (v->tag) { + case FcVStackInteger: if (!FcBlanksAdd (parse->config->blanks, v->u.integer)) + goto bail; + break; + case FcVStackRange: + for (i = v->u.range.begin; i <= v->u.range.end; i++) { - FcConfigMessage (parse, FcSevereError, "out of memory"); - break; + if (!FcBlanksAdd (parse->config->blanks, i)) + goto bail; } + break; + default: + FcConfigMessage (parse, FcSevereError, "invalid element in blank"); + break; } } + return; + bail: + FcConfigMessage (parse, FcSevereError, "out of memory"); } static void commit 51e352a1bde91348888202539639a5a2d0d506d4 Author: Akira TAGOH <akira at tagoh.org> Date: Thu Dec 9 11:32:26 2010 +0900 add some document for range and charset. diff --git a/doc/fontconfig-user.sgml b/doc/fontconfig-user.sgml index 219d906..ce6f158 100644 --- a/doc/fontconfig-user.sgml +++ b/doc/fontconfig-user.sgml @@ -432,6 +432,14 @@ instead of -.5). This element holds the four <literal><double></literal> elements of an affine transformation. </para></refsect2> + <refsect2><title><literal><range></literal></title><para> +This element holds the two <literal><int></literal> elements of a range +representation. + </para></refsect2> + <refsect2><title><literal><charset></literal></title><para> +This element holds at least one <literal><int></literal> element of +an Unicode code point or more. + </para></refsect2> <refsect2><title><literal><name></literal></title><para> Holds a property name. Evaluates to the first value from the property of the font, not the pattern. commit 857b7efe1e301f670329c6836da52fbab8c5df66 Author: Akira TAGOH <akira at tagoh.org> Date: Mon Dec 6 12:10:17 2010 +0900 Add charset editing feature. The syntax to add any characters to the charset table looks like: <match target="scan"> <test name="family"> <string>Buggy Sans</string> </test> <edit name="charset" mode="assign"> <plus> <name>charset</name> <charset> <int>0x3220</int> <!-- PARENTHESIZED IDEOGRAPH ONE --> </charset> </plus> </edit> </match> To remove any characters from the charset table: <match target="scan"> <test name="family"> <string>Buggy Sans</string> </test> <edit name="charset" mode="assign"> <minus> <name>charset</name> <charset> <int>0x06CC</int> <!-- ARABIC LETTER FARSI YEH --> <int>0x06D2</int> <!-- ARABIC LETTER YEH BARREE --> <int>0x06D3</int> <!-- ARABIC LETTER YEH BARREE WITH HAMZA ABOVE --> </charset> </minus> </edit> </match> You could also use the range element for convenience: ... <charset> <int>0x06CC</int> <!-- ARABIC LETTER FARSI YEH --> <range> <int>0x06D2</int> <!-- ARABIC LETTER YEH BARREE --> <int>0x06D3</int> <!-- ARABIC LETTER YEH BARREE WITH HAMZA ABOVE --> </range> </charset> ... diff --git a/fonts.dtd b/fonts.dtd index cbdfdab..5f21e35 100644 --- a/fonts.dtd +++ b/fonts.dtd @@ -196,8 +196,8 @@ <!ATTLIST string xml:space (default|preserve) ''preserve''> <!ELEMENT matrix (double,double,double,double)> <!ELEMENT bool (#PCDATA)> -<!ELEMENT charset (#PCDATA)> -<!ATTLIST charset xml:space (default|preserve) ''preserve''> +<!ELEMENT charset (int|range)*> +<!ELEMENT range (int,int)> <!ELEMENT name (#PCDATA)> <!ATTLIST name xml:space (default|preserve) ''preserve''> <!ELEMENT const (#PCDATA)> diff --git a/src/Makefile.am b/src/Makefile.am index 59b9c75..96500b4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -140,7 +140,7 @@ PUBLIC_FILES = \ $(top_srcdir)/fontconfig/fontconfig.h \ $(top_srcdir)/src/fcdeprecate.h \ $(top_srcdir)/fontconfig/fcprivate.h - + PUBLIC_FT_FILES = \ $(top_srcdir)/fontconfig/fcfreetype.h @@ -160,7 +160,7 @@ fontconfig.def: $(PUBLIC_FILES) $(PUBLIC_FT_FILES) echo Generating $@ (echo EXPORTS; \ (cat $(PUBLIC_FILES) $(PUBLIC_FT_FILES) || echo ''FcERROR ()'' ) | \ - grep ''^Fc[^ ]* *('' | sed -e ''s/ *(.*$$//'' -e ''s/^/ /'' | \ + grep ''^Fc[^ ]* *('' | sed -e ''s/ *(.*$$//'' -e ''s/^/ /'' | \ sort; \ echo LIBRARY libfontconfig- at LIBT_CURRENT_MINUS_AGE@.dll; \ echo VERSION @LIBT_CURRENT at .@LIBT_REVISION@) >$@ diff --git a/src/fccfg.c b/src/fccfg.c index 19a9fef..ad9f7d2 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -1036,6 +1036,25 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) break; } break; + case FcTypeCharSet: + switch (e->op) { + case FcOpPlus: + v.type = FcTypeCharSet; + v.u.c = FcCharSetUnion (vl.u.c, vr.u.c); + if (!v.u.c) + v.type = FcTypeVoid; + break; + case FcOpMinus: + v.type = FcTypeCharSet; + v.u.c = FcCharSetSubtract (vl.u.c, vr.u.c); + if (!v.u.c) + 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 fc3b596..79e1953 100644 --- a/src/fcdbg.c +++ b/src/fcdbg.c @@ -160,6 +160,7 @@ FcOpPrint (FcOp op) case FcOpDouble: printf ("Double"); break; case FcOpString: printf ("String"); break; case FcOpMatrix: printf ("Matrix"); break; + case FcOpRange: printf ("Range"); break; case FcOpBool: printf ("Bool"); break; case FcOpCharSet: printf ("CharSet"); break; case FcOpField: printf ("Field"); break; @@ -210,6 +211,7 @@ FcExprPrint (const FcExpr *expr) expr->u.mval->xy, expr->u.mval->yx, expr->u.mval->yy); break; + case FcOpRange: break; case FcOpBool: printf ("%s", expr->u.bval ? "true" : "false"); break; case FcOpCharSet: printf ("charset\n"); break; case FcOpNil: printf ("nil\n"); break; diff --git a/src/fcint.h b/src/fcint.h index 2bc7878..9519fff 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, FcOpBool, FcOpCharSet, + FcOpInteger, FcOpDouble, FcOpString, FcOpMatrix, FcOpRange, FcOpBool, FcOpCharSet, FcOpNil, FcOpField, FcOpConst, FcOpAssign, FcOpAssignReplace, @@ -507,6 +507,13 @@ typedef struct _FcFileTime { typedef struct _FcCharMap FcCharMap; +typedef struct _FcRange FcRange; + +struct _FcRange { + FcChar32 begin; + FcChar32 end; +}; + /* fcblanks.c */ /* fccache.c */ diff --git a/src/fcxml.c b/src/fcxml.c index 2bd67bf..94e2d4b 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -134,6 +134,18 @@ FcExprCreateBool (FcConfig *config, FcBool b) } static FcExpr * +FcExprCreateCharSet (FcConfig *config, FcCharSet *charset) +{ + FcExpr *e = FcConfigAllocExpr (config); + if (e) + { + e->op = FcOpCharSet; + e->u.cval = FcCharSetCopy (charset); + } + return e; +} + +static FcExpr * FcExprCreateField (FcConfig *config, const char *field) { FcExpr *e = FcConfigAllocExpr (config); @@ -185,6 +197,8 @@ FcExprDestroy (FcExpr *e) case FcOpMatrix: FcMatrixFree (e->u.mval); break; + case FcOpRange: + break; case FcOpCharSet: FcCharSetDestroy (e->u.cval); break; @@ -277,8 +291,9 @@ typedef enum _FcElement { FcElementDouble, FcElementString, FcElementMatrix, + FcElementRange, FcElementBool, - FcElementCharset, + FcElementCharSet, FcElementName, FcElementConst, FcElementOr, @@ -338,8 +353,9 @@ static const struct { { "double", FcElementDouble }, { "string", FcElementString }, { "matrix", FcElementMatrix }, + { "range", FcElementRange }, { "bool", FcElementBool }, - { "charset", FcElementCharset }, + { "charset", FcElementCharSet }, { "name", FcElementName }, { "const", FcElementConst }, { "or", FcElementOr }, @@ -401,7 +417,9 @@ typedef enum _FcVStackTag { FcVStackInteger, FcVStackDouble, FcVStackMatrix, + FcVStackRange, FcVStackBool, + FcVStackCharSet, FcVStackTest, FcVStackExpr, @@ -418,7 +436,9 @@ typedef struct _FcVStack { int integer; double _double; FcMatrix *matrix; + FcRange range; FcBool bool_; + FcCharSet *charset; FcTest *test; FcQual qual; @@ -742,6 +762,18 @@ FcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix) } static FcBool +FcVStackPushRange (FcConfigParse *parse, FcRange *range) +{ + FcVStack *vstack = FcVStackCreateAndPush (parse); + if (!vstack) + return FcFalse; + vstack->u.range.begin = range->begin; + vstack->u.range.end = range->end; + vstack->tag = FcVStackRange; + return FcTrue; +} + +static FcBool FcVStackPushBool (FcConfigParse *parse, FcBool bool_) { FcVStack *vstack = FcVStackCreateAndPush (parse); @@ -753,6 +785,20 @@ FcVStackPushBool (FcConfigParse *parse, FcBool bool_) } static FcBool +FcVStackPushCharSet (FcConfigParse *parse, FcCharSet *charset) +{ + FcVStack *vstack; + if (!charset) + return FcFalse; + vstack = FcVStackCreateAndPush (parse); + if (!vstack) + return FcFalse; + vstack->u.charset = charset; + vstack->tag = FcVStackCharSet; + return FcTrue; +} + +static FcBool FcVStackPushTest (FcConfigParse *parse, FcTest *test) { FcVStack *vstack = FcVStackCreateAndPush (parse); @@ -843,8 +889,12 @@ FcVStackPopAndDestroy (FcConfigParse *parse) case FcVStackMatrix: FcMatrixFree (vstack->u.matrix); break; + case FcVStackRange: case FcVStackBool: break; + case FcVStackCharSet: + FcCharSetDestroy (vstack->u.charset); + break; case FcVStackTest: FcTestDestroy (vstack->u.test); break; @@ -1241,6 +1291,49 @@ FcParseMatrix (FcConfigParse *parse) FcVStackPushMatrix (parse, &m); } +static void +FcParseRange (FcConfigParse *parse) +{ + FcVStack *vstack; + FcRange r; + FcChar32 n; + int count = 1; + + while ((vstack = FcVStackPeek (parse))) + { + if (count < 0) + { + FcConfigMessage (parse, FcSevereError, "too many elements in range"); + return; + } + switch (vstack->tag) { + case FcVStackInteger: + n = vstack->u.integer; + break; + default: + FcConfigMessage (parse, FcSevereError, "invalid element in range"); + break; + } + if (count == 1) + r.end = n; + else + r.begin = n; + count--; + FcVStackPopAndDestroy (parse); + } + if (count < 0) + { + if (r.begin > r.end) + { + FcConfigMessage (parse, FcSevereError, "invalid range"); + return; + } + FcVStackPushRange (parse, &r); + } + else + FcConfigMessage (parse, FcSevereError, "invalid range"); +} + static FcBool FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool_) { @@ -1269,6 +1362,48 @@ FcParseBool (FcConfigParse *parse) FcStrBufDestroy (&parse->pstack->str); } +static void +FcParseCharSet (FcConfigParse *parse) +{ + FcVStack *vstack; + FcCharSet *charset = FcCharSetCreate (); + FcChar32 i; + int n = 0; + + while ((vstack = FcVStackPeek (parse))) + { + switch (vstack->tag) { + case FcVStackInteger: + if (!FcCharSetAddChar (charset, vstack->u.integer)) + { + FcConfigMessage (parse, FcSevereWarning, "invalid character: 0x%04x", vstack->u.integer); + } + else + n++; + break; + case FcVStackRange: + for (i = vstack->u.range.begin; i <= vstack->u.range.end; i++) + { + if (!FcCharSetAddChar (charset, i)) + { + FcConfigMessage (parse, FcSevereWarning, "invalid character: 0x%04x", i); + } + else + n++; + } + break; + default: + FcConfigMessage (parse, FcSevereError, "invalid element in charset"); + break; + } + FcVStackPopAndDestroy (parse); + } + if (n > 0) + FcVStackPushCharSet (parse, charset); + else + FcCharSetDestroy (charset); +} + static FcBool FcConfigLexBinding (FcConfigParse *parse, const FcChar8 *binding_string, @@ -1515,9 +1650,14 @@ FcPopExpr (FcConfigParse *parse) case FcVStackMatrix: expr = FcExprCreateMatrix (parse->config, vstack->u.matrix); break; + case FcVStackRange: + break; case FcVStackBool: expr = FcExprCreateBool (parse->config, vstack->u.bool_); break; + case FcVStackCharSet: + expr = FcExprCreateCharSet (parse->config, vstack->u.charset); + break; case FcVStackTest: break; case FcVStackExpr: @@ -1934,6 +2074,11 @@ FcPopValue (FcConfigParse *parse) value.u.b = vstack->u.bool_; value.type = FcTypeBool; break; + case FcVStackCharSet: + value.u.c = FcCharSetCopy (vstack->u.charset); + if (value.u.c) + value.type = FcTypeCharSet; + break; default: FcConfigMessage (parse, FcSevereWarning, "unknown pattern element %d", vstack->tag); @@ -2199,11 +2344,14 @@ FcEndElement(void *userData, const XML_Char *name) case FcElementMatrix: FcParseMatrix (parse); break; + case FcElementRange: + FcParseRange (parse); + break; case FcElementBool: FcParseBool (parse); break; - case FcElementCharset: -/* FcParseCharset (parse); */ + case FcElementCharSet: + FcParseCharSet (parse); break; case FcElementSelectfont: break;