xref: /petsc/src/sys/classes/draw/impls/x/xtext.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 */
20*9371c9d4SSatish Balay PetscErrorCode PetscDrawXiFontFixed(PetscDraw_X *XBWin, int w, int h, PetscDrawXiFont **outfont) {
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;
31ae7e3b26SLisandro Dalcin   PetscFunctionReturn(0);
32ae7e3b26SLisandro Dalcin }
33ae7e3b26SLisandro Dalcin 
34ae7e3b26SLisandro Dalcin /* this is set by XListFonts at startup */
35ae7e3b26SLisandro Dalcin #define NFONTS 20
36*9371c9d4SSatish Balay static struct { int w, h, descent; } nfonts[NFONTS];
37ae7e3b26SLisandro Dalcin static int act_nfonts = 0;
38ae7e3b26SLisandro Dalcin 
39ae7e3b26SLisandro Dalcin /*
40ae7e3b26SLisandro Dalcin   These routines determine the font to be used based on the requested size,
41ae7e3b26SLisandro Dalcin   and load it if necessary
42ae7e3b26SLisandro Dalcin */
43ae7e3b26SLisandro Dalcin 
44*9371c9d4SSatish Balay static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *XBWin, PetscDrawXiFont *font) {
45ae7e3b26SLisandro Dalcin   char         font_name[100];
46ae7e3b26SLisandro Dalcin   XFontStruct *FontInfo;
47ae7e3b26SLisandro Dalcin   XGCValues    values;
48ae7e3b26SLisandro Dalcin 
49ae7e3b26SLisandro Dalcin   PetscFunctionBegin;
50ae7e3b26SLisandro Dalcin   (void)sprintf(font_name, "%dx%d", font->font_w, font->font_h);
51ae7e3b26SLisandro Dalcin   font->fnt = XLoadFont(XBWin->disp, font_name);
52ae7e3b26SLisandro Dalcin 
53ae7e3b26SLisandro Dalcin   /* The font->descent may not have been set correctly; get it now that
54ae7e3b26SLisandro Dalcin       the font has been loaded */
55ae7e3b26SLisandro Dalcin   FontInfo           = XQueryFont(XBWin->disp, font->fnt);
56ae7e3b26SLisandro Dalcin   font->font_descent = FontInfo->descent;
57ae7e3b26SLisandro Dalcin   font->font_w       = FontInfo->max_bounds.rbearing - FontInfo->min_bounds.lbearing;
58ae7e3b26SLisandro Dalcin   font->font_h       = FontInfo->max_bounds.ascent + FontInfo->max_bounds.descent;
59ae7e3b26SLisandro Dalcin 
6002c9f0b5SLisandro Dalcin   XFreeFontInfo(NULL, FontInfo, 1);
61ae7e3b26SLisandro Dalcin 
62ae7e3b26SLisandro Dalcin   /* Set the current font in the CG */
63ae7e3b26SLisandro Dalcin   values.font = font->fnt;
64ae7e3b26SLisandro Dalcin   XChangeGC(XBWin->disp, XBWin->gc.set, GCFont, &values);
65ae7e3b26SLisandro Dalcin   PetscFunctionReturn(0);
66ae7e3b26SLisandro Dalcin }
67ae7e3b26SLisandro Dalcin 
68ae7e3b26SLisandro Dalcin /* Code to find fonts and their characteristics */
69*9371c9d4SSatish Balay static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *XBWin) {
70ae7e3b26SLisandro Dalcin   char       **names;
71ae7e3b26SLisandro Dalcin   int          cnt, i, j;
72ae7e3b26SLisandro Dalcin   XFontStruct *info;
73ae7e3b26SLisandro Dalcin 
74ae7e3b26SLisandro Dalcin   PetscFunctionBegin;
75ae7e3b26SLisandro Dalcin   /* This just gets the most basic fixed-width fonts */
76ae7e3b26SLisandro Dalcin   names = XListFontsWithInfo(XBWin->disp, "?x??", NFONTS, &cnt, &info);
77ae7e3b26SLisandro Dalcin   j     = 0;
78ae7e3b26SLisandro Dalcin   for (i = 0; i < cnt; i++) {
79ae7e3b26SLisandro Dalcin     names[i][1]       = '\0';
80ae7e3b26SLisandro Dalcin     nfonts[j].w       = info[i].max_bounds.width;
81ae7e3b26SLisandro Dalcin     nfonts[j].h       = info[i].ascent + info[i].descent;
82ae7e3b26SLisandro Dalcin     nfonts[j].descent = info[i].descent;
83ae7e3b26SLisandro Dalcin     if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue;
84ae7e3b26SLisandro Dalcin     j++;
85ae7e3b26SLisandro Dalcin     if (j >= NFONTS) break;
86ae7e3b26SLisandro Dalcin   }
87ae7e3b26SLisandro Dalcin   act_nfonts = j;
88ae7e3b26SLisandro Dalcin   if (cnt > 0) XFreeFontInfo(names, info, cnt);
89ae7e3b26SLisandro Dalcin 
90ae7e3b26SLisandro Dalcin   /* If the above fails,try this: */
91ae7e3b26SLisandro Dalcin   if (!act_nfonts) {
92ae7e3b26SLisandro Dalcin     /* This just gets the most basic fixed-width fonts */
93ae7e3b26SLisandro Dalcin     names = XListFontsWithInfo(XBWin->disp, "?x", NFONTS, &cnt, &info);
94ae7e3b26SLisandro Dalcin     j     = 0;
95ae7e3b26SLisandro Dalcin     for (i = 0; i < cnt; i++) {
96ae7e3b26SLisandro Dalcin       size_t len;
97ae7e3b26SLisandro Dalcin 
989566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(names[i], &len));
99ae7e3b26SLisandro Dalcin       if (len != 2) continue;
100ae7e3b26SLisandro Dalcin       names[i][1]       = '\0';
101ae7e3b26SLisandro Dalcin       nfonts[j].w       = info[i].max_bounds.width;
102ae7e3b26SLisandro Dalcin       /* nfonts[j].w         = info[i].max_bounds.lbearing + info[i].max_bounds.rbearing; */
103ae7e3b26SLisandro Dalcin       nfonts[j].h       = info[i].ascent + info[i].descent;
104ae7e3b26SLisandro Dalcin       nfonts[j].descent = info[i].descent;
105ae7e3b26SLisandro Dalcin       if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue;
106ae7e3b26SLisandro Dalcin       j++;
107ae7e3b26SLisandro Dalcin       if (j >= NFONTS) break;
108ae7e3b26SLisandro Dalcin     }
109ae7e3b26SLisandro Dalcin     act_nfonts = j;
110ae7e3b26SLisandro Dalcin     XFreeFontInfo(names, info, cnt);
111ae7e3b26SLisandro Dalcin   }
112ae7e3b26SLisandro Dalcin   PetscFunctionReturn(0);
113ae7e3b26SLisandro Dalcin }
114ae7e3b26SLisandro Dalcin 
115*9371c9d4SSatish Balay static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *font, int w, int h) {
116ae7e3b26SLisandro Dalcin   int i, max, imax, tmp;
117ae7e3b26SLisandro Dalcin 
118ae7e3b26SLisandro Dalcin   PetscFunctionBegin;
119ae7e3b26SLisandro Dalcin   for (i = 0; i < act_nfonts; i++) {
120ae7e3b26SLisandro Dalcin     if (nfonts[i].w == w && nfonts[i].h == h) {
121ae7e3b26SLisandro Dalcin       font->font_w       = w;
122ae7e3b26SLisandro Dalcin       font->font_h       = h;
123ae7e3b26SLisandro Dalcin       font->font_descent = nfonts[i].descent;
124ae7e3b26SLisandro Dalcin       PetscFunctionReturn(0);
125ae7e3b26SLisandro Dalcin     }
126ae7e3b26SLisandro Dalcin   }
127ae7e3b26SLisandro Dalcin 
128ae7e3b26SLisandro Dalcin   /* determine closest fit,per max. norm */
129ae7e3b26SLisandro Dalcin   imax = 0;
130ae7e3b26SLisandro Dalcin   max  = PetscMax(PetscAbsInt(nfonts[0].w - w), PetscAbsInt(nfonts[0].h - h));
131ae7e3b26SLisandro Dalcin   for (i = 1; i < act_nfonts; i++) {
132ae7e3b26SLisandro Dalcin     tmp = PetscMax(PetscAbsInt(nfonts[i].w - w), PetscAbsInt(nfonts[i].h - h));
133*9371c9d4SSatish Balay     if (tmp < max) {
134*9371c9d4SSatish Balay       max  = tmp;
135*9371c9d4SSatish Balay       imax = i;
136*9371c9d4SSatish Balay     }
137ae7e3b26SLisandro Dalcin   }
138ae7e3b26SLisandro Dalcin 
139ae7e3b26SLisandro Dalcin   /* should use font with closest match */
140ae7e3b26SLisandro Dalcin   font->font_w       = nfonts[imax].w;
141ae7e3b26SLisandro Dalcin   font->font_h       = nfonts[imax].h;
142ae7e3b26SLisandro Dalcin   font->font_descent = nfonts[imax].descent;
143ae7e3b26SLisandro Dalcin   PetscFunctionReturn(0);
144ae7e3b26SLisandro Dalcin }
145