Actual source code: text.c
petsc-3.3-p7 2013-05-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/draw/impls/x/ximpl.h>
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.
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: */
21: PetscErrorCode PetscDrawXiFontFixed(PetscDraw_X *XBWin,int w,int h,PetscDrawXiFont **outfont)
22: {
23: static PetscDrawXiFont *curfont = 0,*font;
24: PetscErrorCode ierr;
27: if (!curfont) { PetscDrawXiInitFonts(XBWin);}
28: PetscNew(PetscDrawXiFont,&font);
29: PetscDrawXiMatchFontSize(font,w,h);
30: 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: */
50: PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *XBWin,PetscDrawXiFont *font)
51: {
52: char font_name[100];
53: XFontStruct *FontInfo;
54: XGCValues values ;
57: (void) sprintf(font_name,"%dx%d",font->font_w,font->font_h);
58: font->fnt = XLoadFont(XBWin->disp,font_name);
60: /* The font->descent may not have been set correctly; get it now that
61: the font has been loaded */
62: FontInfo = XQueryFont(XBWin->disp,font->fnt);
63: font->font_descent = FontInfo->descent;
64: font->font_w = FontInfo->max_bounds.rbearing - FontInfo->min_bounds.lbearing;
65: font->font_h = FontInfo->max_bounds.ascent + FontInfo->max_bounds.descent;
67: XFreeFontInfo(0,FontInfo,1);
69: /* Set the current font in the CG */
70: values.font = font->fnt ;
71: XChangeGC(XBWin->disp,XBWin->gc.set,GCFont,&values);
72: return(0);
73: }
75: /* Code to find fonts and their characteristics */
78: PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *XBWin)
79: {
80: char **names;
81: int cnt,i,j;
82: XFontStruct *info;
85: /* This just gets the most basic fixed-width fonts */
86: names = XListFontsWithInfo(XBWin->disp,"?x??",NFONTS,&cnt,&info);
87: j = 0;
88: for (i=0; i<cnt; i++) {
89: names[i][1] = '\0';
90: nfonts[j].w = info[i].max_bounds.width ;
91: nfonts[j].h = info[i].ascent + info[i].descent;
92: nfonts[j].descent = info[i].descent;
93: if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue;
94: j++;
95: if (j >= NFONTS) break;
96: }
97: act_nfonts = j;
98: if (cnt > 0) {
99: 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++) {
108: size_t len;
110: PetscStrlen(names[i],&len);
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: return(0);
125: }
129: PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *font,int w,int h)
130: {
131: int i,max,imax,tmp;
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: return(0);
140: }
141: }
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: }
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: return(0);
156: }