The following is a set of patches to install on XcRichText-1.5, which will improve the efficiency of the widget when using multiple font instances, as well as better integration of the X11R5 scalable fonts (which we use extensively). The current heuristic counts a scalable font as being the a perfect match. Well, this isn't *exactly* true. You should count a bitmap font first because in general they look better. One last remark about these patches. They *seriously* reduce the number of client/server round-trip times if you use many fonts on a single server. Also, font name caching is per-display (and not per widget), so if you use multiple RTF widgets each with different fontPatterns resources, well, you might get strange results. This is a known bug, but it should affect many applications. Please send me any comments, fixes, etc. -Philip ======== Cut here ======== *** xtextview.h# Wed Sep 23 02:32:07 1992 --- xtextview.h Sat Jul 10 23:02:40 1993 *************** *** 16,21 **** --- 16,23 ---- typedef unsigned long Pixel; + #define FONT_CACHE_SIZE 12 + class XTextFlow; class XNewLineFlow; class XHRule; *************** *** 86,91 **** --- 97,110 ---- { return (double)HeightOfScreen(DefaultScreenOfDisplay(display())) / HeightMMOfScreen(DefaultScreenOfDisplay(display())); }; + double xdpin() const + { return (double)WidthOfScreen(DefaultScreenOfDisplay(display())) / + (WidthMMOfScreen(DefaultScreenOfDisplay(display())) / 25.4); }; + + double ydpin() const + { return (double)HeightOfScreen(DefaultScreenOfDisplay(display())) / + (HeightMMOfScreen(DefaultScreenOfDisplay(display())) / 25.4); }; + Drawable drawable() const { return drawable_; }; //@# what about 0? *** xtextview.C# Thu Jul 1 20:37:04 1993 --- xtextview.C Tue Jul 20 14:32:13 1993 *************** *** 18,25 **** --- 18,29 ---- #include int debug_x = 0; + int debug_fonts = 0; + #include "debug.h" + #define round(x) ((int)(x + 0.5)) + void* XTextView_create(Display* disp, void* widget) { *************** *** 134,174 **** XFontStruct* XTextView::font(int font_family, int half_points, int bold, int italic) { ! static cache_font_family, cache_half_points, cache_bold, cache_italic; ! static XFontStruct* ret = 0; ! if(ret && ! font_family == cache_font_family && ! half_points == cache_half_points && ! bold == cache_bold && ! italic == cache_italic) ! return ret; ! else{ ! cache_font_family = font_family; ! cache_half_points = half_points; ! cache_bold = bold; ! cache_italic = italic; ! } ! ! debug(("looking for fam[%d], size=%dhp bold=%d italic=%d\n", font_family, half_points, bold, italic)); ! debug(("looking for fam[%d], size=%dhp bold=%d italic=%d\n", ! font_family, half_points, bold, italic)); assert(font_family <= MAX_FONT_FAMILY); if(!font_names_[font_family]){ char* pattern = Widget_font_pattern(widget_, font_family); ! debug(("pattern: %s\n", pattern)); if(pattern){ font_names_[font_family] = ! XListFonts(display(), pattern, 100, //MAGIG # &(font_qty_[font_family])); delete pattern; }else font_qty_[font_family] = 0; } int qty = font_qty_[font_family]; const char** cand_names = font_names_[font_family]; const char* font_name; --- 152,212 ---- XFontStruct* XTextView::font(int font_family, int half_points, int bold, int italic) { ! static struct { ! int font_family, half_points, bold, italic, hits; ! XFontStruct* font_struct; ! } cache[FONT_CACHE_SIZE]; ! static int cache_used = 0; ! #if DEBUG ! static int cache_searches = 0, cache_misses = 0; ! Debug(fonts, ("looking for fam[%d], size=%dhp bold=%d italic=%d\n", font_family, half_points, bold, italic)); ! ++cache_searches; ! #endif + for (int i = 0; i < cache_used; ++i) + if(font_family == cache[i].font_family && + half_points == cache[i].half_points && + bold == cache[i].bold && + italic == cache[i].italic) { + ++cache[i].hits; + Debug(fonts, ("got a hit, entry [%d], hits %d (%.2f%% rate)\n", i, cache[i].hits, + 100.0 * ((float) (cache_searches - cache_misses) / (float) + cache_searches))); + return cache[i].font_struct; + } + + #if DEBUG + ++cache_misses; + #endif + assert(font_family <= MAX_FONT_FAMILY); if(!font_names_[font_family]){ char* pattern = Widget_font_pattern(widget_, font_family); ! #if 0 ! Debug(fonts, ("pattern: %s\n", pattern)); ! #endif + #define RND(x) ((x) >= 82.5 ? 100 : 75) + if(pattern){ + char qname[128], foundry[32], font_fam[32]; + sscanf(pattern, "-%[^-]-%[^-]-", foundry, font_fam); + + sprintf(qname, "-%s-%s-*-*-*-*-*-%d-%d-%d-*-*-%s", foundry, font_fam, + 10 * half_points / 2, (int) RND(xdpin()), (int) RND(ydpin()), + (font_family != 4 && font_family != 6) ? "iso8859-1" : "adobe-fontspecific"); + Debug(fonts, ("pattern: %s\n", qname)); font_names_[font_family] = ! XListFonts(display(), qname, 100, //MAGIG # &(font_qty_[font_family])); delete pattern; }else font_qty_[font_family] = 0; } + #undef RND int qty = font_qty_[font_family]; const char** cand_names = font_names_[font_family]; const char* font_name; *************** *** 178,186 **** int best_index = 0; for(int i = 0; i cache[n].hits) ! n = i; ! Debug(fonts, ("cache full: swapping out [%d]\n", n)); ! } ! ! Debug(fonts, ("putting %s into [%d]\n", font_name, n)); ! ! cache[n].font_family = font_family; ! cache[n].half_points = half_points; ! cache[n].bold = bold; ! cache[n].italic = italic; ! cache[n].hits = 0; ! cache[n].font_struct = ret; ! ! Debug(fonts, ("%d hits on %d searches (%.2f%%)\n", cache_searches - cache_misses, ! cache_searches, ! 100.0 * ((float) (cache_searches - cache_misses) / (float) ! cache_searches))); ! ! return ret; } *** RichText.c~ Fri Oct 23 21:11:47 1992 --- RichText.c Tue Jul 20 15:41:27 1993 *************** *** 62,69 **** XcCFontPatterns, XmRXmStringTable, sizeof (XmStringTable), XtOffset (XcRichTextWidget, rich_text.fontPatterns), XmRString, ! (caddr_t) "*-fixed-*,*-adobe-times-*,*-adobe-helvetica-*," ! "*-adobe-courier-*,*-script-*,*-decor-*,*-adobe-symbol-*,*", }, #endif { --- 62,69 ---- XcCFontPatterns, XmRXmStringTable, sizeof (XmStringTable), XtOffset (XcRichTextWidget, rich_text.fontPatterns), XmRString, ! (caddr_t) "-*-fixed-,-adobe-times-,-adobe-helvetica-,-adobe-courier-," ! "-*-script-,-*-decor-,-adobe-symbol-,-*-*-", }, #endif {