Actual source code: xtext.c


  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/classes/draw/impls/x/ximpl.h>

  9: static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *);
 10: static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *, PetscDrawXiFont *);
 11: static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *, int, int);

 13: /*
 14:     PetscDrawXiFontFixed - Return a pointer to the selected font.

 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;

 24:   if (!curfont) PetscDrawXiInitFonts(XBWin);
 25:   PetscNew(&font);
 26:   PetscDrawXiMatchFontSize(font, w, h);
 27:   PetscDrawXiLoadFont(XBWin, font);

 29:   curfont  = font;
 30:   *outfont = curfont;
 31:   return 0;
 32: }

 34: /* this is set by XListFonts at startup */
 35: #define NFONTS 20
 36: static struct {
 37:   int w, h, descent;
 38: } nfonts[NFONTS];
 39: static int act_nfonts = 0;

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

 46: static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *XBWin, PetscDrawXiFont *font)
 47: {
 48:   char         font_name[100];
 49:   XFontStruct *FontInfo;
 50:   XGCValues    values;

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

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

 62:   XFreeFontInfo(NULL, FontInfo, 1);

 64:   /* Set the current font in the CG */
 65:   values.font = font->fnt;
 66:   XChangeGC(XBWin->disp, XBWin->gc.set, GCFont, &values);
 67:   return 0;
 68: }

 70: /* Code to find fonts and their characteristics */
 71: static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *XBWin)
 72: {
 73:   char       **names;
 74:   int          cnt, i, j;
 75:   XFontStruct *info;

 77:   /* This just gets the most basic fixed-width fonts */
 78:   names = XListFontsWithInfo(XBWin->disp, "?x??", NFONTS, &cnt, &info);
 79:   j     = 0;
 80:   for (i = 0; i < cnt; i++) {
 81:     names[i][1]       = '\0';
 82:     nfonts[j].w       = info[i].max_bounds.width;
 83:     nfonts[j].h       = info[i].ascent + info[i].descent;
 84:     nfonts[j].descent = info[i].descent;
 85:     if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue;
 86:     j++;
 87:     if (j >= NFONTS) break;
 88:   }
 89:   act_nfonts = j;
 90:   if (cnt > 0) XFreeFontInfo(names, info, cnt);

 92:   /* If the above fails,try this: */
 93:   if (!act_nfonts) {
 94:     /* This just gets the most basic fixed-width fonts */
 95:     names = XListFontsWithInfo(XBWin->disp, "?x", NFONTS, &cnt, &info);
 96:     j     = 0;
 97:     for (i = 0; i < cnt; i++) {
 98:       size_t len;

100:       PetscStrlen(names[i], &len);
101:       if (len != 2) continue;
102:       names[i][1] = '\0';
103:       nfonts[j].w = info[i].max_bounds.width;
104:       /* nfonts[j].w         = info[i].max_bounds.lbearing + info[i].max_bounds.rbearing; */
105:       nfonts[j].h       = info[i].ascent + info[i].descent;
106:       nfonts[j].descent = info[i].descent;
107:       if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue;
108:       j++;
109:       if (j >= NFONTS) break;
110:     }
111:     act_nfonts = j;
112:     XFreeFontInfo(names, info, cnt);
113:   }
114:   return 0;
115: }

117: static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *font, int w, int h)
118: {
119:   int i, max, imax, tmp;

121:   for (i = 0; i < act_nfonts; i++) {
122:     if (nfonts[i].w == w && nfonts[i].h == h) {
123:       font->font_w       = w;
124:       font->font_h       = h;
125:       font->font_descent = nfonts[i].descent;
126:       return 0;
127:     }
128:   }

130:   /* determine closest fit,per max. norm */
131:   imax = 0;
132:   max  = PetscMax(PetscAbsInt(nfonts[0].w - w), PetscAbsInt(nfonts[0].h - h));
133:   for (i = 1; i < act_nfonts; i++) {
134:     tmp = PetscMax(PetscAbsInt(nfonts[i].w - w), PetscAbsInt(nfonts[i].h - h));
135:     if (tmp < max) {
136:       max  = tmp;
137:       imax = i;
138:     }
139:   }

141:   /* should use font with closest match */
142:   font->font_w       = nfonts[imax].w;
143:   font->font_h       = nfonts[imax].h;
144:   font->font_descent = nfonts[imax].descent;
145:   return 0;
146: }