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