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
}
/*
- * Locate the leaf containing the specified char, return
- * its index if it exists, otherwise return negative of
+ * 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
-FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
+FcCharSetFindLeafForward (const FcCharSet *fcs, int start, FcChar16 num)
{
FcChar16 *numbers = FcCharSetNumbers(fcs);
FcChar16 page;
- int low = 0;
+ int low = start;
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)
+ if (page == num)
return mid;
- if (page < ucs4)
+ if (page < num)
low = mid + 1;
else
high = mid - 1;
}
- if (high < 0 || (high < fcs->num && numbers[high] < ucs4))
+ 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
+ * the (position + 1) where it should be inserted
+ */
+
+static int
+FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
+{
+ return FcCharSetFindLeafForward (fcs, 0, ucs4 >> 8);
+}
+
static FcCharLeaf *
FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4)
{
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;
+ if (changed) {
+ *changed = !FcCharSetIsSubset(b, a);
+ if (!*changed)
+ return FcTrue;
+ }
- FcCharSetIterStart (a, &ai);
- FcCharSetIterStart (b, &bi);
- while (ai.leaf || bi.leaf)
+ while (bi < b->num)
{
- if (ai.ucs4 < bi.ucs4)
- {
- if (!FcCharSetAddLeaf (fcs, ai.ucs4, ai.leaf))
- goto bail;
+ an = ai < a->num ? FcCharSetNumbers(a)[ai] : ~0;
+ bn = FcCharSetNumbers(b)[bi];
- FcCharSetIterNext (a, &ai);
- }
- else if (bi.ucs4 < ai.ucs4)
+ if (an < bn)
{
- if (!FcCharSetAddLeaf (fcs, bi.ucs4, bi.leaf))
- goto bail;
-
- FcCharSetIterNext (b, &bi);
+ 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
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;
}
}
/*
}
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)
{
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
FcSortNode **nodeps, **nodep;
int nnodes;
FcSortNode *new;
- FcCharSet *cs;
int set;
int f;
int i;
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)
return ret;
bail2:
- if (cs)
- FcCharSetDestroy (cs);
FcFontSetDestroy (ret);
bail1:
free (nodes);