]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcpat.c
Add ref counting to font config patterns so that FcFontSort return values
[fontconfig.git] / src / fcpat.c
index b3601654dbd8097f25c772df84831fb6eb194acf..3e19732a4e47b879543a6e3a27869f923d0afd23 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.3 2002/02/19 07:50:44 keithp Exp $
+ * $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.7 2002/06/03 08:31:15 keithp Exp $
  *
  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
  *
@@ -38,6 +38,7 @@ FcPatternCreate (void)
     p->num = 0;
     p->size = 0;
     p->elts = 0;
+    p->ref = 1;
     return p;
 }
 
@@ -142,6 +143,58 @@ FcValueEqual (FcValue va, FcValue vb)
        return FcMatrixEqual (va.u.m, vb.u.m);
     case FcTypeCharSet:
        return FcCharSetEqual (va.u.c, vb.u.c);
+    case FcTypeFTFace:
+       return va.u.f == vb.u.f;
+    }
+    return FcFalse;
+}
+
+static FcChar32
+FcDoubleHash (double d)
+{
+    if (d < 0)
+       d = -d;
+    if (d > 0xffffffff)
+       d = 0xffffffff;
+    return (FcChar32) d;
+}
+
+static FcChar32
+FcStringHash (const FcChar8 *s)
+{
+    FcChar8    c;
+    FcChar32   h = 0;
+    
+    if (s)
+       while ((c = *s++))
+           h = ((h << 1) | (h >> 31)) ^ c;
+    return h;
+}
+
+static FcChar32
+FcValueHash (FcValue v)
+{
+    switch (v.type) {
+    case FcTypeVoid:
+       return 0;
+    case FcTypeInteger:
+       return (FcChar32) v.u.i;
+    case FcTypeDouble:
+       return FcDoubleHash (v.u.d);
+    case FcTypeString:
+       return FcStringHash (v.u.s);
+    case FcTypeBool:
+       return (FcChar32) v.u.b;
+    case FcTypeMatrix:
+       return (FcDoubleHash (v.u.m->xx) ^ 
+               FcDoubleHash (v.u.m->xy) ^ 
+               FcDoubleHash (v.u.m->yx) ^ 
+               FcDoubleHash (v.u.m->yy));
+    case FcTypeCharSet:
+       return (FcChar32) v.u.c->num;
+    case FcTypeFTFace:
+       return FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->family_name) ^
+              FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->style_name);
     }
     return FcFalse;
 }
@@ -161,11 +214,27 @@ FcValueListEqual (FcValueList *la, FcValueList *lb)
     return FcTrue;
 }
 
+static FcChar32
+FcValueListHash (FcValueList *l)
+{
+    FcChar32   hash = 0;
+    
+    while (l)
+    {
+       hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (l->value);
+       l = l->next;
+    }
+    return hash;
+}
+
 void
 FcPatternDestroy (FcPattern *p)
 {
     int                    i;
     
+    if (--p->ref > 0)
+       return;
+
     for (i = 0; i < p->num; i++)
        FcValueListDestroy (p->elts[i].values);
 
@@ -181,84 +250,91 @@ FcPatternDestroy (FcPattern *p)
     free (p);
 }
 
-FcPatternElt *
-FcPatternFind (FcPattern *p, const char *object, FcBool insert)
+static int
+FcPatternPosition (const FcPattern *p, const char *object)
 {
-    int                    i;
-    int                    s;
-    FcPatternElt   *e;
-    
-    int                    low, high;
+    int            low, high, mid, c;
 
-    /* match existing */
     low = 0;
-    high = p->num;
-
-    while (low + 1 < high)
+    high = p->num - 1;
+    c = 1;
+    mid = 0;
+    while (low <= high)
     {
-       i = (low + high) >> 1;
-       s = FcStrCmpIgnoreCase ((FcChar8 *) object, (FcChar8 *) p->elts[i].object);
-       if (s == 0)
-           return &p->elts[i];
-       if (s < 0)
-           low = i;
+       mid = (low + high) >> 1;
+       c = strcmp (p->elts[mid].object, object);
+       if (c == 0)
+           return mid;
+       if (c < 0)
+           low = mid + 1;
        else
-           high = i;
-    }
-
-    i = low;
-    while (i < high)
-    {
-       s = FcStrCmpIgnoreCase ((FcChar8 *) object, (FcChar8 *) p->elts[i].object);
-       if (s == 0)
-           return &p->elts[i];
-       if (s > 0)
-           break;
-       i++;
+           high = mid - 1;
     }
+    if (c < 0)
+       mid++;
+    return -(mid + 1);
+}
 
-    if (!insert)
+FcPatternElt *
+FcPatternFindElt (const FcPattern *p, const char *object)
+{
+    int            i = FcPatternPosition (p, object);
+    if (i < 0)
        return 0;
+    return &p->elts[i];
+}
 
