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