Actual source code: xtext.c
petsc-3.9.4 2018-09-11
2: /*
3: This file contains simple code to manage access to fonts, insuring that
4: library routines access/load fonts only once
5: */
7: #include <../src/sys/classes/draw/impls/x/ximpl.h>
9: static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X*);
10: static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X*,PetscDrawXiFont*);
11: static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont*,int,int);
13: /*
14: PetscDrawXiFontFixed - Return a pointer to the selected font.
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 = 0,*font;
23: PetscErrorCode ierr;
26: if (!curfont) { PetscDrawXiInitFonts(XBWin);}
27: PetscNew(&font);
28: PetscDrawXiMatchFontSize(font,w,h);
29: PetscDrawXiLoadFont(XBWin,font);
31: curfont = font;
32: *outfont = curfont;
33: return(0);
34: }
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;
43: /*
44: These routines determine the font to be used based on the requested size,
45: and load it if necessary
46: */
48: static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *XBWin,PetscDrawXiFont *font)
49: {
50: char font_name[100];
51: XFontStruct *FontInfo;
52: XGCValues values;
55: (void) sprintf(font_name,"%dx%d",font->font_w,font->font_h);
56: font->fnt = XLoadFont(XBWin->disp,font_name);
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;
65: XFreeFontInfo(0,FontInfo,1);
67: /* Set the current font in the CG */
68: values.font = font->fnt;
69: XChangeGC(XBWin->disp,XBWin->gc.set,GCFont,&values);
70: return(0);
71: }
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;
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);
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++) {
103: size_t len;
105: PetscStrlen(names[i],&len);
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: return(0);
120: }
122: static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *font,int w,int h)
123: {
124: int i,max,imax,tmp;
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: return(0);
133: }
134: }
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: }
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: return(0);
149: }