Actual source code: text.c

petsc-3.3-p7 2013-05-11
  2: /*
  3:    This file contains simple code to manage access to fonts, insuring that
  4:    library routines access/load fonts only once
  5:  */

  7: #include <../src/sys/draw/impls/x/ximpl.h>

  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.

 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: */
 21: PetscErrorCode PetscDrawXiFontFixed(PetscDraw_X *XBWin,int w,int h,PetscDrawXiFont **outfont)
 22: {
 23:   static PetscDrawXiFont *curfont = 0,*font;
 24:   PetscErrorCode         ierr;

 27:   if (!curfont) { PetscDrawXiInitFonts(XBWin);}
 28:   PetscNew(PetscDrawXiFont,&font);
 29:   PetscDrawXiMatchFontSize(font,w,h);
 30:   PetscDrawXiLoadFont(XBWin,font);
 31:   curfont = font;
 32:   *outfont = curfont;
 33:   return(0);
 34: }

 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;

 43: /*
 44:   These routines determine the font to be used based on the requested size,
 45:   and load it if necessary
 46: */

 50: PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *XBWin,PetscDrawXiFont *font)
 51: {
 52:   char        font_name[100];
 53:   XFontStruct *FontInfo;
 54:   XGCValues   values ;

 57:   (void) sprintf(font_name,"%dx%d",font->font_w,font->font_h);
 58:   font->fnt  = XLoadFont(XBWin->disp,font_name);

 60:   /* The font->descent may not have been set correctly; get it now that
 61:       the font has been loaded */
 62:   FontInfo   = XQueryFont(XBWin->disp,font->fnt);
 63:   font->font_descent   = FontInfo->descent;
 64:   font->font_w         = FontInfo->max_bounds.rbearing - FontInfo->min_bounds.lbearing;
 65:   font->font_h         = FontInfo->max_bounds.ascent + FontInfo->max_bounds.descent;

 67:   XFreeFontInfo(0,FontInfo,1);

 69:   /* Set the current font in the CG */
 70:   values.font = font->fnt ;
 71:   XChangeGC(XBWin->disp,XBWin->gc.set,GCFont,&values);
 72:   return(0);
 73: }

 75: /* Code to find fonts and their characteristics */
 78: PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *XBWin)
 79: {
 80:   char         **names;
 81:   int          cnt,i,j;
 82:   XFontStruct  *info;

 85:   /* This just gets the most basic fixed-width fonts */
 86:   names   = XListFontsWithInfo(XBWin->disp,"?x??",NFONTS,&cnt,&info);
 87:   j       = 0;
 88:   for (i=0; i<cnt; i++) {
 89:     names[i][1]         = '\0';
 90:     nfonts[j].w         = info[i].max_bounds.width ;
 91:     nfonts[j].h         = info[i].ascent + info[i].descent;
 92:     nfonts[j].descent   = info[i].descent;
 93:     if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue;
 94:     j++;
 95:     if (j >= NFONTS) break;
 96:   }
 97:   act_nfonts    = j;
 98:   if (cnt > 0)  {
 99:     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++) {
108:         size_t len;

110:         PetscStrlen(names[i],&len);
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:   return(0);
125: }

129: PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *font,int w,int h)
130: {
131:   int i,max,imax,tmp;

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:       return(0);
140:     }
141:   }

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:   }

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:   return(0);
156: }