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