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