Change FcCharSetMerge API
To only work on writable charsets. Also, return a bool indicating whether the merge changed the charset. Also changes the implementation of FcCharSetMerge and FcCharSetIsSubset
This commit is contained in:
parent
b8860e2faf
commit
575ee6cddd
|
@ -98,17 +98,19 @@ Returns a set including only those chars found in either <parameter>a</parameter
|
||||||
Returns a set including only those chars found in <parameter>a</parameter> but not <parameter>b</parameter>.
|
Returns a set including only those chars found in <parameter>a</parameter> but not <parameter>b</parameter>.
|
||||||
@@
|
@@
|
||||||
|
|
||||||
@RET@ FcCharSet *
|
@RET@ FcBool
|
||||||
@FUNC@ FcCharSetMerge
|
@FUNC@ FcCharSetMerge
|
||||||
@TYPE1@ const FcCharSet * @ARG1@ a
|
@TYPE1@ FcCharSet * @ARG1@ a
|
||||||
@TYPE2@ const FcCharSet * @ARG2@ b
|
@TYPE2@ const FcCharSet * @ARG2@ b
|
||||||
|
@TYPE3@ FcBool * @ARG3@ changed
|
||||||
@PURPOSE@ Merge charsets
|
@PURPOSE@ Merge charsets
|
||||||
@DESC@
|
@DESC@
|
||||||
If <parameter>a</parameter> is NULL, returns a newly-created copy of <parameter>b</parameter>.
|
Adds all chars in <parameter>b</parameter> to <parameter>a</parameter>.
|
||||||
If <parameter>a</parameter> is an FcCharSet object owned by fontconfig that
|
In other words, this is an in-place version of FcCharSetUnion.
|
||||||
cannot be modified, it returns the union of <parameter>a</parameter> and
|
If <parameter>changed</parameter> is not NULL, then it returns whether any new
|
||||||
<parameter>b</parameter> in a newly-created FcCharSet object.
|
chars from <parameter>b</parameter> were added to <parameter>a</parameter>.
|
||||||
Otherwise, adds all chars in <parameter>b</parameter> to <parameter>a</parameter> and returns <parameter>a</parameter>. In other words, this is an in-place versionof FcCharSetUnion.
|
Returns FcFalse on failure, either when <parameter>a</parameter> is a constant
|
||||||
|
set or from running out of memory.
|
||||||
@@
|
@@
|
||||||
|
|
||||||
@RET@ FcBool
|
@RET@ FcBool
|
||||||
|
|
|
@ -439,8 +439,8 @@ FcCharSetUnion (const FcCharSet *a, const FcCharSet *b);
|
||||||
FcPublic FcCharSet*
|
FcPublic FcCharSet*
|
||||||
FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b);
|
FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b);
|
||||||
|
|
||||||
FcPublic FcCharSet *
|
FcPublic FcBool
|
||||||
FcCharSetMerge (FcCharSet *a, const FcCharSet *b);
|
FcCharSetMerge (FcCharSet *a, const FcCharSet *b, FcBool *changed);
|
||||||
|
|
||||||
FcPublic FcBool
|
FcPublic FcBool
|
||||||
FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4);
|
FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4);
|
||||||
|
|
161
src/fccharset.c
161
src/fccharset.c
|
@ -80,6 +80,39 @@ FcCharSetDestroy (FcCharSet *fcs)
|
||||||
free (fcs);
|
free (fcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search for the leaf containing with the specified num.
|
||||||
|
* Return its index if it exists, otherwise return negative of
|
||||||
|
* the (position + 1) where it should be inserted
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
FcCharSetFindLeafForward (const FcCharSet *fcs, int start, FcChar16 num)
|
||||||
|
{
|
||||||
|
FcChar16 *numbers = FcCharSetNumbers(fcs);
|
||||||
|
FcChar16 page;
|
||||||
|
int low = start;
|
||||||
|
int high = fcs->num - 1;
|
||||||
|
|
||||||
|
if (!numbers)
|
||||||
|
return -1;
|
||||||
|
while (low <= high)
|
||||||
|
{
|
||||||
|
int mid = (low + high) >> 1;
|
||||||
|
page = numbers[mid];
|
||||||
|
if (page == num)
|
||||||
|
return mid;
|
||||||
|
if (page < num)
|
||||||
|
low = mid + 1;
|
||||||
|
else
|
||||||
|
high = mid - 1;
|
||||||
|
}
|
||||||
|
if (high < 0 || (high < fcs->num && numbers[high] < num))
|
||||||
|
high++;
|
||||||
|
return -(high + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locate the leaf containing the specified char, return
|
* Locate the leaf containing the specified char, return
|
||||||
* its index if it exists, otherwise return negative of
|
* its index if it exists, otherwise return negative of
|
||||||
|
@ -89,28 +122,7 @@ FcCharSetDestroy (FcCharSet *fcs)
|
||||||
static int
|
static int
|
||||||
FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
|
FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
|
||||||
{
|
{
|
||||||
FcChar16 *numbers = FcCharSetNumbers(fcs);
|
return FcCharSetFindLeafForward (fcs, 0, ucs4 >> 8);
|
||||||
FcChar16 page;
|
|
||||||
int low = 0;
|
|
||||||
int high = fcs->num - 1;
|
|
||||||
|
|
||||||
if (!numbers)
|
|
||||||
return -1;
|
|
||||||
ucs4 >>= 8;
|
|
||||||
while (low <= high)
|
|
||||||
{
|
|
||||||
int mid = (low + high) >> 1;
|
|
||||||
page = numbers[mid];
|
|
||||||
if (page == ucs4)
|
|
||||||
return mid;
|
|
||||||
if (page < ucs4)
|
|
||||||
low = mid + 1;
|
|
||||||
else
|
|
||||||
high = mid - 1;
|
|
||||||
}
|
|
||||||
if (high < 0 || (high < fcs->num && numbers[high] < ucs4))
|
|
||||||
high++;
|
|
||||||
return -(high + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcCharLeaf *
|
static FcCharLeaf *
|
||||||
|
@ -452,67 +464,52 @@ FcCharSetUnion (const FcCharSet *a, const FcCharSet *b)
|
||||||
return FcCharSetOperate (a, b, FcCharSetUnionLeaf, FcTrue, FcTrue);
|
return FcCharSetOperate (a, b, FcCharSetUnionLeaf, FcTrue, FcTrue);
|
||||||
}
|
}
|
||||||
|
|
||||||
FcCharSet *
|
FcBool
|
||||||
FcCharSetMerge (FcCharSet *a, const FcCharSet *b)
|
FcCharSetMerge (FcCharSet *a, const FcCharSet *b, FcBool *changed)
|
||||||
{
|
{
|
||||||
FcCharSet *fcs;
|
int ai = 0, bi = 0;
|
||||||
FcCharSetIter ai, bi;
|
FcChar16 an, bn;
|
||||||
|
|
||||||
if (a == NULL) {
|
if (a->ref == FC_REF_CONSTANT)
|
||||||
fcs = a = FcCharSetCreate ();
|
return FcFalse;
|
||||||
} else if (a->ref == FC_REF_CONSTANT) {
|
|
||||||
fcs = FcCharSetCreate ();
|
|
||||||
} else
|
|
||||||
fcs = a;
|
|
||||||
|
|
||||||
if (fcs == NULL)
|
if (changed) {
|
||||||
return NULL;
|
*changed = !FcCharSetIsSubset(b, a);
|
||||||
|
if (!*changed)
|
||||||
FcCharSetIterStart (a, &ai);
|
return FcTrue;
|
||||||
FcCharSetIterStart (b, &bi);
|
|
||||||
while (ai.leaf || bi.leaf)
|
|
||||||
{
|
|
||||||
if (ai.ucs4 < bi.ucs4)
|
|
||||||
{
|
|
||||||
if (!FcCharSetAddLeaf (fcs, ai.ucs4, ai.leaf))
|
|
||||||
goto bail;
|
|
||||||
|
|
||||||
FcCharSetIterNext (a, &ai);
|
|
||||||
}
|
}
|
||||||
else if (bi.ucs4 < ai.ucs4)
|
|
||||||
{
|
|
||||||
if (!FcCharSetAddLeaf (fcs, bi.ucs4, bi.leaf))
|
|
||||||
goto bail;
|
|
||||||
|
|
||||||
FcCharSetIterNext (b, &bi);
|
while (bi < b->num)
|
||||||
|
{
|
||||||
|
an = ai < a->num ? FcCharSetNumbers(a)[ai] : ~0;
|
||||||
|
bn = FcCharSetNumbers(b)[bi];
|
||||||
|
|
||||||
|
if (an < bn)
|
||||||
|
{
|
||||||
|
ai = FcCharSetFindLeafForward (a, ai + 1, bn);
|
||||||
|
if (ai < 0)
|
||||||
|
ai = -ai - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FcCharLeaf leaf;
|
FcCharLeaf *bl = FcCharSetLeaf(b, bi);
|
||||||
|
if (bn < an)
|
||||||
if (FcCharSetUnionLeaf (&leaf, ai.leaf, bi.leaf))
|
|
||||||
{
|
{
|
||||||
if (!FcCharSetAddLeaf (fcs, ai.ucs4, &leaf))
|
if (!FcCharSetAddLeaf (a, bn << 8, bl))
|
||||||
goto bail;
|
return FcFalse;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FcCharLeaf *al = FcCharSetLeaf(a, ai);
|
||||||
|
FcCharSetUnionLeaf (al, al, bl);
|
||||||
}
|
}
|
||||||
|
|
||||||
FcCharSetIterNext (a, &ai);
|
ai++;
|
||||||
FcCharSetIterNext (b, &bi);
|
bi++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcs != a)
|
return FcTrue;
|
||||||
FcCharSetDestroy (a);
|
|
||||||
|
|
||||||
return fcs;
|
|
||||||
|
|
||||||
bail:
|
|
||||||
FcCharSetDestroy (fcs);
|
|
||||||
|
|
||||||
if (fcs != a)
|
|
||||||
FcCharSetDestroy (a);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
|
@ -687,29 +684,9 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int low = bi + 1;
|
bi = FcCharSetFindLeafForward (b, bi + 1, an);
|
||||||
int high = b->num - 1;
|
if (bi < 0)
|
||||||
|
bi = -bi - 1;
|
||||||
/*
|
|
||||||
* Search for page 'an' in 'b'
|
|
||||||
*/
|
|
||||||
while (low <= high)
|
|
||||||
{
|
|
||||||
int mid = (low + high) >> 1;
|
|
||||||
bn = FcCharSetNumbers(b)[mid];
|
|
||||||
if (bn == an)
|
|
||||||
{
|
|
||||||
high = mid;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (bn < an)
|
|
||||||
low = mid + 1;
|
|
||||||
else
|
|
||||||
high = mid - 1;
|
|
||||||
}
|
|
||||||
bi = high;
|
|
||||||
while (bi < b->num && FcCharSetNumbers(b)[bi] < an)
|
|
||||||
bi++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -606,38 +606,45 @@ FcSortCompare (const void *aa, const void *ab)
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool trim, FcBool build_cs)
|
FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **csp, FcBool trim)
|
||||||
{
|
{
|
||||||
FcCharSet *ncs;
|
FcBool ret = FcFalse;
|
||||||
FcSortNode *node;
|
FcCharSet *cs;
|
||||||
|
|
||||||
|
cs = 0;
|
||||||
|
if (trim || csp)
|
||||||
|
{
|
||||||
|
cs = FcCharSetCreate ();
|
||||||
|
if (cs == NULL)
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
while (nnode--)
|
while (nnode--)
|
||||||
{
|
{
|
||||||
node = *n++;
|
FcSortNode *node = *n++;
|
||||||
|
FcBool adds_chars = FcFalse;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only fetch node charset if we'd need it
|
* Only fetch node charset if we'd need it
|
||||||
*/
|
*/
|
||||||
if (trim || build_cs)
|
if (cs)
|
||||||
{
|
{
|
||||||
|
FcCharSet *ncs;
|
||||||
|
|
||||||
if (FcPatternGetCharSet (node->pattern, FC_CHARSET, 0, &ncs) !=
|
if (FcPatternGetCharSet (node->pattern, FC_CHARSET, 0, &ncs) !=
|
||||||
FcResultMatch)
|
FcResultMatch)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!FcCharSetMerge (cs, ncs, &adds_chars))
|
||||||
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this font isn't a subset of the previous fonts,
|
* If this font isn't a subset of the previous fonts,
|
||||||
* add it to the list
|
* add it to the list
|
||||||
*/
|
*/
|
||||||
if (!trim || !*cs || !FcCharSetIsSubset (ncs, *cs))
|
if (!trim || adds_chars)
|
||||||
{
|
{
|
||||||
if (trim || build_cs)
|
|
||||||
{
|
|
||||||
*cs = FcCharSetMerge (*cs, ncs);
|
|
||||||
if (*cs == NULL)
|
|
||||||
return FcFalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
FcPatternReference (node->pattern);
|
FcPatternReference (node->pattern);
|
||||||
if (FcDebug () & FC_DBG_MATCHV)
|
if (FcDebug () & FC_DBG_MATCHV)
|
||||||
{
|
{
|
||||||
|
@ -647,11 +654,23 @@ FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool tri
|
||||||
if (!FcFontSetAdd (fs, node->pattern))
|
if (!FcFontSetAdd (fs, node->pattern))
|
||||||
{
|
{
|
||||||
FcPatternDestroy (node->pattern);
|
FcPatternDestroy (node->pattern);
|
||||||
return FcFalse;
|
goto bail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FcTrue;
|
if (csp)
|
||||||
|
{
|
||||||
|
*csp = cs;
|
||||||
|
cs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = FcTrue;
|
||||||
|
|
||||||
|
bail:
|
||||||
|
if (cs)
|
||||||
|
FcCharSetDestroy (cs);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -675,7 +694,6 @@ FcFontSetSort (FcConfig *config,
|
||||||
FcSortNode **nodeps, **nodep;
|
FcSortNode **nodeps, **nodep;
|
||||||
int nnodes;
|
int nnodes;
|
||||||
FcSortNode *new;
|
FcSortNode *new;
|
||||||
FcCharSet *cs;
|
|
||||||
int set;
|
int set;
|
||||||
int f;
|
int f;
|
||||||
int i;
|
int i;
|
||||||
|
@ -803,19 +821,9 @@ FcFontSetSort (FcConfig *config,
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto bail1;
|
goto bail1;
|
||||||
|
|
||||||
cs = 0;
|
if (!FcSortWalk (nodeps, nnodes, ret, csp, trim))
|
||||||
|
|
||||||
if (!FcSortWalk (nodeps, nnodes, ret, &cs, trim, (csp!=0)))
|
|
||||||
goto bail2;
|
goto bail2;
|
||||||
|
|
||||||
if (csp)
|
|
||||||
*csp = cs;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (cs)
|
|
||||||
FcCharSetDestroy (cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
free (nodes);
|
free (nodes);
|
||||||
|
|
||||||
if (FcDebug() & FC_DBG_MATCH)
|
if (FcDebug() & FC_DBG_MATCH)
|
||||||
|
@ -826,8 +834,6 @@ FcFontSetSort (FcConfig *config,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
bail2:
|
bail2:
|
||||||
if (cs)
|
|
||||||
FcCharSetDestroy (cs);
|
|
||||||
FcFontSetDestroy (ret);
|
FcFontSetDestroy (ret);
|
||||||
bail1:
|
bail1:
|
||||||
free (nodes);
|
free (nodes);
|
||||||
|
|
Loading…
Reference in New Issue