]> git.wh0rd.org - fontconfig.git/commitdiff
Change FcCharSetMerge API
authorKarl Tomlinson <bugs.freedesktop@karlt.net>
Tue, 27 Jan 2009 08:35:51 +0000 (03:35 -0500)
committerBehdad Esfahbod <behdad@behdad.org>
Sun, 15 Feb 2009 21:40:18 +0000 (13:40 -0800)
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
fontconfig/fontconfig.h
src/fccharset.c
src/fcmatch.c

index 0dd7d1a5c644d4a00ac052d2c7aba176515486c6..de06aa49be40fd8caec8e3086caadd676d0d230d 100644 (file)
@@ -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 
index 606580db92bbbfb48cc66a35178f0c658e4c8e54..99e2f0421a67909afdd97e58e370c09707230a33 100644 (file)
@@ -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);
index 2daa39d59bef9ef68b43257505e11dfb7a359d34..1885c268d0e43690df3c743ab6210e016a7e4b80 100644 (file)
@@ -81,38 +81,50 @@ FcCharSetDestroy (FcCharSet *fcs)
 }
 
 /*
- * 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)
 {
@@ -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;
        }
     }
     /*
index b86cbbcd4058f8690e2790daa4aea4aee2e1f90f..e06444c8493655293ed6e078560e2df8d6cd7fbd 100644 (file)
@@ -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);