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