1ae7e3b26SLisandro Dalcin /*
2ae7e3b26SLisandro Dalcin This file contains simple code to manage access to fonts, insuring that
3ae7e3b26SLisandro Dalcin library routines access/load fonts only once
4ae7e3b26SLisandro Dalcin */
5ae7e3b26SLisandro Dalcin
6ae7e3b26SLisandro Dalcin #include <../src/sys/classes/draw/impls/x/ximpl.h>
7ae7e3b26SLisandro Dalcin
809440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *);
909440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *, PetscDrawXiFont *);
1009440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *, int, int);
1109440f25SLisandro Dalcin
12ae7e3b26SLisandro Dalcin /*
13ae7e3b26SLisandro Dalcin PetscDrawXiFontFixed - Return a pointer to the selected font.
14ae7e3b26SLisandro Dalcin
15ae7e3b26SLisandro Dalcin Warning: Loads a new font for each window. This should be
16ae7e3b26SLisandro Dalcin ok because there will never be many windows and the graphics
17ae7e3b26SLisandro Dalcin are not intended to be high performance.
18ae7e3b26SLisandro Dalcin */
PetscDrawXiFontFixed(PetscDraw_X * XBWin,int w,int h,PetscDrawXiFont ** outfont)19d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawXiFontFixed(PetscDraw_X *XBWin, int w, int h, PetscDrawXiFont **outfont)
20d71ae5a4SJacob Faibussowitsch {
2102c9f0b5SLisandro Dalcin static PetscDrawXiFont *curfont = NULL, *font;
22ae7e3b26SLisandro Dalcin
23ae7e3b26SLisandro Dalcin PetscFunctionBegin;
249566063dSJacob Faibussowitsch if (!curfont) PetscCall(PetscDrawXiInitFonts(XBWin));
259566063dSJacob Faibussowitsch PetscCall(PetscNew(&font));
269566063dSJacob Faibussowitsch PetscCall(PetscDrawXiMatchFontSize(font, w, h));
279566063dSJacob Faibussowitsch PetscCall(PetscDrawXiLoadFont(XBWin, font));
28ae7e3b26SLisandro Dalcin
29ae7e3b26SLisandro Dalcin curfont = font;
30ae7e3b26SLisandro Dalcin *outfont = curfont;
31*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
32ae7e3b26SLisandro Dalcin }
33ae7e3b26SLisandro Dalcin
34ae7e3b26SLisandro Dalcin /* this is set by XListFonts at startup */
35ae7e3b26SLisandro Dalcin #define NFONTS 20
36d71ae5a4SJacob Faibussowitsch static struct {
37d71ae5a4SJacob Faibussowitsch int w, h, descent;
38d71ae5a4SJacob Faibussowitsch } nfonts[NFONTS];
39ae7e3b26SLisandro Dalcin static int act_nfonts = 0;
40ae7e3b26SLisandro Dalcin
41ae7e3b26SLisandro Dalcin /*
42ae7e3b26SLisandro Dalcin These routines determine the font to be used based on the requested size,
43ae7e3b26SLisandro Dalcin and load it if necessary
44ae7e3b26SLisandro Dalcin */
45ae7e3b26SLisandro Dalcin
PetscDrawXiLoadFont(PetscDraw_X * XBWin,PetscDrawXiFont * font)46d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *XBWin, PetscDrawXiFont *font)
47d71ae5a4SJacob Faibussowitsch {
48ae7e3b26SLisandro Dalcin char font_name[100];
49ae7e3b26SLisandro Dalcin XFontStruct *FontInfo;
50ae7e3b26SLisandro Dalcin XGCValues values;
51ae7e3b26SLisandro Dalcin
52ae7e3b26SLisandro Dalcin PetscFunctionBegin;
53a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(font_name, PETSC_STATIC_ARRAY_LENGTH(font_name), "%dx%d", font->font_w, font->font_h));
54ae7e3b26SLisandro Dalcin font->fnt = XLoadFont(XBWin->disp, font_name);
55ae7e3b26SLisandro Dalcin
56ae7e3b26SLisandro Dalcin /* The font->descent may not have been set correctly; get it now that
57ae7e3b26SLisandro Dalcin the font has been loaded */
58ae7e3b26SLisandro Dalcin FontInfo = XQueryFont(XBWin->disp, font->fnt);
59ae7e3b26SLisandro Dalcin font->font_descent = FontInfo->descent;
60ae7e3b26SLisandro Dalcin font->font_w = FontInfo->max_bounds.rbearing - FontInfo->min_bounds.lbearing;
61ae7e3b26SLisandro Dalcin font->font_h = FontInfo->max_bounds.ascent + FontInfo->max_bounds.descent;
62ae7e3b26SLisandro Dalcin
6302c9f0b5SLisandro Dalcin XFreeFontInfo(NULL, FontInfo, 1);
64ae7e3b26SLisandro Dalcin
65ae7e3b26SLisandro Dalcin /* Set the current font in the CG */
66ae7e3b26SLisandro Dalcin values.font = font->fnt;
67ae7e3b26SLisandro Dalcin XChangeGC(XBWin->disp, XBWin->gc.set, GCFont, &values);
68*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
69ae7e3b26SLisandro Dalcin }
70ae7e3b26SLisandro Dalcin
71ae7e3b26SLisandro Dalcin /* Code to find fonts and their characteristics */
PetscDrawXiInitFonts(PetscDraw_X * XBWin)72d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *XBWin)
73d71ae5a4SJacob Faibussowitsch {
74ae7e3b26SLisandro Dalcin char **names;
75ae7e3b26SLisandro Dalcin int cnt, i, j;
76ae7e3b26SLisandro Dalcin XFontStruct *info;
77ae7e3b26SLisandro Dalcin
78ae7e3b26SLisandro Dalcin PetscFunctionBegin;
79ae7e3b26SLisandro Dalcin /* This just gets the most basic fixed-width fonts */
80ae7e3b26SLisandro Dalcin names = XListFontsWithInfo(XBWin->disp, "?x??", NFONTS, &cnt, &info);
81ae7e3b26SLisandro Dalcin j = 0;
82ae7e3b26SLisandro Dalcin for (i = 0; i < cnt; i++) {
83ae7e3b26SLisandro Dalcin names[i][1] = '\0';
84ae7e3b26SLisandro Dalcin nfonts[j].w = info[i].max_bounds.width;
85ae7e3b26SLisandro Dalcin nfonts[j].h = info[i].ascent + info[i].descent;
86ae7e3b26SLisandro Dalcin nfonts[j].descent = info[i].descent;
87ae7e3b26SLisandro Dalcin if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue;
88ae7e3b26SLisandro Dalcin j++;
89ae7e3b26SLisandro Dalcin if (j >= NFONTS) break;
90ae7e3b26SLisandro Dalcin }
91ae7e3b26SLisandro Dalcin act_nfonts = j;
92ae7e3b26SLisandro Dalcin if (cnt > 0) XFreeFontInfo(names, info, cnt);
93ae7e3b26SLisandro Dalcin
94ae7e3b26SLisandro Dalcin /* If the above fails,try this: */
95ae7e3b26SLisandro Dalcin if (!act_nfonts) {
96ae7e3b26SLisandro Dalcin /* This just gets the most basic fixed-width fonts */
97ae7e3b26SLisandro Dalcin names = XListFontsWithInfo(XBWin->disp, "?x", NFONTS, &cnt, &info);
98ae7e3b26SLisandro Dalcin j = 0;
99ae7e3b26SLisandro Dalcin for (i = 0; i < cnt; i++) {
100ae7e3b26SLisandro Dalcin size_t len;
101ae7e3b26SLisandro Dalcin
1029566063dSJacob Faibussowitsch PetscCall(PetscStrlen(names[i], &len));
103ae7e3b26SLisandro Dalcin if (len != 2) continue;
104ae7e3b26SLisandro Dalcin names[i][1] = '\0';
105ae7e3b26SLisandro Dalcin nfonts[j].w = info[i].max_bounds.width;
106ae7e3b26SLisandro Dalcin /* nfonts[j].w = info[i].max_bounds.lbearing + info[i].max_bounds.rbearing; */
107ae7e3b26SLisandro Dalcin nfonts[j].h = info[i].ascent + info[i].descent;
108ae7e3b26SLisandro Dalcin nfonts[j].descent = info[i].descent;
109ae7e3b26SLisandro Dalcin if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue;
110ae7e3b26SLisandro Dalcin j++;
111ae7e3b26SLisandro Dalcin if (j >= NFONTS) break;
112ae7e3b26SLisandro Dalcin }
113ae7e3b26SLisandro Dalcin act_nfonts = j;
114ae7e3b26SLisandro Dalcin XFreeFontInfo(names, info, cnt);
115ae7e3b26SLisandro Dalcin }
116*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
117ae7e3b26SLisandro Dalcin }
118ae7e3b26SLisandro Dalcin
PetscDrawXiMatchFontSize(PetscDrawXiFont * font,int w,int h)119d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *font, int w, int h)
120d71ae5a4SJacob Faibussowitsch {
121ae7e3b26SLisandro Dalcin int i, max, imax, tmp;
122ae7e3b26SLisandro Dalcin
123ae7e3b26SLisandro Dalcin PetscFunctionBegin;
124ae7e3b26SLisandro Dalcin for (i = 0; i < act_nfonts; i++) {
125ae7e3b26SLisandro Dalcin if (nfonts[i].w == w && nfonts[i].h == h) {
126ae7e3b26SLisandro Dalcin font->font_w = w;
127ae7e3b26SLisandro Dalcin font->font_h = h;
128ae7e3b26SLisandro Dalcin font->font_descent = nfonts[i].descent;
129*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
130ae7e3b26SLisandro Dalcin }
131ae7e3b26SLisandro Dalcin }
132ae7e3b26SLisandro Dalcin
133ae7e3b26SLisandro Dalcin /* determine closest fit,per max. norm */
134ae7e3b26SLisandro Dalcin imax = 0;
135ae7e3b26SLisandro Dalcin max = PetscMax(PetscAbsInt(nfonts[0].w - w), PetscAbsInt(nfonts[0].h - h));
136ae7e3b26SLisandro Dalcin for (i = 1; i < act_nfonts; i++) {
137ae7e3b26SLisandro Dalcin tmp = PetscMax(PetscAbsInt(nfonts[i].w - w), PetscAbsInt(nfonts[i].h - h));
1389371c9d4SSatish Balay if (tmp < max) {
1399371c9d4SSatish Balay max = tmp;
1409371c9d4SSatish Balay imax = i;
1419371c9d4SSatish Balay }
142ae7e3b26SLisandro Dalcin }
143ae7e3b26SLisandro Dalcin
144ae7e3b26SLisandro Dalcin /* should use font with closest match */
145ae7e3b26SLisandro Dalcin font->font_w = nfonts[imax].w;
146ae7e3b26SLisandro Dalcin font->font_h = nfonts[imax].h;
147ae7e3b26SLisandro Dalcin font->font_descent = nfonts[imax].descent;
148*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
149ae7e3b26SLisandro Dalcin }
150