[Fontconfig] fontconfig: Branch 'master' - 10 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Dec 28 01:01:33 PST 2010


 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>&lt;int&gt;</literal> element of
 an Unicode code point or more.
   </para></refsect2>
+  <refsect2><title><literal>&lt;langset&gt;</literal></title><para>
+This element holds at least one <literal>&lt;string&gt;</literal> element of
+a RFC-3066-style languages or more.
+  </para></refsect2>
   <refsect2><title><literal>&lt;name&gt;</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>&lt;double&gt;</literal> elements of an affine
 transformation.
   </para></refsect2>
+  <refsect2><title><literal>&lt;range&gt;</literal></title><para>
+This element holds the two <literal>&lt;int&gt;</literal> elements of a range
+representation.
+  </para></refsect2>
+  <refsect2><title><literal>&lt;charset&gt;</literal></title><para>
+This element holds at least one <literal>&lt;int&gt;</literal> element of
+an Unicode code point or more.
+  </para></refsect2>
   <refsect2><title><literal>&lt;name&gt;</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;


More information about the Fontconfig mailing list