1 2 /* 3 This file contains simple code to manage access to fonts, insuring that 4 library routines access/load fonts only once 5 */ 6 7 #include <../src/sys/classes/draw/impls/x/ximpl.h> 8 9 static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X*); 10 static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X*,PetscDrawXiFont*); 11 static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont*,int,int); 12 13 /* 14 PetscDrawXiFontFixed - Return a pointer to the selected font. 15 16 Warning: Loads a new font for each window. This should be 17 ok because there will never be many windows and the graphics 18 are not intended to be high performance. 19 */ 20 PetscErrorCode PetscDrawXiFontFixed(PetscDraw_X *XBWin,int w,int h,PetscDrawXiFont **outfont) 21 { 22 static PetscDrawXiFont *curfont = NULL,*font; 23 PetscErrorCode ierr; 24 25 PetscFunctionBegin; 26 if (!curfont) { ierr = PetscDrawXiInitFonts(XBWin);CHKERRQ(ierr);} 27 ierr = PetscNew(&font);CHKERRQ(ierr); 28 ierr = PetscDrawXiMatchFontSize(font,w,h);CHKERRQ(ierr); 29 ierr = PetscDrawXiLoadFont(XBWin,font);CHKERRQ(ierr); 30 31 curfont = font; 32 *outfont = curfont; 33 PetscFunctionReturn(0); 34 } 35 36 /* this is set by XListFonts at startup */ 37 #define NFONTS 20 38 static struct { 39 int w,h,descent; 40 } nfonts[NFONTS]; 41 static int act_nfonts = 0; 42 43 /* 44 These routines determine the font to be used based on the requested size, 45 and load it if necessary 46 */ 47 48 static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *XBWin,PetscDrawXiFont *font) 49 { 50 char font_name[100]; 51 XFontStruct *FontInfo; 52 XGCValues values; 53 54 PetscFunctionBegin; 55 (void) sprintf(font_name,"%dx%d",font->font_w,font->font_h); 56 font->fnt = XLoadFont(XBWin->disp,font_name); 57 58 /* The font->descent may not have been set correctly; get it now that 59 the font has been loaded */ 60 FontInfo = XQueryFont(XBWin->disp,font->fnt); 61 font->font_descent = FontInfo->descent; 62 font->font_w = FontInfo->max_bounds.rbearing - FontInfo->min_bounds.lbearing; 63 font->font_h = FontInfo->max_bounds.ascent + FontInfo->max_bounds.descent; 64 65 XFreeFontInfo(NULL,FontInfo,1); 66 67 /* Set the current font in the CG */ 68 values.font = font->fnt; 69 XChangeGC(XBWin->disp,XBWin->gc.set,GCFont,&values); 70 PetscFunctionReturn(0); 71 } 72 73 /* Code to find fonts and their characteristics */ 74 static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *XBWin) 75 { 76 char **names; 77 int cnt,i,j; 78 XFontStruct *info; 79 80 PetscFunctionBegin; 81 /* This just gets the most basic fixed-width fonts */ 82 names = XListFontsWithInfo(XBWin->disp,"?x??",NFONTS,&cnt,&info); 83 j = 0; 84 for (i=0; i<cnt; i++) { 85 names[i][1] = '\0'; 86 nfonts[j].w = info[i].max_bounds.width; 87 nfonts[j].h = info[i].ascent + info[i].descent; 88 nfonts[j].descent = info[i].descent; 89 if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue; 90 j++; 91 if (j >= NFONTS) break; 92 } 93 act_nfonts = j; 94 if (cnt > 0) XFreeFontInfo(names,info,cnt); 95 96 /* If the above fails,try this: */ 97 if (!act_nfonts) { 98 /* This just gets the most basic fixed-width fonts */ 99 names = XListFontsWithInfo(XBWin->disp,"?x",NFONTS,&cnt,&info); 100 j = 0; 101 for (i=0; i<cnt; i++) { 102 PetscErrorCode ierr; 103 size_t len; 104 105 ierr = PetscStrlen(names[i],&len);CHKERRQ(ierr); 106 if (len != 2) continue; 107 names[i][1] = '\0'; 108 nfonts[j].w = info[i].max_bounds.width; 109 /* nfonts[j].w = info[i].max_bounds.lbearing + info[i].max_bounds.rbearing; */ 110 nfonts[j].h = info[i].ascent + info[i].descent; 111 nfonts[j].descent = info[i].descent; 112 if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue; 113 j++; 114 if (j >= NFONTS) break; 115 } 116 act_nfonts = j; 117 XFreeFontInfo(names,info,cnt); 118 } 119 PetscFunctionReturn(0); 120 } 121 122 static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *font,int w,int h) 123 { 124 int i,max,imax,tmp; 125 126 PetscFunctionBegin; 127 for (i=0; i<act_nfonts; i++) { 128 if (nfonts[i].w == w && nfonts[i].h == h) { 129 font->font_w = w; 130 font->font_h = h; 131 font->font_descent = nfonts[i].descent; 132 PetscFunctionReturn(0); 133 } 134 } 135 136 /* determine closest fit,per max. norm */ 137 imax = 0; 138 max = PetscMax(PetscAbsInt(nfonts[0].w - w),PetscAbsInt(nfonts[0].h - h)); 139 for (i=1; i<act_nfonts; i++) { 140 tmp = PetscMax(PetscAbsInt(nfonts[i].w - w),PetscAbsInt(nfonts[i].h - h)); 141 if (tmp < max) {max = tmp; imax = i;} 142 } 143 144 /* should use font with closest match */ 145 font->font_w = nfonts[imax].w; 146 font->font_h = nfonts[imax].h; 147 font->font_descent = nfonts[imax].descent; 148 PetscFunctionReturn(0); 149 } 150