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