Actual source code: xtext.c

  1: /*
  2:    This file contains simple code to manage access to fonts, insuring that
  3:    library routines access/load fonts only once
  4:  */

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

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

 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: */
 19: PetscErrorCode PetscDrawXiFontFixed(PetscDraw_X *XBWin, int w, int h, PetscDrawXiFont **outfont)
 20: {
 21:   static PetscDrawXiFont *curfont = NULL, *font;

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

 29:   curfont  = font;
 30:   *outfont = curfont;
 31:   PetscFunctionReturn(PETSC_SUCCESS);
 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:   PetscFunctionBegin;
 53:   PetscCall(PetscSNPrintf(font_name, PETSC_STATIC_ARRAY_LENGTH(font_name), "%dx%d", font->font_w, font->font_h));
 54:   font->fnt = XLoadFont(XBWin->disp, font_name);

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

 63:   XFreeFontInfo(NULL, FontInfo, 1);

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

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

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

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

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

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

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

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

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