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