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