*** dix/dixfonts.c 1999/12/26 01:57:02 1.1 --- dix/dixfonts.c 1999/12/26 16:25:10 *************** *** 871,876 **** --- 871,1096 ---- return Success; } + // Some stupid X-application such as Netscape repeatedly calls + // StartListFontsWithInfo(client 137651332, pattern *-iso8859-1, max_names 10 0). + // This opens large amount of font files and recalcurate font metrics + // repeatedly. Each call takes more than 10 seconds. So we memorise several + // results ( > 1024 ) in hash table. S. Kono + + int Memorize_FontWithInfo = 1; + #define MEMORIZE_FONTWITHINFO_SIZE 1024 + + #ifdef MEMORIZE_FONTWITHINFO_DEBUG + #define MF_DEBUG(x) x + #else + #define MF_DEBUG(x) + #endif + + static struct FontWithInfoMemoryStart { + int patlen; + char *pattern; + FontPathElementPtr fpe; + int result; + struct FontWithInfoMemoryNext { + int result; + char *name; + int namelen; + int numFonts; + FontInfoRec *pFontInfo; + struct FontWithInfoMemoryNext *next; + } *next,**last; + } *FontWithInfoMemory[MEMORIZE_FONTWITHINFO_SIZE]; + + struct FontWithInfoMemoryStart * + searchFontWithInfoCache(pattern,patlen,fpe) + char *pattern; + int patlen; + FontPathElementPtr fpe; + { + char *p; + unsigned int hash; + struct FontWithInfoMemoryStart *f; + int i; + + // compute hash + for(hash = 0,p = pattern,i=0;*p && i<=patlen; hash = (hash*7) ^ *p++); + for(p = fpe->name,i=0;*p && i<=fpe->name_length; hash = (hash*7) ^ *p++) ; + hash %= MEMORIZE_FONTWITHINFO_SIZE; + if (f=FontWithInfoMemory[hash]) { + struct FontWithInfoMemoryNext *n; + if (f->pattern && f->patlen==patlen + && strncmp(pattern,f->pattern,patlen)==0) { + if (strncmp(f->fpe->name,fpe->name,f->fpe->name_length)==0) { + return f; + } + } + // Wrong entry. Free this and reuse it. + if(--f->fpe->refcount==0) { + if(f->fpe->private) + xfree(f->fpe->private); + xfree(f->fpe); + } + for(n = f->next; n; n=n->next) { + if(n->name) xfree(n->name); + n->name = 0; + if (n->result==Successful) { + if (n->pFontInfo) { + if(n->pFontInfo->props) xfree(n->pFontInfo->props); + if(n->pFontInfo->isStringProp) xfree(n->pFontInfo->isString Prop); + } + } + if (n->pFontInfo) xfree(n->pFontInfo); + n->pFontInfo=0; + // we never free struct FontWithInfoMemoryNext + } + } else { + MF_DEBUG(fprintf(stderr,"FontWithInfoCache(pattern %s) new %x\n",pattern,f)); + // allocate new cache + f = FontWithInfoMemory[hash] = (struct FontWithInfoMemoryStart *) + xalloc(sizeof(struct FontWithInfoMemoryStart)); + if(!f) return f; + f->pattern = 0; + } + if(f->pattern) { // replace pattern + xfree(f->pattern); + f->pattern = 0; + } + f->pattern = (char *)xalloc(patlen); + f->patlen = patlen; + if(!f->pattern) return 0; + strncpy(f->pattern,pattern,patlen); + f->next=0; + f->last = &f->next; + f->fpe=fpe; + fpe->refcount++; + return f; + } + + static int + lookupStartFontWithInfoCache(client,fpe, c) + ClientPtr client; + FontPathElementPtr fpe; + LFWIclosurePtr c; + { + int err; + struct FontWithInfoMemoryStart *f; + + f = searchFontWithInfoCache(c->current.pattern,c->current.patlen,fpe); + if (!f) return BadAlloc; + if (f->next && f->last==0) { // Found completed entry + c->current.private = (pointer)f->next; + return f->result; + } + err = (*fpe_functions[fpe->type].start_list_fonts_with_info) + (client, fpe, c->current.pattern, c->current.patlen, + c->current.max_names, &c->current.private); + f->result = err; + return err; + } + + static int + lookupFontWithInfoCache(client,fpe, pname, pnamelen, ppFontInfo, pnumFonts, c ) + ClientPtr client; + FontPathElementPtr fpe; + LFWIclosurePtr c; + char **pname; + int *pnamelen; + int *pnumFonts; + FontInfoPtr *ppFontInfo; + { + int err; + struct FontWithInfoMemoryStart *f; + struct FontWithInfoMemoryNext *next; + + f = searchFontWithInfoCache(c->current.pattern,c->current.patlen,fpe); + if (!f) goto badAlloc; + if (f->last==0) { // found complete entry + next = c->current.private; + if (!next) { + if (f->pattern) f->pattern[0]=0; // invalidate this entry + MF_DEBUG(fprintf(stderr,"lookupFontWithInfoCache(name %s) BadAlloc return %d %x\n",c->current.pattern,err,next)); + return BadAlloc; + } + err = next->result; + if (err==Successful || err==FontNameAlias) { + *pname = next->name; + *pnamelen = next->namelen; + *ppFontInfo = next->pFontInfo; + *pnumFonts = next->numFonts; + } + c->current.private = (pointer)next->next; + MF_DEBUG(fprintf(stderr,"lookupFontWithInfoCache(name %s) return %d %x\n",c-> current.pattern,err,next)); + return err; + } + err = (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, pname, pnamelen, ppFontInfo, + pnumFonts, c->current.private); + // memorize it + if (err==Successful || err==FontNameAlias || err==BadFontName) { + int i,j; + if (! *f->last) { + if(! (next = *f->last = + (struct FontWithInfoMemoryNext *) + xalloc(sizeof(struct FontWithInfoMemoryNext)))) + goto badAlloc; + next->next=0; + next->name=0; + next->pFontInfo = 0; + f->last = &next->next; + MF_DEBUG(fprintf(stderr,"lookupFontWithInfoCache new next %x\n",next)); + } else { + next = *f->last; + MF_DEBUG(fprintf(stderr,"lookupFontWithInfoCache reuse next %x\n",next)); + } + next->result = err; + if (err==FontNameAlias) { + if(! (next->pFontInfo = (FontInfoPtr)xalloc(strlen((char *)*ppFontI nfo)))) + goto badAlloc; + MF_DEBUG(fprintf(stderr,"lookupFontWithInfoCache(alias) memorize %d %x\n",err ,next)); + strcpy((char *)next->pFontInfo,(char *)*ppFontInfo); + if(! (next->name = (char *)xalloc(*pnamelen))) + goto badAlloc; + strncpy(next->name,*pname,*pnamelen); + next->namelen = *pnamelen; + next->numFonts = *pnumFonts; + return err; + } else if (err!=Successful) { + MF_DEBUG(fprintf(stderr,"lookupFontWithInfoCache(Bad) memorize %d %x\n",err,n ext)); + return err; + } + MF_DEBUG(fprintf(stderr,"lookupFontWithInfoCache(name %s) memorize %d %x\n",* pname,err,next)); + if(! (next->pFontInfo = (FontInfoRec *) xalloc(sizeof(FontInfoRec)))) + goto badAlloc; + next->pFontInfo->props = 0; + next->pFontInfo->isStringProp = 0; + if(! (next->name = (char *)xalloc(*pnamelen))) + goto badAlloc; + strncpy(next->name,*pname,*pnamelen); + next->namelen = *pnamelen; + next->numFonts = *pnumFonts; + *next->pFontInfo = **ppFontInfo; // struct copy + if(j = (*ppFontInfo)->nprops) { + if(!(next->pFontInfo->props = (FontPropPtr)xalloc(sizeof(FontPropRe c)*j))) + goto badAlloc; + for (i = 0; i < j; i++) { + next->pFontInfo->props[i].name = (*ppFontInfo)->props[i].name; + next->pFontInfo->props[i].value = (*ppFontInfo)->props[i].value ; + } + } + if ((*ppFontInfo)->isStringProp) { + if(! (next->pFontInfo->isStringProp = (char *) xalloc(j))) + goto badAlloc; + strncpy(next->pFontInfo->isStringProp,(*ppFontInfo)->isStringProp,j ); + } + } + return err; + badAlloc: + if (f && f->pattern) + f->pattern[0]=0; // Invalidate this entry, if it exists. + return BadAlloc; + } + + int doListFontsWithInfo(client, c) ClientPtr client; *************** *** 909,917 **** err = Successful; if (!c->current.list_started) { ! err = (*fpe_functions[fpe->type].start_list_fonts_with_info) ! (client, fpe, c->current.pattern, c->current.patlen, ! c->current.max_names, &c->current.private); if (err == Suspended) { if (!c->slept) --- 1129,1141 ---- err = Successful; if (!c->current.list_started) { ! if (Memorize_FontWithInfo) { ! err = lookupStartFontWithInfoCache(client, fpe, c); ! } else { ! err = (*fpe_functions[fpe->type].start_list_fonts_with_info) ! (client, fpe, c->current.pattern, c->current.patlen, ! c->current.max_names, &c->current.private); ! } if (err == Suspended) { if (!c->slept) *************** *** 928,936 **** { name = 0; pFontInfo = &fontInfo; ! err = (*fpe_functions[fpe->type].list_next_font_with_info) ! (client, fpe, &name, &namelen, &pFontInfo, ! &numFonts, c->current.private); if (err == Suspended) { if (!c->slept) --- 1152,1166 ---- { name = 0; pFontInfo = &fontInfo; ! if (Memorize_FontWithInfo) { ! err = lookupFontWithInfoCache( ! client, fpe, &name, &namelen, &pFontInfo, ! &numFonts, c); ! } else { ! err = (*fpe_functions[fpe->type].list_next_font_with_info) ! (client, fpe, &name, &namelen, &pFontInfo, ! &numFonts, c->current.private); ! } if (err == Suspended) { if (!c->slept) *************** *** 965,973 **** tmpname = 0; tmpFontInfo = &fontInfo; ! (void) (*fpe_functions[fpe->type].list_next_font_with_info) ! (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, ! &numFonts, c->current.private); if (--aliascount <= 0) { err = BadFontName; --- 1195,1209 ---- tmpname = 0; tmpFontInfo = &fontInfo; ! if (Memorize_FontWithInfo) { ! (void) lookupFontWithInfoCache( ! client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, ! &numFonts, c); ! } else { ! (void) (*fpe_functions[fpe->type].list_next_font_with_info) ! (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, ! &numFonts, c->current.private); ! } if (--aliascount <= 0) { err = BadFontName; *************** *** 998,1003 **** --- 1234,1247 ---- else if (err == BadFontName) { ContBadFontName: ; + if (Memorize_FontWithInfo) { + struct FontWithInfoMemoryStart *f; + f = searchFontWithInfoCache(c->current.pattern,c->current.patle n,fpe); + MF_DEBUG(fprintf(stderr,"doListFontsWithInfo(pattern %s) current fpe end %x\n ",c->current.pattern,f)); + if (f) + f->last = 0; + // else BadAlloc, but this cannot happen + } c->current.list_started = FALSE; c->current.current_fpe++; err = Successful; *************** *** 1072,1077 **** --- 1316,1331 ---- } } finish: + // cache entry completed + if (Memorize_FontWithInfo) { + struct FontWithInfoMemoryStart *f; + f = searchFontWithInfoCache(c->current.pattern,c->current.patlen,fpe); + MF_DEBUG(fprintf(stderr,"doListFontsWithInfo(pattern %s) complete %x\n",c->cu rrent.pattern,f)); + if (f) + f->last = 0; + // else BadAlloc, but this cannot happen + } + length = sizeof(xListFontsWithInfoReply); bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply)); finalReply.type = X_Reply;