From 575ee6cddd391857339f57331d2677fcc868369e Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Tue, 27 Jan 2009 03:35:51 -0500 Subject: [PATCH] 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 --- doc/fccharset.fncs | 16 ++-- fontconfig/fontconfig.h | 4 +- src/fccharset.c | 157 +++++++++++++++++----------------------- src/fcmatch.c | 64 ++++++++-------- 4 files changed, 113 insertions(+), 128 deletions(-) diff --git a/doc/fccharset.fncs b/doc/fccharset.fncs index 0dd7d1a..de06aa4 100644 --- a/doc/fccharset.fncs +++ b/doc/fccharset.fncs @@ -98,17 +98,19 @@ Returns a set including only those chars found in either aa but not b. @@ -@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 a is NULL, returns a newly-created copy of b. -If a is an FcCharSet object owned by fontconfig that -cannot be modified, it returns the union of a and -b in a newly-created FcCharSet object. -Otherwise, adds all chars in b to a and returns a. In other words, this is an in-place versionof FcCharSetUnion. +Adds all chars in b to a. +In other words, this is an in-place version of FcCharSetUnion. +If changed is not NULL, then it returns whether any new +chars from b were added to a. +Returns FcFalse on failure, either when a is a constant +set or from running out of memory. @@ @RET@ FcBool diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h index 606580d..99e2f04 100644 --- a/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig.h @@ -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); diff --git a/src/fccharset.c b/src/fccharset.c index 2daa39d..1885c26 100644 --- a/src/fccharset.c +++ b/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; + 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 @@ -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; } } /* diff --git a/src/fcmatch.c b/src/fcmatch.c index b86cbbc..e06444c 100644 --- a/src/fcmatch.c +++ b/src/fcmatch.c @@ -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);