-    /* grow array */
-    if (p->num + 1 >= p->size)
+FcPatternElt *
+FcPatternInsertElt (FcPattern *p, const char *object)
+{
+    int                    i;
+    FcPatternElt   *e;
+    
+    i = FcPatternPosition (p, object);
+    if (i < 0)
     {
-       s = p->size + 16;
-       if (p->elts)
-           e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
-       else
-           e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
-       if (!e)
-           return FcFalse;
-       p->elts = e;
-       if (p->size)
-           FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
-       FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
-       while (p->size < s)
+       i = -i - 1;
+    
+       /* grow array */
+       if (p->num + 1 >= p->size)
        {
-           p->elts[p->size].object = 0;
-           p->elts[p->size].values = 0;
-           p->size++;
+           int s = p->size + 16;
+           if (p->elts)
+               e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
+           else
+               e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
+           if (!e)
+               return FcFalse;
+           p->elts = e;
+           if (p->size)
+               FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
+           FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
+           while (p->size < s)
+           {
+               p->elts[p->size].object = 0;
+               p->elts[p->size].values = 0;
+               p->size++;
+           }
        }
+       
+       /* move elts up */
+       memmove (p->elts + i + 1,
+                p->elts + i,
+                sizeof (FcPatternElt) *
+                (p->num - i));
+                
+       /* bump count */
+       p->num++;
+       
+       p->elts[i].object = object;
+       p->elts[i].values = 0;
     }
     
-    /* move elts up */
-    memmove (p->elts + i + 1,
-            p->elts + i,
-            sizeof (FcPatternElt) *
-            (p->num - i));
-            
-    /* bump count */
-    p->num++;
-    
-    p->elts[i].object = object;
-    p->elts[i].values = 0;
-    
     return &p->elts[i];
 }
 
 FcBool
-FcPatternEqual (FcPattern *pa, FcPattern *pb)
+FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
 {
     int        i;
 
@@ -266,8 +342,7 @@ FcPatternEqual (FcPattern *pa, FcPattern *pb)
        return FcFalse;
     for (i = 0; i < pa->num; i++)
     {
-       if (FcStrCmpIgnoreCase ((FcChar8 *) pa->elts[i].object,
-                               (FcChar8 *) pb->elts[i].object) != 0)
+       if (strcmp (pa->elts[i].object, pb->elts[i].object) != 0)
            return FcFalse;
        if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values))
            return FcFalse;
@@ -275,6 +350,47 @@ FcPatternEqual (FcPattern *pa, FcPattern *pb)
     return FcTrue;
 }
 
+FcChar32
+FcPatternHash (const FcPattern *p)
+{
+    int                i;
+    FcChar32   h = 0;
+
+    for (i = 0; i < p->num; i++)
+    {
+       h = (((h << 1) | (h >> 31)) ^ 
+            FcStringHash ((const FcChar8 *) p->elts[i].object) ^
+            FcValueListHash (p->elts[i].values));
+    }
+    return h;
+}
+
+FcBool
+FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os)
+{
+    FcPatternElt    *ea, *eb;
+    int                    i;
+    
+    for (i = 0; i < os->nobject; i++)
+    {
+       ea = FcPatternFindElt (pa, os->objects[i]);
+       eb = FcPatternFindElt (pb, os->objects[i]);
+       if (ea)
+       {
+           if (!eb)
+               return FcFalse;
+           if (!FcValueListEqual (ea->values, eb->values))
+               return FcFalse;
+       }
+       else
+       {
+           if (eb)
+               return FcFalse;
+       }
+    }
+    return FcTrue;
+}
+
 FcBool
 FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
 {
@@ -294,7 +410,7 @@ FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
     new->value = value;
     new->next = 0;
     
-    e = FcPatternFind (p, object, FcTrue);
+    e = FcPatternInsertElt (p, object);
     if (!e)
        goto bail2;
     
@@ -338,7 +454,7 @@ FcPatternDel (FcPattern *p, const char *object)
     FcPatternElt   *e;
     int                    i;
 
-    e = FcPatternFind (p, object, FcFalse);
+    e = FcPatternFindElt (p, object);
     if (!e)
        return FcFalse;
 
@@ -417,13 +533,23 @@ FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
     return FcPatternAdd (p, object, v, FcTrue);
 }
 
+FcBool
+FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
+{
+    FcValue    v;
+
+    v.type = FcTypeFTFace;
+    v.u.f = (void *) f;
+    return FcPatternAdd (p, object, v, FcTrue);
+}
+
 FcResult
 FcPatternGet (FcPattern *p, const char *object, int id, FcValue *v)
 {
     FcPatternElt   *e;
     FcValueList    *l;
 
-    e = FcPatternFind (p, object, FcFalse);
+    e = FcPatternFindElt (p, object);
     if (!e)
        return FcResultNoMatch;
     for (l = e->values; l; l = l->next)
@@ -543,6 +669,21 @@ FcPatternGetCharSet (FcPattern *p, const char *object, int id, FcCharSet **c)
     return FcResultMatch;
 }
 
+FcResult
+FcPatternGetFTFace (FcPattern *p, const char *object, int id, FT_Face *f)
+{
+    FcValue    v;
+    FcResult   r;
+
+    r = FcPatternGet (p, object, id, &v);
+    if (r != FcResultMatch)
+       return r;
+    if (v.type != FcTypeFTFace)
+       return FcResultTypeMismatch;
+    *f = (FT_Face) v.u.f;
+    return FcResultMatch;
+}
+
 FcPattern *
 FcPatternDuplicate (FcPattern *orig)
 {
@@ -569,6 +710,12 @@ bail0:
     return 0;
 }
 
+void
+FcPatternReference (FcPattern *p)
+{
+    p->ref++;
+}
+
 FcPattern *
 FcPatternVaBuild (FcPattern *orig, va_list va)
 {