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:
parent
0d47cfabd8
commit
857b7efe1e
|
@ -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)>
|
||||
|
|
19
src/fccfg.c
19
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
156
src/fcxml.c
156
src/fcxml.c
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue