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