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