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>
...
This commit is contained in:
Akira TAGOH 2010-12-06 12:10:17 +09:00
parent 0d47cfabd8
commit 857b7efe1e
6 changed files with 185 additions and 9 deletions

View File

@ -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)>

View File

@ -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-@LIBT_CURRENT_MINUS_AGE@.dll; \
echo VERSION @LIBT_CURRENT@.@LIBT_REVISION@) >$@

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -133,6 +133,18 @@ FcExprCreateBool (FcConfig *config, FcBool b)
return e;
}
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)
{
@ -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;
@ -741,6 +761,18 @@ FcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix)
return FcTrue;
}
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_)
{
@ -752,6 +784,20 @@ FcVStackPushBool (FcConfigParse *parse, FcBool bool_)
return FcTrue;
}
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)
{
@ -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;