patcache.c revision 23a0898a
1/* $Xorg: patcache.c,v 1.4 2001/02/09 02:04:04 xorgcvs Exp $ */ 2 3/* 4 5Copyright 1991, 1998 The Open Group 6 7Permission to use, copy, modify, distribute, and sell this software and its 8documentation for any purpose is hereby granted without fee, provided that 9the above copyright notice appear in all copies and that both that 10copyright notice and this permission notice appear in supporting 11documentation. 12 13The above copyright notice and this permission notice shall be included in 14all copies or substantial portions of the Software. 15 16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 23Except as contained in this notice, the name of The Open Group shall not be 24used in advertising or otherwise to promote the sale, use or other dealings 25in this Software without prior written authorization from The Open Group. 26 27*/ 28/* $XFree86: xc/lib/font/util/patcache.c,v 3.4 2001/01/17 19:43:33 dawes Exp $ */ 29 30/* 31 * Author: Keith Packard, MIT X Consortium 32 */ 33 34#ifdef HAVE_CONFIG_H 35#include <config.h> 36#endif 37#include <X11/fonts/fontmisc.h> 38#include <X11/fonts/fontstruct.h> 39 40/* 41 * Static sized hash table for looking up font name patterns 42 * 43 * LRU entries, reusing old entries 44 */ 45 46#define NBUCKETS 16 47#define NENTRIES 64 48 49#define UNSET (NENTRIES+1) 50 51typedef unsigned char EntryPtr; 52 53typedef struct _FontPatternCacheEntry { 54 struct _FontPatternCacheEntry *next, **prev; 55 short patlen; 56 char *pattern; 57 int hash; 58 FontPtr pFont; /* associated font */ 59} FontPatternCacheEntryRec, *FontPatternCacheEntryPtr; 60 61typedef struct _FontPatternCache { 62 FontPatternCacheEntryPtr buckets[NBUCKETS]; 63 FontPatternCacheEntryRec entries[NENTRIES]; 64 FontPatternCacheEntryPtr free; 65} FontPatternCacheRec; 66 67/* Empty cache (for rehash) */ 68void 69EmptyFontPatternCache (FontPatternCachePtr cache) 70{ 71 int i; 72 73 for (i = 0; i < NBUCKETS; i++) 74 cache->buckets[i] = 0; 75 for (i = 0; i < NENTRIES; i++) 76 { 77 cache->entries[i].next = &cache->entries[i+1]; 78 cache->entries[i].prev = 0; 79 cache->entries[i].pFont = 0; 80 xfree (cache->entries[i].pattern); 81 cache->entries[i].pattern = 0; 82 cache->entries[i].patlen = 0; 83 } 84 cache->free = &cache->entries[0]; 85 cache->entries[NENTRIES - 1].next = 0; 86} 87 88/* Create and initialize cache */ 89FontPatternCachePtr 90MakeFontPatternCache (void) 91{ 92 FontPatternCachePtr cache; 93 int i; 94 cache = (FontPatternCachePtr) xalloc (sizeof *cache); 95 if (!cache) 96 return 0; 97 for (i = 0; i < NENTRIES; i++) { 98 cache->entries[i].patlen = 0; 99 cache->entries[i].pattern = 0; 100 cache->entries[i].pFont = 0; 101 } 102 EmptyFontPatternCache (cache); 103 return cache; 104} 105 106/* toss cache */ 107void 108FreeFontPatternCache (FontPatternCachePtr cache) 109{ 110 int i; 111 112 for (i = 0; i < NENTRIES; i++) 113 xfree (cache->entries[i].pattern); 114 xfree (cache); 115} 116 117/* compute id for string */ 118static int 119Hash (const char *string, int len) 120{ 121 int hash; 122 123 hash = 0; 124 while (len--) 125 hash = (hash << 1) ^ *string++; 126 if (hash < 0) 127 hash = -hash; 128 return hash; 129} 130 131/* add entry */ 132void 133CacheFontPattern (FontPatternCachePtr cache, 134 char *pattern, 135 int patlen, 136 FontPtr pFont) 137{ 138 FontPatternCacheEntryPtr e; 139 char *newpat; 140 int i; 141 142 newpat = (char *) xalloc (patlen); 143 if (!newpat) 144 return; 145 if (cache->free) 146 { 147 e = cache->free; 148 cache->free = e->next; 149 } 150 else 151 { 152 i = rand (); 153 if (i < 0) 154 i = -i; 155 i %= NENTRIES; 156 e = &cache->entries[i]; 157 if (e->next) 158 e->next->prev = e->prev; 159 *e->prev = e->next; 160 xfree (e->pattern); 161 } 162 /* set pattern */ 163 memcpy (newpat, pattern, patlen); 164 e->pattern = newpat; 165 e->patlen = patlen; 166 /* link to new hash chain */ 167 e->hash = Hash (pattern, patlen); 168 i = e->hash % NBUCKETS; 169 e->next = cache->buckets[i]; 170 if (e->next) 171 e->next->prev = &(e->next); 172 cache->buckets[i] = e; 173 e->prev = &(cache->buckets[i]); 174 e->pFont = pFont; 175} 176 177/* find matching entry */ 178FontPtr 179FindCachedFontPattern (FontPatternCachePtr cache, 180 char *pattern, 181 int patlen) 182{ 183 int hash; 184 int i; 185 FontPatternCacheEntryPtr e; 186 187 hash = Hash (pattern, patlen); 188 i = hash % NBUCKETS; 189 for (e = cache->buckets[i]; e; e = e->next) 190 { 191 if (e->patlen == patlen && e->hash == hash && 192 !memcmp (e->pattern, pattern, patlen)) 193 { 194 return e->pFont; 195 } 196 } 197 return 0; 198} 199 200void 201RemoveCachedFontPattern (FontPatternCachePtr cache, 202 FontPtr pFont) 203{ 204 FontPatternCacheEntryPtr e; 205 int i; 206 207 for (i = 0; i < NENTRIES; i++) 208 { 209 if ((e = &cache->entries[i])->pFont == pFont) 210 { 211 e->pFont = 0; 212 if (e->next) 213 e->next->prev = e->prev; 214 *e->prev = e->next; 215 e->next = cache->free; 216 cache->free = e; 217 xfree (e->pattern); 218 e->pattern = 0; 219 } 220 } 221} 222