Actual source code: xtext.c
petsc-3.7.3 2016-08-01
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: */
22: PetscErrorCode PetscDrawXiFontFixed(PetscDraw_X *XBWin,int w,int h,PetscDrawXiFont **outfont)
23: {
24: static PetscDrawXiFont *curfont = 0,*font;
25: PetscErrorCode ierr;
28: if (!curfont) { PetscDrawXiInitFonts(XBWin);}
29: PetscNew(&font);
30: PetscDrawXiMatchFontSize(font,w,h);
31: PetscDrawXiLoadFont(XBWin,font);
33: curfont = font;
34: *outfont = curfont;
35: return(0);
36: }
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;
45: /*
46: These routines determine the font to be used based on the requested size,
47: and load it if necessary
48: */
52: static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *XBWin,PetscDrawXiFont *font)
53: {
54: char font_name[100];
55: XFontStruct *FontInfo;
56: XGCValues values;
59: (void) sprintf(font_name,"%dx%d",font->font_w,font->font_h);
60: font->fnt = XLoadFont(XBWin->disp,font_name);
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;
69: XFreeFontInfo(0,FontInfo,1);
71: /* Set the current font in the CG */
72: values.font = font->fnt;
73: XChangeGC(XBWin->disp,XBWin->gc.set,GCFont,&values);
74: return(0);
75: }
77: /* Code to find fonts and their characteristics */
80: static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *XBWin)
81: {
82: char **names;
83: int cnt,i,j;
84: XFontStruct *info;
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);
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++) {
109: size_t len;
111: PetscStrlen(names[i],&len);
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: return(0);
126: }
130: static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *font,int w,int h)
131: {
132: int i,max,imax,tmp;
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: return(0);
141: }
142: }
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: }
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: return(0);
157: }