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