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:   PetscFunctionBegin;
 25:   if (!curfont) PetscCall(PetscDrawXiInitFonts(XBWin));
 26:   PetscCall(PetscNew(&font));
 27:   PetscCall(PetscDrawXiMatchFontSize(font, w, h));
 28:   PetscCall(PetscDrawXiLoadFont(XBWin, font));

 30:   curfont  = font;
 31:   *outfont = curfont;
 32:   PetscFunctionReturn(PETSC_SUCCESS);
 33: }

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

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

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

 53:   PetscFunctionBegin;
 54:   PetscCall(PetscSNPrintf(font_name, PETSC_STATIC_ARRAY_LENGTH(font_name), "%dx%d", font->font_w, font->font_h));
 55:   font->fnt = XLoadFont(XBWin->disp, font_name);

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

 64:   XFreeFontInfo(NULL, FontInfo, 1);

 66:   /* Set the current font in the CG */
 67:   values.font = font->fnt;
 68:   XChangeGC(XBWin->disp, XBWin->gc.set, GCFont, &values);
 69:   PetscFunctionReturn(PETSC_SUCCESS);
 70: }

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

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

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

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

120: static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *font, int w, int h)
121: {
122:   int i, max, imax, tmp;

124:   PetscFunctionBegin;
125:   for (i = 0; i < act_nfonts; i++) {
126:     if (nfonts[i].w == w && nfonts[i].h == h) {
127:       font->font_w       = w;
128:       font->font_h       = h;
129:       font->font_descent = nfonts[i].descent;
130:       PetscFunctionReturn(PETSC_SUCCESS);
131:     }
132:   }

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

145:   /* should use font with closest match */
146:   font->font_w       = nfonts[imax].w;
147:   font->font_h       = nfonts[imax].h;
148:   font->font_descent = nfonts[imax].descent;
149:   PetscFunctionReturn(PETSC_SUCCESS);
150: }