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