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