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>.
|
||||
@@
|
||||
|
||||
@RET@ FcCharSet *
|
||||
@RET@ FcBool
|
||||
@FUNC@ FcCharSetMerge
|
||||
@TYPE1@ const FcCharSet * @ARG1@ a
|
||||
@TYPE1@ FcCharSet * @ARG1@ a
|
||||
@TYPE2@ const FcCharSet * @ARG2@ b
|
||||
@TYPE3@ FcBool * @ARG3@ changed
|
||||
@PURPOSE@ Merge charsets
|
||||
@DESC@
|
||||
If <parameter>a</parameter> is NULL, returns a newly-created copy of <parameter>b</parameter>.
|
||||
If <parameter>a</parameter> is an FcCharSet object owned by fontconfig that
|
||||
cannot be modified, it returns the union of <parameter>a</parameter> and
|
||||
<parameter>b</parameter> in a newly-created FcCharSet object.
|
||||
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.
|
||||
Adds all chars in <parameter>b</parameter> to <parameter>a</parameter>.
|
||||
In other words, this is an in-place version of FcCharSetUnion.
|
||||
If <parameter>changed</parameter> is not NULL, then it returns whether any new
|
||||
chars from <parameter>b</parameter> were added to <parameter>a</parameter>.
|
||||
Returns FcFalse on failure, either when <parameter>a</parameter> is a constant
|
||||
set or from running out of memory.
|
||||
@@
|
||||
|
||||
@RET@ FcBool
|
||||
|
|
|
@ -439,8 +439,8 @@ FcCharSetUnion (const FcCharSet *a, const FcCharSet *b);
|
|||
FcPublic FcCharSet*
|
||||
FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b);
|
||||
|
||||
FcPublic FcCharSet *
|
||||
FcCharSetMerge (FcCharSet *a, const FcCharSet *b);
|
||||
FcPublic FcBool
|
||||
FcCharSetMerge (FcCharSet *a, const FcCharSet *b, FcBool *changed);
|
||||
|
||||
FcPublic FcBool
|
||||
FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4);
|
||||
|
|
161
src/fccharset.c
161
src/fccharset.c
|
@ -80,6 +80,39 @@ FcCharSetDestroy (FcCharSet *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
|
||||
* its index if it exists, otherwise return negative of
|
||||
|
@ -89,28 +122,7 @@ FcCharSetDestroy (FcCharSet *fcs)
|
|||
static int
|
||||
FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
|
||||
{
|
||||
FcChar16 *numbers = FcCharSetNumbers(fcs);
|
||||
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);
|
||||
return FcCharSetFindLeafForward (fcs, 0, ucs4 >> 8);
|
||||
}
|
||||
|
||||
static FcCharLeaf *
|
||||
|
@ -452,67 +464,52 @@ FcCharSetUnion (const FcCharSet *a, const FcCharSet *b)
|
|||
return FcCharSetOperate (a, b, FcCharSetUnionLeaf, FcTrue, FcTrue);
|
||||
}
|
||||
|
||||
FcCharSet *
|
||||
FcCharSetMerge (FcCharSet *a, const FcCharSet *b)
|
||||
FcBool
|
||||
FcCharSetMerge (FcCharSet *a, const FcCharSet *b, FcBool *changed)
|
||||
{
|
||||
FcCharSet *fcs;
|
||||
FcCharSetIter ai, bi;
|
||||
int ai = 0, bi = 0;
|
||||
FcChar16 an, bn;
|
||||
|
||||
if (a == NULL) {
|
||||
fcs = a = FcCharSetCreate ();
|
||||
} else if (a->ref == FC_REF_CONSTANT) {
|
||||
fcs = FcCharSetCreate ();
|
||||
} else
|
||||
fcs = a;
|
||||
if (a->ref == FC_REF_CONSTANT)
|
||||
return FcFalse;
|
||||
|
||||
if (fcs == NULL)
|
||||
return NULL;
|
||||
|
||||
FcCharSetIterStart (a, &ai);
|
||||
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);
|
||||
if (changed) {
|
||||
*changed = !FcCharSetIsSubset(b, a);
|
||||
if (!*changed)
|
||||
return FcTrue;
|
||||
}
|
||||
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
|
||||
{
|
||||
FcCharLeaf leaf;
|
||||
|
||||
if (FcCharSetUnionLeaf (&leaf, ai.leaf, bi.leaf))
|
||||
FcCharLeaf *bl = FcCharSetLeaf(b, bi);
|
||||
if (bn < an)
|
||||
{
|
||||
if (!FcCharSetAddLeaf (fcs, ai.ucs4, &leaf))
|
||||
goto bail;
|
||||
if (!FcCharSetAddLeaf (a, bn << 8, bl))
|
||||
return FcFalse;
|
||||
}
|
||||
else
|
||||
{
|
||||
FcCharLeaf *al = FcCharSetLeaf(a, ai);
|
||||
FcCharSetUnionLeaf (al, al, bl);
|
||||
}
|
||||
|
||||
FcCharSetIterNext (a, &ai);
|
||||
FcCharSetIterNext (b, &bi);
|
||||
ai++;
|
||||
bi++;
|
||||
}
|
||||
}
|
||||
|
||||
if (fcs != a)
|
||||
FcCharSetDestroy (a);
|
||||
|
||||
return fcs;
|
||||
|
||||
bail:
|
||||
FcCharSetDestroy (fcs);
|
||||
|
||||
if (fcs != a)
|
||||
FcCharSetDestroy (a);
|
||||
|
||||
return NULL;
|
||||
return FcTrue;
|
||||
}
|
||||
|
||||
static FcBool
|
||||
|
@ -687,29 +684,9 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
|
|||
return FcFalse;
|
||||
else
|
||||
{
|
||||
int low = bi + 1;
|
||||
int high = b->num - 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++;
|
||||
bi = FcCharSetFindLeafForward (b, bi + 1, an);
|
||||
if (bi < 0)
|
||||
bi = -bi - 1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -606,38 +606,45 @@ FcSortCompare (const void *aa, const void *ab)
|
|||
}
|
||||
|
||||
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;
|
||||
FcSortNode *node;
|
||||
FcBool ret = FcFalse;
|
||||
FcCharSet *cs;
|
||||
|
||||
cs = 0;
|
||||
if (trim || csp)
|
||||
{
|
||||
cs = FcCharSetCreate ();
|
||||
if (cs == NULL)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
while (nnode--)
|
||||
{
|
||||
node = *n++;
|
||||
FcSortNode *node = *n++;
|
||||
FcBool adds_chars = FcFalse;
|
||||
|
||||
/*
|
||||
* 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) !=
|
||||
FcResultMatch)
|
||||
continue;
|
||||
|
||||
if (!FcCharSetMerge (cs, ncs, &adds_chars))
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this font isn't a subset of the previous fonts,
|
||||
* 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);
|
||||
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))
|
||||
{
|
||||
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
|
||||
|
@ -675,7 +694,6 @@ FcFontSetSort (FcConfig *config,
|
|||
FcSortNode **nodeps, **nodep;
|
||||
int nnodes;
|
||||
FcSortNode *new;
|
||||
FcCharSet *cs;
|
||||
int set;
|
||||
int f;
|
||||
int i;
|
||||
|
@ -803,19 +821,9 @@ FcFontSetSort (FcConfig *config,
|
|||
if (!ret)
|
||||
goto bail1;
|
||||
|
||||
cs = 0;
|
||||
|
||||
if (!FcSortWalk (nodeps, nnodes, ret, &cs, trim, (csp!=0)))
|
||||
if (!FcSortWalk (nodeps, nnodes, ret, csp, trim))
|
||||
goto bail2;
|
||||
|
||||
if (csp)
|
||||
*csp = cs;
|
||||
else
|
||||
{
|
||||
if (cs)
|
||||
FcCharSetDestroy (cs);
|
||||
}
|
||||
|
||||
free (nodes);
|
||||
|
||||
if (FcDebug() & FC_DBG_MATCH)
|
||||
|
@ -826,8 +834,6 @@ FcFontSetSort (FcConfig *config,
|
|||
return ret;
|
||||
|
||||
bail2:
|
||||
if (cs)
|
||||
FcCharSetDestroy (cs);
|
||||
FcFontSetDestroy (ret);
|
||||
bail1:
|
||||
free (nodes);
|
||||
|
|
Loading…
Reference in New Issue