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